Add a test for ReadFile/WriteFile fault handling, make it pass under Wine

Dmitry Timoshkov dmitry at baikal.ru
Fri Nov 26 06:44:22 CST 2004


Hello,

as promised here is a patch for read/write EFAULT handling.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Add a test for ReadFile/WriteFile fault handling, make it pass
    under Wine.

diff -up cvs/hq/wine/dlls/kernel/file.c wine/dlls/kernel/file.c
--- cvs/hq/wine/dlls/kernel/file.c	2004-11-25 18:15:07.000000000 +0800
+++ wine/dlls/kernel/file.c	2004-11-26 20:33:53.000000000 +0800
@@ -449,13 +449,15 @@ BOOL WINAPI WriteFile( HANDLE hFile, LPC
 
     status = NtWriteFile(hFile, hEvent, NULL, NULL, piosb,
                          buffer, bytesToWrite, poffset, NULL);
+
+    if (status != STATUS_PENDING && bytesWritten)
+        *bytesWritten = piosb->Information;
+
     if (status)
     {
         SetLastError( RtlNtStatusToDosError(status) );
         return FALSE;
     }
-    if (bytesWritten) *bytesWritten = piosb->Information;
-
     return TRUE;
 }
 
diff -up cvs/hq/wine/dlls/kernel/tests/file.c wine/dlls/kernel/tests/file.c
--- cvs/hq/wine/dlls/kernel/tests/file.c	2004-08-31 17:27:40.000000000 +0900
+++ wine/dlls/kernel/tests/file.c	2004-11-26 20:04:19.000000000 +0800
@@ -1265,6 +1265,61 @@ static void test_async_file_errors(void)
     /*printf("Error = %ld\n", GetLastError());*/
 }
 
+static void test_read_write(void)
+{
+    DWORD bytes, ret;
+    HANDLE hFile;
+    char temp_path[MAX_PATH];
+    char filename[MAX_PATH];
+    static const char prefix[] = "pfx";
+
+    ret = GetTempPathA(MAX_PATH, temp_path);
+    ok(ret != 0, "GetTempPathA error %ld\n", GetLastError());
+    ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
+
+    ret = GetTempFileNameA(temp_path, prefix, 0, filename);
+    ok(ret != 0, "GetTempFileNameA error %ld\n", GetLastError());
+
+    hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+                        CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
+    ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %ld\n", GetLastError());
+
+    SetLastError(12345678);
+    bytes = 12345678;
+    ret = WriteFile(hFile, NULL, 0, &bytes, NULL);
+    ok(ret && GetLastError() == 12345678,
+	"ret = %ld, error %ld\n", ret, GetLastError());
+    ok(!bytes, "bytes = %ld\n", bytes);
+
+    SetLastError(12345678);
+    bytes = 12345678;
+    ret = WriteFile(hFile, NULL, 10, &bytes, NULL);
+    ok((!ret && GetLastError() == ERROR_INVALID_USER_BUFFER) || /* Win2k */
+	(ret && GetLastError() == 12345678), /* Win9x */
+	"ret = %ld, error %ld\n", ret, GetLastError());
+    ok(!bytes || /* Win2k */
+	bytes == 10, /* Win9x */
+	"bytes = %ld\n", bytes);
+
+    SetLastError(12345678);
+    bytes = 12345678;
+    ret = ReadFile(hFile, NULL, 0, &bytes, NULL);
+    ok(ret && GetLastError() == 12345678,
+	"ret = %ld, error %ld\n", ret, GetLastError());
+    ok(!bytes, "bytes = %ld\n", bytes);
+
+    SetLastError(12345678);
+    bytes = 12345678;
+    ret = ReadFile(hFile, NULL, 10, &bytes, NULL);
+    ok(!ret && (GetLastError() == ERROR_NOACCESS || /* Win2k */
+		GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
+	"ret = %ld, error %ld\n", ret, GetLastError());
+    ok(!bytes, "bytes = %ld\n", bytes);
+
+    ok(CloseHandle(hFile), "CloseHandle: error %ld\n", GetLastError());
+    ok(DeleteFileA(filename), "DeleteFileA: error %ld\n", GetLastError());
+}
+
 START_TEST(file)
 {
     test__hread(  );
@@ -1292,4 +1347,5 @@ START_TEST(file)
     test_MapFile();
     test_GetFileType();
     test_async_file_errors();
+    test_read_write();
 }
diff -up cvs/hq/wine/dlls/ntdll/file.c wine/dlls/ntdll/file.c
--- cvs/hq/wine/dlls/ntdll/file.c	2004-11-22 17:52:21.000000000 +0800
+++ wine/dlls/ntdll/file.c	2004-11-26 20:33:20.000000000 +0800
@@ -531,8 +531,12 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile,
     while ((io_status->Information = read( unix_handle, buffer, length )) == -1)
     {
         if ((errno == EAGAIN) || (errno == EINTR)) continue;
-        if (errno == EFAULT) FIXME( "EFAULT handling broken for now\n" );
-	io_status->u.Status = FILE_GetNtStatus();
+        if (errno == EFAULT)
+        {
+            io_status->Information = 0;
+            io_status->u.Status = STATUS_ACCESS_VIOLATION;
+        }
+        else io_status->u.Status = FILE_GetNtStatus();
 	break;
     }
     wine_server_release_fd( hFile, unix_handle );
@@ -724,8 +728,12 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile
     while ((io_status->Information = write( unix_handle, buffer, length )) == -1)
     {
         if ((errno == EAGAIN) || (errno == EINTR)) continue;
-        if (errno == EFAULT) FIXME( "EFAULT handling broken for now\n" );
-        if (errno == ENOSPC) io_status->u.Status = STATUS_DISK_FULL;
+        if (errno == EFAULT)
+        {
+            io_status->Information = 0;
+            io_status->u.Status = STATUS_INVALID_USER_BUFFER;
+        }
+        else if (errno == ENOSPC) io_status->u.Status = STATUS_DISK_FULL;
         else io_status->u.Status = FILE_GetNtStatus();
         break;
     }






More information about the wine-patches mailing list