Alexandre Julliard : server: Implement lookup_name() for registry keys.

Alexandre Julliard julliard at winehq.org
Thu Jul 7 17:03:25 CDT 2022


Module: wine
Branch: master
Commit: b79ff648ef6b18ac49c87571a3f78f731af78d25
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=b79ff648ef6b18ac49c87571a3f78f731af78d25

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jul  7 11:52:59 2022 +0200

server: Implement lookup_name() for registry keys.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 server/registry.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 86 insertions(+), 1 deletion(-)

diff --git a/server/registry.c b/server/registry.c
index 2c52ec85d29..f800bcd842c 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -164,6 +164,8 @@ static void key_dump( struct object *obj, int verbose );
 static unsigned int key_map_access( struct object *obj, unsigned int access );
 static struct security_descriptor *key_get_sd( struct object *obj );
 static WCHAR *key_get_full_name( struct object *obj, data_size_t *len );
+static struct object *key_lookup_name( struct object *obj, struct unicode_str *name,
+                                       unsigned int attr, struct object *root );
 static int key_link_name( struct object *obj, struct object_name *name, struct object *parent );
 static void key_unlink_name( struct object *obj, struct object_name *name );
 static int key_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
@@ -184,7 +186,7 @@ static const struct object_ops key_ops =
     key_get_sd,              /* get_sd */
     default_set_sd,          /* set_sd */
     key_get_full_name,       /* get_full_name */
-    no_lookup_name,          /* lookup_name */
+    key_lookup_name,         /* lookup_name */
     key_link_name,           /* link_name */
     key_unlink_name,         /* unlink_name */
     no_open_file,            /* open_file */
@@ -485,6 +487,89 @@ static WCHAR *key_get_full_name( struct object *obj, data_size_t *ret_len )
     return (WCHAR *)ret;
 }
 
+static struct object *key_lookup_name( struct object *obj, struct unicode_str *name,
+                                       unsigned int attr, struct object *root )
+{
+    struct key *found, *key = (struct key *)obj;
+    struct unicode_str tmp;
+    data_size_t next;
+    int index;
+
+    assert( obj->ops == &key_ops );
+
+    if (!name) return NULL;  /* open the key itself */
+
+    if (key->flags & KEY_DELETED)
+    {
+        set_error( STATUS_KEY_DELETED );
+        return NULL;
+    }
+
+    if (key->flags & KEY_SYMLINK)
+    {
+        struct unicode_str name_left;
+        struct key_value *value;
+
+        if (!name->len && (attr & OBJ_OPENLINK)) return NULL;
+
+        if (!(value = find_value( key, &symlink_str, &index )) ||
+            value->len < sizeof(WCHAR) || *(WCHAR *)value->data != '\\')
+        {
+            set_error( STATUS_OBJECT_NAME_NOT_FOUND );
+            return NULL;
+        }
+        tmp.str = value->data;
+        tmp.len = (value->len / sizeof(WCHAR)) * sizeof(WCHAR);
+        if ((obj = lookup_named_object( NULL, &tmp, OBJ_CASE_INSENSITIVE, &name_left )))
+        {
+            if (!name->len) *name = name_left;  /* symlink destination can be created if missing */
+            else if (name_left.len)  /* symlink must have been resolved completely */
+            {
+                release_object( obj );
+                obj = NULL;
+                set_error( STATUS_OBJECT_NAME_NOT_FOUND );
+            }
+        }
+        return obj;
+    }
+
+    if (!name->str) return NULL;
+
+    tmp.str = name->str;
+    tmp.len = get_path_element( name->str, name->len );
+
+    if (tmp.len > MAX_NAME_LEN * sizeof(WCHAR))
+    {
+        set_error( STATUS_INVALID_PARAMETER );
+        return 0;
+    }
+
+    /* skip trailing backslashes */
+    for (next = tmp.len; next < name->len; next += sizeof(WCHAR))
+        if (name->str[next / sizeof(WCHAR)] != '\\') break;
+
+    if (!(found = find_subkey( key, &tmp, &index )))
+    {
+        if (next < name->len)  /* path still has elements */
+            set_error( STATUS_OBJECT_NAME_NOT_FOUND );
+        else  /* only trailing backslashes */
+            name->len = tmp.len;
+        return NULL;
+    }
+
+    if (next < name->len)  /* move to the next element */
+    {
+        name->str += next / sizeof(WCHAR);
+        name->len -= next;
+    }
+    else
+    {
+        name->str = NULL;
+        name->len = 0;
+    }
+    return grab_object( found );
+}
+
 static int key_link_name( struct object *obj, struct object_name *name, struct object *parent )
 {
     struct key *key = (struct key *)obj;




More information about the wine-cvs mailing list