server: Implement object name information for registry keys.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-09-22 16:57:04 +02:00
parent bdb2fe0cad
commit 96dcee6430
2 changed files with 31 additions and 22 deletions

View File

@ -1470,7 +1470,7 @@ static void test_query_object(void)
status = pNtCreateKey( &handle, KEY_READ, &attr, 0, 0, 0, 0 ); status = pNtCreateKey( &handle, KEY_READ, &attr, 0, 0, 0, 0 );
ok( status == STATUS_SUCCESS, "NtCreateKey failed status %x\n", status ); ok( status == STATUS_SUCCESS, "NtCreateKey failed status %x\n", status );
test_object_name( handle, L"\\REGISTRY\\MACHINE", TRUE ); test_object_name( handle, L"\\REGISTRY\\MACHINE", FALSE );
test_object_type( handle, L"Key" ); test_object_type( handle, L"Key" );
pNtClose( handle ); pNtClose( handle );

View File

@ -148,6 +148,7 @@ static void key_dump( struct object *obj, int verbose );
static struct object_type *key_get_type( struct object *obj ); static struct object_type *key_get_type( struct object *obj );
static unsigned int key_map_access( struct object *obj, unsigned int access ); static unsigned int key_map_access( struct object *obj, unsigned int access );
static struct security_descriptor *key_get_sd( struct object *obj ); static struct security_descriptor *key_get_sd( struct object *obj );
static WCHAR *key_get_full_name( struct object *obj, data_size_t *len );
static int key_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static int key_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
static void key_destroy( struct object *obj ); static void key_destroy( struct object *obj );
@ -165,7 +166,7 @@ static const struct object_ops key_ops =
key_map_access, /* map_access */ key_map_access, /* map_access */
key_get_sd, /* get_sd */ key_get_sd, /* get_sd */
default_set_sd, /* set_sd */ default_set_sd, /* set_sd */
no_get_full_name, /* get_full_name */ key_get_full_name, /* get_full_name */
no_lookup_name, /* lookup_name */ no_lookup_name, /* lookup_name */
no_link_name, /* link_name */ no_link_name, /* link_name */
NULL, /* unlink_name */ NULL, /* unlink_name */
@ -394,6 +395,29 @@ static struct security_descriptor *key_get_sd( struct object *obj )
return key_default_sd; return key_default_sd;
} }
static WCHAR *key_get_full_name( struct object *obj, data_size_t *ret_len )
{
static const WCHAR backslash = '\\';
struct key *key = (struct key *) obj;
data_size_t len = sizeof(root_name) - sizeof(WCHAR);
char *ret;
for (key = (struct key *)obj; key != root_key; key = key->parent) len += key->namelen + sizeof(WCHAR);
if (!(ret = malloc( len ))) return NULL;
*ret_len = len;
key = (struct key *)obj;
for (key = (struct key *)obj; key != root_key; key = key->parent)
{
memcpy( ret + len - key->namelen, key->name, key->namelen );
dump_strW( (WCHAR *)(ret + len - key->namelen), key->namelen, stderr, "" );
len -= key->namelen + sizeof(WCHAR);
memcpy( ret + len, &backslash, sizeof(WCHAR) );
}
memcpy( ret, root_name, sizeof(root_name) - sizeof(WCHAR) );
return (WCHAR *)ret;
}
/* close the notification associated with a handle */ /* close the notification associated with a handle */
static int key_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) static int key_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
{ {
@ -876,15 +900,13 @@ static struct key *create_key_recursive( struct key *key, const struct unicode_s
} }
/* query information about a key or a subkey */ /* query information about a key or a subkey */
static void enum_key( const struct key *key, int index, int info_class, static void enum_key( struct key *key, int index, int info_class, struct enum_key_reply *reply )
struct enum_key_reply *reply )
{ {
static const WCHAR backslash[] = { '\\' };
int i; int i;
data_size_t len, namelen, classlen; data_size_t len, namelen, classlen;
data_size_t max_subkey = 0, max_class = 0; data_size_t max_subkey = 0, max_class = 0;
data_size_t max_value = 0, max_data = 0; data_size_t max_value = 0, max_data = 0;
const struct key *k; WCHAR *fullname = NULL;
char *data; char *data;
if (index != -1) /* -1 means use the specified key directly */ if (index != -1) /* -1 means use the specified key directly */
@ -903,11 +925,7 @@ static void enum_key( const struct key *key, int index, int info_class,
switch(info_class) switch(info_class)
{ {
case KeyNameInformation: case KeyNameInformation:
namelen = 0; if (!(fullname = key->obj.ops->get_full_name( &key->obj, &namelen ))) return;
for (k = key; k != root_key; k = k->parent)
namelen += k->namelen + sizeof(backslash);
if (!namelen) return;
namelen += sizeof(root_name) - sizeof(backslash);
/* fall through */ /* fall through */
case KeyBasicInformation: case KeyBasicInformation:
classlen = 0; /* only return the name */ classlen = 0; /* only return the name */
@ -959,18 +977,8 @@ static void enum_key( const struct key *key, int index, int info_class,
} }
else if (info_class == KeyNameInformation) else if (info_class == KeyNameInformation)
{ {
data_size_t pos = namelen;
reply->namelen = namelen; reply->namelen = namelen;
for (k = key; k != root_key; k = k->parent) memcpy( data, fullname, namelen );
{
pos -= k->namelen;
if (pos < len) memcpy( data + pos, k->name,
min( k->namelen, len - pos ) );
pos -= sizeof(backslash);
if (pos < len) memcpy( data + pos, backslash,
min( sizeof(backslash), len - pos ) );
}
memcpy( data, root_name, min( sizeof(root_name) - sizeof(backslash), len ) );
} }
else else
{ {
@ -978,6 +986,7 @@ static void enum_key( const struct key *key, int index, int info_class,
memcpy( data, key->name, len ); memcpy( data, key->name, len );
} }
} }
free( fullname );
if (debug_level > 1) dump_operation( key, NULL, "Enum" ); if (debug_level > 1) dump_operation( key, NULL, "Enum" );
} }