[PATCH 7/7] server: Move the STATUS_ALERTED logic from async_request_complete() to async_terminate().

Zebediah Figura zfigura at codeweavers.com
Wed Sep 1 17:28:41 CDT 2021


In particular, don't mark asyncs with output data as "alerted", i.e.
restartable.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/ntoskrnl.exe/tests/ntoskrnl.c | 48 +++++++++++++++++++-----------
 server/async.c                     | 17 +++++++----
 2 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
index 8ede0e55513..b85c0078620 100644
--- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
@@ -663,11 +663,12 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     size = 0xdeadf00d;
     SetLastError(0xdeadf00d);
     ret = DeviceIoControl(device, ioctl, params, sizeof(*params), buffer, sizeof(buffer), &size, NULL);
-    todo_wine_if (NT_SUCCESS(expect_status) != NT_SUCCESS(params->iosb_status))
+    todo_wine_if ((params->iosb_status != STATUS_PENDING && NT_SUCCESS(expect_status) != NT_SUCCESS(params->iosb_status))
+            || (params->iosb_status == STATUS_PENDING && NT_SUCCESS(expect_status)))
         ok(ret == NT_SUCCESS(expect_status), "got %d\n", ret);
     if (NT_SUCCESS(expect_status))
     {
-        todo_wine_if (!NT_SUCCESS(params->iosb_status))
+        todo_wine_if (!NT_SUCCESS(params->iosb_status) || params->iosb_status == STATUS_PENDING)
             ok(GetLastError() == 0xdeadf00d, "got error %u\n", GetLastError());
     }
     else
@@ -679,7 +680,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     if (NT_ERROR(expect_status))
         todo_wine ok(size == 0xdeadf00d, "got size %u\n", size);
     else if (!NT_ERROR(params->iosb_status))
-        ok(size == 3, "got size %u\n", size);
+        todo_wine_if (params->iosb_status == STATUS_PENDING) ok(size == 3, "got size %u\n", size);
     /* size is garbage if !NT_ERROR(expect_status) && NT_ERROR(iosb_status) */
     todo_wine_if (ioctl != IOCTL_WINETEST_RETURN_STATUS_BUFFERED)
         ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
@@ -689,8 +690,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     io.Information = 0xdeadf00d;
     ret = NtDeviceIoControlFile(device, NULL, NULL, NULL, &io,
             ioctl, params, sizeof(*params), buffer, sizeof(buffer));
-    todo_wine_if ((params->ret_status != params->iosb_status && params->ret_status != STATUS_PENDING)
-            || params->iosb_status == STATUS_PENDING)
+    todo_wine_if (params->ret_status != params->iosb_status && params->ret_status != STATUS_PENDING)
         ok(ret == expect_status, "got %#x\n", ret);
     if (NT_ERROR(params->iosb_status))
     {
@@ -700,8 +700,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     else
     {
         todo_wine_if (params->iosb_status == STATUS_PENDING)
+        {
             ok(io.Status == params->iosb_status, "got %#x\n", io.Status);
-        ok(io.Information == 3, "got size %Iu\n", io.Information);
+            ok(io.Information == 3, "got size %Iu\n", io.Information);
+        }
     }
     todo_wine_if (ioctl != IOCTL_WINETEST_RETURN_STATUS_BUFFERED)
         ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
@@ -723,7 +725,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     io.Information = 0xdeadf00d;
     ret = NtDeviceIoControlFile(file, event, NULL, (void *)456, &io,
             ioctl, params, sizeof(*params), buffer, sizeof(buffer));
-    todo_wine_if (params->ret_status != params->iosb_status || params->ret_status == STATUS_PENDING)
+    todo_wine_if (params->ret_status != params->iosb_status)
         ok(ret == params->ret_status
                 || broken(NT_WARNING(params->ret_status) && ret == STATUS_PENDING), /* win10 */
                 "got %#x\n", ret);
@@ -737,8 +739,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     else
     {
         todo_wine_if (params->iosb_status == STATUS_PENDING)
+        {
             ok(io.Status == params->iosb_status, "got %#x\n", io.Status);
-        ok(io.Information == 3, "got size %Iu\n", io.Information);
+            ok(io.Information == 3, "got size %Iu\n", io.Information);
+        }
         ret = WaitForSingleObject(event, 0);
         ok(!ret, "got %d\n", ret);
     }
@@ -761,9 +765,9 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
         ok(!ret, "got %#x\n", ret);
         ok(key == 123, "got key %Iu\n", key);
         ok(value == 456, "got value %Iu\n", value);
+        ok(io.Status == params->iosb_status, "got iosb status %#x\n", io.Status);
         todo_wine_if (params->iosb_status == STATUS_PENDING)
-            ok(io.Status == params->iosb_status, "got iosb status %#x\n", io.Status);
-        ok(io.Information == 3, "got information %Iu\n", io.Information);
+            ok(io.Information == 3, "got information %Iu\n", io.Information);
     }
 
     /* As above, but set the event first, to show that the event is always
@@ -774,7 +778,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     io.Information = 0xdeadf00d;
     ret = NtDeviceIoControlFile(file, event, NULL, NULL, &io,
             ioctl, params, sizeof(*params), buffer, sizeof(buffer));
-    todo_wine_if (params->ret_status != params->iosb_status || params->ret_status == STATUS_PENDING)
+    todo_wine_if (params->ret_status != params->iosb_status)
         ok(ret == params->ret_status
                 || broken(NT_WARNING(params->ret_status) && ret == STATUS_PENDING), /* win10 */
                 "got %#x\n", ret);
@@ -788,8 +792,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     else
     {
         todo_wine_if (params->iosb_status == STATUS_PENDING)
+        {
             ok(io.Status == params->iosb_status, "got %#x\n", io.Status);
-        ok(io.Information == 3, "got size %Iu\n", io.Information);
+            ok(io.Information == 3, "got size %Iu\n", io.Information);
+        }
         ret = WaitForSingleObject(event, 0);
         ok(!ret, "got %d\n", ret);
     }
@@ -805,7 +811,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     io.Information = 0xdeadf00d;
     ret = NtDeviceIoControlFile(file, NULL, NULL, NULL, &io,
             ioctl, params, sizeof(*params), buffer, sizeof(buffer));
-    todo_wine_if (params->ret_status != params->iosb_status || params->ret_status == STATUS_PENDING)
+    todo_wine_if (params->ret_status != params->iosb_status)
         ok(ret == params->ret_status
                 || broken(NT_WARNING(params->ret_status) && ret == STATUS_PENDING), /* win10 */
                 "got %#x\n", ret);
@@ -819,8 +825,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     else
     {
         todo_wine_if (params->iosb_status == STATUS_PENDING)
+        {
             ok(io.Status == params->iosb_status, "got %#x\n", io.Status);
-        ok(io.Information == 3, "got size %Iu\n", io.Information);
+            ok(io.Information == 3, "got size %Iu\n", io.Information);
+        }
         ret = WaitForSingleObject(file, 0);
         ok(!ret, "got %d\n", ret);
     }
@@ -840,7 +848,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
         io.Information = 0xdeadf00d;
         ret = NtDeviceIoControlFile(file, event, NULL, (void *)456, &io,
                 ioctl, params, sizeof(*params), buffer, sizeof(buffer));
-        todo_wine_if (params->ret_status != params->iosb_status || params->ret_status == STATUS_PENDING)
+        todo_wine_if (params->ret_status != params->iosb_status)
             ok(ret == params->ret_status
                     || broken(NT_WARNING(params->ret_status) && ret == STATUS_PENDING), /* win10 */
                     "got %#x\n", ret);
@@ -854,8 +862,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
         else
         {
             todo_wine_if (params->iosb_status == STATUS_PENDING)
+            {
                 ok(io.Status == params->iosb_status, "got %#x\n", io.Status);
-            ok(io.Information == 3, "got size %Iu\n", io.Information);
+                ok(io.Information == 3, "got size %Iu\n", io.Information);
+            }
             ret = WaitForSingleObject(event, 0);
             ok(!ret, "got %d\n", ret);
         }
@@ -909,7 +919,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     io.Information = 0xdeadf00d;
     ret = NtDeviceIoControlFile(file, NULL, return_status_apc, (void *)456, &io,
             ioctl, params, sizeof(*params), buffer, sizeof(buffer));
-    todo_wine_if (params->ret_status != params->iosb_status || params->ret_status == STATUS_PENDING)
+    todo_wine_if (params->ret_status != params->iosb_status)
         ok(ret == params->ret_status, "got %#x\n", ret);
     if (!params->pending && NT_ERROR(params->iosb_status))
     {
@@ -919,8 +929,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     else
     {
         todo_wine_if (params->iosb_status == STATUS_PENDING)
+        {
             ok(io.Status == params->iosb_status, "got %#x\n", io.Status);
-        ok(io.Information == 3, "got size %Iu\n", io.Information);
+            ok(io.Information == 3, "got size %Iu\n", io.Information);
+        }
     }
     todo_wine_if (ioctl != IOCTL_WINETEST_RETURN_STATUS_BUFFERED)
         ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
diff --git a/server/async.c b/server/async.c
index 17ef709f89e..e8d95a62d4b 100644
--- a/server/async.c
+++ b/server/async.c
@@ -156,6 +156,8 @@ static void async_destroy( struct object *obj )
 /* notifies client thread of new status of its async request */
 void async_terminate( struct async *async, unsigned int status )
 {
+    struct iosb *iosb = async->iosb;
+
     if (async->terminated) return;
 
     async->terminated = 1;
@@ -176,7 +178,15 @@ void async_terminate( struct async *async, unsigned int status )
         data.type            = APC_ASYNC_IO;
         data.async_io.user   = async->data.user;
         data.async_io.sb     = async->data.iosb;
-        data.async_io.status = status;
+
+        /* if the result is nonzero or there is output data, the client needs to
+         * make an extra request to retrieve them; use STATUS_ALERTED to signal
+         * this case */
+        if (iosb && (iosb->result || iosb->out_data))
+            data.async_io.status = STATUS_ALERTED;
+        else
+            data.async_io.status = status;
+
         thread_queue_apc( async->thread->process, async->thread, &async->obj, &data );
     }
 
@@ -353,11 +363,6 @@ void async_request_complete( struct async *async, unsigned int status, data_size
 
     release_object( iosb );
 
-    /* if the result is nonzero or there is output data, the client needs to
-     * make an extra request to retrieve them; use STATUS_ALERTED to signal
-     * this case */
-    if (result || out_data)
-        status = STATUS_ALERTED;
     async_terminate( async, status );
 }
 
-- 
2.33.0




More information about the wine-devel mailing list