FAT32解析示例

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

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值