📄 fat.c
字号:
#include "windows.h"
#include "fat.h"
#pragma pack(push,1)
#define MAX_PART 24
static UCHAR g_dwDevIndex=0;
static DWORD g_dwPartNum=0;
static DWORD g_dwVolume =0;
static PARTITION_INFO g_PartitionInfo[MAX_PART];
static VOLUME_FAT g_FatInfo[MAX_PART];
static FILE_DESC g_FileDesc;
static DWORD g_bFatCache[SECTOR_SIZE/4];
static DWORD g_dwCacheSector=-1;
static DWORD g_BufCluster[32768/4];
/**********************************************************************************
Functions releated with partition table
//**********************************************************************************/
__inline ISFATSYSTEM( DWORD data)
{
BOOL bTrue=FALSE;
switch( data ){
case 0x4:
case 0x6:
case 0xB:
case 0xC:
case 0xE:
bTrue=TRUE;
break;
default:
break;
}
return bTrue;
}
#define ISEXTEND(type) ( type ==0x05 || type ==0x0F || type ==0x85 )
BOOL InitializePartionTable( void )
{
int i;
UCHAR *pPartInDisk;
DWORD dwExtendStart;
DWORD dwExtendNum ;
DWORD dwBuffer[SECTOR_SIZE/4];
UCHAR *cBuffer=(PUCHAR)dwBuffer;
RETAILMSG( DEBUG_TEST,(L"Partition: check buffer %x---%x\r\n",cBuffer,dwBuffer));
if( !ReadSectors( g_dwDevIndex, 0, 1, cBuffer) )
return FALSE;
if( cBuffer[0x1Fe] !=0x55 ||
cBuffer[0x1FF] !=0xAA
)
return FALSE;
//check major partitions:
pPartInDisk= cBuffer+0x1BE;
for( i=0; i<4; i++ , pPartInDisk+=16 ){
if( *(pPartInDisk +4) ) //it's a valid partition
{
g_PartitionInfo[g_dwPartNum].dwStartSector=MAKE_DWORD (pPartInDisk +8 );
g_PartitionInfo[g_dwPartNum].dwSectorNum= MAKE_DWORD (pPartInDisk +12 );
g_PartitionInfo[g_dwPartNum].dwType =pPartInDisk[4];
g_PartitionInfo[g_dwPartNum].dwIndex=g_dwPartNum;
RETAILMSG( DEBUG_TEST,(L"Partition: start %u--%x, num %d, type %d\r\n",
g_PartitionInfo[g_dwPartNum].dwStartSector,
g_PartitionInfo[g_dwPartNum].dwStartSector,
g_PartitionInfo[g_dwPartNum].dwSectorNum,
g_PartitionInfo[g_dwPartNum].dwType
));
// RETAILMSG( DEBUG_TEST,(L"Partition: address %x---%x\r\n",pPartInDisk +8, pPartInDisk +12));
// if( ISFATSYSTEM( *(pPartInDisk +4) ) )// || ISEXTEND(*(pPartInDisk +4) ) )
g_dwPartNum++;
}else
break;
}
RETAILMSG( DEBUG_TEST,(L"Partition: major finished \r\n"));
//Check ones in Extend partition.
if( ISEXTEND( g_PartitionInfo[g_dwPartNum-1 ].dwType ) )
{
RETAILMSG( DEBUG_TEST,(L"Partition: last is ext \r\n"));
g_dwPartNum--;
dwExtendStart=g_PartitionInfo[g_dwPartNum].dwStartSector;
dwExtendNum =g_PartitionInfo[g_dwPartNum].dwSectorNum;
}
while( ISEXTEND( g_PartitionInfo[g_dwPartNum ].dwType ) && g_dwPartNum <24) {
DWORD dwNextPart= g_PartitionInfo[g_dwPartNum].dwStartSector;
if( !ReadSectors( g_dwDevIndex, dwNextPart, 1, cBuffer) )
return FALSE;
if( cBuffer[0x1Fe] !=0x55 ||
cBuffer[0x1FF] !=0xAA
)
return FALSE;
pPartInDisk= cBuffer+0x1BE;
for( i=0; i<2; i++ , pPartInDisk+=16 ){
if( *(pPartInDisk +4) ) //it's a valid partition
{
g_PartitionInfo[g_dwPartNum].dwStartSector=MAKE_DWORD (pPartInDisk +8 );// +dwExtendStart;
g_PartitionInfo[g_dwPartNum].dwSectorNum= MAKE_DWORD (pPartInDisk +12 );
g_PartitionInfo[g_dwPartNum].dwType =pPartInDisk[4];
if( !ISEXTEND(*(pPartInDisk +4) ) )
{
g_PartitionInfo[g_dwPartNum].dwStartSector+=dwNextPart;
}else{ //ext
g_PartitionInfo[g_dwPartNum].dwStartSector+=dwExtendStart;
}
RETAILMSG( DEBUG_TEST,(L"Partition in ext: start %u, num %d, type %d, offset %d\r\n",
g_PartitionInfo[g_dwPartNum].dwStartSector,
g_PartitionInfo[g_dwPartNum].dwSectorNum,
g_PartitionInfo[g_dwPartNum].dwType,
MAKE_DWORD (pPartInDisk +8 )
));
g_PartitionInfo[g_dwPartNum].dwIndex=g_dwPartNum;
if( !ISEXTEND(*(pPartInDisk +4) ) )
g_dwPartNum++;
}else
break;
}
if( i==2 )
if( g_PartitionInfo[g_dwPartNum-1].dwStartSector + g_PartitionInfo[g_dwPartNum-1].dwSectorNum !=
g_PartitionInfo[g_dwPartNum].dwStartSector
){
RETAILMSG( DEBUG_TEST,( L"Warning, Partition tabe is invalid\r\n"));
}
}
//dump partion info.
{
DWORD i;
for( i=0; i< g_dwPartNum; i ++ ){
RETAILMSG( DEBUG_ERROR,(L"Partition info: start %u, num %d, type %d\r\n",
g_PartitionInfo[i].dwStartSector,
g_PartitionInfo[i].dwSectorNum,
g_PartitionInfo[i].dwType
));
}
}
return TRUE;
}
BOOL PartitionReadDisk( PPARTITION_INFO pInfo, DWORD dwSector, DWORD dwNum, UCHAR* pBuffer)
{
return ReadSectors( g_dwDevIndex, pInfo->dwStartSector +dwSector , (WORD)dwNum, pBuffer);
}
/**********************************************************************************
Functions releated with FAT file system.
//**********************************************************************************/
BOOL CheckFAT32Part( PVOLUME_FAT pVolume ,char * pTempBuf )
{
PFSINFO pFsInfo = (PFSINFO )(pTempBuf+512);
if( pFsInfo ->dwLeadSig != 0x41615252 )
return FALSE;
if( pFsInfo->dwStructSig !=0x61417272 )
return FALSE;
if( pFsInfo->dwTrailSig != 0xAA550000 )
return FALSE;
/*
pFsInfo ++;
if( pFsInfo->dwTrailSig != 0xAA550000 )
return FALSE;
*/
return TRUE;
}
BOOL CheckFATValidity( PVOLUME_FAT pVolume, char *pcBuf )
{
PBPB_STRUCT pPbp=(PBPB_STRUCT)pcBuf;
PFAT32STRUCT pPbp32;
PFAT16STRUCT pPbp16;
//Following codes implemented exactly following the FAT specification published by Microsoft.
DWORD dwRootDirSectors ,dwFATSize ,dwFirstDataSec;
DWORD dwCountofClusters,dwDataSec ,dwTotSec;
//RETAILMSG( DEBUG_FAT,(TEXT("FAT Mount Disk Check Validity entered 0x%x\r\n"),pcBuf));
pPbp32=(PFAT32STRUCT)(pcBuf+sizeof(BPB_STRUCT));
pPbp16=(PFAT16STRUCT)(pcBuf+sizeof(BPB_STRUCT));
if( pPbp->wBPB_BytePerSec==512 ||
pPbp->wBPB_BytePerSec==1024 ||
pPbp->wBPB_BytePerSec==2048 ||
pPbp->wBPB_BytePerSec==4096
){
//RETAILMSG( DEBUG_FAT,(TEXT("FAT Mount Disk Check rrrr ,%x\r\n"),pPbp));
}else{
return FALSE;
}
if( pPbp->nPBP_SecPerClus == 1 ||
pPbp->nPBP_SecPerClus == 2 ||
pPbp->nPBP_SecPerClus == 4 ||
pPbp->nPBP_SecPerClus == 8 ||
pPbp->nPBP_SecPerClus == 16 ||
pPbp->nPBP_SecPerClus == 32 ||
pPbp->nPBP_SecPerClus == 64 ||
pPbp->nPBP_SecPerClus == 128
){
if( pPbp->wBPB_BytePerSec * pPbp->nPBP_SecPerClus >(32*1024) ) {
return FALSE;
}
}else{
return FALSE;
}
//RETAILMSG( DEBUG_FAT,(TEXT("FAT Mount Disk Check 000000000 ,%x\r\n"),pPbp));
//Now, try to decide the version of the FAT.
dwRootDirSectors = ((pPbp->wPBP_RootEntryCount* 32)+(pPbp->wBPB_BytePerSec-1)) / pPbp->wBPB_BytePerSec;
//First, the size of root directory ;
//RETAILMSG( DEBUG_FAT,(TEXT("FAT Mount Disk Check 111111 \r\n")));
if(pPbp->wPBP_FATSize16!= 0)
dwFATSize = pPbp->wPBP_FATSize16;
else
dwFATSize = pPbp32->dwBPB_FATSize32;
if(pPbp->wPBP_TotalSector16!= 0)
dwTotSec = pPbp->wPBP_TotalSector16;
else
dwTotSec = pPbp->dwPBP_TotalSector32;
//RETAILMSG( DEBUG_FAT,(TEXT("FAT Mount Disk Check 22222222 \r\n")));
dwFirstDataSec=(pPbp->wPBP_RsvdSecCnt + (pPbp->nPBP_NumFATs* dwFATSize) + dwRootDirSectors );
dwDataSec = dwTotSec-dwFirstDataSec;
//RETAILMSG( DEBUG_FAT,(TEXT("FAT Mount Disk Check 333333333 \r\n")));
dwCountofClusters = dwDataSec / pPbp->nPBP_SecPerClus;
if(dwCountofClusters < 4085) {
pVolume->dwVersion=FAT_VERSION12;
// Volume is FAT12
//RETAILMSG( DEBUG_FAT,(TEXT("FAT Mount Disk Check Validity FAT12\r\n")));
return FALSE;
} else if(dwCountofClusters < 65525) {
pVolume->dwVersion=FAT_VERSION16;
// Volume is FAT16
} else {
pVolume->dwVersion=FAT_VERSION32;
// Volume is FAT32
}
//RETAILMSG( DEBUG_FAT,(TEXT("FAT Mount Disk FAT file system detect\r\n")));
if ( pPbp->cBS_JumpRoot[0] ==0xEB ){
if ( pPbp->cBS_JumpRoot[2] !=0x90 ){
return FALSE;
}
}else if(pPbp->cBS_JumpRoot[0] !=0xE9 ){
return FALSE;
}
/*if( pPbp->wBPB_BytePerSec==512 ||
pPbp->wBPB_BytePerSec==1024 ||
pPbp->wBPB_BytePerSec==2048 ||
pPbp->wBPB_BytePerSec==4096
){
if( pPbp->nPBP_SecPerClus == 1 ||
pPbp->nPBP_SecPerClus == 2 ||
pPbp->nPBP_SecPerClus == 4 ||
pPbp->nPBP_SecPerClus == 8 ||
pPbp->nPBP_SecPerClus == 16 ||
pPbp->nPBP_SecPerClus == 32 ||
pPbp->nPBP_SecPerClus == 64 ||
pPbp->nPBP_SecPerClus == 128
){
if( pPbp->wBPB_BytePerSec * pPbp->nPBP_SecPerClus >(32*1024) ) {
return FALSE;
}
}
}*/
if( pPbp->wPBP_RsvdSecCnt ==0 )
return FALSE;
if( pVolume->dwVersion ==FAT_VERSION32 ){
if (pPbp->wPBP_RootEntryCount !=0 )
return FALSE;
if( pPbp->wPBP_TotalSector16 !=0 )
return FALSE;
if( pPbp->wPBP_FATSize16 !=0 )
return FALSE;
if( pPbp->dwPBP_TotalSector32 ==0 )
return FALSE;
}else if( pVolume->dwVersion ==FAT_VERSION16 ){
//if( pPbp->wPBP_TotalSector16 ==0 )
// return FALSE;
if( pPbp->wPBP_FATSize16 ==0 )
return FALSE;
//if( pPbp->dwPBP_TotalSector32 !=0 )
// return FALSE;
if( pPbp->wPBP_TotalSector16 ==0 ){
if( pPbp->dwPBP_TotalSector32 ==0 )
return FALSE;
}
}
// if( (pcBuf[510] !=0x55) || (pcBuf[511] !=0xAA) )
// return FALSE;
//Now, save the volume information.
//pPbp->wPBP_RsvdSecCnt + (pPbp->nPBP_NumFATs* dwFATSize);
pVolume->fat_info.dwBytesPerSec= pPbp->wBPB_BytePerSec;
pVolume->fat_info.dwRsvedSector =pPbp->wPBP_RsvdSecCnt;
pVolume->fat_info.dwNumFAT =pPbp->nPBP_NumFATs;
pVolume->fat_info.dwSecPerCluster=pPbp->nPBP_SecPerClus;
pVolume->dwFirstDataSec =dwFirstDataSec;
pVolume->fat_info.dwClusterCount=dwCountofClusters;
if( pVolume->dwVersion ==FAT_VERSION32 ){
memcpy(pVolume->cLabel,pPbp32->cBS_VolLab, LABEL_SIZE );
pVolume->cLabel[LABEL_SIZE]=0; //set the string end.
pVolume->fat_info.dwRootEntryCount= 0; //it's invalid in FAT32.
pVolume->fat_info.dwFATSize = pPbp32->dwBPB_FATSize32;
//pVolume->fat_info.dwTotalSector = pPbp->dwPBP_TotalSector32;
pVolume->fat_info.dwRootCluster = pPbp32->dwBPB_RootCluster;
if( !CheckFAT32Part( pVolume ,pcBuf ) ){
return FALSE;
}
pVolume->dwRootDirSec = FIRST_SECTOR_OF_CLUSTER( pVolume,pVolume->fat_info.dwRootCluster);
pVolume->dwRootDirClusterNum=0;
}else if( pVolume->dwVersion ==FAT_VERSION16 ){
//memcpy(pVolume->cLabel,pPbp16->cBS_VolLab, LABEL_SIZE );
//pVolume->cLabel[LABEL_SIZE]=0; //set the string end.
pVolume->fat_info.dwRootEntryCount= pPbp->wPBP_RootEntryCount;
pVolume->fat_info.dwFATSize = pPbp->wPBP_FATSize16;
//pVolume->fat_info.dwTotalSector = pPbp->wPBP_TotalSector16;
pVolume->fat_info.dwRootCluster = 0; //Braden modified 2003-4-29...only for testing.
pVolume->dwRootDirSec = pPbp->wPBP_RsvdSecCnt + (pPbp->nPBP_NumFATs* dwFATSize);
pVolume->dwRootDirClusterNum= dwRootDirSectors/ pVolume->fat_info.dwSecPerCluster;
if( dwRootDirSectors% pVolume->fat_info.dwSecPerCluster ){
return FALSE;
}
}
pVolume->fat_info.dwClusterCount += pVolume->dwRootDirClusterNum;
if( pPbp->dwPBP_TotalSector32 )
pVolume->fat_info.dwTotalSector = pPbp->dwPBP_TotalSector32;
else
pVolume->fat_info.dwTotalSector = pPbp->wPBP_TotalSector16;
return TRUE;
}
BOOL LoadFATFileSystem( PPARTITION_INFO pInfoPart, PVOLUME_FAT pVolume)
{
UCHAR pBuffer[3*SECTOR_SIZE];
if( !pBuffer )
return FALSE;
if( !PartitionReadDisk( pInfoPart, 0, 3, pBuffer) ){
goto Load_failed;
}
if( !CheckFATValidity( pVolume, (char*)pBuffer ) )
goto Load_failed;
if( pVolume->fat_info.dwTotalSector > pInfoPart->dwSectorNum )
RETAILMSG( DEBUG_ERROR,(L"Error, partition info is error\r\n"));
return TRUE;
Load_failed:
return FALSE;
}
BOOL InitializeFATSystem( void )
{
DWORD i;
for( i=0; i< g_dwPartNum; i ++ ){
if( ISFATSYSTEM( g_PartitionInfo[ i ].dwType ) ){
if( LoadFATFileSystem( &g_PartitionInfo[i] , &g_FatInfo[g_dwVolume] ) ){
g_FatInfo[g_dwVolume].pPartInfo= &g_PartitionInfo[i];
g_dwVolume++;
}
}
}
return TRUE;
}
/**********************************************************************************
Functions releated with search and find file.
//**********************************************************************************/
//Caculate where is the entry in the FAT table for a specific Cluster.
BOOL GetClusterInFAT( PVOLUME_FAT pVolume , DWORD dwCluster ,DWORD * pdwSectorNum, DWORD * pdwOffsetInSec)
{
DWORD dwOffset;
if( dwCluster < pVolume->dwRootDirClusterNum +2)
return FALSE;
if( dwCluster > pVolume->fat_info.dwClusterCount )
return FALSE;
dwCluster-=pVolume->dwRootDirClusterNum;
if( pVolume->dwVersion ==FAT_VERSION16 ){
dwOffset=dwCluster*2;
}else if ( pVolume->dwVersion ==FAT_VERSION32 ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -