[PATCH 3/4] kernelbase: Set correct error for abandoned completion port waits.

Paul Gofman pgofman at codeweavers.com
Tue Dec 7 04:59:16 CST 2021


Based on a patch by Alexey Prokhin.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/kernelbase/sync.c  |  2 ++
 dlls/ntdll/tests/sync.c | 28 ++++++++++++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/dlls/kernelbase/sync.c b/dlls/kernelbase/sync.c
index ab963c62221..a5522b1d72a 100644
--- a/dlls/kernelbase/sync.c
+++ b/dlls/kernelbase/sync.c
@@ -1067,6 +1067,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetQueuedCompletionStatus( HANDLE port, LPDWORD co
     }
 
     if (status == STATUS_TIMEOUT) SetLastError( WAIT_TIMEOUT );
+    else if (status == STATUS_ABANDONED_WAIT_0) SetLastError( ERROR_ABANDONED_WAIT_0 );
     else SetLastError( RtlNtStatusToDosError(status) );
     return FALSE;
 }
@@ -1087,6 +1088,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetQueuedCompletionStatusEx( HANDLE port, OVERLAPP
                                   written, get_nt_timeout( &time, timeout ), alertable );
     if (ret == STATUS_SUCCESS) return TRUE;
     else if (ret == STATUS_TIMEOUT) SetLastError( WAIT_TIMEOUT );
+    else if (ret == STATUS_ABANDONED_WAIT_0) SetLastError( ERROR_ABANDONED_WAIT_0 );
     else if (ret == STATUS_USER_APC) SetLastError( WAIT_IO_COMPLETION );
     else SetLastError( RtlNtStatusToDosError(ret) );
     return FALSE;
diff --git a/dlls/ntdll/tests/sync.c b/dlls/ntdll/tests/sync.c
index 562df0f66b0..97e8ba1b778 100644
--- a/dlls/ntdll/tests/sync.c
+++ b/dlls/ntdll/tests/sync.c
@@ -846,8 +846,9 @@ static DWORD WINAPI test_close_io_completion_thread(void *param)
     IO_STATUS_BLOCK iosb;
     ULONG_PTR key, value;
     NTSTATUS status;
+    OVERLAPPED *ov;
+    DWORD ret, err;
     ULONG count;
-    DWORD ret;
 
     ret = WaitForSingleObject( test_close_io_completion_port_ready, INFINITE );
     ok( ret == WAIT_OBJECT_0, "Got unexpected ret %#x.\n", ret );
@@ -869,6 +870,29 @@ static DWORD WINAPI test_close_io_completion_thread(void *param)
     else
         ok( status == STATUS_ABANDONED_WAIT_0, "Got unexpected status %#x.\n", status );
 
+    ret = WaitForSingleObject( test_close_io_completion_port_ready, INFINITE );
+    ok( ret == WAIT_OBJECT_0, "Got unexpected ret %#x.\n", ret );
+    SetEvent( test_close_io_completion_test_ready );
+    ov = (void *)0xdeadbeaf;
+    SetLastError(0xdeadbeef);
+    ret = GetQueuedCompletionStatus( test_close_io_completion_port, &count, &key, &ov, INFINITE );
+    err = GetLastError();
+    ok( !ret && (err == ERROR_ABANDONED_WAIT_0 || err == ERROR_INVALID_HANDLE),
+        "Got unexpected ret %#x, error %u.\n", ret, err );
+    ok( !ov, "Got unexpected ov %p.\n", ov );
+
+    ret = WaitForSingleObject( test_close_io_completion_port_ready, INFINITE );
+    ok( ret == WAIT_OBJECT_0, "Got unexpected ret %#x.\n", ret );
+    SetEvent( test_close_io_completion_test_ready );
+    ov = (void *)0xdeadbeaf;
+    SetLastError(0xdeadbeef);
+    ret = GetQueuedCompletionStatusEx( test_close_io_completion_port, (OVERLAPPED_ENTRY *)&info, 1,
+                                       &count, INFINITE, FALSE );
+    err = GetLastError();
+    ok( !ret && (err == ERROR_ABANDONED_WAIT_0 || err == ERROR_INVALID_HANDLE),
+        "Got unexpected ret %#x, error %u.\n", ret, err );
+    ok( count == 1, "Got unexpected count %u.\n", count );
+
     return 0;
 }
 
@@ -885,7 +909,7 @@ static void test_close_io_completion(void)
     thread = CreateThread( NULL, 0, test_close_io_completion_thread, NULL, 0, NULL );
     ok( !!thread, "Failed to create thread, error %u.\n", GetLastError() );
 
-    for (i = 0; i < 2; ++i)
+    for (i = 0; i < 4; ++i)
     {
         status = NtCreateIoCompletion( &test_close_io_completion_port, IO_COMPLETION_ALL_ACCESS, NULL, 0 );
         ok( !status, "Got unexpected status %#x.\n", status );
-- 
2.33.1




More information about the wine-devel mailing list