/** * 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); 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); }
/// <summary> /// Retrieves an array of strings containing all the value names. /// </summary> public unsafe string[] GetValueNames() { EnsureNotDisposed(); var names = new List <string>(); // 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); 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) { 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.ToArray()); }