In commit 27ecc6ba5 ("ntdll: Fix iosb handling in NtCancelIoFile()"), NtCancelIoFile(Ex) was updated to return its status rather than unconditionally setting it in io_status->u.Status (though the write was retained in the success case). As a result, in the error case, the kernelbase wrappers now interpret unitialized memory as an error code, since io_status->u.Status is never written. Fix that by using the return status instead and add an appropriate test that covers this case.
Issue Reference: https://github.com/JuliaLang/julia/issues/43490
Signed-Off-By: Keno Fischer keno@juliacomputing.com --- dlls/kernel32/tests/pipe.c | 12 ++++++++++++ dlls/kernelbase/file.c | 6 ++---- 2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c index 5af92f8f8a5..f73ef627c67 100644 --- a/dlls/kernel32/tests/pipe.c +++ b/dlls/kernel32/tests/pipe.c @@ -2941,6 +2941,7 @@ static void test_blocking_rw(HANDLE writer, HANDLE reader, DWORD buf_size, BOOL OVERLAPPED read_overlapped, read_overlapped2, write_overlapped, write_overlapped2; char buf[10000], read_buf[10000]; HANDLE flush_thread; + BOOL res;
memset(buf, 0xaa, sizeof(buf));
@@ -3074,6 +3075,17 @@ static void test_blocking_rw(HANDLE writer, HANDLE reader, DWORD buf_size, BOOL overlapped_write_sync(writer, buf, 1); test_overlapped_result(reader, &read_overlapped, 1, FALSE);
+ /* Test that canceling the same operation twice gives a sensible error */ + SetLastError(0xdeadbeef); + overlapped_read_async(reader, read_buf, 1, &read_overlapped2); + res = pCancelIoEx(reader, &read_overlapped2); + ok(res, "CancelIoEx failed with error %d\n", GetLastError()); + res = pCancelIoEx(reader, &read_overlapped2); + ok(!res, "CancelIOEx succeeded unexpectedly"); + ok(GetLastError() == ERROR_NOT_FOUND, + "In CancelIoEx failure, expected ERROR_NOT_FOUND, got %d\n", GetLastError()); + test_overlapped_failure(reader, &read_overlapped2, ERROR_OPERATION_ABORTED); + /* make two async writes, cancel the first one and make sure that we read from the second one */ overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped); overlapped_write_async(writer, buf, 1, &write_overlapped2); diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index 5c7b649d805..576e03eb62b 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -2872,8 +2872,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CancelIo( HANDLE handle ) { IO_STATUS_BLOCK io;
- NtCancelIoFile( handle, &io ); - return set_ntstatus( io.u.Status ); + return set_ntstatus( NtCancelIoFile( handle, &io ) ); }
@@ -2884,8 +2883,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CancelIoEx( HANDLE handle, LPOVERLAPPED overlapped { IO_STATUS_BLOCK io;
- NtCancelIoFileEx( handle, (PIO_STATUS_BLOCK)overlapped, &io ); - return set_ntstatus( io.u.Status ); + return set_ntstatus( NtCancelIoFileEx( handle, (PIO_STATUS_BLOCK)overlapped, &io ) ); }