- 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
* 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 <debug.h>
#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 */

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
* 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 <debug.h>
#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 */

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
* 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 <debug.h>
#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 */

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
* 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 <debug.h>
#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 */

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
* 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 <ntifs.h>
#include <ntdddisk.h>
#include <ntddcdrm.h>
#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 <pshpack1.h>
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 <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
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
);

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
* 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 <debug.h>
#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 */

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
* 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 <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 ****************************************************************/
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 */