From: Jacek Caban Subject: [PATCH 10/12] server: Use create_request_async in ioctl request handler. Message-Id: Date: Tue, 13 Jun 2017 16:49:38 +0200 Signed-off-by: Jacek Caban --- dlls/ntdll/file.c | 8 +++++--- dlls/ntdll/tests/pipe.c | 6 +++--- server/device.c | 6 +++--- server/fd.c | 19 +++++++------------ server/file.h | 6 +++--- server/named_pipe.c | 44 ++++++++++++++++++++------------------------ server/serial.c | 47 +++++++++++++++++++++++++++-------------------- server/sock.c | 8 +++----- 8 files changed, 71 insertions(+), 73 deletions(-) diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 0d7efc3dd5..380b3706f8 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -1543,7 +1543,11 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event, status = wine_server_call( req ); wait_handle = wine_server_ptr_handle( reply->wait ); options = reply->options; - if (status != STATUS_PENDING) io->Information = wine_server_reply_size( reply ); + if (wait_handle && status != STATUS_PENDING) + { + io->u.Status = status; + io->Information = wine_server_reply_size( reply ); + } } SERVER_END_REQ; @@ -1557,10 +1561,8 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event, { NtWaitForSingleObject( wait_handle, (options & FILE_SYNCHRONOUS_IO_ALERT), NULL ); status = io->u.Status; - NtClose( wait_handle ); } - if (status != STATUS_PENDING && code != FSCTL_PIPE_LISTEN) io->u.Status = status; return status; } diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c index c0a785b0f4..f567e616a2 100644 --- a/dlls/ntdll/tests/pipe.c +++ b/dlls/ntdll/tests/pipe.c @@ -724,7 +724,7 @@ static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved ) ok( !reserved, "reserved is not 0: %x\n", reserved ); } -static void test_peek(HANDLE pipe) +static void test_peek(HANDLE pipe, BOOL is_msgmode) { FILE_PIPE_PEEK_BUFFER buf; IO_STATUS_BLOCK iosb; @@ -743,7 +743,7 @@ static void test_peek(HANDLE pipe) ok(!status || status == STATUS_PENDING, "NtFsControlFile failed: %x\n", status); ok(buf.ReadDataAvailable == 1, "ReadDataAvailable = %u\n", buf.ReadDataAvailable); ok(!iosb.Status, "iosb.Status = %x\n", iosb.Status); - todo_wine + todo_wine_if(!is_msgmode) ok(is_signaled(event), "event is not signaled\n"); CloseHandle(event); @@ -855,7 +855,7 @@ static void read_pipe_test(ULONG pipe_flags, ULONG pipe_type) ret = WriteFile( write, buffer, 1, &written, NULL ); ok(ret && written == 1, "WriteFile error %d\n", GetLastError()); - test_peek(read); + test_peek(read, pipe_type & PIPE_TYPE_MESSAGE); status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL ); ok( status == STATUS_SUCCESS, "wrong status %x\n", status ); diff --git a/server/device.c b/server/device.c index 4c7aa16cf2..c19905bf30 100644 --- a/server/device.c +++ b/server/device.c @@ -177,7 +177,7 @@ static enum server_fd_type device_file_get_fd_type( struct fd *fd ); static int device_file_read( struct fd *fd, struct async *async, file_pos_t pos ); static int device_file_write( struct fd *fd, struct async *async, file_pos_t pos ); static obj_handle_t device_file_flush( struct fd *fd, struct async *async ); -static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); +static int device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static const struct object_ops device_file_ops = { @@ -546,7 +546,7 @@ static obj_handle_t device_file_flush( struct fd *fd, struct async *async ) return handle; } -static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) +static int device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) { struct device_file *file = get_fd_user( fd ); struct irp_call *irp; @@ -561,7 +561,7 @@ static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct irp = create_irp( file, ¶ms, async ); if (!irp) return 0; - handle = queue_irp( file, irp, async, 1 ); + handle = queue_irp( file, irp, async, 0 ); release_object( irp ); return handle; } diff --git a/server/fd.c b/server/fd.c index 1d98108f6d..c701769a0d 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2183,20 +2183,20 @@ obj_handle_t no_fd_flush( struct fd *fd, struct async *async ) } /* default ioctl() routine */ -obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) +int no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) { set_error( STATUS_OBJECT_TYPE_MISMATCH ); return 0; } /* default ioctl() routine */ -obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) +int default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) { switch(code) { case FSCTL_DISMOUNT_VOLUME: unmount_device( fd ); - return 0; + return 1; default: set_error( STATUS_NOT_SUPPORTED ); return 0; @@ -2491,19 +2491,14 @@ DECL_HANDLER(ioctl) unsigned int access = (req->code >> 14) & (FILE_READ_DATA|FILE_WRITE_DATA); struct fd *fd = get_handle_fd_obj( current->process, req->async.handle, access ); struct async *async; - struct iosb *iosb; if (!fd) return; - if ((iosb = create_iosb( get_req_data(), get_req_data_size(), get_reply_max_size() ))) + if ((async = fd_create_request_async( fd, current, &req->async ))) { - if ((async = create_async( current, &req->async, iosb ))) - { - reply->wait = fd->fd_ops->ioctl( fd, req->code, async ); - reply->options = fd->options; - release_object( async ); - } - release_object( iosb ); + reply->wait = async_handoff( async, fd->fd_ops->ioctl( fd, req->code, async ), fd->default_q, NULL ); + reply->options = fd->options; + release_object( async ); } release_object( fd ); } diff --git a/server/file.h b/server/file.h index 9b034c8b34..ae16680fc1 100644 --- a/server/file.h +++ b/server/file.h @@ -58,7 +58,7 @@ struct fd_ops /* flush the object buffers */ obj_handle_t (*flush)(struct fd *, struct async *); /* perform an ioctl on the file */ - obj_handle_t (*ioctl)(struct fd *fd, ioctl_code_t code, struct async *async ); + int (*ioctl)(struct fd *fd, ioctl_code_t code, struct async *async ); /* queue an async operation */ void (*queue_async)(struct fd *, struct async *async, int type, int count); /* selected events for async i/o need an update */ @@ -103,8 +103,8 @@ extern void fd_reselect_async( struct fd *fd, struct async_queue *queue ); extern int no_fd_read( struct fd *fd, struct async *async, file_pos_t pos ); extern int no_fd_write( struct fd *fd, struct async *async, file_pos_t pos ); extern obj_handle_t no_fd_flush( struct fd *fd, struct async *async ); -extern obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); -extern obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); +extern int no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); +extern int default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); extern void no_fd_queue_async( struct fd *fd, struct async *async, int type, int count ); extern void default_fd_queue_async( struct fd *fd, struct async *async, int type, int count ); extern void default_fd_reselect_async( struct fd *fd, struct async_queue *queue ); diff --git a/server/named_pipe.c b/server/named_pipe.c index f33daf816f..1e51ce8015 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -164,7 +164,7 @@ static void pipe_server_dump( struct object *obj, int verbose ); static struct fd *pipe_server_get_fd( struct object *obj ); static void pipe_server_destroy( struct object *obj); static obj_handle_t pipe_server_flush( struct fd *fd, struct async *async ); -static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); +static int pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static const struct object_ops pipe_server_ops = { @@ -207,7 +207,7 @@ static int pipe_client_signaled( struct object *obj, struct wait_queue_entry *en static struct fd *pipe_client_get_fd( struct object *obj ); static void pipe_client_destroy( struct object *obj ); static obj_handle_t pipe_client_flush( struct fd *fd, struct async *async ); -static obj_handle_t pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); +static int pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static const struct object_ops pipe_client_ops = { @@ -253,8 +253,7 @@ static struct object *named_pipe_device_open_file( struct object *obj, unsigned unsigned int sharing, unsigned int options ); static void named_pipe_device_destroy( struct object *obj ); static enum server_fd_type named_pipe_device_get_fd_type( struct fd *fd ); -static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, - struct async *async ); +static int named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static const struct object_ops named_pipe_device_ops = { @@ -889,7 +888,7 @@ static enum server_fd_type pipe_end_get_fd_type( struct fd *fd ) return FD_TYPE_PIPE; } -static void pipe_end_peek( struct pipe_end *pipe_end ) +static int pipe_end_peek( struct pipe_end *pipe_end ) { unsigned reply_size = get_reply_max_size(); FILE_PIPE_PEEK_BUFFER *buffer; @@ -900,13 +899,13 @@ static void pipe_end_peek( struct pipe_end *pipe_end ) if (!use_server_io( pipe_end )) { set_error( STATUS_NOT_SUPPORTED ); - return; + return 0; } if (reply_size < offsetof( FILE_PIPE_PEEK_BUFFER, Data )) { set_error( STATUS_INFO_LENGTH_MISMATCH ); - return; + return 0; } reply_size -= offsetof( FILE_PIPE_PEEK_BUFFER, Data ); @@ -921,18 +920,18 @@ static void pipe_end_peek( struct pipe_end *pipe_end ) } else reply_size = 0; - if (!(buffer = set_reply_data_size( offsetof( FILE_PIPE_PEEK_BUFFER, Data[reply_size] )))) return; + if (!(buffer = set_reply_data_size( offsetof( FILE_PIPE_PEEK_BUFFER, Data[reply_size] )))) return 0; buffer->NamedPipeState = 0; /* FIXME */ buffer->ReadDataAvailable = avail; buffer->NumberOfMessages = 0; /* FIXME */ buffer->MessageLength = message_length; if (reply_size) memcpy( buffer->Data, (const char *)message->iosb->in_data + message->read_pos, reply_size ); + return 1; } -static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) +static int pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) { struct pipe_server *server = get_fd_user( fd ); - obj_handle_t wait_handle = 0; switch(code) { @@ -943,11 +942,10 @@ static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct case ps_wait_connect: if (fd_queue_async( server->ioctl_fd, async, ASYNC_TYPE_WAIT )) { - if (async_is_blocking( async )) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ); set_server_state( server, ps_wait_open ); if (server->pipe->waiters) async_wake_up( server->pipe->waiters, STATUS_SUCCESS ); set_error( STATUS_PENDING ); - return wait_handle; + return 1; } break; case ps_connected_server: @@ -987,31 +985,29 @@ static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct case ps_idle_server: case ps_wait_open: set_error( STATUS_PIPE_LISTENING ); - break; + return 0; case ps_wait_connect: set_error( STATUS_PIPE_DISCONNECTED ); - break; + return 0; } - return 0; + return 1; case FSCTL_PIPE_PEEK: - pipe_end_peek( &server->pipe_end ); - return 0; + return pipe_end_peek( &server->pipe_end ); default: return default_fd_ioctl( fd, code, async ); } } -static obj_handle_t pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) +static int pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) { struct pipe_client *client = get_fd_user( fd ); switch(code) { case FSCTL_PIPE_PEEK: - pipe_end_peek( &client->pipe_end ); - return 0; + return pipe_end_peek( &client->pipe_end ); default: return default_fd_ioctl( fd, code, async ); @@ -1211,7 +1207,7 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc return &client->pipe_end.obj; } -static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) +static int named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) { struct named_pipe_device *device = get_fd_user( fd ); @@ -1221,7 +1217,6 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, s { const FILE_PIPE_WAIT_FOR_BUFFER *buffer = get_req_data(); data_size_t size = get_req_data_size(); - obj_handle_t wait_handle = 0; struct named_pipe *pipe; struct pipe_server *server; struct unicode_str name; @@ -1244,14 +1239,15 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, s queue_async( pipe->waiters, async ); when = buffer->TimeoutSpecified ? buffer->Timeout.QuadPart : pipe->timeout; async_set_timeout( async, when, STATUS_IO_TIMEOUT ); - if (async_is_blocking( async )) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ); + release_object( pipe ); set_error( STATUS_PENDING ); + return 1; } else release_object( server ); done: release_object( pipe ); - return wait_handle; + return 0; } default: diff --git a/server/serial.c b/server/serial.c index fb29288510..396ca22a2c 100644 --- a/server/serial.c +++ b/server/serial.c @@ -63,7 +63,7 @@ static struct fd *serial_get_fd( struct object *obj ); static void serial_destroy(struct object *obj); static enum server_fd_type serial_get_fd_type( struct fd *fd ); -static obj_handle_t serial_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); +static int serial_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static void serial_queue_async( struct fd *fd, struct async *async, int type, int count ); static void serial_reselect_async( struct fd *fd, struct async_queue *queue ); @@ -175,42 +175,49 @@ static enum server_fd_type serial_get_fd_type( struct fd *fd ) return FD_TYPE_SERIAL; } -static obj_handle_t serial_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) +static int serial_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) { struct serial *serial = get_fd_user( fd ); switch (code) { case IOCTL_SERIAL_GET_TIMEOUTS: - if (get_reply_max_size() >= sizeof(serial->timeouts)) - set_reply_data( &serial->timeouts, sizeof(serial->timeouts )); - else + if (get_reply_max_size() < sizeof(serial->timeouts)) + { set_error( STATUS_BUFFER_TOO_SMALL ); - return 0; + return 0; + } + set_reply_data( &serial->timeouts, sizeof(serial->timeouts )); + return 1; case IOCTL_SERIAL_SET_TIMEOUTS: - if (get_req_data_size() >= sizeof(serial->timeouts)) - memcpy( &serial->timeouts, get_req_data(), sizeof(serial->timeouts) ); - else + if (get_req_data_size() < sizeof(serial->timeouts)) + { set_error( STATUS_BUFFER_TOO_SMALL ); - return 0; + return 0; + } + memcpy( &serial->timeouts, get_req_data(), sizeof(serial->timeouts) ); + return 1; case IOCTL_SERIAL_GET_WAIT_MASK: - if (get_reply_max_size() >= sizeof(serial->eventmask)) - set_reply_data( &serial->eventmask, sizeof(serial->eventmask) ); - else + if (get_reply_max_size() < sizeof(serial->eventmask)) + { set_error( STATUS_BUFFER_TOO_SMALL ); - return 0; + return 0; + } + set_reply_data( &serial->eventmask, sizeof(serial->eventmask) ); + return 1; case IOCTL_SERIAL_SET_WAIT_MASK: - if (get_req_data_size() >= sizeof(serial->eventmask)) + if (get_req_data_size() < sizeof(serial->eventmask)) { - serial->eventmask = *(unsigned int *)get_req_data(); - serial->generation++; - fd_async_wake_up( serial->fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS ); + set_error( STATUS_BUFFER_TOO_SMALL ); + return 0; } - else set_error( STATUS_BUFFER_TOO_SMALL ); - return 0; + serial->eventmask = *(unsigned int *)get_req_data(); + serial->generation++; + fd_async_wake_up( serial->fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS ); + return 1; default: set_error( STATUS_NOT_SUPPORTED ); diff --git a/server/sock.c b/server/sock.c index 1fd625b1a3..d4af01efae 100644 --- a/server/sock.c +++ b/server/sock.c @@ -129,7 +129,7 @@ static void sock_destroy_ifchange_q( struct sock *sock ); static int sock_get_poll_events( struct fd *fd ); static void sock_poll_event( struct fd *fd, int event ); static enum server_fd_type sock_get_fd_type( struct fd *fd ); -static obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); +static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static void sock_queue_async( struct fd *fd, struct async *async, int type, int count ); static void sock_reselect_async( struct fd *fd, struct async_queue *queue ); @@ -534,10 +534,9 @@ static enum server_fd_type sock_get_fd_type( struct fd *fd ) return FD_TYPE_SOCKET; } -obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) +static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) { struct sock *sock = get_fd_user( fd ); - obj_handle_t wait_handle = 0; struct async_queue *ifchange_q; assert( sock->obj.ops == &sock_ops ); @@ -552,9 +551,8 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) } if (!(ifchange_q = sock_get_ifchange_q( sock ))) return 0; queue_async( ifchange_q, async ); - if (async_is_blocking( async )) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ); set_error( STATUS_PENDING ); - return wait_handle; + return 1; default: set_error( STATUS_NOT_SUPPORTED ); return 0;