xref: /reactos/drivers/filesystems/fs_rec/fs_rec.c (revision de972e2b)
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     NTSTATUS Status = STATUS_IMAGE_ALREADY_LOADED;
27     PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
28     UNICODE_STRING DriverName;
29 
30     PAGED_CODE();
31 
32     /* Make sure we haven't already been called */
33     if (DeviceExtension->State != Loaded)
34     {
35         /* Acquire the load lock */
36         KeEnterCriticalRegion();
37         KeWaitForSingleObject(FsRecLoadSync,
38                               Executive,
39                               KernelMode,
40                               FALSE,
41                               NULL);
42 
43         /* Make sure we're active */
44         if (DeviceExtension->State == Pending)
45         {
46             /* Load the FS driver */
47             RtlInitUnicodeString(&DriverName, DriverServiceName);
48             Status = ZwLoadDriver(&DriverName);
49 
50             /* Loop all the linked recognizer objects */
51             while (DeviceExtension->State != Unloading)
52             {
53                 /* Set them to the unload state */
54                 DeviceExtension->State = Unloading;
55 
56                 /* Go to the next one */
57                 DeviceObject = DeviceExtension->Alternate;
58                 DeviceExtension = DeviceObject->DeviceExtension;
59             }
60         }
61 
62         /* Make sure that we haven't already loaded the FS */
63         if (DeviceExtension->State != Loaded)
64         {
65             /* Unregister us, and set us as loaded */
66             IoUnregisterFileSystem(DeviceObject);
67             DeviceExtension->State = Loaded;
68         }
69 
70         /* Release the lock */
71         KeSetEvent(FsRecLoadSync, IO_NO_INCREMENT, FALSE);
72         KeLeaveCriticalRegion();
73     }
74 
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 | OBJ_KERNEL_HANDLE,
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     NTSTATUS Status;
322     ULONG DeviceCount = 0;
323     PDEVICE_OBJECT CdfsObject;
324     PDEVICE_OBJECT UdfsObject;
325     PDEVICE_OBJECT FatObject;
326 
327     PAGED_CODE();
328 
329     UNREFERENCED_PARAMETER(RegistryPath);
330 
331     /* Page the entire driver */
332     MmPageEntireDriver(DriverEntry);
333 
334     /* Allocate the lock */
335     FsRecLoadSync = ExAllocatePoolWithTag(NonPagedPool,
336                                           sizeof(KEVENT),
337                                           FSREC_TAG);
338     if (!FsRecLoadSync) return STATUS_INSUFFICIENT_RESOURCES;
339 
340     /* Initialize it */
341     KeInitializeEvent(FsRecLoadSync, SynchronizationEvent, TRUE);
342 
343     /* Setup the major functions */
344     DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRecCreate;
345     DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecClose;
346     DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecClose;
347     DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl;
348     DriverObject->DriverUnload = FsRecUnload;
349 
350     /* Register CDFS for CDs */
351     Status = FsRecRegisterFs(DriverObject,
352                              NULL,
353                              &CdfsObject,
354                              L"\\Cdfs",
355                              L"\\FileSystem\\CdfsRecognizer",
356                              FS_TYPE_CDFS,
357                              FILE_DEVICE_CD_ROM_FILE_SYSTEM,
358                              DO_LOW_PRIORITY_FILESYSTEM);
359     if (NT_SUCCESS(Status)) DeviceCount++;
360 
361     /* Register CDFS for HDDs */
362     Status = FsRecRegisterFs(DriverObject,
363                              CdfsObject,
364                              NULL,
365                              L"\\CdfsHdd",
366                              L"\\FileSystem\\CdfsHddRecognizer",
367                              FS_TYPE_CDFS,
368                              FILE_DEVICE_DISK_FILE_SYSTEM,
369                              DO_LOW_PRIORITY_FILESYSTEM);
370     if (NT_SUCCESS(Status)) DeviceCount++;
371 
372     /* Register UDFS for CDs */
373     Status = FsRecRegisterFs(DriverObject,
374                              NULL,
375                              &UdfsObject,
376                              L"\\UdfsCdRom",
377                              L"\\FileSystem\\UdfsCdRomRecognizer",
378                              FS_TYPE_UDFS,
379                              FILE_DEVICE_CD_ROM_FILE_SYSTEM,
380                              0);
381     if (NT_SUCCESS(Status)) DeviceCount++;
382 
383     /* Register UDFS for HDDs */
384     Status = FsRecRegisterFs(DriverObject,
385                              UdfsObject,
386                              NULL,
387                              L"\\UdfsDisk",
388                              L"\\FileSystem\\UdfsDiskRecognizer",
389                              FS_TYPE_UDFS,
390                              FILE_DEVICE_DISK_FILE_SYSTEM,
391                              0);
392     if (NT_SUCCESS(Status)) DeviceCount++;
393 
394     /* Register FAT */
395     Status = FsRecRegisterFs(DriverObject,
396                              NULL,
397                              &FatObject,
398                              L"\\Fat",
399                              L"\\FileSystem\\FatRecognizer",
400                              FS_TYPE_VFAT,
401                              FILE_DEVICE_DISK_FILE_SYSTEM,
402                              0);
403     if (NT_SUCCESS(Status)) DeviceCount++;
404 
405     /* Register FAT for CDs */
406     Status = FsRecRegisterFs(DriverObject,
407                              FatObject,
408                              NULL,
409                              L"\\FatCdrom",
410                              L"\\FileSystem\\FatCdRomRecognizer",
411                              FS_TYPE_VFAT,
412                              FILE_DEVICE_CD_ROM_FILE_SYSTEM,
413                              0);
414     if (NT_SUCCESS(Status)) DeviceCount++;
415 
416     /* Register NTFS */
417     Status = FsRecRegisterFs(DriverObject,
418                              NULL,
419                              NULL,
420                              L"\\Ntfs",
421                              L"\\FileSystem\\NtfsRecognizer",
422                              FS_TYPE_NTFS,
423                              FILE_DEVICE_DISK_FILE_SYSTEM,
424                              0);
425     if (NT_SUCCESS(Status)) DeviceCount++;
426 
427     /* Register EXT2 */
428     Status = FsRecRegisterFs(DriverObject,
429                              NULL,
430                              NULL,
431                              L"\\Ext2fs",
432                              L"\\FileSystem\\Ext2Recognizer",
433                              FS_TYPE_EXT2,
434                              FILE_DEVICE_DISK_FILE_SYSTEM,
435                              0);
436     if (NT_SUCCESS(Status)) DeviceCount++;
437 
438     /* Register BTRFS */
439     Status = FsRecRegisterFs(DriverObject,
440                              NULL,
441                              NULL,
442                              L"\\Btrfs",
443                              L"\\FileSystem\\BtrfsRecognizer",
444                              FS_TYPE_BTRFS,
445                              FILE_DEVICE_DISK_FILE_SYSTEM,
446                              0);
447     if (NT_SUCCESS(Status)) DeviceCount++;
448 
449     /* Register REISERFS */
450     Status = FsRecRegisterFs(DriverObject,
451                              NULL,
452                              NULL,
453                              L"\\Reiserfs",
454                              L"\\FileSystem\\ReiserfsRecognizer",
455                              FS_TYPE_REISERFS,
456                              FILE_DEVICE_DISK_FILE_SYSTEM,
457                              0);
458     if (NT_SUCCESS(Status)) DeviceCount++;
459 
460     /* Register FFS */
461     Status = FsRecRegisterFs(DriverObject,
462                              NULL,
463                              NULL,
464                              L"\\ffs",
465                              L"\\FileSystem\\FfsRecognizer",
466                              FS_TYPE_FFS,
467                              FILE_DEVICE_DISK_FILE_SYSTEM,
468                              0);
469     if (NT_SUCCESS(Status)) DeviceCount++;
470 
471     /* Return appropriate Status */
472     return (DeviceCount > 0) ? STATUS_SUCCESS : STATUS_IMAGE_ALREADY_LOADED;
473 }
474 
475 /* EOF */
476