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