5ddb4d8de3bdf772574e337b4a23133995877846
[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
62 DPRINT1("FatMountVolume()\n");
63
64 /* Make sure this IRP is waitable */
65 ASSERT(IrpContext->Flags & IRPCONTEXT_CANWAIT);
66
67 /* Request media changes count, mostly usefull for removable devices */
68 Status = FatPerformDevIoCtrl(TargetDeviceObject,
69 IOCTL_STORAGE_CHECK_VERIFY,
70 NULL,
71 0,
72 &MediaChangeCount,
73 sizeof(ULONG),
74 TRUE);
75
76 if (!NT_SUCCESS(Status)) return Status;
77
78 /* TODO: Check if data-track present in case of a CD drive */
79 /* TODO: IOCTL_DISK_GET_PARTITION_INFO_EX */
80
81 /* Remove unmounted VCBs */
82 FatiCleanVcbs(IrpContext);
83
84 /* Create a new volume device object */
85 Status = IoCreateDevice(FatGlobalData.DriverObject,
86 sizeof(VOLUME_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT),
87 NULL,
88 FILE_DEVICE_DISK_FILE_SYSTEM,
89 0,
90 FALSE,
91 (PDEVICE_OBJECT *)&VolumeDevice);
92
93 if (!NT_SUCCESS(Status)) return Status;
94
95 /* Match alignment requirements */
96 if (TargetDeviceObject->AlignmentRequirement > VolumeDevice->DeviceObject.AlignmentRequirement)
97 {
98 VolumeDevice->DeviceObject.AlignmentRequirement = TargetDeviceObject->AlignmentRequirement;
99 }
100
101 /* Init stack size */
102 VolumeDevice->DeviceObject.StackSize = TargetDeviceObject->StackSize + 1;
103
104 /* Get sector size */
105 Status = FatPerformDevIoCtrl(TargetDeviceObject,
106 IOCTL_DISK_GET_DRIVE_GEOMETRY,
107 NULL,
108 0,
109 &DiskGeometry,
110 sizeof(DISK_GEOMETRY),
111 TRUE);
112
113 if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup;
114
115 VolumeDevice->DeviceObject.SectorSize = (USHORT) DiskGeometry.BytesPerSector;
116
117 /* Signal we're done with initializing */
118 VolumeDevice->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
119
120 /* Save device object in a VPB */
121 Vpb->DeviceObject = (PDEVICE_OBJECT)VolumeDevice;
122
123 /* Initialize VCB for this volume */
124 Status = FatInitializeVcb(IrpContext, &VolumeDevice->Vcb, TargetDeviceObject, Vpb);
125 if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup;
126
127 /* Create root DCB for it */
128 FatCreateRootDcb(IrpContext, &VolumeDevice->Vcb);
129
130 /* Keep trace of media changes */
131 VolumeDevice->Vcb.MediaChangeCount = MediaChangeCount;
132
133 /* Notify about volume mount */
134 FsRtlNotifyVolumeEvent(VolumeDevice->Vcb.StreamFileObject, FSRTL_VOLUME_MOUNT);
135
136 /* Return success */
137 return STATUS_SUCCESS;
138
139
140 FatMountVolumeCleanup:
141
142 /* Unwind the routine actions */
143 IoDeleteDevice((PDEVICE_OBJECT)VolumeDevice);
144 return Status;
145 }
146
147
148
149 NTSTATUS
150 NTAPI
151 FatiFileSystemControl(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
152 {
153 PIO_STACK_LOCATION IrpSp;
154 NTSTATUS Status;
155
156 /* Get current IRP stack location */
157 IrpSp = IoGetCurrentIrpStackLocation(Irp);
158
159 /* Dispatch depending on the minor function */
160 switch (IrpSp->MinorFunction)
161 {
162 case IRP_MN_USER_FS_REQUEST:
163 Status = FatUserFsCtrl(IrpContext, Irp);
164 break;
165
166 case IRP_MN_MOUNT_VOLUME:
167 Status = FatMountVolume(IrpContext,
168 IrpSp->Parameters.MountVolume.DeviceObject,
169 IrpSp->Parameters.MountVolume.Vpb,
170 IrpSp->DeviceObject);
171
172 FatCompleteRequest(IrpContext, Irp, Status);
173
174 break;
175
176 case IRP_MN_VERIFY_VOLUME:
177 Status = FatVerifyVolume(IrpContext, Irp);
178 break;
179
180 default:
181 DPRINT1("Unhandled FSCTL minor 0x%x\n", IrpSp->MinorFunction);
182 FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST);
183 Status = STATUS_INVALID_DEVICE_REQUEST;
184 }
185
186 return Status;
187 }
188
189
190 NTSTATUS
191 NTAPI
192 FatFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
193 {
194 NTSTATUS Status = STATUS_SUCCESS;
195 PFAT_IRP_CONTEXT IrpContext;
196 BOOLEAN CanWait = TRUE;
197
198 DPRINT1("FatFileSystemControl(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
199
200 /* Get CanWait flag */
201 if (IoGetCurrentIrpStackLocation(Irp)->FileObject)
202 {
203 CanWait = IoIsOperationSynchronous(Irp);
204 }
205
206 /* Enter FsRtl critical region */
207 FsRtlEnterFileSystem();
208
209 /* Build an irp context */
210 IrpContext = FatBuildIrpContext(Irp, CanWait);
211
212 /* Call internal function */
213 Status = FatiFileSystemControl(IrpContext, Irp);
214
215 /* Leave FsRtl critical region */
216 FsRtlExitFileSystem();
217
218 return Status;
219 }