1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory 4 * PURPOSE: Test driver for CcPinRead function 5 * PROGRAMMER: Pierre Schweitzer <pierre@reactos.org> 6 */ 7 8 #include <kmt_test.h> 9 10 #define NDEBUG 11 #include <debug.h> 12 13 #define IOCTL_START_TEST 1 14 #define IOCTL_FINISH_TEST 2 15 16 typedef struct _TEST_FCB 17 { 18 FSRTL_ADVANCED_FCB_HEADER Header; 19 SECTION_OBJECT_POINTERS SectionObjectPointers; 20 FAST_MUTEX HeaderMutex; 21 } TEST_FCB, *PTEST_FCB; 22 23 typedef struct _TEST_CONTEXT 24 { 25 PVOID Bcb; 26 PVOID Buffer; 27 ULONG Length; 28 } TEST_CONTEXT, *PTEST_CONTEXT; 29 30 static ULONG TestTestId = -1; 31 static PFILE_OBJECT TestFileObject; 32 static PDEVICE_OBJECT TestDeviceObject; 33 static KMT_IRP_HANDLER TestIrpHandler; 34 static KMT_MESSAGE_HANDLER TestMessageHandler; 35 static BOOLEAN TestWriteCalled = FALSE; 36 static ULONGLONG Memory = 0; 37 static BOOLEAN TS = FALSE; 38 39 NTSTATUS 40 TestEntry( 41 _In_ PDRIVER_OBJECT DriverObject, 42 _In_ PCUNICODE_STRING RegistryPath, 43 _Out_ PCWSTR *DeviceName, 44 _Inout_ INT *Flags) 45 { 46 ULONG Length; 47 SYSTEM_BASIC_INFORMATION SBI; 48 NTSTATUS Status = STATUS_SUCCESS; 49 RTL_OSVERSIONINFOEXW VersionInfo; 50 51 PAGED_CODE(); 52 53 UNREFERENCED_PARAMETER(RegistryPath); 54 55 *DeviceName = L"CcPinRead"; 56 *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE | 57 TESTENTRY_BUFFERED_IO_DEVICE | 58 TESTENTRY_NO_READONLY_DEVICE; 59 60 KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler); 61 KmtRegisterIrpHandler(IRP_MJ_WRITE, NULL, TestIrpHandler); 62 KmtRegisterMessageHandler(0, NULL, TestMessageHandler); 63 64 Status = ZwQuerySystemInformation(SystemBasicInformation, 65 &SBI, 66 sizeof(SBI), 67 &Length); 68 if (NT_SUCCESS(Status)) 69 { 70 Memory = (SBI.NumberOfPhysicalPages * SBI.PageSize) / 1024 / 1024; 71 } 72 else 73 { 74 Status = STATUS_SUCCESS; 75 } 76 77 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo); 78 Status = RtlGetVersion((PRTL_OSVERSIONINFOW)&VersionInfo); 79 if (NT_SUCCESS(Status)) 80 { 81 TS = BooleanFlagOn(VersionInfo.wSuiteMask, VER_SUITE_TERMINAL) && 82 !BooleanFlagOn(VersionInfo.wSuiteMask, VER_SUITE_SINGLEUSERTS); 83 } 84 else 85 { 86 Status = STATUS_SUCCESS; 87 } 88 89 trace("System with %I64dMb RAM and terminal services %S\n", Memory, (TS ? L"enabled" : L"disabled")); 90 91 return Status; 92 } 93 94 VOID 95 TestUnload( 96 _In_ PDRIVER_OBJECT DriverObject) 97 { 98 PAGED_CODE(); 99 } 100 101 BOOLEAN 102 NTAPI 103 AcquireForLazyWrite( 104 _In_ PVOID Context, 105 _In_ BOOLEAN Wait) 106 { 107 return TRUE; 108 } 109 110 VOID 111 NTAPI 112 ReleaseFromLazyWrite( 113 _In_ PVOID Context) 114 { 115 return; 116 } 117 118 BOOLEAN 119 NTAPI 120 AcquireForReadAhead( 121 _In_ PVOID Context, 122 _In_ BOOLEAN Wait) 123 { 124 return TRUE; 125 } 126 127 VOID 128 NTAPI 129 ReleaseFromReadAhead( 130 _In_ PVOID Context) 131 { 132 return; 133 } 134 135 static CACHE_MANAGER_CALLBACKS Callbacks = { 136 AcquireForLazyWrite, 137 ReleaseFromLazyWrite, 138 AcquireForReadAhead, 139 ReleaseFromReadAhead, 140 }; 141 142 static CC_FILE_SIZES FileSizes = { 143 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0x4000), // .AllocationSize 144 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0x4000), // .FileSize 145 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0x4000) // .ValidDataLength 146 }; 147 148 static CC_FILE_SIZES SmallFileSizes = { 149 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)512), // .AllocationSize 150 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)496), // .FileSize 151 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)496) // .ValidDataLength 152 }; 153 154 static 155 PVOID 156 MapAndLockUserBuffer( 157 _In_ _Out_ PIRP Irp, 158 _In_ ULONG BufferLength) 159 { 160 PMDL Mdl; 161 162 if (Irp->MdlAddress == NULL) 163 { 164 Mdl = IoAllocateMdl(Irp->UserBuffer, BufferLength, FALSE, FALSE, Irp); 165 if (Mdl == NULL) 166 { 167 return NULL; 168 } 169 170 _SEH2_TRY 171 { 172 MmProbeAndLockPages(Mdl, Irp->RequestorMode, IoWriteAccess); 173 } 174 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 175 { 176 IoFreeMdl(Mdl); 177 Irp->MdlAddress = NULL; 178 _SEH2_YIELD(return NULL); 179 } 180 _SEH2_END; 181 } 182 183 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); 184 } 185 186 #define ok_bcb(B, L, O) \ 187 { \ 188 PPUBLIC_BCB public_bcb = (B); \ 189 ok(public_bcb->NodeTypeCode == 0x2FD, "Not a BCB: %x\n", public_bcb->NodeTypeCode); \ 190 ok(public_bcb->NodeByteSize == 0, "Invalid size: %d\n", public_bcb->NodeByteSize); \ 191 ok_eq_ulong(public_bcb->MappedLength, (L)); \ 192 ok_eq_longlong(public_bcb->MappedFileOffset.QuadPart, (O)); \ 193 } 194 195 static 196 VOID 197 NTAPI 198 PinInAnotherThread(IN PVOID Context) 199 { 200 BOOLEAN Ret; 201 PULONG Buffer; 202 PVOID Bcb; 203 LARGE_INTEGER Offset; 204 PTEST_CONTEXT TestContext; 205 206 ok(TestFileObject != NULL, "Called in invalid context!\n"); 207 ok_eq_ulong(TestTestId, 3); 208 209 TestContext = Context; 210 ok(TestContext != NULL, "Called in invalid context!\n"); 211 ok(TestContext->Bcb != NULL, "Called in invalid context!\n"); 212 ok(TestContext->Buffer != NULL, "Called in invalid context!\n"); 213 ok(TestContext->Length != 0, "Called in invalid context!\n"); 214 215 Ret = FALSE; 216 Offset.QuadPart = 0x1000; 217 KmtStartSeh(); 218 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT, &Bcb, (PVOID *)&Buffer); 219 KmtEndSeh(STATUS_SUCCESS); 220 221 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 222 { 223 ok_bcb(Bcb, 12288, Offset.QuadPart); 224 ok_eq_pointer(Bcb, TestContext->Bcb); 225 ok_eq_pointer(Buffer, TestContext->Buffer); 226 227 CcUnpinData(Bcb); 228 } 229 230 KmtStartSeh(); 231 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer); 232 KmtEndSeh(STATUS_SUCCESS); 233 234 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 235 { 236 ok_bcb(Bcb, 12288, Offset.QuadPart); 237 ok_eq_pointer(Bcb, TestContext->Bcb); 238 ok_eq_pointer(Buffer, TestContext->Buffer); 239 240 CcUnpinData(Bcb); 241 } 242 243 KmtStartSeh(); 244 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer); 245 KmtEndSeh(STATUS_SUCCESS); 246 247 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 248 { 249 ok_bcb(Bcb, 12288, Offset.QuadPart); 250 ok_eq_pointer(Bcb, TestContext->Bcb); 251 ok_eq_pointer(Buffer, TestContext->Buffer); 252 253 CcUnpinData(Bcb); 254 } 255 256 KmtStartSeh(); 257 Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, MAP_WAIT, &Bcb, (PVOID *)&Buffer); 258 KmtEndSeh(STATUS_SUCCESS); 259 260 if (!skip(Ret == TRUE, "CcMapData failed\n")) 261 { 262 ok(Bcb != TestContext->Bcb, "Returned same BCB!\n"); 263 ok_eq_pointer(Buffer, TestContext->Buffer); 264 265 CcUnpinData(Bcb); 266 } 267 268 Offset.QuadPart = 0x1500; 269 TestContext->Length -= 0x500; 270 271 KmtStartSeh(); 272 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer); 273 KmtEndSeh(STATUS_SUCCESS); 274 275 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 276 { 277 ok_bcb(Bcb, 12288, 4096); 278 ok_eq_pointer(Bcb, TestContext->Bcb); 279 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500)); 280 281 CcUnpinData(Bcb); 282 } 283 284 KmtStartSeh(); 285 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT, &Bcb, (PVOID *)&Buffer); 286 KmtEndSeh(STATUS_SUCCESS); 287 288 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 289 { 290 ok_bcb(Bcb, 12288, 4096); 291 ok_eq_pointer(Bcb, TestContext->Bcb); 292 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500)); 293 294 CcUnpinData(Bcb); 295 } 296 297 KmtStartSeh(); 298 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer); 299 KmtEndSeh(STATUS_SUCCESS); 300 301 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 302 { 303 ok_bcb(Bcb, 12288, 4096); 304 ok_eq_pointer(Bcb, TestContext->Bcb); 305 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500)); 306 307 CcUnpinData(Bcb); 308 } 309 310 return; 311 } 312 313 static 314 VOID 315 NTAPI 316 PinInAnotherThreadExclusive(IN PVOID Context) 317 { 318 BOOLEAN Ret; 319 PULONG Buffer; 320 PVOID Bcb; 321 LARGE_INTEGER Offset; 322 PTEST_CONTEXT TestContext; 323 324 ok(TestFileObject != NULL, "Called in invalid context!\n"); 325 ok_eq_ulong(TestTestId, 3); 326 327 TestContext = Context; 328 ok(TestContext != NULL, "Called in invalid context!\n"); 329 ok(TestContext->Bcb != NULL, "Called in invalid context!\n"); 330 ok(TestContext->Buffer != NULL, "Called in invalid context!\n"); 331 ok(TestContext->Length != 0, "Called in invalid context!\n"); 332 333 Ret = FALSE; 334 Offset.QuadPart = 0x1000; 335 KmtStartSeh(); 336 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer); 337 KmtEndSeh(STATUS_SUCCESS); 338 ok(Ret == FALSE, "CcPinRead succeed\n"); 339 340 if (Ret) 341 { 342 CcUnpinData(Bcb); 343 } 344 345 KmtStartSeh(); 346 Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer); 347 KmtEndSeh(STATUS_SUCCESS); 348 349 if (!skip(Ret == TRUE, "CcMapData failed\n")) 350 { 351 ok(Bcb != TestContext->Bcb, "Returned same BCB!\n"); 352 ok_eq_pointer(Buffer, TestContext->Buffer); 353 354 CcUnpinData(Bcb); 355 } 356 357 Offset.QuadPart = 0x1500; 358 TestContext->Length -= 0x500; 359 360 KmtStartSeh(); 361 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_IF_BCB, &Bcb, (PVOID *)&Buffer); 362 KmtEndSeh(STATUS_SUCCESS); 363 ok(Ret == FALSE, "CcPinRead succeed\n"); 364 365 if (Ret) 366 { 367 CcUnpinData(Bcb); 368 } 369 370 KmtStartSeh(); 371 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer); 372 KmtEndSeh(STATUS_SUCCESS); 373 ok(Ret == FALSE, "CcPinRead succeed\n"); 374 375 if (Ret) 376 { 377 CcUnpinData(Bcb); 378 } 379 380 KmtStartSeh(); 381 Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer); 382 KmtEndSeh(STATUS_SUCCESS); 383 384 if (!skip(Ret == TRUE, "CcMapData failed\n")) 385 { 386 ok(Bcb != TestContext->Bcb, "Returned same BCB!\n"); 387 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500)); 388 389 CcUnpinData(Bcb); 390 } 391 392 return; 393 } 394 395 static 396 VOID 397 PerformTest( 398 ULONG TestId, 399 PDEVICE_OBJECT DeviceObject) 400 { 401 PVOID Bcb; 402 BOOLEAN Ret; 403 PULONG Buffer; 404 PTEST_FCB Fcb; 405 LARGE_INTEGER Offset; 406 407 ok_eq_pointer(TestFileObject, NULL); 408 ok_eq_pointer(TestDeviceObject, NULL); 409 ok_eq_ulong(TestTestId, -1); 410 411 TestDeviceObject = DeviceObject; 412 TestTestId = TestId; 413 TestFileObject = IoCreateStreamFileObject(NULL, DeviceObject); 414 if (!skip(TestFileObject != NULL, "Failed to allocate FO\n")) 415 { 416 Fcb = ExAllocatePool(NonPagedPool, sizeof(TEST_FCB)); 417 if (!skip(Fcb != NULL, "ExAllocatePool failed\n")) 418 { 419 BOOLEAN PinAccess = (TestId != 4); 420 421 RtlZeroMemory(Fcb, sizeof(TEST_FCB)); 422 ExInitializeFastMutex(&Fcb->HeaderMutex); 423 FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex); 424 425 TestFileObject->FsContext = Fcb; 426 TestFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; 427 428 KmtStartSeh(); 429 if (TestId < 6) 430 { 431 CcInitializeCacheMap(TestFileObject, &FileSizes, PinAccess, &Callbacks, NULL); 432 } 433 else 434 { 435 CcInitializeCacheMap(TestFileObject, &SmallFileSizes, PinAccess, &Callbacks, NULL); 436 } 437 KmtEndSeh(STATUS_SUCCESS); 438 439 if (!skip(CcIsFileCached(TestFileObject) == TRUE, "CcInitializeCacheMap failed\n")) 440 { 441 if (TestId < 3) 442 { 443 Ret = FALSE; 444 Offset.QuadPart = TestId * 0x1000; 445 KmtStartSeh(); 446 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &Bcb, (PVOID *)&Buffer); 447 KmtEndSeh(STATUS_SUCCESS); 448 449 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 450 { 451 ok_bcb(Bcb, ((4 - TestId) * 4096), Offset.QuadPart); 452 ok_eq_ulong(Buffer[(0x3000 - TestId * 0x1000) / sizeof(ULONG)], 0xDEADBABE); 453 454 CcUnpinData(Bcb); 455 } 456 } 457 else if (TestId == 3) 458 { 459 PTEST_CONTEXT TestContext; 460 461 TestContext = ExAllocatePool(NonPagedPool, sizeof(TEST_CONTEXT)); 462 if (!skip(TestContext != NULL, "ExAllocatePool failed\n")) 463 { 464 Ret = FALSE; 465 Offset.QuadPart = 0x1000; 466 467 /* Try enforce BCB first */ 468 KmtStartSeh(); 469 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer); 470 KmtEndSeh(STATUS_SUCCESS); 471 ok(Ret == FALSE, "CcPinRead succeed\n"); 472 if (Ret) 473 { 474 CcUnpinData(Bcb); 475 } 476 477 KmtStartSeh(); 478 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &TestContext->Bcb, &TestContext->Buffer); 479 KmtEndSeh(STATUS_SUCCESS); 480 481 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 482 { 483 PKTHREAD ThreadHandle; 484 485 ok_bcb(TestContext->Bcb, 12288, Offset.QuadPart); 486 487 /* That's a bit rough but should do the job */ 488 #ifdef _X86_ 489 if (Memory >= 2 * 1024) 490 { 491 ok((TestContext->Buffer >= (PVOID)0xC1000000 && TestContext->Buffer < (PVOID)0xE0FFFFFF) || 492 (TestContext->Buffer >= (PVOID)0xA4000000 && TestContext->Buffer < (PVOID)0xBFFFFFFF), 493 "Buffer %p not mapped in system space\n", TestContext->Buffer); 494 } 495 else if (TS) 496 { 497 ok(TestContext->Buffer >= (PVOID)0xC1000000 && TestContext->Buffer < (PVOID)0xDCFFFFFF, 498 "Buffer %p not mapped in system space\n", TestContext->Buffer); 499 } 500 else 501 { 502 ok(TestContext->Buffer >= (PVOID)0xC1000000 && TestContext->Buffer < (PVOID)0xDBFFFFFF, 503 "Buffer %p not mapped in system space\n", TestContext->Buffer); 504 } 505 #elif defined(_M_AMD64) 506 ok(TestContext->Buffer >= (PVOID)0xFFFFF98000000000 && TestContext->Buffer < (PVOID)0xFFFFFA8000000000, 507 "Buffer %p not mapped in system space\n", TestContext->Buffer); 508 #else 509 skip(FALSE, "System space mapping not defined\n"); 510 #endif 511 512 TestContext->Length = FileSizes.FileSize.QuadPart - Offset.QuadPart; 513 ThreadHandle = KmtStartThread(PinInAnotherThread, TestContext); 514 KmtFinishThread(ThreadHandle, NULL); 515 516 TestContext->Length = FileSizes.FileSize.QuadPart - 2 * Offset.QuadPart; 517 ThreadHandle = KmtStartThread(PinInAnotherThread, TestContext); 518 KmtFinishThread(ThreadHandle, NULL); 519 520 CcUnpinData(TestContext->Bcb); 521 } 522 523 KmtStartSeh(); 524 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT | PIN_EXCLUSIVE, &TestContext->Bcb, &TestContext->Buffer); 525 KmtEndSeh(STATUS_SUCCESS); 526 527 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 528 { 529 PKTHREAD ThreadHandle; 530 531 ok_bcb(TestContext->Bcb, 12288, Offset.QuadPart); 532 533 TestContext->Length = FileSizes.FileSize.QuadPart - Offset.QuadPart; 534 ThreadHandle = KmtStartThread(PinInAnotherThreadExclusive, TestContext); 535 KmtFinishThread(ThreadHandle, NULL); 536 537 CcUnpinData(TestContext->Bcb); 538 } 539 540 ExFreePool(TestContext); 541 } 542 } 543 else if (TestId == 4) 544 { 545 Ret = FALSE; 546 Offset.QuadPart = 0x1000; 547 KmtStartSeh(); 548 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &Bcb, (PVOID *)&Buffer); 549 KmtEndSeh(STATUS_SUCCESS); 550 551 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 552 { 553 ok_bcb(Bcb, 12288, Offset.QuadPart); 554 ok_eq_ulong(Buffer[0x2000 / sizeof(ULONG)], 0); 555 556 CcUnpinData(Bcb); 557 } 558 } 559 else if (TestId == 5) 560 { 561 /* Pin after EOF */ 562 Ret = FALSE; 563 Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000; 564 565 KmtStartSeh(); 566 Ret = CcPinRead(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer); 567 KmtEndSeh(STATUS_SUCCESS); 568 ok(Ret == FALSE, "CcPinRead succeed\n"); 569 570 if (Ret) 571 { 572 CcUnpinData(Bcb); 573 } 574 575 /* Pin a VACB after EOF */ 576 Ret = FALSE; 577 Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000 + VACB_MAPPING_GRANULARITY; 578 579 KmtStartSeh(); 580 Ret = CcPinRead(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer); 581 KmtEndSeh(STATUS_ACCESS_VIOLATION); 582 ok(Ret == FALSE, "CcPinRead succeed\n"); 583 584 if (Ret) 585 { 586 CcUnpinData(Bcb); 587 } 588 589 /* Pin more than a VACB */ 590 Ret = FALSE; 591 Offset.QuadPart = 0x0; 592 593 KmtStartSeh(); 594 Ret = CcPinRead(TestFileObject, &Offset, 0x1000 + VACB_MAPPING_GRANULARITY, 0, &Bcb, (PVOID *)&Buffer); 595 KmtEndSeh(STATUS_SUCCESS); 596 ok(Ret == FALSE, "CcPinRead succeed\n"); 597 598 if (Ret) 599 { 600 CcUnpinData(Bcb); 601 } 602 } 603 else if (TestId == 6) 604 { 605 Ret = FALSE; 606 Offset.QuadPart = 0; 607 608 KmtStartSeh(); 609 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart, PIN_WAIT, &Bcb, (PVOID *)&Buffer); 610 KmtEndSeh(STATUS_SUCCESS); 611 612 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 613 { 614 ok_bcb(Bcb, PAGE_SIZE * 4, Offset.QuadPart); 615 RtlFillMemory(Buffer, 0xbd, FileSizes.FileSize.LowPart); 616 CcSetDirtyPinnedData(Bcb, NULL); 617 618 CcUnpinData(Bcb); 619 } 620 } 621 } 622 } 623 } 624 } 625 626 627 static 628 VOID 629 CleanupTest( 630 ULONG TestId, 631 PDEVICE_OBJECT DeviceObject) 632 { 633 LARGE_INTEGER Zero = RTL_CONSTANT_LARGE_INTEGER(0LL); 634 CACHE_UNINITIALIZE_EVENT CacheUninitEvent; 635 636 ok_eq_pointer(TestDeviceObject, DeviceObject); 637 ok_eq_ulong(TestTestId, TestId); 638 639 if (!skip(TestFileObject != NULL, "No test FO\n")) 640 { 641 if (CcIsFileCached(TestFileObject)) 642 { 643 KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE); 644 CcUninitializeCacheMap(TestFileObject, &Zero, &CacheUninitEvent); 645 KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL); 646 } 647 648 if (TestFileObject->FsContext != NULL) 649 { 650 ExFreePool(TestFileObject->FsContext); 651 TestFileObject->FsContext = NULL; 652 TestFileObject->SectionObjectPointer = NULL; 653 } 654 655 if (TestTestId == 6) 656 { 657 ok_bool_true(TestWriteCalled, "Write was not called!\n"); 658 } 659 else 660 { 661 ok_bool_false(TestWriteCalled, "Write was unexpectedly called\n"); 662 } 663 664 ObDereferenceObject(TestFileObject); 665 } 666 667 TestFileObject = NULL; 668 TestDeviceObject = NULL; 669 TestTestId = -1; 670 TestWriteCalled = FALSE; 671 } 672 673 674 static 675 NTSTATUS 676 TestMessageHandler( 677 _In_ PDEVICE_OBJECT DeviceObject, 678 _In_ ULONG ControlCode, 679 _In_opt_ PVOID Buffer, 680 _In_ SIZE_T InLength, 681 _Inout_ PSIZE_T OutLength) 682 { 683 NTSTATUS Status = STATUS_SUCCESS; 684 685 FsRtlEnterFileSystem(); 686 687 switch (ControlCode) 688 { 689 case IOCTL_START_TEST: 690 ok_eq_ulong((ULONG)InLength, sizeof(ULONG)); 691 PerformTest(*(PULONG)Buffer, DeviceObject); 692 break; 693 694 case IOCTL_FINISH_TEST: 695 ok_eq_ulong((ULONG)InLength, sizeof(ULONG)); 696 CleanupTest(*(PULONG)Buffer, DeviceObject); 697 break; 698 699 default: 700 Status = STATUS_NOT_IMPLEMENTED; 701 break; 702 } 703 704 FsRtlExitFileSystem(); 705 706 return Status; 707 } 708 709 static 710 NTSTATUS 711 TestIrpHandler( 712 _In_ PDEVICE_OBJECT DeviceObject, 713 _In_ PIRP Irp, 714 _In_ PIO_STACK_LOCATION IoStack) 715 { 716 NTSTATUS Status; 717 718 PAGED_CODE(); 719 720 DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction); 721 ASSERT(IoStack->MajorFunction == IRP_MJ_READ || 722 IoStack->MajorFunction == IRP_MJ_WRITE); 723 724 FsRtlEnterFileSystem(); 725 726 Status = STATUS_NOT_SUPPORTED; 727 Irp->IoStatus.Information = 0; 728 729 if (IoStack->MajorFunction == IRP_MJ_READ) 730 { 731 PMDL Mdl; 732 ULONG Length; 733 PVOID Buffer; 734 LARGE_INTEGER Offset; 735 736 Offset = IoStack->Parameters.Read.ByteOffset; 737 Length = IoStack->Parameters.Read.Length; 738 739 ok_eq_pointer(DeviceObject, TestDeviceObject); 740 ok_eq_pointer(IoStack->FileObject, TestFileObject); 741 742 ok(FlagOn(Irp->Flags, IRP_NOCACHE), "Not coming from Cc\n"); 743 744 ok_irql(APC_LEVEL); 745 ok((Offset.QuadPart % PAGE_SIZE == 0 || Offset.QuadPart == 0), "Offset is not aligned: %I64i\n", Offset.QuadPart); 746 ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length); 747 748 ok(Irp->AssociatedIrp.SystemBuffer == NULL, "A SystemBuffer was allocated!\n"); 749 Buffer = MapAndLockUserBuffer(Irp, Length); 750 ok(Buffer != NULL, "Null pointer!\n"); 751 RtlFillMemory(Buffer, Length, 0xBA); 752 753 Status = STATUS_SUCCESS; 754 if (Offset.QuadPart <= 0x3000 && Offset.QuadPart + Length > 0x3000) 755 { 756 *(PULONG)((ULONG_PTR)Buffer + (ULONG_PTR)(0x3000 - Offset.QuadPart)) = 0xDEADBABE; 757 } 758 759 Mdl = Irp->MdlAddress; 760 ok(Mdl != NULL, "Null pointer for MDL!\n"); 761 ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not locked\n"); 762 ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n"); 763 ok((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0, "Non paging IO\n"); 764 ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n"); 765 766 Irp->IoStatus.Information = Length; 767 } 768 else if (IoStack->MajorFunction == IRP_MJ_WRITE) 769 { 770 PMDL Mdl; 771 ULONG Length; 772 PVOID Buffer; 773 LARGE_INTEGER Offset; 774 775 Offset = IoStack->Parameters.Write.ByteOffset; 776 Length = IoStack->Parameters.Write.Length; 777 778 ok(TestTestId == 6, "Unexpected test id: %d\n", TestTestId); 779 ok_eq_pointer(DeviceObject, TestDeviceObject); 780 ok_eq_pointer(IoStack->FileObject, TestFileObject); 781 782 ok(FlagOn(Irp->Flags, IRP_NOCACHE), "Not coming from Cc\n"); 783 784 ok_irql(PASSIVE_LEVEL); 785 ok(Offset.QuadPart == 0, "Offset is not null: %I64i\n", Offset.QuadPart); 786 ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length); 787 ok(Length == PAGE_SIZE * 4, "Length is not MappedLength-sized: %I64i\n", Length); 788 789 Buffer = MapAndLockUserBuffer(Irp, Length); 790 ok(Buffer != NULL, "Null pointer!\n"); 791 792 Mdl = Irp->MdlAddress; 793 ok(Mdl != NULL, "Null pointer for MDL!\n"); 794 ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not locked\n"); 795 ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n"); 796 ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n"); 797 798 ok_bool_false(TestWriteCalled, "Write has been unexpectedly called twice!\n"); 799 TestWriteCalled = TRUE; 800 801 Status = STATUS_SUCCESS; 802 Irp->IoStatus.Information = Length; 803 } 804 805 if (Status == STATUS_PENDING) 806 { 807 IoMarkIrpPending(Irp); 808 IoCompleteRequest(Irp, IO_NO_INCREMENT); 809 Status = STATUS_PENDING; 810 } 811 else 812 { 813 Irp->IoStatus.Status = Status; 814 IoCompleteRequest(Irp, IO_NO_INCREMENT); 815 } 816 817 FsRtlExitFileSystem(); 818 819 return Status; 820 } 821