server: Always block overlapped device requests until driver dispatches them.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2019-05-23 19:36:27 +02:00 committed by Alexandre Julliard
parent 215adcefa3
commit a55a287cab
5 changed files with 29 additions and 22 deletions

View File

@ -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 ) 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; return io->u.Status;
} }

View File

@ -216,9 +216,7 @@ static void test_overlapped(void)
/* test cancelling all device requests */ /* test cancelling all device requests */
res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped);
todo_wine
ok(res, "DeviceIoControl failed: %u\n", GetLastError()); 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); res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped);
ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %u\n", GetLastError()); ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %u\n", GetLastError());
@ -228,9 +226,7 @@ static void test_overlapped(void)
cancel_cnt = 0xdeadbeef; cancel_cnt = 0xdeadbeef;
res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped); 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()); 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); ok(cancel_cnt == 0, "cancel_cnt = %u\n", cancel_cnt);
CancelIo(file); CancelIo(file);
@ -238,18 +234,13 @@ static void test_overlapped(void)
cancel_cnt = 0xdeadbeef; cancel_cnt = 0xdeadbeef;
res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped); res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped);
todo_wine 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); ok(cancel_cnt == 2, "cancel_cnt = %u\n", cancel_cnt);
/* test cancelling selected overlapped event */ /* test cancelling selected overlapped event */
if (pCancelIoEx) if (pCancelIoEx)
{ {
res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped);
todo_wine
ok(res, "DeviceIoControl failed: %u\n", GetLastError()); 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); res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped);
ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %u\n", GetLastError()); ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %u\n", GetLastError());
@ -261,9 +252,7 @@ static void test_overlapped(void)
cancel_cnt = 0xdeadbeef; cancel_cnt = 0xdeadbeef;
res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped); 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()); ok(res, "DeviceIoControl failed: %u\n", GetLastError());
if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE);
todo_wine todo_wine
ok(cancel_cnt == 1, "cancel_cnt = %u\n", cancel_cnt); ok(cancel_cnt == 1, "cancel_cnt = %u\n", cancel_cnt);
@ -271,9 +260,7 @@ static void test_overlapped(void)
cancel_cnt = 0xdeadbeef; cancel_cnt = 0xdeadbeef;
res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped); 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()); ok(res, "DeviceIoControl failed: %u\n", GetLastError());
if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE);
todo_wine todo_wine
ok(cancel_cnt == 2, "cancel_cnt = %u\n", cancel_cnt); 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()); 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); res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped);
todo_wine
ok(res, "DeviceIoControl failed: %u\n", GetLastError()); ok(res, "DeviceIoControl failed: %u\n", GetLastError());
if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE);
res = GetQueuedCompletionStatus(port, &size, &key, &o, 0); res = GetQueuedCompletionStatus(port, &size, &key, &o, 0);
ok(res, "GetQueuedCompletionStatus failed: %u\n", GetLastError()); ok(res, "GetQueuedCompletionStatus failed: %u\n", GetLastError());
ok(o == &overlapped, "o != overlapped\n"); ok(o == &overlapped, "o != overlapped\n");
@ -297,11 +282,8 @@ static void test_overlapped(void)
ok(res, "SetFileCompletionNotificationModes failed: %u\n", GetLastError()); ok(res, "SetFileCompletionNotificationModes failed: %u\n", GetLastError());
res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped);
todo_wine
ok(res, "DeviceIoControl failed: %u\n", GetLastError()); ok(res, "DeviceIoControl failed: %u\n", GetLastError());
if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE);
res = GetQueuedCompletionStatus(port, &size, &key, &o, 0); res = GetQueuedCompletionStatus(port, &size, &key, &o, 0);
todo_wine
ok(!res && GetLastError() == WAIT_TIMEOUT, "GetQueuedCompletionStatus returned %x(%u)\n", res, GetLastError()); ok(!res && GetLastError() == WAIT_TIMEOUT, "GetQueuedCompletionStatus returned %x(%u)\n", res, GetLastError());
} }

View File

@ -121,6 +121,8 @@ static void async_satisfied( struct object *obj, struct wait_queue_entry *entry
close_handle( async->thread->process, async->wait_handle ); close_handle( async->thread->process, async->wait_handle );
async->wait_handle = 0; async->wait_handle = 0;
} }
if (async->status == STATUS_PENDING) make_wait_abandoned( entry );
} }
static void async_destroy( struct object *obj ) 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; 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 /* create an async associated with iosb for async-based requests
* returned async must be passed to async_handoff */ * 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 ) 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 (!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 ); close_handle( async->thread->process, async->wait_handle );
async->wait_handle = 0; async->wait_handle = 0;
return 0; return 0;

View File

@ -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 ); add_irp_to_queue( file->device->manager, irp, current );
release_object( irp ); release_object( irp );
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
return 1; return 0;
} }
static enum server_fd_type device_file_get_fd_type( struct fd *fd ) 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) if (manager->current_call)
{ {
free_irp_params( manager->current_call ); irp = manager->current_call;
release_object( 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; manager->current_call = NULL;
} }

View File

@ -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 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_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 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 int async_waiting( struct async_queue *queue );
extern void async_terminate( struct async *async, unsigned int status ); extern void async_terminate( struct async *async, unsigned int status );
extern void async_wake_up( struct async_queue *queue, unsigned int status ); extern void async_wake_up( struct async_queue *queue, unsigned int status );