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