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 36 NTSTATUS 37 TestEntry( 38 _In_ PDRIVER_OBJECT DriverObject, 39 _In_ PCUNICODE_STRING RegistryPath, 40 _Out_ PCWSTR *DeviceName, 41 _Inout_ INT *Flags) 42 { 43 NTSTATUS Status = STATUS_SUCCESS; 44 45 PAGED_CODE(); 46 47 UNREFERENCED_PARAMETER(RegistryPath); 48 49 *DeviceName = L"CcPinRead"; 50 *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE | 51 TESTENTRY_BUFFERED_IO_DEVICE | 52 TESTENTRY_NO_READONLY_DEVICE; 53 54 KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler); 55 KmtRegisterMessageHandler(0, NULL, TestMessageHandler); 56 57 58 return Status; 59 } 60 61 VOID 62 TestUnload( 63 _In_ PDRIVER_OBJECT DriverObject) 64 { 65 PAGED_CODE(); 66 } 67 68 BOOLEAN 69 NTAPI 70 AcquireForLazyWrite( 71 _In_ PVOID Context, 72 _In_ BOOLEAN Wait) 73 { 74 return TRUE; 75 } 76 77 VOID 78 NTAPI 79 ReleaseFromLazyWrite( 80 _In_ PVOID Context) 81 { 82 return; 83 } 84 85 BOOLEAN 86 NTAPI 87 AcquireForReadAhead( 88 _In_ PVOID Context, 89 _In_ BOOLEAN Wait) 90 { 91 return TRUE; 92 } 93 94 VOID 95 NTAPI 96 ReleaseFromReadAhead( 97 _In_ PVOID Context) 98 { 99 return; 100 } 101 102 static CACHE_MANAGER_CALLBACKS Callbacks = { 103 AcquireForLazyWrite, 104 ReleaseFromLazyWrite, 105 AcquireForReadAhead, 106 ReleaseFromReadAhead, 107 }; 108 109 static CC_FILE_SIZES FileSizes = { 110 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0x4000), // .AllocationSize 111 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0x4000), // .FileSize 112 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0x4000) // .ValidDataLength 113 }; 114 115 static 116 PVOID 117 MapAndLockUserBuffer( 118 _In_ _Out_ PIRP Irp, 119 _In_ ULONG BufferLength) 120 { 121 PMDL Mdl; 122 123 if (Irp->MdlAddress == NULL) 124 { 125 Mdl = IoAllocateMdl(Irp->UserBuffer, BufferLength, FALSE, FALSE, Irp); 126 if (Mdl == NULL) 127 { 128 return NULL; 129 } 130 131 _SEH2_TRY 132 { 133 MmProbeAndLockPages(Mdl, Irp->RequestorMode, IoWriteAccess); 134 } 135 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 136 { 137 IoFreeMdl(Mdl); 138 Irp->MdlAddress = NULL; 139 _SEH2_YIELD(return NULL); 140 } 141 _SEH2_END; 142 } 143 144 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); 145 } 146 147 #define ok_bcb(B, L, O) \ 148 { \ 149 PPUBLIC_BCB public_bcb = (B); \ 150 ok(public_bcb->NodeTypeCode == 0x2FD, "Not a BCB: %x\n", public_bcb->NodeTypeCode); \ 151 ok(public_bcb->NodeByteSize == 0, "Invalid size: %d\n", public_bcb->NodeByteSize); \ 152 ok_eq_ulong(public_bcb->MappedLength, (L)); \ 153 ok_eq_longlong(public_bcb->MappedFileOffset.QuadPart, (O)); \ 154 } 155 156 static 157 VOID 158 NTAPI 159 PinInAnotherThread(IN PVOID Context) 160 { 161 BOOLEAN Ret; 162 PULONG Buffer; 163 PVOID Bcb; 164 LARGE_INTEGER Offset; 165 PTEST_CONTEXT TestContext; 166 167 ok(TestFileObject != NULL, "Called in invalid context!\n"); 168 ok_eq_ulong(TestTestId, 3); 169 170 TestContext = Context; 171 ok(TestContext != NULL, "Called in invalid context!\n"); 172 ok(TestContext->Bcb != NULL, "Called in invalid context!\n"); 173 ok(TestContext->Buffer != NULL, "Called in invalid context!\n"); 174 ok(TestContext->Length != 0, "Called in invalid context!\n"); 175 176 Ret = FALSE; 177 Offset.QuadPart = 0x1000; 178 KmtStartSeh(); 179 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT, &Bcb, (PVOID *)&Buffer); 180 KmtEndSeh(STATUS_SUCCESS); 181 182 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 183 { 184 ok_bcb(Bcb, 12288, Offset.QuadPart); 185 ok_eq_pointer(Bcb, TestContext->Bcb); 186 ok_eq_pointer(Buffer, TestContext->Buffer); 187 188 CcUnpinData(Bcb); 189 } 190 191 KmtStartSeh(); 192 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer); 193 KmtEndSeh(STATUS_SUCCESS); 194 195 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 196 { 197 ok_bcb(Bcb, 12288, Offset.QuadPart); 198 ok_eq_pointer(Bcb, TestContext->Bcb); 199 ok_eq_pointer(Buffer, TestContext->Buffer); 200 201 CcUnpinData(Bcb); 202 } 203 204 KmtStartSeh(); 205 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer); 206 KmtEndSeh(STATUS_SUCCESS); 207 208 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 209 { 210 ok_bcb(Bcb, 12288, Offset.QuadPart); 211 ok_eq_pointer(Bcb, TestContext->Bcb); 212 ok_eq_pointer(Buffer, TestContext->Buffer); 213 214 CcUnpinData(Bcb); 215 } 216 217 KmtStartSeh(); 218 Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, MAP_WAIT, &Bcb, (PVOID *)&Buffer); 219 KmtEndSeh(STATUS_SUCCESS); 220 221 if (!skip(Ret == TRUE, "CcMapData failed\n")) 222 { 223 ok(Bcb != TestContext->Bcb, "Returned same BCB!\n"); 224 ok_eq_pointer(Buffer, TestContext->Buffer); 225 226 CcUnpinData(Bcb); 227 } 228 229 Offset.QuadPart = 0x1500; 230 TestContext->Length -= 0x500; 231 232 KmtStartSeh(); 233 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer); 234 KmtEndSeh(STATUS_SUCCESS); 235 236 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 237 { 238 ok_bcb(Bcb, 12288, 4096); 239 ok_eq_pointer(Bcb, TestContext->Bcb); 240 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500)); 241 242 CcUnpinData(Bcb); 243 } 244 245 KmtStartSeh(); 246 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT, &Bcb, (PVOID *)&Buffer); 247 KmtEndSeh(STATUS_SUCCESS); 248 249 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 250 { 251 ok_bcb(Bcb, 12288, 4096); 252 ok_eq_pointer(Bcb, TestContext->Bcb); 253 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500)); 254 255 CcUnpinData(Bcb); 256 } 257 258 KmtStartSeh(); 259 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer); 260 KmtEndSeh(STATUS_SUCCESS); 261 262 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 263 { 264 ok_bcb(Bcb, 12288, 4096); 265 ok_eq_pointer(Bcb, TestContext->Bcb); 266 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500)); 267 268 CcUnpinData(Bcb); 269 } 270 271 return; 272 } 273 274 static 275 VOID 276 NTAPI 277 PinInAnotherThreadExclusive(IN PVOID Context) 278 { 279 BOOLEAN Ret; 280 PULONG Buffer; 281 PVOID Bcb; 282 LARGE_INTEGER Offset; 283 PTEST_CONTEXT TestContext; 284 285 ok(TestFileObject != NULL, "Called in invalid context!\n"); 286 ok_eq_ulong(TestTestId, 3); 287 288 TestContext = Context; 289 ok(TestContext != NULL, "Called in invalid context!\n"); 290 ok(TestContext->Bcb != NULL, "Called in invalid context!\n"); 291 ok(TestContext->Buffer != NULL, "Called in invalid context!\n"); 292 ok(TestContext->Length != 0, "Called in invalid context!\n"); 293 294 Ret = FALSE; 295 Offset.QuadPart = 0x1000; 296 KmtStartSeh(); 297 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer); 298 KmtEndSeh(STATUS_SUCCESS); 299 ok(Ret == FALSE, "CcPinRead succeed\n"); 300 301 if (Ret) 302 { 303 CcUnpinData(Bcb); 304 } 305 306 KmtStartSeh(); 307 Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer); 308 KmtEndSeh(STATUS_SUCCESS); 309 310 if (!skip(Ret == TRUE, "CcMapData failed\n")) 311 { 312 ok(Bcb != TestContext->Bcb, "Returned same BCB!\n"); 313 ok_eq_pointer(Buffer, TestContext->Buffer); 314 315 CcUnpinData(Bcb); 316 } 317 318 Offset.QuadPart = 0x1500; 319 TestContext->Length -= 0x500; 320 321 KmtStartSeh(); 322 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_IF_BCB, &Bcb, (PVOID *)&Buffer); 323 KmtEndSeh(STATUS_SUCCESS); 324 ok(Ret == FALSE, "CcPinRead succeed\n"); 325 326 if (Ret) 327 { 328 CcUnpinData(Bcb); 329 } 330 331 KmtStartSeh(); 332 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer); 333 KmtEndSeh(STATUS_SUCCESS); 334 ok(Ret == FALSE, "CcPinRead succeed\n"); 335 336 if (Ret) 337 { 338 CcUnpinData(Bcb); 339 } 340 341 KmtStartSeh(); 342 Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer); 343 KmtEndSeh(STATUS_SUCCESS); 344 345 if (!skip(Ret == TRUE, "CcMapData failed\n")) 346 { 347 ok(Bcb != TestContext->Bcb, "Returned same BCB!\n"); 348 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500)); 349 350 CcUnpinData(Bcb); 351 } 352 353 return; 354 } 355 356 static 357 VOID 358 PerformTest( 359 ULONG TestId, 360 PDEVICE_OBJECT DeviceObject) 361 { 362 PVOID Bcb; 363 BOOLEAN Ret; 364 PULONG Buffer; 365 PTEST_FCB Fcb; 366 LARGE_INTEGER Offset; 367 368 ok_eq_pointer(TestFileObject, NULL); 369 ok_eq_pointer(TestDeviceObject, NULL); 370 ok_eq_ulong(TestTestId, -1); 371 372 TestDeviceObject = DeviceObject; 373 TestTestId = TestId; 374 TestFileObject = IoCreateStreamFileObject(NULL, DeviceObject); 375 if (!skip(TestFileObject != NULL, "Failed to allocate FO\n")) 376 { 377 Fcb = ExAllocatePool(NonPagedPool, sizeof(TEST_FCB)); 378 if (!skip(Fcb != NULL, "ExAllocatePool failed\n")) 379 { 380 BOOLEAN PinAccess = (TestId != 4); 381 382 RtlZeroMemory(Fcb, sizeof(TEST_FCB)); 383 ExInitializeFastMutex(&Fcb->HeaderMutex); 384 FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex); 385 386 TestFileObject->FsContext = Fcb; 387 TestFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; 388 389 KmtStartSeh(); 390 CcInitializeCacheMap(TestFileObject, &FileSizes, PinAccess, &Callbacks, NULL); 391 KmtEndSeh(STATUS_SUCCESS); 392 393 if (!skip(CcIsFileCached(TestFileObject) == TRUE, "CcInitializeCacheMap failed\n")) 394 { 395 if (TestId < 3) 396 { 397 Ret = FALSE; 398 Offset.QuadPart = TestId * 0x1000; 399 KmtStartSeh(); 400 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &Bcb, (PVOID *)&Buffer); 401 KmtEndSeh(STATUS_SUCCESS); 402 403 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 404 { 405 ok_bcb(Bcb, ((4 - TestId) * 4096), Offset.QuadPart); 406 ok_eq_ulong(Buffer[(0x3000 - TestId * 0x1000) / sizeof(ULONG)], 0xDEADBABE); 407 408 CcUnpinData(Bcb); 409 } 410 } 411 else if (TestId == 3) 412 { 413 PTEST_CONTEXT TestContext; 414 415 TestContext = ExAllocatePool(NonPagedPool, sizeof(TEST_CONTEXT)); 416 if (!skip(TestContext != NULL, "ExAllocatePool failed\n")) 417 { 418 Ret = FALSE; 419 Offset.QuadPart = 0x1000; 420 421 /* Try enforce BCB first */ 422 KmtStartSeh(); 423 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer); 424 KmtEndSeh(STATUS_SUCCESS); 425 ok(Ret == FALSE, "CcPinRead succeed\n"); 426 if (Ret) 427 { 428 CcUnpinData(Bcb); 429 } 430 431 KmtStartSeh(); 432 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &TestContext->Bcb, &TestContext->Buffer); 433 KmtEndSeh(STATUS_SUCCESS); 434 435 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 436 { 437 PKTHREAD ThreadHandle; 438 439 ok_bcb(TestContext->Bcb, 12288, Offset.QuadPart); 440 441 #ifdef _X86_ 442 /* FIXME: Should be fixed, will fail under certains conditions */ 443 ok(TestContext->Buffer > (PVOID)0xC1000000 && TestContext->Buffer < (PVOID)0xDCFFFFFF, 444 "Buffer %p not mapped in system space\n", TestContext->Buffer); 445 #else 446 #ifdef _M_AMD64 447 ok(TestContext->Buffer > (PVOID)0xFFFFF98000000000 && TestContext->Buffer < (PVOID)0xFFFFFA8000000000, 448 "Buffer %p not mapped in system space\n", TestContext->Buffer); 449 #else 450 skip(FALSE, "System space mapping not defined\n"); 451 #endif 452 #endif 453 TestContext->Length = FileSizes.FileSize.QuadPart - Offset.QuadPart; 454 ThreadHandle = KmtStartThread(PinInAnotherThread, TestContext); 455 KmtFinishThread(ThreadHandle, NULL); 456 457 TestContext->Length = FileSizes.FileSize.QuadPart - 2 * Offset.QuadPart; 458 ThreadHandle = KmtStartThread(PinInAnotherThread, TestContext); 459 KmtFinishThread(ThreadHandle, NULL); 460 461 CcUnpinData(TestContext->Bcb); 462 } 463 464 KmtStartSeh(); 465 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT | PIN_EXCLUSIVE, &TestContext->Bcb, &TestContext->Buffer); 466 KmtEndSeh(STATUS_SUCCESS); 467 468 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 469 { 470 PKTHREAD ThreadHandle; 471 472 ok_bcb(TestContext->Bcb, 12288, Offset.QuadPart); 473 474 TestContext->Length = FileSizes.FileSize.QuadPart - Offset.QuadPart; 475 ThreadHandle = KmtStartThread(PinInAnotherThreadExclusive, TestContext); 476 KmtFinishThread(ThreadHandle, NULL); 477 478 CcUnpinData(TestContext->Bcb); 479 } 480 481 ExFreePool(TestContext); 482 } 483 } 484 else if (TestId == 4) 485 { 486 Ret = FALSE; 487 Offset.QuadPart = 0x1000; 488 KmtStartSeh(); 489 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &Bcb, (PVOID *)&Buffer); 490 KmtEndSeh(STATUS_SUCCESS); 491 492 if (!skip(Ret == TRUE, "CcPinRead failed\n")) 493 { 494 ok_bcb(Bcb, 12288, Offset.QuadPart); 495 ok_eq_ulong(Buffer[0x2000 / sizeof(ULONG)], 0); 496 497 CcUnpinData(Bcb); 498 } 499 } 500 else if (TestId == 5) 501 { 502 /* Pin after EOF */ 503 Ret = FALSE; 504 Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000; 505 506 KmtStartSeh(); 507 Ret = CcPinRead(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer); 508 KmtEndSeh(STATUS_SUCCESS); 509 ok(Ret == FALSE, "CcPinRead succeed\n"); 510 511 if (Ret) 512 { 513 CcUnpinData(Bcb); 514 } 515 516 /* Pin a VACB after EOF */ 517 Ret = FALSE; 518 Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000 + VACB_MAPPING_GRANULARITY; 519 520 KmtStartSeh(); 521 Ret = CcPinRead(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer); 522 KmtEndSeh(STATUS_ACCESS_VIOLATION); 523 ok(Ret == FALSE, "CcPinRead succeed\n"); 524 525 if (Ret) 526 { 527 CcUnpinData(Bcb); 528 } 529 530 /* Pin more than a VACB */ 531 Ret = FALSE; 532 Offset.QuadPart = 0x0; 533 534 KmtStartSeh(); 535 Ret = CcPinRead(TestFileObject, &Offset, 0x1000 + VACB_MAPPING_GRANULARITY, 0, &Bcb, (PVOID *)&Buffer); 536 KmtEndSeh(STATUS_SUCCESS); 537 ok(Ret == FALSE, "CcPinRead succeed\n"); 538 539 if (Ret) 540 { 541 CcUnpinData(Bcb); 542 } 543 } 544 } 545 } 546 } 547 } 548 549 550 static 551 VOID 552 CleanupTest( 553 ULONG TestId, 554 PDEVICE_OBJECT DeviceObject) 555 { 556 LARGE_INTEGER Zero = RTL_CONSTANT_LARGE_INTEGER(0LL); 557 CACHE_UNINITIALIZE_EVENT CacheUninitEvent; 558 559 ok_eq_pointer(TestDeviceObject, DeviceObject); 560 ok_eq_ulong(TestTestId, TestId); 561 562 if (!skip(TestFileObject != NULL, "No test FO\n")) 563 { 564 if (CcIsFileCached(TestFileObject)) 565 { 566 KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE); 567 CcUninitializeCacheMap(TestFileObject, &Zero, &CacheUninitEvent); 568 KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL); 569 } 570 571 if (TestFileObject->FsContext != NULL) 572 { 573 ExFreePool(TestFileObject->FsContext); 574 TestFileObject->FsContext = NULL; 575 TestFileObject->SectionObjectPointer = NULL; 576 } 577 578 ObDereferenceObject(TestFileObject); 579 } 580 581 TestFileObject = NULL; 582 TestDeviceObject = NULL; 583 TestTestId = -1; 584 } 585 586 587 static 588 NTSTATUS 589 TestMessageHandler( 590 _In_ PDEVICE_OBJECT DeviceObject, 591 _In_ ULONG ControlCode, 592 _In_opt_ PVOID Buffer, 593 _In_ SIZE_T InLength, 594 _Inout_ PSIZE_T OutLength) 595 { 596 NTSTATUS Status = STATUS_SUCCESS; 597 598 FsRtlEnterFileSystem(); 599 600 switch (ControlCode) 601 { 602 case IOCTL_START_TEST: 603 ok_eq_ulong((ULONG)InLength, sizeof(ULONG)); 604 PerformTest(*(PULONG)Buffer, DeviceObject); 605 break; 606 607 case IOCTL_FINISH_TEST: 608 ok_eq_ulong((ULONG)InLength, sizeof(ULONG)); 609 CleanupTest(*(PULONG)Buffer, DeviceObject); 610 break; 611 612 default: 613 Status = STATUS_NOT_IMPLEMENTED; 614 break; 615 } 616 617 FsRtlExitFileSystem(); 618 619 return Status; 620 } 621 622 static 623 NTSTATUS 624 TestIrpHandler( 625 _In_ PDEVICE_OBJECT DeviceObject, 626 _In_ PIRP Irp, 627 _In_ PIO_STACK_LOCATION IoStack) 628 { 629 NTSTATUS Status; 630 631 PAGED_CODE(); 632 633 DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction); 634 ASSERT(IoStack->MajorFunction == IRP_MJ_READ); 635 636 FsRtlEnterFileSystem(); 637 638 Status = STATUS_NOT_SUPPORTED; 639 Irp->IoStatus.Information = 0; 640 641 if (IoStack->MajorFunction == IRP_MJ_READ) 642 { 643 PMDL Mdl; 644 ULONG Length; 645 PVOID Buffer; 646 LARGE_INTEGER Offset; 647 648 Offset = IoStack->Parameters.Read.ByteOffset; 649 Length = IoStack->Parameters.Read.Length; 650 651 ok_eq_pointer(DeviceObject, TestDeviceObject); 652 ok_eq_pointer(IoStack->FileObject, TestFileObject); 653 654 ok(FlagOn(Irp->Flags, IRP_NOCACHE), "Not coming from Cc\n"); 655 656 ok_irql(APC_LEVEL); 657 ok((Offset.QuadPart % PAGE_SIZE == 0 || Offset.QuadPart == 0), "Offset is not aligned: %I64i\n", Offset.QuadPart); 658 ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length); 659 660 ok(Irp->AssociatedIrp.SystemBuffer == NULL, "A SystemBuffer was allocated!\n"); 661 Buffer = MapAndLockUserBuffer(Irp, Length); 662 ok(Buffer != NULL, "Null pointer!\n"); 663 RtlFillMemory(Buffer, Length, 0xBA); 664 665 Status = STATUS_SUCCESS; 666 if (Offset.QuadPart <= 0x3000 && Offset.QuadPart + Length > 0x3000) 667 { 668 *(PULONG)((ULONG_PTR)Buffer + (ULONG_PTR)(0x3000 - Offset.QuadPart)) = 0xDEADBABE; 669 } 670 671 Mdl = Irp->MdlAddress; 672 ok(Mdl != NULL, "Null pointer for MDL!\n"); 673 ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not locked\n"); 674 ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n"); 675 ok((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0, "Non paging IO\n"); 676 ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n"); 677 678 Irp->IoStatus.Information = Length; 679 } 680 681 if (Status == STATUS_PENDING) 682 { 683 IoMarkIrpPending(Irp); 684 IoCompleteRequest(Irp, IO_NO_INCREMENT); 685 Status = STATUS_PENDING; 686 } 687 else 688 { 689 Irp->IoStatus.Status = Status; 690 IoCompleteRequest(Irp, IO_NO_INCREMENT); 691 } 692 693 FsRtlExitFileSystem(); 694 695 return Status; 696 } 697