A deleted key returns STATUS_KEY_DELETED when ObjectNameInformation is requested, but succeeds when ObjectBasicInformation is requested.
Signed-off-by: Zebediah Figura [email protected] --- server/handle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/handle.c b/server/handle.c index d86f0960ccf..d1288239903 100644 --- a/server/handle.c +++ b/server/handle.c @@ -693,7 +693,7 @@ DECL_HANDLER(get_object_info) reply->access = get_handle_access( current->process, req->handle ); reply->ref_count = obj->refcount; reply->handle_count = obj->handle_count; - if ((name = obj->ops->get_full_name( obj, &reply->total ))) + if (get_reply_max_size() && (name = obj->ops->get_full_name( obj, &reply->total ))) set_reply_data_ptr( name, min( reply->total, get_reply_max_size() )); release_object( obj ); }
This fixes a server crash that can be triggered by deleting a key and then trying to retrieve its name. In that case key->parent is NULL.
Signed-off-by: Zebediah Figura [email protected] --- server/registry.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/server/registry.c b/server/registry.c index f36760e6cc1..b7971770728 100644 --- a/server/registry.c +++ b/server/registry.c @@ -413,6 +413,12 @@ static WCHAR *key_get_full_name( struct object *obj, data_size_t *ret_len ) data_size_t len = sizeof(root_name) - sizeof(WCHAR); char *ret;
+ if (key->flags & KEY_DELETED) + { + set_error( STATUS_KEY_DELETED ); + return NULL; + } + for (key = (struct key *)obj; key != root_key; key = key->parent) len += key->namelen + sizeof(WCHAR); if (!(ret = malloc( len ))) return NULL;
Signed-off-by: Zebediah Figura [email protected] --- dlls/ntdll/tests/reg.c | 53 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 7463f98aa29..91b752ac069 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -125,6 +125,8 @@ static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, PHANDLE); static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES); static NTSTATUS (WINAPI * pNtOpenKeyEx)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG); static NTSTATUS (WINAPI * pNtClose)(IN HANDLE); +static NTSTATUS (WINAPI * pNtEnumerateKey)(HANDLE, ULONG, KEY_INFORMATION_CLASS, void *, DWORD, DWORD *); +static NTSTATUS (WINAPI * pNtEnumerateValueKey)(HANDLE, ULONG, KEY_VALUE_INFORMATION_CLASS, void *, DWORD, DWORD *); static NTSTATUS (WINAPI * pNtFlushKey)(HANDLE); static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE); static NTSTATUS (WINAPI * pNtCreateKey)( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, @@ -132,6 +134,7 @@ static NTSTATUS (WINAPI * pNtCreateKey)( PHANDLE retkey, ACCESS_MASK access, con PULONG dispos ); static NTSTATUS (WINAPI * pNtQueryKey)(HANDLE,KEY_INFORMATION_CLASS,PVOID,ULONG,PULONG); static NTSTATUS (WINAPI * pNtQueryLicenseValue)(const UNICODE_STRING *,ULONG *,PVOID,ULONG,ULONG *); +static NTSTATUS (WINAPI * pNtQueryObject)(HANDLE, OBJECT_INFORMATION_CLASS, void *, ULONG, ULONG *); static NTSTATUS (WINAPI * pNtQueryValueKey)(HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *); static NTSTATUS (WINAPI * pNtSetValueKey)(HANDLE, const PUNICODE_STRING, ULONG, ULONG, const void*, ULONG ); @@ -181,9 +184,12 @@ static BOOL InitFunctionPtrs(void) NTDLL_GET_PROC(NtClose) NTDLL_GET_PROC(NtDeleteValueKey) NTDLL_GET_PROC(NtCreateKey) + NTDLL_GET_PROC(NtEnumerateKey) + NTDLL_GET_PROC(NtEnumerateValueKey) NTDLL_GET_PROC(NtFlushKey) NTDLL_GET_PROC(NtDeleteKey) NTDLL_GET_PROC(NtQueryKey) + NTDLL_GET_PROC(NtQueryObject) NTDLL_GET_PROC(NtQueryValueKey) NTDLL_GET_PROC(NtQueryInformationProcess) NTDLL_GET_PROC(NtSetValueKey) @@ -844,20 +850,61 @@ static void test_NtQueryValueKey(void)
static void test_NtDeleteKey(void) { + UNICODE_STRING string; + char buffer[200]; NTSTATUS status; - HANDLE hkey; + HANDLE hkey, hkey2; OBJECT_ATTRIBUTES attr; - ACCESS_MASK am = KEY_ALL_ACCESS; + DWORD size;
status = pNtDeleteKey(NULL); ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); - status = pNtOpenKey(&hkey, am, &attr); + status = pNtOpenKey(&hkey, KEY_ALL_ACCESS, &attr); ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
status = pNtDeleteKey(hkey); ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status); + + status = pNtQueryKey(hkey, KeyNameInformation, buffer, sizeof(buffer), &size); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtEnumerateKey(hkey, 0, KeyFullInformation, buffer, sizeof(buffer), &size); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + pRtlInitUnicodeString(&string, L"value"); + status = pNtQueryValueKey(hkey, &string, KeyValueBasicInformation, buffer, sizeof(buffer), &size); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtEnumerateValueKey(hkey, 0, KeyValuePartialInformation, buffer, sizeof(buffer), &size); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtSetValueKey(hkey, &string, 0, REG_SZ, "test", 5); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtDeleteValueKey(hkey, &string); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtDeleteKey(hkey); + todo_wine ok(!status, "got %#x\n", status); + + RtlInitUnicodeString(&string, L"subkey"); + InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE, hkey, NULL); + status = pNtOpenKey(&hkey2, KEY_READ, &attr); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtCreateKey(&hkey2, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtQueryObject(hkey, ObjectNameInformation, buffer, sizeof(buffer), &size); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtQueryObject(hkey, ObjectBasicInformation, buffer, sizeof(OBJECT_BASIC_INFORMATION), &size); + ok(!status, "got %#x\n", status); + + status = pNtClose(hkey); + ok(status == STATUS_SUCCESS, "got %#x\n", status); }
static void test_NtQueryLicenseKey(void)
Signed-off-by: Zebediah Figura [email protected] --- v3: fix more test failures!
dlls/advapi32/tests/registry.c | 138 +++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 72423eae94c..cf7536eff75 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -99,6 +99,11 @@ static void InitFunctionPtrs(void) pNtUnloadKey = (void *)GetProcAddress( hntdll, "NtUnloadKey" ); }
+static BOOL is_special_key(HKEY key) +{ + return !!((ULONG_PTR)key & 0x80000000); +} + /* delete key and all its subkeys */ static DWORD delete_key( HKEY hkey ) { @@ -3809,6 +3814,138 @@ todo_wine ok(dwret == ERROR_SUCCESS, "got %u\n", dwret); }
+static void test_perflib_key(void) +{ + unsigned int primary_lang = PRIMARYLANGID(GetUserDefaultLangID()); + unsigned int buffer_size = 1024 * 1024; + OBJECT_NAME_INFORMATION *name_info; + HKEY perflib_key, key, key2; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING string; + char lang_name[4]; + char *buffer; + DWORD size; + LONG ret; + + ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, + "Software\Microsoft\Windows NT\CurrentVersion\Perflib", 0, KEY_READ, &perflib_key); + ok(!ret, "got %u\n", ret); + + ret = RegOpenKeyExA(perflib_key, "009", 0, KEY_READ, &key); + todo_wine ok(!ret, "got %u\n", ret); + /* English always returns TEXT; most other languages return NLSTEXT, but + * some (e.g. Hindi) return TEXT */ + 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); + + RtlInitUnicodeString(&string, L"009"); + InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE, perflib_key, NULL); + ret = NtOpenKey((HANDLE *)&key, KEY_ALL_ACCESS, &attr); + todo_wine ok(ret == STATUS_PREDEFINED_HANDLE || ret == STATUS_ACCESS_DENIED + || 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 if (ret == STATUS_SUCCESS) + ok(key == HKEY_PERFORMANCE_TEXT, "got key %p\n", key); + else + { + skip("Not enough permissions to test the perflib key.\n"); + RegCloseKey(perflib_key); + return; + } + + buffer = malloc(buffer_size); + + ret = NtQueryKey(key, KeyFullInformation, buffer, buffer_size, &size); + ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); + + ret = NtEnumerateKey(key, 0, KeyFullInformation, buffer, buffer_size, &size); + ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); + + RtlInitUnicodeString(&string, L"counter"); + ret = NtQueryValueKey(key, &string, KeyValuePartialInformation, buffer, buffer_size, &size); + ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); + + ret = NtEnumerateValueKey(key, 0, KeyValuePartialInformation, buffer, buffer_size, &size); + 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); + + ret = NtDeleteValueKey(key, &string); + ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); + + ret = NtDeleteKey(key); + ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); + + RtlInitUnicodeString(&string, L"subkey"); + InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE, key, NULL); + ret = NtOpenKey((HANDLE *)&key2, KEY_READ, &attr); + if (is_special_key(key)) + ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); + else + ok(ret == STATUS_OBJECT_NAME_NOT_FOUND + || broken(ret == STATUS_INVALID_HANDLE) /* WoW64 */, "got %#x\n", ret); + + ret = NtCreateKey((HANDLE *)&key2, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL); + if (is_special_key(key)) + ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); + else + ok(!ret || 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 + ok(!ret, "got %#x\n", ret); + if (!ret) + { + name_info = (OBJECT_NAME_INFORMATION *)buffer; + ok(!wcsicmp(name_info->Name.Buffer, L"\REGISTRY\MACHINE\SOFTWARE\Microsoft\Windows NT" + "\CurrentVersion\Perflib\009"), "got name %s\n", debugstr_w(name_info->Name.Buffer)); + } + + ret = NtClose(key); + if (is_special_key(key)) + ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret); + else + ok(!ret, "got %#x\n", ret); + + /* multilingual support was not really completely thought through */ + + sprintf(lang_name, "%03x", primary_lang); + if (primary_lang != LANG_ENGLISH) + { + ret = RegOpenKeyExA(perflib_key, lang_name, 0, KEY_READ, &key); + ok(!ret, "got %u\n", ret); + ok(!is_special_key(key), "expected a normal handle, got %p\n", key); + + ret = RegQueryValueExA(key, "counter", NULL, NULL, (BYTE *)buffer, &size); + ok(ret == ERROR_FILE_NOT_FOUND, "got %u\n", ret); + + ret = RegCloseKey(key); + ok(!ret, "got %u\n", ret); + } + + ret = RegCloseKey(perflib_key); + ok(!ret, "got %u\n", ret); + + RtlInitUnicodeString(&string, L"\Registry\PerfData"); + InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL); + ret = NtOpenKey((HANDLE *)&key, KEY_READ, &attr); + todo_wine ok(ret == STATUS_OBJECT_NAME_NOT_FOUND, "got %#x\n", ret); + + free(buffer); +} + static void test_RegLoadMUIString(void) { HMODULE hUser32, hResDll, hFile; @@ -4213,6 +4350,7 @@ START_TEST(registry) test_RegQueryValueExPerformanceData(); test_RegLoadMUIString(); test_EnumDynamicTimeZoneInformation(); + test_perflib_key();
/* cleanup */ delete_key( hkey_main );
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=93368
Your paranoid android.
=== w8adm (32 bit report) ===
advapi32: registry.c:3896: Test failed: got 0xc0000022
=== w1064_tsign (64 bit report) ===
advapi32: registry.c:3466: Test failed: expected ERROR_SUCCESS, got 6 registry.c:3594: Test failed: expected WAIT_OBJECT_0, got 258
Signed-off-by: Zebediah Figura [email protected] --- dlls/advapi32/tests/registry.c | 4 +-- server/registry.c | 52 ++++++++++++++++++++++++++++++++++ server/trace.c | 1 + 3 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index cf7536eff75..122292ce39d 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -3838,12 +3838,12 @@ 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_ALL_ACCESS, &attr); - todo_wine ok(ret == STATUS_PREDEFINED_HANDLE || ret == STATUS_ACCESS_DENIED + ok(ret == STATUS_PREDEFINED_HANDLE || ret == STATUS_ACCESS_DENIED || 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); 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 },
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=93369
Your paranoid android.
=== w8adm (32 bit report) ===
advapi32: registry.c:3896: Test failed: got 0xc0000022
=== debiant2 (32 bit Arabic:Morocco report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit German report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit French report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit Hebrew:Israel report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit Hindi:India report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit Japanese:Japan report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit Chinese:China report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
Signed-off-by: Zebediah Figura [email protected] --- dlls/advapi32/tests/registry.c | 4 ++-- dlls/kernelbase/registry.c | 39 ++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 122292ce39d..316676b8417 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -3832,10 +3832,10 @@ static void test_perflib_key(void) ok(!ret, "got %u\n", ret);
ret = RegOpenKeyExA(perflib_key, "009", 0, KEY_READ, &key); - todo_wine ok(!ret, "got %u\n", ret); + ok(!ret, "got %u\n", ret); /* English always returns TEXT; most other languages return NLSTEXT, but * some (e.g. Hindi) return TEXT */ - todo_wine ok(key == HKEY_PERFORMANCE_TEXT || key == HKEY_PERFORMANCE_NLSTEXT, "got key %p\n", key); + ok(key == HKEY_PERFORMANCE_TEXT || key == HKEY_PERFORMANCE_NLSTEXT, "got key %p\n", key);
ret = RegCloseKey(key); ok(!ret, "got %u\n", ret); diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 2ed5e268119..d9d62e81b31 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -121,6 +121,25 @@ static HANDLE open_wow6432node( HANDLE key ) return ret; }
+static HKEY get_perflib_key( HANDLE key ) +{ + static const WCHAR performance_text[] = + L"\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\Perflib\009"; + char buffer[200]; + OBJECT_NAME_INFORMATION *info = (OBJECT_NAME_INFORMATION *)buffer; + + if (!NtQueryObject( key, ObjectNameInformation, buffer, sizeof(buffer), NULL )) + { + if (!wcsicmp( info->Name.Buffer, performance_text )) + { + NtClose( key ); + return HKEY_PERFORMANCE_TEXT; + } + } + + return key; +} + /* wrapper for NtCreateKey that creates the key recursively if necessary */ static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, const UNICODE_STRING *class, ULONG options, PULONG dispos ) @@ -172,7 +191,7 @@ static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES options & ~REG_OPTION_CREATE_LINK, dispos ); } if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); - if (status) return status; + if (!NT_SUCCESS(status)) return status; if (i == len) break; attr->RootDirectory = subkey; while (i < len && buffer[i] == '\') i++; @@ -186,6 +205,11 @@ static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); attr->RootDirectory = subkey; } + if (status == STATUS_PREDEFINED_HANDLE) + { + attr->RootDirectory = get_perflib_key( attr->RootDirectory ); + status = STATUS_SUCCESS; + } *retkey = attr->RootDirectory; return status; } @@ -205,7 +229,13 @@ static NTSTATUS open_key( HKEY *retkey, DWORD options, ACCESS_MASK access, OBJEC if (!force_wow32) { if (options & REG_OPTION_OPEN_LINK) attr->Attributes |= OBJ_OPENLINK; - return NtOpenKeyEx( (HANDLE *)retkey, access, attr, options ); + status = NtOpenKeyEx( (HANDLE *)retkey, access, attr, options ); + if (status == STATUS_PREDEFINED_HANDLE) + { + *retkey = get_perflib_key( *retkey ); + status = STATUS_SUCCESS; + } + return status; }
if (len && buffer[0] == '\') return STATUS_OBJECT_PATH_INVALID; @@ -249,6 +279,11 @@ static NTSTATUS open_key( HKEY *retkey, DWORD options, ACCESS_MASK access, OBJEC if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); attr->RootDirectory = subkey; } + if (status == STATUS_PREDEFINED_HANDLE) + { + attr->RootDirectory = get_perflib_key( attr->RootDirectory ); + status = STATUS_SUCCESS; + } *retkey = attr->RootDirectory; return status; }
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=93370
Your paranoid android.
=== w8adm (32 bit report) ===
advapi32: registry.c:3896: Test failed: got 0xc0000022
=== debiant2 (32 bit Arabic:Morocco report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit German report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit French report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit Hebrew:Israel report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit Hindi:India report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit Japanese:Japan report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6
=== debiant2 (32 bit Chinese:China report) ===
advapi32: registry.c:3928: Test failed: got 2 registry.c:3932: Test failed: got 6 registry.c:3935: Test failed: got 6