This patch sequence fixes Wolfenstein II, Bug 43935.
Signed-off-by: Andrew Eikum aeikum@codeweavers.com --- dlls/kernel32/tests/file.c | 28 ++++++++++++++++++++-------- dlls/ntdll/file.c | 4 +++- 2 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 0b8cef23f8..44fbf7a4b1 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -4353,7 +4353,8 @@ static void test_WriteFileGather(void) FILE_SEGMENT_ELEMENT fse[2]; OVERLAPPED ovl, *povl = NULL; SYSTEM_INFO si; - LPVOID buf = NULL; + BOOL br; + char *wbuf = NULL, *rbuf1;
ret = GetTempPathA( MAX_PATH, temp_path ); ok( ret != 0, "GetTempPathA error %d\n", GetLastError() ); @@ -4371,12 +4372,16 @@ static void test_WriteFileGather(void) ok( hiocp2 != 0, "CreateIoCompletionPort failed err %u\n", GetLastError() );
GetSystemInfo( &si ); - buf = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE ); - ok( buf != NULL, "VirtualAlloc failed err %u\n", GetLastError() ); + wbuf = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE ); + ok( wbuf != NULL, "VirtualAlloc failed err %u\n", GetLastError() ); + + rbuf1 = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE ); + ok( rbuf1 != NULL, "VirtualAlloc failed err %u\n", GetLastError() );
memset( &ovl, 0, sizeof(ovl) ); memset( fse, 0, sizeof(fse) ); - fse[0].Buffer = buf; + memset( wbuf, 0x42, si.dwPageSize ); + fse[0].Buffer = wbuf; if (!WriteFileGather( hfile, fse, si.dwPageSize, NULL, &ovl )) ok( GetLastError() == ERROR_IO_PENDING, "WriteFileGather failed err %u\n", GetLastError() );
@@ -4384,20 +4389,27 @@ static void test_WriteFileGather(void) ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError()); ok( povl == &ovl, "wrong ovl %p\n", povl );
+ /* read exact size */ memset( &ovl, 0, sizeof(ovl) ); memset( fse, 0, sizeof(fse) ); - fse[0].Buffer = buf; - if (!ReadFileScatter( hfile, fse, si.dwPageSize, NULL, &ovl )) - ok( GetLastError() == ERROR_IO_PENDING, "ReadFileScatter failed err %u\n", GetLastError() ); + fse[0].Buffer = rbuf1; + memset( rbuf1, 0, si.dwPageSize ); + br = ReadFileScatter( hfile, fse, si.dwPageSize, NULL, &ovl ); + ok( br == FALSE, "ReadFileScatter should be asynchronous\n" ); + ok( GetLastError() == ERROR_IO_PENDING, "ReadFileScatter failed err %u\n", GetLastError() );
ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 1000 ); ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError()); ok( povl == &ovl, "wrong ovl %p\n", povl );
+ ok( memcmp( rbuf1, wbuf, si.dwPageSize ) == 0, + "data was not read into buffer\n" ); + CloseHandle( hfile ); CloseHandle( hiocp1 ); CloseHandle( hiocp2 ); - VirtualFree( buf, 0, MEM_RELEASE ); + VirtualFree( wbuf, 0, MEM_RELEASE ); + VirtualFree( rbuf1, 0, MEM_RELEASE ); DeleteFileA( filename ); }
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index ca2afa0e89..bdfc383d7e 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -1090,7 +1090,9 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap if (needs_close) close( unix_handle ); if (status == STATUS_SUCCESS) { - io_status->u.Status = status; + /* report status asynchronously */ + status = STATUS_PENDING; + io_status->u.Status = STATUS_SUCCESS; io_status->Information = total; TRACE("= SUCCESS (%u)\n", total); if (event) NtSetEvent( event, NULL );
Andrew Eikum aeikum@codeweavers.com writes:
@@ -1090,7 +1090,9 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap if (needs_close) close( unix_handle ); if (status == STATUS_SUCCESS) {
io_status->u.Status = status;
/* report status asynchronously */
status = STATUS_PENDING;
This will cause the fd completion a few lines below to be reported with STATUS_PENDING, which doesn't seem right.