From: Jacek Caban Subject: [PATCH 5/7] server: Create async object in ioctl request handler. Message-Id: <4565f5cb-346f-3e1f-34c3-29f04be17199@codeweavers.com> Date: Wed, 15 Feb 2017 22:12:59 +0100 Signed-off-by: Jacek Caban --- dlls/ntdll/tests/file.c | 26 ++++++++++++++++++++++++++ dlls/ntdll/tests/pipe.c | 7 +++++++ server/device.c | 7 +++---- server/fd.c | 21 +++++++++++++++------ server/file.h | 6 +++--- server/named_pipe.c | 31 ++++++++++++------------------- server/sock.c | 7 ++----- 7 files changed, 68 insertions(+), 37 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 57d7df9..faefd7d 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -67,6 +67,7 @@ static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent, static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE hFile, PIO_STATUS_BLOCK io_status); static NTSTATUS (WINAPI *pNtCancelIoFileEx)(HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status); static NTSTATUS (WINAPI *pNtClose)( PHANDLE ); +static NTSTATUS (WINAPI *pNtFsControlFile) (HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, PVOID apc_context, PIO_STATUS_BLOCK io, ULONG code, PVOID in_buffer, ULONG in_size, PVOID out_buffer, ULONG out_size); static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG); static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); @@ -4205,6 +4206,29 @@ static void test_read_write(void) CloseHandle(hfile); } +static void test_ioctl(void) +{ + HANDLE event = CreateEventA(NULL, TRUE, FALSE, NULL); + IO_STATUS_BLOCK iosb; + HANDLE file; + NTSTATUS status; + + file = create_temp_file(FILE_FLAG_OVERLAPPED); + ok(file != INVALID_HANDLE_VALUE, "coult not create temp file\n"); + + SetEvent(event); + status = pNtFsControlFile(file, event, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0); + todo_wine + ok(status == STATUS_INVALID_DEVICE_REQUEST, "NtFsControlFile returned %x\n", status); + ok(!is_signaled(event), "event is signaled\n"); + + status = pNtFsControlFile(file, (HANDLE)0xdeadbeef, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0); + ok(status == STATUS_INVALID_HANDLE, "NtFsControlFile returned %x\n", status); + + CloseHandle(event); + CloseHandle(file); +} + START_TEST(file) { HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); @@ -4231,6 +4255,7 @@ START_TEST(file) pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile"); pNtCancelIoFileEx = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx"); pNtClose = (void *)GetProcAddress(hntdll, "NtClose"); + pNtFsControlFile = (void *)GetProcAddress(hntdll, "NtFsControlFile"); pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion"); pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion"); pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion"); @@ -4262,4 +4287,5 @@ START_TEST(file) test_file_disposition_information(); test_query_volume_information_file(); test_query_attribute_information_file(); + test_ioctl(); } diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c index dce5d34..176e908 100644 --- a/dlls/ntdll/tests/pipe.c +++ b/dlls/ntdll/tests/pipe.c @@ -106,6 +106,11 @@ static BOOL init_func_ptrs(void) return TRUE; } +static inline BOOL is_signaled( HANDLE obj ) +{ + return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0; +} + static const WCHAR testpipe[] = { '\\', '\\', '.', '\\', 'p', 'i', 'p', 'e', '\\', 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 }; static const WCHAR testpipe_nt[] = { '\\', '?', '?', '\\', 'p', 'i', 'p', 'e', '\\', @@ -312,10 +317,12 @@ static void test_overlapped(void) if (hClient != INVALID_HANDLE_VALUE) { + SetEvent(hEvent); memset(&iosb, 0x55, sizeof(iosb)); res = listen_pipe(hPipe, hEvent, &iosb, TRUE); ok(res == STATUS_PIPE_CONNECTED, "NtFsControlFile returned %x\n", res); ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status); + ok(!is_signaled(hEvent), "hEvent not signaled\n"); CloseHandle(hClient); } diff --git a/server/device.c b/server/device.c index 90ebc9e..1479a1c 100644 --- a/server/device.c +++ b/server/device.c @@ -177,8 +177,7 @@ static enum server_fd_type device_file_get_fd_type( struct fd *fd ); static obj_handle_t device_file_read( struct fd *fd, struct async *async, int blocking, file_pos_t pos ); static obj_handle_t device_file_write( struct fd *fd, struct async *async, int blocking, file_pos_t pos ); static obj_handle_t device_file_flush( struct fd *fd, const async_data_t *async_data, int blocking ); -static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data, - int blocking ); +static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, int blocking ); static const struct object_ops device_file_ops = { @@ -554,7 +553,7 @@ static obj_handle_t device_file_flush( struct fd *fd, const async_data_t *async_ return handle; } -static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data, +static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, int blocking ) { struct device_file *file = get_fd_user( fd ); @@ -574,7 +573,7 @@ static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, const a release_object(iosb); if (!irp) return 0; - handle = queue_irp( file, irp, async_data, blocking ); + handle = queue_irp( file, irp, async_get_data( async ), blocking ); release_object( irp ); return handle; } diff --git a/server/fd.c b/server/fd.c index 4aa1b1d..d8ee682 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2186,14 +2186,14 @@ obj_handle_t no_fd_flush( struct fd *fd, const async_data_t *async, int blocking } /* default ioctl() routine */ -obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async, int blocking ) +obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, int blocking ) { set_error( STATUS_OBJECT_TYPE_MISMATCH ); return 0; } /* default ioctl() routine */ -obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async, int blocking ) +obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, int blocking ) { switch(code) { @@ -2494,13 +2494,22 @@ 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) + if (!fd) return; + + if ((iosb = create_iosb( get_req_data(), get_req_data_size(), get_reply_max_size() ))) { - reply->wait = fd->fd_ops->ioctl( fd, req->code, &req->async, req->blocking ); - reply->options = fd->options; - release_object( fd ); + if ((async = create_async( current, &req->async, iosb ))) + { + reply->wait = fd->fd_ops->ioctl( fd, req->code, async, req->blocking ); + reply->options = fd->options; + release_object( async ); + } + release_object( iosb ); } + release_object( fd ); } /* create / reschedule an async I/O */ diff --git a/server/file.h b/server/file.h index 98a1e84..c3938c2 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 *, const async_data_t *, int); /* perform an ioctl on the file */ - obj_handle_t (*ioctl)(struct fd *fd, ioctl_code_t code, const async_data_t *async, int blocking ); + obj_handle_t (*ioctl)(struct fd *fd, ioctl_code_t code, struct async *async, int blocking ); /* 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 obj_handle_t no_fd_read( struct fd *fd, struct async *async, int blocking, file_pos_t pos ); extern obj_handle_t no_fd_write( struct fd *fd, struct async *async, int blocking, file_pos_t pos ); extern obj_handle_t no_fd_flush( struct fd *fd, const async_data_t *async, int blocking ); -extern obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async, int blocking ); -extern obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async, int blocking ); +extern obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, int blocking ); +extern obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, int blocking ); 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 4eee875..1668aaf 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -144,7 +144,7 @@ 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, const async_data_t *async, int blocking ); static enum server_fd_type pipe_server_get_fd_type( struct fd *fd ); -static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async, +static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, int blocking ); static const struct object_ops pipe_server_ops = @@ -235,7 +235,7 @@ static struct object *named_pipe_device_open_file( struct object *obj, unsigned 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, - const async_data_t *async_data, int blocking ); + struct async *async, int blocking ); static const struct object_ops named_pipe_device_ops = { @@ -588,11 +588,10 @@ static enum server_fd_type pipe_client_get_fd_type( struct fd *fd ) return FD_TYPE_PIPE; } -static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data, +static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, int blocking ) { struct pipe_server *server = get_fd_user( fd ); - struct async *async; obj_handle_t wait_handle = 0; switch(code) @@ -602,7 +601,7 @@ static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const a { case ps_idle_server: case ps_wait_connect: - if ((async = fd_queue_async( server->ioctl_fd, async_data, NULL, ASYNC_TYPE_WAIT ))) + if ((async = fd_queue_async( server->ioctl_fd, async_get_data( async ), NULL, ASYNC_TYPE_WAIT ))) { if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ); set_server_state( server, ps_wait_open ); @@ -655,7 +654,7 @@ static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const a return 0; default: - return default_fd_ioctl( fd, code, async_data, blocking ); + return default_fd_ioctl( fd, code, async, blocking ); } } @@ -824,7 +823,7 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc } static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, - const async_data_t *async_data, int blocking ) + struct async *async, int blocking ) { struct named_pipe_device *device = get_fd_user( fd ); @@ -852,19 +851,13 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, if (!(server = find_available_server( pipe ))) { - struct async *async; - if (!pipe->waiters && !(pipe->waiters = create_async_queue( NULL ))) goto done; - if ((async = create_async( current, async_data, NULL ))) - { - queue_async( pipe->waiters, async ); - when = buffer->TimeoutSpecified ? buffer->Timeout.QuadPart : pipe->timeout; - async_set_timeout( async, when, STATUS_IO_TIMEOUT ); - if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ); - release_object( async ); - set_error( STATUS_PENDING ); - } + queue_async( pipe->waiters, async ); + when = buffer->TimeoutSpecified ? buffer->Timeout.QuadPart : pipe->timeout; + async_set_timeout( async, when, STATUS_IO_TIMEOUT ); + if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ); + set_error( STATUS_PENDING ); } else release_object( server ); @@ -874,7 +867,7 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, } default: - return default_fd_ioctl( fd, code, async_data, blocking ); + return default_fd_ioctl( fd, code, async, blocking ); } } diff --git a/server/sock.c b/server/sock.c index c997bf3..59ab427 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, const async_data_t *async, int blocking ); +static obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, int blocking ); 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,12 +534,11 @@ 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, const async_data_t *async_data, int blocking ) +obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, int blocking ) { struct sock *sock = get_fd_user( fd ); obj_handle_t wait_handle = 0; struct async_queue *ifchange_q; - struct async *async; assert( sock->obj.ops == &sock_ops ); @@ -552,10 +551,8 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a return 0; } if (!(ifchange_q = sock_get_ifchange_q( sock ))) return 0; - if (!(async = create_async( current, async_data, NULL ))) return 0; queue_async( ifchange_q, async ); if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ); - release_object( async ); set_error( STATUS_PENDING ); return wait_handle; default: