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:
parent
215adcefa3
commit
a55a287cab
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
Loading…
Reference in New Issue