- Refactored some parts of the FS Recognizer Driver.

- Added support for some more advanced storage stack support.
- Added locking and states.
- Added the ability for a file system to span across different device types (such as UDFS which is both for disks and optical media)
- Updated NTFS, UDFS validation to use new functions. CDFS validation was removed (NT doesn't do it).
- Improved some parts of FAT validation and relaxed others to match NT's.

svn path=/trunk/; revision=26266
This commit is contained in:
Alex Ionescu 2007-04-05 00:11:35 +00:00
parent fe6c48c65b
commit dd73f432c2
7 changed files with 1157 additions and 1113 deletions

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS File System Recognizer
* FILE: services/fs/fs_rec/blockdev.c * FILE: drivers/filesystems/fs_rec/blockdev.c
* PURPOSE: Filesystem recognizer driver * PURPOSE: Generic Helper Functions
* PROGRAMMER: Eric Kohl * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "fs_rec.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#include "fs_rec.h"
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
NTSTATUS BOOLEAN
FsRecReadSectors(IN PDEVICE_OBJECT DeviceObject, NTAPI
IN ULONG DiskSector, FsRecGetDeviceSectors(IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorCount, IN ULONG SectorSize,
IN ULONG SectorSize, OUT PLARGE_INTEGER SectorCount)
IN OUT PUCHAR Buffer)
{ {
IO_STATUS_BLOCK IoStatus; PARTITION_INFORMATION PartitionInfo;
LARGE_INTEGER Offset; IO_STATUS_BLOCK IoStatusBlock;
ULONG BlockSize; KEVENT Event;
PKEVENT Event; PIRP Irp;
PIRP Irp; NTSTATUS Status;
NTSTATUS Status; ULONG Remainder;
PAGED_CODE();
Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); /* Only needed for disks */
if (Event == NULL) 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, /* Fail if we couldn't get the data */
NotificationEvent, if (!NT_SUCCESS(Status)) return FALSE;
FALSE);
Offset.QuadPart = (LONGLONG)DiskSector * (LONGLONG)SectorSize; /* Otherwise, return the number of sectors */
BlockSize = SectorCount * SectorSize; *SectorCount = RtlExtendedLargeIntegerDivide(PartitionInfo.PartitionLength,
SectorSize,
DPRINT("FsrecReadSectors(DeviceObject %x, DiskSector %d, Buffer %x)\n", &Remainder);
DeviceObject, DiskSector, Buffer); return TRUE;
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);
} }
BOOLEAN
NTSTATUS NTAPI
FsRecDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, FsRecGetDeviceSectorSize(IN PDEVICE_OBJECT DeviceObject,
IN ULONG ControlCode, OUT PULONG SectorSize)
IN PVOID InputBuffer,
IN ULONG InputBufferSize,
IN OUT PVOID OutputBuffer,
IN OUT PULONG OutputBufferSize)
{ {
ULONG BufferSize = 0; DISK_GEOMETRY DiskGeometry;
PKEVENT Event; IO_STATUS_BLOCK IoStatusBlock;
PIRP Irp; KEVENT Event;
IO_STATUS_BLOCK IoStatus; PIRP Irp;
NTSTATUS Status; 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)); /* Build the information IRP */
if (Event == NULL) 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"); /* Return the sector size if it's valid */
Irp = IoBuildDeviceIoControlRequest(ControlCode, if (!DiskGeometry.BytesPerSector) return FALSE;
DeviceObject, *SectorSize = DiskGeometry.BytesPerSector;
InputBuffer, return TRUE;
InputBufferSize, }
OutputBuffer,
BufferSize, BOOLEAN
FALSE, NTAPI
Event, FsRecReadBlock(IN PDEVICE_OBJECT DeviceObject,
&IoStatus); IN PLARGE_INTEGER Offset,
if (Irp == NULL) IN ULONG Length,
{ IN ULONG SectorSize,
DPRINT("IoBuildDeviceIoControlRequest() failed\n"); IN OUT PVOID *Buffer,
ExFreePool(Event); OUT PBOOLEAN DeviceError OPTIONAL)
return(STATUS_INSUFFICIENT_RESOURCES); {
} IO_STATUS_BLOCK IoStatusBlock;
KEVENT Event;
DPRINT("Calling IO Driver... with irp %x\n", Irp); PIRP Irp;
Status = IoCallDriver(DeviceObject, Irp); NTSTATUS Status;
if (Status == STATUS_PENDING) PAGED_CODE();
{
KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL); /* Assume failure */
Status = IoStatus.Status; if (DeviceError) *DeviceError = FALSE;
}
/* Check if the caller requested too little */
if (OutputBufferSize != NULL) if (Length < SectorSize)
{ {
*OutputBufferSize = IoStatus.Information; /* Read at least the sector size */
} Length = SectorSize;
}
ExFreePool(Event); else
{
return(Status); /* 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 */

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS File System Recognizer
* FILE: services/fs/fs_rec/cdfs.c * FILE: drivers/filesystems/fs_rec/cdfs.c
* PURPOSE: Filesystem recognizer driver * PURPOSE: CDFS Recognizer
* PROGRAMMER: Eric Kohl * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "fs_rec.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#include "fs_rec.h"
#define CDFS_PVD_SECTOR 16
/* FUNCTIONS ****************************************************************/ /* 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 NTSTATUS
NTAPI
FsRecCdfsFsControl(IN PDEVICE_OBJECT DeviceObject, FsRecCdfsFsControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) IN PIRP Irp)
{ {
PIO_STACK_LOCATION Stack; PIO_STACK_LOCATION Stack;
static UNICODE_STRING RegistryPath = NTSTATUS Status;
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Cdfs"); PAGED_CODE();
NTSTATUS Status;
Stack = IoGetCurrentIrpStackLocation(Irp); /* Get the I/O Stack and check the function type */
Stack = IoGetCurrentIrpStackLocation(Irp);
switch (Stack->MinorFunction) switch (Stack->MinorFunction)
{ {
case IRP_MN_MOUNT_VOLUME: 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_LOAD_FILE_SYSTEM: /* We don't validate */
DPRINT("Cdfs: IRP_MN_LOAD_FILE_SYSTEM\n"); Status = STATUS_FS_DRIVER_REQUIRED;
Status = ZwLoadDriver(&RegistryPath); break;
if (!NT_SUCCESS(Status))
{
DPRINT("ZwLoadDriver failed (Status %x)\n", Status);
}
else
{
IoUnregisterFileSystem(DeviceObject);
}
break;
default: case IRP_MN_LOAD_FILE_SYSTEM:
DPRINT("Cdfs: Unknown minor function %lx\n", Stack->MinorFunction);
Status = STATUS_INVALID_DEVICE_REQUEST; /* Load the file system */
break; 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 */ /* EOF */

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS File System Recognizer
* FILE: drivers/fs/fs_rec/vfat.c * FILE: drivers/filesystems/fs_rec/fat.c
* PURPOSE: Filesystem recognizer driver * PURPOSE: FAT Recognizer
* PROGRAMMER: Eric Kohl * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "fs_rec.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#include "fs_rec.h"
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
static NTSTATUS NTSTATUS
FsRecIsFatVolume(IN PDEVICE_OBJECT DeviceObject) NTAPI
FsRecIsFatVolume(IN PPACKED_BOOT_SECTOR PackedBootSector)
{ {
NTSTATUS Status; BIOS_PARAMETER_BLOCK Bpb;
PARTITION_INFORMATION PartitionInfo; BOOLEAN Result = TRUE;
DISK_GEOMETRY DiskGeometry; PAGED_CODE();
ULONG Size;
struct _BootSector* Boot;
BOOLEAN RecognizedFS = FALSE;
Size = sizeof(DISK_GEOMETRY);
Status = FsRecDeviceIoControl(DeviceObject, /* Unpack the BPB and do a small fix up */
IOCTL_DISK_GET_DRIVE_GEOMETRY, FatUnpackBios(&Bpb, &PackedBootSector->PackedBpb);
NULL, if (Bpb.Sectors) Bpb.LargeSectors = 0;
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;
}
if (PartitionInfo.PartitionType) /* Recognize jump */
{ if ((PackedBootSector->Jump[0] != 0x49) &&
if (PartitionInfo.PartitionType == PARTITION_FAT_12 || (PackedBootSector->Jump[0] != 0xE9) &&
PartitionInfo.PartitionType == PARTITION_FAT_16 || (PackedBootSector->Jump[0] != 0xEB))
PartitionInfo.PartitionType == PARTITION_HUGE || {
PartitionInfo.PartitionType == PARTITION_FAT32 || /* Fail */
PartitionInfo.PartitionType == PARTITION_FAT32_XINT13 || Result = FALSE;
PartitionInfo.PartitionType == PARTITION_XINT13) }
{ else if ((Bpb.BytesPerSector != 128) &&
RecognizedFS = TRUE; (Bpb.BytesPerSector != 256) &&
} (Bpb.BytesPerSector != 512) &&
} (Bpb.BytesPerSector != 1024) &&
else if (DiskGeometry.MediaType == RemovableMedia && (Bpb.BytesPerSector != 2048) &&
PartitionInfo.PartitionNumber > 0 && (Bpb.BytesPerSector != 4096))
PartitionInfo.StartingOffset.QuadPart == 0 && {
PartitionInfo.PartitionLength.QuadPart > 0) /* Fail */
{ Result = FALSE;
/* This is possible a removable media formated as super floppy */ }
RecognizedFS = TRUE; else if ((Bpb.SectorsPerCluster != 1) &&
} (Bpb.SectorsPerCluster != 2) &&
} (Bpb.SectorsPerCluster != 4) &&
if (DiskGeometry.MediaType > Unknown && DiskGeometry.MediaType < RemovableMedia ) (Bpb.SectorsPerCluster != 8) &&
{ (Bpb.SectorsPerCluster != 16) &&
RecognizedFS = TRUE; (Bpb.SectorsPerCluster != 32) &&
} (Bpb.SectorsPerCluster != 64) &&
if (RecognizedFS == FALSE) (Bpb.SectorsPerCluster != 128))
{ {
return STATUS_UNRECOGNIZED_VOLUME; /* 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); /* Return the result */
if (Boot == NULL) return Result;
{
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;
} }
NTSTATUS NTSTATUS
NTAPI
FsRecVfatFsControl(IN PDEVICE_OBJECT DeviceObject, FsRecVfatFsControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) IN PIRP Irp)
{ {
PIO_STACK_LOCATION Stack; PIO_STACK_LOCATION Stack;
static UNICODE_STRING RegistryPath = NTSTATUS Status;
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Vfatfs"); PDEVICE_OBJECT MountDevice;
NTSTATUS Status; PPACKED_BOOT_SECTOR Bpb = NULL;
ULONG SectorSize;
LARGE_INTEGER Offset = {{0}};
BOOLEAN DeviceError = FALSE;
PAGED_CODE();
Stack = IoGetCurrentIrpStackLocation(Irp); /* Get the I/O Stack and check the function type */
Stack = IoGetCurrentIrpStackLocation(Irp);
switch (Stack->MinorFunction) switch (Stack->MinorFunction)
{ {
case IRP_MN_MOUNT_VOLUME: 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_LOAD_FILE_SYSTEM: /* Assume failure */
DPRINT("FAT: IRP_MN_LOAD_FILE_SYSTEM\n"); Status = STATUS_UNRECOGNIZED_VOLUME;
Status = ZwLoadDriver(&RegistryPath);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwLoadDriver failed (Status %x)\n", Status);
}
else
{
IoUnregisterFileSystem(DeviceObject);
}
break;
default: /* Get the device object and request the sector size */
DPRINT("FAT: Unknown minor function %lx\n", Stack->MinorFunction); MountDevice = Stack->Parameters.MountVolume.DeviceObject;
Status = STATUS_INVALID_DEVICE_REQUEST; if (FsRecGetDeviceSectorSize(MountDevice, &SectorSize))
break; {
/* 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 */ /* EOF */

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS File System Recognizer
* FILE: drivers/fs/fs_rec/fs_rec.c * FILE: drivers/filesystems/fs_rec/fs_rec.c
* PURPOSE: Filesystem recognizer driver * PURPOSE: Main Driver Entrypoint and FS Registration
* PROGRAMMER: Eric Kohl * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "fs_rec.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#include "fs_rec.h" PKEVENT FsRecLoadSync;
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
static NTSTATUS STDCALL NTSTATUS
FsRecCreate(IN PDEVICE_OBJECT DeviceObject, NTAPI
IN PIRP Irp) 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();
/* Make sure we haven't already been called */
Status = STATUS_SUCCESS; if (DeviceExtension->State != Loaded)
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)
{ {
case FS_TYPE_VFAT: /* Acquire the load lock */
Status = FsRecVfatFsControl(DeviceObject, Irp); KeWaitForSingleObject(FsRecLoadSync,
break; Executive,
KernelMode,
FALSE,
NULL);
KeEnterCriticalRegion();
case FS_TYPE_NTFS: /* Make sure we're active */
Status = FsRecNtfsFsControl(DeviceObject, Irp); if (DeviceExtension->State == Pending)
break; {
/* Load the FS driver */
RtlInitUnicodeString(&DriverName, DriverServiceName);
Status = ZwLoadDriver(&DriverName);
case FS_TYPE_CDFS: /* Loop all the linked recognizer objects */
Status = FsRecCdfsFsControl(DeviceObject, Irp); while (DeviceExtension->State != Unloading)
break; {
/* Set them to the unload state */
DeviceExtension->State = Unloading;
case FS_TYPE_UDFS: /* Go to the next one */
Status = FsRecUdfsFsControl(DeviceObject, Irp); DeviceObject = DeviceExtension->Alternate;
break; DeviceExtension = DeviceObject->DeviceExtension;
}
}
default: /* Make sure that we haven't already loaded the FS */
Status = STATUS_INVALID_DEVICE_REQUEST; 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; /* Return */
IoCompleteRequest(Irp, return Status;
IO_NO_INCREMENT);
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) FsRecUnload(IN PDRIVER_OBJECT DriverObject)
{ {
PDEVICE_OBJECT NextDevice; PAGED_CODE();
PDEVICE_OBJECT ThisDevice;
/* Delete all remaining device objects */ /* Loop all driver device objects */
NextDevice = DriverObject->DeviceObject; while (DriverObject->DeviceObject)
while (NextDevice != NULL)
{ {
ThisDevice = NextDevice; /* Delete this device */
NextDevice = NextDevice->NextDevice; IoDeleteDevice(DriverObject->DeviceObject);
IoDeleteDevice(ThisDevice);
} }
/* Free the lock */
ExFreePool(FsRecLoadSync);
} }
NTSTATUS
static NTSTATUS STDCALL
FsRecRegisterFs(PDRIVER_OBJECT DriverObject, FsRecRegisterFs(IN PDRIVER_OBJECT DriverObject,
PCWSTR FsName, IN PDEVICE_OBJECT ParentObject OPTIONAL,
PCWSTR RecognizerName, OUT PDEVICE_OBJECT *NewDeviceObject OPTIONAL,
ULONG DeviceType, IN PCWSTR FsName,
ULONG FsType) IN PCWSTR RecognizerName,
IN ULONG FsType,
IN DEVICE_TYPE DeviceType)
{ {
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatus; IO_STATUS_BLOCK IoStatus;
PDEVICE_EXTENSION DeviceExt; PDEVICE_EXTENSION DeviceExtension;
UNICODE_STRING DeviceName; UNICODE_STRING DeviceName;
UNICODE_STRING FileName; PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT DeviceObject; HANDLE FileHandle;
HANDLE FileHandle; NTSTATUS Status;
NTSTATUS Status;
RtlInitUnicodeString(&FileName, /* Assume failure */
FsName); if (NewDeviceObject) *NewDeviceObject = NULL;
InitializeObjectAttributes(&ObjectAttributes, /* Setup the attributes */
&FileName, RtlInitUnicodeString(&DeviceName, FsName);
OBJ_CASE_INSENSITIVE, InitializeObjectAttributes(&ObjectAttributes,
0, &DeviceName,
NULL); OBJ_CASE_INSENSITIVE,
0,
NULL);
Status = ZwCreateFile(&FileHandle, /* Open the device */
0x100000, Status = ZwCreateFile(&FileHandle,
&ObjectAttributes, SYNCHRONIZE,
&IoStatus, &ObjectAttributes,
NULL, &IoStatus,
0, NULL,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
FILE_OPEN, FILE_SHARE_READ | FILE_SHARE_WRITE,
0, FILE_OPEN,
NULL, 0,
0); NULL,
if (NT_SUCCESS(Status)) 0);
if (NT_SUCCESS(Status))
{ {
ZwClose(FileHandle); /* We suceeded, close the handle */
return(STATUS_IMAGE_ALREADY_LOADED); 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 */ /* If we succeeded, there's no point in trying this again */
RtlInitUnicodeString(&DeviceName, if (NT_SUCCESS(Status)) return STATUS_IMAGE_ALREADY_LOADED;
RecognizerName);
Status = IoCreateDevice(DriverObject, /* Create recognizer device object */
sizeof(DEVICE_EXTENSION), RtlInitUnicodeString(&DeviceName, RecognizerName);
&DeviceName, Status = IoCreateDevice(DriverObject,
DeviceType, sizeof(DEVICE_EXTENSION),
0, &DeviceName,
FALSE, DeviceType,
&DeviceObject); 0,
FALSE,
if (NT_SUCCESS(Status)) &DeviceObject);
if (NT_SUCCESS(Status))
{ {
DeviceExt = DeviceObject->DeviceExtension; /* Get the device extension and set it up */
DeviceExt->FsType = FsType; DeviceExtension = DeviceObject->DeviceExtension;
IoRegisterFileSystem(DeviceObject); DeviceExtension->FsType = FsType;
DPRINT("Created recognizer device '%wZ'\n", &DeviceName); 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
NTSTATUS STDCALL NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject, DriverEntry(IN PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath) IN PUNICODE_STRING RegistryPath)
{ {
PCONFIGURATION_INFORMATION ConfigInfo; ULONG DeviceCount = 0;
ULONG DeviceCount; NTSTATUS Status;
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; /* Initialize it */
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecClose; KeInitializeEvent(FsRecLoadSync, SynchronizationEvent, TRUE);
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecClose;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl;
DriverObject->DriverUnload = FsRecUnload;
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) /* Register CDFS */
{ Status = FsRecRegisterFs(DriverObject,
Status = FsRecRegisterFs(DriverObject, NULL,
L"\\Cdfs", NULL,
L"\\FileSystem\\CdfsRecognizer", L"\\Cdfs",
FILE_DEVICE_CD_ROM_FILE_SYSTEM, L"\\FileSystem\\CdfsRecognizer",
FS_TYPE_CDFS); FS_TYPE_CDFS,
if (NT_SUCCESS(Status)) FILE_DEVICE_CD_ROM_FILE_SYSTEM);
{ if (NT_SUCCESS(Status)) DeviceCount++;
DeviceCount++;
}
Status = FsRecRegisterFs(DriverObject, /* Register UDFS for CDs */
L"\\Udfs", Status = FsRecRegisterFs(DriverObject,
L"\\FileSystem\\UdfsRecognizer", NULL,
FILE_DEVICE_CD_ROM_FILE_SYSTEM, &UdfsObject,
FS_TYPE_UDFS); L"\\UdfsCdRom",
if (NT_SUCCESS(Status)) L"\\FileSystem\\UdfsCdRomRecognizer",
{ FS_TYPE_UDFS,
DeviceCount++; FILE_DEVICE_CD_ROM_FILE_SYSTEM);
} if (NT_SUCCESS(Status)) DeviceCount++;
}
Status = FsRecRegisterFs(DriverObject, /* Register UDFS for HDDs */
L"\\Fat", Status = FsRecRegisterFs(DriverObject,
L"\\FileSystem\\FatRecognizer", UdfsObject,
FILE_DEVICE_DISK_FILE_SYSTEM, NULL,
FS_TYPE_VFAT); L"\\UdfsDisk",
if (NT_SUCCESS(Status)) L"\\FileSystem\\UdfsDiskRecognizer",
{ FS_TYPE_UDFS,
DeviceCount++; FILE_DEVICE_DISK_FILE_SYSTEM);
} if (NT_SUCCESS(Status)) DeviceCount++;
Status = FsRecRegisterFs(DriverObject, /* Register FAT */
L"\\Ntfs", Status = FsRecRegisterFs(DriverObject,
L"\\FileSystem\\NtfsRecognizer", NULL,
FILE_DEVICE_DISK_FILE_SYSTEM, NULL,
FS_TYPE_NTFS); L"\\Fat",
if (NT_SUCCESS(Status)) L"\\FileSystem\\FatRecognizer",
{ FS_TYPE_VFAT,
DeviceCount++; 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 */ /* EOF */

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS File System Recognizer
* FILE: drivers/fs/fs_rec/fs_rec.h * FILE: drivers/filesystems/fs_rec/fs_rec.h
* PURPOSE: Filesystem recognizer driver * PURPOSE: Main Header File
* PROGRAMMER: Eric Kohl * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
*/ */
//
// IFS Headers
//
#include <ntifs.h> #include <ntifs.h>
#include <ntdddisk.h> #include <ntdddisk.h>
#include <ntddcdrm.h> #include <ntddcdrm.h>
#include "helper.h"
#ifdef _MSC_VER //
#define STDCALL __stdcall // Tag for memory allocations
#endif //
#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 // Conversion types and macros taken from internal ntifs headers
#define FS_TYPE_NTFS 2 //
#define FS_TYPE_CDFS 3 typedef union _UCHAR1
#define FS_TYPE_UDFS 4
typedef struct _DEVICE_EXTENSION
{ {
ULONG FsType; UCHAR Uchar[1];
} DEVICE_EXTENSION, *PDEVICE_EXTENSION; 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 <pshpack1.h> #include <pshpack1.h>
struct _BootSector typedef struct _TAG
{ {
unsigned char magic0, res0, magic1; USHORT Identifier;
unsigned char OEMName[8]; USHORT Version;
unsigned short BytesPerSector; UCHAR Checksum;
unsigned char SectorsPerCluster; UCHAR Reserved;
unsigned short ReservedSectors; USHORT SerialNumber;
unsigned char FATCount; USHORT Crc;
unsigned short RootEntries, Sectors; USHORT CrcLength;
unsigned char Media; ULONG Location;
unsigned short FATSectors, SectorsPerTrack, Heads; } TAG, *PTAG;
unsigned long HiddenSectors, SectorsHuge;
unsigned char Drive, Res1, Sig; typedef struct _EXTENT
unsigned long VolumeID; {
unsigned char VolumeLabel[11], SysType[8]; ULONG Length;
unsigned char Res2[448]; ULONG Location;
unsigned short Signatur1; } EXTENT, *PEXTENT;
};
typedef struct _AVDP
{
TAG DescriptorTag;
EXTENT MainVolumeDescriptorExtent;
EXTENT ReserveVolumeDescriptorExtent;
} AVDP, *PAVDP;
#include <poppack.h> #include <poppack.h>
/* 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 NTSTATUS
FsRecReadSectors(IN PDEVICE_OBJECT DeviceObject, NTAPI
IN ULONG DiskSector, FsRecVfatFsControl(
IN ULONG SectorCount, IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize, IN PIRP Irp
IN OUT PUCHAR Buffer); );
NTSTATUS NTSTATUS
FsRecDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, NTAPI
IN ULONG ControlCode, FsRecNtfsFsControl(
IN PVOID InputBuffer, IN PDEVICE_OBJECT DeviceObject,
IN ULONG InputBufferSize, IN PIRP Irp
IN OUT PVOID OutputBuffer, );
IN OUT PULONG OutputBufferSize);
/* cdfs.c */
NTSTATUS NTSTATUS
FsRecCdfsFsControl(IN PDEVICE_OBJECT DeviceObject, NTAPI
IN PIRP Irp); 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 NTSTATUS
FsRecVfatFsControl(IN PDEVICE_OBJECT DeviceObject, NTAPI
IN PIRP Irp); FsRecLoadFileSystem(
IN PDEVICE_OBJECT DeviceObject,
IN PWCHAR DriverServiceName
/* 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 */

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS File System Recognizer
* FILE: drivers/fs/fs_rec/ntfs.c * FILE: drivers/filesystems/fs_rec/ntfs.c
* PURPOSE: Filesystem recognizer driver * PURPOSE: NTFS Recognizer
* PROGRAMMER: Eric Kohl * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "fs_rec.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#include "fs_rec.h"
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
static NTSTATUS BOOLEAN
FsRecIsNtfsVolume(IN PDEVICE_OBJECT DeviceObject) NTAPI
FsRecIsNtfsVolume(IN PPACKED_BOOT_SECTOR BootSector,
IN ULONG BytesPerSector,
IN PLARGE_INTEGER NumberOfSectors)
{ {
DISK_GEOMETRY DiskGeometry; PAGED_CODE();
PUCHAR Buffer; BOOLEAN Result;
ULONG Size;
NTSTATUS Status;
Size = sizeof(DISK_GEOMETRY); /* Assume success */
Status = FsRecDeviceIoControl(DeviceObject, Result = TRUE;
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL, if ((BootSector->Oem[0] == 'N') &&
0, (BootSector->Oem[1] == 'T') &&
&DiskGeometry, (BootSector->Oem[2] == 'F') &&
&Size); (BootSector->Oem[3] == 'S') &&
if (!NT_SUCCESS(Status)) (BootSector->Oem[4] == ' ') &&
(BootSector->Oem[5] == ' ') &&
(BootSector->Oem[6] == ' ') &&
(BootSector->Oem[7] == ' '))
{ {
DPRINT("FsRecDeviceIoControl() failed (Status %lx)\n", Status); /* Fail */
return(Status); Result = FALSE;
} }
DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector); /* Return the result */
Buffer = ExAllocatePool(NonPagedPool, return Result;
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);
} }
NTSTATUS NTSTATUS
NTAPI
FsRecNtfsFsControl(IN PDEVICE_OBJECT DeviceObject, FsRecNtfsFsControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) IN PIRP Irp)
{ {
PIO_STACK_LOCATION Stack; PIO_STACK_LOCATION Stack;
static UNICODE_STRING RegistryPath = NTSTATUS Status;
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Ntfs"); PDEVICE_OBJECT MountDevice;
NTSTATUS Status; PPACKED_BOOT_SECTOR Bpb = NULL;
ULONG SectorSize;
LARGE_INTEGER Offset = {{0}}, Offset2, Offset3, SectorCount;
PAGED_CODE();
Stack = IoGetCurrentIrpStackLocation(Irp); /* Get the I/O Stack and check the function type */
Stack = IoGetCurrentIrpStackLocation(Irp);
switch (Stack->MinorFunction) switch (Stack->MinorFunction)
{ {
case IRP_MN_MOUNT_VOLUME: case IRP_MN_MOUNT_VOLUME:
DPRINT("NTFS: IRP_MN_MOUNT_VOLUME\n");
Status = FsRecIsNtfsVolume(Stack->Parameters.MountVolume.DeviceObject); /* Assume failure */
if (NT_SUCCESS(Status)) Status = STATUS_UNRECOGNIZED_VOLUME;
{
DPRINT("Identified NTFS volume\n");
Status = STATUS_FS_DRIVER_REQUIRED;
}
break;
case IRP_MN_LOAD_FILE_SYSTEM: /* Get the device object and request the sector size */
DPRINT("NTFS: IRP_MN_LOAD_FILE_SYSTEM\n"); MountDevice = Stack->Parameters.MountVolume.DeviceObject;
Status = ZwLoadDriver(&RegistryPath); if ((FsRecGetDeviceSectorSize(MountDevice, &SectorSize)) &&
if (!NT_SUCCESS(Status)) (FsRecGetDeviceSectors(MountDevice, SectorSize, &SectorCount)))
{ {
DPRINT("ZwLoadDriver failed (Status %x)\n", Status); /* Setup other offsets to try */
} Offset2.QuadPart = SectorCount.QuadPart >> 1;
else Offset2.QuadPart *= SectorSize;
{ Offset3.QuadPart = (SectorCount.QuadPart - 1) * SectorSize;
IoUnregisterFileSystem(DeviceObject);
}
break;
default: /* Try to read the BPB */
DPRINT("NTFS: Unknown minor function %lx\n", Stack->MinorFunction); if (FsRecReadBlock(MountDevice,
Status = STATUS_INVALID_DEVICE_REQUEST; &Offset,
break; 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 */ /* EOF */

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS File System Recognizer
* FILE: drivers/fs/fs_rec/udfs.c * FILE: drivers/filesystems/fs_rec/udfs.c
* PURPOSE: Filesystem recognizer driver * PURPOSE: USFS Recognizer
* PROGRAMMER: Eric Kohl * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "fs_rec.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#include "fs_rec.h"
#define UDFS_VRS_START_SECTOR 16
#define UDFS_AVDP_SECTOR 256
/* TYPES ********************************************************************/
#include <pshpack1.h>
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 <poppack.h>
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
static NTSTATUS BOOLEAN
FsRecCheckVolumeRecognitionSequence(IN PDEVICE_OBJECT DeviceObject, NTAPI
IN ULONG SectorSize) FsRecIsUdfsVolume(IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize)
{ {
PUCHAR Buffer; PUCHAR Buffer = NULL;
ULONG Sector; LARGE_INTEGER Offset;
NTSTATUS Status; ULONG State = 0;
ULONG State;
Buffer = ExAllocatePool(NonPagedPool, Offset.QuadPart = UDFS_VRS_START_SECTOR;
SectorSize); while (TRUE)
if (Buffer == NULL)
{ {
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; ExFreePool(Buffer);
Sector = UDFS_VRS_START_SECTOR; return TRUE;
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);
} }
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 NTSTATUS
NTAPI
FsRecUdfsFsControl(IN PDEVICE_OBJECT DeviceObject, FsRecUdfsFsControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) IN PIRP Irp)
{ {
PIO_STACK_LOCATION Stack; PIO_STACK_LOCATION Stack;
static UNICODE_STRING RegistryPath = NTSTATUS Status;
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Udfs"); PDEVICE_OBJECT MountDevice;
NTSTATUS Status; ULONG SectorSize;
PAGED_CODE();
Stack = IoGetCurrentIrpStackLocation(Irp); /* Get the I/O Stack and check the function type */
Stack = IoGetCurrentIrpStackLocation(Irp);
switch (Stack->MinorFunction) switch (Stack->MinorFunction)
{ {
case IRP_MN_MOUNT_VOLUME: 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_LOAD_FILE_SYSTEM: /* Assume failure */
DPRINT("Udfs: IRP_MN_LOAD_FILE_SYSTEM\n"); Status = STATUS_UNRECOGNIZED_VOLUME;
Status = ZwLoadDriver(&RegistryPath);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwLoadDriver failed (Status %x)\n", Status);
}
else
{
IoUnregisterFileSystem(DeviceObject);
}
break;
default: /* Get the device object and request the sector size */
DPRINT("Udfs: Unknown minor function %lx\n", Stack->MinorFunction); MountDevice = Stack->Parameters.MountVolume.DeviceObject;
Status = STATUS_INVALID_DEVICE_REQUEST; if (FsRecGetDeviceSectorSize(MountDevice, &SectorSize))
break; {
/* 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 */ /* EOF */