Add autoconf checks for platforms without IPv6
[mono.git] / mcs / class / corlib / Microsoft.Win32 / RegistryKey.cs
1 //
2 // RegistryKey.cs: a single node in the Windows registry
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Erik LeBel (eriklebel@yahoo.ca)
7 //   Gert Driesen (drieseng@users.sourceforge.net)
8 //
9 //
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System;
33 using System.IO;
34 using System.Collections;
35 using System.Diagnostics;
36 using System.Runtime.InteropServices;
37 using System.Security;
38 using System.Text;
39 using System.Security.AccessControl;
40 using System.Security.Permissions;
41 using Microsoft.Win32.SafeHandles;
42
43 namespace Microsoft.Win32
44 {
45
46 #if MOBILE && !WIN_PLATFORM
47         public sealed class RegistryKey : IDisposable
48         {
49                 internal RegistryKey (RegistryHive hiveId)
50                 {
51                         throw new PlatformNotSupportedException ();
52                 }
53
54                 public void Dispose ()
55                 {
56                 }
57
58                 public RegistryKey CreateSubKey (string subkey)
59                 {
60                         throw new PlatformNotSupportedException ();
61                 }
62
63                 public RegistryKey CreateSubKey (String subkey, bool writable)
64                 {
65                         throw new PlatformNotSupportedException ();
66                 }
67
68                 public RegistryKey CreateSubKey (String subkey, bool writable, RegistryOptions options)
69                 {
70                         throw new PlatformNotSupportedException ();
71                 }
72
73                 public void DeleteSubKey (string subkey)
74                 {
75                 }
76
77                 public void DeleteSubKey (string subkey, bool throwOnMissingSubKey)
78                 {
79                 }
80
81                 public void DeleteSubKeyTree (string subkey)
82                 {
83                 }
84
85                 public void DeleteSubKeyTree (string subkey, bool throwOnMissingSubKey)
86                 {
87                 }
88
89                 public void DeleteValue (string name)
90                 {
91                 }
92
93                 public void DeleteValue (string name, bool throwOnMissingValue)
94                 {
95                 }
96
97                 public void Flush()
98                 {
99                 }
100
101                 public static RegistryKey FromHandle (SafeRegistryHandle handle)
102                 {
103                         throw new PlatformNotSupportedException ();
104                 }
105
106                 public static RegistryKey FromHandle (SafeRegistryHandle handle, RegistryView view)
107                 {
108                         throw new PlatformNotSupportedException ();
109                 }
110
111                 public string[] GetSubKeyNames ()
112                 {
113                         throw new PlatformNotSupportedException ();
114                 }
115
116                 public object GetValue (string name)
117                 {
118                         throw new PlatformNotSupportedException ();
119                 }
120
121                 public object GetValue (string name, object defaultValue)
122                 {
123                         throw new PlatformNotSupportedException ();
124                 }
125
126                 public object GetValue (string name, object defaultValue, RegistryValueOptions options)
127                 {
128                         throw new PlatformNotSupportedException ();
129                 }
130
131                 public RegistryValueKind GetValueKind (string name)
132                 {
133                         throw new PlatformNotSupportedException ();
134                 }
135
136                 public string[] GetValueNames ()
137                 {
138                         throw new PlatformNotSupportedException ();
139                 }
140
141                 public static RegistryKey OpenBaseKey (RegistryHive hKey, RegistryView view)
142                 {
143                         throw new PlatformNotSupportedException ();
144                 }
145
146                 public RegistryKey OpenSubKey (string name)
147                 {
148                         throw new PlatformNotSupportedException ();
149                 }
150
151                 public RegistryKey OpenSubKey (string name, bool writable)
152                 {
153                         throw new PlatformNotSupportedException ();
154                 }
155
156                 public RegistryKey OpenSubKey (string name, RegistryRights rights)
157                 {
158                         throw new PlatformNotSupportedException ();
159                 }
160
161                 public void SetValue (string name, object value)
162                 {
163                 }
164
165                 public void SetValue (string name, object value, RegistryValueKind valueKind)
166                 {
167                 }
168
169                 public SafeRegistryHandle Handle {
170                         get { throw new PlatformNotSupportedException (); }
171                 }
172
173                 public string Name {
174                         get { throw new PlatformNotSupportedException (); }
175                 }
176
177                 public int SubKeyCount {
178                         get { throw new PlatformNotSupportedException (); }
179                 }
180
181                 public int ValueCount {
182                         get { throw new PlatformNotSupportedException (); }
183                 }
184
185                 public RegistryView View {
186                         get { throw new PlatformNotSupportedException (); }
187                 }
188         }
189 #else
190         /// <summary>
191         ///     Wrapper class for Windows Registry Entry.
192         /// </summary>
193         [ComVisible (true)]
194         public sealed class RegistryKey : MarshalByRefObject, IDisposable 
195         {
196                 //
197                 // This represents the backend data, used when creating the
198                 // RegistryKey object
199                 //
200                 object handle;
201                 SafeRegistryHandle safe_handle;
202
203                 object hive; // the RegistryHive if the key represents a base key
204                 readonly string qname;  // the fully qualified registry key name
205                 readonly bool isRemoteRoot;     // is an instance of a remote root key?
206                 readonly bool isWritable;       // is the key openen in writable mode
207
208                 static readonly IRegistryApi RegistryApi;
209
210                 static RegistryKey ()
211                 {
212                         if (Path.DirectorySeparatorChar == '\\')
213                                 RegistryApi = new Win32RegistryApi ();
214                         else
215                                 RegistryApi = new UnixRegistryApi ();
216                 }
217
218                 /// <summary>
219                 ///     Construct an instance of a root registry key entry.
220                 /// </summary>
221                 internal RegistryKey (RegistryHive hiveId) : this (hiveId, 
222                         new IntPtr ((int) hiveId), false)
223                 {
224                 }
225
226                 /// <summary>
227                 ///     Construct an instance of a root registry key entry.
228                 /// </summary>
229                 internal RegistryKey (RegistryHive hiveId, IntPtr keyHandle, bool remoteRoot)
230                 {
231                         hive = hiveId;
232                         handle = keyHandle;
233                         qname = GetHiveName (hiveId);
234                         isRemoteRoot = remoteRoot;
235                         isWritable = true; // always consider root writable
236                 }
237
238                 /// <summary>
239                 ///     Construct an instance of a registry key entry.
240                 /// </summary>
241                 internal RegistryKey (object data, string keyName, bool writable)
242                 {
243                         handle = data;
244                         qname = keyName;
245                         isWritable = writable;
246                 }
247
248                 static internal bool IsEquals (RegistryKey a, RegistryKey b)
249                 {
250                         return a.hive == b.hive && a.handle == b.handle && a.qname == b.qname  && a.isRemoteRoot == b.isRemoteRoot && a.isWritable == b.isWritable;
251                 }
252
253                 #region PublicAPI
254
255                 /// <summary>
256                 ///     Dispose of registry key object. Close the 
257                 ///     key if it's still open.
258                 /// </summary>
259                 public void Dispose ()
260                 {
261                         GC.SuppressFinalize (this);
262                         Close ();
263                 }
264
265                 /// <summary>
266                 ///     Get the fully qualified registry key name.
267                 /// </summary>
268                 public string Name {
269                         get { return qname; }
270                 }
271         
272                 
273                 /// <summary>
274                 ///     Flush the current registry state to disk.
275                 /// </summary>
276                 public void Flush()
277                 {
278                         RegistryApi.Flush (this);
279                 }
280                 
281                 
282                 /// <summary>
283                 ///     Close the current registry key and flushes the state of the registry
284                 /// right away.
285                 /// </summary>
286                 public void Close()
287                 {
288                         Flush ();
289
290                         // a handle to a remote hive must be closed, while one to a local
291                         // hive should not be closed
292                         if (!isRemoteRoot && IsRoot)
293                                 return;
294                         
295                         RegistryApi.Close (this);
296                         handle = null;
297                         safe_handle = null;
298                 }
299                 
300                 
301                 /// <summary>
302                 ///     get the number of sub-keys for this key
303                 /// </summary>
304                 public int SubKeyCount {
305                         get {
306                                 AssertKeyStillValid ();
307
308                                 return RegistryApi.SubKeyCount (this);
309                         }
310                 }
311
312                 
313                 /// <summary>
314                 ///     get the number of values for this key
315                 /// </summary>
316                 public int ValueCount {
317                         get {
318                                 AssertKeyStillValid ();
319
320                                 return RegistryApi.ValueCount (this);
321                         }
322                 }
323
324                 [ComVisible (false)]
325                 [MonoTODO ("Not implemented in Unix")]
326                 public SafeRegistryHandle Handle {
327                         get {
328                                 AssertKeyStillValid ();
329
330                                 if (safe_handle == null) {
331                                         IntPtr h = RegistryApi.GetHandle (this);
332                                         safe_handle = new SafeRegistryHandle (h, true);
333                                 }
334
335                                 return safe_handle;
336                         }
337                 }
338
339                 [ComVisible (false)]
340                 [MonoLimitation ("View is ignored in Mono.")]
341                 public RegistryView View {
342                         get {
343                                 return RegistryView.Default;
344                         }
345                 }
346
347                 
348                 /// <summary>
349                 ///     Set a registry value.
350                 /// </summary>
351                 public void SetValue (string name, object value)
352                 {
353                         AssertKeyStillValid ();
354
355                         if (value == null)
356                                 throw new ArgumentNullException ("value");
357
358                         if (name != null)
359                                 AssertKeyNameLength (name);
360
361                         if (!IsWritable)
362                                 throw new UnauthorizedAccessException ("Cannot write to the registry key.");
363
364                         RegistryApi.SetValue (this, name, value);
365                 }
366
367                 [ComVisible (false)]
368                 public void SetValue (string name, object value, RegistryValueKind valueKind)
369                 {
370                         AssertKeyStillValid ();
371                         
372                         if (value == null)
373                                 throw new ArgumentNullException ("value");
374
375                         if (name != null)
376                                 AssertKeyNameLength (name);
377
378                         if (!IsWritable)
379                                 throw new UnauthorizedAccessException ("Cannot write to the registry key.");
380
381                         RegistryApi.SetValue (this, name, value, valueKind);
382                 }
383
384                 /// <summary>
385                 ///     Open the sub key specified, for read access.
386                 /// </summary>
387                 public RegistryKey OpenSubKey (string name)
388                 {
389                         return OpenSubKey (name, false);
390                 }
391
392                 
393                 /// <summary>
394                 ///     Open the sub key specified.
395                 /// </summary>
396                 public RegistryKey OpenSubKey (string name, bool writable)
397                 {
398                         AssertKeyStillValid ();
399
400                         if (name == null)
401                                 throw new ArgumentNullException ("name");
402
403                         AssertKeyNameLength (name);
404
405                         return RegistryApi.OpenSubKey (this, name, writable);
406                 }
407                 
408                 
409                 /// <summary>
410                 ///     Get a registry value.
411                 /// </summary>
412                 public object GetValue (string name)
413                 {
414                         return GetValue (name, null);
415                 }
416
417                 
418                 /// <summary>
419                 ///     Get a registry value.
420                 /// </summary>
421                 public object GetValue (string name, object defaultValue)
422                 {
423                         AssertKeyStillValid ();
424                         
425                         return RegistryApi.GetValue (this, name, defaultValue,
426                                 RegistryValueOptions.None);
427                 }
428
429                 [ComVisible (false)]
430                 public object GetValue (string name, object defaultValue, RegistryValueOptions options)
431                 {
432                         AssertKeyStillValid ();
433
434                         return RegistryApi.GetValue (this, name, defaultValue, options);
435                 }
436
437                 [ComVisible (false)]
438                 public RegistryValueKind GetValueKind (string name)
439                 {
440                         return RegistryApi.GetValueKind (this, name);
441                 }
442
443                 /// <summary>
444                 ///     Create a sub key.
445                 /// </summary>
446                 public RegistryKey CreateSubKey (string subkey)
447                 {
448                         AssertKeyStillValid ();
449                         AssertKeyNameNotNull (subkey);
450                         AssertKeyNameLength (subkey);
451
452                         if (!IsWritable)
453                                 throw new UnauthorizedAccessException ("Cannot write to the registry key.");
454                         return RegistryApi.CreateSubKey (this, subkey);
455                 }
456
457                 [ComVisible (false)]
458                 [MonoLimitation ("permissionCheck is ignored in Mono")]
459                 public RegistryKey CreateSubKey (string subkey, RegistryKeyPermissionCheck permissionCheck)
460                 {
461                         return CreateSubKey (subkey);
462                 }
463
464                 [ComVisible (false)]
465                 [MonoLimitation ("permissionCheck and registrySecurity are ignored in Mono")]
466                 public RegistryKey CreateSubKey (string subkey, RegistryKeyPermissionCheck permissionCheck, RegistrySecurity registrySecurity)
467                 {
468                         return CreateSubKey (subkey);
469                 }
470
471                 [ComVisible (false)]
472                 [MonoLimitation ("permissionCheck is ignored in Mono")]
473                 public RegistryKey CreateSubKey (string subkey, RegistryKeyPermissionCheck permissionCheck, RegistryOptions options)
474                 {
475                         AssertKeyStillValid ();
476                         AssertKeyNameNotNull (subkey);
477                         AssertKeyNameLength (subkey);
478
479                         if (!IsWritable)
480                                 throw new UnauthorizedAccessException ("Cannot write to the registry key.");
481
482                         return RegistryApi.CreateSubKey (this, subkey, options);
483                 }
484
485                 [ComVisible (false)]
486                 [MonoLimitation ("permissionCheck and registrySecurity are ignored in Mono")]
487                 public RegistryKey CreateSubKey (string subkey, RegistryKeyPermissionCheck permissionCheck, RegistryOptions registryOptions,
488                         RegistrySecurity registrySecurity)
489                 {
490                         return CreateSubKey (subkey, permissionCheck, registryOptions);
491                 }
492
493                 [ComVisible(false)]
494                 public RegistryKey CreateSubKey (string subkey, bool writable)
495                 {
496                         return CreateSubKey (subkey, writable ? RegistryKeyPermissionCheck.ReadWriteSubTree : RegistryKeyPermissionCheck.ReadSubTree);
497                 }
498
499                 [ComVisible(false)]
500                 public RegistryKey CreateSubKey (string subkey, bool writable, RegistryOptions options)
501                 {
502                         return CreateSubKey (subkey, writable ? RegistryKeyPermissionCheck.ReadWriteSubTree : RegistryKeyPermissionCheck.ReadSubTree, options);
503                 }
504
505                 /// <summary>
506                 ///     Delete the specified subkey.
507                 /// </summary>
508                 public void DeleteSubKey(string subkey)
509                 {
510                         DeleteSubKey (subkey, true);
511                 }
512                 
513                 
514                 /// <summary>
515                 ///     Delete the specified subkey.
516                 /// </summary>
517                 public void DeleteSubKey(string subkey, bool throwOnMissingSubKey)
518                 {
519                         AssertKeyStillValid ();
520                         AssertKeyNameNotNull (subkey);
521                         AssertKeyNameLength (subkey);
522
523                         if (!IsWritable)
524                                 throw new UnauthorizedAccessException ("Cannot write to the registry key.");
525
526                         RegistryKey child = OpenSubKey (subkey);
527                         
528                         if (child == null) {
529                                 if (throwOnMissingSubKey)
530                                         throw new ArgumentException ("Cannot delete a subkey tree"
531                                                 + " because the subkey does not exist.");
532                                 return;
533                         }
534
535                         if (child.SubKeyCount > 0){
536                                 throw new InvalidOperationException ("Registry key has subkeys"
537                                         + " and recursive removes are not supported by this method.");
538                         }
539                         
540                         child.Close ();
541
542                         RegistryApi.DeleteKey (this, subkey, throwOnMissingSubKey);
543                 }
544                 
545                 
546                 /// <summary>
547                 ///     Delete a sub tree (node, and values alike).
548                 /// </summary>
549                 public void DeleteSubKeyTree(string subkey)
550                 {
551                         DeleteSubKeyTree (subkey, true);
552                 }
553
554                 public
555                 void DeleteSubKeyTree (string subkey, bool throwOnMissingSubKey)
556                 {
557                         // Note: this is done by deleting sub-nodes recursively.
558                         // The preformance is not very good. There may be a 
559                         // better way to implement this.
560                         
561                         AssertKeyStillValid ();
562                         AssertKeyNameNotNull (subkey);
563                         AssertKeyNameLength (subkey);
564                         
565                         RegistryKey child = OpenSubKey (subkey, true);
566                         if (child == null) {
567                                 if (!throwOnMissingSubKey)
568                                         return;
569
570                                 throw new ArgumentException ("Cannot delete a subkey tree"
571                                         + " because the subkey does not exist.");
572                         }
573
574                         child.DeleteChildKeysAndValues ();
575                         child.Close ();
576                         DeleteSubKey (subkey, false);
577                 }
578                 
579
580                 /// <summary>
581                 ///     Delete a value from the registry.
582                 /// </summary>
583                 public void DeleteValue(string name)
584                 {
585                         DeleteValue (name, true);
586                 }
587                 
588                 
589                 /// <summary>
590                 ///     Delete a value from the registry.
591                 /// </summary>
592                 public void DeleteValue(string name, bool throwOnMissingValue)
593                 {
594                         AssertKeyStillValid ();
595
596                         if (name == null)
597                                 throw new ArgumentNullException ("name");
598
599                         if (!IsWritable)
600                                 throw new UnauthorizedAccessException ("Cannot write to the registry key.");
601
602                         RegistryApi.DeleteValue (this, name, throwOnMissingValue);
603                 }
604
605                 public RegistrySecurity GetAccessControl ()
606                 {
607                         return GetAccessControl (AccessControlSections.Owner |
608                                                  AccessControlSections.Group |
609                                                  AccessControlSections.Access);
610                 }
611                 
612                 public RegistrySecurity GetAccessControl (AccessControlSections includeSections)
613                 {
614                         return new RegistrySecurity (Name, includeSections);
615                 }
616                 
617                 
618                 /// <summary>
619                 ///     Get the names of the sub keys.
620                 /// </summary>
621                 public string[] GetSubKeyNames()
622                 {
623                         AssertKeyStillValid ();
624
625                         return RegistryApi.GetSubKeyNames (this);
626                 }
627                 
628                 
629                 /// <summary>
630                 ///     Get the names of values contained in this key.
631                 /// </summary>
632                 public string[] GetValueNames()
633                 {
634                         AssertKeyStillValid ();
635                         return RegistryApi.GetValueNames (this);
636                 }
637
638                 [ComVisible (false)]
639                 [SecurityPermission (SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
640                 [MonoTODO ("Not implemented on unix")]
641                 public static RegistryKey FromHandle (SafeRegistryHandle handle)
642                 {
643                         if (handle == null)
644                                 throw new ArgumentNullException ("handle");
645
646                         return RegistryApi.FromHandle (handle);
647                 }
648
649                 [ComVisible (false)]
650                 [SecurityPermission (SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
651                 [MonoTODO ("Not implemented on unix")]
652                 public static RegistryKey FromHandle (SafeRegistryHandle handle, RegistryView view)
653                 {
654                         return FromHandle (handle);
655                 }
656                 
657                 
658                 [MonoTODO ("Not implemented on unix")]
659                 public static RegistryKey OpenRemoteBaseKey(RegistryHive hKey,string machineName)
660                 {
661                         if (machineName == null)
662                                 throw new ArgumentNullException ("machineName");
663                         return RegistryApi.OpenRemoteBaseKey (hKey, machineName);
664                 }
665
666                 [ComVisible (false)]
667                 [MonoTODO ("Not implemented on unix")]
668                 public static RegistryKey OpenRemoteBaseKey (RegistryHive hKey, string machineName, RegistryView view)
669                 {
670                         if (machineName == null)
671                                 throw new ArgumentNullException ("machineName");
672                         return RegistryApi.OpenRemoteBaseKey (hKey, machineName);
673                 }
674
675                 [ComVisible (false)]
676                 [MonoLimitation ("View is ignored in Mono")]
677                 public static RegistryKey OpenBaseKey (RegistryHive hKey, RegistryView view)
678                 {
679                         switch (hKey) {
680                                 case RegistryHive.ClassesRoot:
681                                         return Registry.ClassesRoot;
682                                 case RegistryHive.CurrentConfig:
683                                         return Registry.CurrentConfig;
684                                 case RegistryHive.CurrentUser:
685                                         return Registry.CurrentUser;
686                                 case RegistryHive.DynData:
687                                         return Registry.DynData;
688                                 case RegistryHive.LocalMachine:
689                                         return Registry.LocalMachine;
690                                 case RegistryHive.PerformanceData:
691                                         return Registry.PerformanceData;
692                                 case RegistryHive.Users:
693                                         return Registry.Users;
694                         }
695
696                         throw new ArgumentException ("hKey");
697                 }
698
699                 [ComVisible (false)]
700                 public RegistryKey OpenSubKey (string name, RegistryKeyPermissionCheck permissionCheck)
701                 {
702                         return OpenSubKey (name, permissionCheck == RegistryKeyPermissionCheck.ReadWriteSubTree);
703                 }
704
705                 [ComVisible (false)]
706                 [MonoLimitation ("rights are ignored in Mono")]
707                 public RegistryKey OpenSubKey (string name, RegistryRights rights)
708                 {
709                         return OpenSubKey (name);
710                 }
711
712                 [ComVisible (false)]
713                 [MonoLimitation ("rights are ignored in Mono")]
714                 public RegistryKey OpenSubKey (string name, RegistryKeyPermissionCheck permissionCheck, RegistryRights rights)
715                 {
716                         return OpenSubKey (name, permissionCheck == RegistryKeyPermissionCheck.ReadWriteSubTree);
717                 }
718                 
719                 public void SetAccessControl (RegistrySecurity registrySecurity)
720                 {
721                         if (null == registrySecurity)
722                                 throw new ArgumentNullException ("registrySecurity");
723                                 
724                         registrySecurity.PersistModifications (Name);
725                 }
726                 
727                 
728                 /// <summary>
729                 ///     Build a string representation of the registry key.
730                 ///     Conatins the fully qualified key name, and the Hex
731                 ///     representation of the registry key handle.
732                 /// </summary>
733                 public override string ToString()
734                 {
735                         AssertKeyStillValid ();
736
737                         return RegistryApi.ToString (this);
738                 }
739
740                 #endregion // PublicAPI
741
742                 internal bool IsRoot {
743                         get { return hive != null; }
744                 }
745
746                 private bool IsWritable {
747                         get { return isWritable; }
748                 }
749
750                 internal RegistryHive Hive {
751                         get {
752                                 if (!IsRoot)
753                                         throw new NotSupportedException ();
754                                 return (RegistryHive) hive;
755                         }
756                 }
757
758                 // returns the key handle for the win32 implementation and the
759                 // KeyHandler for the unix implementation
760                 internal object InternalHandle {
761                         get { return handle; }
762                 }
763
764                 /// <summary>
765                 /// validate that the registry key handle is still usable.
766                 /// </summary>
767                 private void AssertKeyStillValid ()
768                 {
769                         if (handle == null)
770                                 throw new ObjectDisposedException ("Microsoft.Win32.RegistryKey");
771                 }
772
773                 
774                 /// <summary>
775                 /// validate that the registry key handle is still usable, and
776                 /// that the 'subKeyName' is not null.
777                 /// </summary>
778                 private void AssertKeyNameNotNull (string subKeyName)
779                 {
780                         if (subKeyName == null)
781                                 throw new ArgumentNullException ("name");
782                 }
783
784                 private void AssertKeyNameLength (string name)
785                 {
786                         if (name.Length > 255)
787                                 throw new ArgumentException ("Name of registry key cannot be greater than 255 characters");
788                 }
789
790                 /// <summary>
791                 ///     Utility method to delelte a key's sub keys and values.
792                 ///     This method removes a level of indirection when deleting
793                 ///     key node trees.
794                 /// </summary>
795                 private void DeleteChildKeysAndValues ()
796                 {
797                         if (IsRoot)
798                                 return;
799                         
800                         string[] subKeys = GetSubKeyNames ();
801                         foreach (string subKey in subKeys)
802                         {
803                                 RegistryKey sub = OpenSubKey (subKey, true);
804                                 sub.DeleteChildKeysAndValues ();
805                                 sub.Close ();
806                                 DeleteSubKey (subKey, false);
807                         }
808
809                         string[] values = GetValueNames ();
810                         foreach (string value in values) {
811                                 DeleteValue (value, false);
812                         }
813                 }
814
815                 /// <summary>
816                 ///     decode a byte array as a string, and strip trailing nulls
817                 /// </summary>
818                 static internal string DecodeString (byte[] data)
819                 {
820                         string stringRep = Encoding.Unicode.GetString (data);
821                         int idx = stringRep.IndexOf ('\0');
822                         if (idx != -1)
823                                 stringRep = stringRep.TrimEnd ('\0');
824                         return stringRep;
825                 }
826
827                 static internal IOException CreateMarkedForDeletionException ()
828                 {
829                         throw new IOException ("Illegal operation attempted on a"
830                                 + " registry key that has been marked for deletion.");
831                 }
832
833                 static string GetHiveName (RegistryHive hive)
834                 {
835                         switch (hive) {
836                         case RegistryHive.ClassesRoot:
837                                 return "HKEY_CLASSES_ROOT";
838                         case RegistryHive.CurrentConfig:
839                                 return "HKEY_CURRENT_CONFIG";
840                         case RegistryHive.CurrentUser:
841                                 return "HKEY_CURRENT_USER";
842                         case RegistryHive.DynData:
843                                 return "HKEY_DYN_DATA";
844                         case RegistryHive.LocalMachine:
845                                 return "HKEY_LOCAL_MACHINE";
846                         case RegistryHive.PerformanceData:
847                                 return "HKEY_PERFORMANCE_DATA";
848                         case RegistryHive.Users:
849                                 return "HKEY_USERS";
850                         }
851
852                         throw new NotImplementedException (string.Format (
853                                 "Registry hive '{0}' is not implemented.", hive.ToString ()));
854                 }
855
856         }
857 #endif
858 }
859