Module: wine Branch: master Commit: 553ba810b8e5034415992d99bf970b2ebb7a85ce URL: http://source.winehq.org/git/wine.git/?a=commit;h=553ba810b8e5034415992d99bf...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Sep 10 13:49:40 2014 +0200
kernel32: Pass the correct completion values in ReadFileScatter and WriteFileGather.
Test case based on a patch by Guo Jian.
---
dlls/kernel32/file.c | 10 ++++++-- dlls/kernel32/tests/file.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/file.c b/dlls/kernel32/file.c index 412659b..cf683df 100644 --- a/dlls/kernel32/file.c +++ b/dlls/kernel32/file.c @@ -374,17 +374,20 @@ BOOL WINAPI ReadFileScatter( HANDLE file, FILE_SEGMENT_ELEMENT *segments, DWORD { PIO_STATUS_BLOCK io_status; LARGE_INTEGER offset; + void *cvalue = NULL; NTSTATUS status;
TRACE( "(%p %p %u %p)\n", file, segments, count, overlapped );
offset.u.LowPart = overlapped->u.s.Offset; offset.u.HighPart = overlapped->u.s.OffsetHigh; + if (!((ULONG_PTR)overlapped->hEvent & 1)) cvalue = overlapped; io_status = (PIO_STATUS_BLOCK)overlapped; io_status->u.Status = STATUS_PENDING; io_status->Information = 0;
- status = NtReadFileScatter( file, NULL, NULL, NULL, io_status, segments, count, &offset, NULL ); + status = NtReadFileScatter( file, overlapped->hEvent, NULL, cvalue, io_status, + segments, count, &offset, NULL ); if (status) SetLastError( RtlNtStatusToDosError(status) ); return !status; } @@ -513,17 +516,20 @@ BOOL WINAPI WriteFileGather( HANDLE file, FILE_SEGMENT_ELEMENT *segments, DWORD { PIO_STATUS_BLOCK io_status; LARGE_INTEGER offset; + void *cvalue = NULL; NTSTATUS status;
TRACE( "%p %p %u %p\n", file, segments, count, overlapped );
offset.u.LowPart = overlapped->u.s.Offset; offset.u.HighPart = overlapped->u.s.OffsetHigh; + if (!((ULONG_PTR)overlapped->hEvent & 1)) cvalue = overlapped; io_status = (PIO_STATUS_BLOCK)overlapped; io_status->u.Status = STATUS_PENDING; io_status->Information = 0;
- status = NtWriteFileGather( file, NULL, NULL, NULL, io_status, segments, count, &offset, NULL ); + status = NtWriteFileGather( file, overlapped->hEvent, NULL, cvalue, io_status, + segments, count, &offset, NULL ); if (status) SetLastError( RtlNtStatusToDosError(status) ); return !status; } diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 492a34f..ddfa019 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -3959,6 +3959,63 @@ static void test_SetFileValidData(void) DeleteFileA(filename); }
+static void test_WriteFileGather(void) +{ + char temp_path[MAX_PATH], filename[MAX_PATH]; + HANDLE hfile, hiocp1, hiocp2; + DWORD ret, size; + ULONG_PTR key; + FILE_SEGMENT_ELEMENT fse[2]; + OVERLAPPED ovl, *povl = NULL; + SYSTEM_INFO si; + LPVOID buf = NULL; + + ret = GetTempPathA( MAX_PATH, temp_path ); + ok( ret != 0, "GetTempPathA error %d\n", GetLastError() ); + ok( ret < MAX_PATH, "temp path should fit into MAX_PATH\n" ); + ret = GetTempFileNameA( temp_path, "wfg", 0, filename ); + ok( ret != 0, "GetTempFileNameA error %d\n", GetLastError() ); + + hfile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL, 0 ); + ok( hfile != INVALID_HANDLE_VALUE, "CreateFile failed err %u\n", GetLastError() ); + if (hfile == INVALID_HANDLE_VALUE) return; + + hiocp1 = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 999, 0 ); + hiocp2 = CreateIoCompletionPort( hfile, hiocp1, 999, 0 ); + 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() ); + + memset( &ovl, 0, sizeof(ovl) ); + memset( fse, 0, sizeof(fse) ); + fse[0].Buffer = buf; + if (!WriteFileGather( hfile, fse, si.dwPageSize, NULL, &ovl )) + ok( GetLastError() == ERROR_IO_PENDING, "WriteFileGather 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 ); + + 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() ); + + ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 1000 ); + ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError()); + ok( povl == &ovl, "wrong ovl %p\n", povl ); + + CloseHandle( hfile ); + CloseHandle( hiocp1 ); + CloseHandle( hiocp2 ); + VirtualFree( buf, 0, MEM_RELEASE ); + DeleteFileA( filename ); +} + static unsigned file_map_access(unsigned access) { if (access & GENERIC_READ) access |= FILE_GENERIC_READ; @@ -4132,5 +4189,6 @@ START_TEST(file) test_GetFileInformationByHandleEx(); test_OpenFileById(); test_SetFileValidData(); + test_WriteFileGather(); test_file_access(); }