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