From d01deff9cf6ad791b3335c4925a3ba3db8b916f9 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 19 Jan 2016 15:03:37 +0900 Subject: [PATCH] server: Pass full object attributes in the create_key request. Signed-off-by: Alexandre Julliard --- dlls/ntdll/reg.c | 11 ++++++---- include/wine/server_protocol.h | 8 +++----- server/protocol.def | 5 +---- server/registry.c | 37 +++++++++++++++++----------------- server/request.h | 9 +++------ server/trace.c | 7 ++----- 6 files changed, 35 insertions(+), 42 deletions(-) diff --git a/dlls/ntdll/reg.c b/dlls/ntdll/reg.c index be95a2a2f62..ed9d15523d1 100644 --- a/dlls/ntdll/reg.c +++ b/dlls/ntdll/reg.c @@ -56,6 +56,8 @@ NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_AT PULONG dispos ) { NTSTATUS ret; + data_size_t len; + struct object_attributes *objattr; if (!retkey || !attr) return STATUS_ACCESS_VIOLATION; if (attr->Length > sizeof(OBJECT_ATTRIBUTES)) return STATUS_INVALID_PARAMETER; @@ -64,14 +66,13 @@ NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_AT TRACE( "(%p,%s,%s,%x,%x,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName), debugstr_us(class), options, access, retkey ); + if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; + SERVER_START_REQ( create_key ) { - req->parent = wine_server_obj_handle( attr->RootDirectory ); req->access = access; - req->attributes = attr->Attributes; req->options = options; - req->namelen = attr->ObjectName->Length; - wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length ); + wine_server_add_data( req, objattr, len ); if (class) wine_server_add_data( req, class->Buffer, class->Length ); if (!(ret = wine_server_call( req ))) { @@ -80,7 +81,9 @@ NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_AT } } SERVER_END_REQ; + TRACE("<- %p\n", *retkey); + RtlFreeHeap( GetProcessHeap(), 0, objattr ); return ret; } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 19ea2fcb13d..caa2dc9fafd 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2393,13 +2393,11 @@ struct write_process_memory_reply struct create_key_request { struct request_header __header; - obj_handle_t parent; unsigned int access; - unsigned int attributes; unsigned int options; - data_size_t namelen; - /* VARARG(name,unicode_str,namelen); */ + /* VARARG(objattr,object_attributes); */ /* VARARG(class,unicode_str); */ + char __pad_20[4]; }; struct create_key_reply { @@ -6159,6 +6157,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 497 +#define SERVER_PROTOCOL_VERSION 498 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index 390651d6207..a391c88d1d7 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1820,12 +1820,9 @@ enum char_info_mode /* Create a registry key */ @REQ(create_key) - obj_handle_t parent; /* handle to the parent key */ unsigned int access; /* desired access rights */ - unsigned int attributes; /* object attributes */ unsigned int options; /* creation options */ - data_size_t namelen; /* length of key name in bytes */ - VARARG(name,unicode_str,namelen); /* key name */ + VARARG(objattr,object_attributes); /* object attributes */ VARARG(class,unicode_str); /* class name */ @REPLY obj_handle_t hkey; /* handle to the created key */ diff --git a/server/registry.c b/server/registry.c index a3c139016c8..adf2892f4a7 100644 --- a/server/registry.c +++ b/server/registry.c @@ -759,7 +759,8 @@ static struct key *open_key( struct key *key, const struct unicode_str *name, un /* create a subkey */ static struct key *create_key( struct key *key, const struct unicode_str *name, const struct unicode_str *class, unsigned int options, - unsigned int access, unsigned int attributes, int *created ) + unsigned int access, unsigned int attributes, + const struct security_descriptor *sd, int *created ) { int index; struct unicode_str token, next; @@ -807,6 +808,9 @@ static struct key *create_key( struct key *key, const struct unicode_str *name, if (options & REG_OPTION_VOLATILE) key->flags |= KEY_VOLATILE; else key->flags |= KEY_DIRTY; + if (sd) default_set_sd( &key->obj, sd, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION ); + if (debug_level > 1) dump_operation( key, NULL, "Create" ); if (class && class->len) { @@ -2021,33 +2025,30 @@ DECL_HANDLER(create_key) struct key *key = NULL, *parent; struct unicode_str name, class; unsigned int access = req->access; + const struct security_descriptor *sd; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &name ); + + if (!objattr) return; if (!is_wow64_thread( current )) access = (access & ~KEY_WOW64_32KEY) | KEY_WOW64_64KEY; - reply->hkey = 0; + class.str = get_req_data_after_objattr( objattr, &class.len ); + class.len = (class.len / sizeof(WCHAR)) * sizeof(WCHAR); - if (req->namelen > get_req_data_size()) + if (!objattr->rootdir && name.len >= sizeof(root_name) && + !memicmpW( name.str, root_name, sizeof(root_name)/sizeof(WCHAR) )) { - set_error( STATUS_INVALID_PARAMETER ); - return; + name.str += sizeof(root_name)/sizeof(WCHAR); + name.len -= sizeof(root_name); } - class.str = (const WCHAR *)get_req_data() + req->namelen / sizeof(WCHAR); - class.len = ((get_req_data_size() - req->namelen) / sizeof(WCHAR)) * sizeof(WCHAR); - get_req_path( &name, !req->parent ); - if (name.str > class.str) - { - set_error( STATUS_INVALID_PARAMETER ); - return; - } - name.len = (class.str - name.str) * sizeof(WCHAR); /* 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( objattr->rootdir ))) { if ((key = create_key( parent, &name, &class, req->options, access, - req->attributes, &reply->created ))) + objattr->attributes, sd, &reply->created ))) { - reply->hkey = alloc_handle( current->process, key, access, req->attributes ); + reply->hkey = alloc_handle( current->process, key, access, objattr->attributes ); release_object( key ); } release_object( parent ); @@ -2194,7 +2195,7 @@ DECL_HANDLER(load_registry) { int dummy; get_req_path( &name, !req->hkey ); - if ((key = create_key( parent, &name, NULL, 0, KEY_WOW64_64KEY, 0, &dummy ))) + if ((key = create_key( parent, &name, NULL, 0, KEY_WOW64_64KEY, 0, NULL, &dummy ))) { load_registry( key, req->file ); release_object( key ); diff --git a/server/request.h b/server/request.h index caaa30ed1a2..87cae7350c0 100644 --- a/server/request.h +++ b/server/request.h @@ -1287,12 +1287,9 @@ C_ASSERT( sizeof(struct read_process_memory_reply) == 8 ); C_ASSERT( FIELD_OFFSET(struct write_process_memory_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct write_process_memory_request, addr) == 16 ); C_ASSERT( sizeof(struct write_process_memory_request) == 24 ); -C_ASSERT( FIELD_OFFSET(struct create_key_request, parent) == 12 ); -C_ASSERT( FIELD_OFFSET(struct create_key_request, access) == 16 ); -C_ASSERT( FIELD_OFFSET(struct create_key_request, attributes) == 20 ); -C_ASSERT( FIELD_OFFSET(struct create_key_request, options) == 24 ); -C_ASSERT( FIELD_OFFSET(struct create_key_request, namelen) == 28 ); -C_ASSERT( sizeof(struct create_key_request) == 32 ); +C_ASSERT( FIELD_OFFSET(struct create_key_request, access) == 12 ); +C_ASSERT( FIELD_OFFSET(struct create_key_request, options) == 16 ); +C_ASSERT( sizeof(struct create_key_request) == 24 ); C_ASSERT( FIELD_OFFSET(struct create_key_reply, hkey) == 8 ); C_ASSERT( FIELD_OFFSET(struct create_key_reply, created) == 12 ); C_ASSERT( sizeof(struct create_key_reply) == 16 ); diff --git a/server/trace.c b/server/trace.c index edbc8c9fac6..89ecdfb5ba9 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2308,12 +2308,9 @@ static void dump_write_process_memory_request( const struct write_process_memory static void dump_create_key_request( const struct create_key_request *req ) { - fprintf( stderr, " parent=%04x", req->parent ); - fprintf( stderr, ", access=%08x", req->access ); - fprintf( stderr, ", attributes=%08x", req->attributes ); + fprintf( stderr, " access=%08x", req->access ); fprintf( stderr, ", options=%08x", req->options ); - fprintf( stderr, ", namelen=%u", req->namelen ); - dump_varargs_unicode_str( ", name=", min(cur_size,req->namelen) ); + dump_varargs_object_attributes( ", objattr=", cur_size ); dump_varargs_unicode_str( ", class=", cur_size ); }