Sync with trunk revision 64099.
[reactos.git] / drivers / filesystems / fs_rec / fs_rec.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS File System Recognizer
4 * FILE: drivers/filesystems/fs_rec/fs_rec.c
5 * PURPOSE: Main Driver Entrypoint and FS Registration
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 * Eric Kohl
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "fs_rec.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 PKEVENT FsRecLoadSync;
18
19 /* FUNCTIONS ****************************************************************/
20
21 NTSTATUS
22 NTAPI
23 FsRecLoadFileSystem(IN PDEVICE_OBJECT DeviceObject,
24 IN PWCHAR DriverServiceName)
25 {
26 UNICODE_STRING DriverName;
27 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
28 NTSTATUS Status = STATUS_IMAGE_ALREADY_LOADED;
29 PAGED_CODE();
30
31 /* Make sure we haven't already been called */
32 if (DeviceExtension->State != Loaded)
33 {
34 /* Acquire the load lock */
35 KeWaitForSingleObject(FsRecLoadSync,
36 Executive,
37 KernelMode,
38 FALSE,
39 NULL);
40 KeEnterCriticalRegion();
41
42 /* Make sure we're active */
43 if (DeviceExtension->State == Pending)
44 {
45 /* Load the FS driver */
46 RtlInitUnicodeString(&DriverName, DriverServiceName);
47 Status = ZwLoadDriver(&DriverName);
48
49 /* Loop all the linked recognizer objects */
50 while (DeviceExtension->State != Unloading)
51 {
52 /* Set them to the unload state */
53 DeviceExtension->State = Unloading;
54
55 /* Go to the next one */
56 DeviceObject = DeviceExtension->Alternate;
57 DeviceExtension = DeviceObject->DeviceExtension;
58 }
59 }
60
61 /* Make sure that we haven't already loaded the FS */
62 if (DeviceExtension->State != Loaded)
63 {
64 /* Unregiser us, and set us as loaded */
65 IoUnregisterFileSystem(DeviceObject);
66 DeviceExtension->State = Loaded;
67 }
68
69 /* Release the lock */
70 KeSetEvent(FsRecLoadSync, 0, FALSE);
71 KeLeaveCriticalRegion();
72 }
73
74 /* Return */
75 return Status;
76 }
77
78 DRIVER_DISPATCH FsRecCreate;
79 NTSTATUS
80 NTAPI
81 FsRecCreate(IN PDEVICE_OBJECT DeviceObject,
82 IN PIRP Irp)
83 {
84 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
85 NTSTATUS Status;
86 PAGED_CODE();
87
88 UNREFERENCED_PARAMETER(DeviceObject);
89
90 /* Make sure we have a file name */
91 if (IoStack->FileObject->FileName.Length)
92 {
93 /* Fail the request */
94 Status = STATUS_OBJECT_PATH_NOT_FOUND;
95 }
96 else
97 {
98 /* Let it through */
99 Status = STATUS_SUCCESS;
100 }
101
102 /* Complete the IRP */
103 Irp->IoStatus.Status = Status;
104 Irp->IoStatus.Information = FILE_OPENED;
105 IoCompleteRequest(Irp, IO_NO_INCREMENT);
106 return Status;
107 }
108
109 DRIVER_DISPATCH FsRecClose;
110 NTSTATUS
111 NTAPI
112 FsRecClose(IN PDEVICE_OBJECT DeviceObject,
113 IN PIRP Irp)
114 {
115 PAGED_CODE();
116
117 UNREFERENCED_PARAMETER(DeviceObject);
118
119 /* Just complete the IRP and return success */
120 IoCompleteRequest(Irp, IO_NO_INCREMENT);
121 return STATUS_SUCCESS;
122 }
123
124 DRIVER_DISPATCH FsRecFsControl;
125 NTSTATUS
126 NTAPI
127 FsRecFsControl(IN PDEVICE_OBJECT DeviceObject,
128 IN PIRP Irp)
129 {
130 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
131 NTSTATUS Status;
132 PAGED_CODE();
133
134 /* Check the file system type */
135 switch (DeviceExtension->FsType)
136 {
137 case FS_TYPE_VFAT:
138
139 /* Send FAT command */
140 Status = FsRecVfatFsControl(DeviceObject, Irp);
141 break;
142
143 case FS_TYPE_NTFS:
144
145 /* Send NTFS command */
146 Status = FsRecNtfsFsControl(DeviceObject, Irp);
147 break;
148
149 case FS_TYPE_CDFS:
150
151 /* Send CDFS command */
152 Status = FsRecCdfsFsControl(DeviceObject, Irp);
153 break;
154
155 case FS_TYPE_UDFS:
156
157 /* Send UDFS command */
158 Status = FsRecUdfsFsControl(DeviceObject, Irp);
159 break;
160
161 case FS_TYPE_EXT2:
162
163 /* Send EXT2 command */
164 Status = FsRecExt2FsControl(DeviceObject, Irp);
165 break;
166
167 default:
168
169 /* Unrecognized FS */
170 Status = STATUS_INVALID_DEVICE_REQUEST;
171 }
172
173 /* Complete the IRP */
174 Irp->IoStatus.Status = Status;
175 IoCompleteRequest(Irp, IO_NO_INCREMENT);
176 return Status;
177 }
178
179 DRIVER_UNLOAD FsRecUnload;
180 VOID
181 NTAPI
182 FsRecUnload(IN PDRIVER_OBJECT DriverObject)
183 {
184 PAGED_CODE();
185
186 /* Loop all driver device objects */
187 while (DriverObject->DeviceObject)
188 {
189 /* Delete this device */
190 IoDeleteDevice(DriverObject->DeviceObject);
191 }
192
193 /* Free the lock */
194 ExFreePool(FsRecLoadSync);
195 }
196
197 NTSTATUS
198 NTAPI
199 FsRecRegisterFs(IN PDRIVER_OBJECT DriverObject,
200 IN PDEVICE_OBJECT ParentObject OPTIONAL,
201 OUT PDEVICE_OBJECT *NewDeviceObject OPTIONAL,
202 IN PCWSTR FsName,
203 IN PCWSTR RecognizerName,
204 IN ULONG FsType,
205 IN DEVICE_TYPE DeviceType)
206 {
207 OBJECT_ATTRIBUTES ObjectAttributes;
208 IO_STATUS_BLOCK IoStatus;
209 PDEVICE_EXTENSION DeviceExtension;
210 UNICODE_STRING DeviceName;
211 PDEVICE_OBJECT DeviceObject;
212 HANDLE FileHandle;
213 NTSTATUS Status;
214
215 /* Assume failure */
216 if (NewDeviceObject) *NewDeviceObject = NULL;
217
218 /* Setup the attributes */
219 RtlInitUnicodeString(&DeviceName, FsName);
220 InitializeObjectAttributes(&ObjectAttributes,
221 &DeviceName,
222 OBJ_CASE_INSENSITIVE,
223 0,
224 NULL);
225
226 /* Open the device */
227 Status = ZwCreateFile(&FileHandle,
228 SYNCHRONIZE,
229 &ObjectAttributes,
230 &IoStatus,
231 NULL,
232 0,
233 FILE_SHARE_READ | FILE_SHARE_WRITE,
234 FILE_OPEN,
235 0,
236 NULL,
237 0);
238 if (NT_SUCCESS(Status))
239 {
240 /* We suceeded, close the handle */
241 ZwClose(FileHandle);
242 }
243 else if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
244 {
245 /* We failed with anything else then what we want to fail with */
246 Status = STATUS_SUCCESS;
247 }
248
249 /* If we succeeded, there's no point in trying this again */
250 if (NT_SUCCESS(Status)) return STATUS_IMAGE_ALREADY_LOADED;
251
252 /* Create recognizer device object */
253 RtlInitUnicodeString(&DeviceName, RecognizerName);
254 Status = IoCreateDevice(DriverObject,
255 sizeof(DEVICE_EXTENSION),
256 &DeviceName,
257 DeviceType,
258 0,
259 FALSE,
260 &DeviceObject);
261 if (NT_SUCCESS(Status))
262 {
263 /* Get the device extension and set it up */
264 DeviceExtension = DeviceObject->DeviceExtension;
265 DeviceExtension->FsType = FsType;
266 DeviceExtension->State = Pending;
267
268 /* Do we have a parent? */
269 if (ParentObject)
270 {
271 /* Link it in */
272 DeviceExtension->Alternate =
273 ((PDEVICE_EXTENSION)ParentObject->DeviceExtension)->Alternate;
274 ((PDEVICE_EXTENSION)ParentObject->DeviceExtension)->Alternate =
275 DeviceObject;
276 }
277 else
278 {
279 /* Otherwise, we're the only one */
280 DeviceExtension->Alternate = DeviceObject;
281 }
282
283 /* Return the DO if needed */
284 if (NewDeviceObject) *NewDeviceObject = DeviceObject;
285
286 /* Register the file system */
287 IoRegisterFileSystem(DeviceObject);
288 }
289
290 /* Return Status */
291 return Status;
292 }
293
294 NTSTATUS
295 NTAPI
296 DriverEntry(IN PDRIVER_OBJECT DriverObject,
297 IN PUNICODE_STRING RegistryPath)
298 {
299 ULONG DeviceCount = 0;
300 NTSTATUS Status;
301 PDEVICE_OBJECT UdfsObject;
302 PAGED_CODE();
303
304 UNREFERENCED_PARAMETER(RegistryPath);
305
306 /* Page the entire driver */
307 MmPageEntireDriver(DriverEntry);
308
309 /* Allocate the lock */
310 FsRecLoadSync = ExAllocatePoolWithTag(NonPagedPool,
311 sizeof(KEVENT),
312 FSREC_TAG);
313 if (!FsRecLoadSync) return STATUS_INSUFFICIENT_RESOURCES;
314
315 /* Initialize it */
316 KeInitializeEvent(FsRecLoadSync, SynchronizationEvent, TRUE);
317
318 /* Setup the major functions */
319 DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRecCreate;
320 DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecClose;
321 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecClose;
322 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl;
323 DriverObject->DriverUnload = FsRecUnload;
324
325 /* Register CDFS */
326 Status = FsRecRegisterFs(DriverObject,
327 NULL,
328 NULL,
329 L"\\Cdfs",
330 L"\\FileSystem\\CdfsRecognizer",
331 FS_TYPE_CDFS,
332 FILE_DEVICE_CD_ROM_FILE_SYSTEM);
333 if (NT_SUCCESS(Status)) DeviceCount++;
334
335 /* Register UDFS for CDs */
336 Status = FsRecRegisterFs(DriverObject,
337 NULL,
338 &UdfsObject,
339 L"\\UdfsCdRom",
340 L"\\FileSystem\\UdfsCdRomRecognizer",
341 FS_TYPE_UDFS,
342 FILE_DEVICE_CD_ROM_FILE_SYSTEM);
343 if (NT_SUCCESS(Status)) DeviceCount++;
344
345 /* Register UDFS for HDDs */
346 Status = FsRecRegisterFs(DriverObject,
347 UdfsObject,
348 NULL,
349 L"\\UdfsDisk",
350 L"\\FileSystem\\UdfsDiskRecognizer",
351 FS_TYPE_UDFS,
352 FILE_DEVICE_DISK_FILE_SYSTEM);
353 if (NT_SUCCESS(Status)) DeviceCount++;
354
355 /* Register FAT */
356 Status = FsRecRegisterFs(DriverObject,
357 NULL,
358 NULL,
359 L"\\Fat",
360 L"\\FileSystem\\FatRecognizer",
361 FS_TYPE_VFAT,
362 FILE_DEVICE_DISK_FILE_SYSTEM);
363 if (NT_SUCCESS(Status)) DeviceCount++;
364
365 /* Register NTFS */
366 Status = FsRecRegisterFs(DriverObject,
367 NULL,
368 NULL,
369 L"\\Ntfs",
370 L"\\FileSystem\\NtfsRecognizer",
371 FS_TYPE_NTFS,
372 FILE_DEVICE_DISK_FILE_SYSTEM);
373 if (NT_SUCCESS(Status)) DeviceCount++;
374
375 /* Register EXT2 */
376 Status = FsRecRegisterFs(DriverObject,
377 NULL,
378 NULL,
379 L"\\Ext2fs",
380 L"\\FileSystem\\Ext2Recognizer",
381 FS_TYPE_EXT2,
382 FILE_DEVICE_DISK_FILE_SYSTEM);
383 if (NT_SUCCESS(Status)) DeviceCount++;
384
385 /* Return appropriate Status */
386 return (DeviceCount > 0) ? STATUS_SUCCESS : STATUS_IMAGE_ALREADY_LOADED;
387 }
388
389 /* EOF */