From 6105a93be6f4c79e045a23b6efcd8ad3dd182b1c Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 18 Apr 2007 16:26:37 +0200 Subject: [PATCH] server: Moved the FSCTL_PIPE_LISTEN implementation to the server. --- dlls/ntdll/file.c | 39 --------- include/wine/server_protocol.h | 17 +--- server/named_pipe.c | 146 +++++++++++++++++---------------- server/protocol.def | 6 -- server/request.h | 2 - server/trace.c | 11 +-- 6 files changed, 78 insertions(+), 143 deletions(-) diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index c2b3273c985..d0229af4ab7 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -1019,15 +1019,6 @@ NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE handle, HANDLE event, return status; } -/*********************************************************************** - * pipe_completion_wait (Internal) - */ -static NTSTATUS pipe_completion_wait(void *arg, PIO_STATUS_BLOCK iosb, NTSTATUS status) -{ - TRACE("for %p, status=%08x\n", iosb, status); - iosb->u.Status = status; - return status; -} /************************************************************************** * NtFsControlFile [NTDLL.@] @@ -1072,36 +1063,6 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc break; case FSCTL_PIPE_LISTEN: - { - HANDLE internal_event = 0; - - if(!event && !apc) - { - status = NtCreateEvent(&internal_event, EVENT_ALL_ACCESS, NULL, FALSE, FALSE); - if (status != STATUS_SUCCESS) break; - } - SERVER_START_REQ(connect_named_pipe) - { - req->handle = handle; - req->async.callback = pipe_completion_wait; - req->async.iosb = io; - req->async.arg = NULL; - req->async.apc = apc; - req->async.apc_arg = apc_context; - req->async.event = event ? event : internal_event; - status = wine_server_call(req); - } - SERVER_END_REQ; - - if (internal_event && status == STATUS_PENDING) - { - while (NtWaitForSingleObject(internal_event, TRUE, NULL) == STATUS_USER_APC) /*nothing*/ ; - status = io->u.Status; - } - if (internal_event) NtClose(internal_event); - } - break; - case FSCTL_PIPE_WAIT: { HANDLE internal_event = 0; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index f9f4bf27b3b..1fde1260779 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2708,18 +2708,6 @@ struct create_named_pipe_reply #define NAMED_PIPE_SERVER_END 0x8000 -struct connect_named_pipe_request -{ - struct request_header __header; - obj_handle_t handle; - async_data_t async; -}; -struct connect_named_pipe_reply -{ - struct reply_header __header; -}; - - struct get_named_pipe_info_request { struct request_header __header; @@ -4117,7 +4105,6 @@ enum request REQ_cancel_async, REQ_ioctl, REQ_create_named_pipe, - REQ_connect_named_pipe, REQ_get_named_pipe_info, REQ_create_window, REQ_destroy_window, @@ -4339,7 +4326,6 @@ union generic_request struct cancel_async_request cancel_async_request; struct ioctl_request ioctl_request; struct create_named_pipe_request create_named_pipe_request; - struct connect_named_pipe_request connect_named_pipe_request; struct get_named_pipe_info_request get_named_pipe_info_request; struct create_window_request create_window_request; struct destroy_window_request destroy_window_request; @@ -4559,7 +4545,6 @@ union generic_reply struct cancel_async_reply cancel_async_reply; struct ioctl_reply ioctl_reply; struct create_named_pipe_reply create_named_pipe_reply; - struct connect_named_pipe_reply connect_named_pipe_reply; struct get_named_pipe_info_reply get_named_pipe_info_reply; struct create_window_reply create_window_reply; struct destroy_window_reply destroy_window_reply; @@ -4640,6 +4625,6 @@ union generic_reply struct allocate_locally_unique_id_reply allocate_locally_unique_id_reply; }; -#define SERVER_PROTOCOL_VERSION 297 +#define SERVER_PROTOCOL_VERSION 298 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/named_pipe.c b/server/named_pipe.c index d4be777994d..9db5a58d14a 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -69,6 +69,7 @@ struct pipe_server { struct object obj; /* object header */ struct fd *fd; /* pipe file descriptor */ + struct fd *ioctl_fd; /* file descriptor for ioctls when not connected */ struct list entry; /* entry in named pipe servers list */ enum pipe_state state; /* server state */ struct pipe_client *client; /* client that this server is connected to */ @@ -297,28 +298,34 @@ static struct fd *pipe_client_get_fd( struct object *obj ) return NULL; } -static struct fd *pipe_server_get_fd( struct object *obj ) +static void set_server_state( struct pipe_server *server, enum pipe_state state ) { - struct pipe_server *server = (struct pipe_server *) obj; + server->state = state; - switch(server->state) + switch(state) { case ps_connected_server: case ps_wait_disconnect: assert( server->fd ); - return (struct fd *) grab_object( server->fd ); - + break; case ps_wait_open: case ps_idle_server: - set_error( STATUS_PIPE_LISTENING ); + assert( !server->fd ); + set_no_fd_status( server->ioctl_fd, STATUS_PIPE_LISTENING ); break; - case ps_disconnected_server: case ps_wait_connect: - set_error( STATUS_PIPE_DISCONNECTED ); + assert( !server->fd ); + set_no_fd_status( server->ioctl_fd, STATUS_PIPE_DISCONNECTED ); break; } - return NULL; +} + +static struct fd *pipe_server_get_fd( struct object *obj ) +{ + struct pipe_server *server = (struct pipe_server *) obj; + + return (struct fd *)grab_object( server->fd ? server->fd : server->ioctl_fd ); } @@ -383,6 +390,7 @@ static void pipe_server_destroy( struct object *obj) assert( server->pipe->instances ); server->pipe->instances--; + if (server->ioctl_fd) release_object( server->ioctl_fd ); list_remove( &server->entry ); release_object( server->pipe ); } @@ -403,12 +411,10 @@ static void pipe_client_destroy( struct object *obj) case ps_connected_server: /* Don't destroy the server's fd here as we can't do a successful flush without it. */ - server->state = ps_wait_disconnect; - release_object( client->fd ); - client->fd = NULL; + set_server_state( server, ps_wait_disconnect ); break; case ps_disconnected_server: - server->state = ps_wait_connect; + set_server_state( server, ps_wait_connect ); break; case ps_idle_server: case ps_wait_open: @@ -420,7 +426,7 @@ static void pipe_client_destroy( struct object *obj) server->client = NULL; client->server = NULL; } - assert( !client->fd ); + if (client->fd) release_object( client->fd ); } static void named_pipe_device_dump( struct object *obj, int verbose ) @@ -567,13 +573,42 @@ static enum server_fd_type pipe_client_get_fd_type( struct fd *fd ) return FD_TYPE_PIPE; } -static void pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async, +static void pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data, const void *data, data_size_t size ) { struct pipe_server *server = get_fd_user( fd ); + struct async *async; switch(code) { + case FSCTL_PIPE_LISTEN: + switch(server->state) + { + case ps_idle_server: + case ps_wait_connect: + set_server_state( server, ps_wait_open ); + if ((async = create_async( current, server->wait_q, async_data ))) + { + if (server->pipe->waiters) async_wake_up( server->pipe->waiters, STATUS_SUCCESS ); + release_object( async ); + set_error( STATUS_PENDING ); + } + break; + case ps_connected_server: + set_error( STATUS_PIPE_CONNECTED ); + break; + case ps_disconnected_server: + set_error( STATUS_PIPE_BUSY ); + break; + case ps_wait_disconnect: + set_error( STATUS_NO_DATA_DETECTED ); + break; + case ps_wait_open: + set_error( STATUS_INVALID_HANDLE ); + break; + } + break; + case FSCTL_PIPE_DISCONNECT: switch(server->state) { @@ -585,24 +620,27 @@ static void pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_dat /* dump the client and server fds, but keep the pointers around - client loses all waiting data */ - server->state = ps_disconnected_server; do_disconnect( server ); + set_server_state( server, ps_disconnected_server ); break; case ps_wait_disconnect: assert( !server->client ); do_disconnect( server ); - server->state = ps_wait_connect; + set_server_state( server, ps_wait_connect ); break; case ps_idle_server: case ps_wait_open: + set_error( STATUS_PIPE_LISTENING ); + break; case ps_disconnected_server: case ps_wait_connect: - assert(0); /* shouldn't even get an fd */ + set_error( STATUS_PIPE_DISCONNECTED ); break; } break; + default: - default_fd_ioctl( fd, code, async, data, size ); + default_fd_ioctl( fd, code, async_data, data, size ); break; } } @@ -668,7 +706,6 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned server->fd = NULL; server->pipe = pipe; - server->state = ps_idle_server; server->client = NULL; server->flush_poll = NULL; server->options = options; @@ -676,7 +713,12 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned list_add_head( &pipe->servers, &server->entry ); grab_object( pipe ); - + if (!(server->ioctl_fd = alloc_pseudo_fd( &pipe_server_fd_ops, &server->obj ))) + { + release_object( server ); + server = NULL; + } + set_server_state( server, ps_idle_server ); return server; } @@ -725,18 +767,13 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc { if (!socketpair( PF_UNIX, SOCK_STREAM, 0, fds )) { - int res = 0; - - assert( !client->fd ); assert( !server->fd ); /* for performance reasons, only set nonblocking mode when using * overlapped I/O. Otherwise, we will be doing too much busy * looping */ - if (is_overlapped( options )) - res = fcntl( fds[1], F_SETFL, O_NONBLOCK ); - if ((res != -1) && is_overlapped( server->options )) - res = fcntl( fds[0], F_SETFL, O_NONBLOCK ); + if (is_overlapped( options )) fcntl( fds[1], F_SETFL, O_NONBLOCK ); + if (is_overlapped( server->options )) fcntl( fds[0], F_SETFL, O_NONBLOCK ); if (pipe->insize) { @@ -751,17 +788,26 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc client->fd = create_anonymous_fd( &pipe_client_fd_ops, fds[1], &client->obj, options ); server->fd = create_anonymous_fd( &pipe_server_fd_ops, fds[0], &server->obj, server->options ); - if (client->fd && server->fd && res != 1) + if (client->fd && server->fd) { if (server->state == ps_wait_open) async_wake_up( server->wait_q, STATUS_SUCCESS ); - server->state = ps_connected_server; + set_server_state( server, ps_connected_server ); server->client = client; client->server = server; } + else + { + release_object( client ); + client = NULL; + } } else + { file_set_error(); + release_object( client ); + client = NULL; + } } release_object( server ); return &client->obj; @@ -884,46 +930,6 @@ DECL_HANDLER(create_named_pipe) release_object( pipe ); } -DECL_HANDLER(connect_named_pipe) -{ - struct pipe_server *server; - struct async *async; - - server = get_pipe_server_obj(current->process, req->handle, 0); - if (!server) - return; - - switch(server->state) - { - case ps_idle_server: - case ps_wait_connect: - assert( !server->fd ); - server->state = ps_wait_open; - if ((async = create_async( current, server->wait_q, &req->async ))) - { - if (server->pipe->waiters) async_wake_up( server->pipe->waiters, STATUS_SUCCESS ); - release_object( async ); - set_error( STATUS_PENDING ); - } - break; - case ps_connected_server: - assert( server->fd ); - set_error( STATUS_PIPE_CONNECTED ); - break; - case ps_disconnected_server: - set_error( STATUS_PIPE_BUSY ); - break; - case ps_wait_disconnect: - set_error( STATUS_NO_DATA_DETECTED ); - break; - case ps_wait_open: - set_error( STATUS_INVALID_HANDLE ); - break; - } - - release_object(server); -} - DECL_HANDLER(get_named_pipe_info) { struct pipe_server *server; diff --git a/server/protocol.def b/server/protocol.def index a5f91abd53a..02dee2def5f 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1998,12 +1998,6 @@ enum message_type #define NAMED_PIPE_NONBLOCKING_MODE 0x0004 #define NAMED_PIPE_SERVER_END 0x8000 -/* Connect to a named pipe */ -@REQ(connect_named_pipe) - obj_handle_t handle; - async_data_t async; /* async I/O parameters */ -@END - @REQ(get_named_pipe_info) obj_handle_t handle; diff --git a/server/request.h b/server/request.h index 1b8da0ea2de..36301542c77 100644 --- a/server/request.h +++ b/server/request.h @@ -246,7 +246,6 @@ DECL_HANDLER(register_async); DECL_HANDLER(cancel_async); DECL_HANDLER(ioctl); DECL_HANDLER(create_named_pipe); -DECL_HANDLER(connect_named_pipe); DECL_HANDLER(get_named_pipe_info); DECL_HANDLER(create_window); DECL_HANDLER(destroy_window); @@ -467,7 +466,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_cancel_async, (req_handler)req_ioctl, (req_handler)req_create_named_pipe, - (req_handler)req_connect_named_pipe, (req_handler)req_get_named_pipe_info, (req_handler)req_create_window, (req_handler)req_destroy_window, diff --git a/server/trace.c b/server/trace.c index 3751cdf70db..09af4419eeb 100644 --- a/server/trace.c +++ b/server/trace.c @@ -90,6 +90,7 @@ static void dump_ioctl_code( const ioctl_code_t *code ) #define CASE(c) case c: fputs( #c, stderr ); break CASE(FSCTL_DISMOUNT_VOLUME); CASE(FSCTL_PIPE_DISCONNECT); + CASE(FSCTL_PIPE_LISTEN); CASE(FSCTL_PIPE_WAIT); default: fprintf( stderr, "%08x", *code ); break; #undef CASE @@ -2443,13 +2444,6 @@ static void dump_create_named_pipe_reply( const struct create_named_pipe_reply * fprintf( stderr, " handle=%p", req->handle ); } -static void dump_connect_named_pipe_request( const struct connect_named_pipe_request *req ) -{ - fprintf( stderr, " handle=%p,", req->handle ); - fprintf( stderr, " async=" ); - dump_async_data( &req->async ); -} - static void dump_get_named_pipe_info_request( const struct get_named_pipe_info_request *req ) { fprintf( stderr, " handle=%p", req->handle ); @@ -3601,7 +3595,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_cancel_async_request, (dump_func)dump_ioctl_request, (dump_func)dump_create_named_pipe_request, - (dump_func)dump_connect_named_pipe_request, (dump_func)dump_get_named_pipe_info_request, (dump_func)dump_create_window_request, (dump_func)dump_destroy_window_request, @@ -3819,7 +3812,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)0, (dump_func)dump_ioctl_reply, (dump_func)dump_create_named_pipe_reply, - (dump_func)0, (dump_func)dump_get_named_pipe_info_reply, (dump_func)dump_create_window_reply, (dump_func)0, @@ -4037,7 +4029,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "cancel_async", "ioctl", "create_named_pipe", - "connect_named_pipe", "get_named_pipe_info", "create_window", "destroy_window",