[PATCH v2 0/5] MR2483: kernelbase: Add full support for shared Software\Classes keys.
I initially wanted to do the refactoring in a separate merge request, but since my merge request yesterday broke the tests, I decided to add the implementation into this commit as well. -- v2: kernelbase: Recursively obtain the Wow6432Node parent. kernelbase: Add support for shared registry keys. https://gitlab.winehq.org/wine/wine/-/merge_requests/2483
From: Sven Baars <sbaars(a)codeweavers.com> These can never exist in a newly created key. --- dlls/kernelbase/registry.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 63855eeb555..9fd1abceabb 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -303,19 +303,6 @@ static NTSTATUS create_key( HKEY *retkey, HKEY root, UNICODE_STRING name, ULONG while (i < len && buffer[i] == '\\') i++; buffer += i; len -= i; - - if (force_wow32) - { - name.Buffer = buffer; - name.Length = len * sizeof(WCHAR); - if (is_wow6432node( &name )) force_wow32 = FALSE; - else if ((subkey = open_wow6432node( attr.RootDirectory ))) - { - NtClose( attr.RootDirectory ); - attr.RootDirectory = subkey; - force_wow32 = FALSE; - } - } } } if (status == STATUS_PREDEFINED_HANDLE) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/2483
From: Sven Baars <sbaars(a)codeweavers.com> --- dlls/kernelbase/registry.c | 121 ++++++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 50 deletions(-) diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 9fd1abceabb..f9e647a026a 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -227,25 +227,76 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING *name, DWORD o return status; } -/* wrapper for NtCreateKey that creates the key recursively if necessary */ -static NTSTATUS create_key( HKEY *retkey, HKEY root, UNICODE_STRING name, ULONG options, ACCESS_MASK access, - const UNICODE_STRING *class, PULONG dispos ) +static NTSTATUS create_subkey( HKEY *subkey, HKEY root, UNICODE_STRING *name, DWORD options, ACCESS_MASK access, + const UNICODE_STRING *class, PULONG dispos ) { - BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY); - NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND; + DWORD i = 0, len = name->Length / sizeof(WCHAR); + WCHAR *buffer = name->Buffer; OBJECT_ATTRIBUTES attr; - HKEY subkey; + UNICODE_STRING str; + NTSTATUS status; attr.Length = sizeof(attr); attr.RootDirectory = root; - attr.ObjectName = &name; + attr.ObjectName = &str; attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; - if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK; - if (!force_wow32) + if (i < len && buffer[i] == '\\') return STATUS_OBJECT_PATH_INVALID; + while (i < len && buffer[i] != '\\') i++; + + str.Buffer = name->Buffer; + str.Length = i * sizeof(WCHAR); + + if (i == len) + { + if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK; + } + else + { + options &= ~REG_OPTION_CREATE_LINK; + } + + status = NtCreateKey( (HANDLE *)subkey, access, &attr, 0, class, options, dispos ); + if (status == STATUS_PREDEFINED_HANDLE) + { + *subkey = get_perflib_key( *subkey ); + status = STATUS_SUCCESS; + } + + if (!status) + { + while (i < len && buffer[i] == '\\') i++; + + name->Buffer += i; + name->Length -= i * sizeof(WCHAR); + } + + return status; +} + +/* wrapper for NtCreateKey that creates the key recursively if necessary */ +static NTSTATUS create_key( HKEY *retkey, HKEY root, UNICODE_STRING name, ULONG options, ACCESS_MASK access, + const UNICODE_STRING *class, PULONG dispos ) +{ + NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND; + HKEY subkey, subkey_root = root; + + *retkey = NULL; + + if (!(is_win64 && (access & KEY_WOW64_32KEY))) { + OBJECT_ATTRIBUTES attr; + + attr.Length = sizeof(attr); + attr.RootDirectory = root; + attr.ObjectName = &name; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK; + status = NtCreateKey( (HANDLE *)retkey, access, &attr, 0, class, options, dispos ); if (status == STATUS_PREDEFINED_HANDLE) { @@ -257,60 +308,30 @@ static NTSTATUS create_key( HKEY *retkey, HKEY root, UNICODE_STRING name, ULONG return status; } - status = open_key( &subkey, root, &name, options & REG_OPTION_OPEN_LINK, access, TRUE ); + status = open_key( &subkey_root, root, &name, options & REG_OPTION_OPEN_LINK, access, TRUE ); if (!status && (options & REG_OPTION_CREATE_LINK)) { - NtClose( subkey ); + NtClose( subkey_root ); status = STATUS_OBJECT_NAME_COLLISION; } if (!status) if (dispos) *dispos = REG_OPENED_EXISTING_KEY; - attr.RootDirectory = subkey; if (status == STATUS_OBJECT_NAME_NOT_FOUND) { - DWORD attrs, i, len = name.Length / sizeof(WCHAR); - WCHAR *buffer = name.Buffer; - - attrs = attr.Attributes; - - while (len) + status = STATUS_SUCCESS; + while (!status && name.Length) { - i = 0; - - /* don't try to create registry root */ - if (!attr.RootDirectory && len > 10 && !wcsnicmp( buffer, L"\\Registry\\", 10 )) i += 10; - while (i < len && buffer[i] != '\\') i++; - - name.Buffer = buffer; - name.Length = i * sizeof(WCHAR); - - if (i == len) - { - attr.Attributes = attrs; - status = NtCreateKey( (HANDLE *)&subkey, access, &attr, 0, class, options, dispos ); - } - else - { - attr.Attributes = attrs & ~OBJ_OPENLINK; - status = NtCreateKey( (HANDLE *)&subkey, access, &attr, 0, class, - options & ~REG_OPTION_CREATE_LINK, dispos ); - } - if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); - if (!NT_SUCCESS(status)) return status; - attr.RootDirectory = subkey; - while (i < len && buffer[i] == '\\') i++; - buffer += i; - len -= i; + status = create_subkey( &subkey, subkey_root, &name, options, access, class, dispos ); + if (subkey_root && subkey_root != root) NtClose( subkey_root ); + subkey_root = subkey; } } - if (status == STATUS_PREDEFINED_HANDLE) - { - attr.RootDirectory = get_perflib_key( attr.RootDirectory ); - status = STATUS_SUCCESS; - } - *retkey = attr.RootDirectory; + + if (!status) + *retkey = subkey_root; + return status; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/2483
From: Sven Baars <sbaars(a)codeweavers.com> --- dlls/kernelbase/registry.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index f9e647a026a..a69a87ebb3d 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -227,44 +227,28 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING *name, DWORD o return status; } +static NTSTATUS create_key( HKEY *retkey, HKEY root, UNICODE_STRING name, ULONG options, ACCESS_MASK access, + const UNICODE_STRING *class, PULONG dispos ); + static NTSTATUS create_subkey( HKEY *subkey, HKEY root, UNICODE_STRING *name, DWORD options, ACCESS_MASK access, const UNICODE_STRING *class, PULONG dispos ) { + ACCESS_MASK access_64 = access & ~KEY_WOW64_32KEY; DWORD i = 0, len = name->Length / sizeof(WCHAR); WCHAR *buffer = name->Buffer; - OBJECT_ATTRIBUTES attr; UNICODE_STRING str; NTSTATUS status; - attr.Length = sizeof(attr); - attr.RootDirectory = root; - attr.ObjectName = &str; - attr.Attributes = 0; - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; - if (i < len && buffer[i] == '\\') return STATUS_OBJECT_PATH_INVALID; while (i < len && buffer[i] != '\\') i++; str.Buffer = name->Buffer; str.Length = i * sizeof(WCHAR); - if (i == len) - { - if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK; - } - else - { + if (i < len) options &= ~REG_OPTION_CREATE_LINK; - } - - status = NtCreateKey( (HANDLE *)subkey, access, &attr, 0, class, options, dispos ); - if (status == STATUS_PREDEFINED_HANDLE) - { - *subkey = get_perflib_key( *subkey ); - status = STATUS_SUCCESS; - } + status = create_key( subkey, root, str, options, access_64, class, dispos ); if (!status) { while (i < len && buffer[i] == '\\') i++; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/2483
From: Sven Baars <sbaars(a)codeweavers.com> --- dlls/advapi32/tests/registry.c | 132 ++++++++++++++++----------------- dlls/kernelbase/registry.c | 108 +++++++++++++++++++++++++-- 2 files changed, 168 insertions(+), 72 deletions(-) diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 80bf39bb178..e7e9ef0c2ab 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -2589,8 +2589,7 @@ static void _todo_check_key_value( int line, HANDLE root, const char *name, DWOR } #define todo_check_key_value(root,name,flags,expect, todo) _todo_check_key_value( __LINE__, root, name, flags, expect, todo ) -static void _check_enum_value( int line, const char *name, DWORD flags, DWORD subkeys_in, BOOL found_in, - BOOL todo_subkeys, BOOL todo_found) +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; @@ -2603,7 +2602,7 @@ static void _check_enum_value( int line, const char *name, DWORD flags, DWORD su err = RegQueryInfoKeyA( key, NULL, NULL, NULL, &subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); ok_( __FILE__, line )( err == ERROR_SUCCESS, "RegQueryInfoKeyA failed: %lu\n", err ); - todo_wine_if(todo_subkeys) ok_( __FILE__, line )( subkeys == subkeys_in, "wrong number of subkeys: %lu\n", subkeys ); + ok_( __FILE__, line )( subkeys == subkeys_in, "wrong number of subkeys: %lu\n", subkeys ); found = FALSE; for (i = 0; i < subkeys; i++) @@ -2614,11 +2613,10 @@ static void _check_enum_value( int line, const char *name, DWORD flags, DWORD su if (!strcmp(buffer, "Wine")) found = TRUE; } - todo_wine_if(todo_found) ok_( __FILE__, line )( found == found_in, "found equals %d\n", found ); + ok_( __FILE__, line )( found == found_in, "found equals %d\n", found ); RegCloseKey( key ); } -#define check_enum_value(name, flags, subkeys, found, todo_subkeys, todo_found) _check_enum_value( \ - __LINE__, name, flags, subkeys, found, todo_subkeys, todo_found ) +#define check_enum_value(name, flags, subkeys, found) _check_enum_value( __LINE__, name, flags, subkeys, found ) static void test_redirection(void) { @@ -2834,7 +2832,7 @@ static void test_redirection(void) 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 == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); RegCloseKey( key ); err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine", @@ -2857,16 +2855,16 @@ static void test_redirection(void) check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", 0, 64 ); check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", KEY_WOW64_64KEY, 64 ); - todo_check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", KEY_WOW64_32KEY, 64, ptr_size == 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 ); - todo_check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine", KEY_WOW64_32KEY, 64, ptr_size == 64 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine", KEY_WOW64_32KEY, 64 ); RegDeleteKeyA( key32, "" ); RegCloseKey( key32 ); - todo_check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", 0, 0, ptr_size == 64 ); - todo_check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", KEY_WOW64_64KEY, 0, ptr_size == 64 ); + 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 ); @@ -2892,11 +2890,11 @@ static void test_redirection(void) RegCloseKey( key ); err = RegOpenKeyExA( root32, "Wine", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key ); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); RegCloseKey( key ); err = RegOpenKeyExA( root32, "Wine", 0, KEY_ALL_ACCESS, &key ); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); RegCloseKey( key ); err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0, @@ -2914,16 +2912,16 @@ static void test_redirection(void) 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 ); - todo_check_key_value( root32, "Wine", 0, 64, ptr_size == 64 ); - todo_check_key_value( root32, "Wine", KEY_WOW64_64KEY, 64, ptr_size == 64 ); - todo_check_key_value( root32, "Wine", KEY_WOW64_32KEY, 64, ptr_size == 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 ); - todo_check_key_value( root64, "Wine", 0, 0, ptr_size == 64 ); - todo_check_key_value( root64, "Wine", KEY_WOW64_64KEY, 0, ptr_size == 64 ); - todo_check_key_value( root64, "Wine", KEY_WOW64_32KEY, 0, ptr_size == 64 ); + 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 ); @@ -2939,9 +2937,9 @@ static void test_redirection(void) err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err ); - todo_check_key_value( root64, "Wine", 0, 32, ptr_size == 64 ); - todo_check_key_value( root64, "Wine", KEY_WOW64_64KEY, 32, ptr_size == 64 ); - todo_check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32, ptr_size == 64 ); + 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 ); @@ -2958,7 +2956,7 @@ static void test_redirection(void) err = RegOpenKeyExA( HKEY_CLASSES_ROOT, "Interface", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &root32 ); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); err = RegOpenKeyExA( HKEY_CLASSES_ROOT, "Interface", 0, KEY_ALL_ACCESS, &root ); @@ -2966,10 +2964,10 @@ static void test_redirection(void) err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key32, NULL); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); err = RegOpenKeyExA( root, "Wine", 0, KEY_ALL_ACCESS, &key ); - ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + todo_wine_if(ptr_size == 64) ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), "RegOpenKeyExA failed: %lu\n", err ); if (!err) RegCloseKey( key ); @@ -2978,10 +2976,10 @@ static void test_redirection(void) err = RegCreateKeyExA( root64, "Wine", 0, NULL, 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key64, NULL); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); err = RegOpenKeyExA( root, "Wine", 0, KEY_ALL_ACCESS, &key ); - todo_wine_if(ptr_size == 64) ok( err == (ptr_size == 32 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + ok( err == (ptr_size == 32 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), "RegOpenKeyExA failed: %lu\n", err ); if (!err) RegCloseKey( key ); @@ -3014,7 +3012,7 @@ static void test_redirection(void) err = RegOpenKeyExA( root32, "Interface", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key32 ); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); err = RegOpenKeyExA( root, "Interface", 0, KEY_ALL_ACCESS, &key ); @@ -3030,10 +3028,10 @@ static void test_redirection(void) err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key32, NULL); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); err = RegOpenKeyExA( root, "Wine", 0, KEY_ALL_ACCESS, &key ); - ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + todo_wine_if(ptr_size == 64) ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), "RegOpenKeyExA failed: %lu\n", err ); if (!err) RegCloseKey( key ); @@ -3067,11 +3065,11 @@ static void test_redirection(void) err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key32, NULL); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); dw = 32; err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err ); dw = 64; err = RegSetValueExA( key64, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); @@ -3080,9 +3078,9 @@ static void test_redirection(void) check_key_value( root64, "Wine", 0, 64 ); check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64 ); todo_check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32, ptr_size == 64 ); - todo_wine_if(ptr_size == 64) check_key_value( root32, "Wine", 0, 32 ); - todo_wine_if(ptr_size == 64) check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32 ); - todo_wine_if(ptr_size == 64) check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32 ); + todo_check_key_value( root32, "Wine", 0, 32, ptr_size == 64 ); + todo_check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32, ptr_size == 64 ); + todo_check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32, ptr_size == 64 ); err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface", 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &key ); @@ -3094,10 +3092,10 @@ static void test_redirection(void) err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key ); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); - todo_wine_if(ptr_size == 64) check_key_value( key, "Wine", 0, 32 ); - todo_wine_if(ptr_size == 64) check_key_value( key, "Wine", KEY_WOW64_64KEY, 32 ); - todo_wine_if(ptr_size == 64) check_key_value( key, "Wine", KEY_WOW64_32KEY, 32 ); + ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err ); + todo_check_key_value( key, "Wine", 0, 32, ptr_size == 64 ); + todo_check_key_value( key, "Wine", KEY_WOW64_64KEY, 32, ptr_size == 64 ); + todo_check_key_value( key, "Wine", KEY_WOW64_32KEY, 32, ptr_size == 64 ); RegCloseKey( key ); check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", 0, ptr_size ); @@ -3107,15 +3105,15 @@ static void test_redirection(void) RegDeleteKeyA( key32, "" ); RegCloseKey( key32 ); - check_key_value( root64, "Wine", 0, 64 ); - check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64 ); - todo_check_key_value( root64, "Wine", KEY_WOW64_32KEY, 0, ptr_size == 64 ); - todo_wine_if(ptr_size == 64) check_key_value( root32, "Wine", 0, 0 ); - todo_wine_if(ptr_size == 64) check_key_value( root32, "Wine", KEY_WOW64_64KEY, 0 ); - todo_wine_if(ptr_size == 64) check_key_value( root32, "Wine", KEY_WOW64_32KEY, 0 ); + todo_check_key_value( root64, "Wine", 0, 64, ptr_size == 64 ); + todo_check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64, ptr_size == 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 ); + todo_wine_if(ptr_size == 64) check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", 0, ptr_size == 64 ? 64 : 0 ); + todo_wine_if(ptr_size == 64) 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, "" ); @@ -3123,18 +3121,18 @@ static void test_redirection(void) err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key32, NULL); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); dw = 32; err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); - todo_wine_if(ptr_size == 64) ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err ); + ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err ); - check_key_value( root64, "Wine", 0, 0 ); - check_key_value( root64, "Wine", KEY_WOW64_64KEY, 0 ); - todo_wine_if(ptr_size == 64) check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32 ); - todo_wine_if(ptr_size == 64) check_key_value( root32, "Wine", 0, 32 ); - todo_wine_if(ptr_size == 64) check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32 ); - todo_wine_if(ptr_size == 64) check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32 ); + todo_check_key_value( root64, "Wine", 0, 0, ptr_size == 64 ); + todo_check_key_value( root64, "Wine", KEY_WOW64_64KEY, 0, ptr_size == 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 ); RegDeleteKeyA( key32, "" ); RegCloseKey( key32 ); @@ -3153,7 +3151,7 @@ static void test_redirection(void) err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key ); - ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + todo_wine_if(ptr_size == 64) ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), "RegOpenKeyExA failed: %lu\n", err ); if (!err) RegCloseKey( key ); @@ -3171,7 +3169,7 @@ static void test_redirection(void) err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key ); - ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + todo_wine_if(ptr_size == 64) ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), "RegOpenKeyExA failed: %lu\n", err ); if (!err) RegCloseKey( key ); @@ -3188,7 +3186,7 @@ static void test_redirection(void) err = RegQueryInfoKeyA(root32, NULL, NULL, NULL, &subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); ok( err == ERROR_SUCCESS, "RegQueryInfoKeyA failed: %lu\n", err ); - todo_wine_if(ptr_size == 64) ok( subkeys > 0, "wrong number of subkeys: %lu\n", subkeys ); + ok( subkeys > 0, "wrong number of subkeys: %lu\n", subkeys ); subkeys32 = subkeys; RegCloseKey( root32 ); @@ -3204,23 +3202,23 @@ static void test_redirection(void) RegCloseKey( root64 ); check_enum_value( "Software\\Classes", - KEY_WOW64_32KEY | KEY_ALL_ACCESS, subkeys64, ptr_size == 32, ptr_size == 64, FALSE ); + 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, FALSE, FALSE ); + KEY_WOW64_64KEY | KEY_ALL_ACCESS, subkeys64, ptr_size == 32 ); check_enum_value( "Software\\Classes", - KEY_ALL_ACCESS, subkeys64, ptr_size == 32, FALSE, FALSE ); + KEY_ALL_ACCESS, subkeys64, ptr_size == 32 ); check_enum_value( "Software\\Classes\\Wow6432Node", - KEY_WOW64_32KEY | KEY_ALL_ACCESS, subkeys32, ptr_size == 64, FALSE, ptr_size == 64 ); + 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, ptr_size == 64, FALSE ); + KEY_WOW64_64KEY | KEY_ALL_ACCESS, subkeys32, ptr_size == 64 ); check_enum_value( "Software\\Classes\\Wow6432Node", - KEY_ALL_ACCESS, subkeys32, ptr_size == 64, ptr_size == 64, FALSE ); + KEY_ALL_ACCESS, subkeys32, ptr_size == 64 ); check_enum_value( "Software\\Wow6432Node\\Classes", - KEY_WOW64_32KEY | KEY_ALL_ACCESS, subkeys64, ptr_size == 32, ptr_size == 64, FALSE ); + 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, ptr_size == 64, FALSE ); + 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, ptr_size == 64, FALSE ); + KEY_ALL_ACCESS, ptr_size == 32 ? subkeys64 : subkeys32, TRUE ); RegDeleteKeyA( key32, "" ); RegCloseKey( key32 ); diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index a69a87ebb3d..8d27e2dfa36 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -104,11 +104,56 @@ static BOOL is_wow6432node( const UNICODE_STRING *name ) return (len >= 11 && !wcsnicmp( name->Buffer, L"Wow6432Node\\", min( len, 12 ) )); } -/* open the Wow6432Node subkey of the specified key */ +static BOOL is_classes_root( const UNICODE_STRING *name ) +{ + return (name->Length >= wcslen(root_key_names[0]) * sizeof(WCHAR) && !wcsnicmp( name->Buffer, root_key_names[0], wcslen(root_key_names[0]) )); +} + +static BOOL is_classes_wow6432node( HKEY key ) +{ + char buffer[256], *buf_ptr = buffer; + KEY_NAME_INFORMATION *info = (KEY_NAME_INFORMATION *)buffer; + DWORD len = sizeof(buffer); + UNICODE_STRING name; + NTSTATUS status; + BOOL ret = FALSE; + + /* Obtain the name of the root key */ + status = NtQueryKey( key, KeyNameInformation, info, len, &len ); + if (status && status != STATUS_BUFFER_OVERFLOW) return FALSE; + + /* Retry with a dynamically allocated buffer */ + while (status == STATUS_BUFFER_OVERFLOW) + { + if (buf_ptr != buffer) heap_free( buf_ptr ); + if (!(buf_ptr = heap_alloc( len ))) return FALSE; + info = (KEY_NAME_INFORMATION *)buf_ptr; + status = NtQueryKey( key, KeyNameInformation, info, len, &len ); + } + + /* Check if the key ends in Wow6432Node and if the root is the Classes key*/ + if (!status && info->NameLength / sizeof(WCHAR) >= 11) + { + name.Buffer = info->Name + info->NameLength / sizeof(WCHAR) - 11; + name.Length = 11 * sizeof(WCHAR); + if (is_wow6432node( &name )) + { + name.Buffer = info->Name; + name.Length = info->NameLength; + ret = is_classes_root( &name ); + } + } + + if (buf_ptr != buffer) heap_free( buf_ptr ); + + return ret; +} + +/* Open the Wow6432Node subkey of the specified key */ static HANDLE open_wow6432node( HANDLE key ) { - OBJECT_ATTRIBUTES attr; UNICODE_STRING nameW = RTL_CONSTANT_STRING( L"Wow6432Node" ); + OBJECT_ATTRIBUTES attr; HANDLE ret; attr.Length = sizeof(attr); @@ -117,7 +162,25 @@ static HANDLE open_wow6432node( HANDLE key ) attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; - if (NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 )) ret = 0; + if (NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 )) return key; + return ret; +} + +/* Open HKCR, which should already exist because it's used when we're in its Wow6432Node child */ +static HANDLE open_classes_root( void ) +{ + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW; + HANDLE ret = 0; + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + RtlInitUnicodeString( &nameW, root_key_names[0] ); + NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 ); return ret; } @@ -162,6 +225,21 @@ static NTSTATUS open_subkey( HKEY *subkey, HKEY root, UNICODE_STRING *name, DWOR options &= ~REG_OPTION_OPEN_LINK; status = open_key( subkey, root, &str, options, access_64, FALSE ); + if (status == STATUS_OBJECT_NAME_NOT_FOUND && root && is_wow64_key) + { + /* Try to open the shared parent if we can't find the key in the Wow6432Node */ + if (!is_classes_wow6432node( root )) + return STATUS_OBJECT_NAME_NOT_FOUND; + + root = open_classes_root(); + status = open_key( subkey, root, &str, options, access_64, FALSE ); + + if (!status) + NtClose( root ); + else + *subkey = root; + } + if (!status) { while (i < len && buffer[i] == '\\') i++; @@ -172,7 +250,7 @@ static NTSTATUS open_subkey( HKEY *subkey, HKEY root, UNICODE_STRING *name, DWOR if (is_wow64_key && !is_wow6432node( name )) { HKEY wow6432node = open_wow6432node( *subkey ); - if (wow6432node) + if (wow6432node != *subkey) { NtClose( *subkey ); *subkey = wow6432node; @@ -186,8 +264,10 @@ static NTSTATUS open_subkey( HKEY *subkey, HKEY root, UNICODE_STRING *name, DWOR /* wrapper for NtOpenKeyEx to handle Wow6432 nodes */ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING *name, DWORD options, ACCESS_MASK access, BOOL create ) { + BOOL is_wow64_key = (access & KEY_WOW64_32KEY) || (is_wow64 && !(access & KEY_WOW64_64KEY)); HKEY subkey = 0, subkey_root = root; - NTSTATUS status = 0; + NTSTATUS status = STATUS_SUCCESS; + BOOL was_wow6432node = TRUE; *retkey = NULL; @@ -212,13 +292,31 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING *name, DWORD o return status; } + if (root && is_wow64 && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name )) + { + subkey_root = open_wow6432node( root ); + if (!is_classes_wow6432node( subkey_root ) && subkey_root != root) + { + NtClose( subkey_root ); + subkey_root = root; + } + } + while (!status && (name->Length || !subkey)) { + was_wow6432node = is_wow6432node( name ); status = open_subkey( &subkey, subkey_root, name, options, access ); if (subkey && subkey_root && subkey_root != root) NtClose( subkey_root ); if (subkey) subkey_root = subkey; } + /* Return the shared parent if we didn't explicitly look for the Wow6432Node */ + if (!status && !was_wow6432node && is_wow64_key && is_classes_wow6432node( subkey_root )) + { + if (subkey_root && subkey_root != root) NtClose( subkey_root ); + subkey_root = open_classes_root(); + } + if (!status || (status == STATUS_OBJECT_NAME_NOT_FOUND && create)) *retkey = subkey_root; else if (subkey_root && subkey_root != root) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/2483
From: Sven Baars <sbaars(a)codeweavers.com> --- dlls/advapi32/tests/registry.c | 60 +++++++++++++--------------------- dlls/kernelbase/registry.c | 49 ++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 38 deletions(-) diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index e7e9ef0c2ab..9e051056eed 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -2582,13 +2582,6 @@ 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 _todo_check_key_value( int line, HANDLE root, const char *name, DWORD flags, DWORD expect, BOOL todo ) -{ - DWORD dw = get_key_value( root, name, flags ); - todo_wine_if(todo) ok_(__FILE__,line)( dw == expect, "%08lx: wrong value %lu/%lu\n", flags, dw, expect ); -} -#define todo_check_key_value(root,name,flags,expect, todo) _todo_check_key_value( __LINE__, root, name, flags, expect, todo ) - static void _check_enum_value( int line, const char *name, DWORD flags, DWORD subkeys_in, BOOL found_in) { char buffer[1024]; @@ -2679,12 +2672,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 ); @@ -2696,8 +2686,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 ); @@ -2774,9 +2763,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, @@ -2784,8 +2771,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, @@ -2967,7 +2953,7 @@ static void test_redirection(void) ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); err = RegOpenKeyExA( root, "Wine", 0, KEY_ALL_ACCESS, &key ); - todo_wine_if(ptr_size == 64) ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), "RegOpenKeyExA failed: %lu\n", err ); if (!err) RegCloseKey( key ); @@ -3031,7 +3017,7 @@ static void test_redirection(void) ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); err = RegOpenKeyExA( root, "Wine", 0, KEY_ALL_ACCESS, &key ); - todo_wine_if(ptr_size == 64) ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), + ok( err == (ptr_size == 64 ? ERROR_FILE_NOT_FOUND : ERROR_SUCCESS), "RegOpenKeyExA failed: %lu\n", err ); if (!err) RegCloseKey( key ); @@ -3058,10 +3044,10 @@ static void test_redirection(void) ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err ); err = RegOpenKeyExA( root32, "Wine", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key ); - todo_wine_if(ptr_size == 64) ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKeyExA failed: %lu\n", err ); + ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKeyExA failed: %lu\n", err ); err = RegOpenKeyExA( root32, "Wine", 0, KEY_ALL_ACCESS, &key ); - todo_wine_if(ptr_size == 64) ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKeyExA failed: %lu\n", err ); + ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKeyExA failed: %lu\n", err ); err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key32, NULL); @@ -3077,43 +3063,43 @@ static void test_redirection(void) check_key_value( root64, "Wine", 0, 64 ); check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64 ); - todo_check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32, ptr_size == 64 ); - todo_check_key_value( root32, "Wine", 0, 32, ptr_size == 64 ); - todo_check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32, ptr_size == 64 ); - todo_check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32, ptr_size == 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: %lu\n", err ); check_key_value( key, "Wine", 0, 64 ); check_key_value( key, "Wine", KEY_WOW64_64KEY, 64 ); - todo_check_key_value( key, "Wine", KEY_WOW64_32KEY, 32, ptr_size == 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: %lu\n", err ); - todo_check_key_value( key, "Wine", 0, 32, ptr_size == 64 ); - todo_check_key_value( key, "Wine", KEY_WOW64_64KEY, 32, ptr_size == 64 ); - todo_check_key_value( key, "Wine", KEY_WOW64_32KEY, 32, ptr_size == 64 ); + 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 ); - todo_check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", KEY_WOW64_32KEY, 32, ptr_size == 64 ); + check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", KEY_WOW64_32KEY, 32 ); RegDeleteKeyA( key32, "" ); RegCloseKey( key32 ); - todo_check_key_value( root64, "Wine", 0, 64, ptr_size == 64 ); - todo_check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64, ptr_size == 64 ); + 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 ); - todo_wine_if(ptr_size == 64) check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", 0, ptr_size == 64 ? 64 : 0 ); - todo_wine_if(ptr_size == 64) check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", KEY_WOW64_64KEY, 64 ); + 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, "" ); @@ -3127,8 +3113,8 @@ static void test_redirection(void) err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err ); - todo_check_key_value( root64, "Wine", 0, 0, ptr_size == 64 ); - todo_check_key_value( root64, "Wine", KEY_WOW64_64KEY, 0, ptr_size == 64 ); + 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 ); diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 8d27e2dfa36..00a16349319 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -261,6 +261,51 @@ static NTSTATUS open_subkey( HKEY *subkey, HKEY root, UNICODE_STRING *name, DWOR return status; } +static NTSTATUS open_wow6432node_parent( HKEY *retkey, HKEY root, DWORD options, ACCESS_MASK access ) +{ + char buffer[256], *buf_ptr = buffer; + KEY_NAME_INFORMATION *info = (KEY_NAME_INFORMATION *)buffer; + DWORD len = sizeof(buffer); + UNICODE_STRING name; + NTSTATUS status; + + /* Obtain the name of the root key */ + status = NtQueryKey( root, KeyNameInformation, info, len, &len ); + if (status && status != STATUS_BUFFER_OVERFLOW) return status; + + /* Retry with a dynamically allocated buffer */ + while (status == STATUS_BUFFER_OVERFLOW) + { + if (buf_ptr != buffer) heap_free( buf_ptr ); + if (!(buf_ptr = heap_alloc( len ))) + return STATUS_NO_MEMORY; + info = (KEY_NAME_INFORMATION *)buf_ptr; + status = NtQueryKey( root, KeyNameInformation, info, len, &len ); + } + + if (status) + { + if (buf_ptr != buffer) heap_free( buf_ptr ); + return status; + } + + name.Buffer = info->Name; + name.Length = info->NameLength; + root = 0; + + /* Obtain the parent Wow6432Node if it exists */ + while (!status && name.Length) + { + status = open_subkey( retkey, root, &name, options & ~REG_OPTION_OPEN_LINK, access ); + if (root) NtClose( root ); + root = *retkey; + } + + if (buf_ptr != buffer) heap_free( buf_ptr ); + + return status; +} + /* wrapper for NtOpenKeyEx to handle Wow6432 nodes */ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING *name, DWORD options, ACCESS_MASK access, BOOL create ) { @@ -292,7 +337,9 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING *name, DWORD o return status; } - if (root && is_wow64 && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name )) + if (root && (access & KEY_WOW64_32KEY) && !is_wow6432node( name )) + status = open_wow6432node_parent( &subkey_root, root, options, access ); + else if (root && is_wow64 && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name )) { subkey_root = open_wow6432node( root ); if (!is_classes_wow6432node( subkey_root ) && subkey_root != root) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/2483
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 full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=130972 Your paranoid android. === build (build log) === error: patch failed: dlls/wined3d/adapter_vk.c:98 error: patch failed: dlls/wined3d/directx.c:2811 error: patch failed: dlls/wined3d/state.c:4589 error: patch failed: dlls/kernelbase/registry.c:227 Task: Patch failed to apply === debian11 (build log) === error: patch failed: dlls/wined3d/adapter_vk.c:98 error: patch failed: dlls/wined3d/directx.c:2811 error: patch failed: dlls/wined3d/state.c:4589 error: patch failed: dlls/kernelbase/registry.c:227 Task: Patch failed to apply === debian11b (build log) === error: patch failed: dlls/wined3d/adapter_vk.c:98 error: patch failed: dlls/wined3d/directx.c:2811 error: patch failed: dlls/wined3d/state.c:4589 error: patch failed: dlls/kernelbase/registry.c:227 Task: Patch failed to apply
participants (3)
-
Marvin -
Sven Baars -
Sven Baars (@sbaars)