From 45e6befeba8145914fac0e1e9690026145e9ac25 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 17 Aug 2015 01:11:47 +0200
Subject: [PATCH] server: Store a reference to the parent object for pipe
 servers. (v2)

---
 dlls/ntdll/tests/om.c |  3 ---
 server/named_pipe.c   | 44 ++++++++++++++++++++++++++++++++++++--------
 server/object.c       | 22 ++++++++++++++--------
 server/object.h       |  2 ++
 4 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c
index be137b8..1c65464 100644
--- a/dlls/ntdll/tests/om.c
+++ b/dlls/ntdll/tests/om.c
@@ -1503,14 +1503,11 @@ static void test_query_object(void)
     status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
     ok( status == STATUS_SUCCESS , "NtQueryObject returned %x\n", status );
     str = (UNICODE_STRING *)buffer;
-    todo_wine
     ok( len > sizeof(UNICODE_STRING), "unexpected len %u\n", len );
     str = (UNICODE_STRING *)buffer;
     expected_len = sizeof(UNICODE_STRING) + str->Length + sizeof(WCHAR);
-    todo_wine
     ok( len == expected_len || broken(len == expected_len - sizeof(WCHAR)), /* NT4 */
         "unexpected len %u\n", len );
-    todo_wine
     ok( len > sizeof(UNICODE_STRING) + sizeof("\\test_pipe") * sizeof(WCHAR),
         "name too short %s\n", wine_dbgstr_w(str->Buffer) );
     trace( "got %s len %u\n", wine_dbgstr_w(str->Buffer), len );
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 141a052..62b6905 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -159,6 +159,8 @@ static struct security_descriptor *pipe_server_get_sd( struct object *obj );
 static int pipe_server_set_sd( struct object *obj, const struct security_descriptor *sd,
                                unsigned int set_info );
 static void pipe_server_destroy( struct object *obj);
+static int pipe_server_link_name( struct object *obj, struct object_name *name, struct object *parent );
+static void pipe_server_unlink_name( struct object *obj, struct object_name *name );
 static int pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
 static void pipe_server_get_file_info( struct fd *fd, unsigned int info_class );
 
@@ -177,8 +179,8 @@ static const struct object_ops pipe_server_ops =
     pipe_server_get_sd,           /* get_sd */
     pipe_server_set_sd,           /* set_sd */
     no_lookup_name,               /* lookup_name */
-    no_link_name,                 /* link_name */
-    NULL,                         /* unlink_name */
+    pipe_server_link_name,        /* link_name */
+    pipe_server_unlink_name,      /* unlink_name */
     no_open_file,                 /* open_file */
     no_alloc_handle,              /* alloc_handle */
     fd_close_handle,              /* close_handle */
@@ -205,6 +207,8 @@ static void pipe_client_dump( struct object *obj, int verbose );
 static struct security_descriptor *pipe_client_get_sd( struct object *obj );
 static int pipe_client_set_sd( struct object *obj, const struct security_descriptor *sd,
                                unsigned int set_info );
+static int pipe_client_link_name( struct object *obj, struct object_name *name, struct object *parent );
+static void pipe_client_unlink_name( struct object *obj, struct object_name *name );
 static void pipe_client_destroy( struct object *obj );
 static int pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
 static void pipe_client_get_file_info( struct fd *fd, unsigned int info_class );
@@ -224,8 +228,8 @@ static const struct object_ops pipe_client_ops =
     pipe_client_get_sd,           /* get_sd */
     pipe_client_set_sd,           /* set_sd */
     no_lookup_name,               /* lookup_name */
-    no_link_name,                 /* link_name */
-    NULL,                         /* unlink_name */
+    pipe_client_link_name,        /* link_name */
+    pipe_client_unlink_name,      /* unlink_name */
     no_open_file,                 /* open_file */
     no_alloc_handle,              /* alloc_handle */
     fd_close_handle,              /* close_handle */
@@ -422,6 +426,17 @@ static void pipe_end_destroy( struct pipe_end *pipe_end )
     if (pipe_end->fd) release_object( pipe_end->fd );
 }
 
+static int pipe_server_link_name( struct object *obj, struct object_name *name, struct object *parent )
+{
+    assert( parent->ops == &named_pipe_ops );
+    name->parent = grab_object( parent );
+    return 1;
+}
+
+static void pipe_server_unlink_name( struct object *obj, struct object_name *name )
+{
+}
+
 static void pipe_server_destroy( struct object *obj)
 {
     struct pipe_server *server = (struct pipe_server *)obj;
@@ -444,6 +459,17 @@ static void pipe_server_destroy( struct object *obj)
     release_object( server->pipe );
 }
 
