mirror of
https://github.com/reactos/reactos.git
synced 2024-11-03 05:18:55 +00:00
f27ecf0960
New test case which is matching the MS FastFAT CcCopyRead (minus the offset) and shows clearly the issue in our Cc. It also shows that my hack is utterly broken :-). CORE-11003 CORE-11819 svn path=/trunk/; revision=72182
318 lines
8.7 KiB
C
318 lines
8.7 KiB
C
/*
|
|
* PROJECT: ReactOS kernel-mode tests
|
|
* LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
|
|
* PURPOSE: Test driver for CcCopyRead function
|
|
* PROGRAMMER: Pierre Schweitzer <pierre@reactos.org>
|
|
*/
|
|
|
|
#include <kmt_test.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
typedef struct _TEST_FCB
|
|
{
|
|
FSRTL_ADVANCED_FCB_HEADER Header;
|
|
SECTION_OBJECT_POINTERS SectionObjectPointers;
|
|
FAST_MUTEX HeaderMutex;
|
|
} TEST_FCB, *PTEST_FCB;
|
|
|
|
static PFILE_OBJECT TestFileObject;
|
|
static PDEVICE_OBJECT TestDeviceObject;
|
|
static KMT_IRP_HANDLER TestIrpHandler;
|
|
static FAST_IO_DISPATCH TestFastIoDispatch;
|
|
|
|
static
|
|
BOOLEAN
|
|
NTAPI
|
|
FastIoRead(
|
|
_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)
|
|
{
|
|
IoStatus->Status = STATUS_NOT_SUPPORTED;
|
|
return FALSE;
|
|
}
|
|
|
|
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"CcCopyRead";
|
|
*Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE |
|
|
TESTENTRY_BUFFERED_IO_DEVICE |
|
|
TESTENTRY_NO_READONLY_DEVICE;
|
|
|
|
KmtRegisterIrpHandler(IRP_MJ_CLEANUP, NULL, TestIrpHandler);
|
|
KmtRegisterIrpHandler(IRP_MJ_CREATE, NULL, TestIrpHandler);
|
|
KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler);
|
|
|
|
TestFastIoDispatch.FastIoRead = FastIoRead;
|
|
DriverObject->FastIoDispatch = &TestFastIoDispatch;
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
TestUnload(
|
|
_In_ PDRIVER_OBJECT DriverObject)
|
|
{
|
|
PAGED_CODE();
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
AcquireForLazyWrite(
|
|
_In_ PVOID Context,
|
|
_In_ BOOLEAN Wait)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
ReleaseFromLazyWrite(
|
|
_In_ PVOID Context)
|
|
{
|
|
return;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
AcquireForReadAhead(
|
|
_In_ PVOID Context,
|
|
_In_ BOOLEAN Wait)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
ReleaseFromReadAhead(
|
|
_In_ PVOID Context)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static CACHE_MANAGER_CALLBACKS Callbacks = {
|
|
AcquireForLazyWrite,
|
|
ReleaseFromLazyWrite,
|
|
AcquireForReadAhead,
|
|
ReleaseFromReadAhead,
|
|
};
|
|
|
|
static
|
|
PVOID
|
|
MapAndLockUserBuffer(
|
|
_In_ _Out_ PIRP Irp,
|
|
_In_ ULONG BufferLength)
|
|
{
|
|
PMDL Mdl;
|
|
|
|
if (Irp->MdlAddress == NULL)
|
|
{
|
|
Mdl = IoAllocateMdl(Irp->UserBuffer, BufferLength, FALSE, FALSE, Irp);
|
|
if (Mdl == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
_SEH2_TRY
|
|
{
|
|
MmProbeAndLockPages(Mdl, Irp->RequestorMode, IoWriteAccess);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
IoFreeMdl(Mdl);
|
|
Irp->MdlAddress = NULL;
|
|
_SEH2_YIELD(return NULL);
|
|
}
|
|
_SEH2_END;
|
|
}
|
|
|
|
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
TestIrpHandler(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_In_ PIRP Irp,
|
|
_In_ PIO_STACK_LOCATION IoStack)
|
|
{
|
|
NTSTATUS Status;
|
|
PTEST_FCB Fcb;
|
|
CACHE_UNINITIALIZE_EVENT CacheUninitEvent;
|
|
|
|
PAGED_CODE();
|
|
|
|
DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction);
|
|
ASSERT(IoStack->MajorFunction == IRP_MJ_CLEANUP ||
|
|
IoStack->MajorFunction == IRP_MJ_CREATE ||
|
|
IoStack->MajorFunction == IRP_MJ_READ);
|
|
|
|
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);
|
|
if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR) &&
|
|
IoStack->FileObject->FileName.Buffer[1] == 'B')
|
|
{
|
|
Fcb->Header.AllocationSize.QuadPart = 1000000;
|
|
Fcb->Header.FileSize.QuadPart = 1000000;
|
|
Fcb->Header.ValidDataLength.QuadPart = 1000000;
|
|
}
|
|
else if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR) &&
|
|
IoStack->FileObject->FileName.Buffer[1] == 'S')
|
|
{
|
|
Fcb->Header.AllocationSize.QuadPart = 1004;
|
|
Fcb->Header.FileSize.QuadPart = 1004;
|
|
Fcb->Header.ValidDataLength.QuadPart = 1004;
|
|
}
|
|
else if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR) &&
|
|
IoStack->FileObject->FileName.Buffer[1] == 'R')
|
|
{
|
|
Fcb->Header.AllocationSize.QuadPart = 62;
|
|
Fcb->Header.FileSize.QuadPart = 62;
|
|
Fcb->Header.ValidDataLength.QuadPart = 62;
|
|
}
|
|
else
|
|
{
|
|
Fcb->Header.AllocationSize.QuadPart = 512;
|
|
Fcb->Header.FileSize.QuadPart = 512;
|
|
Fcb->Header.ValidDataLength.QuadPart = 512;
|
|
}
|
|
Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
|
|
IoStack->FileObject->FsContext = Fcb;
|
|
IoStack->FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
|
|
|
|
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_READ)
|
|
{
|
|
BOOLEAN Ret;
|
|
ULONG Length;
|
|
PVOID Buffer;
|
|
LARGE_INTEGER Offset;
|
|
|
|
Offset = IoStack->Parameters.Read.ByteOffset;
|
|
Length = IoStack->Parameters.Read.Length;
|
|
Fcb = IoStack->FileObject->FsContext;
|
|
|
|
ok_eq_pointer(DeviceObject, TestDeviceObject);
|
|
ok_eq_pointer(IoStack->FileObject, TestFileObject);
|
|
|
|
if (!FlagOn(Irp->Flags, IRP_NOCACHE))
|
|
{
|
|
ok(Offset.QuadPart % PAGE_SIZE != 0, "Offset is aligned: %I64i\n", Offset.QuadPart);
|
|
ok(Length % PAGE_SIZE != 0, "Length is aligned: %I64i\n", Length);
|
|
|
|
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
|
ok(Buffer != NULL, "Null pointer!\n");
|
|
|
|
_SEH2_TRY
|
|
{
|
|
Ret = CcCopyRead(IoStack->FileObject, &Offset, Length, TRUE, Buffer,
|
|
&Irp->IoStatus);
|
|
ok_bool_true(Ret, "CcCopyRead");
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Irp->IoStatus.Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END;
|
|
|
|
Status = Irp->IoStatus.Status;
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (Offset.QuadPart <= 1000LL && Offset.QuadPart + Length > 1000LL)
|
|
{
|
|
ok_eq_hex(*(PUSHORT)((ULONG_PTR)Buffer + (ULONG_PTR)(1000LL - Offset.QuadPart)), 0xFFFF);
|
|
}
|
|
else
|
|
{
|
|
ok_eq_hex(*(PUSHORT)Buffer, 0xBABA);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ok((Offset.QuadPart % PAGE_SIZE == 0 || Offset.QuadPart == 0), "Offset is not aligned: %I64i\n", Offset.QuadPart);
|
|
ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length);
|
|
|
|
ok(Irp->AssociatedIrp.SystemBuffer == NULL, "A SystemBuffer was allocated!\n");
|
|
Buffer = MapAndLockUserBuffer(Irp, Length);
|
|
ok(Buffer != NULL, "Null pointer!\n");
|
|
RtlFillMemory(Buffer, Length, 0xBA);
|
|
|
|
Status = STATUS_SUCCESS;
|
|
if (Offset.QuadPart <= 1000LL && Offset.QuadPart + Length > 1000LL)
|
|
{
|
|
*(PUSHORT)((ULONG_PTR)Buffer + (ULONG_PTR)(1000LL - Offset.QuadPart)) = 0xFFFF;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Irp->IoStatus.Information = Length;
|
|
IoStack->FileObject->CurrentByteOffset.QuadPart = Offset.QuadPart + Length;
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|