3dec2248922df5e9a1dc100d73d30e7b02780e4c
[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(&VolumeDevice->Vcb, TargetDeviceObject, Vpb);
125 if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup;
126
127 /* Keep trace of media changes */
128 VolumeDevice->Vcb.MediaChangeCount = MediaChangeCount;
129
130 /* Notify about volume mount */
131 FsRtlNotifyVolumeEvent(VolumeDevice->Vcb.StreamFileObject, FSRTL_VOLUME_MOUNT);
132
133 /* Return success */
134 return STATUS_SUCCESS;
135
136
137 FatMountVolumeCleanup:
138
139 /* Unwind the routine actions */
140 IoDeleteDevice((PDEVICE_OBJECT)VolumeDevice);
141 return Status;
142 }
143
144
145
146 NTSTATUS
147 NTAPI
148 FatiFileSystemControl(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
149 {
150 PIO_STACK_LOCATION IrpSp;
151 NTSTATUS Status;
152
153 /* Get current IRP stack location */
154 IrpSp = IoGetCurrentIrpStackLocation(Irp);
155
156 /* Dispatch depending on the minor function */
157 switch (IrpSp->MinorFunction)
158 {
159 case IRP_MN_USER_FS_REQUEST:
160 Status = FatUserFsCtrl(IrpContext, Irp);
161 break;
162
163 case IRP_MN_MOUNT_VOLUME:
164 Status = FatMountVolume(IrpContext,
165 IrpSp->Parameters.MountVolume.DeviceObject,
166 IrpSp->Parameters.MountVolume.Vpb,
167 IrpSp->DeviceObject);
168
169 FatCompleteRequest(IrpContext, Irp, Status);
170
171 break;
172
173 case IRP_MN_VERIFY_VOLUME:
174 Status = FatVerifyVolume(IrpContext, Irp);
175 break;
176
177 default:
178 DPRINT1("Unhandled FSCTL minor 0x%x\n", IrpSp->MinorFunction);
179 FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST);
180 Status = STATUS_INVALID_DEVICE_REQUEST;
181 }
182
183 return Status;
184 }
185
186
187 NTSTATUS
188 NTAPI
189 FatFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
190 {
191 NTSTATUS Status = STATUS_SUCCESS;
192 PFAT_IRP_CONTEXT IrpContext;
193 BOOLEAN CanWait = TRUE;
194
195 DPRINT1("FatFileSystemControl(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
196
197 /* Get CanWait flag */
198 if (IoGetCurrentIrpStackLocation(Irp)->FileObject)
199 {
200 CanWait = IoIsOperationSynchronous(Irp);
201 }
202
203 /* Enter FsRtl critical region */
204 FsRtlEnterFileSystem();
205
206 /* Build an irp context */
207 IrpContext = FatBuildIrpContext(Irp, CanWait);
208
209 /* Call internal function */
210 Status = FatiFileSystemControl(IrpContext, Irp);
211
212 /* Leave FsRtl critical region */
213 FsRtlExitFileSystem();
214
215 return Status;
216 }