#define FAT_ENTRY_DELETED(DirEntry) ((DirEntry).Filename[0] == 0xe5) //如果目录项开头是0xe5,表明是删除了的文件,数据恢复之类的用得到
#define FAT_ENTRY_END(DirEntry) ((DirEntry).Filename[0] == 0)
#define FAT_ENTRY_LONG(DirEntry) (((DirEntry).Attrib & 0x3f) == 0x0f) //长文件名项的标志
#define FAT_ENTRY_VOLUME(DirEntry) (((DirEntry).Attrib & 0x1f) == 0x08)
#pragma pack(1)
typedef struct _BOOT_SECTOR
{
BYTE JMPCode[3]; // 0
unsigned char OEMName[8]; // 3
WORD BytesPerSector; // 11
unsigned char SectorsPerCluster; // 13
unsigned short ReservedSectors; // 14
unsigned char FATCount; // 16
unsigned short RootEntries, Sectors; // 17
unsigned char Media; // 21
unsigned short FATSectors, SectorsPerTrack, Heads; // 22
unsigned long HiddenSectors, SectorsHuge; // 28
unsigned long SectorsperFAT; // 36
unsigned short ExtFlag; // 40
unsigned short FSVersion; // 42
unsigned long Rootdir1stcluster; // 44
unsigned short FSInfoSector; // 48
unsigned short BootBackup; // 50
unsigned char Res3[12]; // 52
unsigned char Drive; // 64
unsigned char Res4; // 65
unsigned char ExtBootSignature; // 66
unsigned long VolumeID; // 67
unsigned char VolumeLabel[11], SysType[8]; // 71
unsigned char Res2[420]; // 90
unsigned short Signature1; // 510
}BOOT_SECTOR,*PBOOT_SECTOR;
//自定义结构
typedef struct _FAT_INFO
{
ULONG fat_start; //fat 起始扇区,在保留扇区之后
ULONG fat_count; //表数 一般是2,两个FAT紧挨着的
ULONG SectorsPerFAT; //一个FAT占的扇区数
ULONG BytesPerSector; //扇区字节数 一般是512
ULONG FATDiscriPerSection; //每个扇区所能存放的描述项
ULONG SectorsPerCluster; //簇的扇区数 一般是8
ULONG RootDirStart; //根目录的起始,紧跟在FAT之后
HANDLE hDisk;
}FAT_INFO,*PFAT_INFO;
typedef struct _FATDirEntry
{
union
{
struct { unsigned char Filename[8], Ext[3]; };
unsigned char ShortName[11];
};
unsigned char Attrib;
unsigned char lCase;
unsigned char CreationTimeMs;
unsigned short CreationTime,CreationDate,AccessDate;
union
{
unsigned short FirstClusterHigh; // FAT32
unsigned short ExtendedAttributes; // FAT12/FAT16
};
unsigned short UpdateTime; //time create/update
unsigned short UpdateDate; //date create/update
unsigned short FirstCluster;
unsigned long FileSize;
}FATDirEntry,*PFATDirEntry;
typedef struct _slot
{
unsigned char id; // sequence number for slot
WCHAR name0_4[5]; // first 5 characters in name
unsigned char attr; // attribute byte
unsigned char reserved; // always 0
unsigned char alias_checksum; // checksum for 8.3 alias
WCHAR name5_10[6]; // 6 more characters in name
unsigned char start[2]; // starting cluster number
WCHAR name11_12[2]; // last 2 characters in name
}slot,*pslot;
// 自定义结构,记录读取的FAT扇区缓存,因为FAT描述项大多数情况下是连续的,所以没必要每次插寻FAT都读扇区
typedef struct _CURRENT_CLUSTER_CONTEXT
{
PVOID pBuffer;
ULONG offset;
}CCC,*PCCC;
VOID PrintFileNameByDir(ULONG DirStartCluster);
ULONG FAT32ClusterToSector(ULONG Cluster);
ULONG FAT32GetFATSectorByCluster(PFAT_INFO pfi,ULONG Cluster,PULONG ArryNum);
ULONG FAT32GetNextCluster(ULONG CurrentCluster);
CCC g_Ccontext = {0};
FAT_INFO fi = {0};
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
_tsetlocale(LC_ALL,_T("chs") );
fi.hDisk = NULL;
//初始化,得到k盘句柄
fi.hDisk = CreateFile(L".//K:", /
GENERIC_READ , /
FILE_SHARE_READ | FILE_SHARE_WRITE, /
NULL, /
OPEN_EXISTING, /
FILE_ATTRIBUTE_NORMAL, /
NULL
);
if ( INVALID_HANDLE_VALUE == fi.hDisk )
{
printf( "Open Disk Error! error code is %d/n", GetLastError() );
system("pause");
return 0;
}
PBYTE pByteRead = new BYTE[512];
DWORD dwRead;
//读取引导扇区
ReadFile( fi.hDisk, (LPVOID)pByteRead, 512, &dwRead,NULL );
PBOOT_SECTOR pbs = (PBOOT_SECTOR)pByteRead;
/* printf("OEM:%s/n",pbs->OEMName);*/
//存储一些结构信息
fi.BytesPerSector = pbs->BytesPerSector; //一般是512
fi.SectorsPerCluster = pbs->SectorsPerCluster; //一般是8
fi.SectorsPerFAT = pbs->SectorsperFAT;
fi.fat_count = pbs->FATCount; //一般是两个紧挨着,第二个应该是备份的,跟第一个一模一样
fi.fat_start = pbs->ReservedSectors*fi.BytesPerSector; //保留扇区之后便是 FAT
fi.RootDirStart = fi.fat_start + fi.fat_count*fi.SectorsPerFAT*fi.BytesPerSector; //FAT之后便是根目录
fi.FATDiscriPerSection = fi.BytesPerSector / sizeof(ULONG);
delete pByteRead;
//得到一些磁盘信息,初始化完毕
// printf("fat addr:0x%x/n",fi.fat_start);
// printf("root addr:0x%x/n",fi.RootDirStart);
//根目录开始的地方是第二簇,从此开始线性排列
PrintFileNameByDir(2);
if (g_Ccontext.pBuffer!=0)
{
free(g_Ccontext.pBuffer);
}
system("pause");
return 0;
}
//************************************
// Method: PrintFileNameByDir
// FullName: PrintFileNameByDir
// Access: public
// Returns: VOID
// Qualifier:
// Parameter: ULONG DirStartCluster
//************************************
VOID PrintFileNameByDir(ULONG DirStartCluster)
{
DWORD dwRead;
CString s,sTmp;
BOOL bRootDir = FALSE;
if (DirStartCluster == 2)
{
bRootDir =TRUE;
}
ULONG uStartSector = FAT32ClusterToSector(DirStartCluster);
PFATDirEntry DirEnrtyArry = new FATDirEntry[16*8];
do
{
// 读取一个簇
SetFilePointer(fi.hDisk,uStartSector*0x200,0,FILE_BEGIN);
if (!ReadFile(fi.hDisk,DirEnrtyArry,512*8,&dwRead,0))
{
break;
}
for (int i=0;i<512*8/32;i++)
{
if (!FAT_ENTRY_DELETED(DirEnrtyArry[i])
&& !FAT_ENTRY_END(DirEnrtyArry[i])
&& !FAT_ENTRY_LONG(DirEnrtyArry[i]))
{
//得到了一个未删除的目录项,向上查看是否有长文件名项
int j =i-1;
while(j>0 && FAT_ENTRY_LONG(DirEnrtyArry[j]) && !FAT_ENTRY_DELETED(DirEnrtyArry[j]))
{
pslot sloter = (pslot)&DirEnrtyArry[j];
sTmp.Format(L"%.5s",sloter->name0_4);
s+=sTmp;
sTmp.Format(L"%.6s",sloter->name5_10);
s+=sTmp;
sTmp.Format(L"%.2s",sloter->name11_12);
s+=sTmp;
printf_s("%.13ws",s);
s.Format(L"");
j--;
}
if (j==i-1)
{
printf_s("8.3: %-8.8s.%-3.3s/n",DirEnrtyArry[i].Filename,DirEnrtyArry[i].Ext);
}
else
printf("/n");
//这样递归显然是容易出问题的,这里只是调试用
// if (DirEnrtyArry[i].FileSize == 0
// && (i>1 || bRootDir&&i>0))
// {
// //不去递归 "." ".." 这两个文件夹
// PrintFileNameByDir(MAKELONG(DirEnrtyArry[i].FirstCluster,DirEnrtyArry[i].FirstClusterHigh));
// }
}
}
//得到目录的下一个簇
DirStartCluster = FAT32GetNextCluster(DirStartCluster);
uStartSector = FAT32ClusterToSector(DirStartCluster);
} while (uStartSector);
delete DirEnrtyArry;
}
//从簇得到扇区号,从第二簇开始线性排列
//************************************
// Method: FAT32ClusterToSector
// FullName: FAT32ClusterToSector
// Access: public
// Returns: ULONG 扇区号
// Qualifier:
// Parameter: PFAT_INFO pfi
// Parameter: ULONG Cluster
//************************************
ULONG FAT32ClusterToSector(ULONG Cluster)
{
if (Cluster<2)
{
return 0;
}
return fi.RootDirStart/512 + fi.SectorsPerCluster*(Cluster-2);
}
//************************************
// Method: FAT32GetNextCluster
// FullName: FAT32GetNextCluster
// Access: public
// Returns: ULONG 返回下一个簇,如果没有,返回0
// Qualifier:
// Parameter: ULONG CurrentCluster 当前簇
//************************************
ULONG FAT32GetNextCluster(ULONG CurrentCluster)
{
DWORD dwRead;
PULONG ClusterArry ;
// 获得该fat起始扇区
ULONG offset = fi.fat_start + fi.BytesPerSector*(CurrentCluster/fi.FATDiscriPerSection);
//如果是读过的扇区,则不用重新读,否则就要读取
if (g_Ccontext.offset == offset)
{
ClusterArry = (PULONG)g_Ccontext.pBuffer;
}
else
{
if (g_Ccontext.pBuffer!=0)
{
delete g_Ccontext.pBuffer;
}
ClusterArry = (PULONG)malloc(512);
g_Ccontext.pBuffer = (PVOID)ClusterArry;
g_Ccontext.offset = offset;
SetFilePointer(fi.hDisk,offset,0,FILE_BEGIN);
ReadFile( fi.hDisk,ClusterArry, 512, &dwRead,NULL );
}
//获得数组下标
ULONG Index = CurrentCluster%fi.FATDiscriPerSection;
ULONG uNum = ClusterArry[Index];
if (uNum == 0 || uNum >=0x0ffffff8 )
{
return 0;
}
return uNum;
}
FAT32解析示例
最新推荐文章于 2024-06-12 16:31:56 发布