Commit f2ef2c2b authored by Alexandre Julliard's avatar Alexandre Julliard

Handle special registry root keys directly in advapi32, and avoid

using them in kernel and ntdll.
parent fb40a72f
......@@ -39,6 +39,47 @@
WINE_DEFAULT_DEBUG_CHANNEL(reg);
/* allowed bits for access mask */
#define KEY_ACCESS_MASK (KEY_ALL_ACCESS | MAXIMUM_ALLOWED)
#define HKEY_SPECIAL_ROOT_FIRST HKEY_CLASSES_ROOT
#define HKEY_SPECIAL_ROOT_LAST HKEY_DYN_DATA
#define NB_SPECIAL_ROOT_KEYS ((UINT)HKEY_SPECIAL_ROOT_LAST - (UINT)HKEY_SPECIAL_ROOT_FIRST + 1)
static HKEY special_root_keys[NB_SPECIAL_ROOT_KEYS];
static const WCHAR name_CLASSES_ROOT[] =
{'M','a','c','h','i','n','e','\\',
'S','o','f','t','w','a','r','e','\\',
'C','l','a','s','s','e','s',0};
static const WCHAR name_LOCAL_MACHINE[] =
{'M','a','c','h','i','n','e',0};
static const WCHAR name_USERS[] =
{'U','s','e','r',0};
static const WCHAR name_PERFORMANCE_DATA[] =
{'P','e','r','f','D','a','t','a',0};
static const WCHAR name_CURRENT_CONFIG[] =
{'M','a','c','h','i','n','e','\\',
'S','y','s','t','e','m','\\',
'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
'H','a','r','d','w','a','r','e','P','r','o','f','i','l','e','s','\\',
'C','u','r','r','e','n','t',0};
static const WCHAR name_DYN_DATA[] =
{'D','y','n','D','a','t','a',0};
#define DECL_STR(key) { sizeof(name_##key)-sizeof(WCHAR), sizeof(name_##key), (LPWSTR)name_##key }
static UNICODE_STRING root_key_names[NB_SPECIAL_ROOT_KEYS] =
{
DECL_STR(CLASSES_ROOT),
{ 0, 0, NULL }, /* HKEY_CURRENT_USER is determined dynamically */
DECL_STR(LOCAL_MACHINE),
DECL_STR(USERS),
DECL_STR(PERFORMANCE_DATA),
DECL_STR(CURRENT_CONFIG),
DECL_STR(DYN_DATA)
};
#undef DECL_STR
/* check if value type needs string conversion (Ansi<->Unicode) */
inline static int is_string( DWORD type )
......@@ -52,8 +93,51 @@ inline static int is_version_nt(void)
return !(GetVersion() & 0x80000000);
}
/* allowed bits for access mask */
#define KEY_ACCESS_MASK (KEY_ALL_ACCESS | MAXIMUM_ALLOWED)
/* create one of the HKEY_* special root keys */
static HKEY create_special_root_hkey( HKEY hkey, DWORD access )
{
HKEY ret = 0;
int idx = (UINT)hkey - (UINT)HKEY_SPECIAL_ROOT_FIRST;
if (hkey == HKEY_CURRENT_USER)
{
if (RtlOpenCurrentUser( access, &hkey )) return 0;
TRACE( "HKEY_CURRENT_USER -> %08x\n", hkey );
}
else
{
OBJECT_ATTRIBUTES attr;
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = &root_key_names[idx];
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
if (NtCreateKey( &hkey, access, &attr, 0, NULL, 0, NULL )) return 0;
TRACE( "%s -> %08x\n", debugstr_w(attr.ObjectName->Buffer), hkey );
}
if (!(ret = InterlockedCompareExchange( (PLONG)&special_root_keys[idx], hkey, 0 )))
ret = hkey;
else
NtClose( hkey ); /* somebody beat us to it */
return ret;
}
/* map the hkey from special root to normal key if necessary */
inline static HKEY get_special_root_hkey( HKEY hkey )
{
HKEY ret = hkey;
if ((hkey >= HKEY_SPECIAL_ROOT_FIRST) && (hkey <= HKEY_SPECIAL_ROOT_LAST))
{
if (!(ret = special_root_keys[(UINT)hkey - (UINT)HKEY_SPECIAL_ROOT_FIRST]))
ret = create_special_root_hkey( hkey, KEY_ALL_ACCESS );
}
return ret;
}
/******************************************************************************
* RegCreateKeyExW [ADVAPI32.@]
......@@ -83,6 +167,7 @@ DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR cl
if (reserved) return ERROR_INVALID_PARAMETER;
if (!(access & KEY_ACCESS_MASK) || (access & ~KEY_ACCESS_MASK)) return ERROR_ACCESS_DENIED;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
......@@ -115,6 +200,7 @@ DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR clas
if (reserved) return ERROR_INVALID_PARAMETER;
if (!is_version_nt()) access = KEY_ALL_ACCESS; /* Win95 ignores the access mask */
else if (!(access & KEY_ACCESS_MASK) || (access & ~KEY_ACCESS_MASK)) return ERROR_ACCESS_DENIED;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
......@@ -187,6 +273,8 @@ DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM acce
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
......@@ -209,6 +297,8 @@ DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM acces
if (!is_version_nt()) access = KEY_ALL_ACCESS; /* Win95 ignores the access mask */
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &NtCurrentTeb()->StaticUnicodeString;
......@@ -295,8 +385,7 @@ DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_le
name_len ? *name_len : -1, reserved, class, class_len, ft );
if (reserved) return ERROR_INVALID_PARAMETER;
if (!hkey) return ERROR_INVALID_HANDLE;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
status = NtEnumerateKey( hkey, index, KeyNodeInformation,
buffer, sizeof(buffer), &total_size );
......@@ -358,8 +447,7 @@ DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len
name_len ? *name_len : -1, reserved, class, class_len, ft );
if (reserved) return ERROR_INVALID_PARAMETER;
if (!hkey) return ERROR_INVALID_HANDLE;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
status = NtEnumerateKey( hkey, index, KeyNodeInformation,
buffer, sizeof(buffer), &total_size );
......@@ -464,6 +552,7 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
if (class && !class_len && is_version_nt()) return ERROR_INVALID_PARAMETER;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
......@@ -612,6 +701,7 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
if (class && !class_len && is_version_nt()) return ERROR_INVALID_PARAMETER;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
......@@ -694,6 +784,8 @@ DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
DWORD ret;
HKEY tmp;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
if (!name || !*name)
{
ret = RtlNtStatusToDosError( NtDeleteKey( hkey ) );
......@@ -726,6 +818,8 @@ DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
DWORD ret;
HKEY tmp;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
if (!name || !*name)
{
ret = RtlNtStatusToDosError( NtDeleteKey( hkey ) );
......@@ -788,6 +882,7 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
if (str[count / sizeof(WCHAR) - 1] && !str[count / sizeof(WCHAR)])
count += sizeof(WCHAR);
}
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) );
......@@ -814,6 +909,8 @@ DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
if (data[count-1] && !data[count]) count++;
}
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
if (is_string( type )) /* need to convert to Unicode */
{
DWORD lenW;
......@@ -916,6 +1013,7 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
RtlInitUnicodeString( &name_str, name );
......@@ -983,6 +1081,7 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
RtlInitAnsiString( &nameA, name );
if ((status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString,
......@@ -1132,6 +1231,7 @@ DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD index, LPWSTR value, LPDWORD val_co
/* NT only checks count, not val_count */
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
if (data) total_size += *count;
......@@ -1214,6 +1314,7 @@ DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_cou
/* NT only checks count, not val_count */
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
if (data) total_size += *count;
......@@ -1313,6 +1414,9 @@ DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_cou
DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
{
UNICODE_STRING nameW;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtDeleteValueKey( hkey, &nameW ) );
}
......@@ -1326,12 +1430,12 @@ DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
STRING nameA;
NTSTATUS status;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
RtlInitAnsiString( &nameA, name );
if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString,
&nameA, FALSE )))
{
status = NtDeleteValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString );
}
return RtlNtStatusToDosError( status );
}
......@@ -1353,6 +1457,7 @@ LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename )
if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
len = strlenW( subkey ) * sizeof(WCHAR);
if (len > MAX_PATH*sizeof(WCHAR)) return ERROR_INVALID_PARAMETER;
......@@ -1393,6 +1498,7 @@ LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
if (!(len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), buffer, MAX_PATH )))
return ERROR_INVALID_PARAMETER;
......@@ -1439,6 +1545,7 @@ LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa )
TRACE( "(%x,%s,%p)\n", hkey, debugstr_a(file), sa );
if (!file || !*file) return ERROR_INVALID_PARAMETER;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
err = GetLastError();
GetFullPathNameA( file, sizeof(buffer), buffer, &name );
......
......@@ -188,7 +188,7 @@ void CDROM_InitRegistry(int dev)
DWORD disp;
attr.Length = sizeof(attr);
attr.RootDirectory = HKEY_LOCAL_MACHINE;
attr.RootDirectory = 0;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
......@@ -198,7 +198,7 @@ void CDROM_InitRegistry(int dev)
return;
/* Ensure there is Scsi key */
if (!RtlCreateUnicodeStringFromAsciiz( &nameW, "HARDWARE\\DEVICEMAP\\Scsi" ) ||
if (!RtlCreateUnicodeStringFromAsciiz( &nameW, "Machine\\HARDWARE\\DEVICEMAP\\Scsi" ) ||
NtCreateKey( &scsiKey, KEY_ALL_ACCESS, &attr, 0,
NULL, REG_OPTION_VOLATILE, &disp ))
{
......
......@@ -621,7 +621,7 @@ DWORD WINAPI RtlOpenCurrentUser(
RtlFormatCurrentUserKeyPath(&ObjectName);
InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
ret = NtOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
ret = NtCreateKey(KeyHandle, DesiredAccess, &ObjectAttributes, 0, NULL, 0, NULL);
RtlFreeUnicodeString(&ObjectName);
return ret;
}
......@@ -1086,7 +1086,8 @@ static void _save_at_exit(HKEY hkey,LPCSTR path)
}
/* configure save files and start the periodic saving timer [Internal] */
static void _init_registry_saving( HKEY hkey_users_default )
static void _init_registry_saving( HKEY hkey_local_machine, HKEY hkey_current_user,
HKEY hkey_users_default )
{
int all;
int period = 0;
......@@ -1106,8 +1107,8 @@ static void _init_registry_saving( HKEY hkey_users_default )
if (PROFILE_GetWineIniBool(registryW, WritetoHomeRegistryFilesW, 1))
{
_save_at_exit(HKEY_CURRENT_USER,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER );
_save_at_exit(HKEY_LOCAL_MACHINE,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
_save_at_exit(hkey_current_user,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER );
_save_at_exit(hkey_local_machine,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
_save_at_exit(hkey_users_default,"/" SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
}
......@@ -1503,7 +1504,8 @@ static void _convert_and_load_native_registry(LPCWSTR fn, HKEY hkey, int reg_typ
}
/* load all native windows registry files [Internal] */
static void _load_windows_registry( HKEY hkey_users_default )
static void _load_windows_registry( HKEY hkey_local_machine, HKEY hkey_current_user,
HKEY hkey_users_default )
{
int reg_type;
WCHAR windir[MAX_PATHNAME_LEN];
......@@ -1515,7 +1517,6 @@ static void _load_windows_registry( HKEY hkey_users_default )
static const WCHAR WineW[] = {'W','i','n','e',0};
static const WCHAR ProfileW[] = {'P','r','o','f','i','l','e',0};
static const WCHAR empty_strW[] = { 0 };
static const WCHAR Machine[] = {'M','a','c','h','i','n','e',0};
static const WCHAR System[] = {'M','a','c','h','i','n','e','\\','S','y','s','t','e','m',0};
static const WCHAR Software[] = {'M','a','c','h','i','n','e','\\','S','o','f','t','w','a','r','e',0};
static const WCHAR Clone[] = {'M','a','c','h','i','n','e','\\',
......@@ -1545,7 +1546,7 @@ static void _load_windows_registry( HKEY hkey_users_default )
/* user specific ntuser.dat */
if (PROFILE_GetWineIniString( WineW, ProfileW, empty_strW, path, MAX_PATHNAME_LEN )) {
strcatW(path, ntuser_datW);
_convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WINNT,1);
_convert_and_load_native_registry(path,hkey_current_user,REG_WINNT,1);
}
/* default user.dat */
......@@ -1576,18 +1577,13 @@ static void _load_windows_registry( HKEY hkey_users_default )
NtClose( hkey );
}
RtlInitUnicodeString( &nameW, Machine );
if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
{
strcpyW(path, windir);
strcatW(path, samW);
_convert_and_load_native_registry(path,hkey,REG_WINNT,0);
_convert_and_load_native_registry(path,hkey_local_machine,REG_WINNT,0);
strcpyW(path,windir);
strcatW(path, securityW);
_convert_and_load_native_registry(path,hkey,REG_WINNT,0);
NtClose( hkey );
}
_convert_and_load_native_registry(path,hkey_local_machine,REG_WINNT,0);
/* this key is generated when the nt-core booted successfully */
RtlInitUnicodeString( &nameW, Clone );
......@@ -1602,16 +1598,11 @@ static void _load_windows_registry( HKEY hkey_users_default )
static const WCHAR classes_datW[] = {'\\','c','l','a','s','s','e','s','.','d','a','t',0};
static const WCHAR user_datW[] = {'\\','u','s','e','r','.','d','a','t',0};
RtlInitUnicodeString( &nameW, Machine );
if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
{
_convert_and_load_native_registry(system_1stW,hkey,REG_WIN95,0);
_convert_and_load_native_registry(system_1stW,hkey_local_machine,REG_WIN95,0);
strcpyW(path, windir);
strcatW(path, system_datW);
_convert_and_load_native_registry(path,hkey,REG_WIN95,0);
NtClose( hkey );
}
_convert_and_load_native_registry(path,hkey_local_machine,REG_WIN95,0);
RtlInitUnicodeString( &nameW, ClassesRootW );
if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
......@@ -1625,7 +1616,7 @@ static void _load_windows_registry( HKEY hkey_users_default )
if (PROFILE_GetWineIniString(WineW, ProfileW, empty_strW, path, MAX_PATHNAME_LEN)) {
/* user specific user.dat */
strcatW(path, user_datW);
_convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WIN95,1);
_convert_and_load_native_registry(path,hkey_current_user,REG_WIN95,1);
/* default user.dat */
if (hkey_users_default) {
......@@ -1636,7 +1627,7 @@ static void _load_windows_registry( HKEY hkey_users_default )
} else {
strcpyW(path, windir);
strcatW(path, user_datW);
_convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WIN95,1);
_convert_and_load_native_registry(path,hkey_current_user,REG_WIN95,1);
}
break;
}
......@@ -1658,19 +1649,20 @@ static void _load_windows_registry( HKEY hkey_users_default )
}
/* load global registry files (stored in /etc/wine) [Internal] */
static void _load_global_registry(void)
static void _load_global_registry( HKEY hkey_local_machine, HKEY hkey_users )
{
TRACE("(void)\n");
/* Load the global HKU hive directly from sysconfdir */
load_wine_registry( HKEY_USERS, SAVE_GLOBAL_REGBRANCH_USER_DEFAULT );
load_wine_registry( hkey_users, SAVE_GLOBAL_REGBRANCH_USER_DEFAULT );
/* Load the global machine defaults directly from sysconfdir */
load_wine_registry( HKEY_LOCAL_MACHINE, SAVE_GLOBAL_REGBRANCH_LOCAL_MACHINE );
load_wine_registry( hkey_local_machine, SAVE_GLOBAL_REGBRANCH_LOCAL_MACHINE );
}
/* load home registry files (stored in ~/.wine) [Internal] */
static void _load_home_registry( HKEY hkey_users_default )
static void _load_home_registry( HKEY hkey_local_machine, HKEY hkey_current_user,
HKEY hkey_users_default )
{
LPCSTR confdir = wine_get_config_dir();
LPSTR tmp = _xmalloc(strlen(confdir)+20);
......@@ -1681,11 +1673,11 @@ static void _load_home_registry( HKEY hkey_users_default )
strcpy(tmp,confdir);
strcat(tmp,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER);
load_wine_registry(HKEY_CURRENT_USER,tmp);
load_wine_registry(hkey_current_user,tmp);
strcpy(tmp,confdir);
strcat(tmp,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
load_wine_registry(HKEY_LOCAL_MACHINE,tmp);
load_wine_registry(hkey_local_machine,tmp);
free(tmp);
}
......@@ -1693,11 +1685,13 @@ static void _load_home_registry( HKEY hkey_users_default )
/* load all registry (native and global and home) */
void SHELL_LoadRegistry( void )
{
HKEY hkey_users_default;
HKEY hkey_local_machine, hkey_users, hkey_users_default, hkey_current_user;
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
static const WCHAR DefaultW[] = {'U','s','e','r','\\','.','D','e','f','a','u','l','t',0};
static const WCHAR MachineW[] = {'M','a','c','h','i','n','e',0};
static const WCHAR UserW[] = {'U','s','e','r',0};
static const WCHAR DefaultW[] = {'.','D','e','f','a','u','l','t',0};
static const WCHAR RegistryW[] = {'R','e','g','i','s','t','r','y',0};
static const WCHAR load_win_reg_filesW[] = {'L','o','a','d','W','i','n','d','o','w','s','R','e','g','i','s','t','r','y','F','i','l','e','s',0};
static const WCHAR load_global_reg_filesW[] = {'L','o','a','d','G','l','o','b','a','l','R','e','g','i','s','t','r','y','F','i','l','e','s',0};
......@@ -1714,22 +1708,32 @@ void SHELL_LoadRegistry( void )
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &nameW, MachineW );
NtCreateKey( &hkey_local_machine, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL );
RtlInitUnicodeString( &nameW, UserW );
NtCreateKey( &hkey_users, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL );
attr.RootDirectory = hkey_users;
RtlInitUnicodeString( &nameW, DefaultW );
if (NtCreateKey( &hkey_users_default, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
{
ERR("Cannot create HKEY_USERS/.Default\n" );
ExitProcess(1);
}
RtlOpenCurrentUser( KEY_ALL_ACCESS, &hkey_current_user );
_set_registry_levels(0,0,0);
_allocate_default_keys();
if (PROFILE_GetWineIniBool(RegistryW, load_win_reg_filesW, 1))
_load_windows_registry( hkey_users_default );
_load_windows_registry( hkey_local_machine, hkey_current_user, hkey_users_default );
if (PROFILE_GetWineIniBool(RegistryW, load_global_reg_filesW, 1))
_load_global_registry();
_load_global_registry( hkey_local_machine, hkey_users );
_set_registry_levels(1,0,0);
if (PROFILE_GetWineIniBool(RegistryW, load_home_reg_filesW, 1))
_load_home_registry( hkey_users_default );
_init_registry_saving( hkey_users_default );
_load_home_registry( hkey_local_machine, hkey_current_user, hkey_users_default );
_init_registry_saving( hkey_local_machine, hkey_current_user, hkey_users_default );
NtClose(hkey_users_default);
NtClose(hkey_current_user);
NtClose(hkey_users);
NtClose(hkey_local_machine);
}
......@@ -570,12 +570,95 @@ void VxDCall( DWORD service, CONTEXT86 *context )
*/
#define HKEY_SPECIAL_ROOT_FIRST HKEY_CLASSES_ROOT
#define HKEY_SPECIAL_ROOT_LAST HKEY_DYN_DATA
#define NB_SPECIAL_ROOT_KEYS ((UINT)HKEY_SPECIAL_ROOT_LAST - (UINT)HKEY_SPECIAL_ROOT_FIRST + 1)
static HKEY special_root_keys[NB_SPECIAL_ROOT_KEYS];
static const WCHAR name_CLASSES_ROOT[] =
{'M','a','c','h','i','n','e','\\',
'S','o','f','t','w','a','r','e','\\',
'C','l','a','s','s','e','s',0};
static const WCHAR name_LOCAL_MACHINE[] =
{'M','a','c','h','i','n','e',0};
static const WCHAR name_USERS[] =
{'U','s','e','r',0};
static const WCHAR name_PERFORMANCE_DATA[] =
{'P','e','r','f','D','a','t','a',0};
static const WCHAR name_CURRENT_CONFIG[] =
{'M','a','c','h','i','n','e','\\',
'S','y','s','t','e','m','\\',
'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
'H','a','r','d','w','a','r','e','P','r','o','f','i','l','e','s','\\',
'C','u','r','r','e','n','t',0};
static const WCHAR name_DYN_DATA[] =
{'D','y','n','D','a','t','a',0};
#define DECL_STR(key) { sizeof(name_##key)-sizeof(WCHAR), sizeof(name_##key), (LPWSTR)name_##key }
static UNICODE_STRING root_key_names[NB_SPECIAL_ROOT_KEYS] =
{
DECL_STR(CLASSES_ROOT),
{ 0, 0, NULL }, /* HKEY_CURRENT_USER is determined dynamically */
DECL_STR(LOCAL_MACHINE),
DECL_STR(USERS),
DECL_STR(PERFORMANCE_DATA),
DECL_STR(CURRENT_CONFIG),
DECL_STR(DYN_DATA)
};
#undef DECL_STR
/* check if value type needs string conversion (Ansi<->Unicode) */
inline static int is_string( DWORD type )
{
return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
}
/* create one of the HKEY_* special root keys */
static HKEY create_special_root_hkey( HKEY hkey, DWORD access )
{
HKEY ret = 0;
int idx = (UINT)hkey - (UINT)HKEY_SPECIAL_ROOT_FIRST;
if (hkey == HKEY_CURRENT_USER)
{
if (RtlOpenCurrentUser( access, &hkey )) return 0;
}
else
{
OBJECT_ATTRIBUTES attr;
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = &root_key_names[idx];
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
if (NtCreateKey( &hkey, access, &attr, 0, NULL, 0, NULL )) return 0;
}
if (!(ret = InterlockedCompareExchange( (PLONG)&special_root_keys[idx], hkey, 0 )))
ret = hkey;
else
NtClose( hkey ); /* somebody beat us to it */
return ret;
}
/* map the hkey from special root to normal key if necessary */
inline static HKEY get_special_root_hkey( HKEY hkey )
{
HKEY ret = hkey;
if ((hkey >= HKEY_SPECIAL_ROOT_FIRST) && (hkey <= HKEY_SPECIAL_ROOT_LAST))
{
if (!(ret = special_root_keys[(UINT)hkey - (UINT)HKEY_SPECIAL_ROOT_FIRST]))
ret = create_special_root_hkey( hkey, KEY_ALL_ACCESS );
}
return ret;
}
/******************************************************************************
* VMM_RegCreateKeyA
*/
......@@ -586,6 +669,8 @@ static DWORD VMM_RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
ANSI_STRING nameA;
NTSTATUS status;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
......@@ -614,6 +699,8 @@ DWORD WINAPI VMM_RegOpenKeyExA(HKEY hkey, LPCSTR name, DWORD reserved, REGSAM ac
STRING nameA;
NTSTATUS status;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
......@@ -649,7 +736,9 @@ static DWORD VMM_RegDeleteKeyA( HKEY hkey, LPCSTR name )
DWORD ret;
HKEY tmp;
if (!name || !*name) return NtDeleteKey( hkey );
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
if (!name || !*name) return RtlNtStatusToDosError( NtDeleteKey( hkey ) );
if (!(ret = VMM_RegOpenKeyExA( hkey, name, 0, 0, &tmp )))
{
ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
......@@ -670,6 +759,8 @@ static DWORD VMM_RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD t
WCHAR *dataW = NULL;
NTSTATUS status;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
if (is_string(type))
{
DWORD lenW;
......@@ -726,6 +817,8 @@ static DWORD VMM_RegDeleteValueA( HKEY hkey, LPCSTR name )
STRING nameA;
NTSTATUS status;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
RtlInitAnsiString( &nameA, name );
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{
......@@ -751,6 +844,7 @@ static DWORD VMM_RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPD
static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
RtlInitAnsiString( &nameA, name );
if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
......@@ -862,6 +956,7 @@ static DWORD VMM_RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val
/* NT only checks count, not val_count */
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
if (data) total_size += *count;
......@@ -957,6 +1052,8 @@ static DWORD VMM_RegEnumKeyA( HKEY hkey, DWORD index, LPSTR name, DWORD name_len
KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
DWORD total_size;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
status = NtEnumerateKey( hkey, index, KeyNodeInformation,
buffer, sizeof(buffer), &total_size );
......@@ -1003,6 +1100,8 @@ static DWORD VMM_RegQueryInfoKeyA( HKEY hkey, LPDWORD subkeys, LPDWORD max_subke
KEY_FULL_INFORMATION info;
DWORD total_size;
if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
status = NtQueryKey( hkey, KeyFullInformation, &info, sizeof(info), &total_size );
if (status && status != STATUS_BUFFER_OVERFLOW) return RtlNtStatusToDosError( status );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment