[KMTESTS:CC] A pin BCB has a node type code
[reactos.git] / modules / rostests / kmtests / ntos_cc / CcPinRead_drv.c
index 0d63e48..26ae0ed 100644 (file)
@@ -27,7 +27,6 @@ typedef struct _TEST_CONTEXT
     ULONG Length;
 } TEST_CONTEXT, *PTEST_CONTEXT;
 
-static BOOLEAN TestMap = FALSE;
 static ULONG TestTestId = -1;
 static PFILE_OBJECT TestFileObject;
 static PDEVICE_OBJECT TestDeviceObject;
@@ -47,7 +46,7 @@ TestEntry(
 
     UNREFERENCED_PARAMETER(RegistryPath);
 
-    *DeviceName = L"CcMapData";
+    *DeviceName = L"CcPinRead";
     *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE |
              TESTENTRY_BUFFERED_IO_DEVICE |
              TESTENTRY_NO_READONLY_DEVICE;
@@ -148,7 +147,7 @@ MapAndLockUserBuffer(
 static
 VOID
 NTAPI
-MapInAnotherThread(IN PVOID Context)
+PinInAnotherThread(IN PVOID Context)
 {
     BOOLEAN Ret;
     PULONG Buffer;
@@ -168,19 +167,180 @@ MapInAnotherThread(IN PVOID Context)
     Ret = FALSE;
     Offset.QuadPart = 0x1000;
     KmtStartSeh();
-    TestMap = TRUE;
+    Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
+    KmtEndSeh(STATUS_SUCCESS);
+
+    if (!skip(Ret == TRUE, "CcPinRead failed\n"))
+    {
+        ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
+        ok_eq_pointer(Bcb, TestContext->Bcb);
+        ok_eq_pointer(Buffer, TestContext->Buffer);
+
+        CcUnpinData(Bcb);
+    }
+
+    KmtStartSeh();
+    Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer);
+    KmtEndSeh(STATUS_SUCCESS);
+
+    if (!skip(Ret == TRUE, "CcPinRead failed\n"))
+    {
+        ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
+        ok_eq_pointer(Bcb, TestContext->Bcb);
+        ok_eq_pointer(Buffer, TestContext->Buffer);
+
+        CcUnpinData(Bcb);
+    }
+
+    KmtStartSeh();
+    Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer);
+    KmtEndSeh(STATUS_SUCCESS);
+
+    if (!skip(Ret == TRUE, "CcPinRead failed\n"))
+    {
+        ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
+        ok_eq_pointer(Bcb, TestContext->Bcb);
+        ok_eq_pointer(Buffer, TestContext->Buffer);
+
+        CcUnpinData(Bcb);
+    }
+
+    KmtStartSeh();
     Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
-    TestMap = FALSE;
     KmtEndSeh(STATUS_SUCCESS);
 
     if (!skip(Ret == TRUE, "CcMapData failed\n"))
     {
+        ok(Bcb != TestContext->Bcb, "Returned same BCB!\n");
+        ok_eq_pointer(Buffer, TestContext->Buffer);
+
+        CcUnpinData(Bcb);
+    }
+
+    Offset.QuadPart = 0x1500;
+    TestContext->Length -= 0x500;
+
+    KmtStartSeh();
+    Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer);
+    KmtEndSeh(STATUS_SUCCESS);
+
+    if (!skip(Ret == TRUE, "CcPinRead failed\n"))
+    {
+        ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
         ok_eq_pointer(Bcb, TestContext->Bcb);
+        ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500));
+
+        CcUnpinData(Bcb);
+    }
+
+    KmtStartSeh();
+    Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
+    KmtEndSeh(STATUS_SUCCESS);
+
+    if (!skip(Ret == TRUE, "CcPinRead failed\n"))
+    {
+        ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
+        ok_eq_pointer(Bcb, TestContext->Bcb);
+        ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500));
+
+        CcUnpinData(Bcb);
+    }
+
+    KmtStartSeh();
+    Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer);
+    KmtEndSeh(STATUS_SUCCESS);
+
+    if (!skip(Ret == TRUE, "CcPinRead failed\n"))
+    {
+        ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
+        ok_eq_pointer(Bcb, TestContext->Bcb);
+        ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500));
+
+        CcUnpinData(Bcb);
+    }
+
+    return;
+}
+
+static
+VOID
+NTAPI
+PinInAnotherThreadExclusive(IN PVOID Context)
+{
+    BOOLEAN Ret;
+    PULONG Buffer;
+    PVOID Bcb;
+    LARGE_INTEGER Offset;
+    PTEST_CONTEXT TestContext;
+
+    ok(TestFileObject != NULL, "Called in invalid context!\n");
+    ok_eq_ulong(TestTestId, 3);
+
+    TestContext = Context;
+    ok(TestContext != NULL, "Called in invalid context!\n");
+    ok(TestContext->Bcb != NULL, "Called in invalid context!\n");
+    ok(TestContext->Buffer != NULL, "Called in invalid context!\n");
+    ok(TestContext->Length != 0, "Called in invalid context!\n");
+
+    Ret = FALSE;
+    Offset.QuadPart = 0x1000;
+    KmtStartSeh();
+    Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer);
+    KmtEndSeh(STATUS_SUCCESS);
+    ok(Ret == FALSE, "CcPinRead succeed\n");
+
+    if (Ret)
+    {
+        CcUnpinData(Bcb);
+    }
+
+    KmtStartSeh();
+    Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer);
+    KmtEndSeh(STATUS_SUCCESS);
+
+    if (!skip(Ret == TRUE, "CcMapData failed\n"))
+    {
+        ok(Bcb != TestContext->Bcb, "Returned same BCB!\n");
         ok_eq_pointer(Buffer, TestContext->Buffer);
 
         CcUnpinData(Bcb);
     }
 
