2 * PROJECT: ReactOS FAT file system driver
3 * LICENSE: GNU GPLv3 as published by the Free Software Foundation
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 FatiUnpackBpb(PBIOS_PARAMETER_BLOCK Bpb
, PPACKED_BIOS_PARAMETER_BLOCK PackedBpb
)
54 CopyUchar2(&Bpb
->BytesPerSector
, &PackedBpb
->BytesPerSector
[0]);
55 CopyUchar1(&Bpb
->SectorsPerCluster
, &PackedBpb
->SectorsPerCluster
[0]);
56 CopyUchar2(&Bpb
->ReservedSectors
, &PackedBpb
->ReservedSectors
[0]);
57 CopyUchar1(&Bpb
->Fats
, &PackedBpb
->Fats
[0]);
58 CopyUchar2(&Bpb
->RootEntries
, &PackedBpb
->RootEntries
[0]);
59 CopyUchar2(&Bpb
->Sectors
, &PackedBpb
->Sectors
[0]);
60 CopyUchar1(&Bpb
->Media
, &PackedBpb
->Media
[0]);
61 CopyUchar2(&Bpb
->SectorsPerFat
, &PackedBpb
->SectorsPerFat
[0]);
62 CopyUchar2(&Bpb
->SectorsPerTrack
, &PackedBpb
->SectorsPerTrack
[0]);
63 CopyUchar2(&Bpb
->Heads
, &PackedBpb
->Heads
[0]);
64 CopyUchar4(&Bpb
->HiddenSectors
, &PackedBpb
->HiddenSectors
[0]);
65 CopyUchar4(&Bpb
->LargeSectors
, &PackedBpb
->LargeSectors
[0]);
66 CopyUchar4(&Bpb
->LargeSectorsPerFat
, &((PPACKED_BIOS_PARAMETER_BLOCK_EX
)PackedBpb
)->LargeSectorsPerFat
[0]);
67 CopyUchar2(&Bpb
->ExtendedFlags
, &((PPACKED_BIOS_PARAMETER_BLOCK_EX
)PackedBpb
)->ExtendedFlags
[0]);
68 CopyUchar2(&Bpb
->FsVersion
, &((PPACKED_BIOS_PARAMETER_BLOCK_EX
)PackedBpb
)->FsVersion
[0]);
69 CopyUchar4(&Bpb
->RootDirFirstCluster
,&((PPACKED_BIOS_PARAMETER_BLOCK_EX
)PackedBpb
)->RootDirFirstCluster
[0]);
70 CopyUchar2(&Bpb
->FsInfoSector
, &((PPACKED_BIOS_PARAMETER_BLOCK_EX
)PackedBpb
)->FsInfoSector
[0]);
71 CopyUchar2(&Bpb
->BackupBootSector
, &((PPACKED_BIOS_PARAMETER_BLOCK_EX
)PackedBpb
)->BackupBootSector
[0]);
76 FatiBpbFat32(PPACKED_BIOS_PARAMETER_BLOCK PackedBpb
)
78 return (*(USHORT
*)(&PackedBpb
->SectorsPerFat
) == 0);
83 FatMountVolume(PFAT_IRP_CONTEXT IrpContext
,
84 PDEVICE_OBJECT TargetDeviceObject
,
86 PDEVICE_OBJECT FsDeviceObject
)
89 DISK_GEOMETRY DiskGeometry
;
90 ULONG MediaChangeCount
= 0;
91 PVOLUME_DEVICE_OBJECT VolumeDevice
;
95 PPACKED_BOOT_SECTOR BootSector
;
97 DPRINT1("FatMountVolume()\n");
99 /* Make sure this IRP is waitable */
100 ASSERT(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
);
102 /* Request media changes count, mostly useful for removable devices */
103 Status
= FatPerformDevIoCtrl(TargetDeviceObject
,
104 IOCTL_STORAGE_CHECK_VERIFY
,
111 if (!NT_SUCCESS(Status
)) return Status
;
113 /* TODO: Check if data-track present in case of a CD drive */
114 /* TODO: IOCTL_DISK_GET_PARTITION_INFO_EX */
116 /* Remove unmounted VCBs */
117 FatiCleanVcbs(IrpContext
);
119 /* Acquire the global exclusive lock */
120 FatAcquireExclusiveGlobal(IrpContext
);
122 /* Create a new volume device object */
123 Status
= IoCreateDevice(FatGlobalData
.DriverObject
,
124 sizeof(VOLUME_DEVICE_OBJECT
) - sizeof(DEVICE_OBJECT
),
126 FILE_DEVICE_DISK_FILE_SYSTEM
,
129 (PDEVICE_OBJECT
*)&VolumeDevice
);
131 if (!NT_SUCCESS(Status
))
133 /* Release the global lock */
134 FatReleaseGlobal(IrpContext
);
139 /* Match alignment requirements */
140 if (TargetDeviceObject
->AlignmentRequirement
> VolumeDevice
->DeviceObject
.AlignmentRequirement
)
142 VolumeDevice
->DeviceObject
.AlignmentRequirement
= TargetDeviceObject
->AlignmentRequirement
;
145 /* Init stack size */
146 VolumeDevice
->DeviceObject
.StackSize
= TargetDeviceObject
->StackSize
+ 1;
148 /* Get sector size */
149 Status
= FatPerformDevIoCtrl(TargetDeviceObject
,
150 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
154 sizeof(DISK_GEOMETRY
),
157 if (!NT_SUCCESS(Status
)) goto FatMountVolumeCleanup
;
159 VolumeDevice
->DeviceObject
.SectorSize
= (USHORT
) DiskGeometry
.BytesPerSector
;
161 /* Signal we're done with initializing */
162 VolumeDevice
->DeviceObject
.Flags
&= ~DO_DEVICE_INITIALIZING
;
164 /* Save device object in a VPB */
165 Vpb
->DeviceObject
= (PDEVICE_OBJECT
)VolumeDevice
;
167 /* Initialize VCB for this volume */
168 Status
= FatInitializeVcb(IrpContext
, &VolumeDevice
->Vcb
, TargetDeviceObject
, Vpb
);
169 if (!NT_SUCCESS(Status
)) goto FatMountVolumeCleanup
;
171 Vcb
= &VolumeDevice
->Vcb
;
173 /* Initialize FullFAT library */
174 Vcb
->Ioman
= FF_CreateIOMAN(NULL
,
176 VolumeDevice
->DeviceObject
.SectorSize
,
181 /* Register block device read/write functions */
182 Error
= FF_RegisterBlkDevice(Vcb
->Ioman
,
183 VolumeDevice
->DeviceObject
.SectorSize
,
184 (FF_WRITE_BLOCKS
)FatWriteBlocks
,
185 (FF_READ_BLOCKS
)FatReadBlocks
,
190 DPRINT1("Registering block device with FullFAT failed with error %d\n", Error
);
191 FF_DestroyIOMAN(Vcb
->Ioman
);
192 goto FatMountVolumeCleanup
;
195 /* Mount the volume using FullFAT */
196 if(FF_MountPartition(Vcb
->Ioman
, 0))
198 DPRINT1("Partition mounting failed\n");
199 FF_DestroyIOMAN(Vcb
->Ioman
);
200 goto FatMountVolumeCleanup
;
203 /* Read the boot sector */
204 FatReadStreamFile(Vcb
, 0, sizeof(PACKED_BOOT_SECTOR
), &BootBcb
, (PVOID
)&BootSector
);
206 /* Check if it's successful */
209 Status
= STATUS_UNRECOGNIZED_VOLUME
;
210 goto FatMountVolumeCleanup
;
214 FatiUnpackBpb(&Vcb
->Bpb
, &BootSector
->PackedBpb
);
216 /* Verify if sector size matches */
217 if (DiskGeometry
.BytesPerSector
!= Vcb
->Bpb
.BytesPerSector
)
219 DPRINT1("Disk geometry BPS %d and bios BPS %d don't match!\n",
220 DiskGeometry
.BytesPerSector
, Vcb
->Bpb
.BytesPerSector
);
223 Status
= STATUS_UNRECOGNIZED_VOLUME
;
224 goto FatMountVolumeCleanup
;
227 /* If Sectors value is set, discard the LargeSectors value */
228 if (Vcb
->Bpb
.Sectors
) Vcb
->Bpb
.LargeSectors
= 0;
230 /* Copy serial number */
231 if (FatiBpbFat32(&BootSector
->PackedBpb
))
233 CopyUchar4(&Vpb
->SerialNumber
, ((PPACKED_BOOT_SECTOR_EX
)BootSector
)->Id
);
237 /* This is FAT12/16 */
238 CopyUchar4(&Vpb
->SerialNumber
, BootSector
->Id
);
242 CcUnpinData(BootBcb
);
244 /* Create root DCB for it */
245 FatCreateRootDcb(IrpContext
, &VolumeDevice
->Vcb
);
247 /* Keep trace of media changes */
248 VolumeDevice
->Vcb
.MediaChangeCount
= MediaChangeCount
;
250 //ObDereferenceObject(TargetDeviceObject);
252 /* Release the global lock */
253 FatReleaseGlobal(IrpContext
);
255 /* Notify about volume mount */
256 //FsRtlNotifyVolumeEvent(VolumeDevice->Vcb.StreamFileObject, FSRTL_VOLUME_MOUNT);
259 return STATUS_SUCCESS
;
262 FatMountVolumeCleanup
:
264 /* Unwind the routine actions */
265 IoDeleteDevice((PDEVICE_OBJECT
)VolumeDevice
);
267 /* Release the global lock */
268 FatReleaseGlobal(IrpContext
);
277 FatiFileSystemControl(PFAT_IRP_CONTEXT IrpContext
, PIRP Irp
)
279 PIO_STACK_LOCATION IrpSp
;
282 /* Get current IRP stack location */
283 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
285 /* Dispatch depending on the minor function */
286 switch (IrpSp
->MinorFunction
)
288 case IRP_MN_USER_FS_REQUEST
:
289 Status
= FatUserFsCtrl(IrpContext
, Irp
);
292 case IRP_MN_MOUNT_VOLUME
:
293 Status
= FatMountVolume(IrpContext
,
294 IrpSp
->Parameters
.MountVolume
.DeviceObject
,
295 IrpSp
->Parameters
.MountVolume
.Vpb
,
296 IrpSp
->DeviceObject
);
298 FatCompleteRequest(IrpContext
, Irp
, Status
);
302 case IRP_MN_VERIFY_VOLUME
:
303 Status
= FatVerifyVolume(IrpContext
, Irp
);
307 DPRINT1("Unhandled FSCTL minor 0x%x\n", IrpSp
->MinorFunction
);
308 FatCompleteRequest(IrpContext
, Irp
, STATUS_INVALID_DEVICE_REQUEST
);
309 Status
= STATUS_INVALID_DEVICE_REQUEST
;
318 FatFileSystemControl(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
320 NTSTATUS Status
= STATUS_SUCCESS
;
321 PFAT_IRP_CONTEXT IrpContext
;
322 BOOLEAN CanWait
= TRUE
;
324 DPRINT("FatFileSystemControl(DeviceObject %p, Irp %p)\n", DeviceObject
, Irp
);
326 /* Get CanWait flag */
327 if (IoGetCurrentIrpStackLocation(Irp
)->FileObject
)
329 CanWait
= IoIsOperationSynchronous(Irp
);
332 /* Enter FsRtl critical region */
333 FsRtlEnterFileSystem();
335 /* Build an irp context */
336 IrpContext
= FatBuildIrpContext(Irp
, CanWait
);
338 /* Call internal function */
339 Status
= FatiFileSystemControl(IrpContext
, Irp
);
341 /* Leave FsRtl critical region */
342 FsRtlExitFileSystem();