From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ntdll/tests/reg.c | 69 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 2c158be17b4..b0cbf137086 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -2115,6 +2115,74 @@ static void test_RtlCreateRegistryKey(void) pRtlFreeUnicodeString(&str); }
+static void test_NtRenameKey(void) +{ + KEY_NAME_INFORMATION *info = NULL; + UNICODE_STRING str, str2; + OBJECT_ATTRIBUTES attr; + HANDLE key, subkey; + char buffer[200]; + NTSTATUS status; + DWORD size; + + status = NtRenameKey(NULL, NULL); + todo_wine + ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#lx.\n", status); + + InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); + status = pNtCreateKey(&key, KEY_READ|DELETE, &attr, 0, 0, 0, 0); + ok(!status, "Unexpected status %#lx.\n", status); + + attr.RootDirectory = key; + attr.ObjectName = &str; + + pRtlCreateUnicodeStringFromAsciiz(&str, "rename_subkey"); + status = pNtCreateKey(&subkey, KEY_READ|DELETE, &attr, 0, 0, 0, 0); + ok(!status, "Unexpected status %#lx.\n", status); + + pRtlCreateUnicodeStringFromAsciiz(&str2, "renamed_subkey"); + + status = NtRenameKey(subkey, NULL); + todo_wine + ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#lx.\n", status); + status = NtRenameKey(NULL, &str); + todo_wine + ok(status == STATUS_INVALID_HANDLE, "Unexpected status %#lx.\n", status); + + status = NtRenameKey(subkey, &str2); + todo_wine + ok(status == STATUS_ACCESS_DENIED, "Unexpected status %#lx.\n", status); + pNtClose(subkey); + + status = pNtCreateKey(&subkey, KEY_WRITE|DELETE, &attr, 0, 0, 0, 0); + ok(!status, "Unexpected status %#lx.\n", status); + /* Rename to itself. */ + status = NtRenameKey(subkey, &str); + todo_wine + ok(status == STATUS_CANNOT_DELETE, "Unexpected status %#lx.\n", status); + status = NtRenameKey(subkey, &str2); + todo_wine + ok(!status, "Unexpected status %#lx.\n", status); + + pRtlFreeUnicodeString(&str2); + pRtlFreeUnicodeString(&str); + + info = (KEY_NAME_INFORMATION *)buffer; + status = pNtQueryKey(subkey, KeyNameInformation, info, sizeof(buffer), &size); + todo_wine + ok(!status, "Unexpected status %#lx.\n", status); + if (status == STATUS_SUCCESS) + { + info->Name[info->NameLength/sizeof(WCHAR)] = 0; + ok(!!wcsstr(info->Name, L"renamed_subkey"), "Unexpected subkey name %s.\n", wine_dbgstr_w(info->Name)); + } + + pNtDeleteKey(subkey); + pNtDeleteKey(key); + pNtClose(subkey); + pNtClose(key); +} + START_TEST(reg) { static const WCHAR winetest[] = {'\','W','i','n','e','T','e','s','t',0}; @@ -2144,6 +2212,7 @@ START_TEST(reg) test_NtDeleteKey(); test_symlinks(); test_redirection(); + test_NtRenameKey();
pRtlFreeUnicodeString(&winetestpath);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/advapi32/tests/registry.c | 73 ++++++++++++++++++++++++++++++++++ include/winreg.h | 1 + 2 files changed, 74 insertions(+)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 6152a313803..c2e78192f2e 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -4475,6 +4475,78 @@ static void test_EnumDynamicTimeZoneInformation(void) RegCloseKey(key); }
+static void test_RegRenameKey(void) +{ + HKEY key, key2; + LSTATUS ret; + + ret = RegRenameKey(NULL, NULL, NULL); + todo_wine + ok(ret == ERROR_INVALID_PARAMETER, "Unexpected return value %ld.\n", ret); + ret = RegRenameKey(NULL, NULL, L"newname"); + todo_wine + ok(ret == ERROR_INVALID_HANDLE, "Unexpected return value %ld.\n", ret); + ret = RegRenameKey(NULL, L"oldname", NULL); + todo_wine + ok(ret == ERROR_INVALID_HANDLE, "Unexpected return value %ld.\n", ret); + ret = RegRenameKey(NULL, L"oldname", L"newname"); + todo_wine + ok(ret == ERROR_INVALID_HANDLE, "Unexpected return value %ld.\n", ret); + + ret = RegCreateKeyExA(hkey_main, "TestRenameKey", 0, NULL, 0, KEY_READ, NULL, &key, NULL); + ok(!ret, "Unexpected return value %ld.\n", ret); + ret = RegRenameKey(key, NULL, L"TestNewRenameKey"); + todo_wine + ok(ret == ERROR_ACCESS_DENIED, "Unexpected return value %ld.\n", ret); + RegCloseKey(key); + + /* Rename itself. */ + ret = RegCreateKeyExA(hkey_main, "TestRenameKey", 0, NULL, 0, KEY_WRITE, NULL, &key, NULL); + ok(!ret, "Unexpected return value %ld.\n", ret); + ret = RegRenameKey(key, NULL, NULL); + todo_wine + ok(ret == ERROR_INVALID_PARAMETER, "Unexpected return value %ld.\n", ret); + ret = RegRenameKey(key, NULL, L"TestNewRenameKey"); + todo_wine + ok(!ret, "Unexpected return value %ld.\n", ret); + RegCloseKey(key); + + ret = RegDeleteKeyA(hkey_main, "TestNewRenameKey"); + todo_wine + ok(!ret, "Unexpected return value %ld.\n", ret); + ret = RegDeleteKeyA(hkey_main, "TestRenameKey"); + todo_wine + ok(ret, "Unexpected return value %ld.\n", ret); + + /* Subkey does not exist. */ + ret = RegCreateKeyExA(hkey_main, "TestRenameKey", 0, NULL, 0, KEY_WRITE, NULL, &key, NULL); + ok(!ret, "Unexpected return value %ld.\n", ret); + ret = RegRenameKey(key, L"unknown_subkey", NULL); + todo_wine + ok(ret == ERROR_FILE_NOT_FOUND, "Unexpected return value %ld.\n", ret); + ret = RegRenameKey(key, L"unknown_subkey", L"known_subkey"); + todo_wine + ok(ret == ERROR_FILE_NOT_FOUND, "Unexpected return value %ld.\n", ret); + + /* Rename existing subkey. */ + ret = RegCreateKeyExA(key, "known_subkey", 0, NULL, 0, KEY_WRITE, NULL, &key2, NULL); + ok(!ret, "Unexpected return value %ld.\n", ret); + RegCloseKey(key2); + + ret = RegRenameKey(key, L"known_subkey", L"renamed_subkey"); + todo_wine + ok(!ret, "Unexpected return value %ld.\n", ret); + + ret = RegDeleteKeyA(key, "renamed_subkey"); + todo_wine + ok(!ret, "Unexpected return value %ld.\n", ret); + ret = RegDeleteKeyA(key, "known_subkey"); + todo_wine + ok(ret, "Unexpected return value %ld.\n", ret); + + RegCloseKey(key); +} + START_TEST(registry) { /* Load pointers for functions that are not available in all Windows versions */ @@ -4514,6 +4586,7 @@ START_TEST(registry) test_RegLoadMUIString(); test_EnumDynamicTimeZoneInformation(); test_perflib_key(); + test_RegRenameKey();
/* cleanup */ delete_key( hkey_main ); diff --git a/include/winreg.h b/include/winreg.h index 00bc8c02dc8..da92fb11f94 100644 --- a/include/winreg.h +++ b/include/winreg.h @@ -178,6 +178,7 @@ WINADVAPI LSTATUS WINAPI RegQueryValueW(HKEY,LPCWSTR,LPWSTR,LPLONG); WINADVAPI LSTATUS WINAPI RegQueryValueExA(HKEY,LPCSTR,LPDWORD,LPDWORD,LPBYTE,LPDWORD); WINADVAPI LSTATUS WINAPI RegQueryValueExW(HKEY,LPCWSTR,LPDWORD,LPDWORD,LPBYTE,LPDWORD); #define RegQueryValueEx WINELIB_NAME_AW(RegQueryValueEx) +WINADVAPI LSTATUS WINAPI RegRenameKey(HKEY,LPCWSTR,LPCWSTR); WINADVAPI LSTATUS WINAPI RegReplaceKeyA(HKEY,LPCSTR,LPCSTR,LPCSTR); WINADVAPI LSTATUS WINAPI RegReplaceKeyW(HKEY,LPCWSTR,LPCWSTR,LPCWSTR); #define RegReplaceKey WINELIB_NAME_AW(RegReplaceKey)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116601
Your paranoid android.
=== w1064_tsign (64 bit report) ===
advapi32: registry.c:3471: Test failed: expected ERROR_SUCCESS, got 6 registry.c:3599: Test failed: expected WAIT_OBJECT_0, got 258
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ntdll/tests/reg.c | 10 ++++------ dlls/ntdll/unix/registry.c | 19 ++++++++++++++++--- include/wine/server_protocol.h | 18 +++++++++++++++++- server/protocol.def | 7 +++++++ server/registry.c | 32 ++++++++++++++++++++++++++++++++ server/request.h | 4 ++++ server/trace.c | 9 +++++++++ 7 files changed, 89 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index b0cbf137086..7c9d4914ba7 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -2126,7 +2126,6 @@ static void test_NtRenameKey(void) DWORD size;
status = NtRenameKey(NULL, NULL); - todo_wine ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#lx.\n", status);
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); @@ -2140,17 +2139,18 @@ static void test_NtRenameKey(void) status = pNtCreateKey(&subkey, KEY_READ|DELETE, &attr, 0, 0, 0, 0); ok(!status, "Unexpected status %#lx.\n", status);
+ memset(&str2, 0, sizeof(str2)); + status = NtRenameKey(subkey, &str2); + ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %#lx.\n", status); + pRtlCreateUnicodeStringFromAsciiz(&str2, "renamed_subkey");
status = NtRenameKey(subkey, NULL); - todo_wine ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#lx.\n", status); status = NtRenameKey(NULL, &str); - todo_wine ok(status == STATUS_INVALID_HANDLE, "Unexpected status %#lx.\n", status);
status = NtRenameKey(subkey, &str2); - todo_wine ok(status == STATUS_ACCESS_DENIED, "Unexpected status %#lx.\n", status); pNtClose(subkey);
@@ -2158,10 +2158,8 @@ static void test_NtRenameKey(void) ok(!status, "Unexpected status %#lx.\n", status); /* Rename to itself. */ status = NtRenameKey(subkey, &str); - todo_wine ok(status == STATUS_CANNOT_DELETE, "Unexpected status %#lx.\n", status); status = NtRenameKey(subkey, &str2); - todo_wine ok(!status, "Unexpected status %#lx.\n", status);
pRtlFreeUnicodeString(&str2); diff --git a/dlls/ntdll/unix/registry.c b/dlls/ntdll/unix/registry.c index 6628454440a..8901c350868 100644 --- a/dlls/ntdll/unix/registry.c +++ b/dlls/ntdll/unix/registry.c @@ -199,10 +199,23 @@ NTSTATUS WINAPI NtDeleteKey( HANDLE key ) /****************************************************************************** * NtRenameKey (NTDLL.@) */ -NTSTATUS WINAPI NtRenameKey( HANDLE handle, UNICODE_STRING *name ) +NTSTATUS WINAPI NtRenameKey( HANDLE key, UNICODE_STRING *name ) { - FIXME( "(%p %s)\n", handle, debugstr_us(name) ); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS ret; + + TRACE( "(%p %s)\n", key, debugstr_us(name) ); + + if (!name) return STATUS_ACCESS_VIOLATION; + if (!name->Buffer || !name->Length) return STATUS_INVALID_PARAMETER; + + SERVER_START_REQ( rename_key ) + { + req->hkey = wine_server_obj_handle( key ); + wine_server_add_data( req, name->Buffer, name->Length ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + return ret; }
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 868add58abf..ce1b2630f53 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2384,6 +2384,19 @@ struct set_registry_notification_reply
+struct rename_key_request +{ + struct request_header __header; + obj_handle_t hkey; + /* VARARG(name,unicode_str); */ +}; +struct rename_key_reply +{ + struct reply_header __header; +}; + + + struct create_timer_request { struct request_header __header; @@ -5538,6 +5551,7 @@ enum request REQ_unload_registry, REQ_save_registry, REQ_set_registry_notification, + REQ_rename_key, REQ_create_timer, REQ_open_timer, REQ_set_timer, @@ -5820,6 +5834,7 @@ union generic_request struct unload_registry_request unload_registry_request; struct save_registry_request save_registry_request; struct set_registry_notification_request set_registry_notification_request; + struct rename_key_request rename_key_request; struct create_timer_request create_timer_request; struct open_timer_request open_timer_request; struct set_timer_request set_timer_request; @@ -6100,6 +6115,7 @@ union generic_reply struct unload_registry_reply unload_registry_reply; struct save_registry_reply save_registry_reply; struct set_registry_notification_reply set_registry_notification_reply; + struct rename_key_reply rename_key_reply; struct create_timer_reply create_timer_reply; struct open_timer_reply open_timer_reply; struct set_timer_reply set_timer_reply; @@ -6288,7 +6304,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 751 +#define SERVER_PROTOCOL_VERSION 752
/* ### protocol_version end ### */
diff --git a/server/protocol.def b/server/protocol.def index 2be1658fca2..1fe2c4410fd 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1837,6 +1837,13 @@ struct process_info @END
+/* Renames a registry key */ +@REQ(rename_key) + obj_handle_t hkey; /* handle to the key to be renamed */ + VARARG(name,unicode_str); /* new name */ +@END + + /* Create a waitable timer */ @REQ(create_timer) unsigned int access; /* wanted access rights */ diff --git a/server/registry.c b/server/registry.c index 93e8a309593..824007f8cf2 100644 --- a/server/registry.c +++ b/server/registry.c @@ -2413,3 +2413,35 @@ DECL_HANDLER(set_registry_notification) release_object( key ); } } + +DECL_HANDLER(rename_key) +{ + struct key *key, *subkey; + struct unicode_str name; + WCHAR *ptr; + int index; + + key = get_hkey_obj( req->hkey, KEY_WRITE ); + if (key) + { + name.str = get_req_data(); + name.len = (get_req_data_size() / sizeof(WCHAR)) * sizeof(WCHAR); + + if (!name.len) + { + set_error( STATUS_INVALID_PARAMETER ); + } + else if (!key->parent || (subkey = find_subkey( key->parent, &name, &index ))) + { + set_error( STATUS_CANNOT_DELETE ); + } + else if ((ptr = memdup( name.str, name.len ))) + { + free( key->name ); + key->name = ptr; + key->namelen = name.len; + } + + release_object( key ); + } +} diff --git a/server/request.h b/server/request.h index 7fd63905e0e..cbb4c5d7a01 100644 --- a/server/request.h +++ b/server/request.h @@ -210,6 +210,7 @@ DECL_HANDLER(load_registry); DECL_HANDLER(unload_registry); DECL_HANDLER(save_registry); DECL_HANDLER(set_registry_notification); +DECL_HANDLER(rename_key); DECL_HANDLER(create_timer); DECL_HANDLER(open_timer); DECL_HANDLER(set_timer); @@ -491,6 +492,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_unload_registry, (req_handler)req_save_registry, (req_handler)req_set_registry_notification, + (req_handler)req_rename_key, (req_handler)req_create_timer, (req_handler)req_open_timer, (req_handler)req_set_timer, @@ -1230,6 +1232,8 @@ C_ASSERT( FIELD_OFFSET(struct set_registry_notification_request, event) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_registry_notification_request, subtree) == 20 ); C_ASSERT( FIELD_OFFSET(struct set_registry_notification_request, filter) == 24 ); C_ASSERT( sizeof(struct set_registry_notification_request) == 32 ); +C_ASSERT( FIELD_OFFSET(struct rename_key_request, hkey) == 12 ); +C_ASSERT( sizeof(struct rename_key_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct create_timer_request, access) == 12 ); C_ASSERT( FIELD_OFFSET(struct create_timer_request, manual) == 16 ); C_ASSERT( sizeof(struct create_timer_request) == 24 ); diff --git a/server/trace.c b/server/trace.c index 15ca4e7d71e..4d4789d050a 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2414,6 +2414,12 @@ static void dump_set_registry_notification_request( const struct set_registry_no fprintf( stderr, ", filter=%08x", req->filter ); }
+static void dump_rename_key_request( const struct rename_key_request *req ) +{ + fprintf( stderr, " hkey=%04x", req->hkey ); + dump_varargs_unicode_str( ", name=", cur_size ); +} + static void dump_create_timer_request( const struct create_timer_request *req ) { fprintf( stderr, " access=%08x", req->access ); @@ -4578,6 +4584,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_unload_registry_request, (dump_func)dump_save_registry_request, (dump_func)dump_set_registry_notification_request, + (dump_func)dump_rename_key_request, (dump_func)dump_create_timer_request, (dump_func)dump_open_timer_request, (dump_func)dump_set_timer_request, @@ -4856,6 +4863,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { NULL, NULL, NULL, + NULL, (dump_func)dump_create_timer_reply, (dump_func)dump_open_timer_reply, (dump_func)dump_set_timer_reply, @@ -5134,6 +5142,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "unload_registry", "save_registry", "set_registry_notification", + "rename_key", "create_timer", "open_timer", "set_timer",
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/advapi32/registry.c | 22 +++++++++++++++++++--- dlls/advapi32/tests/registry.c | 14 -------------- 2 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c index 730ca850c2b..85e883bdcc9 100644 --- a/dlls/advapi32/registry.c +++ b/dlls/advapi32/registry.c @@ -510,10 +510,26 @@ LSTATUS WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile, * RegRenameKey [ADVAPI32.@] * */ -LSTATUS WINAPI RegRenameKey( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewName ) +LSTATUS WINAPI RegRenameKey( HKEY hkey, LPCWSTR subkey_name, LPCWSTR new_name ) { - FIXME("(%p,%s,%s): stub\n", hkey, debugstr_w(lpSubKey), debugstr_w(lpNewName)); - return ERROR_CALL_NOT_IMPLEMENTED; + UNICODE_STRING str; + LSTATUS ret; + HKEY subkey; + + TRACE("%p, %s, %s.\n", hkey, debugstr_w(subkey_name), debugstr_w(new_name)); + + RtlInitUnicodeString(&str, new_name); + + if (!subkey_name) + return RtlNtStatusToDosError( NtRenameKey( hkey, &str )); + + if ((ret = RegOpenKeyExW( hkey, subkey_name, 0, KEY_WRITE, &subkey ))) + return ret; + + ret = RtlNtStatusToDosError( NtRenameKey( subkey, &str )); + RegCloseKey( subkey ); + + return ret; }
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index c2e78192f2e..cae9fc98734 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -4481,22 +4481,17 @@ static void test_RegRenameKey(void) LSTATUS ret;
ret = RegRenameKey(NULL, NULL, NULL); - todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Unexpected return value %ld.\n", ret); ret = RegRenameKey(NULL, NULL, L"newname"); - todo_wine ok(ret == ERROR_INVALID_HANDLE, "Unexpected return value %ld.\n", ret); ret = RegRenameKey(NULL, L"oldname", NULL); - todo_wine ok(ret == ERROR_INVALID_HANDLE, "Unexpected return value %ld.\n", ret); ret = RegRenameKey(NULL, L"oldname", L"newname"); - todo_wine ok(ret == ERROR_INVALID_HANDLE, "Unexpected return value %ld.\n", ret);
ret = RegCreateKeyExA(hkey_main, "TestRenameKey", 0, NULL, 0, KEY_READ, NULL, &key, NULL); ok(!ret, "Unexpected return value %ld.\n", ret); ret = RegRenameKey(key, NULL, L"TestNewRenameKey"); - todo_wine ok(ret == ERROR_ACCESS_DENIED, "Unexpected return value %ld.\n", ret); RegCloseKey(key);
@@ -4504,28 +4499,22 @@ static void test_RegRenameKey(void) ret = RegCreateKeyExA(hkey_main, "TestRenameKey", 0, NULL, 0, KEY_WRITE, NULL, &key, NULL); ok(!ret, "Unexpected return value %ld.\n", ret); ret = RegRenameKey(key, NULL, NULL); - todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Unexpected return value %ld.\n", ret); ret = RegRenameKey(key, NULL, L"TestNewRenameKey"); - todo_wine ok(!ret, "Unexpected return value %ld.\n", ret); RegCloseKey(key);
ret = RegDeleteKeyA(hkey_main, "TestNewRenameKey"); - todo_wine ok(!ret, "Unexpected return value %ld.\n", ret); ret = RegDeleteKeyA(hkey_main, "TestRenameKey"); - todo_wine ok(ret, "Unexpected return value %ld.\n", ret);
/* Subkey does not exist. */ ret = RegCreateKeyExA(hkey_main, "TestRenameKey", 0, NULL, 0, KEY_WRITE, NULL, &key, NULL); ok(!ret, "Unexpected return value %ld.\n", ret); ret = RegRenameKey(key, L"unknown_subkey", NULL); - todo_wine ok(ret == ERROR_FILE_NOT_FOUND, "Unexpected return value %ld.\n", ret); ret = RegRenameKey(key, L"unknown_subkey", L"known_subkey"); - todo_wine ok(ret == ERROR_FILE_NOT_FOUND, "Unexpected return value %ld.\n", ret);
/* Rename existing subkey. */ @@ -4534,14 +4523,11 @@ static void test_RegRenameKey(void) RegCloseKey(key2);
ret = RegRenameKey(key, L"known_subkey", L"renamed_subkey"); - todo_wine ok(!ret, "Unexpected return value %ld.\n", ret);
ret = RegDeleteKeyA(key, "renamed_subkey"); - todo_wine ok(!ret, "Unexpected return value %ld.\n", ret); ret = RegDeleteKeyA(key, "known_subkey"); - todo_wine ok(ret, "Unexpected return value %ld.\n", ret);
RegCloseKey(key);
Alexandre Julliard (@julliard) commented about server/registry.c:
name.len = (get_req_data_size() / sizeof(WCHAR)) * sizeof(WCHAR);
if (!name.len)
{
set_error( STATUS_INVALID_PARAMETER );
}
else if (!key->parent || (subkey = find_subkey( key->parent, &name, &index )))
{
set_error( STATUS_CANNOT_DELETE );
}
else if ((ptr = memdup( name.str, name.len )))
{
free( key->name );
key->name = ptr;
key->namelen = name.len;
}
The key needs to be properly sorted into the parent's subkey array. You'd also need to check if the name contains a backslash, handle renaming Wow6432Node, set the dirty flag, send notifications, etc. Basically you have to replicate most of what create_key() does.