+    Offset.QuadPart = 0x1500;
+    TestContext->Length -= 0x500;
+
+    KmtStartSeh();
+    Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_IF_BCB, &Bcb, (PVOID *)&Buffer);
+    KmtEndSeh(STATUS_SUCCESS);
+    ok(Ret == FALSE, "CcPinRead succeed\n");
+
+    if (Ret)
+    {
+        CcUnpinData(Bcb);
+    }
+
+    KmtStartSeh();
+    Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer);
+    KmtEndSeh(STATUS_SUCCESS);
+    ok(Ret == FALSE, "CcPinRead succeed\n");
+
+    if (Ret)
+    {
+        CcUnpinData(Bcb);
+    }
+
+    KmtStartSeh();
+    Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer);
+    KmtEndSeh(STATUS_SUCCESS);
+
+    if (!skip(Ret == TRUE, "CcMapData failed\n"))
+    {
+        ok(Bcb != TestContext->Bcb, "Returned same BCB!\n");
+        ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500));
+
+        CcUnpinData(Bcb);
+    }
+
     return;
 }
 
@@ -208,6 +368,8 @@ PerformTest(
         Fcb = ExAllocatePool(NonPagedPool, sizeof(TEST_FCB));
         if (!skip(Fcb != NULL, "ExAllocatePool failed\n"))
         {
+            BOOLEAN PinAccess = (TestId != 4);
+
             RtlZeroMemory(Fcb, sizeof(TEST_FCB));
             ExInitializeFastMutex(&Fcb->HeaderMutex);
             FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex);
@@ -216,7 +378,7 @@ PerformTest(
             TestFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
 
             KmtStartSeh();
-            CcInitializeCacheMap(TestFileObject, &FileSizes, FALSE, &Callbacks, NULL);
+            CcInitializeCacheMap(TestFileObject, &FileSizes, PinAccess, &Callbacks, NULL);
             KmtEndSeh(STATUS_SUCCESS);
 
             if (!skip(CcIsFileCached(TestFileObject) == TRUE, "CcInitializeCacheMap failed\n"))
@@ -226,11 +388,12 @@ PerformTest(
                     Ret = FALSE;
                     Offset.QuadPart = TestId * 0x1000;
                     KmtStartSeh();
-                    Ret = CcMapData(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
+                    Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
                     KmtEndSeh(STATUS_SUCCESS);
 
-                    if (!skip(Ret == TRUE, "CcMapData failed\n"))
+                    if (!skip(Ret == TRUE, "CcPinRead failed\n"))
                     {
+                        ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
                         ok_eq_ulong(Buffer[(0x3000 - TestId * 0x1000) / sizeof(ULONG)], 0xDEADBABE);
 
                         CcUnpinData(Bcb);
@@ -245,16 +408,27 @@ PerformTest(
                     {
                         Ret = FALSE;
                         Offset.QuadPart = 0x1000;
+
+                        /* Try enforce BCB first */
                         KmtStartSeh();
-                        TestMap = TRUE;
-                        Ret = CcMapData(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, MAP_WAIT, &TestContext->Bcb, &TestContext->Buffer);
-                        TestMap = FALSE;
+                        Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer);
                         KmtEndSeh(STATUS_SUCCESS);
+                        ok(Ret == FALSE, "CcPinRead succeed\n");
+                        if (Ret)
+                        {
+                            CcUnpinData(Bcb);
+                        }
 
-                        if (!skip(Ret == TRUE, "CcMapData failed\n"))
+                        KmtStartSeh();
+                        Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &TestContext->Bcb, &TestContext->Buffer);
+                        KmtEndSeh(STATUS_SUCCESS);
+
+                        if (!skip(Ret == TRUE, "CcPinRead failed\n"))
                         {
                             PKTHREAD ThreadHandle;
 
+                            ok(*(PUSHORT)TestContext->Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)TestContext->Bcb);
+
 #ifdef _X86_
                             /* FIXME: Should be fixed, will fail under certains conditions */
                             ok(TestContext->Buffer > (PVOID)0xC1000000 && TestContext->Buffer < (PVOID)0xDCFFFFFF,
@@ -267,13 +441,29 @@ PerformTest(
                             skip(FALSE, "System space mapping not defined\n");
 #endif
 #endif
-
                             TestContext->Length = FileSizes.FileSize.QuadPart - Offset.QuadPart;
-                            ThreadHandle = KmtStartThread(MapInAnotherThread, TestContext);
+                            ThreadHandle = KmtStartThread(PinInAnotherThread, TestContext);
                             KmtFinishThread(ThreadHandle, NULL);
 
                             TestContext->Length = FileSizes.FileSize.QuadPart - 2 * Offset.QuadPart;
-                            ThreadHandle = KmtStartThread(MapInAnotherThread, TestContext);
+                            ThreadHandle = KmtStartThread(PinInAnotherThread, TestContext);
+                            KmtFinishThread(ThreadHandle, NULL);
+
+                            CcUnpinData(TestContext->Bcb);
+                        }
+
+                        KmtStartSeh();
+                        Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT | PIN_EXCLUSIVE, &TestContext->Bcb, &TestContext->Buffer);
+                        KmtEndSeh(STATUS_SUCCESS);
+
+                        if (!skip(Ret == TRUE, "CcPinRead failed\n"))
+                        {
+                            PKTHREAD ThreadHandle;
+
+                            ok(*(PUSHORT)TestContext->Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)TestContext->Bcb);
+
+                            TestContext->Length = FileSizes.FileSize.QuadPart - Offset.QuadPart;
+                            ThreadHandle = KmtStartThread(PinInAnotherThreadExclusive, TestContext);
                             KmtFinishThread(ThreadHandle, NULL);
 
                             CcUnpinData(TestContext->Bcb);
@@ -282,6 +472,66 @@ PerformTest(
                         ExFreePool(TestContext);
                     }
                 }
+                else if (TestId == 4)
+                {
+                    Ret = FALSE;
+                    Offset.QuadPart = 0x1000;
+                    KmtStartSeh();
+                    Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
+                    KmtEndSeh(STATUS_SUCCESS);
+
+                    if (!skip(Ret == TRUE, "CcPinRead failed\n"))
+                    {
+                        ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
+                        ok_eq_ulong(Buffer[0x2000 / sizeof(ULONG)], 0);
+
+                        CcUnpinData(Bcb);
+                    }
+                }
+                else if (TestId == 5)
+                {
+                    /* Pin after EOF */
+                    Ret = FALSE;
+                    Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000;
+
+                    KmtStartSeh();
+                    Ret = CcPinRead(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer);
+                    KmtEndSeh(STATUS_SUCCESS);
+                    ok(Ret == FALSE, "CcPinRead succeed\n");
+
+                    if (Ret)
+                    {
+                        CcUnpinData(Bcb);
+                    }
+
+                    /* Pin a VACB after EOF */
+                    Ret = FALSE;
+                    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");
+
+                    if (Ret)
+                    {
+                        CcUnpinData(Bcb);
+                    }
+
+                    /* Pin more than a VACB */
+                    Ret = FALSE;
+                    Offset.QuadPart = 0x0;
+
+                    KmtStartSeh();
+                    Ret = CcPinRead(TestFileObject, &Offset, 0x1000 + VACB_MAPPING_GRANULARITY, 0, &Bcb, (PVOID *)&Buffer);
+                    KmtEndSeh(STATUS_SUCCESS);
+                    ok(Ret == FALSE, "CcPinRead succeed\n");
+
+                    if (Ret)
+                    {
+                        CcUnpinData(Bcb);
+                    }
+                }
             }
         }
     }
@@ -336,6 +586,8 @@ TestMessageHandler(
 {
     NTSTATUS Status = STATUS_SUCCESS;
 
+    FsRtlEnterFileSystem();
+
     switch (ControlCode)
     {
         case IOCTL_START_TEST:
@@ -353,6 +605,8 @@ TestMessageHandler(
             break;
     }
 
+    FsRtlExitFileSystem();
+
     return Status;
 }
 
@@ -370,6 +624,8 @@ TestIrpHandler(
     DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction);
     ASSERT(IoStack->MajorFunction == IRP_MJ_READ);
 
+    FsRtlEnterFileSystem();
+
     Status = STATUS_NOT_SUPPORTED;
     Irp->IoStatus.Information = 0;
 
@@ -425,5 +681,7 @@ TestIrpHandler(
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
     }
 
+    FsRtlExitFileSystem();
+
     return Status;
 }