VfatHasFileSystem函数主要用来读取FAT文件系统信息,并且判断这个磁盘卷是否为FAT文件系统,具体实现如下:
#001 static NTSTATUS
#002 VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
#003 PBOOLEAN RecognizedFS,
#004 PFATINFO pFatInfo)
#005 {
#006 NTSTATUS Status;
#007 PARTITION_INFORMATION PartitionInfo;
#008 DISK_GEOMETRY DiskGeometry;
#009 FATINFO FatInfo;
#010 ULONG Size;
#011 ULONG Sectors;
#012 LARGE_INTEGER Offset;
#013 struct _BootSector* Boot;
#014 struct _BootSectorFatX* BootFatX;
#015 BOOLEAN PartitionInfoIsValid = FALSE;
#016
#017 DPRINT("VfatHasFileSystem/n");
#018
设置返回结果为不认识这个FAT文件系统。
#019 *RecognizedFS = FALSE;
#020
#021 Size = sizeof(DISK_GEOMETRY);
#022 Status = VfatBlockDeviceIoControl(DeviceToMount,
#023 IOCTL_DISK_GET_DRIVE_GEOMETRY,
#024 NULL,
#025 0,
#026 &DiskGeometry,
#027 &Size,
#028 FALSE);
#029 if (!NT_SUCCESS(Status))
#030 {
#031 DPRINT("VfatBlockDeviceIoControl faild (%x)/n",Status);
#032 return Status;
#033 }
判断磁盘是否为固定媒介。
#034 FatInfo.FixedMedia = DiskGeometry.MediaType == FixedMedia ? TRUE : FALSE;
不管是固定的,还是移动的磁盘,反正就是找到了磁盘设备。
#035 if (DiskGeometry.MediaType == FixedMedia || DiskGeometry.MediaType == RemovableMedia)
#036 {
通过底层磁盘驱动程序获取磁盘分区信息。
#037 // We have found a hard disk
#038 Size = sizeof(PARTITION_INFORMATION);
#039 Status = VfatBlockDeviceIoControl(DeviceToMount,
#040 IOCTL_DISK_GET_PARTITION_INFO,
#041 NULL,
#042 0,
#043 &PartitionInfo,
#044 &Size,
#045 FALSE);
#046 if (!NT_SUCCESS(Status))
#047 {
#048 DPRINT("VfatBlockDeviceIoControl faild (%x)/n",Status);
#049 return Status;
#050 }
设置磁盘分区信息读取到有效数据。
#051 PartitionInfoIsValid = TRUE;
#052 DPRINT("Partition Information:/n");
#053 DPRINT("StartingOffset %u/n",PartitionInfo.StartingOffset.QuadPart / 512);
#054 DPRINT("PartitionLength %u/n",PartitionInfo.PartitionLength.QuadPart / 512);
#055 DPRINT("HiddenSectors %u/n",PartitionInfo.HiddenSectors);
#056 DPRINT("PartitionNumber %u/n",PartitionInfo.PartitionNumber);
#057 DPRINT("PartitionType %u/n",PartitionInfo.PartitionType);
#058 DPRINT("BootIndicator %u/n",PartitionInfo.BootIndicator);
#059 DPRINT("RecognizedPartition %u/n",PartitionInfo.RecognizedPartition);
#060 DPRINT("RewritePartition %u/n",PartitionInfo.RewritePartition);
根据磁盘格式类型来判断是否FAT驱动程序可以支持的文件系统类型。
#061 if (PartitionInfo.PartitionType)
#062 {
#063 if (PartitionInfo.PartitionType == PARTITION_FAT_12 ||
#064 PartitionInfo.PartitionType == PARTITION_FAT_16 ||
#065 PartitionInfo.PartitionType == PARTITION_HUGE ||
#066 PartitionInfo.PartitionType == PARTITION_FAT32 ||
#067 PartitionInfo.PartitionType == PARTITION_FAT32_XINT13 ||
#068 PartitionInfo.PartitionType == PARTITION_XINT13)
#069 {
#070 *RecognizedFS = TRUE;
#071 }
#072 }
#073 else if (DiskGeometry.MediaType == RemovableMedia &&
#074 PartitionInfo.PartitionNumber > 0 &&
#075 PartitionInfo.StartingOffset.QuadPart == 0 &&
#076 PartitionInfo.PartitionLength.QuadPart > 0)
#077 {
#078 /* This is possible a removable media formated as super floppy */
#079 *RecognizedFS = TRUE;
#080 }
#081 }
#082 else if (DiskGeometry.MediaType == Unknown)
#083 {
#084 /*
#085 * Floppy disk driver can return Unknown as media type if it
#086 * doesn't know yet what floppy in the drive really is. This is
#087 * perfectly correct to do under Windows.
#088 */
#089 *RecognizedFS = TRUE;
#090 DiskGeometry.BytesPerSector = 512;
#091 }
#092 else
#093 {
#094 *RecognizedFS = TRUE;
#095 }
#096 if (*RecognizedFS)
#097 {
#098
#099 Boot = ExAllocatePoolWithTag(NonPagedPool,DiskGeometry.BytesPerSector,TAG_VFAT);
#100 if (Boot == NULL)
#101 {
#102 return STATUS_INSUFFICIENT_RESOURCES;
#103 }
#104
#105 Offset.QuadPart = 0;
#106
读取FAT的引导扇区数据。
#107 /* Try to recognize FAT12/FAT16/FAT32 partitions */
#108 Status = VfatReadDisk(DeviceToMount,&Offset,(PUCHAR) Boot,FALSE);
如果读取成功,再进一步处理。
#109 if (NT_SUCCESS(Status))
#110 {
检验最后两个字节的标志是为0xaa55,如果不是,就是不认识的分区。
#111 if (Boot->Signatur1 != 0xaa55)
#112 {
#113 *RecognizedFS = FALSE;
#114 }
#115 if (*RecognizedFS &&
#116 Boot->BytesPerSector != 512 &&
#117 Boot->BytesPerSector != 1024 &&
#118 Boot->BytesPerSector != 2048 &&
#119 Boot->BytesPerSector != 4096)
#120 {
#121 DPRINT1("BytesPerSector %d/n",Boot->BytesPerSector);
#122 *RecognizedFS = FALSE;
#123 }
#124
#125 if (*RecognizedFS &&
#126 Boot->FATCount != 1 &&
#127 Boot->FATCount != 2)
#128 {
#129 DPRINT1("FATCount %d/n",Boot->FATCount);
#130 *RecognizedFS = FALSE;
#131 }
#132
#133 if (*RecognizedFS &&
#134 Boot->Media != 0xf0 &&
#135 Boot->Media != 0xf8 &&
#136 Boot->Media != 0xf9 &&
#137 Boot->Media != 0xfa &&
#138 Boot->Media != 0xfb &&
#139 Boot->Media != 0xfc &&
#140 Boot->Media != 0xfd &&
#141 Boot->Media != 0xfe &&
#142 Boot->Media != 0xff)
#143 {
#144 DPRINT1("Media %02x/n",Boot->Media);
#145 *RecognizedFS = FALSE;
#146 }
#147
每簇扇区大小,最多支持的个数。
#148 if (*RecognizedFS &&
#149 Boot->SectorsPerCluster != 1 &&
#150 Boot->SectorsPerCluster != 2 &&
#151 Boot->SectorsPerCluster != 4 &&
#152 Boot->SectorsPerCluster != 8 &&
#153 Boot->SectorsPerCluster != 16 &&
#154 Boot->SectorsPerCluster != 32 &&
#155 Boot->SectorsPerCluster != 64 &&
#156 Boot->SectorsPerCluster != 128)
#157 {
#158 DPRINT1("SectorsPerCluster %02x/n",Boot->SectorsPerCluster);
#159 *RecognizedFS = FALSE;
#160 }
#161
每簇支持最大的字节。
#162 if (*RecognizedFS &&
#163 Boot->BytesPerSector * Boot->SectorsPerCluster > 32 * 1024)
#164 {
#165 DPRINT1("ClusterSize %dx/n",Boot->BytesPerSector * Boot->SectorsPerCluster);
#166 *RecognizedFS = FALSE;
#167 }
#168
#169 if (*RecognizedFS)
#170 {
FAT卷标识号。
#171 FatInfo.VolumeID = Boot->VolumeID;
FAT的分配表的开始位置。
#172 FatInfo.FATStart = Boot->ReservedSectors;
FAT的分配表的个数。
#173 FatInfo.FATCount = Boot->FATCount;
#174 FatInfo.FATSectors = Boot->FATSectors ? Boot->FATSectors : ((struct _BootSector32*) Boot)->FATSectors32;
每扇区的多少字节。
#175 FatInfo.BytesPerSector = Boot->BytesPerSector;
每簇包括多少扇区。
#176 FatInfo.SectorsPerCluster = Boot->SectorsPerCluster;
每簇包括多少字节。
#177 FatInfo.BytesPerCluster = FatInfo.BytesPerSector * FatInfo.SectorsPerCluster;
根目录扇区数。
#178 FatInfo.rootDirectorySectors = ((Boot->RootEntries * 32) + Boot->BytesPerSector - 1) / Boot->BytesPerSector;
根目录开始位置。
#179 FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
FAT文件系统数据开始位置。
#180 FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
#181 FatInfo.Sectors = Sectors = Boot->Sectors ? Boot->Sectors : Boot->SectorsHuge;
计算分区里有多少簇。
#182 Sectors -= Boot->ReservedSectors + FatInfo.FATCount * FatInfo.FATSectors + FatInfo.rootDirectorySectors;
#183 FatInfo.NumberOfClusters = Sectors / Boot->SectorsPerCluster;
根据簇数大小来区分采用FAT12,还是FAT32等等。
#184 if (FatInfo.NumberOfClusters < 4085)
#185 {
#186 DPRINT("FAT12/n");
#187 FatInfo.FatType = FAT12;
#188 FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
#189 }
#190 else if (FatInfo.NumberOfClusters >= 65525)
#191 {
#192 DPRINT("FAT32/n");
#193 FatInfo.FatType = FAT32;
#194 FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster;
#195 FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster);
#196 FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID;
#197 }
#198 else
#199 {
#200 DPRINT("FAT16/n");
#201 FatInfo.FatType = FAT16;
#202 FatInfo.RootCluster = FatInfo.rootStart / FatInfo.SectorsPerCluster;
#203 }
#204 if (PartitionInfoIsValid &&
#205 FatInfo.Sectors > PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector)
#206 {
#207 *RecognizedFS = FALSE;
#208 }
#209
#210 if (pFatInfo && *RecognizedFS)
#211 {
#212 *pFatInfo = FatInfo;
#213 }
#214 }
#215 }
#216
#217 ExFreePool(Boot);
#218 }
#219
如果不认识的FAT文件系统,就进行下面的处理。
#220 if (!*RecognizedFS && PartitionInfoIsValid)
#221 {
#222 BootFatX = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _BootSectorFatX),TAG_VFAT);
#223 if (BootFatX == NULL)
#224 {
#225 *RecognizedFS=FALSE;
#226 return STATUS_INSUFFICIENT_RESOURCES;
#227 }
#228
#229 Offset.QuadPart = 0;
#230
扩展的FAT文件系统识别。
#231 /* Try to recognize FATX16/FATX32 partitions (XBox) */
#232 Status = VfatReadDisk(DeviceToMount,(PUCHAR) BootFatX,FALSE);
#233 if (NT_SUCCESS(Status))
#234 {
#235 *RecognizedFS = TRUE;
#236 if (BootFatX->SysType[0] != 'F' ||
#237 BootFatX->SysType[1] != 'A' ||
#238 BootFatX->SysType[2] != 'T' ||
#239 BootFatX->SysType[3] != 'X')
#240 {
#241 DPRINT1("SysType %c%c%c%c/n",BootFatX->SysType[0],BootFatX->SysType[1],BootFatX->SysType[2],BootFatX->SysType[3]);
#242 *RecognizedFS=FALSE;
#243 }
#244
#245 if (*RecognizedFS &&
#246 BootFatX->SectorsPerCluster != 1 &&
#247 BootFatX->SectorsPerCluster != 2 &&
#248 BootFatX->SectorsPerCluster != 4 &&
#249 BootFatX->SectorsPerCluster != 8 &&
#250 BootFatX->SectorsPerCluster != 16 &&
#251 BootFatX->SectorsPerCluster != 32 &&
#252 BootFatX->SectorsPerCluster != 64 &&
#253 BootFatX->SectorsPerCluster != 128)
#254 {
#255 DPRINT1("SectorsPerCluster %lu/n",BootFatX->SectorsPerCluster);
#256 *RecognizedFS=FALSE;
#257 }
#258
#259 if (*RecognizedFS)
#260 {
#261 FatInfo.BytesPerSector = DiskGeometry.BytesPerSector;
#262 FatInfo.SectorsPerCluster = BootFatX->SectorsPerCluster;
#263 FatInfo.rootDirectorySectors = BootFatX->SectorsPerCluster;
#264 FatInfo.BytesPerCluster = BootFatX->SectorsPerCluster * DiskGeometry.BytesPerSector;
#265 FatInfo.Sectors = (ULONG)(PartitionInfo.PartitionLength.QuadPart / DiskGeometry.BytesPerSector);
#266 if (FatInfo.Sectors / FatInfo.SectorsPerCluster < 65525)
#267 {
#268 DPRINT("FATX16/n");
#269 FatInfo.FatType = FATX16;
#270 }
#271 else
#272 {
#273 DPRINT("FATX32/n");
#274 FatInfo.FatType = FATX32;
#275 }
#276 FatInfo.VolumeID = BootFatX->VolumeID;
#277 FatInfo.FATStart = sizeof(struct _BootSectorFatX) / DiskGeometry.BytesPerSector;
#278 FatInfo.FATCount = BootFatX->FATCount;
#279 FatInfo.FATSectors =
#280 ROUND_UP(FatInfo.Sectors / FatInfo.SectorsPerCluster * (FatInfo.FatType == FATX16 ? 2 : 4),4096) /
#281 FatInfo.BytesPerSector;
#282 FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
#283 FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
#284 FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
#285 FatInfo.NumberOfClusters = (FatInfo.Sectors - FatInfo.dataStart) / FatInfo.SectorsPerCluster;
#286
#287 if (pFatInfo && *RecognizedFS)
#288 {
#289 *pFatInfo = FatInfo;
#290 }
#291 }
#292 }
#293 ExFreePool(BootFatX);
#294 }
#295
#296 DPRINT("VfatHasFileSystem done/n");
#297 return Status;
#298 }
#299