Module: wine Branch: master Commit: 68a5c34731253e5965615b0b1cf920b63938e035 URL: http://source.winehq.org/git/wine.git/?a=commit;h=68a5c34731253e5965615b0b1c...
Author: Alexandre Julliard julliard@winehq.org Date: Fri Apr 2 11:51:15 2010 +0200
advapi32: Add support for the KEY_WOW64_32KEY flag in RegCreateKey on 64-bit.
---
dlls/advapi32/registry.c | 71 ++++++++++++++++++++++++++++++++++------ dlls/advapi32/tests/registry.c | 4 ++- 2 files changed, 64 insertions(+), 11 deletions(-)
diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c index 9266d3f..ba9d9a7 100644 --- a/dlls/advapi32/registry.c +++ b/dlls/advapi32/registry.c @@ -78,6 +78,7 @@ static const WCHAR * const root_key_names[NB_SPECIAL_ROOT_KEYS] = name_DYN_DATA };
+static const int is_win64 = (sizeof(void *) > sizeof(int));
/* check if value type needs string conversion (Ansi<->Unicode) */ static inline int is_string( DWORD type ) @@ -91,34 +92,84 @@ static inline int is_version_nt(void) return !(GetVersion() & 0x80000000); }
+static BOOL is_wow6432node( const UNICODE_STRING *name ) +{ + static const WCHAR wow6432nodeW[] = {'W','o','w','6','4','3','2','N','o','d','e'}; + + return (name->Length == sizeof(wow6432nodeW) && + !memicmpW( name->Buffer, wow6432nodeW, sizeof(wow6432nodeW)/sizeof(WCHAR) )); +} + +/* open the Wow6432Node subkey of the specified key */ +static HANDLE open_wow6432node( HANDLE key, const UNICODE_STRING *name ) +{ + static const WCHAR wow6432nodeW[] = {'W','o','w','6','4','3','2','N','o','d','e',0}; + 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, wow6432nodeW ); + if (NtOpenKey( &ret, MAXIMUM_ALLOWED, &attr )) ret = 0; + return ret; +} + /* wrapper for NtCreateKey that creates the key recursively if necessary */ static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, const UNICODE_STRING *class, ULONG options, PULONG dispos ) { - NTSTATUS status = NtCreateKey( (HANDLE *)retkey, access, attr, 0, class, options, dispos ); + BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY); + NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND; + + if (!force_wow32) status = NtCreateKey( (HANDLE *)retkey, access, attr, 0, class, options, dispos );
if (status == STATUS_OBJECT_NAME_NOT_FOUND) { - DWORD attrs, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR); + HANDLE subkey, root = attr->RootDirectory; + WCHAR *buffer = attr->ObjectName->Buffer; + DWORD attrs, pos = 0, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR); + UNICODE_STRING str; + + while (i < len && buffer[i] != '\') i++; + if (i == len && !force_wow32) return status;
- while (i < len && attr->ObjectName->Buffer[i] != '\') i++; - if (i == len) return status; attrs = attr->Attributes; attr->Attributes &= ~OBJ_OPENLINK; + attr->ObjectName = &str;
while (i < len) { - attr->ObjectName->Length = i * sizeof(WCHAR); - status = NtCreateKey( (HANDLE *)retkey, access, attr, 0, class, + 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, &str ))) + { + if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); + attr->RootDirectory = subkey; + force_wow32 = FALSE; + } + } + status = NtCreateKey( &subkey, access, attr, 0, class, options & ~REG_OPTION_CREATE_LINK, dispos ); + if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); if (status) return status; - NtClose( *retkey ); - while (i < len && attr->ObjectName->Buffer[i] == '\') i++; - while (i < len && attr->ObjectName->Buffer[i] != '\') i++; + attr->RootDirectory = subkey; + while (i < len && buffer[i] == '\') i++; + pos = i; + while (i < len && buffer[i] != '\') i++; } + str.Buffer = buffer + pos; + str.Length = (i - pos) * sizeof(WCHAR); attr->Attributes = attrs; - attr->ObjectName->Length = len * sizeof(WCHAR); status = NtCreateKey( (PHANDLE)retkey, access, attr, 0, class, options, dispos ); + if (attr->RootDirectory != root) NtClose( attr->RootDirectory ); } return status; } diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 63ed984..ea036e8 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -1862,7 +1862,9 @@ static void test_redirection(void) ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); check_key_value( key, "Winetest", 0, ptr_size ); check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : ptr_size ); - check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 ); + dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY ); + if (ptr_size == 32) ok( dw == 32, "wrong value %u\n", dw ); + else todo_wine ok( dw == 32, "wrong value %u\n", dw ); RegCloseKey( key );
if (ptr_size == 32)