QueryChangesVirtualDisk is returning ERROR_INVALID_HANDLE(6) even though OpenVirtualDisk is succesfull

0

I am trying out VirtualDisk APIs, So far I am able to Open a VHDX file, get some of the properties by using GetVirtualDiskInformation. But I am not able to get RCT information and ChangedAreas.

The first call to GetVirtualDiskInformation is successful. The second call to GetVirtualDiskInformation fails with insufficient buffer ERROR_INSUFFICIENT_BUFFER(122). Call to QueryChangesVirtualDisk fails with ERROR_INVALID_HANDLE(6). The RCT ID hardcoded in the code is proper, I am able to get the ChangedAreas using WMI Explorer. Attached screenshot of the same.

If it is invalid handle, then GetVirtualDiskInformation should also throw the same error?


#include "pch.h"
#include <iostream>
#include <string>
#include <cstdlib>
#define WINVER _WIN32_WINNT_WIN10
#include <windows.h>
#include <winioctl.h>
#include <virtdisk.h>
#include <initguid.h>
#pragma comment(lib, "virtdisk.lib")

DEFINE_GUID(VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT, 0xec984aec, 0xa0f9, 0x47e9, 0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b);
DEFINE_GUID(VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN, 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);

int main()
{
    HANDLE vhdHandle;
    _VIRTUAL_STORAGE_TYPE storageType;
    storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
    storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;

    wchar_t path[] = L"C:\\Hyper-V\\Virtual Hard Disks\\Lacazette\\Windows2016.vhdx";
    VIRTUAL_DISK_ACCESS_MASK mask = VIRTUAL_DISK_ACCESS_GET_INFO;

    PGET_VIRTUAL_DISK_INFO diskInfo;
    ULONG diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO);
    std::wcout << "size of diskinfo structure " << diskInfoSize << std::endl;
    diskInfo = (PGET_VIRTUAL_DISK_INFO)malloc(diskInfoSize);
    if (diskInfo == NULL)
    {
        std::cout << "Failed to malloc disk info, ret=" << std::endl;
        return 0;
    }


    std::wcout << "Opening Virtual disk " << path << std::endl;
    DWORD res = OpenVirtualDisk(&storageType, path,
                                VIRTUAL_DISK_ACCESS_GET_INFO,
                                OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS,
                                NULL,
                                &vhdHandle);

    if (res != ERROR_SUCCESS)
    {
        std::cout << "Failed to open disk, ret=" << res << std::endl;
        return 0;
    }

    diskInfo->Version = GET_VIRTUAL_DISK_INFO_SIZE;
    res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
    if (res != ERROR_SUCCESS)
    {
        std::cout << "Failed to GET_VIRTUAL_DISK_INFO_SIZE, ret=" << res << std::endl;
    }
    long physicalSize = diskInfo->Size.PhysicalSize;
    long virtualSize = diskInfo->Size.VirtualSize;
    long sectorSize = diskInfo->Size.SectorSize;
    long blockSize = diskInfo->Size.BlockSize;
    std::wcout << "physicalSize :" << physicalSize << std::endl;
    std::wcout << "virtualSize :" << virtualSize << std::endl;
    std::wcout << "sectorSize :" << sectorSize << std::endl;
    std::wcout << "blockSize :" << blockSize << std::endl;

    diskInfo->Version = GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;

    res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
    if (res != ERROR_SUCCESS)
    {
        std::cout << "Failed to GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE, ret=" << res << std::endl;
    }
    std::cout << "\nrct id:" << diskInfo->ChangeTrackingState.MostRecentId << std::endl;

    std::cout << "\nQuerying for changed disk areas...\n" << std::endl;

    wchar_t rctId[] = L"rctX:c2eb01d9:ccb1:405d:acb6:f0e76d055906:00000001";
    ULONG64   byteOffset = 0L;
    ULONG64   byteLength = 19327352832;
    QUERY_CHANGES_VIRTUAL_DISK_RANGE* changedAreas = NULL;
    ULONG     rangeCount = 0L;
    ULONG64   processedLength = 0L;
    res = QueryChangesVirtualDisk(&vhdHandle, rctId, byteOffset, byteLength,
        QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
        changedAreas, &rangeCount, &processedLength);

    if (res != ERROR_SUCCESS)
    {
        std::cout << "Failed to get chanegd areas, ret=" << res << std::endl;
        if (vhdHandle != NULL)
        {
            CloseHandle(vhdHandle);
            std::cout << "closing handle!" <<std::endl;
        }
        return 0;
    }

    std::cout << "Total changed areas:" << rangeCount << std::endl;
    std::cout << "Total processed length:" << processedLength << std::endl;

    if (vhdHandle != NULL)
    {
        CloseHandle(vhdHandle);
    }
    return 0;
}

Output of the program:

enter image description here

Screenshot of wmi explorer output.

enter image description here

c++
wmi
hyper-v
vhd
virtual-disk
asked on Stack Overflow Aug 11, 2020 by Shree Hari

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0