[PATCH v2 0/1] MR9303: ntdll/tests: Add NtRenameKey tests checking subkey after rename.
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(a)uniontech.com> -- v2: ntdll/tests: Add NtRenameKey tests checking subkey after rename. https://gitlab.winehq.org/wine/wine/-/merge_requests/9303
From: chenzhengyong <chenzhengyong(a)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(a)uniontech.com> --- dlls/ntdll/tests/reg.c | 94 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 4 deletions(-) diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 0e191a125cc..e2cbc3217f1 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -2344,15 +2344,54 @@ static void test_RtlCreateRegistryKey(void) pRtlFreeUnicodeString(&str); } +/* helper function for test_NtRenameKey */ +static void check_subkeys(HANDLE key, const WCHAR **expected_names, int expected_count) +{ + NTSTATUS status; + DWORD size; + int i; + char buffer[200]; + PKEY_BASIC_INFORMATION info; + BOOL match; + + for (i = 0;; i++) + { + info = (PKEY_BASIC_INFORMATION)buffer; + status = pNtEnumerateKey(key, 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); + + info->Name[info->NameLength / sizeof(WCHAR)] = 0; + + match = FALSE; + for (int j = 0; j < expected_count; j++) + { + if (!wcscmp(info->Name, expected_names[j])) + { + match = TRUE; + break; + } + } + ok(match, "Unexpected subkey name %s.\n", wine_dbgstr_w(info->Name)); + } +} + static void test_NtRenameKey(void) { KEY_NAME_INFORMATION *info = NULL; UNICODE_STRING str, str2; OBJECT_ATTRIBUTES attr; - HANDLE key, subkey; + HANDLE key, subkey, hsub_b, hsub_c, hsub_d; char buffer[200]; NTSTATUS status; DWORD size; + const WCHAR *expected_names[4]; + int expected_count; status = NtRenameKey(NULL, NULL); ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#lx.\n", status); @@ -2391,9 +2430,6 @@ static void test_NtRenameKey(void) status = NtRenameKey(subkey, &str2); ok(!status, "Unexpected status %#lx.\n", status); - pRtlFreeUnicodeString(&str2); - pRtlFreeUnicodeString(&str); - info = (KEY_NAME_INFORMATION *)buffer; status = pNtQueryKey(subkey, KeyNameInformation, info, sizeof(buffer), &size); ok(!status, "Unexpected status %#lx.\n", status); @@ -2403,6 +2439,56 @@ static void test_NtRenameKey(void) ok(!!wcsstr(info->Name, L"renamed_subkey"), "Unexpected subkey name %s.\n", wine_dbgstr_w(info->Name)); } + /* create subkey b, c, d */ + pRtlCreateUnicodeStringFromAsciiz(&str, "b"); + status = pNtCreateKey(&hsub_b, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0); + ok(!status, "Create subkey 'b' failed, status %#lx\n", status); + + pRtlCreateUnicodeStringFromAsciiz(&str, "c"); + status = pNtCreateKey(&hsub_c, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0); + ok(!status, "Create subkey 'c' failed, status %#lx\n", status); + + pRtlCreateUnicodeStringFromAsciiz(&str, "d"); + status = pNtCreateKey(&hsub_d, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0); + ok(!status, "Create subkey 'd' failed, status %#lx\n", status); + + /* rename "b" to "a" */ + pRtlCreateUnicodeStringFromAsciiz(&str2, "a"); + status = NtRenameKey(hsub_b, &str2); + 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_names[3] = L"renamed_subkey"; + expected_count = ARRAY_SIZE(expected_names); + check_subkeys(key, expected_names, expected_count); + + /* rename "a" -> "b" again */ + pRtlCreateUnicodeStringFromAsciiz(&str2, "b"); + status = NtRenameKey(hsub_b, &str2); + 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"; + expected_names[3] = L"renamed_subkey"; + expected_count = ARRAY_SIZE(expected_names); + check_subkeys(key, expected_names, expected_count); + + /* clean */ + pRtlFreeUnicodeString(&str2); + pRtlFreeUnicodeString(&str); + + pNtDeleteKey(hsub_b); + pNtDeleteKey(hsub_c); + pNtDeleteKey(hsub_d); + pNtClose(hsub_b); + pNtClose(hsub_c); + pNtClose(hsub_d); + pNtDeleteKey(subkey); pNtDeleteKey(key); pNtClose(subkey); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9303
On Wed Oct 29 12:12:49 2025 +0000, Nikolay Sivov wrote:
I'm only curious, why have you thought that key order might change? It is not about checking the order of the subkeys, but rather verifying whether the subkey names are correct after renaming, because according to MR !!9247, modifying a key value may also alter subsequent key values.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9303#note_119980
On Wed Oct 29 12:12:49 2025 +0000, zhengyong chen wrote:
It is not about checking the order of the subkeys, but rather verifying whether the subkey names are correct after renaming, because according to MR !!9247, modifying a key value may also alter subsequent key values. Before !!9247, if we have subkeys **`[a, c, d, renamed_key]`** where:
* **`a`** is at **`cur_index = 0`** * If renaming a to b, after find_subkey, **`index = 1`** * After rename_key, will get \[b, b, d, **`renamed_key`**\] This test can verify this prolem -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9303#note_119983
participants (2)
-
chenzhengyong -
zhengyong chen (@chenzhengyong)