有什么方法可以确定跨区卷的特定逻辑偏移量驻留在哪个磁盘上?

问题描述 投票:0回答:1

我的一些同事开发了一个微型端口驱动程序,该驱动程序在将数据写入卷时对数据进行加密,并在读取数据时对其进行解密。对于用户来说,此时可能发生的一个问题是确定数据是否实际上在磁盘上加密。为了解决这个问题,我编写了一个程序,当给定完整的文件路径时,它将打印硬盘上存在的文件的数据,从而向用户显示文件数据的加密版本。当卷属于单个磁盘时,我已经成功处理该卷,但当该卷是跨区卷时,我遇到了问题。获取文件的逻辑地址后,我将其转换为物理偏移量,从而读取数据,但在跨区卷的情况下,我无法推断出该物理偏移量属于哪个硬盘,因为该卷现在驻留在多个磁盘上。有什么方法可以推断出这一点,还是我需要将其添加为我的程序的限制?

到目前为止我的代码是这样的。

void fetchData(string filenameWithPath) {
    string driveLetter = "\\\\.\\" + filenameWithPath.substr(0, 2);

    map<int, pair<unsigned long long, unsigned long long>> volStruct;

    wstring wdriveLetter = wstring(driveLetter.begin(), driveLetter.end());

    wstring wfilenameWithPath = wstring(filenameWithPath.begin(), filenameWithPath.end());
    HANDLE volHandle = CreateFile(wdriveLetter.c_str(),
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);

    if (volHandle == INVALID_HANDLE_VALUE) {
        cerr << "Failed to open volume. Error code: " << GetLastError() << std::endl;
        return;
    }

    HANDLE handle = CreateFileW(wfilenameWithPath.c_str(), GENERIC_READ, 0, NULL,
        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED |
        FILE_FLAG_NO_BUFFERING, NULL);

    if (handle == INVALID_HANDLE_VALUE) {
        cerr << "Failed to open file Handle. Error code: " << GetLastError() << endl;
        return;
    }

    VOLUME_DISK_EXTENTS* diskExtents = nullptr;
    DWORD buffersize = sizeof(diskExtents)*4;
    DWORD bytesReturned = 0;

    while (true) {
        diskExtents = (VOLUME_DISK_EXTENTS*)malloc(buffersize);
        if(DeviceIoControl(volHandle,
            IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
            NULL,
            0,
            diskExtents,
            buffersize,
            &bytesReturned,
            NULL)){

            break;
        }
        
        if (GetLastError() != ERROR_MORE_DATA) {
            cout << endl << "FAILED TO GET VOLUME DISK EXTENTS DATA. ERROR CODE [" << GetLastError() << "]";
            CloseHandle(handle);
            break;
        }

        buffersize = buffersize * 2;
        free(diskExtents);
    }

    
    CloseHandle(volHandle);
    CloseHandle(handle);

    
    for (DWORD i = 0; i < diskExtents->NumberOfDiskExtents; i++) {
        pair<unsigned long long, unsigned long long> temp;
        temp.first = diskExtents->Extents[i].StartingOffset.QuadPart;
        temp.second = diskExtents->Extents[i].ExtentLength.QuadPart;
        volStruct[diskExtents->Extents[i].DiskNumber] = temp;
    }

    
    cout << endl << "Exiting";
    free(diskExtents);
    return;


}
c++ winapi storage ioctl fileapi
1个回答
0
投票

好吧,我找到了如何确定跨区卷的特定逻辑偏移量驻留在哪个磁盘上。我所要做的就是创建一个 VOLUME_LOGICAL_OFFSET 缓冲区。然后将此缓冲区传递给 IOCTL IOCTL_VOLUME_LOGICAL_TO_PHYSICAL。这给出了 VOLUME_PHYSICAL_OFFSET 类型的输出缓冲区。该缓冲区包含物理偏移量以及与该物理偏移量相关的磁盘号。

VOLUME_LOGICAL_OFFSET logicalOff;
logicalOff.LogicalOffset = 16049504256;
VOLUME_PHYSICAL_OFFSETS physicalOff;
DWORD bytesReturned2;

if (!DeviceIoControl(
    volHandle,
    IOCTL_VOLUME_LOGICAL_TO_PHYSICAL,
    &logicalOff,
    sizeof(VOLUME_LOGICAL_OFFSET),
    &physicalOff,
    sizeof(VOLUME_PHYSICAL_OFFSETS),
    &bytesReturned2,
    NULL)) {

    cout << endl << "Error converting Logical address to physical address...";
    cout << endl << "The last error is " << GetLastError();
  
    CloseHandle(volHandle);
    return;

}
CloseHandle(volHandle);

cout << endl << "The logical offset " << logicalOff.LogicalOffset
    << " belongs to disk " << physicalOff.PhysicalOffset[0].DiskNumber
    << " and the physical offset is " << physicalOff.PhysicalOffset[0].Offset;
© www.soinside.com 2019 - 2024. All rights reserved.