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