11use crate :: system:: detector:: SystemDetectorError ;
2- use winreg :: {
3- RegKey ,
4- enums :: { HKEY_LOCAL_MACHINE , KEY_READ } ,
2+ use windows_sys :: Win32 :: Foundation :: ERROR_SUCCESS ;
3+ use windows_sys :: Win32 :: System :: Registry :: {
4+ HKEY_LOCAL_MACHINE , KEY_READ , REG_SZ , RegCloseKey , RegOpenKeyExW , RegQueryValueExW ,
55} ;
66
77const CRYPTOGRAPHY_KEY_PATH : & str = "SOFTWARE\\ Microsoft\\ Cryptography" ;
@@ -11,17 +11,114 @@ const MACHINE_GUID_KEY_NAME: &str = "MachineGuid";
1111pub struct MachineIdentityProvider { }
1212
1313impl MachineIdentityProvider {
14- /// Reads the _MachineGuid_ from the Windows registry using [winreg] .
14+ /// Reads the _MachineGuid_ from the Windows registry.
1515 pub fn provide ( & self ) -> Result < String , SystemDetectorError > {
16- let hklm = RegKey :: predef ( HKEY_LOCAL_MACHINE ) ; // Open the local machine root key.
17- // Open the Cryptography reg key with read permissions
18- let cryptography_key = hklm
19- . open_subkey_with_flags ( CRYPTOGRAPHY_KEY_PATH , KEY_READ )
20- . map_err ( |err| SystemDetectorError :: MachineIDError ( err. to_string ( ) ) ) ?;
21- // Get the value from the registry
22- cryptography_key
23- . get_value ( MACHINE_GUID_KEY_NAME )
24- . map_err ( |err| SystemDetectorError :: MachineIDError ( err. to_string ( ) ) )
16+ // Convert the value names to wide strings (UTF-16)
17+ let key_path: Vec < u16 > = CRYPTOGRAPHY_KEY_PATH
18+ . encode_utf16 ( )
19+ . chain ( std:: iter:: once ( 0 ) )
20+ . collect ( ) ;
21+ let key_name: Vec < u16 > = MACHINE_GUID_KEY_NAME
22+ . encode_utf16 ( )
23+ . chain ( std:: iter:: once ( 0 ) )
24+ . collect ( ) ;
25+
26+ Self :: read_string_from_registry ( key_path, key_name)
27+ }
28+
29+ /// Helper to read a string from the registry
30+ pub fn read_string_from_registry (
31+ key_path : Vec < u16 > ,
32+ key_name : Vec < u16 > ,
33+ ) -> Result < String , SystemDetectorError > {
34+ unsafe {
35+ // Open the registry key
36+ let mut registry_key: * mut std:: ffi:: c_void = std:: ptr:: null_mut ( ) ;
37+ let result = RegOpenKeyExW (
38+ HKEY_LOCAL_MACHINE ,
39+ key_path. as_ptr ( ) ,
40+ 0 ,
41+ KEY_READ ,
42+ & mut registry_key,
43+ ) ;
44+
45+ if result != ERROR_SUCCESS {
46+ return Err ( SystemDetectorError :: MachineIDError ( format ! (
47+ "failed to open registry key: error code {}" ,
48+ result
49+ ) ) ) ;
50+ }
51+
52+ // Query the type and size of the value
53+ let mut value_type = 0u32 ;
54+ let mut data_size = 0u32 ;
55+
56+ let result = RegQueryValueExW (
57+ registry_key,
58+ key_name. as_ptr ( ) ,
59+ std:: ptr:: null ( ) ,
60+ & mut value_type,
61+ std:: ptr:: null_mut ( ) ,
62+ & mut data_size,
63+ ) ;
64+
65+ if result != ERROR_SUCCESS {
66+ Self :: close_registry_key ( registry_key) ?;
67+ return Err ( SystemDetectorError :: MachineIDError ( format ! (
68+ "failed to query registry value size: error code {}" ,
69+ result
70+ ) ) ) ;
71+ }
72+
73+ // Allocate buffer and read the actual value
74+ let mut buffer: Vec < u16 > = vec ! [ 0 ; ( data_size / 2 ) as usize ] ;
75+
76+ let result = RegQueryValueExW (
77+ registry_key,
78+ key_name. as_ptr ( ) ,
79+ std:: ptr:: null ( ) ,
80+ & mut value_type,
81+ buffer. as_mut_ptr ( ) as * mut u8 ,
82+ & mut data_size,
83+ ) ;
84+
85+ Self :: close_registry_key ( registry_key) ?;
86+
87+ if result != ERROR_SUCCESS {
88+ return Err ( SystemDetectorError :: MachineIDError ( format ! (
89+ "failed to read registry value: error code {}" ,
90+ result
91+ ) ) ) ;
92+ }
93+
94+ // Verify it's a string type
95+ if value_type != REG_SZ {
96+ return Err ( SystemDetectorError :: MachineIDError ( format ! (
97+ "unexpected registry value type: {}" ,
98+ value_type
99+ ) ) ) ;
100+ }
101+
102+ // Convert from UTF-16 to String, removing the null terminator
103+ let string_value = String :: from_utf16_lossy ( & buffer)
104+ . trim_end_matches ( '\0' )
105+ . to_string ( ) ;
106+
107+ Ok ( string_value)
108+ }
109+ }
110+
111+ /// Helper to close the registry key returning the corresponding error on failure
112+ unsafe fn close_registry_key ( hkey : * mut std:: ffi:: c_void ) -> Result < ( ) , SystemDetectorError > {
113+ unsafe {
114+ let result = RegCloseKey ( hkey) ;
115+ if result != ERROR_SUCCESS {
116+ return Err ( SystemDetectorError :: MachineIDError ( format ! (
117+ "failed to close the registry key: error code {result}"
118+ ) ) ) ;
119+ }
120+ Ok ( ( ) )
121+ }
25122 }
26123}
27124
0 commit comments