server: Moved the FSCTL_PIPE_LISTEN implementation to the server.
This commit is contained in:
parent
f3fbae4546
commit
6105a93be6
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue