summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2017-04-13 14:17:19 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2017-04-13 14:17:19 +0900
commita56e30c8d33048216567753d9d3fefc2152af8ac (patch)
tree7e5d979695fc4a431740982eb1cfecc2898b23a5 /src/mscorlib/src/Microsoft/Win32/RegistryKey.cs
parent4b11dc566a5bbfa1378d6266525c281b028abcc8 (diff)
downloadcoreclr-a56e30c8d33048216567753d9d3fefc2152af8ac.tar.gz
coreclr-a56e30c8d33048216567753d9d3fefc2152af8ac.tar.bz2
coreclr-a56e30c8d33048216567753d9d3fefc2152af8ac.zip
Imported Upstream version 2.0.0.11353upstream/2.0.0.11353
Diffstat (limited to 'src/mscorlib/src/Microsoft/Win32/RegistryKey.cs')
-rw-r--r--src/mscorlib/src/Microsoft/Win32/RegistryKey.cs1290
1 files changed, 408 insertions, 882 deletions
diff --git a/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs b/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs
index f82b276059..e39b95903e 100644
--- a/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs
+++ b/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs
@@ -2,28 +2,6 @@
// 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
@@ -48,70 +26,41 @@
*/
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
namespace Microsoft.Win32
{
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Security;
- 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 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)
*/
- internal sealed class RegistryKey : MarshalByRefObject, IDisposable
+ internal sealed class RegistryKey : MarshalByRefObject, IDisposable
{
+ // Use the public Registry.CurrentUser
+ internal static readonly RegistryKey CurrentUser =
+ GetBaseKey(new IntPtr(unchecked((int)0x80000001)), "HKEY_CURRENT_USER");
+
+ // Use the public Registry.LocalMachine
+ internal static readonly RegistryKey LocalMachine =
+ GetBaseKey(new IntPtr(unchecked((int)0x80000002)), "HKEY_LOCAL_MACHINE");
// 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));
-
- // Dirty indicates that we have munged data that should be potentially
- // written to disk.
- //
- private const int STATE_DIRTY = 0x0001;
+ private static readonly IntPtr HKEY_CURRENT_USER = new IntPtr(unchecked((int)0x80000001));
+ private static readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(unchecked((int)0x80000002));
// SystemKey indicates that this is a "SYSTEMKEY" and shouldn't be "opened"
// or "closed".
//
- private const int STATE_SYSTEMKEY = 0x0002;
+ 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",
- };
+ private const int STATE_WRITEACCESS = 0x0004;
// MSDN defines the following limits for registry key names & values:
// Key Name: 255 characters
@@ -122,30 +71,7 @@ namespace Microsoft.Win32
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
- };
-
+ private volatile string keyName;
/**
* Creates a RegistryKey.
@@ -156,37 +82,32 @@ namespace Microsoft.Win32
* 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.
*/
- private RegistryKey(SafeRegistryHandle hkey, bool writable, bool systemkey, bool remoteKey, bool isPerfData, RegistryView view) {
+ private RegistryKey(SafeRegistryHandle hkey, bool writable, bool systemkey)
+ {
this.hkey = hkey;
- this.keyName = "";
- this.remoteKey = remoteKey;
- this.regView = view;
- if (systemkey) {
- this.state |= STATE_SYSTEMKEY;
+ keyName = "";
+ if (systemkey)
+ {
+ state |= STATE_SYSTEMKEY;
}
- if (writable) {
- this.state |= STATE_WRITEACCESS;
+ if (writable)
+ {
+ 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);
}
- private void Dispose(bool disposing) {
- if (hkey != null) {
-
- if (!IsSystemKey()) {
- try {
+ private void Dispose(bool disposing)
+ {
+ if (hkey != null)
+ {
+ if (!IsSystemKey())
+ {
+ try
+ {
hkey.Dispose();
}
- catch (IOException){
+ catch (IOException)
+ {
// we don't really care if the handle is invalid at this point
}
finally
@@ -194,20 +115,6 @@ namespace Microsoft.Win32
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);
- }
}
}
@@ -216,278 +123,199 @@ namespace Microsoft.Win32
Dispose(true);
}
- public void DeleteValue(String name, bool throwOnMissingValue) {
+ 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
+ // 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);
+ 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.
- */
- internal static RegistryKey GetBaseKey(IntPtr hKey) {
- return GetBaseKey(hKey, RegistryView.Default);
+ Debug.Assert(errorCode == 0, "RegDeleteValue failed. Here's your error code: " + errorCode);
}
- 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);
+ private static RegistryKey GetBaseKey(IntPtr hKey, string keyName)
+ {
+ SafeRegistryHandle srh = new SafeRegistryHandle(hKey, ownsHandle: false);
- RegistryKey key = new RegistryKey(srh, true, true,false, isPerf, view);
- key.checkMode = RegistryKeyPermissionCheck.Default;
- key.keyName = hkeyNames[index];
+ RegistryKey key = new RegistryKey(srh, true, true);
+ key.keyName = keyName;
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.
- */
- public RegistryKey OpenSubKey(string name, bool writable ) {
+ /// <summary>
+ /// Retrieves a subkey or null if the operation failed.
+ /// </summary>
+ /// <param name="writable">True to open writable, otherwise opens the key read-only.</param>
+ 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,
+ writable ? Win32Native.KEY_READ | Win32Native.KEY_WRITE : Win32Native.KEY_READ,
out result);
- if (ret == 0 && !result.IsInvalid) {
- RegistryKey key = new RegistryKey(result, writable, false, remoteKey, false, regView);
- key.checkMode = GetSubKeyPermissonCheck(writable);
+ if (ret == 0 && !result.IsInvalid)
+ {
+ RegistryKey key = new RegistryKey(result, writable, false);
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) {
+ 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;
- }
-
- // 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
- 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.
- */
- public RegistryKey OpenSubKey(String name) {
- return OpenSubKey(name, false);
- }
-
- 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.
- */
- public String[] GetSubKeyNames() {
- CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default);
- return InternalGetSubKeyNames();
- }
-
- internal unsafe String[] InternalGetSubKeyNames() {
+ /// <summary>
+ /// Retrieves an array of strings containing all the subkey names.
+ /// </summary>
+ public string[] GetSubKeyNames()
+ {
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;
+ var names = new List<string>();
+ char[] name = ArrayPool<char>.Shared.Rent(MaxKeyLength + 1);
- fixed (char *namePtr = &name[0])
+ try
+ {
+ int result;
+ int nameLength = name.Length;
+
+ while ((result = Win32Native.RegEnumKeyEx(
+ hkey,
+ names.Count,
+ name,
+ ref nameLength,
+ null,
+ null,
+ null,
+ null)) != Interop.Errors.ERROR_NO_MORE_ITEMS)
{
- 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);
+ switch (result)
+ {
+ case Interop.Errors.ERROR_SUCCESS:
+ names.Add(new string(name, 0, nameLength));
+ nameLength = name.Length;
+ break;
+ default:
+ // Throw the error
+ Win32Error(result, null);
+ break;
}
}
}
+ finally
+ {
+ ArrayPool<char>.Shared.Return(name);
+ }
- return names;
+ return names.ToArray();
}
- 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.
- */
- public unsafe String[] GetValueNames() {
- CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default);
+ /// <summary>
+ /// Retrieves an array of strings containing all the value names.
+ /// </summary>
+ public unsafe string[] GetValueNames()
+ {
EnsureNotDisposed();
+ var names = new List<string>();
- int values = InternalValueCount();
- String[] names = new String[values];
+ // Names in the registry aren't usually very long, although they can go to as large
+ // as 16383 characters (MaxValueLength).
+ //
+ // Every call to RegEnumValue will allocate another buffer to get the data from
+ // NtEnumerateValueKey before copying it back out to our passed in buffer. This can
+ // add up quickly- we'll try to keep the memory pressure low and grow the buffer
+ // only if needed.
- if (values > 0) {
- char[] name = new char[MaxValueLength + 1];
- int namelen;
+ char[] name = ArrayPool<char>.Shared.Rent(100);
- fixed (char *namePtr = &name[0])
+ try
+ {
+ int result;
+ int nameLength = name.Length;
+
+ while ((result = Win32Native.RegEnumValue(
+ hkey,
+ names.Count,
+ name,
+ ref nameLength,
+ IntPtr.Zero,
+ null,
+ null,
+ null)) != Interop.Errors.ERROR_NO_MORE_ITEMS)
{
- 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);
+ switch (result)
+ {
+ // The size is only ever reported back correctly in the case
+ // of ERROR_SUCCESS. It will almost always be changed, however.
+ case Interop.Errors.ERROR_SUCCESS:
+ names.Add(new string(name, 0, nameLength));
+ break;
+ case Interop.Errors.ERROR_MORE_DATA:
+ if (IsPerfDataKey())
+ {
+ // Enumerating the values for Perf keys always returns
+ // ERROR_MORE_DATA, but has a valid name. Buffer does need
+ // to be big enough however. 8 characters is the largest
+ // known name. The size isn't returned, but the string is
+ // null terminated.
+ fixed (char* c = &name[0])
+ {
+ names.Add(new string(c));
+ }
+ }
+ else
+ {
+ char[] oldName = name;
+ int oldLength = oldName.Length;
+ name = null;
+ ArrayPool<char>.Shared.Return(oldName);
+ name = ArrayPool<char>.Shared.Rent(checked(oldLength * 2));
+ }
+ break;
+ default:
+ // Throw the error
+ Win32Error(result, null);
+ break;
}
+
+ // Always set the name length back to the buffer size
+ nameLength = name.Length;
}
}
+ finally
+ {
+ if (name != null)
+ ArrayPool<char>.Shared.Return(name);
+ }
- 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.
- */
- public Object GetValue(String name) {
- CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default);
- return InternalGetValue(name, null, false, true);
+ return names.ToArray();
}
/**
@@ -505,426 +333,257 @@ namespace Microsoft.Win32
*
* @return the data associated with the value.
*/
- public Object GetValue(String name, Object defaultValue) {
- CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default);
- return InternalGetValue(name, defaultValue, false, true);
- }
-
- 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), nameof(options));
- }
- bool doNotExpand = (options == RegistryValueOptions.DoNotExpandEnvironmentNames);
- CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default);
- return InternalGetValue(name, defaultValue, doNotExpand, true);
- }
-
- 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();
- }
+ public object GetValue(string name, object defaultValue = null, bool doNotExpand = false)
+ {
+ EnsureNotDisposed();
- Object data = defaultValue;
+ 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 (ret != 0)
+ {
+ // 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) {
+ if (datasize < 0)
+ {
// unexpected code path
- BCLDebug.Assert(false, "[InternalGetValue] RegQueryValue returned ERROR_SUCCESS but gave a negative datasize");
+ Debug.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;
+ Debug.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);
- 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;
- }
-
- 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;
- }
-
- 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);
- }
-
- public unsafe void SetValue(String name, Object value, RegistryValueKind valueKind) {
- if (value==null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+ 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;
+ Debug.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);
- if (name != null && name.Length > MaxValueLength) {
- throw new ArgumentException(Environment.GetResourceString("Arg_RegValStrLenBug"));
- }
+ data = blob;
+ }
+ break;
- if (!Enum.IsDefined(typeof(RegistryValueKind), valueKind))
- throw new ArgumentException(Environment.GetResourceString("Arg_RegBadKeyKind"), nameof(valueKind));
+ 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(SR.Arg_RegGetOverflowBug, e);
+ }
+ }
+ char[] blob = new char[datasize / 2];
- EnsureWriteable();
+ 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;
- 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);
- }
+ 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(SR.Arg_RegGetOverflowBug, e);
+ }
+ }
+ char[] blob = new char[datasize / 2];
- 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);
- }
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref datasize);
- int ret = 0;
- try {
- switch (valueKind) {
- case RegistryValueKind.ExpandString:
- case RegistryValueKind.String:
+ if (blob.Length > 0 && blob[blob.Length - 1] == (char)0)
{
- String data = value.ToString();
- ret = Win32Native.RegSetValueEx(hkey,
- name,
- 0,
- valueKind,
- data,
- checked(data.Length * 2 + 2));
- break;
+ 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);
}
- case RegistryValueKind.MultiString:
+ if (!doNotExpand)
+ data = Environment.ExpandEnvironmentVariables((string)data);
+ }
+ break;
+ case Win32Native.REG_MULTI_SZ:
+ {
+ if (datasize % 2 == 1)
{
- // 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);
+ // handle the case where the registry contains an odd-byte length (corrupt data?)
+ try
+ {
+ datasize = checked(datasize + 1);
+ }
+ catch (OverflowException e)
+ {
+ throw new IOException(SR.Arg_RegGetOverflowBug, e);
}
- break;
}
+ char[] blob = new char[datasize / 2];
- 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:
+ 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)
{
- // 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;
+ 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(SR.Arg_RegGetOverflowBug, e);
+ }
+ blob[blob.Length - 1] = (char)0;
}
- case RegistryValueKind.QWord:
+ IList<string> strings = new List<string>();
+ int cur = 0;
+ int len = blob.Length;
+
+ while (ret == 0 && cur < len)
{
- long data = Convert.ToInt64(value, System.Globalization.CultureInfo.InvariantCulture);
-
- ret = Win32Native.RegSetValueEx(hkey,
- name,
- 0,
- RegistryValueKind.QWord,
- ref data,
- 8);
- break;
+ int nextNull = cur;
+ while (nextNull < len && blob[nextNull] != (char)0)
+ {
+ nextNull++;
+ }
+
+ if (nextNull < len)
+ {
+ Debug.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;
}
- }
- }
- 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();
+ data = new string[strings.Count];
+ strings.CopyTo((string[])data, 0);
+ }
+ break;
+ case Win32Native.REG_LINK:
+ default:
+ break;
}
- else
- Win32Error(ret, null);
+ return data;
+ }
+
+ private bool IsSystemKey()
+ {
+ return (state & STATE_SYSTEMKEY) != 0;
}
- 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));
+ private bool IsWritable()
+ {
+ return (state & STATE_WRITEACCESS) != 0;
+ }
+
+ private bool IsPerfDataKey()
+ {
+ return false;
+ }
+
+ public unsafe void SetStringValue(string name, string value)
+ {
+ if (value == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+
+ if (name != null && name.Length > MaxValueLength)
+ {
+ throw new ArgumentException(SR.Arg_RegValStrLenBug);
}
- else
- return RegistryValueKind.String;
+
+ EnsureWriteable();
+
+ int result = Win32Native.RegSetValueEx(hkey,
+ name,
+ 0,
+ RegistryValueKind.String,
+ value,
+ checked(value.Length * 2 + 2));
+
+ if (result != 0)
+ Win32Error(result, null);
}
/**
@@ -932,7 +591,8 @@ namespace Microsoft.Win32
*
* @return a string representing the key.
*/
- public override String ToString() {
+ public override string ToString()
+ {
EnsureNotDisposed();
return keyName;
}
@@ -944,164 +604,51 @@ namespace Microsoft.Win32
* error, and depending on the error, insert a string into the message
* gotten from the ResourceManager.
*/
- internal void Win32Error(int errorCode, String str) {
- switch (errorCode) {
+ 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));
+ throw new UnauthorizedAccessException(SR.Format(SR.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);
+ throw new IOException(SR.Arg_RegKeyNotFound, errorCode);
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)
+ private void EnsureNotDisposed()
{
- 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)
+ if (hkey == null)
{
- i = 0;
- int j = 0;
- while (i < length)
- {
- if(path[i] == markerChar)
- {
- i++;
- continue;
- }
- path[j] = path[i];
- i++;
- j++;
- }
- path.Length += j - i;
- }
-
- }
-
- private void CheckPermission(RegistryInternalCheck check, string item, bool subKeyWritable, RegistryKeyPermissionCheck subKeyCheck)
- {
- // TODO: Cleanup
- }
-
- 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;
- }
-
- private void EnsureNotDisposed(){
- if (hkey == null) {
ThrowHelper.ThrowObjectDisposedException(keyName, ExceptionResource.ObjectDisposed_RegKeyClosed);
}
}
- private void EnsureWriteable() {
+ private void EnsureWriteable()
+ {
EnsureNotDisposed();
- if (!IsWritable()) {
+ 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;
- }
-
- 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) {
+ static private void ValidateKeyName(string name)
+ {
+ if (name == null)
+ {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.name);
}
int nextSlash = name.IndexOf("\\", StringComparison.OrdinalIgnoreCase);
int current = 0;
- while (nextSlash != -1) {
+ while (nextSlash != -1)
+ {
if ((nextSlash - current) > MaxKeyLength)
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegKeyStrLenBug);
@@ -1111,32 +658,11 @@ namespace Microsoft.Win32
if ((name.Length - current) > MaxKeyLength)
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegKeyStrLenBug);
-
- }
-
- static private void ValidateKeyView(RegistryView view) {
- if (view != RegistryView.Default && view != RegistryView.Registry32 && view != RegistryView.Registry64) {
- ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidRegistryViewCheck, ExceptionArgument.view);
- }
}
// 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_FROM_SYSTEM = 0x00001000;
private const int FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000;
}
-
- [Flags]
- internal enum RegistryValueOptions {
- None = 0,
- DoNotExpandEnvironmentNames = 1
- }
-
- // the name for this API is meant to mimic FileMode, which has similar values
-
- internal enum RegistryKeyPermissionCheck {
- Default = 0,
- ReadSubTree = 1,
- ReadWriteSubTree = 2
- }
}