diff --git a/dlls/ntdll/reg.c b/dlls/ntdll/reg.c index ed9d15523d1..c0e213ab929 100644 --- a/dlls/ntdll/reg.c +++ b/dlls/ntdll/reg.c @@ -660,6 +660,8 @@ NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *fil NTSTATUS ret; HANDLE hive; IO_STATUS_BLOCK io; + data_size_t len; + struct object_attributes *objattr; TRACE("(%p,%p)\n", attr, file); @@ -667,17 +669,18 @@ NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *fil FILE_OPEN, 0, NULL, 0); if (ret) return ret; + if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; + SERVER_START_REQ( load_registry ) { - req->hkey = wine_server_obj_handle( attr->RootDirectory ); req->file = wine_server_obj_handle( hive ); - wine_server_add_data(req, attr->ObjectName->Buffer, attr->ObjectName->Length); + wine_server_add_data( req, objattr, len ); ret = wine_server_call( req ); } SERVER_END_REQ; NtClose(hive); - + RtlFreeHeap( GetProcessHeap(), 0, objattr ); return ret; } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index caa2dc9fafd..753f8e35b12 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2541,10 +2541,8 @@ struct delete_key_value_reply struct load_registry_request { struct request_header __header; - obj_handle_t hkey; obj_handle_t file; - /* VARARG(name,unicode_str); */ - char __pad_20[4]; + /* VARARG(objattr,object_attributes); */ }; struct load_registry_reply { @@ -6157,6 +6155,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 498 +#define SERVER_PROTOCOL_VERSION 499 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index a391c88d1d7..08c5bc16df0 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1916,9 +1916,8 @@ enum char_info_mode /* Load a registry branch from a file */ @REQ(load_registry) - obj_handle_t hkey; /* root key to load to */ obj_handle_t file; /* file to load from */ - VARARG(name,unicode_str); /* subkey name */ + VARARG(objattr,object_attributes); /* object attributes */ @END diff --git a/server/registry.c b/server/registry.c index adf2892f4a7..e1d66d31bb7 100644 --- a/server/registry.c +++ b/server/registry.c @@ -2184,6 +2184,8 @@ DECL_HANDLER(load_registry) { struct key *key, *parent; struct unicode_str name; + const struct security_descriptor *sd; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &name ); if (!thread_single_check_privilege( current, &SeRestorePrivilege )) { @@ -2191,11 +2193,17 @@ DECL_HANDLER(load_registry) return; } - if ((parent = get_parent_hkey_obj( req->hkey ))) + if (!objattr->rootdir && name.len >= sizeof(root_name) && + !memicmpW( name.str, root_name, sizeof(root_name)/sizeof(WCHAR) )) + { + name.str += sizeof(root_name)/sizeof(WCHAR); + name.len -= sizeof(root_name); + } + + if ((parent = get_parent_hkey_obj( objattr->rootdir ))) { int dummy; - get_req_path( &name, !req->hkey ); - if ((key = create_key( parent, &name, NULL, 0, KEY_WOW64_64KEY, 0, NULL, &dummy ))) + if ((key = create_key( parent, &name, NULL, 0, KEY_WOW64_64KEY, 0, sd, &dummy ))) { load_registry( key, req->file ); release_object( key ); diff --git a/server/request.h b/server/request.h index 87cae7350c0..d21a539ec62 100644 --- a/server/request.h +++ b/server/request.h @@ -1336,9 +1336,8 @@ C_ASSERT( FIELD_OFFSET(struct enum_key_value_reply, namelen) == 16 ); C_ASSERT( sizeof(struct enum_key_value_reply) == 24 ); C_ASSERT( FIELD_OFFSET(struct delete_key_value_request, hkey) == 12 ); C_ASSERT( sizeof(struct delete_key_value_request) == 16 ); -C_ASSERT( FIELD_OFFSET(struct load_registry_request, hkey) == 12 ); -C_ASSERT( FIELD_OFFSET(struct load_registry_request, file) == 16 ); -C_ASSERT( sizeof(struct load_registry_request) == 24 ); +C_ASSERT( FIELD_OFFSET(struct load_registry_request, file) == 12 ); +C_ASSERT( sizeof(struct load_registry_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct unload_registry_request, hkey) == 12 ); C_ASSERT( sizeof(struct unload_registry_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct save_registry_request, hkey) == 12 ); diff --git a/server/trace.c b/server/trace.c index 89ecdfb5ba9..84ed113dcd2 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2411,9 +2411,8 @@ static void dump_delete_key_value_request( const struct delete_key_value_request static void dump_load_registry_request( const struct load_registry_request *req ) { - fprintf( stderr, " hkey=%04x", req->hkey ); - fprintf( stderr, ", file=%04x", req->file ); - dump_varargs_unicode_str( ", name=", cur_size ); + fprintf( stderr, " file=%04x", req->file ); + dump_varargs_object_attributes( ", objattr=", cur_size ); } static void dump_unload_registry_request( const struct unload_registry_request *req )