Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/advapi32/tests/registry.c | 23 +++++++++------ server/registry.c | 52 ++++++++++++++++++++++++++++++++++ server/trace.c | 1 + 3 files changed, 67 insertions(+), 9 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 179b044e28a..7d6d8a05354 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -3840,16 +3840,16 @@ static void test_perflib_key(void) todo_wine ok(key == HKEY_PERFORMANCE_TEXT || key == HKEY_PERFORMANCE_NLSTEXT, "got key %p\n", key);
ret = RegCloseKey(key); - todo_wine ok(!ret, "got %u\n", ret); + ok(!ret, "got %u\n", ret);
RtlInitUnicodeString(&string, L"009"); InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE, perflib_key, NULL); ret = NtOpenKey((HANDLE *)&key, KEY_READ, &attr); - todo_wine ok(ret == STATUS_PREDEFINED_HANDLE || ret == STATUS_SUCCESS /* Win < 7 */, "got %#x\n", ret); + ok(ret == STATUS_PREDEFINED_HANDLE || ret == STATUS_SUCCESS /* Win < 7 */, "got %#x\n", ret); if (ret == STATUS_PREDEFINED_HANDLE) ok(!is_special_key(key), "expected a normal handle, got %p\n", key); else - todo_wine ok(key == HKEY_PERFORMANCE_TEXT, "got key %p\n", key); + ok(key == HKEY_PERFORMANCE_TEXT, "got key %p\n", key);
ret = NtQueryKey(key, KeyFullInformation, buffer, buffer_size, &size); ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); @@ -3865,13 +3865,13 @@ static void test_perflib_key(void) ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret);
ret = NtSetValueKey(key, &string, 0, REG_SZ, "test", 5); - ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); + todo_wine ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret);
ret = NtDeleteValueKey(key, &string); - ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); + todo_wine ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret);
ret = NtDeleteKey(key); - ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); + todo_wine ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret);
RtlInitUnicodeString(&string, L"subkey"); InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE, key, NULL); @@ -3886,15 +3886,20 @@ static void test_perflib_key(void) if (is_special_key(key)) ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); else - ok(ret == STATUS_ACCESS_DENIED + todo_wine ok(ret == STATUS_ACCESS_DENIED || broken(ret == STATUS_INVALID_HANDLE) /* WoW64 */, "got %#x\n", ret); + if (!ret) + { + NtDeleteKey(key2); + NtClose(key2); + }
/* it's a real handle, though */ ret = NtQueryObject(key, ObjectNameInformation, buffer, buffer_size, &size); if (is_special_key(key)) ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); else - todo_wine ok(!ret, "got %#x\n", ret); + ok(!ret, "got %#x\n", ret); if (!ret) { name_info = (OBJECT_NAME_INFORMATION *)buffer; @@ -3906,7 +3911,7 @@ static void test_perflib_key(void) if (is_special_key(key)) ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); else - todo_wine ok(!ret, "got %#x\n", ret); + ok(!ret, "got %#x\n", ret);
/* multilingual support was not really completely thought through */
diff --git a/server/registry.c b/server/registry.c index b7971770728..427da8a5883 100644 --- a/server/registry.c +++ b/server/registry.c @@ -101,6 +101,7 @@ struct key #define KEY_SYMLINK 0x0008 /* key is a symbolic link */ #define KEY_WOW64 0x0010 /* key contains a Wow6432Node subkey */ #define KEY_WOWSHARE 0x0020 /* key is a Wow64 shared key (used for Software\Classes) */ +#define KEY_PREDEF 0x0040 /* key is marked as predefined */
/* a key value */ struct key_value @@ -801,6 +802,7 @@ static struct key *open_key( struct key *key, const struct unicode_str *name, un return NULL; } if (debug_level > 1) dump_operation( key, NULL, "Open" ); + if (key->flags & KEY_PREDEF) set_error( STATUS_PREDEFINED_HANDLE ); grab_object( key ); return key; } @@ -831,6 +833,7 @@ static struct key *create_key( struct key *key, const struct unicode_str *name, return NULL; } if (debug_level > 1) dump_operation( key, NULL, "Open" ); + if (key->flags & KEY_PREDEF) set_error( STATUS_PREDEFINED_HANDLE ); grab_object( key ); return key; } @@ -925,6 +928,12 @@ static void enum_key( struct key *key, int index, int info_class, struct enum_ke WCHAR *fullname = NULL; char *data;
+ if (key->flags & KEY_PREDEF) + { + set_error( STATUS_INVALID_HANDLE ); + return; + } + if (index != -1) /* -1 means use the specified key directly */ { if ((index < 0) || (index > key->last_subkey)) @@ -1020,6 +1029,12 @@ static int delete_key( struct key *key, int recurse ) } assert( parent );
+ if (key->flags & KEY_PREDEF) + { + set_error( STATUS_INVALID_HANDLE ); + return -1; + } + while (recurse && (key->last_subkey>=0)) if (0 > delete_key(key->subkeys[key->last_subkey], 1)) return -1; @@ -1126,6 +1141,12 @@ static void set_value( struct key *key, const struct unicode_str *name, void *ptr = NULL; int index;
+ if (key->flags & KEY_PREDEF) + { + set_error( STATUS_INVALID_HANDLE ); + return; + } + if ((value = find_value( key, name, &index ))) { /* check if the new value is identical to the existing one */ @@ -1172,6 +1193,12 @@ static void get_value( struct key *key, const struct unicode_str *name, int *typ struct key_value *value; int index;
+ if (key->flags & KEY_PREDEF) + { + set_error( STATUS_INVALID_HANDLE ); + return; + } + if ((value = find_value( key, name, &index ))) { *type = value->type; @@ -1191,6 +1218,12 @@ static void enum_value( struct key *key, int i, int info_class, struct enum_key_ { struct key_value *value;
+ if (key->flags & KEY_PREDEF) + { + set_error( STATUS_INVALID_HANDLE ); + return; + } + if (i < 0 || i > key->last_value) set_error( STATUS_NO_MORE_ENTRIES ); else { @@ -1243,6 +1276,12 @@ static void delete_value( struct key *key, const struct unicode_str *name ) struct key_value *value; int i, index, nb_values;
+ if (key->flags & KEY_PREDEF) + { + set_error( STATUS_INVALID_HANDLE ); + return; + } + if (!(value = find_value( key, name, &index ))) { set_error( STATUS_OBJECT_NAME_NOT_FOUND ); @@ -1817,9 +1856,16 @@ void init_registry(void) static const WCHAR classes_arm64[] = {'S','o','f','t','w','a','r','e','\', 'C','l','a','s','s','e','s','\', 'W','o','w','A','A','6','4','N','o','d','e'}; + static const WCHAR perflib[] = {'S','o','f','t','w','a','r','e','\', + 'M','i','c','r','o','s','o','f','t','\', + 'W','i','n','d','o','w','s',' ','N','T','\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\', + 'P','e','r','f','l','i','b','\', + '0','0','9'}; static const struct unicode_str root_name = { NULL, 0 }; static const struct unicode_str HKLM_name = { HKLM, sizeof(HKLM) }; static const struct unicode_str HKU_name = { HKU_default, sizeof(HKU_default) }; + static const struct unicode_str perflib_name = { perflib, sizeof(perflib) };
WCHAR *current_user_path; struct unicode_str current_user_str; @@ -1891,6 +1937,12 @@ void init_registry(void) /* FIXME: handle HKCU too */ }
+ if ((key = create_key_recursive( hklm, &perflib_name, current_time ))) + { + key->flags |= KEY_PREDEF; + release_object( key ); + } + release_object( hklm ); release_object( hkcu );
diff --git a/server/trace.c b/server/trace.c index 55068d1179b..395b72b8d6f 100644 --- a/server/trace.c +++ b/server/trace.c @@ -5485,6 +5485,7 @@ static const struct { "PIPE_LISTENING", STATUS_PIPE_LISTENING }, { "PIPE_NOT_AVAILABLE", STATUS_PIPE_NOT_AVAILABLE }, { "PORT_NOT_SET", STATUS_PORT_NOT_SET }, + { "PREDEFINED_HANDLE", STATUS_PREDEFINED_HANDLE }, { "PRIVILEGE_NOT_HELD", STATUS_PRIVILEGE_NOT_HELD }, { "PROCESS_IN_JOB", STATUS_PROCESS_IN_JOB }, { "PROCESS_IS_TERMINATING", STATUS_PROCESS_IS_TERMINATING },