server: Moved the FSCTL_PIPE_LISTEN implementation to the server.

This commit is contained in:
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;
}
/***********************************************************************
* 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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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,

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
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",