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