From 0badf072e0e0c44c99412f2236adc1b29364bd18 Mon Sep 17 00:00:00 2001 From: Sven Baars Date: Tue, 8 Nov 2022 12:42:28 +0100 Subject: [PATCH] kernelbase: Factor opening a subkey out of open_key(). --- dlls/kernelbase/registry.c | 125 ++++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 50 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,26 +221,84 @@ 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 (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; + } + else + { + if (!(options & REG_OPTION_OPEN_LINK)) attr.Attributes &= ~OBJ_OPENLINK; + options &= ~REG_OPTION_OPEN_LINK; + } + + status = NtOpenKeyEx( (HANDLE *)subkey, access, &attr, options ); + 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); + + if (!is_wow6432node( name )) + { + HKEY wow6432node = open_wow6432node( *subkey ); + if (wow6432node) + { + NtClose( *subkey ); + *subkey = wow6432node; + } + } + } + + 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))) { + 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) @@ -251,49 +309,16 @@ static NTSTATUS open_key( HKEY *retkey, HKEY root, UNICODE_STRING name, DWORD op return status; } - while (len) + while (!status && name.Length) { - 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; - 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; - while (i < len && buffer[i] == '\\') i++; - buffer += i; - len -= i; - - name.Buffer = buffer; - name.Length = len * sizeof(WCHAR); - if (!is_wow6432node( &name )) - { - if ((subkey = open_wow6432node( attr.RootDirectory ))) - { - NtClose( attr.RootDirectory ); - attr.RootDirectory = subkey; - } - } + status = open_subkey( &subkey, subkey_root, &name, options, access ); + 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; }