From ba40a0db8a7bd05b2e6e2763041875bcbc5af1b8 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 16 Aug 2018 15:10:33 +0200 Subject: [PATCH] server: Store named_pipe reference in pipe_end struct. Allows pipe clients to access named_pipe object after server is closed without disconnecting. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- server/named_pipe.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/server/named_pipe.c b/server/named_pipe.c index 768567ffcd1..ab71f36e82a 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -67,6 +67,7 @@ struct pipe_end struct fd *fd; /* pipe file descriptor */ unsigned int flags; /* pipe flags */ unsigned int state; /* pipe state */ + struct named_pipe *pipe; struct pipe_end *connection; /* the other end of the pipe */ process_id_t client_pid; /* process that created the client */ process_id_t server_pid; /* process that created the server */ @@ -416,14 +417,20 @@ static void pipe_end_destroy( struct pipe_end *pipe_end ) free_async_queue( &pipe_end->read_q ); free_async_queue( &pipe_end->write_q ); if (pipe_end->fd) release_object( pipe_end->fd ); + if (pipe_end->pipe) release_object( pipe_end->pipe ); } static void pipe_server_destroy( struct object *obj) { struct pipe_server *server = (struct pipe_server *)obj; + struct named_pipe *pipe = server->pipe_end.pipe; assert( obj->ops == &pipe_server_ops ); + assert( pipe->instances ); + if (!--pipe->instances) unlink_named_object( &pipe->obj ); + list_remove( &server->entry ); + pipe_end_disconnect( &server->pipe_end, STATUS_PIPE_BROKEN ); pipe_end_destroy( &server->pipe_end ); @@ -433,11 +440,7 @@ static void pipe_server_destroy( struct object *obj) server->client = NULL; } - assert( server->pipe->instances ); - server->pipe->instances--; - - list_remove( &server->entry ); - release_object( server->pipe ); + release_object( pipe ); } static void pipe_client_destroy( struct object *obj) @@ -573,6 +576,12 @@ static void pipe_end_get_file_info( struct fd *fd, struct named_pipe *pipe, unsi } name = get_object_name( &pipe->obj, &name_len ); + /* FIXME: We should be able to return on unlinked pipe */ + if (!name) + { + set_error( STATUS_PIPE_DISCONNECTED ); + return; + } reply_size = offsetof( FILE_NAME_INFORMATION, FileName[name_len/sizeof(WCHAR) + 1] ); if (reply_size > get_reply_max_size()) { @@ -1043,7 +1052,10 @@ static int pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *as case ps_connected_server: assert( server->client ); - /* dump the client and server fds - client loses all waiting data */ + /* dump the client connection - all data is lost */ + release_object( server->pipe_end.connection->pipe ); + server->pipe_end.connection->pipe = NULL; + pipe_end_disconnect( &server->pipe_end, STATUS_PIPE_DISCONNECTED ); server->client->server = NULL; server->client = NULL; @@ -1092,8 +1104,10 @@ static struct pipe_server *get_pipe_server_obj( struct process *process, return (struct pipe_server *) obj; } -static void init_pipe_end( struct pipe_end *pipe_end, unsigned int pipe_flags, data_size_t buffer_size ) +static void init_pipe_end( struct pipe_end *pipe_end, struct named_pipe *pipe, + unsigned int pipe_flags, data_size_t buffer_size ) { + pipe_end->pipe = (struct named_pipe *)grab_object( pipe ); pipe_end->fd = NULL; pipe_end->flags = pipe_flags; pipe_end->connection = NULL; @@ -1115,7 +1129,7 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned server->pipe = pipe; server->client = NULL; server->options = options; - init_pipe_end( &server->pipe_end, pipe_flags, pipe->insize ); + init_pipe_end( &server->pipe_end, pipe, pipe_flags, pipe->insize ); server->pipe_end.state = FILE_PIPE_LISTENING_STATE; server->pipe_end.server_pid = get_process_id( current->process ); @@ -1132,7 +1146,7 @@ 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( unsigned int flags, struct named_pipe *pipe, data_size_t buffer_size, unsigned int options ) { struct pipe_client *client; @@ -1143,7 +1157,7 @@ static struct pipe_client *create_pipe_client( unsigned int flags, unsigned int client->server = NULL; client->flags = flags; - init_pipe_end( &client->pipe_end, pipe_flags, buffer_size ); + init_pipe_end( &client->pipe_end, pipe, pipe->flags, buffer_size ); client->pipe_end.state = FILE_PIPE_CONNECTED_STATE; client->pipe_end.client_pid = get_process_id( current->process ); @@ -1217,7 +1231,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( options, pipe, pipe->outsize, options ))) { if (server->state == ps_wait_open) fd_async_wake_up( server->pipe_end.fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );