2 * FFS File System Driver for Windows
8 * Lee Jae-Hong, http://www.pyrasis.com
19 extern PFFS_GLOBAL FFSGlobal
;
24 typedef struct _FFS_RW_CONTEXT
{
30 } FFS_RW_CONTEXT
, *PFFS_RW_CONTEXT
;
33 IO_COMPLETION_ROUTINE FFSReadWriteBlockSyncCompletionRoutine
;
34 IO_COMPLETION_ROUTINE FFSReadWriteBlockAsyncCompletionRoutine
;
35 IO_COMPLETION_ROUTINE FFSMediaEjectControlCompletion
;
39 FFSReadWriteBlockSyncCompletionRoutine(
40 IN PDEVICE_OBJECT DeviceObject
,
45 FFSReadWriteBlockAsyncCompletionRoutine(
46 IN PDEVICE_OBJECT DeviceObject
,
51 FFSMediaEjectControlCompletion(
52 IN PDEVICE_OBJECT DeviceObject
,
58 #pragma alloc_text(PAGE, FFSLockUserBuffer)
59 #pragma alloc_text(PAGE, FFSGetUserBuffer)
60 #pragma alloc_text(PAGE, FFSReadSync)
61 #pragma alloc_text(PAGE, FFSReadDisk)
62 #pragma alloc_text(PAGE, FFSDiskIoControl)
63 #pragma alloc_text(PAGE, FFSReadWriteBlocks)
64 #pragma alloc_text(PAGE, FFSMediaEjectControl)
65 #pragma alloc_text(PAGE, FFSDiskShutDown)
73 IN LOCK_OPERATION Operation
)
81 if (Irp
->MdlAddress
!= NULL
)
83 return STATUS_SUCCESS
;
86 IoAllocateMdl(Irp
->UserBuffer
, Length
, FALSE
, FALSE
, Irp
);
88 if (Irp
->MdlAddress
== NULL
)
90 return STATUS_INSUFFICIENT_RESOURCES
;
95 MmProbeAndLockPages(Irp
->MdlAddress
, Irp
->RequestorMode
, Operation
);
97 Status
= STATUS_SUCCESS
;
99 _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
)
101 IoFreeMdl(Irp
->MdlAddress
);
103 Irp
->MdlAddress
= NULL
;
107 Status
= STATUS_INVALID_USER_BUFFER
;
124 #if (_WIN32_WINNT >= 0x0500)
125 return MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
127 return MmGetSystemAddressForMdl(Irp
->MdlAddress
);
132 return Irp
->UserBuffer
;
138 FFSReadWriteBlockSyncCompletionRoutine(
139 IN PDEVICE_OBJECT DeviceObject
,
143 PFFS_RW_CONTEXT pContext
= (PFFS_RW_CONTEXT
)Context
;
145 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
148 pContext
->MasterIrp
->IoStatus
= Irp
->IoStatus
;
151 IoFreeMdl(Irp
->MdlAddress
);
154 if (InterlockedDecrement(&pContext
->Blocks
) == 0)
156 pContext
->MasterIrp
->IoStatus
.Information
= 0;
158 if (NT_SUCCESS(pContext
->MasterIrp
->IoStatus
.Status
))
160 pContext
->MasterIrp
->IoStatus
.Information
=
164 KeSetEvent(&pContext
->Event
, 0, FALSE
);
167 UNREFERENCED_PARAMETER(DeviceObject
);
169 return STATUS_MORE_PROCESSING_REQUIRED
;
173 FFSReadWriteBlockAsyncCompletionRoutine(
174 IN PDEVICE_OBJECT DeviceObject
,
178 PFFS_RW_CONTEXT pContext
= (PFFS_RW_CONTEXT
)Context
;
180 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
182 pContext
->MasterIrp
->IoStatus
= Irp
->IoStatus
;
185 if (InterlockedDecrement(&pContext
->Blocks
) == 0)
187 pContext
->MasterIrp
->IoStatus
.Information
= 0;
189 if (NT_SUCCESS(pContext
->MasterIrp
->IoStatus
.Status
))
191 pContext
->MasterIrp
->IoStatus
.Information
=
195 IoMarkIrpPending(pContext
->MasterIrp
);
197 ExFreePool(pContext
);
200 UNREFERENCED_PARAMETER(DeviceObject
);
202 return STATUS_SUCCESS
;
208 IN PFFS_IRP_CONTEXT IrpContext
,
217 PIRP MasterIrp
= IrpContext
->Irp
;
218 PIO_STACK_LOCATION IrpSp
;
219 NTSTATUS Status
= STATUS_SUCCESS
;
220 PFFS_RW_CONTEXT pContext
= NULL
;
222 BOOLEAN bBugCheck
= FALSE
;
231 pContext
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(FFS_RW_CONTEXT
), FFS_POOL_TAG
);
235 Status
= STATUS_INSUFFICIENT_RESOURCES
;
239 RtlZeroMemory(pContext
, sizeof(FFS_RW_CONTEXT
));
241 pContext
->Wait
= IrpContext
->IsSynchronous
;
242 pContext
->MasterIrp
= MasterIrp
;
243 pContext
->Blocks
= Count
;
244 pContext
->Length
= 0;
248 KeInitializeEvent(&(pContext
->Event
), NotificationEvent
, FALSE
);
251 for (i
= 0; i
< Count
; i
++)
254 Irp
= IoMakeAssociatedIrp(MasterIrp
,
255 (CCHAR
)(Vcb
->TargetDeviceObject
->StackSize
+ 1));
259 ExFreePoolWithTag(pContext
, FFS_POOL_TAG
);
262 Status
= STATUS_INSUFFICIENT_RESOURCES
;
266 Mdl
= IoAllocateMdl((PCHAR
)MasterIrp
->UserBuffer
+
276 ExFreePoolWithTag(pContext
, FFS_POOL_TAG
);
279 Status
= STATUS_INSUFFICIENT_RESOURCES
;
283 IoBuildPartialMdl(MasterIrp
->MdlAddress
,
285 (PCHAR
)MasterIrp
->UserBuffer
+ FFSBDL
[i
].Offset
,
288 IoSetNextIrpStackLocation(Irp
);
289 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
292 IrpSp
->MajorFunction
= IrpContext
->MajorFunction
;
293 IrpSp
->Parameters
.Read
.Length
= FFSBDL
[i
].Length
;
294 IrpSp
->Parameters
.Read
.ByteOffset
.QuadPart
= FFSBDL
[i
].Lba
;
296 IoSetCompletionRoutine(Irp
,
297 IrpContext
->IsSynchronous
?
298 &FFSReadWriteBlockSyncCompletionRoutine
:
299 &FFSReadWriteBlockAsyncCompletionRoutine
,
305 IrpSp
= IoGetNextIrpStackLocation(Irp
);
307 IrpSp
->MajorFunction
= IrpContext
->MajorFunction
;
308 IrpSp
->Parameters
.Read
.Length
= FFSBDL
[i
].Length
;
309 IrpSp
->Parameters
.Read
.ByteOffset
.QuadPart
= FFSBDL
[i
].Lba
;
313 SetFlag(IrpSp
->Flags
, SL_OVERRIDE_VERIFY_VOLUME
);
319 MasterIrp
->AssociatedIrp
.IrpCount
= Count
;
321 if (IrpContext
->IsSynchronous
)
323 MasterIrp
->AssociatedIrp
.IrpCount
+= 1;
326 pContext
->Length
= Length
;
330 for (i
= 0; i
< Count
; i
++)
332 Status
= IoCallDriver(Vcb
->TargetDeviceObject
,
336 if (IrpContext
->IsSynchronous
)
338 KeWaitForSingleObject(&(pContext
->Event
),
339 Executive
, KernelMode
, FALSE
, NULL
);
341 KeClearEvent(&(pContext
->Event
));
347 if (IrpContext
->IsSynchronous
)
350 Status
= MasterIrp
->IoStatus
.Status
;
353 ExFreePool(pContext
);
358 IrpContext
->Irp
= NULL
;
359 Status
= STATUS_PENDING
;
362 if (_SEH2_AbnormalTermination())
366 FFSBugCheck(FFS_BUGCHK_BLOCK
, 0, 0, 0);
369 for (i
= 0; i
< Count
; i
++)
371 if (FFSBDL
[i
].Irp
!= NULL
)
373 if (FFSBDL
[i
].Irp
->MdlAddress
!= NULL
)
375 IoFreeMdl(FFSBDL
[i
].Irp
->MdlAddress
);
378 IoFreeIrp(FFSBDL
[i
].Irp
);
398 IO_STATUS_BLOCK IoStatus
;
404 ASSERT(Vcb
->TargetDeviceObject
!= NULL
);
405 ASSERT(Buffer
!= NULL
);
407 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
409 Irp
= IoBuildSynchronousFsdRequest(
411 Vcb
->TargetDeviceObject
,
414 (PLARGE_INTEGER
)(&Offset
),
420 return STATUS_INSUFFICIENT_RESOURCES
;
425 SetFlag(IoGetNextIrpStackLocation(Irp
)->Flags
,
426 SL_OVERRIDE_VERIFY_VOLUME
);
429 Status
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
431 if (Status
== STATUS_PENDING
)
433 KeWaitForSingleObject(
440 Status
= IoStatus
.Status
;
462 Lba
= Offset
& (~((ULONGLONG
)SECTOR_SIZE
- 1));
463 Length
= (ULONG
)(Size
+ Offset
+ SECTOR_SIZE
- 1 - Lba
) &
464 (~((ULONG
)SECTOR_SIZE
- 1));
466 Buf
= ExAllocatePoolWithTag(PagedPool
, Length
, FFS_POOL_TAG
);
469 FFSPrint((DBG_ERROR
, "FFSReadDisk: no enough memory.\n"));
470 Status
= STATUS_INSUFFICIENT_RESOURCES
;
475 Status
= FFSReadSync(Vcb
,
481 if (!NT_SUCCESS(Status
))
483 FFSPrint((DBG_ERROR
, "FFSReadDisk: Read Block Device error.\n"));
488 RtlCopyMemory(Buffer
, &Buf
[Offset
- Lba
], Size
);
501 IN PDEVICE_OBJECT DeviceObject
,
503 IN PVOID InputBuffer
,
504 IN ULONG InputBufferSize
,
505 IN OUT PVOID OutputBuffer
,
506 IN OUT PULONG OutputBufferSize
)
508 ULONG OutBufferSize
= 0;
511 IO_STATUS_BLOCK IoStatus
;
516 ASSERT(DeviceObject
!= NULL
);
518 if (OutputBufferSize
)
520 OutBufferSize
= *OutputBufferSize
;
523 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
525 Irp
= IoBuildDeviceIoControlRequest(
538 FFSPrint((DBG_ERROR
, "FFSDiskIoControl: Building IRQ error!\n"));
539 return STATUS_INSUFFICIENT_RESOURCES
;
542 Status
= IoCallDriver(DeviceObject
, Irp
);
544 if (Status
== STATUS_PENDING
)
546 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
547 Status
= IoStatus
.Status
;
550 if (OutputBufferSize
)
552 *OutputBufferSize
= (ULONG
) IoStatus
.Information
;
560 FFSMediaEjectControlCompletion(
561 IN PDEVICE_OBJECT DeviceObject
,
565 PKEVENT Event
= (PKEVENT
)Contxt
;
567 KeSetEvent(Event
, 0, FALSE
);
569 UNREFERENCED_PARAMETER(DeviceObject
);
571 return STATUS_SUCCESS
;
575 __drv_mustHoldCriticalRegion
577 FFSMediaEjectControl(
578 IN PFFS_IRP_CONTEXT IrpContext
,
585 PREVENT_MEDIA_REMOVAL Prevent
;
586 IO_STATUS_BLOCK IoStatus
;
590 ExAcquireResourceExclusiveLite(
594 if (bPrevent
!= IsFlagOn(Vcb
->Flags
, VCB_REMOVAL_PREVENTED
))
598 SetFlag(Vcb
->Flags
, VCB_REMOVAL_PREVENTED
);
602 ClearFlag(Vcb
->Flags
, VCB_REMOVAL_PREVENTED
);
606 ExReleaseResourceForThreadLite(
608 ExGetCurrentResourceThread());
610 Prevent
.PreventMediaRemoval
= bPrevent
;
612 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
614 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_MEDIA_REMOVAL
,
615 Vcb
->TargetDeviceObject
,
617 sizeof(PREVENT_MEDIA_REMOVAL
),
626 IoSetCompletionRoutine(Irp
,
627 FFSMediaEjectControlCompletion
,
633 Status
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
635 if (Status
== STATUS_PENDING
)
637 Status
= KeWaitForSingleObject(&Event
,
654 IO_STATUS_BLOCK IoStatus
;
658 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
660 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN
,
661 Vcb
->TargetDeviceObject
,
670 Status
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
672 if (Status
== STATUS_PENDING
)
674 KeWaitForSingleObject(&Event
,
680 Status
= IoStatus
.Status
;
685 Status
= IoStatus
.Status
;