https://git.reactos.org/?p=reactos.git;a=commitdiff;h=115b8290cd77d5f0919378e49df1e76f87b3bea5

commit 115b8290cd77d5f0919378e49df1e76f87b3bea5
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Fri Dec 18 15:23:22 2020 +0100
Commit:     Jérôme Gardou <[email protected]>
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;

Reply via email to