[PATCH 2/2] ntdll: Return STATUS_PENDING from NtReadFile() for async read with regular file.

Paul Gofman gofmanp at gmail.com
Thu Mar 7 03:28:35 CST 2019


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43071
Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
After running grep for ReadFile over the source tree and sorting out
ReadFile() calls with explicit NULL for overlapped structure or
NtReadFile() calls with NULL offset, the following remains:

dlls/user.exe16/comm.c:	Calls ReadFileEx() in comm_waitread() on a device file,
doesn't check any status and relies on completion routine.

dlls/winemac.drv/clipboard.c: Calls ReadFile() on pipe, handles possible outputs.

dlls/quartz/filesource.c: Calls ReadFile() in FileAsyncReader_Request() to queue read request,
does not record the difference between sync or async result. Leaves FileAsyncReader_WaitForNext() to
deal with waits and calling GetOverlappedResult(). I did not unwind the whole
logic behind waits and condition for calling GetOverlappedResult(), but since GetOverlappedResult()
is the only way it uses to get the actual read status and number of bytes read, I suppose it has no
reason to suffer from async return status. Actually the sync result looks a bit more problematic in theory:
GetOverlappedResult() after sync result would hang on Windows (while does not hang under Wine as
file handles are always signalled).

dlls/quartz/filesource.c: sync_read(): Calls ReadFile() on pipe and GetOverlappedResult() in case of
sync return or ERROR_IO_PENDING.

programs/services/rpc.c: Calls ReadFile() on pipe for overlapped read in process_send_command(),
processes async result.


 dlls/ntdll/file.c       |  2 +-
 dlls/ntdll/tests/file.c | 14 +++++++-------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 7ecde56669..e8775a3c64 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -1013,7 +1013,7 @@ err:
         if (status != STATUS_PENDING && hEvent) NtResetEvent( hEvent, NULL );
     }
 
-    ret_status = async_read && (options & FILE_NO_INTERMEDIATE_BUFFERING) && status == STATUS_SUCCESS
+    ret_status = async_read && type == FD_TYPE_FILE && status == STATUS_SUCCESS
             ? STATUS_PENDING : status;
 
     if (send_completion) NTDLL_AddCompletion( hFile, cvalue, status, total, ret_status == STATUS_PENDING );
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 5058439953..d107c2ed2b 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -635,7 +635,7 @@ static void read_file_test(void)
     offset.QuadPart = 0;
     ResetEvent( event );
     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
-    todo_wine ok(status == STATUS_PENDING
+    ok(status == STATUS_PENDING
             || broken(status == STATUS_SUCCESS) /* before Vista */,
             "wrong status %x.\n", status);
     if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
@@ -4450,7 +4450,7 @@ static void test_read_write(void)
     bytes = 0xdeadbeef;
     SetLastError(0xdeadbeef);
     ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
-    todo_wine ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
+    ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
             "Unexpected result, ret %#x, GetLastError() %u.\n", ret, GetLastError());
     ret = GetLastError();
     ok(bytes == 0, "bytes %u\n", bytes);
@@ -4479,7 +4479,7 @@ static void test_read_write(void)
     bytes = 0xdeadbeef;
     SetLastError(0xdeadbeef);
     ret = ReadFile(hfile, NULL, 0, &bytes, &ovl);
-    todo_wine ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
+    ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
             "Unexpected result, ret %#x, GetLastError() %u.\n", ret, GetLastError());
     ret = GetLastError();
     ok(bytes == 0, "bytes %u\n", bytes);
@@ -4524,7 +4524,7 @@ static void test_read_write(void)
     iob.Information = -1;
     offset.QuadPart = sizeof(contents);
     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
-    todo_wine ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
+    ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
             "expected STATUS_PENDING, got %#x.\n", status);
     if (status == STATUS_PENDING)
     {
@@ -4550,7 +4550,7 @@ static void test_read_write(void)
     bytes = 0;
     SetLastError(0xdeadbeef);
     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
-    todo_wine ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
+    ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
             "Unexpected result, ret %#x, GetLastError() %u.\n", ret, GetLastError());
     if (!ret)
         ok(bytes == 0, "bytes %u\n", bytes);
@@ -4598,7 +4598,7 @@ static void test_read_write(void)
     iob.Information = -1;
     offset.QuadPart = 0;
     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
-    todo_wine ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
+    ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
             "expected STATUS_PENDING, got %#x.\n", status);
     if (status == STATUS_PENDING)
     {
@@ -4658,7 +4658,7 @@ static void test_read_write(void)
     bytes = 0;
     SetLastError(0xdeadbeef);
     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
-    todo_wine ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
+    ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
             "Unexpected result %#x, GetLastError() %u.\n", ret, GetLastError());
     if (!ret)
     {
-- 
2.20.1




More information about the wine-devel mailing list