d06343737e53d93493360a6715c8fe252f6a2d62
[reactos.git] / reactos / drivers / filesystems / ext2 / src / block.c
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 device error.\n"));
572
573 goto errorout;
574 }
575
576 RtlCopyMemory(Buffer, &Buf[Offset - Lba], Size);
577
578 errorout:
579
580 if (Buf) {
581 Ext2FreePool(Buf, EXT2_DATA_MAGIC);
582 DEC_MEM_COUNT(PS_DISK_BUFFER, Buf, Length);
583 }
584
585 return Status;
586 }
587
588
589 NTSTATUS
590 Ext2DiskIoControl (
591 IN PDEVICE_OBJECT DeviceObject,
592 IN ULONG IoctlCode,
593 IN PVOID InputBuffer,
594 IN ULONG InputBufferSize,
595 IN OUT PVOID OutputBuffer,
596 IN OUT PULONG OutputBufferSize)
597 {
598 ULONG OutBufferSize = 0;
599 KEVENT Event;
600 PIRP Irp;
601 IO_STATUS_BLOCK IoStatus;
602 NTSTATUS Status;
603
604 ASSERT(DeviceObject != NULL);
605
606 if (OutputBufferSize)
607 {
608 OutBufferSize = *OutputBufferSize;
609 }
610
611 KeInitializeEvent(&Event, NotificationEvent, FALSE);
612
613 Irp = IoBuildDeviceIoControlRequest(
614 IoctlCode,
615 DeviceObject,
616 InputBuffer,
617 InputBufferSize,
618 OutputBuffer,
619 OutBufferSize,
620 FALSE,
621 &Event,
622 &IoStatus
623 );
624
625 if (Irp == NULL) {
626 DEBUG(DL_ERR, ( "Ext2DiskIoControl: failed to build Irp!\n"));
627 return STATUS_INSUFFICIENT_RESOURCES;
628 }
629
630 Status = IoCallDriver(DeviceObject, Irp);
631
632 if (Status == STATUS_PENDING) {
633 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
634 Status = IoStatus.Status;
635 }
636
637 if (OutputBufferSize) {
638 *OutputBufferSize = (ULONG)(IoStatus.Information);
639 }
640
641 return Status;
642 }
643
644
645 NTSTATUS NTAPI
646 Ext2MediaEjectControlCompletion (
647 IN PDEVICE_OBJECT DeviceObject,
648 IN PIRP Irp,
649 IN PVOID Contxt
650 )
651 {
652 PKEVENT Event = (PKEVENT)Contxt;
653
654 KeSetEvent( Event, 0, FALSE );
655
656 UNREFERENCED_PARAMETER( DeviceObject );
657
658 return STATUS_SUCCESS;
659 }
660
661 VOID
662 Ext2MediaEjectControl (
663 IN PEXT2_IRP_CONTEXT IrpContext,
664 IN PEXT2_VCB Vcb,
665 IN BOOLEAN bPrevent
666 )
667 {
668 PIRP Irp;
669 KEVENT Event;
670 NTSTATUS Status;
671 PREVENT_MEDIA_REMOVAL Prevent;
672 IO_STATUS_BLOCK IoStatus;
673
674
675 ExAcquireResourceExclusiveLite(
676 &Vcb->MainResource,
677 TRUE );
678
679 if (bPrevent != IsFlagOn(Vcb->Flags, VCB_REMOVAL_PREVENTED)) {
680 if (bPrevent) {
681 SetFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED);
682 } else {
683 ClearFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED);
684 }
685 }
686
687 ExReleaseResourceLite(&Vcb->MainResource);
688
689 Prevent.PreventMediaRemoval = bPrevent;
690
691 KeInitializeEvent( &Event, NotificationEvent, FALSE );
692
693 Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_MEDIA_REMOVAL,
694 Vcb->TargetDeviceObject,
695 &Prevent,
696 sizeof(PREVENT_MEDIA_REMOVAL),
697 NULL,
698 0,
699 FALSE,
700 NULL,
701 &IoStatus );
702
703 if (Irp != NULL) {
704 IoSetCompletionRoutine( Irp,
705 Ext2MediaEjectControlCompletion,
706 &Event,
707 TRUE,
708 TRUE,
709 TRUE );
710
711 Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
712
713 if (Status == STATUS_PENDING) {
714 Status = KeWaitForSingleObject( &Event,
715 Executive,
716 KernelMode,
717 FALSE,
718 NULL );
719 }
720 }
721 }
722
723
724 NTSTATUS
725 Ext2DiskShutDown(PEXT2_VCB Vcb)
726 {
727 PIRP Irp;
728 KEVENT Event;
729
730 NTSTATUS Status;
731 IO_STATUS_BLOCK IoStatus;
732
733 KeInitializeEvent(&Event, NotificationEvent, FALSE);
734
735 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
736 Vcb->TargetDeviceObject,
737 NULL,
738 0,
739 NULL,
740 &Event,
741 &IoStatus);
742
743 if (Irp) {
744 Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
745
746 if (Status == STATUS_PENDING) {
747 KeWaitForSingleObject(&Event,
748 Executive,
749 KernelMode,
750 FALSE,
751 NULL);
752
753 Status = IoStatus.Status;
754 }
755 } else {
756 Status = IoStatus.Status;
757 }
758
759 return Status;
760 }