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);
}
}