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));
258 Status
= STATUS_INSUFFICIENT_RESOURCES
;
262 Mdl
= IoAllocateMdl((PCHAR
)MasterIrp
->UserBuffer
+
271 Status
= STATUS_INSUFFICIENT_RESOURCES
;
275 IoBuildPartialMdl(MasterIrp
->MdlAddress
,
277 (PCHAR
)MasterIrp
->UserBuffer
+ FFSBDL
[i
].Offset
,
280 IoSetNextIrpStackLocation(Irp
);
281 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
284 IrpSp
->MajorFunction
= IrpContext
->MajorFunction
;
285 IrpSp
->Parameters
.Read
.Length
= FFSBDL
[i
].Length
;
286 IrpSp
->Parameters
.Read
.ByteOffset
.QuadPart
= FFSBDL
[i
].Lba
;
288 IoSetCompletionRoutine(Irp
,
289 IrpContext
->IsSynchronous
?
290 &FFSReadWriteBlockSyncCompletionRoutine
:
291 &FFSReadWriteBlockAsyncCompletionRoutine
,
297 IrpSp
= IoGetNextIrpStackLocation(Irp
);
299 IrpSp
->MajorFunction
= IrpContext
->MajorFunction
;
300 IrpSp
->Parameters
.Read
.Length
= FFSBDL
[i
].Length
;
301 IrpSp
->Parameters
.Read
.ByteOffset
.QuadPart
= FFSBDL
[i
].Lba
;
305 SetFlag(IrpSp
->Flags
, SL_OVERRIDE_VERIFY_VOLUME
);
311 MasterIrp
->AssociatedIrp
.IrpCount
= Count
;
313 if (IrpContext
->IsSynchronous
)
315 MasterIrp
->AssociatedIrp
.IrpCount
+= 1;
318 pContext
->Length
= Length
;
322 for (i
= 0; i
< Count
; i
++)
324 Status
= IoCallDriver(Vcb
->TargetDeviceObject
,
328 if (IrpContext
->IsSynchronous
)
330 KeWaitForSingleObject(&(pContext
->Event
),
331 Executive
, KernelMode
, FALSE
, NULL
);
333 KeClearEvent(&(pContext
->Event
));
339 if (IrpContext
->IsSynchronous
)
342 Status
= MasterIrp
->IoStatus
.Status
;
345 ExFreePool(pContext
);
350 IrpContext
->Irp
= NULL
;
351 Status
= STATUS_PENDING
;
354 if (_SEH2_AbnormalTermination())
358 FFSBugCheck(FFS_BUGCHK_BLOCK
, 0, 0, 0);
361 for (i
= 0; i
< Count
; i
++)
363 if (FFSBDL
[i
].Irp
!= NULL
)
365 if (FFSBDL
[i
].Irp
->MdlAddress
!= NULL
)
367 IoFreeMdl(FFSBDL
[i
].Irp
->MdlAddress
);
370 IoFreeIrp(FFSBDL
[i
].Irp
);
390 IO_STATUS_BLOCK IoStatus
;
396 ASSERT(Vcb
->TargetDeviceObject
!= NULL
);
397 ASSERT(Buffer
!= NULL
);
399 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
401 Irp
= IoBuildSynchronousFsdRequest(
403 Vcb
->TargetDeviceObject
,
406 (PLARGE_INTEGER
)(&Offset
),
412 return STATUS_INSUFFICIENT_RESOURCES
;
417 SetFlag(IoGetNextIrpStackLocation(Irp
)->Flags
,
418 SL_OVERRIDE_VERIFY_VOLUME
);
421 Status
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
423 if (Status
== STATUS_PENDING
)
425 KeWaitForSingleObject(
432 Status
= IoStatus
.Status
;
454 Lba
= Offset
& (~((ULONGLONG
)SECTOR_SIZE
- 1));
455 Length
= (ULONG
)(Size
+ Offset
+ SECTOR_SIZE
- 1 - Lba
) &
456 (~((ULONG
)SECTOR_SIZE
- 1));
458 Buf
= ExAllocatePoolWithTag(PagedPool
, Length
, FFS_POOL_TAG
);
461 FFSPrint((DBG_ERROR
, "FFSReadDisk: no enough memory.\n"));
462 Status
= STATUS_INSUFFICIENT_RESOURCES
;
467 Status
= FFSReadSync(Vcb
,
473 if (!NT_SUCCESS(Status
))
475 FFSPrint((DBG_ERROR
, "FFSReadDisk: Read Block Device error.\n"));
480 RtlCopyMemory(Buffer
, &Buf
[Offset
- Lba
], Size
);
493 IN PDEVICE_OBJECT DeviceObject
,
495 IN PVOID InputBuffer
,
496 IN ULONG InputBufferSize
,
497 IN OUT PVOID OutputBuffer
,
498 IN OUT PULONG OutputBufferSize
)
500 ULONG OutBufferSize
= 0;
503 IO_STATUS_BLOCK IoStatus
;
508 ASSERT(DeviceObject
!= NULL
);
510 if (OutputBufferSize
)
512 OutBufferSize
= *OutputBufferSize
;
515 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
517 Irp
= IoBuildDeviceIoControlRequest(
530 FFSPrint((DBG_ERROR
, "FFSDiskIoControl: Building IRQ error!\n"));
531 return STATUS_INSUFFICIENT_RESOURCES
;
534 Status
= IoCallDriver(DeviceObject
, Irp
);
536 if (Status
== STATUS_PENDING
)
538 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
539 Status
= IoStatus
.Status
;
542 if (OutputBufferSize
)
544 *OutputBufferSize
= (ULONG
) IoStatus
.Information
;
552 FFSMediaEjectControlCompletion(
553 IN PDEVICE_OBJECT DeviceObject
,
557 PKEVENT Event
= (PKEVENT
)Contxt
;
559 KeSetEvent(Event
, 0, FALSE
);
561 UNREFERENCED_PARAMETER(DeviceObject
);
563 return STATUS_SUCCESS
;
567 __drv_mustHoldCriticalRegion
569 FFSMediaEjectControl(
570 IN PFFS_IRP_CONTEXT IrpContext
,
577 PREVENT_MEDIA_REMOVAL Prevent
;
578 IO_STATUS_BLOCK IoStatus
;
582 ExAcquireResourceExclusiveLite(
586 if (bPrevent
!= IsFlagOn(Vcb
->Flags
, VCB_REMOVAL_PREVENTED
))
590 SetFlag(Vcb
->Flags
, VCB_REMOVAL_PREVENTED
);
594 ClearFlag(Vcb
->Flags
, VCB_REMOVAL_PREVENTED
);
598 ExReleaseResourceForThreadLite(
600 ExGetCurrentResourceThread());
602 Prevent
.PreventMediaRemoval
= bPrevent
;
604 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
606 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_MEDIA_REMOVAL
,
607 Vcb
->TargetDeviceObject
,
609 sizeof(PREVENT_MEDIA_REMOVAL
),
618 IoSetCompletionRoutine(Irp
,
619 FFSMediaEjectControlCompletion
,
625 Status
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
627 if (Status
== STATUS_PENDING
)
629 Status
= KeWaitForSingleObject(&Event
,
646 IO_STATUS_BLOCK IoStatus
;
650 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
652 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN
,
653 Vcb
->TargetDeviceObject
,
662 Status
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
664 if (Status
== STATUS_PENDING
)
666 KeWaitForSingleObject(&Event
,
672 Status
= IoStatus
.Status
;
677 Status
= IoStatus
.Status
;