server: Moved the FSCTL_PIPE_LISTEN implementation to the server.

oldstable
Alexandre Julliard 2007-04-18 16:26:37 +02:00
parent f3fbae4546
commit 6105a93be6
6 changed files with 78 additions and 143 deletions

View File

@ -1019,15 +1019,6 @@ NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE handle, HANDLE event,
return status; 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.@] * NtFsControlFile [NTDLL.@]
@ -1072,36 +1063,6 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
break; break;
case FSCTL_PIPE_LISTEN: 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: case FSCTL_PIPE_WAIT:
{ {
HANDLE internal_event = 0; HANDLE internal_event = 0;

View File

@ -2708,18 +2708,6 @@ struct create_named_pipe_reply
#define NAMED_PIPE_SERVER_END 0x8000 #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 get_named_pipe_info_request
{ {
struct request_header __header; struct request_header __header;
@ -4117,7 +4105,6 @@ enum request
REQ_cancel_async, REQ_cancel_async,
REQ_ioctl, REQ_ioctl,
REQ_create_named_pipe, REQ_create_named_pipe,
REQ_connect_named_pipe,
REQ_get_named_pipe_info, REQ_get_named_pipe_info,
REQ_create_window, REQ_create_window,
REQ_destroy_window, REQ_destroy_window,
@ -4339,7 +4326,6 @@ union generic_request
struct cancel_async_request cancel_async_request; struct cancel_async_request cancel_async_request;
struct ioctl_request ioctl_request; struct ioctl_request ioctl_request;
struct create_named_pipe_request create_named_pipe_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 get_named_pipe_info_request get_named_pipe_info_request;
struct create_window_request create_window_request; struct create_window_request create_window_request;
struct destroy_window_request destroy_window_request; struct destroy_window_request destroy_window_request;
@ -4559,7 +4545,6 @@ union generic_reply
struct cancel_async_reply cancel_async_reply; struct cancel_async_reply cancel_async_reply;
struct ioctl_reply ioctl_reply; struct ioctl_reply ioctl_reply;
struct create_named_pipe_reply create_named_pipe_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 get_named_pipe_info_reply get_named_pipe_info_reply;
struct create_window_reply create_window_reply; struct create_window_reply create_window_reply;
struct destroy_window_reply destroy_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; 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 */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -69,6 +69,7 @@ struct pipe_server
{ {
struct object obj; /* object header */ struct object obj; /* object header */
struct fd *fd; /* pipe file descriptor */ 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 */ struct list entry; /* entry in named pipe servers list */
enum pipe_state state; /* server state */ enum pipe_state state; /* server state */
struct pipe_client *client; /* client that this server is connected to */ 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; 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_connected_server:
case ps_wait_disconnect: case ps_wait_disconnect:
assert( server->fd ); assert( server->fd );
return (struct fd *) grab_object( server->fd ); break;
case ps_wait_open: case ps_wait_open:
case ps_idle_server: case ps_idle_server:
set_error( STATUS_PIPE_LISTENING ); assert( !server->fd );
set_no_fd_status( server->ioctl_fd, STATUS_PIPE_LISTENING );
break; break;
case ps_disconnected_server: case ps_disconnected_server:
case ps_wait_connect: case ps_wait_connect:
set_error( STATUS_PIPE_DISCONNECTED ); assert( !server->fd );
set_no_fd_status( server->ioctl_fd, STATUS_PIPE_DISCONNECTED );
break; 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 ); assert( server->pipe->instances );
server->pipe->instances--; server->pipe->instances--;
if (server->ioctl_fd) release_object( server->ioctl_fd );
list_remove( &server->entry ); list_remove( &server->entry );
release_object( server->pipe ); release_object( server->pipe );
} }
@ -403,12 +411,10 @@ static void pipe_client_destroy( struct object *obj)
case ps_connected_server: case ps_connected_server:
/* Don't destroy the server's fd here as we can't /* Don't destroy the server's fd here as we can't
do a successful flush without it. */ do a successful flush without it. */
server->state = ps_wait_disconnect; set_server_state( server, ps_wait_disconnect );
release_object( client->fd );
client->fd = NULL;
break; break;
case ps_disconnected_server: case ps_disconnected_server:
server->state = ps_wait_connect; set_server_state( server, ps_wait_connect );
break; break;
case ps_idle_server: case ps_idle_server:
case ps_wait_open: case ps_wait_open:
@ -420,7 +426,7 @@ static void pipe_client_destroy( struct object *obj)
server->client = NULL; server->client = NULL;
client->server = 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 ) 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; 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 ) const void *data, data_size_t size )
{ {
struct pipe_server *server = get_fd_user( fd ); struct pipe_server *server = get_fd_user( fd );
struct async *async;
switch(code) 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: case FSCTL_PIPE_DISCONNECT:
switch(server->state) 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 /* dump the client and server fds, but keep the pointers
around - client loses all waiting data */ around - client loses all waiting data */
server->state = ps_disconnected_server;
do_disconnect( server ); do_disconnect( server );
set_server_state( server, ps_disconnected_server );
break; break;
case ps_wait_disconnect: case ps_wait_disconnect:
assert( !server->client ); assert( !server->client );
do_disconnect( server ); do_disconnect( server );
server->state = ps_wait_connect; set_server_state( server, ps_wait_connect );
break; break;
case ps_idle_server: case ps_idle_server:
case ps_wait_open: case ps_wait_open:
set_error( STATUS_PIPE_LISTENING );
break;
case ps_disconnected_server: case ps_disconnected_server:
case ps_wait_connect: case ps_wait_connect:
assert(0); /* shouldn't even get an fd */ set_error( STATUS_PIPE_DISCONNECTED );
break; break;
} }
break; break;
default: default:
default_fd_ioctl( fd, code, async, data, size ); default_fd_ioctl( fd, code, async_data, data, size );
break; break;
} }
} }
@ -668,7 +706,6 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned
server->fd = NULL; server->fd = NULL;
server->pipe = pipe; server->pipe = pipe;
server->state = ps_idle_server;
server->client = NULL; server->client = NULL;
server->flush_poll = NULL; server->flush_poll = NULL;
server->options = options; 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 ); list_add_head( &pipe->servers, &server->entry );
grab_object( pipe ); 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; 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 )) if (!socketpair( PF_UNIX, SOCK_STREAM, 0, fds ))
{ {
int res = 0;
assert( !client->fd );
assert( !server->fd ); assert( !server->fd );
/* for performance reasons, only set nonblocking mode when using /* for performance reasons, only set nonblocking mode when using
* overlapped I/O. Otherwise, we will be doing too much busy * overlapped I/O. Otherwise, we will be doing too much busy
* looping */ * looping */
if (is_overlapped( options )) if (is_overlapped( options )) fcntl( fds[1], F_SETFL, O_NONBLOCK );
res = fcntl( fds[1], F_SETFL, O_NONBLOCK ); if (is_overlapped( server->options )) fcntl( fds[0], F_SETFL, O_NONBLOCK );
if ((res != -1) && is_overlapped( server->options ))
res = fcntl( fds[0], F_SETFL, O_NONBLOCK );
if (pipe->insize) 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 ); 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 ); 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) if (server->state == ps_wait_open)
async_wake_up( server->wait_q, STATUS_SUCCESS ); async_wake_up( server->wait_q, STATUS_SUCCESS );
server->state = ps_connected_server; set_server_state( server, ps_connected_server );
server->client = client; server->client = client;
client->server = server; client->server = server;
} }
else
{
release_object( client );
client = NULL;
}
} }
else else
{
file_set_error(); file_set_error();
release_object( client );
client = NULL;
}
} }
release_object( server ); release_object( server );
return &client->obj; return &client->obj;
@ -884,46 +930,6 @@ DECL_HANDLER(create_named_pipe)
release_object( 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) DECL_HANDLER(get_named_pipe_info)
{ {
struct pipe_server *server; struct pipe_server *server;

View File

@ -1998,12 +1998,6 @@ enum message_type
#define NAMED_PIPE_NONBLOCKING_MODE 0x0004 #define NAMED_PIPE_NONBLOCKING_MODE 0x0004
#define NAMED_PIPE_SERVER_END 0x8000 #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) @REQ(get_named_pipe_info)
obj_handle_t handle; obj_handle_t handle;

View File

@ -246,7 +246,6 @@ DECL_HANDLER(register_async);
DECL_HANDLER(cancel_async); DECL_HANDLER(cancel_async);
DECL_HANDLER(ioctl); DECL_HANDLER(ioctl);
DECL_HANDLER(create_named_pipe); DECL_HANDLER(create_named_pipe);
DECL_HANDLER(connect_named_pipe);
DECL_HANDLER(get_named_pipe_info); DECL_HANDLER(get_named_pipe_info);
DECL_HANDLER(create_window); DECL_HANDLER(create_window);
DECL_HANDLER(destroy_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_cancel_async,
(req_handler)req_ioctl, (req_handler)req_ioctl,
(req_handler)req_create_named_pipe, (req_handler)req_create_named_pipe,
(req_handler)req_connect_named_pipe,
(req_handler)req_get_named_pipe_info, (req_handler)req_get_named_pipe_info,
(req_handler)req_create_window, (req_handler)req_create_window,
(req_handler)req_destroy_window, (req_handler)req_destroy_window,

View File

@ -90,6 +90,7 @@ static void dump_ioctl_code( const ioctl_code_t *code )
#define CASE(c) case c: fputs( #c, stderr ); break #define CASE(c) case c: fputs( #c, stderr ); break
CASE(FSCTL_DISMOUNT_VOLUME); CASE(FSCTL_DISMOUNT_VOLUME);
CASE(FSCTL_PIPE_DISCONNECT); CASE(FSCTL_PIPE_DISCONNECT);
CASE(FSCTL_PIPE_LISTEN);
CASE(FSCTL_PIPE_WAIT); CASE(FSCTL_PIPE_WAIT);
default: fprintf( stderr, "%08x", *code ); break; default: fprintf( stderr, "%08x", *code ); break;
#undef CASE #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 ); 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 ) static void dump_get_named_pipe_info_request( const struct get_named_pipe_info_request *req )
{ {
fprintf( stderr, " handle=%p", req->handle ); 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_cancel_async_request,
(dump_func)dump_ioctl_request, (dump_func)dump_ioctl_request,
(dump_func)dump_create_named_pipe_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_get_named_pipe_info_request,
(dump_func)dump_create_window_request, (dump_func)dump_create_window_request,
(dump_func)dump_destroy_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)0,
(dump_func)dump_ioctl_reply, (dump_func)dump_ioctl_reply,
(dump_func)dump_create_named_pipe_reply, (dump_func)dump_create_named_pipe_reply,
(dump_func)0,
(dump_func)dump_get_named_pipe_info_reply, (dump_func)dump_get_named_pipe_info_reply,
(dump_func)dump_create_window_reply, (dump_func)dump_create_window_reply,
(dump_func)0, (dump_func)0,
@ -4037,7 +4029,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"cancel_async", "cancel_async",
"ioctl", "ioctl",
"create_named_pipe", "create_named_pipe",
"connect_named_pipe",
"get_named_pipe_info", "get_named_pipe_info",
"create_window", "create_window",
"destroy_window", "destroy_window",