public void DeleteValue(String name, bool throwOnMissingValue) { EnsureWriteable(); 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); }
public void DeleteSubKeyTree(string subkey, bool 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(SR.Arg_RegKeyDelHive); } EnsureWriteable(); subkey = FixupName(subkey); // Fixup multiple slashes to a single slash RegistryKey key = InternalOpenSubKeyWithoutSecurityChecks(subkey, true); if (key != null) { using (key) { if (key.InternalSubKeyCount() > 0) { string[] keys = key.InternalGetSubKeyNames(); for (int i = 0; i < keys.Length; i++) { key.DeleteSubKeyTreeInternal(keys[i]); } } } DeleteSubKeyTreeCore(subkey); } else if (throwOnMissingSubKey) { ThrowHelper.ThrowArgumentException(SR.Arg_RegSubKeyAbsent); } }
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); if (ret == 0 && !result.IsInvalid) { RegistryKey key = new RegistryKey(result, IsWritable((int)rights), false, _remoteKey, false, _regView); key._keyName = _keyName + "\\" + name; return key; } if (throwOnPermissionFailure) { if (ret == Interop.mincore.Errors.ERROR_ACCESS_DENIED || ret == Interop.mincore.Errors.ERROR_BAD_IMPERSONATION_LEVEL) { // We need to throw SecurityException here for compatibility reason, // although UnauthorizedAccessException will make more sense. ThrowHelper.ThrowSecurityException(SR.Security_RegistryPermission); } } // Return null if we didn't find the key. return null; }
private static void ValidateKeyName(string name) { if (name == null) { ThrowHelper.ThrowArgumentNullException(nameof(name)); } int nextSlash = name.IndexOf("\\", StringComparison.OrdinalIgnoreCase); int current = 0; while (nextSlash != -1) { if ((nextSlash - current) > MaxKeyLength) { ThrowHelper.ThrowArgumentException(SR.Arg_RegKeyStrLenBug, nameof(name)); } current = nextSlash + 1; nextSlash = name.IndexOf("\\", current, StringComparison.OrdinalIgnoreCase); } if ((name.Length - current) > MaxKeyLength) { ThrowHelper.ThrowArgumentException(SR.Arg_RegKeyStrLenBug, nameof(name)); } }
/// <summary> /// 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. /// </summary> private void DeleteSubKeyTreeInternal(string subkey) { RegistryKey key = InternalOpenSubKeyWithoutSecurityChecks(subkey, true); if (key != null) { using (key) { if (key.InternalSubKeyCount() > 0) { string[] keys = key.InternalGetSubKeyNames(); for (int i = 0; i < keys.Length; i++) { key.DeleteSubKeyTreeInternal(keys[i]); } } } DeleteSubKeyTreeCore(subkey); } else { ThrowHelper.ThrowArgumentException(SR.Arg_RegSubKeyAbsent); } }
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(SR.Arg_RegValStrLenBug); } if (!Enum.IsDefined(typeof(RegistryValueKind), valueKind)) { throw new ArgumentException(SR.Arg_RegBadKeyKind, nameof(valueKind)); } EnsureWriteable(); 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 unsafe void SetValueCore(string name, object value, RegistryValueKind valueKind) { int ret = 0; try { switch (valueKind) { case RegistryValueKind.ExpandString: case RegistryValueKind.String: { string data = value.ToString(); ret = Interop.Advapi32.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()); // First determine the size of the array // // Format is null terminator between strings and final null terminator at the end. // e.g. str1\0str2\0str3\0\0 // int sizeInChars = 1; // no matter what, we have the final null terminator. for (int i = 0; i < dataStrings.Length; i++) { if (dataStrings[i] == null) { ThrowHelper.ThrowArgumentException(SR.Arg_RegSetStrArrNull); } sizeInChars = checked (sizeInChars + (dataStrings[i].Length + 1)); } int sizeInBytes = checked (sizeInChars * sizeof(char)); // Write out the strings... // char[] dataChars = new char[sizeInChars]; int destinationIndex = 0; for (int i = 0; i < dataStrings.Length; i++) { int length = dataStrings[i].Length; dataStrings[i].CopyTo(0, dataChars, destinationIndex, length); destinationIndex += (length + 1); // +1 for null terminator, which is already zero-initialized in new array. } ret = Interop.Advapi32.RegSetValueEx(_hkey, name, 0, RegistryValueKind.MultiString, dataChars, sizeInBytes); break; } case RegistryValueKind.None: case RegistryValueKind.Binary: byte[] dataBytes = (byte[])value; ret = Interop.Advapi32.RegSetValueEx(_hkey, name, 0, (valueKind == RegistryValueKind.None ? Interop.Advapi32.RegistryValues.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 = Interop.Advapi32.RegSetValueEx(_hkey, name, 0, RegistryValueKind.DWord, ref data, 4); break; } case RegistryValueKind.QWord: { long data = Convert.ToInt64(value, System.Globalization.CultureInfo.InvariantCulture); ret = Interop.Advapi32.RegSetValueEx(_hkey, name, 0, RegistryValueKind.QWord, ref data, 8); break; } } } catch (Exception exc) when(exc is OverflowException || exc is InvalidOperationException || exc is FormatException || exc is InvalidCastException) { ThrowHelper.ThrowArgumentException(SR.Arg_RegSetMismatchedKind); } if (ret == 0) { SetDirty(); } else { Win32Error(ret, null); } }