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

View file

@ -36,6 +36,9 @@ static BOOLEAN TestWriteCalled = FALSE;
static ULONGLONG Memory = 0; static ULONGLONG Memory = 0;
static BOOLEAN TS = FALSE; static BOOLEAN TS = FALSE;
LARGE_INTEGER WriteOffset;
ULONG WriteLength;
NTSTATUS NTSTATUS
TestEntry( TestEntry(
_In_ PDRIVER_OBJECT DriverObject, _In_ PDRIVER_OBJECT DriverObject,
@ -558,15 +561,17 @@ PerformTest(
} }
else if (TestId == 5) else if (TestId == 5)
{ {
FileSizes.AllocationSize.QuadPart += VACB_MAPPING_GRANULARITY;
CcSetFileSizes(TestFileObject, &FileSizes);
/* Pin after EOF */ /* Pin after EOF */
Ret = FALSE; Ret = FALSE;
Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000; Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000;
KmtStartSeh(); KmtStartSeh();
Ret = CcPinRead(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer); Ret = CcPinRead(TestFileObject, &Offset, 0x1000, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_SUCCESS); KmtEndSeh(STATUS_SUCCESS);
ok(Ret == FALSE, "CcPinRead succeed\n"); ok(Ret == TRUE, "CcPinRead failed\n");
if (Ret) if (Ret)
{ {
CcUnpinData(Bcb); CcUnpinData(Bcb);
@ -577,27 +582,84 @@ PerformTest(
Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000 + VACB_MAPPING_GRANULARITY; Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000 + VACB_MAPPING_GRANULARITY;
KmtStartSeh(); KmtStartSeh();
Ret = CcPinRead(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer); Ret = CcPinRead(TestFileObject, &Offset, 0x1000, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
KmtEndSeh(STATUS_ACCESS_VIOLATION); KmtEndSeh(STATUS_SUCCESS);
ok(Ret == FALSE, "CcPinRead succeed\n"); ok(Ret == TRUE, "CcPinRead failed\n");
if (Ret) if (Ret)
{ {
CcUnpinData(Bcb); 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 */ /* Pin more than a VACB */
Ret = FALSE; Ret = FALSE;
Offset.QuadPart = 0x0; Offset.QuadPart = 0x0;
KmtStartSeh(); 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); KmtEndSeh(STATUS_SUCCESS);
ok(Ret == FALSE, "CcPinRead succeed\n"); ok(Ret == TRUE, "CcPinRead failed\n");
if (Ret) if (Ret)
{ {
/* Set this one dirty */
CcSetDirtyPinnedData(Bcb, NULL);
CcUnpinData(Bcb); 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) else if (TestId == 6)
@ -690,7 +752,7 @@ TestMessageHandler(
ok_eq_ulong((ULONG)InLength, sizeof(ULONG)); ok_eq_ulong((ULONG)InLength, sizeof(ULONG));
PerformTest(*(PULONG)Buffer, DeviceObject); PerformTest(*(PULONG)Buffer, DeviceObject);
break; break;
case IOCTL_FINISH_TEST: case IOCTL_FINISH_TEST:
ok_eq_ulong((ULONG)InLength, sizeof(ULONG)); ok_eq_ulong((ULONG)InLength, sizeof(ULONG));
CleanupTest(*(PULONG)Buffer, DeviceObject); CleanupTest(*(PULONG)Buffer, DeviceObject);
@ -775,28 +837,50 @@ TestIrpHandler(
Offset = IoStack->Parameters.Write.ByteOffset; Offset = IoStack->Parameters.Write.ByteOffset;
Length = IoStack->Parameters.Write.Length; 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(DeviceObject, TestDeviceObject);
ok_eq_pointer(IoStack->FileObject, TestFileObject); ok_eq_pointer(IoStack->FileObject, TestFileObject);
ok(FlagOn(Irp->Flags, IRP_NOCACHE), "Not coming from Cc\n"); ok(FlagOn(Irp->Flags, IRP_NOCACHE), "Not coming from Cc\n");
ok_irql(PASSIVE_LEVEL); 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); if (TestTestId == 5)
ok(Buffer != NULL, "Null pointer!\n"); {
/* This assumes continuous writes. */
if (WriteOffset.QuadPart != -1)
{
LONGLONG WriteEnd = WriteOffset.QuadPart + WriteLength;
Mdl = Irp->MdlAddress; if (WriteOffset.QuadPart > Offset.QuadPart)
ok(Mdl != NULL, "Null pointer for MDL!\n"); WriteOffset = Offset;
ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not locked\n"); if (WriteEnd < (Offset.QuadPart + Length))
ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n"); WriteLength = (Offset.QuadPart + Length) - WriteOffset.QuadPart;
ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n"); }
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"); Buffer = MapAndLockUserBuffer(Irp, Length);
TestWriteCalled = TRUE; 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; Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Length; Irp->IoStatus.Information = Length;