#include "imagpart.h" // // FAT boot sector. // #pragma pack(1) typedef struct FAT_BOOT_SECTOR { BYTE Jump[3]; // offset = 0x00 0 UCHAR Oem[8]; // offset = 0x03 3 USHORT BytesPerSector; // offset = 0x0b 11 BYTE SectorsPerCluster; // offset = 0x0d 13 USHORT ReservedSectors; // offset = 0x0e 14 BYTE Fats; // offset = 0x10 16 USHORT RootEntries; // offset = 0x11 17 USHORT Sectors; // offset = 0x13 19 BYTE Media; // offset = 0x15 21 USHORT SectorsPerFat; // offset = 0x16 22 USHORT SectorsPerTrack; // offset = 0x18 24 USHORT Heads; // offset = 0x1a 26 ULONG HiddenSectors; // offset = 0x1c 28 ULONG LargeSectors; // offset = 0x20 32 BYTE PhysicalDriveNumber; // offset = 0x24 36 BYTE Reserved; // offset = 0x25 37 BYTE Signature; // offset = 0x26 38 ULONG Id; // offset = 0x27 39 UCHAR VolumeLabel[11]; // offset = 0x2B 43 UCHAR SystemId[8]; // offset = 0x36 54 BYTE BootStrap[510-62]; // offset = 0x3e 62 BYTE AA55Signature[2]; // offset = 0x1fe 510 } FAT_BOOT_SECTOR,_far *FPFAT_BOOT_SECTOR; #pragma pack() typedef enum { Fat12, Fat16, Fat32 } FatSize; FatSize pFatDetermineFatSize( IN FPFAT_BOOT_SECTOR BootSector ); ULONG pFatClusterCount( IN FPFAT_BOOT_SECTOR BootSector ); ULONG pFatFirstClusterSector( IN FPFAT_BOOT_SECTOR BootSector ); ULONG pFatSectorsPerFat( IN FPFAT_BOOT_SECTOR BootSector ); BOOL FatIsFat( IN HPARTITION PartitionHandle ) { FPFAT_BOOT_SECTOR BootSector; if(!ReadPartition(PartitionHandle,0,1,IoBuffer)) { return(FALSE); } BootSector = IoBuffer; if(BootSector->Sectors) { BootSector->LargeSectors = 0; } // // Check various fields for permissible values. // if((BootSector->Jump[0] != 0x49) // Fujitsu FMR && (BootSector->Jump[0] != 0xe9) && (BootSector->Jump[0] != 0xeb)) { return(FALSE); } if(BootSector->BytesPerSector != 512) { return(FALSE); } if((BootSector->SectorsPerCluster != 1) && (BootSector->SectorsPerCluster != 2) && (BootSector->SectorsPerCluster != 4) && (BootSector->SectorsPerCluster != 8) && (BootSector->SectorsPerCluster != 16) && (BootSector->SectorsPerCluster != 32) && (BootSector->SectorsPerCluster != 64) && (BootSector->SectorsPerCluster != 128)) { return(FALSE); } if(!BootSector->ReservedSectors || !BootSector->Fats) { return(FALSE); } if(!BootSector->Sectors && !BootSector->LargeSectors) { return(FALSE); } if((BootSector->Media != 0x00) // FMR (formatted by OS/2) && (BootSector->Media != 0x01) // FMR (floppy, formatted by DOS) && (BootSector->Media != 0xf0) && (BootSector->Media != 0xf8) && (BootSector->Media != 0xf9) && (BootSector->Media != 0xfa) // FMR && (BootSector->Media != 0xfb) && (BootSector->Media != 0xfc) && (BootSector->Media != 0xfd) && (BootSector->Media != 0xfe) && (BootSector->Media != 0xff)) { return(FALSE); } if(BootSector->SectorsPerFat && !BootSector->RootEntries) { return(FALSE); } return(TRUE); } BOOL FatInitializeVolumeData( IN HPARTITION PartitionHandle, OUT ULONG *TotalSectorCount, OUT ULONG *NonClusterSectors, OUT ULONG *ClusterCount, OUT BYTE *SectorsPerCluster ) { FPFAT_BOOT_SECTOR BootSector; if(!ReadPartition(PartitionHandle,0,1,IoBuffer)) { fprintf(stderr,"\n"); fprintf(stderr,textReadFailedAtSector,0L); fprintf(stderr,"\n"); return(FALSE); } BootSector = IoBuffer; *TotalSectorCount = BootSector->Sectors ? (ULONG)BootSector->Sectors : BootSector->LargeSectors; *ClusterCount = pFatClusterCount(BootSector); *NonClusterSectors = pFatFirstClusterSector(BootSector); *SectorsPerCluster = BootSector->SectorsPerCluster; return(TRUE); } BOOL FatBuildClusterBitmap( IN HPARTITION PartitionHandle, IN UINT FileHandle, IN OUT PARTITION_IMAGE *PartitionImage ) { FPFAT_BOOT_SECTOR BootSector; FatSize fatsize; ULONG CurrentFatSectorBase; ULONG FatSectorsLeft; ULONG CurrentCluster; ULONG SectorsPerFat; BYTE c; USHORT ClusterLimit; USHORT i; USHORT x1; ULONG x2; printf(textScanningFat,0L); printf("\r"); if(!ReadPartition(PartitionHandle,0,1,IoBuffer)) { fprintf(stderr,"\n"); fprintf(stderr,textReadFailedAtSector,0L); fprintf(stderr,"\n"); return(FALSE); } BootSector = IoBuffer; fatsize = pFatDetermineFatSize(BootSector); CurrentFatSectorBase = BootSector->ReservedSectors; SectorsPerFat = pFatSectorsPerFat(BootSector); FatSectorsLeft = SectorsPerFat; CurrentCluster = 0; InitClusterBuffer((FPBYTE)IoBuffer + (3*512),FileHandle); while(CurrentCluster < PartitionImage->ClusterCount) { // // Read next block of fat sectors. Deal with 3 at a time so // we never get partial 12-bit fat entries. // c = 3; if((ULONG)c > FatSectorsLeft) { c = (BYTE)FatSectorsLeft; } if(!ReadPartition(PartitionHandle,CurrentFatSectorBase,c,IoBuffer)) { fprintf(stderr,"\n"); fprintf(stderr,textReadFailedAtSector,CurrentFatSectorBase); fprintf(stderr,"\n"); return(FALSE); } // // Figure out how many clusters are described by the 3 sectors // of the FAT we just read in // switch(fatsize) { case Fat12: ClusterLimit = 1024; break; case Fat16: ClusterLimit = 768; break; case Fat32: ClusterLimit = 384; break; } if((CurrentCluster + ClusterLimit) > PartitionImage->ClusterCount) { ClusterLimit = (USHORT)(PartitionImage->ClusterCount - CurrentCluster); } // // Fat values: // // 0 - free cluster // 1 - (unused) // [ffff]ff0 - [ffff]ff6 - (reserved) // [ffff]ff7 - bad cluster // [ffff]ff8 - [ffff]fff - last cluster of file // // All other values - used cluster // switch(fatsize) { case Fat12: for(i=0; i>= 4; } else { x1 &= 0xfffU; } if((((x1 > 1) && (x1 <= 0xfefU)) || (x1 >= 0xff8U)) && (CurrentCluster >= 2)) { PartitionImage->LastUsedCluster = CurrentCluster-2; PartitionImage->UsedClusterCount++; if(!MarkClusterUsed(CurrentCluster-2)) { return(FALSE); } } } break; case Fat16: for(i=0; i 1) && (x1 <= 0xffefU)) || (x1 >= 0xfff8U)) && (CurrentCluster >= 2)) { PartitionImage->LastUsedCluster = CurrentCluster-2; PartitionImage->UsedClusterCount++; if(!MarkClusterUsed(CurrentCluster-2)) { return(FALSE); } } } break; case Fat32: for(i=0; i 1) && (x2 <= 0xfffffefUL)) || (x2 >= 0xffffff8UL)) && (CurrentCluster >= 2)) { PartitionImage->LastUsedCluster = CurrentCluster-2; PartitionImage->UsedClusterCount++; if(!MarkClusterUsed(CurrentCluster-2)) { return(FALSE); } } } break; } CurrentFatSectorBase += c; FatSectorsLeft -= c; printf(textScanningFat,100 * (SectorsPerFat - FatSectorsLeft) / SectorsPerFat); printf("\r"); } printf("\n"); if(!FlushClusterBuffer()) { return(FALSE); } return(TRUE); } FatSize pFatDetermineFatSize( IN FPFAT_BOOT_SECTOR BootSector ) { // // For fat32 the # of root dir entries in the bpb is 0. // if(!BootSector->SectorsPerFat) { return(Fat32); } // // See whether we overflow a 12-bit fat and return result. // return((pFatClusterCount(BootSector) < 4087L) ? Fat12 : Fat16); } ULONG pFatClusterCount( IN FPFAT_BOOT_SECTOR BootSector ) { ULONG s; // // Calculate the number of sectors that are in the data area, // which is the size of the volume minus the number of sectors // that are not in the data area. // s = BootSector->Sectors ? (ULONG)BootSector->Sectors : BootSector->LargeSectors; s -= pFatFirstClusterSector(BootSector); return(s / BootSector->SectorsPerCluster); } ULONG pFatFirstClusterSector( IN FPFAT_BOOT_SECTOR BootSector ) { ULONG s; // // Calculate the number of sectors that are not // part of the data area. This includes reserved sectors, // sectors used for the fats, and in the non-fat32 case, // sectors used for the root directory. // // Note that for fat32 the # of root dir entries in the bpb is 0. // s = BootSector->ReservedSectors; s += BootSector->Fats * pFatSectorsPerFat(BootSector); s += BootSector->RootEntries / 16; return(s); } ULONG pFatSectorsPerFat( IN FPFAT_BOOT_SECTOR BootSector ) { ULONG SectorsPerFat; SectorsPerFat = BootSector->SectorsPerFat ? (ULONG)BootSector->SectorsPerFat : *(FPULONG)((FPBYTE)BootSector + 0x24); // large sectors per fat return(SectorsPerFat); }