xref: /reactos/drivers/filesystems/fs_rec/fs_rec.c (revision 69931a4a)
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         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
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
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
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 
333     PAGED_CODE();
334 
335     UNREFERENCED_PARAMETER(RegistryPath);
336 
337     /* Page the entire driver */
338     MmPageEntireDriver(DriverEntry);
339 
340     /* Allocate the lock */
341     FsRecLoadSync = ExAllocatePoolWithTag(NonPagedPool,
342                                           sizeof(KEVENT),
343                                           FSREC_TAG);
344     if (!FsRecLoadSync) return STATUS_INSUFFICIENT_RESOURCES;
345 
346     /* Initialize it */
347     KeInitializeEvent(FsRecLoadSync, SynchronizationEvent, TRUE);
348 
349     /* Setup the major functions */
350     DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRecCreate;
351     DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecClose;
352     DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecClose;
353     DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl;
354     DriverObject->DriverUnload = FsRecUnload;
355 
356     /* Register CDFS for CDs */
357     Status = FsRecRegisterFs(DriverObject,
358                              NULL,
359                              &CdfsObject,
360                              L"\\Cdfs",
361                              L"\\FileSystem\\CdfsRecognizer",
362                              FS_TYPE_CDFS,
363                              FILE_DEVICE_CD_ROM_FILE_SYSTEM,
364                              DO_LOW_PRIORITY_FILESYSTEM);
365     if (NT_SUCCESS(Status)) DeviceCount++;
366 
367     /* Register CDFS for HDDs */
368     Status = FsRecRegisterFs(DriverObject,
369                              CdfsObject,
370                              NULL,
371                              L"\\CdfsHdd",
372                              L"\\FileSystem\\CdfsHddRecognizer",
373                              FS_TYPE_CDFS,
374                              FILE_DEVICE_DISK_FILE_SYSTEM,
375                              DO_LOW_PRIORITY_FILESYSTEM);
376     if (NT_SUCCESS(Status)) DeviceCount++;
377 
378     /* Register UDFS for CDs */
379     Status = FsRecRegisterFs(DriverObject,
380                              NULL,
381                              &UdfsObject,
382                              L"\\UdfsCdRom",
383                              L"\\FileSystem\\UdfsCdRomRecognizer",
384                              FS_TYPE_UDFS,
385                              FILE_DEVICE_CD_ROM_FILE_SYSTEM,
386                              0);
387     if (NT_SUCCESS(Status)) DeviceCount++;
388 
389     /* Register UDFS for HDDs */
390     Status = FsRecRegisterFs(DriverObject,
391                              UdfsObject,
392                              NULL,
393                              L"\\UdfsDisk",
394                              L"\\FileSystem\\UdfsDiskRecognizer",
395                              FS_TYPE_UDFS,
396                              FILE_DEVICE_DISK_FILE_SYSTEM,
397                              0);
398     if (NT_SUCCESS(Status)) DeviceCount++;
399 
400     /* Register FAT */
401     Status = FsRecRegisterFs(DriverObject,
402                              NULL,
403                              &FatObject,
404                              L"\\Fat",
405                              L"\\FileSystem\\FatRecognizer",
406                              FS_TYPE_VFAT,
407                              FILE_DEVICE_DISK_FILE_SYSTEM,
408                              0);
409     if (NT_SUCCESS(Status)) DeviceCount++;
410 
411     /* Register FAT for CDs */
412     Status = FsRecRegisterFs(DriverObject,
413                              FatObject,
414                              NULL,
415                              L"\\FatCdrom",
416                              L"\\FileSystem\\FatCdRomRecognizer",
417                              FS_TYPE_VFAT,
418                              FILE_DEVICE_CD_ROM_FILE_SYSTEM,
419                              0);
420     if (NT_SUCCESS(Status)) DeviceCount++;
421 
422     /* Register NTFS */
423     Status = FsRecRegisterFs(DriverObject,
424                              NULL,
425                              NULL,
426                              L"\\Ntfs",
427                              L"\\FileSystem\\NtfsRecognizer",
428                              FS_TYPE_NTFS,
429                              FILE_DEVICE_DISK_FILE_SYSTEM,
430                              0);
431     if (NT_SUCCESS(Status)) DeviceCount++;
432 
433     /* Register EXT2 */
434     Status = FsRecRegisterFs(DriverObject,
435                              NULL,
436                              NULL,
437                              L"\\Ext2fs",
438                              L"\\FileSystem\\Ext2Recognizer",
439                              FS_TYPE_EXT2,
440                              FILE_DEVICE_DISK_FILE_SYSTEM,
441                              0);
442     if (NT_SUCCESS(Status)) DeviceCount++;
443 
444     /* Register BTRFS */
445     Status = FsRecRegisterFs(DriverObject,
446                              NULL,
447                              NULL,
448                              L"\\Btrfs",
449                              L"\\FileSystem\\BtrfsRecognizer",
450                              FS_TYPE_BTRFS,
451                              FILE_DEVICE_DISK_FILE_SYSTEM,
452                              0);
453     if (NT_SUCCESS(Status)) DeviceCount++;
454 
455     /* Register REISERFS */
456     Status = FsRecRegisterFs(DriverObject,
457                              NULL,
458                              NULL,
459                              L"\\Reiserfs",
460                              L"\\FileSystem\\ReiserfsRecognizer",
461                              FS_TYPE_REISERFS,
462                              FILE_DEVICE_DISK_FILE_SYSTEM,
463                              0);
464     if (NT_SUCCESS(Status)) DeviceCount++;
465 
466     /* Register FFS */
467     Status = FsRecRegisterFs(DriverObject,
468                              NULL,
469                              NULL,
470                              L"\\ffs",
471                              L"\\FileSystem\\FfsRecognizer",
472                              FS_TYPE_FFS,
473                              FILE_DEVICE_DISK_FILE_SYSTEM,
474                              0);
475     if (NT_SUCCESS(Status)) DeviceCount++;
476 
477     /* Register FATX */
478     Status = FsRecRegisterFs(DriverObject,
479                              NULL,
480                              NULL,
481                              L"\\FatX",
482                              L"\\FileSystem\\FatXRecognizer",
483                              FS_TYPE_FATX,
484                              FILE_DEVICE_DISK_FILE_SYSTEM,
485                              0);
486     if (NT_SUCCESS(Status)) DeviceCount++;
487 
488     /* Return appropriate Status */
489     return (DeviceCount > 0) ? STATUS_SUCCESS : STATUS_IMAGE_ALREADY_LOADED;
490 }
491 
492 /* EOF */
493