From 8340f789a1d8aaeb705acd66c02738ba2bb15da3 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Thu, 20 Sep 2018 18:10:47 -0700 Subject: [PATCH] Add back moved files and fix build breaks Commit migrated from https://github.com/dotnet/corefx/commit/046c0291d0172bf23139cf6d3f856f92364ac94c --- .../src/Microsoft.Win32.Registry.csproj | 28 ++---- .../src/Microsoft/Win32/Registry.cs | 99 ++++++++++++++++++++++ .../src/Microsoft/Win32/RegistryHive.cs | 19 +++++ .../src/Microsoft/Win32/RegistryKey.FileSystem.cs | 7 +- .../src/Microsoft/Win32/RegistryKey.Windows.cs | 17 ++-- .../src/Microsoft/Win32/RegistryKey.cs | 7 +- .../Microsoft/Win32/RegistryKeyPermissionCheck.cs | 7 +- .../src/Microsoft/Win32/RegistryOptions.cs | 15 ++++ .../src/Microsoft/Win32/RegistryValueKind.cs | 18 ++++ .../src/Microsoft/Win32/RegistryValueOptions.cs | 15 ++++ .../src/Microsoft/Win32/RegistryView.cs | 15 ++++ .../SafeHandles/SafeRegistryHandle.FileSystem.cs | 7 +- .../Security/AccessControl/RegistryRights.cs | 37 ++++++++ .../tests/Microsoft.Win32.Registry.Tests.csproj | 1 + .../RegistryKey_GetValue_CorruptData.cs | 4 +- 15 files changed, 238 insertions(+), 58 deletions(-) create mode 100644 src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs create mode 100644 src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryHive.cs create mode 100644 src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryOptions.cs create mode 100644 src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryValueKind.cs create mode 100644 src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryValueOptions.cs create mode 100644 src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryView.cs create mode 100644 src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistryRights.cs diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj b/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj index ea8e9c8..28f3236 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj @@ -18,32 +18,18 @@ Common\CoreLib\Interop\Windows\Advapi32\Interop.RegistryConstants.cs - - Common\CoreLib\Microsoft\Win32\Registry.cs - - - Common\CoreLib\Microsoft\Win32\RegistryHive.cs - - - Common\CoreLib\Microsoft\Win32\RegistryValueKind.cs - Common\CoreLib\Microsoft\Win32\SafeHandles\SafeRegistryHandle.cs + + + - - Common\CoreLib\Microsoft\Win32\RegistryOptions.cs - - - Common\CoreLib\Microsoft\Win32\RegistryValueOptions.cs - - - Common\CoreLib\Microsoft\Win32\RegistryView.cs - - - Common\CoreLib\System\Security\AccessControl\RegistryRights.cs - + + + + diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs new file mode 100644 index 0000000..f86f170 --- /dev/null +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs @@ -0,0 +1,99 @@ +// 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. + +using System; +using System.Diagnostics; + +namespace Microsoft.Win32 +{ + /// Registry encapsulation. Contains members representing all top level system keys. + public static class Registry + { + /// Current User Key. This key should be used as the root for all user specific settings. + public static readonly RegistryKey CurrentUser = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default); + + /// Local Machine key. This key should be used as the root for all machine specific settings. + public static readonly RegistryKey LocalMachine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default); + + /// Classes Root Key. This is the root key of class information. + public static readonly RegistryKey ClassesRoot = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default); + + /// Users Root Key. This is the root of users. + public static readonly RegistryKey Users = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default); + + /// Performance Root Key. This is where dynamic performance data is stored on NT. + public static readonly RegistryKey PerformanceData = RegistryKey.OpenBaseKey(RegistryHive.PerformanceData, RegistryView.Default); + + /// Current Config Root Key. This is where current configuration information is stored. + public static readonly RegistryKey CurrentConfig = RegistryKey.OpenBaseKey(RegistryHive.CurrentConfig, RegistryView.Default); + + /// + /// 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. + /// + private static RegistryKey GetBaseKeyFromKeyName(string keyName, out string subKeyName) + { + if (keyName == null) + { + throw new ArgumentNullException(nameof(keyName)); + } + + int i = keyName.IndexOf('\\'); + int length = i != -1 ? i : keyName.Length; + + // Determine the potential base key from the length. + RegistryKey baseKey = null; + switch (length) + { + case 10: baseKey = Users; break; // HKEY_USERS + case 17: baseKey = char.ToUpperInvariant(keyName[6]) == 'L' ? ClassesRoot : CurrentUser; break; // HKEY_C[L]ASSES_ROOT, otherwise HKEY_CURRENT_USER + case 18: baseKey = LocalMachine; break; // HKEY_LOCAL_MACHINE + case 19: baseKey = CurrentConfig; break; // HKEY_CURRENT_CONFIG + case 21: baseKey = PerformanceData; break; // HKEY_PERFORMANCE_DATA + } + + // If a potential base key was found, see if keyName actually starts with the potential base key's name. + if (baseKey != null && keyName.StartsWith(baseKey.Name, StringComparison.OrdinalIgnoreCase)) + { + subKeyName = (i == -1 || i == keyName.Length) ? + string.Empty : + keyName.Substring(i + 1, keyName.Length - i - 1); + + return baseKey; + } + + throw new ArgumentException(SR.Format(SR.Arg_RegInvalidKeyName, nameof(keyName)), nameof(keyName)); + } + + public static object GetValue(string keyName, string valueName, object defaultValue) + { + string subKeyName; + RegistryKey basekey = GetBaseKeyFromKeyName(keyName, out subKeyName); + + using (RegistryKey key = basekey.OpenSubKey(subKeyName)) + { + return key?.GetValue(valueName, defaultValue); + } + } + + public static void SetValue(string keyName, string valueName, object value) + { + SetValue(keyName, valueName, value, RegistryValueKind.Unknown); + } + + public static void SetValue(string keyName, string valueName, object value, RegistryValueKind valueKind) + { + string subKeyName; + RegistryKey basekey = GetBaseKeyFromKeyName(keyName, out subKeyName); + + using (RegistryKey key = basekey.CreateSubKey(subKeyName)) + { + Debug.Assert(key != null, "An exception should be thrown if failed!"); + key.SetValue(valueName, value, valueKind); + } + } + } +} diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryHive.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryHive.cs new file mode 100644 index 0000000..059e484 --- /dev/null +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryHive.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. + +namespace Microsoft.Win32 +{ + /** + * Registry hive values. Useful only for GetRemoteBaseKey + */ + 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), + } +} diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.FileSystem.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.FileSystem.cs index 1391212..c0b9846 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.FileSystem.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.FileSystem.cs @@ -7,12 +7,7 @@ using System; namespace Microsoft.Win32 { -#if REGISTRY_ASSEMBLY - public -#else - internal -#endif - sealed partial class RegistryKey : MarshalByRefObject, IDisposable + public sealed partial class RegistryKey : MarshalByRefObject, IDisposable { private void ClosePerfDataKey() { diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.Windows.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.Windows.cs index 7f4ce24..c7686fd 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.Windows.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.Windows.cs @@ -57,12 +57,7 @@ using System.Security.AccessControl; namespace Microsoft.Win32 { -#if REGISTRY_ASSEMBLY - public -#else - internal -#endif - sealed partial class RegistryKey : MarshalByRefObject, IDisposable + public sealed partial class RegistryKey : MarshalByRefObject, IDisposable { private void ClosePerfDataKey() { @@ -815,7 +810,7 @@ namespace Microsoft.Win32 ret = Interop.Advapi32.RegSetValueEx(_hkey, name, 0, - valueKind, + (int)valueKind, data, checked(data.Length * 2 + 2)); break; @@ -857,7 +852,7 @@ namespace Microsoft.Win32 ret = Interop.Advapi32.RegSetValueEx(_hkey, name, 0, - RegistryValueKind.MultiString, + Interop.Advapi32.RegistryValues.REG_MULTI_SZ, dataChars, sizeInBytes); @@ -870,7 +865,7 @@ namespace Microsoft.Win32 ret = Interop.Advapi32.RegSetValueEx(_hkey, name, 0, - (valueKind == RegistryValueKind.None ? Interop.Advapi32.RegistryValues.REG_NONE : RegistryValueKind.Binary), + (valueKind == RegistryValueKind.None ? Interop.Advapi32.RegistryValues.REG_NONE : Interop.Advapi32.RegistryValues.REG_BINARY), dataBytes, dataBytes.Length); break; @@ -884,7 +879,7 @@ namespace Microsoft.Win32 ret = Interop.Advapi32.RegSetValueEx(_hkey, name, 0, - RegistryValueKind.DWord, + Interop.Advapi32.RegistryValues.REG_DWORD, ref data, 4); break; @@ -897,7 +892,7 @@ namespace Microsoft.Win32 ret = Interop.Advapi32.RegSetValueEx(_hkey, name, 0, - RegistryValueKind.QWord, + Interop.Advapi32.RegistryValues.REG_QWORD, ref data, 8); break; diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs index c0742a9..185d872 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs @@ -14,12 +14,7 @@ using System.Text; namespace Microsoft.Win32 { /// Registry encapsulation. To get an instance of a RegistryKey use the Registry class's static members then call OpenSubKey. -#if REGISTRY_ASSEMBLY - public -#else - internal -#endif - sealed partial class RegistryKey : MarshalByRefObject, IDisposable + public sealed partial class RegistryKey : MarshalByRefObject, IDisposable { private static readonly IntPtr HKEY_CLASSES_ROOT = new IntPtr(unchecked((int)0x80000000)); private static readonly IntPtr HKEY_CURRENT_USER = new IntPtr(unchecked((int)0x80000001)); diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKeyPermissionCheck.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKeyPermissionCheck.cs index b632477..92b8b01 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKeyPermissionCheck.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKeyPermissionCheck.cs @@ -6,12 +6,7 @@ using System; namespace Microsoft.Win32 { -#if REGISTRY_ASSEMBLY - public -#else - internal -#endif - enum RegistryKeyPermissionCheck + public enum RegistryKeyPermissionCheck { Default = 0, ReadSubTree = 1, diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryOptions.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryOptions.cs new file mode 100644 index 0000000..112efd2 --- /dev/null +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryOptions.cs @@ -0,0 +1,15 @@ +// 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. + +using System; + +namespace Microsoft.Win32 +{ + [Flags] + public enum RegistryOptions + { + None = Interop.Advapi32.RegistryOptions.REG_OPTION_NON_VOLATILE, // 0x0000 + Volatile = Interop.Advapi32.RegistryOptions.REG_OPTION_VOLATILE, // 0x0001 + }; +} diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryValueKind.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryValueKind.cs new file mode 100644 index 0000000..d71ca3e --- /dev/null +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryValueKind.cs @@ -0,0 +1,18 @@ +// 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 +{ + public enum RegistryValueKind + { + String = Interop.Advapi32.RegistryValues.REG_SZ, + ExpandString = Interop.Advapi32.RegistryValues.REG_EXPAND_SZ, + Binary = Interop.Advapi32.RegistryValues.REG_BINARY, + DWord = Interop.Advapi32.RegistryValues.REG_DWORD, + MultiString = Interop.Advapi32.RegistryValues.REG_MULTI_SZ, + QWord = Interop.Advapi32.RegistryValues.REG_QWORD, + Unknown = 0, // REG_NONE is defined as zero but BCL + None = unchecked((int)0xFFFFFFFF), // mistakenly overrode this value. + } // Now instead of using Interop.Kernel32.RegistryValues.REG_NONE we use "-1". +} diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryValueOptions.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryValueOptions.cs new file mode 100644 index 0000000..622a7dd --- /dev/null +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryValueOptions.cs @@ -0,0 +1,15 @@ +// 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. + +using System; + +namespace Microsoft.Win32 +{ + [Flags] + public enum RegistryValueOptions + { + None = 0, + DoNotExpandEnvironmentNames = 1 + } +} diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryView.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryView.cs new file mode 100644 index 0000000..0bfe1a5 --- /dev/null +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryView.cs @@ -0,0 +1,15 @@ +// 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. + +using System; + +namespace Microsoft.Win32 +{ + public enum RegistryView + { + Default = 0, // 0x0000 operate on the default registry view + Registry64 = Interop.Advapi32.RegistryView.KEY_WOW64_64KEY, // 0x0100 operate on the 64-bit registry view + Registry32 = Interop.Advapi32.RegistryView.KEY_WOW64_32KEY, // 0x0200 operate on the 32-bit registry view + }; +} diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.FileSystem.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.FileSystem.cs index 50c2875..296e93b 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.FileSystem.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.FileSystem.cs @@ -6,12 +6,7 @@ using System.Runtime.InteropServices; namespace Microsoft.Win32.SafeHandles { -#if REGISTRY_ASSEMBLY - public -#else - internal -#endif - sealed partial class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid + public sealed partial class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid { // TODO: implement this if necessary protected override bool ReleaseHandle() => true; diff --git a/src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistryRights.cs b/src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistryRights.cs new file mode 100644 index 0000000..b5095b9 --- /dev/null +++ b/src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistryRights.cs @@ -0,0 +1,37 @@ +// 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. + +using Microsoft.Win32; + +namespace System.Security.AccessControl +{ + // We derived this enum from the definitions of KEY_READ and such from + // winnt.h and from MSDN, plus some experimental validation with regedit. + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/registry_key_security_and_access_rights.asp + [Flags] + public enum RegistryRights + { + // No None field - An ACE with the value 0 cannot grant nor deny. + QueryValues = Interop.Advapi32.RegistryOperations.KEY_QUERY_VALUE, // 0x0001 query the values of a registry key + SetValue = Interop.Advapi32.RegistryOperations.KEY_SET_VALUE, // 0x0002 create, delete, or set a registry value + CreateSubKey = Interop.Advapi32.RegistryOperations.KEY_CREATE_SUB_KEY, // 0x0004 required to create a subkey of a specific key + EnumerateSubKeys = Interop.Advapi32.RegistryOperations.KEY_ENUMERATE_SUB_KEYS, // 0x0008 required to enumerate sub keys of a key + Notify = Interop.Advapi32.RegistryOperations.KEY_NOTIFY, // 0x0010 needed to request change notifications + CreateLink = Interop.Advapi32.RegistryOperations.KEY_CREATE_LINK, // 0x0020 reserved for system use + /// + /// The Windows Kernel team agrees that it was a bad design to expose the WOW64_n options as permissions. + /// in the .NET Framework these options are exposed via the RegistryView enum + /// + /// Reg64 = Interop.Advapi32.RegistryOptions.KEY_WOW64_64KEY, // 0x0100 operate on the 64-bit registry view + /// Reg32 = Interop.Advapi32.RegistryOptions.KEY_WOW64_32KEY, // 0x0200 operate on the 32-bit registry view + ExecuteKey = ReadKey, + ReadKey = Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_READ | QueryValues | EnumerateSubKeys | Notify, + WriteKey = Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_WRITE | SetValue | CreateSubKey, + Delete = 0x10000, + ReadPermissions = 0x20000, + ChangePermissions = 0x40000, + TakeOwnership = 0x80000, + FullControl = 0xF003F | Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_READ | Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_WRITE + } +} diff --git a/src/libraries/Microsoft.Win32.Registry/tests/Microsoft.Win32.Registry.Tests.csproj b/src/libraries/Microsoft.Win32.Registry/tests/Microsoft.Win32.Registry.Tests.csproj index fc5cc02..0ac872e 100644 --- a/src/libraries/Microsoft.Win32.Registry/tests/Microsoft.Win32.Registry.Tests.csproj +++ b/src/libraries/Microsoft.Win32.Registry/tests/Microsoft.Win32.Registry.Tests.csproj @@ -1,6 +1,7 @@ {20A2BA2C-5517-483F-8FFE-643441A59852} + $(DefineConstants);REGISTRY_ASSEMBLY netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;netfx-Windows_NT-Debug;netfx-Windows_NT-Release diff --git a/src/libraries/Microsoft.Win32.Registry/tests/RegistryKey/RegistryKey_GetValue_CorruptData.cs b/src/libraries/Microsoft.Win32.Registry/tests/RegistryKey/RegistryKey_GetValue_CorruptData.cs index 7dbe4ba..3ce8618 100644 --- a/src/libraries/Microsoft.Win32.Registry/tests/RegistryKey/RegistryKey_GetValue_CorruptData.cs +++ b/src/libraries/Microsoft.Win32.Registry/tests/RegistryKey/RegistryKey_GetValue_CorruptData.cs @@ -26,7 +26,7 @@ namespace Microsoft.Win32.RegistryTests SafeRegistryHandle handle = TestRegistryKey.Handle; int ret = Interop.Advapi32.RegSetValueEx(handle, TestValueName, 0, - RegistryValueKind.MultiString, corrupt, corrupt.Length * 2); + (int)RegistryValueKind.MultiString, corrupt, corrupt.Length * 2); Assert.Equal(0, ret); try { @@ -54,7 +54,7 @@ namespace Microsoft.Win32.RegistryTests SafeRegistryHandle handle = TestRegistryKey.Handle; int ret = Interop.Advapi32.RegSetValueEx(handle, TestValueName, 0, - kind, contents, contents.Length); + (int)kind, contents, contents.Length); Assert.Equal(0, ret); try { -- 2.7.4