1 /* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: block.c 5 * PROGRAMMER: Matt Wu <mattwu@163.com> 6 * HOMEPAGE: http://www.ext2fsd.com 7 * UPDATE HISTORY: 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include "ext2fs.h" 13 14 /* GLOBALS ***************************************************************/ 15 16 extern PEXT2_GLOBAL Ext2Global; 17 18 /* DEFINITIONS *************************************************************/ 19 20 NTSTATUS NTAPI 21 Ext2ReadWriteBlockSyncCompletionRoutine ( 22 IN PDEVICE_OBJECT DeviceObject, 23 IN PIRP Irp, 24 IN PVOID Context ); 25 26 NTSTATUS NTAPI 27 Ext2ReadWriteBlockAsyncCompletionRoutine ( 28 IN PDEVICE_OBJECT DeviceObject, 29 IN PIRP Irp, 30 IN PVOID Context ); 31 32 33 NTSTATUS NTAPI 34 Ext2MediaEjectControlCompletion ( 35 IN PDEVICE_OBJECT DeviceObject, 36 IN PIRP Irp, 37 IN PVOID Contxt ); 38 39 #ifdef ALLOC_PRAGMA 40 #pragma alloc_text(PAGE, Ext2LockUserBuffer) 41 #pragma alloc_text(PAGE, Ext2ReadSync) 42 #pragma alloc_text(PAGE, Ext2ReadDisk) 43 #pragma alloc_text(PAGE, Ext2DiskIoControl) 44 #pragma alloc_text(PAGE, Ext2MediaEjectControl) 45 #pragma alloc_text(PAGE, Ext2DiskShutDown) 46 #endif 47 48 49 /* FUNCTIONS ***************************************************************/ 50 51 PMDL 52 Ext2CreateMdl ( 53 IN PVOID Buffer, 54 IN ULONG Length, 55 IN LOCK_OPERATION op 56 ) 57 { 58 NTSTATUS Status; 59 PMDL Mdl = NULL; 60 61 ASSERT (Buffer != NULL); 62 Mdl = IoAllocateMdl (Buffer, Length, FALSE, FALSE, NULL); 63 if (Mdl == NULL) { 64 Status = STATUS_INSUFFICIENT_RESOURCES; 65 } else { 66 _SEH2_TRY { 67 if (MmIsNonPagedSystemAddressValid(Buffer)) { 68 MmBuildMdlForNonPagedPool(Mdl); 69 } else { 70 MmProbeAndLockPages(Mdl, KernelMode, op); 71 } 72 Status = STATUS_SUCCESS; 73 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { 74 IoFreeMdl (Mdl); 75 Mdl = NULL; 76 DbgBreak(); 77 Status = STATUS_INVALID_USER_BUFFER; 78 } _SEH2_END; 79 } 80 return Mdl; 81 } 82 83 84 VOID 85 Ext2DestroyMdl (IN PMDL Mdl) 86 { 87 ASSERT (Mdl != NULL); 88 while (Mdl) { 89 PMDL Next; 90 Next = Mdl->Next; 91 Mdl->Next = NULL; 92 if (IsFlagOn(Mdl->MdlFlags, MDL_PAGES_LOCKED)) { 93 MmUnlockPages (Mdl); 94 } 95 IoFreeMdl (Mdl); 96 Mdl = Next; 97 } 98 } 99 100 NTSTATUS 101 Ext2LockUserBuffer (IN PIRP Irp, 102 IN ULONG Length, 103 IN LOCK_OPERATION Operation) 104 { 105 NTSTATUS Status; 106 ASSERT(Irp != NULL); 107 108 if (Irp->MdlAddress != NULL) { 109 return STATUS_SUCCESS; 110 } 111 112 IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp); 113 if (Irp->MdlAddress == NULL) { 114 return STATUS_INSUFFICIENT_RESOURCES; 115 } 116 117 _SEH2_TRY { 118 119 MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation); 120 Status = STATUS_SUCCESS; 121 122 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { 123 124 DbgBreak(); 125 IoFreeMdl(Irp->MdlAddress); 126 Irp->MdlAddress = NULL; 127 Status = STATUS_INVALID_USER_BUFFER; 128 } _SEH2_END; 129 130 return Status; 131 } 132 133 PVOID 134 Ext2GetUserBuffer (IN PIRP Irp ) 135 { 136 ASSERT(Irp != NULL); 137 138 if (Irp->MdlAddress) { 139 140 #if (_WIN32_WINNT >= 0x0500) 141 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); 142 #else 143 return MmGetSystemAddressForMdl(Irp->MdlAddress); 144 #endif 145 } else { 146 147 return Irp->UserBuffer; 148 } 149 } 150 151 NTSTATUS NTAPI 152 Ext2ReadWriteBlockSyncCompletionRoutine ( 153 IN PDEVICE_OBJECT DeviceObject, 154 IN PIRP Irp, 155 IN PVOID Context ) 156 { 157 PEXT2_RW_CONTEXT pContext = (PEXT2_RW_CONTEXT)Context; 158 159 if (Irp != pContext->MasterIrp) { 160 161 if (!NT_SUCCESS(Irp->IoStatus.Status)) { 162 pContext->MasterIrp->IoStatus = Irp->IoStatus; 163 } 164 165 IoFreeMdl(Irp->MdlAddress); 166 IoFreeIrp(Irp ); 167 } 168 169 if (InterlockedDecrement(&pContext->Blocks) == 0) { 170 171 pContext->MasterIrp->IoStatus.Information = 0; 172 if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status)) { 173 174 pContext->MasterIrp->IoStatus.Information = 175 pContext->Length; 176 } 177 178 KeSetEvent(&pContext->Event, 0, FALSE); 179 } 180 181 return STATUS_MORE_PROCESSING_REQUIRED; 182 } 183 184 NTSTATUS NTAPI 185 Ext2ReadWriteBlockAsyncCompletionRoutine ( 186 IN PDEVICE_OBJECT DeviceObject, 187 IN PIRP Irp, 188 IN PVOID Context 189 ) 190 { 191 PEXT2_RW_CONTEXT pContext = (PEXT2_RW_CONTEXT)Context; 192 PIO_STACK_LOCATION iosp; 193 194 ASSERT(FALSE == pContext->Wait); 195 196 if (Irp != pContext->MasterIrp && !NT_SUCCESS(Irp->IoStatus.Status)) { 197 pContext->MasterIrp->IoStatus = Irp->IoStatus; 198 } 199 200 if (InterlockedDecrement(&pContext->Blocks) == 0) { 201 202 if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status)) { 203 204 /* set written bytes to status information */ 205 pContext->MasterIrp->IoStatus.Information = pContext->Length; 206 207 if (pContext->FileObject != NULL && !IsFlagOn(pContext->MasterIrp->Flags, IRP_PAGING_IO)) { 208 209 /* modify FileObject flags, skip this for volume direct access */ 210 SetFlag( pContext->FileObject->Flags, 211 IsFlagOn(pContext->Flags, EXT2_RW_CONTEXT_WRITE) ? 212 FO_FILE_MODIFIED : FO_FILE_FAST_IO_READ); 213 214 /* update Current Byteoffset */ 215 if (IsFlagOn(pContext->FileObject->Flags, FO_SYNCHRONOUS_IO)) { 216 iosp = IoGetCurrentIrpStackLocation(pContext->MasterIrp); 217 pContext->FileObject->CurrentByteOffset.QuadPart = 218 iosp->Parameters.Read.ByteOffset.QuadPart + pContext->Length; 219 } 220 } 221 222 } else { 223 224 pContext->MasterIrp->IoStatus.Information = 0; 225 } 226 227 /* release the locked resource acquired by the caller */ 228 if (pContext->Resource) { 229 ExReleaseResourceForThread(pContext->Resource, pContext->ThreadId); 230 } 231 232 Ext2FreePool(pContext, EXT2_RWC_MAGIC); 233 DEC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); 234 } 235 236 return STATUS_SUCCESS; 237 } 238 239 NTSTATUS 240 Ext2ReadWriteBlocks( 241 IN PEXT2_IRP_CONTEXT IrpContext, 242 IN PEXT2_VCB Vcb, 243 IN PEXT2_EXTENT Chain, 244 IN ULONG Length 245 ) 246 { 247 PIRP Irp; 248 PIRP MasterIrp = IrpContext->Irp; 249 PIO_STACK_LOCATION IrpSp; 250 PMDL Mdl; 251 PEXT2_RW_CONTEXT pContext = NULL; 252 PEXT2_EXTENT Extent; 253 KEVENT Wait; 254 NTSTATUS Status = STATUS_SUCCESS; 255 BOOLEAN bMasterCompleted = FALSE; 256 BOOLEAN bBugCheck = FALSE; 257 258 ASSERT(MasterIrp); 259 260 _SEH2_TRY { 261 262 pContext = Ext2AllocatePool(NonPagedPool, sizeof(EXT2_RW_CONTEXT), EXT2_RWC_MAGIC); 263 264 if (!pContext) { 265 DEBUG(DL_ERR, ( "Ex2ReadWriteBlocks: failed to allocate pContext.\n")); 266 Status = STATUS_INSUFFICIENT_RESOURCES; 267 _SEH2_LEAVE; 268 } 269 270 INC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); 271 RtlZeroMemory(pContext, sizeof(EXT2_RW_CONTEXT)); 272 pContext->Wait = Ext2CanIWait(); 273 pContext->MasterIrp = MasterIrp; 274 pContext->Length = Length; 275 276 if (IrpContext->MajorFunction == IRP_MJ_WRITE) { 277 SetFlag(pContext->Flags, EXT2_RW_CONTEXT_WRITE); 278 } 279 280 if (pContext->Wait) { 281 282 KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE); 283 284 } else if (IrpContext->Fcb->Identifier.Type == EXT2FCB) { 285 286 if (IsFlagOn(MasterIrp->Flags, IRP_PAGING_IO)) { 287 pContext->Resource = &IrpContext->Fcb->PagingIoResource; 288 } else { 289 pContext->Resource = &IrpContext->Fcb->MainResource; 290 } 291 292 pContext->FileObject = IrpContext->FileObject; 293 pContext->ThreadId = ExGetCurrentResourceThread(); 294 } 295 296 297 if (NULL == Chain->Next && 0 == Chain->Offset) { 298 299 /* we get only 1 extent to dispatch, then don't bother allocating new irps */ 300 301 /* setup the Stack location to do a read from the disk driver. */ 302 IrpSp = IoGetNextIrpStackLocation(MasterIrp); 303 IrpSp->MajorFunction = IrpContext->MajorFunction; 304 IrpSp->Parameters.Read.Length = Chain->Length; 305 IrpSp->Parameters.Read.ByteOffset.QuadPart = Chain->Lba; 306 if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) { 307 SetFlag(IrpSp->Flags, SL_WRITE_THROUGH); 308 } 309 if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) { 310 SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME); 311 } 312 313 IoSetCompletionRoutine( 314 MasterIrp, 315 Ext2CanIWait() ? 316 Ext2ReadWriteBlockSyncCompletionRoutine : 317 Ext2ReadWriteBlockAsyncCompletionRoutine, 318 (PVOID) pContext, 319 TRUE, 320 TRUE, 321 TRUE ); 322 323 /* intialize context block */ 324 Chain->Irp = MasterIrp; 325 pContext->Blocks = 1; 326 327 } else { 328 329 for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { 330 331 Irp = IoMakeAssociatedIrp( 332 MasterIrp, 333 (CCHAR)(Vcb->TargetDeviceObject->StackSize + 1) ); 334 335 if (!Irp) { 336 Status = STATUS_INSUFFICIENT_RESOURCES; 337 _SEH2_LEAVE; 338 } 339 340 Mdl = IoAllocateMdl( (PCHAR)MasterIrp->UserBuffer + 341 Extent->Offset, 342 Extent->Length, 343 FALSE, 344 FALSE, 345 Irp ); 346 347 if (!Mdl) { 348 Status = STATUS_INSUFFICIENT_RESOURCES; 349 _SEH2_LEAVE; 350 } 351 352 IoBuildPartialMdl( MasterIrp->MdlAddress, 353 Mdl, 354 (PCHAR)MasterIrp->UserBuffer+Extent->Offset, 355 Extent->Length ); 356 357 IoSetNextIrpStackLocation(Irp); 358 IrpSp = IoGetCurrentIrpStackLocation(Irp); 359 360 IrpSp->MajorFunction = IrpContext->MajorFunction; 361 IrpSp->Parameters.Read.Length = Extent->Length; 362 IrpSp->Parameters.Read.ByteOffset.QuadPart = Extent->Lba; 363 364 IoSetCompletionRoutine( 365 Irp, 366 Ext2CanIWait() ? 367 Ext2ReadWriteBlockSyncCompletionRoutine : 368 Ext2ReadWriteBlockAsyncCompletionRoutine, 369 (PVOID) pContext, 370 TRUE, 371 TRUE, 372 TRUE ); 373 374 IrpSp = IoGetNextIrpStackLocation(Irp); 375 376 IrpSp->MajorFunction = IrpContext->MajorFunction; 377 IrpSp->Parameters.Read.Length =Extent->Length; 378 IrpSp->Parameters.Read.ByteOffset.QuadPart = Extent->Lba; 379 380 /* set write through flag */ 381 if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) { 382 SetFlag( IrpSp->Flags, SL_WRITE_THROUGH ); 383 } 384 385 /* set verify flag */ 386 if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) { 387 SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME); 388 } 389 390 Extent->Irp = Irp; 391 pContext->Blocks += 1; 392 } 393 394 MasterIrp->AssociatedIrp.IrpCount = pContext->Blocks; 395 if (Ext2CanIWait()) { 396 MasterIrp->AssociatedIrp.IrpCount += 1; 397 } 398 } 399 if (!Ext2CanIWait()) { 400 /* mark MasterIrp pending */ 401 IoMarkIrpPending(pContext->MasterIrp); 402 } 403 404 bBugCheck = TRUE; 405 406 for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { 407 Status = IoCallDriver ( Vcb->TargetDeviceObject, 408 Extent->Irp); 409 Extent->Irp = NULL; 410 } 411 412 if (Ext2CanIWait()) { 413 KeWaitForSingleObject( &(pContext->Event), 414 Executive, KernelMode, FALSE, NULL ); 415 KeClearEvent( &(pContext->Event) ); 416 } else { 417 bMasterCompleted = TRUE; 418 } 419 420 } _SEH2_FINALLY { 421 422 for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { 423 if (Extent->Irp != NULL ) { 424 if (Extent->Irp->MdlAddress != NULL) { 425 IoFreeMdl(Extent->Irp->MdlAddress ); 426 } 427 IoFreeIrp(Extent->Irp); 428 } 429 } 430 431 if (IrpContext->ExceptionInProgress) { 432 433 if (bBugCheck) { 434 Ext2BugCheck(EXT2_BUGCHK_BLOCK, 0, 0, 0); 435 } 436 437 } else { 438 439 if (Ext2CanIWait()) { 440 if (MasterIrp) { 441 Status = MasterIrp->IoStatus.Status; 442 } 443 if (pContext) { 444 Ext2FreePool(pContext, EXT2_RWC_MAGIC); 445 DEC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); 446 } 447 } else { 448 if (bMasterCompleted) { 449 IrpContext->Irp = NULL; 450 Status = STATUS_PENDING; 451 } 452 } 453 } 454 } _SEH2_END; 455 456 return Status; 457 } 458 459 NTSTATUS 460 Ext2ReadSync( 461 IN PEXT2_VCB Vcb, 462 IN ULONGLONG Offset, 463 IN ULONG Length, 464 OUT PVOID Buffer, 465 BOOLEAN bVerify 466 ) 467 { 468 PKEVENT Event = NULL; 469 470 PIRP Irp; 471 IO_STATUS_BLOCK IoStatus; 472 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; 473 474 475 ASSERT(Vcb != NULL); 476 ASSERT(Vcb->TargetDeviceObject != NULL); 477 ASSERT(Buffer != NULL); 478 479 _SEH2_TRY { 480 481 Event = Ext2AllocatePool(NonPagedPool, sizeof(KEVENT), 'EK2E'); 482 483 if (NULL == Event) { 484 DEBUG(DL_ERR, ( "Ex2ReadSync: failed to allocate Event.\n")); 485 _SEH2_LEAVE; 486 } 487 488 INC_MEM_COUNT(PS_DISK_EVENT, Event, sizeof(KEVENT)); 489 490 KeInitializeEvent(Event, NotificationEvent, FALSE); 491 492 Irp = IoBuildSynchronousFsdRequest( 493 IRP_MJ_READ, 494 Vcb->TargetDeviceObject, 495 Buffer, 496 Length, 497 (PLARGE_INTEGER)(&Offset), 498 Event, 499 &IoStatus 500 ); 501 502 if (!Irp) { 503 Status = STATUS_INSUFFICIENT_RESOURCES; 504 _SEH2_LEAVE; 505 } 506 507 if (bVerify) { 508 SetFlag( IoGetNextIrpStackLocation(Irp)->Flags, 509 SL_OVERRIDE_VERIFY_VOLUME ); 510 } 511 512 Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); 513 514 if (Status == STATUS_PENDING) { 515 KeWaitForSingleObject( 516 Event, 517 Suspended, 518 KernelMode, 519 FALSE, 520 NULL 521 ); 522 523 Status = IoStatus.Status; 524 } 525 526 } _SEH2_FINALLY { 527 528 if (Event) { 529 Ext2FreePool(Event, 'EK2E'); 530 DEC_MEM_COUNT(PS_DISK_EVENT, Event, sizeof(KEVENT)); 531 } 532 } _SEH2_END; 533 534 return Status; 535 } 536 537 538 NTSTATUS 539 Ext2ReadDisk( 540 IN PEXT2_VCB Vcb, 541 IN ULONGLONG Offset, 542 IN ULONG Size, 543 IN PVOID Buffer, 544 IN BOOLEAN bVerify ) 545 { 546 NTSTATUS Status; 547 PUCHAR Buf; 548 ULONG Length; 549 ULONGLONG Lba; 550 551 Lba = Offset & (~((ULONGLONG)SECTOR_SIZE - 1)); 552 Length = (ULONG)(Size + Offset + SECTOR_SIZE - 1 - Lba) & 553 (~((ULONG)SECTOR_SIZE - 1)); 554 555 Buf = Ext2AllocatePool(PagedPool, Length, EXT2_DATA_MAGIC); 556 if (!Buf) { 557 DEBUG(DL_ERR, ( "Ext2ReadDisk: failed to allocate Buffer.\n")); 558 Status = STATUS_INSUFFICIENT_RESOURCES; 559 560 goto errorout; 561 } 562 INC_MEM_COUNT(PS_DISK_BUFFER, Buf, Length); 563 564 Status = Ext2ReadSync( Vcb, 565 Lba, 566 Length, 567 Buf, 568 FALSE ); 569 570 if (!NT_SUCCESS(Status)) { 571 DEBUG(DL_ERR, ("Ext2ReadDisk: disk i/o error: %xh.\n", Status)); 572 goto errorout; 573 } 574 575 RtlCopyMemory(Buffer, &Buf[Offset - Lba], Size); 576 577 errorout: 578 579 if (Buf) { 580 Ext2FreePool(Buf, EXT2_DATA_MAGIC); 581 DEC_MEM_COUNT(PS_DISK_BUFFER, Buf, Length); 582 } 583 584 return Status; 585 } 586 587 588 NTSTATUS 589 Ext2DiskIoControl ( 590 IN PDEVICE_OBJECT DeviceObject, 591 IN ULONG IoctlCode, 592 IN PVOID InputBuffer, 593 IN ULONG InputBufferSize, 594 IN OUT PVOID OutputBuffer, 595 IN OUT PULONG OutputBufferSize) 596 { 597 ULONG OutBufferSize = 0; 598 KEVENT Event; 599 PIRP Irp; 600 IO_STATUS_BLOCK IoStatus; 601 NTSTATUS Status; 602 603 ASSERT(DeviceObject != NULL); 604 605 if (OutputBufferSize) 606 { 607 OutBufferSize = *OutputBufferSize; 608 } 609 610 KeInitializeEvent(&Event, NotificationEvent, FALSE); 611 612 Irp = IoBuildDeviceIoControlRequest( 613 IoctlCode, 614 DeviceObject, 615 InputBuffer, 616 InputBufferSize, 617 OutputBuffer, 618 OutBufferSize, 619 FALSE, 620 &Event, 621 &IoStatus 622 ); 623 624 if (Irp == NULL) { 625 DEBUG(DL_ERR, ( "Ext2DiskIoControl: failed to build Irp!\n")); 626 return STATUS_INSUFFICIENT_RESOURCES; 627 } 628 629 Status = IoCallDriver(DeviceObject, Irp); 630 631 if (Status == STATUS_PENDING) { 632 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 633 Status = IoStatus.Status; 634 } 635 636 if (OutputBufferSize) { 637 *OutputBufferSize = (ULONG)(IoStatus.Information); 638 } 639 640 return Status; 641 } 642 643 644 NTSTATUS NTAPI 645 Ext2MediaEjectControlCompletion ( 646 IN PDEVICE_OBJECT DeviceObject, 647 IN PIRP Irp, 648 IN PVOID Contxt 649 ) 650 { 651 PKEVENT Event = (PKEVENT)Contxt; 652 653 KeSetEvent( Event, 0, FALSE ); 654 655 UNREFERENCED_PARAMETER( DeviceObject ); 656 657 return STATUS_SUCCESS; 658 } 659 660 VOID 661 Ext2MediaEjectControl ( 662 IN PEXT2_IRP_CONTEXT IrpContext, 663 IN PEXT2_VCB Vcb, 664 IN BOOLEAN bPrevent 665 ) 666 { 667 PIRP Irp; 668 KEVENT Event; 669 NTSTATUS Status; 670 PREVENT_MEDIA_REMOVAL Prevent; 671 IO_STATUS_BLOCK IoStatus; 672 673 674 ExAcquireResourceExclusiveLite( 675 &Vcb->MainResource, 676 TRUE ); 677 678 if (bPrevent != IsFlagOn(Vcb->Flags, VCB_REMOVAL_PREVENTED)) { 679 if (bPrevent) { 680 SetFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED); 681 } else { 682 ClearFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED); 683 } 684 } 685 686 ExReleaseResourceLite(&Vcb->MainResource); 687 688 Prevent.PreventMediaRemoval = bPrevent; 689 690 KeInitializeEvent( &Event, NotificationEvent, FALSE ); 691 692 Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_MEDIA_REMOVAL, 693 Vcb->TargetDeviceObject, 694 &Prevent, 695 sizeof(PREVENT_MEDIA_REMOVAL), 696 NULL, 697 0, 698 FALSE, 699 NULL, 700 &IoStatus ); 701 702 if (Irp != NULL) { 703 IoSetCompletionRoutine( Irp, 704 Ext2MediaEjectControlCompletion, 705 &Event, 706 TRUE, 707 TRUE, 708 TRUE ); 709 710 Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); 711 712 if (Status == STATUS_PENDING) { 713 Status = KeWaitForSingleObject( &Event, 714 Executive, 715 KernelMode, 716 FALSE, 717 NULL ); 718 } 719 } 720 } 721 722 723 NTSTATUS 724 Ext2DiskShutDown(PEXT2_VCB Vcb) 725 { 726 PIRP Irp; 727 KEVENT Event; 728 729 NTSTATUS Status; 730 IO_STATUS_BLOCK IoStatus; 731 732 KeInitializeEvent(&Event, NotificationEvent, FALSE); 733 734 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, 735 Vcb->TargetDeviceObject, 736 NULL, 737 0, 738 NULL, 739 &Event, 740 &IoStatus); 741 742 if (Irp) { 743 Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); 744 745 if (Status == STATUS_PENDING) { 746 KeWaitForSingleObject(&Event, 747 Executive, 748 KernelMode, 749 FALSE, 750 NULL); 751 752 Status = IoStatus.Status; 753 } 754 } else { 755 Status = IoStatus.Status; 756 } 757 758 return Status; 759 } 760