Commit 553ba810 authored by Alexandre Julliard's avatar Alexandre Julliard

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

Test case based on a patch by Guo Jian.
parent 213b244c
...@@ -374,17 +374,20 @@ BOOL WINAPI ReadFileScatter( HANDLE file, FILE_SEGMENT_ELEMENT *segments, DWORD ...@@ -374,17 +374,20 @@ BOOL WINAPI ReadFileScatter( HANDLE file, FILE_SEGMENT_ELEMENT *segments, DWORD
{ {
PIO_STATUS_BLOCK io_status; PIO_STATUS_BLOCK io_status;
LARGE_INTEGER offset; LARGE_INTEGER offset;
void *cvalue = NULL;
NTSTATUS status; NTSTATUS status;
TRACE( "(%p %p %u %p)\n", file, segments, count, overlapped ); TRACE( "(%p %p %u %p)\n", file, segments, count, overlapped );
offset.u.LowPart = overlapped->u.s.Offset; offset.u.LowPart = overlapped->u.s.Offset;
offset.u.HighPart = overlapped->u.s.OffsetHigh; offset.u.HighPart = overlapped->u.s.OffsetHigh;
if (!((ULONG_PTR)overlapped->hEvent & 1)) cvalue = overlapped;
io_status = (PIO_STATUS_BLOCK)overlapped; io_status = (PIO_STATUS_BLOCK)overlapped;
io_status->u.Status = STATUS_PENDING; io_status->u.Status = STATUS_PENDING;
io_status->Information = 0; 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) ); if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status; return !status;
} }
...@@ -513,17 +516,20 @@ BOOL WINAPI WriteFileGather( HANDLE file, FILE_SEGMENT_ELEMENT *segments, DWORD ...@@ -513,17 +516,20 @@ BOOL WINAPI WriteFileGather( HANDLE file, FILE_SEGMENT_ELEMENT *segments, DWORD
{ {
PIO_STATUS_BLOCK io_status; PIO_STATUS_BLOCK io_status;
LARGE_INTEGER offset; LARGE_INTEGER offset;
void *cvalue = NULL;
NTSTATUS status; NTSTATUS status;
TRACE( "%p %p %u %p\n", file, segments, count, overlapped ); TRACE( "%p %p %u %p\n", file, segments, count, overlapped );
offset.u.LowPart = overlapped->u.s.Offset; offset.u.LowPart = overlapped->u.s.Offset;
offset.u.HighPart = overlapped->u.s.OffsetHigh; offset.u.HighPart = overlapped->u.s.OffsetHigh;
if (!((ULONG_PTR)overlapped->hEvent & 1)) cvalue = overlapped;
io_status = (PIO_STATUS_BLOCK)overlapped; io_status = (PIO_STATUS_BLOCK)overlapped;
io_status->u.Status = STATUS_PENDING; io_status->u.Status = STATUS_PENDING;
io_status->Information = 0; 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) ); if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status; return !status;
} }
......
...@@ -3959,6 +3959,63 @@ static void test_SetFileValidData(void) ...@@ -3959,6 +3959,63 @@ static void test_SetFileValidData(void)
DeleteFileA(filename); 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) static unsigned file_map_access(unsigned access)
{ {
if (access & GENERIC_READ) access |= FILE_GENERIC_READ; if (access & GENERIC_READ) access |= FILE_GENERIC_READ;
...@@ -4132,5 +4189,6 @@ START_TEST(file) ...@@ -4132,5 +4189,6 @@ START_TEST(file)
test_GetFileInformationByHandleEx(); test_GetFileInformationByHandleEx();
test_OpenFileById(); test_OpenFileById();
test_SetFileValidData(); test_SetFileValidData();
test_WriteFileGather();
test_file_access(); test_file_access();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment