使用SetFilePointerEx读取文件的最后一个簇

时间:2014-06-12 21:05:36

标签: c++ winapi

需要一些关于ReadFile显示内容的逻辑和说明的帮助。所以我的小项目的目的是找到任何文件的最后一个集群并读取最后一个集群的二进制文件。

截至目前,我正在使用下面的代码查找具有控制代码FSCTL_GET_RETRIEVAL_POINTERS的CreateFile()和DeviceIoControl()之后的最后一个簇地址:

    DWORD lastExtentN = retrievalBuffer->ExtentCount - 1;
    LONGLONG lastExtent = retrievalBuffer->Extents[lastExtentN].Lcn.QuadPart;
    LONGLONG lengthOfExtent = retrievalBuffer->Extents[lastExtentN].NextVcn.QuadPart - retrievalBuffer->Extents[lastExtentN - 1].NextVcn.QuadPart;

    while (error == ERROR_MORE_DATA){

        error = GetLastError();

        switch (error){

        case ERROR_HANDLE_EOF:
            //file sizes 0-1kb will return EOF error 
            cout << "ERROR_HANDLE_EOF" << endl;
            returns = true;
            break;

        case ERROR_MORE_DATA:
            cout << "ERROR_MORE_DATA" << endl;
            startVcn.StartingVcn = retrievalBuffer->Extents[0].NextVcn;

        case NO_ERROR:
            cout << "NO_ERROR, here is some info: " << endl;
            cout << "This is the lcnextent : " << retrievalBuffer->Extents[lastExtentN].Lcn.QuadPart << endl;
            cout << "This is the nextvnc: " << retrievalBuffer->Extents[lastExtentN].NextVcn.QuadPart << endl;
            cout << "This is the Extent count: " << retrievalBuffer->ExtentCount << endl;
            cout << "This is the Starting Vnc: " << retrievalBuffer->StartingVcn.QuadPart << endl;
            cout << "The length of the cluster is: " << lengthOfExtent << endl;
            cout << "The last cluster is: " << lastExtent + lengthOfExtent - 1 << endl << endl << endl;

            returns = true;
            break;

        default:
            cout << "Error in the code or input error" << endl;
            break;
        }
    }

接下来,我使用GetDiskFreeSpace()来查找群集信息:

diskClust = GetDiskFreeSpace(pathFile,
                                 &dwSectPerClust,
                                 &dwBytesPerSect,
                                 &dwFreeClusters,
                                 &dwTotalClusters);

找到群集大小后:

// Get cluster size
    DWORD totalClusterSize = dwSectPerClust * dwBytesPerSect;
    cout << "Sectors Per Cluster " << dwSectPerClust << " * Bytes Per Sector " << dwBytesPerSect << " = Cluster size: " << totalClusterSize << endl;

接下来,我使用CreateFile()设置磁盘卷的句柄,后跟SetFilePointerEx()

LARGE_INTEGER dist;
    dist.QuadPart = (lastExtent + lengthOfExtent - 1) * totalClusterSize;
    BOOL res = SetFilePointerEx(hDevice, dist, nullptr, FILE_BEGIN);
    if (!res){
        // handle error
        DWORD error = GetLastError();
        cout<<GetLastError()<<GetLastError()<<endl;
        if (error == ERROR_INVALID_HANDLE){
            cout << "ERROR_INVALID_HANDLE" << endl;
        }
        cout << "'There is an error with SetFilePointerEX" << endl;
    }

最后,我尝试使用ReadFile()来读取文件的最后一个簇:

DWORD nRead;

    unsigned int buff[4096];

    BOOL fileFromVol = ReadFile(hDevice,
                                buff,
                                4096,
                                &nRead,
                                NULL);

    if (fileFromVol == 0){         //Error handling
        cout << "Error with fileFromVol" << "\n\n";
        DWORD error = GetLastError();
            if (error == ERROR_ACCESS_DENIED){
                cout << "error_access_denied"<<endl;
            }
        cout << GetLastErrorStdStr() << endl;
        system("pause");
    }
    cout<<"\n\n"<<buff<<"\n\n";

对不起,这篇文章太长了,但我用了很多代码片段来引用。所以我的困惑是:

  • 这看起来像文件的最后一个集群:lastExtent + lengthOfExtent - 1 4096字节似乎适合集群大小: DWORD totalClusterSize = dwSectPerClust * dwBytesPerSect;
  • 将最后一个集群*作为集群大小是否有意义 为了将文件指针移动到最后一个集群:dist.QuadPart = (lastExtent + lengthOfExtent - 1) * totalClusterSize;

最后,我将数据读入缓冲区并打印出来:cout<<"\n\n"<<buff<<"\n\n";所以我在一个带有一堆&a 39的文本文件中对此进行了测试#39; s它给了我一个010F3290的十六进制结果,我相信它是用字符串翻译成2并不是真的有意义。请随意批评任何代码,询问有关它的任何问题,或提出任何建议。任何帮助都会很棒。

1 个答案:

答案 0 :(得分:2)

您假设第一个群集(LCN 0)从卷的第一个扇区开始。这是错误的。

您可以使用FSCTL_GET_RETRIEVAL_POINTER_BASE来获取从音量开头到第一个LCN的扇区偏移。

通过我的计算,最终聚类的字节偏移的正确公式是

dist.QuadPart = (FileAreaOffset * dwBytesPerSect) + 
                ((lastExtent + lengthOfExtent - 1) * totalClusterSize);