#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;}