xref: /reactos/drivers/filesystems/ext2/src/block.c (revision aaeb131b)
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
Ext2CreateMdl(IN PVOID Buffer,IN ULONG Length,IN LOCK_OPERATION op)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
Ext2DestroyMdl(IN PMDL Mdl)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
Ext2LockUserBuffer(IN PIRP Irp,IN ULONG Length,IN LOCK_OPERATION Operation)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
Ext2GetUserBuffer(IN PIRP Irp)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
Ext2ReadWriteBlockSyncCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)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
Ext2ReadWriteBlockAsyncCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)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
Ext2ReadWriteBlocks(IN PEXT2_IRP_CONTEXT IrpContext,IN PEXT2_VCB Vcb,IN PEXT2_EXTENT Chain,IN ULONG Length)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
Ext2ReadSync(IN PEXT2_VCB Vcb,IN ULONGLONG Offset,IN ULONG Length,OUT PVOID Buffer,BOOLEAN bVerify)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
Ext2ReadDisk(IN PEXT2_VCB Vcb,IN ULONGLONG Offset,IN ULONG Size,IN PVOID Buffer,IN BOOLEAN bVerify)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
Ext2DiskIoControl(IN PDEVICE_OBJECT DeviceObject,IN ULONG IoctlCode,IN PVOID InputBuffer,IN ULONG InputBufferSize,IN OUT PVOID OutputBuffer,IN OUT PULONG OutputBufferSize)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
Ext2MediaEjectControlCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Contxt)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
Ext2MediaEjectControl(IN PEXT2_IRP_CONTEXT IrpContext,IN PEXT2_VCB Vcb,IN BOOLEAN bPrevent)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
Ext2DiskShutDown(PEXT2_VCB Vcb)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