Windwos下读取被独占打开文件的方法

对于已经被独占打开的,采用 API 读取文件内容会被系统拒绝,比较简单的方法是获得文件在分区上的物理存储位置,然后打开文件所在分区,直接进行读出文件内容。其核心的方法是通过调用 DeviceIoControl ,向系统发生 FSCTL_GET_RETRIEVAL_POINTERS 命令,获得关于文件保存位置信息的 RETRIEVAL_POINTERS_BUFFER 结构体。 RETRIEVAL_POINTERS_BUFFER 结构体的构成如下所示:

ExtentCount

  typedef struct RETRIEVAL_POINTERS_BUFFER {

  DWORD ExtentCount;

  LARGE_INTEGER StartingVcn ;

  struct {

LARGE_INTEGER NextVcn;

       LARGE_INTEGER Lcn;

} Extents [1];

} RETRIEVAL_POINTERS_BUFFER,  *PRETRIEVAL_POINTERS_BUFFER;

 

这里要解释一下 LCN 和 VCN 的含义,文件系统通过 LCN ( Logic Cluster Number )和 VCN ( Virtual Cluster Number )来对分卷的簇进行标识,其中 LCN 是对卷的第一个簇到最后一个簇进行编号,通过 LCN 号和簇的大小以及卷的起始扇区位置,就可以对该簇进行定位; VCN 则是对某个特定文件所占用的簇从头到尾进行编号,并且 VCN 并不要求在物理上是联系的,也就是说某个特定文件的内容可以离散的分布在卷上的各个位置。对于已经被文件占用的簇来说,它既有 VCN 号又有 LCN 号。

    在 RETRIEVAL_POINTERS_BUFFER 结构体中, StartinVcn 表示文件起始的虚拟簇号,通常为零,其成员 Extents ,则组成了一个 cluster 链,用来标示该文件所有簇的所在位置,则表示结构体中一个有多少个 Extents 组成的数组一共有多少个成员。当文件中的某些内容在分区中的物理位置连续时就只需要一个 Extents 元素来标识,当物理位置发生跳转时,会有一个新的元素来表示 NextVCN 和 LCN 。通过与上一个 Extents 元素中 NextVCN 相减,就可以知道在上一个 LCN 中有多少个连续簇属于该文件。将这些簇上的数据读出来就可以实现对独占文件的读取了。

    对于 NTFS 和 FAT32 的文件系统,读取文件时有所区别,在 NTFS 文件系统下, RETRIEVAL_POINTERS_BUFFER 结构体中的 Extents 域中的 LCN 即是该簇的绝对位置,而在 FAT32 文件系统下,由 RETRIEVAL_POINTERS_BUFFER 获得的 LCN 还要加上卷隐含扇区数,才是簇的绝对起始位置。这里的隐含扇区包括保留扇区、 2 个 FAT 表占用的扇区。

    这种读取独占文件的方法也存在一定的不足,就是读取 NTFS 文件系统上小于 1K 的文件,会出现读取失败的情况,这是因为小于 1K 文件的内容直接放在 NTFS 分区的 MFT( 主文件表 Master File Table) 中,调用 DeviceIoControl 函数也就不能获得正确的 LCN 和 VCN ,所以必须直接打开 MFT 表,找到所需的文件。

 

具体方法可以参考 http://apps.hi.baidu.com/share/detail/15620676

 

你可能感兴趣的:(struct,api,table,Integer,buffer,Pointers)