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