SafeNativeMethods.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.ServiceModel.ComIntegration
  5. {
  6. using System;
  7. using System.Collections.Specialized;
  8. using System.ComponentModel;
  9. using System.Runtime;
  10. using System.Runtime.InteropServices;
  11. using System.Runtime.InteropServices.ComTypes;
  12. using System.Runtime.Versioning;
  13. using System.Security;
  14. using System.Security.Permissions;
  15. using System.Security.Principal;
  16. using System.ServiceModel.Diagnostics;
  17. using System.Text;
  18. using Microsoft.Win32.SafeHandles;
  19. using SafeCloseHandle = System.IdentityModel.SafeCloseHandle;
  20. using SafeHGlobalHandle = System.IdentityModel.SafeHGlobalHandle;
  21. [Flags]
  22. enum CLSCTX
  23. {
  24. INPROC_SERVER = 0x1,
  25. INPROC_HANDLER = 0x2,
  26. LOCAL_SERVER = 0x4,
  27. INPROC_SERVER16 = 0x8,
  28. REMOTE_SERVER = 0x10,
  29. INPROC_HANDLER16 = 0x20,
  30. RESERVED1 = 0x40,
  31. RESERVED2 = 0x80,
  32. RESERVED3 = 0x100,
  33. RESERVED4 = 0x200,
  34. NO_CODE_DOWNLOAD = 0x400,
  35. RESERVED5 = 0x800,
  36. NO_CUSTOM_MARSHAL = 0x1000,
  37. ENABLE_CODE_DOWNLOAD = 0x2000,
  38. NO_FAILURE_LOG = 0x4000,
  39. DISABLE_AAA = 0x8000,
  40. ENABLE_AAA = 0x10000,
  41. FROM_DEFAULT_CONTEXT = 0x20000,
  42. ACTIVATE_32_BIT_SERVER = 0x40000,
  43. ACTIVATE_64_BIT_SERVER = 0x80000,
  44. INPROC = INPROC_SERVER | INPROC_HANDLER,
  45. SERVER = INPROC_SERVER | LOCAL_SERVER | REMOTE_SERVER,
  46. ALL = SERVER | INPROC_HANDLER
  47. }
  48. [Flags]
  49. enum ComRights
  50. {
  51. EXECUTE = 0x01,
  52. EXECUTE_LOCAL = 0x02,
  53. EXECUTE_REMOTE = 0x04,
  54. ACTIVATE_LOCAL = 0x08,
  55. ACTIVATE_REMOTE = 0x10
  56. }
  57. enum TOKEN_INFORMATION_CLASS
  58. {
  59. TokenUser = 1,
  60. TokenGroups,
  61. TokenPrivileges,
  62. TokenOwner,
  63. TokenPrimaryGroup,
  64. TokenDefaultDacl,
  65. TokenSource,
  66. TokenType,
  67. TokenImpersonationLevel,
  68. TokenStatistics,
  69. TokenRestrictedSids,
  70. TokenSessionId,
  71. TokenGroupsAndPrivileges,
  72. TokenSessionReference,
  73. TokenSandBoxInert
  74. }
  75. enum SecurityImpersonationLevel
  76. {
  77. Anonymous = 0,
  78. Identification = 1,
  79. Impersonation = 2,
  80. Delegation = 3,
  81. }
  82. enum TokenType
  83. {
  84. TokenPrimary = 1,
  85. TokenImpersonation
  86. }
  87. enum Win32Error
  88. {
  89. ERROR_SUCCESS = 0,
  90. ERROR_INSUFFICIENT_BUFFER = 122,
  91. ERROR_NO_TOKEN = 1008,
  92. ERROR_NONE_MAPPED = 1332,
  93. }
  94. enum EXTENDED_NAME_FORMAT
  95. {
  96. NameUnknown = 0,
  97. NameFullyQualifiedDN = 1,
  98. NameSamCompatible = 2,
  99. NameDisplay = 3,
  100. NameUniqueId = 6,
  101. NameCanonical = 7,
  102. NameUserPrincipalName = 8,
  103. NameCanonicalEx = 9,
  104. NameServicePrincipalName = 10,
  105. NameDnsDomainName = 12
  106. }
  107. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  108. struct TagVariant
  109. {
  110. public ushort vt;
  111. public ushort reserved1;
  112. public ushort reserved2;
  113. public ushort reserved3;
  114. public IntPtr ptr;
  115. public IntPtr pRecInfo;
  116. }
  117. static class HR
  118. {
  119. internal static readonly int S_OK = 0;
  120. internal static readonly int S_FALSE = 1;
  121. internal static readonly int MK_E_SYNTAX = unchecked((int)0x800401e4);
  122. internal static readonly int E_INVALIDARG = unchecked((int)0x80070057);
  123. internal static readonly int E_UNEXPECTED = unchecked((int)0x8000ffff);
  124. internal static readonly int DISP_E_UNKNOWNINTERFACE = unchecked((int)0x80020001);
  125. internal static readonly int DISP_E_MEMBERNOTFOUND = unchecked((int)0x80020003);
  126. internal static readonly int DISP_E_PARAMNOTFOUND = unchecked((int)0x80020004);
  127. internal static readonly int DISP_E_TYPEMISMATCH = unchecked((int)0x80020005);
  128. internal static readonly int DISP_E_UNKNOWNNAME = unchecked((int)0x80020006);
  129. internal static readonly int DISP_E_NONAMEDARGS = unchecked((int)0x80020007);
  130. internal static readonly int DISP_E_BADVARTYPE = unchecked((int)0x80020008);
  131. internal static readonly int DISP_E_EXCEPTION = unchecked((int)0x80020009);
  132. internal static readonly int DISP_E_OVERFLOW = unchecked((int)0x8002000A);
  133. internal static readonly int DISP_E_BADINDEX = unchecked((int)0x8002000B);
  134. internal static readonly int DISP_E_UNKNOWNLCID = unchecked((int)0x8002000C);
  135. internal static readonly int DISP_E_ARRAYISLOCKED = unchecked((int)0x8002000D);
  136. internal static readonly int DISP_E_BADPARAMCOUNT = unchecked((int)0x8002000E);
  137. internal static readonly int DISP_E_PARAMNOTOPTIONAL = unchecked((int)0x8002000F);
  138. internal static readonly int DISP_E_BADCALLEE = unchecked((int)0x80020010);
  139. internal static readonly int DISP_E_NOTACOLLECTION = unchecked((int)0x80020011);
  140. internal static readonly int DISP_E_DIVBYZERO = unchecked((int)0x80020012);
  141. internal static readonly int DISP_E_BUFFERTOOSMALL = unchecked((int)0x80020013);
  142. internal static readonly int RPC_E_TOO_LATE = unchecked((int)0x80010119);
  143. internal static readonly int RPC_NT_BINDING_HAS_NO_AUTH = unchecked((int)0x800706d2);
  144. internal static readonly int E_FAIL = unchecked((int)0x80040005);
  145. internal static readonly int COMADMIN_E_PARTITIONS_DISABLED = unchecked((int)0x80110824);
  146. internal static readonly int CONTEXT_E_NOTRANSACTION = unchecked((int)0x8004E027);
  147. internal static readonly int ERROR_BAD_IMPERSONATION_LEVEL = unchecked((int)(0x80070542));
  148. }
  149. static class InterfaceID
  150. {
  151. public static readonly Guid idISupportErrorInfo = new Guid("{df0b3d60-548f-101b-8e65-08002b2bd119}");
  152. public static readonly Guid idIDispatch = new Guid("00020400-0000-0000-C000-000000000046");
  153. }
  154. [StructLayout(LayoutKind.Sequential)]
  155. struct LUID
  156. {
  157. internal uint LowPart;
  158. internal int HighPart;
  159. }
  160. [StructLayout(LayoutKind.Sequential)]
  161. struct TOKEN_STATISTICS
  162. {
  163. internal LUID TokenId;
  164. internal LUID AuthenticationId;
  165. internal Int64 ExpirationTime;
  166. internal uint TokenType;
  167. internal SecurityImpersonationLevel ImpersonationLevel;
  168. internal uint DynamicCharged;
  169. internal uint DynamicAvailable;
  170. internal uint GroupCount;
  171. internal uint PrivilegeCount;
  172. internal LUID ModifiedId;
  173. }
  174. [StructLayout(LayoutKind.Sequential)]
  175. class GENERIC_MAPPING
  176. {
  177. internal uint genericRead = 0;
  178. internal uint genericWrite = 0;
  179. internal uint genericExecute = 0;
  180. internal uint genericAll = 0;
  181. }
  182. [Flags]
  183. internal enum PrivilegeAttribute : uint
  184. {
  185. SE_PRIVILEGE_DISABLED = 0x00000000, // note that this is not defined in the header files
  186. SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001,
  187. SE_PRIVILEGE_ENABLED = 0x00000002,
  188. SE_PRIVILEGE_REMOVED = 0X00000004,
  189. SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000,
  190. }
  191. [StructLayout(LayoutKind.Sequential)]
  192. struct LUID_AND_ATTRIBUTES
  193. {
  194. internal LUID Luid;
  195. internal PrivilegeAttribute Attributes;
  196. }
  197. [StructLayout(LayoutKind.Sequential)]
  198. class PRIVILEGE_SET
  199. {
  200. internal uint PrivilegeCount = 1;
  201. internal uint Control = 0;
  202. internal LUID_AND_ATTRIBUTES Privilege;
  203. }
  204. [SuppressUnmanagedCodeSecurity]
  205. static class SafeNativeMethods
  206. {
  207. internal const String KERNEL32 = "kernel32.dll";
  208. internal const String ADVAPI32 = "advapi32.dll";
  209. internal const String OLE32 = "ole32.dll";
  210. internal const String OLEAUT32 = "oleaut32.dll";
  211. internal const String COMSVCS = "comsvcs.dll";
  212. internal const String SECUR32 = "secur32.dll";
  213. internal const int ERROR_MORE_DATA = 0xEA;
  214. internal const int ERROR_SUCCESS = 0;
  215. internal const int ERROR_INVALID_HANDLE = 6;
  216. internal const int ERROR_NOT_SUPPORTED = 50;
  217. internal const int READ_CONTROL = 0x00020000;
  218. internal const int SYNCHRONIZE = 0x00100000;
  219. internal const int STANDARD_RIGHTS_READ = READ_CONTROL;
  220. internal const int STANDARD_RIGHTS_WRITE = READ_CONTROL;
  221. internal const int KEY_QUERY_VALUE = 0x0001;
  222. internal const int KEY_SET_VALUE = 0x0002;
  223. internal const int KEY_CREATE_SUB_KEY = 0x0004;
  224. internal const int KEY_ENUMERATE_SUB_KEYS = 0x0008;
  225. internal const int KEY_NOTIFY = 0x0010;
  226. internal const int KEY_CREATE_LINK = 0x0020;
  227. internal const int KEY_READ = ((STANDARD_RIGHTS_READ |
  228. KEY_QUERY_VALUE |
  229. KEY_ENUMERATE_SUB_KEYS |
  230. KEY_NOTIFY)
  231. &
  232. (~SYNCHRONIZE));
  233. internal const int KEY_WRITE = STANDARD_RIGHTS_WRITE |
  234. KEY_SET_VALUE |
  235. KEY_CREATE_SUB_KEY;
  236. internal const int REG_NONE = 0; // No value type
  237. internal const int REG_SZ = 1; // Unicode nul terminated string
  238. internal const int REG_EXPAND_SZ = 2; // Unicode nul terminated string
  239. internal const int KEY_WOW64_32KEY = (0x0200);
  240. internal const int KEY_WOW64_64KEY = (0x0100);
  241. // (with environment variable references)
  242. internal const int REG_BINARY = 3; // Free form binary
  243. internal const int REG_DWORD = 4; // 32-bit number
  244. internal const int REG_DWORD_LITTLE_ENDIAN = 4; // 32-bit number (same as REG_DWORD)
  245. internal const int REG_DWORD_BIG_ENDIAN = 5; // 32-bit number
  246. internal const int REG_LINK = 6; // Symbolic Link (unicode)
  247. internal const int REG_MULTI_SZ = 7; // Multiple Unicode strings
  248. internal const int REG_RESOURCE_LIST = 8; // Resource list in the resource map
  249. internal const int REG_FULL_RESOURCE_DESCRIPTOR = 9; // Resource list in the hardware description
  250. internal const int REG_RESOURCE_REQUIREMENTS_LIST = 10;
  251. internal const int REG_QWORD = 11; // 64-bit number
  252. internal const int HWND_BROADCAST = 0xffff;
  253. internal const int WM_SETTINGCHANGE = 0x001A;
  254. [DllImport(ADVAPI32, CharSet = CharSet.Unicode, BestFitMapping = false)]
  255. [ResourceExposure(ResourceScope.Machine)]
  256. internal static extern int RegOpenKeyEx(RegistryHandle hKey, String lpSubKey,
  257. int ulOptions, int samDesired, out RegistryHandle hkResult);
  258. [DllImport(ADVAPI32, CharSet = CharSet.Unicode, BestFitMapping = false)]
  259. [ResourceExposure(ResourceScope.None)]
  260. internal static extern int RegSetValueEx(RegistryHandle hKey, String lpValueName,
  261. int Reserved, int dwType, String val, int cbData);
  262. [DllImport(ADVAPI32, SetLastError = false)]
  263. [ResourceExposure(ResourceScope.None)]
  264. internal static extern int RegCloseKey(IntPtr handle);
  265. [DllImport(ADVAPI32, CharSet = CharSet.Unicode, BestFitMapping = false)]
  266. [ResourceExposure(ResourceScope.None)]
  267. internal static extern int RegQueryValueEx(RegistryHandle hKey, String lpValueName,
  268. int[] lpReserved, ref int lpType, [Out] byte[] lpData,
  269. ref int lpcbData);
  270. [DllImport(ADVAPI32, CharSet = CharSet.Unicode, BestFitMapping = false)]
  271. [ResourceExposure(ResourceScope.None)]
  272. internal static extern int RegEnumKey(RegistryHandle hKey, int index, StringBuilder lpName, ref int len);
  273. [DllImport(ADVAPI32, CharSet = CharSet.Unicode, BestFitMapping = false)]
  274. [ResourceExposure(ResourceScope.None)]
  275. internal static extern int RegDeleteKey(RegistryHandle hKey, String lpValueName);
  276. [DllImport(ADVAPI32, SetLastError = true)]
  277. [ResourceExposure(ResourceScope.None)]
  278. internal static extern bool
  279. DuplicateTokenEx(
  280. [In] SafeCloseHandle ExistingToken,
  281. [In] TokenAccessLevels DesiredAccess,
  282. [In] IntPtr TokenAttributes,
  283. [In] SecurityImpersonationLevel ImpersonationLevel,
  284. [In] TokenType TokenType,
  285. [Out] out SafeCloseHandle NewToken);
  286. [DllImport(ADVAPI32, SetLastError = true)]
  287. [ResourceExposure(ResourceScope.None)]
  288. internal static extern bool
  289. AccessCheck(
  290. [In] byte[] SecurityDescriptor,
  291. [In] SafeCloseHandle ClientToken,
  292. [In] int DesiredAccess,
  293. [In] GENERIC_MAPPING GenericMapping,
  294. [Out] out PRIVILEGE_SET PrivilegeSet,
  295. [In, Out] ref uint PrivilegeSetLength,
  296. [Out] out uint GrantedAccess,
  297. [Out] out bool AccessStatus);
  298. [DllImport(ADVAPI32, SetLastError = true, EntryPoint = "ImpersonateAnonymousToken")]
  299. [ResourceExposure(ResourceScope.None)]
  300. internal static extern bool
  301. ImpersonateAnonymousUserOnCurrentThread(
  302. [In] IntPtr CurrentThread);
  303. [DllImport(ADVAPI32, SetLastError = true, EntryPoint = "OpenThreadToken")]
  304. [ResourceExposure(ResourceScope.None)]
  305. internal static extern bool
  306. OpenCurrentThreadToken(
  307. [In] IntPtr ThreadHandle,
  308. [In] TokenAccessLevels DesiredAccess,
  309. [In] bool OpenAsSelf,
  310. [Out] out SafeCloseHandle TokenHandle);
  311. [DllImport(ADVAPI32, SetLastError = true, EntryPoint = "SetThreadToken")]
  312. [ResourceExposure(ResourceScope.None)]
  313. internal static extern bool
  314. SetCurrentThreadToken(
  315. [In] IntPtr ThreadHandle,
  316. [In] SafeCloseHandle TokenHandle);
  317. [DllImport(KERNEL32, SetLastError = true)]
  318. [ResourceExposure(ResourceScope.None)]
  319. internal static extern IntPtr
  320. GetCurrentThread();
  321. [DllImport(KERNEL32, SetLastError = false)]
  322. [ResourceExposure(ResourceScope.None)]
  323. internal static extern int
  324. GetCurrentThreadId();
  325. [DllImport(ADVAPI32, SetLastError = true)]
  326. [ResourceExposure(ResourceScope.None)]
  327. internal static extern bool
  328. RevertToSelf();
  329. [DllImport(ADVAPI32, SetLastError = true)]
  330. [ResourceExposure(ResourceScope.None)]
  331. internal static extern bool
  332. GetTokenInformation(
  333. [In] SafeCloseHandle TokenHandle,
  334. [In] TOKEN_INFORMATION_CLASS TokenInformationClass,
  335. [In] SafeHandle TokenInformation,
  336. [Out] uint TokenInformationLength,
  337. [Out] out uint ReturnLength);
  338. [DllImport(KERNEL32, SetLastError = true)]
  339. [ResourceExposure(ResourceScope.None)]
  340. internal static extern IntPtr
  341. GetCurrentProcess();
  342. [DllImport(ADVAPI32, SetLastError = true, EntryPoint = "OpenProcessToken")]
  343. [ResourceExposure(ResourceScope.None)]
  344. internal static extern bool
  345. GetCurrentProcessToken(
  346. [In]IntPtr ProcessHandle,
  347. [In]TokenAccessLevels DesiredAccess,
  348. [Out]out SafeCloseHandle TokenHandle);
  349. [DllImport(OLE32, ExactSpelling = true, PreserveSig = false)]
  350. [return: MarshalAs(UnmanagedType.Interface)]
  351. [ResourceExposure(ResourceScope.None)]
  352. public static extern object CoCreateInstance(
  353. [In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
  354. [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter,
  355. [In] CLSCTX dwClsContext,
  356. [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
  357. [DllImport(OLE32, ExactSpelling = true, PreserveSig = false)]
  358. [return: MarshalAs(UnmanagedType.Interface)]
  359. [ResourceExposure(ResourceScope.None)]
  360. public static extern IStream CreateStreamOnHGlobal(
  361. [In] SafeHGlobalHandle hGlobal,
  362. [In, MarshalAs(UnmanagedType.Bool)] bool fDeleteOnRelease);
  363. [DllImport(OLE32, ExactSpelling = true, PreserveSig = false)]
  364. [ResourceExposure(ResourceScope.None)]
  365. public static extern SafeHGlobalHandle GetHGlobalFromStream(IStream stream);
  366. [DllImport(OLE32, ExactSpelling = true, PreserveSig = false)]
  367. [return: MarshalAs(UnmanagedType.Interface)]
  368. [ResourceExposure(ResourceScope.None)]
  369. public static extern object CoGetObjectContext(
  370. [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
  371. [DllImport(COMSVCS, ExactSpelling = true, PreserveSig = false)]
  372. [return: MarshalAs(UnmanagedType.Interface)]
  373. [ResourceExposure(ResourceScope.None)]
  374. public static extern object CoCreateActivity(
  375. [In, MarshalAs(UnmanagedType.IUnknown)] object pIUnknown,
  376. [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
  377. [DllImport(OLE32, ExactSpelling = true, PreserveSig = false)]
  378. [ResourceExposure(ResourceScope.None)]
  379. internal static extern IntPtr CoSwitchCallContext(IntPtr newSecurityObject);
  380. [DllImport(KERNEL32, ExactSpelling = true, PreserveSig = true)]
  381. [ResourceExposure(ResourceScope.None)]
  382. internal static extern IntPtr GlobalLock(SafeHGlobalHandle hGlobal);
  383. [DllImport(KERNEL32, ExactSpelling = true, PreserveSig = true)]
  384. [return: MarshalAs(UnmanagedType.Bool)]
  385. [ResourceExposure(ResourceScope.None)]
  386. internal static extern bool GlobalUnlock(SafeHGlobalHandle hGlobal);
  387. [DllImport(KERNEL32, ExactSpelling = true, PreserveSig = true)]
  388. [ResourceExposure(ResourceScope.None)]
  389. internal static extern IntPtr GlobalSize(SafeHGlobalHandle hGlobal);
  390. [DllImport(OLEAUT32,
  391. ExactSpelling = true,
  392. CharSet = CharSet.Unicode,
  393. PreserveSig = true)]
  394. [ResourceExposure(ResourceScope.None)]
  395. internal static extern int LoadRegTypeLib(ref Guid rguid, ushort major, ushort minor, int lcid,
  396. [MarshalAs(UnmanagedType.Interface)] out object typeLib);
  397. [DllImport(OLEAUT32,
  398. ExactSpelling = true,
  399. CharSet = CharSet.Unicode,
  400. PreserveSig = true)]
  401. [ResourceExposure(ResourceScope.None)]
  402. internal static extern int SafeArrayGetDim(IntPtr pSafeArray);
  403. [DllImport(OLEAUT32,
  404. ExactSpelling = true,
  405. CharSet = CharSet.Unicode,
  406. PreserveSig = true)]
  407. [ResourceExposure(ResourceScope.None)]
  408. internal static extern int SafeArrayGetElemsize(IntPtr pSafeArray);
  409. [DllImport(OLEAUT32,
  410. ExactSpelling = true,
  411. CharSet = CharSet.Unicode,
  412. PreserveSig = false)]
  413. [ResourceExposure(ResourceScope.None)]
  414. internal static extern int SafeArrayGetLBound(IntPtr pSafeArray, int cDims);
  415. [DllImport(OLEAUT32,
  416. ExactSpelling = true,
  417. CharSet = CharSet.Unicode,
  418. PreserveSig = false)]
  419. [ResourceExposure(ResourceScope.None)]
  420. internal static extern int SafeArrayGetUBound(IntPtr pSafeArray, int cDims);
  421. [DllImport(OLEAUT32,
  422. ExactSpelling = true,
  423. CharSet = CharSet.Unicode,
  424. PreserveSig = false)]
  425. [ResourceExposure(ResourceScope.None)]
  426. internal static extern IntPtr SafeArrayAccessData(IntPtr pSafeArray);
  427. [DllImport(OLEAUT32,
  428. ExactSpelling = true,
  429. CharSet = CharSet.Unicode,
  430. PreserveSig = false)]
  431. [ResourceExposure(ResourceScope.None)]
  432. internal static extern void SafeArrayUnaccessData(IntPtr pSafeArray);
  433. [DllImport(SECUR32, CharSet = CharSet.Unicode, SetLastError = true)]
  434. [return: MarshalAs(UnmanagedType.U1)]
  435. [ResourceExposure(ResourceScope.None)]
  436. internal extern static bool TranslateName(string input, EXTENDED_NAME_FORMAT inputFormat, EXTENDED_NAME_FORMAT outputFormat, StringBuilder outputString, out uint size);
  437. }
  438. internal static class InterfaceHelper
  439. {
  440. // only use this helper to get interfaces that are guaranteed to be supported
  441. internal static IntPtr GetInterfacePtrForObject(Guid iid, object obj)
  442. {
  443. IntPtr pUnk = Marshal.GetIUnknownForObject(obj);
  444. if (IntPtr.Zero == pUnk)
  445. {
  446. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.UnableToRetrievepUnk)));
  447. }
  448. IntPtr ppv = IntPtr.Zero;
  449. int hr = Marshal.QueryInterface(pUnk, ref iid, out ppv);
  450. Marshal.Release(pUnk);
  451. if (hr != HR.S_OK)
  452. {
  453. throw Fx.AssertAndThrow("QueryInterface should succeed");
  454. }
  455. return ppv;
  456. }
  457. }
  458. internal class RegistryHandle : SafeHandleZeroOrMinusOneIsInvalid
  459. {
  460. internal static readonly RegistryHandle HKEY_CLASSES_ROOT = new RegistryHandle(new IntPtr(unchecked((int)0x80000000)), false);
  461. internal static readonly RegistryHandle HKEY_CURRENT_USER = new RegistryHandle(new IntPtr(unchecked((int)0x80000001)), false);
  462. internal static readonly RegistryHandle HKEY_LOCAL_MACHINE = new RegistryHandle(new IntPtr(unchecked((int)0x80000002)), false);
  463. internal static readonly RegistryHandle HKEY_USERS = new RegistryHandle(new IntPtr(unchecked((int)0x80000003)), false);
  464. internal static readonly RegistryHandle HKEY_PERFORMANCE_DATA = new RegistryHandle(new IntPtr(unchecked((int)0x80000004)), false);
  465. internal static readonly RegistryHandle HKEY_CURRENT_CONFIG = new RegistryHandle(new IntPtr(unchecked((int)0x80000005)), false);
  466. internal static readonly RegistryHandle HKEY_DYN_DATA = new RegistryHandle(new IntPtr(unchecked((int)0x80000006)), false);
  467. [ResourceConsumption(ResourceScope.Machine)]
  468. static RegistryHandle GetHKCR()
  469. {
  470. RegistryHandle regHandle = null;
  471. int status = SafeNativeMethods.RegOpenKeyEx(HKEY_LOCAL_MACHINE, @"Software\Classes", 0, SafeNativeMethods.KEY_READ, out regHandle);
  472. if (status != SafeNativeMethods.ERROR_SUCCESS)
  473. {
  474. Utility.CloseInvalidOutSafeHandle(regHandle);
  475. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(status));
  476. }
  477. if (null == regHandle || regHandle.IsInvalid)
  478. {
  479. Fx.Assert("GetHKCR: RegOpenKeyEx returned null but with an invalid handle.");
  480. Utility.CloseInvalidOutSafeHandle(regHandle);
  481. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(SafeNativeMethods.ERROR_INVALID_HANDLE));
  482. }
  483. return regHandle;
  484. }
  485. [ResourceConsumption(ResourceScope.Machine)]
  486. static RegistryHandle Get64bitHKCR()
  487. {
  488. RegistryHandle regHandle = null;
  489. int status = SafeNativeMethods.RegOpenKeyEx(HKEY_LOCAL_MACHINE, @"Software\Classes", 0, SafeNativeMethods.KEY_READ | SafeNativeMethods.KEY_WOW64_64KEY, out regHandle);
  490. if (status != SafeNativeMethods.ERROR_SUCCESS)
  491. {
  492. Utility.CloseInvalidOutSafeHandle(regHandle);
  493. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(status));
  494. }
  495. if (null == regHandle || regHandle.IsInvalid)
  496. {
  497. Fx.Assert("Get64bitHKCR: RegOpenKeyEx returned null but with an invalid handle.");
  498. Utility.CloseInvalidOutSafeHandle(regHandle);
  499. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(SafeNativeMethods.ERROR_INVALID_HANDLE));
  500. }
  501. return regHandle;
  502. }
  503. [ResourceConsumption(ResourceScope.Machine)]
  504. static RegistryHandle Get32bitHKCR()
  505. {
  506. RegistryHandle regHandle = null;
  507. int status = SafeNativeMethods.RegOpenKeyEx(HKEY_LOCAL_MACHINE, @"Software\Classes", 0, SafeNativeMethods.KEY_READ | SafeNativeMethods.KEY_WOW64_32KEY, out regHandle);
  508. if (status != SafeNativeMethods.ERROR_SUCCESS)
  509. {
  510. Utility.CloseInvalidOutSafeHandle(regHandle);
  511. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(status));
  512. }
  513. if (null == regHandle || regHandle.IsInvalid)
  514. {
  515. Fx.Assert("Get64bitHKCR: RegOpenKeyEx returned null but with an invalid handle.");
  516. Utility.CloseInvalidOutSafeHandle(regHandle);
  517. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(SafeNativeMethods.ERROR_INVALID_HANDLE));
  518. }
  519. return regHandle;
  520. }
  521. static RegistryHandle GetCorrectBitnessHive(bool is64bit)
  522. {
  523. if (is64bit && IntPtr.Size == 8) // No worries we are trying to open up a 64 bit hive just return
  524. return GetHKCR();
  525. else if (is64bit && IntPtr.Size == 4) // we are running under wow get the 64 bit hive
  526. return Get64bitHKCR();
  527. else if (!is64bit && IntPtr.Size == 8) // we are running in 64 bit but need to open a 32 bit hive
  528. return Get32bitHKCR();
  529. else if (!is64bit && IntPtr.Size == 4)
  530. return GetHKCR();
  531. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(SafeNativeMethods.ERROR_NOT_SUPPORTED));
  532. }
  533. public static RegistryHandle GetBitnessHKCR(bool is64bit)
  534. {
  535. return GetCorrectBitnessHive(is64bit);
  536. }
  537. public static RegistryHandle GetCorrectBitnessHKLMSubkey(bool is64bit, string key)
  538. {
  539. if (is64bit && IntPtr.Size == 8) // No worries we are trying to open up a 64 bit hive just return
  540. return GetHKLMSubkey(key);
  541. else if (is64bit && IntPtr.Size == 4) // we are running under wow get the 64 bit hive
  542. return Get64bitHKLMSubkey(key);
  543. else if (!is64bit && IntPtr.Size == 8) // we are running in 64 bit but need to open a 32 bit hive
  544. return Get32bitHKLMSubkey(key);
  545. else if (!is64bit && IntPtr.Size == 4)
  546. return GetHKLMSubkey(key);
  547. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(SafeNativeMethods.ERROR_NOT_SUPPORTED));
  548. }
  549. [ResourceConsumption(ResourceScope.Machine)]
  550. static RegistryHandle GetHKLMSubkey(string key)
  551. {
  552. RegistryHandle regHandle = null;
  553. int status = SafeNativeMethods.RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, SafeNativeMethods.KEY_READ, out regHandle);
  554. if (status != SafeNativeMethods.ERROR_SUCCESS)
  555. {
  556. Utility.CloseInvalidOutSafeHandle(regHandle);
  557. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(status));
  558. }
  559. if (null == regHandle || regHandle.IsInvalid)
  560. {
  561. Fx.Assert("GetHKLMSubkey: RegOpenKeyEx returned null but with an invalid handle.");
  562. Utility.CloseInvalidOutSafeHandle(regHandle);
  563. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(SafeNativeMethods.ERROR_INVALID_HANDLE));
  564. }
  565. return regHandle;
  566. }
  567. [ResourceConsumption(ResourceScope.Machine)]
  568. static RegistryHandle Get64bitHKLMSubkey(string key)
  569. {
  570. RegistryHandle regHandle = null;
  571. int status = SafeNativeMethods.RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, SafeNativeMethods.KEY_READ | SafeNativeMethods.KEY_WOW64_64KEY, out regHandle);
  572. if (status != SafeNativeMethods.ERROR_SUCCESS)
  573. {
  574. Utility.CloseInvalidOutSafeHandle(regHandle);
  575. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(status));
  576. }
  577. if (null == regHandle || regHandle.IsInvalid)
  578. {
  579. Fx.Assert("Get64bitHKLMSubkey: RegOpenKeyEx returned null but with an invalid handle.");
  580. Utility.CloseInvalidOutSafeHandle(regHandle);
  581. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(SafeNativeMethods.ERROR_INVALID_HANDLE));
  582. }
  583. return regHandle;
  584. }
  585. [ResourceConsumption(ResourceScope.Machine)]
  586. static RegistryHandle Get32bitHKLMSubkey(string key)
  587. {
  588. RegistryHandle regHandle = null;
  589. int status = SafeNativeMethods.RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, SafeNativeMethods.KEY_READ | SafeNativeMethods.KEY_WOW64_32KEY, out regHandle);
  590. if (status != SafeNativeMethods.ERROR_SUCCESS)
  591. {
  592. Utility.CloseInvalidOutSafeHandle(regHandle);
  593. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(status));
  594. }
  595. if (null == regHandle || regHandle.IsInvalid)
  596. {
  597. Fx.Assert("Get32bitHKLMSubkey: RegOpenKeyEx returned null but with an invalid handle.");
  598. Utility.CloseInvalidOutSafeHandle(regHandle);
  599. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(SafeNativeMethods.ERROR_INVALID_HANDLE));
  600. }
  601. return regHandle;
  602. }
  603. [ResourceConsumption(ResourceScope.Machine)]
  604. internal static RegistryHandle GetNativeHKLMSubkey(string subKey, bool writeable)
  605. {
  606. RegistryHandle regHandle = null;
  607. int samDesired = SafeNativeMethods.KEY_READ | SafeNativeMethods.KEY_WOW64_64KEY;
  608. if (writeable)
  609. {
  610. samDesired |= SafeNativeMethods.KEY_WRITE;
  611. }
  612. int status = SafeNativeMethods.RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, samDesired, out regHandle);
  613. if (status != SafeNativeMethods.ERROR_SUCCESS || regHandle == null || regHandle.IsInvalid)
  614. {
  615. Utility.CloseInvalidOutSafeHandle(regHandle);
  616. return null;
  617. }
  618. return regHandle;
  619. }
  620. public RegistryHandle(IntPtr hKey, bool ownHandle)
  621. : base(ownHandle)
  622. {
  623. handle = hKey;
  624. }
  625. public RegistryHandle()
  626. : base(true)
  627. {
  628. }
  629. public bool DeleteKey(string key)
  630. {
  631. int status = SafeNativeMethods.RegDeleteKey(this, key);
  632. if (status == SafeNativeMethods.ERROR_SUCCESS)
  633. return true;
  634. else
  635. return false;
  636. }
  637. public void SetValue(string valName, string value)
  638. {
  639. int status = SafeNativeMethods.RegSetValueEx(this, valName, 0, SafeNativeMethods.REG_SZ, value, (value.Length * 2) + 2);
  640. if (status != SafeNativeMethods.ERROR_SUCCESS)
  641. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(status));
  642. }
  643. [ResourceConsumption(ResourceScope.Machine)]
  644. public RegistryHandle OpenSubKey(string subkey)
  645. {
  646. RegistryHandle regHandle = null;
  647. int status = SafeNativeMethods.RegOpenKeyEx(this, subkey, 0, SafeNativeMethods.KEY_READ, out regHandle);
  648. if (status != SafeNativeMethods.ERROR_SUCCESS || regHandle == null || regHandle.IsInvalid)
  649. {
  650. Utility.CloseInvalidOutSafeHandle(regHandle);
  651. return null;
  652. }
  653. return regHandle;
  654. }
  655. public string GetStringValue(string valName)
  656. {
  657. int type = 0;
  658. int datasize = 0;
  659. int ret = SafeNativeMethods.RegQueryValueEx(this, valName, null, ref type, (byte[])null, ref datasize);
  660. if (ret == SafeNativeMethods.ERROR_SUCCESS)
  661. if (type == SafeNativeMethods.REG_SZ)
  662. {
  663. byte[] blob = new byte[datasize];
  664. ret = SafeNativeMethods.RegQueryValueEx(this, valName, null, ref type, (byte[])blob, ref datasize);
  665. UnicodeEncoding unicode = new UnicodeEncoding();
  666. return unicode.GetString(blob);
  667. }
  668. return null;
  669. }
  670. public StringCollection GetSubKeyNames()
  671. {
  672. int ret = 0;
  673. int index = 0;
  674. StringCollection keyNames = new StringCollection();
  675. do
  676. {
  677. int lengthInChars = 0;
  678. ret = SafeNativeMethods.RegEnumKey(this, index, null, ref lengthInChars);
  679. if (ret == SafeNativeMethods.ERROR_MORE_DATA)
  680. {
  681. StringBuilder keyName = new StringBuilder(lengthInChars + 1);
  682. ret = SafeNativeMethods.RegEnumKey(this, index, keyName, ref lengthInChars);
  683. if (ret == SafeNativeMethods.ERROR_SUCCESS)
  684. keyNames.Add(keyName.ToString());
  685. }
  686. index++;
  687. }
  688. while (ret == SafeNativeMethods.ERROR_SUCCESS);
  689. return keyNames;
  690. }
  691. [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
  692. internal unsafe object GetValue(string valName)
  693. {
  694. object retVal = null;
  695. int type = 0;
  696. int datasize = 0;
  697. int ret = SafeNativeMethods.RegQueryValueEx(this, valName, null, ref type, (byte[])null, ref datasize);
  698. if (SafeNativeMethods.ERROR_SUCCESS == ret)
  699. {
  700. byte[] blob = new byte[datasize];
  701. ret = SafeNativeMethods.RegQueryValueEx(this, valName, null, ref type, (byte[])blob, ref datasize);
  702. if (SafeNativeMethods.ERROR_SUCCESS == ret)
  703. {
  704. UnicodeEncoding unicode = new UnicodeEncoding();
  705. string stringVal = unicode.GetString(blob);
  706. switch (type)
  707. {
  708. case (SafeNativeMethods.REG_BINARY):
  709. retVal = blob;
  710. break;
  711. case (SafeNativeMethods.REG_DWORD):
  712. fixed (byte* pBuffer = blob)
  713. {
  714. retVal = Marshal.ReadInt32((IntPtr)pBuffer);
  715. }
  716. break;
  717. case (SafeNativeMethods.REG_MULTI_SZ):
  718. retVal = stringVal.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
  719. break;
  720. case (SafeNativeMethods.REG_QWORD):
  721. fixed (byte* pBuffer = blob)
  722. {
  723. retVal = Marshal.ReadInt64((IntPtr)pBuffer);
  724. }
  725. break;
  726. case (SafeNativeMethods.REG_EXPAND_SZ):
  727. case (SafeNativeMethods.REG_SZ):
  728. retVal = stringVal.Trim(new char[] { '\0' });
  729. break;
  730. default:
  731. retVal = blob;
  732. break;
  733. }
  734. }
  735. }
  736. return retVal;
  737. }
  738. protected override bool ReleaseHandle()
  739. {
  740. if (SafeNativeMethods.RegCloseKey(handle) == SafeNativeMethods.ERROR_SUCCESS)
  741. return true;
  742. else
  743. return false;
  744. }
  745. }
  746. }