[PATCH v4 2/3] ntdll: Don't return an error when reading past EOF in NtReadFileScatter

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH v4 2/3] ntdll: Don't return an error when reading past EOF in NtReadFileScatter

Andrew Eikum-2
Signed-off-by: Andrew Eikum <[hidden email]>
---
 dlls/kernel32/tests/file.c | 34 +++++++++++++++++++++++++++++++++-
 dlls/ntdll/file.c          |  8 +++-----
 2 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index 4980e02d7d..94feee6372 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;
+    LPVOID wbuf = NULL, rbuf1, rbuf2;
     BOOL br;
 
     evt = CreateEventW( NULL, TRUE, FALSE, NULL );
@@ -4380,6 +4380,9 @@ static void test_WriteFileGather(void)
     rbuf1 = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
     ok( rbuf1 != NULL, "VirtualAlloc failed err %u\n", GetLastError() );
 
+    rbuf2 = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
+    ok( rbuf2 != NULL, "VirtualAlloc failed err %u\n", GetLastError() );
+
     memset( &ovl, 0, sizeof(ovl) );
     ovl.hEvent = evt;
     memset( fse, 0, sizeof(fse) );
@@ -4461,6 +4464,34 @@ static void test_WriteFileGather(void)
 
     ResetEvent( evt );
 
+    /* read past EOF */
+    memset( &ovl, 0, sizeof(ovl) );
+    ovl.hEvent = evt;
+    memset( fse, 0, sizeof(fse) );
+    fse[0].Buffer = rbuf1;
+    fse[1].Buffer = rbuf2;
+    memset( rbuf1, 0, si.dwPageSize );
+    memset( rbuf2, 0x17, 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, "got unexpected bytes transferred: %u\n", tx );
+
+    ok( memcmp( rbuf1, wbuf, si.dwPageSize ) == 0,
+            "data was not read into buffer\n" );
+    memset( rbuf1, 0x17, si.dwPageSize );
+    ok( memcmp( rbuf2, rbuf1, si.dwPageSize ) == 0,
+            "data should not have been read into buffer\n" );
+
     CloseHandle( hfile );
     CloseHandle( hiocp1 );
     CloseHandle( hiocp2 );
@@ -4481,6 +4512,7 @@ static void test_WriteFileGather(void)
 
     VirtualFree( wbuf, 0, MEM_RELEASE );
     VirtualFree( rbuf1, 0, MEM_RELEASE );
+    VirtualFree( rbuf2, 0, MEM_RELEASE );
     CloseHandle( evt );
     DeleteFileA( filename );
 }
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 9df15ffe1d..3d4a94923b 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -1070,11 +1070,7 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
             status = FILE_GetNtStatus();
             break;
         }
-        if (!result)
-        {
-            status = STATUS_END_OF_FILE;
-            break;
-        }
+        if (!result) break;
         total += result;
         length -= result;
         if ((pos += result) == page_size)
@@ -1084,6 +1080,8 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
         }
     }
 
+    if (total == 0) status = STATUS_END_OF_FILE;
+
     send_completion = cvalue != 0;
 
     if (needs_close) close( unix_handle );
--
2.15.1