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