From dac03ffdd55e5a9c16e73c0335f95591ec2f24d8 Mon Sep 17 00:00:00 2001 From: Poppyto Date: Tue, 22 Nov 2022 23:50:21 +0100 Subject: [PATCH 1/3] Avoid redondant verification EnsureNotDisposed() already called by SubKeyCount & ValueCount. --- .../src/Microsoft/Win32/RegistryKey.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs index 31168f59d2719..c5b341bbf53c3 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs @@ -784,7 +784,6 @@ public static RegistryKey FromHandle(SafeRegistryHandle handle, RegistryView vie /// All subkey names. public string[] GetSubKeyNames() { - EnsureNotDisposed(); int subkeys = SubKeyCount; if (subkeys <= 0) @@ -858,8 +857,6 @@ public int ValueCount /// All value names. public unsafe string[] GetValueNames() { - EnsureNotDisposed(); - int values = ValueCount; if (values <= 0) From 8e53fb0cace017d46f76cc7f5bbe336c349f7c88 Mon Sep 17 00:00:00 2001 From: Poppyto Date: Tue, 22 Nov 2022 23:51:12 +0100 Subject: [PATCH 2/3] Replace List by string[] to avoid List.ToArray() copy (it must handle rare cases where there are more or less elements during the loop). --- .../src/Microsoft/Win32/RegistryKey.cs | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs index c5b341bbf53c3..32a2ba44c6e74 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs @@ -791,16 +791,17 @@ public string[] GetSubKeyNames() return Array.Empty(); } - List names = new List(subkeys); - Span name = stackalloc char[MaxKeyLength + 1]; + string[] names = new string[subkeys]; + Span nameSpan = stackalloc char[MaxKeyLength + 1]; int result; - int nameLength = name.Length; + int nameLength = nameSpan.Length; + int cpt = 0; while ((result = Interop.Advapi32.RegEnumKeyEx( _hkey, - names.Count, - ref MemoryMarshal.GetReference(name), + cpt, + ref MemoryMarshal.GetReference(nameSpan), ref nameLength, null, null, @@ -810,8 +811,14 @@ ref MemoryMarshal.GetReference(name), switch (result) { case Interop.Errors.ERROR_SUCCESS: - names.Add(new string(name.Slice(0, nameLength))); - nameLength = name.Length; + + if (cpt >= names.Length) // possible new item during loop + { + Array.Resize(ref names, names.Length * 2); + } + + names[cpt++] = new string(nameSpan.Slice(0, nameLength)); + nameLength = nameSpan.Length; break; default: // Throw the error @@ -820,7 +827,13 @@ ref MemoryMarshal.GetReference(name), } } - return names.ToArray(); + // Shrink array to fit found items, if necessary + if (cpt < names.Length) + { + Array.Resize(ref names, cpt); + } + + return names; } /// Retrieves the count of values. From 14fdd77c93d189e4f1c28a17103f66e31e72e00a Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Thu, 1 Dec 2022 14:21:25 -0500 Subject: [PATCH 3/3] Apply suggestions from code review --- .../Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs index 32a2ba44c6e74..023b22f198ee8 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs @@ -811,7 +811,6 @@ ref MemoryMarshal.GetReference(nameSpan), switch (result) { case Interop.Errors.ERROR_SUCCESS: - if (cpt >= names.Length) // possible new item during loop { Array.Resize(ref names, names.Length * 2); @@ -820,6 +819,7 @@ ref MemoryMarshal.GetReference(nameSpan), names[cpt++] = new string(nameSpan.Slice(0, nameLength)); nameLength = nameSpan.Length; break; + default: // Throw the error Win32Error(result, null);