Branching for 0.3.15 release after two days of no response from a certain sphere...
[reactos.git] / 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 /* Make sure we have a file name */
88 if (IoStack->FileObject->FileName.Length)
89 {
90 /* Fail the request */
91 Status = STATUS_OBJECT_PATH_NOT_FOUND;
92 }
93 else
94 {
95 /* Let it through */
96 Status = STATUS_SUCCESS;
97 }
98
99 /* Complete the IRP */
100 Irp->IoStatus.Status = Status;
101 Irp->IoStatus.Information = FILE_OPENED;
102 IoCompleteRequest(Irp, IO_NO_INCREMENT);
103 return Status;
104 }
105
106 DRIVER_DISPATCH FsRecClose;
107 NTSTATUS
108 NTAPI
109 FsRecClose(IN PDEVICE_OBJECT DeviceObject,
110 IN PIRP Irp)
111 {
112 PAGED_CODE();
113
114 /* Just complete the IRP and return success */
115 IoCompleteRequest(Irp, IO_NO_INCREMENT);
116 return STATUS_SUCCESS;
117 }
118
119 DRIVER_DISPATCH FsRecFsControl;
120 NTSTATUS
121 NTAPI
122 FsRecFsControl(IN PDEVICE_OBJECT DeviceObject,
123 IN PIRP Irp)
124 {
125 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
126 NTSTATUS Status;
127 PAGED_CODE();
128
129 /* Check the file system type */
130 switch (DeviceExtension->FsType)
131 {
132 case FS_TYPE_VFAT:
133
134 /* Send FAT command */
135 Status = FsRecVfatFsControl(DeviceObject, Irp);
136 break;
137
138 case FS_TYPE_NTFS:
139
140 /* Send NTFS command */
141 Status = FsRecNtfsFsControl(DeviceObject, Irp);
142 break;
143
144 case FS_TYPE_CDFS:
145
146 /* Send CDFS command */
147 Status = FsRecCdfsFsControl(DeviceObject, Irp);
148 break;
149
150 case FS_TYPE_UDFS:
151
152 /* Send UDFS command */
153 Status = FsRecUdfsFsControl(DeviceObject, Irp);
154 break;
155
156 case FS_TYPE_EXT2:
157
158 /* Send EXT2 command */
159 Status = FsRecExt2FsControl(DeviceObject, Irp);
160 break;
161
162 default:
163
164 /* Unrecognized FS */
165 Status = STATUS_INVALID_DEVICE_REQUEST;
166 }
167
168 /* Complete the IRP */
169 Irp->IoStatus.Status = Status;
170 IoCompleteRequest(Irp, IO_NO_INCREMENT);
171 return Status;
172 }
173
174 DRIVER_UNLOAD FsRecUnload;
175 VOID
176 NTAPI
177 FsRecUnload(IN PDRIVER_OBJECT DriverObject)
178 {
179 PAGED_CODE();
180
181 /* Loop all driver device objects */
182 while (DriverObject->DeviceObject)
183 {
184 /* Delete this device */
185 IoDeleteDevice(DriverObject->DeviceObject);
186 }
187
188 /* Free the lock */
189 ExFreePool(FsRecLoadSync);
190 }
191
192 NTSTATUS
193 NTAPI
194 FsRecRegisterFs(IN PDRIVER_OBJECT DriverObject,
195 IN PDEVICE_OBJECT ParentObject OPTIONAL,
196 OUT PDEVICE_OBJECT *NewDeviceObject OPTIONAL,
197 IN PCWSTR FsName,
198 IN PCWSTR RecognizerName,
199 IN ULONG FsType,
200 IN DEVICE_TYPE DeviceType)
201 {
202 OBJECT_ATTRIBUTES ObjectAttributes;
203 IO_STATUS_BLOCK IoStatus;
204 PDEVICE_EXTENSION DeviceExtension;
205 UNICODE_STRING DeviceName;
206 PDEVICE_OBJECT DeviceObject;
207 HANDLE FileHandle;
208 NTSTATUS Status;
209
210 /* Assume failure */
211 if (NewDeviceObject) *NewDeviceObject = NULL;
212
213 /* Setup the attributes */
214 RtlInitUnicodeString(&DeviceName, FsName);
215 InitializeObjectAttributes(&ObjectAttributes,
216 &DeviceName,
217 OBJ_CASE_INSENSITIVE,
218 0,
219 NULL);
220
221 /* Open the device */
222 Status = ZwCreateFile(&FileHandle,
223 SYNCHRONIZE,
224 &ObjectAttributes,
225 &IoStatus,
226 NULL,
227 0,
228 FILE_SHARE_READ | FILE_SHARE_WRITE,
229 FILE_OPEN,
230 0,
231 NULL,
232 0);
233 if (NT_SUCCESS(Status))
234 {
235 /* We suceeded, close the handle */
236 ZwClose(FileHandle);
237 }
238 else if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
239 {
240 /* We failed with anything else then what we want to fail with */
241 Status = STATUS_SUCCESS;
242 }
243
244 /* If we succeeded, there's no point in trying this again */
245 if (NT_SUCCESS(Status)) return STATUS_IMAGE_ALREADY_LOADED;
246
247 /* Create recognizer device object */
248 RtlInitUnicodeString(&DeviceName, RecognizerName);
249 Status = IoCreateDevice(DriverObject,
250 sizeof(DEVICE_EXTENSION),
251 &DeviceName,
252 DeviceType,
253 0,
254 FALSE,
255 &DeviceObject);
256 if (NT_SUCCESS(Status))
257 {
258 /* Get the device extension and set it up */
259 DeviceExtension = DeviceObject->DeviceExtension;
260 DeviceExtension->FsType = FsType;
261 DeviceExtension->State = Pending;
262
263 /* Do we have a parent? */
264 if (ParentObject)
265 {
266 /* Link it in */
267 DeviceExtension->Alternate =
268 ((PDEVICE_EXTENSION)ParentObject->DeviceExtension)->Alternate;
269 ((PDEVICE_EXTENSION)ParentObject->DeviceExtension)->Alternate =
270 DeviceObject;
271 }
272 else
273 {
274 /* Otherwise, we're the only one */
275 DeviceExtension->Alternate = DeviceObject;
276 }
277
278 /* Return the DO if needed */
279 if (NewDeviceObject) *NewDeviceObject = DeviceObject;
280
281 /* Register the file system */
282 IoRegisterFileSystem(DeviceObject);
283 }
284
285 /* Return Status */
286 return Status;
287 }
288
289 NTSTATUS
290 NTAPI
291 DriverEntry(IN PDRIVER_OBJECT DriverObject,
292 IN PUNICODE_STRING RegistryPath)
293 {
294 ULONG DeviceCount = 0;
295 NTSTATUS Status;
296 PDEVICE_OBJECT UdfsObject;
297 PAGED_CODE();
298
299 /* Page the entire driver */
300 MmPageEntireDriver(DriverEntry);
301
302 /* Allocate the lock */
303 FsRecLoadSync = ExAllocatePoolWithTag(NonPagedPool,
304 sizeof(KEVENT),
305 FSREC_TAG);
306 if (!FsRecLoadSync) return STATUS_INSUFFICIENT_RESOURCES;
307
308 /* Initialize it */
309 KeInitializeEvent(FsRecLoadSync, SynchronizationEvent, TRUE);
310
311 /* Setup the major functions */
312 DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRecCreate;
313 DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecClose;
314 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecClose;
315 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl;
316 DriverObject->DriverUnload = FsRecUnload;
317
318 /* Register CDFS */
319 Status = FsRecRegisterFs(DriverObject,
320 NULL,
321 NULL,
322 L"\\Cdfs",
323 L"\\FileSystem\\CdfsRecognizer",
324 FS_TYPE_CDFS,
325 FILE_DEVICE_CD_ROM_FILE_SYSTEM);
326 if (NT_SUCCESS(Status)) DeviceCount++;
327
328 /* Register UDFS for CDs */
329 Status = FsRecRegisterFs(DriverObject,
330 NULL,
331 &UdfsObject,
332 L"\\UdfsCdRom",
333 L"\\FileSystem\\UdfsCdRomRecognizer",
334 FS_TYPE_UDFS,
335 FILE_DEVICE_CD_ROM_FILE_SYSTEM);
336 if (NT_SUCCESS(Status)) DeviceCount++;
337
338 /* Register UDFS for HDDs */
339 Status = FsRecRegisterFs(DriverObject,
340 UdfsObject,
341 NULL,
342 L"\\UdfsDisk",
343 L"\\FileSystem\\UdfsDiskRecognizer",
344 FS_TYPE_UDFS,
345 FILE_DEVICE_DISK_FILE_SYSTEM);
346 if (NT_SUCCESS(Status)) DeviceCount++;
347
348 /* Register FAT */
349 Status = FsRecRegisterFs(DriverObject,
350 NULL,
351 NULL,
352 L"\\Fat",
353 L"\\FileSystem\\FatRecognizer",
354 FS_TYPE_VFAT,
355 FILE_DEVICE_DISK_FILE_SYSTEM);
356 if (NT_SUCCESS(Status)) DeviceCount++;
357
358 /* Register NTFS */
359 Status = FsRecRegisterFs(DriverObject,
360 NULL,
361 NULL,
362 L"\\Ntfs",
363 L"\\FileSystem\\NtfsRecognizer",
364 FS_TYPE_NTFS,
365 FILE_DEVICE_DISK_FILE_SYSTEM);
366 if (NT_SUCCESS(Status)) DeviceCount++;
367
368 /* Register EXT2 */
369 /*Status = FsRecRegisterFs(DriverObject,
370 NULL,
371 NULL,
372 L"\\Ext2",
373 L"\\FileSystem\\Ext2Recognizer",
374 FS_TYPE_EXT2,
375 FILE_DEVICE_DISK_FILE_SYSTEM);
376 if (NT_SUCCESS(Status)) DeviceCount++;*/
377
378 /* Return appropriate Status */
379 return (DeviceCount > 0) ? STATUS_SUCCESS : STATUS_IMAGE_ALREADY_LOADED;
380 }
381
382 /* EOF */