Alexandre Julliard : kernel32: Pass the correct completion values in ReadFileScatter and WriteFileGather.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Sep 10 14:47:22 CDT 2014


Module: wine
Branch: master
Commit: 553ba810b8e5034415992d99bf970b2ebb7a85ce
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=553ba810b8e5034415992d99bf970b2ebb7a85ce

Author: Alexandre Julliard <julliard at 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();
 }




More information about the wine-cvs mailing list