From e04da6bb72936b65ed963202d8aa9c94686d6133 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Sun, 28 Nov 2004 14:58:11 +0000 Subject: [PATCH] Add a test for ReadFile/WriteFile fault handling, make it pass under Wine. --- dlls/kernel/file.c | 6 ++++-- dlls/kernel/tests/file.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/file.c | 16 ++++++++++---- 3 files changed, 72 insertions(+), 6 deletions(-) diff --git a/dlls/kernel/file.c b/dlls/kernel/file.c index 342b32475f6..d07f2cf1d5d 100644 --- a/dlls/kernel/file.c +++ b/dlls/kernel/file.c @@ -449,13 +449,15 @@ BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, 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 --git a/dlls/kernel/tests/file.c b/dlls/kernel/tests/file.c index 4bfae610c64..2ce3243d8eb 100644 --- a/dlls/kernel/tests/file.c +++ b/dlls/kernel/tests/file.c @@ -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 --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index e1ee49fa98b..320fb1c71e6 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -531,8 +531,12 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, 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, HANDLE hEvent, 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; } -- 2.11.4.GIT