1

我正在创建文件删除工具,因此使用原始磁盘访问。做了一些读取数据的功能。

有点抱歉,因为发布了这么多代码,但不确定真正的问题在哪里。

struct Extent
{
    LONGLONG ClustersCount; 
    LARGE_INTEGER Lcn;          //lcn - logical cluster number - the offset of a cluster from some arbitary point within volume

    Extent() : ClustersCount(), Lcn()
    {}

    Extent(LONGLONG clustersCount, LARGE_INTEGER lcn) : ClustersCount(clustersCount), Lcn(lcn)
    {}
};

typedef std::vector<Extent> ExtentsVector;

bool GetFileExtentPoints(const std::wstring& filePath, ExtentsVector& output)
{
    output.clear();
    DWORD err = ERROR_SUCCESS;
    HANDLE file = CreateFile(filePath.c_str(), FILE_READ_ATTRIBUTES, (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), NULL, OPEN_EXISTING, 0, 0);
    if (file != INVALID_HANDLE_VALUE)
    {
        STARTING_VCN_INPUT_BUFFER vcnStartBuffer = {};
        RETRIEVAL_POINTERS_BUFFER pointsBuffer = {};
        DWORD deviceIoControlDataritten = 0;

        do 
        {
            if (DeviceIoControl(file, FSCTL_GET_RETRIEVAL_POINTERS, &vcnStartBuffer, sizeof(vcnStartBuffer), &pointsBuffer, sizeof(pointsBuffer), &deviceIoControlDataritten, NULL))
            {
                Extent extent(pointsBuffer.Extents->NextVcn.QuadPart - pointsBuffer.StartingVcn.QuadPart, pointsBuffer.Extents[0].Lcn);
                output.push_back(extent);
                CloseHandle(file);
                return true;
            }
            if (pointsBuffer.ExtentCount == 0)  //small files could be stroed in master file table, so this part shouldn't always return false
            {
                CloseHandle(file);
                return false;
            }
            Extent extent(pointsBuffer.Extents->NextVcn.QuadPart - pointsBuffer.StartingVcn.QuadPart, pointsBuffer.Extents[0].Lcn);
            output.push_back(extent);
            vcnStartBuffer.StartingVcn = pointsBuffer.Extents->NextVcn;
        }
        while (ERROR_MORE_DATA == GetLastError());
        CloseHandle(file);
    }
    return false;
}

bool PermanentDeleteFile/*for now just read...*/(const std::wstring& filePath)
{
    ExtentsVector extents;
    if (!GetFileExtentPoints(filePath, extents))
        return false;

    DWORD sectorsPerCluster = 0;
    DWORD bytesPerSector = 0;
    LARGE_INTEGER fileSize = {};

    HANDLE file = CreateFile(filePath.c_str(), FILE_READ_ATTRIBUTES, (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), NULL, OPEN_EXISTING, 0, 0);
    if (file != INVALID_HANDLE_VALUE)
    {
        TCHAR drive[] = L"?:\\"; 
        drive[0] = filePath[0];

        if (!GetDiskFreeSpace(drive, &sectorsPerCluster, &bytesPerSector, NULL, NULL))
        {
            CloseHandle(file);
            return false;
        }
        if (!GetFileSizeEx(file, &fileSize))
        {
            CloseHandle(file);
            return false;
        }
        CloseHandle(file);
    }
    LONGLONG clusterSize = sectorsPerCluster * bytesPerSector;
    LONGLONG clustersCount = fileSize.QuadPart / clusterSize + ((fileSize.QuadPart % clusterSize == 0) ? 0 : 1);

    TCHAR rawDrive[] = L"\\\\.\\?:"; 
    rawDrive[4] = filePath[0];

    HANDLE driveHandle = CreateFile(rawDrive, /*GENERIC_WRITE*/GENERIC_READ/**/, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);

    if (driveHandle != INVALID_HANDLE_VALUE)
    {
        for (ExtentsVector::iterator it = extents.begin(); it != extents.end(); ++it)
        {
            LARGE_INTEGER distance = {};
            distance.QuadPart = it->Lcn.QuadPart * clusterSize;

            BOOL b = SetFilePointerEx(driveHandle, distance, NULL, FILE_BEGIN);
            if (b)
            {
                std::string buffer;
                buffer.resize(clusterSize * it->ClustersCount);
                DWORD read = 0;
                BOOL B = ReadFile(driveHandle, &buffer[0], clusterSize * it->ClustersCount, &read, NULL);
                B = FALSE;//here I have breakpoint and for FAT type drives buffer contains invalid data
            }
            else
            {
                CloseHandle(driveHandle);
                return false;
            }

        }
    }
    return false;
}

GetFileExtentPoints应根据给定文件为后面的操作收集集群条目和集群链大小。

发现问题的地方在PermanentDeleteFile我已经用评论标记了那个地方。

我试图读取我所有的 FAT32 驱动器,发现我正在寻找的数据在驱动器中,但在其他地方,据我所知,FAT 使用某种数据偏移量。之后读到这个。因为我认为偏移量由驱动器中的前 3 个字节描述,但不明白如何使用它。就我而言,它是0xEB 0x58 0x90。想问一下,如何将文件系统头解码成数据偏移量。

顺便提一句。我正在使用 C++ 进行编码并使用 WinAPI。

编辑:我已将我的行更改为distance.QuadPart = it->Lcn.QuadPart * clusterSize + 0x01000000;,这适用于 FAT,但是我不想硬编码常量,所以有人可以判断它是否始终是这个值,或者它是通过某种方式计算出来的。

4

0 回答 0