summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/Microsoft
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/Microsoft')
-rw-r--r--src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs134
-rw-r--r--src/mscorlib/src/Microsoft/Win32/Registry.cs174
-rw-r--r--src/mscorlib/src/Microsoft/Win32/RegistryKey.cs2166
-rw-r--r--src/mscorlib/src/Microsoft/Win32/RegistryOptions.cs25
-rw-r--r--src/mscorlib/src/Microsoft/Win32/RegistryValueKind.cs20
-rw-r--r--src/mscorlib/src/Microsoft/Win32/RegistryView.cs19
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs43
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs43
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs35
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs29
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs29
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs41
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs50
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs47
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs112
-rw-r--r--src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs282
-rw-r--r--src/mscorlib/src/Microsoft/Win32/Win32Native.cs2455
17 files changed, 5704 insertions, 0 deletions
diff --git a/src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs b/src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs
new file mode 100644
index 0000000000..118c69b8b7
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs
@@ -0,0 +1,134 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This class only exists to provide support for
+** implenting IDispatch on managed objects. It is
+** used to provide OleAut style coercion rules.
+**
+**
+===========================================================*/
+namespace Microsoft.Win32 {
+
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ internal static class OAVariantLib
+ {
+ #region Constants
+
+ // Constants for VariantChangeType from OleAuto.h
+ public const int NoValueProp = 0x01;
+ public const int AlphaBool = 0x02;
+ public const int NoUserOverride = 0x04;
+ public const int CalendarHijri = 0x08;
+ public const int LocalBool = 0x10;
+
+ internal static readonly Type [] ClassTypes = {
+ typeof(Empty),
+ typeof(void),
+ typeof(Boolean),
+ typeof(Char),
+ typeof(SByte),
+ typeof(Byte),
+ typeof(Int16),
+ typeof(UInt16),
+ typeof(Int32),
+ typeof(UInt32),
+ typeof(Int64),
+ typeof(UInt64),
+ typeof(Single),
+ typeof(Double),
+ typeof(String),
+ typeof(void),
+ typeof(DateTime),
+ typeof(TimeSpan),
+ typeof(Object),
+ typeof(Decimal),
+ null, // Enums - what do we do here?
+ typeof(Missing),
+ typeof(DBNull),
+ };
+
+ // Keep these numbers in sync w/ the above array.
+ private const int CV_OBJECT=0x12;
+
+ #endregion
+
+
+ #region Internal Methods
+
+ /**
+ * Changes a Variant from one type to another, calling the OLE
+ * Automation VariantChangeTypeEx routine. Note the legal types here are
+ * restricted to the subset of what can be legally found in a VB
+ * Variant and the types that CLR supports explicitly in the
+ * CLR Variant class.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Variant ChangeType(Variant source, Type targetClass, short options, CultureInfo culture)
+ {
+ if (targetClass == null)
+ throw new ArgumentNullException("targetClass");
+ if (culture == null)
+ throw new ArgumentNullException("culture");
+ Variant result = new Variant ();
+ ChangeTypeEx(ref result, ref source,
+#if FEATURE_USE_LCID
+ culture.LCID,
+#else
+ // @CORESYSTODO: what does CoreSystem expect for this argument?
+ 0,
+#endif
+ targetClass.TypeHandle.Value, GetCVTypeFromClass(targetClass), options);
+ return result;
+ }
+
+ #endregion
+
+
+ #region Private Helpers
+
+ private static int GetCVTypeFromClass(Type ctype)
+ {
+ Contract.Requires(ctype != null);
+#if _DEBUG
+ BCLDebug.Assert(ClassTypes[CV_OBJECT] == typeof(Object), "OAVariantLib::ClassTypes[CV_OBJECT] == Object.class");
+#endif
+
+ int cvtype=-1;
+ for (int i=0; i<ClassTypes.Length; i++) {
+ if (ctype.Equals(ClassTypes[i])) {
+ cvtype=i;
+ break;
+ }
+ }
+
+ // OleAut Binder works better if unrecognized
+ // types were changed to Object. So don't throw here.
+ if (cvtype == -1)
+ cvtype = CV_OBJECT;
+
+ return cvtype;
+ }
+
+ #endregion
+
+
+ #region Private FCalls
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void ChangeTypeEx(ref Variant result, ref Variant source, int lcid, IntPtr typeHandle, int cvType, short flags);
+
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/Registry.cs b/src/mscorlib/src/Microsoft/Win32/Registry.cs
new file mode 100644
index 0000000000..4faf29da7f
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/Registry.cs
@@ -0,0 +1,174 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace Microsoft.Win32 {
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+
+ /**
+ * Registry encapsulation. Contains members representing all top level system
+ * keys.
+ *
+ * @security(checkClassLinking=on)
+ */
+ //This class contains only static members and does not need to be serializable.
+ [ComVisible(true)]
+ public static class Registry {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static Registry()
+ {
+ }
+
+ /**
+ * Current User Key.
+ *
+ * This key should be used as the root for all user specific settings.
+ */
+ public static readonly RegistryKey CurrentUser = RegistryKey.GetBaseKey(RegistryKey.HKEY_CURRENT_USER);
+
+ /**
+ * Local Machine Key.
+ *
+ * This key should be used as the root for all machine specific settings.
+ */
+ public static readonly RegistryKey LocalMachine = RegistryKey.GetBaseKey(RegistryKey.HKEY_LOCAL_MACHINE);
+
+ /**
+ * Classes Root Key.
+ *
+ * This is the root key of class information.
+ */
+ public static readonly RegistryKey ClassesRoot = RegistryKey.GetBaseKey(RegistryKey.HKEY_CLASSES_ROOT);
+
+ /**
+ * Users Root Key.
+ *
+ * This is the root of users.
+ */
+ public static readonly RegistryKey Users = RegistryKey.GetBaseKey(RegistryKey.HKEY_USERS);
+
+ /**
+ * Performance Root Key.
+ *
+ * This is where dynamic performance data is stored on NT.
+ */
+ public static readonly RegistryKey PerformanceData = RegistryKey.GetBaseKey(RegistryKey.HKEY_PERFORMANCE_DATA);
+
+ /**
+ * Current Config Root Key.
+ *
+ * This is where current configuration information is stored.
+ */
+ public static readonly RegistryKey CurrentConfig = RegistryKey.GetBaseKey(RegistryKey.HKEY_CURRENT_CONFIG);
+
+#if !FEATURE_CORECLR
+ /**
+ * Dynamic Data Root Key.
+ *
+ * LEGACY: This is where dynamic performance data is stored on Win9X.
+ * This does not exist on NT.
+ */
+ [Obsolete("The DynData registry key only works on Win9x, which is no longer supported by the CLR. On NT-based operating systems, use the PerformanceData registry key instead.")]
+ public static readonly RegistryKey DynData = RegistryKey.GetBaseKey(RegistryKey.HKEY_DYN_DATA);
+#endif
+
+ //
+ // Following function will parse a keyName and returns the basekey for it.
+ // It will also store the subkey name in the out parameter.
+ // If the keyName is not valid, we will throw ArgumentException.
+ // The return value shouldn't be null.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ private static RegistryKey GetBaseKeyFromKeyName(string keyName, out string subKeyName) {
+ if( keyName == null) {
+ throw new ArgumentNullException("keyName");
+ }
+
+ string basekeyName;
+ int i = keyName.IndexOf('\\');
+ if( i != -1) {
+ basekeyName = keyName.Substring(0, i).ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+ }
+ else {
+ basekeyName = keyName.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+ }
+ RegistryKey basekey = null;
+
+ switch(basekeyName) {
+ case "HKEY_CURRENT_USER":
+ basekey = Registry.CurrentUser;
+ break;
+ case "HKEY_LOCAL_MACHINE":
+ basekey = Registry.LocalMachine;
+ break;
+ case "HKEY_CLASSES_ROOT":
+ basekey = Registry.ClassesRoot;
+ break;
+ case "HKEY_USERS":
+ basekey = Registry.Users;
+ break;
+ case "HKEY_PERFORMANCE_DATA":
+ basekey = Registry.PerformanceData;
+ break;
+ case "HKEY_CURRENT_CONFIG":
+ basekey = Registry.CurrentConfig;
+ break;
+#if !FEATURE_CORECLR
+ case "HKEY_DYN_DATA":
+ basekey = RegistryKey.GetBaseKey(RegistryKey.HKEY_DYN_DATA);
+ break;
+#endif
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegInvalidKeyName", "keyName"));
+ }
+ if( i == -1 || i == keyName.Length) {
+ subKeyName = string.Empty;
+ }
+ else {
+ subKeyName = keyName.Substring(i + 1, keyName.Length - i - 1);
+ }
+ return basekey;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static object GetValue(string keyName, string valueName, object defaultValue ) {
+ string subKeyName;
+ RegistryKey basekey = GetBaseKeyFromKeyName(keyName, out subKeyName);
+ BCLDebug.Assert(basekey != null, "basekey can't be null.");
+ RegistryKey key = basekey.OpenSubKey(subKeyName);
+ if(key == null) { // if the key doesn't exist, do nothing
+ return null;
+ }
+ try {
+ return key.GetValue(valueName, defaultValue);
+ }
+ finally {
+ key.Close();
+ }
+ }
+
+ public static void SetValue(string keyName, string valueName, object value ) {
+ SetValue(keyName, valueName, value, RegistryValueKind.Unknown);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void SetValue(string keyName, string valueName, object value, RegistryValueKind valueKind ) {
+ string subKeyName;
+ RegistryKey basekey = GetBaseKeyFromKeyName(keyName, out subKeyName);
+ BCLDebug.Assert(basekey != null, "basekey can't be null!");
+ RegistryKey key = basekey.CreateSubKey(subKeyName);
+ BCLDebug.Assert(key != null, "An exception should be thrown if failed!");
+ try {
+ key.SetValue(valueName, value, valueKind);
+ }
+ finally {
+ key.Close();
+ }
+ }
+ }
+}
+
+
diff --git a/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs b/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs
new file mode 100644
index 0000000000..dcf31dc60c
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs
@@ -0,0 +1,2166 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+/*
+ Note on transaction support:
+ Eventually we will want to add support for NT's transactions to our
+ RegistryKey API's (possibly Whidbey M3?). When we do this, here's
+ the list of API's we need to make transaction-aware:
+
+ RegCreateKeyEx
+ RegDeleteKey
+ RegDeleteValue
+ RegEnumKeyEx
+ RegEnumValue
+ RegOpenKeyEx
+ RegQueryInfoKey
+ RegQueryValueEx
+ RegSetValueEx
+
+ We can ignore RegConnectRegistry (remote registry access doesn't yet have
+ transaction support) and RegFlushKey. RegCloseKey doesn't require any
+ additional work. .
+ */
+
+/*
+ Note on ACL support:
+ The key thing to note about ACL's is you set them on a kernel object like a
+ registry key, then the ACL only gets checked when you construct handles to
+ them. So if you set an ACL to deny read access to yourself, you'll still be
+ able to read with that handle, but not with new handles.
+
+ Another peculiarity is a Terminal Server app compatibility workaround. The OS
+ will second guess your attempt to open a handle sometimes. If a certain
+ combination of Terminal Server app compat registry keys are set, then the
+ OS will try to reopen your handle with lesser permissions if you couldn't
+ open it in the specified mode. So on some machines, we will see handles that
+ may not be able to read or write to a registry key. It's very strange. But
+ the real test of these handles is attempting to read or set a value in an
+ affected registry key.
+
+ For reference, at least two registry keys must be set to particular values
+ for this behavior:
+ HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\RegistryExtensionFlags, the least significant bit must be 1.
+ HKLM\SYSTEM\CurrentControlSet\Control\TerminalServer\TSAppCompat must be 1
+ There might possibly be an interaction with yet a third registry key as well.
+
+*/
+
+
+namespace Microsoft.Win32 {
+
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Security;
+#if FEATURE_MACL
+ using System.Security.AccessControl;
+#endif
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Threading;
+ using System.IO;
+ using System.Runtime.Remoting;
+ using System.Runtime.InteropServices;
+ using Microsoft.Win32.SafeHandles;
+ using System.Runtime.Versioning;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.CodeAnalysis;
+
+ /**
+ * Registry hive values. Useful only for GetRemoteBaseKey
+ */
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum RegistryHive
+ {
+ ClassesRoot = unchecked((int)0x80000000),
+ CurrentUser = unchecked((int)0x80000001),
+ LocalMachine = unchecked((int)0x80000002),
+ Users = unchecked((int)0x80000003),
+ PerformanceData = unchecked((int)0x80000004),
+ CurrentConfig = unchecked((int)0x80000005),
+#if !FEATURE_CORECLR
+ DynData = unchecked((int)0x80000006),
+#endif
+ }
+
+ /**
+ * Registry encapsulation. To get an instance of a RegistryKey use the
+ * Registry class's static members then call OpenSubKey.
+ *
+ * @see Registry
+ * @security(checkDllCalls=off)
+ * @security(checkClassLinking=on)
+ */
+#if FEATURE_REMOTING
+ [ComVisible(true)]
+ public sealed class RegistryKey : MarshalByRefObject, IDisposable
+#else
+ [ComVisible(true)]
+ public sealed class RegistryKey : IDisposable
+#endif
+ {
+
+ // We could use const here, if C# supported ELEMENT_TYPE_I fully.
+ internal static readonly IntPtr HKEY_CLASSES_ROOT = new IntPtr(unchecked((int)0x80000000));
+ internal static readonly IntPtr HKEY_CURRENT_USER = new IntPtr(unchecked((int)0x80000001));
+ internal static readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(unchecked((int)0x80000002));
+ internal static readonly IntPtr HKEY_USERS = new IntPtr(unchecked((int)0x80000003));
+ internal static readonly IntPtr HKEY_PERFORMANCE_DATA = new IntPtr(unchecked((int)0x80000004));
+ internal static readonly IntPtr HKEY_CURRENT_CONFIG = new IntPtr(unchecked((int)0x80000005));
+#if !FEATURE_CORECLR
+ internal static readonly IntPtr HKEY_DYN_DATA = new IntPtr(unchecked((int)0x80000006));
+#endif
+
+ // Dirty indicates that we have munged data that should be potentially
+ // written to disk.
+ //
+ private const int STATE_DIRTY = 0x0001;
+
+ // SystemKey indicates that this is a "SYSTEMKEY" and shouldn't be "opened"
+ // or "closed".
+ //
+ private const int STATE_SYSTEMKEY = 0x0002;
+
+ // Access
+ //
+ private const int STATE_WRITEACCESS = 0x0004;
+
+ // Indicates if this key is for HKEY_PERFORMANCE_DATA
+ private const int STATE_PERF_DATA = 0x0008;
+
+ // Names of keys. This array must be in the same order as the HKEY values listed above.
+ //
+ private static readonly String[] hkeyNames = new String[] {
+ "HKEY_CLASSES_ROOT",
+ "HKEY_CURRENT_USER",
+ "HKEY_LOCAL_MACHINE",
+ "HKEY_USERS",
+ "HKEY_PERFORMANCE_DATA",
+ "HKEY_CURRENT_CONFIG",
+#if !FEATURE_CORECLR
+ "HKEY_DYN_DATA"
+#endif
+ };
+
+ // MSDN defines the following limits for registry key names & values:
+ // Key Name: 255 characters
+ // Value name: 16,383 Unicode characters
+ // Value: either 1 MB or current available memory, depending on registry format.
+ private const int MaxKeyLength = 255;
+ private const int MaxValueLength = 16383;
+
+ [System.Security.SecurityCritical] // auto-generated
+ private volatile SafeRegistryHandle hkey = null;
+ private volatile int state = 0;
+ private volatile String keyName;
+ private volatile bool remoteKey = false;
+ private volatile RegistryKeyPermissionCheck checkMode;
+ private volatile RegistryView regView = RegistryView.Default;
+
+ /**
+ * RegistryInternalCheck values. Useful only for CheckPermission
+ */
+ private enum RegistryInternalCheck {
+ CheckSubKeyWritePermission = 0,
+ CheckSubKeyReadPermission = 1,
+ CheckSubKeyCreatePermission = 2,
+ CheckSubTreeReadPermission = 3,
+ CheckSubTreeWritePermission = 4,
+ CheckSubTreeReadWritePermission = 5,
+ CheckValueWritePermission = 6,
+ CheckValueCreatePermission = 7,
+ CheckValueReadPermission = 8,
+ CheckKeyReadPermission = 9,
+ CheckSubTreePermission = 10,
+ CheckOpenSubKeyWithWritablePermission = 11,
+ CheckOpenSubKeyPermission = 12
+ };
+
+
+ /**
+ * Creates a RegistryKey.
+ *
+ * This key is bound to hkey, if writable is <b>false</b> then no write operations
+ * will be allowed.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ private RegistryKey(SafeRegistryHandle hkey, bool writable, RegistryView view)
+ : this(hkey, writable, false, false, false, view) {
+ }
+
+
+ /**
+ * Creates a RegistryKey.
+ *
+ * This key is bound to hkey, if writable is <b>false</b> then no write operations
+ * will be allowed. If systemkey is set then the hkey won't be released
+ * when the object is GC'ed.
+ * The remoteKey flag when set to true indicates that we are dealing with registry entries
+ * on a remote machine and requires the program making these calls to have full trust.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ private RegistryKey(SafeRegistryHandle hkey, bool writable, bool systemkey, bool remoteKey, bool isPerfData, RegistryView view) {
+ this.hkey = hkey;
+ this.keyName = "";
+ this.remoteKey = remoteKey;
+ this.regView = view;
+ if (systemkey) {
+ this.state |= STATE_SYSTEMKEY;
+ }
+ if (writable) {
+ this.state |= STATE_WRITEACCESS;
+ }
+ if (isPerfData)
+ this.state |= STATE_PERF_DATA;
+ ValidateKeyView(view);
+ }
+
+ /**
+ * Closes this key, flushes it to disk if the contents have been modified.
+ */
+ public void Close() {
+ Dispose(true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private void Dispose(bool disposing) {
+ if (hkey != null) {
+
+ if (!IsSystemKey()) {
+ try {
+ hkey.Dispose();
+ }
+ catch (IOException){
+ // we don't really care if the handle is invalid at this point
+ }
+ finally
+ {
+ hkey = null;
+ }
+ }
+ else if (disposing && IsPerfDataKey()) {
+ // System keys should never be closed. However, we want to call RegCloseKey
+ // on HKEY_PERFORMANCE_DATA when called from PerformanceCounter.CloseSharedResources
+ // (i.e. when disposing is true) so that we release the PERFLIB cache and cause it
+ // to be refreshed (by re-reading the registry) when accessed subsequently.
+ // This is the only way we can see the just installed perf counter.
+ // NOTE: since HKEY_PERFORMANCE_DATA is process wide, there is inherent race condition in closing
+ // the key asynchronously. While Vista is smart enough to rebuild the PERFLIB resources
+ // in this situation the down level OSes are not. We have a small window between
+ // the dispose below and usage elsewhere (other threads). This is By Design.
+ // This is less of an issue when OS > NT5 (i.e Vista & higher), we can close the perfkey
+ // (to release & refresh PERFLIB resources) and the OS will rebuild PERFLIB as necessary.
+ SafeRegistryHandle.RegCloseKey(RegistryKey.HKEY_PERFORMANCE_DATA);
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Flush() {
+ if (hkey != null) {
+ if (IsDirty()) {
+ Win32Native.RegFlushKey(hkey);
+ }
+ }
+ }
+
+#if FEATURE_CORECLR
+ void IDisposable.Dispose()
+#else
+ public void Dispose()
+#endif
+ {
+ Dispose(true);
+ }
+
+ /**
+ * Creates a new subkey, or opens an existing one.
+ *
+ * @param subkey Name or path to subkey to create or open.
+ *
+ * @return the subkey, or <b>null</b> if the operation failed.
+ */
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ public RegistryKey CreateSubKey(String subkey) {
+ return CreateSubKey(subkey, checkMode);
+ }
+
+ [ComVisible(false)]
+ public RegistryKey CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck)
+ {
+ return CreateSubKeyInternal(subkey, permissionCheck, null, RegistryOptions.None);
+ }
+
+ [ComVisible(false)]
+ public RegistryKey CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistryOptions options)
+ {
+ return CreateSubKeyInternal(subkey, permissionCheck, null, options);
+ }
+
+ [ComVisible(false)]
+ public RegistryKey CreateSubKey(String subkey, bool writable)
+ {
+ return CreateSubKeyInternal(subkey, writable ? RegistryKeyPermissionCheck.ReadWriteSubTree : RegistryKeyPermissionCheck.ReadSubTree, null, RegistryOptions.None);
+ }
+
+ [ComVisible(false)]
+ public RegistryKey CreateSubKey(String subkey, bool writable, RegistryOptions options)
+ {
+ return CreateSubKeyInternal(subkey, writable ? RegistryKeyPermissionCheck.ReadWriteSubTree : RegistryKeyPermissionCheck.ReadSubTree, null, options);
+ }
+
+
+#if FEATURE_MACL
+ [ComVisible(false)]
+ public unsafe RegistryKey CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistrySecurity registrySecurity)
+ {
+ return CreateSubKeyInternal(subkey, permissionCheck, registrySecurity, RegistryOptions.None);
+ }
+
+ [ComVisible(false)]
+ public unsafe RegistryKey CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistryOptions registryOptions, RegistrySecurity registrySecurity)
+ {
+ return CreateSubKeyInternal(subkey, permissionCheck, registrySecurity, registryOptions);
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ private unsafe RegistryKey CreateSubKeyInternal(String subkey, RegistryKeyPermissionCheck permissionCheck, object registrySecurityObj, RegistryOptions registryOptions)
+ {
+ ValidateKeyOptions(registryOptions);
+ ValidateKeyName(subkey);
+ ValidateKeyMode(permissionCheck);
+ EnsureWriteable();
+ subkey = FixupName(subkey); // Fixup multiple slashes to a single slash
+
+ // only keys opened under read mode is not writable
+ if (!remoteKey) {
+ RegistryKey key = InternalOpenSubKey(subkey, (permissionCheck != RegistryKeyPermissionCheck.ReadSubTree));
+ if (key != null) { // Key already exits
+ CheckPermission(RegistryInternalCheck.CheckSubKeyWritePermission, subkey, false, RegistryKeyPermissionCheck.Default);
+ CheckPermission(RegistryInternalCheck.CheckSubTreePermission, subkey, false, permissionCheck);
+ key.checkMode = permissionCheck;
+ return key;
+ }
+ }
+
+ CheckPermission(RegistryInternalCheck.CheckSubKeyCreatePermission, subkey, false, RegistryKeyPermissionCheck.Default);
+
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
+#if FEATURE_MACL
+ RegistrySecurity registrySecurity = (RegistrySecurity)registrySecurityObj;
+ // For ACL's, get the security descriptor from the RegistrySecurity.
+ if (registrySecurity != null) {
+ secAttrs = new Win32Native.SECURITY_ATTRIBUTES();
+ secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
+
+ byte[] sd = registrySecurity.GetSecurityDescriptorBinaryForm();
+ // We allocate memory on the stack to improve the speed.
+ // So this part of code can't be refactored into a method.
+ byte* pSecDescriptor = stackalloc byte[sd.Length];
+ Buffer.Memcpy(pSecDescriptor, 0, sd, 0, sd.Length);
+ secAttrs.pSecurityDescriptor = pSecDescriptor;
+ }
+#endif
+ int disposition = 0;
+
+ // By default, the new key will be writable.
+ SafeRegistryHandle result = null;
+ int ret = Win32Native.RegCreateKeyEx(hkey,
+ subkey,
+ 0,
+ null,
+ (int)registryOptions /* specifies if the key is volatile */,
+ GetRegistryKeyAccess(permissionCheck != RegistryKeyPermissionCheck.ReadSubTree) | (int)regView,
+ secAttrs,
+ out result,
+ out disposition);
+
+ if (ret == 0 && !result.IsInvalid) {
+ RegistryKey key = new RegistryKey(result, (permissionCheck != RegistryKeyPermissionCheck.ReadSubTree), false, remoteKey, false, regView);
+ CheckPermission(RegistryInternalCheck.CheckSubTreePermission, subkey, false, permissionCheck);
+ key.checkMode = permissionCheck;
+
+ if (subkey.Length == 0)
+ key.keyName = keyName;
+ else
+ key.keyName = keyName + "\\" + subkey;
+ return key;
+ }
+ else if (ret != 0) // syscall failed, ret is an error code.
+ Win32Error(ret, keyName + "\\" + subkey); // Access denied?
+
+ BCLDebug.Assert(false, "Unexpected code path in RegistryKey::CreateSubKey");
+ return null;
+ }
+
+ /**
+ * Deletes the specified subkey. Will throw an exception if the subkey has
+ * subkeys. To delete a tree of subkeys use, DeleteSubKeyTree.
+ *
+ * @param subkey SubKey to delete.
+ *
+ * @exception InvalidOperationException thrown if the subkey has child subkeys.
+ */
+ public void DeleteSubKey(String subkey) {
+ DeleteSubKey(subkey, true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void DeleteSubKey(String subkey, bool throwOnMissingSubKey) {
+ ValidateKeyName(subkey);
+ EnsureWriteable();
+ subkey = FixupName(subkey); // Fixup multiple slashes to a single slash
+ CheckPermission(RegistryInternalCheck.CheckSubKeyWritePermission, subkey, false, RegistryKeyPermissionCheck.Default);
+
+ // Open the key we are deleting and check for children. Be sure to
+ // explicitly call close to avoid keeping an extra HKEY open.
+ //
+ RegistryKey key = InternalOpenSubKey(subkey,false);
+ if (key != null) {
+ try {
+ if (key.InternalSubKeyCount() > 0) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_RegRemoveSubKey);
+ }
+ }
+ finally {
+ key.Close();
+ }
+
+ int ret;
+
+ try {
+ ret = Win32Native.RegDeleteKeyEx(hkey, subkey, (int)regView, 0);
+ }
+ catch (EntryPointNotFoundException) {
+ ret = Win32Native.RegDeleteKey(hkey, subkey);
+ }
+
+ if (ret!=0) {
+ if (ret == Win32Native.ERROR_FILE_NOT_FOUND) {
+ if (throwOnMissingSubKey)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyAbsent);
+ }
+ else
+ Win32Error(ret, null);
+ }
+ }
+ else { // there is no key which also means there is no subkey
+ if (throwOnMissingSubKey)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyAbsent);
+ }
+ }
+
+ /**
+ * Recursively deletes a subkey and any child subkeys.
+ *
+ * @param subkey SubKey to delete.
+ */
+ public void DeleteSubKeyTree(String subkey) {
+ DeleteSubKeyTree(subkey, true /*throwOnMissingSubKey*/);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public void DeleteSubKeyTree(String subkey, Boolean throwOnMissingSubKey) {
+ ValidateKeyName(subkey);
+
+ // Security concern: Deleting a hive's "" subkey would delete all
+ // of that hive's contents. Don't allow "".
+ if (subkey.Length==0 && IsSystemKey()) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegKeyDelHive);
+ }
+
+ EnsureWriteable();
+
+ subkey = FixupName(subkey); // Fixup multiple slashes to a single slash
+ CheckPermission(RegistryInternalCheck.CheckSubTreeWritePermission, subkey, false, RegistryKeyPermissionCheck.Default);
+
+ RegistryKey key = InternalOpenSubKey(subkey, true);
+ if (key != null) {
+ try {
+ if (key.InternalSubKeyCount() > 0) {
+ String[] keys = key.InternalGetSubKeyNames();
+
+ for (int i=0; i<keys.Length; i++) {
+ key.DeleteSubKeyTreeInternal(keys[i]);
+ }
+ }
+ }
+ finally {
+ key.Close();
+ }
+
+ int ret;
+ try {
+ ret = Win32Native.RegDeleteKeyEx(hkey, subkey, (int)regView, 0);
+ }
+ catch (EntryPointNotFoundException) {
+ ret = Win32Native.RegDeleteKey(hkey, subkey);
+ }
+
+ if (ret!=0) Win32Error(ret, null);
+ }
+ else if(throwOnMissingSubKey) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyAbsent);
+ }
+ }
+
+ // An internal version which does no security checks or argument checking. Skipping the
+ // security checks should give us a slight perf gain on large trees.
+ [System.Security.SecurityCritical] // auto-generated
+ private void DeleteSubKeyTreeInternal(string subkey) {
+ RegistryKey key = InternalOpenSubKey(subkey, true);
+ if (key != null) {
+ try {
+ if (key.InternalSubKeyCount() > 0) {
+ String[] keys = key.InternalGetSubKeyNames();
+
+ for (int i=0; i<keys.Length; i++) {
+ key.DeleteSubKeyTreeInternal(keys[i]);
+ }
+ }
+ }
+ finally {
+ key.Close();
+ }
+
+ int ret;
+ try {
+ ret = Win32Native.RegDeleteKeyEx(hkey, subkey, (int)regView, 0);
+ }
+ catch (EntryPointNotFoundException) {
+ ret = Win32Native.RegDeleteKey(hkey, subkey);
+ }
+ if (ret!=0) Win32Error(ret, null);
+ }
+ else {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyAbsent);
+ }
+ }
+
+ /**
+ * Deletes the specified value from this key.
+ *
+ * @param name Name of value to delete.
+ */
+ public void DeleteValue(String name) {
+ DeleteValue(name, true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void DeleteValue(String name, bool throwOnMissingValue) {
+ EnsureWriteable();
+ CheckPermission(RegistryInternalCheck.CheckValueWritePermission, name, false, RegistryKeyPermissionCheck.Default);
+ int errorCode = Win32Native.RegDeleteValue(hkey, name);
+
+ //
+ // From windows 2003 server, if the name is too long we will get error code ERROR_FILENAME_EXCED_RANGE
+ // This still means the name doesn't exist. We need to be consistent with previous OS.
+ //
+ if (errorCode == Win32Native.ERROR_FILE_NOT_FOUND || errorCode == Win32Native.ERROR_FILENAME_EXCED_RANGE) {
+ if (throwOnMissingValue) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyValueAbsent);
+ }
+ // Otherwise, just return giving no indication to the user.
+ // (For compatibility)
+ }
+ // We really should throw an exception here if errorCode was bad,
+ // but we can't for compatibility reasons.
+ BCLDebug.Correctness(errorCode == 0, "RegDeleteValue failed. Here's your error code: "+errorCode);
+ }
+
+ /**
+ * Retrieves a new RegistryKey that represents the requested key. Valid
+ * values are:
+ *
+ * HKEY_CLASSES_ROOT,
+ * HKEY_CURRENT_USER,
+ * HKEY_LOCAL_MACHINE,
+ * HKEY_USERS,
+ * HKEY_PERFORMANCE_DATA,
+ * HKEY_CURRENT_CONFIG,
+ * HKEY_DYN_DATA.
+ *
+ * @param hKey HKEY_* to open.
+ *
+ * @return the RegistryKey requested.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RegistryKey GetBaseKey(IntPtr hKey) {
+ return GetBaseKey(hKey, RegistryView.Default);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RegistryKey GetBaseKey(IntPtr hKey, RegistryView view) {
+
+ int index = ((int)hKey) & 0x0FFFFFFF;
+ BCLDebug.Assert(index >= 0 && index < hkeyNames.Length, "index is out of range!");
+ BCLDebug.Assert((((int)hKey) & 0xFFFFFFF0) == 0x80000000, "Invalid hkey value!");
+
+ bool isPerf = hKey == HKEY_PERFORMANCE_DATA;
+ // only mark the SafeHandle as ownsHandle if the key is HKEY_PERFORMANCE_DATA.
+ SafeRegistryHandle srh = new SafeRegistryHandle(hKey, isPerf);
+
+ RegistryKey key = new RegistryKey(srh, true, true,false, isPerf, view);
+ key.checkMode = RegistryKeyPermissionCheck.Default;
+ key.keyName = hkeyNames[index];
+ return key;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public static RegistryKey OpenBaseKey(RegistryHive hKey, RegistryView view) {
+ ValidateKeyView(view);
+ CheckUnmanagedCodePermission();
+ return GetBaseKey((IntPtr)((int)hKey), view);
+ }
+
+ /**
+ * Retrieves a new RegistryKey that represents the requested key on a foreign
+ * machine. Valid values for hKey are members of the RegistryHive enum, or
+ * Win32 integers such as:
+ *
+ * HKEY_CLASSES_ROOT,
+ * HKEY_CURRENT_USER,
+ * HKEY_LOCAL_MACHINE,
+ * HKEY_USERS,
+ * HKEY_PERFORMANCE_DATA,
+ * HKEY_CURRENT_CONFIG,
+ * HKEY_DYN_DATA.
+ *
+ * @param hKey HKEY_* to open.
+ * @param machineName the machine to connect to
+ *
+ * @return the RegistryKey requested.
+ */
+ public static RegistryKey OpenRemoteBaseKey(RegistryHive hKey, String machineName) {
+ return OpenRemoteBaseKey(hKey, machineName, RegistryView.Default);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public static RegistryKey OpenRemoteBaseKey(RegistryHive hKey, String machineName, RegistryView view) {
+ if (machineName==null)
+ throw new ArgumentNullException("machineName");
+ int index = (int)hKey & 0x0FFFFFFF;
+ if (index < 0 || index >= hkeyNames.Length || ((int)hKey & 0xFFFFFFF0) != 0x80000000) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegKeyOutOfRange"));
+ }
+ ValidateKeyView(view);
+
+ CheckUnmanagedCodePermission();
+ // connect to the specified remote registry
+ SafeRegistryHandle foreignHKey = null;
+ int ret = Win32Native.RegConnectRegistry(machineName, new SafeRegistryHandle(new IntPtr((int)hKey), false), out foreignHKey);
+
+ if (ret == Win32Native.ERROR_DLL_INIT_FAILED)
+ // return value indicates an error occurred
+ throw new ArgumentException(Environment.GetResourceString("Arg_DllInitFailure"));
+
+ if (ret != 0)
+ Win32ErrorStatic(ret, null);
+
+ if (foreignHKey.IsInvalid)
+ // return value indicates an error occurred
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegKeyNoRemoteConnect", machineName));
+
+ RegistryKey key = new RegistryKey(foreignHKey, true, false, true, ((IntPtr) hKey) == HKEY_PERFORMANCE_DATA, view);
+ key.checkMode = RegistryKeyPermissionCheck.Default;
+ key.keyName = hkeyNames[index];
+ return key;
+ }
+
+ /**
+ * Retrieves a subkey. If readonly is <b>true</b>, then the subkey is opened with
+ * read-only access.
+ *
+ * @param name Name or path of subkey to open.
+ * @param readonly Set to <b>true</b> if you only need readonly access.
+ *
+ * @return the Subkey requested, or <b>null</b> if the operation failed.
+ */
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public RegistryKey OpenSubKey(string name, bool writable ) {
+ ValidateKeyName(name);
+ EnsureNotDisposed();
+ name = FixupName(name); // Fixup multiple slashes to a single slash
+
+ CheckPermission(RegistryInternalCheck.CheckOpenSubKeyWithWritablePermission, name, writable, RegistryKeyPermissionCheck.Default);
+ SafeRegistryHandle result = null;
+ int ret = Win32Native.RegOpenKeyEx(hkey,
+ name,
+ 0,
+ GetRegistryKeyAccess(writable) | (int)regView,
+ out result);
+
+ if (ret == 0 && !result.IsInvalid) {
+ RegistryKey key = new RegistryKey(result, writable, false, remoteKey, false, regView);
+ key.checkMode = GetSubKeyPermissonCheck(writable);
+ key.keyName = keyName + "\\" + name;
+ return key;
+ }
+
+ // Return null if we didn't find the key.
+ if (ret == Win32Native.ERROR_ACCESS_DENIED || ret == Win32Native.ERROR_BAD_IMPERSONATION_LEVEL) {
+ // We need to throw SecurityException here for compatibility reasons,
+ // although UnauthorizedAccessException will make more sense.
+ ThrowHelper.ThrowSecurityException(ExceptionResource.Security_RegistryPermission);
+ }
+
+ return null;
+ }
+
+#if FEATURE_MACL
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public RegistryKey OpenSubKey(String name, RegistryKeyPermissionCheck permissionCheck) {
+ ValidateKeyMode(permissionCheck);
+ return InternalOpenSubKey(name, permissionCheck, GetRegistryKeyAccess(permissionCheck));
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [ComVisible(false)]
+ public RegistryKey OpenSubKey(String name, RegistryRights rights)
+ {
+ return InternalOpenSubKey(name, this.checkMode, (int)rights);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public RegistryKey OpenSubKey(String name, RegistryKeyPermissionCheck permissionCheck, RegistryRights rights) {
+ return InternalOpenSubKey(name, permissionCheck, (int)rights);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private RegistryKey InternalOpenSubKey(String name, RegistryKeyPermissionCheck permissionCheck, int rights) {
+ ValidateKeyName(name);
+ ValidateKeyMode(permissionCheck);
+
+ ValidateKeyRights(rights);
+
+ EnsureNotDisposed();
+ name = FixupName(name); // Fixup multiple slashes to a single slash
+
+ CheckPermission(RegistryInternalCheck.CheckOpenSubKeyPermission, name, false, permissionCheck);
+ CheckPermission(RegistryInternalCheck.CheckSubTreePermission, name, false, permissionCheck);
+ SafeRegistryHandle result = null;
+ int ret = Win32Native.RegOpenKeyEx(hkey, name, 0, (rights | (int)regView), out result);
+ if (ret == 0 && !result.IsInvalid) {
+ RegistryKey key = new RegistryKey(result, (permissionCheck == RegistryKeyPermissionCheck.ReadWriteSubTree), false, remoteKey, false, regView);
+ key.keyName = keyName + "\\" + name;
+ key.checkMode = permissionCheck;
+ return key;
+ }
+
+ // Return null if we didn't find the key.
+ if (ret == Win32Native.ERROR_ACCESS_DENIED || ret == Win32Native.ERROR_BAD_IMPERSONATION_LEVEL) {
+ // We need to throw SecurityException here for compatiblity reason,
+ // although UnauthorizedAccessException will make more sense.
+ ThrowHelper.ThrowSecurityException(ExceptionResource.Security_RegistryPermission);
+ }
+
+ return null;
+ }
+#endif
+
+ // This required no security checks. This is to get around the Deleting SubKeys which only require
+ // write permission. They call OpenSubKey which required read. Now instead call this function w/o security checks
+ [System.Security.SecurityCritical] // auto-generated
+ internal RegistryKey InternalOpenSubKey(String name, bool writable) {
+ ValidateKeyName(name);
+ EnsureNotDisposed();
+
+ SafeRegistryHandle result = null;
+ int ret = Win32Native.RegOpenKeyEx(hkey,
+ name,
+ 0,
+ GetRegistryKeyAccess(writable) | (int)regView,
+ out result);
+
+ if (ret == 0 && !result.IsInvalid) {
+ RegistryKey key = new RegistryKey(result, writable, false, remoteKey, false, regView);
+ key.keyName = keyName + "\\" + name;
+ return key;
+ }
+ return null;
+ }
+
+ /**
+ * Returns a subkey with read only permissions.
+ *
+ * @param name Name or path of subkey to open.
+ *
+ * @return the Subkey requested, or <b>null</b> if the operation failed.
+ */
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical]
+#endif
+ public RegistryKey OpenSubKey(String name) {
+ return OpenSubKey(name, false);
+ }
+
+ /**
+ * Retrieves the count of subkeys.
+ *
+ * @return a count of subkeys.
+ */
+ public int SubKeyCount {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default);
+ return InternalSubKeyCount();
+ }
+ }
+
+ [ComVisible(false)]
+ public RegistryView View {
+ [System.Security.SecuritySafeCritical]
+ get {
+ EnsureNotDisposed();
+ return regView;
+ }
+ }
+
+#if !FEATURE_CORECLR
+ [ComVisible(false)]
+ public SafeRegistryHandle Handle {
+ [System.Security.SecurityCritical]
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ get {
+ EnsureNotDisposed();
+ int ret = Win32Native.ERROR_INVALID_HANDLE;
+ if (IsSystemKey()) {
+ IntPtr baseKey = (IntPtr)0;
+ switch (keyName) {
+ case "HKEY_CLASSES_ROOT":
+ baseKey = HKEY_CLASSES_ROOT;
+ break;
+ case "HKEY_CURRENT_USER":
+ baseKey = HKEY_CURRENT_USER;
+ break;
+ case "HKEY_LOCAL_MACHINE":
+ baseKey = HKEY_LOCAL_MACHINE;
+ break;
+ case "HKEY_USERS":
+ baseKey = HKEY_USERS;
+ break;
+ case "HKEY_PERFORMANCE_DATA":
+ baseKey = HKEY_PERFORMANCE_DATA;
+ break;
+ case "HKEY_CURRENT_CONFIG":
+ baseKey = HKEY_CURRENT_CONFIG;
+ break;
+ case "HKEY_DYN_DATA":
+ baseKey = HKEY_DYN_DATA;
+ break;
+ default:
+ Win32Error(ret, null);
+ break;
+ }
+ // open the base key so that RegistryKey.Handle will return a valid handle
+ SafeRegistryHandle result;
+ ret = Win32Native.RegOpenKeyEx(baseKey,
+ null,
+ 0,
+ GetRegistryKeyAccess(IsWritable()) | (int)regView,
+ out result);
+
+ if (ret == 0 && !result.IsInvalid) {
+ return result;
+ }
+ else {
+ Win32Error(ret, null);
+ }
+ }
+ else {
+ return hkey;
+ }
+ throw new IOException(Win32Native.GetMessage(ret), ret);
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ [ComVisible(false)]
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ public static RegistryKey FromHandle(SafeRegistryHandle handle) {
+ return FromHandle(handle, RegistryView.Default);
+ }
+
+ [System.Security.SecurityCritical]
+ [ComVisible(false)]
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ public static RegistryKey FromHandle(SafeRegistryHandle handle, RegistryView view) {
+ if (handle == null) throw new ArgumentNullException("handle");
+ ValidateKeyView(view);
+
+ return new RegistryKey(handle, true /* isWritable */, view);
+ }
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal int InternalSubKeyCount() {
+ EnsureNotDisposed();
+
+ int subkeys = 0;
+ int junk = 0;
+ int ret = Win32Native.RegQueryInfoKey(hkey,
+ null,
+ null,
+ IntPtr.Zero,
+ ref subkeys, // subkeys
+ null,
+ null,
+ ref junk, // values
+ null,
+ null,
+ null,
+ null);
+
+ if (ret != 0)
+ Win32Error(ret, null);
+ return subkeys;
+ }
+
+ /**
+ * Retrieves an array of strings containing all the subkey names.
+ *
+ * @return all subkey names.
+ */
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public String[] GetSubKeyNames() {
+ CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default);
+ return InternalGetSubKeyNames();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe String[] InternalGetSubKeyNames() {
+ EnsureNotDisposed();
+ int subkeys = InternalSubKeyCount();
+ String[] names = new String[subkeys]; // Returns 0-length array if empty.
+
+ if (subkeys > 0) {
+ char[] name = new char[MaxKeyLength + 1];
+
+ int namelen;
+
+ fixed (char *namePtr = &name[0])
+ {
+ for (int i=0; i<subkeys; i++) {
+ namelen = name.Length; // Don't remove this. The API's doesn't work if this is not properly initialised.
+ int ret = Win32Native.RegEnumKeyEx(hkey,
+ i,
+ namePtr,
+ ref namelen,
+ null,
+ null,
+ null,
+ null);
+ if (ret != 0)
+ Win32Error(ret, null);
+ names[i] = new String(namePtr);
+ }
+ }
+ }
+
+ return names;
+ }
+
+ /**
+ * Retrieves the count of values.
+ *
+ * @return a count of values.
+ */
+ public int ValueCount {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default);
+ return InternalValueCount();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal int InternalValueCount() {
+ EnsureNotDisposed();
+ int values = 0;
+ int junk = 0;
+ int ret = Win32Native.RegQueryInfoKey(hkey,
+ null,
+ null,
+ IntPtr.Zero,
+ ref junk, // subkeys
+ null,
+ null,
+ ref values, // values
+ null,
+ null,
+ null,
+ null);
+ if (ret != 0)
+ Win32Error(ret, null);
+ return values;
+ }
+
+ /**
+ * Retrieves an array of strings containing all the value names.
+ *
+ * @return all value names.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe String[] GetValueNames() {
+ CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default);
+ EnsureNotDisposed();
+
+ int values = InternalValueCount();
+ String[] names = new String[values];
+
+ if (values > 0) {
+ char[] name = new char[MaxValueLength + 1];
+ int namelen;
+
+ fixed (char *namePtr = &name[0])
+ {
+ for (int i=0; i<values; i++) {
+ namelen = name.Length;
+
+ int ret = Win32Native.RegEnumValue(hkey,
+ i,
+ namePtr,
+ ref namelen,
+ IntPtr.Zero,
+ null,
+ null,
+ null);
+
+ if (ret != 0) {
+ // ignore ERROR_MORE_DATA if we're querying HKEY_PERFORMANCE_DATA
+ if (!(IsPerfDataKey() && ret == Win32Native.ERROR_MORE_DATA))
+ Win32Error(ret, null);
+ }
+
+ names[i] = new String(namePtr);
+ }
+ }
+ }
+
+ return names;
+ }
+
+ /**
+ * Retrieves the specified value. <b>null</b> is returned if the value
+ * doesn't exist.
+ *
+ * Note that <var>name</var> can be null or "", at which point the
+ * unnamed or default value of this Registry key is returned, if any.
+ *
+ * @param name Name of value to retrieve.
+ *
+ * @return the data associated with the value.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Object GetValue(String name) {
+ CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default);
+ return InternalGetValue(name, null, false, true);
+ }
+
+ /**
+ * Retrieves the specified value. <i>defaultValue</i> is returned if the value doesn't exist.
+ *
+ * Note that <var>name</var> can be null or "", at which point the
+ * unnamed or default value of this Registry key is returned, if any.
+ * The default values for RegistryKeys are OS-dependent. NT doesn't
+ * have them by default, but they can exist and be of any type. On
+ * Win95, the default value is always an empty key of type REG_SZ.
+ * Win98 supports default values of any type, but defaults to REG_SZ.
+ *
+ * @param name Name of value to retrieve.
+ * @param defaultValue Value to return if <i>name</i> doesn't exist.
+ *
+ * @return the data associated with the value.
+ */
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public Object GetValue(String name, Object defaultValue) {
+ CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default);
+ return InternalGetValue(name, defaultValue, false, true);
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ [ComVisible(false)]
+ public Object GetValue(String name, Object defaultValue, RegistryValueOptions options) {
+ if( options < RegistryValueOptions.None || options > RegistryValueOptions.DoNotExpandEnvironmentNames) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)options), "options");
+ }
+ bool doNotExpand = (options == RegistryValueOptions.DoNotExpandEnvironmentNames);
+ CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default);
+ return InternalGetValue(name, defaultValue, doNotExpand, true);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Object InternalGetValue(String name, Object defaultValue, bool doNotExpand, bool checkSecurity) {
+ if (checkSecurity) {
+ // Name can be null! It's the most common use of RegQueryValueEx
+ EnsureNotDisposed();
+ }
+
+ Object data = defaultValue;
+ int type = 0;
+ int datasize = 0;
+
+ int ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, (byte[])null, ref datasize);
+
+ if (ret != 0) {
+ if (IsPerfDataKey()) {
+ int size = 65000;
+ int sizeInput = size;
+
+ int r;
+ byte[] blob = new byte[size];
+ while (Win32Native.ERROR_MORE_DATA == (r = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref sizeInput))) {
+ if (size == Int32.MaxValue) {
+ // ERROR_MORE_DATA was returned however we cannot increase the buffer size beyond Int32.MaxValue
+ Win32Error(r, name);
+ }
+ else if (size > (Int32.MaxValue / 2)) {
+ // at this point in the loop "size * 2" would cause an overflow
+ size = Int32.MaxValue;
+ }
+ else {
+ size *= 2;
+ }
+ sizeInput = size;
+ blob = new byte[size];
+ }
+ if (r != 0)
+ Win32Error(r, name);
+ return blob;
+ }
+ else {
+ // For stuff like ERROR_FILE_NOT_FOUND, we want to return null (data).
+ // Some OS's returned ERROR_MORE_DATA even in success cases, so we
+ // want to continue on through the function.
+ if (ret != Win32Native.ERROR_MORE_DATA)
+ return data;
+ }
+ }
+
+ if (datasize < 0) {
+ // unexpected code path
+ BCLDebug.Assert(false, "[InternalGetValue] RegQueryValue returned ERROR_SUCCESS but gave a negative datasize");
+ datasize = 0;
+ }
+
+
+ switch (type) {
+ case Win32Native.REG_NONE:
+ case Win32Native.REG_DWORD_BIG_ENDIAN:
+ case Win32Native.REG_BINARY: {
+ byte[] blob = new byte[datasize];
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref datasize);
+ data = blob;
+ }
+ break;
+ case Win32Native.REG_QWORD:
+ { // also REG_QWORD_LITTLE_ENDIAN
+ if (datasize > 8) {
+ // prevent an AV in the edge case that datasize is larger than sizeof(long)
+ goto case Win32Native.REG_BINARY;
+ }
+ long blob = 0;
+ BCLDebug.Assert(datasize==8, "datasize==8");
+ // Here, datasize must be 8 when calling this
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, ref blob, ref datasize);
+
+ data = blob;
+ }
+ break;
+ case Win32Native.REG_DWORD:
+ { // also REG_DWORD_LITTLE_ENDIAN
+ if (datasize > 4) {
+ // prevent an AV in the edge case that datasize is larger than sizeof(int)
+ goto case Win32Native.REG_QWORD;
+ }
+ int blob = 0;
+ BCLDebug.Assert(datasize==4, "datasize==4");
+ // Here, datasize must be four when calling this
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, ref blob, ref datasize);
+
+ data = blob;
+ }
+ break;
+
+ case Win32Native.REG_SZ:
+ {
+ if (datasize % 2 == 1) {
+ // handle the case where the registry contains an odd-byte length (corrupt data?)
+ try {
+ datasize = checked(datasize + 1);
+ }
+ catch (OverflowException e) {
+ throw new IOException(Environment.GetResourceString("Arg_RegGetOverflowBug"), e);
+ }
+ }
+ char[] blob = new char[datasize/2];
+
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref datasize);
+ if (blob.Length > 0 && blob[blob.Length - 1] == (char)0) {
+ data = new String(blob, 0, blob.Length - 1);
+ }
+ else {
+ // in the very unlikely case the data is missing null termination,
+ // pass in the whole char[] to prevent truncating a character
+ data = new String(blob);
+ }
+ }
+ break;
+
+ case Win32Native.REG_EXPAND_SZ:
+ {
+ if (datasize % 2 == 1) {
+ // handle the case where the registry contains an odd-byte length (corrupt data?)
+ try {
+ datasize = checked(datasize + 1);
+ }
+ catch (OverflowException e) {
+ throw new IOException(Environment.GetResourceString("Arg_RegGetOverflowBug"), e);
+ }
+ }
+ char[] blob = new char[datasize/2];
+
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref datasize);
+
+ if (blob.Length > 0 && blob[blob.Length - 1] == (char)0) {
+ data = new String(blob, 0, blob.Length - 1);
+ }
+ else {
+ // in the very unlikely case the data is missing null termination,
+ // pass in the whole char[] to prevent truncating a character
+ data = new String(blob);
+ }
+
+ if (!doNotExpand)
+ data = Environment.ExpandEnvironmentVariables((String)data);
+ }
+ break;
+ case Win32Native.REG_MULTI_SZ:
+ {
+ if (datasize % 2 == 1) {
+ // handle the case where the registry contains an odd-byte length (corrupt data?)
+ try {
+ datasize = checked(datasize + 1);
+ }
+ catch (OverflowException e) {
+ throw new IOException(Environment.GetResourceString("Arg_RegGetOverflowBug"), e);
+ }
+ }
+ char[] blob = new char[datasize/2];
+
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref datasize);
+
+ // make sure the string is null terminated before processing the data
+ if (blob.Length > 0 && blob[blob.Length - 1] != (char)0) {
+ try {
+ char[] newBlob = new char[checked(blob.Length + 1)];
+ for (int i = 0; i < blob.Length; i++) {
+ newBlob[i] = blob[i];
+ }
+ newBlob[newBlob.Length - 1] = (char)0;
+ blob = newBlob;
+ }
+ catch (OverflowException e) {
+ throw new IOException(Environment.GetResourceString("Arg_RegGetOverflowBug"), e);
+ }
+ blob[blob.Length - 1] = (char)0;
+ }
+
+
+ IList<String> strings = new List<String>();
+ int cur = 0;
+ int len = blob.Length;
+
+ while (ret == 0 && cur < len) {
+ int nextNull = cur;
+ while (nextNull < len && blob[nextNull] != (char)0) {
+ nextNull++;
+ }
+
+ if (nextNull < len) {
+ BCLDebug.Assert(blob[nextNull] == (char)0, "blob[nextNull] should be 0");
+ if (nextNull-cur > 0) {
+ strings.Add(new String(blob, cur, nextNull-cur));
+ }
+ else {
+ // we found an empty string. But if we're at the end of the data,
+ // it's just the extra null terminator.
+ if (nextNull != len-1)
+ strings.Add(String.Empty);
+ }
+ }
+ else {
+ strings.Add(new String(blob, cur, len-cur));
+ }
+ cur = nextNull+1;
+ }
+
+ data = new String[strings.Count];
+ strings.CopyTo((String[])data, 0);
+ }
+ break;
+ case Win32Native.REG_LINK:
+ default:
+ break;
+ }
+
+ return data;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public RegistryValueKind GetValueKind(string name) {
+ CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default);
+ EnsureNotDisposed();
+
+ int type = 0;
+ int datasize = 0;
+ int ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, (byte[])null, ref datasize);
+ if (ret != 0)
+ Win32Error(ret, null);
+ if (type == Win32Native.REG_NONE)
+ return RegistryValueKind.None;
+ else if (!Enum.IsDefined(typeof(RegistryValueKind), type))
+ return RegistryValueKind.Unknown;
+ else
+ return (RegistryValueKind) type;
+ }
+
+ /**
+ * Retrieves the current state of the dirty property.
+ *
+ * A key is marked as dirty if any operation has occurred that modifies the
+ * contents of the key.
+ *
+ * @return <b>true</b> if the key has been modified.
+ */
+ private bool IsDirty() {
+ return (this.state & STATE_DIRTY) != 0;
+ }
+
+ private bool IsSystemKey() {
+ return (this.state & STATE_SYSTEMKEY) != 0;
+ }
+
+ private bool IsWritable() {
+ return (this.state & STATE_WRITEACCESS) != 0;
+ }
+
+ private bool IsPerfDataKey() {
+ return (this.state & STATE_PERF_DATA) != 0;
+ }
+
+ public String Name {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ EnsureNotDisposed();
+ return keyName;
+ }
+ }
+
+ private void SetDirty() {
+ this.state |= STATE_DIRTY;
+ }
+
+ /**
+ * Sets the specified value.
+ *
+ * @param name Name of value to store data in.
+ * @param value Data to store.
+ */
+ public void SetValue(String name, Object value) {
+ SetValue(name, value, RegistryValueKind.Unknown);
+ }
+
+ [System.Security.SecuritySafeCritical] //auto-generated
+ [ComVisible(false)]
+ public unsafe void SetValue(String name, Object value, RegistryValueKind valueKind) {
+ if (value==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+
+ if (name != null && name.Length > MaxValueLength) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegValStrLenBug"));
+ }
+
+ if (!Enum.IsDefined(typeof(RegistryValueKind), valueKind))
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegBadKeyKind"), "valueKind");
+
+ EnsureWriteable();
+
+ if (!remoteKey && ContainsRegistryValue(name)) { // Existing key
+ CheckPermission(RegistryInternalCheck.CheckValueWritePermission, name, false, RegistryKeyPermissionCheck.Default);
+ }
+ else { // Creating a new value
+ CheckPermission(RegistryInternalCheck.CheckValueCreatePermission, name, false, RegistryKeyPermissionCheck.Default);
+ }
+
+ if (valueKind == RegistryValueKind.Unknown) {
+ // this is to maintain compatibility with the old way of autodetecting the type.
+ // SetValue(string, object) will come through this codepath.
+ valueKind = CalculateValueKind(value);
+ }
+
+ int ret = 0;
+ try {
+ switch (valueKind) {
+ case RegistryValueKind.ExpandString:
+ case RegistryValueKind.String:
+ {
+ String data = value.ToString();
+ ret = Win32Native.RegSetValueEx(hkey,
+ name,
+ 0,
+ valueKind,
+ data,
+ checked(data.Length * 2 + 2));
+ break;
+ }
+
+ case RegistryValueKind.MultiString:
+ {
+ // Other thread might modify the input array after we calculate the buffer length.
+ // Make a copy of the input array to be safe.
+ string[] dataStrings = (string[])(((string[])value).Clone());
+ int sizeInBytes = 0;
+
+ // First determine the size of the array
+ //
+ for (int i=0; i<dataStrings.Length; i++) {
+ if (dataStrings[i] == null) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSetStrArrNull);
+ }
+ sizeInBytes = checked(sizeInBytes + (dataStrings[i].Length+1) * 2);
+ }
+ sizeInBytes = checked(sizeInBytes + 2);
+
+ byte[] basePtr = new byte[sizeInBytes];
+ fixed(byte* b = basePtr) {
+ IntPtr currentPtr = new IntPtr( (void *) b);
+
+ // Write out the strings...
+ //
+ for (int i=0; i<dataStrings.Length; i++) {
+ // Assumes that the Strings are always null terminated.
+ String.InternalCopy(dataStrings[i],currentPtr,(checked(dataStrings[i].Length*2)));
+ currentPtr = new IntPtr((long)currentPtr + (checked(dataStrings[i].Length*2)));
+ *(char*)(currentPtr.ToPointer()) = '\0';
+ currentPtr = new IntPtr((long)currentPtr + 2);
+ }
+
+ *(char*)(currentPtr.ToPointer()) = '\0';
+ currentPtr = new IntPtr((long)currentPtr + 2);
+
+ ret = Win32Native.RegSetValueEx(hkey,
+ name,
+ 0,
+ RegistryValueKind.MultiString,
+ basePtr,
+ sizeInBytes);
+ }
+ break;
+ }
+
+ case RegistryValueKind.None:
+ case RegistryValueKind.Binary:
+ byte[] dataBytes = (byte[]) value;
+ ret = Win32Native.RegSetValueEx(hkey,
+ name,
+ 0,
+ (valueKind == RegistryValueKind.None ? Win32Native.REG_NONE: RegistryValueKind.Binary),
+ dataBytes,
+ dataBytes.Length);
+ break;
+
+ case RegistryValueKind.DWord:
+ {
+ // We need to use Convert here because we could have a boxed type cannot be
+ // unboxed and cast at the same time. I.e. ((int)(object)(short) 5) will fail.
+ int data = Convert.ToInt32(value, System.Globalization.CultureInfo.InvariantCulture);
+
+ ret = Win32Native.RegSetValueEx(hkey,
+ name,
+ 0,
+ RegistryValueKind.DWord,
+ ref data,
+ 4);
+ break;
+ }
+
+ case RegistryValueKind.QWord:
+ {
+ long data = Convert.ToInt64(value, System.Globalization.CultureInfo.InvariantCulture);
+
+ ret = Win32Native.RegSetValueEx(hkey,
+ name,
+ 0,
+ RegistryValueKind.QWord,
+ ref data,
+ 8);
+ break;
+ }
+ }
+ }
+ catch (OverflowException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSetMismatchedKind);
+ }
+ catch (InvalidOperationException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSetMismatchedKind);
+ }
+ catch (FormatException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSetMismatchedKind);
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSetMismatchedKind);
+ }
+
+ if (ret == 0) {
+ SetDirty();
+ }
+ else
+ Win32Error(ret, null);
+
+ }
+
+ private RegistryValueKind CalculateValueKind(Object value) {
+ // This logic matches what used to be in SetValue(string name, object value) in the v1.0 and v1.1 days.
+ // Even though we could add detection for an int64 in here, we want to maintain compatibility with the
+ // old behavior.
+ if (value is Int32)
+ return RegistryValueKind.DWord;
+ else if (value is Array) {
+ if (value is byte[])
+ return RegistryValueKind.Binary;
+ else if (value is String[])
+ return RegistryValueKind.MultiString;
+ else
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegSetBadArrType", value.GetType().Name));
+ }
+ else
+ return RegistryValueKind.String;
+ }
+
+ /**
+ * Retrieves a string representation of this key.
+ *
+ * @return a string representing the key.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ EnsureNotDisposed();
+ return keyName;
+ }
+
+#if FEATURE_MACL
+ public RegistrySecurity GetAccessControl() {
+ return GetAccessControl(AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public RegistrySecurity GetAccessControl(AccessControlSections includeSections) {
+ EnsureNotDisposed();
+ return new RegistrySecurity(hkey, keyName, includeSections);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetAccessControl(RegistrySecurity registrySecurity) {
+ EnsureWriteable();
+ if (registrySecurity == null)
+ throw new ArgumentNullException("registrySecurity");
+
+ registrySecurity.Persist(hkey, keyName);
+ }
+#endif
+
+ /**
+ * After calling GetLastWin32Error(), it clears the last error field,
+ * so you must save the HResult and pass it to this method. This method
+ * will determine the appropriate exception to throw dependent on your
+ * error, and depending on the error, insert a string into the message
+ * gotten from the ResourceManager.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal void Win32Error(int errorCode, String str) {
+ switch (errorCode) {
+ case Win32Native.ERROR_ACCESS_DENIED:
+ if (str != null)
+ throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_RegistryKeyGeneric_Key", str));
+ else
+ throw new UnauthorizedAccessException();
+
+ case Win32Native.ERROR_INVALID_HANDLE:
+ /**
+ * For normal RegistryKey instances we dispose the SafeRegHandle and throw IOException.
+ * However, for HKEY_PERFORMANCE_DATA (on a local or remote machine) we avoid disposing the
+ * SafeRegHandle and only throw the IOException. This is to workaround reentrancy issues
+ * in PerformanceCounter.NextValue() where the API could throw {NullReference, ObjectDisposed, ArgumentNull}Exception
+ * on reentrant calls because of this error code path in RegistryKey
+ *
+ * Normally we'd make our caller synchronize access to a shared RegistryKey instead of doing something like this,
+ * however we shipped PerformanceCounter.NextValue() un-synchronized in v2.0RTM and customers have taken a dependency on
+ * this behavior (being able to simultaneously query multiple remote-machine counters on multiple threads, instead of
+ * having serialized access).
+ */
+ if (!IsPerfDataKey()) {
+ this.hkey.SetHandleAsInvalid();
+ this.hkey = null;
+ }
+ goto default;
+
+ case Win32Native.ERROR_FILE_NOT_FOUND:
+ throw new IOException(Environment.GetResourceString("Arg_RegKeyNotFound"), errorCode);
+
+ default:
+ throw new IOException(Win32Native.GetMessage(errorCode), errorCode);
+ }
+ }
+
+ [SecuritySafeCritical]
+ internal static void Win32ErrorStatic(int errorCode, String str) {
+ switch (errorCode) {
+ case Win32Native.ERROR_ACCESS_DENIED:
+ if (str != null)
+ throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_RegistryKeyGeneric_Key", str));
+ else
+ throw new UnauthorizedAccessException();
+
+ default:
+ throw new IOException(Win32Native.GetMessage(errorCode), errorCode);
+ }
+ }
+
+ internal static String FixupName(String name)
+ {
+ BCLDebug.Assert(name!=null,"[FixupName]name!=null");
+ if (name.IndexOf('\\') == -1)
+ return name;
+
+ StringBuilder sb = new StringBuilder(name);
+ FixupPath(sb);
+ int temp = sb.Length - 1;
+ if (temp >= 0 && sb[temp] == '\\') // Remove trailing slash
+ sb.Length = temp;
+ return sb.ToString();
+ }
+
+
+ private static void FixupPath(StringBuilder path)
+ {
+ Contract.Requires(path != null);
+ int length = path.Length;
+ bool fixup = false;
+ char markerChar = (char)0xFFFF;
+
+ int i = 1;
+ while (i < length - 1)
+ {
+ if (path[i] == '\\')
+ {
+ i++;
+ while (i < length)
+ {
+ if (path[i] == '\\')
+ {
+ path[i] = markerChar;
+ i++;
+ fixup = true;
+ }
+ else
+ break;
+ }
+
+ }
+ i++;
+ }
+
+ if (fixup)
+ {
+ i = 0;
+ int j = 0;
+ while (i < length)
+ {
+ if(path[i] == markerChar)
+ {
+ i++;
+ continue;
+ }
+ path[j] = path[i];
+ i++;
+ j++;
+ }
+ path.Length += j - i;
+ }
+
+ }
+
+ //
+ // Read/Write/Create SubKey Permission
+ //
+ private void GetSubKeyReadPermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Read;
+ path = keyName + "\\" + subkeyName + "\\.";
+ }
+ private void GetSubKeyWritePermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ // If we want to open a subkey of a read-only key as writeable, we need to do the check.
+ access = RegistryPermissionAccess.Write;
+ path = keyName + "\\" + subkeyName + "\\.";
+ }
+ private void GetSubKeyCreatePermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Create;
+ path = keyName + "\\" + subkeyName + "\\.";
+ }
+
+ //
+ // Read/Write/ReadWrite SubTree Permission
+ //
+ private void GetSubTreeReadPermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Read;
+ path = keyName + "\\" + subkeyName + "\\";
+ }
+ private void GetSubTreeWritePermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Write;
+ path = keyName + "\\" + subkeyName + "\\";
+ }
+ private void GetSubTreeReadWritePermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Write | RegistryPermissionAccess.Read;
+ path = keyName + "\\" + subkeyName;
+ }
+
+ //
+ // Read/Write/Create Value Permission
+ //
+ private void GetValueReadPermission(string valueName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Read;
+ path = keyName+"\\"+valueName;
+ }
+ private void GetValueWritePermission(string valueName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Write;
+ path = keyName+"\\"+valueName;
+ }
+ private void GetValueCreatePermission(string valueName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Create;
+ path = keyName+"\\"+valueName;
+ }
+
+ // Read Key Permission
+ private void GetKeyReadPermission(out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Read;
+ path = keyName + "\\.";
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void CheckPermission(RegistryInternalCheck check, string item, bool subKeyWritable, RegistryKeyPermissionCheck subKeyCheck) {
+ bool demand = false;
+ RegistryPermissionAccess access = RegistryPermissionAccess.NoAccess;
+ string path = null;
+
+#if !FEATURE_CORECLR
+ if (CodeAccessSecurityEngine.QuickCheckForAllDemands()) {
+ return; // full trust fast path
+ }
+#endif // !FEATURE_CORECLR
+
+ switch (check) {
+ //
+ // Read/Write/Create SubKey Permission
+ //
+ case RegistryInternalCheck.CheckSubKeyReadPermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode == RegistryKeyPermissionCheck.Default, "Should be called from a key opened under default mode only!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ demand = true;
+ GetSubKeyReadPermission(item, out access, out path);
+ }
+ break;
+ case RegistryInternalCheck.CheckSubKeyWritePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode != RegistryKeyPermissionCheck.ReadSubTree, "We shouldn't allow creating sub key under read-only key!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetSubKeyWritePermission(item, out access, out path);
+ }
+ }
+ break;
+ case RegistryInternalCheck.CheckSubKeyCreatePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode != RegistryKeyPermissionCheck.ReadSubTree, "We shouldn't allow creating sub key under read-only key!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetSubKeyCreatePermission(item, out access, out path);
+ }
+ }
+ break;
+ //
+ // Read/Write/ReadWrite SubTree Permission
+ //
+ case RegistryInternalCheck.CheckSubTreeReadPermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetSubTreeReadPermission(item, out access, out path);
+ }
+ }
+ break;
+ case RegistryInternalCheck.CheckSubTreeWritePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode != RegistryKeyPermissionCheck.ReadSubTree, "We shouldn't allow writing value to read-only key!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetSubTreeWritePermission(item, out access, out path);
+ }
+ }
+ break;
+ case RegistryInternalCheck.CheckSubTreeReadWritePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ // If we want to open a subkey of a read-only key as writeable, we need to do the check.
+ demand = true;
+ GetSubTreeReadWritePermission(item, out access, out path);
+ }
+ break;
+ //
+ // Read/Write/Create Value Permission
+ //
+ case RegistryInternalCheck.CheckValueReadPermission:
+ ///*** no remoteKey check ***///
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ // only need to check for default mode (dynamice check)
+ demand = true;
+ GetValueReadPermission(item, out access, out path);
+ }
+ break;
+ case RegistryInternalCheck.CheckValueWritePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode != RegistryKeyPermissionCheck.ReadSubTree, "We shouldn't allow writing value to read-only key!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ // skip the security check if the key is opened under write mode
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetValueWritePermission(item, out access, out path);
+ }
+ }
+ break;
+ case RegistryInternalCheck.CheckValueCreatePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode != RegistryKeyPermissionCheck.ReadSubTree, "We shouldn't allow creating value under read-only key!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ // skip the security check if the key is opened under write mode
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetValueCreatePermission(item, out access, out path);
+ }
+ }
+ break;
+ //
+ // CheckKeyReadPermission
+ //
+ case RegistryInternalCheck.CheckKeyReadPermission:
+ ///*** no remoteKey check ***///
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ BCLDebug.Assert(item == null, "CheckKeyReadPermission should never have a non-null item parameter!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+
+ // only need to check for default mode (dynamice check)
+ demand = true;
+ GetKeyReadPermission(out access, out path);
+ }
+ break;
+ //
+ // CheckSubTreePermission
+ //
+ case RegistryInternalCheck.CheckSubTreePermission:
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ if( subKeyCheck == RegistryKeyPermissionCheck.ReadSubTree) {
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ if( remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ demand = true;
+ GetSubTreeReadPermission(item, out access, out path);
+ }
+ }
+ }
+ else if(subKeyCheck == RegistryKeyPermissionCheck.ReadWriteSubTree) {
+ if( checkMode != RegistryKeyPermissionCheck.ReadWriteSubTree) {
+ if( remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ demand = true;
+ GetSubTreeReadWritePermission(item, out access, out path);
+ }
+ }
+ }
+ break;
+
+ //
+ // CheckOpenSubKeyWithWritablePermission uses the 'subKeyWritable' parameter
+ //
+ case RegistryInternalCheck.CheckOpenSubKeyWithWritablePermission:
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ // If the parent key is not opened under default mode, we have access already.
+ // If the parent key is opened under default mode, we need to check for permission.
+ if(checkMode == RegistryKeyPermissionCheck.Default) {
+ if( remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ demand = true;
+ GetSubKeyReadPermission(item, out access, out path);
+ }
+ break;
+ }
+ if( subKeyWritable && (checkMode == RegistryKeyPermissionCheck.ReadSubTree)) {
+ if( remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ demand = true;
+ GetSubTreeReadWritePermission(item, out access, out path);
+ }
+ break;
+ }
+ break;
+
+ //
+ // CheckOpenSubKeyPermission uses the 'subKeyCheck' parameter
+ //
+ case RegistryInternalCheck.CheckOpenSubKeyPermission:
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ if(subKeyCheck == RegistryKeyPermissionCheck.Default) {
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ if(remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ demand = true;
+ GetSubKeyReadPermission(item, out access, out path);
+ }
+ }
+ }
+ break;
+
+ default:
+ BCLDebug.Assert(false, "CheckPermission default switch case should never be hit!");
+ break;
+ }
+
+ if (demand) {
+ new RegistryPermission(access, path).Demand();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static private void CheckUnmanagedCodePermission() {
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private bool ContainsRegistryValue(string name) {
+ int type = 0;
+ int datasize = 0;
+ int retval = Win32Native.RegQueryValueEx(hkey, name, null, ref type, (byte[])null, ref datasize);
+ return retval == 0;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void EnsureNotDisposed(){
+ if (hkey == null) {
+ ThrowHelper.ThrowObjectDisposedException(keyName, ExceptionResource.ObjectDisposed_RegKeyClosed);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void EnsureWriteable() {
+ EnsureNotDisposed();
+ if (!IsWritable()) {
+ ThrowHelper.ThrowUnauthorizedAccessException(ExceptionResource.UnauthorizedAccess_RegistryNoWrite);
+ }
+ }
+
+ static int GetRegistryKeyAccess(bool isWritable) {
+ int winAccess;
+ if (!isWritable) {
+ winAccess = Win32Native.KEY_READ;
+ }
+ else {
+ winAccess = Win32Native.KEY_READ | Win32Native.KEY_WRITE;
+ }
+
+ return winAccess;
+ }
+
+ static int GetRegistryKeyAccess(RegistryKeyPermissionCheck mode) {
+ int winAccess = 0;
+ switch(mode) {
+ case RegistryKeyPermissionCheck.ReadSubTree:
+ case RegistryKeyPermissionCheck.Default:
+ winAccess = Win32Native.KEY_READ;
+ break;
+
+ case RegistryKeyPermissionCheck.ReadWriteSubTree:
+ winAccess = Win32Native.KEY_READ| Win32Native.KEY_WRITE;
+ break;
+
+ default:
+ BCLDebug.Assert(false, "unexpected code path");
+ break;
+ }
+
+ return winAccess;
+ }
+
+ private RegistryKeyPermissionCheck GetSubKeyPermissonCheck(bool subkeyWritable) {
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ return checkMode;
+ }
+
+ if(subkeyWritable) {
+ return RegistryKeyPermissionCheck.ReadWriteSubTree;
+ }
+ else {
+ return RegistryKeyPermissionCheck.ReadSubTree;
+ }
+ }
+
+ static private void ValidateKeyName(string name) {
+ Contract.Ensures(name != null);
+ if (name == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.name);
+ }
+
+ int nextSlash = name.IndexOf("\\", StringComparison.OrdinalIgnoreCase);
+ int current = 0;
+ while (nextSlash != -1) {
+ if ((nextSlash - current) > MaxKeyLength)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegKeyStrLenBug);
+
+ current = nextSlash + 1;
+ nextSlash = name.IndexOf("\\", current, StringComparison.OrdinalIgnoreCase);
+ }
+
+ if ((name.Length - current) > MaxKeyLength)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegKeyStrLenBug);
+
+ }
+
+ static private void ValidateKeyMode(RegistryKeyPermissionCheck mode) {
+ if( mode < RegistryKeyPermissionCheck.Default || mode > RegistryKeyPermissionCheck.ReadWriteSubTree) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidRegistryKeyPermissionCheck, ExceptionArgument.mode);
+ }
+ }
+
+ static private void ValidateKeyOptions(RegistryOptions options) {
+ if (options < RegistryOptions.None || options > RegistryOptions.Volatile) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidRegistryOptionsCheck, ExceptionArgument.options);
+ }
+ }
+
+ static private void ValidateKeyView(RegistryView view) {
+ if (view != RegistryView.Default && view != RegistryView.Registry32 && view != RegistryView.Registry64) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidRegistryViewCheck, ExceptionArgument.view);
+ }
+ }
+
+
+#if FEATURE_MACL
+ static private void ValidateKeyRights(int rights) {
+ if(0 != (rights & ~((int)RegistryRights.FullControl))) {
+ // We need to throw SecurityException here for compatiblity reason,
+ // although UnauthorizedAccessException will make more sense.
+ ThrowHelper.ThrowSecurityException(ExceptionResource.Security_RegistryPermission);
+ }
+ }
+#endif
+ // Win32 constants for error handling
+ private const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
+ private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
+ private const int FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000;
+ }
+
+ [Flags]
+ public enum RegistryValueOptions {
+ None = 0,
+ DoNotExpandEnvironmentNames = 1
+ }
+
+ // the name for this API is meant to mimic FileMode, which has similar values
+
+ public enum RegistryKeyPermissionCheck {
+ Default = 0,
+ ReadSubTree = 1,
+ ReadWriteSubTree = 2
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/RegistryOptions.cs b/src/mscorlib/src/Microsoft/Win32/RegistryOptions.cs
new file mode 100644
index 0000000000..4d5e3aaab1
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/RegistryOptions.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+//
+// Implements Microsoft.Win32.RegistryOptions
+//
+// ======================================================================================
+namespace Microsoft.Win32 {
+ using System;
+
+ [Flags]
+ public enum RegistryOptions {
+ None = Win32Native.REG_OPTION_NON_VOLATILE, // 0x0000
+ Volatile = Win32Native.REG_OPTION_VOLATILE, // 0x0001
+///
+/// Consider exposing more options in a future release. Users can access this
+/// functionality by calling [RegistryKey].Handle and pinvoking
+///
+/// CreateLink = Win32Native.REG_OPTION_CREATE_LINK, // 0x0002
+/// BackupRestore = Win32Native.REG_OPTION_BACKUP_RESTORE,// 0x0004
+ };
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/RegistryValueKind.cs b/src/mscorlib/src/Microsoft/Win32/RegistryValueKind.cs
new file mode 100644
index 0000000000..c88d5f920a
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/RegistryValueKind.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace Microsoft.Win32 {
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum RegistryValueKind {
+ String = Win32Native.REG_SZ,
+ ExpandString = Win32Native.REG_EXPAND_SZ,
+ Binary = Win32Native.REG_BINARY,
+ DWord = Win32Native.REG_DWORD,
+ MultiString = Win32Native.REG_MULTI_SZ,
+ QWord = Win32Native.REG_QWORD,
+ Unknown = 0, // REG_NONE is defined as zero but BCL
+ [System.Runtime.InteropServices.ComVisible(false)]
+ None = unchecked((int)0xFFFFFFFF), // mistakingly overrode this value.
+ } // Now instead of using Win32Native.REG_NONE we use "-1" and play games internally.
+}
+
diff --git a/src/mscorlib/src/Microsoft/Win32/RegistryView.cs b/src/mscorlib/src/Microsoft/Win32/RegistryView.cs
new file mode 100644
index 0000000000..7fbc2b3391
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/RegistryView.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+//
+// Implements Microsoft.Win32.RegistryView
+//
+// ======================================================================================
+namespace Microsoft.Win32 {
+ using System;
+
+ public enum RegistryView {
+ Default = 0, // 0x0000 operate on the default registry view
+ Registry64 = Win32Native.KEY_WOW64_64KEY, // 0x0100 operate on the 64-bit registry view
+ Registry32 = Win32Native.KEY_WOW64_32KEY, // 0x0200 operate on the 32-bit registry view
+ };
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs
new file mode 100644
index 0000000000..ab06347ee4
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A wrapper for file handles
+**
+**
+===========================================================*/
+
+using System;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+using Microsoft.Win32;
+
+namespace Microsoft.Win32.SafeHandles {
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public sealed class SafeFileHandle: SafeHandleZeroOrMinusOneIsInvalid {
+
+ private SafeFileHandle() : base(true)
+ {
+ }
+
+ public SafeFileHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle) {
+ SetHandle(preexistingHandle);
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.CloseHandle(handle);
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs
new file mode 100644
index 0000000000..5e1b5100bc
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A wrapper for file handles
+**
+**
+===========================================================*/
+using System;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+
+namespace Microsoft.Win32.SafeHandles
+{
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeFileMappingHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal SafeFileMappingHandle() : base(true) {}
+
+ // 0 is an Invalid Handle
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal SafeFileMappingHandle(IntPtr handle, bool ownsHandle) : base (ownsHandle)
+ {
+ SetHandle(handle);
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.CloseHandle(handle);
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs
new file mode 100644
index 0000000000..b24535f997
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A wrapper for find handles
+**
+**
+===========================================================*/
+
+using System;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using Microsoft.Win32;
+
+namespace Microsoft.Win32.SafeHandles {
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal SafeFindHandle() : base(true) {}
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.FindClose(handle);
+ }
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs
new file mode 100644
index 0000000000..d2ea42b14e
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.Win32 {
+ using Microsoft.Win32;
+ using Microsoft.Win32.SafeHandles;
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Text;
+
+ [System.Security.SecurityCritical] // auto-generated
+ [HostProtectionAttribute(MayLeakOnAbort = true)]
+ sealed internal class SafeLibraryHandle : SafeHandleZeroOrMinusOneIsInvalid {
+ internal SafeLibraryHandle() : base(true) {}
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return UnsafeNativeMethods.FreeLibrary(handle);
+ }
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs
new file mode 100644
index 0000000000..3eea2b9937
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+namespace Microsoft.Win32.SafeHandles {
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.ConstrainedExecution;
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeLocalAllocHandle : SafeBuffer {
+ private SafeLocalAllocHandle () : base(true) {}
+
+ // 0 is an Invalid Handle
+ internal SafeLocalAllocHandle (IntPtr handle) : base (true) {
+ SetHandle(handle);
+ }
+
+ internal static SafeLocalAllocHandle InvalidHandle {
+ get { return new SafeLocalAllocHandle(IntPtr.Zero); }
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.LocalFree(handle) == IntPtr.Zero;
+ }
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs
new file mode 100644
index 0000000000..d0e3f048f2
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+//
+// Implements Microsoft.Win32.SafeHandles.SafeRegistryHandle
+//
+// ======================================================================================
+namespace Microsoft.Win32.SafeHandles {
+ using System;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+
+ [System.Security.SecurityCritical]
+ public sealed class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid {
+ [System.Security.SecurityCritical]
+ internal SafeRegistryHandle() : base(true) {}
+
+ [System.Security.SecurityCritical]
+ public SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle) {
+ SetHandle(preexistingHandle);
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle() {
+ return (RegCloseKey(handle) == Win32Native.ERROR_SUCCESS);
+ }
+
+ [DllImport(Win32Native.ADVAPI32)]
+ [SuppressUnmanagedCodeSecurity]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int RegCloseKey(IntPtr hKey);
+ }
+}
+
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs
new file mode 100644
index 0000000000..01ec4d2ad8
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A wrapper for file handles
+**
+**
+===========================================================*/
+using System;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+
+namespace Microsoft.Win32.SafeHandles
+{
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeViewOfFileHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal SafeViewOfFileHandle() : base(true) {}
+
+ // 0 is an Invalid Handle
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal SafeViewOfFileHandle(IntPtr handle, bool ownsHandle) : base (ownsHandle) {
+ SetHandle(handle);
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ if (Win32Native.UnmapViewOfFile(handle))
+ {
+ handle = IntPtr.Zero;
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
new file mode 100644
index 0000000000..fa24c96718
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A wrapper for Win32 events (mutexes, auto reset events, and
+** manual reset events). Used by WaitHandle.
+**
+**
+===========================================================*/
+
+using System;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+using Microsoft.Win32;
+using System.Threading;
+
+namespace Microsoft.Win32.SafeHandles {
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public sealed class SafeWaitHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ // Called by P/Invoke marshaler
+ private SafeWaitHandle() : base(true)
+ {
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public SafeWaitHandle(IntPtr existingHandle, bool ownsHandle) : base(ownsHandle)
+ {
+ SetHandle(existingHandle);
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.CloseHandle(handle);
+ }
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs
new file mode 100644
index 0000000000..58e0d7ad1d
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs
@@ -0,0 +1,112 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// Abstract derivations of SafeHandle designed to provide the common
+// functionality supporting Win32 handles. More specifically, they describe how
+// an invalid handle looks (for instance, some handles use -1 as an invalid
+// handle value, others use 0).
+//
+// Further derivations of these classes can specialise this even further (e.g.
+// file or registry handles).
+//
+//
+
+namespace Microsoft.Win32.SafeHandles
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Security.Permissions;
+ using System.Runtime.ConstrainedExecution;
+
+ // Class of safe handle which uses 0 or -1 as an invalid handle.
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+ public abstract class SafeHandleZeroOrMinusOneIsInvalid : SafeHandle
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected SafeHandleZeroOrMinusOneIsInvalid(bool ownsHandle) : base(IntPtr.Zero, ownsHandle)
+ {
+ }
+
+#if FEATURE_CORECLR
+ // A default constructor is needed to satisfy CoreCLR inheritence rules. It should not be called at runtime
+ protected SafeHandleZeroOrMinusOneIsInvalid()
+ {
+ throw new NotImplementedException();
+ }
+#endif // FEATURE_CORECLR
+
+ public override bool IsInvalid {
+ [System.Security.SecurityCritical]
+ get { return handle.IsNull() || handle == new IntPtr(-1); }
+ }
+ }
+
+ // Class of safe handle which uses only -1 as an invalid handle.
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+ public abstract class SafeHandleMinusOneIsInvalid : SafeHandle
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected SafeHandleMinusOneIsInvalid(bool ownsHandle) : base(new IntPtr(-1), ownsHandle)
+ {
+ }
+
+#if FEATURE_CORECLR
+ // A default constructor is needed to satisfy CoreCLR inheritence rules. It should not be called at runtime
+ protected SafeHandleMinusOneIsInvalid()
+ {
+ throw new NotImplementedException();
+ }
+#endif // FEATURE_CORECLR
+
+ public override bool IsInvalid {
+ [System.Security.SecurityCritical]
+ get { return handle == new IntPtr(-1); }
+ }
+ }
+
+ // Class of critical handle which uses 0 or -1 as an invalid handle.
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+ public abstract class CriticalHandleZeroOrMinusOneIsInvalid : CriticalHandle
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected CriticalHandleZeroOrMinusOneIsInvalid() : base(IntPtr.Zero)
+ {
+ }
+
+ public override bool IsInvalid {
+ [System.Security.SecurityCritical]
+ get { return handle.IsNull() || handle == new IntPtr(-1); }
+ }
+ }
+
+ // Class of critical handle which uses only -1 as an invalid handle.
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+ public abstract class CriticalHandleMinusOneIsInvalid : CriticalHandle
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected CriticalHandleMinusOneIsInvalid() : base(new IntPtr(-1))
+ {
+ }
+
+ public override bool IsInvalid {
+ [System.Security.SecurityCritical]
+ get { return handle == new IntPtr(-1); }
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs b/src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs
new file mode 100644
index 0000000000..9da9811ee8
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs
@@ -0,0 +1,282 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.Win32 {
+ using Microsoft.Win32;
+ using Microsoft.Win32.SafeHandles;
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Diagnostics.Tracing;
+
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal static class UnsafeNativeMethods {
+
+ [DllImport(Win32Native.KERNEL32, EntryPoint="GetTimeZoneInformation", SetLastError = true, ExactSpelling = true)]
+ internal static extern int GetTimeZoneInformation(out Win32Native.TimeZoneInformation lpTimeZoneInformation);
+
+ [DllImport(Win32Native.KERNEL32, EntryPoint="GetDynamicTimeZoneInformation", SetLastError = true, ExactSpelling = true)]
+ internal static extern int GetDynamicTimeZoneInformation(out Win32Native.DynamicTimeZoneInformation lpDynamicTimeZoneInformation);
+
+ //
+ // BOOL GetFileMUIPath(
+ // DWORD dwFlags,
+ // PCWSTR pcwszFilePath,
+ // PWSTR pwszLanguage,
+ // PULONG pcchLanguage,
+ // PWSTR pwszFileMUIPath,
+ // PULONG pcchFileMUIPath,
+ // PULONGLONG pululEnumerator
+ // );
+ //
+ [DllImport(Win32Native.KERNEL32, EntryPoint="GetFileMUIPath", SetLastError = true, ExactSpelling = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool GetFileMUIPath(
+ int flags,
+ [MarshalAs(UnmanagedType.LPWStr)]
+ String filePath,
+ [MarshalAs(UnmanagedType.LPWStr)]
+ StringBuilder language,
+ ref int languageLength,
+ [Out, MarshalAs(UnmanagedType.LPWStr)]
+ StringBuilder fileMuiPath,
+ ref int fileMuiPathLength,
+ ref Int64 enumerator);
+
+
+ [DllImport(Win32Native.USER32, EntryPoint="LoadStringW", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
+ internal static extern int LoadString(SafeLibraryHandle handle, int id, [Out] StringBuilder buffer, int bufferLength);
+
+ [DllImport(Win32Native.KERNEL32, CharSet=System.Runtime.InteropServices.CharSet.Unicode, SetLastError=true)]
+ internal static extern SafeLibraryHandle LoadLibraryEx(string libFilename, IntPtr reserved, int flags);
+
+ [DllImport(Win32Native.KERNEL32, CharSet=System.Runtime.InteropServices.CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool FreeLibrary(IntPtr hModule);
+
+
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal static unsafe class ManifestEtw
+ {
+ //
+ // Constants error coded returned by ETW APIs
+ //
+
+ // The event size is larger than the allowed maximum (64k - header).
+ internal const int ERROR_ARITHMETIC_OVERFLOW = 534;
+
+ // Occurs when filled buffers are trying to flush to disk,
+ // but disk IOs are not happening fast enough.
+ // This happens when the disk is slow and event traffic is heavy.
+ // Eventually, there are no more free (empty) buffers and the event is dropped.
+ internal const int ERROR_NOT_ENOUGH_MEMORY = 8;
+
+ internal const int ERROR_MORE_DATA = 0xEA;
+ internal const int ERROR_NOT_SUPPORTED = 50;
+ internal const int ERROR_INVALID_PARAMETER = 0x57;
+
+ //
+ // ETW Methods
+ //
+
+ internal const int EVENT_CONTROL_CODE_DISABLE_PROVIDER = 0;
+ internal const int EVENT_CONTROL_CODE_ENABLE_PROVIDER = 1;
+ internal const int EVENT_CONTROL_CODE_CAPTURE_STATE = 2;
+
+ //
+ // Callback
+ //
+ [SecurityCritical]
+ internal unsafe delegate void EtwEnableCallback(
+ [In] ref Guid sourceId,
+ [In] int isEnabled,
+ [In] byte level,
+ [In] long matchAnyKeywords,
+ [In] long matchAllKeywords,
+ [In] EVENT_FILTER_DESCRIPTOR* filterData,
+ [In] void* callbackContext
+ );
+
+ //
+ // Registration APIs
+ //
+ [SecurityCritical]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventRegister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern unsafe uint EventRegister(
+ [In] ref Guid providerId,
+ [In]EtwEnableCallback enableCallback,
+ [In]void* callbackContext,
+ [In][Out]ref long registrationHandle
+ );
+
+ //
+ [SecurityCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventUnregister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern uint EventUnregister([In] long registrationHandle);
+
+ //
+ // Writing (Publishing/Logging) APIs
+ //
+ //
+ [SecurityCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventWrite", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern unsafe int EventWrite(
+ [In] long registrationHandle,
+ [In] ref EventDescriptor eventDescriptor,
+ [In] int userDataCount,
+ [In] EventProvider.EventData* userData
+ );
+
+ [SecurityCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventWriteString", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern unsafe int EventWriteString(
+ [In] long registrationHandle,
+ [In] byte level,
+ [In] long keyword,
+ [In] string msg
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe internal struct EVENT_FILTER_DESCRIPTOR
+ {
+ public long Ptr;
+ public int Size;
+ public int Type;
+ };
+
+ /// <summary>
+ /// Call the ETW native API EventWriteTransfer and checks for invalid argument error.
+ /// The implementation of EventWriteTransfer on some older OSes (Windows 2008) does not accept null relatedActivityId.
+ /// So, for these cases we will retry the call with an empty Guid.
+ /// </summary>
+ internal static int EventWriteTransferWrapper(long registrationHandle,
+ ref EventDescriptor eventDescriptor,
+ Guid* activityId,
+ Guid* relatedActivityId,
+ int userDataCount,
+ EventProvider.EventData* userData)
+ {
+ int HResult = EventWriteTransfer(registrationHandle, ref eventDescriptor, activityId, relatedActivityId, userDataCount, userData);
+ if (HResult == ERROR_INVALID_PARAMETER && relatedActivityId == null)
+ {
+ Guid emptyGuid = Guid.Empty;
+ HResult = EventWriteTransfer(registrationHandle, ref eventDescriptor, activityId, &emptyGuid, userDataCount, userData);
+ }
+
+ return HResult;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventWriteTransfer", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ private static extern int EventWriteTransfer(
+ [In] long registrationHandle,
+ [In] ref EventDescriptor eventDescriptor,
+ [In] Guid* activityId,
+ [In] Guid* relatedActivityId,
+ [In] int userDataCount,
+ [In] EventProvider.EventData* userData
+ );
+
+ internal enum ActivityControl : uint
+ {
+ EVENT_ACTIVITY_CTRL_GET_ID = 1,
+ EVENT_ACTIVITY_CTRL_SET_ID = 2,
+ EVENT_ACTIVITY_CTRL_CREATE_ID = 3,
+ EVENT_ACTIVITY_CTRL_GET_SET_ID = 4,
+ EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5
+ };
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventActivityIdControl", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ internal static extern int EventActivityIdControl([In] ActivityControl ControlCode, [In][Out] ref Guid ActivityId);
+
+ internal enum EVENT_INFO_CLASS
+ {
+ BinaryTrackInfo,
+ SetEnableAllKeywords,
+ SetTraits,
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventSetInformation", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ internal static extern int EventSetInformation(
+ [In] long registrationHandle,
+ [In] EVENT_INFO_CLASS informationClass,
+ [In] void* eventInformation,
+ [In] int informationLength);
+
+ // Support for EnumerateTraceGuidsEx
+ internal enum TRACE_QUERY_INFO_CLASS
+ {
+ TraceGuidQueryList,
+ TraceGuidQueryInfo,
+ TraceGuidQueryProcess,
+ TraceStackTracingInfo,
+ MaxTraceSetInfoClass
+ };
+
+ internal struct TRACE_GUID_INFO
+ {
+ public int InstanceCount;
+ public int Reserved;
+ };
+
+ internal struct TRACE_PROVIDER_INSTANCE_INFO
+ {
+ public int NextOffset;
+ public int EnableCount;
+ public int Pid;
+ public int Flags;
+ };
+
+ internal struct TRACE_ENABLE_INFO
+ {
+ public int IsEnabled;
+ public byte Level;
+ public byte Reserved1;
+ public ushort LoggerId;
+ public int EnableProperty;
+ public int Reserved2;
+ public long MatchAnyKeyword;
+ public long MatchAllKeyword;
+ };
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EnumerateTraceGuidsEx", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ internal static extern int EnumerateTraceGuidsEx(
+ TRACE_QUERY_INFO_CLASS TraceQueryInfoClass,
+ void* InBuffer,
+ int InBufferSize,
+ void* OutBuffer,
+ int OutBufferSize,
+ ref int ReturnLength);
+
+ }
+#if FEATURE_COMINTEROP
+ [SecurityCritical]
+ [DllImport("combase.dll", PreserveSig = true)]
+ internal static extern int RoGetActivationFactory(
+ [MarshalAs(UnmanagedType.HString)] string activatableClassId,
+ [In] ref Guid iid,
+ [Out,MarshalAs(UnmanagedType.IInspectable)] out Object factory);
+#endif
+
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/Win32Native.cs b/src/mscorlib/src/Microsoft/Win32/Win32Native.cs
new file mode 100644
index 0000000000..ebe53f45af
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/Win32Native.cs
@@ -0,0 +1,2455 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: The CLR wrapper for all Win32 as well as
+** ROTOR-style Unix PAL, etc. native operations
+**
+**
+===========================================================*/
+/**
+ * Notes to PInvoke users: Getting the syntax exactly correct is crucial, and
+ * more than a little confusing. Here's some guidelines.
+ *
+ * For handles, you should use a SafeHandle subclass specific to your handle
+ * type. For files, we have the following set of interesting definitions:
+ *
+ * [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ * private static extern SafeFileHandle CreateFile(...);
+ *
+ * [DllImport(KERNEL32, SetLastError=true)]
+ * unsafe internal static extern int ReadFile(SafeFileHandle handle, ...);
+ *
+ * [DllImport(KERNEL32, SetLastError=true)]
+ * internal static extern bool CloseHandle(IntPtr handle);
+ *
+ * P/Invoke will create the SafeFileHandle instance for you and assign the
+ * return value from CreateFile into the handle atomically. When we call
+ * ReadFile, P/Invoke will increment a ref count, make the call, then decrement
+ * it (preventing handle recycling vulnerabilities). Then SafeFileHandle's
+ * ReleaseHandle method will call CloseHandle, passing in the handle field
+ * as an IntPtr.
+ *
+ * If for some reason you cannot use a SafeHandle subclass for your handles,
+ * then use IntPtr as the handle type (or possibly HandleRef - understand when
+ * to use GC.KeepAlive). If your code will run in SQL Server (or any other
+ * long-running process that can't be recycled easily), use a constrained
+ * execution region to prevent thread aborts while allocating your
+ * handle, and consider making your handle wrapper subclass
+ * CriticalFinalizerObject to ensure you can free the handle. As you can
+ * probably guess, SafeHandle will save you a lot of headaches if your code
+ * needs to be robust to thread aborts and OOM.
+ *
+ *
+ * If you have a method that takes a native struct, you have two options for
+ * declaring that struct. You can make it a value type ('struct' in CSharp),
+ * or a reference type ('class'). This choice doesn't seem very interesting,
+ * but your function prototype must use different syntax depending on your
+ * choice. For example, if your native method is prototyped as such:
+ *
+ * bool GetVersionEx(OSVERSIONINFO & lposvi);
+ *
+ *
+ * you must use EITHER THIS OR THE NEXT syntax:
+ *
+ * [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ * internal struct OSVERSIONINFO { ... }
+ *
+ * [DllImport(KERNEL32, CharSet=CharSet.Auto)]
+ * internal static extern bool GetVersionEx(ref OSVERSIONINFO lposvi);
+ *
+ * OR:
+ *
+ * [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ * internal class OSVERSIONINFO { ... }
+ *
+ * [DllImport(KERNEL32, CharSet=CharSet.Auto)]
+ * internal static extern bool GetVersionEx([In, Out] OSVERSIONINFO lposvi);
+ *
+ * Note that classes require being marked as [In, Out] while value types must
+ * be passed as ref parameters.
+ *
+ * Also note the CharSet.Auto on GetVersionEx - while it does not take a String
+ * as a parameter, the OSVERSIONINFO contains an embedded array of TCHARs, so
+ * the size of the struct varies on different platforms, and there's a
+ * GetVersionExA & a GetVersionExW. Also, the OSVERSIONINFO struct has a sizeof
+ * field so the OS can ensure you've passed in the correctly-sized copy of an
+ * OSVERSIONINFO. You must explicitly set this using Marshal.SizeOf(Object);
+ *
+ * For security reasons, if you're making a P/Invoke method to a Win32 method
+ * that takes an ANSI String and that String is the name of some resource you've
+ * done a security check on (such as a file name), you want to disable best fit
+ * mapping in WideCharToMultiByte. Do this by setting BestFitMapping=false
+ * in your DllImportAttribute.
+ */
+
+namespace Microsoft.Win32 {
+ using System;
+ using System.Security;
+#if FEATURE_IMPERSONATION
+ using System.Security.Principal;
+#endif
+ using System.Text;
+ using System.Configuration.Assemblies;
+ using System.Runtime.Remoting;
+ using System.Runtime.InteropServices;
+ using System.Threading;
+ using Microsoft.Win32.SafeHandles;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+
+ using BOOL = System.Int32;
+ using DWORD = System.UInt32;
+ using ULONG = System.UInt32;
+
+ /**
+ * Win32 encapsulation for MSCORLIB.
+ */
+ // Remove the default demands for all P/Invoke methods with this
+ // global declaration on the class.
+
+ [System.Security.SecurityCritical]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal static class Win32Native {
+
+ internal const int KEY_QUERY_VALUE = 0x0001;
+ internal const int KEY_SET_VALUE = 0x0002;
+ internal const int KEY_CREATE_SUB_KEY = 0x0004;
+ internal const int KEY_ENUMERATE_SUB_KEYS = 0x0008;
+ internal const int KEY_NOTIFY = 0x0010;
+ internal const int KEY_CREATE_LINK = 0x0020;
+ internal const int KEY_READ =((STANDARD_RIGHTS_READ |
+ KEY_QUERY_VALUE |
+ KEY_ENUMERATE_SUB_KEYS |
+ KEY_NOTIFY)
+ &
+ (~SYNCHRONIZE));
+
+ internal const int KEY_WRITE =((STANDARD_RIGHTS_WRITE |
+ KEY_SET_VALUE |
+ KEY_CREATE_SUB_KEY)
+ &
+ (~SYNCHRONIZE));
+ internal const int KEY_WOW64_64KEY = 0x0100; //
+ internal const int KEY_WOW64_32KEY = 0x0200; //
+ internal const int REG_OPTION_NON_VOLATILE= 0x0000; // (default) keys are persisted beyond reboot/unload
+ internal const int REG_OPTION_VOLATILE = 0x0001; // All keys created by the function are volatile
+ internal const int REG_OPTION_CREATE_LINK = 0x0002; // They key is a symbolic link
+ internal const int REG_OPTION_BACKUP_RESTORE = 0x0004; // Use SE_BACKUP_NAME process special privileges
+ internal const int REG_NONE = 0; // No value type
+ internal const int REG_SZ = 1; // Unicode nul terminated string
+ internal const int REG_EXPAND_SZ = 2; // Unicode nul terminated string
+ // (with environment variable references)
+ internal const int REG_BINARY = 3; // Free form binary
+ internal const int REG_DWORD = 4; // 32-bit number
+ internal const int REG_DWORD_LITTLE_ENDIAN = 4; // 32-bit number (same as REG_DWORD)
+ internal const int REG_DWORD_BIG_ENDIAN = 5; // 32-bit number
+ internal const int REG_LINK = 6; // Symbolic Link (unicode)
+ internal const int REG_MULTI_SZ = 7; // Multiple Unicode strings
+ internal const int REG_RESOURCE_LIST = 8; // Resource list in the resource map
+ internal const int REG_FULL_RESOURCE_DESCRIPTOR = 9; // Resource list in the hardware description
+ internal const int REG_RESOURCE_REQUIREMENTS_LIST = 10;
+ internal const int REG_QWORD = 11; // 64-bit number
+
+ internal const int HWND_BROADCAST = 0xffff;
+ internal const int WM_SETTINGCHANGE = 0x001A;
+
+ // CryptProtectMemory and CryptUnprotectMemory.
+ internal const uint CRYPTPROTECTMEMORY_BLOCK_SIZE = 16;
+ internal const uint CRYPTPROTECTMEMORY_SAME_PROCESS = 0x00;
+ internal const uint CRYPTPROTECTMEMORY_CROSS_PROCESS = 0x01;
+ internal const uint CRYPTPROTECTMEMORY_SAME_LOGON = 0x02;
+
+ // Security Quality of Service flags
+ internal const int SECURITY_ANONYMOUS = ((int)SECURITY_IMPERSONATION_LEVEL.Anonymous << 16);
+ internal const int SECURITY_SQOS_PRESENT = 0x00100000;
+
+ // Access Control library.
+ internal const string MICROSOFT_KERBEROS_NAME = "Kerberos";
+ internal const uint ANONYMOUS_LOGON_LUID = 0x3e6;
+
+ internal const int SECURITY_ANONYMOUS_LOGON_RID = 0x00000007;
+ internal const int SECURITY_AUTHENTICATED_USER_RID = 0x0000000B;
+ internal const int SECURITY_LOCAL_SYSTEM_RID = 0x00000012;
+ internal const int SECURITY_BUILTIN_DOMAIN_RID = 0x00000020;
+
+ internal const uint SE_PRIVILEGE_DISABLED = 0x00000000;
+ internal const uint SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001;
+ internal const uint SE_PRIVILEGE_ENABLED = 0x00000002;
+ internal const uint SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000;
+
+ internal const uint SE_GROUP_MANDATORY = 0x00000001;
+ internal const uint SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002;
+ internal const uint SE_GROUP_ENABLED = 0x00000004;
+ internal const uint SE_GROUP_OWNER = 0x00000008;
+ internal const uint SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010;
+ internal const uint SE_GROUP_LOGON_ID = 0xC0000000;
+ internal const uint SE_GROUP_RESOURCE = 0x20000000;
+
+ internal const uint DUPLICATE_CLOSE_SOURCE = 0x00000001;
+ internal const uint DUPLICATE_SAME_ACCESS = 0x00000002;
+ internal const uint DUPLICATE_SAME_ATTRIBUTES = 0x00000004;
+
+ // TimeZone
+ internal const int TIME_ZONE_ID_INVALID = -1;
+ internal const int TIME_ZONE_ID_UNKNOWN = 0;
+ internal const int TIME_ZONE_ID_STANDARD = 1;
+ internal const int TIME_ZONE_ID_DAYLIGHT = 2;
+ internal const int MAX_PATH = 260;
+
+ internal const int MUI_LANGUAGE_ID = 0x4;
+ internal const int MUI_LANGUAGE_NAME = 0x8;
+ internal const int MUI_PREFERRED_UI_LANGUAGES = 0x10;
+ internal const int MUI_INSTALLED_LANGUAGES = 0x20;
+ internal const int MUI_ALL_LANGUAGES = 0x40;
+ internal const int MUI_LANG_NEUTRAL_PE_FILE = 0x100;
+ internal const int MUI_NON_LANG_NEUTRAL_FILE = 0x200;
+
+ internal const int LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
+ internal const int LOAD_STRING_MAX_LENGTH = 500;
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SystemTime {
+ [MarshalAs(UnmanagedType.U2)]
+ public short Year;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Month;
+ [MarshalAs(UnmanagedType.U2)]
+ public short DayOfWeek;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Day;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Hour;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Minute;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Second;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Milliseconds;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal struct TimeZoneInformation {
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 Bias;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string StandardName;
+ public SystemTime StandardDate;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 StandardBias;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string DaylightName;
+ public SystemTime DaylightDate;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 DaylightBias;
+
+ public TimeZoneInformation(Win32Native.DynamicTimeZoneInformation dtzi) {
+ Bias = dtzi.Bias;
+ StandardName = dtzi.StandardName;
+ StandardDate = dtzi.StandardDate;
+ StandardBias = dtzi.StandardBias;
+ DaylightName = dtzi.DaylightName;
+ DaylightDate = dtzi.DaylightDate;
+ DaylightBias = dtzi.DaylightBias;
+ }
+ }
+
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal struct DynamicTimeZoneInformation {
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 Bias;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string StandardName;
+ public SystemTime StandardDate;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 StandardBias;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string DaylightName;
+ public SystemTime DaylightDate;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 DaylightBias;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
+ public string TimeZoneKeyName;
+ [MarshalAs(UnmanagedType.Bool)]
+ public bool DynamicDaylightTimeDisabled;
+ }
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct RegistryTimeZoneInformation {
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 Bias;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 StandardBias;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 DaylightBias;
+ public SystemTime StandardDate;
+ public SystemTime DaylightDate;
+
+ public RegistryTimeZoneInformation(Win32Native.TimeZoneInformation tzi) {
+ Bias = tzi.Bias;
+ StandardDate = tzi.StandardDate;
+ StandardBias = tzi.StandardBias;
+ DaylightDate = tzi.DaylightDate;
+ DaylightBias = tzi.DaylightBias;
+ }
+
+ public RegistryTimeZoneInformation(Byte[] bytes) {
+ //
+ // typedef struct _REG_TZI_FORMAT {
+ // [00-03] LONG Bias;
+ // [04-07] LONG StandardBias;
+ // [08-11] LONG DaylightBias;
+ // [12-27] SYSTEMTIME StandardDate;
+ // [12-13] WORD wYear;
+ // [14-15] WORD wMonth;
+ // [16-17] WORD wDayOfWeek;
+ // [18-19] WORD wDay;
+ // [20-21] WORD wHour;
+ // [22-23] WORD wMinute;
+ // [24-25] WORD wSecond;
+ // [26-27] WORD wMilliseconds;
+ // [28-43] SYSTEMTIME DaylightDate;
+ // [28-29] WORD wYear;
+ // [30-31] WORD wMonth;
+ // [32-33] WORD wDayOfWeek;
+ // [34-35] WORD wDay;
+ // [36-37] WORD wHour;
+ // [38-39] WORD wMinute;
+ // [40-41] WORD wSecond;
+ // [42-43] WORD wMilliseconds;
+ // } REG_TZI_FORMAT;
+ //
+ if (bytes == null || bytes.Length != 44) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidREG_TZI_FORMAT"), "bytes");
+ }
+ Bias = BitConverter.ToInt32(bytes, 0);
+ StandardBias = BitConverter.ToInt32(bytes, 4);
+ DaylightBias = BitConverter.ToInt32(bytes, 8);
+
+ StandardDate.Year = BitConverter.ToInt16(bytes, 12);
+ StandardDate.Month = BitConverter.ToInt16(bytes, 14);
+ StandardDate.DayOfWeek = BitConverter.ToInt16(bytes, 16);
+ StandardDate.Day = BitConverter.ToInt16(bytes, 18);
+ StandardDate.Hour = BitConverter.ToInt16(bytes, 20);
+ StandardDate.Minute = BitConverter.ToInt16(bytes, 22);
+ StandardDate.Second = BitConverter.ToInt16(bytes, 24);
+ StandardDate.Milliseconds = BitConverter.ToInt16(bytes, 26);
+
+ DaylightDate.Year = BitConverter.ToInt16(bytes, 28);
+ DaylightDate.Month = BitConverter.ToInt16(bytes, 30);
+ DaylightDate.DayOfWeek = BitConverter.ToInt16(bytes, 32);
+ DaylightDate.Day = BitConverter.ToInt16(bytes, 34);
+ DaylightDate.Hour = BitConverter.ToInt16(bytes, 36);
+ DaylightDate.Minute = BitConverter.ToInt16(bytes, 38);
+ DaylightDate.Second = BitConverter.ToInt16(bytes, 40);
+ DaylightDate.Milliseconds = BitConverter.ToInt16(bytes, 42);
+ }
+ }
+
+ // end of TimeZone
+
+
+ // Win32 ACL-related constants:
+ internal const int READ_CONTROL = 0x00020000;
+ internal const int SYNCHRONIZE = 0x00100000;
+
+ internal const int STANDARD_RIGHTS_READ = READ_CONTROL;
+ internal const int STANDARD_RIGHTS_WRITE = READ_CONTROL;
+
+ // STANDARD_RIGHTS_REQUIRED (0x000F0000L)
+ // SEMAPHORE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
+
+ // SEMAPHORE and Event both use 0x0002
+ // MUTEX uses 0x001 (MUTANT_QUERY_STATE)
+
+ // Note that you may need to specify the SYNCHRONIZE bit as well
+ // to be able to open a synchronization primitive.
+ internal const int SEMAPHORE_MODIFY_STATE = 0x00000002;
+ internal const int EVENT_MODIFY_STATE = 0x00000002;
+ internal const int MUTEX_MODIFY_STATE = 0x00000001;
+ internal const int MUTEX_ALL_ACCESS = 0x001F0001;
+
+
+ internal const int LMEM_FIXED = 0x0000;
+ internal const int LMEM_ZEROINIT = 0x0040;
+ internal const int LPTR = (LMEM_FIXED | LMEM_ZEROINIT);
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ internal class OSVERSIONINFO {
+ internal OSVERSIONINFO() {
+ OSVersionInfoSize = (int)Marshal.SizeOf(this);
+ }
+
+ // The OSVersionInfoSize field must be set to Marshal.SizeOf(this)
+ internal int OSVersionInfoSize = 0;
+ internal int MajorVersion = 0;
+ internal int MinorVersion = 0;
+ internal int BuildNumber = 0;
+ internal int PlatformId = 0;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
+ internal String CSDVersion = null;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ internal class OSVERSIONINFOEX {
+
+ public OSVERSIONINFOEX() {
+ OSVersionInfoSize = (int)Marshal.SizeOf(this);
+ }
+
+ // The OSVersionInfoSize field must be set to Marshal.SizeOf(this)
+ internal int OSVersionInfoSize = 0;
+ internal int MajorVersion = 0;
+ internal int MinorVersion = 0;
+ internal int BuildNumber = 0;
+ internal int PlatformId = 0;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
+ internal string CSDVersion = null;
+ internal ushort ServicePackMajor = 0;
+ internal ushort ServicePackMinor = 0;
+ internal short SuiteMask = 0;
+ internal byte ProductType = 0;
+ internal byte Reserved = 0;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SYSTEM_INFO {
+ internal int dwOemId; // This is a union of a DWORD and a struct containing 2 WORDs.
+ internal int dwPageSize;
+ internal IntPtr lpMinimumApplicationAddress;
+ internal IntPtr lpMaximumApplicationAddress;
+ internal IntPtr dwActiveProcessorMask;
+ internal int dwNumberOfProcessors;
+ internal int dwProcessorType;
+ internal int dwAllocationGranularity;
+ internal short wProcessorLevel;
+ internal short wProcessorRevision;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal class SECURITY_ATTRIBUTES {
+ internal int nLength = 0;
+ // don't remove null, or this field will disappear in bcl.small
+ internal unsafe byte * pSecurityDescriptor = null;
+ internal int bInheritHandle = 0;
+ }
+
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct WIN32_FILE_ATTRIBUTE_DATA {
+ internal int fileAttributes;
+ internal uint ftCreationTimeLow;
+ internal uint ftCreationTimeHigh;
+ internal uint ftLastAccessTimeLow;
+ internal uint ftLastAccessTimeHigh;
+ internal uint ftLastWriteTimeLow;
+ internal uint ftLastWriteTimeHigh;
+ internal int fileSizeHigh;
+ internal int fileSizeLow;
+
+ [System.Security.SecurityCritical]
+ internal void PopulateFrom(WIN32_FIND_DATA findData) {
+ // Copy the information to data
+ fileAttributes = findData.dwFileAttributes;
+ ftCreationTimeLow = findData.ftCreationTime_dwLowDateTime;
+ ftCreationTimeHigh = findData.ftCreationTime_dwHighDateTime;
+ ftLastAccessTimeLow = findData.ftLastAccessTime_dwLowDateTime;
+ ftLastAccessTimeHigh = findData.ftLastAccessTime_dwHighDateTime;
+ ftLastWriteTimeLow = findData.ftLastWriteTime_dwLowDateTime;
+ ftLastWriteTimeHigh = findData.ftLastWriteTime_dwHighDateTime;
+ fileSizeHigh = findData.nFileSizeHigh;
+ fileSizeLow = findData.nFileSizeLow;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct FILE_TIME {
+ public FILE_TIME(long fileTime) {
+ ftTimeLow = (uint) fileTime;
+ ftTimeHigh = (uint) (fileTime >> 32);
+ }
+
+ public long ToTicks() {
+ return ((long) ftTimeHigh << 32) + ftTimeLow;
+ }
+
+ internal uint ftTimeLow;
+ internal uint ftTimeHigh;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct KERB_S4U_LOGON {
+ internal uint MessageType;
+ internal uint Flags;
+ internal UNICODE_INTPTR_STRING ClientUpn; // REQUIRED: UPN for client
+ internal UNICODE_INTPTR_STRING ClientRealm; // Optional: Client Realm, if known
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct LSA_OBJECT_ATTRIBUTES {
+ internal int Length;
+ internal IntPtr RootDirectory;
+ internal IntPtr ObjectName;
+ internal int Attributes;
+ internal IntPtr SecurityDescriptor;
+ internal IntPtr SecurityQualityOfService;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct UNICODE_STRING {
+ internal ushort Length;
+ internal ushort MaximumLength;
+ [MarshalAs(UnmanagedType.LPWStr)] internal string Buffer;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct UNICODE_INTPTR_STRING {
+ /// <remarks>
+ /// Note - this constructor extracts the raw pointer from the safe handle, so any
+ /// strings created with this version of the constructor will be unsafe to use after the buffer
+ /// has been freed.
+ /// </remarks>
+ [System.Security.SecurityCritical] // auto-generated
+ internal UNICODE_INTPTR_STRING (int stringBytes, SafeLocalAllocHandle buffer) {
+ BCLDebug.Assert(buffer == null || (stringBytes >= 0 && (ulong)stringBytes <= buffer.ByteLength),
+ "buffer == null || (stringBytes >= 0 && stringBytes <= buffer.ByteLength)");
+
+ this.Length = (ushort) stringBytes;
+ this.MaxLength = (ushort) buffer.ByteLength;
+
+ // Marshaling with a SafePointer does not work correctly, so unfortunately we need to extract
+ // the raw handle here.
+ this.Buffer = buffer.DangerousGetHandle();
+ }
+
+ /// <remarks>
+ /// This constructor should be used for constructing UNICODE_STRING structures with pointers
+ /// into a block of memory managed by a SafeHandle or the GC. It shouldn't be used to own
+ /// any memory on its own.
+ /// </remarks>
+ internal UNICODE_INTPTR_STRING(int stringBytes, IntPtr buffer) {
+ BCLDebug.Assert((stringBytes == 0 && buffer == IntPtr.Zero) || (stringBytes > 0 && stringBytes <= UInt16.MaxValue && buffer != IntPtr.Zero),
+ "(stringBytes == 0 && buffer == IntPtr.Zero) || (stringBytes > 0 && stringBytes <= UInt16.MaxValue && buffer != IntPtr.Zero)");
+
+ this.Length = (ushort)stringBytes;
+ this.MaxLength = (ushort)stringBytes;
+ this.Buffer = buffer;
+ }
+
+ internal ushort Length;
+ internal ushort MaxLength;
+ internal IntPtr Buffer;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct LSA_TRANSLATED_NAME {
+ internal int Use;
+ internal UNICODE_INTPTR_STRING Name;
+ internal int DomainIndex;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct LSA_TRANSLATED_SID {
+ internal int Use;
+ internal uint Rid;
+ internal int DomainIndex;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct LSA_TRANSLATED_SID2 {
+ internal int Use;
+ internal IntPtr Sid;
+ internal int DomainIndex;
+ uint Flags;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct LSA_TRUST_INFORMATION {
+ internal UNICODE_INTPTR_STRING Name;
+ internal IntPtr Sid;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct LSA_REFERENCED_DOMAIN_LIST {
+ internal int Entries;
+ internal IntPtr Domains;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct LUID {
+ internal uint LowPart;
+ internal uint HighPart;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct LUID_AND_ATTRIBUTES {
+ internal LUID Luid;
+ internal uint Attributes;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct QUOTA_LIMITS {
+ internal IntPtr PagedPoolLimit;
+ internal IntPtr NonPagedPoolLimit;
+ internal IntPtr MinimumWorkingSetSize;
+ internal IntPtr MaximumWorkingSetSize;
+ internal IntPtr PagefileLimit;
+ internal IntPtr TimeLimit;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct SECURITY_LOGON_SESSION_DATA {
+ internal uint Size;
+ internal LUID LogonId;
+ internal UNICODE_INTPTR_STRING UserName;
+ internal UNICODE_INTPTR_STRING LogonDomain;
+ internal UNICODE_INTPTR_STRING AuthenticationPackage;
+ internal uint LogonType;
+ internal uint Session;
+ internal IntPtr Sid;
+ internal long LogonTime;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct SID_AND_ATTRIBUTES {
+ internal IntPtr Sid;
+ internal uint Attributes;
+ internal static readonly long SizeOf = (long)Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct TOKEN_GROUPS {
+ internal uint GroupCount;
+ internal SID_AND_ATTRIBUTES Groups; // SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY];
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal struct TOKEN_PRIMARY_GROUP
+ {
+ internal IntPtr PrimaryGroup;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct TOKEN_PRIVILEGE {
+ internal uint PrivilegeCount;
+ internal LUID_AND_ATTRIBUTES Privilege;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct TOKEN_SOURCE {
+ private const int TOKEN_SOURCE_LENGTH = 8;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst=TOKEN_SOURCE_LENGTH)]
+ internal char[] Name;
+ internal LUID SourceIdentifier;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct TOKEN_STATISTICS {
+ internal LUID TokenId;
+ internal LUID AuthenticationId;
+ internal long ExpirationTime;
+ internal uint TokenType;
+ internal uint ImpersonationLevel;
+ internal uint DynamicCharged;
+ internal uint DynamicAvailable;
+ internal uint GroupCount;
+ internal uint PrivilegeCount;
+ internal LUID ModifiedId;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct TOKEN_USER {
+ internal SID_AND_ATTRIBUTES User;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct MEMORYSTATUSEX {
+ // The length field must be set to the size of this data structure.
+ internal int length;
+ internal int memoryLoad;
+ internal ulong totalPhys;
+ internal ulong availPhys;
+ internal ulong totalPageFile;
+ internal ulong availPageFile;
+ internal ulong totalVirtual;
+ internal ulong availVirtual;
+ internal ulong availExtendedVirtual;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct MEMORY_BASIC_INFORMATION {
+ internal void* BaseAddress;
+ internal void* AllocationBase;
+ internal uint AllocationProtect;
+ internal UIntPtr RegionSize;
+ internal uint State;
+ internal uint Protect;
+ internal uint Type;
+ }
+
+#if !FEATURE_PAL
+ internal const String KERNEL32 = "kernel32.dll";
+ internal const String USER32 = "user32.dll";
+ internal const String OLE32 = "ole32.dll";
+ internal const String OLEAUT32 = "oleaut32.dll";
+ internal const String NTDLL = "ntdll.dll";
+#else //FEATURE_PAL
+ internal const String KERNEL32 = "libcoreclr";
+ internal const String USER32 = "libcoreclr";
+ internal const String OLE32 = "libcoreclr";
+ internal const String OLEAUT32 = "libcoreclr";
+ internal const String NTDLL = "libcoreclr";
+#endif //FEATURE_PAL
+ internal const String ADVAPI32 = "advapi32.dll";
+ internal const String SHELL32 = "shell32.dll";
+ internal const String SHIM = "mscoree.dll";
+ internal const String CRYPT32 = "crypt32.dll";
+ internal const String SECUR32 = "secur32.dll";
+#if FEATURE_MAIN_CLR_MODULE_USES_CORE_NAME
+ internal const String MSCORWKS = "coreclr.dll";
+#else //FEATURE_MAIN_CLR_MODULE_USES_CORE_NAME
+ internal const String MSCORWKS = "clr.dll";
+#endif //FEATURE_MAIN_CLR_MODULE_USES_CORE_NAME
+
+ // From WinBase.h
+ internal const int SEM_FAILCRITICALERRORS = 1;
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern void GetSystemInfo(ref SYSTEM_INFO lpSystemInfo);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, BestFitMapping=true)]
+ internal static extern int FormatMessage(int dwFlags, IntPtr lpSource,
+ int dwMessageId, int dwLanguageId, [Out]StringBuilder lpBuffer,
+ int nSize, IntPtr va_list_arguments);
+
+ // Gets an error message for a Win32 error code.
+ internal static String GetMessage(int errorCode) {
+ StringBuilder sb = StringBuilderCache.Acquire(512);
+ int result = Win32Native.FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ IntPtr.Zero, errorCode, 0, sb, sb.Capacity, IntPtr.Zero);
+ if (result != 0) {
+ // result is the # of characters copied to the StringBuilder.
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+ else {
+ StringBuilderCache.Release(sb);
+ return Environment.GetResourceString("UnknownError_Num", errorCode);
+ }
+ }
+
+ [DllImport(KERNEL32, EntryPoint="LocalAlloc")]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern IntPtr LocalAlloc_NoSafeHandle(int uFlags, UIntPtr sizetdwBytes);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ SafeLocalAllocHandle LocalAlloc(
+ [In] int uFlags,
+ [In] UIntPtr sizetdwBytes);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern IntPtr LocalFree(IntPtr handle);
+
+ // MSDN says the length is a SIZE_T.
+ [DllImport(NTDLL, EntryPoint = "RtlZeroMemory")]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern void ZeroMemory(IntPtr address, UIntPtr length);
+
+ internal static bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX buffer)
+ {
+ buffer.length = Marshal.SizeOf(typeof(MEMORYSTATUSEX));
+ return GlobalMemoryStatusExNative(ref buffer);
+ }
+
+ [DllImport(KERNEL32, SetLastError=true, EntryPoint="GlobalMemoryStatusEx")]
+ private static extern bool GlobalMemoryStatusExNative([In, Out] ref MEMORYSTATUSEX buffer);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ unsafe internal static extern UIntPtr VirtualQuery(void* address, ref MEMORY_BASIC_INFORMATION buffer, UIntPtr sizeOfBuffer);
+
+ // VirtualAlloc should generally be avoided, but is needed in
+ // the MemoryFailPoint implementation (within a CER) to increase the
+ // size of the page file, ignoring any host memory allocators.
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ unsafe internal static extern void * VirtualAlloc(void* address, UIntPtr numBytes, int commitOrReserve, int pageProtectionMode);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ unsafe internal static extern bool VirtualFree(void* address, UIntPtr numBytes, int pageFreeMode);
+
+
+
+ // Note - do NOT use this to call methods. Use P/Invoke, which will
+ // do much better things w.r.t. marshaling, pinning memory, security
+ // stuff, better interactions with thread aborts, etc. This is used
+ // solely by DoesWin32MethodExist for avoiding try/catch EntryPointNotFoundException
+ // in scenarios where an OS Version check is insufficient
+ [DllImport(KERNEL32, CharSet=CharSet.Ansi, BestFitMapping=false, SetLastError=true, ExactSpelling=true)]
+ private static extern IntPtr GetProcAddress(IntPtr hModule, String methodName);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, BestFitMapping=false, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private static extern IntPtr GetModuleHandle(String moduleName);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool DoesWin32MethodExist(String moduleName, String methodName)
+ {
+ // GetModuleHandle does not increment the module's ref count, so we don't need to call FreeLibrary.
+ IntPtr hModule = Win32Native.GetModuleHandle(moduleName);
+ if (hModule == IntPtr.Zero) {
+ BCLDebug.Assert(hModule != IntPtr.Zero, "GetModuleHandle failed. Dll isn't loaded?");
+ return false;
+ }
+ IntPtr functionPointer = Win32Native.GetProcAddress(hModule, methodName);
+ return (functionPointer != IntPtr.Zero);
+ }
+
+ // There is no need to call CloseProcess or to use a SafeHandle if you get the handle
+ // using GetCurrentProcess as it returns a pseudohandle
+ [DllImport(KERNEL32, SetLastError = true, CallingConvention = CallingConvention.Winapi)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool IsWow64Process(
+ [In]
+ IntPtr hSourceProcessHandle,
+ [Out, MarshalAs(UnmanagedType.Bool)]
+ out bool isWow64);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern uint GetTempPath(int bufferLen, [Out]StringBuilder buffer);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Ansi, ExactSpelling=true, EntryPoint="lstrlenA")]
+ internal static extern int lstrlenA(IntPtr ptr);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode, ExactSpelling=true, EntryPoint="lstrlenW")]
+ internal static extern int lstrlenW(IntPtr ptr);
+
+ [DllImport(Win32Native.OLEAUT32, CharSet = CharSet.Unicode)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern IntPtr SysAllocStringLen(String src, int len); // BSTR
+
+ [DllImport(Win32Native.OLEAUT32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern uint SysStringLen(IntPtr bstr);
+
+ [DllImport(Win32Native.OLEAUT32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern void SysFreeString(IntPtr bstr);
+
+#if FEATURE_COMINTEROP
+ [DllImport(Win32Native.OLEAUT32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern IntPtr SysAllocStringByteLen(byte[] str, uint len); // BSTR
+
+ [DllImport(Win32Native.OLEAUT32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern uint SysStringByteLen(IntPtr bstr);
+
+#if FEATURE_LEGACYSURFACE
+ [DllImport(Win32Native.OLEAUT32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern uint SysStringLen(SafeBSTRHandle bstr);
+#endif
+
+#endif
+
+ [DllImport(KERNEL32)]
+ internal static extern int GetACP();
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetEvent(SafeWaitHandle handle);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool ResetEvent(SafeWaitHandle handle);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern SafeWaitHandle CreateEvent(SECURITY_ATTRIBUTES lpSecurityAttributes, bool isManualReset, bool initialState, String name);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern SafeWaitHandle OpenEvent(/* DWORD */ int desiredAccess, bool inheritHandle, String name);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern SafeWaitHandle CreateMutex(SECURITY_ATTRIBUTES lpSecurityAttributes, bool initialOwner, String name);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern SafeWaitHandle OpenMutex(/* DWORD */ int desiredAccess, bool inheritHandle, String name);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern bool ReleaseMutex(SafeWaitHandle handle);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal unsafe static extern int GetFullPathName(char* path, int numBufferChars, char* buffer, IntPtr mustBeZero);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal unsafe static extern int GetFullPathName(String path, int numBufferChars, [Out]StringBuilder buffer, IntPtr mustBeZero);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal unsafe static extern int GetLongPathName(char* path, char* longPathBuffer, int bufferLength);
+
+ [DllImport(KERNEL32, SetLastError = true, ExactSpelling = true)]
+ internal unsafe static extern uint GetFullPathNameW(char* path, uint numBufferChars, SafeHandle buffer, IntPtr mustBeZero);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern int GetLongPathName(String path, [Out]StringBuilder longPathBuffer, int bufferLength);
+
+ [DllImport(KERNEL32, SetLastError = true, ExactSpelling = true)]
+ internal static extern uint GetLongPathNameW(SafeHandle lpszShortPath, SafeHandle lpszLongPath, uint cchBuffer);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
+ internal static extern uint GetLongPathNameW(string lpszShortPath, SafeHandle lpszLongPath, uint cchBuffer);
+
+ // Disallow access to all non-file devices from methods that take
+ // a String. This disallows DOS devices like "con:", "com1:",
+ // "lpt1:", etc. Use this to avoid security problems, like allowing
+ // a web client asking a server for "http://server/com1.aspx" and
+ // then causing a worker process to hang.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static SafeFileHandle SafeCreateFile(String lpFileName,
+ int dwDesiredAccess, System.IO.FileShare dwShareMode,
+ SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition,
+ int dwFlagsAndAttributes, IntPtr hTemplateFile)
+ {
+ SafeFileHandle handle = CreateFile( lpFileName, dwDesiredAccess, dwShareMode,
+ securityAttrs, dwCreationDisposition,
+ dwFlagsAndAttributes, hTemplateFile );
+
+ if (!handle.IsInvalid)
+ {
+ int fileType = Win32Native.GetFileType(handle);
+ if (fileType != Win32Native.FILE_TYPE_DISK) {
+ handle.Dispose();
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FileStreamOnNonFiles"));
+ }
+ }
+
+ return handle;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static SafeFileHandle UnsafeCreateFile(String lpFileName,
+ int dwDesiredAccess, System.IO.FileShare dwShareMode,
+ SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition,
+ int dwFlagsAndAttributes, IntPtr hTemplateFile)
+ {
+ SafeFileHandle handle = CreateFile( lpFileName, dwDesiredAccess, dwShareMode,
+ securityAttrs, dwCreationDisposition,
+ dwFlagsAndAttributes, hTemplateFile );
+
+ return handle;
+ }
+
+ // Do not use these directly, use the safe or unsafe versions above.
+ // The safe version does not support devices (aka if will only open
+ // files on disk), while the unsafe version give you the full semantic
+ // of the native version.
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ private static extern SafeFileHandle CreateFile(String lpFileName,
+ int dwDesiredAccess, System.IO.FileShare dwShareMode,
+ SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition,
+ int dwFlagsAndAttributes, IntPtr hTemplateFile);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern SafeFileMappingHandle CreateFileMapping(SafeFileHandle hFile, IntPtr lpAttributes, uint fProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, String lpName);
+
+ [DllImport(KERNEL32, SetLastError=true, ExactSpelling=true)]
+ internal static extern IntPtr MapViewOfFile(
+ SafeFileMappingHandle handle, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, UIntPtr dwNumerOfBytesToMap);
+
+ [DllImport(KERNEL32, ExactSpelling=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool UnmapViewOfFile(IntPtr lpBaseAddress );
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool CloseHandle(IntPtr handle);
+
+ [DllImport(KERNEL32)]
+ internal static extern int GetFileType(SafeFileHandle handle);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetEndOfFile(SafeFileHandle hFile);
+
+ [DllImport(KERNEL32, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool FlushFileBuffers(SafeFileHandle hFile);
+
+ [DllImport(KERNEL32, SetLastError=true, EntryPoint="SetFilePointer")]
+ private unsafe static extern int SetFilePointerWin32(SafeFileHandle handle, int lo, int * hi, int origin);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static long SetFilePointer(SafeFileHandle handle, long offset, System.IO.SeekOrigin origin, out int hr) {
+ hr = 0;
+ int lo = (int) offset;
+ int hi = (int) (offset >> 32);
+ lo = SetFilePointerWin32(handle, lo, &hi, (int) origin);
+
+ if (lo == -1 && ((hr = Marshal.GetLastWin32Error()) != 0))
+ return -1;
+ return (long) (((ulong) ((uint) hi)) << 32) | ((uint) lo);
+ }
+
+ // Note there are two different ReadFile prototypes - this is to use
+ // the type system to force you to not trip across a "feature" in
+ // Win32's async IO support. You can't do the following three things
+ // simultaneously: overlapped IO, free the memory for the overlapped
+ // struct in a callback (or an EndRead method called by that callback),
+ // and pass in an address for the numBytesRead parameter.
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ unsafe internal static extern int ReadFile(SafeFileHandle handle, byte* bytes, int numBytesToRead, IntPtr numBytesRead_mustBeZero, NativeOverlapped* overlapped);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ unsafe internal static extern int ReadFile(SafeFileHandle handle, byte* bytes, int numBytesToRead, out int numBytesRead, IntPtr mustBeZero);
+
+ // Note there are two different WriteFile prototypes - this is to use
+ // the type system to force you to not trip across a "feature" in
+ // Win32's async IO support. You can't do the following three things
+ // simultaneously: overlapped IO, free the memory for the overlapped
+ // struct in a callback (or an EndWrite method called by that callback),
+ // and pass in an address for the numBytesRead parameter.
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern int WriteFile(SafeFileHandle handle, byte* bytes, int numBytesToWrite, IntPtr numBytesWritten_mustBeZero, NativeOverlapped* lpOverlapped);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern int WriteFile(SafeFileHandle handle, byte* bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero);
+
+ // This is only available on Vista or higher
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern bool CancelIoEx(SafeFileHandle handle, NativeOverlapped* lpOverlapped);
+
+ // NOTE: The out parameters are PULARGE_INTEGERs and may require
+ // some byte munging magic.
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern bool GetDiskFreeSpaceEx(String drive, out long freeBytesForUser, out long totalBytes, out long freeBytes);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern int GetDriveType(String drive);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern bool GetVolumeInformation(String drive, [Out]StringBuilder volumeName, int volumeNameBufLen, out int volSerialNumber, out int maxFileNameLen, out int fileSystemFlags, [Out]StringBuilder fileSystemName, int fileSystemNameBufLen);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern bool SetVolumeLabel(String driveLetter, String volumeName);
+
+ // The following 4 methods are used by Microsoft.WlcProfile
+ [DllImport(KERNEL32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool QueryPerformanceCounter(out long value);
+
+ [DllImport(KERNEL32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool QueryPerformanceFrequency(out long value);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern SafeWaitHandle CreateSemaphore(SECURITY_ATTRIBUTES lpSecurityAttributes, int initialCount, int maximumCount, String name);
+
+ [DllImport(KERNEL32, SetLastError = true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool ReleaseSemaphore(SafeWaitHandle handle, int releaseCount, out int previousCount);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern SafeWaitHandle OpenSemaphore(/* DWORD */ int desiredAccess, bool inheritHandle, String name);
+
+ // Will be in winnls.h
+ internal const int FIND_STARTSWITH = 0x00100000; // see if value is at the beginning of source
+ internal const int FIND_ENDSWITH = 0x00200000; // see if value is at the end of source
+ internal const int FIND_FROMSTART = 0x00400000; // look for value in source, starting at the beginning
+ internal const int FIND_FROMEND = 0x00800000; // look for value in source, starting at the end
+
+#if !FEATURE_CORECLR
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct NlsVersionInfoEx
+ {
+ internal int dwNLSVersionInfoSize;
+ internal int dwNLSVersion;
+ internal int dwDefinedVersion;
+ internal int dwEffectiveId;
+ internal Guid guidCustomVersion;
+ }
+#endif
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern int GetWindowsDirectory([Out]StringBuilder sb, int length);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern int GetSystemDirectory([Out]StringBuilder sb, int length);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal unsafe static extern bool SetFileTime(SafeFileHandle hFile, FILE_TIME* creationTime,
+ FILE_TIME* lastAccessTime, FILE_TIME* lastWriteTime);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern int GetFileSize(SafeFileHandle hFile, out int highSize);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool LockFile(SafeFileHandle handle, int offsetLow, int offsetHigh, int countLow, int countHigh);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool UnlockFile(SafeFileHandle handle, int offsetLow, int offsetHigh, int countLow, int countHigh);
+
+ internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); // WinBase.h
+
+ // Note, these are #defines used to extract handles, and are NOT handles.
+ internal const int STD_INPUT_HANDLE = -10;
+ internal const int STD_OUTPUT_HANDLE = -11;
+ internal const int STD_ERROR_HANDLE = -12;
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern IntPtr GetStdHandle(int nStdHandle); // param is NOT a handle, but it returns one!
+
+ // From wincon.h
+ internal const int CTRL_C_EVENT = 0;
+ internal const int CTRL_BREAK_EVENT = 1;
+ internal const int CTRL_CLOSE_EVENT = 2;
+ internal const int CTRL_LOGOFF_EVENT = 5;
+ internal const int CTRL_SHUTDOWN_EVENT = 6;
+ internal const short KEY_EVENT = 1;
+
+ // From WinBase.h
+ internal const int FILE_TYPE_DISK = 0x0001;
+ internal const int FILE_TYPE_CHAR = 0x0002;
+ internal const int FILE_TYPE_PIPE = 0x0003;
+
+ internal const int REPLACEFILE_WRITE_THROUGH = 0x1;
+ internal const int REPLACEFILE_IGNORE_MERGE_ERRORS = 0x2;
+
+ private const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
+ private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
+ private const int FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000;
+
+ internal const uint FILE_MAP_WRITE = 0x0002;
+ internal const uint FILE_MAP_READ = 0x0004;
+
+ // Constants from WinNT.h
+ internal const int FILE_ATTRIBUTE_READONLY = 0x00000001;
+ internal const int FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
+ internal const int FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400;
+
+ internal const int IO_REPARSE_TAG_MOUNT_POINT = unchecked((int)0xA0000003);
+
+ internal const int PAGE_READWRITE = 0x04;
+
+ internal const int MEM_COMMIT = 0x1000;
+ internal const int MEM_RESERVE = 0x2000;
+ internal const int MEM_RELEASE = 0x8000;
+ internal const int MEM_FREE = 0x10000;
+
+ // Error codes from WinError.h
+ internal const int ERROR_SUCCESS = 0x0;
+ internal const int ERROR_INVALID_FUNCTION = 0x1;
+ internal const int ERROR_FILE_NOT_FOUND = 0x2;
+ internal const int ERROR_PATH_NOT_FOUND = 0x3;
+ internal const int ERROR_ACCESS_DENIED = 0x5;
+ internal const int ERROR_INVALID_HANDLE = 0x6;
+ internal const int ERROR_NOT_ENOUGH_MEMORY = 0x8;
+ internal const int ERROR_INVALID_DATA = 0xd;
+ internal const int ERROR_INVALID_DRIVE = 0xf;
+ internal const int ERROR_NO_MORE_FILES = 0x12;
+ internal const int ERROR_NOT_READY = 0x15;
+ internal const int ERROR_BAD_LENGTH = 0x18;
+ internal const int ERROR_SHARING_VIOLATION = 0x20;
+ internal const int ERROR_NOT_SUPPORTED = 0x32;
+ internal const int ERROR_FILE_EXISTS = 0x50;
+ internal const int ERROR_INVALID_PARAMETER = 0x57;
+ internal const int ERROR_BROKEN_PIPE = 0x6D;
+ internal const int ERROR_CALL_NOT_IMPLEMENTED = 0x78;
+ internal const int ERROR_INSUFFICIENT_BUFFER = 0x7A;
+ internal const int ERROR_INVALID_NAME = 0x7B;
+ internal const int ERROR_BAD_PATHNAME = 0xA1;
+ internal const int ERROR_ALREADY_EXISTS = 0xB7;
+ internal const int ERROR_ENVVAR_NOT_FOUND = 0xCB;
+ internal const int ERROR_FILENAME_EXCED_RANGE = 0xCE; // filename too long.
+ internal const int ERROR_NO_DATA = 0xE8;
+ internal const int ERROR_PIPE_NOT_CONNECTED = 0xE9;
+ internal const int ERROR_MORE_DATA = 0xEA;
+ internal const int ERROR_DIRECTORY = 0x10B;
+ internal const int ERROR_OPERATION_ABORTED = 0x3E3; // 995; For IO Cancellation
+ internal const int ERROR_NOT_FOUND = 0x490; // 1168; For IO Cancellation
+ internal const int ERROR_NO_TOKEN = 0x3f0;
+ internal const int ERROR_DLL_INIT_FAILED = 0x45A;
+ internal const int ERROR_NON_ACCOUNT_SID = 0x4E9;
+ internal const int ERROR_NOT_ALL_ASSIGNED = 0x514;
+ internal const int ERROR_UNKNOWN_REVISION = 0x519;
+ internal const int ERROR_INVALID_OWNER = 0x51B;
+ internal const int ERROR_INVALID_PRIMARY_GROUP = 0x51C;
+ internal const int ERROR_NO_SUCH_PRIVILEGE = 0x521;
+ internal const int ERROR_PRIVILEGE_NOT_HELD = 0x522;
+ internal const int ERROR_NONE_MAPPED = 0x534;
+ internal const int ERROR_INVALID_ACL = 0x538;
+ internal const int ERROR_INVALID_SID = 0x539;
+ internal const int ERROR_INVALID_SECURITY_DESCR = 0x53A;
+ internal const int ERROR_BAD_IMPERSONATION_LEVEL = 0x542;
+ internal const int ERROR_CANT_OPEN_ANONYMOUS = 0x543;
+ internal const int ERROR_NO_SECURITY_ON_OBJECT = 0x546;
+ internal const int ERROR_TRUSTED_RELATIONSHIP_FAILURE = 0x6FD;
+
+ // Error codes from ntstatus.h
+ internal const uint STATUS_SUCCESS = 0x00000000;
+ internal const uint STATUS_SOME_NOT_MAPPED = 0x00000107;
+ internal const uint STATUS_NO_MEMORY = 0xC0000017;
+ internal const uint STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034;
+ internal const uint STATUS_NONE_MAPPED = 0xC0000073;
+ internal const uint STATUS_INSUFFICIENT_RESOURCES = 0xC000009A;
+ internal const uint STATUS_ACCESS_DENIED = 0xC0000022;
+
+ internal const int INVALID_FILE_SIZE = -1;
+
+ // From WinStatus.h
+ internal const int STATUS_ACCOUNT_RESTRICTION = unchecked((int) 0xC000006E);
+
+ // Use this to translate error codes like the above into HRESULTs like
+ // 0x80070006 for ERROR_INVALID_HANDLE
+ internal static int MakeHRFromErrorCode(int errorCode)
+ {
+ BCLDebug.Assert((0xFFFF0000 & errorCode) == 0, "This is an HRESULT, not an error code!");
+ return unchecked(((int)0x80070000) | errorCode);
+ }
+
+ // Win32 Structs in N/Direct style
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ [BestFitMapping(false)]
+ internal class WIN32_FIND_DATA {
+ internal int dwFileAttributes = 0;
+ // ftCreationTime was a by-value FILETIME structure
+ internal uint ftCreationTime_dwLowDateTime = 0 ;
+ internal uint ftCreationTime_dwHighDateTime = 0;
+ // ftLastAccessTime was a by-value FILETIME structure
+ internal uint ftLastAccessTime_dwLowDateTime = 0;
+ internal uint ftLastAccessTime_dwHighDateTime = 0;
+ // ftLastWriteTime was a by-value FILETIME structure
+ internal uint ftLastWriteTime_dwLowDateTime = 0;
+ internal uint ftLastWriteTime_dwHighDateTime = 0;
+ internal int nFileSizeHigh = 0;
+ internal int nFileSizeLow = 0;
+ // If the file attributes' reparse point flag is set, then
+ // dwReserved0 is the file tag (aka reparse tag) for the
+ // reparse point. Use this to figure out whether something is
+ // a volume mount point or a symbolic link.
+ internal int dwReserved0 = 0;
+ internal int dwReserved1 = 0;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)]
+ internal String cFileName = null;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst=14)]
+ internal String cAlternateFileName = null;
+ }
+
+#if FEATURE_CORESYSTEM
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ private static extern bool CopyFileEx(String src,
+ String dst,
+ IntPtr progressRoutine,
+ IntPtr progressData,
+ ref uint cancel,
+ uint flags);
+
+ internal static bool CopyFile(String src, String dst, bool failIfExists)
+ {
+ uint cancel = 0;
+ return CopyFileEx(src, dst, IntPtr.Zero, IntPtr.Zero, ref cancel, failIfExists ? 1U : 0U);
+ }
+#else // FEATURE_CORESYSTEM
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool CopyFile(
+ String src, String dst, bool failIfExists);
+#endif // FEATURE_CORESYSTEM
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool CreateDirectory(
+ String path, SECURITY_ATTRIBUTES lpSecurityAttributes);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool DeleteFile(String path);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool ReplaceFile(String replacedFileName, String replacementFileName, String backupFileName, int dwReplaceFlags, IntPtr lpExclude, IntPtr lpReserved);
+
+ [DllImport(ADVAPI32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool DecryptFile(String path, int reservedMustBeZero);
+
+ [DllImport(ADVAPI32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool EncryptFile(String path);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern SafeFindHandle FindFirstFile(String fileName, [In, Out] Win32Native.WIN32_FIND_DATA data);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool FindNextFile(
+ SafeFindHandle hndFindFile,
+ [In, Out, MarshalAs(UnmanagedType.LPStruct)]
+ WIN32_FIND_DATA lpFindFileData);
+
+ [DllImport(KERNEL32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool FindClose(IntPtr handle);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int GetCurrentDirectory(
+ int nBufferLength,
+ [Out]StringBuilder lpBuffer);
+
+ [DllImport(KERNEL32, SetLastError = true, ExactSpelling = true)]
+ internal static extern uint GetCurrentDirectoryW(uint nBufferLength, SafeHandle lpBuffer);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool GetFileAttributesEx(String name, int fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool SetFileAttributes(String name, int attr);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern int GetLogicalDrives();
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern uint GetTempFileName(String tmpPath, String prefix, uint uniqueIdOrZero, [Out]StringBuilder tmpFileName);
+
+#if FEATURE_CORESYSTEM
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ private static extern bool MoveFileEx(String src, String dst, uint flags);
+
+ internal static bool MoveFile(String src, String dst)
+ {
+ return MoveFileEx(src, dst, 2 /* MOVEFILE_COPY_ALLOWED */);
+ }
+#else // FEATURE_CORESYSTEM
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool MoveFile(String src, String dst);
+#endif // FEATURE_CORESYSTEM
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool DeleteVolumeMountPoint(String mountPoint);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool RemoveDirectory(String path);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool SetCurrentDirectory(String path);
+
+ [DllImport(KERNEL32, SetLastError=false, EntryPoint="SetErrorMode", ExactSpelling=true)]
+ private static extern int SetErrorMode_VistaAndOlder(int newMode);
+
+ [DllImport(KERNEL32, SetLastError=true, EntryPoint="SetThreadErrorMode")]
+ private static extern bool SetErrorMode_Win7AndNewer(int newMode, out int oldMode);
+
+ // RTM versions of Win7 and Windows Server 2008 R2
+ private static readonly Version ThreadErrorModeMinOsVersion = new Version(6, 1, 7600);
+
+ // this method uses the thread-safe version of SetErrorMode on Windows 7 / Windows Server 2008 R2 operating systems.
+ internal static int SetErrorMode(int newMode)
+ {
+#if !FEATURE_CORESYSTEM // ARMSTUB
+ if (Environment.OSVersion.Version >= ThreadErrorModeMinOsVersion)
+ {
+ int oldMode;
+ SetErrorMode_Win7AndNewer(newMode, out oldMode);
+ return oldMode;
+ }
+#endif
+ return SetErrorMode_VistaAndOlder(newMode);
+ }
+
+ internal const int LCID_SUPPORTED = 0x00000002; // supported locale ids
+
+ [DllImport(KERNEL32)]
+ internal static extern unsafe int WideCharToMultiByte(uint cp, uint flags, char* pwzSource, int cchSource, byte* pbDestBuffer, int cbDestBuffer, IntPtr null1, IntPtr null2);
+
+ // A Win32 HandlerRoutine
+ internal delegate bool ConsoleCtrlHandlerRoutine(int controlType);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool SetConsoleCtrlHandler(ConsoleCtrlHandlerRoutine handler, bool addOrRemove);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern bool SetEnvironmentVariable(string lpName, string lpValue);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern int GetEnvironmentVariable(string lpName, [Out]StringBuilder lpValue, int size);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode)]
+ internal static unsafe extern char * GetEnvironmentStrings();
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode)]
+ internal static unsafe extern bool FreeEnvironmentStrings(char * pStrings);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern uint GetCurrentProcessId();
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto)]
+ internal static extern bool GetUserName([Out]StringBuilder lpBuffer, ref int nSize);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal extern static int GetComputerName([Out]StringBuilder nameBuffer, ref int bufferSize);
+
+ [DllImport(OLE32)]
+ internal extern static int CoCreateGuid(out Guid guid);
+
+ [DllImport(OLE32)]
+ internal static extern IntPtr CoTaskMemAlloc(UIntPtr cb);
+
+ [DllImport(OLE32)]
+ internal static extern void CoTaskMemFree(IntPtr ptr);
+
+ [DllImport(OLE32)]
+ internal static extern IntPtr CoTaskMemRealloc(IntPtr pv, UIntPtr cb);
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct COORD
+ {
+ internal short X;
+ internal short Y;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct SMALL_RECT
+ {
+ internal short Left;
+ internal short Top;
+ internal short Right;
+ internal short Bottom;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct CONSOLE_SCREEN_BUFFER_INFO
+ {
+ internal COORD dwSize;
+ internal COORD dwCursorPosition;
+ internal short wAttributes;
+ internal SMALL_RECT srWindow;
+ internal COORD dwMaximumWindowSize;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct CONSOLE_CURSOR_INFO
+ {
+ internal int dwSize;
+ internal bool bVisible;
+ }
+
+ // Win32's KEY_EVENT_RECORD
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ internal struct KeyEventRecord
+ {
+ internal bool keyDown;
+ internal short repeatCount;
+ internal short virtualKeyCode;
+ internal short virtualScanCode;
+ internal char uChar; // Union between WCHAR and ASCII char
+ internal int controlKeyState;
+ }
+
+ // Really, this is a union of KeyEventRecords and other types.
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ internal struct InputRecord
+ {
+ internal short eventType;
+ internal KeyEventRecord keyEvent;
+ // This struct is a union! Word alighment should take care of padding!
+ }
+
+[Serializable]
+ [Flags]
+ internal enum Color : short
+ {
+ Black = 0,
+ ForegroundBlue = 0x1,
+ ForegroundGreen = 0x2,
+ ForegroundRed = 0x4,
+ ForegroundYellow = 0x6,
+ ForegroundIntensity = 0x8,
+ BackgroundBlue = 0x10,
+ BackgroundGreen = 0x20,
+ BackgroundRed = 0x40,
+ BackgroundYellow = 0x60,
+ BackgroundIntensity = 0x80,
+
+ ForegroundMask = 0xf,
+ BackgroundMask = 0xf0,
+ ColorMask = 0xff
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct CHAR_INFO
+ {
+ ushort charData; // Union between WCHAR and ASCII char
+ short attributes;
+ }
+
+ internal const int ENABLE_PROCESSED_INPUT = 0x0001;
+ internal const int ENABLE_LINE_INPUT = 0x0002;
+ internal const int ENABLE_ECHO_INPUT = 0x0004;
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleMode(IntPtr hConsoleHandle, int mode);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool GetConsoleMode(IntPtr hConsoleHandle, out int mode);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool Beep(int frequency, int duration);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput,
+ out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleScreenBufferSize(IntPtr hConsoleOutput, COORD size);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern COORD GetLargestConsoleWindowSize(IntPtr hConsoleOutput);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern bool FillConsoleOutputCharacter(IntPtr hConsoleOutput,
+ char character, int nLength, COORD dwWriteCoord, out int pNumCharsWritten);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool FillConsoleOutputAttribute(IntPtr hConsoleOutput,
+ short wColorAttribute, int numCells, COORD startCoord, out int pNumBytesWritten);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern bool SetConsoleWindowInfo(IntPtr hConsoleOutput,
+ bool absolute, SMALL_RECT* consoleWindow);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleTextAttribute(IntPtr hConsoleOutput, short attributes);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleCursorPosition(IntPtr hConsoleOutput,
+ COORD cursorPosition);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool GetConsoleCursorInfo(IntPtr hConsoleOutput,
+ out CONSOLE_CURSOR_INFO cci);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleCursorInfo(IntPtr hConsoleOutput,
+ ref CONSOLE_CURSOR_INFO cci);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=true)]
+ internal static extern bool SetConsoleTitle(String title);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern bool ReadConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern bool PeekConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern bool ReadConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* pBuffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT readRegion);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode, SetLastError=true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static unsafe extern bool ReadConsoleW(SafeFileHandle hConsoleInput, Byte* lpBuffer, Int32 nNumberOfCharsToRead, out Int32 lpNumberOfCharsRead, IntPtr pInputControl);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern bool WriteConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* buffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT writeRegion);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode, SetLastError=true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static unsafe extern bool WriteConsoleW(SafeFileHandle hConsoleOutput, Byte* lpBuffer, Int32 nNumberOfCharsToWrite, out Int32 lpNumberOfCharsWritten, IntPtr lpReservedMustBeNull);
+
+ [DllImport(USER32)] // Appears to always succeed
+ internal static extern short GetKeyState(int virtualKeyCode);
+
+ [DllImport(KERNEL32, SetLastError=false)]
+ internal static extern uint GetConsoleCP();
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleCP(uint codePage);
+
+ [DllImport(KERNEL32, SetLastError=false)]
+ internal static extern uint GetConsoleOutputCP();
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleOutputCP(uint codePage);
+
+#if FEATURE_WIN32_REGISTRY
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegConnectRegistry(String machineName,
+ SafeRegistryHandle key, out SafeRegistryHandle result);
+
+ // Note: RegCreateKeyEx won't set the last error on failure - it returns
+ // an error code if it fails.
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegCreateKeyEx(SafeRegistryHandle hKey, String lpSubKey,
+ int Reserved, String lpClass, int dwOptions,
+ int samDesired, SECURITY_ATTRIBUTES lpSecurityAttributes,
+ out SafeRegistryHandle hkResult, out int lpdwDisposition);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegDeleteKey(SafeRegistryHandle hKey, String lpSubKey);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegDeleteKeyEx(SafeRegistryHandle hKey, String lpSubKey,
+ int samDesired, int Reserved);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegDeleteValue(SafeRegistryHandle hKey, String lpValueName);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal unsafe static extern int RegEnumKeyEx(SafeRegistryHandle hKey, int dwIndex,
+ char *lpName, ref int lpcbName, int[] lpReserved,
+ [Out]StringBuilder lpClass, int[] lpcbClass,
+ long[] lpftLastWriteTime);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal unsafe static extern int RegEnumValue(SafeRegistryHandle hKey, int dwIndex,
+ char *lpValueName, ref int lpcbValueName,
+ IntPtr lpReserved_MustBeZero, int[] lpType, byte[] lpData,
+ int[] lpcbData);
+
+
+ [DllImport(ADVAPI32)]
+ internal static extern int RegFlushKey(SafeRegistryHandle hKey);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegOpenKeyEx(SafeRegistryHandle hKey, String lpSubKey,
+ int ulOptions, int samDesired, out SafeRegistryHandle hkResult);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegOpenKeyEx(IntPtr hKey, String lpSubKey,
+ int ulOptions, int samDesired, out SafeRegistryHandle hkResult);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryInfoKey(SafeRegistryHandle hKey, [Out]StringBuilder lpClass,
+ int[] lpcbClass, IntPtr lpReserved_MustBeZero, ref int lpcSubKeys,
+ int[] lpcbMaxSubKeyLen, int[] lpcbMaxClassLen,
+ ref int lpcValues, int[] lpcbMaxValueNameLen,
+ int[] lpcbMaxValueLen, int[] lpcbSecurityDescriptor,
+ int[] lpftLastWriteTime);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, [Out] byte[] lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, ref int lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, ref long lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, [Out] char[] lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, [Out]StringBuilder lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegSetValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int Reserved, RegistryValueKind dwType, byte[] lpData, int cbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegSetValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int Reserved, RegistryValueKind dwType, ref int lpData, int cbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegSetValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int Reserved, RegistryValueKind dwType, ref long lpData, int cbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegSetValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int Reserved, RegistryValueKind dwType, String lpData, int cbData);
+#endif // FEATURE_WIN32_REGISTRY
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern int ExpandEnvironmentStrings(String lpSrc, [Out]StringBuilder lpDst, int nSize);
+
+ [DllImport(KERNEL32)]
+ internal static extern IntPtr LocalReAlloc(IntPtr handle, IntPtr sizetcbBytes, int uFlags);
+
+ internal const int SHGFP_TYPE_CURRENT = 0; // the current (user) folder path setting
+ internal const int UOI_FLAGS = 1;
+ internal const int WSF_VISIBLE = 1;
+
+ // .NET Framework 4.0 and newer - all versions of windows ||| \public\sdk\inc\shlobj.h
+ internal const int CSIDL_FLAG_CREATE = 0x8000; // force folder creation in SHGetFolderPath
+ internal const int CSIDL_FLAG_DONT_VERIFY = 0x4000; // return an unverified folder path
+ internal const int CSIDL_ADMINTOOLS = 0x0030; // <user name>\Start Menu\Programs\Administrative Tools
+ internal const int CSIDL_CDBURN_AREA = 0x003b; // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
+ internal const int CSIDL_COMMON_ADMINTOOLS = 0x002f; // All Users\Start Menu\Programs\Administrative Tools
+ internal const int CSIDL_COMMON_DOCUMENTS = 0x002e; // All Users\Documents
+ internal const int CSIDL_COMMON_MUSIC = 0x0035; // All Users\My Music
+ internal const int CSIDL_COMMON_OEM_LINKS = 0x003a; // Links to All Users OEM specific apps
+ internal const int CSIDL_COMMON_PICTURES = 0x0036; // All Users\My Pictures
+ internal const int CSIDL_COMMON_STARTMENU = 0x0016; // All Users\Start Menu
+ internal const int CSIDL_COMMON_PROGRAMS = 0X0017; // All Users\Start Menu\Programs
+ internal const int CSIDL_COMMON_STARTUP = 0x0018; // All Users\Startup
+ internal const int CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019; // All Users\Desktop
+ internal const int CSIDL_COMMON_TEMPLATES = 0x002d; // All Users\Templates
+ internal const int CSIDL_COMMON_VIDEO = 0x0037; // All Users\My Video
+ internal const int CSIDL_FONTS = 0x0014; // windows\fonts
+ internal const int CSIDL_MYVIDEO = 0x000e; // "My Videos" folder
+ internal const int CSIDL_NETHOOD = 0x0013; // %APPDATA%\Microsoft\Windows\Network Shortcuts
+ internal const int CSIDL_PRINTHOOD = 0x001b; // %APPDATA%\Microsoft\Windows\Printer Shortcuts
+ internal const int CSIDL_PROFILE = 0x0028; // %USERPROFILE% (%SystemDrive%\Users\%USERNAME%)
+ internal const int CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c; // x86 Program Files\Common on RISC
+ internal const int CSIDL_PROGRAM_FILESX86 = 0x002a; // x86 C:\Program Files on RISC
+ internal const int CSIDL_RESOURCES = 0x0038; // %windir%\Resources
+ internal const int CSIDL_RESOURCES_LOCALIZED = 0x0039; // %windir%\resources\0409 (code page)
+ internal const int CSIDL_SYSTEMX86 = 0x0029; // %windir%\system32
+ internal const int CSIDL_WINDOWS = 0x0024; // GetWindowsDirectory()
+
+ // .NET Framework 3.5 and earlier - all versions of windows
+ internal const int CSIDL_APPDATA = 0x001a;
+ internal const int CSIDL_COMMON_APPDATA = 0x0023;
+ internal const int CSIDL_LOCAL_APPDATA = 0x001c;
+ internal const int CSIDL_COOKIES = 0x0021;
+ internal const int CSIDL_FAVORITES = 0x0006;
+ internal const int CSIDL_HISTORY = 0x0022;
+ internal const int CSIDL_INTERNET_CACHE = 0x0020;
+ internal const int CSIDL_PROGRAMS = 0x0002;
+ internal const int CSIDL_RECENT = 0x0008;
+ internal const int CSIDL_SENDTO = 0x0009;
+ internal const int CSIDL_STARTMENU = 0x000b;
+ internal const int CSIDL_STARTUP = 0x0007;
+ internal const int CSIDL_SYSTEM = 0x0025;
+ internal const int CSIDL_TEMPLATES = 0x0015;
+ internal const int CSIDL_DESKTOPDIRECTORY = 0x0010;
+ internal const int CSIDL_PERSONAL = 0x0005;
+ internal const int CSIDL_PROGRAM_FILES = 0x0026;
+ internal const int CSIDL_PROGRAM_FILES_COMMON = 0x002b;
+ internal const int CSIDL_DESKTOP = 0x0000;
+ internal const int CSIDL_DRIVES = 0x0011;
+ internal const int CSIDL_MYMUSIC = 0x000d;
+ internal const int CSIDL_MYPICTURES = 0x0027;
+
+ [DllImport(SHELL32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, int dwFlags, [Out]StringBuilder lpszPath);
+
+ internal const int NameSamCompatible = 2;
+
+ [DllImport(SECUR32, CharSet=CharSet.Unicode, SetLastError=true)]
+ // Win32 return type is BOOLEAN (which is 1 byte and not BOOL which is 4bytes)
+ internal static extern byte GetUserNameEx(int format, [Out]StringBuilder domainName, ref uint domainNameLen);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern bool LookupAccountName(string machineName, string accountName, byte[] sid,
+ ref int sidLen, [Out]StringBuilder domainName, ref uint domainNameLen, out int peUse);
+
+ // Note: This returns a handle, but it shouldn't be closed. The Avalon
+ // team says CloseWindowStation would ignore this handle. So there
+ // isn't a lot of value to switching to SafeHandle here.
+ [DllImport(USER32, ExactSpelling=true)]
+ internal static extern IntPtr GetProcessWindowStation();
+
+ [DllImport(USER32, SetLastError=true)]
+ internal static extern bool GetUserObjectInformation(IntPtr hObj, int nIndex,
+ [MarshalAs(UnmanagedType.LPStruct)] USEROBJECTFLAGS pvBuffer, int nLength, ref int lpnLengthNeeded);
+
+ [DllImport(USER32, SetLastError=true, BestFitMapping=false)]
+ internal static extern IntPtr SendMessageTimeout(IntPtr hWnd, int Msg, IntPtr wParam, String lParam, uint fuFlags, uint uTimeout, IntPtr lpdwResult);
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal class USEROBJECTFLAGS {
+ internal int fInherit = 0;
+ internal int fReserved = 0;
+ internal int dwFlags = 0;
+ }
+
+ //
+ // DPAPI
+ //
+
+#if FEATURE_LEGACYSURFACE
+ //
+ // RtlEncryptMemory and RtlDecryptMemory are declared in the internal header file crypt.h.
+ // They were also recently declared in the public header file ntsecapi.h (in the Platform SDK as well as the current build of Server 2003).
+ // We use them instead of CryptProtectMemory and CryptUnprotectMemory because
+ // they are available in both WinXP and in Windows Server 2003.
+ //
+
+ [DllImport(Win32Native.ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern
+ int SystemFunction040 (
+ [In,Out] SafeBSTRHandle pDataIn,
+ [In] uint cbDataIn, // multiple of RTL_ENCRYPT_MEMORY_SIZE
+ [In] uint dwFlags);
+
+ [DllImport(Win32Native.ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ int SystemFunction041 (
+ [In,Out] SafeBSTRHandle pDataIn,
+ [In] uint cbDataIn, // multiple of RTL_ENCRYPT_MEMORY_SIZE
+ [In] uint dwFlags);
+#endif // FEATURE_LEGACYSURFACE
+
+#if FEATURE_CORECLR
+ [DllImport(NTDLL, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ int RtlNtStatusToDosError (
+ [In] int status);
+#else
+ // identical to RtlNtStatusToDosError, but we are in ask mode for desktop CLR
+ [DllImport(ADVAPI32, CharSet = CharSet.Unicode, SetLastError = true)]
+ internal static extern
+ int LsaNtStatusToWinError (
+ [In] int status);
+#endif
+ // Get the current FIPS policy setting on Vista and above
+ [DllImport("bcrypt.dll")]
+ internal static extern uint BCryptGetFipsAlgorithmMode(
+ [MarshalAs(UnmanagedType.U1), Out]out bool pfEnabled);
+
+ //
+ // Managed ACLs
+ //
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [DllImport(ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ bool AdjustTokenPrivileges (
+ [In] SafeAccessTokenHandle TokenHandle,
+ [In] bool DisableAllPrivileges,
+ [In] ref TOKEN_PRIVILEGE NewState,
+ [In] uint BufferLength,
+ [In,Out] ref TOKEN_PRIVILEGE PreviousState,
+ [In,Out] ref uint ReturnLength);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ bool AllocateLocallyUniqueId(
+ [In,Out] ref LUID Luid);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ bool CheckTokenMembership(
+ [In] SafeAccessTokenHandle TokenHandle,
+ [In] byte[] SidToCheck,
+ [In,Out] ref bool IsMember);
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="ConvertSecurityDescriptorToStringSecurityDescriptorW",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL ConvertSdToStringSd(
+ byte[] securityDescriptor,
+ /* DWORD */ uint requestedRevision,
+ ULONG securityInformation,
+ out IntPtr resultString,
+ ref ULONG resultStringLength );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="ConvertStringSecurityDescriptorToSecurityDescriptorW",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL ConvertStringSdToSd(
+ string stringSd,
+ /* DWORD */ uint stringSdRevision,
+ out IntPtr resultSd,
+ ref ULONG resultSdLength );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="ConvertStringSidToSidW",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL ConvertStringSidToSid(
+ string stringSid,
+ out IntPtr ByteArray
+ );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint = "ConvertSidToStringSidW",
+ CallingConvention = CallingConvention.Winapi,
+ SetLastError = true,
+ ExactSpelling = true,
+ CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool ConvertSidToStringSid(
+ IntPtr Sid,
+ ref IntPtr StringSid
+ );
+
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="CreateWellKnownSid",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL CreateWellKnownSid(
+ int sidType,
+ byte[] domainSid,
+ [Out] byte[] resultSid,
+ ref /*DWORD*/ uint resultSidLength );
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool DuplicateHandle (
+ [In] IntPtr hSourceProcessHandle,
+ [In] IntPtr hSourceHandle,
+ [In] IntPtr hTargetProcessHandle,
+ [In,Out] ref SafeAccessTokenHandle lpTargetHandle,
+ [In] uint dwDesiredAccess,
+ [In] bool bInheritHandle,
+ [In] uint dwOptions);
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool DuplicateHandle (
+ [In] IntPtr hSourceProcessHandle,
+ [In] SafeAccessTokenHandle hSourceHandle,
+ [In] IntPtr hTargetProcessHandle,
+ [In,Out] ref SafeAccessTokenHandle lpTargetHandle,
+ [In] uint dwDesiredAccess,
+ [In] bool bInheritHandle,
+ [In] uint dwOptions);
+
+#if FEATURE_IMPERSONATION
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool DuplicateTokenEx (
+ [In] SafeAccessTokenHandle ExistingTokenHandle,
+ [In] TokenAccessLevels DesiredAccess,
+ [In] IntPtr TokenAttributes,
+ [In] SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+ [In] System.Security.Principal.TokenType TokenType,
+ [In,Out] ref SafeAccessTokenHandle DuplicateTokenHandle );
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool DuplicateTokenEx (
+ [In] SafeAccessTokenHandle hExistingToken,
+ [In] uint dwDesiredAccess,
+ [In] IntPtr lpTokenAttributes, // LPSECURITY_ATTRIBUTES
+ [In] uint ImpersonationLevel,
+ [In] uint TokenType,
+ [In,Out] ref SafeAccessTokenHandle phNewToken);
+#endif
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="EqualDomainSid",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL IsEqualDomainSid(
+ byte[] sid1,
+ byte[] sid2,
+ out bool result);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern IntPtr GetCurrentProcess();
+
+ [DllImport(KERNEL32, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern IntPtr GetCurrentThread();
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="GetSecurityDescriptorLength",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint GetSecurityDescriptorLength(
+ IntPtr byteArray );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="GetSecurityInfo",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint GetSecurityInfoByHandle(
+ SafeHandle handle,
+ /*DWORD*/ uint objectType,
+ /*DWORD*/ uint securityInformation,
+ out IntPtr sidOwner,
+ out IntPtr sidGroup,
+ out IntPtr dacl,
+ out IntPtr sacl,
+ out IntPtr securityDescriptor );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="GetNamedSecurityInfoW",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint GetSecurityInfoByName(
+ string name,
+ /*DWORD*/ uint objectType,
+ /*DWORD*/ uint securityInformation,
+ out IntPtr sidOwner,
+ out IntPtr sidGroup,
+ out IntPtr dacl,
+ out IntPtr sacl,
+ out IntPtr securityDescriptor );
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool GetTokenInformation (
+ [In] IntPtr TokenHandle,
+ [In] uint TokenInformationClass,
+ [In] SafeLocalAllocHandle TokenInformation,
+ [In] uint TokenInformationLength,
+ [Out] out uint ReturnLength);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool GetTokenInformation (
+ [In] SafeAccessTokenHandle TokenHandle,
+ [In] uint TokenInformationClass,
+ [In] SafeLocalAllocHandle TokenInformation,
+ [In] uint TokenInformationLength,
+ [Out] out uint ReturnLength);
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="GetWindowsAccountDomainSid",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL GetWindowsAccountDomainSid(
+ byte[] sid,
+ [Out] byte[] resultSid,
+ ref /*DWORD*/ uint resultSidLength );
+
+ internal enum SECURITY_IMPERSONATION_LEVEL
+ {
+ Anonymous = 0,
+ Identification = 1,
+ Impersonation = 2,
+ Delegation = 3,
+ }
+
+ // Structures and definitions for Claims that are being introduced in Win8
+ // inside the NTTOken - see winnt.h. They will be surfaced through WindowsIdentity.Claims
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_INVALID -> 0x00
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_INVALID = 0;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64 -> 0x01
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64 = 1;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64 -> 0x02
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64 = 2;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING -> 0x03
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING = 3;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN -> 0x04
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN = 4;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_SID -> 0x05
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_SID = 5;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN -> 0x06
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN = 6;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING -> 0x10
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING = 16;
+
+ // CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE -> 0x0001
+ internal const int CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE = 1;
+
+ // CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE -> 0x0002
+ internal const int CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE = 2;
+
+ // CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY -> 0x0004
+ internal const int CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY = 4;
+
+ // CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT -> 0x0008
+ internal const int CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT = 8;
+
+ // CLAIM_SECURITY_ATTRIBUTE_DISABLED -> 0x0010
+ internal const int CLAIM_SECURITY_ATTRIBUTE_DISABLED = 16;
+
+ // CLAIM_SECURITY_ATTRIBUTE_MANDATORY -> 0x0020
+ internal const int CLAIM_SECURITY_ATTRIBUTE_MANDATORY = 32;
+
+ internal const int CLAIM_SECURITY_ATTRIBUTE_VALID_FLAGS =
+ CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE
+ | CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE
+ | CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY
+ | CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT
+ | CLAIM_SECURITY_ATTRIBUTE_DISABLED
+ | CLAIM_SECURITY_ATTRIBUTE_MANDATORY;
+
+
+ [StructLayoutAttribute( LayoutKind.Explicit )]
+ internal struct CLAIM_SECURITY_ATTRIBUTE_INFORMATION_V1
+ {
+ // defined as union in CLAIM_SECURITY_ATTRIBUTES_INFORMATION
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr pAttributeV1;
+ }
+
+ [StructLayoutAttribute( LayoutKind.Sequential )]
+ internal struct CLAIM_SECURITY_ATTRIBUTES_INFORMATION
+ {
+ /// WORD->unsigned short
+ public ushort Version;
+
+ /// WORD->unsigned short
+ public ushort Reserved;
+
+ /// DWORD->unsigned int
+ public uint AttributeCount;
+
+ /// CLAIM_SECURITY_ATTRIBUTE_V1
+ public CLAIM_SECURITY_ATTRIBUTE_INFORMATION_V1 Attribute;
+ }
+
+ //
+ // Fully-qualified binary name.
+ //
+ [StructLayoutAttribute( LayoutKind.Sequential, CharSet = CharSet.Unicode )]
+ internal struct CLAIM_SECURITY_ATTRIBUTE_FQBN_VALUE
+ {
+ // DWORD64->unsigned __int64
+ public ulong Version;
+
+ // PWSTR->WCHAR*
+ [MarshalAsAttribute( UnmanagedType.LPWStr )]
+ public string Name;
+ }
+
+ [StructLayoutAttribute( LayoutKind.Sequential, CharSet = CharSet.Unicode )]
+ internal struct CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE
+ {
+ /// PVOID->void*
+ public IntPtr pValue;
+
+ /// DWORD->unsigned int
+ public uint ValueLength;
+ }
+
+ [StructLayoutAttribute( LayoutKind.Explicit, CharSet = CharSet.Unicode )]
+ internal struct CLAIM_VALUES_ATTRIBUTE_V1
+ {
+ // PLONG64->__int64*
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr pInt64;
+
+ // PDWORD64->unsigned __int64*
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr pUint64;
+
+ // PWSTR*
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr ppString;
+
+ // PCLAIM_SECURITY_ATTRIBUTE_FQBN_VALUE->_CLAIM_SECURITY_ATTRIBUTE_FQBN_VALUE*
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr pFqbn;
+
+ // PCLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE->_CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE*
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr pOctetString;
+ }
+
+ [StructLayoutAttribute( LayoutKind.Sequential, CharSet = CharSet.Unicode )]
+ internal struct CLAIM_SECURITY_ATTRIBUTE_V1
+ {
+ // PWSTR->WCHAR*
+ [MarshalAsAttribute( UnmanagedType.LPWStr )]
+ public string Name;
+
+ // WORD->unsigned short
+ public ushort ValueType;
+
+ // WORD->unsigned short
+ public ushort Reserved;
+
+ // DWORD->unsigned int
+ public uint Flags;
+
+ // DWORD->unsigned int
+ public uint ValueCount;
+
+ // struct CLAIM_VALUES - a union of 4 possible values
+ public CLAIM_VALUES_ATTRIBUTE_V1 Values;
+ }
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="IsWellKnownSid",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL IsWellKnownSid(
+ byte[] sid,
+ int type );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="LsaOpenPolicy",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint LsaOpenPolicy(
+ string systemName,
+ ref LSA_OBJECT_ATTRIBUTES attributes,
+ int accessMask,
+ out SafeLsaPolicyHandle handle
+ );
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="LookupPrivilegeValueW",
+ CharSet=CharSet.Auto,
+ SetLastError=true,
+ ExactSpelling=true,
+ BestFitMapping=false)]
+ internal static extern
+ bool LookupPrivilegeValue (
+ [In] string lpSystemName,
+ [In] string lpName,
+ [In,Out] ref LUID Luid);
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="LsaLookupSids",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint LsaLookupSids(
+ SafeLsaPolicyHandle handle,
+ int count,
+ IntPtr[] sids,
+ ref SafeLsaMemoryHandle referencedDomains,
+ ref SafeLsaMemoryHandle names
+ );
+
+ [DllImport(ADVAPI32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int LsaFreeMemory( IntPtr handle );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="LsaLookupNames",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint LsaLookupNames(
+ SafeLsaPolicyHandle handle,
+ int count,
+ UNICODE_STRING[] names,
+ ref SafeLsaMemoryHandle referencedDomains,
+ ref SafeLsaMemoryHandle sids
+ );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="LsaLookupNames2",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint LsaLookupNames2(
+ SafeLsaPolicyHandle handle,
+ int flags,
+ int count,
+ UNICODE_STRING[] names,
+ ref SafeLsaMemoryHandle referencedDomains,
+ ref SafeLsaMemoryHandle sids
+ );
+
+ [DllImport(SECUR32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ int LsaConnectUntrusted (
+ [In,Out] ref SafeLsaLogonProcessHandle LsaHandle);
+
+ [DllImport(SECUR32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ int LsaGetLogonSessionData (
+ [In] ref LUID LogonId,
+ [In,Out] ref SafeLsaReturnBufferHandle ppLogonSessionData);
+
+ [DllImport(SECUR32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ int LsaLogonUser (
+ [In] SafeLsaLogonProcessHandle LsaHandle,
+ [In] ref UNICODE_INTPTR_STRING OriginName,
+ [In] uint LogonType,
+ [In] uint AuthenticationPackage,
+ [In] IntPtr AuthenticationInformation,
+ [In] uint AuthenticationInformationLength,
+ [In] IntPtr LocalGroups,
+ [In] ref TOKEN_SOURCE SourceContext,
+ [In,Out] ref SafeLsaReturnBufferHandle ProfileBuffer,
+ [In,Out] ref uint ProfileBufferLength,
+ [In,Out] ref LUID LogonId,
+ [In,Out] ref SafeAccessTokenHandle Token,
+ [In,Out] ref QUOTA_LIMITS Quotas,
+ [In,Out] ref int SubStatus);
+
+ [DllImport(SECUR32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ int LsaLookupAuthenticationPackage (
+ [In] SafeLsaLogonProcessHandle LsaHandle,
+ [In] ref UNICODE_INTPTR_STRING PackageName,
+ [In,Out] ref uint AuthenticationPackage);
+
+ [DllImport(SECUR32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ int LsaRegisterLogonProcess (
+ [In] ref UNICODE_INTPTR_STRING LogonProcessName,
+ [In,Out] ref SafeLsaLogonProcessHandle LsaHandle,
+ [In,Out] ref IntPtr SecurityMode);
+
+ [DllImport(SECUR32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int LsaDeregisterLogonProcess(IntPtr handle);
+
+ [DllImport(ADVAPI32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int LsaClose( IntPtr handle );
+
+ [DllImport(SECUR32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int LsaFreeReturnBuffer(IntPtr handle);
+
+#if FEATURE_IMPERSONATION
+ [DllImport (ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ bool OpenProcessToken (
+ [In] IntPtr ProcessToken,
+ [In] TokenAccessLevels DesiredAccess,
+ [Out] out SafeAccessTokenHandle TokenHandle);
+#endif
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="SetNamedSecurityInfoW",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint SetSecurityInfoByName(
+ string name,
+ /*DWORD*/ uint objectType,
+ /*DWORD*/ uint securityInformation,
+ byte[] owner,
+ byte[] group,
+ byte[] dacl,
+ byte[] sacl );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="SetSecurityInfo",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint SetSecurityInfoByHandle(
+ SafeHandle handle,
+ /*DWORD*/ uint objectType,
+ /*DWORD*/ uint securityInformation,
+ byte[] owner,
+ byte[] group,
+ byte[] dacl,
+ byte[] sacl );
+
+ // Fusion APIs
+#if FEATURE_FUSION
+ [DllImport(MSCORWKS, CharSet=CharSet.Unicode)]
+ internal static extern int CreateAssemblyNameObject(out IAssemblyName ppEnum, String szAssemblyName, uint dwFlags, IntPtr pvReserved);
+
+ [DllImport(MSCORWKS, CharSet=CharSet.Auto)]
+ internal static extern int CreateAssemblyEnum(out IAssemblyEnum ppEnum, IApplicationContext pAppCtx, IAssemblyName pName, uint dwFlags, IntPtr pvReserved);
+#endif // FEATURE_FUSION
+
+#if FEATURE_CORECLR
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal unsafe static extern int WideCharToMultiByte(
+ int CodePage,
+ UInt32 dwFlags,
+ char* lpWideCharStr,
+ int cchWideChar,
+ byte* lpMultiByteStr,
+ int cchMultiByte,
+ char* lpDefaultChar,
+ bool* lpUsedDefaultChar);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal unsafe static extern int MultiByteToWideChar(
+ int CodePage,
+ UInt32 dwFlags,
+ byte* lpMultiByteStr,
+ int cchMultiByte,
+ char* lpWideCharStr,
+ int cchWideChar);
+#endif // FEATURE_CORECLR
+
+ [DllImport(KERNEL32, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal extern static bool QueryUnbiasedInterruptTime(out ulong UnbiasedTime);
+
+#if FEATURE_CORECLR
+#if FEATURE_PAL
+ [DllImport(KERNEL32, EntryPoint = "PAL_Random")]
+ internal extern static bool Random(bool bStrong,
+ [Out, MarshalAs(UnmanagedType.LPArray)] byte[] buffer, int length);
+#else
+ private const int BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002;
+
+ [DllImport("BCrypt.dll", CharSet = CharSet.Unicode)]
+ private static extern uint BCryptGenRandom(IntPtr hAlgorithm, [In, Out] byte[] pbBuffer, int cbBuffer, int dwFlags);
+
+ internal static void Random(bool bStrong, byte[] buffer, int length)
+ {
+ uint status = BCryptGenRandom(IntPtr.Zero, buffer, length, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+ if (status != STATUS_SUCCESS)
+ {
+ if (status == STATUS_NO_MEMORY)
+ {
+ throw new OutOfMemoryException();
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ }
+ }
+#endif
+#endif
+ }
+}