Commit b139b935 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Implement registry symlinks.

parent 2ec945d4
...@@ -638,22 +638,18 @@ static void test_symlinks(void) ...@@ -638,22 +638,18 @@ static void test_symlinks(void)
/* REG_SZ is not allowed */ /* REG_SZ is not allowed */
status = pNtSetValueKey( link, &symlink_str, 0, REG_SZ, target, target_len ); status = pNtSetValueKey( link, &symlink_str, 0, REG_SZ, target, target_len );
todo_wine
ok( status == STATUS_ACCESS_DENIED, "NtSetValueKey wrong status 0x%08x\n", status ); ok( status == STATUS_ACCESS_DENIED, "NtSetValueKey wrong status 0x%08x\n", status );
status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) ); status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) );
ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
/* other values are not allowed */ /* other values are not allowed */
status = pNtSetValueKey( link, &link_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) ); status = pNtSetValueKey( link, &link_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) );
todo_wine
ok( status == STATUS_ACCESS_DENIED, "NtSetValueKey wrong status 0x%08x\n", status ); ok( status == STATUS_ACCESS_DENIED, "NtSetValueKey wrong status 0x%08x\n", status );
/* try opening the target through the link */ /* try opening the target through the link */
attr.ObjectName = &link_str; attr.ObjectName = &link_str;
status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
todo_wine
ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status ); ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status );
if (!status) pNtClose( key );
attr.ObjectName = &target_str; attr.ObjectName = &target_str;
status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
...@@ -670,14 +666,10 @@ static void test_symlinks(void) ...@@ -670,14 +666,10 @@ static void test_symlinks(void)
len = sizeof(buffer); len = sizeof(buffer);
status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len ); status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len );
todo_wine
{
ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + sizeof(DWORD), "wrong len %u\n", len ); ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + sizeof(DWORD), "wrong len %u\n", len );
}
status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
todo_wine
ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status ); ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status );
/* REG_LINK can be created in non-link keys */ /* REG_LINK can be created in non-link keys */
...@@ -699,11 +691,8 @@ static void test_symlinks(void) ...@@ -699,11 +691,8 @@ static void test_symlinks(void)
len = sizeof(buffer); len = sizeof(buffer);
status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len ); status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len );
todo_wine
{
ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + sizeof(DWORD), "wrong len %u\n", len ); ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + sizeof(DWORD), "wrong len %u\n", len );
}
status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status ); ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status );
...@@ -719,24 +708,18 @@ static void test_symlinks(void) ...@@ -719,24 +708,18 @@ static void test_symlinks(void)
len = sizeof(buffer); len = sizeof(buffer);
status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
todo_wine
{
ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR), ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
"wrong len %u\n", len ); "wrong len %u\n", len );
}
pNtClose( key ); pNtClose( key );
status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
len = sizeof(buffer); len = sizeof(buffer);
status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
todo_wine
{
ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR), ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
"wrong len %u\n", len ); "wrong len %u\n", len );
}
pNtClose( key ); pNtClose( key );
/* reopen the link from itself */ /* reopen the link from itself */
...@@ -748,24 +731,18 @@ static void test_symlinks(void) ...@@ -748,24 +731,18 @@ static void test_symlinks(void)
ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
len = sizeof(buffer); len = sizeof(buffer);
status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
todo_wine
{
ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR), ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
"wrong len %u\n", len ); "wrong len %u\n", len );
}
pNtClose( key ); pNtClose( key );
status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
len = sizeof(buffer); len = sizeof(buffer);
status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
todo_wine
{
ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR), ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
"wrong len %u\n", len ); "wrong len %u\n", len );
}
pNtClose( key ); pNtClose( key );
if (0) /* crashes the Windows kernel in most versions */ if (0) /* crashes the Windows kernel in most versions */
...@@ -793,9 +770,7 @@ static void test_symlinks(void) ...@@ -793,9 +770,7 @@ static void test_symlinks(void)
attr.Attributes = 0; attr.Attributes = 0;
attr.ObjectName = &link_str; attr.ObjectName = &link_str;
status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
todo_wine
ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status ); ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status );
if (!status) pNtClose( key );
/* relative symlink, works only on win2k */ /* relative symlink, works only on win2k */
status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, targetW+1, sizeof(targetW)-2*sizeof(WCHAR) ); status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, targetW+1, sizeof(targetW)-2*sizeof(WCHAR) );
...@@ -804,12 +779,9 @@ static void test_symlinks(void) ...@@ -804,12 +779,9 @@ static void test_symlinks(void)
status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
ok( status == STATUS_SUCCESS || status == STATUS_OBJECT_NAME_NOT_FOUND, ok( status == STATUS_SUCCESS || status == STATUS_OBJECT_NAME_NOT_FOUND,
"NtOpenKey wrong status 0x%08x\n", status ); "NtOpenKey wrong status 0x%08x\n", status );
if (!status) pNtClose( key );
status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, 0 ); status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, 0 );
todo_wine
ok( status == STATUS_OBJECT_NAME_COLLISION, "NtCreateKey failed: 0x%08x\n", status ); ok( status == STATUS_OBJECT_NAME_COLLISION, "NtCreateKey failed: 0x%08x\n", status );
if (!status) pNtClose( key );
status = pNtDeleteKey( link ); status = pNtDeleteKey( link );
ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
...@@ -832,10 +804,8 @@ static void test_symlinks(void) ...@@ -832,10 +804,8 @@ static void test_symlinks(void)
ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
todo_wine
ok( status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_NAME_TOO_LONG, ok( status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_NAME_TOO_LONG,
"NtOpenKey failed: 0x%08x\n", status ); "NtOpenKey failed: 0x%08x\n", status );
if (!status) pNtClose( key );
attr.Attributes = OBJ_OPENLINK; attr.Attributes = OBJ_OPENLINK;
status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
......
...@@ -83,6 +83,7 @@ struct key ...@@ -83,6 +83,7 @@ struct key
#define KEY_VOLATILE 0x0001 /* key is volatile (not saved to disk) */ #define KEY_VOLATILE 0x0001 /* key is volatile (not saved to disk) */
#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 */
/* a key value */ /* a key value */
struct key_value struct key_value
...@@ -107,7 +108,12 @@ static const timeout_t ticks_1601_to_1970 = (timeout_t)86400 * (369 * 365 + 89) ...@@ -107,7 +108,12 @@ static const timeout_t ticks_1601_to_1970 = (timeout_t)86400 * (369 * 365 + 89)
static const timeout_t save_period = 30 * -TICKS_PER_SEC; /* delay between periodic saves */ static const timeout_t save_period = 30 * -TICKS_PER_SEC; /* delay between periodic saves */
static struct timeout_user *save_timeout_user; /* saving timer */ static struct timeout_user *save_timeout_user; /* saving timer */
static const WCHAR root_name[] = { '\\','R','e','g','i','s','t','r','y','\\' };
static const WCHAR symlink_value[] = {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e'};
static const struct unicode_str symlink_str = { symlink_value, sizeof(symlink_value) };
static void set_periodic_save_timer(void); static void set_periodic_save_timer(void);
static struct key_value *find_value( const struct key *key, const struct unicode_str *name, int *index );
/* information about where to save a registry branch */ /* information about where to save a registry branch */
struct save_branch_info struct save_branch_info
...@@ -351,8 +357,6 @@ static void key_destroy( struct object *obj ) ...@@ -351,8 +357,6 @@ static void key_destroy( struct object *obj )
/* get the request vararg as registry path */ /* get the request vararg as registry path */
static inline void get_req_path( struct unicode_str *str, int skip_root ) static inline void get_req_path( struct unicode_str *str, int skip_root )
{ {
static const WCHAR root_name[] = { '\\','R','e','g','i','s','t','r','y','\\' };
str->str = get_req_data(); str->str = get_req_data();
str->len = (get_req_data_size() / sizeof(WCHAR)) * sizeof(WCHAR); str->len = (get_req_data_size() / sizeof(WCHAR)) * sizeof(WCHAR);
...@@ -576,8 +580,38 @@ static struct key *find_subkey( const struct key *key, const struct unicode_str ...@@ -576,8 +580,38 @@ static struct key *find_subkey( const struct key *key, const struct unicode_str
return NULL; return NULL;
} }
/* follow a symlink and return the resolved key */
static struct key *follow_symlink( struct key *key, int iteration )
{
struct unicode_str path, token;
struct key_value *value;
int index;
if (iteration > 16) return NULL;
if (!(key->flags & KEY_SYMLINK)) return key;
if (!(value = find_value( key, &symlink_str, &index ))) return NULL;
path.str = value->data;
path.len = (value->len / sizeof(WCHAR)) * sizeof(WCHAR);
if (path.len <= sizeof(root_name)) return NULL;
if (memicmpW( path.str, root_name, sizeof(root_name)/sizeof(WCHAR) )) return NULL;
path.str += sizeof(root_name) / sizeof(WCHAR);
path.len -= sizeof(root_name);
key = root_key;
token.str = NULL;
if (!get_path_token( &path, &token )) return NULL;
while (token.len)
{
if (!(key = find_subkey( key, &token, &index ))) break;
if (!(key = follow_symlink( key, iteration + 1 ))) break;
get_path_token( &path, &token );
}
return key;
}
/* open a subkey */ /* open a subkey */
static struct key *open_key( struct key *key, const struct unicode_str *name ) static struct key *open_key( struct key *key, const struct unicode_str *name, unsigned int attributes )
{ {
int index; int index;
struct unicode_str token; struct unicode_str token;
...@@ -589,19 +623,31 @@ static struct key *open_key( struct key *key, const struct unicode_str *name ) ...@@ -589,19 +623,31 @@ static struct key *open_key( struct key *key, const struct unicode_str *name )
if (!(key = find_subkey( key, &token, &index ))) if (!(key = find_subkey( key, &token, &index )))
{ {
set_error( STATUS_OBJECT_NAME_NOT_FOUND ); set_error( STATUS_OBJECT_NAME_NOT_FOUND );
break; return NULL;
} }
get_path_token( name, &token ); get_path_token( name, &token );
if (!token.len) break;
if (!(key = follow_symlink( key, 0 )))
{
set_error( STATUS_OBJECT_NAME_NOT_FOUND );
return NULL;
}
} }
if (!(attributes & OBJ_OPENLINK) && !(key = follow_symlink( key, 0 )))
{
set_error( STATUS_OBJECT_NAME_NOT_FOUND );
return NULL;
}
if (debug_level > 1) dump_operation( key, NULL, "Open" ); if (debug_level > 1) dump_operation( key, NULL, "Open" );
if (key) grab_object( key ); grab_object( key );
return key; return key;
} }
/* create a subkey */ /* create a subkey */
static struct key *create_key( struct key *key, const struct unicode_str *name, static struct key *create_key( struct key *key, const struct unicode_str *name,
const struct unicode_str *class, int flags, timeout_t modif, int *created ) const struct unicode_str *class, int flags, unsigned int options,
unsigned int attributes, timeout_t modif, int *created )
{ {
struct key *base; struct key *base;
int index; int index;
...@@ -622,12 +668,35 @@ static struct key *create_key( struct key *key, const struct unicode_str *name, ...@@ -622,12 +668,35 @@ static struct key *create_key( struct key *key, const struct unicode_str *name,
if (!(subkey = find_subkey( key, &token, &index ))) break; if (!(subkey = find_subkey( key, &token, &index ))) break;
key = subkey; key = subkey;
get_path_token( name, &token ); get_path_token( name, &token );
if (!token.len) break;
if (!(subkey = follow_symlink( subkey, 0 )))
{
set_error( STATUS_OBJECT_NAME_NOT_FOUND );
return NULL;
}
} }
/* create the remaining part */ /* create the remaining part */
if (!token.len) goto done; if (!token.len)
if (!(flags & KEY_VOLATILE) && (key->flags & KEY_VOLATILE)) {
if (options & REG_OPTION_CREATE_LINK)
{
set_error( STATUS_OBJECT_NAME_COLLISION );
return NULL;
}
if (!(attributes & OBJ_OPENLINK) && !(key = follow_symlink( key, 0 )))
{
set_error( STATUS_OBJECT_NAME_NOT_FOUND );
return NULL;
}
goto done;
}
if (options & REG_OPTION_VOLATILE)
{
flags = (flags & ~KEY_DIRTY) | KEY_VOLATILE;
}
else if (key->flags & KEY_VOLATILE)
{ {
set_error( STATUS_CHILD_MUST_BE_VOLATILE ); set_error( STATUS_CHILD_MUST_BE_VOLATILE );
return NULL; return NULL;
...@@ -648,6 +717,8 @@ static struct key *create_key( struct key *key, const struct unicode_str *name, ...@@ -648,6 +717,8 @@ static struct key *create_key( struct key *key, const struct unicode_str *name,
return NULL; return NULL;
} }
} }
/* FIXME: no saving of symlinks yet */
if (options & REG_OPTION_CREATE_LINK) key->flags |= KEY_SYMLINK | KEY_VOLATILE;
done: done:
if (debug_level > 1) dump_operation( key, NULL, "Create" ); if (debug_level > 1) dump_operation( key, NULL, "Create" );
...@@ -879,6 +950,16 @@ static void set_value( struct key *key, const struct unicode_str *name, ...@@ -879,6 +950,16 @@ static void set_value( struct key *key, const struct unicode_str *name,
} }
} }
if (key->flags & KEY_SYMLINK)
{
if (type != REG_LINK || name->len != symlink_str.len ||
memicmpW( name->str, symlink_str.str, name->len / sizeof(WCHAR) ))
{
set_error( STATUS_ACCESS_DENIED );
return;
}
}
if (len && !(ptr = memdup( data, len ))) return; if (len && !(ptr = memdup( data, len ))) return;
if (!value) if (!value)
...@@ -1140,7 +1221,7 @@ static struct key *load_key( struct key *base, const char *buffer, int flags, ...@@ -1140,7 +1221,7 @@ static struct key *load_key( struct key *base, const char *buffer, int flags,
} }
name.str = p; name.str = p;
name.len = len - (p - info->tmp + 1) * sizeof(WCHAR); name.len = len - (p - info->tmp + 1) * sizeof(WCHAR);
return create_key( base, &name, NULL, flags, modif, &res ); return create_key( base, &name, NULL, flags, 0, 0, modif, &res );
} }
/* parse a comma-separated list of hex digits */ /* parse a comma-separated list of hex digits */
...@@ -1448,7 +1529,7 @@ void init_registry(void) ...@@ -1448,7 +1529,7 @@ void init_registry(void)
/* load system.reg into Registry\Machine */ /* load system.reg into Registry\Machine */
if (!(key = create_key( root_key, &HKLM_name, NULL, 0, current_time, &dummy ))) if (!(key = create_key( root_key, &HKLM_name, NULL, 0, 0, 0, current_time, &dummy )))
fatal_error( "could not create Machine registry key\n" ); fatal_error( "could not create Machine registry key\n" );
load_init_registry_from_file( "system.reg", key ); load_init_registry_from_file( "system.reg", key );
...@@ -1456,7 +1537,7 @@ void init_registry(void) ...@@ -1456,7 +1537,7 @@ void init_registry(void)
/* load userdef.reg into Registry\User\.Default */ /* load userdef.reg into Registry\User\.Default */
if (!(key = create_key( root_key, &HKU_name, NULL, 0, current_time, &dummy ))) if (!(key = create_key( root_key, &HKU_name, NULL, 0, 0, 0, current_time, &dummy )))
fatal_error( "could not create User\\.Default registry key\n" ); fatal_error( "could not create User\\.Default registry key\n" );
load_init_registry_from_file( "userdef.reg", key ); load_init_registry_from_file( "userdef.reg", key );
...@@ -1467,7 +1548,7 @@ void init_registry(void) ...@@ -1467,7 +1548,7 @@ void init_registry(void)
/* FIXME: match default user in token.c. should get from process token instead */ /* FIXME: match default user in token.c. should get from process token instead */
current_user_path = format_user_registry_path( security_interactive_sid, &current_user_str ); current_user_path = format_user_registry_path( security_interactive_sid, &current_user_str );
if (!current_user_path || if (!current_user_path ||
!(key = create_key( root_key, &current_user_str, NULL, 0, current_time, &dummy ))) !(key = create_key( root_key, &current_user_str, NULL, 0, 0, 0, current_time, &dummy )))
fatal_error( "could not create HKEY_CURRENT_USER registry key\n" ); fatal_error( "could not create HKEY_CURRENT_USER registry key\n" );
free( current_user_path ); free( current_user_path );
load_init_registry_from_file( "user.reg", key ); load_init_registry_from_file( "user.reg", key );
...@@ -1660,9 +1741,8 @@ DECL_HANDLER(create_key) ...@@ -1660,9 +1741,8 @@ DECL_HANDLER(create_key)
/* NOTE: no access rights are required from the parent handle to create a key */ /* NOTE: no access rights are required from the parent handle to create a key */
if ((parent = get_parent_hkey_obj( req->parent ))) if ((parent = get_parent_hkey_obj( req->parent )))
{ {
int flags = (req->options & REG_OPTION_VOLATILE) ? KEY_VOLATILE : KEY_DIRTY; if ((key = create_key( parent, &name, &class, KEY_DIRTY, req->options,
req->attributes, current_time, &reply->created )))
if ((key = create_key( parent, &name, &class, flags, current_time, &reply->created )))
{ {
reply->hkey = alloc_handle( current->process, key, access, req->attributes ); reply->hkey = alloc_handle( current->process, key, access, req->attributes );
release_object( key ); release_object( key );
...@@ -1683,7 +1763,7 @@ DECL_HANDLER(open_key) ...@@ -1683,7 +1763,7 @@ DECL_HANDLER(open_key)
if ((parent = get_parent_hkey_obj( req->parent ))) if ((parent = get_parent_hkey_obj( req->parent )))
{ {
get_req_path( &name, !req->parent ); get_req_path( &name, !req->parent );
if ((key = open_key( parent, &name ))) if ((key = open_key( parent, &name, req->attributes )))
{ {
reply->hkey = alloc_handle( current->process, key, access, req->attributes ); reply->hkey = alloc_handle( current->process, key, access, req->attributes );
release_object( key ); release_object( key );
...@@ -1817,7 +1897,7 @@ DECL_HANDLER(load_registry) ...@@ -1817,7 +1897,7 @@ DECL_HANDLER(load_registry)
{ {
int dummy; int dummy;
get_req_path( &name, !req->hkey ); get_req_path( &name, !req->hkey );
if ((key = create_key( parent, &name, NULL, KEY_DIRTY, current_time, &dummy ))) if ((key = create_key( parent, &name, NULL, KEY_DIRTY, 0, 0, current_time, &dummy )))
{ {
load_registry( key, req->file ); load_registry( key, req->file );
release_object( key ); release_object( key );
......
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