FAT32解析示例

来源:互联网 发布:windows故障转移集群 编辑:程序博客网 时间:2024/05/16 14:06
#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;}