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 + -
显示快捷键?