https://git.reactos.org/?p=reactos.git;a=commitdiff;h=115b8290cd77d5f091937…
commit 115b8290cd77d5f0919378e49df1e76f87b3bea5
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Fri Dec 18 15:23:22 2020 +0100
Commit: Jérôme Gardou <jerome.gardou(a)reactos.org>
CommitDate: Tue Dec 22 11:03:51 2020 +0100
[KMTESTS] Add more tests for CcMapData & CcPinRead
Those show the shortcomings of the current implementation in ReactOS
---
modules/rostests/kmtests/ntos_cc/CcMapData_drv.c | 48 +++++++--
modules/rostests/kmtests/ntos_cc/CcPinRead_drv.c | 130 +++++++++++++++++++----
2 files changed, 146 insertions(+), 32 deletions(-)
diff --git a/modules/rostests/kmtests/ntos_cc/CcMapData_drv.c
b/modules/rostests/kmtests/ntos_cc/CcMapData_drv.c
index 12e8286b936..5e43eb77408 100644
--- a/modules/rostests/kmtests/ntos_cc/CcMapData_drv.c
+++ b/modules/rostests/kmtests/ntos_cc/CcMapData_drv.c
@@ -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);
diff --git a/modules/rostests/kmtests/ntos_cc/CcPinRead_drv.c
b/modules/rostests/kmtests/ntos_cc/CcPinRead_drv.c
index 40a802b566e..3f18625d893 100644
--- a/modules/rostests/kmtests/ntos_cc/CcPinRead_drv.c
+++ b/modules/rostests/kmtests/ntos_cc/CcPinRead_drv.c
@@ -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,13 +582,60 @@ 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 */
@@ -591,13 +643,23 @@ PerformTest(
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;