2 * PROJECT: ReactOS FAT file system driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/filesystems/fastfat/fsctl.c
5 * PURPOSE: Filesystem control
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
9 /* INCLUDES *****************************************************************/
14 /* FUNCTIONS ****************************************************************/
18 FatUserFsCtrl(PFAT_IRP_CONTEXT IrpContext
, PIRP Irp
)
20 DPRINT1("FatUserFsCtrl()\n");
21 FatCompleteRequest(IrpContext
, Irp
, STATUS_INVALID_DEVICE_REQUEST
);
22 return STATUS_INVALID_DEVICE_REQUEST
;
27 FatVerifyVolume(PFAT_IRP_CONTEXT IrpContext
, PIRP Irp
)
29 DPRINT1("FatVerifyVolume()\n");
30 FatCompleteRequest(IrpContext
, Irp
, STATUS_INVALID_DEVICE_REQUEST
);
31 return STATUS_INVALID_DEVICE_REQUEST
;
36 FatiCleanVcbs(PFAT_IRP_CONTEXT IrpContext
)
38 /* Make sure this IRP is waitable */
39 ASSERT(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
);
41 /* Acquire global resource */
42 ExAcquireResourceExclusiveLite(&FatGlobalData
.Resource
, TRUE
);
44 /* TODO: Go through all VCBs and delete unmounted ones */
46 /* Release global resource */
47 ExReleaseResourceLite(&FatGlobalData
.Resource
);
52 FatMountVolume(PFAT_IRP_CONTEXT IrpContext
,
53 PDEVICE_OBJECT TargetDeviceObject
,
55 PDEVICE_OBJECT FsDeviceObject
)
58 DISK_GEOMETRY DiskGeometry
;
59 ULONG MediaChangeCount
= 0;
60 PVOLUME_DEVICE_OBJECT VolumeDevice
;
64 DPRINT1("FatMountVolume()\n");
66 /* Make sure this IRP is waitable */
67 ASSERT(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
);
69 /* Request media changes count, mostly usefull for removable devices */
70 Status
= FatPerformDevIoCtrl(TargetDeviceObject
,
71 IOCTL_STORAGE_CHECK_VERIFY
,
78 if (!NT_SUCCESS(Status
)) return Status
;
80 /* TODO: Check if data-track present in case of a CD drive */
81 /* TODO: IOCTL_DISK_GET_PARTITION_INFO_EX */
83 /* Remove unmounted VCBs */
84 FatiCleanVcbs(IrpContext
);
86 /* Acquire the global exclusive lock */
87 FatAcquireExclusiveGlobal(IrpContext
);
89 /* Create a new volume device object */
90 Status
= IoCreateDevice(FatGlobalData
.DriverObject
,
91 sizeof(VOLUME_DEVICE_OBJECT
) - sizeof(DEVICE_OBJECT
),
93 FILE_DEVICE_DISK_FILE_SYSTEM
,
96 (PDEVICE_OBJECT
*)&VolumeDevice
);
98 if (!NT_SUCCESS(Status
))
100 /* Release the global lock */
101 FatReleaseGlobal(IrpContext
);
106 /* Match alignment requirements */
107 if (TargetDeviceObject
->AlignmentRequirement
> VolumeDevice
->DeviceObject
.AlignmentRequirement
)
109 VolumeDevice
->DeviceObject
.AlignmentRequirement
= TargetDeviceObject
->AlignmentRequirement
;
112 /* Init stack size */
113 VolumeDevice
->DeviceObject
.StackSize
= TargetDeviceObject
->StackSize
+ 1;
115 /* Get sector size */
116 Status
= FatPerformDevIoCtrl(TargetDeviceObject
,
117 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
121 sizeof(DISK_GEOMETRY
),
124 if (!NT_SUCCESS(Status
)) goto FatMountVolumeCleanup
;
126 VolumeDevice
->DeviceObject
.SectorSize
= (USHORT
) DiskGeometry
.BytesPerSector
;
128 /* Signal we're done with initializing */
129 VolumeDevice
->DeviceObject
.Flags
&= ~DO_DEVICE_INITIALIZING
;
131 /* Save device object in a VPB */
132 Vpb
->DeviceObject
= (PDEVICE_OBJECT
)VolumeDevice
;
134 /* Initialize VCB for this volume */
135 Status
= FatInitializeVcb(IrpContext
, &VolumeDevice
->Vcb
, TargetDeviceObject
, Vpb
);
136 if (!NT_SUCCESS(Status
)) goto FatMountVolumeCleanup
;
138 Vcb
= &VolumeDevice
->Vcb
;
140 /* Initialize FullFAT library */
141 Vcb
->Ioman
= FF_CreateIOMAN(NULL
,
143 VolumeDevice
->DeviceObject
.SectorSize
,
148 /* Register block device read/write functions */
149 Error
= FF_RegisterBlkDevice(Vcb
->Ioman
,
150 VolumeDevice
->DeviceObject
.SectorSize
,
151 (FF_WRITE_BLOCKS
)FatWriteBlocks
,
152 (FF_READ_BLOCKS
)FatReadBlocks
,
157 DPRINT1("Registering block device with FullFAT failed with error %d\n", Error
);
158 FF_DestroyIOMAN(Vcb
->Ioman
);
159 goto FatMountVolumeCleanup
;
162 /* Mount the volume using FullFAT */
163 if(FF_MountPartition(Vcb
->Ioman
, 0))
165 DPRINT1("Partition mounting failed\n");
166 FF_DestroyIOMAN(Vcb
->Ioman
);
167 goto FatMountVolumeCleanup
;
170 // TODO: Read BPB and store it in Vcb->Bpb
172 /* Create root DCB for it */
173 FatCreateRootDcb(IrpContext
, &VolumeDevice
->Vcb
);
175 /* Keep trace of media changes */
176 VolumeDevice
->Vcb
.MediaChangeCount
= MediaChangeCount
;
178 //ObDereferenceObject(TargetDeviceObject);
180 /* Release the global lock */
181 FatReleaseGlobal(IrpContext
);
183 /* Notify about volume mount */
184 //FsRtlNotifyVolumeEvent(VolumeDevice->Vcb.StreamFileObject, FSRTL_VOLUME_MOUNT);
187 return STATUS_SUCCESS
;
190 FatMountVolumeCleanup
:
192 /* Unwind the routine actions */
193 IoDeleteDevice((PDEVICE_OBJECT
)VolumeDevice
);
195 /* Release the global lock */
196 FatReleaseGlobal(IrpContext
);
205 FatiFileSystemControl(PFAT_IRP_CONTEXT IrpContext
, PIRP Irp
)
207 PIO_STACK_LOCATION IrpSp
;
210 /* Get current IRP stack location */
211 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
213 /* Dispatch depending on the minor function */
214 switch (IrpSp
->MinorFunction
)
216 case IRP_MN_USER_FS_REQUEST
:
217 Status
= FatUserFsCtrl(IrpContext
, Irp
);
220 case IRP_MN_MOUNT_VOLUME
:
221 Status
= FatMountVolume(IrpContext
,
222 IrpSp
->Parameters
.MountVolume
.DeviceObject
,
223 IrpSp
->Parameters
.MountVolume
.Vpb
,
224 IrpSp
->DeviceObject
);
226 FatCompleteRequest(IrpContext
, Irp
, Status
);
230 case IRP_MN_VERIFY_VOLUME
:
231 Status
= FatVerifyVolume(IrpContext
, Irp
);
235 DPRINT1("Unhandled FSCTL minor 0x%x\n", IrpSp
->MinorFunction
);
236 FatCompleteRequest(IrpContext
, Irp
, STATUS_INVALID_DEVICE_REQUEST
);
237 Status
= STATUS_INVALID_DEVICE_REQUEST
;
246 FatFileSystemControl(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
248 NTSTATUS Status
= STATUS_SUCCESS
;
249 PFAT_IRP_CONTEXT IrpContext
;
250 BOOLEAN CanWait
= TRUE
;
252 DPRINT1("FatFileSystemControl(DeviceObject %p, Irp %p)\n", DeviceObject
, Irp
);
254 /* Get CanWait flag */
255 if (IoGetCurrentIrpStackLocation(Irp
)->FileObject
)
257 CanWait
= IoIsOperationSynchronous(Irp
);
260 /* Enter FsRtl critical region */
261 FsRtlEnterFileSystem();
263 /* Build an irp context */
264 IrpContext
= FatBuildIrpContext(Irp
, CanWait
);
266 /* Call internal function */
267 Status
= FatiFileSystemControl(IrpContext
, Irp
);
269 /* Leave FsRtl critical region */
270 FsRtlExitFileSystem();