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).
-- v4: wine.inf: Put the Clients key in the right place. advapi32/tests: Copy Software\Classes tests from ntdll. ntdll/tests: Refactor the Software\Classes tests. 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/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 9d436e82e2f..08f814f2bda 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 ); @@ -1993,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 | 196 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 194 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index c7d9d7e4c7f..9d436e82e2f 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( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); + ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08lx\n", status ); + pNtDeleteKey( key ); + pNtClose( key ); + 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,186 @@ 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 ); + pNtClose( key ); + + 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/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 568bf628dca..c0ae33bd90a 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 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 08f814f2bda..568bf628dca 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 | 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 c0ae33bd90a..45114e204dc 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..03e5f20cae5 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) && !name->str) + { + 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
--- 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 bb52bf8c184..41df93f2676 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
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 03e5f20cae5..bb52bf8c184 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
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
--- dlls/ntdll/tests/reg.c | 268 +++++++++++++---------------------------- 1 file changed, 83 insertions(+), 185 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 45114e204dc..200b39b3818 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -1464,20 +1464,81 @@ 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, "found equals %d\n", found ); + pNtClose( key ); + + status = pNtCreateKey( &key, flags, &attr, 0, 0, 0, 0 ); + ok_( __FILE__, line )( status == STATUS_SUCCESS, "NtCreateKey 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, "found equals %d\n", found ); + 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 +2181,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 );
From: Sven Baars sbaars@codeweavers.com
And add some extra ones. --- dlls/ntdll/tests/reg.c | 251 ++++++++++++----------------------------- 1 file changed, 72 insertions(+), 179 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 200b39b3818..1fbe3a98546 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -1763,68 +1763,27 @@ static void test_redirection(void) 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 ); - - pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes\Wine" ); - 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 );
- 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 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Wine", 0, 64 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Wine", KEY_WOW64_32KEY, 64 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Wow6432Node\Wine", 0, ptr_size == 64 ? 32 : 64 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Wow6432Node\Wine", KEY_WOW64_64KEY, ptr_size == 64 ? 32 : 0 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Wow6432Node\Wine", KEY_WOW64_32KEY, ptr_size == 64 ? 32 : 64 );
- pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes\Wow6432Node\Wine" ); - 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 == 64 ? 32 : 64), "wrong value %lu\n", dw ); pNtDeleteKey( key32 ); pNtClose( key32 );
- pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes\Wine" ); - 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 == ptr_size, "wrong value %lu\n", dw ); - pNtClose( key ); - } - - 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) - { - 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 == ptr_size, "wrong value %lu\n", dw ); - pNtClose( key ); - } + check_key_value( 0, "\Registry\Machine\Software\Classes\Wine", 0, ptr_size == 32 ? 0 : 64 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Wine", KEY_WOW64_64KEY, ptr_size == 32 ? 0 : 64 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Wine", KEY_WOW64_32KEY, ptr_size == 32 ? 0 : 64 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Wow6432Node\Wine", 0, 0 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Wow6432Node\Wine", KEY_WOW64_64KEY, 0 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Wow6432Node\Wine", KEY_WOW64_32KEY, 0 );
pNtDeleteKey( key64 ); pNtClose( key64 ); @@ -1862,85 +1821,45 @@ static void test_redirection(void) 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 ); + check_key_value( root64, "Wine", 0, 64 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, 64 ); + check_key_value( root32, "Wine", 0, 64 ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, 64 );
- 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 == 64, "wrong value %lu\n", dw ); pNtDeleteKey( key32 ); pNtClose( key32 );
- attr.RootDirectory = root64; - 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 ); - - 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 ); + check_key_value( root64, "Wine", 0, 0 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, 0 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, 0 ); + check_key_value( root32, "Wine", 0, 0 ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, 0 ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, 0 );
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; 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 == 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 == 32, "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 == 32, "wrong value %lu\n", dw ); - pNtClose( key64 ); + check_key_value( root64, "Wine", 0, 32 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, 32 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32 ); + check_key_value( root32, "Wine", 0, 32 ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32 ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32 );
pNtDeleteKey( key32 ); pNtClose( key32 ); @@ -2030,96 +1949,70 @@ static void test_redirection(void) 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 ); + check_key_value( root64, "Wine", 0, 64 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, ptr_size ); + check_key_value( root32, "Wine", 0, ptr_size ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, ptr_size ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, ptr_size ); + + pRtlInitUnicodeString( &str, L"\Registry\Machine\Software\Classes\Interface" ); + attr.RootDirectory = 0; + status = pNtOpenKey( &key, KEY_WOW64_64KEY | 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 ); + check_key_value( key, "Wine", 0, 64 ); + check_key_value( key, "Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( key, "Wine", KEY_WOW64_32KEY, ptr_size ); pNtClose( key );
- attr.RootDirectory = root64; - status = pNtOpenKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr ); + status = pNtOpenKey( &key, KEY_WOW64_32KEY | 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 ); + check_key_value( key, "Wine", 0, ptr_size ); + check_key_value( key, "Wine", KEY_WOW64_64KEY, ptr_size ); + check_key_value( key, "Wine", KEY_WOW64_32KEY, ptr_size ); + pNtClose( key ); + + check_key_value( 0, "\Registry\Machine\Software\Classes\Interface\Wine", 0, ptr_size ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Interface\Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Interface\Wine", KEY_WOW64_32KEY, ptr_size );
- 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 ); - ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey failed: 0x%08lx\n", status ); - if (!status) pNtClose( key ); + check_key_value( root64, "Wine", 0, ptr_size == 64 ? 0 : 64 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, ptr_size == 64 ? 0 : 64 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, 0 ); + check_key_value( root32, "Wine", 0, 0 ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, 0 ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, 0 );
- 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 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Interface\Wine", 0, 0 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Interface\Wine", KEY_WOW64_64KEY, ptr_size == 64 ? 0 : 64 ); + check_key_value( 0, "\Registry\Machine\Software\Classes\Interface\Wine", KEY_WOW64_32KEY, 0 );
pNtDeleteKey( key64 ); pNtClose( key64 );
+ pRtlInitUnicodeString( &str, L"Wine" ); + 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; 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 ); - } + check_key_value( root64, "Wine", 0, ptr_size == 64 ? 32 : 0 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, ptr_size == 64 ? 32 : 0 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32 ); + check_key_value( root32, "Wine", 0, 32 ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32 ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32 );
pNtDeleteKey( key32 ); pNtClose( key32 );
From: Sven Baars sbaars@codeweavers.com
--- dlls/advapi32/tests/registry.c | 410 ++++++++++++++++++++++++++++++--- 1 file changed, 384 insertions(+), 26 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index fe84c0ef417..2f2c9958399 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -2554,11 +2554,40 @@ 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 char *name, DWORD flags, DWORD subkeys_in, BOOL found_in) +{ + char buffer[1024]; + DWORD err, i, subkeys; + BOOL found; + HKEY key; + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, name, 0, flags, &key ); + ok_( __FILE__, line )( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegQueryInfoKeyA( key, NULL, NULL, NULL, &subkeys, + NULL, NULL, NULL, NULL, NULL, NULL, NULL ); + ok_( __FILE__, line )( err == ERROR_SUCCESS, "RegQueryInfoKeyA failed: 0x%08lx\n", err ); + ok_( __FILE__, line )( subkeys == subkeys_in, "wrong number of subkeys: %lu\n", subkeys ); + + found = FALSE; + for (i = 0; i < subkeys; i++) + { + err = RegEnumKeyA( key, i, buffer, sizeof(buffer) ); + ok_( __FILE__, line )( err == ERROR_SUCCESS, "RegEnumKeyA failed: 0x%08lx\n", err ); + + if (!strcmp(buffer, "Wine")) + found = TRUE; + } + ok_( __FILE__, line )( found == found_in, "found equals %d\n", found ); + RegCloseKey( key ); +} +#define check_enum_value(name, flags, subkeys, found) _check_enum_value( __LINE__, name, flags, subkeys, found ) + static void test_redirection(void) { DWORD err, type, dw, len; - HKEY key, root32, root64, key32, key64, native, op_key; - REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY); + HKEY key, key32, key64, root, root32, root64; + DWORD subkeys, subkeys32, subkeys64;
if (ptr_size != 64) { @@ -2748,36 +2777,365 @@ static void test_redirection(void) RegCloseKey( root32 ); RegCloseKey( root64 );
- /* open key in native bit mode */ - err = RegOpenKeyExA(HKEY_CLASSES_ROOT, "Interface", 0, KEY_ALL_ACCESS, &native); - ok(err == ERROR_SUCCESS, "got %li\n", err); - - pRegDeleteKeyExA(native, "AWineTest", 0, 0); + /* Software\Classes is shared/reflected so behavior is different */
- /* write subkey in opposite bit mode */ - err = RegOpenKeyExA(HKEY_CLASSES_ROOT, "Interface", 0, KEY_ALL_ACCESS | opposite, &op_key); - ok(err == ERROR_SUCCESS, "got %li\n", err); - - err = RegCreateKeyExA(op_key, "AWineTest", 0, NULL, 0, KEY_ALL_ACCESS | opposite, - NULL, &key, NULL); - ok(err == ERROR_SUCCESS || err == ERROR_ACCESS_DENIED, "got %li\n", err); - if(err != ERROR_SUCCESS){ - win_skip("Can't write to registry\n"); - RegCloseKey(op_key); - RegCloseKey(native); + err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wine", + 0, NULL, 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key64, NULL); + if (err == ERROR_ACCESS_DENIED) + { + skip("Not authorized to modify the Classes key\n"); return; } - RegCloseKey(key); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", + 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + RegCloseKey( key ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", + 0, KEY_ALL_ACCESS, &key ); + ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + "RegOpenKeyExA failed: 0x%08lx\n", err ); + if (!err) RegCloseKey( key ); + + err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", + 0, NULL, 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key32, NULL); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err ); + + dw = 32; + err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); + ok( err == ERROR_SUCCESS, "RegSetValueExA failed: 0x%08lx\n", err ); + + dw = 64; + err = RegSetValueExA( key64, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); + ok( err == ERROR_SUCCESS, "RegSetValueExA failed: 0x%08lx\n", err ); + + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wine", 0, 64 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wine", KEY_WOW64_32KEY, 64 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", 0, ptr_size == 64 ? 0 : 64 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", KEY_WOW64_64KEY, 0 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", KEY_WOW64_32KEY, 64 ); + + RegDeleteKeyA( key32, "" ); + RegCloseKey( key32 ); + + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wine", 0, 0 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wine", KEY_WOW64_64KEY, 0 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wine", KEY_WOW64_32KEY, 0 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", 0, 0 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", KEY_WOW64_64KEY, 0 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", KEY_WOW64_32KEY, 0 ); + + RegDeleteKeyA( key64, "" ); + RegCloseKey( key64 ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes", 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &root64 ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &root32 ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegCreateKeyExA( root64, "Wine", 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &key64, NULL); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err ); + + err = RegCreateKeyExA( key64, "Wine", 0, NULL, 0, + KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key, NULL); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err ); + RegDeleteKeyA( key, "" ); + RegCloseKey( key ); + + err = RegOpenKeyExA( root32, "Wine", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + RegCloseKey( key ); + + err = RegOpenKeyExA( root32, "Wine", 0, KEY_ALL_ACCESS, &key ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + RegCloseKey( key ); + + err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &key32, NULL); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err ); + + dw = 32; + err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); + ok( err == ERROR_SUCCESS, "RegSetValueExA failed: 0x%08lx\n", err ); + + dw = 64; + err = RegSetValueExA( key64, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); + ok( err == ERROR_SUCCESS, "RegSetValueExA failed: 0x%08lx\n", err ); + + check_key_value( root64, "Wine", 0, 64 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, 64 ); + check_key_value( root32, "Wine", 0, 64 ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, 64 ); + + RegDeleteKeyA( key32, "" ); + RegCloseKey( key32 ); + + check_key_value( root64, "Wine", 0, 0 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, 0 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, 0 ); + check_key_value( root32, "Wine", 0, 0 ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, 0 ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, 0 );
- /* verify subkey is not present in native mode */ - err = RegOpenKeyExA(native, "AWineTest", 0, KEY_ALL_ACCESS, &key); - ok(err == ERROR_FILE_NOT_FOUND, "got %li\n", err); + RegDeleteKeyA( key64, "" ); + RegCloseKey( key64 );
- err = pRegDeleteKeyExA(op_key, "AWineTest", opposite, 0); - ok(err == ERROR_SUCCESS, "got %li\n", err); + err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &key32, NULL); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err );
- RegCloseKey(op_key); - RegCloseKey(native); + dw = 32; + err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); + ok( err == ERROR_SUCCESS, "RegSetValueExA failed: 0x%08lx\n", err ); + + check_key_value( root64, "Wine", 0, 32 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, 32 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32 ); + check_key_value( root32, "Wine", 0, 32 ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32 ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32 ); + + RegDeleteKeyA( key32, "" ); + RegCloseKey( key32 ); + + RegCloseKey( root64 ); + RegCloseKey( root32 ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes", + 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &root64 ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes", + 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &root32 ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes", + 0, KEY_ALL_ACCESS, &root ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( root64, "Interface", + 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &key64 ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( root32, "Interface", + 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key32 ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( root, "Interface", + 0, KEY_ALL_ACCESS, &key ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + RegCloseKey( root64 ); + RegCloseKey( root32 ); + RegCloseKey( root ); + + root64 = key64; + root32 = key32; + root = key; + + err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0, + KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key32, NULL); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( root, "Wine", 0, KEY_ALL_ACCESS, &key ); + ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + "RegOpenKeyExA failed: 0x%08lx\n", err ); + if (!err) RegCloseKey( key ); + + RegDeleteKeyA( key32, "" ); + RegCloseKey( key32 ); + + err = RegCreateKeyExA( root64, "Wine", 0, NULL, 0, + KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key64, NULL); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( root, "Wine", 0, KEY_ALL_ACCESS, &key ); + ok( err == (ptr_size == 32 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + "RegOpenKeyExA failed: 0x%08lx\n", err ); + if (!err) RegCloseKey( key ); + + RegDeleteKeyA( key64, "" ); + RegCloseKey( key64 ); + + RegDeleteKeyA( root, "" ); + RegCloseKey( root ); + + err = RegCreateKeyExA( root64, "Wine", 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &key64, NULL); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( root32, "Wine", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key ); + ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( root32, "Wine", 0, KEY_ALL_ACCESS, &key ); + ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &key32, NULL); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err ); + + dw = 32; + err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); + ok( err == ERROR_SUCCESS, "RegSetValueExA failed: 0x%08lx\n", err ); + + dw = 64; + err = RegSetValueExA( key64, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); + ok( err == ERROR_SUCCESS, "RegSetValueExA failed: 0x%08lx\n", err ); + + check_key_value( root64, "Wine", 0, 64 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32 ); + check_key_value( root32, "Wine", 0, 32 ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32 ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32 ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Interface", + 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &key ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + check_key_value( key, "Wine", 0, 64 ); + check_key_value( key, "Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( key, "Wine", KEY_WOW64_32KEY, 32 ); + RegCloseKey( key ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Interface", + 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + check_key_value( key, "Wine", 0, 32 ); + check_key_value( key, "Wine", KEY_WOW64_64KEY, 32 ); + check_key_value( key, "Wine", KEY_WOW64_32KEY, 32 ); + RegCloseKey( key ); + + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Interface\Wine", 0, ptr_size ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Interface\Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Interface\Wine", KEY_WOW64_32KEY, 32 ); + + RegDeleteKeyA( key32, "" ); + RegCloseKey( key32 ); + + check_key_value( root64, "Wine", 0, 64 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, 0 ); + check_key_value( root32, "Wine", 0, 0 ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, 0 ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, 0 ); + + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Interface\Wine", 0, ptr_size == 64 ? 64 : 0 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Interface\Wine", KEY_WOW64_64KEY, 64 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\Classes\Interface\Wine", KEY_WOW64_32KEY, 0 ); + + RegDeleteKeyA( key64, "" ); + RegCloseKey( key64 ); + + err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &key32, NULL); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err ); + + dw = 32; + err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); + ok( err == ERROR_SUCCESS, "RegSetValueExA failed: 0x%08lx\n", err ); + + check_key_value( root64, "Wine", 0, 0 ); + check_key_value( root64, "Wine", KEY_WOW64_64KEY, 0 ); + check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32 ); + check_key_value( root32, "Wine", 0, 32 ); + check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32 ); + check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32 ); + + RegDeleteKeyA( key32, "" ); + RegCloseKey( key32 ); + + RegCloseKey( root64 ); + RegCloseKey( root32 ); + + err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", + 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key32, NULL); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: 0x%08lx\n", err ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", + 0, KEY_ALL_ACCESS, &key ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + RegCloseKey( key ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", + 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key ); + todo_wine_if(ptr_size == 64) ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + "RegOpenKeyExA failed: 0x%08lx\n", err ); + if (!err) RegCloseKey( key ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node\Wine", + 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &key ); + ok( err == (ptr_size == 32 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + "RegOpenKeyExA failed: 0x%08lx\n", err ); + if (!err) RegCloseKey( key ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wine", + 0, KEY_ALL_ACCESS, &key ); + ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + "RegOpenKeyExA failed: 0x%08lx\n", err ); + if (!err) RegCloseKey( key ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wine", + 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key ); + todo_wine_if(ptr_size == 64) ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + "RegOpenKeyExA failed: 0x%08lx\n", err ); + if (!err) RegCloseKey( key ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wine", + 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &key ); + ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + "RegOpenKeyExA failed: 0x%08lx\n", err ); + if (!err) RegCloseKey( key ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes\Wow6432Node", + 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &root32 ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegQueryInfoKeyA(root32, NULL, NULL, NULL, &subkeys, + NULL, NULL, NULL, NULL, NULL, NULL, NULL ); + ok( err == ERROR_SUCCESS, "RegQueryInfoKeyA failed: 0x%08lx\n", err ); + ok( subkeys > 0, "wrong number of subkeys: %lu\n", subkeys ); + subkeys32 = subkeys; + RegCloseKey( root32 ); + + err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\Classes", + 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &root64 ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: 0x%08lx\n", err ); + + err = RegQueryInfoKeyA(root64, NULL, NULL, NULL, &subkeys, + NULL, NULL, NULL, NULL, NULL, NULL, NULL ); + ok( err == ERROR_SUCCESS, "RegQueryInfoKeyA failed: 0x%08lx\n", err ); + ok( subkeys > subkeys32, "wrong number of subkeys: %lu\n", subkeys ); + subkeys64 = subkeys; + RegCloseKey( root64 ); + + check_enum_value( "Software\Classes", + KEY_WOW64_32KEY | KEY_ALL_ACCESS, subkeys64, ptr_size == 32 ); + check_enum_value( "Software\Classes", + KEY_WOW64_64KEY | KEY_ALL_ACCESS, subkeys64, ptr_size == 32 ); + check_enum_value( "Software\Classes", + KEY_ALL_ACCESS, subkeys64, ptr_size == 32 ); + check_enum_value( "Software\Classes\Wow6432Node", + KEY_WOW64_32KEY | KEY_ALL_ACCESS, subkeys32, ptr_size == 64 ); + check_enum_value( "Software\Classes\Wow6432Node", + KEY_WOW64_64KEY | KEY_ALL_ACCESS, subkeys32, ptr_size == 64 ); + check_enum_value( "Software\Classes\Wow6432Node", + KEY_ALL_ACCESS, subkeys32, ptr_size == 64 ); + check_enum_value( "Software\Wow6432Node\Classes", + KEY_WOW64_32KEY | KEY_ALL_ACCESS, subkeys64, ptr_size == 32 ); + check_enum_value( "Software\Wow6432Node\Classes", + KEY_WOW64_64KEY | KEY_ALL_ACCESS, subkeys32, ptr_size == 64 ); + check_enum_value( "Software\Wow6432Node\Classes", + KEY_ALL_ACCESS, ptr_size == 32 ? subkeys64 : subkeys32, TRUE ); + + RegDeleteKeyA( key32, "" ); + RegCloseKey( key32 ); }
static void test_classesroot(void)
Patch 11/12 is titled "Copy Software\Classes tests from ntdll.", but it looks like they were copied from kernel32, right?
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=125135
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) ===
0798:err:winediag:d3d_device_create The application wants to create a Direct3D device, but the current DirectDrawRenderer does not support this. 0798:err:winediag:d3d_device_create The application wants to create a Direct3D device, but the current DirectDrawRenderer does not support this. 0798:err:winediag:d3d_device_create The application wants to create a Direct3D device, but the current DirectDrawRenderer does not support this.
=== debian11 (build log) ===
Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24720. Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24720. Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24720.
I copy-pasted the tests to advapi32 and had to add two instances of todo_wine_if, so maybe they did make a small mistake when reimplementing everything in kernelbase? I guess I'll try to do that as well then...
On Wed Oct 19 15:39:51 2022 +0000, **** wrote:
Zebediah Figura replied on the mailing list:
Patch 11/12 is titled "Copy Software\Classes tests from ntdll.", but it looks like they were copied from kernel32, right?
No, I copied all the tests from ntdll and replaced the Nt* calls with Reg* calls. Just to show that the behavior is as expected when I pass OBJ_KEY_WOW64 to the server.
Note that using this internal flag is not prohibited in the server, so applications (accidentally) setting this would already be broken before my patches.