This is in preparation of implementing all logic from the server in kernelbase, which is needed because Nt*Key ignores KEY_WOW64_32KEY. Unfortunately this requires a lot of server calls.
The full branch can be found here
https://gitlab.winehq.org/sbaars/wine/-/tree/shared-classes-new
The old approach that doesn't duplicate code to kernelbase can be found here
https://gitlab.winehq.org/sbaars/wine/-/tree/shared-classes-old
I ran make_requests by the way, not sure if we should still leave that out with the gitlab workflow.
-- v15: kernelbase: Restructure the create_key() loop. kernelbase: Add a fast path to create_key(). kernelbase: Move create_key() below open_key(). kernelbase: Factor opening a subkey out of open_key(). kernelbase: Always try to open the Wow6432Node in open_key(). kernelbase: Restructure the open_key() loop. kernelbase: Pass the key name to create_key(). kernelbase: Pass the root key to create_key(). kernelbase: Pass the key name to open_key(). kernelbase: Pass the root key to open_key().
From: Sven Baars sbaars@codeweavers.com
--- dlls/kernelbase/registry.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 0137cbe6cad..36c48d565d5 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -214,11 +214,11 @@ static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES }
/* wrapper for NtOpenKeyEx to handle Wow6432 nodes */ -static NTSTATUS open_key( HKEY *retkey, DWORD options, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr ) +static NTSTATUS open_key( HKEY *retkey, HKEY root, DWORD options, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr ) { NTSTATUS status; BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY); - HANDLE subkey, root = attr->RootDirectory; + HANDLE subkey; WCHAR *buffer = attr->ObjectName->Buffer; DWORD pos = 0, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR); UNICODE_STRING str; @@ -537,7 +537,7 @@ 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 ) ); + return RtlNtStatusToDosError( open_key( retkey, hkey, options, access, &attr ) ); }
@@ -595,7 +595,7 @@ 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 ); + status = open_key( retkey, hkey, options, access, &attr ); } return RtlNtStatusToDosError( status ); }
From: Sven Baars sbaars@codeweavers.com
--- dlls/kernelbase/registry.c | 73 +++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 41 deletions(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 36c48d565d5..714f6a20227 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -214,21 +214,28 @@ static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES }
/* wrapper for NtOpenKeyEx to handle Wow6432 nodes */ -static NTSTATUS open_key( HKEY *retkey, HKEY root, DWORD options, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr ) +static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING name, DWORD options, ACCESS_MASK access ) { + OBJECT_ATTRIBUTES attr; NTSTATUS status; BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY); HANDLE subkey; - WCHAR *buffer = attr->ObjectName->Buffer; - DWORD pos = 0, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR); - UNICODE_STRING str; + WCHAR *buffer = name.Buffer; + DWORD pos = 0, i = 0, len = name.Length / sizeof(WCHAR);
*retkey = NULL;
+ attr.Length = sizeof(attr); + attr.RootDirectory = root; + attr.ObjectName = &name; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + if (!force_wow32) { - if (options & REG_OPTION_OPEN_LINK) attr->Attributes |= OBJ_OPENLINK; - status = NtOpenKeyEx( (HANDLE *)retkey, access, attr, options ); + 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 ); @@ -239,51 +246,50 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, DWORD options, ACCESS_MASK ac
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); + name.Buffer = buffer + pos; + name.Length = (i - pos) * sizeof(WCHAR); if (force_wow32 && pos) { - if (is_wow6432node( &str )) force_wow32 = FALSE; - else if ((subkey = open_wow6432node( attr->RootDirectory ))) + if (is_wow6432node( &name )) force_wow32 = FALSE; + else if ((subkey = open_wow6432node( attr.RootDirectory ))) { - if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); - attr->RootDirectory = subkey; + 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 ); + 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 (!(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 (attr.RootDirectory != root) NtClose( attr.RootDirectory ); if (status) return status; - attr->RootDirectory = subkey; + 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 (force_wow32 && (subkey = open_wow6432node( attr.RootDirectory ))) { - if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); - attr->RootDirectory = subkey; + if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); + attr.RootDirectory = subkey; } if (status == STATUS_PREDEFINED_HANDLE) { - attr->RootDirectory = get_perflib_key( attr->RootDirectory ); + attr.RootDirectory = get_perflib_key( attr.RootDirectory ); status = STATUS_SUCCESS; } - *retkey = attr->RootDirectory; + *retkey = attr.RootDirectory; return status; }
@@ -512,7 +518,6 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD */ LSTATUS WINAPI DECLSPEC_HOTPATCH RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD options, REGSAM access, PHKEY retkey ) { - OBJECT_ATTRIBUTES attr; UNICODE_STRING nameW;
if (retkey && (!name || !name[0]) && @@ -530,14 +535,8 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD o *retkey = NULL; if (!(hkey = get_special_root_hkey( hkey, access ))) return ERROR_INVALID_HANDLE;
- attr.Length = sizeof(attr); - attr.RootDirectory = hkey; - attr.ObjectName = &nameW; - attr.Attributes = 0; - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; RtlInitUnicodeString( &nameW, name ); - return RtlNtStatusToDosError( open_key( retkey, hkey, options, access, &attr ) ); + return RtlNtStatusToDosError( open_key( retkey, hkey, nameW, options, access ) ); }
@@ -563,7 +562,6 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD o */ LSTATUS WINAPI DECLSPEC_HOTPATCH RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD options, REGSAM access, PHKEY retkey ) { - OBJECT_ATTRIBUTES attr; STRING nameA; NTSTATUS status;
@@ -584,18 +582,11 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD op
if (!(hkey = get_special_root_hkey( hkey, access ))) return ERROR_INVALID_HANDLE;
- attr.Length = sizeof(attr); - attr.RootDirectory = hkey; - attr.ObjectName = &NtCurrentTeb()->StaticUnicodeString; - attr.Attributes = 0; - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; - RtlInitAnsiString( &nameA, name ); if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, &nameA, FALSE ))) { - status = open_key( retkey, hkey, options, access, &attr ); + status = open_key( retkey, hkey, NtCurrentTeb()->StaticUnicodeString, options, access ); } return RtlNtStatusToDosError( status ); }
From: Sven Baars sbaars@codeweavers.com
--- dlls/kernelbase/registry.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 714f6a20227..de1410a2e95 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -140,12 +140,12 @@ static HKEY get_perflib_key( HANDLE key ) }
/* wrapper for NtCreateKey that creates the key recursively if necessary */ -static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, +static NTSTATUS create_key( HKEY *retkey, HKEY root, 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; + HANDLE subkey;
if (!force_wow32) status = NtCreateKey( &subkey, access, attr, 0, class, options, dispos );
@@ -316,7 +316,7 @@ static HKEY create_special_root_hkey( HKEY hkey, DWORD access ) attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; RtlInitUnicodeString( &name, root_key_names[idx] ); - if (create_key( &hkey, access, &attr, NULL, 0, NULL )) return 0; + if (create_key( &hkey, 0, access, &attr, NULL, 0, NULL )) return 0; TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey ); }
@@ -444,7 +444,7 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD RtlInitUnicodeString( &nameW, name ); RtlInitUnicodeString( &classW, class );
- return RtlNtStatusToDosError( create_key( retkey, access, &attr, &classW, options, dispos ) ); + return RtlNtStatusToDosError( create_key( retkey, hkey, access, &attr, &classW, options, dispos ) ); }
@@ -503,7 +503,7 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD { if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE ))) { - status = create_key( retkey, access, &attr, &classW, options, dispos ); + status = create_key( retkey, hkey, access, &attr, &classW, options, dispos ); RtlFreeUnicodeString( &classW ); } }
From: Sven Baars sbaars@codeweavers.com
--- dlls/kernelbase/registry.c | 92 ++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 54 deletions(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index de1410a2e95..7e4e93302e4 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -140,76 +140,83 @@ static HKEY get_perflib_key( HANDLE key ) }
/* wrapper for NtCreateKey that creates the key recursively if necessary */ -static NTSTATUS create_key( HKEY *retkey, HKEY root, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, - const UNICODE_STRING *class, ULONG options, PULONG dispos ) +static NTSTATUS create_key( HKEY *retkey, HKEY root, UNICODE_STRING name, ULONG 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; + OBJECT_ATTRIBUTES attr; HANDLE subkey;
- if (!force_wow32) status = NtCreateKey( &subkey, access, attr, 0, class, options, dispos ); + 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; + + if (!force_wow32) status = NtCreateKey( &subkey, access, &attr, 0, class, options, dispos );
if (status == STATUS_OBJECT_NAME_NOT_FOUND) { - WCHAR *buffer = attr->ObjectName->Buffer; - DWORD attrs, pos = 0, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR); - UNICODE_STRING str; + WCHAR *buffer = name.Buffer; + DWORD attrs, pos = 0, i = 0, len = name.Length / sizeof(WCHAR);
/* don't try to create registry root */ - if (!attr->RootDirectory && len > 10 && !wcsnicmp( buffer, L"\Registry\", 10 )) i += 10; + 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;
- attrs = attr->Attributes; - attr->ObjectName = &str; + attrs = attr.Attributes;
for (;;) { - str.Buffer = buffer + pos; - str.Length = (i - pos) * sizeof(WCHAR); + name.Buffer = buffer + pos; + name.Length = (i - pos) * sizeof(WCHAR); if (force_wow32 && pos) { - if (is_wow6432node( &str )) force_wow32 = FALSE; - else if ((subkey = open_wow6432node( attr->RootDirectory ))) + if (is_wow6432node( &name )) force_wow32 = FALSE; + else if ((subkey = open_wow6432node( attr.RootDirectory ))) { - if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); - attr->RootDirectory = subkey; + if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); + attr.RootDirectory = subkey; force_wow32 = FALSE; } } if (i == len) { - attr->Attributes = attrs; - status = NtCreateKey( &subkey, access, attr, 0, class, options, dispos ); + attr.Attributes = attrs; + status = NtCreateKey( &subkey, access, &attr, 0, class, options, dispos ); } else { - attr->Attributes = attrs & ~OBJ_OPENLINK; - status = NtCreateKey( &subkey, access, attr, 0, class, + attr.Attributes = attrs & ~OBJ_OPENLINK; + status = NtCreateKey( &subkey, access, &attr, 0, class, options & ~REG_OPTION_CREATE_LINK, dispos ); } - if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); + if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); if (!NT_SUCCESS(status)) return status; if (i == len) break; - attr->RootDirectory = subkey; + attr.RootDirectory = subkey; while (i < len && buffer[i] == '\') i++; pos = i; while (i < len && buffer[i] != '\') i++; } } - attr->RootDirectory = subkey; - if (force_wow32 && (subkey = open_wow6432node( attr->RootDirectory ))) + attr.RootDirectory = subkey; + if (force_wow32 && (subkey = open_wow6432node( attr.RootDirectory ))) { - if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); - attr->RootDirectory = subkey; + if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); + attr.RootDirectory = subkey; } if (status == STATUS_PREDEFINED_HANDLE) { - attr->RootDirectory = get_perflib_key( attr->RootDirectory ); + attr.RootDirectory = get_perflib_key( attr.RootDirectory ); status = STATUS_SUCCESS; } - *retkey = attr->RootDirectory; + *retkey = attr.RootDirectory; return status; }
@@ -306,18 +313,11 @@ static HKEY create_special_root_hkey( HKEY hkey, DWORD access ) } else { - OBJECT_ATTRIBUTES attr; UNICODE_STRING name;
- attr.Length = sizeof(attr); - attr.RootDirectory = 0; - attr.ObjectName = &name; - attr.Attributes = 0; - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; RtlInitUnicodeString( &name, root_key_names[idx] ); - if (create_key( &hkey, 0, access, &attr, NULL, 0, NULL )) return 0; - TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey ); + if (create_key( &hkey, 0, name, 0, access, NULL, NULL )) return 0; + TRACE( "%s -> %p\n", debugstr_w(name.Buffer), hkey ); }
if (!cache_disabled[idx] && !(access & (KEY_WOW64_64KEY | KEY_WOW64_32KEY))) @@ -428,23 +428,15 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, PHKEY retkey, LPDWORD dispos ) { - OBJECT_ATTRIBUTES attr; UNICODE_STRING nameW, classW;
if (reserved) return ERROR_INVALID_PARAMETER; if (!(hkey = get_special_root_hkey( hkey, access ))) return ERROR_INVALID_HANDLE;
- attr.Length = sizeof(attr); - attr.RootDirectory = hkey; - attr.ObjectName = &nameW; - attr.Attributes = 0; - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; - if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK; RtlInitUnicodeString( &nameW, name ); RtlInitUnicodeString( &classW, class );
- return RtlNtStatusToDosError( create_key( retkey, hkey, access, &attr, &classW, options, dispos ) ); + return RtlNtStatusToDosError( create_key( retkey, hkey, nameW, options, access, &classW, dispos ) ); }
@@ -475,7 +467,6 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, PHKEY retkey, LPDWORD dispos ) { - OBJECT_ATTRIBUTES attr; UNICODE_STRING classW; ANSI_STRING nameA, classA; NTSTATUS status; @@ -488,13 +479,6 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD } if (!(hkey = get_special_root_hkey( hkey, access ))) return ERROR_INVALID_HANDLE;
- attr.Length = sizeof(attr); - attr.RootDirectory = hkey; - attr.ObjectName = &NtCurrentTeb()->StaticUnicodeString; - attr.Attributes = 0; - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; - if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK; RtlInitAnsiString( &nameA, name ); RtlInitAnsiString( &classA, class );
@@ -503,7 +487,7 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD { if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE ))) { - status = create_key( retkey, hkey, access, &attr, &classW, options, dispos ); + status = create_key( retkey, hkey, NtCurrentTeb()->StaticUnicodeString, options, access, &classW, dispos ); RtlFreeUnicodeString( &classW ); } }
From: Sven Baars sbaars@codeweavers.com
--- dlls/kernelbase/registry.c | 52 +++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 26 deletions(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 7e4e93302e4..a6fec29bd08 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -100,7 +100,8 @@ static inline BOOL is_version_nt(void)
static BOOL is_wow6432node( const UNICODE_STRING *name ) { - return (name->Length == 11 * sizeof(WCHAR) && !wcsnicmp( name->Buffer, L"Wow6432Node", 11 )); + DWORD len = name->Length / sizeof(WCHAR); + return (len >= 11 && !wcsnicmp( name->Buffer, L"Wow6432Node\", min( len, 12 ) )); }
/* open the Wow6432Node subkey of the specified key */ @@ -228,7 +229,7 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING name, DWORD op BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY); HANDLE subkey; WCHAR *buffer = name.Buffer; - DWORD pos = 0, i = 0, len = name.Length / sizeof(WCHAR); + DWORD i, len = name.Length / sizeof(WCHAR);
*retkey = NULL;
@@ -251,23 +252,15 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING name, DWORD op return status; }
- if (len && buffer[0] == '\') return STATUS_OBJECT_PATH_INVALID; - while (i < len && buffer[i] != '\') i++; - - for (;;) + while (len) { - name.Buffer = buffer + pos; - name.Length = (i - pos) * sizeof(WCHAR); - if (force_wow32 && pos) - { - if (is_wow6432node( &name )) force_wow32 = FALSE; - else if ((subkey = open_wow6432node( attr.RootDirectory ))) - { - if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); - attr.RootDirectory = subkey; - force_wow32 = FALSE; - } - } + i = 0; + if (buffer[0] == '\') return STATUS_OBJECT_PATH_INVALID; + while (i < len && buffer[i] != '\') i++; + + name.Buffer = buffer; + name.Length = i * sizeof(WCHAR); + if (i == len) { if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK; @@ -281,15 +274,22 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING name, DWORD op 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; + 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) {
From: Sven Baars sbaars@codeweavers.com
--- dlls/kernelbase/registry.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index a6fec29bd08..a78aea82fc1 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -226,7 +226,6 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING name, DWORD op { OBJECT_ATTRIBUTES attr; NTSTATUS status; - BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY); HANDLE subkey; WCHAR *buffer = name.Buffer; DWORD i, len = name.Length / sizeof(WCHAR); @@ -240,7 +239,7 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING name, DWORD op attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL;
- if (!force_wow32) + if (!(is_win64 && (access & KEY_WOW64_32KEY))) { if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK; status = NtOpenKeyEx( (HANDLE *)retkey, access, &attr, options ); @@ -278,16 +277,14 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING name, DWORD op buffer += i; len -= i;
- if (force_wow32) + name.Buffer = buffer; + name.Length = len * sizeof(WCHAR); + if (!is_wow6432node( &name )) { - name.Buffer = buffer; - name.Length = len * sizeof(WCHAR); - if (is_wow6432node( &name )) force_wow32 = FALSE; - else if ((subkey = open_wow6432node( attr.RootDirectory ))) + if ((subkey = open_wow6432node( attr.RootDirectory ))) { NtClose( attr.RootDirectory ); attr.RootDirectory = subkey; - force_wow32 = FALSE; } } }
From: Sven Baars sbaars@codeweavers.com
--- dlls/kernelbase/registry.c | 123 ++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 49 deletions(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index a78aea82fc1..133214c84d4 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -221,79 +221,104 @@ static NTSTATUS create_key( HKEY *retkey, HKEY root, UNICODE_STRING name, ULONG 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 ) +static NTSTATUS open_subkey( HKEY *subkey, HKEY root, UNICODE_STRING *name, DWORD options, ACCESS_MASK access ) { + DWORD i = 0, len = name->Length / sizeof(WCHAR); + WCHAR *buffer = name->Buffer; OBJECT_ATTRIBUTES attr; - NTSTATUS status; - HANDLE subkey; - WCHAR *buffer = name.Buffer; - DWORD i, len = name.Length / sizeof(WCHAR); - - *retkey = NULL; + UNICODE_STRING str; + NTSTATUS status = 0;
attr.Length = sizeof(attr); attr.RootDirectory = root; - attr.ObjectName = &name; + attr.ObjectName = &str; attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL;
- if (!(is_win64 && (access & KEY_WOW64_32KEY))) + if (buffer[0] == '\') 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; - status = NtOpenKeyEx( (HANDLE *)retkey, access, &attr, options ); - if (status == STATUS_PREDEFINED_HANDLE) - { - *retkey = get_perflib_key( *retkey ); - status = STATUS_SUCCESS; - } - return status; } - - while (len) + else { - i = 0; - if (buffer[0] == '\') return STATUS_OBJECT_PATH_INVALID; - while (i < len && buffer[i] != '\') i++; + if (!(options & REG_OPTION_OPEN_LINK)) attr.Attributes &= ~OBJ_OPENLINK; + options &= ~REG_OPTION_OPEN_LINK; + }
- name.Buffer = buffer; - name.Length = i * sizeof(WCHAR); + status = NtOpenKeyEx( (HANDLE *)subkey, access, &attr, options ); + if (status == STATUS_PREDEFINED_HANDLE) + { + *subkey = get_perflib_key( *subkey ); + status = STATUS_SUCCESS; + }
- 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 (!status) + { while (i < len && buffer[i] == '\') i++; - buffer += i; - len -= i;
- name.Buffer = buffer; - name.Length = len * sizeof(WCHAR); - if (!is_wow6432node( &name )) + name->Buffer += i; + name->Length -= i * sizeof(WCHAR); + + if (!is_wow6432node( name )) { - if ((subkey = open_wow6432node( attr.RootDirectory ))) + HKEY wow6432node = open_wow6432node( *subkey ); + if (wow6432node) { - NtClose( attr.RootDirectory ); - attr.RootDirectory = subkey; + NtClose( *subkey ); + *subkey = wow6432node; } } } - if (status == STATUS_PREDEFINED_HANDLE) + + 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 ) +{ + HKEY subkey, subkey_root = root; + NTSTATUS status = 0; + + *retkey = NULL; + + if (!(is_win64 && (access & KEY_WOW64_32KEY))) { - attr.RootDirectory = get_perflib_key( attr.RootDirectory ); - status = STATUS_SUCCESS; + 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 = NtOpenKeyEx( (HANDLE *)retkey, access, &attr, options ); + if (status == STATUS_PREDEFINED_HANDLE) + { + *retkey = get_perflib_key( *retkey ); + status = STATUS_SUCCESS; + } + return status; } - *retkey = attr.RootDirectory; + + while (!status && name.Length) + { + status = open_subkey( &subkey, subkey_root, &name, options, access ); + if (subkey_root && subkey_root != root) NtClose( subkey_root ); + subkey_root = subkey; + } + + if (!status) + *retkey = subkey_root; + return status; }
From: Sven Baars sbaars@codeweavers.com
--- dlls/kernelbase/registry.c | 162 ++++++++++++++++++------------------- 1 file changed, 81 insertions(+), 81 deletions(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 133214c84d4..a74a4d8e411 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -140,87 +140,6 @@ static HKEY get_perflib_key( HANDLE key ) return key; }
-/* 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 ) -{ - BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY); - NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND; - OBJECT_ATTRIBUTES attr; - HANDLE subkey; - - 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; - - if (!force_wow32) status = NtCreateKey( &subkey, access, &attr, 0, class, options, dispos ); - - if (status == STATUS_OBJECT_NAME_NOT_FOUND) - { - WCHAR *buffer = name.Buffer; - DWORD attrs, pos = 0, i = 0, len = name.Length / sizeof(WCHAR); - - /* 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++; - if (i == len && !force_wow32) return status; - - attrs = attr.Attributes; - - for (;;) - { - name.Buffer = buffer + pos; - name.Length = (i - pos) * sizeof(WCHAR); - if (force_wow32 && pos) - { - if (is_wow6432node( &name )) 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; - status = NtCreateKey( &subkey, access, &attr, 0, class, options, dispos ); - } - else - { - attr.Attributes = attrs & ~OBJ_OPENLINK; - status = NtCreateKey( &subkey, access, &attr, 0, class, - options & ~REG_OPTION_CREATE_LINK, dispos ); - } - if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); - if (!NT_SUCCESS(status)) return status; - if (i == len) break; - attr.RootDirectory = subkey; - while (i < len && buffer[i] == '\') i++; - pos = i; - while (i < len && buffer[i] != '\') i++; - } - } - 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 ); - status = STATUS_SUCCESS; - } - *retkey = attr.RootDirectory; - return status; -} - static NTSTATUS open_subkey( HKEY *subkey, HKEY root, UNICODE_STRING *name, DWORD options, ACCESS_MASK access ) { DWORD i = 0, len = name->Length / sizeof(WCHAR); @@ -322,6 +241,87 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING name, DWORD op 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 ) +{ + BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY); + NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND; + OBJECT_ATTRIBUTES attr; + HANDLE subkey; + + 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; + + if (!force_wow32) status = NtCreateKey( &subkey, access, &attr, 0, class, options, dispos ); + + if (status == STATUS_OBJECT_NAME_NOT_FOUND) + { + WCHAR *buffer = name.Buffer; + DWORD attrs, pos = 0, i = 0, len = name.Length / sizeof(WCHAR); + + /* 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++; + if (i == len && !force_wow32) return status; + + attrs = attr.Attributes; + + for (;;) + { + name.Buffer = buffer + pos; + name.Length = (i - pos) * sizeof(WCHAR); + if (force_wow32 && pos) + { + if (is_wow6432node( &name )) 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; + status = NtCreateKey( &subkey, access, &attr, 0, class, options, dispos ); + } + else + { + attr.Attributes = attrs & ~OBJ_OPENLINK; + status = NtCreateKey( &subkey, access, &attr, 0, class, + options & ~REG_OPTION_CREATE_LINK, dispos ); + } + if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); + if (!NT_SUCCESS(status)) return status; + if (i == len) break; + attr.RootDirectory = subkey; + while (i < len && buffer[i] == '\') i++; + pos = i; + while (i < len && buffer[i] != '\') i++; + } + } + 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 ); + 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 ) {
From: Sven Baars sbaars@codeweavers.com
--- dlls/kernelbase/registry.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index a74a4d8e411..c690d659eb4 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -258,7 +258,18 @@ static NTSTATUS create_key( HKEY *retkey, HKEY root, UNICODE_STRING name, ULONG attr.SecurityQualityOfService = NULL; if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK;
- if (!force_wow32) status = NtCreateKey( &subkey, access, &attr, 0, class, options, dispos ); + if (!force_wow32) + { + status = NtCreateKey( (HANDLE *)retkey, access, &attr, 0, class, options, dispos ); + if (status == STATUS_PREDEFINED_HANDLE) + { + *retkey = get_perflib_key( *retkey ); + status = STATUS_SUCCESS; + } + + if (!status || status != STATUS_OBJECT_NAME_NOT_FOUND) + return status; + }
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
From: Sven Baars sbaars@codeweavers.com
--- dlls/kernelbase/registry.c | 55 ++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 29 deletions(-)
diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index c690d659eb4..d414b210026 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -274,30 +274,21 @@ static NTSTATUS create_key( HKEY *retkey, HKEY root, UNICODE_STRING name, ULONG if (status == STATUS_OBJECT_NAME_NOT_FOUND) { WCHAR *buffer = name.Buffer; - DWORD attrs, pos = 0, i = 0, len = name.Length / sizeof(WCHAR); - - /* 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++; - if (i == len && !force_wow32) return status; + DWORD attrs, i, len = name.Length / sizeof(WCHAR);
attrs = attr.Attributes;
- for (;;) + while (len) { - name.Buffer = buffer + pos; - name.Length = (i - pos) * sizeof(WCHAR); - if (force_wow32 && pos) - { - if (is_wow6432node( &name )) force_wow32 = FALSE; - else if ((subkey = open_wow6432node( attr.RootDirectory ))) - { - if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); - attr.RootDirectory = subkey; - force_wow32 = FALSE; - } - } + 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; @@ -311,19 +302,25 @@ static NTSTATUS create_key( HKEY *retkey, HKEY root, UNICODE_STRING name, ULONG } if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); if (!NT_SUCCESS(status)) return status; - if (i == len) break; attr.RootDirectory = subkey; while (i < len && buffer[i] == '\') i++; - pos = i; - 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; + } + } } } - 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 );
On Thu Mar 9 09:30:49 2023 +0000, Sven Baars wrote:
That's very strange since I didn't modify these lines of code, so I'd expect the warning to also be there before any of my patches. I also don't see the warning locally. I do get rid of this code later in my patch series. Fixing it earlier will create a mess since attr is currently used everywhere, but I guess it could be done. Since I don't see the warning it may be difficult to do without introducing it again in intermediate commits.
I pushed 4 extra commits that move attr to open_key() and create_key() before doing anything else.