@@ -50,6 +50,8 @@ public static class PythonWinReg {
5050 public const int KEY_EXECUTE = 0X20019 ;
5151 public const int KEY_READ = 0X20019 ;
5252 public const int KEY_WRITE = 0X20006 ;
53+ public const int KEY_WOW64_64KEY = 0X100 ;
54+ public const int KEY_WOW64_32KEY = 0X200 ;
5355
5456 public const int REG_CREATED_NEW_KEY = 0X1 ;
5557 public const int REG_OPENED_EXISTING_KEY = 0X2 ;
@@ -93,42 +95,42 @@ public static void CloseKey(HKEYType key) {
9395 key . Close ( ) ;
9496 }
9597
96- public static HKEYType CreateKey ( object key , string subKeyName ) {
98+ public static HKEYType CreateKey ( object key , string sub_key ) {
9799 // the .NET APIs don't work with a key name of length 256, use CreateKeyEx which PInvokes instead
98- if ( subKeyName . Length == 256 )
99- return CreateKeyEx ( key , subKeyName , 0 , KEY_ALL_ACCESS ) ;
100+ if ( sub_key . Length == 256 )
101+ return CreateKeyEx ( key , sub_key , 0 , KEY_ALL_ACCESS ) ;
100102
101103 HKEYType rootKey = GetRootKey ( key ) ;
102104
103105 //if key is a system key and no subkey is specified return that.
104- if ( key is BigInteger && string . IsNullOrEmpty ( subKeyName ) )
106+ if ( key is BigInteger && string . IsNullOrEmpty ( sub_key ) )
105107 return rootKey ;
106108
107- HKEYType subKey = new HKEYType ( rootKey . GetKey ( ) . CreateSubKey ( subKeyName ) ) ;
109+ HKEYType subKey = new HKEYType ( rootKey . GetKey ( ) . CreateSubKey ( sub_key ) ) ;
108110 return subKey ;
109111 }
110112
111113 private static string FormatError ( int errorCode ) {
112114 return new Win32Exception ( errorCode ) . Message ;
113115 }
114116
115- public static HKEYType CreateKeyEx ( object key , string subKeyName , int res = 0 , int sam = KEY_ALL_ACCESS ) {
117+ public static HKEYType CreateKeyEx ( object key , string sub_key , int reserved = 0 , int access = KEY_ALL_ACCESS ) {
116118 HKEYType rootKey = GetRootKey ( key ) ;
117119
118120 //if key is a system key and no subkey is specified return that.
119- if ( key is BigInteger && string . IsNullOrEmpty ( subKeyName ) )
121+ if ( key is BigInteger && string . IsNullOrEmpty ( sub_key ) )
120122 return rootKey ;
121123
122124 SafeRegistryHandle handle ;
123125 int disposition ;
124126
125127 int result = RegCreateKeyEx (
126128 rootKey . GetKey ( ) . Handle ,
127- subKeyName ,
129+ sub_key ,
128130 0 ,
129131 null ,
130132 RegistryOptions . None ,
131- ( RegistryRights ) sam ,
133+ ( RegistryRights ) access ,
132134 IntPtr . Zero ,
133135 out handle ,
134136 out disposition
@@ -187,6 +189,13 @@ internal static extern int RegDeleteKey(
187189 SafeRegistryHandle hKey ,
188190 string lpSubKey ) ;
189191
192+ [ DllImport ( "advapi32.dll" , CharSet = CharSet . Unicode ) ]
193+ internal static extern int RegDeleteKeyEx (
194+ SafeRegistryHandle hKey ,
195+ string lpSubKey ,
196+ int samDesired ,
197+ int Reserved ) ;
198+
190199 [ DllImport ( "advapi32.dll" , CharSet = CharSet . Unicode ) ]
191200 internal static extern int RegDisableReflectionKey (
192201 SafeRegistryHandle hKey ) ;
@@ -200,22 +209,38 @@ internal static extern int RegQueryReflectionKey(
200209 SafeRegistryHandle hBase ,
201210 out bool bIsReflectionDisabled ) ;
202211
203- public static void DeleteKey ( object key , string subKeyName ) {
212+ public static void DeleteKey ( object key , string sub_key ) {
204213 HKEYType rootKey = GetRootKey ( key ) ;
205214
206- if ( key is BigInteger && string . IsNullOrEmpty ( subKeyName ) )
215+ if ( key is BigInteger && string . IsNullOrEmpty ( sub_key ) )
207216 throw new InvalidCastException ( "DeleteKey() argument 2 must be string, not None" ) ;
208217
209218 // the .NET APIs don't work with a key name of length 256, use a PInvoke instead
210- if ( subKeyName . Length == 256 ) {
211- RegDeleteKey ( rootKey . GetKey ( ) . Handle , subKeyName ) ;
219+ // unlike in CreateKey(), `subKeyName.Length` on deletion can be greater than 256 if combined with parent key name.
220+ if ( sub_key . Length >= 256 ) {
221+ int result = RegDeleteKey ( rootKey . GetKey ( ) . Handle , sub_key ) ;
222+ if ( result != ERROR_SUCCESS ) {
223+ throw PythonExceptions . CreateThrowable ( PythonExceptions . OSError , result ) ;
224+ }
212225 return ;
213226 }
214227
215228 try {
216- rootKey . GetKey ( ) . DeleteSubKey ( subKeyName ) ;
229+ rootKey . GetKey ( ) . DeleteSubKey ( sub_key ) ;
217230 } catch ( ArgumentException e ) {
218- throw new ExternalException ( e . Message ) ;
231+ throw PythonExceptions . CreateThrowable ( PythonExceptions . OSError , e . HResult ) ;
232+ }
233+ }
234+
235+ public static void DeleteKeyEx ( object key , string sub_key , int access = KEY_WOW64_64KEY , int reserved = 0 ) {
236+ HKEYType rootKey = GetRootKey ( key ) ;
237+
238+ if ( key is BigInteger && string . IsNullOrEmpty ( sub_key ) )
239+ throw new InvalidCastException ( "DeleteKeyEx() argument 2 must be string, not None" ) ;
240+
241+ int result = RegDeleteKeyEx ( rootKey . GetKey ( ) . Handle , sub_key , access , reserved ) ;
242+ if ( result != ERROR_SUCCESS ) {
243+ throw PythonExceptions . CreateThrowable ( PythonExceptions . OSError , result ) ;
219244 }
220245 }
221246
@@ -311,7 +336,11 @@ private static void QueryValueExImpl(SafeRegistryHandle handle, string valueName
311336 value = list ;
312337 break ;
313338 case REG_BINARY :
314- value = length == 0 ? null : PythonOps . MakeString ( data , ( int ) length ) ;
339+ var tight_fit_data = new byte [ length ] ;
340+ for ( int i = 0 ; i < length ; i ++ ) {
341+ tight_fit_data [ i ] = data [ i ] ;
342+ }
343+ value = length == 0 ? null : new Bytes ( tight_fit_data ) ;
315344 break ;
316345 case REG_EXPAND_SZ :
317346 case REG_SZ :
@@ -359,11 +388,11 @@ public static void FlushKey(object key) {
359388 rootKey . GetKey ( ) . Flush ( ) ;
360389 }
361390
362- public static HKEYType OpenKey ( object key , string subKeyName ) {
363- return OpenKey ( key , subKeyName , 0 , KEY_READ ) ;
391+ public static HKEYType OpenKey ( object key , string sub_key ) {
392+ return OpenKey ( key , sub_key , 0 , KEY_READ ) ;
364393 }
365394
366- public static HKEYType OpenKey ( object key , string subKeyName , int res = 0 , int sam = KEY_READ ) {
395+ public static HKEYType OpenKey ( object key , string sub_key , int reserved = 0 , int access = KEY_READ ) {
367396 HKEYType rootKey = GetRootKey ( key ) ;
368397 RegistryKey newKey = null ;
369398
@@ -377,20 +406,20 @@ public static HKEYType OpenKey(object key, string subKeyName, int res=0, int sam
377406
378407 var nativeRootKey = rootKey . GetKey ( ) ;
379408 try {
380- if ( ( sam & KEY_SET_VALUE ) == KEY_SET_VALUE ||
381- ( sam & KEY_CREATE_SUB_KEY ) == KEY_CREATE_SUB_KEY ) {
382- if ( res != 0 ) {
383- newKey = nativeRootKey . OpenSubKey ( subKeyName , RegistryKeyPermissionCheck . Default , ( RegistryRights ) res ) ;
409+ if ( ( access & KEY_SET_VALUE ) == KEY_SET_VALUE ||
410+ ( access & KEY_CREATE_SUB_KEY ) == KEY_CREATE_SUB_KEY ) {
411+ if ( reserved != 0 ) {
412+ newKey = nativeRootKey . OpenSubKey ( sub_key , RegistryKeyPermissionCheck . Default , ( RegistryRights ) reserved ) ;
384413 } else {
385- newKey = nativeRootKey . OpenSubKey ( subKeyName , true ) ;
414+ newKey = nativeRootKey . OpenSubKey ( sub_key , true ) ;
386415 }
387- } else if ( ( sam & KEY_QUERY_VALUE ) == KEY_QUERY_VALUE ||
388- ( sam & KEY_ENUMERATE_SUB_KEYS ) == KEY_ENUMERATE_SUB_KEYS ||
389- ( sam & KEY_NOTIFY ) == KEY_NOTIFY ) {
390- if ( res != 0 ) {
391- newKey = nativeRootKey . OpenSubKey ( subKeyName , RegistryKeyPermissionCheck . ReadSubTree , ( RegistryRights ) res ) ;
416+ } else if ( ( access & KEY_QUERY_VALUE ) == KEY_QUERY_VALUE ||
417+ ( access & KEY_ENUMERATE_SUB_KEYS ) == KEY_ENUMERATE_SUB_KEYS ||
418+ ( access & KEY_NOTIFY ) == KEY_NOTIFY ) {
419+ if ( reserved != 0 ) {
420+ newKey = nativeRootKey . OpenSubKey ( sub_key , RegistryKeyPermissionCheck . ReadSubTree , ( RegistryRights ) reserved ) ;
392421 } else {
393- newKey = nativeRootKey . OpenSubKey ( subKeyName , false ) ;
422+ newKey = nativeRootKey . OpenSubKey ( sub_key , false ) ;
394423 }
395424 } else {
396425 throw new Win32Exception ( "Unexpected mode" ) ;
@@ -407,8 +436,8 @@ public static HKEYType OpenKey(object key, string subKeyName, int res=0, int sam
407436 return new HKEYType ( newKey ) ;
408437 }
409438
410- public static HKEYType OpenKeyEx ( object key , string subKeyName , int res = 0 , int sam = KEY_READ ) {
411- return OpenKey ( key , subKeyName , res , sam ) ;
439+ public static HKEYType OpenKeyEx ( object key , string sub_key , int reserved = 0 , int access = KEY_READ ) {
440+ return OpenKey ( key , sub_key , reserved , access ) ;
412441 }
413442
414443 public static PythonTuple QueryInfoKey ( object key ) {
@@ -436,83 +465,85 @@ public static PythonTuple QueryInfoKey(object key) {
436465 }
437466 }
438467
439- public static object QueryValue ( object key , string subKeyName ) {
440- HKEYType pyKey = OpenKey ( key , subKeyName ) ;
468+ public static object QueryValue ( object key , string sub_key ) {
469+ HKEYType pyKey = OpenKey ( key , sub_key ) ;
441470 return pyKey . GetKey ( ) . GetValue ( null ) ;
442471 }
443472
444- public static PythonTuple QueryValueEx ( object key , string valueName ) {
473+ public static PythonTuple QueryValueEx ( object key , string value_name ) {
445474 HKEYType rootKey = GetRootKey ( key ) ;
446475
447476 // it looks like rootKey.GetKey().Handle fails on HKEY_PERFORMANCE_DATA so manually create the handle instead
448477 var handle = rootKey . hkey == HKEY_PERFORMANCE_DATA ? new SafeRegistryHandle ( new IntPtr ( unchecked ( ( int ) 0x80000004 ) ) , true ) : rootKey . GetKey ( ) . Handle ;
449478
450479 int valueKind ;
451480 object value ;
452- QueryValueExImpl ( handle , valueName , out valueKind , out value ) ;
481+ QueryValueExImpl ( handle , value_name , out valueKind , out value ) ;
453482
454483 return PythonTuple . MakeTuple ( value , valueKind ) ;
455484 }
456485
457- public static void SetValue ( object key , string subKeyName , int type , string value ) {
458- HKEYType pyKey = CreateKey ( key , subKeyName ) ;
486+ public static void SetValue ( object key , string sub_key , int type , string value ) {
487+ HKEYType pyKey = CreateKey ( key , sub_key ) ;
459488 pyKey . GetKey ( ) . SetValue ( null , value ) ;
460489 }
461490
462- public static void SetValueEx ( object key , string valueName , object reserved , int type , object value ) {
491+ public static void SetValueEx ( object key , string value_name , object reserved , int type , object value ) {
463492 HKEYType rootKey = GetRootKey ( key ) ;
464493 RegistryValueKind regKind = ( RegistryValueKind ) type ;
465494
466495 // null is a valid value but RegistryKey.SetValue doesn't like it so PInvoke to set it
467496 if ( value == null ) {
468- RegSetValueEx ( rootKey . GetKey ( ) . Handle , valueName , 0 , type , null , 0 ) ;
497+ RegSetValueEx ( rootKey . GetKey ( ) . Handle , value_name , 0 , type , null , 0 ) ;
469498 return ;
470499 }
471500
472501 if ( regKind == RegistryValueKind . MultiString ) {
473502 int size = ( ( PythonList ) value ) . _size ;
474503 string [ ] strArray = new string [ size ] ;
475504 Array . Copy ( ( ( PythonList ) value ) . _data , strArray , size ) ;
476- rootKey . GetKey ( ) . SetValue ( valueName , strArray , regKind ) ;
505+ rootKey . GetKey ( ) . SetValue ( value_name , strArray , regKind ) ;
477506 } else if ( regKind == RegistryValueKind . Binary ) {
478507 byte [ ] byteArr = null ;
479508 if ( value is string ) {
480509 string strValue = value as string ;
481510 ASCIIEncoding encoding = new ASCIIEncoding ( ) ;
482511 byteArr = encoding . GetBytes ( strValue ) ;
512+ } else if ( value is Bytes ibytes ) {
513+ byteArr = ibytes . UnsafeByteArray ;
483514 }
484- rootKey . GetKey ( ) . SetValue ( valueName , byteArr , regKind ) ;
515+ rootKey . GetKey ( ) . SetValue ( value_name , byteArr , regKind ) ;
485516 } else if ( regKind == RegistryValueKind . DWord ) {
486517 // DWORDs are uint but the .NET API requires int
487518 if ( value is BigInteger ) {
488519 var val = ( uint ) ( BigInteger ) value ;
489520 value = unchecked ( ( int ) val ) ;
490521 }
491- rootKey . GetKey ( ) . SetValue ( valueName , value , regKind ) ;
522+ rootKey . GetKey ( ) . SetValue ( value_name , value , regKind ) ;
492523 } else if ( regKind == RegistryValueKind . QWord ) {
493524 // QWORDs are ulong but the .NET API requires long
494525 if ( value is BigInteger ) {
495526 var val = ( ulong ) ( BigInteger ) value ;
496527 value = unchecked ( ( long ) val ) ;
497528 }
498- rootKey . GetKey ( ) . SetValue ( valueName , value , regKind ) ;
529+ rootKey . GetKey ( ) . SetValue ( value_name , value , regKind ) ;
499530 } else {
500- rootKey . GetKey ( ) . SetValue ( valueName , value , regKind ) ;
531+ rootKey . GetKey ( ) . SetValue ( value_name , value , regKind ) ;
501532 }
502533
503534 }
504535
505- public static HKEYType ConnectRegistry ( string computerName , BigInteger key ) {
506- if ( string . IsNullOrEmpty ( computerName ) )
507- computerName = string . Empty ;
536+ public static HKEYType ConnectRegistry ( string computer_name , BigInteger key ) {
537+ if ( string . IsNullOrEmpty ( computer_name ) )
538+ computer_name = string . Empty ;
508539
509540 RegistryKey newKey = null ;
510541 try {
511- if ( computerName == string . Empty ) {
542+ if ( computer_name == string . Empty ) {
512543 newKey = RegistryKey . OpenBaseKey ( MapSystemKey ( key ) , RegistryView . Default ) ;
513544 }
514545 else {
515- newKey = RegistryKey . OpenRemoteBaseKey ( MapSystemKey ( key ) , computerName ) ;
546+ newKey = RegistryKey . OpenRemoteBaseKey ( MapSystemKey ( key ) , computer_name ) ;
516547 }
517548 }
518549 catch ( IOException ioe ) {
0 commit comments