diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 1f93c5265ac..1cbaa1b2931 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -427,7 +427,7 @@ static async_data_t server_async( HANDLE handle, struct async_fileio *user, HAND static NTSTATUS wait_async( HANDLE handle, BOOL alertable, IO_STATUS_BLOCK *io ) { - NtWaitForSingleObject( handle, alertable, NULL ); + if (NtWaitForSingleObject( handle, alertable, NULL )) return STATUS_PENDING; return io->u.Status; } diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index d47943a9acd..49490bbd1e4 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -216,9 +216,7 @@ static void test_overlapped(void) /* test cancelling all device requests */ res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); - todo_wine ok(res, "DeviceIoControl failed: %u\n", GetLastError()); - if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE); res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %u\n", GetLastError()); @@ -228,9 +226,7 @@ static void test_overlapped(void) cancel_cnt = 0xdeadbeef; res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped); - todo_wine ok(res, "DeviceIoControl failed: %u\n", GetLastError()); - if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE); ok(cancel_cnt == 0, "cancel_cnt = %u\n", cancel_cnt); CancelIo(file); @@ -238,18 +234,13 @@ static void test_overlapped(void) cancel_cnt = 0xdeadbeef; res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped); todo_wine - ok(res, "DeviceIoControl failed: %u\n", GetLastError()); - if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE); - todo_wine ok(cancel_cnt == 2, "cancel_cnt = %u\n", cancel_cnt); /* test cancelling selected overlapped event */ if (pCancelIoEx) { res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); - todo_wine ok(res, "DeviceIoControl failed: %u\n", GetLastError()); - if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE); res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %u\n", GetLastError()); @@ -261,9 +252,7 @@ static void test_overlapped(void) cancel_cnt = 0xdeadbeef; res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped); - todo_wine ok(res, "DeviceIoControl failed: %u\n", GetLastError()); - if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE); todo_wine ok(cancel_cnt == 1, "cancel_cnt = %u\n", cancel_cnt); @@ -271,9 +260,7 @@ static void test_overlapped(void) cancel_cnt = 0xdeadbeef; res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped); - todo_wine ok(res, "DeviceIoControl failed: %u\n", GetLastError()); - if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE); todo_wine ok(cancel_cnt == 2, "cancel_cnt = %u\n", cancel_cnt); } @@ -284,9 +271,7 @@ static void test_overlapped(void) ok(!res && GetLastError() == WAIT_TIMEOUT, "GetQueuedCompletionStatus returned %x(%u)\n", res, GetLastError()); res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); - todo_wine ok(res, "DeviceIoControl failed: %u\n", GetLastError()); - if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE); res = GetQueuedCompletionStatus(port, &size, &key, &o, 0); ok(res, "GetQueuedCompletionStatus failed: %u\n", GetLastError()); ok(o == &overlapped, "o != overlapped\n"); @@ -297,11 +282,8 @@ static void test_overlapped(void) ok(res, "SetFileCompletionNotificationModes failed: %u\n", GetLastError()); res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); - todo_wine ok(res, "DeviceIoControl failed: %u\n", GetLastError()); - if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE); res = GetQueuedCompletionStatus(port, &size, &key, &o, 0); - todo_wine ok(!res && GetLastError() == WAIT_TIMEOUT, "GetQueuedCompletionStatus returned %x(%u)\n", res, GetLastError()); } diff --git a/server/async.c b/server/async.c index c0b84c2d4d7..94cac47f1b9 100644 --- a/server/async.c +++ b/server/async.c @@ -121,6 +121,8 @@ static void async_satisfied( struct object *obj, struct wait_queue_entry *entry close_handle( async->thread->process, async->wait_handle ); async->wait_handle = 0; } + + if (async->status == STATUS_PENDING) make_wait_abandoned( entry ); } static void async_destroy( struct object *obj ) @@ -261,6 +263,19 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da return async; } +void set_async_pending( struct async *async, int signal ) +{ + if (async->status == STATUS_PENDING) + { + async->pending = 1; + if (signal && !async->signaled) + { + async->signaled = 1; + wake_up( &async->obj, 0 ); + } + } +} + /* create an async associated with iosb for async-based requests * returned async must be passed to async_handoff */ struct async *create_request_async( struct fd *fd, unsigned int comp_flags, const async_data_t *data ) @@ -292,6 +307,12 @@ obj_handle_t async_handoff( struct async *async, int success, data_size_t *resul { if (!success) { + if (get_error() == STATUS_PENDING) + { + /* we don't know the result yet, so client needs to wait */ + async->direct_result = 0; + return async->wait_handle; + } close_handle( async->thread->process, async->wait_handle ); async->wait_handle = 0; return 0; diff --git a/server/device.c b/server/device.c index 6885bf0af1f..1dcd5001146 100644 --- a/server/device.c +++ b/server/device.c @@ -597,7 +597,7 @@ static int queue_irp( struct device_file *file, const irp_params_t *params, stru add_irp_to_queue( file->device->manager, irp, current ); release_object( irp ); set_error( STATUS_PENDING ); - return 1; + return 0; } static enum server_fd_type device_file_get_fd_type( struct fd *fd ) @@ -896,8 +896,11 @@ DECL_HANDLER(get_next_device_request) if (manager->current_call) { - free_irp_params( manager->current_call ); - release_object( manager->current_call ); + irp = manager->current_call; + if (irp->async) + set_async_pending( irp->async, irp->file && is_fd_overlapped( irp->file->fd ) ); + free_irp_params( irp ); + release_object( irp ); manager->current_call = NULL; } diff --git a/server/file.h b/server/file.h index 0621b479431..4341ad3b040 100644 --- a/server/file.h +++ b/server/file.h @@ -192,6 +192,7 @@ extern obj_handle_t async_handoff( struct async *async, int success, data_size_t extern void queue_async( struct async_queue *queue, struct async *async ); extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status ); extern void async_set_result( struct object *obj, unsigned int status, apc_param_t total ); +extern void set_async_pending( struct async *async, int signal ); extern int async_waiting( struct async_queue *queue ); extern void async_terminate( struct async *async, unsigned int status ); extern void async_wake_up( struct async_queue *queue, unsigned int status );