mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
- 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:
parent
fe6c48c65b
commit
dd73f432c2
7 changed files with 1157 additions and 1113 deletions
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue