reactos/modules/rostests/kmtests/ntos_io/IoReadWrite_user.c

389 lines
14 KiB
C

/*
* PROJECT: ReactOS kernel-mode tests
* LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
* PURPOSE: Test for Read/Write operations
* PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
*/
#include <kmt_test.h>
#include "IoReadWrite.h"
static
VOID
TestRead(
_In_ HANDLE FileHandle,
_In_ BOOLEAN Cached,
_In_ BOOLEAN UseFastIo,
_In_ BOOLEAN ReturnPending)
{
NTSTATUS Status;
IO_STATUS_BLOCK IoStatus;
HANDLE EventHandle;
UCHAR Buffer[32];
LARGE_INTEGER Offset;
ULONG BaseKey, StatusKey, Key;
DWORD WaitStatus;
BaseKey = (UseFastIo ? KEY_USE_FASTIO : 0) |
(ReturnPending ? KEY_RETURN_PENDING : 0);
EventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
ok(EventHandle != NULL, "CreateEvent failed with %lu\n", GetLastError());
for (StatusKey = KEY_SUCCEED ; StatusKey != 0xff; StatusKey = KEY_NEXT(StatusKey))
{
//trace("\tSTATUS KEY: %lx\n", StatusKey);
ResetEvent(EventHandle);
RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
Key = BaseKey | StatusKey | KEY_DATA(0x11);
Offset.QuadPart = 0;
Status = NtReadFile(FileHandle,
EventHandle,
NULL,
NULL,
&IoStatus,
NULL,
0,
&Offset,
&Key);
WaitStatus = WaitForSingleObject(EventHandle, 0);
if (ReturnPending)
ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
else
ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW);
if (Cached && UseFastIo && !ReturnPending)
{
ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
ok_eq_hex(IoStatus.Status, STATUS_BUFFER_OVERFLOW);
ok_eq_ulongptr(IoStatus.Information, TEST_FILE_SIZE);
}
else
{
ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
ok_eq_hex(IoStatus.Status, 0x55555555);
ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
}
KmtStartSeh()
ResetEvent(EventHandle);
RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
Key = BaseKey | StatusKey | KEY_DATA(0x22);
Offset.QuadPart = 0;
Status = NtReadFile(FileHandle,
EventHandle,
NULL,
NULL,
&IoStatus,
NULL,
sizeof(Buffer),
&Offset,
&Key);
WaitStatus = WaitForSingleObject(EventHandle, 0);
ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
ok_eq_hex(IoStatus.Status, 0x55555555);
ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
KmtEndSeh(STATUS_SUCCESS);
ResetEvent(EventHandle);
RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
RtlFillMemory(Buffer, sizeof(Buffer), 0x55);
Key = BaseKey | StatusKey | KEY_DATA(0x33);
Offset.QuadPart = 0;
Status = NtReadFile(FileHandle,
EventHandle,
NULL,
NULL,
&IoStatus,
Buffer,
0,
&Offset,
&Key);
WaitStatus = WaitForSingleObject(EventHandle, 0);
if (ReturnPending)
ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
else
ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW);
if (Cached && UseFastIo && !ReturnPending)
{
ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
ok_eq_hex(IoStatus.Status, STATUS_BUFFER_OVERFLOW);
ok_eq_ulongptr(IoStatus.Information, TEST_FILE_SIZE);
}
else
{
ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
ok_eq_hex(IoStatus.Status, 0x55555555);
ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
}
ok_eq_uint(Buffer[0], 0x55);
ResetEvent(EventHandle);
RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
RtlFillMemory(Buffer, sizeof(Buffer), 0x55);
Key = BaseKey | StatusKey | KEY_DATA(0x44);
Offset.QuadPart = 0;
Status = NtReadFile(FileHandle,
EventHandle,
NULL,
NULL,
&IoStatus,
Buffer,
sizeof(Buffer),
&Offset,
&Key);
WaitStatus = WaitForSingleObject(EventHandle, 0);
ok_eq_hex(Status, TestGetReturnStatus(StatusKey));
if ((Cached && UseFastIo && !ReturnPending &&
(StatusKey == KEY_SUCCEED || StatusKey == KEY_FAIL_OVERFLOW || StatusKey == KEY_FAIL_EOF)) ||
!KEY_ERROR(StatusKey))
{
ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
ok_eq_hex(IoStatus.Status, TestGetReturnStatus(StatusKey));
ok_eq_ulongptr(IoStatus.Information, TEST_FILE_SIZE);
}
else
{
ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
ok_eq_hex(IoStatus.Status, 0x55555555);
ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
}
if ((StatusKey != KEY_FAIL_VERIFY_REQUIRED && !KEY_ERROR(StatusKey)) ||
Cached)
{
ok_eq_uint(Buffer[0], 0x44);
ok_eq_uint(Buffer[TEST_FILE_SIZE - 1], 0x44);
ok_eq_uint(Buffer[TEST_FILE_SIZE], 0x55);
}
else
{
ok_eq_uint(Buffer[0], 0x55);
}
}
}
static
VOID
TestWrite(
_In_ HANDLE FileHandle,
_In_ BOOLEAN Cached,
_In_ BOOLEAN UseFastIo,
_In_ BOOLEAN ReturnPending)
{
NTSTATUS Status;
IO_STATUS_BLOCK IoStatus;
HANDLE EventHandle;
UCHAR Buffer[32];
LARGE_INTEGER Offset;
ULONG BaseKey, StatusKey, Key;
DWORD WaitStatus;
BaseKey = (UseFastIo ? KEY_USE_FASTIO : 0) |
(ReturnPending ? KEY_RETURN_PENDING : 0);
EventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
ok(EventHandle != NULL, "CreateEvent failed with %lu\n", GetLastError());
for (StatusKey = KEY_SUCCEED ; StatusKey != 0xff; StatusKey = KEY_NEXT(StatusKey))
{
//trace("\tSTATUS KEY: %lx\n", StatusKey);
ResetEvent(EventHandle);
RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
Key = BaseKey | StatusKey | KEY_DATA(0x11);
Offset.QuadPart = 0;
Status = NtWriteFile(FileHandle,
EventHandle,
NULL,
NULL,
&IoStatus,
NULL,
0,
&Offset,
&Key);
WaitStatus = WaitForSingleObject(EventHandle, 0);
ok_eq_hex(Status, TestGetReturnStatus(StatusKey));
if (!KEY_ERROR(StatusKey))
{
ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
ok_eq_hex(IoStatus.Status, TestGetReturnStatus(StatusKey));
ok_eq_ulongptr(IoStatus.Information, 0);
}
else
{
ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
ok_eq_hex(IoStatus.Status, 0x55555555);
ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
}
KmtStartSeh()
ResetEvent(EventHandle);
RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
Key = BaseKey | StatusKey | KEY_DATA(0x22);
Offset.QuadPart = 0;
Status = NtWriteFile(FileHandle,
EventHandle,
NULL,
NULL,
&IoStatus,
NULL,
sizeof(Buffer),
&Offset,
&Key);
WaitStatus = WaitForSingleObject(EventHandle, 0);
ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
ok_eq_hex(IoStatus.Status, 0x55555555);
ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
KmtEndSeh(STATUS_SUCCESS);
ResetEvent(EventHandle);
RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
RtlFillMemory(Buffer, sizeof(Buffer), 0x55);
Key = BaseKey | StatusKey | KEY_DATA(0x33);
Offset.QuadPart = 0;
Status = NtWriteFile(FileHandle,
EventHandle,
NULL,
NULL,
&IoStatus,
Buffer,
0,
&Offset,
&Key);
WaitStatus = WaitForSingleObject(EventHandle, 0);
ok_eq_hex(Status, TestGetReturnStatus(StatusKey));
if (!KEY_ERROR(StatusKey))
{
ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
ok_eq_hex(IoStatus.Status, TestGetReturnStatus(StatusKey));
ok_eq_ulongptr(IoStatus.Information, 0);
}
else
{
ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
ok_eq_hex(IoStatus.Status, 0x55555555);
ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
}
ResetEvent(EventHandle);
RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
RtlFillMemory(Buffer, sizeof(Buffer), 0x44);
Key = BaseKey | StatusKey | KEY_DATA(0x44);
Offset.QuadPart = 0;
Status = NtWriteFile(FileHandle,
EventHandle,
NULL,
NULL,
&IoStatus,
Buffer,
sizeof(Buffer),
&Offset,
&Key);
WaitStatus = WaitForSingleObject(EventHandle, 0);
ok_eq_hex(Status, TestGetReturnStatus(StatusKey));
if (!KEY_ERROR(StatusKey))
{
ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
ok_eq_hex(IoStatus.Status, TestGetReturnStatus(StatusKey));
ok_eq_ulongptr(IoStatus.Information, sizeof(Buffer));
}
else
{
ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
ok_eq_hex(IoStatus.Status, 0x55555555);
ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
}
}
}
START_TEST(IoReadWrite)
{
HANDLE FileHandle;
UNICODE_STRING CachedFileName = RTL_CONSTANT_STRING(L"\\Device\\Kmtest-IoReadWrite\\Cached");
UNICODE_STRING NonCachedFileName = RTL_CONSTANT_STRING(L"\\Device\\Kmtest-IoReadWrite\\NonCached");
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
KmtLoadDriver(L"IoReadWrite", FALSE);
KmtOpenDriver();
RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
InitializeObjectAttributes(&ObjectAttributes,
&NonCachedFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(&FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatus,
0,
FILE_NON_DIRECTORY_FILE |
FILE_SYNCHRONOUS_IO_NONALERT);
ok_eq_hex(Status, STATUS_SUCCESS);
if (!skip(NT_SUCCESS(Status), "No file\n"))
{
ok_eq_hex(IoStatus.Status, STATUS_SUCCESS);
ok_eq_ulongptr(IoStatus.Information, FILE_OPENED);
trace("Non-Cached read, no FastIo, direct return\n");
TestRead(FileHandle, FALSE, FALSE, FALSE);
trace("Non-Cached read, allow FastIo, direct return\n");
TestRead(FileHandle, FALSE, TRUE, FALSE);
trace("Non-Cached read, no FastIo, pending return\n");
TestRead(FileHandle, FALSE, FALSE, TRUE);
trace("Non-Cached read, allow FastIo, pending return\n");
TestRead(FileHandle, FALSE, TRUE, TRUE);
trace("Non-Cached write, no FastIo, direct return\n");
TestWrite(FileHandle, FALSE, FALSE, FALSE);
trace("Non-Cached write, allow FastIo, direct return\n");
TestWrite(FileHandle, FALSE, TRUE, FALSE);
trace("Non-Cached write, no FastIo, pending return\n");
TestWrite(FileHandle, FALSE, FALSE, TRUE);
trace("Non-Cached write, allow FastIo, pending return\n");
TestWrite(FileHandle, FALSE, TRUE, TRUE);
NtClose(FileHandle);
}
RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
InitializeObjectAttributes(&ObjectAttributes,
&CachedFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(&FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatus,
0,
FILE_NON_DIRECTORY_FILE |
FILE_SYNCHRONOUS_IO_NONALERT);
ok_eq_hex(Status, STATUS_SUCCESS);
if (!skip(NT_SUCCESS(Status), "No file\n"))
{
ok_eq_hex(IoStatus.Status, STATUS_SUCCESS);
ok_eq_ulongptr(IoStatus.Information, FILE_OPENED);
trace("Cached read, no FastIo, direct return\n");
TestRead(FileHandle, TRUE, FALSE, FALSE);
trace("Cached read, allow FastIo, direct return\n");
TestRead(FileHandle, TRUE, TRUE, FALSE);
trace("Cached read, no FastIo, pending return\n");
TestRead(FileHandle, TRUE, FALSE, TRUE);
trace("Cached read, allow FastIo, pending return\n");
TestRead(FileHandle, TRUE, TRUE, TRUE);
trace("Cached write, no FastIo, direct return\n");
TestWrite(FileHandle, TRUE, FALSE, FALSE);
trace("Cached write, allow FastIo, direct return\n");
TestWrite(FileHandle, TRUE, TRUE, FALSE);
trace("Cached write, no FastIo, pending return\n");
TestWrite(FileHandle, TRUE, FALSE, TRUE);
trace("Cached write, allow FastIo, pending return\n");
TestWrite(FileHandle, TRUE, TRUE, TRUE);
NtClose(FileHandle);
}
KmtCloseDriver();
KmtUnloadDriver();
}