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