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