[fastfat_new]
[reactos.git] / reactos / drivers / filesystems / fastfat_new / fsctl.c
1 /*
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)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #define NDEBUG
12 #include "fastfat.h"
13
14 /* FUNCTIONS ****************************************************************/
15
16 NTSTATUS
17 NTAPI
18 FatUserFsCtrl(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
19 {
20 DPRINT1("FatUserFsCtrl()\n");
21 FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST);
22 return STATUS_INVALID_DEVICE_REQUEST;
23 }
24
25 NTSTATUS
26 NTAPI
27 FatVerifyVolume(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
28 {
29 DPRINT1("FatVerifyVolume()\n");
30 FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST);
31 return STATUS_INVALID_DEVICE_REQUEST;
32 }
33
34 VOID
35 NTAPI
36 FatiCleanVcbs(PFAT_IRP_CONTEXT IrpContext)
37 {
38 /* Make sure this IRP is waitable */
39 ASSERT(IrpContext->Flags & IRPCONTEXT_CANWAIT);
40
41 /* Acquire global resource */
42 ExAcquireResourceExclusiveLite(&FatGlobalData.Resource, TRUE);
43
44 /* TODO: Go through all VCBs and delete unmounted ones */
45
46 /* Release global resource */
47 ExReleaseResourceLite(&FatGlobalData.Resource);
48 }
49
50 NTSTATUS
51 NTAPI
52 FatMountVolume(PFAT_IRP_CONTEXT IrpContext,
53 PDEVICE_OBJECT TargetDeviceObject,
54 PVPB Vpb,
55 PDEVICE_OBJECT FsDeviceObject)
56 {
57 NTSTATUS Status;
58 DISK_GEOMETRY DiskGeometry;
59 ULONG MediaChangeCount = 0;
60 PVOLUME_DEVICE_OBJECT VolumeDevice;
61 VCB *Vcb;
62 FF_ERROR Error;
63
64 DPRINT1("FatMountVolume()\n");
65
66 /* Make sure this IRP is waitable */
67 ASSERT(IrpContext->Flags & IRPCONTEXT_CANWAIT);
68
69 /* Request media changes count, mostly usefull for removable devices */
70 Status = FatPerformDevIoCtrl(TargetDeviceObject,
71 IOCTL_STORAGE_CHECK_VERIFY,
72 NULL,
73 0,
74 &MediaChangeCount,
75 sizeof(ULONG),
76 TRUE);
77
78 if (!NT_SUCCESS(Status)) return Status;
79
80 /* TODO: Check if data-track present in case of a CD drive */
81 /* TODO: IOCTL_DISK_GET_PARTITION_INFO_EX */
82
83 /* Remove unmounted VCBs */
84 FatiCleanVcbs(IrpContext);
85
86 /* Acquire the global exclusive lock */
87 FatAcquireExclusiveGlobal(IrpContext);
88
89 /* Create a new volume device object */
90 Status = IoCreateDevice(FatGlobalData.DriverObject,
91 sizeof(VOLUME_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT),
92 NULL,
93 FILE_DEVICE_DISK_FILE_SYSTEM,
94 0,
95 FALSE,
96 (PDEVICE_OBJECT *)&VolumeDevice);
97
98 if (!NT_SUCCESS(Status))
99 {
100 /* Release the global lock */
101 FatReleaseGlobal(IrpContext);
102
103 return Status;
104 }
105
106 /* Match alignment requirements */
107 if (TargetDeviceObject->AlignmentRequirement > VolumeDevice->DeviceObject.AlignmentRequirement)
108 {
109 VolumeDevice->DeviceObject.AlignmentRequirement = TargetDeviceObject->AlignmentRequirement;
110 }
111
112 /* Init stack size */
113 VolumeDevice->DeviceObject.StackSize = TargetDeviceObject->StackSize + 1;
114
115 /* Get sector size */
116 Status = FatPerformDevIoCtrl(TargetDeviceObject,
117 IOCTL_DISK_GET_DRIVE_GEOMETRY,
118 NULL,
119 0,
120 &DiskGeometry,
121 sizeof(DISK_GEOMETRY),
122 TRUE);
123
124 if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup;
125
126 VolumeDevice->DeviceObject.SectorSize = (USHORT) DiskGeometry.BytesPerSector;
127
128 /* Signal we're done with initializing */
129 VolumeDevice->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
130
131 /* Save device object in a VPB */
132 Vpb->DeviceObject = (PDEVICE_OBJECT)VolumeDevice;
133
134 /* Initialize VCB for this volume */
135 Status = FatInitializeVcb(IrpContext, &VolumeDevice->Vcb, TargetDeviceObject, Vpb);
136 if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup;
137
138 Vcb = &VolumeDevice->Vcb;
139
140 /* Initialize FullFAT library */
141 Vcb->Ioman = FF_CreateIOMAN(NULL,
142 8192,
143 VolumeDevice->DeviceObject.SectorSize,
144 &Error);
145
146 ASSERT(Vcb->Ioman);
147
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,
153 Vcb);
154
155 if (Error)
156 {
157 DPRINT1("Registering block device with FullFAT failed with error %d\n", Error);
158 FF_DestroyIOMAN(Vcb->Ioman);
159 goto FatMountVolumeCleanup;
160 }
161
162 /* Mount the volume using FullFAT */
163 if(FF_MountPartition(Vcb->Ioman, 0))
164 {
165 DPRINT1("Partition mounting failed\n");
166 FF_DestroyIOMAN(Vcb->Ioman);
167 goto FatMountVolumeCleanup;
168 }
169
170 // TODO: Read BPB and store it in Vcb->Bpb
171
172 /* Create root DCB for it */
173 FatCreateRootDcb(IrpContext, &VolumeDevice->Vcb);
174
175 /* Keep trace of media changes */
176 VolumeDevice->Vcb.MediaChangeCount = MediaChangeCount;
177
178 //ObDereferenceObject(TargetDeviceObject);
179
180 /* Release the global lock */
181 FatReleaseGlobal(IrpContext);
182
183 /* Notify about volume mount */
184 //FsRtlNotifyVolumeEvent(VolumeDevice->Vcb.StreamFileObject, FSRTL_VOLUME_MOUNT);
185
186 /* Return success */
187 return STATUS_SUCCESS;
188
189
190 FatMountVolumeCleanup:
191
192 /* Unwind the routine actions */
193 IoDeleteDevice((PDEVICE_OBJECT)VolumeDevice);
194
195 /* Release the global lock */
196 FatReleaseGlobal(IrpContext);
197
198 return Status;
199 }
200
201
202
203 NTSTATUS
204 NTAPI
205 FatiFileSystemControl(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
206 {
207 PIO_STACK_LOCATION IrpSp;
208 NTSTATUS Status;
209
210 /* Get current IRP stack location */
211 IrpSp = IoGetCurrentIrpStackLocation(Irp);
212
213 /* Dispatch depending on the minor function */
214 switch (IrpSp->MinorFunction)
215 {
216 case IRP_MN_USER_FS_REQUEST:
217 Status = FatUserFsCtrl(IrpContext, Irp);
218 break;
219
220 case IRP_MN_MOUNT_VOLUME:
221 Status = FatMountVolume(IrpContext,
222 IrpSp->Parameters.MountVolume.DeviceObject,
223 IrpSp->Parameters.MountVolume.Vpb,
224 IrpSp->DeviceObject);
225
226 FatCompleteRequest(IrpContext, Irp, Status);
227
228 break;
229
230 case IRP_MN_VERIFY_VOLUME:
231 Status = FatVerifyVolume(IrpContext, Irp);
232 break;
233
234 default:
235 DPRINT1("Unhandled FSCTL minor 0x%x\n", IrpSp->MinorFunction);
236 FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST);
237 Status = STATUS_INVALID_DEVICE_REQUEST;
238 }
239
240 return Status;
241 }
242
243
244 NTSTATUS
245 NTAPI
246 FatFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
247 {
248 NTSTATUS Status = STATUS_SUCCESS;
249 PFAT_IRP_CONTEXT IrpContext;
250 BOOLEAN CanWait = TRUE;
251
252 DPRINT1("FatFileSystemControl(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
253
254 /* Get CanWait flag */
255 if (IoGetCurrentIrpStackLocation(Irp)->FileObject)
256 {
257 CanWait = IoIsOperationSynchronous(Irp);
258 }
259
260 /* Enter FsRtl critical region */
261 FsRtlEnterFileSystem();
262
263 /* Build an irp context */
264 IrpContext = FatBuildIrpContext(Irp, CanWait);
265
266 /* Call internal function */
267 Status = FatiFileSystemControl(IrpContext, Irp);
268
269 /* Leave FsRtl critical region */
270 FsRtlExitFileSystem();
271
272 return Status;
273 }