Add a test verifying that subkeys are correctly renamed and enumerated in the expected order after calling NtRenameKey.
See merge request !9247.
Signed-off-by: chenzhengyong chenzhengyong@uniontech.com
From: chenzhengyong chenzhengyong@uniontech.com
Add a test verifying that subkeys are correctly renamed and enumerated in the expected order after calling NtRenameKey.
See merge request !9247.
Signed-off-by: chenzhengyong chenzhengyong@uniontech.com --- dlls/ntdll/tests/reg.c | 116 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 0e191a125cc..7859a7f8b3c 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -2409,6 +2409,121 @@ static void test_NtRenameKey(void) pNtClose(key); }
+/* rename key and check it */ +static void test_NtRenameKey_check(void) +{ + OBJECT_ATTRIBUTES attr, sub_attr; + UNICODE_STRING sub_name, new_name; + HANDLE hkey = NULL, hsub_b = NULL, hsub_c = NULL, hsub_d = NULL; + char buffer[256]; + DWORD size; + NTSTATUS status; + const WCHAR *expected_names[3]; + int expected_count, i; + PKEY_BASIC_INFORMATION info; + BOOL match; + + InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); + status = pNtCreateKey(&hkey, KEY_READ|DELETE, &attr, 0, 0, 0, 0); + ok(!status, "Unexpected status %#lx.\n", status); + + /* create subkey b, c, d */ + sub_attr = attr; + sub_attr.RootDirectory = hkey; + sub_attr.ObjectName = &sub_name; + + pRtlCreateUnicodeStringFromAsciiz(&sub_name, "b"); + status = pNtCreateKey(&hsub_b, KEY_ALL_ACCESS, &sub_attr, 0, 0, 0, 0); + ok(!status, "Create subkey 'b' failed, status %#lx\n", status); + + pRtlCreateUnicodeStringFromAsciiz(&sub_name, "c"); + status = pNtCreateKey(&hsub_c, KEY_ALL_ACCESS, &sub_attr, 0, 0, 0, 0); + ok(!status, "Create subkey 'c' failed, status %#lx\n", status); + + pRtlCreateUnicodeStringFromAsciiz(&sub_name, "d"); + status = pNtCreateKey(&hsub_d, KEY_ALL_ACCESS, &sub_attr, 0, 0, 0, 0); + ok(!status, "Create subkey 'd' failed, status %#lx\n", status); + + /* rename "b" to "a" */ + pRtlCreateUnicodeStringFromAsciiz(&new_name, "a"); + status = NtRenameKey(hsub_b, &new_name); + ok(!status, "NtRenameKey failed, status %#lx\n", status); + + /* expected subkeys: a, c, d */ + expected_names[0] = L"a"; + expected_names[1] = L"c"; + expected_names[2] = L"d"; + expected_count = ARRAY_SIZE(expected_names); + + for (i = 0;; i++) + { + info = (PKEY_BASIC_INFORMATION)buffer; + status = pNtEnumerateKey(hkey, i, KeyBasicInformation, info, sizeof(buffer), &size); + if (status == STATUS_NO_MORE_ENTRIES) + { + ok(i == expected_count, "Expected %d subkeys, found %d\n", expected_count, i); + break; + } + + ok(!status, "NtEnumerateKey failed, status %#lx\n", status); + if (status) + break; + + info->Name[info->NameLength / sizeof(WCHAR)] = 0; + + if (i < expected_count) + { + match = !wcscmp(info->Name, expected_names[i]); + ok(match, "Expected subkey[%d] '%S', got '%S'\n", + i, expected_names[i], info->Name); + } + } + + /* rename "a" -> "b" again */ + pRtlCreateUnicodeStringFromAsciiz(&new_name, "b"); + status = NtRenameKey(hsub_b, &new_name); + ok(!status, "NtRenameKey failed, status %#lx\n", status); + + /* expected subkeys: b, c, d */ + expected_names[0] = L"b"; + expected_names[1] = L"c"; + expected_names[2] = L"d"; + + for (i = 0;; i++) + { + info = (PKEY_BASIC_INFORMATION)buffer; + status = pNtEnumerateKey(hkey, i, KeyBasicInformation, info, sizeof(buffer), &size); + if (status == STATUS_NO_MORE_ENTRIES) + { + ok(i == expected_count, "Expected %d subkeys, found %d\n", expected_count, i); + break; + } + + ok(!status, "NtEnumerateKey failed, status %#lx\n", status); + if (status) + break; + + info->Name[info->NameLength / sizeof(WCHAR)] = 0; + + if (i < expected_count) + { + match = !wcscmp(info->Name, expected_names[i]); + ok(match, "Expected subkey[%d] '%S', got '%S'\n", + i, expected_names[i], info->Name); + } + } + + /* clean */ + pNtDeleteKey(hsub_b); + pNtDeleteKey(hsub_c); + pNtDeleteKey(hsub_d); + pNtDeleteKey(hkey); + pNtClose(hsub_b); + pNtClose(hsub_c); + pNtClose(hsub_d); + pNtClose(hkey); +} + static BOOL set_privileges(LPCSTR privilege, BOOL set) { TOKEN_PRIVILEGES tp; @@ -3100,6 +3215,7 @@ START_TEST(reg) test_symlinks(); test_redirection(); test_NtRenameKey(); + test_NtRenameKey_check(); test_NtRegLoadKeyEx(); test_RtlQueryRegistryValues();
Nikolay Sivov (@nsivov) commented about dlls/ntdll/tests/reg.c:
pNtClose(key);}
+/* rename key and check it */ +static void test_NtRenameKey_check(void)
I think using existing function is better.
Nikolay Sivov (@nsivov) commented about dlls/ntdll/tests/reg.c:
break;}ok(!status, "NtEnumerateKey failed, status %#lx\n", status);if (status)break;info->Name[info->NameLength / sizeof(WCHAR)] = 0;if (i < expected_count){match = !wcscmp(info->Name, expected_names[i]);ok(match, "Expected subkey[%d] '%S', got '%S'\n",i, expected_names[i], info->Name);}- }
This could be a helper, but probably not critical, since it's used only twice so far.
I'm only curious, why have you thought that key order might change?
On Wed Oct 29 07:04:17 2025 +0000, Nikolay Sivov wrote:
I think using existing function is better.
OK, I'll add to existing function