From: Pierre Schweitzer Date: Sat, 22 Dec 2018 11:29:18 +0000 (+0100) Subject: [KMTESTS:CC] Add tests for CcSetFileSizes X-Git-Tag: 0.4.13-dev~929 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=ba5d6e977bf36a6248e51bf5ed1588a530cb9baa [KMTESTS:CC] Add tests for CcSetFileSizes These are passing in W2K3 but failing in ReactOS. CORE-11819 --- diff --git a/modules/rostests/kmtests/CMakeLists.txt b/modules/rostests/kmtests/CMakeLists.txt index 623188e913e..feb522be36f 100644 --- a/modules/rostests/kmtests/CMakeLists.txt +++ b/modules/rostests/kmtests/CMakeLists.txt @@ -139,6 +139,7 @@ list(APPEND KMTEST_SOURCE ntos_cc/CcMapData_user.c ntos_cc/CcPinMappedData_user.c ntos_cc/CcPinRead_user.c + ntos_cc/CcSetFileSizes_user.c ntos_io/IoCreateFile_user.c ntos_io/IoDeviceObject_user.c ntos_io/IoReadWrite_user.c diff --git a/modules/rostests/kmtests/kmtest/testlist.c b/modules/rostests/kmtests/kmtest/testlist.c index 5b5b65364bf..0c5e2010d6f 100644 --- a/modules/rostests/kmtests/kmtest/testlist.c +++ b/modules/rostests/kmtests/kmtest/testlist.c @@ -10,6 +10,7 @@ KMT_TESTFUNC Test_CcCopyRead; KMT_TESTFUNC Test_CcMapData; KMT_TESTFUNC Test_CcPinMappedData; KMT_TESTFUNC Test_CcPinRead; +KMT_TESTFUNC Test_CcSetFileSizes; KMT_TESTFUNC Test_Example; KMT_TESTFUNC Test_FileAttributes; KMT_TESTFUNC Test_FindFile; @@ -41,6 +42,7 @@ const KMT_TEST TestList[] = { "CcMapData", Test_CcMapData }, { "CcPinMappedData", Test_CcPinMappedData }, { "CcPinRead", Test_CcPinRead }, + { "CcSetFileSizes", Test_CcSetFileSizes }, { "-Example", Test_Example }, { "FileAttributes", Test_FileAttributes }, { "FindFile", Test_FindFile }, diff --git a/modules/rostests/kmtests/ntos_cc/CMakeLists.txt b/modules/rostests/kmtests/ntos_cc/CMakeLists.txt index 3357f19e68d..8815f5c8979 100644 --- a/modules/rostests/kmtests/ntos_cc/CMakeLists.txt +++ b/modules/rostests/kmtests/ntos_cc/CMakeLists.txt @@ -60,3 +60,18 @@ add_importlibs(ccpinread_drv ntoskrnl hal) add_target_compile_definitions(ccpinread_drv KMT_STANDALONE_DRIVER) #add_pch(ccmapdata_drv ../include/kmt_test.h) add_rostests_file(TARGET ccpinread_drv) + +# +# CcSetFileSizes +# +list(APPEND CCSETFILESIZES_DRV_SOURCE + ../kmtest_drv/kmtest_standalone.c + CcSetFileSizes_drv.c) + +add_library(ccsetfilesizes_drv SHARED ${CCSETFILESIZES_DRV_SOURCE}) +set_module_type(ccsetfilesizes_drv kernelmodedriver) +target_link_libraries(ccsetfilesizes_drv kmtest_printf ${PSEH_LIB}) +add_importlibs(ccsetfilesizes_drv ntoskrnl hal) +add_target_compile_definitions(ccsetfilesizes_drv KMT_STANDALONE_DRIVER) +#add_pch(ccsetfilesizes_drv ../include/kmt_test.h) +add_rostests_file(TARGET ccsetfilesizes_drv) diff --git a/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_drv.c b/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_drv.c new file mode 100644 index 00000000000..cc8840dc85d --- /dev/null +++ b/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_drv.c @@ -0,0 +1,408 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Test driver for CcSetFileSizes function + * PROGRAMMER: Pierre Schweitzer + */ + +#include + +#define NDEBUG +#include + +#define IOCTL_START_TEST 1 +#define IOCTL_FINISH_TEST 2 + +typedef struct _TEST_FCB +{ + FSRTL_ADVANCED_FCB_HEADER Header; + SECTION_OBJECT_POINTERS SectionObjectPointers; + FAST_MUTEX HeaderMutex; +} TEST_FCB, *PTEST_FCB; + +static ULONG TestTestId = -1; +static PFILE_OBJECT TestFileObject; +static PDEVICE_OBJECT TestDeviceObject; +static KMT_IRP_HANDLER TestIrpHandler; +static KMT_MESSAGE_HANDLER TestMessageHandler; + +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"CcSetFileSizes"; + *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE | + TESTENTRY_BUFFERED_IO_DEVICE | + TESTENTRY_NO_READONLY_DEVICE; + + KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler); + KmtRegisterMessageHandler(0, NULL, TestMessageHandler); + + 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 CC_FILE_SIZES NewFileSizes = { + RTL_CONSTANT_LARGE_INTEGER((LONGLONG)VACB_MAPPING_GRANULARITY), // .AllocationSize + RTL_CONSTANT_LARGE_INTEGER((LONGLONG)VACB_MAPPING_GRANULARITY), // .FileSize + RTL_CONSTANT_LARGE_INTEGER((LONGLONG)VACB_MAPPING_GRANULARITY) // .ValidDataLength +}; + +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 +VOID +PerformTest( + ULONG TestId, + PDEVICE_OBJECT DeviceObject) +{ + PVOID Bcb; + BOOLEAN Ret; + PULONG Buffer; + PTEST_FCB Fcb; + LARGE_INTEGER Offset; + IO_STATUS_BLOCK IoStatus; + + ok_eq_pointer(TestFileObject, NULL); + ok_eq_pointer(TestDeviceObject, NULL); + ok_eq_ulong(TestTestId, -1); + + TestDeviceObject = DeviceObject; + TestTestId = TestId; + TestFileObject = IoCreateStreamFileObject(NULL, DeviceObject); + if (!skip(TestFileObject != NULL, "Failed to allocate FO\n")) + { + Fcb = ExAllocatePool(NonPagedPool, sizeof(TEST_FCB)); + if (!skip(Fcb != NULL, "ExAllocatePool failed\n")) + { + RtlZeroMemory(Fcb, sizeof(TEST_FCB)); + ExInitializeFastMutex(&Fcb->HeaderMutex); + FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex); + + TestFileObject->FsContext = Fcb; + TestFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; + Fcb->Header.AllocationSize.QuadPart = VACB_MAPPING_GRANULARITY; + Fcb->Header.FileSize.QuadPart = VACB_MAPPING_GRANULARITY - PAGE_SIZE; + Fcb->Header.ValidDataLength.QuadPart = VACB_MAPPING_GRANULARITY - PAGE_SIZE; + + KmtStartSeh(); + CcInitializeCacheMap(TestFileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize, TRUE, &Callbacks, NULL); + KmtEndSeh(STATUS_SUCCESS); + + if (!skip(CcIsFileCached(TestFileObject) == TRUE, "CcInitializeCacheMap failed\n")) + { + if (TestId == 0) + { + Offset.QuadPart = 0; + KmtStartSeh(); + Ret = CcMapData(TestFileObject, &Offset, VACB_MAPPING_GRANULARITY - PAGE_SIZE, MAP_WAIT, &Bcb, (PVOID *)&Buffer); + KmtEndSeh(STATUS_SUCCESS); + + if (!skip(Ret == TRUE, "CcMapData failed\n")) + { + ok_eq_ulong(Buffer[(VACB_MAPPING_GRANULARITY - PAGE_SIZE - sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA); + CcUnpinData(Bcb); + } + + KmtStartSeh(); + CcSetFileSizes(TestFileObject, &NewFileSizes); + KmtEndSeh(STATUS_SUCCESS); + + Fcb->Header.FileSize.QuadPart = VACB_MAPPING_GRANULARITY; + + Offset.QuadPart = 0; + KmtStartSeh(); + Ret = CcMapData(TestFileObject, &Offset, VACB_MAPPING_GRANULARITY, MAP_WAIT, &Bcb, (PVOID *)&Buffer); + KmtEndSeh(STATUS_SUCCESS); + + if (!skip(Ret == TRUE, "CcMapData failed\n")) + { + ok_eq_ulong(Buffer[(VACB_MAPPING_GRANULARITY - sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA); + + CcUnpinData(Bcb); + } + } + else if (TestId == 1) + { + Buffer = ExAllocatePool(NonPagedPool, PAGE_SIZE); + if (!skip(Buffer != NULL, "ExAllocatePool failed\n")) + { + Ret = FALSE; + Offset.QuadPart = VACB_MAPPING_GRANULARITY - 2 * PAGE_SIZE; + + KmtStartSeh(); + Ret = CcCopyRead(TestFileObject, &Offset, PAGE_SIZE, TRUE, Buffer, &IoStatus); + KmtEndSeh(STATUS_SUCCESS); + + ok_eq_ulong(Buffer[(PAGE_SIZE - sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA); + + KmtStartSeh(); + CcSetFileSizes(TestFileObject, &NewFileSizes); + KmtEndSeh(STATUS_SUCCESS); + + Fcb->Header.FileSize.QuadPart = VACB_MAPPING_GRANULARITY; + RtlZeroMemory(Buffer, PAGE_SIZE); + + Offset.QuadPart = VACB_MAPPING_GRANULARITY - PAGE_SIZE; + + KmtStartSeh(); + Ret = CcCopyRead(TestFileObject, &Offset, PAGE_SIZE, TRUE, Buffer, &IoStatus); + KmtEndSeh(STATUS_SUCCESS); + + ok_eq_ulong(Buffer[(PAGE_SIZE - sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA); + + ExFreePool(Buffer); + } + } + } + } + } +} + + +static +VOID +CleanupTest( + ULONG TestId, + PDEVICE_OBJECT DeviceObject) +{ + LARGE_INTEGER Zero = RTL_CONSTANT_LARGE_INTEGER(0LL); + CACHE_UNINITIALIZE_EVENT CacheUninitEvent; + + ok_eq_pointer(TestDeviceObject, DeviceObject); + ok_eq_ulong(TestTestId, TestId); + + if (!skip(TestFileObject != NULL, "No test FO\n")) + { + if (CcIsFileCached(TestFileObject)) + { + KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE); + CcUninitializeCacheMap(TestFileObject, &Zero, &CacheUninitEvent); + KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL); + } + + if (TestFileObject->FsContext != NULL) + { + ExFreePool(TestFileObject->FsContext); + TestFileObject->FsContext = NULL; + TestFileObject->SectionObjectPointer = NULL; + } + + ObDereferenceObject(TestFileObject); + } + + TestFileObject = NULL; + TestDeviceObject = NULL; + TestTestId = -1; +} + + +static +NTSTATUS +TestMessageHandler( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG ControlCode, + _In_opt_ PVOID Buffer, + _In_ SIZE_T InLength, + _Inout_ PSIZE_T OutLength) +{ + NTSTATUS Status = STATUS_SUCCESS; + + FsRtlEnterFileSystem(); + + switch (ControlCode) + { + case IOCTL_START_TEST: + ok_eq_ulong((ULONG)InLength, sizeof(ULONG)); + PerformTest(*(PULONG)Buffer, DeviceObject); + break; + + case IOCTL_FINISH_TEST: + ok_eq_ulong((ULONG)InLength, sizeof(ULONG)); + CleanupTest(*(PULONG)Buffer, DeviceObject); + break; + + default: + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + FsRtlExitFileSystem(); + + return Status; +} + +static +NTSTATUS +TestIrpHandler( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ PIRP Irp, + _In_ PIO_STACK_LOCATION IoStack) +{ + NTSTATUS Status; + + PAGED_CODE(); + + DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction); + ASSERT(IoStack->MajorFunction == IRP_MJ_READ); + + FsRtlEnterFileSystem(); + + Status = STATUS_NOT_SUPPORTED; + Irp->IoStatus.Information = 0; + + if (IoStack->MajorFunction == IRP_MJ_READ) + { + PMDL Mdl; + ULONG Length; + PVOID Buffer; + PTEST_FCB Fcb; + 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); + ok(Fcb != NULL, "Null FCB\n"); + + ok(FlagOn(Irp->Flags, IRP_NOCACHE), "Not coming from Cc\n"); + + ok_irql(APC_LEVEL); + 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"); + + if (Offset.QuadPart < Fcb->Header.FileSize.QuadPart) + { + RtlFillMemory(Buffer, min(Length, Fcb->Header.FileSize.QuadPart - Offset.QuadPart), 0xBA); + Buffer = (PVOID)((ULONG_PTR)Buffer + (ULONG_PTR)min(Length, Fcb->Header.FileSize.QuadPart - Offset.QuadPart)); + + if (Length > (Fcb->Header.FileSize.QuadPart - Offset.QuadPart)) + { + RtlFillMemory(Buffer, Length - Fcb->Header.FileSize.QuadPart, 0xBD); + } + } + else + { + RtlFillMemory(Buffer, Length, 0xBD); + } + + Status = STATUS_SUCCESS; + + Mdl = Irp->MdlAddress; + ok(Mdl != NULL, "Null pointer for MDL!\n"); + ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not locked\n"); + ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n"); + ok((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0, "Non paging IO\n"); + ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n"); + + Irp->IoStatus.Information = Length; + } + + if (Status == STATUS_PENDING) + { + IoMarkIrpPending(Irp); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + Status = STATUS_PENDING; + } + else + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + FsRtlExitFileSystem(); + + return Status; +} diff --git a/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_user.c b/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_user.c new file mode 100644 index 00000000000..6e8a11dfff7 --- /dev/null +++ b/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_user.c @@ -0,0 +1,34 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Kernel-Mode Test Suite CcSetFileSizes test user-mode part + * PROGRAMMER: Pierre Schweitzer + */ + +#include + +#define IOCTL_START_TEST 1 +#define IOCTL_FINISH_TEST 2 + +START_TEST(CcSetFileSizes) +{ + DWORD Ret; + ULONG TestId; + + KmtLoadDriver(L"CcSetFileSizes", FALSE); + KmtOpenDriver(); + + /* 0: mapped data + * 1: copy read + */ + for (TestId = 0; TestId < 2; ++TestId) + { + Ret = KmtSendUlongToDriver(IOCTL_START_TEST, TestId); + ok(Ret == ERROR_SUCCESS, "KmtSendUlongToDriver failed: %lx\n", Ret); + Ret = KmtSendUlongToDriver(IOCTL_FINISH_TEST, TestId); + ok(Ret == ERROR_SUCCESS, "KmtSendUlongToDriver failed: %lx\n", Ret); + } + + KmtCloseDriver(); + KmtUnloadDriver(); +}