fsctl.c
来自「一个类似windows」· C语言 代码 · 共 928 行 · 第 1/3 页
C
928 行
/*
* 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: drivers/fs/vfat/fsctl.c
* PURPOSE: VFAT Filesystem
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "vfat.h"
/* FUNCTIONS ****************************************************************/
#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \
(pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE)
#define VOLUME_IS_DIRTY 0x00000001
static NTSTATUS
VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
PBOOLEAN RecognizedFS,
PFATINFO pFatInfo)
{
NTSTATUS Status;
PARTITION_INFORMATION PartitionInfo;
DISK_GEOMETRY DiskGeometry;
FATINFO FatInfo;
ULONG Size;
ULONG Sectors;
LARGE_INTEGER Offset;
struct _BootSector* Boot;
struct _BootSectorFatX* BootFatX;
BOOLEAN PartitionInfoIsValid = FALSE;
DPRINT("VfatHasFileSystem\n");
*RecognizedFS = FALSE;
Size = sizeof(DISK_GEOMETRY);
Status = VfatBlockDeviceIoControl(DeviceToMount,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&DiskGeometry,
&Size,
FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
return Status;
}
FatInfo.FixedMedia = DiskGeometry.MediaType == FixedMedia ? TRUE : FALSE;
if (DiskGeometry.MediaType == FixedMedia || DiskGeometry.MediaType == RemovableMedia)
{
// We have found a hard disk
Size = sizeof(PARTITION_INFORMATION);
Status = VfatBlockDeviceIoControl(DeviceToMount,
IOCTL_DISK_GET_PARTITION_INFO,
NULL,
0,
&PartitionInfo,
&Size,
FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
return Status;
}
PartitionInfoIsValid = TRUE;
DPRINT("Partition Information:\n");
DPRINT("StartingOffset %u\n", PartitionInfo.StartingOffset.QuadPart / 512);
DPRINT("PartitionLength %u\n", PartitionInfo.PartitionLength.QuadPart / 512);
DPRINT("HiddenSectors %u\n", PartitionInfo.HiddenSectors);
DPRINT("PartitionNumber %u\n", PartitionInfo.PartitionNumber);
DPRINT("PartitionType %u\n", PartitionInfo.PartitionType);
DPRINT("BootIndicator %u\n", PartitionInfo.BootIndicator);
DPRINT("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition);
DPRINT("RewritePartition %u\n", PartitionInfo.RewritePartition);
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;
}
}
else if (DiskGeometry.MediaType == Unknown)
{
/*
* Floppy disk driver can return Unknown as media type if it
* doesn't know yet what floppy in the drive really is. This is
* perfectly correct to do under Windows.
*/
*RecognizedFS = TRUE;
DiskGeometry.BytesPerSector = 512;
}
else
{
*RecognizedFS = TRUE;
}
if (*RecognizedFS)
{
Boot = ExAllocatePool(NonPagedPool, DiskGeometry.BytesPerSector);
if (Boot == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Offset.QuadPart = 0;
/* Try to recognize FAT12/FAT16/FAT32 partitions */
Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot, FALSE);
if (NT_SUCCESS(Status))
{
if (Boot->Signatur1 != 0xaa55)
{
*RecognizedFS = FALSE;
}
if (*RecognizedFS &&
Boot->BytesPerSector != 512 &&
Boot->BytesPerSector != 1024 &&
Boot->BytesPerSector != 2048 &&
Boot->BytesPerSector != 4096)
{
DPRINT1("BytesPerSector %d\n", Boot->BytesPerSector);
*RecognizedFS = FALSE;
}
if (*RecognizedFS &&
Boot->FATCount != 1 &&
Boot->FATCount != 2)
{
DPRINT1("FATCount %d\n", Boot->FATCount);
*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)
{
DPRINT1("Media %02x\n", Boot->Media);
*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)
{
DPRINT1("SectorsPerCluster %02x\n", Boot->SectorsPerCluster);
*RecognizedFS = FALSE;
}
if (*RecognizedFS &&
Boot->BytesPerSector * Boot->SectorsPerCluster > 32 * 1024)
{
DPRINT1("ClusterSize %dx\n", Boot->BytesPerSector * Boot->SectorsPerCluster);
*RecognizedFS = FALSE;
}
if (*RecognizedFS)
{
FatInfo.VolumeID = Boot->VolumeID;
FatInfo.FATStart = Boot->ReservedSectors;
FatInfo.FATCount = Boot->FATCount;
FatInfo.FATSectors = Boot->FATSectors ? Boot->FATSectors : ((struct _BootSector32*) Boot)->FATSectors32;
FatInfo.BytesPerSector = Boot->BytesPerSector;
FatInfo.SectorsPerCluster = Boot->SectorsPerCluster;
FatInfo.BytesPerCluster = FatInfo.BytesPerSector * FatInfo.SectorsPerCluster;
FatInfo.rootDirectorySectors = ((Boot->RootEntries * 32) + Boot->BytesPerSector - 1) / Boot->BytesPerSector;
FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
FatInfo.Sectors = Sectors = Boot->Sectors ? Boot->Sectors : Boot->SectorsHuge;
Sectors -= Boot->ReservedSectors + FatInfo.FATCount * FatInfo.FATSectors + FatInfo.rootDirectorySectors;
FatInfo.NumberOfClusters = Sectors / Boot->SectorsPerCluster;
if (FatInfo.NumberOfClusters < 4085)
{
DPRINT("FAT12\n");
FatInfo.FatType = FAT12;
FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
}
else if (FatInfo.NumberOfClusters >= 65525)
{
DPRINT("FAT32\n");
FatInfo.FatType = FAT32;
FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster;
FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster);
FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID;
}
else
{
DPRINT("FAT16\n");
FatInfo.FatType = FAT16;
FatInfo.RootCluster = FatInfo.rootStart / FatInfo.SectorsPerCluster;
}
if (PartitionInfoIsValid &&
FatInfo.Sectors > PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector)
{
CHECKPOINT1;
*RecognizedFS = FALSE;
}
if (pFatInfo && *RecognizedFS)
{
*pFatInfo = FatInfo;
}
}
}
ExFreePool(Boot);
}
if (!*RecognizedFS && PartitionInfoIsValid)
{
BootFatX = ExAllocatePool(NonPagedPool, sizeof(struct _BootSectorFatX));
if (BootFatX == NULL)
{
*RecognizedFS=FALSE;
return STATUS_INSUFFICIENT_RESOURCES;
}
Offset.QuadPart = 0;
/* Try to recognize FATX16/FATX32 partitions (Xbox) */
Status = VfatReadDisk(DeviceToMount, &Offset, sizeof(struct _BootSectorFatX), (PUCHAR) BootFatX, FALSE);
if (NT_SUCCESS(Status))
{
*RecognizedFS = TRUE;
if (BootFatX->SysType[0] != 'F' ||
BootFatX->SysType[1] != 'A' ||
BootFatX->SysType[2] != 'T' ||
BootFatX->SysType[3] != 'X')
{
DPRINT1("SysType %c%c%c%c\n", BootFatX->SysType[0], BootFatX->SysType[1], BootFatX->SysType[2], BootFatX->SysType[3]);
*RecognizedFS=FALSE;
}
if (*RecognizedFS &&
BootFatX->SectorsPerCluster != 1 &&
BootFatX->SectorsPerCluster != 2 &&
BootFatX->SectorsPerCluster != 4 &&
BootFatX->SectorsPerCluster != 8 &&
BootFatX->SectorsPerCluster != 16 &&
BootFatX->SectorsPerCluster != 32 &&
BootFatX->SectorsPerCluster != 64 &&
BootFatX->SectorsPerCluster != 128)
{
DPRINT1("SectorsPerCluster %lu\n", BootFatX->SectorsPerCluster);
*RecognizedFS=FALSE;
}
if (*RecognizedFS)
{
FatInfo.BytesPerSector = DiskGeometry.BytesPerSector;
FatInfo.SectorsPerCluster = BootFatX->SectorsPerCluster;
FatInfo.rootDirectorySectors = BootFatX->SectorsPerCluster;
FatInfo.BytesPerCluster = BootFatX->SectorsPerCluster * DiskGeometry.BytesPerSector;
FatInfo.Sectors = (ULONG)(PartitionInfo.PartitionLength.QuadPart / DiskGeometry.BytesPerSector);
if (FatInfo.Sectors / FatInfo.SectorsPerCluster < 65525)
{
DPRINT("FATX16\n");
FatInfo.FatType = FATX16;
}
else
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?