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