Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.Windows.cs')
-rw-r--r--src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.Windows.cs172
1 files changed, 112 insertions, 60 deletions
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.Windows.cs b/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.Windows.cs
index 492247757..b9221327e 100644
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.Windows.cs
+++ b/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.Windows.cs
@@ -4,6 +4,7 @@
using Microsoft.Win32.SafeHandles;
using System;
+using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -82,7 +83,7 @@ namespace Microsoft.Win32
{
if (_hkey != null && IsDirty())
{
- Interop.mincore.RegFlushKey(_hkey);
+ Interop.Advapi32.RegFlushKey(_hkey);
}
}
@@ -93,7 +94,7 @@ namespace Microsoft.Win32
// By default, the new key will be writable.
SafeRegistryHandle result = null;
- int ret = Interop.mincore.RegCreateKeyEx(_hkey,
+ int ret = Interop.Advapi32.RegCreateKeyEx(_hkey,
subkey,
0,
null,
@@ -185,7 +186,7 @@ namespace Microsoft.Win32
private RegistryKey InternalOpenSubKeyCore(string name, RegistryRights rights, bool throwOnPermissionFailure)
{
SafeRegistryHandle result = null;
- int ret = Interop.mincore.RegOpenKeyEx(_hkey, name, 0, ((int)rights | (int)_regView), out result);
+ int ret = Interop.Advapi32.RegOpenKeyEx(_hkey, name, 0, ((int)rights | (int)_regView), out result);
if (ret == 0 && !result.IsInvalid)
{
RegistryKey key = new RegistryKey(result, IsWritable((int)rights), false, _remoteKey, false, _regView);
@@ -242,7 +243,7 @@ namespace Microsoft.Win32
// open the base key so that RegistryKey.Handle will return a valid handle
SafeRegistryHandle result;
- ret = Interop.mincore.RegOpenKeyEx(baseKey,
+ ret = Interop.Advapi32.RegOpenKeyEx(baseKey,
null,
0,
(int)GetRegistryKeyRights(IsWritable()) | (int)_regView,
@@ -264,7 +265,7 @@ namespace Microsoft.Win32
{
int subkeys = 0;
int junk = 0;
- int ret = Interop.mincore.RegQueryInfoKey(_hkey,
+ int ret = Interop.Advapi32.RegQueryInfoKey(_hkey,
null,
null,
IntPtr.Zero,
@@ -285,43 +286,52 @@ namespace Microsoft.Win32
return subkeys;
}
- private unsafe string[] InternalGetSubKeyNamesCore(int subkeys)
+ private string[] InternalGetSubKeyNamesCore(int subkeys)
{
- string[] names = new string[subkeys];
- char[] name = new char[MaxKeyLength + 1];
+ var names = new List<string>(subkeys);
+ char[] name = ArrayPool<char>.Shared.Rent(MaxKeyLength + 1);
- int namelen;
-
- fixed (char* namePtr = &name[0])
+ try
{
- for (int i = 0; i < subkeys; i++)
+ int result;
+ int nameLength = name.Length;
+
+ while ((result = Interop.Advapi32.RegEnumKeyEx(
+ _hkey,
+ names.Count,
+ name,
+ ref nameLength,
+ null,
+ null,
+ null,
+ null)) != Interop.Errors.ERROR_NO_MORE_ITEMS)
{
- namelen = name.Length; // Don't remove this. The API's doesn't work if this is not properly initialized.
- int ret = Interop.mincore.RegEnumKeyEx(_hkey,
- i,
- namePtr,
- ref namelen,
- null,
- null,
- null,
- null);
- if (ret != 0)
+ switch (result)
{
- Win32Error(ret, null);
+ case Interop.Errors.ERROR_SUCCESS:
+ names.Add(new string(name, 0, nameLength));
+ nameLength = name.Length;
+ break;
+ default:
+ // Throw the error
+ Win32Error(result, null);
+ break;
}
-
- names[i] = new string(namePtr);
}
}
+ finally
+ {
+ ArrayPool<char>.Shared.Return(name);
+ }
- return names;
+ return names.ToArray();
}
private int InternalValueCountCore()
{
int values = 0;
int junk = 0;
- int ret = Interop.mincore.RegQueryInfoKey(_hkey,
+ int ret = Interop.Advapi32.RegQueryInfoKey(_hkey,
null,
null,
IntPtr.Zero,
@@ -345,37 +355,79 @@ namespace Microsoft.Win32
/// <returns>All value names.</returns>
private unsafe string[] GetValueNamesCore(int values)
{
- string[] names = new string[values];
- char[] name = new char[MaxValueLength + 1];
- int namelen;
+ var names = new List<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.
+
+ char[] name = ArrayPool<char>.Shared.Rent(100);
- fixed (char* namePtr = &name[0])
+ try
{
- for (int i = 0; i < values; i++)
+ int result;
+ int nameLength = name.Length;
+
+ while ((result = Interop.Advapi32.RegEnumValue(
+ _hkey,
+ names.Count,
+ name,
+ ref nameLength,
+ IntPtr.Zero,
+ null,
+ null,
+ null)) != Interop.Errors.ERROR_NO_MORE_ITEMS)
{
- namelen = name.Length;
-
- int ret = Interop.mincore.RegEnumValue(_hkey,
- i,
- namePtr,
- ref namelen,
- IntPtr.Zero,
- null,
- null,
- null);
-
- if (ret != 0)
+ switch (result)
{
- // ignore ERROR_MORE_DATA if we're querying HKEY_PERFORMANCE_DATA
- if (!(IsPerfDataKey() && ret == Interop.Errors.ERROR_MORE_DATA))
- Win32Error(ret, null);
+ // 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;
}
- names[i] = new string(namePtr);
+ // Always set the name length back to the buffer size
+ nameLength = name.Length;
}
}
+ finally
+ {
+ if (name != null)
+ ArrayPool<char>.Shared.Return(name);
+ }
- return names;
+ return names.ToArray();
}
private object InternalGetValueCore(string name, object defaultValue, bool doNotExpand)
@@ -384,7 +436,7 @@ namespace Microsoft.Win32
int type = 0;
int datasize = 0;
- int ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, (byte[])null, ref datasize);
+ int ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, (byte[])null, ref datasize);
if (ret != 0)
{
@@ -395,7 +447,7 @@ namespace Microsoft.Win32
int r;
byte[] blob = new byte[size];
- while (Interop.Errors.ERROR_MORE_DATA == (r = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, blob, ref sizeInput)))
+ while (Interop.Errors.ERROR_MORE_DATA == (r = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, blob, ref sizeInput)))
{
if (size == int.MaxValue)
{
@@ -446,7 +498,7 @@ namespace Microsoft.Win32
case Interop.Advapi32.RegistryValues.REG_BINARY:
{
byte[] blob = new byte[datasize];
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
+ ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
data = blob;
}
break;
@@ -460,7 +512,7 @@ namespace Microsoft.Win32
long blob = 0;
Debug.Assert(datasize == 8, "datasize==8");
// Here, datasize must be 8 when calling this
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, ref blob, ref datasize);
+ ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, ref blob, ref datasize);
data = blob;
}
@@ -475,7 +527,7 @@ namespace Microsoft.Win32
int blob = 0;
Debug.Assert(datasize == 4, "datasize==4");
// Here, datasize must be four when calling this
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, ref blob, ref datasize);
+ ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, ref blob, ref datasize);
data = blob;
}
@@ -497,7 +549,7 @@ namespace Microsoft.Win32
}
char[] blob = new char[datasize / 2];
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
+ ret = Interop.Advapi32.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);
@@ -527,7 +579,7 @@ namespace Microsoft.Win32
}
char[] blob = new char[datasize / 2];
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
+ ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
if (blob.Length > 0 && blob[blob.Length - 1] == (char)0)
{
@@ -562,7 +614,7 @@ namespace Microsoft.Win32
}
char[] blob = new char[datasize / 2];
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
+ ret = Interop.Advapi32.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)
@@ -634,7 +686,7 @@ namespace Microsoft.Win32
{
int type = 0;
int datasize = 0;
- int ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, (byte[])null, ref datasize);
+ int ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, (byte[])null, ref datasize);
if (ret != 0)
{
Win32Error(ret, null);
@@ -719,8 +771,8 @@ namespace Microsoft.Win32
private static bool IsWritable(int rights)
{
- return (rights & (Interop.mincore.RegistryOperations.KEY_SET_VALUE |
- Interop.mincore.RegistryOperations.KEY_CREATE_SUB_KEY |
+ return (rights & (Interop.Advapi32.RegistryOperations.KEY_SET_VALUE |
+ Interop.Advapi32.RegistryOperations.KEY_CREATE_SUB_KEY |
(int)RegistryRights.Delete |
(int)RegistryRights.TakeOwnership |
(int)RegistryRights.ChangePermissions)) != 0;