Jacek Caban : server: Always block overlapped device requests until driver dispatches them.
Alexandre Julliard
julliard at winehq.org
Thu May 23 16:04:39 CDT 2019
Module: wine
Branch: master
Commit: a55a287cab25b85c2788e9a07e09057f76e76926
URL: https://source.winehq.org/git/wine.git/?a=commit;h=a55a287cab25b85c2788e9a07e09057f76e76926
Author: Jacek Caban <jacek at codeweavers.com>
Date: Thu May 23 19:36:27 2019 +0200
server: Always block overlapped device requests until driver dispatches them.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/file.c | 2 +-
dlls/ntoskrnl.exe/tests/ntoskrnl.c | 18 ------------------
server/async.c | 21 +++++++++++++++++++++
server/device.c | 9 ++++++---
server/file.h | 1 +
5 files changed, 29 insertions(+), 22 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 1f93c52..1cbaa1b 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 d47943a..49490bb 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 c0b84c2..94cac47 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 6885bf0..1dcd500 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 0621b47..4341ad3 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 );
More information about the wine-cvs
mailing list