+static int pipe_client_link_name( struct object *obj, struct object_name *name, struct object *parent )
+{
+    assert( parent->ops == &named_pipe_ops );
+    name->parent = grab_object( parent );
+    return 1;
+}
+
+static void pipe_client_unlink_name( struct object *obj, struct object_name *name )
+{
+}
+
 static void pipe_client_destroy( struct object *obj)
 {
     struct pipe_client *client = (struct pipe_client *)obj;
@@ -1109,9 +1135,10 @@ static void init_pipe_end( struct pipe_end *pipe_end, unsigned int pipe_flags, d
 static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned int options,
                                                unsigned int pipe_flags )
 {
+    static const struct unicode_str str = { NULL, 0 };
     struct pipe_server *server;
 
-    server = alloc_object( &pipe_server_ops );
+    server = create_object( &pipe->obj, &pipe_server_ops, &str, NULL );
     if (!server)
         return NULL;
 
@@ -1135,12 +1162,13 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned
     return server;
 }
 
-static struct pipe_client *create_pipe_client( unsigned int flags, unsigned int pipe_flags,
+static struct pipe_client *create_pipe_client( struct named_pipe *pipe, unsigned int flags, unsigned int pipe_flags,
                                                data_size_t buffer_size, unsigned int options )
 {
+    static const struct unicode_str str = { NULL, 0 };
     struct pipe_client *client;
 
-    client = alloc_object( &pipe_client_ops );
+    client = create_object( &pipe->obj, &pipe_client_ops, &str, NULL );
     if (!client)
         return NULL;
 
@@ -1220,7 +1248,7 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc
         return NULL;
     }
 
-    if ((client = create_pipe_client( options, pipe->flags, pipe->outsize, options )))
+    if ((client = create_pipe_client( pipe, options, pipe->flags, pipe->outsize, options )))
     {
         if (server->state == ps_wait_open)
             fd_async_wake_up( server->pipe_end.fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );
diff --git a/server/object.c b/server/object.c
index d0750c5..f40aebe 100644
--- a/server/object.c
+++ b/server/object.c
@@ -176,7 +176,7 @@ WCHAR *get_object_full_name( struct object *obj, data_size_t *ret_len )
     while (ptr && ptr->name)
     {
         struct object_name *name = ptr->name;
-        len += name->len + sizeof(WCHAR);
+        if (name->len) len += name->len + sizeof(WCHAR);
         ptr = name->parent;
     }
     if (!len) return NULL;
@@ -186,9 +186,12 @@ WCHAR *get_object_full_name( struct object *obj, data_size_t *ret_len )
     while (obj && obj->name)
     {
         struct object_name *name = obj->name;
-        memcpy( ret + len - name->len, name->name, name->len );
-        len -= name->len + sizeof(WCHAR);
-        memcpy( ret + len, &backslash, sizeof(WCHAR) );
+        if (name->len)
+        {
+            memcpy( ret + len - name->len, name->name, name->len );
+            len -= name->len + sizeof(WCHAR);
+            memcpy( ret + len, &backslash, sizeof(WCHAR) );
+        }
         obj = name->parent;
     }
     return (WCHAR *)ret;
@@ -276,8 +279,8 @@ struct object *lookup_named_object( struct object *root, const struct unicode_st
     return parent;
 }
 
-static struct object *create_object( struct object *parent, const struct object_ops *ops,
-                                     const struct unicode_str *name, const struct security_descriptor *sd )
+void *create_object( struct object *parent, const struct object_ops *ops,
+                     const struct unicode_str *name, const struct security_descriptor *sd )
 {
     struct object *obj;
     struct object_name *name_ptr;
@@ -372,8 +375,11 @@ static void dump_name( struct object *obj )
 
     if (!name) return;
     if (name->parent) dump_name( name->parent );
-    fputs( "\\\\", stderr );
-    dump_strW( name->name, name->len / sizeof(WCHAR), stderr, "[]" );
+    if (name->len)
+    {
+        fputs( "\\\\", stderr );
+        dump_strW( name->name, name->len / sizeof(WCHAR), stderr, "[]" );
+    }
 }
 
 /* dump the name of an object to stderr */
diff --git a/server/object.h b/server/object.h
index 9ff123e..4a5d282 100644
--- a/server/object.h
+++ b/server/object.h
@@ -135,6 +135,8 @@ extern WCHAR *get_object_full_name( struct object *obj, data_size_t *ret_len );
 extern void dump_object_name( struct object *obj );
 extern struct object *lookup_named_object( struct object *root, const struct unicode_str *name,
                                            unsigned int attr, struct unicode_str *name_left );
+extern void *create_object( struct object *parent, const struct object_ops *ops,
+                            const struct unicode_str *name, const struct security_descriptor *sd );
 extern void *create_named_object( struct object *parent, const struct object_ops *ops,
                                   const struct unicode_str *name, unsigned int attributes,
                                   const struct security_descriptor *sd );
-- 
1.9.1

