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