From: Bernhard Übelacker bernhardu@mailbox.org
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55000 --- dlls/advapi32/tests/registry.c | 26 ++++++++++++++++++++++++++ server/registry.c | 12 ++++++++++++ 2 files changed, 38 insertions(+)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 35df1b226f5..89a81303b37 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -1604,6 +1604,31 @@ static void test_reg_unload_key(void) DeleteFileA("saved_key.LOG"); }
+static void test_reg_unload_key_default(void) +{ + UNICODE_STRING key_name; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + DWORD ret; + + if (!set_privileges(SE_RESTORE_NAME, TRUE) || + !set_privileges(SE_BACKUP_NAME, FALSE)) + { + win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n"); + return; + } + + pRtlInitUnicodeString(&key_name, L"\REGISTRY\User\.Default"); + InitializeObjectAttributes(&attr, &key_name, OBJ_CASE_INSENSITIVE, NULL, NULL); + status = pNtUnloadKey(&attr); + ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %08lx\n", status); + + ret = RegUnLoadKeyA(HKEY_USERS, ".Default"); + ok(ret == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", ret); + + set_privileges(SE_RESTORE_NAME, FALSE); +} + /* Helper function to wait for a file blocked by the registry to be available */ static void wait_file_available(char *path) { @@ -4946,6 +4971,7 @@ START_TEST(registry) test_reg_save_key(); test_reg_load_key(); test_reg_unload_key(); + test_reg_unload_key_default(); test_reg_load_app_key(); test_reg_copy_tree(); test_reg_delete_tree(); diff --git a/server/registry.c b/server/registry.c index 0128b8be9d8..89c0d3b26f1 100644 --- a/server/registry.c +++ b/server/registry.c @@ -2156,6 +2156,16 @@ void flush_registry(void) if (fchdir( server_dir_fd ) == -1) fatal_error( "chdir to server dir: %s\n", strerror( errno )); }
+static int save_branch_info_contains(struct key *key) +{ + int i; + + for (i = 0; i < save_branch_count; i++) + if (&save_branch_info[i].key->obj == &key->obj) + return 1; + return 0; +} + /* determine if the thread is wow64 (32-bit client running on 64-bit prefix) */ static int is_wow64_thread( struct thread *thread ) { @@ -2357,6 +2367,8 @@ DECL_HANDLER(unload_registry) { if (key->obj.handle_count) set_error( STATUS_CANNOT_DELETE ); + else if (save_branch_info_contains(key)) + set_error( STATUS_ACCESS_DENIED ); else delete_key( key, 1 ); /* FIXME */ release_object( key );