diff --git a/reactos/drivers/filesystems/fs_rec/blockdev.c b/reactos/drivers/filesystems/fs_rec/blockdev.c index 17a9769cec6..69a4430f6d5 100644 --- a/reactos/drivers/filesystems/fs_rec/blockdev.c +++ b/reactos/drivers/filesystems/fs_rec/blockdev.c @@ -1,162 +1,224 @@ -/* - * ReactOS kernel - * Copyright (C) 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: services/fs/fs_rec/blockdev.c - * PURPOSE: Filesystem recognizer driver - * PROGRAMMER: Eric Kohl + * PROJECT: ReactOS File System Recognizer + * FILE: drivers/filesystems/fs_rec/blockdev.c + * PURPOSE: Generic Helper Functions + * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) + * Eric Kohl */ /* INCLUDES *****************************************************************/ +#include "fs_rec.h" #define NDEBUG #include -#include "fs_rec.h" - - /* FUNCTIONS ****************************************************************/ -NTSTATUS -FsRecReadSectors(IN PDEVICE_OBJECT DeviceObject, - IN ULONG DiskSector, - IN ULONG SectorCount, - IN ULONG SectorSize, - IN OUT PUCHAR Buffer) +BOOLEAN +NTAPI +FsRecGetDeviceSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + OUT PLARGE_INTEGER SectorCount) { - IO_STATUS_BLOCK IoStatus; - LARGE_INTEGER Offset; - ULONG BlockSize; - PKEVENT Event; - PIRP Irp; - NTSTATUS Status; + PARTITION_INFORMATION PartitionInfo; + IO_STATUS_BLOCK IoStatusBlock; + KEVENT Event; + PIRP Irp; + NTSTATUS Status; + ULONG Remainder; + PAGED_CODE(); - Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); - if (Event == NULL) + /* Only needed for disks */ + if (DeviceObject->DeviceType != FILE_DEVICE_DISK) return FALSE; + + /* Build the information IRP */ + KeInitializeEvent(&Event, SynchronizationEvent, FALSE); + Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO, + DeviceObject, + NULL, + 0, + &PartitionInfo, + sizeof(PARTITION_INFORMATION), + FALSE, + &Event, + &IoStatusBlock); + if (!Irp) return FALSE; + + /* Override verification */ + IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME; + + /* Do the request */ + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) { - return(STATUS_INSUFFICIENT_RESOURCES); + /* Wait for completion */ + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; } - KeInitializeEvent(Event, - NotificationEvent, - FALSE); + /* Fail if we couldn't get the data */ + if (!NT_SUCCESS(Status)) return FALSE; - Offset.QuadPart = (LONGLONG)DiskSector * (LONGLONG)SectorSize; - BlockSize = SectorCount * SectorSize; - - DPRINT("FsrecReadSectors(DeviceObject %x, DiskSector %d, Buffer %x)\n", - DeviceObject, DiskSector, Buffer); - DPRINT("Offset %I64x BlockSize %ld\n", - Offset.QuadPart, - BlockSize); - - DPRINT("Building synchronous FSD Request...\n"); - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, - DeviceObject, - Buffer, - BlockSize, - &Offset, - Event, - &IoStatus); - if (Irp == NULL) - { - DPRINT("IoBuildSynchronousFsdRequest failed\n"); - ExFreePool(Event); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - DPRINT("Calling IO Driver... with irp %x\n", Irp); - Status = IoCallDriver(DeviceObject, Irp); - if (Status == STATUS_PENDING) - { - DPRINT("Operation pending\n"); - KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL); - Status = IoStatus.Status; - } - - ExFreePool(Event); - - return(STATUS_SUCCESS); + /* Otherwise, return the number of sectors */ + *SectorCount = RtlExtendedLargeIntegerDivide(PartitionInfo.PartitionLength, + SectorSize, + &Remainder); + return TRUE; } - -NTSTATUS -FsRecDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, - IN ULONG ControlCode, - IN PVOID InputBuffer, - IN ULONG InputBufferSize, - IN OUT PVOID OutputBuffer, - IN OUT PULONG OutputBufferSize) +BOOLEAN +NTAPI +FsRecGetDeviceSectorSize(IN PDEVICE_OBJECT DeviceObject, + OUT PULONG SectorSize) { - ULONG BufferSize = 0; - PKEVENT Event; - PIRP Irp; - IO_STATUS_BLOCK IoStatus; - NTSTATUS Status; + DISK_GEOMETRY DiskGeometry; + IO_STATUS_BLOCK IoStatusBlock; + KEVENT Event; + PIRP Irp; + NTSTATUS Status; + ULONG ControlCode; + PAGED_CODE(); - if (OutputBufferSize != NULL) + /* Check what device we have */ + switch (DeviceObject->DeviceType) { - BufferSize = *OutputBufferSize; + case FILE_DEVICE_CD_ROM: + + /* Use the CD IOCTL */ + ControlCode = IOCTL_CDROM_GET_DRIVE_GEOMETRY; + break; + + case FILE_DEVICE_DISK: + + /* Use the Disk IOCTL */ + ControlCode = IOCTL_DISK_GET_DRIVE_GEOMETRY; + break; + + default: + + /* Invalid device type */ + return FALSE; } - Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); - if (Event == NULL) + /* Build the information IRP */ + KeInitializeEvent(&Event, SynchronizationEvent, FALSE); + Irp = IoBuildDeviceIoControlRequest(ControlCode, + DeviceObject, + NULL, + 0, + &DiskGeometry, + sizeof(DISK_GEOMETRY), + FALSE, + &Event, + &IoStatusBlock); + if (!Irp) return FALSE; + + /* Override verification */ + IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME; + + /* Do the request */ + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) { - return(STATUS_INSUFFICIENT_RESOURCES); + /* Wait for completion */ + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; } - KeInitializeEvent(Event, NotificationEvent, FALSE); + /* Fail if we couldn't get the data */ + if (!NT_SUCCESS(Status)) return FALSE; - DPRINT("Building device I/O control request ...\n"); - Irp = IoBuildDeviceIoControlRequest(ControlCode, - DeviceObject, - InputBuffer, - InputBufferSize, - OutputBuffer, - BufferSize, - FALSE, - Event, - &IoStatus); - if (Irp == NULL) - { - DPRINT("IoBuildDeviceIoControlRequest() failed\n"); - ExFreePool(Event); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - DPRINT("Calling IO Driver... with irp %x\n", Irp); - Status = IoCallDriver(DeviceObject, Irp); - if (Status == STATUS_PENDING) - { - KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL); - Status = IoStatus.Status; - } - - if (OutputBufferSize != NULL) - { - *OutputBufferSize = IoStatus.Information; - } - - ExFreePool(Event); - - return(Status); + /* Return the sector size if it's valid */ + if (!DiskGeometry.BytesPerSector) return FALSE; + *SectorSize = DiskGeometry.BytesPerSector; + return TRUE; +} + +BOOLEAN +NTAPI +FsRecReadBlock(IN PDEVICE_OBJECT DeviceObject, + IN PLARGE_INTEGER Offset, + IN ULONG Length, + IN ULONG SectorSize, + IN OUT PVOID *Buffer, + OUT PBOOLEAN DeviceError OPTIONAL) +{ + IO_STATUS_BLOCK IoStatusBlock; + KEVENT Event; + PIRP Irp; + NTSTATUS Status; + PAGED_CODE(); + + /* Assume failure */ + if (DeviceError) *DeviceError = FALSE; + + /* Check if the caller requested too little */ + if (Length < SectorSize) + { + /* Read at least the sector size */ + Length = SectorSize; + } + else + { + /* Otherwise, just round up the request to sector size */ + Length = ROUND_UP(Length, SectorSize); + } + + /* Check if the caller gave us a buffer */ + if (!*Buffer) + { + /* He didn't, allocate one */ + *Buffer = ExAllocatePoolWithTag(NonPagedPool, + PAGE_ROUND_UP(Length), + FSREC_TAG); + if (!*Buffer) return FALSE; + } + + /* Build the IRP */ + KeInitializeEvent(&Event, SynchronizationEvent, FALSE); + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + DeviceObject, + *Buffer, + Length, + Offset, + &Event, + &IoStatusBlock); + if (!Irp) return FALSE; + + /* Override verification */ + IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME; + + /* Do the request */ + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + /* Check if we couldn't get the data */ + if (!NT_SUCCESS(Status)) + { + /* Check if caller wanted to know about the device and fail */ + if (DeviceError) *DeviceError = TRUE; + return FALSE; + } + + /* All went well */ + return TRUE; } -/* EOF */ diff --git a/reactos/drivers/filesystems/fs_rec/cdfs.c b/reactos/drivers/filesystems/fs_rec/cdfs.c index e7db97b18af..5b2fbb46167 100644 --- a/reactos/drivers/filesystems/fs_rec/cdfs.c +++ b/reactos/drivers/filesystems/fs_rec/cdfs.c @@ -1,140 +1,54 @@ -/* - * ReactOS kernel - * Copyright (C) 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: services/fs/fs_rec/cdfs.c - * PURPOSE: Filesystem recognizer driver - * PROGRAMMER: Eric Kohl + * PROJECT: ReactOS File System Recognizer + * FILE: drivers/filesystems/fs_rec/cdfs.c + * PURPOSE: CDFS Recognizer + * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) + * Eric Kohl */ /* INCLUDES *****************************************************************/ +#include "fs_rec.h" #define NDEBUG #include -#include "fs_rec.h" - - -#define CDFS_PVD_SECTOR 16 - /* FUNCTIONS ****************************************************************/ -static NTSTATUS -FsRecIsCdfsVolume(IN PDEVICE_OBJECT DeviceObject) -{ - DISK_GEOMETRY DiskGeometry; - PUCHAR Buffer; - NTSTATUS Status; - ULONG Size; - - Size = sizeof(DISK_GEOMETRY); - Status = FsRecDeviceIoControl(DeviceObject, - IOCTL_CDROM_GET_DRIVE_GEOMETRY, - NULL, - 0, - &DiskGeometry, - &Size); - if (!NT_SUCCESS(Status)) - { - DPRINT("FsRecDeviceIoControl() failed (Status %lx)\n", Status); - return(Status); - } - - DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector); - Buffer = ExAllocatePool(NonPagedPool, - DiskGeometry.BytesPerSector); - if (Buffer == NULL) - { - return(STATUS_INSUFFICIENT_RESOURCES); - } - - Status = FsRecReadSectors(DeviceObject, - CDFS_PVD_SECTOR, - 1, - DiskGeometry.BytesPerSector, - Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT("FsRecReadSectors() failed (Status %lx)\n", Status); - ExFreePool(Buffer); - return(Status); - } - - Buffer[6] = 0; - DPRINT("CD-identifier: [%.5s]\n", Buffer + 1); - - Status = (Buffer[0] == 1 && - Buffer[1] == 'C' && - Buffer[2] == 'D' && - Buffer[3] == '0' && - Buffer[4] == '0' && - Buffer[5] == '1') ? STATUS_SUCCESS : STATUS_UNRECOGNIZED_VOLUME; - - ExFreePool(Buffer); - - return(Status); -} - - NTSTATUS +NTAPI FsRecCdfsFsControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) + IN PIRP Irp) { - PIO_STACK_LOCATION Stack; - static UNICODE_STRING RegistryPath = - RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Cdfs"); - NTSTATUS Status; + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + PAGED_CODE(); - Stack = IoGetCurrentIrpStackLocation(Irp); - - switch (Stack->MinorFunction) + /* Get the I/O Stack and check the function type */ + Stack = IoGetCurrentIrpStackLocation(Irp); + switch (Stack->MinorFunction) { - case IRP_MN_MOUNT_VOLUME: - DPRINT("Cdfs: IRP_MN_MOUNT_VOLUME\n"); - Status = FsRecIsCdfsVolume(Stack->Parameters.MountVolume.DeviceObject); - if (NT_SUCCESS(Status)) - { - DPRINT("Identified CDFS volume\n"); - Status = STATUS_FS_DRIVER_REQUIRED; - } - break; + case IRP_MN_MOUNT_VOLUME: - case IRP_MN_LOAD_FILE_SYSTEM: - DPRINT("Cdfs: IRP_MN_LOAD_FILE_SYSTEM\n"); - Status = ZwLoadDriver(&RegistryPath); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwLoadDriver failed (Status %x)\n", Status); - } - else - { - IoUnregisterFileSystem(DeviceObject); - } - break; + /* We don't validate */ + Status = STATUS_FS_DRIVER_REQUIRED; + break; - default: - DPRINT("Cdfs: Unknown minor function %lx\n", Stack->MinorFunction); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; + case IRP_MN_LOAD_FILE_SYSTEM: + + /* Load the file system */ + Status = FsRecLoadFileSystem(DeviceObject, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Cdfs"); + break; + + default: + + /* Invalid request */ + Status = STATUS_INVALID_DEVICE_REQUEST; } - return(Status); + + /* Return Status */ + return Status; } /* EOF */ diff --git a/reactos/drivers/filesystems/fs_rec/fat.c b/reactos/drivers/filesystems/fs_rec/fat.c index 7eef61bc60e..ade1f6b0945 100644 --- a/reactos/drivers/filesystems/fs_rec/fat.c +++ b/reactos/drivers/filesystems/fs_rec/fat.c @@ -1,224 +1,177 @@ -/* - * ReactOS kernel - * Copyright (C) 2002,2003 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/fs/fs_rec/vfat.c - * PURPOSE: Filesystem recognizer driver - * PROGRAMMER: Eric Kohl + * PROJECT: ReactOS File System Recognizer + * FILE: drivers/filesystems/fs_rec/fat.c + * PURPOSE: FAT Recognizer + * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) + * Eric Kohl */ /* INCLUDES *****************************************************************/ +#include "fs_rec.h" #define NDEBUG #include -#include "fs_rec.h" - - /* FUNCTIONS ****************************************************************/ -static NTSTATUS -FsRecIsFatVolume(IN PDEVICE_OBJECT DeviceObject) +NTSTATUS +NTAPI +FsRecIsFatVolume(IN PPACKED_BOOT_SECTOR PackedBootSector) { - NTSTATUS Status; - PARTITION_INFORMATION PartitionInfo; - DISK_GEOMETRY DiskGeometry; - ULONG Size; - struct _BootSector* Boot; - BOOLEAN RecognizedFS = FALSE; - Size = sizeof(DISK_GEOMETRY); + BIOS_PARAMETER_BLOCK Bpb; + BOOLEAN Result = TRUE; + PAGED_CODE(); - Status = FsRecDeviceIoControl(DeviceObject, - IOCTL_DISK_GET_DRIVE_GEOMETRY, - NULL, - 0, - &DiskGeometry, - &Size); - if (!NT_SUCCESS(Status)) - { - DPRINT("FsRecDeviceIoControl faild (%x)\n", Status); - return Status; - } - if (DiskGeometry.MediaType == FixedMedia || DiskGeometry.MediaType == RemovableMedia) - { - // We have found a hard disk - Size = sizeof(PARTITION_INFORMATION); - Status = FsRecDeviceIoControl(DeviceObject, - IOCTL_DISK_GET_PARTITION_INFO, - NULL, - 0, - &PartitionInfo, - &Size); - if (!NT_SUCCESS(Status)) - { - DPRINT("FsRecDeviceIoControl faild (%x)\n", Status); - return Status; - } + /* Unpack the BPB and do a small fix up */ + FatUnpackBios(&Bpb, &PackedBootSector->PackedBpb); + if (Bpb.Sectors) Bpb.LargeSectors = 0; - if (PartitionInfo.PartitionType) - { - if (PartitionInfo.PartitionType == PARTITION_FAT_12 || - PartitionInfo.PartitionType == PARTITION_FAT_16 || - PartitionInfo.PartitionType == PARTITION_HUGE || - PartitionInfo.PartitionType == PARTITION_FAT32 || - PartitionInfo.PartitionType == PARTITION_FAT32_XINT13 || - PartitionInfo.PartitionType == PARTITION_XINT13) - { - RecognizedFS = TRUE; - } - } - else if (DiskGeometry.MediaType == RemovableMedia && - PartitionInfo.PartitionNumber > 0 && - PartitionInfo.StartingOffset.QuadPart == 0 && - PartitionInfo.PartitionLength.QuadPart > 0) - { - /* This is possible a removable media formated as super floppy */ - RecognizedFS = TRUE; - } - } - if (DiskGeometry.MediaType > Unknown && DiskGeometry.MediaType < RemovableMedia ) - { - RecognizedFS = TRUE; - } - if (RecognizedFS == FALSE) - { - return STATUS_UNRECOGNIZED_VOLUME; - } + /* Recognize jump */ + if ((PackedBootSector->Jump[0] != 0x49) && + (PackedBootSector->Jump[0] != 0xE9) && + (PackedBootSector->Jump[0] != 0xEB)) + { + /* Fail */ + Result = FALSE; + } + else if ((Bpb.BytesPerSector != 128) && + (Bpb.BytesPerSector != 256) && + (Bpb.BytesPerSector != 512) && + (Bpb.BytesPerSector != 1024) && + (Bpb.BytesPerSector != 2048) && + (Bpb.BytesPerSector != 4096)) + { + /* Fail */ + Result = FALSE; + } + else if ((Bpb.SectorsPerCluster != 1) && + (Bpb.SectorsPerCluster != 2) && + (Bpb.SectorsPerCluster != 4) && + (Bpb.SectorsPerCluster != 8) && + (Bpb.SectorsPerCluster != 16) && + (Bpb.SectorsPerCluster != 32) && + (Bpb.SectorsPerCluster != 64) && + (Bpb.SectorsPerCluster != 128)) + { + /* Fail */ + Result = FALSE; + } + else if (!Bpb.ReservedSectors) + { + /* Fail */ + Result = FALSE; + } + else if (!(Bpb.Sectors) && !(Bpb.LargeSectors)) + { + /* Fail */ + Result = FALSE; + } + else if ((Bpb.Media != 0x00) && + (Bpb.Media != 0x01) && + (Bpb.Media != 0xf0) && + (Bpb.Media != 0xf8) && + (Bpb.Media != 0xf9) && + (Bpb.Media != 0xfa) && + (Bpb.Media != 0xfb) && + (Bpb.Media != 0xfc) && + (Bpb.Media != 0xfd) && + (Bpb.Media != 0xfe) && + (Bpb.Media != 0xff)) + { + /* Fail */ + Result = FALSE; + } + else if ((Bpb.SectorsPerFat) && !(Bpb.RootEntries)) + { + /* Fail */ + Result = FALSE; + } - Boot = ExAllocatePool(NonPagedPool, DiskGeometry.BytesPerSector); - if (Boot == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - Status = FsRecReadSectors(DeviceObject, - 0, - 1, - DiskGeometry.BytesPerSector, - (PUCHAR) Boot); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - if (Boot->Signatur1 != 0xaa55) - { - RecognizedFS=FALSE; - } - if (RecognizedFS && - Boot->BytesPerSector != 512 && - Boot->BytesPerSector != 1024 && - Boot->BytesPerSector != 2048 && - Boot->BytesPerSector == 4096) - { - RecognizedFS=FALSE; - } - - if (RecognizedFS && - Boot->FATCount != 1 && - Boot->FATCount != 2) - { - RecognizedFS=FALSE; - } - - if (RecognizedFS && - Boot->Media != 0xf0 && - Boot->Media != 0xf8 && - Boot->Media != 0xf9 && - Boot->Media != 0xfa && - Boot->Media != 0xfb && - Boot->Media != 0xfc && - Boot->Media != 0xfd && - Boot->Media != 0xfe && - Boot->Media != 0xff) - { - RecognizedFS=FALSE; - } - - if (RecognizedFS && - Boot->SectorsPerCluster != 1 && - Boot->SectorsPerCluster != 2 && - Boot->SectorsPerCluster != 4 && - Boot->SectorsPerCluster != 8 && - Boot->SectorsPerCluster != 16 && - Boot->SectorsPerCluster != 32 && - Boot->SectorsPerCluster != 64 && - Boot->SectorsPerCluster != 128) - { - RecognizedFS=FALSE; - } - - if (RecognizedFS && - Boot->BytesPerSector * Boot->SectorsPerCluster > 32 * 1024) - { - RecognizedFS=FALSE; - } - - - ExFreePool(Boot); - return RecognizedFS ? STATUS_SUCCESS : STATUS_UNRECOGNIZED_VOLUME; + /* Return the result */ + return Result; } - NTSTATUS +NTAPI FsRecVfatFsControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) + IN PIRP Irp) { - PIO_STACK_LOCATION Stack; - static UNICODE_STRING RegistryPath = - RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Vfatfs"); - NTSTATUS Status; + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + PDEVICE_OBJECT MountDevice; + PPACKED_BOOT_SECTOR Bpb = NULL; + ULONG SectorSize; + LARGE_INTEGER Offset = {{0}}; + BOOLEAN DeviceError = FALSE; + PAGED_CODE(); - Stack = IoGetCurrentIrpStackLocation(Irp); - - switch (Stack->MinorFunction) + /* Get the I/O Stack and check the function type */ + Stack = IoGetCurrentIrpStackLocation(Irp); + switch (Stack->MinorFunction) { - case IRP_MN_MOUNT_VOLUME: - DPRINT("FAT: IRP_MN_MOUNT_VOLUME\n"); - Status = FsRecIsFatVolume(Stack->Parameters.MountVolume.DeviceObject); - if (NT_SUCCESS(Status)) - { - DPRINT("Identified FAT volume\n"); - Status = STATUS_FS_DRIVER_REQUIRED; - } - break; + case IRP_MN_MOUNT_VOLUME: - case IRP_MN_LOAD_FILE_SYSTEM: - DPRINT("FAT: IRP_MN_LOAD_FILE_SYSTEM\n"); - Status = ZwLoadDriver(&RegistryPath); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwLoadDriver failed (Status %x)\n", Status); - } - else - { - IoUnregisterFileSystem(DeviceObject); - } - break; + /* Assume failure */ + Status = STATUS_UNRECOGNIZED_VOLUME; - default: - DPRINT("FAT: Unknown minor function %lx\n", Stack->MinorFunction); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; + /* Get the device object and request the sector size */ + MountDevice = Stack->Parameters.MountVolume.DeviceObject; + if (FsRecGetDeviceSectorSize(MountDevice, &SectorSize)) + { + /* Try to read the BPB */ + if (FsRecReadBlock(MountDevice, + &Offset, + 512, + SectorSize, + (PVOID)&Bpb, + &DeviceError)) + { + /* Check if it's an actual FAT volume */ + if (FsRecIsFatVolume(Bpb)) + { + /* It is! */ + Status = STATUS_FS_DRIVER_REQUIRED; + } + } + + /* Free the boot sector if we have one */ + ExFreePool(Bpb); + } + else + { + /* We have some sort of failure in the storage stack */ + DeviceError = TRUE; + } + + /* Check if we have an error on the stack */ + if (DeviceError) + { + /* Was this because of a floppy? */ + if (MountDevice->Characteristics & FILE_FLOPPY_DISKETTE) + { + /* Let the FS try anyway */ + Status = STATUS_FS_DRIVER_REQUIRED; + } + } + + break; + + case IRP_MN_LOAD_FILE_SYSTEM: + + /* Load the file system */ + Status = FsRecLoadFileSystem(DeviceObject, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Vfatfs"); + break; + + default: + + /* Invalid request */ + Status = STATUS_INVALID_DEVICE_REQUEST; } - return(Status); + + /* Return Status */ + return Status; } /* EOF */ diff --git a/reactos/drivers/filesystems/fs_rec/fs_rec.c b/reactos/drivers/filesystems/fs_rec/fs_rec.c index 8f48f9ae335..c5cb0b460e5 100644 --- a/reactos/drivers/filesystems/fs_rec/fs_rec.c +++ b/reactos/drivers/filesystems/fs_rec/fs_rec.c @@ -1,254 +1,362 @@ -/* - * ReactOS kernel - * Copyright (C) 2002,2003 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/fs/fs_rec/fs_rec.c - * PURPOSE: Filesystem recognizer driver - * PROGRAMMER: Eric Kohl + * PROJECT: ReactOS File System Recognizer + * FILE: drivers/filesystems/fs_rec/fs_rec.c + * PURPOSE: Main Driver Entrypoint and FS Registration + * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) + * Eric Kohl */ /* INCLUDES *****************************************************************/ +#include "fs_rec.h" #define NDEBUG #include -#include "fs_rec.h" - +PKEVENT FsRecLoadSync; /* FUNCTIONS ****************************************************************/ -static NTSTATUS STDCALL -FsRecCreate(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) +NTSTATUS +NTAPI +FsRecLoadFileSystem(IN PDEVICE_OBJECT DeviceObject, + IN PWCHAR DriverServiceName) { - NTSTATUS Status; + UNICODE_STRING DriverName; + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + NTSTATUS Status = STATUS_IMAGE_ALREADY_LOADED; + PAGED_CODE(); - - Status = STATUS_SUCCESS; - - - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, - IO_NO_INCREMENT); - - return(Status); -} - - -static NTSTATUS STDCALL -FsRecClose(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, - IO_NO_INCREMENT); - - return(STATUS_SUCCESS); -} - - -static NTSTATUS STDCALL -FsRecFsControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PDEVICE_EXTENSION DeviceExt; - NTSTATUS Status; - - DeviceExt = DeviceObject->DeviceExtension; - switch (DeviceExt->FsType) + /* Make sure we haven't already been called */ + if (DeviceExtension->State != Loaded) { - case FS_TYPE_VFAT: - Status = FsRecVfatFsControl(DeviceObject, Irp); - break; + /* Acquire the load lock */ + KeWaitForSingleObject(FsRecLoadSync, + Executive, + KernelMode, + FALSE, + NULL); + KeEnterCriticalRegion(); - case FS_TYPE_NTFS: - Status = FsRecNtfsFsControl(DeviceObject, Irp); - break; + /* Make sure we're active */ + if (DeviceExtension->State == Pending) + { + /* Load the FS driver */ + RtlInitUnicodeString(&DriverName, DriverServiceName); + Status = ZwLoadDriver(&DriverName); - case FS_TYPE_CDFS: - Status = FsRecCdfsFsControl(DeviceObject, Irp); - break; + /* Loop all the linked recognizer objects */ + while (DeviceExtension->State != Unloading) + { + /* Set them to the unload state */ + DeviceExtension->State = Unloading; - case FS_TYPE_UDFS: - Status = FsRecUdfsFsControl(DeviceObject, Irp); - break; + /* Go to the next one */ + DeviceObject = DeviceExtension->Alternate; + DeviceExtension = DeviceObject->DeviceExtension; + } + } - default: - Status = STATUS_INVALID_DEVICE_REQUEST; + /* Make sure that we haven't already loaded the FS */ + if (DeviceExtension->State != Loaded) + { + /* Unregiser us, and set us as loaded */ + IoUnregisterFileSystem(DeviceObject); + DeviceExtension->State = Loaded; + } + + /* Release the lock */ + KeSetEvent(FsRecLoadSync, 0, FALSE); + KeLeaveCriticalRegion(); } - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, - IO_NO_INCREMENT); - - return(Status); + /* Return */ + return Status; } +NTSTATUS +STDCALL +FsRecCreate(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS Status; + PAGED_CODE(); -static VOID STDCALL + /* Make sure we have a file name */ + if (IoStack->FileObject->FileName.Length) + { + /* Fail the request */ + Status = STATUS_OBJECT_PATH_NOT_FOUND; + } + else + { + /* Let it through */ + Status = STATUS_SUCCESS; + } + + /* Complete the IRP */ + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = FILE_OPENED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} + +NTSTATUS +STDCALL +FsRecClose(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PAGED_CODE(); + + /* Just complete the IRP and return success */ + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +NTSTATUS +STDCALL +FsRecFsControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + NTSTATUS Status; + PAGED_CODE(); + + /* Check the file system type */ + switch (DeviceExtension->FsType) + { + case FS_TYPE_VFAT: + + /* Send FAT command */ + Status = FsRecVfatFsControl(DeviceObject, Irp); + break; + + case FS_TYPE_NTFS: + + /* Send NTFS command */ + Status = FsRecNtfsFsControl(DeviceObject, Irp); + break; + + case FS_TYPE_CDFS: + + /* Send CDFS command */ + Status = FsRecCdfsFsControl(DeviceObject, Irp); + break; + + case FS_TYPE_UDFS: + + /* Send UDFS command */ + Status = FsRecUdfsFsControl(DeviceObject, Irp); + break; + + default: + + /* Unrecognized FS */ + Status = STATUS_INVALID_DEVICE_REQUEST; + } + + /* Complete the IRP */ + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} + +VOID +STDCALL FsRecUnload(IN PDRIVER_OBJECT DriverObject) { - PDEVICE_OBJECT NextDevice; - PDEVICE_OBJECT ThisDevice; + PAGED_CODE(); - /* Delete all remaining device objects */ - NextDevice = DriverObject->DeviceObject; - while (NextDevice != NULL) + /* Loop all driver device objects */ + while (DriverObject->DeviceObject) { - ThisDevice = NextDevice; - NextDevice = NextDevice->NextDevice; - IoDeleteDevice(ThisDevice); + /* Delete this device */ + IoDeleteDevice(DriverObject->DeviceObject); } + + /* Free the lock */ + ExFreePool(FsRecLoadSync); } - -static NTSTATUS -FsRecRegisterFs(PDRIVER_OBJECT DriverObject, - PCWSTR FsName, - PCWSTR RecognizerName, - ULONG DeviceType, - ULONG FsType) +NTSTATUS +STDCALL +FsRecRegisterFs(IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT ParentObject OPTIONAL, + OUT PDEVICE_OBJECT *NewDeviceObject OPTIONAL, + IN PCWSTR FsName, + IN PCWSTR RecognizerName, + IN ULONG FsType, + IN DEVICE_TYPE DeviceType) { - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatus; - PDEVICE_EXTENSION DeviceExt; - UNICODE_STRING DeviceName; - UNICODE_STRING FileName; - PDEVICE_OBJECT DeviceObject; - HANDLE FileHandle; - NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatus; + PDEVICE_EXTENSION DeviceExtension; + UNICODE_STRING DeviceName; + PDEVICE_OBJECT DeviceObject; + HANDLE FileHandle; + NTSTATUS Status; - RtlInitUnicodeString(&FileName, - FsName); + /* Assume failure */ + if (NewDeviceObject) *NewDeviceObject = NULL; - InitializeObjectAttributes(&ObjectAttributes, - &FileName, - OBJ_CASE_INSENSITIVE, - 0, - NULL); + /* Setup the attributes */ + RtlInitUnicodeString(&DeviceName, FsName); + InitializeObjectAttributes(&ObjectAttributes, + &DeviceName, + OBJ_CASE_INSENSITIVE, + 0, + NULL); - Status = ZwCreateFile(&FileHandle, - 0x100000, - &ObjectAttributes, - &IoStatus, - NULL, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN, - 0, - NULL, - 0); - if (NT_SUCCESS(Status)) + /* Open the device */ + Status = ZwCreateFile(&FileHandle, + SYNCHRONIZE, + &ObjectAttributes, + &IoStatus, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + 0, + NULL, + 0); + if (NT_SUCCESS(Status)) { - ZwClose(FileHandle); - return(STATUS_IMAGE_ALREADY_LOADED); + /* We suceeded, close the handle */ + ZwClose(FileHandle); + } + else if (Status != STATUS_OBJECT_NAME_NOT_FOUND) + { + /* We failed with anything else then what we want to fail with */ + Status = STATUS_SUCCESS; } - /* Create recognizer device object */ - RtlInitUnicodeString(&DeviceName, - RecognizerName); + /* If we succeeded, there's no point in trying this again */ + if (NT_SUCCESS(Status)) return STATUS_IMAGE_ALREADY_LOADED; - Status = IoCreateDevice(DriverObject, - sizeof(DEVICE_EXTENSION), - &DeviceName, - DeviceType, - 0, - FALSE, - &DeviceObject); - - if (NT_SUCCESS(Status)) + /* Create recognizer device object */ + RtlInitUnicodeString(&DeviceName, RecognizerName); + Status = IoCreateDevice(DriverObject, + sizeof(DEVICE_EXTENSION), + &DeviceName, + DeviceType, + 0, + FALSE, + &DeviceObject); + if (NT_SUCCESS(Status)) { - DeviceExt = DeviceObject->DeviceExtension; - DeviceExt->FsType = FsType; - IoRegisterFileSystem(DeviceObject); - DPRINT("Created recognizer device '%wZ'\n", &DeviceName); + /* Get the device extension and set it up */ + DeviceExtension = DeviceObject->DeviceExtension; + DeviceExtension->FsType = FsType; + DeviceExtension->State = Pending; + + /* Do we have a parent? */ + if (ParentObject) + { + /* Link it in */ + DeviceExtension->Alternate = + ((PDEVICE_EXTENSION)ParentObject->DeviceExtension)->Alternate; + ((PDEVICE_EXTENSION)ParentObject->DeviceExtension)->Alternate = + DeviceObject; + } + else + { + /* Otherwise, we're the only one */ + DeviceExtension->Alternate = DeviceObject; + } + + /* Return the DO if needed */ + if (NewDeviceObject) *NewDeviceObject = DeviceObject; + + /* Register the file system */ + IoRegisterFileSystem(DeviceObject); } - return(Status); + /* Return Status */ + return Status; } - -NTSTATUS STDCALL -DriverEntry(PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath) +NTSTATUS +NTAPI +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) { - PCONFIGURATION_INFORMATION ConfigInfo; - ULONG DeviceCount; - NTSTATUS Status; + ULONG DeviceCount = 0; + NTSTATUS Status; + PDEVICE_OBJECT UdfsObject; + PAGED_CODE(); - DPRINT("FileSystem recognizer 0.0.2\n"); + /* Page the entire driver */ + MmPageEntireDriver(DriverEntry); - DeviceCount = 0; + /* Allocate the lock */ + FsRecLoadSync = ExAllocatePoolWithTag(NonPagedPool, + sizeof(KEVENT), + FSREC_TAG); + if (!FsRecLoadSync) return STATUS_INSUFFICIENT_RESOURCES; - DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRecCreate; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecClose; - DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecClose; - DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl; - DriverObject->DriverUnload = FsRecUnload; + /* Initialize it */ + KeInitializeEvent(FsRecLoadSync, SynchronizationEvent, TRUE); - ConfigInfo = IoGetConfigurationInformation(); + /* Setup the major functions */ + DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRecCreate; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecClose; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecClose; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl; + DriverObject->DriverUnload = FsRecUnload; - if (ConfigInfo->CdRomCount > 0) - { - Status = FsRecRegisterFs(DriverObject, - L"\\Cdfs", - L"\\FileSystem\\CdfsRecognizer", - FILE_DEVICE_CD_ROM_FILE_SYSTEM, - FS_TYPE_CDFS); - if (NT_SUCCESS(Status)) - { - DeviceCount++; - } + /* Register CDFS */ + Status = FsRecRegisterFs(DriverObject, + NULL, + NULL, + L"\\Cdfs", + L"\\FileSystem\\CdfsRecognizer", + FS_TYPE_CDFS, + FILE_DEVICE_CD_ROM_FILE_SYSTEM); + if (NT_SUCCESS(Status)) DeviceCount++; - Status = FsRecRegisterFs(DriverObject, - L"\\Udfs", - L"\\FileSystem\\UdfsRecognizer", - FILE_DEVICE_CD_ROM_FILE_SYSTEM, - FS_TYPE_UDFS); - if (NT_SUCCESS(Status)) - { - DeviceCount++; - } - } + /* Register UDFS for CDs */ + Status = FsRecRegisterFs(DriverObject, + NULL, + &UdfsObject, + L"\\UdfsCdRom", + L"\\FileSystem\\UdfsCdRomRecognizer", + FS_TYPE_UDFS, + FILE_DEVICE_CD_ROM_FILE_SYSTEM); + if (NT_SUCCESS(Status)) DeviceCount++; - Status = FsRecRegisterFs(DriverObject, - L"\\Fat", - L"\\FileSystem\\FatRecognizer", - FILE_DEVICE_DISK_FILE_SYSTEM, - FS_TYPE_VFAT); - if (NT_SUCCESS(Status)) - { - DeviceCount++; - } + /* Register UDFS for HDDs */ + Status = FsRecRegisterFs(DriverObject, + UdfsObject, + NULL, + L"\\UdfsDisk", + L"\\FileSystem\\UdfsDiskRecognizer", + FS_TYPE_UDFS, + FILE_DEVICE_DISK_FILE_SYSTEM); + if (NT_SUCCESS(Status)) DeviceCount++; - Status = FsRecRegisterFs(DriverObject, - L"\\Ntfs", - L"\\FileSystem\\NtfsRecognizer", - FILE_DEVICE_DISK_FILE_SYSTEM, - FS_TYPE_NTFS); - if (NT_SUCCESS(Status)) - { - DeviceCount++; - } + /* Register FAT */ + Status = FsRecRegisterFs(DriverObject, + NULL, + NULL, + L"\\Fat", + L"\\FileSystem\\FatRecognizer", + FS_TYPE_VFAT, + FILE_DEVICE_DISK_FILE_SYSTEM); + if (NT_SUCCESS(Status)) DeviceCount++; - return((DeviceCount > 0) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); + /* Register NTFS */ + Status = FsRecRegisterFs(DriverObject, + NULL, + NULL, + L"\\Ntfs", + L"\\FileSystem\\NtfsRecognizer", + FS_TYPE_NTFS, + FILE_DEVICE_DISK_FILE_SYSTEM); + if (NT_SUCCESS(Status)) DeviceCount++; + + /* Return appropriate Status */ + return (DeviceCount > 0) ? STATUS_SUCCESS : STATUS_IMAGE_ALREADY_LOADED; } /* EOF */ diff --git a/reactos/drivers/filesystems/fs_rec/fs_rec.h b/reactos/drivers/filesystems/fs_rec/fs_rec.h index 5de92225922..090dc408c37 100644 --- a/reactos/drivers/filesystems/fs_rec/fs_rec.h +++ b/reactos/drivers/filesystems/fs_rec/fs_rec.h @@ -1,121 +1,268 @@ -/* - * ReactOS kernel - * Copyright (C) 2002,2003 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/fs/fs_rec/fs_rec.h - * PURPOSE: Filesystem recognizer driver - * PROGRAMMER: Eric Kohl + * PROJECT: ReactOS File System Recognizer + * FILE: drivers/filesystems/fs_rec/fs_rec.h + * PURPOSE: Main Header File + * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) + * Eric Kohl */ +// +// IFS Headers +// #include #include #include +#include "helper.h" -#ifdef _MSC_VER -#define STDCALL __stdcall -#endif +// +// Tag for memory allocations +// +#define FSREC_TAG TAG('F', 's', 'R', 'c') -/* Filesystem types (add new filesystems here)*/ +// +// UDFS Offsets +// +#define UDFS_VRS_START_SECTOR 16 +#define UDFS_AVDP_SECTOR 256 -#define FS_TYPE_UNUSED 0 -#define FS_TYPE_VFAT 1 -#define FS_TYPE_NTFS 2 -#define FS_TYPE_CDFS 3 -#define FS_TYPE_UDFS 4 - - -typedef struct _DEVICE_EXTENSION +// +// Conversion types and macros taken from internal ntifs headers +// +typedef union _UCHAR1 { - ULONG FsType; -} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + UCHAR Uchar[1]; + UCHAR ForceAlignment; +} UCHAR1, *PUCHAR1; +typedef union _UCHAR2 +{ + UCHAR Uchar[2]; + USHORT ForceAlignment; +} UCHAR2, *PUCHAR2; + +typedef union _UCHAR4 +{ + UCHAR Uchar[4]; + ULONG ForceAlignment; +} UCHAR4, *PUCHAR4; + +#define CopyUchar1(Dst,Src) { \ + *((UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src)); \ +} + +#define CopyUchar2(Dst,Src) { \ + *((UCHAR2 *)(Dst)) = *((UNALIGNED UCHAR2 *)(Src)); \ +} + +#define CopyUchar4(Dst,Src) { \ + *((UCHAR4 *)(Dst)) = *((UNALIGNED UCHAR4 *)(Src)); \ +} + +#define FatUnpackBios(Bios,Pbios) { \ + CopyUchar2(&(Bios)->BytesPerSector, &(Pbios)->BytesPerSector[0] ); \ + CopyUchar1(&(Bios)->SectorsPerCluster, &(Pbios)->SectorsPerCluster[0]); \ + CopyUchar2(&(Bios)->ReservedSectors, &(Pbios)->ReservedSectors[0] ); \ + CopyUchar1(&(Bios)->Fats, &(Pbios)->Fats[0] ); \ + CopyUchar2(&(Bios)->RootEntries, &(Pbios)->RootEntries[0] ); \ + CopyUchar2(&(Bios)->Sectors, &(Pbios)->Sectors[0] ); \ + CopyUchar1(&(Bios)->Media, &(Pbios)->Media[0] ); \ + CopyUchar2(&(Bios)->SectorsPerFat, &(Pbios)->SectorsPerFat[0] ); \ + CopyUchar2(&(Bios)->SectorsPerTrack, &(Pbios)->SectorsPerTrack[0] ); \ + CopyUchar2(&(Bios)->Heads, &(Pbios)->Heads[0] ); \ + CopyUchar4(&(Bios)->HiddenSectors, &(Pbios)->HiddenSectors[0] ); \ + CopyUchar4(&(Bios)->LargeSectors, &(Pbios)->LargeSectors[0] ); \ +} + +// +// Packed versions of the BPB and Boot Sector +// +typedef struct _PACKED_BIOS_PARAMETER_BLOCK +{ + UCHAR BytesPerSector[2]; + UCHAR SectorsPerCluster[1]; + UCHAR ReservedSectors[2]; + UCHAR Fats[1]; + UCHAR RootEntries[2]; + UCHAR Sectors[2]; + UCHAR Media[1]; + UCHAR SectorsPerFat[2]; + UCHAR SectorsPerTrack[2]; + UCHAR Heads[2]; + UCHAR HiddenSectors[4]; + UCHAR LargeSectors[4]; +} PACKED_BIOS_PARAMETER_BLOCK, *PPACKED_BIOS_PARAMETER_BLOCK; + +typedef struct _PACKED_BOOT_SECTOR +{ + UCHAR Jump[3]; + UCHAR Oem[8]; + PACKED_BIOS_PARAMETER_BLOCK PackedBpb; + UCHAR PhysicalDriveNumber; + UCHAR CurrentHead; + UCHAR Signature; + UCHAR Id[4]; + UCHAR VolumeLabel[11]; + UCHAR SystemId[8]; +} PACKED_BOOT_SECTOR, *PPACKED_BOOT_SECTOR; + +// +// Unpacked version of the BPB +// +typedef struct BIOS_PARAMETER_BLOCK +{ + USHORT BytesPerSector; + UCHAR SectorsPerCluster; + USHORT ReservedSectors; + UCHAR Fats; + USHORT RootEntries; + USHORT Sectors; + UCHAR Media; + USHORT SectorsPerFat; + USHORT SectorsPerTrack; + USHORT Heads; + ULONG32 HiddenSectors; + ULONG32 LargeSectors; + ULONG32 LargeSectorsPerFat; + union + { + USHORT ExtendedFlags; + struct + { + ULONG ActiveFat:4; + ULONG Reserved0:3; + ULONG MirrorDisabled:1; + ULONG Reserved1:8; + }; + }; + USHORT FsVersion; + ULONG32 RootDirFirstCluster; + USHORT FsInfoSector; + USHORT BackupBootSector; +} BIOS_PARAMETER_BLOCK, *PBIOS_PARAMETER_BLOCK; + +// +// UDFS Structures +// #include -struct _BootSector +typedef struct _TAG { - unsigned char magic0, res0, magic1; - unsigned char OEMName[8]; - unsigned short BytesPerSector; - unsigned char SectorsPerCluster; - unsigned short ReservedSectors; - unsigned char FATCount; - unsigned short RootEntries, Sectors; - unsigned char Media; - unsigned short FATSectors, SectorsPerTrack, Heads; - unsigned long HiddenSectors, SectorsHuge; - unsigned char Drive, Res1, Sig; - unsigned long VolumeID; - unsigned char VolumeLabel[11], SysType[8]; - unsigned char Res2[448]; - unsigned short Signatur1; -}; + USHORT Identifier; + USHORT Version; + UCHAR Checksum; + UCHAR Reserved; + USHORT SerialNumber; + USHORT Crc; + USHORT CrcLength; + ULONG Location; +} TAG, *PTAG; + +typedef struct _EXTENT +{ + ULONG Length; + ULONG Location; +} EXTENT, *PEXTENT; + +typedef struct _AVDP +{ + TAG DescriptorTag; + EXTENT MainVolumeDescriptorExtent; + EXTENT ReserveVolumeDescriptorExtent; +} AVDP, *PAVDP; #include -/* blockdev.c */ +// +// Filesystem Types +// +typedef enum _FILE_SYSTEM_TYPE +{ + FS_TYPE_UNUSED, + FS_TYPE_VFAT, + FS_TYPE_NTFS, + FS_TYPE_CDFS, + FS_TYPE_UDFS +} FILE_SYSTEM_TYPE, *PFILE_SYSTEM_TYPE; + +// +// FS Recognizer State +// +typedef enum _FS_REC_STATE +{ + Pending, + Loaded, + Unloading +} FS_REC_STATE, *PFS_REC_STATE; + +// +// Device extension +// +typedef struct _DEVICE_EXTENSION +{ + FS_REC_STATE State; + FILE_SYSTEM_TYPE FsType; + PDEVICE_OBJECT Alternate; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +// +// Prototypes +// +NTSTATUS +NTAPI +FsRecCdfsFsControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp +); NTSTATUS -FsRecReadSectors(IN PDEVICE_OBJECT DeviceObject, - IN ULONG DiskSector, - IN ULONG SectorCount, - IN ULONG SectorSize, - IN OUT PUCHAR Buffer); +NTAPI +FsRecVfatFsControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp +); NTSTATUS -FsRecDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, - IN ULONG ControlCode, - IN PVOID InputBuffer, - IN ULONG InputBufferSize, - IN OUT PVOID OutputBuffer, - IN OUT PULONG OutputBufferSize); - - -/* cdfs.c */ +NTAPI +FsRecNtfsFsControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp +); NTSTATUS -FsRecCdfsFsControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); +NTAPI +FsRecUdfsFsControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp +); +BOOLEAN +NTAPI +FsRecGetDeviceSectors( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + OUT PLARGE_INTEGER SectorCount +); -/* fat.c */ +BOOLEAN +NTAPI +FsRecGetDeviceSectorSize( + IN PDEVICE_OBJECT DeviceObject, + OUT PULONG SectorSize +); + +BOOLEAN +NTAPI +FsRecReadBlock( + IN PDEVICE_OBJECT DeviceObject, + IN PLARGE_INTEGER Offset, + IN ULONG Length, + IN ULONG SectorSize, + IN OUT PVOID *Buffer, + OUT PBOOLEAN DeviceError OPTIONAL +); NTSTATUS -FsRecVfatFsControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - - -/* ntfs.c */ - -NTSTATUS -FsRecNtfsFsControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - - -/* udfs.c */ - -NTSTATUS -FsRecUdfsFsControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -/* fs_rec.c */ - -NTSTATUS STDCALL -DriverEntry(PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath); - -/* EOF */ +NTAPI +FsRecLoadFileSystem( + IN PDEVICE_OBJECT DeviceObject, + IN PWCHAR DriverServiceName +); diff --git a/reactos/drivers/filesystems/fs_rec/ntfs.c b/reactos/drivers/filesystems/fs_rec/ntfs.c index ccfdf073544..83fc5f2e23e 100644 --- a/reactos/drivers/filesystems/fs_rec/ntfs.c +++ b/reactos/drivers/filesystems/fs_rec/ntfs.c @@ -1,139 +1,145 @@ -/* - * ReactOS kernel - * Copyright (C) 2002,2003 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/fs/fs_rec/ntfs.c - * PURPOSE: Filesystem recognizer driver - * PROGRAMMER: Eric Kohl + * PROJECT: ReactOS File System Recognizer + * FILE: drivers/filesystems/fs_rec/ntfs.c + * PURPOSE: NTFS Recognizer + * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) + * Eric Kohl */ /* INCLUDES *****************************************************************/ +#include "fs_rec.h" #define NDEBUG #include -#include "fs_rec.h" - - /* FUNCTIONS ****************************************************************/ -static NTSTATUS -FsRecIsNtfsVolume(IN PDEVICE_OBJECT DeviceObject) +BOOLEAN +NTAPI +FsRecIsNtfsVolume(IN PPACKED_BOOT_SECTOR BootSector, + IN ULONG BytesPerSector, + IN PLARGE_INTEGER NumberOfSectors) { - DISK_GEOMETRY DiskGeometry; - PUCHAR Buffer; - ULONG Size; - NTSTATUS Status; + PAGED_CODE(); + BOOLEAN Result; - Size = sizeof(DISK_GEOMETRY); - Status = FsRecDeviceIoControl(DeviceObject, - IOCTL_DISK_GET_DRIVE_GEOMETRY, - NULL, - 0, - &DiskGeometry, - &Size); - if (!NT_SUCCESS(Status)) + /* Assume success */ + Result = TRUE; + + if ((BootSector->Oem[0] == 'N') && + (BootSector->Oem[1] == 'T') && + (BootSector->Oem[2] == 'F') && + (BootSector->Oem[3] == 'S') && + (BootSector->Oem[4] == ' ') && + (BootSector->Oem[5] == ' ') && + (BootSector->Oem[6] == ' ') && + (BootSector->Oem[7] == ' ')) { - DPRINT("FsRecDeviceIoControl() failed (Status %lx)\n", Status); - return(Status); + /* Fail */ + Result = FALSE; } - DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector); - Buffer = ExAllocatePool(NonPagedPool, - DiskGeometry.BytesPerSector); - if (Buffer == NULL) - { - return(STATUS_INSUFFICIENT_RESOURCES); - } - - Status = FsRecReadSectors(DeviceObject, - 0, /* Partition boot sector */ - 1, - DiskGeometry.BytesPerSector, - Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT("FsRecReadSectors() failed (Status %lx)\n", Status); - ExFreePool(Buffer); - return(Status); - } - - DPRINT("NTFS-identifier: [%.8s]\n", &Buffer[3]); - if (RtlCompareMemory(&Buffer[3], "NTFS ", 8) == 8) - { - Status = STATUS_SUCCESS; - } - else - { - Status = STATUS_UNRECOGNIZED_VOLUME; - } - - ExFreePool(Buffer); - - return(Status); + /* Return the result */ + return Result; } - NTSTATUS +NTAPI FsRecNtfsFsControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) + IN PIRP Irp) { - PIO_STACK_LOCATION Stack; - static UNICODE_STRING RegistryPath = - RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Ntfs"); - NTSTATUS Status; + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + PDEVICE_OBJECT MountDevice; + PPACKED_BOOT_SECTOR Bpb = NULL; + ULONG SectorSize; + LARGE_INTEGER Offset = {{0}}, Offset2, Offset3, SectorCount; + PAGED_CODE(); - Stack = IoGetCurrentIrpStackLocation(Irp); - - switch (Stack->MinorFunction) + /* Get the I/O Stack and check the function type */ + Stack = IoGetCurrentIrpStackLocation(Irp); + switch (Stack->MinorFunction) { - case IRP_MN_MOUNT_VOLUME: - DPRINT("NTFS: IRP_MN_MOUNT_VOLUME\n"); + case IRP_MN_MOUNT_VOLUME: - Status = FsRecIsNtfsVolume(Stack->Parameters.MountVolume.DeviceObject); - if (NT_SUCCESS(Status)) - { - DPRINT("Identified NTFS volume\n"); - Status = STATUS_FS_DRIVER_REQUIRED; - } - break; + /* Assume failure */ + Status = STATUS_UNRECOGNIZED_VOLUME; - case IRP_MN_LOAD_FILE_SYSTEM: - DPRINT("NTFS: IRP_MN_LOAD_FILE_SYSTEM\n"); - Status = ZwLoadDriver(&RegistryPath); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwLoadDriver failed (Status %x)\n", Status); - } - else - { - IoUnregisterFileSystem(DeviceObject); - } - break; + /* Get the device object and request the sector size */ + MountDevice = Stack->Parameters.MountVolume.DeviceObject; + if ((FsRecGetDeviceSectorSize(MountDevice, &SectorSize)) && + (FsRecGetDeviceSectors(MountDevice, SectorSize, &SectorCount))) + { + /* Setup other offsets to try */ + Offset2.QuadPart = SectorCount.QuadPart >> 1; + Offset2.QuadPart *= SectorSize; + Offset3.QuadPart = (SectorCount.QuadPart - 1) * SectorSize; - default: - DPRINT("NTFS: Unknown minor function %lx\n", Stack->MinorFunction); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; + /* Try to read the BPB */ + if (FsRecReadBlock(MountDevice, + &Offset, + 512, + SectorSize, + (PVOID)&Bpb, + NULL)) + { + /* Check if it's an actual FAT volume */ + if (FsRecIsNtfsVolume(Bpb, SectorSize, &SectorCount)) + { + /* It is! */ + Status = STATUS_FS_DRIVER_REQUIRED; + } + } + else if (FsRecReadBlock(MountDevice, + &Offset2, + 512, + SectorSize, + (PVOID)&Bpb, + NULL)) + { + /* Check if it's an actual FAT volume */ + if (FsRecIsNtfsVolume(Bpb, SectorSize, &SectorCount)) + { + /* It is! */ + Status = STATUS_FS_DRIVER_REQUIRED; + } + } + else if (FsRecReadBlock(MountDevice, + &Offset3, + 512, + SectorSize, + (PVOID)&Bpb, + NULL)) + { + /* Check if it's an actual FAT volume */ + if (FsRecIsNtfsVolume(Bpb, SectorSize, &SectorCount)) + { + /* It is! */ + Status = STATUS_FS_DRIVER_REQUIRED; + } + } + + /* Free the boot sector if we have one */ + ExFreePool(Bpb); + } + break; + + case IRP_MN_LOAD_FILE_SYSTEM: + + /* Load the file system */ + Status = FsRecLoadFileSystem(DeviceObject, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Ntfs"); + break; + + default: + + /* Invalid request */ + Status = STATUS_INVALID_DEVICE_REQUEST; } - return(Status); + + /* Return Status */ + return Status; } /* EOF */ diff --git a/reactos/drivers/filesystems/fs_rec/udfs.c b/reactos/drivers/filesystems/fs_rec/udfs.c index cf9e10cb5ed..d9f611e5980 100644 --- a/reactos/drivers/filesystems/fs_rec/udfs.c +++ b/reactos/drivers/filesystems/fs_rec/udfs.c @@ -1,295 +1,149 @@ -/* - * ReactOS kernel - * Copyright (C) 2003 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/fs/fs_rec/udfs.c - * PURPOSE: Filesystem recognizer driver - * PROGRAMMER: Eric Kohl + * PROJECT: ReactOS File System Recognizer + * FILE: drivers/filesystems/fs_rec/udfs.c + * PURPOSE: USFS Recognizer + * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) + * Eric Kohl */ /* INCLUDES *****************************************************************/ +#include "fs_rec.h" #define NDEBUG #include -#include "fs_rec.h" - - -#define UDFS_VRS_START_SECTOR 16 -#define UDFS_AVDP_SECTOR 256 - -/* TYPES ********************************************************************/ - -#include - -typedef struct _TAG -{ - USHORT Identifier; - USHORT Version; - UCHAR Checksum; - UCHAR Reserved; - USHORT SerialNumber; - USHORT Crc; - USHORT CrcLength; - ULONG Location; -} TAG, *PTAG; - -typedef struct _EXTENT -{ - ULONG Length; - ULONG Location; -} EXTENT, *PEXTENT; - -typedef struct _AVDP -{ - TAG DescriptorTag; - EXTENT MainVolumeDescriptorExtent; - EXTENT ReserveVolumeDescriptorExtent; -} AVDP, *PAVDP; - -#include - - /* FUNCTIONS ****************************************************************/ -static NTSTATUS -FsRecCheckVolumeRecognitionSequence(IN PDEVICE_OBJECT DeviceObject, - IN ULONG SectorSize) +BOOLEAN +NTAPI +FsRecIsUdfsVolume(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize) { - PUCHAR Buffer; - ULONG Sector; - NTSTATUS Status; - ULONG State; + PUCHAR Buffer = NULL; + LARGE_INTEGER Offset; + ULONG State = 0; - Buffer = ExAllocatePool(NonPagedPool, - SectorSize); - if (Buffer == NULL) + Offset.QuadPart = UDFS_VRS_START_SECTOR; + while (TRUE) { - return(STATUS_INSUFFICIENT_RESOURCES); + if (!FsRecReadBlock(DeviceObject, + &Offset, + 512, + SectorSize, + (PVOID)&Buffer, + NULL)) + { + break; + } + + switch (State) + { + case 0: + + if ((Offset.QuadPart == UDFS_VRS_START_SECTOR) && + (Buffer[1] == 'B') && + (Buffer[2] == 'E') && + (Buffer[3] == 'A') && + (Buffer[4] == '0') && + (Buffer[5] == '1')) + { + State = 1; + } + else + { + ExFreePool(Buffer); + return FALSE; + } + break; + + case 1: + + if ((Buffer[1] == 'N') && + (Buffer[2] == 'S') && + (Buffer[3] == 'R') && + (Buffer[4] == '0') && + ((Buffer[5] == '2') || (Buffer[5] == '3'))) + { + State = 2; + } + break; + + case 2: + + if ((Buffer[1] == 'T') && + (Buffer[2] == 'E') && + (Buffer[3] == 'A') && + (Buffer[4] == '0') && + (Buffer[5] == '1')) + { + ExFreePool(Buffer); + return TRUE; + } + break; + } + + Offset.QuadPart++; + if (Offset.QuadPart == UDFS_AVDP_SECTOR) + { + ExFreePool(Buffer); + return FALSE; + } } - State = 0; - Sector = UDFS_VRS_START_SECTOR; - while (TRUE) - { - Status = FsRecReadSectors(DeviceObject, - Sector, - 1, - SectorSize, - Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT ("FsRecReadSectors() failed (Status %lx)\n", Status); - break; - } - - DPRINT ("Descriptor identifier: [%.5s]\n", Buffer + 1); - - switch (State) - { - case 0: - if ((Sector == UDFS_VRS_START_SECTOR) && - (Buffer[1] == 'B') && - (Buffer[2] == 'E') && - (Buffer[3] == 'A') && - (Buffer[4] == '0') && - (Buffer[5] == '1')) - { - State = 1; - } - else - { - DPRINT ("VRS start sector is not 'BEA01'\n"); - ExFreePool(Buffer); - return(STATUS_UNRECOGNIZED_VOLUME); - } - break; - - case 1: - if ((Buffer[1] == 'N') && - (Buffer[2] == 'S') && - (Buffer[3] == 'R') && - (Buffer[4] == '0') && - ((Buffer[5] == '2') || (Buffer[5] == '3'))) - { - State = 2; - } - break; - - case 2: - if ((Buffer[1] == 'T') && - (Buffer[2] == 'E') && - (Buffer[3] == 'A') && - (Buffer[4] == '0') && - (Buffer[5] == '1')) - { - DPRINT ("Found 'TEA01'\n"); - ExFreePool(Buffer); - return(STATUS_SUCCESS); - } - break; - } - - Sector++; - if (Sector == UDFS_AVDP_SECTOR) - { - DPRINT ("No 'TEA01' found\n"); - ExFreePool(Buffer); - return(STATUS_UNRECOGNIZED_VOLUME); - } - } - - ExFreePool(Buffer); - - return(STATUS_UNRECOGNIZED_VOLUME); + ExFreePool(Buffer); + return TRUE; } - -static NTSTATUS -FsRecCheckAnchorVolumeDescriptorPointer(IN PDEVICE_OBJECT DeviceObject, - IN ULONG SectorSize) -{ - PUCHAR Buffer; - ULONG Sector; - NTSTATUS Status; - PAVDP Avdp; - - Buffer = ExAllocatePool(NonPagedPool, - SectorSize); - if (Buffer == NULL) - { - return(STATUS_INSUFFICIENT_RESOURCES); - } - - Sector = UDFS_AVDP_SECTOR; - Status = FsRecReadSectors(DeviceObject, - Sector, - 1, - SectorSize, - Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT ("FsRecReadSectors() failed (Status %lx)\n", Status); - ExFreePool(Buffer); - return(Status); - } - - Avdp = (PAVDP)Buffer; - DPRINT ("Descriptor identifier: %hu\n", Avdp->DescriptorTag.Identifier); - - DPRINT ("Main volume descriptor sequence location: %lu\n", - Avdp->MainVolumeDescriptorExtent.Location); - - DPRINT ("Main volume descriptor sequence length: %lu\n", - Avdp->MainVolumeDescriptorExtent.Length); - - DPRINT ("Reserve volume descriptor sequence location: %lu\n", - Avdp->ReserveVolumeDescriptorExtent.Location); - - DPRINT ("Reserve volume descriptor sequence length: %lu\n", - Avdp->ReserveVolumeDescriptorExtent.Length); - - ExFreePool(Buffer); - -// return(Status); - return(STATUS_SUCCESS); -} - - -static NTSTATUS -FsRecIsUdfsVolume(IN PDEVICE_OBJECT DeviceObject) -{ - DISK_GEOMETRY DiskGeometry; - ULONG Size; - NTSTATUS Status; - - Size = sizeof(DISK_GEOMETRY); - Status = FsRecDeviceIoControl(DeviceObject, - IOCTL_CDROM_GET_DRIVE_GEOMETRY, - NULL, - 0, - &DiskGeometry, - &Size); - if (!NT_SUCCESS(Status)) - { - DPRINT ("FsRecDeviceIoControl() failed (Status %lx)\n", Status); - return(Status); - } - - /* Check the volume recognition sequence */ - Status = FsRecCheckVolumeRecognitionSequence(DeviceObject, - DiskGeometry.BytesPerSector); - if (!NT_SUCCESS(Status)) - return(Status); - - Status = FsRecCheckAnchorVolumeDescriptorPointer(DeviceObject, - DiskGeometry.BytesPerSector); - if (!NT_SUCCESS(Status)) - return(Status); - - return(STATUS_SUCCESS); -} - - NTSTATUS +NTAPI FsRecUdfsFsControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) + IN PIRP Irp) { - PIO_STACK_LOCATION Stack; - static UNICODE_STRING RegistryPath = - RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Udfs"); - NTSTATUS Status; + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + PDEVICE_OBJECT MountDevice; + ULONG SectorSize; + PAGED_CODE(); - Stack = IoGetCurrentIrpStackLocation(Irp); - - switch (Stack->MinorFunction) + /* Get the I/O Stack and check the function type */ + Stack = IoGetCurrentIrpStackLocation(Irp); + switch (Stack->MinorFunction) { - case IRP_MN_MOUNT_VOLUME: - DPRINT("Udfs: IRP_MN_MOUNT_VOLUME\n"); - Status = FsRecIsUdfsVolume(Stack->Parameters.MountVolume.DeviceObject); - if (NT_SUCCESS(Status)) - { - DPRINT("Identified UDFS volume\n"); - Status = STATUS_FS_DRIVER_REQUIRED; - } - break; + case IRP_MN_MOUNT_VOLUME: - case IRP_MN_LOAD_FILE_SYSTEM: - DPRINT("Udfs: IRP_MN_LOAD_FILE_SYSTEM\n"); - Status = ZwLoadDriver(&RegistryPath); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwLoadDriver failed (Status %x)\n", Status); - } - else - { - IoUnregisterFileSystem(DeviceObject); - } - break; + /* Assume failure */ + Status = STATUS_UNRECOGNIZED_VOLUME; - default: - DPRINT("Udfs: Unknown minor function %lx\n", Stack->MinorFunction); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; + /* Get the device object and request the sector size */ + MountDevice = Stack->Parameters.MountVolume.DeviceObject; + if (FsRecGetDeviceSectorSize(MountDevice, &SectorSize)) + { + /* Check if it's an actual FAT volume */ + if (FsRecIsUdfsVolume(MountDevice, SectorSize)) + { + /* It is! */ + Status = STATUS_FS_DRIVER_REQUIRED; + } + } + + break; + + case IRP_MN_LOAD_FILE_SYSTEM: + + /* Load the file system */ + Status = FsRecLoadFileSystem(DeviceObject, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Udfs"); + break; + + default: + + /* Invalid request */ + Status = STATUS_INVALID_DEVICE_REQUEST; } - return(Status); + + /* Return Status */ + return Status; } /* EOF */