From f87a2f0e4cd4d36f3a218ac499d7a8f1933335a5 Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Wed, 6 Dec 2017 15:08:00 -0600 Subject: [PATCH] ntdll: Don't require full-page reads in NtReadFileScatter. Signed-off-by: Andrew Eikum Signed-off-by: Alexandre Julliard --- dlls/kernel32/tests/file.c | 30 +++++++++++++++++++++++++++++- dlls/ntdll/file.c | 5 ++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 94feee6372a..410c3f05912 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -4353,7 +4353,7 @@ static void test_WriteFileGather(void) FILE_SEGMENT_ELEMENT fse[2]; OVERLAPPED ovl, *povl = NULL; SYSTEM_INFO si; - LPVOID wbuf = NULL, rbuf1, rbuf2; + char *wbuf = NULL, *rbuf1, *rbuf2; BOOL br; evt = CreateEventW( NULL, TRUE, FALSE, NULL ); @@ -4492,6 +4492,34 @@ static void test_WriteFileGather(void) ok( memcmp( rbuf2, rbuf1, si.dwPageSize ) == 0, "data should not have been read into buffer\n" ); + ResetEvent( evt ); + + /* partial page read */ + memset( &ovl, 0, sizeof(ovl) ); + ovl.hEvent = evt; + memset( fse, 0, sizeof(fse) ); + fse[0].Buffer = rbuf1; + memset( rbuf1, 0, si.dwPageSize ); + SetLastError( 0xdeadbeef ); + br = ReadFileScatter( hfile, fse, si.dwPageSize / 2, 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 ); + + tx = 0; + br = GetOverlappedResult( hfile, &ovl, &tx, TRUE ); + ok( br == TRUE, "GetOverlappedResult failed: %u\n", GetLastError() ); + ok( tx == si.dwPageSize / 2, "got unexpected bytes transferred: %u\n", tx ); + + ok( memcmp( rbuf1, wbuf, si.dwPageSize / 2 ) == 0, + "invalid data was read into buffer\n" ); + memset( rbuf2, 0, si.dwPageSize ); + ok( memcmp( rbuf1 + si.dwPageSize / 2, rbuf2, si.dwPageSize - si.dwPageSize / 2 ) == 0, + "invalid data was read into buffer\n" ); + CloseHandle( hfile ); CloseHandle( hiocp1 ); CloseHandle( hiocp2 ); diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 3d4a94923b9..570e46c0a7a 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -1041,7 +1041,6 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap TRACE( "(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n", file, event, apc, apc_user, io_status, segments, length, offset, key); - if (length % page_size) return STATUS_INVALID_PARAMETER; if (!io_status) return STATUS_ACCESS_VIOLATION; status = server_get_unix_fd( file, FILE_READ_DATA, &unix_handle, @@ -1060,9 +1059,9 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap { if (offset && offset->QuadPart != FILE_USE_FILE_POINTER_POSITION) result = pread( unix_handle, (char *)segments->Buffer + pos, - page_size - pos, offset->QuadPart + total ); + min( length - pos, page_size - pos ), offset->QuadPart + total ); else - result = read( unix_handle, (char *)segments->Buffer + pos, page_size - pos ); + result = read( unix_handle, (char *)segments->Buffer + pos, min( length - pos, page_size - pos ) ); if (result == -1) {