Add license and copyright to all source files in corlib
[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 //
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
40 namespace Microsoft.Win32
41 {
42         /// <summary>
43         ///     Wrapper class for Windows Registry Entry.
44         /// </summary>
45         public sealed class RegistryKey : MarshalByRefObject, IDisposable 
46         {
47                 const char NullChar = '\0';
48                 
49                 // Arbitrary max size for key/values names that can be fetched.
50                 // .NET framework SDK docs say that the max name length that can 
51                 // be used is 255 characters, we'll allow for a bit more.
52                 const int BufferMaxLength = 1024;
53
54                 // FIXME must be a way to determin this dynamically?
55                 const int Int32ByteSize = 4;
56
57                 // FIXME this is hard coded on Mono, can it be determined dynamically? 
58                 readonly int NativeBytesPerCharacter = Marshal.SystemDefaultCharSize;
59
60                 // FIXME this should be determined dynamically.
61                 // It will be used to decode some return strings
62                 // for which embeded '\0' must be preserved.
63                 readonly Encoding Decoder = Encoding.Unicode;
64                 
65                 
66                 IntPtr hkey;    // the reg key handle
67                 string qname;   // the fully qualified registry key name
68                 bool isRoot;    // is the an instance of a root key?
69                 
70                 IRegistryApi reg_api;
71
72                 /// <summary>
73                 ///     Construct an instance of a root registry key entry.
74                 /// </summary>
75                 internal RegistryKey (RegistryHive hiveId, string keyName)
76                 {
77                         hkey = new IntPtr ((int)hiveId);
78                         qname = keyName;
79                         isRoot = true;
80
81                         InitRegistryApi ();
82                 }
83                 
84                 /// <summary>
85                 ///     Construct an instance of a registry key entry.
86                 /// </summary>
87                 internal RegistryKey (IntPtr hkey, string keyName)
88                 {
89                         this.hkey = hkey;
90                         qname = keyName;
91                         isRoot = false;
92
93                         InitRegistryApi ();
94                 }
95
96                 internal void InitRegistryApi ()
97                 {
98                         if (Path.DirectorySeparatorChar == '\\')
99                                 reg_api = new Win32RegistryApi ();
100                 }
101
102                 private IRegistryApi RegistryApi {
103                         get {
104                                 if (reg_api == null)
105                                         throw new NotImplementedException ("The registry is" +
106                                                         " only available on Windows.");
107                                 return reg_api;
108                         }
109                 }
110
111                 /// <summary>
112                 ///     Fetch the inetrnal registry key.
113                 /// </summary>
114                 private IntPtr Handle {
115                         get { return hkey; }
116                 }
117
118                 
119                 #region PublicAPI
120
121                 /// <summary>
122                 ///     Dispose of registry key object. Close the 
123                 ///     key if it's still open.
124                 /// </summary>
125                 void IDisposable.Dispose ()
126                 {
127                         Close ();
128                         GC.SuppressFinalize (this);
129                 }
130
131                 
132                 /// <summary>
133                 ///     Final cleanup of registry key object. Close the 
134                 ///     key if it's still open.
135                 /// </summary>
136                 ~RegistryKey ()
137                 {
138                         Close ();
139                 }
140
141                 
142                 /// <summary>
143                 ///     Get the fully qualified registry key name.
144                 /// </summary>
145                 public string Name {
146                         get { return qname; }
147                 }
148         
149                 
150                 /// <summary>
151                 ///     Flush the current registry state to disk.
152                 /// </summary>
153                 public void Flush()
154                 {
155                         RegTrace (" +Flush");
156                         RegistryApi.RegFlushKey (Handle);
157                         RegTrace (" -Flush");
158                 }
159                 
160                 
161                 /// <summary>
162                 ///     Close the current registry key. This may not 
163                 ///     flush the state of the registry right away.
164                 /// </summary>
165                 public void Close()
166                 {
167                         if (isRoot)
168                                 return;
169                         
170                         RegTrace (" +Close");
171                         RegistryApi.RegCloseKey (Handle);
172                         hkey = IntPtr.Zero;
173                         RegTrace (" -Close");
174                 }
175                 
176                 
177                 /// <summary>
178                 ///     get the number of sub-keys for this key
179                 /// </summary>
180                 public int SubKeyCount {
181                         get {
182                                 RegTrace (" +SubKeyCount");
183                                 AssertKeyStillValid ();
184                                 
185                                 int index, result;
186                                 byte[] stringBuffer = new byte [BufferMaxLength];
187
188                                 for (index = 0; true; index ++)
189                                 {
190                                         result = RegistryApi.RegEnumKey (Handle, index, 
191                                                         stringBuffer, BufferMaxLength);
192                                         
193                                         if (result == Win32ResultCode.Success)
194                                                 continue;
195                                         
196                                         if (result == Win32ResultCode.NoMoreEntries)
197                                                 break;
198                                         
199                                         // something is wrong!!
200                                         RegTrace ("Win32Api::ReEnumKey  result='{0}'  name='{1}'", 
201                                                         result, Name);
202                                         GenerateException (result);
203                                 }
204                                 
205                                 RegTrace (" -SubKeyCount");
206                                 return index;
207                         }
208                 }
209
210                 
211                 /// <summary>
212                 ///     get the number of values for this key
213                 /// </summary>
214                 public int ValueCount {
215                         get {
216                                 RegTrace (" +ValueCount");      
217                                 AssertKeyStillValid ();
218                         
219                                 int index, result, type, bufferCapacity;
220                                 StringBuilder buffer = new StringBuilder (BufferMaxLength);
221                                 
222                                 for (index = 0; true; index ++)
223                                 {
224                                         type = 0;
225                                         bufferCapacity = buffer.Capacity;
226                                         result = RegistryApi.RegEnumValue (Handle, index, 
227                                                         buffer, ref bufferCapacity,
228                                                         IntPtr.Zero, ref type, 
229                                                         IntPtr.Zero, IntPtr.Zero);
230
231                                         if (result == Win32ResultCode.Success || result == Win32ResultCode.MoreData)
232                                                 continue;
233                                         
234                                         if (result == Win32ResultCode.NoMoreEntries)
235                                                 break;
236
237                                         // something is wrong
238                                         RegTrace ("Win32Api::RegEnumValue  result='{0}'  name='{1}'", 
239                                                         result, Name);
240                                         GenerateException (result);
241                                 }
242
243                                 RegTrace (" -ValueCount");
244                                 return index;
245                         }
246                 }
247
248                 
249                 /// <summary>
250                 ///     Set a registry value.
251                 /// </summary>
252                 public void SetValue (string name, object value)
253                 {
254                         RegTrace (" +SetValue");
255                         AssertKeyStillValid ();
256                         
257                         if (value == null)
258                                 throw new ArgumentNullException ();
259                         
260                         Type type = value.GetType ();
261                         int result;
262
263                         if (type == typeof (int))
264                         {
265                                 int rawValue = (int)value;
266                                 result = RegistryApi.RegSetValueEx (Handle, name, 
267                                                 IntPtr.Zero, RegistryApi.RegDwordType, 
268                                                 ref rawValue, Int32ByteSize); 
269                         }
270                         else if (type == typeof (byte[]))
271                         {
272                                 byte[] rawValue = (byte[]) value;
273                                 result = RegistryApi.RegSetValueEx (Handle, name,
274                                                 IntPtr.Zero, RegistryApi.RegBinaryType,
275                                                 rawValue, rawValue.Length);
276                         }
277                         else if (type == typeof (string[]))
278                         {
279                                 string[] vals = (string[]) value;
280                                 StringBuilder fullStringValue = new StringBuilder ();
281                                 foreach (string v in vals)
282                                 {
283                                         fullStringValue.Append (v);
284                                         fullStringValue.Append (NullChar);
285                                 }
286                                 fullStringValue.Append (NullChar);
287
288                                 byte[] rawValue = Decoder.GetBytes (fullStringValue.ToString ());
289                         
290                                 result = RegistryApi.RegSetValueEx (Handle, name, 
291                                                 IntPtr.Zero, RegistryApi.RegStringArrayType, 
292                                                 rawValue, rawValue.Length); 
293                         }
294                         else if (type.IsArray)
295                         {
296                                 throw new ArgumentException ("Only string and byte arrays can written as registry values");
297                         }
298                         else
299                         {
300                                 string rawValue = String.Format ("{0}{1}", value, NullChar);
301                                 result = RegistryApi.RegSetValueEx (Handle, name,
302                                                 IntPtr.Zero, RegistryApi.RegStringType,
303                                                 rawValue, rawValue.Length * NativeBytesPerCharacter);
304                         }
305
306                         // handle the result codes
307                         if (result != Win32ResultCode.Success)
308                         {
309                                 RegTrace ("Win32Api::RegSetValueEx: result: {0}", result);
310                                 GenerateException (result);
311                         }
312                         
313                         RegTrace (" -SetValue");
314                 }
315
316                 
317                 /// <summary>
318                 ///     Open the sub key specified, for read access.
319                 /// </summary>
320                 public RegistryKey OpenSubKey (string keyName)
321                 {
322                         return OpenSubKey (keyName, false);
323                 }
324
325                 
326                 /// <summary>
327                 ///     Open the sub key specified.
328                 /// </summary>
329                 public RegistryKey OpenSubKey (string keyName, bool writtable)
330                 {
331                         RegTrace (" +OpenSubKey");
332                         AssertKeyStillValid ();
333                         AssertKeyNameNotNull (keyName);
334                         
335                         int access = RegistryApi.OpenRegKeyRead;
336                         if (writtable) access |= RegistryApi.OpenRegKeyWrite;
337                         
338                         IntPtr subKeyHandle;
339                         int result = RegistryApi.RegOpenKeyEx (Handle, keyName, IntPtr.Zero, 
340                                         access, out subKeyHandle);
341
342                         if (result == Win32ResultCode.FileNotFound)
343                         {
344                                 RegTrace (" -OpenSubKey");
345                                 return null;
346                         }
347                         
348                         if (result != Win32ResultCode.Success)
349                         {
350                                 RegTrace ("Win32Api::RegOpenKeyEx  result='{0}'  key name='{1}'", 
351                                                 result, CombineName (keyName));
352                                 GenerateException (result);
353                         }
354                         
355                         RegistryKey subKey = new RegistryKey (subKeyHandle, CombineName (keyName));
356                         RegTrace (" -OpenSubKey");
357                         return subKey;
358                 }
359                 
360                 
361                 /// <summary>
362                 ///     Get a registry value.
363                 /// </summary>
364                 public object GetValue (string name)
365                 {
366                         RegTrace (" +GetValue");
367                         object obj = GetValueImpl (name, false, null);
368                         RegTrace (" -GetValue");
369                         return obj;
370                 }
371
372                 
373                 /// <summary>
374                 ///     Get a registry value.
375                 /// </summary>
376                 public object GetValue (string name, object defaultValue)
377                 {
378                         RegTrace (" +GetValue");
379                         object obj = GetValueImpl (name, true, defaultValue);
380                         RegTrace (" -GetValue");
381                         return obj;
382                 }
383
384                 
385                 /// <summary>
386                 ///     Create a sub key.
387                 /// </summary>
388                 public RegistryKey CreateSubKey (string keyName)
389                 {
390                         RegTrace (" +CreateSubKey");
391                         AssertKeyStillValid ();
392                         AssertKeyNameNotNull (keyName);
393                         
394                         IntPtr subKeyHandle;
395                         int result = RegistryApi.RegCreateKey (Handle , keyName, out subKeyHandle);
396
397                         if (result != Win32ResultCode.Success)
398                         {
399                                 RegTrace ("Win32Api::RegCreateKey: result='{0}' key name='{1}'", 
400                                                 result, CombineName (keyName));
401                                 GenerateException (result);
402                         }
403                         
404                         RegistryKey subKey = new RegistryKey (subKeyHandle, CombineName (keyName));
405                         RegTrace (" -CreateSubKey");
406                         return subKey;
407                 }
408                 
409                 
410                 /// <summary>
411                 ///     Delete the specified subkey.
412                 /// </summary>
413                 public void DeleteSubKey(string subkey)
414                 {
415                         DeleteSubKey (subkey, true);
416                 }
417                 
418                 
419                 /// <summary>
420                 ///     Delete the specified subkey.
421                 /// </summary>
422                 public void DeleteSubKey(string keyName, bool shouldThrowWhenKeyMissing)
423                 {
424                         RegTrace (" +DeleteSubKey");
425                         AssertKeyStillValid ();
426                         AssertKeyNameNotNull (keyName);
427                         
428                         RegistryKey child = OpenSubKey (keyName);
429                         
430                         if (child == null)
431                         {
432                                 if (shouldThrowWhenKeyMissing)
433                                         throw new ArgumentException ("key " + keyName);
434                                 RegTrace (" -DeleteSubKey");
435                                 return;
436                         }
437
438                         if (child.SubKeyCount > 0)
439                                 throw new InvalidOperationException ("key " + keyName + " has sub keys");
440                         
441                         child.Close ();
442
443                         int result = RegistryApi.RegDeleteKey (Handle, keyName);
444                         if (result == Win32ResultCode.FileNotFound)
445                         {
446                                 if (shouldThrowWhenKeyMissing)
447                                         throw new ArgumentException ("key " + keyName);
448                                 RegTrace (" -DeleteSubKey");
449                                 return;
450                         }
451                         
452                         if (result != Win32ResultCode.Success)
453                         {
454                                 RegTrace ("Win32Api::RegDeleteKey: result='{0}' key name='{1}'", 
455                                                 result, CombineName (keyName));
456                                 GenerateException (result);
457                         }
458
459                         RegTrace (" -DeleteSubKey");
460                 }
461                 
462                 
463                 /// <summary>
464                 ///     Delete a sub tree (node, and values alike).
465                 /// </summary>
466                 public void DeleteSubKeyTree(string keyName)
467                 {
468                         // Note: this is done by deleting sub-nodes recursively.
469                         // The preformance is not very good. There may be a 
470                         // better way to implement this.
471                         RegTrace (" +DeleteSubKeyTree");
472                         AssertKeyStillValid ();
473                         AssertKeyNameNotNull (keyName);
474                         
475                         RegistryKey child = OpenSubKey (keyName, true);
476                         if (child == null)
477                                 throw new ArgumentException ("key " + keyName);
478
479                         child.DeleteChildKeysAndValues ();
480                         child.Close ();
481                         DeleteSubKey (keyName, false);
482                         RegTrace (" -DeleteSubKeyTree");
483                 }
484                 
485
486                 /// <summary>
487                 ///     Delete a value from the registry.
488                 /// </summary>
489                 public void DeleteValue(string value)
490                 {
491                         DeleteValue (value, true);
492                 }
493                 
494                 
495                 /// <summary>
496                 ///     Delete a value from the registry.
497                 /// </summary>
498                 public void DeleteValue(string value, bool shouldThrowWhenKeyMissing)
499                 {
500                         RegTrace (" +DeleteValue");
501                         AssertKeyStillValid ();
502                         AssertKeyNameNotNull (value);
503                         
504                         int result = RegistryApi.RegDeleteValue (Handle, value);
505                         
506                         if (result == Win32ResultCode.FileNotFound)
507                         {
508                                 if (shouldThrowWhenKeyMissing)
509                                         throw new ArgumentException ("value " + value);
510                                 RegTrace (" -DeleteValue");
511                                 return;
512                         }
513                         
514                         if (result != Win32ResultCode.Success)
515                         {
516                                 RegTrace ("Win32Api::RegDeleteValue: result='{0}' value name='{1}'", 
517                                                 result, CombineName (value));
518                                 GenerateException (result);
519                         }
520                         
521                         RegTrace (" -DeleteValue");
522                 }
523                 
524                 
525                 /// <summary>
526                 ///     Get the names of the sub keys.
527                 /// </summary>
528                 public string[] GetSubKeyNames()
529                 {
530                         RegTrace (" +GetSubKeyNames");
531                         AssertKeyStillValid ();
532                         
533                         byte[] buffer = new byte [BufferMaxLength];
534                         int bufferCapacity = BufferMaxLength;
535                         ArrayList keys = new ArrayList ();
536                                 
537                         for (int index = 0; true; index ++)
538                         {
539                                 int result = RegistryApi.RegEnumKey (Handle, index, buffer, bufferCapacity);
540
541                                 if (result == Win32ResultCode.Success)
542                                 {
543                                         keys.Add (DecodeString (buffer));
544                                         continue;
545                                 }
546
547                                 if (result == Win32ResultCode.NoMoreEntries)
548                                         break;
549
550                                 // should not be here!
551                                 RegTrace ("Win32Api::RegEnumKey: result='{0}' value name='{1}'", 
552                                                 result, CombineName (Name));
553                                 GenerateException (result);
554                         }
555
556                         RegTrace (" -GetSubKeyNames");
557                         return (string []) keys.ToArray (typeof(String));
558                 }
559                 
560                 
561                 /// <summary>
562                 ///     Get the names of values contained in this key.
563                 /// </summary>
564                 public string[] GetValueNames()
565                 {
566                         RegTrace (" +GetValueNames");
567                         AssertKeyStillValid ();
568                         
569                         ArrayList values = new ArrayList ();
570                         
571                         for (int index = 0; true; index ++)
572                         {
573                                 StringBuilder buffer = new StringBuilder (BufferMaxLength);
574                                 int bufferCapacity = buffer.Capacity;
575                                 int type = 0;
576                                 
577                                 int result = RegistryApi.RegEnumValue (Handle, index, buffer, ref bufferCapacity,
578                                                         IntPtr.Zero, ref type, IntPtr.Zero, IntPtr.Zero);
579
580                                 if (result == Win32ResultCode.Success || result == Win32ResultCode.MoreData)
581                                 {
582                                         values.Add (buffer.ToString ());
583                                         continue;
584                                 }
585                                 
586                                 if (result == Win32ResultCode.NoMoreEntries)
587                                         break;
588                                         
589                                 // should not be here!
590                                 RegTrace ("RegistryApi.RegEnumValue: result code='{0}' name='{1}'", 
591                                                 result, CombineName (Name));
592                                 GenerateException (result);
593                         }
594
595                         RegTrace (" -GetValueNames");
596                         return (string []) values.ToArray (typeof(String));
597                 }
598                 
599                 
600                 [MonoTODO]
601                 public static RegistryKey OpenRemoteBaseKey(RegistryHive hKey,string machineName)
602                 {
603                         throw new NotImplementedException ();
604                 }
605                 
606                 
607                 /// <summary>
608                 ///     Build a string representation of the registry key.
609                 ///     Conatins the fully qualified key name, and the Hex
610                 ///     representation of the registry key handle.
611                 /// </summary>
612                 public override string ToString()
613                 {
614                         return String.Format ("{0} [0x{1:X}]", Name, Handle.ToInt32 ());
615                 }
616
617                 #endregion // PublicAPI
618
619                 
620                 /// <summary>
621                 /// validate that the registry key handle is still usable.
622                 /// </summary>
623                 private void AssertKeyStillValid ()
624                 {
625                         if (Handle == IntPtr.Zero)
626                                 throw new ObjectDisposedException ("Microsoft.Win32.RegistryKey");
627                 }
628
629                 
630                 /// <summary>
631                 /// validate that the registry key handle is still usable, and
632                 /// that the 'subKeyName' is not null.
633                 /// </summary>
634                 private void AssertKeyNameNotNull (string subKeyName)
635                 {
636                         if (subKeyName == null)
637                                 throw new ArgumentNullException ();
638                 }
639                 
640
641                 /// <summary>
642                 ///     Utility method to delelte a key's sub keys and values.
643                 ///     This method removes a level of indirection when deleting
644                 ///     key node trees.
645                 /// </summary>
646                 private void DeleteChildKeysAndValues ()
647                 {
648                         RegTrace (" +DeleteChildKeysAndValues");
649                         if (isRoot)
650                         {
651                                 RegTrace (" -DeleteChildKeysAndValues");
652                                 return;
653                         }
654                         
655                         string[] subKeys = GetSubKeyNames ();
656                         foreach (string subKey in subKeys)
657                         {
658                                 RegistryKey sub = OpenSubKey (subKey, true);
659                                 sub.DeleteChildKeysAndValues ();
660                                 sub.Close ();
661                                 DeleteSubKey (subKey, false);
662                         }
663
664                         string[] values = GetValueNames ();
665                         foreach (string value in values)
666                         {
667                                 DeleteValue (value, false);
668                         }
669                         
670                         RegTrace (" -DeleteChildKeysAndValues");
671                 }
672
673
674                 /// <summary>
675                 ///     Acctually read a registry value. Requires knoledge of the
676                 ///     value's type and size.
677                 /// </summary>
678                 private object GetValueImpl (string name, bool returnDefaultValue, object defaultValue)
679                 {
680                         RegTrace (" +GetValueImpl");
681                         AssertKeyStillValid ();
682                         
683                         int type = 0;
684                         int size = 0;
685                         object obj = null;
686                         
687                         int result = RegistryApi.RegQueryValueEx (Handle, name, IntPtr.Zero,
688                                         ref type, IntPtr.Zero, ref size);
689                 
690                         if (returnDefaultValue && result == Win32ResultCode.FileNotFound)
691                         {
692                                 RegTrace (" -GetValueImpl");
693                                 return defaultValue;
694                         }
695                         
696                         if (result != Win32ResultCode.MoreData && result != Win32ResultCode.Success )
697                         {
698                                 RegTrace ("Win32Api::RegQueryValueEx: result='{0}'  name='{1}'  type='{2}'  size='{3}'",        
699                                                 result, name, type, size);
700                                 GenerateException (result);
701                         }
702                         
703                         if (type == RegistryApi.RegStringType || type == RegistryApi.RegEnvironmentString)
704                         {
705                                 byte[] data;
706                                 result = GetBinaryValue (name, type, out data, size);
707                                 obj = DecodeString (data);
708                         }
709                         else if (type == RegistryApi.RegDwordType)
710                         {
711                                 int data = 0;
712                                 result = RegistryApi.RegQueryValueEx (Handle, name, IntPtr.Zero,
713                                                 ref type, ref data, ref size);
714                                 obj = data;
715                         }
716                         else if (type == RegistryApi.RegBinaryType)
717                         {
718                                 byte[] data;
719                                 result = GetBinaryValue (name, type, out data, size);
720                                 obj = data;
721                         }
722                         else if (type == RegistryApi.RegStringArrayType)
723                         {
724                                 obj = null;
725                                 byte[] data;
726                                 result = GetBinaryValue (name, type, out data, size);
727                                 
728                                 if (result == Win32ResultCode.Success)
729                                         obj = DecodeString (data).Split (NullChar);
730                         }
731                         else
732                         {
733                                 // should never get here
734                                 throw new SystemException ();
735                         }
736
737                         // check result codes again:
738                         if (result != Win32ResultCode.Success)
739                         {
740                                 RegTrace ("Win32Api::RegQueryValueEx: result='{0}' name='{1}'", 
741                                                 result, name);
742                                 GenerateException (result);
743                         }
744                         
745                         RegTrace (" -ReadValueImpl");
746                         return obj;
747                 }
748
749                 
750                 /// <summary>
751                 ///     Get a binary value.
752                 /// </summary>
753                 private int GetBinaryValue (string name, int type, out byte[] data, int size)
754                 {
755                         byte[] internalData = new byte [size];
756                         int result = RegistryApi.RegQueryValueEx (Handle, name, 
757                                         IntPtr.Zero, ref type, internalData, ref size);
758                         data = internalData;
759                         return result;
760                 }
761
762                 
763                 /// <summary>
764                 ///     decode a byte array as a string, and strip trailing nulls
765                 /// </summary>
766                 private string DecodeString (byte[] data)
767                 {
768                         string stringRep = Decoder.GetString (data);
769                         return stringRep.TrimEnd (NullChar);
770                 }
771                 
772                 
773                 /// <summary>
774                 ///     utility: Combine the sub key name to the current name to produce a 
775                 ///     fully qualified sub key name.
776                 /// </summary>
777                 private string CombineName (string localName)
778                 {
779                         return String.Format ("{0}\\{1}", Name, localName);
780                 }
781                 
782                 
783                 /// <summary>
784                 /// convert a win32 error code into an appropriate exception.
785                 /// </summary>
786                 private void GenerateException (int errorCode)
787                 {
788                         switch (errorCode) {
789                                 case Win32ResultCode.FileNotFound:
790                                 case Win32ResultCode.InvalidParameter:
791                                         throw new ArgumentException ();
792                                 
793                                 case Win32ResultCode.AccessDenied:
794                                         throw new SecurityException ();
795
796                                 default:
797                                         // unidentified system exception
798                                         throw new SystemException ();
799                         }
800                 }
801                 
802 #if (false)
803                 /// <summary>
804                 ///     dump trace messages if this code was compiled with tracing enabled.
805                 /// </summary>
806                 [Conditional("TRACE")]
807                 private static void RegTrace (string message, params object[] args)
808                 {
809                         message = "REG " + message;
810                         if (args.Length > 0)
811                                 message = String.Format (message, args);
812
813                         Trace.WriteLine (message);
814                         //Console.WriteLine (message);
815                 }
816 #endif          
817                 private static void RegTrace (string message, params object[] args)
818                 {
819                 }
820         }
821 }
822