Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit b047ab4

Browse files
committed
Merge pull request #2577 from Maxwe11/win32-registry-improvements
Win32.Registry improvements
2 parents a73b4d7 + 373acc9 commit b047ab4

File tree

3 files changed

+59
-23
lines changed

3 files changed

+59
-23
lines changed

src/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -842,10 +842,10 @@ internal unsafe String[] InternalGetSubKeyNames()
842842
{
843843
EnsureNotDisposed();
844844
int subkeys = InternalSubKeyCount();
845-
String[] names = new String[subkeys]; // Returns 0-length array if empty.
846845

847846
if (subkeys > 0)
848847
{
848+
String[] names = new String[subkeys];
849849
char[] name = new char[MaxKeyLength + 1];
850850

851851
int namelen;
@@ -868,9 +868,11 @@ internal unsafe String[] InternalGetSubKeyNames()
868868
names[i] = new String(namePtr);
869869
}
870870
}
871+
872+
return names;
871873
}
872874

873-
return names;
875+
return Array.Empty<String>();
874876
}
875877

876878
/**
@@ -921,10 +923,10 @@ public unsafe String[] GetValueNames()
921923
EnsureNotDisposed();
922924

923925
int values = InternalValueCount();
924-
String[] names = new String[values];
925926

926927
if (values > 0)
927928
{
929+
String[] names = new String[values];
928930
char[] name = new char[MaxValueLength + 1];
929931
int namelen;
930932

@@ -953,9 +955,11 @@ public unsafe String[] GetValueNames()
953955
names[i] = new String(namePtr);
954956
}
955957
}
958+
959+
return names;
956960
}
957961

958-
return names;
962+
return Array.Empty<String>();
959963
}
960964

961965
/**
@@ -1201,10 +1205,7 @@ internal Object InternalGetValue(String name, Object defaultValue, bool doNotExp
12011205
try
12021206
{
12031207
char[] newBlob = new char[checked(blob.Length + 1)];
1204-
for (int i = 0; i < blob.Length; i++)
1205-
{
1206-
newBlob[i] = blob[i];
1207-
}
1208+
Array.Copy(blob, 0, newBlob, 0, blob.Length);
12081209
newBlob[newBlob.Length - 1] = (char)0;
12091210
blob = newBlob;
12101211
}
@@ -1215,8 +1216,7 @@ internal Object InternalGetValue(String name, Object defaultValue, bool doNotExp
12151216
blob[blob.Length - 1] = (char)0;
12161217
}
12171218

1218-
1219-
IList<String> strings = new List<String>();
1219+
var strings = new List<String>();
12201220
int cur = 0;
12211221
int len = blob.Length;
12221222

@@ -1250,8 +1250,7 @@ internal Object InternalGetValue(String name, Object defaultValue, bool doNotExp
12501250
cur = nextNull + 1;
12511251
}
12521252

1253-
data = new String[strings.Count];
1254-
strings.CopyTo((String[])data, 0);
1253+
data = strings.ToArray();
12551254
}
12561255
break;
12571256
case Interop.mincore.RegistryValues.REG_LINK:

src/Microsoft.Win32.Registry/tests/Registry/Registry_Getvalue_str_str_obj.cs

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ public static void NegativeTests()
2626

2727
// Passing a string which does NOT start with one of the valid base key names, that should throw ArgumentException.
2828
Assert.Throws<ArgumentException>(() => Registry.GetValue("HHHH_MMMM", null, null));
29+
30+
// Should throw if passed string which only starts with one of the valid base key names but actually it isn't valid.
31+
Assert.Throws<ArgumentException>(() => Registry.GetValue("HKEY_CURRENT_USER_FOOBAR", null, null));
2932
}
3033

3134
[Fact]
@@ -55,19 +58,26 @@ public static IEnumerable<object[]> TestRegistryKeys
5558
{
5659
return new[]
5760
{
58-
new object[] { Registry.CurrentUser, "Test1" },
59-
new object[] { Registry.LocalMachine, "Test2" },
60-
new object[] { Registry.ClassesRoot, "Test3" },
61-
new object[] { Registry.Users, "Test4" },
62-
new object[] { Registry.PerformanceData, "Test5" },
63-
new object[] { Registry.CurrentConfig, "Test6" },
61+
new object[] { Registry.CurrentUser, "Test1", true },
62+
new object[] { Registry.LocalMachine, "Test2", true },
63+
new object[] { Registry.ClassesRoot, "Test3", true },
64+
new object[] { Registry.Users, "Test4", true },
65+
new object[] { Registry.PerformanceData, "Test5", true },
66+
new object[] { Registry.CurrentConfig, "Test6", true },
67+
68+
new object[] { Registry.CurrentUser, "Test7", false },
69+
new object[] { Registry.LocalMachine, "Test8", false },
70+
new object[] { Registry.ClassesRoot, "Test9", false },
71+
new object[] { Registry.Users, "Test10", false },
72+
new object[] { Registry.PerformanceData, "Test11", false },
73+
new object[] { Registry.CurrentConfig, "Test12", false },
6474
};
6575
}
6676
}
6777

6878
[Theory]
6979
[MemberData("TestRegistryKeys")]
70-
public static void GetValueFromDifferentKeys(RegistryKey key, string valueName)
80+
public static void GetValueFromDifferentKeys(RegistryKey key, string valueName, bool useSeparator)
7181
{
7282
const int expectedValue = 11;
7383
const int defaultValue = 42;
@@ -76,7 +86,9 @@ public static void GetValueFromDifferentKeys(RegistryKey key, string valueName)
7686
key.SetValue(valueName, expectedValue);
7787
try
7888
{
79-
Assert.Equal(expectedValue, (int)Registry.GetValue(key.Name, valueName, defaultValue));
89+
// keyName should be case insensitive so we mix casing
90+
string keyName = MixUpperAndLowerCase(key.Name) + (useSeparator ? "\\" : "");
91+
Assert.Equal(expectedValue, (int)Registry.GetValue(keyName, valueName, defaultValue));
8092
}
8193
finally
8294
{
@@ -89,21 +101,43 @@ public static void GetValueFromDifferentKeys(RegistryKey key, string valueName)
89101

90102
[Theory]
91103
[MemberData("TestRegistryKeys")]
92-
public static void GetDefaultValueFromDifferentKeys(RegistryKey key, string valueName)
104+
public static void GetDefaultValueFromDifferentKeys(RegistryKey key, string valueName, bool useSeparator)
93105
{
106+
// We ignore valueName because we test against default value
94107
valueName = null;
95108
try
96109
{
110+
// keyName should be case insensitive so we mix casing
111+
string keyName = MixUpperAndLowerCase(key.Name) + (useSeparator ? "\\" : "");
97112
if (key.IsDefaultValueSet())
98113
{
99-
Registry.GetValue(key.Name, valueName, null);
114+
Registry.GetValue(keyName, valueName, null);
100115
}
101116
else
102117
{
103-
Assert.Equal(TestData.DefaultValue, Registry.GetValue(key.Name, valueName, TestData.DefaultValue));
118+
Assert.Equal(TestData.DefaultValue, Registry.GetValue(keyName, valueName, TestData.DefaultValue));
104119
}
105120
}
106121
catch (IOException) { }
107122
}
123+
124+
private static string MixUpperAndLowerCase(string str)
125+
{
126+
var builder = new System.Text.StringBuilder(str);
127+
128+
for (int i = 0; i < builder.Length; ++i)
129+
{
130+
if (i % 2 == 0)
131+
{
132+
builder[i] = char.ToLowerInvariant(builder[i]);
133+
}
134+
else
135+
{
136+
builder[i] = char.ToUpperInvariant(builder[i]);
137+
}
138+
}
139+
140+
return builder.ToString();
141+
}
108142
}
109143
}

src/Microsoft.Win32.Registry/tests/Registry/Registry_SetValue_str_str_obj.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ public void NegativeTests()
3838
// Should throw if passed string does NOT start with one of the valid base key names
3939
Assert.Throws<ArgumentException>(() => Registry.SetValue("HHHH_MMMM", "test", "test"));
4040

41+
// Should throw if passed string which only starts with one of the valid base key names but actually it isn't valid.
42+
Assert.Throws<ArgumentException>(() => Registry.SetValue("HKEY_LOCAL_MACHINE_FOOBAR", "test", "test"));
43+
4144
// Should throw if key length above 255 characters but prior to V4, the limit is 16383
4245
const int maxValueNameLength = 16383;
4346
Assert.Throws<ArgumentException>(() => Registry.SetValue(_testRegistryKey.Name, new string('a', maxValueNameLength + 1), 5));

0 commit comments

Comments
 (0)