PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/IronPython/IronPython.Modules/_winreg.cs

http://github.com/IronLanguages/main
C# | 719 lines | 562 code | 115 blank | 42 comment | 136 complexity | c8cf3dea0e185ac3e8b019d022c1c46b MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if FEATURE_REGISTRY //Registry not available in silverlight and we require .NET 4.0 APIs for implementing this.
  16. using System;
  17. using System.Collections.Generic;
  18. using System.ComponentModel;
  19. using System.Diagnostics;
  20. using System.IO;
  21. using System.Runtime.InteropServices;
  22. using System.Security;
  23. using System.Security.AccessControl;
  24. using System.Text;
  25. using Microsoft.Win32;
  26. using Microsoft.Win32.SafeHandles;
  27. using IronPython.Runtime;
  28. using IronPython.Runtime.Exceptions;
  29. using IronPython.Runtime.Operations;
  30. using IronPython.Runtime.Types;
  31. #if FEATURE_NUMERICS
  32. using System.Numerics;
  33. #else
  34. using Microsoft.Scripting.Math;
  35. #endif
  36. [assembly: PythonModule("_winreg", typeof(IronPython.Modules.PythonWinReg), PlatformID.MacOSX, PlatformID.Unix)]
  37. namespace IronPython.Modules {
  38. public static class PythonWinReg {
  39. public const string __doc__ = "Provides access to the Windows registry.";
  40. public static PythonType error = PythonExceptions.WindowsError;
  41. #region Constants
  42. public static BigInteger HKEY_CLASSES_ROOT = 0x80000000L;
  43. public static BigInteger HKEY_CURRENT_USER = 0x80000001L;
  44. public static BigInteger HKEY_LOCAL_MACHINE = 0x80000002L;
  45. public static BigInteger HKEY_USERS = 0x80000003L;
  46. public static BigInteger HKEY_PERFORMANCE_DATA = 0x80000004L;
  47. public static BigInteger HKEY_CURRENT_CONFIG = 0x80000005L;
  48. public static BigInteger HKEY_DYN_DATA = 0x80000006L;
  49. public const int KEY_QUERY_VALUE = 0X1;
  50. public const int KEY_SET_VALUE = 0X2;
  51. public const int KEY_CREATE_SUB_KEY = 0X4;
  52. public const int KEY_ENUMERATE_SUB_KEYS = 0X8;
  53. public const int KEY_NOTIFY = 0X10;
  54. public const int KEY_CREATE_LINK = 0X20;
  55. public const int KEY_ALL_ACCESS = 0XF003F;
  56. public const int KEY_EXECUTE = 0X20019;
  57. public const int KEY_READ = 0X20019;
  58. public const int KEY_WRITE = 0X20006;
  59. public const int REG_CREATED_NEW_KEY = 0X1;
  60. public const int REG_OPENED_EXISTING_KEY = 0X2;
  61. public const int REG_NONE = 0X0;
  62. public const int REG_SZ = 0X1;
  63. public const int REG_EXPAND_SZ = 0X2;
  64. public const int REG_BINARY = 0X3;
  65. public const int REG_DWORD = 0X4;
  66. public const int REG_DWORD_LITTLE_ENDIAN = 0X4;
  67. public const int REG_DWORD_BIG_ENDIAN = 0X5;
  68. public const int REG_LINK = 0X6;
  69. public const int REG_MULTI_SZ = 0X7;
  70. public const int REG_RESOURCE_LIST = 0X8;
  71. public const int REG_FULL_RESOURCE_DESCRIPTOR = 0X9;
  72. public const int REG_RESOURCE_REQUIREMENTS_LIST = 0XA;
  73. public const int REG_NOTIFY_CHANGE_NAME = 0X1;
  74. public const int REG_NOTIFY_CHANGE_ATTRIBUTES = 0X2;
  75. public const int REG_NOTIFY_CHANGE_LAST_SET = 0X4;
  76. public const int REG_NOTIFY_CHANGE_SECURITY = 0X8;
  77. public const int REG_OPTION_RESERVED = 0X0;
  78. public const int REG_OPTION_NON_VOLATILE = 0X0;
  79. public const int REG_OPTION_VOLATILE = 0X1;
  80. public const int REG_OPTION_CREATE_LINK = 0X2;
  81. public const int REG_OPTION_BACKUP_RESTORE = 0X4;
  82. public const int REG_OPTION_OPEN_LINK = 0X8;
  83. public const int REG_NO_LAZY_FLUSH = 0X4;
  84. public const int REG_REFRESH_HIVE = 0X2;
  85. public const int REG_LEGAL_CHANGE_FILTER = 0XF;
  86. public const int REG_LEGAL_OPTION = 0XF;
  87. public const int REG_WHOLE_HIVE_VOLATILE = 0X1;
  88. #endregion
  89. #region Module Methods
  90. public static void CloseKey(HKEYType key) {
  91. key.Close();
  92. }
  93. public static HKEYType CreateKey(object key, string subKeyName) {
  94. // the .NET APIs don't work with a key name of length 256, use CreateKeyEx which PInvokes instead
  95. if (subKeyName.Length == 256)
  96. return CreateKeyEx(key, subKeyName, 0, KEY_ALL_ACCESS);
  97. HKEYType rootKey = GetRootKey(key);
  98. //if key is a system key and no subkey is specified return that.
  99. if (key is BigInteger && string.IsNullOrEmpty(subKeyName))
  100. return rootKey;
  101. HKEYType subKey = new HKEYType(rootKey.GetKey().CreateSubKey(subKeyName));
  102. return subKey;
  103. }
  104. private static string FormatError(int errorCode) {
  105. return new Win32Exception(errorCode).Message;
  106. }
  107. public static HKEYType CreateKeyEx(object key, string subKeyName, [DefaultParameterValue(0)]int res, [DefaultParameterValue(KEY_ALL_ACCESS)]int sam) {
  108. HKEYType rootKey = GetRootKey(key);
  109. //if key is a system key and no subkey is specified return that.
  110. if (key is BigInteger && string.IsNullOrEmpty(subKeyName))
  111. return rootKey;
  112. SafeRegistryHandle handle;
  113. int disposition;
  114. int result = RegCreateKeyEx(
  115. rootKey.GetKey().Handle,
  116. subKeyName,
  117. 0,
  118. null,
  119. RegistryOptions.None,
  120. (RegistryRights)sam,
  121. IntPtr.Zero,
  122. out handle,
  123. out disposition
  124. );
  125. if (result != ERROR_SUCCESS) {
  126. throw PythonExceptions.CreateThrowable(error, result, FormatError(result));
  127. }
  128. return new HKEYType(RegistryKey.FromHandle(handle));
  129. }
  130. [DllImport("advapi32.dll", SetLastError = true)]
  131. static extern int RegCreateKeyEx(
  132. SafeRegistryHandle hKey,
  133. string lpSubKey,
  134. int Reserved,
  135. string lpClass,
  136. RegistryOptions dwOptions,
  137. RegistryRights samDesired,
  138. IntPtr lpSecurityAttributes,
  139. out SafeRegistryHandle phkResult,
  140. out int lpdwDisposition);
  141. [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  142. static extern int RegQueryValueEx(
  143. SafeRegistryHandle hKey,
  144. string lpValueName,
  145. IntPtr lpReserved,
  146. out int lpType,
  147. byte[] lpData,
  148. ref uint lpcbData
  149. );
  150. [DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
  151. static extern int RegEnumKeyEx(
  152. SafeRegistryHandle hKey,
  153. int dwIndex,
  154. StringBuilder lpName,
  155. ref int lpcbName,
  156. IntPtr lpReserved,
  157. IntPtr lpClass,
  158. IntPtr lpcbClass,
  159. IntPtr lpftLastWriteTime);
  160. [DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
  161. static extern int RegSetValueEx(
  162. SafeRegistryHandle hKey,
  163. string lpValueName,
  164. int Reserved,
  165. int dwType,
  166. byte[] lpData,
  167. int cbData);
  168. [DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
  169. internal static extern int RegDeleteKey(
  170. SafeRegistryHandle hKey,
  171. string lpSubKey);
  172. [DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
  173. internal static extern int RegDisableReflectionKey(
  174. SafeRegistryHandle hKey);
  175. [DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
  176. internal static extern int RegEnableReflectionKey(
  177. SafeRegistryHandle hKey);
  178. [DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
  179. internal static extern int RegQueryReflectionKey(
  180. SafeRegistryHandle hBase,
  181. out bool bIsReflectionDisabled);
  182. public static void DeleteKey(object key, string subKeyName) {
  183. HKEYType rootKey = GetRootKey(key);
  184. if (key is BigInteger && string.IsNullOrEmpty(subKeyName))
  185. throw new InvalidCastException("DeleteKey() argument 2 must be string, not None");
  186. // the .NET APIs don't work with a key name of length 256, use a PInvoke instead
  187. if (subKeyName.Length == 256) {
  188. RegDeleteKey(rootKey.GetKey().Handle, subKeyName);
  189. return;
  190. }
  191. try {
  192. rootKey.GetKey().DeleteSubKey(subKeyName);
  193. } catch (ArgumentException e) {
  194. throw new ExternalException(e.Message);
  195. }
  196. }
  197. public static void DeleteValue(object key, string value) {
  198. HKEYType rootKey = GetRootKey(key);
  199. rootKey.GetKey().DeleteValue(value, true);
  200. }
  201. public static string EnumKey(object key, int index)
  202. {
  203. HKEYType rootKey = GetRootKey(key);
  204. int len = 257; // maximum key name length is 256
  205. StringBuilder name = new StringBuilder(len);
  206. int ret = RegEnumKeyEx(rootKey.GetKey().Handle, index, name, ref len, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
  207. if (ret != ERROR_SUCCESS) {
  208. Debug.Assert(ret == ERROR_NO_MORE_ITEMS);
  209. throw PythonExceptions.CreateThrowable(PythonExceptions.WindowsError, PythonExceptions._WindowsError.ERROR_BAD_COMMAND, "No more data is available");
  210. }
  211. return name.ToString();
  212. }
  213. const int ERROR_NO_MORE_ITEMS = 259;
  214. const int ERROR_MORE_DATA = 234;
  215. const int ERROR_SUCCESS = 0;
  216. public static PythonTuple EnumValue(object key, int index) {
  217. HKEYType rootKey = GetRootKey(key);
  218. if (index >= rootKey.GetKey().ValueCount) {
  219. throw PythonExceptions.CreateThrowable(PythonExceptions.WindowsError, PythonExceptions._WindowsError.ERROR_BAD_COMMAND, "No more data is available");
  220. }
  221. var nativeRootKey = rootKey.GetKey();
  222. string valueName = nativeRootKey.GetValueNames()[index];
  223. // it looks like nativeRootKey.Handle fails on HKEY_PERFORMANCE_DATA so manually create the handle instead
  224. var handle = rootKey.hkey == HKEY_PERFORMANCE_DATA ? new SafeRegistryHandle(new IntPtr(unchecked((int)0x80000004)), true) : nativeRootKey.Handle;
  225. int valueKind;
  226. object value;
  227. QueryValueExImpl(handle, valueName, out valueKind, out value);
  228. return PythonTuple.MakeTuple(valueName, value, valueKind);
  229. }
  230. private static void QueryValueExImpl(SafeRegistryHandle handle, string valueName, out int valueKind, out object value) {
  231. valueName = valueName ?? ""; // it looks like RegQueryValueEx can fail with null, use empty string instead
  232. valueKind = 0;
  233. int dwRet;
  234. byte[] data = new byte[128];
  235. uint length = (uint)data.Length;
  236. // query the size first, reading the data as we query...
  237. dwRet = RegQueryValueEx(handle, valueName, IntPtr.Zero, out valueKind, data, ref length);
  238. while (dwRet == ERROR_MORE_DATA) {
  239. data = new byte[data.Length * 2];
  240. length = (uint)data.Length;
  241. dwRet = RegQueryValueEx(handle, valueName, IntPtr.Zero, out valueKind, data, ref length);
  242. }
  243. if (dwRet == PythonExceptions._WindowsError.ERROR_FILE_NOT_FOUND) {
  244. throw PythonExceptions.CreateThrowable(PythonExceptions.WindowsError, PythonExceptions._WindowsError.ERROR_FILE_NOT_FOUND, "The system cannot find the file specified");
  245. }
  246. if (dwRet != ERROR_SUCCESS) {
  247. throw PythonExceptions.CreateThrowable(PythonExceptions.WindowsError, dwRet);
  248. }
  249. // convert the result into a Python object
  250. switch (valueKind) {
  251. case REG_MULTI_SZ:
  252. List list = new List();
  253. int curIndex = 0;
  254. while (curIndex < length) {
  255. for (int dataIndex = curIndex; dataIndex < length; dataIndex += 2) {
  256. if (data[dataIndex] == 0 && data[dataIndex + 1] == 0) {
  257. // got a full string
  258. list.Add(ExtractString(data, curIndex, dataIndex));
  259. curIndex = dataIndex + 2;
  260. if (curIndex + 2 <= length && data[curIndex] == 0 && data[curIndex + 1] == 0) {
  261. // double null terminated
  262. curIndex = data.Length;
  263. break;
  264. }
  265. }
  266. }
  267. if (curIndex != data.Length) {
  268. // not null terminated
  269. list.Add(ExtractString(data, curIndex, data.Length));
  270. }
  271. }
  272. value = list;
  273. break;
  274. case REG_BINARY:
  275. value = length == 0 ? null : PythonOps.MakeString(data, (int)length);
  276. break;
  277. case REG_EXPAND_SZ:
  278. case REG_SZ:
  279. if (length >= 2 && data[length - 1] == 0 && data[length - 2] == 0) {
  280. value = ExtractString(data, 0, (int)length - 2);
  281. } else {
  282. value = ExtractString(data, 0, (int)length);
  283. }
  284. break;
  285. case REG_DWORD:
  286. if (BitConverter.IsLittleEndian) {
  287. value = (uint)((data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]);
  288. } else {
  289. value = (uint)((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]);
  290. }
  291. break;
  292. default:
  293. value = null;
  294. break;
  295. }
  296. }
  297. public static string ExpandEnvironmentStrings(string value)
  298. {
  299. if (value == null)
  300. throw PythonExceptions.CreateThrowable(PythonExceptions.TypeError, "must be unicode, not None");
  301. return Environment.ExpandEnvironmentVariables(value);
  302. }
  303. private static string ExtractString(byte[] data, int start, int end) {
  304. if (end <= start) {
  305. return String.Empty;
  306. }
  307. char[] chars = new char[(end - start) / 2];
  308. for (int i = 0; i < chars.Length; i++) {
  309. chars[i] = (char)((data[i*2 + start]) | (data[i*2 + start + 1] << 8));
  310. }
  311. return new string(chars);
  312. }
  313. public static void FlushKey(object key) {
  314. HKEYType rootKey = GetRootKey(key);
  315. rootKey.GetKey().Flush();
  316. }
  317. public static HKEYType OpenKey(object key, string subKeyName) {
  318. return OpenKey(key, subKeyName, 0, KEY_READ);
  319. }
  320. public static HKEYType OpenKey(object key, string subKeyName, [DefaultParameterValue(0)]int res, [DefaultParameterValue(KEY_READ)]int sam) {
  321. HKEYType rootKey = GetRootKey(key);
  322. RegistryKey newKey = null;
  323. // I'm assuming that the masks that CPy uses are the same as the Win32 API one mentioned here-
  324. // http://msdn2.microsoft.com/en-us/library/ms724878(VS.85).aspx
  325. // KEY_WRITE is a combination of KEY_SET_VALUE and KEY_CREATE_SUB_KEY. We'll open with write access
  326. // if any of this is set.
  327. // KEY_READ is a combination of KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS and KEY_NOTIFY. We'll open
  328. // with read access for all of these.
  329. var nativeRootKey = rootKey.GetKey();
  330. try {
  331. if ((sam & KEY_SET_VALUE) == KEY_SET_VALUE ||
  332. (sam & KEY_CREATE_SUB_KEY) == KEY_CREATE_SUB_KEY) {
  333. if (res != 0) {
  334. #if NETSTANDARD
  335. newKey = nativeRootKey.OpenSubKey(subKeyName, (RegistryRights)res);
  336. #else
  337. newKey = nativeRootKey.OpenSubKey(subKeyName, RegistryKeyPermissionCheck.Default, (RegistryRights)res);
  338. #endif
  339. } else {
  340. newKey = nativeRootKey.OpenSubKey(subKeyName, true);
  341. }
  342. } else if ((sam & KEY_QUERY_VALUE) == KEY_QUERY_VALUE ||
  343. (sam & KEY_ENUMERATE_SUB_KEYS) == KEY_ENUMERATE_SUB_KEYS ||
  344. (sam & KEY_NOTIFY) == KEY_NOTIFY) {
  345. if (res != 0) {
  346. #if NETSTANDARD
  347. newKey = nativeRootKey.OpenSubKey(subKeyName, (RegistryRights)res);
  348. #else
  349. newKey = nativeRootKey.OpenSubKey(subKeyName, RegistryKeyPermissionCheck.ReadSubTree, (RegistryRights)res);
  350. #endif
  351. } else {
  352. newKey = nativeRootKey.OpenSubKey(subKeyName, false);
  353. }
  354. } else {
  355. throw new Win32Exception("Unexpected mode");
  356. }
  357. } catch (SecurityException) {
  358. throw PythonExceptions.CreateThrowable(PythonExceptions.WindowsError, PythonExceptions._WindowsError.ERROR_ACCESS_DENIED, "Access is denied");
  359. }
  360. if (newKey == null) {
  361. throw PythonExceptions.CreateThrowable(PythonExceptions.WindowsError, PythonExceptions._WindowsError.ERROR_FILE_NOT_FOUND, "The system cannot find the file specified");
  362. }
  363. return new HKEYType(newKey);
  364. }
  365. public static HKEYType OpenKeyEx(object key, string subKeyName, [DefaultParameterValue(0)]int res, [DefaultParameterValue(KEY_READ)]int sam) {
  366. return OpenKey(key, subKeyName, res, sam);
  367. }
  368. public static PythonTuple QueryInfoKey(object key) {
  369. HKEYType rootKey = null;
  370. //The key can also be a handle. If it is, then retrieve it from the cache.
  371. if (key is int) {
  372. if (HKeyHandleCache.cache.ContainsKey((int)key)) {
  373. if (HKeyHandleCache.cache[(int)key].IsAlive) {
  374. rootKey = HKeyHandleCache.cache[(int)key].Target as HKEYType;
  375. }
  376. }
  377. } else {
  378. rootKey = GetRootKey(key);
  379. }
  380. if (rootKey == null) {
  381. throw PythonExceptions.CreateThrowable(PythonExceptions.EnvironmentError, "key has been closed");
  382. }
  383. try {
  384. var nativeRootKey = rootKey.GetKey();
  385. return PythonTuple.MakeTuple(nativeRootKey.SubKeyCount, nativeRootKey.ValueCount, 0);
  386. } catch (ObjectDisposedException e) {
  387. throw new ExternalException(e.Message);
  388. }
  389. }
  390. public static object QueryValue(object key, string subKeyName) {
  391. HKEYType pyKey = OpenKey(key, subKeyName);
  392. return pyKey.GetKey().GetValue(null);
  393. }
  394. public static PythonTuple QueryValueEx(object key, string valueName) {
  395. HKEYType rootKey = GetRootKey(key);
  396. // it looks like rootKey.GetKey().Handle fails on HKEY_PERFORMANCE_DATA so manually create the handle instead
  397. var handle = rootKey.hkey == HKEY_PERFORMANCE_DATA ? new SafeRegistryHandle(new IntPtr(unchecked((int)0x80000004)), true) : rootKey.GetKey().Handle;
  398. int valueKind;
  399. object value;
  400. QueryValueExImpl(handle, valueName, out valueKind, out value);
  401. return PythonTuple.MakeTuple(value, valueKind);
  402. }
  403. public static void SetValue(object key, string subKeyName, int type, string value) {
  404. HKEYType pyKey = CreateKey(key, subKeyName);
  405. pyKey.GetKey().SetValue(null, value);
  406. }
  407. public static void SetValueEx(object key, string valueName, object reserved, int type, object value) {
  408. HKEYType rootKey = GetRootKey(key);
  409. RegistryValueKind regKind = (RegistryValueKind)type;
  410. // null is a valid value but RegistryKey.SetValue doesn't like it so PInvoke to set it
  411. if (value == null) {
  412. RegSetValueEx(rootKey.GetKey().Handle, valueName, 0, type, null, 0);
  413. return;
  414. }
  415. if (regKind == RegistryValueKind.MultiString) {
  416. int size = ((List)value)._size;
  417. string[] strArray = new string[size];
  418. Array.Copy(((List)value)._data, strArray, size);
  419. rootKey.GetKey().SetValue(valueName, strArray, regKind);
  420. } else if (regKind == RegistryValueKind.Binary) {
  421. byte[] byteArr = null;
  422. if (value is string) {
  423. string strValue = value as string;
  424. ASCIIEncoding encoding = new ASCIIEncoding();
  425. byteArr = encoding.GetBytes(strValue);
  426. }
  427. rootKey.GetKey().SetValue(valueName, byteArr, regKind);
  428. } else if (regKind == RegistryValueKind.DWord) {
  429. // DWORDs are uint but the .NET API requires int
  430. if (value is BigInteger) {
  431. var val = (uint)(BigInteger)value;
  432. value = unchecked((int)val);
  433. }
  434. rootKey.GetKey().SetValue(valueName, value, regKind);
  435. } else if (regKind == RegistryValueKind.QWord) {
  436. // QWORDs are ulong but the .NET API requires long
  437. if (value is BigInteger) {
  438. var val = (ulong)(BigInteger)value;
  439. value = unchecked((long)val);
  440. }
  441. rootKey.GetKey().SetValue(valueName, value, regKind);
  442. } else {
  443. rootKey.GetKey().SetValue(valueName, value, regKind);
  444. }
  445. }
  446. public static HKEYType ConnectRegistry(string computerName, BigInteger key) {
  447. if (string.IsNullOrEmpty(computerName))
  448. computerName = string.Empty;
  449. #if NETSTANDARD
  450. if (computerName != string.Empty) {
  451. throw PythonExceptions.CreateThrowable(PythonExceptions.WindowsError);
  452. }
  453. #endif
  454. RegistryKey newKey = null;
  455. try {
  456. if (computerName == string.Empty) {
  457. newKey = RegistryKey.OpenBaseKey(MapSystemKey(key), RegistryView.Default);
  458. }
  459. #if !NETSTANDARD
  460. else {
  461. newKey = RegistryKey.OpenRemoteBaseKey(MapSystemKey(key), computerName);
  462. }
  463. #endif
  464. }
  465. catch (IOException ioe) {
  466. throw PythonExceptions.CreateThrowable(PythonExceptions.WindowsError, PythonExceptions._WindowsError.ERROR_BAD_NETPATH, ioe.Message);
  467. } catch (Exception e) {
  468. throw new ExternalException(e.Message);
  469. }
  470. return new HKEYType(newKey);
  471. }
  472. public static void DisableReflectionKey(object key) {
  473. HKEYType rootKey = GetRootKey(key);
  474. if (!Environment.Is64BitOperatingSystem) {
  475. throw new NotImplementedException("not implemented on this platform");
  476. }
  477. int dwRet = RegDisableReflectionKey(rootKey.GetKey().Handle);
  478. if (dwRet != ERROR_SUCCESS) {
  479. throw PythonExceptions.CreateThrowable(PythonExceptions.WindowsError, dwRet);
  480. }
  481. }
  482. public static void EnableReflectionKey(object key) {
  483. HKEYType rootKey = GetRootKey(key);
  484. if (!Environment.Is64BitOperatingSystem) {
  485. throw new NotImplementedException("not implemented on this platform");
  486. }
  487. int dwRet = RegEnableReflectionKey(rootKey.GetKey().Handle);
  488. if (dwRet != ERROR_SUCCESS) {
  489. throw PythonExceptions.CreateThrowable(PythonExceptions.WindowsError, dwRet);
  490. }
  491. }
  492. public static bool QueryReflectionKey(object key) {
  493. HKEYType rootKey = GetRootKey(key);
  494. bool isDisabled;
  495. if(!Environment.Is64BitOperatingSystem) {
  496. throw new NotImplementedException("not implemented on this platform");
  497. }
  498. int dwRet = RegQueryReflectionKey(rootKey.GetKey().Handle, out isDisabled);
  499. if (dwRet != ERROR_SUCCESS) {
  500. throw PythonExceptions.CreateThrowable(PythonExceptions.WindowsError, dwRet);
  501. }
  502. return isDisabled;
  503. }
  504. #endregion
  505. #region Helpers
  506. private static HKEYType GetRootKey(object key) {
  507. HKEYType rootKey;
  508. rootKey = key as HKEYType;
  509. if (rootKey == null) {
  510. if (key is BigInteger) {
  511. rootKey = new HKEYType(RegistryKey.OpenBaseKey(MapSystemKey((BigInteger)key), RegistryView.Default), (BigInteger)key);
  512. } else {
  513. throw new InvalidCastException("The object is not a PyHKEY object");
  514. }
  515. }
  516. return rootKey;
  517. }
  518. private static RegistryHive MapSystemKey(BigInteger hKey) {
  519. const RegistryHive RegistryHiveDynData = (RegistryHive)unchecked((int)0x80000006);
  520. if (hKey == HKEY_CLASSES_ROOT)
  521. return RegistryHive.ClassesRoot;
  522. else if (hKey == HKEY_CURRENT_CONFIG)
  523. return RegistryHive.CurrentConfig;
  524. else if (hKey == HKEY_CURRENT_USER)
  525. return RegistryHive.CurrentUser;
  526. else if (hKey == HKEY_DYN_DATA)
  527. return RegistryHiveDynData;
  528. else if (hKey == HKEY_LOCAL_MACHINE)
  529. return RegistryHive.LocalMachine;
  530. else if (hKey == HKEY_PERFORMANCE_DATA)
  531. return RegistryHive.PerformanceData;
  532. else if (hKey == HKEY_USERS)
  533. return RegistryHive.Users;
  534. else
  535. throw new ValueErrorException("Unknown system key");
  536. }
  537. private static int MapRegistryValueKind(RegistryValueKind registryValueKind) {
  538. return (int)registryValueKind;
  539. }
  540. #endregion
  541. [PythonType]
  542. public class HKEYType : IDisposable {
  543. private RegistryKey key;
  544. internal HKEYType(RegistryKey key) {
  545. this.key = key;
  546. HKeyHandleCache.cache[key.GetHashCode()] = new WeakReference(this);
  547. }
  548. internal readonly BigInteger hkey = 0;
  549. internal HKEYType(RegistryKey key, BigInteger hkey) : this(key) {
  550. this.hkey = hkey;
  551. }
  552. public void Close() {
  553. lock (this) {
  554. if (key != null) {
  555. HKeyHandleCache.cache.Remove(key.GetHashCode());
  556. key.Dispose();
  557. key = null;
  558. }
  559. }
  560. }
  561. public int Detach() {
  562. return 0; //Can't keep handle after the object is destroyed.
  563. }
  564. public int handle {
  565. get {
  566. lock (this) {
  567. if (key == null) {
  568. return 0;
  569. }
  570. return key.GetHashCode();
  571. }
  572. }
  573. }
  574. public static implicit operator int(HKEYType hKey) {
  575. return hKey.handle;
  576. }
  577. /// <summary>
  578. /// Returns the underlying .NET RegistryKey
  579. /// </summary>
  580. /// <returns></returns>
  581. [PythonHidden]
  582. public RegistryKey GetKey() {
  583. lock (this) {
  584. if (key == null) {
  585. throw PythonExceptions.CreateThrowable(PythonExceptions.EnvironmentError, "key has been closed");
  586. }
  587. return key;
  588. }
  589. }
  590. #region IDisposable Members
  591. void IDisposable.Dispose() {
  592. Close();
  593. }
  594. #endregion
  595. }
  596. }
  597. //CPython exposes the native handle for the registry keys as well. Since there is no .NET API to
  598. //expose the native handle, we return the hashcode of the key as the "handle". To track these handles
  599. //and return the right RegistryKey we maintain this cache of the generated handles.
  600. internal static class HKeyHandleCache {
  601. internal static Dictionary<int, WeakReference> cache = new Dictionary<int, WeakReference>();
  602. }
  603. }
  604. #endif