mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 19:26:32 +00:00
[KMTESTS:IO]
- Add a test for the interaction between NtReadFile and a file system driver CORE-9624 svn path=/trunk/; revision=67487
This commit is contained in:
@@ -109,6 +109,7 @@ list(APPEND KMTEST_SOURCE
|
||||
example/Example_user.c
|
||||
kernel32/FindFile_user.c
|
||||
ntos_io/IoDeviceObject_user.c
|
||||
ntos_io/IoReadWrite_user.c
|
||||
tcpip/TcpIp_user.c
|
||||
${COMMON_SOURCE}
|
||||
|
||||
@@ -132,6 +133,7 @@ add_dependencies(kmtest_drivers
|
||||
example_drv
|
||||
iodeviceobject_drv
|
||||
iohelper_drv
|
||||
ioreadwrite_drv
|
||||
tcpip_drv)
|
||||
|
||||
add_custom_target(kmtest_all)
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <winreg.h>
|
||||
#include <winsvc.h>
|
||||
#include <ndk/cmfuncs.h>
|
||||
#include <ndk/iofuncs.h>
|
||||
#include <ndk/obfuncs.h>
|
||||
#include <ndk/rtlfuncs.h>
|
||||
#include <ndk/mmfuncs.h>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
KMT_TESTFUNC Test_Example;
|
||||
KMT_TESTFUNC Test_FindFile;
|
||||
KMT_TESTFUNC Test_IoDeviceObject;
|
||||
KMT_TESTFUNC Test_IoReadWrite;
|
||||
KMT_TESTFUNC Test_RtlAvlTree;
|
||||
KMT_TESTFUNC Test_RtlException;
|
||||
KMT_TESTFUNC Test_RtlIntSafe;
|
||||
@@ -27,6 +28,7 @@ const KMT_TEST TestList[] =
|
||||
{ "-Example", Test_Example },
|
||||
{ "FindFile", Test_FindFile },
|
||||
{ "IoDeviceObject", Test_IoDeviceObject },
|
||||
{ "IoReadWrite", Test_IoReadWrite },
|
||||
{ "RtlAvlTree", Test_RtlAvlTree },
|
||||
{ "RtlException", Test_RtlException },
|
||||
{ "RtlIntSafe", Test_RtlIntSafe },
|
||||
|
||||
@@ -30,3 +30,18 @@ add_importlibs(iohelper_drv ntoskrnl hal)
|
||||
add_target_compile_definitions(iohelper_drv KMT_STANDALONE_DRIVER)
|
||||
#add_pch(iohelper_drv ../include/kmt_test.h)
|
||||
add_cd_file(TARGET iohelper_drv DESTINATION reactos/bin FOR all)
|
||||
|
||||
#
|
||||
# IoReadWrite
|
||||
#
|
||||
list(APPEND IOREADWRITE_DRV_SOURCE
|
||||
../kmtest_drv/kmtest_standalone.c
|
||||
IoReadWrite_drv.c)
|
||||
|
||||
add_library(ioreadwrite_drv SHARED ${IOREADWRITE_DRV_SOURCE})
|
||||
set_module_type(ioreadwrite_drv kernelmodedriver)
|
||||
target_link_libraries(ioreadwrite_drv kmtest_printf ${PSEH_LIB})
|
||||
add_importlibs(ioreadwrite_drv ntoskrnl hal)
|
||||
add_target_compile_definitions(ioreadwrite_drv KMT_STANDALONE_DRIVER)
|
||||
#add_pch(ioreadwrite_drv ../include/kmt_test.h)
|
||||
add_cd_file(TARGET ioreadwrite_drv DESTINATION reactos/bin FOR all)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* PROJECT: ReactOS kernel-mode tests
|
||||
* LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
|
||||
* PURPOSE: Read/Write operations test declarations
|
||||
* PROGRAMMER: Thomas Faber <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _KMTEST_IOREADFILE_H_
|
||||
#define _KMTEST_IOREADFILE_H_
|
||||
|
||||
#define TEST_FILE_SIZE 17
|
||||
|
||||
#define KEY_SUCCEED 0x00
|
||||
#define KEY_FAIL_MISALIGNED 0x81
|
||||
#define KEY_FAIL_OVERFLOW 0x82
|
||||
#define KEY_FAIL_PARTIAL 0x83
|
||||
#define KEY_FAIL_BUSY 0x84
|
||||
#define KEY_FAIL_VERIFY_REQUIRED 0x85
|
||||
|
||||
#define KEY_FAIL_UNSUCCESSFUL 0xc1
|
||||
#define KEY_FAIL_NOT_IMPLEMENTED 0xc2
|
||||
#define KEY_FAIL_ACCESS_VIOLATION 0xc3
|
||||
#define KEY_FAIL_IN_PAGE_ERROR 0xc4
|
||||
#define KEY_FAIL_EOF 0xc5
|
||||
#define KEY_FAIL_ACCESS_DENIED 0xc6
|
||||
#define KEY_FAIL_MISALIGNED_ERROR 0xc7
|
||||
#define KEY_RESULT_MASK 0xff
|
||||
|
||||
#define KEY_NEXT(key) ( (key) == KEY_FAIL_MISALIGNED_ERROR ? 0xff : \
|
||||
(key) == KEY_FAIL_VERIFY_REQUIRED ? KEY_FAIL_UNSUCCESSFUL : \
|
||||
(key) == KEY_SUCCEED ? KEY_FAIL_MISALIGNED : \
|
||||
(key) + 1 )
|
||||
#define KEY_ERROR(key) (((key) & 0xc0) == 0xc0)
|
||||
static
|
||||
NTSTATUS
|
||||
TestGetReturnStatus(
|
||||
_In_ ULONG LockKey)
|
||||
{
|
||||
switch (LockKey & KEY_RESULT_MASK)
|
||||
{
|
||||
case KEY_SUCCEED:
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
case KEY_FAIL_MISALIGNED:
|
||||
return STATUS_DATATYPE_MISALIGNMENT;
|
||||
case KEY_FAIL_OVERFLOW:
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
case KEY_FAIL_PARTIAL:
|
||||
return STATUS_PARTIAL_COPY;
|
||||
case KEY_FAIL_BUSY:
|
||||
return STATUS_DEVICE_BUSY;
|
||||
case KEY_FAIL_VERIFY_REQUIRED:
|
||||
return STATUS_VERIFY_REQUIRED;
|
||||
|
||||
case KEY_FAIL_UNSUCCESSFUL:
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
case KEY_FAIL_NOT_IMPLEMENTED:
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
case KEY_FAIL_ACCESS_VIOLATION:
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
case KEY_FAIL_IN_PAGE_ERROR:
|
||||
return STATUS_IN_PAGE_ERROR;
|
||||
case KEY_FAIL_EOF:
|
||||
return STATUS_END_OF_FILE;
|
||||
case KEY_FAIL_ACCESS_DENIED:
|
||||
return STATUS_ACCESS_DENIED;
|
||||
case KEY_FAIL_MISALIGNED_ERROR:
|
||||
return STATUS_DATATYPE_MISALIGNMENT_ERROR;
|
||||
default:
|
||||
ok(0, "Key = %lx\n", LockKey);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
#define KEY_USE_FASTIO 0x100
|
||||
#define KEY_RETURN_PENDING 0x200
|
||||
|
||||
#define KEY_DATA(c) (((c) & 0xff) << 24)
|
||||
#define KEY_GET_DATA(key) ((key) >> 24)
|
||||
|
||||
#endif /* !defined _KMTEST_IOREADFILE_H_ */
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* PROJECT: ReactOS kernel-mode tests
|
||||
* LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
|
||||
* PURPOSE: Test driver for Read/Write operations
|
||||
* PROGRAMMER: Thomas Faber <[email protected]>
|
||||
*/
|
||||
|
||||
#include <kmt_test.h>
|
||||
#include "IoReadWrite.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
typedef struct _TEST_FCB
|
||||
{
|
||||
FSRTL_ADVANCED_FCB_HEADER Header;
|
||||
SECTION_OBJECT_POINTERS SectionObjectPointers;
|
||||
FAST_MUTEX HeaderMutex;
|
||||
BOOLEAN Cached;
|
||||
} TEST_FCB, *PTEST_FCB;
|
||||
|
||||
static KMT_IRP_HANDLER TestIrpHandler;
|
||||
static FAST_IO_READ TestFastIoRead;
|
||||
static FAST_IO_WRITE TestFastIoWrite;
|
||||
|
||||
static FAST_IO_DISPATCH TestFastIoDispatch;
|
||||
static ULONG TestLastFastReadKey;
|
||||
static ULONG TestLastFastWriteKey;
|
||||
static PFILE_OBJECT TestFileObject;
|
||||
static PDEVICE_OBJECT TestDeviceObject;
|
||||
|
||||
NTSTATUS
|
||||
TestEntry(
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
_In_ PCUNICODE_STRING RegistryPath,
|
||||
_Out_ PCWSTR *DeviceName,
|
||||
_Inout_ INT *Flags)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER(RegistryPath);
|
||||
|
||||
*DeviceName = L"IoReadWrite";
|
||||
*Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE | TESTENTRY_BUFFERED_IO_DEVICE;
|
||||
|
||||
TestFastIoDispatch.FastIoRead = TestFastIoRead;
|
||||
TestFastIoDispatch.FastIoWrite = TestFastIoWrite;
|
||||
DriverObject->FastIoDispatch = &TestFastIoDispatch;
|
||||
|
||||
KmtRegisterIrpHandler(IRP_MJ_CREATE, NULL, TestIrpHandler);
|
||||
KmtRegisterIrpHandler(IRP_MJ_CLEANUP, NULL, TestIrpHandler);
|
||||
KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler);
|
||||
//KmtRegisterIrpHandler(IRP_MJ_WRITE, NULL, TestIrpHandler);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
TestUnload(
|
||||
_In_ PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
TestAcquireForLazyWrite(
|
||||
_In_ PVOID Context,
|
||||
_In_ BOOLEAN Wait)
|
||||
{
|
||||
ok_eq_pointer(Context, NULL);
|
||||
ok(0, "Unexpected call to AcquireForLazyWrite\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
NTAPI
|
||||
TestReleaseFromLazyWrite(
|
||||
_In_ PVOID Context)
|
||||
{
|
||||
ok_eq_pointer(Context, NULL);
|
||||
ok(0, "Unexpected call to ReleaseFromLazyWrite\n");
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
TestAcquireForReadAhead(
|
||||
_In_ PVOID Context,
|
||||
_In_ BOOLEAN Wait)
|
||||
{
|
||||
ok_eq_pointer(Context, NULL);
|
||||
ok(0, "Unexpected call to AcquireForReadAhead\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
NTAPI
|
||||
TestReleaseFromReadAhead(
|
||||
_In_ PVOID Context)
|
||||
{
|
||||
ok_eq_pointer(Context, NULL);
|
||||
ok(0, "Unexpected call to ReleaseFromReadAhead\n");
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
TestCommonRead(
|
||||
_In_ PVOID Buffer,
|
||||
_In_ ULONG Length,
|
||||
_In_ LONGLONG FileOffset,
|
||||
_In_ ULONG LockKey,
|
||||
_Out_ PIO_STATUS_BLOCK IoStatus)
|
||||
{
|
||||
if (FileOffset >= TEST_FILE_SIZE)
|
||||
{
|
||||
trace("FileOffset %I64d > file size\n", FileOffset);
|
||||
IoStatus->Status = STATUS_END_OF_FILE;
|
||||
IoStatus->Information = 0;
|
||||
}
|
||||
else if (Length == 0 || Buffer == NULL)
|
||||
{
|
||||
IoStatus->Status = STATUS_BUFFER_OVERFLOW;
|
||||
IoStatus->Information = TEST_FILE_SIZE - FileOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
Length = min(Length, TEST_FILE_SIZE - FileOffset);
|
||||
RtlFillMemory(Buffer, Length, KEY_GET_DATA(LockKey));
|
||||
IoStatus->Status = TestGetReturnStatus(LockKey);
|
||||
IoStatus->Information = Length;
|
||||
}
|
||||
if (LockKey & KEY_RETURN_PENDING)
|
||||
return STATUS_PENDING;
|
||||
return IoStatus->Status;
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
TestFastIoRead(
|
||||
_In_ PFILE_OBJECT FileObject,
|
||||
_In_ PLARGE_INTEGER FileOffset,
|
||||
_In_ ULONG Length,
|
||||
_In_ BOOLEAN Wait,
|
||||
_In_ ULONG LockKey,
|
||||
_Out_ PVOID Buffer,
|
||||
_Out_ PIO_STATUS_BLOCK IoStatus,
|
||||
_In_ PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PTEST_FCB Fcb;
|
||||
NTSTATUS Status;
|
||||
|
||||
//trace("FastIoRead: %p %lx %I64d+%lu -> %p\n", FileObject, LockKey, FileOffset->QuadPart, Length, Buffer);
|
||||
ok_eq_pointer(FileObject, TestFileObject);
|
||||
ok_bool_true(Wait, "Wait is");
|
||||
ok_eq_pointer(DeviceObject, TestDeviceObject);
|
||||
Fcb = FileObject->FsContext;
|
||||
ok_bool_true(Fcb->Cached, "Cached is");
|
||||
|
||||
TestLastFastReadKey = LockKey;
|
||||
ok((ULONG_PTR)Buffer < MM_USER_PROBE_ADDRESS, "Buffer is %p\n", Buffer);
|
||||
ok((ULONG_PTR)FileOffset > MM_USER_PROBE_ADDRESS, "FileOffset is %p\n", FileOffset);
|
||||
ok((ULONG_PTR)IoStatus > MM_USER_PROBE_ADDRESS, "IoStatus is %p\n", IoStatus);
|
||||
_SEH2_TRY
|
||||
{
|
||||
Status = TestCommonRead(Buffer, Length, FileOffset->QuadPart, LockKey, IoStatus);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
IoStatus->Status = _SEH2_GetExceptionCode();
|
||||
return FALSE;
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
return FALSE;
|
||||
|
||||
if (LockKey & KEY_USE_FASTIO)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
TestFastIoWrite(
|
||||
_In_ PFILE_OBJECT FileObject,
|
||||
_In_ PLARGE_INTEGER FileOffset,
|
||||
_In_ ULONG Length,
|
||||
_In_ BOOLEAN Wait,
|
||||
_In_ ULONG LockKey,
|
||||
_In_ PVOID Buffer,
|
||||
_Out_ PIO_STATUS_BLOCK IoStatus,
|
||||
_In_ PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
TestIrpHandler(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp,
|
||||
_In_ PIO_STACK_LOCATION IoStack)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PTEST_FCB Fcb;
|
||||
CACHE_MANAGER_CALLBACKS Callbacks;
|
||||
CACHE_UNINITIALIZE_EVENT CacheUninitEvent;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction);
|
||||
ASSERT(IoStack->MajorFunction == IRP_MJ_CREATE ||
|
||||
IoStack->MajorFunction == IRP_MJ_CLEANUP ||
|
||||
IoStack->MajorFunction == IRP_MJ_READ ||
|
||||
IoStack->MajorFunction == IRP_MJ_WRITE);
|
||||
|
||||
Status = STATUS_NOT_SUPPORTED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
if (IoStack->MajorFunction == IRP_MJ_CREATE)
|
||||
{
|
||||
if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR))
|
||||
{
|
||||
TestDeviceObject = DeviceObject;
|
||||
TestFileObject = IoStack->FileObject;
|
||||
}
|
||||
Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Fcb), 'FwrI');
|
||||
RtlZeroMemory(Fcb, sizeof(*Fcb));
|
||||
ExInitializeFastMutex(&Fcb->HeaderMutex);
|
||||
FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex);
|
||||
Fcb->Header.AllocationSize.QuadPart = TEST_FILE_SIZE;
|
||||
Fcb->Header.FileSize.QuadPart = TEST_FILE_SIZE;
|
||||
Fcb->Header.ValidDataLength.QuadPart = TEST_FILE_SIZE;
|
||||
IoStack->FileObject->FsContext = Fcb;
|
||||
IoStack->FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
|
||||
if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR) &&
|
||||
IoStack->FileObject->FileName.Buffer[1] != 'N')
|
||||
{
|
||||
Fcb->Cached = TRUE;
|
||||
Callbacks.AcquireForLazyWrite = TestAcquireForLazyWrite;
|
||||
Callbacks.ReleaseFromLazyWrite = TestReleaseFromLazyWrite;
|
||||
Callbacks.AcquireForReadAhead = TestAcquireForReadAhead;
|
||||
Callbacks.ReleaseFromReadAhead = TestReleaseFromReadAhead;
|
||||
CcInitializeCacheMap(IoStack->FileObject,
|
||||
(PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
|
||||
FALSE,
|
||||
&Callbacks,
|
||||
NULL);
|
||||
}
|
||||
Irp->IoStatus.Information = FILE_OPENED;
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else if (IoStack->MajorFunction == IRP_MJ_CLEANUP)
|
||||
{
|
||||
KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE);
|
||||
CcUninitializeCacheMap(IoStack->FileObject, NULL, &CacheUninitEvent);
|
||||
KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL);
|
||||
Fcb = IoStack->FileObject->FsContext;
|
||||
ExFreePoolWithTag(Fcb, 'FwrI');
|
||||
IoStack->FileObject->FsContext = NULL;
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else if (IoStack->MajorFunction == IRP_MJ_READ)
|
||||
{
|
||||
//trace("IRP_MJ_READ: %p %lx %I64d+%lu -> %p\n", IoStack->FileObject, IoStack->Parameters.Read.Key, IoStack->Parameters.Read.ByteOffset.QuadPart, IoStack->Parameters.Read.Length, Irp->AssociatedIrp.SystemBuffer);
|
||||
ok_eq_pointer(DeviceObject, TestDeviceObject);
|
||||
ok_eq_pointer(IoStack->FileObject, TestFileObject);
|
||||
Fcb = IoStack->FileObject->FsContext;
|
||||
if (Fcb->Cached)
|
||||
ok_eq_hex(IoStack->Parameters.Read.Key, TestLastFastReadKey);
|
||||
ok(Irp->AssociatedIrp.SystemBuffer == NULL ||
|
||||
(ULONG_PTR)Irp->AssociatedIrp.SystemBuffer > MM_USER_PROBE_ADDRESS,
|
||||
"Buffer is %p\n",
|
||||
Irp->AssociatedIrp.SystemBuffer);
|
||||
Status = TestCommonRead(Irp->AssociatedIrp.SystemBuffer,
|
||||
IoStack->Parameters.Read.Length,
|
||||
IoStack->Parameters.Read.ByteOffset.QuadPart,
|
||||
IoStack->Parameters.Read.Key,
|
||||
&Irp->IoStatus);
|
||||
}
|
||||
else if (IoStack->MajorFunction == IRP_MJ_WRITE)
|
||||
{
|
||||
ok_eq_pointer(DeviceObject, TestDeviceObject);
|
||||
ok_eq_pointer(IoStack->FileObject, TestFileObject);
|
||||
UNIMPLEMENTED;
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
IoMarkIrpPending(Irp);
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
Status = STATUS_PENDING;
|
||||
}
|
||||
else
|
||||
{
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* 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 <[email protected]>
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, no FastIo, direct return\n");
|
||||
TestRead(FileHandle, FALSE, FALSE, FALSE);
|
||||
trace("Non-Cached, allow FastIo, direct return\n");
|
||||
TestRead(FileHandle, FALSE, TRUE, FALSE);
|
||||
trace("Non-Cached, no FastIo, pending return\n");
|
||||
TestRead(FileHandle, FALSE, FALSE, TRUE);
|
||||
trace("Non-Cached, allow FastIo, pending return\n");
|
||||
TestRead(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, no FastIo, direct return\n");
|
||||
TestRead(FileHandle, TRUE, FALSE, FALSE);
|
||||
trace("Cached, allow FastIo, direct return\n");
|
||||
TestRead(FileHandle, TRUE, TRUE, FALSE);
|
||||
trace("Cached, no FastIo, pending return\n");
|
||||
TestRead(FileHandle, TRUE, FALSE, TRUE);
|
||||
trace("Cached, allow FastIo, pending return\n");
|
||||
TestRead(FileHandle, TRUE, TRUE, TRUE);
|
||||
NtClose(FileHandle);
|
||||
}
|
||||
|
||||
KmtCloseDriver();
|
||||
KmtUnloadDriver();
|
||||
}
|
||||
Reference in New Issue
Block a user