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).
-- v2: 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. ntdll/tests: Add some Software\Classes subkey tests.
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 | 4 ++-- server/registry.c | 36 +++++++++++++++++++++++++++++----- 3 files changed, 34 insertions(+), 8 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..ae681bb7aba 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -1631,7 +1631,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_if (ptr_size == 32) ok( dw == ptr_size, "wrong value %lu\n", dw ); + ok( dw == ptr_size, "wrong value %lu\n", dw ); pNtClose( key );
status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); @@ -1992,7 +1992,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 ae681bb7aba..59d14c1d14b 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -1649,6 +1649,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 59d14c1d14b..6db961d5bf4 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) { @@ -2060,6 +2065,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 6db961d5bf4..80083632061 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -2125,7 +2125,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; @@ -2137,7 +2137,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 ); @@ -2165,7 +2165,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; @@ -2177,7 +2177,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" ); @@ -2247,7 +2247,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; @@ -2259,7 +2259,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 ); @@ -2287,7 +2287,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; @@ -2299,7 +2299,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 acccess mask value to NtOpenKey(). --- dlls/advapi32/tests/registry.c | 9 ++-- dlls/kernelbase/registry.c | 95 +++++++--------------------------- include/winnt.h | 3 ++ server/registry.c | 3 +- 4 files changed, 28 insertions(+), 82 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index b4f0398b358..6d7f8d4f7bb 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -2619,7 +2619,7 @@ static void test_redirection(void) 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 ); + ok( dw == 32, "wrong value %lu\n", dw );
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 ); @@ -2633,7 +2633,7 @@ static void test_redirection(void) 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 ); + ok( dw == 32, "wrong value %lu\n", dw ); 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 ); @@ -2711,8 +2711,7 @@ static void test_redirection(void) 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 ); + ok( dw == 32, "wrong value %lu\n", dw ); RegCloseKey( key );
err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\Wine", 0, NULL, 0, @@ -2721,7 +2720,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_if (ptr_size == 64) ok( dw == 32, "wrong value %lu\n", dw ); + ok( dw == 32, "wrong value %lu\n", dw ); 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..16cf8c73523 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -214,80 +214,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 +441,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 +465,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_FORCE_32KEY; + 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 +532,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_FORCE_32KEY; + 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/include/winnt.h b/include/winnt.h index 836bd7123e5..90f04bdb42c 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -5511,6 +5511,9 @@ typedef struct _TAPE_GET_MEDIA_PARAMETERS { #define KEY_WOW64_64KEY 0x00000100 #define KEY_WOW64_32KEY 0x00000200 #define KEY_WOW64_RES 0x00000300 +#ifdef __WINESRC__ +#define KEY_WOW64_FORCE_32KEY 0x80000000 /* Not a Windows flag */ +#endif
/* for RegKeyRestore flags */ #define REG_WHOLE_HIVE_VOLATILE 0x00000001 diff --git a/server/registry.c b/server/registry.c index f34ccc3ef24..0f96ae23c1d 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 ) && !((access & KEY_WOW64_32KEY) && (access & KEY_WOW64_FORCE_32KEY))) + 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 16cf8c73523..a0cd2be33ea 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -98,29 +98,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[] = @@ -144,11 +121,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_FORCE_32KEY; + + status = NtCreateKey( &subkey, access, attr, 0, class, options, dispos );
if (status == STATUS_OBJECT_NAME_NOT_FOUND) { @@ -160,7 +138,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; @@ -169,16 +147,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; @@ -200,11 +168,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 0f96ae23c1d..6e1c2f3bfc8 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 ) && !((access & KEY_WOW64_32KEY) && (access & KEY_WOW64_FORCE_32KEY))) + 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 a0cd2be33ea..4f9d83f423d 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -204,7 +204,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; @@ -220,15 +220,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
--- 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 80083632061..7349b29becb 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) { @@ -2120,187 +2161,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 );
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).
I don't think we want to add a Wine-specific flag. There has to be a way of doing that with the existing APIs.