PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/corlib/Microsoft.Win32/Win32RegistryApi.cs

https://bitbucket.org/foobar22/mono
C# | 636 lines | 450 code | 108 blank | 78 comment | 147 complexity | cb6ab8e266785b848a30be814799e38c MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, Unlicense, Apache-2.0, LGPL-2.0
  1. //
  2. // Microsoft.Win32/Win32RegistryApi.cs: wrapper for win32 registry API
  3. //
  4. // Authos:
  5. // Erik LeBel (eriklebel@yahoo.ca)
  6. // Jackson Harper (jackson@ximian.com)
  7. // Miguel de Icaza (miguel@gnome.org)
  8. //
  9. // Copyright (C) Erik LeBel 2004
  10. // (C) 2004, 2005 Novell, Inc (http://www.novell.com)
  11. //
  12. //
  13. // Copyright (C) 2004, 2005 Novell, Inc (http://www.novell.com)
  14. //
  15. // Permission is hereby granted, free of charge, to any person obtaining
  16. // a copy of this software and associated documentation files (the
  17. // "Software"), to deal in the Software without restriction, including
  18. // without limitation the rights to use, copy, modify, merge, publish,
  19. // distribute, sublicense, and/or sell copies of the Software, and to
  20. // permit persons to whom the Software is furnished to do so, subject to
  21. // the following conditions:
  22. //
  23. // The above copyright notice and this permission notice shall be
  24. // included in all copies or substantial portions of the Software.
  25. //
  26. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  27. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  28. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  29. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  30. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  31. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  32. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  33. //
  34. #if !NET_2_1
  35. using System;
  36. using System.Collections;
  37. using System.Collections.Generic;
  38. using System.IO;
  39. using System.Runtime.InteropServices;
  40. using System.Security;
  41. using System.Text;
  42. using Microsoft.Win32.SafeHandles;
  43. namespace Microsoft.Win32
  44. {
  45. /// <summary>
  46. /// Function stubs, constants and helper functions for
  47. /// the Win32 registry manipulation utilities.
  48. /// </summary>
  49. internal class Win32RegistryApi : IRegistryApi
  50. {
  51. // bit masks for registry key open access permissions
  52. const int OpenRegKeyRead = 0x00020019;
  53. const int OpenRegKeyWrite = 0x00020006;
  54. // FIXME must be a way to determin this dynamically?
  55. const int Int32ByteSize = 4;
  56. const int Int64ByteSize = 8;
  57. // FIXME this is hard coded on Mono, can it be determined dynamically?
  58. readonly int NativeBytesPerCharacter = Marshal.SystemDefaultCharSize;
  59. const int RegOptionsNonVolatile = 0x00000000;
  60. const int RegOptionsVolatile = 0x00000001;
  61. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegCreateKeyEx")]
  62. static extern int RegCreateKeyEx (IntPtr keyBase, string keyName, int reserved,
  63. IntPtr lpClass, int options, int access, IntPtr securityAttrs,
  64. out IntPtr keyHandle, out int disposition);
  65. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegCloseKey")]
  66. static extern int RegCloseKey (IntPtr keyHandle);
  67. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode)]
  68. static extern int RegConnectRegistry (string machineName, IntPtr hKey,
  69. out IntPtr keyHandle);
  70. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegFlushKey")]
  71. private static extern int RegFlushKey (IntPtr keyHandle);
  72. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegOpenKeyEx")]
  73. private static extern int RegOpenKeyEx (IntPtr keyBase,
  74. string keyName, IntPtr reserved, int access,
  75. out IntPtr keyHandle);
  76. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegDeleteKey")]
  77. private static extern int RegDeleteKey (IntPtr keyHandle, string valueName);
  78. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegDeleteValue")]
  79. private static extern int RegDeleteValue (IntPtr keyHandle, string valueName);
  80. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegEnumKey")]
  81. private static extern int RegEnumKey (IntPtr keyBase, int index, StringBuilder nameBuffer, int bufferLength);
  82. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegEnumValue")]
  83. private static extern int RegEnumValue (IntPtr keyBase,
  84. int index, StringBuilder nameBuffer,
  85. ref int nameLength, IntPtr reserved,
  86. ref RegistryValueKind type, IntPtr data, IntPtr dataLength);
  87. // [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegSetValueEx")]
  88. // private static extern int RegSetValueEx (IntPtr keyBase,
  89. // string valueName, IntPtr reserved, RegistryValueKind type,
  90. // StringBuilder data, int rawDataLength);
  91. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegSetValueEx")]
  92. private static extern int RegSetValueEx (IntPtr keyBase,
  93. string valueName, IntPtr reserved, RegistryValueKind type,
  94. string data, int rawDataLength);
  95. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegSetValueEx")]
  96. private static extern int RegSetValueEx (IntPtr keyBase,
  97. string valueName, IntPtr reserved, RegistryValueKind type,
  98. byte[] rawData, int rawDataLength);
  99. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegSetValueEx")]
  100. private static extern int RegSetValueEx (IntPtr keyBase,
  101. string valueName, IntPtr reserved, RegistryValueKind type,
  102. ref int data, int rawDataLength);
  103. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegSetValueEx")]
  104. private static extern int RegSetValueEx (IntPtr keyBase,
  105. string valueName, IntPtr reserved, RegistryValueKind type,
  106. ref long data, int rawDataLength);
  107. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegQueryValueEx")]
  108. private static extern int RegQueryValueEx (IntPtr keyBase,
  109. string valueName, IntPtr reserved, ref RegistryValueKind type,
  110. IntPtr zero, ref int dataSize);
  111. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegQueryValueEx")]
  112. private static extern int RegQueryValueEx (IntPtr keyBase,
  113. string valueName, IntPtr reserved, ref RegistryValueKind type,
  114. [Out] byte[] data, ref int dataSize);
  115. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegQueryValueEx")]
  116. private static extern int RegQueryValueEx (IntPtr keyBase,
  117. string valueName, IntPtr reserved, ref RegistryValueKind type,
  118. ref int data, ref int dataSize);
  119. [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegQueryValueEx")]
  120. private static extern int RegQueryValueEx (IntPtr keyBase,
  121. string valueName, IntPtr reserved, ref RegistryValueKind type,
  122. ref long data, ref int dataSize);
  123. // Returns our handle from the RegistryKey
  124. public IntPtr GetHandle (RegistryKey key)
  125. {
  126. return (IntPtr) key.InternalHandle;
  127. }
  128. static bool IsHandleValid (RegistryKey key)
  129. {
  130. return key.InternalHandle != null;
  131. }
  132. public RegistryValueKind GetValueKind (RegistryKey rkey, string name)
  133. {
  134. RegistryValueKind type = 0;
  135. int size = 0;
  136. IntPtr handle = GetHandle (rkey);
  137. int result = RegQueryValueEx (handle, name, IntPtr.Zero, ref type, IntPtr.Zero, ref size);
  138. if (result == Win32ResultCode.FileNotFound || result == Win32ResultCode.MarkedForDeletion)
  139. return RegistryValueKind.Unknown;
  140. return type;
  141. }
  142. /// <summary>
  143. /// Acctually read a registry value. Requires knowledge of the
  144. /// value's type and size.
  145. /// </summary>
  146. public object GetValue (RegistryKey rkey, string name, object defaultValue, RegistryValueOptions options)
  147. {
  148. RegistryValueKind type = 0;
  149. int size = 0;
  150. object obj = null;
  151. IntPtr handle = GetHandle (rkey);
  152. int result = RegQueryValueEx (handle, name, IntPtr.Zero, ref type, IntPtr.Zero, ref size);
  153. if (result == Win32ResultCode.FileNotFound || result == Win32ResultCode.MarkedForDeletion) {
  154. return defaultValue;
  155. }
  156. if (result != Win32ResultCode.MoreData && result != Win32ResultCode.Success ) {
  157. GenerateException (result);
  158. }
  159. if (type == RegistryValueKind.String) {
  160. byte[] data;
  161. result = GetBinaryValue (rkey, name, type, out data, size);
  162. obj = RegistryKey.DecodeString (data);
  163. } else if (type == RegistryValueKind.ExpandString) {
  164. byte [] data;
  165. result = GetBinaryValue (rkey, name, type, out data, size);
  166. obj = RegistryKey.DecodeString (data);
  167. if ((options & RegistryValueOptions.DoNotExpandEnvironmentNames) == 0)
  168. obj = Environment.ExpandEnvironmentVariables ((string) obj);
  169. } else if (type == RegistryValueKind.DWord) {
  170. int data = 0;
  171. result = RegQueryValueEx (handle, name, IntPtr.Zero, ref type, ref data, ref size);
  172. obj = data;
  173. } else if (type == RegistryValueKind.QWord) {
  174. long data = 0;
  175. result = RegQueryValueEx (handle, name, IntPtr.Zero, ref type, ref data, ref size);
  176. obj = data;
  177. } else if (type == RegistryValueKind.Binary) {
  178. byte[] data;
  179. result = GetBinaryValue (rkey, name, type, out data, size);
  180. obj = data;
  181. } else if (type == RegistryValueKind.MultiString) {
  182. obj = null;
  183. byte[] data;
  184. result = GetBinaryValue (rkey, name, type, out data, size);
  185. if (result == Win32ResultCode.Success)
  186. obj = RegistryKey.DecodeString (data).Split ('\0');
  187. } else {
  188. // should never get here
  189. throw new SystemException ();
  190. }
  191. // check result codes again:
  192. if (result != Win32ResultCode.Success)
  193. {
  194. GenerateException (result);
  195. }
  196. return obj;
  197. }
  198. //
  199. // This version has to do extra checking, make sure that the requested
  200. // valueKind matches the type of the value being stored
  201. //
  202. public void SetValue (RegistryKey rkey, string name, object value, RegistryValueKind valueKind)
  203. {
  204. Type type = value.GetType ();
  205. int result;
  206. IntPtr handle = GetHandle (rkey);
  207. if (valueKind == RegistryValueKind.QWord && type == typeof (long)) {
  208. long rawValue = (long)value;
  209. result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.QWord, ref rawValue, Int64ByteSize);
  210. } else if (valueKind == RegistryValueKind.DWord && type == typeof (int)) {
  211. int rawValue = (int)value;
  212. result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.DWord, ref rawValue, Int32ByteSize);
  213. } else if (valueKind == RegistryValueKind.Binary && type == typeof (byte[])) {
  214. byte[] rawValue = (byte[]) value;
  215. result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.Binary, rawValue, rawValue.Length);
  216. } else if (valueKind == RegistryValueKind.MultiString && type == typeof (string[])) {
  217. string[] vals = (string[]) value;
  218. StringBuilder fullStringValue = new StringBuilder ();
  219. foreach (string v in vals)
  220. {
  221. fullStringValue.Append (v);
  222. fullStringValue.Append ('\0');
  223. }
  224. fullStringValue.Append ('\0');
  225. byte[] rawValue = Encoding.Unicode.GetBytes (fullStringValue.ToString ());
  226. result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.MultiString, rawValue, rawValue.Length);
  227. } else if ((valueKind == RegistryValueKind.String || valueKind == RegistryValueKind.ExpandString) &&
  228. type == typeof (string)){
  229. string rawValue = String.Format ("{0}{1}", value, '\0');
  230. result = RegSetValueEx (handle, name, IntPtr.Zero, valueKind, rawValue,
  231. rawValue.Length * NativeBytesPerCharacter);
  232. } else if (type.IsArray) {
  233. throw new ArgumentException ("Only string and byte arrays can written as registry values");
  234. } else {
  235. throw new ArgumentException ("Type does not match the valueKind");
  236. }
  237. // handle the result codes
  238. if (result != Win32ResultCode.Success)
  239. {
  240. GenerateException (result);
  241. }
  242. }
  243. public void SetValue (RegistryKey rkey, string name, object value)
  244. {
  245. Type type = value.GetType ();
  246. int result;
  247. IntPtr handle = GetHandle (rkey);
  248. if (type == typeof (int)) {
  249. int rawValue = (int)value;
  250. result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.DWord, ref rawValue, Int32ByteSize);
  251. } else if (type == typeof (byte[])) {
  252. byte[] rawValue = (byte[]) value;
  253. result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.Binary, rawValue, rawValue.Length);
  254. } else if (type == typeof (string[])) {
  255. string[] vals = (string[]) value;
  256. StringBuilder fullStringValue = new StringBuilder ();
  257. foreach (string v in vals)
  258. {
  259. fullStringValue.Append (v);
  260. fullStringValue.Append ('\0');
  261. }
  262. fullStringValue.Append ('\0');
  263. byte[] rawValue = Encoding.Unicode.GetBytes (fullStringValue.ToString ());
  264. result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.MultiString, rawValue, rawValue.Length);
  265. } else if (type.IsArray) {
  266. throw new ArgumentException ("Only string and byte arrays can written as registry values");
  267. } else {
  268. string rawValue = String.Format ("{0}{1}", value, '\0');
  269. result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.String, rawValue,
  270. rawValue.Length * NativeBytesPerCharacter);
  271. }
  272. if (result == Win32ResultCode.MarkedForDeletion)
  273. throw RegistryKey.CreateMarkedForDeletionException ();
  274. // handle the result codes
  275. if (result != Win32ResultCode.Success)
  276. {
  277. GenerateException (result);
  278. }
  279. }
  280. /// <summary>
  281. /// Get a binary value.
  282. /// </summary>
  283. private int GetBinaryValue (RegistryKey rkey, string name, RegistryValueKind type, out byte[] data, int size)
  284. {
  285. byte[] internalData = new byte [size];
  286. IntPtr handle = GetHandle (rkey);
  287. int result = RegQueryValueEx (handle, name, IntPtr.Zero, ref type, internalData, ref size);
  288. data = internalData;
  289. return result;
  290. }
  291. // Arbitrary max size for key/values names that can be fetched.
  292. // .NET framework SDK docs say that the max name length that can
  293. // be used is 255 characters, we'll allow for a bit more.
  294. const int BufferMaxLength = 1024;
  295. public int SubKeyCount (RegistryKey rkey)
  296. {
  297. int index;
  298. StringBuilder stringBuffer = new StringBuilder (BufferMaxLength);
  299. IntPtr handle = GetHandle (rkey);
  300. for (index = 0; true; index ++) {
  301. int result = RegEnumKey (handle, index, stringBuffer,
  302. stringBuffer.Capacity);
  303. if (result == Win32ResultCode.MarkedForDeletion)
  304. throw RegistryKey.CreateMarkedForDeletionException ();
  305. if (result == Win32ResultCode.Success)
  306. continue;
  307. if (result == Win32ResultCode.NoMoreEntries)
  308. break;
  309. // something is wrong!!
  310. GenerateException (result);
  311. }
  312. return index;
  313. }
  314. public int ValueCount (RegistryKey rkey)
  315. {
  316. int index, result, bufferCapacity;
  317. RegistryValueKind type;
  318. StringBuilder buffer = new StringBuilder (BufferMaxLength);
  319. IntPtr handle = GetHandle (rkey);
  320. for (index = 0; true; index ++) {
  321. type = 0;
  322. bufferCapacity = buffer.Capacity;
  323. result = RegEnumValue (handle, index,
  324. buffer, ref bufferCapacity,
  325. IntPtr.Zero, ref type,
  326. IntPtr.Zero, IntPtr.Zero);
  327. if (result == Win32ResultCode.MarkedForDeletion)
  328. throw RegistryKey.CreateMarkedForDeletionException ();
  329. if (result == Win32ResultCode.Success || result == Win32ResultCode.MoreData)
  330. continue;
  331. if (result == Win32ResultCode.NoMoreEntries)
  332. break;
  333. // something is wrong
  334. GenerateException (result);
  335. }
  336. return index;
  337. }
  338. public RegistryKey OpenRemoteBaseKey (RegistryHive hKey, string machineName)
  339. {
  340. IntPtr handle = new IntPtr ((int) hKey);
  341. IntPtr keyHandle;
  342. int result = RegConnectRegistry (machineName, handle, out keyHandle);
  343. if (result != Win32ResultCode.Success)
  344. GenerateException (result);
  345. return new RegistryKey (hKey, keyHandle, true);
  346. }
  347. public RegistryKey OpenSubKey (RegistryKey rkey, string keyName, bool writable)
  348. {
  349. int access = OpenRegKeyRead;
  350. if (writable) access |= OpenRegKeyWrite;
  351. IntPtr handle = GetHandle (rkey);
  352. IntPtr subKeyHandle;
  353. int result = RegOpenKeyEx (handle, keyName, IntPtr.Zero, access, out subKeyHandle);
  354. if (result == Win32ResultCode.FileNotFound || result == Win32ResultCode.MarkedForDeletion)
  355. return null;
  356. if (result != Win32ResultCode.Success)
  357. GenerateException (result);
  358. return new RegistryKey (subKeyHandle, CombineName (rkey, keyName), writable);
  359. }
  360. public void Flush (RegistryKey rkey)
  361. {
  362. if (!IsHandleValid (rkey))
  363. return;
  364. IntPtr handle = GetHandle (rkey);
  365. RegFlushKey (handle);
  366. }
  367. public void Close (RegistryKey rkey)
  368. {
  369. if (!IsHandleValid (rkey))
  370. return;
  371. #if NET_4_0
  372. SafeRegistryHandle safe_handle = rkey.Handle;
  373. if (safe_handle != null) {
  374. // closes the unmanaged pointer for us.
  375. safe_handle.Close ();
  376. return;
  377. }
  378. #endif
  379. IntPtr handle = GetHandle (rkey);
  380. RegCloseKey (handle);
  381. }
  382. #if NET_4_0
  383. public RegistryKey FromHandle (SafeRegistryHandle handle)
  384. {
  385. // At this point we can't tell whether the key is writable
  386. // or not (nor the name), so we let the error check code handle it later, as
  387. // .Net seems to do.
  388. return new RegistryKey (handle.DangerousGetHandle (), String.Empty, true);
  389. }
  390. #endif
  391. public RegistryKey CreateSubKey (RegistryKey rkey, string keyName)
  392. {
  393. IntPtr handle = GetHandle (rkey);
  394. IntPtr subKeyHandle;
  395. int disposition;
  396. int result = RegCreateKeyEx (handle , keyName, 0, IntPtr.Zero,
  397. RegOptionsNonVolatile,
  398. OpenRegKeyRead | OpenRegKeyWrite, IntPtr.Zero, out subKeyHandle, out disposition);
  399. if (result == Win32ResultCode.MarkedForDeletion)
  400. throw RegistryKey.CreateMarkedForDeletionException ();
  401. if (result != Win32ResultCode.Success) {
  402. GenerateException (result);
  403. }
  404. return new RegistryKey (subKeyHandle, CombineName (rkey, keyName),
  405. true);
  406. }
  407. #if NET_4_0
  408. public RegistryKey CreateSubKey (RegistryKey rkey, string keyName, RegistryOptions options)
  409. {
  410. IntPtr handle = GetHandle (rkey);
  411. IntPtr subKeyHandle;
  412. int disposition;
  413. int result = RegCreateKeyEx (handle , keyName, 0, IntPtr.Zero,
  414. options == RegistryOptions.Volatile ? RegOptionsVolatile : RegOptionsNonVolatile,
  415. OpenRegKeyRead | OpenRegKeyWrite, IntPtr.Zero, out subKeyHandle, out disposition);
  416. if (result == Win32ResultCode.MarkedForDeletion)
  417. throw RegistryKey.CreateMarkedForDeletionException ();
  418. if (result != Win32ResultCode.Success)
  419. GenerateException (result);
  420. return new RegistryKey (subKeyHandle, CombineName (rkey, keyName),
  421. true);
  422. }
  423. #endif
  424. public void DeleteKey (RegistryKey rkey, string keyName, bool shouldThrowWhenKeyMissing)
  425. {
  426. IntPtr handle = GetHandle (rkey);
  427. int result = RegDeleteKey (handle, keyName);
  428. if (result == Win32ResultCode.FileNotFound) {
  429. if (shouldThrowWhenKeyMissing)
  430. throw new ArgumentException ("key " + keyName);
  431. return;
  432. }
  433. if (result != Win32ResultCode.Success)
  434. GenerateException (result);
  435. }
  436. public void DeleteValue (RegistryKey rkey, string value, bool shouldThrowWhenKeyMissing)
  437. {
  438. IntPtr handle = GetHandle (rkey);
  439. int result = RegDeleteValue (handle, value);
  440. if (result == Win32ResultCode.MarkedForDeletion)
  441. return;
  442. if (result == Win32ResultCode.FileNotFound){
  443. if (shouldThrowWhenKeyMissing)
  444. throw new ArgumentException ("value " + value);
  445. return;
  446. }
  447. if (result != Win32ResultCode.Success)
  448. GenerateException (result);
  449. }
  450. public string [] GetSubKeyNames (RegistryKey rkey)
  451. {
  452. IntPtr handle = GetHandle (rkey);
  453. StringBuilder buffer = new StringBuilder (BufferMaxLength);
  454. var keys = new List<string> ();
  455. for (int index = 0; true; index ++) {
  456. int result = RegEnumKey (handle, index, buffer, buffer.Capacity);
  457. if (result == Win32ResultCode.Success) {
  458. keys.Add (buffer.ToString ());
  459. buffer.Length = 0;
  460. continue;
  461. }
  462. if (result == Win32ResultCode.NoMoreEntries)
  463. break;
  464. // should not be here!
  465. GenerateException (result);
  466. }
  467. return keys.ToArray ();
  468. }
  469. public string [] GetValueNames (RegistryKey rkey)
  470. {
  471. IntPtr handle = GetHandle (rkey);
  472. var values = new List<string> ();
  473. for (int index = 0; true; index ++)
  474. {
  475. StringBuilder buffer = new StringBuilder (BufferMaxLength);
  476. int bufferCapacity = buffer.Capacity;
  477. RegistryValueKind type = 0;
  478. int result = RegEnumValue (handle, index, buffer, ref bufferCapacity,
  479. IntPtr.Zero, ref type, IntPtr.Zero, IntPtr.Zero);
  480. if (result == Win32ResultCode.Success || result == Win32ResultCode.MoreData) {
  481. values.Add (buffer.ToString ());
  482. continue;
  483. }
  484. if (result == Win32ResultCode.NoMoreEntries)
  485. break;
  486. if (result == Win32ResultCode.MarkedForDeletion)
  487. throw RegistryKey.CreateMarkedForDeletionException ();
  488. GenerateException (result);
  489. }
  490. return values.ToArray ();
  491. }
  492. /// <summary>
  493. /// convert a win32 error code into an appropriate exception.
  494. /// </summary>
  495. private void GenerateException (int errorCode)
  496. {
  497. switch (errorCode) {
  498. case Win32ResultCode.FileNotFound:
  499. case Win32ResultCode.InvalidParameter:
  500. throw new ArgumentException ();
  501. case Win32ResultCode.AccessDenied:
  502. throw new SecurityException ();
  503. case Win32ResultCode.NetworkPathNotFound:
  504. throw new IOException ("The network path was not found.");
  505. case Win32ResultCode.InvalidHandle:
  506. throw new IOException ("Invalid handle.");
  507. default:
  508. // unidentified system exception
  509. throw new SystemException ();
  510. }
  511. }
  512. public string ToString (RegistryKey rkey)
  513. {
  514. return rkey.Name;
  515. }
  516. /// <summary>
  517. /// utility: Combine the sub key name to the current name to produce a
  518. /// fully qualified sub key name.
  519. /// </summary>
  520. internal static string CombineName (RegistryKey rkey, string localName)
  521. {
  522. return String.Concat (rkey.Name, "\\", localName);
  523. }
  524. }
  525. }
  526. #endif // NET_2_1