- removed copying of HKEY_USERS to HKEY_CURRENT_USER
- HKEY_CURRENT_USER is now subkey of HKEY_USERS - changed query_key_info_request to return the key name too (NtQueryKey needs this) - the rootkeys (MACHINE and USER) do have names
This commit is contained in:
parent
d1795f674c
commit
5d0ae2dcd9
|
@ -895,6 +895,7 @@ struct query_key_info_request
|
|||
OUT int max_value; /* longest value name */
|
||||
OUT int max_data; /* longest value data */
|
||||
OUT time_t modif; /* last modification time */
|
||||
OUT path_t name; /* key name */
|
||||
OUT WCHAR class[1]; /* class name */
|
||||
};
|
||||
|
||||
|
|
107
misc/registry.c
107
misc/registry.c
|
@ -659,78 +659,7 @@ static void _wine_loadreg( HKEY hkey, char *fn )
|
|||
fclose(F);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* _flush_registry [Internal]
|
||||
*
|
||||
* This function allow to flush section of the internal registry. It is mainly
|
||||
* implements to fix a problem with the global HKU and the local HKU.
|
||||
* Those two files are read to build the HKU\.Default branch to finaly copy
|
||||
* this branch onto HKCU hive, once this is done, if we keep the HKU hive as is,
|
||||
* all the global HKU are saved onto the user's personal version of HKU hive.
|
||||
* which is bad...
|
||||
*/
|
||||
|
||||
static void _flush_registry( HKEY hkey )
|
||||
{
|
||||
WCHAR name[MAX_PATH];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
HKEY subkey;
|
||||
/* FIXME: we assume that deleting a key will move the other ones up, */
|
||||
/* so that we can always use index 0 until there are no more keys */
|
||||
if (RegEnumKeyW( hkey, 0, name, sizeof(name) ) != ERROR_SUCCESS) break;
|
||||
if (RegOpenKeyW( hkey, name, &subkey ) != ERROR_SUCCESS) break;
|
||||
_flush_registry( subkey );
|
||||
if (RegDeleteKeyW( subkey, NULL ) != ERROR_SUCCESS) break;
|
||||
RegCloseKey( subkey );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* _copy_registry [Internal]
|
||||
*/
|
||||
static void _copy_registry( HKEY from, HKEY to )
|
||||
{
|
||||
int index;
|
||||
HKEY subkey;
|
||||
FILETIME ft;
|
||||
DWORD type, name_len, len;
|
||||
static WCHAR name[MAX_PATH];
|
||||
static BYTE data[2048];
|
||||
|
||||
/* copy values */
|
||||
index = 0;
|
||||
for (;;)
|
||||
{
|
||||
len = sizeof(data);
|
||||
name_len = sizeof(name);
|
||||
if (RegEnumValueW( from, index++, name, &name_len,
|
||||
NULL, &type, data, &len ) != ERROR_SUCCESS) break;
|
||||
RegSetValueExW( to, name, 0, type, data, len );
|
||||
}
|
||||
|
||||
/* copy subkeys */
|
||||
index = 0;
|
||||
for (;;)
|
||||
{
|
||||
name_len = sizeof(name);
|
||||
if (RegEnumKeyExW( from, index++, name, &name_len,
|
||||
NULL, NULL, 0, &ft ) != ERROR_SUCCESS)
|
||||
break;
|
||||
if (RegOpenKeyW( from, name, &subkey ) == ERROR_SUCCESS)
|
||||
{
|
||||
HKEY newsub;
|
||||
if (RegCreateKeyW( to, name, &newsub ) == ERROR_SUCCESS)
|
||||
{
|
||||
_copy_registry( subkey, newsub );
|
||||
RegCloseKey( newsub );
|
||||
}
|
||||
RegCloseKey( subkey );
|
||||
}
|
||||
}
|
||||
}
|
||||
/* NT REGISTRY LOADER */
|
||||
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
|
@ -1762,42 +1691,8 @@ void SHELL_LoadRegistry( void )
|
|||
_wine_loadreg( HKEY_LOCAL_MACHINE, fn );
|
||||
}
|
||||
free (fn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the handle of the HKU\.Default key.
|
||||
* in order to copy HKU\.Default\* onto HKEY_CURRENT_USER
|
||||
*/
|
||||
if (RegCreateKeyA(HKEY_USERS,".Default",&hkey) != ERROR_SUCCESS)
|
||||
WARN("Could not create global user default key\n");
|
||||
else
|
||||
_copy_registry( hkey, HKEY_CURRENT_USER );
|
||||
RegCloseKey(hkey);
|
||||
|
||||
/*
|
||||
* Since HKU is built from the global HKU and the local user HKU file we must
|
||||
* flush the HKU tree we have built at this point otherwise the part brought
|
||||
* in from the global HKU is saved into the local HKU. To avoid this
|
||||
* useless dupplication of HKU keys we reread the local HKU key.
|
||||
*/
|
||||
|
||||
/* Allways flush the HKU hive and reload it only with user's personal HKU */
|
||||
_flush_registry( HKEY_USERS );
|
||||
|
||||
/* Reload user's local HKU hive */
|
||||
if (home && PROFILE_GetWineIniBool ("registry","LoadHomeRegistryFiles",1))
|
||||
{
|
||||
fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX)
|
||||
+ strlen(SAVE_LOCAL_USERS_DEFAULT) + 2);
|
||||
|
||||
strcpy(fn,home);
|
||||
strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
|
||||
|
||||
_wine_loadreg( HKEY_USERS, fn );
|
||||
|
||||
free(fn);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Make sure the update mode is there
|
||||
*/
|
||||
|
|
|
@ -138,16 +138,15 @@ static inline char to_hex( char ch )
|
|||
}
|
||||
|
||||
/* dump the full path of a key */
|
||||
static void dump_path( struct key *key, FILE *f )
|
||||
static void dump_path( struct key *key, struct key *base, FILE *f )
|
||||
{
|
||||
if (key->parent) dump_path( key->parent, f );
|
||||
else if (key->name) fprintf( f, "?????" );
|
||||
|
||||
if (key->name)
|
||||
if (key->parent && key != base)
|
||||
{
|
||||
dump_path( key->parent, base, f );
|
||||
fprintf( f, "\\\\" );
|
||||
dump_strW( key->name, strlenW(key->name), f, "[]" );
|
||||
}
|
||||
|
||||
if (key->name) dump_strW( key->name, strlenW(key->name), f, "[]" );
|
||||
else /* root key */
|
||||
{
|
||||
int i;
|
||||
|
@ -210,7 +209,7 @@ static void dump_value( struct key_value *value, FILE *f )
|
|||
}
|
||||
|
||||
/* save a registry and all its subkeys to a text file */
|
||||
static void save_subkeys( struct key *key, FILE *f )
|
||||
static void save_subkeys( struct key *key, struct key *base, FILE *f )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -220,17 +219,17 @@ static void save_subkeys( struct key *key, FILE *f )
|
|||
if ((key->level >= saving_level) && ((key->last_value >= 0) || (key->last_subkey == -1)))
|
||||
{
|
||||
fprintf( f, "\n[" );
|
||||
dump_path( key, f );
|
||||
dump_path( key, base, f );
|
||||
fprintf( f, "] %ld\n", key->modif );
|
||||
for (i = 0; i <= key->last_value; i++) dump_value( &key->values[i], f );
|
||||
}
|
||||
for (i = 0; i <= key->last_subkey; i++) save_subkeys( key->subkeys[i], f );
|
||||
for (i = 0; i <= key->last_subkey; i++) save_subkeys( key->subkeys[i], base, f );
|
||||
}
|
||||
|
||||
static void dump_operation( struct key *key, struct key_value *value, const char *op )
|
||||
{
|
||||
fprintf( stderr, "%s key ", op );
|
||||
if (key) dump_path( key, stderr );
|
||||
if (key) dump_path( key, NULL, stderr );
|
||||
else fprintf( stderr, "ERROR" );
|
||||
if (value)
|
||||
{
|
||||
|
@ -245,7 +244,7 @@ static void key_dump( struct object *obj, int verbose )
|
|||
struct key *key = (struct key *)obj;
|
||||
assert( obj->ops == &key_ops );
|
||||
fprintf( stderr, "Key flags=%x ", key->flags );
|
||||
dump_path( key, stderr );
|
||||
dump_path( key, NULL, stderr );
|
||||
fprintf( stderr, "\n" );
|
||||
}
|
||||
|
||||
|
@ -575,6 +574,7 @@ static void query_key( struct key *key, struct query_key_info_request *req )
|
|||
req->max_value = max_value;
|
||||
req->max_data = max_data;
|
||||
req->modif = key->modif;
|
||||
strcpyW( req->name, key->name);
|
||||
if (key->class) strcpyW( req->class, key->class ); /* FIXME: length */
|
||||
else req->class[0] = 0;
|
||||
if (debug_level > 1) dump_operation( key, NULL, "Query" );
|
||||
|
@ -807,6 +807,20 @@ static struct key *create_root_key( int hkey )
|
|||
|
||||
switch(hkey)
|
||||
{
|
||||
/* the two real root-keys */
|
||||
case HKEY_LOCAL_MACHINE:
|
||||
{
|
||||
static const WCHAR name[] = { 'M','A','C','H','I','N','E',0 };
|
||||
key = alloc_key( name, time(NULL) );
|
||||
}
|
||||
break;
|
||||
case HKEY_USERS:
|
||||
{
|
||||
static const WCHAR name[] = { 'U','S','E','R',0 };
|
||||
key = alloc_key( name, time(NULL) );
|
||||
}
|
||||
break;
|
||||
/* special subkeys */
|
||||
case HKEY_CLASSES_ROOT:
|
||||
{
|
||||
static const WCHAR name[] =
|
||||
|
@ -818,12 +832,32 @@ static struct key *create_root_key( int hkey )
|
|||
release_object( root );
|
||||
}
|
||||
break;
|
||||
case HKEY_CURRENT_USER: /* FIXME: should be HKEY_USERS\\the_current_user_SID */
|
||||
case HKEY_LOCAL_MACHINE:
|
||||
case HKEY_USERS:
|
||||
case HKEY_CURRENT_CONFIG:
|
||||
{
|
||||
static const WCHAR name[] = {
|
||||
'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};
|
||||
struct key *root = get_hkey_obj( HKEY_LOCAL_MACHINE, 0 );
|
||||
if (!root) return NULL;
|
||||
key = create_key( root, name, sizeof(name), NULL, 0, time(NULL), &dummy );
|
||||
release_object( root );
|
||||
}
|
||||
break;
|
||||
case HKEY_CURRENT_USER:
|
||||
{
|
||||
/* FIXME: should be HKEY_USERS\\the_current_user_SID */
|
||||
static const WCHAR name[] = { '.','D','e','f','a','u','l','t',0 };
|
||||
struct key *root = get_hkey_obj( HKEY_USERS, 0 );
|
||||
if (!root) return NULL;
|
||||
key = create_key( root, name, sizeof(name), NULL, 0, time(NULL), &dummy );
|
||||
release_object( root );
|
||||
}
|
||||
break;
|
||||
/* dynamically generated keys */
|
||||
case HKEY_PERFORMANCE_DATA:
|
||||
case HKEY_DYN_DATA:
|
||||
case HKEY_CURRENT_CONFIG:
|
||||
key = alloc_key( NULL, time(NULL) );
|
||||
break;
|
||||
default:
|
||||
|
@ -1297,7 +1331,7 @@ static void save_registry( struct key *key, int handle )
|
|||
if (f)
|
||||
{
|
||||
fprintf( f, "WINE REGISTRY Version %d\n", saving_version );
|
||||
if (saving_version == 2) save_subkeys( key, f );
|
||||
if (saving_version == 2) save_subkeys( key, key, f );
|
||||
else
|
||||
{
|
||||
update_level( key );
|
||||
|
|
|
@ -923,6 +923,9 @@ static void dump_query_key_info_reply( struct query_key_info_request *req )
|
|||
fprintf( stderr, " max_value=%d,", req->max_value );
|
||||
fprintf( stderr, " max_data=%d,", req->max_data );
|
||||
fprintf( stderr, " modif=%ld,", req->modif );
|
||||
fprintf( stderr, " name=" );
|
||||
dump_unicode_string( req->name );
|
||||
fprintf( stderr, "," );
|
||||
fprintf( stderr, " class=" );
|
||||
dump_unicode_string( req->class );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue