mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[KMTESTS] Add more tests for CcMapData & CcPinRead
Those show the shortcomings of the current implementation in ReactOS
This commit is contained in:
parent
a6c0af2e21
commit
115b8290cd
2 changed files with 147 additions and 33 deletions
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue