a12d6bfd8b9364d9bf679a6da1277714aae35aa1
[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 #define NDEBUG
14 #include <debug.h>
15
16 PKEVENT FsRecLoadSync;
17
18 /* FUNCTIONS ****************************************************************/
19
20 NTSTATUS
21 NTAPI
22 FsRecLoadFileSystem(IN PDEVICE_OBJECT DeviceObject,
23 IN PWCHAR DriverServiceName)
24 {
25 UNICODE_STRING DriverName;
26 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
27 NTSTATUS Status = STATUS_IMAGE_ALREADY_LOADED;
28 PAGED_CODE();
29
30 /* Make sure we haven't already been called */
31 if (DeviceExtension->State != Loaded)
32 {
33 /* Acquire the load lock */
34 KeWaitForSingleObject(FsRecLoadSync,
35 Executive,
36 KernelMode,
37 FALSE,
38 NULL);
39 KeEnterCriticalRegion();
40
41 /* Make sure we're active */
42 if (DeviceExtension->State == Pending)
43 {
44 /* Load the FS driver */
45 RtlInitUnicodeString(&DriverName, DriverServiceName);
46 Status = ZwLoadDriver(&DriverName);
47
48 /* Loop all the linked recognizer objects */
49 while (DeviceExtension->State != Unloading)
50 {
51 /* Set them to the unload state */
52 DeviceExtension->State = Unloading;
53
54 /* Go to the next one */
55 DeviceObject = DeviceExtension->Alternate;
56 DeviceExtension = DeviceObject->DeviceExtension;
57 }
58 }
59
60 /* Make sure that we haven't already loaded the FS */
61 if (DeviceExtension->State != Loaded)
62 {
63 /* Unregiser us, and set us as loaded */
64 IoUnregisterFileSystem(DeviceObject);
65 DeviceExtension->State = Loaded;
66 }
67
68 /* Release the lock */
69 KeSetEvent(FsRecLoadSync, 0, FALSE);
70 KeLeaveCriticalRegion();
71 }
72
73 /* Return */
74 return Status;
75 }
76
77 DRIVER_DISPATCH FsRecCreate;
78 NTSTATUS
79 NTAPI
80 FsRecCreate(IN PDEVICE_OBJECT DeviceObject,
81 IN PIRP Irp)
82 {
83 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
84 NTSTATUS Status;
85 PAGED_CODE();
86
87 UNREFERENCED_PARAMETER(DeviceObject);
88
89 /* Make sure we have a file name */
90 if (IoStack->FileObject->FileName.Length)
91 {
92 /* Fail the request */
93 Status = STATUS_OBJECT_PATH_NOT_FOUND;
94 }
95 else
96 {
97 /* Let it through */
98 Status = STATUS_SUCCESS;
99 }
100
101 /* Complete the IRP */
102 Irp->IoStatus.Status = Status;
103 Irp->IoStatus.Information = FILE_OPENED;
104 IoCompleteRequest(Irp, IO_NO_INCREMENT);
105 return Status;
106 }
107
108 DRIVER_DISPATCH FsRecClose;
109 NTSTATUS
110 NTAPI
111 FsRecClose(IN PDEVICE_OBJECT DeviceObject,
112 IN PIRP Irp)
113 {
114 PAGED_CODE();
115
116 UNREFERENCED_PARAMETER(DeviceObject);
117
118 /* Just complete the IRP and return success */
119 IoCompleteRequest(Irp, IO_NO_INCREMENT);
120 return STATUS_SUCCESS;
121 }
122
123 DRIVER_DISPATCH FsRecFsControl;
124 NTSTATUS
125 NTAPI
126 FsRecFsControl(IN PDEVICE_OBJECT DeviceObject,
127 IN PIRP Irp)
128 {
129 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
130 NTSTATUS Status;
131 PAGED_CODE();
132
133 /* Check the file system type */
134 switch (DeviceExtension->FsType)
135 {
136 case FS_TYPE_VFAT:
137
138 /* Send FAT command */
139 Status = FsRecVfatFsControl(DeviceObject, Irp);
140 break;
141
142 case FS_TYPE_NTFS:
143
144 /* Send NTFS command */
145 Status = FsRecNtfsFsControl(DeviceObject, Irp);
146 break;
147
148 case FS_TYPE_CDFS:
149
150 /* Send CDFS command */
151 Status = FsRecCdfsFsControl(DeviceObject, Irp);
152 break;
153
154 case FS_TYPE_UDFS:
155
156 /* Send UDFS command */
157 Status = FsRecUdfsFsControl(DeviceObject, Irp);
158 break;
159
160 case FS_TYPE_EXT2:
161
162 /* Send EXT2 command */
163 Status = FsRecExt2FsControl(DeviceObject, Irp);
164 break;
165
166 default:
167
168 /* Unrecognized FS */
169 Status = STATUS_INVALID_DEVICE_REQUEST;
170 }
171
172 /* Complete the IRP */
173 Irp->IoStatus.Status = Status;
174 IoCompleteRequest(Irp, IO_NO_INCREMENT);
175 return Status;
176 }
177
178 DRIVER_UNLOAD FsRecUnload;
179 VOID
180 NTAPI
181 FsRecUnload(IN PDRIVER_OBJECT DriverObject)
182 {
183 PAGED_CODE();
184
185 /* Loop all driver device objects */
186 while (DriverObject->DeviceObject)
187 {
188 /* Delete this device */
189 IoDeleteDevice(DriverObject->DeviceObject);
190 }
191
192 /* Free the lock */
193 ExFreePool(FsRecLoadSync);
194 }
195
196 NTSTATUS
197 NTAPI
198 FsRecRegisterFs(IN PDRIVER_OBJECT DriverObject,
199 IN PDEVICE_OBJECT ParentObject OPTIONAL,
200 OUT PDEVICE_OBJECT *NewDeviceObject OPTIONAL,
201 IN PCWSTR FsName,
202 IN PCWSTR RecognizerName,
203 IN ULONG FsType,
204 IN DEVICE_TYPE DeviceType)
205 {
206 OBJECT_ATTRIBUTES ObjectAttributes;
207 IO_STATUS_BLOCK IoStatus;
208 PDEVICE_EXTENSION DeviceExtension;
209 UNICODE_STRING DeviceName;
210 PDEVICE_OBJECT DeviceObject;
211 HANDLE FileHandle;
212 NTSTATUS Status;
213
214 /* Assume failure */
215 if (NewDeviceObject) *NewDeviceObject = NULL;
216
217 /* Setup the attributes */
218 RtlInitUnicodeString(&DeviceName, FsName);
219 InitializeObjectAttributes(&ObjectAttributes,
220 &DeviceName,
221 OBJ_CASE_INSENSITIVE,
222 0,
223 NULL);
224
225 /* Open the device */
226 Status = ZwCreateFile(&FileHandle,
227 SYNCHRONIZE,
228 &ObjectAttributes,
229 &IoStatus,
230 NULL,
231 0,
232 FILE_SHARE_READ | FILE_SHARE_WRITE,
233 FILE_OPEN,
234 0,
235 NULL,
236 0);
237 if (NT_SUCCESS(Status))
238 {
239 /* We suceeded, close the handle */
240 ZwClose(FileHandle);
241 }
242 else if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
243 {
244 /* We failed with anything else then what we want to fail with */
245 Status = STATUS_SUCCESS;
246 }
247
248 /* If we succeeded, there's no point in trying this again */
249 if (NT_SUCCESS(Status)) return STATUS_IMAGE_ALREADY_LOADED;
250
251 /* Create recognizer device object */
252 RtlInitUnicodeString(&DeviceName, RecognizerName);
253 Status = IoCreateDevice(DriverObject,
254 sizeof(DEVICE_EXTENSION),
255 &DeviceName,
256 DeviceType,
257 0,
258 FALSE,
259 &DeviceObject);
260 if (NT_SUCCESS(Status))
261 {
262 /* Get the device extension and set it up */
263 DeviceExtension = DeviceObject->DeviceExtension;
264 DeviceExtension->FsType = FsType;
265 DeviceExtension->State = Pending;
266
267 /* Do we have a parent? */
268 if (ParentObject)
269 {
270 /* Link it in */
271 DeviceExtension->Alternate =
272 ((PDEVICE_EXTENSION)ParentObject->DeviceExtension)->Alternate;
273 ((PDEVICE_EXTENSION)ParentObject->DeviceExtension)->Alternate =
274 DeviceObject;
275 }
276 else
277 {
278 /* Otherwise, we're the only one */
279 DeviceExtension->Alternate = DeviceObject;
280 }
281
282 /* Return the DO if needed */
283 if (NewDeviceObject) *NewDeviceObject = DeviceObject;
284
285 /* Register the file system */
286 IoRegisterFileSystem(DeviceObject);
287 }
288
289 /* Return Status */
290 return Status;
291 }
292
293 NTSTATUS
294 NTAPI
295 DriverEntry(IN PDRIVER_OBJECT DriverObject,
296 IN PUNICODE_STRING RegistryPath)
297 {
298 ULONG DeviceCount = 0;
299 NTSTATUS Status;
300 PDEVICE_OBJECT UdfsObject;
301 PAGED_CODE();
302
303 UNREFERENCED_PARAMETER(RegistryPath);
304
305 /* Page the entire driver */
306 MmPageEntireDriver(DriverEntry);
307
308 /* Allocate the lock */
309 FsRecLoadSync = ExAllocatePoolWithTag(NonPagedPool,
310 sizeof(KEVENT),
311 FSREC_TAG);
312 if (!FsRecLoadSync) return STATUS_INSUFFICIENT_RESOURCES;
313
314 /* Initialize it */
315 KeInitializeEvent(FsRecLoadSync, SynchronizationEvent, TRUE);
316
317 /* Setup the major functions */
318 DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRecCreate;
319 DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecClose;
320 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecClose;
321 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl;
322 DriverObject->DriverUnload = FsRecUnload;
323
324 /* Register CDFS */
325 Status = FsRecRegisterFs(DriverObject,
326 NULL,
327 NULL,
328 L"\\Cdfs",
329 L"\\FileSystem\\CdfsRecognizer",
330 FS_TYPE_CDFS,
331 FILE_DEVICE_CD_ROM_FILE_SYSTEM);
332 if (NT_SUCCESS(Status)) DeviceCount++;
333
334 /* Register UDFS for CDs */
335 Status = FsRecRegisterFs(DriverObject,
336 NULL,
337 &UdfsObject,
338 L"\\UdfsCdRom",
339 L"\\FileSystem\\UdfsCdRomRecognizer",
340 FS_TYPE_UDFS,
341 FILE_DEVICE_CD_ROM_FILE_SYSTEM);
342 if (NT_SUCCESS(Status)) DeviceCount++;
343
344 /* Register UDFS for HDDs */
345 Status = FsRecRegisterFs(DriverObject,
346 UdfsObject,
347 NULL,
348 L"\\UdfsDisk",
349 L"\\FileSystem\\UdfsDiskRecognizer",
350 FS_TYPE_UDFS,
351 FILE_DEVICE_DISK_FILE_SYSTEM);
352 if (NT_SUCCESS(Status)) DeviceCount++;
353
354 /* Register FAT */
355 Status = FsRecRegisterFs(DriverObject,
356 NULL,
357 NULL,
358 L"\\Fat",
359 L"\\FileSystem\\FatRecognizer",
360 FS_TYPE_VFAT,
361 FILE_DEVICE_DISK_FILE_SYSTEM);
362 if (NT_SUCCESS(Status)) DeviceCount++;
363
364 /* Register NTFS */
365 Status = FsRecRegisterFs(DriverObject,
366 NULL,
367 NULL,
368 L"\\Ntfs",
369 L"\\FileSystem\\NtfsRecognizer",
370 FS_TYPE_NTFS,
371 FILE_DEVICE_DISK_FILE_SYSTEM);
372 if (NT_SUCCESS(Status)) DeviceCount++;
373
374 /* Register EXT2 */
375 /*Status = FsRecRegisterFs(DriverObject,
376 NULL,
377 NULL,
378 L"\\Ext2",
379 L"\\FileSystem\\Ext2Recognizer",
380 FS_TYPE_EXT2,
381 FILE_DEVICE_DISK_FILE_SYSTEM);
382 if (NT_SUCCESS(Status)) DeviceCount++;*/
383
384 /* Return appropriate Status */
385 return (DeviceCount > 0) ? STATUS_SUCCESS : STATUS_IMAGE_ALREADY_LOADED;
386 }
387
388 /* EOF */