[KMTESTS] Add more tests for CcMapData & CcPinRead

Those show the shortcomings of the current implementation in ReactOS
This commit is contained in:
Jérôme Gardou 2020-12-18 15:23:22 +01:00
parent a6c0af2e21
commit 115b8290cd
2 changed files with 147 additions and 33 deletions

View file

@ -371,28 +371,58 @@ PerformTest(
}
else if (TestId == 4)
{
FileSizes.AllocationSize.QuadPart += VACB_MAPPING_GRANULARITY;
CcSetFileSizes(TestFileObject, &FileSizes);
/* Map after EOF */
Ret = FALSE;
Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000;
KmtStartSeh();
Ret = CcMapData(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer);
Ret = CcMapData(TestFileObject, &Offset, 0x1000, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_SUCCESS);
ok(Ret == FALSE, "CcMapData succeed\n");
ok(Ret == TRUE, "CcMapData failed\n");
if (Ret)
{
CcUnpinData(Bcb);
}
/* Map a VACB after EOF */
/* Map a VACB after EOF. */
Ret = FALSE;
Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000 + VACB_MAPPING_GRANULARITY;
KmtStartSeh();
Ret = CcMapData(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_ACCESS_VIOLATION);
ok(Ret == FALSE, "CcMapData succeed\n");
Ret = CcMapData(TestFileObject, &Offset, 0x1000, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_SUCCESS);
ok(Ret == TRUE, "CcMapData failed\n");
if (Ret)
{
CcUnpinData(Bcb);
}
/* Map after Allocation */
Ret = FALSE;
Offset.QuadPart = FileSizes.AllocationSize.QuadPart + 0x1000;
KmtStartSeh();
Ret = CcMapData(TestFileObject, &Offset, 0x1000, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_SUCCESS);
ok(Ret == TRUE, "CcMapData failed\n");
if (Ret)
{
CcUnpinData(Bcb);
}
Ret = FALSE;
Offset.QuadPart = FileSizes.AllocationSize.QuadPart + 0x1000 + VACB_MAPPING_GRANULARITY;
KmtStartSeh();
Ret = CcMapData(TestFileObject, &Offset, 0x1000, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_SUCCESS);
ok(Ret == TRUE, "CcMapData failed\n");
if (Ret)
{
@ -404,9 +434,9 @@ PerformTest(
Offset.QuadPart = 0x0;
KmtStartSeh();
Ret = CcMapData(TestFileObject, &Offset, 0x1000 + VACB_MAPPING_GRANULARITY, 0, &Bcb, (PVOID *)&Buffer);
Ret = CcMapData(TestFileObject, &Offset, 0x1000 + VACB_MAPPING_GRANULARITY, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_SUCCESS);
ok(Ret == FALSE, "CcMapData succeed\n");
ok(Ret == TRUE, "CcMapData failed\n");
if (Ret)
{
@ -475,7 +505,7 @@ TestMessageHandler(
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);

View file

@ -36,6 +36,9 @@ static BOOLEAN TestWriteCalled = FALSE;
static ULONGLONG Memory = 0;
static BOOLEAN TS = FALSE;
LARGE_INTEGER WriteOffset;
ULONG WriteLength;
NTSTATUS
TestEntry(
_In_ PDRIVER_OBJECT DriverObject,
@ -558,15 +561,17 @@ PerformTest(
}
else if (TestId == 5)
{
FileSizes.AllocationSize.QuadPart += VACB_MAPPING_GRANULARITY;
CcSetFileSizes(TestFileObject, &FileSizes);
/* Pin after EOF */
Ret = FALSE;
Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000;
KmtStartSeh();
Ret = CcPinRead(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer);
Ret = CcPinRead(TestFileObject, &Offset, 0x1000, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_SUCCESS);
ok(Ret == FALSE, "CcPinRead succeed\n");
ok(Ret == TRUE, "CcPinRead failed\n");
if (Ret)
{
CcUnpinData(Bcb);
@ -577,27 +582,84 @@ PerformTest(
Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000 + VACB_MAPPING_GRANULARITY;
KmtStartSeh();
Ret = CcPinRead(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_ACCESS_VIOLATION);
ok(Ret == FALSE, "CcPinRead succeed\n");
Ret = CcPinRead(TestFileObject, &Offset, 0x1000, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_SUCCESS);
ok(Ret == TRUE, "CcPinRead failed\n");
if (Ret)
{
CcUnpinData(Bcb);
}
/* Pin after Allocation */
Ret = FALSE;
Offset.QuadPart = FileSizes.AllocationSize.QuadPart + 0x1000;
KmtStartSeh();
Ret = CcPinRead(TestFileObject, &Offset, 0x1000, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_SUCCESS);
ok(Ret == TRUE, "CcPinRead failed\n");
if (Ret)
{
/* Set this one dirty */
CcSetDirtyPinnedData(Bcb, NULL);
CcUnpinData(Bcb);
WriteOffset.QuadPart = -1LL;
WriteLength = MAXULONG;
/* Flush to trigger the write */
CcFlushCache(TestFileObject->SectionObjectPointer, &Offset, 0x1000, NULL);
ok_eq_longlong(WriteOffset.QuadPart, Offset.QuadPart);
ok_eq_ulong(WriteLength, 0x1000);
}
/* Pin a VACB after Allocation */
Ret = FALSE;
Offset.QuadPart = FileSizes.AllocationSize.QuadPart + 0x1000 + VACB_MAPPING_GRANULARITY;
KmtStartSeh();
Ret = CcPinRead(TestFileObject, &Offset, 0x1000, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_SUCCESS);
ok(Ret == TRUE, "CcPinRead failed\n");
if (Ret)
{
/* Set this one dirty */
CcSetDirtyPinnedData(Bcb, NULL);
CcUnpinData(Bcb);
WriteOffset.QuadPart = -1LL;
WriteLength = MAXULONG;
/* Flush to trigger the write */
CcFlushCache(TestFileObject->SectionObjectPointer, &Offset, 0x1000, NULL);
ok_eq_longlong(WriteOffset.QuadPart, Offset.QuadPart);
ok_eq_ulong(WriteLength, 0x1000);
}
/* Pin more than a VACB */
Ret = FALSE;
Offset.QuadPart = 0x0;
KmtStartSeh();
Ret = CcPinRead(TestFileObject, &Offset, 0x1000 + VACB_MAPPING_GRANULARITY, 0, &Bcb, (PVOID *)&Buffer);
Ret = CcPinRead(TestFileObject, &Offset, 0x1000 + VACB_MAPPING_GRANULARITY, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_SUCCESS);
ok(Ret == FALSE, "CcPinRead succeed\n");
ok(Ret == TRUE, "CcPinRead failed\n");
if (Ret)
{
/* Set this one dirty */
CcSetDirtyPinnedData(Bcb, NULL);
CcUnpinData(Bcb);
/* The data is dirtified through the VACB */
WriteOffset.QuadPart = -1LL;
WriteLength = MAXULONG;
CcFlushCache(TestFileObject->SectionObjectPointer, &Offset, VACB_MAPPING_GRANULARITY + 0x1000, NULL);
ok_eq_longlong(WriteOffset.QuadPart, Offset.QuadPart);
ok_eq_ulong(WriteLength, VACB_MAPPING_GRANULARITY + 0x1000);
}
}
else if (TestId == 6)
@ -690,7 +752,7 @@ TestMessageHandler(
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);
@ -775,28 +837,50 @@ TestIrpHandler(
Offset = IoStack->Parameters.Write.ByteOffset;
Length = IoStack->Parameters.Write.Length;
ok(TestTestId == 6, "Unexpected test id: %d\n", TestTestId);
ok((TestTestId == 5) || (TestTestId == 6), "Unexpected test id: %d\n", TestTestId);
ok_eq_pointer(DeviceObject, TestDeviceObject);
ok_eq_pointer(IoStack->FileObject, TestFileObject);
ok(FlagOn(Irp->Flags, IRP_NOCACHE), "Not coming from Cc\n");
ok_irql(PASSIVE_LEVEL);
ok(Offset.QuadPart == 0, "Offset is not null: %I64i\n", Offset.QuadPart);
ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length);
ok(Length == PAGE_SIZE * 4, "Length is not MappedLength-sized: %I64i\n", Length);
Buffer = MapAndLockUserBuffer(Irp, Length);
ok(Buffer != NULL, "Null pointer!\n");
if (TestTestId == 5)
{
/* This assumes continuous writes. */
if (WriteOffset.QuadPart != -1)
{
LONGLONG WriteEnd = WriteOffset.QuadPart + WriteLength;
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((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n");
if (WriteOffset.QuadPart > Offset.QuadPart)
WriteOffset = Offset;
if (WriteEnd < (Offset.QuadPart + Length))
WriteLength = (Offset.QuadPart + Length) - WriteOffset.QuadPart;
}
else
{
WriteOffset = Offset;
WriteLength = Length;
}
}
else
{
ok(Offset.QuadPart == 0, "Offset is not null: %I64i\n", Offset.QuadPart);
ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length);
ok(Length == PAGE_SIZE * 4, "Length is not MappedLength-sized: %I64i\n", Length);
ok_bool_false(TestWriteCalled, "Write has been unexpectedly called twice!\n");
TestWriteCalled = TRUE;
Buffer = MapAndLockUserBuffer(Irp, Length);
ok(Buffer != NULL, "Null pointer!\n");
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((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n");
ok_bool_false(TestWriteCalled, "Write has been unexpectedly called twice!\n");
TestWriteCalled = TRUE;
}
Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Length;