mirror of
https://gitlab.winehq.org/wine/wine.git
synced 2024-11-21 17:09:06 -07:00
Merge branch 'reg_shared_hkcu' into 'master'
server, kernelbase: Force WoW sharing on HKCU/Software key. See merge request wine/wine!6072
This commit is contained in:
commit
786b3e4812
4 changed files with 203 additions and 24 deletions
|
@ -3375,6 +3375,78 @@ static void test_redirection(void)
|
||||||
|
|
||||||
RegDeleteKeyA( key32, "" );
|
RegDeleteKeyA( key32, "" );
|
||||||
RegCloseKey( key32 );
|
RegCloseKey( key32 );
|
||||||
|
|
||||||
|
/* HKCU\\Software is shared. */
|
||||||
|
err = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Wow6432Node\\tmp", 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, NULL, &key, NULL );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
RegDeleteKeyA( key, "" );
|
||||||
|
RegCloseKey( key );
|
||||||
|
|
||||||
|
err = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\TestKey", 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, NULL, &root64, NULL );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
err = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\Wow6432Node\\TestKey", 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &root32 );
|
||||||
|
ok ( err == ERROR_FILE_NOT_FOUND, "got %#lx.\n", err );
|
||||||
|
|
||||||
|
err = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Wow6432Node\\TestKey", 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, NULL, &root32, NULL );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
|
||||||
|
dw = 1;
|
||||||
|
err = RegSetKeyValueA( root64, NULL, "val", REG_DWORD, &dw, sizeof(dw) );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
|
||||||
|
dw = 2;
|
||||||
|
err = RegSetKeyValueA( root32, NULL, "val", REG_DWORD, &dw, sizeof(dw) );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
|
||||||
|
err = RegCreateKeyExA( root64, "subkey", 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, &key64, NULL );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
dw = 1;
|
||||||
|
err = RegSetKeyValueA( key64, NULL, "val", REG_DWORD, &dw, sizeof(dw) );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
|
||||||
|
err = RegCreateKeyExA( root32, "subkey", 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, NULL, &key32, NULL );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
dw = 2;
|
||||||
|
err = RegSetKeyValueA( key32, NULL, "val", REG_DWORD, &dw, sizeof(dw) );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
|
||||||
|
err = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\TestKey", 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &key );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
len = sizeof(dw);
|
||||||
|
err = RegQueryValueExA( key, "val", NULL, NULL, (BYTE *)&dw, &len );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
ok( dw == 1, "got %lu.\n", dw );
|
||||||
|
RegCloseKey( key );
|
||||||
|
err = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\TestKey", 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, &key );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
len = sizeof(dw);
|
||||||
|
err = RegQueryValueExA( key, "val", NULL, NULL, (BYTE *)&dw, &len );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
ok( dw == 1, "got %lu.\n", dw );
|
||||||
|
RegCloseKey( key );
|
||||||
|
err = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\TestKey\\subkey", 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &key );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
len = sizeof(dw);
|
||||||
|
err = RegQueryValueExA( key, "val", NULL, NULL, (BYTE *)&dw, &len );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
ok( dw == 1, "got %lu.\n", dw );
|
||||||
|
RegCloseKey( key );
|
||||||
|
err = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\TestKey\\subkey", 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, &key );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
len = sizeof(dw);
|
||||||
|
err = RegQueryValueExA( key, "val", NULL, NULL, (BYTE *)&dw, &len );
|
||||||
|
ok( !err, "got %#lx.\n", err );
|
||||||
|
ok( dw == 1, "got %lu.\n", dw );
|
||||||
|
RegCloseKey( key );
|
||||||
|
|
||||||
|
RegDeleteKeyA( key64, "" );
|
||||||
|
RegCloseKey( key64 );
|
||||||
|
RegDeleteKeyA( key32, "" );
|
||||||
|
RegCloseKey( key32 );
|
||||||
|
RegDeleteKeyA( root32, "" );
|
||||||
|
RegCloseKey( root32 );
|
||||||
|
RegDeleteKeyA( root64, "" );
|
||||||
|
RegCloseKey( root64 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_classesroot(void)
|
static void test_classesroot(void)
|
||||||
|
|
|
@ -112,20 +112,15 @@ static BOOL is_classes_root( const UNICODE_STRING *name )
|
||||||
return (len >= classes_root_len - 1 && !wcsnicmp( name->Buffer, classes_root, min( len, classes_root_len ) ));
|
return (len >= classes_root_len - 1 && !wcsnicmp( name->Buffer, classes_root, min( len, classes_root_len ) ));
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL is_classes_wow6432node( HKEY key )
|
static KEY_NAME_INFORMATION *get_key_name( HKEY key, char *buffer, DWORD len )
|
||||||
{
|
{
|
||||||
char buffer[256], *buf_ptr = buffer;
|
char *buf_ptr = buffer;
|
||||||
KEY_NAME_INFORMATION *info = (KEY_NAME_INFORMATION *)buffer;
|
KEY_NAME_INFORMATION *info = (KEY_NAME_INFORMATION *)buffer;
|
||||||
DWORD len = sizeof(buffer);
|
|
||||||
UNICODE_STRING name;
|
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
BOOL ret = FALSE;
|
|
||||||
|
|
||||||
/* Obtain the name of the root key */
|
status = NtQueryKey( key, KeyNameInformation, buf_ptr, len, &len );
|
||||||
status = NtQueryKey( key, KeyNameInformation, info, len, &len );
|
if (status && status != STATUS_BUFFER_OVERFLOW) return NULL;
|
||||||
if (status && status != STATUS_BUFFER_OVERFLOW) return FALSE;
|
|
||||||
|
|
||||||
/* Retry with a dynamically allocated buffer */
|
|
||||||
while (status == STATUS_BUFFER_OVERFLOW)
|
while (status == STATUS_BUFFER_OVERFLOW)
|
||||||
{
|
{
|
||||||
if (buf_ptr != buffer) heap_free( buf_ptr );
|
if (buf_ptr != buffer) heap_free( buf_ptr );
|
||||||
|
@ -133,9 +128,22 @@ static BOOL is_classes_wow6432node( HKEY key )
|
||||||
info = (KEY_NAME_INFORMATION *)buf_ptr;
|
info = (KEY_NAME_INFORMATION *)buf_ptr;
|
||||||
status = NtQueryKey( key, KeyNameInformation, info, len, &len );
|
status = NtQueryKey( key, KeyNameInformation, info, len, &len );
|
||||||
}
|
}
|
||||||
|
if (!status) return (KEY_NAME_INFORMATION *)buf_ptr;
|
||||||
|
if (buf_ptr != buffer) heap_free( buf_ptr );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL is_classes_wow6432node( HKEY key )
|
||||||
|
{
|
||||||
|
KEY_NAME_INFORMATION *info;
|
||||||
|
char buffer[256];
|
||||||
|
UNICODE_STRING name;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
if (!(info = get_key_name( key, buffer, sizeof(buffer) ))) return FALSE;
|
||||||
|
|
||||||
/* Check if the key ends in Wow6432Node and if the root is the Classes key*/
|
/* Check if the key ends in Wow6432Node and if the root is the Classes key*/
|
||||||
if (!status && info->NameLength / sizeof(WCHAR) >= 11)
|
if (info->NameLength / sizeof(WCHAR) >= 11)
|
||||||
{
|
{
|
||||||
name.Buffer = info->Name + info->NameLength / sizeof(WCHAR) - 11;
|
name.Buffer = info->Name + info->NameLength / sizeof(WCHAR) - 11;
|
||||||
name.Length = 11 * sizeof(WCHAR);
|
name.Length = 11 * sizeof(WCHAR);
|
||||||
|
@ -146,9 +154,39 @@ static BOOL is_classes_wow6432node( HKEY key )
|
||||||
ret = is_classes_root( &name );
|
ret = is_classes_root( &name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((char *)info != buffer) heap_free( info );
|
||||||
|
|
||||||
if (buf_ptr != buffer) heap_free( buf_ptr );
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL is_wow6432_shared( HANDLE key )
|
||||||
|
{
|
||||||
|
static const WCHAR users_root[] = L"\\Registry\\User\\";
|
||||||
|
const DWORD users_root_len = ARRAY_SIZE( users_root ) - 1;
|
||||||
|
static const WCHAR software[] = L"\\Software";
|
||||||
|
const DWORD software_len = ARRAY_SIZE( software ) - 1;
|
||||||
|
KEY_NAME_INFORMATION *info;
|
||||||
|
char buffer[256];
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
WCHAR *name;
|
||||||
|
DWORD len;
|
||||||
|
|
||||||
|
if (!(info = get_key_name( key, buffer, sizeof(buffer) ))) return FALSE;
|
||||||
|
len = info->NameLength / sizeof(WCHAR);
|
||||||
|
if (len <= users_root_len) goto done;
|
||||||
|
name = info->Name;
|
||||||
|
if (wcsnicmp( name, users_root, users_root_len )) goto done;
|
||||||
|
name += users_root_len;
|
||||||
|
len -= users_root_len;
|
||||||
|
while (len && *name != '\\')
|
||||||
|
{
|
||||||
|
++name;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
if (len != software_len) goto done;
|
||||||
|
ret = !wcsnicmp( name, software, software_len );
|
||||||
|
done:
|
||||||
|
if ((char *)info != buffer) heap_free( info );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +204,11 @@ static HANDLE open_wow6432node( HANDLE key )
|
||||||
attr.SecurityDescriptor = NULL;
|
attr.SecurityDescriptor = NULL;
|
||||||
attr.SecurityQualityOfService = NULL;
|
attr.SecurityQualityOfService = NULL;
|
||||||
if (NtOpenKeyEx( &ret, MAXIMUM_ALLOWED | KEY_WOW64_64KEY, &attr, 0 )) return key;
|
if (NtOpenKeyEx( &ret, MAXIMUM_ALLOWED | KEY_WOW64_64KEY, &attr, 0 )) return key;
|
||||||
|
if (is_wow6432_shared( key ))
|
||||||
|
{
|
||||||
|
NtClose( ret );
|
||||||
|
return key;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1454,7 +1454,7 @@ static void test_redirection(void)
|
||||||
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
|
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
|
||||||
KEY_FULL_INFORMATION *full_info = (KEY_FULL_INFORMATION *)buffer;
|
KEY_FULL_INFORMATION *full_info = (KEY_FULL_INFORMATION *)buffer;
|
||||||
DWORD dw, len;
|
DWORD dw, len;
|
||||||
HANDLE key, key32, key64, root, root32, root64;
|
HANDLE key, key32, key64, root, root32, root64, hkcu;
|
||||||
int subkeys64, subkeys32;
|
int subkeys64, subkeys32;
|
||||||
|
|
||||||
if (ptr_size != 64)
|
if (ptr_size != 64)
|
||||||
|
@ -2012,6 +2012,62 @@ static void test_redirection(void)
|
||||||
|
|
||||||
pNtDeleteKey( key32 );
|
pNtDeleteKey( key32 );
|
||||||
pNtClose( key32 );
|
pNtClose( key32 );
|
||||||
|
|
||||||
|
/* HKCU\\Software is shared. */
|
||||||
|
pRtlOpenCurrentUser( KEY_ALL_ACCESS, (HANDLE *)&hkcu );
|
||||||
|
attr.RootDirectory = hkcu;
|
||||||
|
pRtlInitUnicodeString( &str, L"Software\\Wow6432Node\\tmp" );
|
||||||
|
status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
|
||||||
|
ok( !status, "got %#lx.\n", status );
|
||||||
|
pNtDeleteKey( key );
|
||||||
|
pNtClose( key );
|
||||||
|
|
||||||
|
pRtlInitUnicodeString( &str, L"Software\\TestKey" );
|
||||||
|
status = pNtCreateKey( &root64, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
|
||||||
|
ok( !status, "got %#lx.\n", status );
|
||||||
|
|
||||||
|
pRtlInitUnicodeString( &str, L"Software\\Wow6432Node\\TestKey" );
|
||||||
|
status = pNtOpenKey( &root32, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr );
|
||||||
|
ok ( status == STATUS_OBJECT_NAME_NOT_FOUND, "got %#lx.\n", status );
|
||||||
|
status = pNtCreateKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
|
||||||
|
ok( !status, "got %#lx.\n", status );
|
||||||
|
|
||||||
|
dw = 1;
|
||||||
|
status = pNtSetValueKey( root64, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
|
||||||
|
ok( !status, "got %#lx.\n", status );
|
||||||
|
dw = 2;
|
||||||
|
status = pNtSetValueKey( root32, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
|
||||||
|
ok( !status, "got %#lx.\n", status );
|
||||||
|
|
||||||
|
attr.RootDirectory = root64;
|
||||||
|
pRtlInitUnicodeString( &str, L"subkey" );
|
||||||
|
status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
|
||||||
|
ok( !status, "got %#lx.\n", status );
|
||||||
|
dw = 1;
|
||||||
|
status = pNtSetValueKey( key64, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
|
||||||
|
ok( !status, "got %#lx.\n", status );
|
||||||
|
|
||||||
|
attr.RootDirectory = root32;
|
||||||
|
status = pNtCreateKey( &key32, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
|
||||||
|
ok( !status, "got %#lx.\n", status );
|
||||||
|
dw = 2;
|
||||||
|
status = pNtSetValueKey( key32, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
|
||||||
|
ok( !status, "got %#lx.\n", status );
|
||||||
|
|
||||||
|
check_key_value( hkcu, "Software\\TestKey", KEY_WOW64_64KEY, 1 );
|
||||||
|
check_key_value( hkcu, "Software\\TestKey", KEY_WOW64_32KEY, 1 );
|
||||||
|
check_key_value( hkcu, "Software\\TestKey\\subkey", KEY_WOW64_64KEY, 1 );
|
||||||
|
check_key_value( hkcu, "Software\\TestKey\\subkey", KEY_WOW64_32KEY, 1 );
|
||||||
|
|
||||||
|
pNtDeleteKey( key64 );
|
||||||
|
pNtClose( key64 );
|
||||||
|
pNtDeleteKey( key32 );
|
||||||
|
pNtClose( key32 );
|
||||||
|
pNtDeleteKey( root32 );
|
||||||
|
pNtClose( root32 );
|
||||||
|
pNtDeleteKey( root64 );
|
||||||
|
pNtClose( root64 );
|
||||||
|
pNtClose( hkcu );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_long_value_name(void)
|
static void test_long_value_name(void)
|
||||||
|
|
|
@ -97,8 +97,9 @@ struct key
|
||||||
#define KEY_DELETED 0x0002 /* key has been deleted */
|
#define KEY_DELETED 0x0002 /* key has been deleted */
|
||||||
#define KEY_DIRTY 0x0004 /* key has been modified */
|
#define KEY_DIRTY 0x0004 /* key has been modified */
|
||||||
#define KEY_SYMLINK 0x0008 /* key is a symbolic link */
|
#define KEY_SYMLINK 0x0008 /* key is a symbolic link */
|
||||||
#define KEY_WOWSHARE 0x0010 /* key is a Wow64 shared key (used for Software\Classes) */
|
#define KEY_WOWREFLECT 0x0010 /* key is a Wow64 shared and reflected key (used for Software\Classes) */
|
||||||
#define KEY_PREDEF 0x0020 /* key is marked as predefined */
|
#define KEY_PREDEF 0x0020 /* key is marked as predefined */
|
||||||
|
#define KEY_WOWSHARE 0x0040 /* key is Wow64 shared */
|
||||||
|
|
||||||
#define OBJ_KEY_WOW64 0x100000 /* magic flag added to attributes for WoW64 redirection */
|
#define OBJ_KEY_WOW64 0x100000 /* magic flag added to attributes for WoW64 redirection */
|
||||||
|
|
||||||
|
@ -518,7 +519,7 @@ static struct object *key_lookup_name( struct object *obj, struct unicode_str *n
|
||||||
}
|
}
|
||||||
|
|
||||||
key = (struct key *)obj;
|
key = (struct key *)obj;
|
||||||
if (key && (key->flags & KEY_WOWSHARE) && (attr & OBJ_KEY_WOW64) && !name->str)
|
if (key && (key->flags & KEY_WOWREFLECT) && (attr & OBJ_KEY_WOW64) && !name->str)
|
||||||
{
|
{
|
||||||
key = get_parent( key );
|
key = get_parent( key );
|
||||||
release_object( obj );
|
release_object( obj );
|
||||||
|
@ -545,7 +546,7 @@ static struct object *key_lookup_name( struct object *obj, struct unicode_str *n
|
||||||
|
|
||||||
if (!(found = find_subkey( key, &tmp, &index )))
|
if (!(found = find_subkey( key, &tmp, &index )))
|
||||||
{
|
{
|
||||||
if ((key->flags & KEY_WOWSHARE) && (attr & OBJ_KEY_WOW64))
|
if ((key->flags & KEY_WOWREFLECT) && (attr & OBJ_KEY_WOW64))
|
||||||
{
|
{
|
||||||
/* try in the 64-bit parent */
|
/* try in the 64-bit parent */
|
||||||
key = get_parent( key );
|
key = get_parent( key );
|
||||||
|
@ -604,7 +605,7 @@ static int key_link_name( struct object *obj, struct object_name *name, struct o
|
||||||
for (i = ++parent_key->last_subkey; i > index; i--)
|
for (i = ++parent_key->last_subkey; i > index; i--)
|
||||||
parent_key->subkeys[i] = parent_key->subkeys[i - 1];
|
parent_key->subkeys[i] = parent_key->subkeys[i - 1];
|
||||||
parent_key->subkeys[index] = (struct key *)grab_object( key );
|
parent_key->subkeys[index] = (struct key *)grab_object( key );
|
||||||
if (is_wow6432node( name->name, name->len ) &&
|
if (!(parent_key->flags & KEY_WOWSHARE) && is_wow6432node( name->name, name->len ) &&
|
||||||
!is_wow6432node( parent_key->obj.name->name, parent_key->obj.name->len ))
|
!is_wow6432node( parent_key->obj.name->name, parent_key->obj.name->len ))
|
||||||
parent_key->wow6432node = key;
|
parent_key->wow6432node = key;
|
||||||
name->parent = parent;
|
name->parent = parent;
|
||||||
|
@ -777,7 +778,7 @@ static struct key *grab_wow6432node( struct key *key )
|
||||||
struct key *ret = key->wow6432node;
|
struct key *ret = key->wow6432node;
|
||||||
|
|
||||||
if (!ret) return key;
|
if (!ret) return key;
|
||||||
if (ret->flags & KEY_WOWSHARE) return key;
|
if (ret->flags & KEY_WOWREFLECT) return key;
|
||||||
grab_object( ret );
|
grab_object( ret );
|
||||||
release_object( key );
|
release_object( key );
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -823,7 +824,7 @@ static struct key *open_key( struct key *parent, const struct unicode_str *name,
|
||||||
if (parent && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name->str, name->len ))
|
if (parent && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name->str, name->len ))
|
||||||
{
|
{
|
||||||
key = get_wow6432node( parent );
|
key = get_wow6432node( parent );
|
||||||
if (key && ((access & KEY_WOW64_32KEY) || (key->flags & KEY_WOWSHARE)))
|
if (key && ((access & KEY_WOW64_32KEY) || (key->flags & KEY_WOWREFLECT)))
|
||||||
parent = key;
|
parent = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,7 +850,7 @@ static struct key *create_key( struct key *parent, const struct unicode_str *nam
|
||||||
if (parent && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name->str, name->len ))
|
if (parent && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name->str, name->len ))
|
||||||
{
|
{
|
||||||
key = get_wow6432node( parent );
|
key = get_wow6432node( parent );
|
||||||
if (key && ((access & KEY_WOW64_32KEY) || (key->flags & KEY_WOWSHARE)))
|
if (key && ((access & KEY_WOW64_32KEY) || (key->flags & KEY_WOWREFLECT)))
|
||||||
parent = key;
|
parent = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1886,13 +1887,14 @@ void init_registry(void)
|
||||||
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
|
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
|
||||||
'P','e','r','f','l','i','b','\\',
|
'P','e','r','f','l','i','b','\\',
|
||||||
'0','0','9'};
|
'0','0','9'};
|
||||||
|
static const WCHAR software[] = {'S','o','f','t','w','a','r','e',};
|
||||||
static const struct unicode_str root_name = { REGISTRY, sizeof(REGISTRY) };
|
static const struct unicode_str root_name = { REGISTRY, sizeof(REGISTRY) };
|
||||||
static const struct unicode_str HKLM_name = { HKLM, sizeof(HKLM) };
|
static const struct unicode_str HKLM_name = { HKLM, sizeof(HKLM) };
|
||||||
static const struct unicode_str HKU_name = { HKU_default, sizeof(HKU_default) };
|
static const struct unicode_str HKU_name = { HKU_default, sizeof(HKU_default) };
|
||||||
static const struct unicode_str perflib_name = { perflib, sizeof(perflib) };
|
static const struct unicode_str perflib_name = { perflib, sizeof(perflib) };
|
||||||
|
|
||||||
WCHAR *current_user_path;
|
WCHAR *current_user_path;
|
||||||
struct unicode_str current_user_str;
|
struct unicode_str current_user_str, name;
|
||||||
struct key *key, *hklm, *hkcu;
|
struct key *key, *hklm, *hkcu;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
char *p;
|
char *p;
|
||||||
|
@ -1944,8 +1946,6 @@ void init_registry(void)
|
||||||
/* set the shared flag on Software\Classes\Wow6432Node for all platforms */
|
/* set the shared flag on Software\Classes\Wow6432Node for all platforms */
|
||||||
for (i = 1; i < supported_machines_count; i++)
|
for (i = 1; i < supported_machines_count; i++)
|
||||||
{
|
{
|
||||||
struct unicode_str name;
|
|
||||||
|
|
||||||
switch (supported_machines[i])
|
switch (supported_machines[i])
|
||||||
{
|
{
|
||||||
case IMAGE_FILE_MACHINE_I386: name.str = classes_i386; name.len = sizeof(classes_i386); break;
|
case IMAGE_FILE_MACHINE_I386: name.str = classes_i386; name.len = sizeof(classes_i386); break;
|
||||||
|
@ -1954,10 +1954,18 @@ void init_registry(void)
|
||||||
}
|
}
|
||||||
if ((key = create_key_recursive( hklm, &name, current_time )))
|
if ((key = create_key_recursive( hklm, &name, current_time )))
|
||||||
{
|
{
|
||||||
key->flags |= KEY_WOWSHARE;
|
key->flags |= KEY_WOWREFLECT;
|
||||||
release_object( key );
|
release_object( key );
|
||||||
}
|
}
|
||||||
/* FIXME: handle HKCU too */
|
}
|
||||||
|
|
||||||
|
name.str = software;
|
||||||
|
name.len = sizeof(software);
|
||||||
|
if ((key = create_key_recursive( hkcu, &name, current_time )))
|
||||||
|
{
|
||||||
|
key->flags |= KEY_WOWSHARE;
|
||||||
|
key->wow6432node = NULL;
|
||||||
|
release_object( key );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((key = create_key_recursive( hklm, &perflib_name, current_time )))
|
if ((key = create_key_recursive( hklm, &perflib_name, current_time )))
|
||||||
|
|
Loading…
Reference in a new issue