Alexandre Julliard : advapi32: Add support for the KEY_WOW64_32KEY flag in RegCreateKey on 64-bit.
Alexandre Julliard
julliard at winehq.org
Fri Apr 2 10:17:11 CDT 2010
Module: wine
Branch: master
Commit: 68a5c34731253e5965615b0b1cf920b63938e035
URL: http://source.winehq.org/git/wine.git/?a=commit;h=68a5c34731253e5965615b0b1cf920b63938e035
Author: Alexandre Julliard <julliard at 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)
More information about the wine-cvs
mailing list