This seems to be more correct than what we previously had with fewer lines of code, so I like that. I still don't really like the extra flag I had to add for Nt{Create,Open}Key, but I couldn't find a way to make things work without it. I also checked that Windows doesn't use a similar flag (by iterating over all bit masks).
-- v3: wine.inf: Put the Clients key in the right place. ntdll/tests: Factor out the NtEnumerateKey() tests. kernelbase: Remove special Wow64 handling for HKEY_CLASSES_ROOT. kernelbase: Remove special Wow6432Node handling from RegCreateKeyEx(). kernelbase: Remove special Wow6432Node handling from RegOpenKeyEx(). server: Don't return the actual 32-bit Software\Classes key. ntdll/tests: Add some some Software\Classes query and enumerate tests. ntdll/tests: Test that NtCreateKeyEx() also recursively obtains the Wow6432Node parent. server: Recursively obtain the Wow6432Node parent.
From: Sven Baars sbaars@codeweavers.com
--- dlls/ntdll/tests/reg.c | 195 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 193 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index c7d9d7e4c7f..dd7dbe19d17 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -1472,7 +1472,7 @@ static void test_redirection(void) char buffer[1024]; KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; DWORD dw, len; - HANDLE key, root32, root64, key32, key64; + HANDLE key, key32, key64, root, root32, root64;
if (ptr_size != 64) { @@ -1760,6 +1760,12 @@ static void test_redirection(void) status = pNtCreateKey( &key64, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status );
+ attr.RootDirectory = key64; + status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); + ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status ); + pNtDeleteKey( key32 ); + pNtClose( key32 ); + attr.RootDirectory = root32; status = pNtOpenKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); @@ -1819,10 +1825,16 @@ static void test_redirection(void) status = pNtOpenKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey failed: 0x%08lx\n", status );
+ attr.RootDirectory = root32; + status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtOpenKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey failed: 0x%08lx\n", status ); + pNtDeleteKey( key64 ); pNtClose( key64 );
- attr.RootDirectory = root32; status = pNtCreateKey( &key32, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status ); dw = 32; @@ -1847,6 +1859,185 @@ static void test_redirection(void) ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08lx\n", status ); dw = *(DWORD *)info->Data; ok( dw == 32, "wrong value %lu\n", dw ); + pNtClose( key64 ); + + pNtDeleteKey( key32 ); + pNtClose( key32 ); + + pNtClose( root64 ); + pNtClose( root32 ); + + pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes" ); + attr.RootDirectory = 0; + status = pNtOpenKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtOpenKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtOpenKey( &root, KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + pRtlInitUnicodeString( &str, L"Interface" ); + attr.RootDirectory = root64; + status = pNtOpenKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + attr.RootDirectory = root32; + status = pNtOpenKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + attr.RootDirectory = root; + status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + pNtClose( root64 ); + pNtClose( root32 ); + pNtClose( root ); + + root64 = key64; + root32 = key32; + root = key; + + pRtlInitUnicodeString( &str, L"Wine" ); + attr.RootDirectory = root32; + status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); + ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status ); + + attr.RootDirectory = root; + status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + pNtDeleteKey( key32 ); + pNtClose( key32 ); + + attr.RootDirectory = root64; + status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); + ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status ); + + attr.RootDirectory = root; + status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); + ok( status == (ptr_size == 32 ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS), + "NtOpenKey failed: 0x%08lx\n", status ); + if (!status) pNtClose( key ); + + pNtDeleteKey( key64 ); + pNtClose( key64 ); + + pNtDeleteKey( root ); + pNtClose( root ); + + attr.RootDirectory = root64; + status = pNtCreateKey( &key64, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); + ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status ); + + attr.RootDirectory = root32; + status = pNtOpenKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == (ptr_size == 32 ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS), + "NtOpenKey failed: 0x%08lx\n", status ); + if (!status) pNtClose( key ); + + status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); + ok( status == (ptr_size == 32 ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS), + "NtOpenKey failed: 0x%08lx\n", status ); + if (!status) pNtClose( key ); + + status = pNtCreateKey( &key32, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); + ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status ); + + dw = 32; + status = pNtSetValueKey( key32, &value_str, 0, REG_DWORD, &dw, sizeof(dw) ); + ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08lx\n", status ); + pNtClose( key32 ); + + dw = 64; + status = pNtSetValueKey( key64, &value_str, 0, REG_DWORD, &dw, sizeof(dw) ); + ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08lx\n", status ); + pNtClose( key64 ); + + attr.RootDirectory = root64; + status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + len = sizeof(buffer); + status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len ); + ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08lx\n", status ); + dw = *(DWORD *)info->Data; + ok( dw == 64, "wrong value %lu\n", dw ); + pNtClose( key ); + + attr.RootDirectory = root64; + status = pNtOpenKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + len = sizeof(buffer); + status = pNtQueryValueKey( key64, &value_str, KeyValuePartialInformation, info, len, &len ); + ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08lx\n", status ); + dw = *(DWORD *)info->Data; + ok( dw == 64, "wrong value %lu\n", dw ); + + attr.RootDirectory = root32; + status = pNtOpenKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + len = sizeof(buffer); + status = pNtQueryValueKey( key32, &value_str, KeyValuePartialInformation, info, len, &len ); + ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08lx\n", status ); + dw = *(DWORD *)info->Data; + ok( dw == ptr_size, "wrong value %lu\n", dw ); + pNtDeleteKey( key32 ); + pNtClose( key32 ); + + attr.RootDirectory = root64; + status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); + ok( status == (ptr_size == 64 ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS), + "NtOpenKey failed: 0x%08lx\n", status ); + if (!status) pNtClose( key ); + + status = pNtOpenKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + todo_wine_if(ptr_size == 32) ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey failed: 0x%08lx\n", status ); + if (!status) pNtClose( key ); + + attr.RootDirectory = root32; + status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtOpenKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey failed: 0x%08lx\n", status ); + + pNtDeleteKey( key64 ); + pNtClose( key64 ); + + status = pNtCreateKey( &key32, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); + ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status ); + dw = 32; + status = pNtSetValueKey( key32, &value_str, 0, REG_DWORD, &dw, sizeof(dw) ); + ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08lx\n", status ); + + attr.RootDirectory = root64; + status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); + ok( status == (ptr_size == 32 ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS), + "NtOpenKey failed: 0x%08lx\n", status ); + if (!status) + { + len = sizeof(buffer); + status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len ); + ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08lx\n", status ); + dw = *(DWORD *)info->Data; + ok( dw == 32, "wrong value %lu\n", dw ); + pNtClose( key ); + } + + attr.RootDirectory = root64; + status = pNtOpenKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); + ok( status == (ptr_size == 32 ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS), + "NtOpenKey failed: 0x%08lx\n", status ); + if (!status) + { + len = sizeof(buffer); + status = pNtQueryValueKey( key64, &value_str, KeyValuePartialInformation, info, len, &len ); + ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08lx\n", status ); + dw = *(DWORD *)info->Data; + ok( dw == 32, "wrong value %lu\n", dw ); + pNtClose( key64 ); + }
pNtDeleteKey( key32 ); pNtClose( key32 );
From: Sven Baars sbaars@codeweavers.com
--- dlls/advapi32/tests/registry.c | 2 +- dlls/ntdll/tests/reg.c | 5 ++--- server/registry.c | 36 +++++++++++++++++++++++++++++----- 3 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 55a8074f1b7..b4f0398b358 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -2721,7 +2721,7 @@ static void test_redirection(void) check_key_value( key, "Winetest", 0, 64 ); check_key_value( key, "Winetest", KEY_WOW64_64KEY, 64 ); dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY ); - todo_wine ok( dw == 32, "wrong value %lu\n", dw ); + todo_wine_if (ptr_size == 64) ok( dw == 32, "wrong value %lu\n", dw ); RegCloseKey( key );
err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\Wine", 0, NULL, 0, diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index dd7dbe19d17..1f4e7aabb99 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -1630,8 +1630,7 @@ static void test_redirection(void) ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status ); check_key_value( key, "Winetest", 0, 64 ); check_key_value( key, "Winetest", KEY_WOW64_64KEY, 64 ); - dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY ); - todo_wine_if (ptr_size == 32) ok( dw == ptr_size, "wrong value %lu\n", dw ); + check_key_value( key, "Winetest", KEY_WOW64_32KEY, ptr_size ); pNtClose( key );
status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); @@ -1992,7 +1991,7 @@ static void test_redirection(void) if (!status) pNtClose( key );
status = pNtOpenKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); - todo_wine_if(ptr_size == 32) ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey failed: 0x%08lx\n", status ); + ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey failed: 0x%08lx\n", status ); if (!status) pNtClose( key );
attr.RootDirectory = root32; diff --git a/server/registry.c b/server/registry.c index 96ba18a0a5a..d112987b2b9 100644 --- a/server/registry.c +++ b/server/registry.c @@ -773,6 +773,31 @@ static struct key *grab_wow6432node( struct key *key ) return ret; }
+/* recursively obtain the wow6432node parent key if any */ +static struct key *get_wow6432node( struct key *key ) +{ + struct key *parent, *ret; + struct unicode_str name; + int index; + + if (!key) + return NULL; + + if (key->wow6432node) + return key->wow6432node; + + parent = get_parent( key ); + if (parent && key == parent->wow6432node) + return key; + + if (!(ret = get_wow6432node( parent ))) + return key; + + name.str = key->obj.name->name; + name.len = key->obj.name->len; + return find_subkey( ret, &name, &index ); +} + /* open a subkey */ static struct key *open_key( struct key *parent, const struct unicode_str *name, unsigned int access, unsigned int attributes ) @@ -785,10 +810,10 @@ static struct key *open_key( struct key *parent, const struct unicode_str *name, return NULL; }
- if (parent && (access & KEY_WOW64_32KEY)) + if (parent && (access & KEY_WOW64_32KEY) && !is_wow6432node( name->str, name->len )) { - if (parent->wow6432node && !is_wow6432node( name->str, name->len )) - parent = parent->wow6432node; + if ((key = get_wow6432node( parent ))) + parent = key; }
if (!(access & KEY_WOW64_64KEY)) attributes |= OBJ_KEY_WOW64; @@ -810,9 +835,10 @@ static struct key *create_key( struct key *parent, const struct unicode_str *nam
if (options & REG_OPTION_CREATE_LINK) attributes = (attributes & ~OBJ_OPENIF) | OBJ_OPENLINK;
- if (parent && (access & KEY_WOW64_32KEY)) + if (parent && (access & KEY_WOW64_32KEY) && !is_wow6432node( name->str, name->len )) { - if (parent->wow6432node && !is_wow6432node( name->str, name->len )) parent = parent->wow6432node; + if ((key = get_wow6432node( parent ))) + parent = key; }
if (!(access & KEY_WOW64_64KEY)) attributes |= OBJ_KEY_WOW64;
From: Sven Baars sbaars@codeweavers.com
--- dlls/ntdll/tests/reg.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 1f4e7aabb99..1a73b53b49f 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -1648,6 +1648,22 @@ static void test_redirection(void) ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08lx\n", status ); pNtClose( key64 );
+ pRtlInitUnicodeString( &str, L"Winetest" ); + attr.RootDirectory = root64; + status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); + ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status ); + + pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Wow6432Node\Wine\Winetest" ); + attr.RootDirectory = 0; + status = pNtOpenKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == (ptr_size == 64 ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS), + "NtOpenKey failed: 0x%08lx\n", status ); + pNtClose( key ); + + status = pNtDeleteKey( key32 ); + ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08lx\n", status ); + pNtClose( key32 ); + pNtDeleteKey( root32 ); pNtClose( root32 ); pNtDeleteKey( root64 );
From: Sven Baars sbaars@codeweavers.com
--- dlls/ntdll/tests/reg.c | 244 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 1a73b53b49f..420dd1b755f 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -1466,13 +1466,18 @@ static void _check_key_value( int line, HANDLE root, const char *name, DWORD fla
static void test_redirection(void) { + WCHAR wineW[] = {'W','i','n','e'}; NTSTATUS status; OBJECT_ATTRIBUTES attr; UNICODE_STRING str; char buffer[1024]; KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; + KEY_BASIC_INFORMATION *basic_info = (KEY_BASIC_INFORMATION *)buffer; + KEY_FULL_INFORMATION *full_info = (KEY_FULL_INFORMATION *)buffer; DWORD dw, len; HANDLE key, key32, key64, root, root32, root64; + int i, subkeys, subkeys64, subkeys32; + BOOL found;
if (ptr_size != 64) { @@ -2059,6 +2064,245 @@ static void test_redirection(void)
pNtClose( root64 ); pNtClose( root32 ); + + pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes\Wow6432Node\Wine" ); + attr.RootDirectory = 0; + status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); + ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status ); + + status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + pNtClose( key ); + + status = pNtOpenKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + pNtClose( key ); + + status = pNtOpenKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); + ok( status == (ptr_size == 32 ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS), + "NtOpenKey failed: 0x%08lx\n", status ); + if (!status) pNtClose( key ); + + pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes\Wine" ); + status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); + ok( status == (ptr_size == 64 ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS), + "NtOpenKey failed: 0x%08lx\n", status ); + if (!status) pNtClose( key ); + + status = pNtOpenKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == (ptr_size == 64 ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS), + "NtOpenKey failed: 0x%08lx\n", status ); + if (!status) pNtClose( key ); + + status = pNtOpenKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); + ok( status == (ptr_size == 64 ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS), + "NtOpenKey failed: 0x%08lx\n", status ); + if (!status) pNtClose( key ); + + pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes\Wow6432Node" ); + status = pNtOpenKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( root32, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); + ok( full_info->SubKeys > 0, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys32 = full_info->SubKeys; + pNtClose( root32 ); + + pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes" ); + status = pNtOpenKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); + ok( full_info->SubKeys > subkeys32, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys64 = full_info->SubKeys; + pNtClose( root64 ); + + status = pNtOpenKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( root32, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); + todo_wine_if(ptr_size == 32) ok( full_info->SubKeys == subkeys64, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys = full_info->SubKeys; + + found = FALSE; + for (i = 0; i < subkeys; i++) + { + status = pNtEnumerateKey( root32, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); + + if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) + found = TRUE; + } + todo_wine_if(ptr_size == 32) ok( ptr_size == 32 ? found : !found, "key not found\n" ); + pNtClose( root32 ); + + status = pNtOpenKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); + ok( full_info->SubKeys == subkeys64, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys = full_info->SubKeys; + + found = FALSE; + for (i = 0; i < subkeys; i++) + { + status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); + + if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) + found = TRUE; + } + ok( ptr_size == 32 ? found : !found, "key not found\n" ); + pNtClose( root64 ); + + status = pNtOpenKey( &root64, KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); + todo_wine_if(ptr_size == 32) ok( full_info->SubKeys == subkeys64, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys = full_info->SubKeys; + + found = FALSE; + for (i = 0; i < subkeys; i++) + { + status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); + + if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) + found = TRUE; + } + todo_wine_if(ptr_size == 32) ok( ptr_size == 32 ? found : !found, "key not found\n" ); + pNtClose( root64 ); + + pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes\Wow6432Node" ); + status = pNtOpenKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( root32, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); + ok( full_info->SubKeys == subkeys32, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys = full_info->SubKeys; + + found = FALSE; + for (i = 0; i < subkeys; i++) + { + status = pNtEnumerateKey( root32, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); + + if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) + found = TRUE; + } + ok( ptr_size == 32 ? !found : found, "key not found\n" ); + pNtClose( root32 ); + + status = pNtOpenKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); + ok( full_info->SubKeys == subkeys32, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys = full_info->SubKeys; + + found = FALSE; + for (i = 0; i < subkeys; i++) + { + status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); + + if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) + found = TRUE; + } + ok( ptr_size == 32 ? !found : found, "key not found\n" ); + pNtClose( root64 ); + + status = pNtOpenKey( &root64, KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); + ok( full_info->SubKeys == subkeys32, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys = full_info->SubKeys; + + found = FALSE; + for (i = 0; i < subkeys; i++) + { + status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); + + if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) + found = TRUE; + } + ok( ptr_size == 32 ? !found : found, "key not found\n" ); + pNtClose( root64 ); + + pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Wow6432Node\Classes" ); + status = pNtOpenKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( root32, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); + todo_wine_if(ptr_size == 32) ok( full_info->SubKeys == (ptr_size == 32 ? subkeys64 : subkeys32), "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys = full_info->SubKeys; + + found = FALSE; + for (i = 0; i < subkeys; i++) + { + status = pNtEnumerateKey( root32, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); + + if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) + found = TRUE; + } + todo_wine_if(ptr_size == 32) ok( found, "key not found\n" ); + pNtClose( root32 ); + + status = pNtOpenKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); + ok( full_info->SubKeys == subkeys32, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys = full_info->SubKeys; + + found = FALSE; + for (i = 0; i < subkeys; i++) + { + status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); + + if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) + found = TRUE; + } + ok( ptr_size == 32 ? !found : found, "key not found\n" ); + pNtClose( root64 ); + + status = pNtOpenKey( &root64, KEY_ALL_ACCESS, &attr ); + ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NQtueryKey failed: 0x%08lx\n", status ); + todo_wine_if(ptr_size == 32) ok( full_info->SubKeys == (ptr_size == 32 ? subkeys64 : subkeys32), "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys = full_info->SubKeys; + + found = FALSE; + for (i = 0; i < subkeys; i++) + { + status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); + ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); + + if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) + found = TRUE; + } + todo_wine_if(ptr_size == 32) ok( found, "key not found\n" ); + pNtClose( root64 ); + + pNtDeleteKey( key32 ); + pNtClose( key32 ); }
static void test_long_value_name(void)
From: Sven Baars sbaars@codeweavers.com
--- dlls/ntdll/tests/reg.c | 16 ++++++++-------- server/registry.c | 20 ++++++++++++++++---- 2 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 420dd1b755f..9b61409fc27 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -2124,7 +2124,7 @@ static void test_redirection(void)
status = pNtQueryKey( root32, KeyFullInformation, full_info, sizeof(buffer), &len ); ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); - todo_wine_if(ptr_size == 32) ok( full_info->SubKeys == subkeys64, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + ok( full_info->SubKeys == subkeys64, "wrong number of subkeys: %lu\n", full_info->SubKeys ); subkeys = full_info->SubKeys;
found = FALSE; @@ -2136,7 +2136,7 @@ static void test_redirection(void) if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) found = TRUE; } - todo_wine_if(ptr_size == 32) ok( ptr_size == 32 ? found : !found, "key not found\n" ); + ok( ptr_size == 32 ? found : !found, "key not found\n" ); pNtClose( root32 );
status = pNtOpenKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); @@ -2164,7 +2164,7 @@ static void test_redirection(void)
status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); - todo_wine_if(ptr_size == 32) ok( full_info->SubKeys == subkeys64, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + ok( full_info->SubKeys == subkeys64, "wrong number of subkeys: %lu\n", full_info->SubKeys ); subkeys = full_info->SubKeys;
found = FALSE; @@ -2176,7 +2176,7 @@ static void test_redirection(void) if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) found = TRUE; } - todo_wine_if(ptr_size == 32) ok( ptr_size == 32 ? found : !found, "key not found\n" ); + ok( ptr_size == 32 ? found : !found, "key not found\n" ); pNtClose( root64 );
pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes\Wow6432Node" ); @@ -2246,7 +2246,7 @@ static void test_redirection(void)
status = pNtQueryKey( root32, KeyFullInformation, full_info, sizeof(buffer), &len ); ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); - todo_wine_if(ptr_size == 32) ok( full_info->SubKeys == (ptr_size == 32 ? subkeys64 : subkeys32), "wrong number of subkeys: %lu\n", full_info->SubKeys ); + ok( full_info->SubKeys == (ptr_size == 32 ? subkeys64 : subkeys32), "wrong number of subkeys: %lu\n", full_info->SubKeys ); subkeys = full_info->SubKeys;
found = FALSE; @@ -2258,7 +2258,7 @@ static void test_redirection(void) if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) found = TRUE; } - todo_wine_if(ptr_size == 32) ok( found, "key not found\n" ); + ok( found, "key not found\n" ); pNtClose( root32 );
status = pNtOpenKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); @@ -2286,7 +2286,7 @@ static void test_redirection(void)
status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); ok( status == STATUS_SUCCESS, "NQtueryKey failed: 0x%08lx\n", status ); - todo_wine_if(ptr_size == 32) ok( full_info->SubKeys == (ptr_size == 32 ? subkeys64 : subkeys32), "wrong number of subkeys: %lu\n", full_info->SubKeys ); + ok( full_info->SubKeys == (ptr_size == 32 ? subkeys64 : subkeys32), "wrong number of subkeys: %lu\n", full_info->SubKeys ); subkeys = full_info->SubKeys;
found = FALSE; @@ -2298,7 +2298,7 @@ static void test_redirection(void) if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) found = TRUE; } - todo_wine_if(ptr_size == 32) ok( found, "key not found\n" ); + ok( found, "key not found\n" ); pNtClose( root64 );
pNtDeleteKey( key32 ); diff --git a/server/registry.c b/server/registry.c index d112987b2b9..f34ccc3ef24 100644 --- a/server/registry.c +++ b/server/registry.c @@ -516,6 +516,15 @@ static struct object *key_lookup_name( struct object *obj, struct unicode_str *n set_error( STATUS_OBJECT_NAME_NOT_FOUND ); } } + + key = (struct key *)obj; + if (key && (key->flags & KEY_WOWSHARE) && (attr & OBJ_KEY_WOW64)) + { + key = get_parent( key ); + release_object( obj ); + return grab_object( key ); + } + return obj; }
@@ -768,6 +777,7 @@ static struct key *grab_wow6432node( struct key *key ) struct key *ret = key->wow6432node;
if (!ret) return key; + if (ret->flags & KEY_WOWSHARE) return key; grab_object( ret ); release_object( key ); return ret; @@ -810,9 +820,10 @@ static struct key *open_key( struct key *parent, const struct unicode_str *name, return NULL; }
- if (parent && (access & KEY_WOW64_32KEY) && !is_wow6432node( name->str, name->len )) + if (parent && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name->str, name->len )) { - if ((key = get_wow6432node( parent ))) + key = get_wow6432node( parent ); + if (key && ((access & KEY_WOW64_32KEY) || (key->flags & KEY_WOWSHARE))) parent = key; }
@@ -835,9 +846,10 @@ static struct key *create_key( struct key *parent, const struct unicode_str *nam
if (options & REG_OPTION_CREATE_LINK) attributes = (attributes & ~OBJ_OPENIF) | OBJ_OPENLINK;
- if (parent && (access & KEY_WOW64_32KEY) && !is_wow6432node( name->str, name->len )) + if (parent && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name->str, name->len )) { - if ((key = get_wow6432node( parent ))) + key = get_wow6432node( parent ); + if (key && ((access & KEY_WOW64_32KEY) || (key->flags & KEY_WOWSHARE))) parent = key; }
From: Sven Baars sbaars@codeweavers.com
Instead pass a Wine specific attribute to NtOpenKey() that was already used internally in the server. --- dlls/advapi32/tests/registry.c | 15 ++---- dlls/kernelbase/registry.c | 97 ++++++++-------------------------- server/registry.c | 3 +- 3 files changed, 27 insertions(+), 88 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index b4f0398b358..fe84c0ef417 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -2615,12 +2615,9 @@ static void test_redirection(void) err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL ); ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err ); - check_key_value( key, "Wine\Winetest", 0, ptr_size ); check_key_value( key, "Wine\Winetest", KEY_WOW64_64KEY, ptr_size ); - dw = get_key_value( key, "Wine\Winetest", KEY_WOW64_32KEY ); - todo_wine_if (ptr_size == 64) ok( dw == 32, "wrong value %lu\n", dw ); - + check_key_value( key, "Wine\Winetest", KEY_WOW64_32KEY, 32 ); check_key_value( key, "Wow6432Node\Wine\Winetest", 0, ptr_size == 32 ? 0 : 32 ); check_key_value( key, "Wow6432Node\Wine\Winetest", KEY_WOW64_64KEY, ptr_size == 32 ? 0 : 32 ); check_key_value( key, "Wow6432Node\Wine\Winetest", KEY_WOW64_32KEY, ptr_size == 32 ? 0 : 32 ); @@ -2632,8 +2629,7 @@ static void test_redirection(void) dw = get_key_value( key, "Wine\Winetest", 0 ); ok( dw == 64 || broken(dw == 32) /* win7 */, "wrong value %lu\n", dw ); check_key_value( key, "Wine\Winetest", KEY_WOW64_64KEY, 64 ); - dw = get_key_value( key, "Wine\Winetest", KEY_WOW64_32KEY ); - todo_wine_if (ptr_size == 64) ok( dw == 32, "wrong value %lu\n", dw ); + check_key_value( key, "Wine\Winetest", KEY_WOW64_32KEY, 32 ); check_key_value( key, "Wow6432Node\Wine\Winetest", 0, 32 ); check_key_value( key, "Wow6432Node\Wine\Winetest", KEY_WOW64_64KEY, 32 ); check_key_value( key, "Wow6432Node\Wine\Winetest", KEY_WOW64_32KEY, 32 ); @@ -2710,9 +2706,7 @@ static void test_redirection(void) ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err ); check_key_value( key, "Winetest", 0, ptr_size ); check_key_value( key, "Winetest", KEY_WOW64_64KEY, ptr_size ); - dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY ); - todo_wine_if (ptr_size != 32) - ok( dw == 32, "wrong value %lu\n", dw ); + check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 ); RegCloseKey( key );
err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\Wine", 0, NULL, 0, @@ -2720,8 +2714,7 @@ static void test_redirection(void) ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err ); check_key_value( key, "Winetest", 0, 64 ); check_key_value( key, "Winetest", KEY_WOW64_64KEY, 64 ); - dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY ); - todo_wine_if (ptr_size == 64) ok( dw == 32, "wrong value %lu\n", dw ); + check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 ); RegCloseKey( key );
err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\Wine", 0, NULL, 0, diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 91462d80e06..5fd4c5aef2d 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -50,6 +50,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(reg); #define HKEY_SPECIAL_ROOT_FIRST HKEY_CLASSES_ROOT #define HKEY_SPECIAL_ROOT_LAST HKEY_DYN_DATA
+#define OBJ_KEY_WOW64 0x100000 /* magic flag added to attributes for WoW64 redirection */ + static const WCHAR * const root_key_names[] = { L"\Registry\Machine\Software\Classes", @@ -214,80 +216,6 @@ static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES return status; }
-/* wrapper for NtOpenKeyEx to handle Wow6432 nodes */ -static NTSTATUS open_key( HKEY *retkey, DWORD options, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr ) -{ - NTSTATUS status; - BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY); - HANDLE subkey, root = attr->RootDirectory; - WCHAR *buffer = attr->ObjectName->Buffer; - DWORD pos = 0, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR); - UNICODE_STRING str; - - *retkey = NULL; - - if (!force_wow32) - { - if (options & REG_OPTION_OPEN_LINK) attr->Attributes |= OBJ_OPENLINK; - 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; - while (i < len && buffer[i] != '\') i++; - attr->ObjectName = &str; - - for (;;) - { - str.Buffer = buffer + pos; - str.Length = (i - pos) * sizeof(WCHAR); - if (force_wow32 && pos) - { - if (is_wow6432node( &str )) force_wow32 = FALSE; - else if ((subkey = open_wow6432node( attr->RootDirectory ))) - { - if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); - attr->RootDirectory = subkey; - force_wow32 = FALSE; - } - } - if (i == len) - { - if (options & REG_OPTION_OPEN_LINK) attr->Attributes |= OBJ_OPENLINK; - status = NtOpenKeyEx( &subkey, access, attr, options ); - } - else - { - if (!(options & REG_OPTION_OPEN_LINK)) attr->Attributes &= ~OBJ_OPENLINK; - status = NtOpenKeyEx( &subkey, access, attr, options & ~REG_OPTION_OPEN_LINK ); - } - if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); - if (status) return status; - attr->RootDirectory = subkey; - if (i == len) break; - while (i < len && buffer[i] == '\') i++; - pos = i; - while (i < len && buffer[i] != '\') i++; - } - if (force_wow32 && (subkey = open_wow6432node( attr->RootDirectory ))) - { - 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; -} - /* create one of the HKEY_* special root keys */ static HKEY create_special_root_hkey( HKEY hkey, DWORD access ) { @@ -515,6 +443,7 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD o { OBJECT_ATTRIBUTES attr; UNICODE_STRING nameW; + NTSTATUS status;
if (retkey && (!name || !name[0]) && (HandleToUlong(hkey) >= HandleToUlong(HKEY_SPECIAL_ROOT_FIRST)) && @@ -538,7 +467,16 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD o attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; RtlInitUnicodeString( &nameW, name ); - return RtlNtStatusToDosError( open_key( retkey, options, access, &attr ) ); + + if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK; + if (!is_wow64 && (access & KEY_WOW64_32KEY)) attr.Attributes |= OBJ_KEY_WOW64; + status = NtOpenKeyEx( (HANDLE *)retkey, access, &attr, options ); + if (status == STATUS_PREDEFINED_HANDLE) + { + *retkey = get_perflib_key( *retkey ); + status = STATUS_SUCCESS; + } + return RtlNtStatusToDosError( status ); }
@@ -596,7 +534,14 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD op if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, &nameA, FALSE ))) { - status = open_key( retkey, options, access, &attr ); + if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK; + if (!is_wow64 && (access & KEY_WOW64_32KEY)) attr.Attributes |= OBJ_KEY_WOW64; + status = NtOpenKeyEx( (HANDLE *)retkey, access, &attr, options ); + if (status == STATUS_PREDEFINED_HANDLE) + { + *retkey = get_perflib_key( *retkey ); + status = STATUS_SUCCESS; + } } return RtlNtStatusToDosError( status ); } diff --git a/server/registry.c b/server/registry.c index f34ccc3ef24..802374f46b6 100644 --- a/server/registry.c +++ b/server/registry.c @@ -2203,7 +2203,8 @@ DECL_HANDLER(open_key) unsigned int access = req->access; struct unicode_str name = get_req_unicode_str();
- if (!is_wow64_thread( current )) access = (access & ~KEY_WOW64_32KEY) | KEY_WOW64_64KEY; + if (!is_wow64_thread( current ) && !(req->attributes & OBJ_KEY_WOW64)) + access = (access & ~KEY_WOW64_32KEY) | KEY_WOW64_64KEY;
if (req->parent && !(parent = get_hkey_obj( req->parent, 0 ))) return;
From: Sven Baars sbaars@codeweavers.com
--- dlls/kernelbase/registry.c | 45 ++++---------------------------------- server/registry.c | 3 ++- 2 files changed, 6 insertions(+), 42 deletions(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 5fd4c5aef2d..78c8e7fdf6e 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -100,29 +100,6 @@ static inline BOOL is_version_nt(void) return !(GetVersion() & 0x80000000); }
-static BOOL is_wow6432node( const UNICODE_STRING *name ) -{ - return (name->Length == 11 * sizeof(WCHAR) && !wcsnicmp( name->Buffer, L"Wow6432Node", 11 )); -} - -/* open the Wow6432Node subkey of the specified key */ -static HANDLE open_wow6432node( HANDLE key ) -{ - OBJECT_ATTRIBUTES attr; - UNICODE_STRING nameW; - HANDLE ret; - - attr.Length = sizeof(attr); - attr.RootDirectory = key; - attr.ObjectName = &nameW; - attr.Attributes = 0; - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; - RtlInitUnicodeString( &nameW, L"Wow6432Node" ); - if (NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 )) ret = 0; - return ret; -} - static HKEY get_perflib_key( HANDLE key ) { static const WCHAR performance_text[] = @@ -146,11 +123,12 @@ static HKEY get_perflib_key( HANDLE key ) static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, const UNICODE_STRING *class, ULONG options, PULONG dispos ) { - BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY); NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND; HANDLE subkey, root = attr->RootDirectory;
- if (!force_wow32) status = NtCreateKey( &subkey, access, attr, 0, class, options, dispos ); + if (!is_wow64 && (access & KEY_WOW64_32KEY)) attr->Attributes |= OBJ_KEY_WOW64; + + status = NtCreateKey( &subkey, access, attr, 0, class, options, dispos );
if (status == STATUS_OBJECT_NAME_NOT_FOUND) { @@ -162,7 +140,7 @@ static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES if (!attr->RootDirectory && len > 10 && !wcsnicmp( buffer, L"\Registry\", 10 )) i += 10;
while (i < len && buffer[i] != '\') i++; - if (i == len && !force_wow32) return status; + if (i == len) return status;
attrs = attr->Attributes; attr->ObjectName = &str; @@ -171,16 +149,6 @@ static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES { str.Buffer = buffer + pos; str.Length = (i - pos) * sizeof(WCHAR); - if (force_wow32 && pos) - { - if (is_wow6432node( &str )) force_wow32 = FALSE; - else if ((subkey = open_wow6432node( attr->RootDirectory ))) - { - if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); - attr->RootDirectory = subkey; - force_wow32 = FALSE; - } - } if (i == len) { attr->Attributes = attrs; @@ -202,11 +170,6 @@ static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES } } attr->RootDirectory = subkey; - if (force_wow32 && (subkey = open_wow6432node( attr->RootDirectory ))) - { - if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); - attr->RootDirectory = subkey; - } if (status == STATUS_PREDEFINED_HANDLE) { attr->RootDirectory = get_perflib_key( attr->RootDirectory ); diff --git a/server/registry.c b/server/registry.c index 802374f46b6..20fbfba34d5 100644 --- a/server/registry.c +++ b/server/registry.c @@ -2176,7 +2176,8 @@ DECL_HANDLER(create_key)
if (!objattr) return;
- if (!is_wow64_thread( current )) access = (access & ~KEY_WOW64_32KEY) | KEY_WOW64_64KEY; + if (!is_wow64_thread( current ) && !(objattr->attributes & OBJ_KEY_WOW64)) + access = (access & ~KEY_WOW64_32KEY) | KEY_WOW64_64KEY;
if (objattr->rootdir) {
From: Sven Baars sbaars@codeweavers.com
The server always returns the same key now anyway. --- dlls/kernelbase/registry.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 78c8e7fdf6e..350e104130c 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -206,7 +206,7 @@ static HKEY create_special_root_hkey( HKEY hkey, DWORD access ) TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey ); }
- if (!cache_disabled[idx] && !(access & (KEY_WOW64_64KEY | KEY_WOW64_32KEY))) + if (!cache_disabled[idx]) { if (!(ret = InterlockedCompareExchangePointer( (void **)&special_root_keys[idx], hkey, 0 ))) ret = hkey; @@ -222,15 +222,10 @@ static HKEY create_special_root_hkey( HKEY hkey, DWORD access ) static inline HKEY get_special_root_hkey( HKEY hkey, REGSAM access ) { unsigned int index = HandleToUlong(hkey) - HandleToUlong(HKEY_SPECIAL_ROOT_FIRST); - DWORD wow64_flags = access & (KEY_WOW64_32KEY | KEY_WOW64_64KEY);
switch (HandleToUlong(hkey)) { case (LONG)(LONG_PTR)HKEY_CLASSES_ROOT: - if (wow64_flags) - return create_special_root_hkey( hkey, MAXIMUM_ALLOWED | wow64_flags ); - /* fall through */ - case (LONG)(LONG_PTR)HKEY_CURRENT_USER: case (LONG)(LONG_PTR)HKEY_LOCAL_MACHINE: case (LONG)(LONG_PTR)HKEY_USERS:
From: Sven Baars sbaars@codeweavers.com
--- loader/wine.inf.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/loader/wine.inf.in b/loader/wine.inf.in index e7b435ed0f0..bcea63e484a 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -521,11 +521,11 @@ HKLM,%MciExtStr%,"wvx",,"MPEGVideo"
[Misc] HKLM,Software\Borland\Database Engine\Settings\SYSTEM\INIT,SHAREDMEMLOCATION,,9000 +HKLM,Software\Clients,,16 HKLM,Software\Clients\Mail,,2,"Native Mail Client" HKLM,Software\Clients\Mail\Native Mail Client,,2,"Native Mail Client" HKLM,Software\Clients\Mail\Native Mail Client,"DLLPath",2,"%11%\winemapi.dll" HKLM,Software\Microsoft\Advanced INF Setup,,16 -HKLM,Software\Microsoft\Clients,,16 HKLM,Software\Microsoft\Cryptography\Calais\Current,,16 HKLM,Software\Microsoft\Cryptography\Calais\Readers,,16 HKLM,Software\Microsoft\Cryptography\Services,,16 @@ -2497,7 +2497,7 @@ HKLM,Software\Classes\Wow6432Node\Interface,,16 HKLM,Software\Classes\Wow6432Node\Media Type,,16 HKLM,Software\Classes\Wow6432Node\MediaFoundation,,16 ; symlinks for shared keys under HKLM\Software -HKLM,Software\Wow6432Node\Microsoft\Clients,"SymbolicLinkValue",0x60000,"\Registry\Machine\Software\Microsoft\Clients" +HKLM,Software\Wow6432Node\Clients,"SymbolicLinkValue",0x60000,"\Registry\Machine\Software\Clients" HKLM,Software\Wow6432Node\Microsoft\Cryptography\Calais\Current,"SymbolicLinkValue",0x60000,"\Registry\Machine\Software\Microsoft\Cryptography\Calais\Current" HKLM,Software\Wow6432Node\Microsoft\Cryptography\Calais\Readers,"SymbolicLinkValue",0x60000,"\Registry\Machine\Software\Microsoft\Cryptography\Calais\Readers" HKLM,Software\Wow6432Node\Microsoft\Cryptography\Services,"SymbolicLinkValue",0x60000,"\Registry\Machine\Software\Microsoft\Cryptography\Services"
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=125096
Your paranoid android.
=== debian11 (32 bit report) ===
ddraw: ddraw7.c:15663: Test failed: Expected unsynchronised map for flags 0x1000. ddraw7.c:15663: Test failed: Expected unsynchronised map for flags 0x3000.
=== debian11 (build log) ===
Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24892. Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24892. Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24892.
From: Sven Baars sbaars@codeweavers.com
--- dlls/ntdll/tests/reg.c | 248 +++++++++++------------------------------ 1 file changed, 63 insertions(+), 185 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 9b61409fc27..71f30924d1f 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -1464,20 +1464,61 @@ static void _check_key_value( int line, HANDLE root, const char *name, DWORD fla } #define check_key_value(root,name,flags,expect) _check_key_value( __LINE__, root, name, flags, expect )
+static void _check_enum_value( int line, const WCHAR *name, DWORD flags, int subkeys, BOOL present) +{ + static const WCHAR wineW[] = {'W','i','n','e'}; + char buffer[1024]; + KEY_BASIC_INFORMATION *basic_info = (KEY_BASIC_INFORMATION *)buffer; + KEY_FULL_INFORMATION *full_info = (KEY_FULL_INFORMATION *)buffer; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING str; + NTSTATUS status; + BOOL found; + HANDLE key; + DWORD len; + int i; + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &str; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + + pRtlInitUnicodeString( &str, name ); + status = pNtOpenKey( &key, flags, &attr ); + ok_( __FILE__, line )( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); + + status = pNtQueryKey( key, KeyFullInformation, full_info, sizeof(buffer), &len ); + ok_( __FILE__, line )( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); + ok_( __FILE__, line )( full_info->SubKeys == subkeys, "wrong number of subkeys: %lu\n", full_info->SubKeys ); + subkeys = full_info->SubKeys; + + found = FALSE; + for (i = 0; i < subkeys; i++) + { + status = pNtEnumerateKey( key, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); + ok_( __FILE__, line )( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); + + if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) + found = TRUE; + } + ok_( __FILE__, line )( found == present, "key not found\n" ); + pNtClose( key ); +} +#define check_enum_value(name, flags, subkeys, present) _check_enum_value( __LINE__, name, flags, subkeys, present ) + static void test_redirection(void) { - WCHAR wineW[] = {'W','i','n','e'}; NTSTATUS status; OBJECT_ATTRIBUTES attr; UNICODE_STRING str; char buffer[1024]; KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; - KEY_BASIC_INFORMATION *basic_info = (KEY_BASIC_INFORMATION *)buffer; KEY_FULL_INFORMATION *full_info = (KEY_FULL_INFORMATION *)buffer; DWORD dw, len; HANDLE key, key32, key64, root, root32, root64; - int i, subkeys, subkeys64, subkeys32; - BOOL found; + int subkeys64, subkeys32;
if (ptr_size != 64) { @@ -2119,187 +2160,24 @@ static void test_redirection(void) subkeys64 = full_info->SubKeys; pNtClose( root64 );
- status = pNtOpenKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); - ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); - - status = pNtQueryKey( root32, KeyFullInformation, full_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); - ok( full_info->SubKeys == subkeys64, "wrong number of subkeys: %lu\n", full_info->SubKeys ); - subkeys = full_info->SubKeys; - - found = FALSE; - for (i = 0; i < subkeys; i++) - { - status = pNtEnumerateKey( root32, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); - - if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) - found = TRUE; - } - ok( ptr_size == 32 ? found : !found, "key not found\n" ); - pNtClose( root32 ); - - status = pNtOpenKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); - ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); - - status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); - ok( full_info->SubKeys == subkeys64, "wrong number of subkeys: %lu\n", full_info->SubKeys ); - subkeys = full_info->SubKeys; - - found = FALSE; - for (i = 0; i < subkeys; i++) - { - status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); - - if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) - found = TRUE; - } - ok( ptr_size == 32 ? found : !found, "key not found\n" ); - pNtClose( root64 ); - - status = pNtOpenKey( &root64, KEY_ALL_ACCESS, &attr ); - ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); - - status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); - ok( full_info->SubKeys == subkeys64, "wrong number of subkeys: %lu\n", full_info->SubKeys ); - subkeys = full_info->SubKeys; - - found = FALSE; - for (i = 0; i < subkeys; i++) - { - status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); - - if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) - found = TRUE; - } - ok( ptr_size == 32 ? found : !found, "key not found\n" ); - pNtClose( root64 ); - - pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes\Wow6432Node" ); - status = pNtOpenKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); - ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); - - status = pNtQueryKey( root32, KeyFullInformation, full_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); - ok( full_info->SubKeys == subkeys32, "wrong number of subkeys: %lu\n", full_info->SubKeys ); - subkeys = full_info->SubKeys; - - found = FALSE; - for (i = 0; i < subkeys; i++) - { - status = pNtEnumerateKey( root32, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); - - if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) - found = TRUE; - } - ok( ptr_size == 32 ? !found : found, "key not found\n" ); - pNtClose( root32 ); - - status = pNtOpenKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); - ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); - - status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); - ok( full_info->SubKeys == subkeys32, "wrong number of subkeys: %lu\n", full_info->SubKeys ); - subkeys = full_info->SubKeys; - - found = FALSE; - for (i = 0; i < subkeys; i++) - { - status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); - - if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) - found = TRUE; - } - ok( ptr_size == 32 ? !found : found, "key not found\n" ); - pNtClose( root64 ); - - status = pNtOpenKey( &root64, KEY_ALL_ACCESS, &attr ); - ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); - - status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); - ok( full_info->SubKeys == subkeys32, "wrong number of subkeys: %lu\n", full_info->SubKeys ); - subkeys = full_info->SubKeys; - - found = FALSE; - for (i = 0; i < subkeys; i++) - { - status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); - - if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) - found = TRUE; - } - ok( ptr_size == 32 ? !found : found, "key not found\n" ); - pNtClose( root64 ); - - pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Wow6432Node\Classes" ); - status = pNtOpenKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr ); - ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); - - status = pNtQueryKey( root32, KeyFullInformation, full_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); - ok( full_info->SubKeys == (ptr_size == 32 ? subkeys64 : subkeys32), "wrong number of subkeys: %lu\n", full_info->SubKeys ); - subkeys = full_info->SubKeys; - - found = FALSE; - for (i = 0; i < subkeys; i++) - { - status = pNtEnumerateKey( root32, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); - - if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) - found = TRUE; - } - ok( found, "key not found\n" ); - pNtClose( root32 ); - - status = pNtOpenKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); - ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); - - status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtQueryKey failed: 0x%08lx\n", status ); - ok( full_info->SubKeys == subkeys32, "wrong number of subkeys: %lu\n", full_info->SubKeys ); - subkeys = full_info->SubKeys; - - found = FALSE; - for (i = 0; i < subkeys; i++) - { - status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); - - if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) - found = TRUE; - } - ok( ptr_size == 32 ? !found : found, "key not found\n" ); - pNtClose( root64 ); - - status = pNtOpenKey( &root64, KEY_ALL_ACCESS, &attr ); - ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status ); - - status = pNtQueryKey( root64, KeyFullInformation, full_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NQtueryKey failed: 0x%08lx\n", status ); - ok( full_info->SubKeys == (ptr_size == 32 ? subkeys64 : subkeys32), "wrong number of subkeys: %lu\n", full_info->SubKeys ); - subkeys = full_info->SubKeys; - - found = FALSE; - for (i = 0; i < subkeys; i++) - { - status = pNtEnumerateKey( root64, i, KeyBasicInformation, basic_info, sizeof(buffer), &len ); - ok( status == STATUS_SUCCESS, "NtEnumerateKey failed: 0x%08lx\n", status ); - - if (basic_info->NameLength == sizeof(wineW) && !memcmp(basic_info->Name, wineW, sizeof(wineW) )) - found = TRUE; - } - ok( found, "key not found\n" ); - pNtClose( root64 ); + check_enum_value( L"\Registry\Machine\Software\Classes", + KEY_WOW64_32KEY | KEY_ALL_ACCESS, subkeys64, ptr_size == 32 ); + check_enum_value( L"\Registry\Machine\Software\Classes", + KEY_WOW64_64KEY | KEY_ALL_ACCESS, subkeys64, ptr_size == 32 ); + check_enum_value( L"\Registry\Machine\Software\Classes", + KEY_ALL_ACCESS, subkeys64, ptr_size == 32 ); + check_enum_value( L"\Registry\Machine\Software\Classes\Wow6432Node", + KEY_WOW64_32KEY | KEY_ALL_ACCESS, subkeys32, ptr_size == 64 ); + check_enum_value( L"\Registry\Machine\Software\Classes\Wow6432Node", + KEY_WOW64_64KEY | KEY_ALL_ACCESS, subkeys32, ptr_size == 64 ); + check_enum_value( L"\Registry\Machine\Software\Classes\Wow6432Node", + KEY_ALL_ACCESS, subkeys32, ptr_size == 64 ); + check_enum_value( L"\Registry\Machine\Software\Wow6432Node\Classes", + KEY_WOW64_32KEY | KEY_ALL_ACCESS, ptr_size == 32 ? subkeys64 : subkeys32, TRUE ); + check_enum_value( L"\Registry\Machine\Software\Wow6432Node\Classes", + KEY_WOW64_64KEY | KEY_ALL_ACCESS, subkeys32, ptr_size == 64 ); + check_enum_value( L"\Registry\Machine\Software\Wow6432Node\Classes", + KEY_ALL_ACCESS, ptr_size == 32 ? subkeys64 : subkeys32, TRUE );
pNtDeleteKey( key32 ); pNtClose( key32 );
Not sure if this will be helpful, but I guess Windows really does implement all the redirection at the advapi32 level, not in the kernel.
Chrome implements its registry APIs on top of Nt* and has to re-implement all the redirection rules there by adding `WOW6432Node` into the path at the right place: https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_elf/n...
Also: https://stackoverflow.com/questions/13239049/whats-the-correct-way-to-redire... and https://learn.microsoft.com/en-us/windows/win32/winprog64/shared-registry-ke...
Maybe they do, but somehow all of the weird edge cases I tested are the same (which I find suspicious), and this has to be a pain to implement (we already did it wrong once) without having the full registry tree available, especially when you have to recurse backwards like I do in the second patch. If I can somehow just use what we already have in the server that would probably save us some future debugging, and also makes the code easier to read.
While refactoring the tests so I could copy-paste them to advapi32 to prove my above point in a readable manner I found another thing that doesn't work with the shared registry. Guess I'm back to fixing things.