[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