xref: /reactos/drivers/filesystems/fs_rec/fs_rec.c (revision 50cf16b3)
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             /* Unregister 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         case FS_TYPE_BTRFS:
168 
169             /* Send BTRFS command */
170             Status = FsRecBtrfsFsControl(DeviceObject, Irp);
171             break;
172 
173         case FS_TYPE_REISERFS:
174 
175             /* Send REISERFS command */
176             Status = FsRecReiserfsFsControl(DeviceObject, Irp);
177             break;
178 
179         case FS_TYPE_FFS:
180 
181             /* Send FFS command */
182             Status = FsRecFfsFsControl(DeviceObject, Irp);
183             break;
184 
185         default:
186 
187             /* Unrecognized FS */
188             Status = STATUS_INVALID_DEVICE_REQUEST;
189     }
190 
191     /* Complete the IRP */
192     Irp->IoStatus.Status = Status;
193     IoCompleteRequest(Irp, IO_NO_INCREMENT);
194     return Status;
195 }
196 
197 DRIVER_UNLOAD FsRecUnload;
198 VOID
199 NTAPI
200 FsRecUnload(IN PDRIVER_OBJECT DriverObject)
201 {
202     PAGED_CODE();
203 
204     /* Loop all driver device objects */
205     while (DriverObject->DeviceObject)
206     {
207         /* Delete this device */
208         IoDeleteDevice(DriverObject->DeviceObject);
209     }
210 
211     /* Free the lock */
212     ExFreePool(FsRecLoadSync);
213 }
214 
215 NTSTATUS
216 NTAPI
217 FsRecRegisterFs(IN PDRIVER_OBJECT DriverObject,
218                 IN PDEVICE_OBJECT ParentObject OPTIONAL,
219                 OUT PDEVICE_OBJECT *NewDeviceObject OPTIONAL,
220                 IN PCWSTR FsName,
221                 IN PCWSTR RecognizerName,
222                 IN ULONG FsType,
223                 IN DEVICE_TYPE DeviceType,
224                 IN ULONG AdditionalFlags)
225 {
226     OBJECT_ATTRIBUTES ObjectAttributes;
227     IO_STATUS_BLOCK IoStatus;
228     PDEVICE_EXTENSION DeviceExtension;
229     UNICODE_STRING DeviceName;
230     PDEVICE_OBJECT DeviceObject;
231     HANDLE FileHandle;
232     NTSTATUS Status;
233 
234     /* Assume failure */
235     if (NewDeviceObject) *NewDeviceObject = NULL;
236 
237     /* Setup the attributes */
238     RtlInitUnicodeString(&DeviceName, FsName);
239     InitializeObjectAttributes(&ObjectAttributes,
240                                &DeviceName,
241                                OBJ_CASE_INSENSITIVE,
242                                0,
243                                NULL);
244 
245     /* Open the device */
246     Status = ZwCreateFile(&FileHandle,
247                           SYNCHRONIZE,
248                           &ObjectAttributes,
249                           &IoStatus,
250                           NULL,
251                           0,
252                           FILE_SHARE_READ | FILE_SHARE_WRITE,
253                           FILE_OPEN,
254                           0,
255                           NULL,
256                           0);
257     if (NT_SUCCESS(Status))
258     {
259         /* We succeeded, close the handle */
260         ZwClose(FileHandle);
261     }
262     else if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
263     {
264         /* We failed with anything else then what we want to fail with */
265         Status = STATUS_SUCCESS;
266     }
267 
268     /* If we succeeded, there's no point in trying this again */
269     if (NT_SUCCESS(Status)) return STATUS_IMAGE_ALREADY_LOADED;
270 
271     /* Create recognizer device object */
272     RtlInitUnicodeString(&DeviceName, RecognizerName);
273     Status = IoCreateDevice(DriverObject,
274                             sizeof(DEVICE_EXTENSION),
275                             &DeviceName,
276                             DeviceType,
277                             0,
278                             FALSE,
279                             &DeviceObject);
280     if (NT_SUCCESS(Status))
281     {
282         /* Set additional flags in the device object */
283         DeviceObject->Flags |= AdditionalFlags;
284 
285         /* Get the device extension and set it up */
286         DeviceExtension = DeviceObject->DeviceExtension;
287         DeviceExtension->FsType = FsType;
288         DeviceExtension->State = Pending;
289 
290         /* Do we have a parent? */
291         if (ParentObject)
292         {
293             /* Link it in */
294             DeviceExtension->Alternate =
295                 ((PDEVICE_EXTENSION)ParentObject->DeviceExtension)->Alternate;
296             ((PDEVICE_EXTENSION)ParentObject->DeviceExtension)->Alternate =
297                 DeviceObject;
298         }
299         else
300         {
301             /* Otherwise, we're the only one */
302             DeviceExtension->Alternate = DeviceObject;
303         }
304 
305         /* Return the DO if needed */
306         if (NewDeviceObject) *NewDeviceObject = DeviceObject;
307 
308         /* Register the file system */
309         IoRegisterFileSystem(DeviceObject);
310     }
311 
312     /* Return Status */
313     return Status;
314 }
315 
316 NTSTATUS
317 NTAPI
318 DriverEntry(IN PDRIVER_OBJECT DriverObject,
319             IN PUNICODE_STRING RegistryPath)
320 {
321     ULONG DeviceCount = 0;
322     NTSTATUS Status;
323     PDEVICE_OBJECT CdfsObject;
324     PDEVICE_OBJECT UdfsObject;
325     PAGED_CODE();
326 
327     UNREFERENCED_PARAMETER(RegistryPath);
328 
329     /* Page the entire driver */
330     MmPageEntireDriver(DriverEntry);
331 
332     /* Allocate the lock */
333     FsRecLoadSync = ExAllocatePoolWithTag(NonPagedPool,
334                                           sizeof(KEVENT),
335                                           FSREC_TAG);
336     if (!FsRecLoadSync) return STATUS_INSUFFICIENT_RESOURCES;
337 
338     /* Initialize it */
339     KeInitializeEvent(FsRecLoadSync, SynchronizationEvent, TRUE);
340 
341     /* Setup the major functions */
342     DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRecCreate;
343     DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecClose;
344     DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecClose;
345     DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl;
346     DriverObject->DriverUnload = FsRecUnload;
347 
348     /* Register CDFS for CDs */
349     Status = FsRecRegisterFs(DriverObject,
350                              NULL,
351                              &CdfsObject,
352                              L"\\Cdfs",
353                              L"\\FileSystem\\CdfsRecognizer",
354                              FS_TYPE_CDFS,
355                              FILE_DEVICE_CD_ROM_FILE_SYSTEM,
356                              DO_LOW_PRIORITY_FILESYSTEM);
357     if (NT_SUCCESS(Status)) DeviceCount++;
358 
359     /* Register CDFS for HDDs */
360     Status = FsRecRegisterFs(DriverObject,
361                              CdfsObject,
362                              NULL,
363                              L"\\CdfsHdd",
364                              L"\\FileSystem\\CdfsHddRecognizer",
365                              FS_TYPE_CDFS,
366                              FILE_DEVICE_DISK_FILE_SYSTEM,
367                              DO_LOW_PRIORITY_FILESYSTEM);
368     if (NT_SUCCESS(Status)) DeviceCount++;
369 
370     /* Register UDFS for CDs */
371     Status = FsRecRegisterFs(DriverObject,
372                              NULL,
373                              &UdfsObject,
374                              L"\\UdfsCdRom",
375                              L"\\FileSystem\\UdfsCdRomRecognizer",
376                              FS_TYPE_UDFS,
377                              FILE_DEVICE_CD_ROM_FILE_SYSTEM,
378                              0);
379     if (NT_SUCCESS(Status)) DeviceCount++;
380 
381     /* Register UDFS for HDDs */
382     Status = FsRecRegisterFs(DriverObject,
383                              UdfsObject,
384                              NULL,
385                              L"\\UdfsDisk",
386                              L"\\FileSystem\\UdfsDiskRecognizer",
387                              FS_TYPE_UDFS,
388                              FILE_DEVICE_DISK_FILE_SYSTEM,
389                              0);
390     if (NT_SUCCESS(Status)) DeviceCount++;
391 
392     /* Register FAT */
393     Status = FsRecRegisterFs(DriverObject,
394                              NULL,
395                              NULL,
396                              L"\\Fat",
397                              L"\\FileSystem\\FatRecognizer",
398                              FS_TYPE_VFAT,
399                              FILE_DEVICE_DISK_FILE_SYSTEM,
400                              0);
401     if (NT_SUCCESS(Status)) DeviceCount++;
402 
403     /* Register NTFS */
404     Status = FsRecRegisterFs(DriverObject,
405                              NULL,
406                              NULL,
407                              L"\\Ntfs",
408                              L"\\FileSystem\\NtfsRecognizer",
409                              FS_TYPE_NTFS,
410                              FILE_DEVICE_DISK_FILE_SYSTEM,
411                              0);
412     if (NT_SUCCESS(Status)) DeviceCount++;
413 
414     /* Register EXT2 */
415     Status = FsRecRegisterFs(DriverObject,
416                              NULL,
417                              NULL,
418                              L"\\Ext2fs",
419                              L"\\FileSystem\\Ext2Recognizer",
420                              FS_TYPE_EXT2,
421                              FILE_DEVICE_DISK_FILE_SYSTEM,
422                              0);
423     if (NT_SUCCESS(Status)) DeviceCount++;
424 
425     /* Register BTRFS */
426     Status = FsRecRegisterFs(DriverObject,
427                              NULL,
428                              NULL,
429                              L"\\Btrfs",
430                              L"\\FileSystem\\BtrfsRecognizer",
431                              FS_TYPE_BTRFS,
432                              FILE_DEVICE_DISK_FILE_SYSTEM,
433                              0);
434     if (NT_SUCCESS(Status)) DeviceCount++;
435 
436     /* Register REISERFS */
437     Status = FsRecRegisterFs(DriverObject,
438                              NULL,
439                              NULL,
440                              L"\\Reiserfs",
441                              L"\\FileSystem\\ReiserfsRecognizer",
442                              FS_TYPE_REISERFS,
443                              FILE_DEVICE_DISK_FILE_SYSTEM,
444                              0);
445     if (NT_SUCCESS(Status)) DeviceCount++;
446 
447     /* Register FFS */
448     Status = FsRecRegisterFs(DriverObject,
449                              NULL,
450                              NULL,
451                              L"\\ffs",
452                              L"\\FileSystem\\FfsRecognizer",
453                              FS_TYPE_FFS,
454                              FILE_DEVICE_DISK_FILE_SYSTEM,
455                              0);
456     if (NT_SUCCESS(Status)) DeviceCount++;
457 
458     /* Return appropriate Status */
459     return (DeviceCount > 0) ? STATUS_SUCCESS : STATUS_IMAGE_ALREADY_LOADED;
460 }
461 
462 /* EOF */
463