C++ h QueryChangesVirtualDisk()函数将RangeCount返回为0

C++ h QueryChangesVirtualDisk()函数将RangeCount返回为0,c++,hyper-v,windows-server-2016,change-tracking,virtual-disk,C++,Hyper V,Windows Server 2016,Change Tracking,Virtual Disk,我正在尝试获取两个虚拟磁盘或两个Resillent更改跟踪ID(RCT)之间的差异 但是RangeCount始终返回为0 我用两个枚举参数打开了虚拟磁盘文件(vhdx)virtual\u disk\u ACCESS\u GET\u INFO,OPEN\u virtual\u disk\u FLAG\u NONE opStatus = OpenVirtualDisk( &storageType, VirtualDiskPath, VIRTUA

我正在尝试获取两个虚拟磁盘或两个Resillent更改跟踪ID(RCT)之间的差异

但是
RangeCount
始终返回为0

我用两个枚举参数打开了虚拟磁盘文件(vhdx)
virtual\u disk\u ACCESS\u GET\u INFO
OPEN\u virtual\u disk\u FLAG\u NONE

opStatus = OpenVirtualDisk(
        &storageType,
        VirtualDiskPath,
        VIRTUAL_DISK_ACCESS_GET_INFO,
        OPEN_VIRTUAL_DISK_FLAG_NONE,
        NULL,
        &vhdHandle ); // output handle
然后使用
QueryChangesVirtualDisk()

OpenVirtualDisk()
QueryChangesVirtualDisk()

这两个函数都没有返回错误,但在任何情况下,
RangeCount
的值始终为0

虚拟磁盘文件和RCT ID之间肯定有区别

请给我一些建议

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <initguid.h>
#include <strsafe.h>
#include <virtdisk.h>

#include "Storage.h"

DWORD QueryChangesVirtualDisk(_In_    LPCWSTR     VirtualDiskPath, _In_    LPCWSTR     ChangeTrackingId)
{
    VIRTUAL_STORAGE_TYPE storageType;
    PGET_VIRTUAL_DISK_INFO diskInfo;
    ULONG diskInfoSize;
    DWORD opStatus;

    HANDLE vhdHandle;

    QUERY_CHANGES_VIRTUAL_DISK_RANGE *pRctRanges;
    ULONG                            rctRangeCnt;
    ULONG64                          processedLength;
    UINT                             i;

    vhdHandle = INVALID_HANDLE_VALUE;
    diskInfo = NULL;
    diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO);

    rctRangeCnt = 0L;
    processedLength = 0L;
    pRctRanges = NULL;

    i = 0;

    diskInfo = (PGET_VIRTUAL_DISK_INFO)malloc(diskInfoSize);
    if (diskInfo == NULL)
    {
        opStatus = ERROR_NOT_ENOUGH_MEMORY;
        goto Cleanup;
    }

    storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
    storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;

    //////////////////////////////////////////////////////////////////

    opStatus = OpenVirtualDisk(
        &storageType,
        VirtualDiskPath,
        VIRTUAL_DISK_ACCESS_GET_INFO,
        OPEN_VIRTUAL_DISK_FLAG_NONE,
        NULL,
        &vhdHandle);

    if (opStatus != ERROR_SUCCESS)
    {
        wprintf(L"OpenVirtualDisk fail\n");
        goto Cleanup;
    }

    opStatus = QueryChangesVirtualDisk(
        vhdHandle,
        ChangeTrackingId,
        0,
        32212254720,
        QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
        pRctRanges,
        &rctRangeCnt,
        &processedLength
        );

    wprintf(L"rctRangeCnt : %lu\n", rctRangeCnt);
    wprintf(L"processedLength : %llu\n", processedLength);

    for (i = 0; i < rctRangeCnt; i++)
    {
        wprintf(L"ByteOffset : %lld   ByteLength : %lld\n", pRctRanges[i].ByteOffset, pRctRanges[i].ByteLength);
    }

    if (opStatus != ERROR_SUCCESS)
    {
        wprintf(L"QueryChangesVirtualDisk fail\n");
        goto Cleanup;
    }

Cleanup:

    if (opStatus == ERROR_SUCCESS)
    {
        wprintf(L"success\n");
    }
    else
    {
        wprintf(L"error = %u\n", opStatus);
    }

    if (vhdHandle != INVALID_HANDLE_VALUE)
    {
        CloseHandle(vhdHandle);
    }

    if (diskInfo != NULL)
    {
        free(diskInfo);
    }

    if (pRctRanges != NULL)
    {
        for (i = 0; i < rctRangeCnt; i++)
        {
            free(&pRctRanges[i]);
        }
    }

    return opStatus;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括“Storage.h”
DWORD QueryChangesVirtualDisk(u在uuCwstr VirtualDiskPath中,u在uCwstr ChangeTrackingId中)
{
虚拟存储类型存储类型;
虚拟磁盘信息磁盘信息;
ULONG磁盘大小;
德沃德地位;
把手;
查询\更改\虚拟\磁盘\范围*pRctRanges;
ULONG rctRangeCnt;
ULONG64处理长度;
UINT i;
vhdHandle=无效的\u句柄\u值;
diskInfo=NULL;
diskInfoSize=sizeof(获取虚拟磁盘信息);
rctRangeCnt=0升;
处理长度=0L;
pRctRanges=NULL;
i=0;
diskInfo=(PGET\u VIRTUAL\u DISK\u INFO)malloc(diskInfoSize);
如果(diskInfo==NULL)
{
opStatus=错误\u内存不足\u;
去清理;
}
storageType.DeviceId=虚拟存储设备未知;
storageType.VendorId=虚拟存储类型供应商未知;
//////////////////////////////////////////////////////////////////
opStatus=OpenVirtualDisk(
&存储类型,
VirtualDiskPath,
虚拟磁盘访问获取信息,
打开虚拟磁盘标志无,
无效的
&vhd手柄);
if(opStatus!=错误\u成功)
{
wprintf(L“OpenVirtualDisk失败\n”);
去清理;
}
opStatus=QueryChangesVirtualDisk(
拉手,
ChangeTrackingId,
0,
32212254720,
查询\u更改\u虚拟磁盘\u标志\u无,
pRctRanges,
&rctRangeCnt,
&加工长度
);
wprintf(L“rctRangeCnt:%lu\n”,rctRangeCnt);
wprintf(L“processedLength:%llu\n”,processedLength);
对于(i=0;i
问题在于,为
范围
参数传递空指针,为
范围计数
传递零指针

对于
Ranges
您应该传递一个指向第一个元素或
QUERY\u CHANGES\u VIRTUAL\u DISK\u RANGE
元素数组的指针,并且
RangeCount
应该初始化为该数组中的元素数

QueryChangesVirtualDisk
函数返回时,它将
RangeCount
修改为
范围
数组中的初始化元素数

从链接到的文档中,关于
RangeCount
参数:

输入时,该值表示
范围
参数指向的数组可以容纳的
查询\u更改\u虚拟磁盘\u范围
结构的数量。在输出时,该值包含方法放置在数组中的
QUERY\u CHANGES\u VIRTUAL\u DISK\u RANGE
结构的数量


简而言之:函数不会为您创建此数组,您必须在调用函数之前创建它。

下次我应该更仔细地阅读文档。。。谢谢你的帮助me@TK_WooDong这在快照和正在运行的VM的基础磁盘上有效吗?还是在脱机VM上查询已更改的块?使用正在运行的VM,我的访问被拒绝。。有什么建议吗?
opStatus = QueryChangesVirtualDisk(
    vhdHandle,
    ChangeTrackingId,
    0,
    32212254720,
    QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
    pRctRanges,
    &rctRangeCnt,
    &processedLength
    );
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <initguid.h>
#include <strsafe.h>
#include <virtdisk.h>

#include "Storage.h"

DWORD QueryChangesVirtualDisk(_In_    LPCWSTR     VirtualDiskPath, _In_    LPCWSTR     ChangeTrackingId)
{
    VIRTUAL_STORAGE_TYPE storageType;
    PGET_VIRTUAL_DISK_INFO diskInfo;
    ULONG diskInfoSize;
    DWORD opStatus;

    HANDLE vhdHandle;

    QUERY_CHANGES_VIRTUAL_DISK_RANGE *pRctRanges;
    ULONG                            rctRangeCnt;
    ULONG64                          processedLength;
    UINT                             i;

    vhdHandle = INVALID_HANDLE_VALUE;
    diskInfo = NULL;
    diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO);

    rctRangeCnt = 0L;
    processedLength = 0L;
    pRctRanges = NULL;

    i = 0;

    diskInfo = (PGET_VIRTUAL_DISK_INFO)malloc(diskInfoSize);
    if (diskInfo == NULL)
    {
        opStatus = ERROR_NOT_ENOUGH_MEMORY;
        goto Cleanup;
    }

    storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
    storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;

    //////////////////////////////////////////////////////////////////

    opStatus = OpenVirtualDisk(
        &storageType,
        VirtualDiskPath,
        VIRTUAL_DISK_ACCESS_GET_INFO,
        OPEN_VIRTUAL_DISK_FLAG_NONE,
        NULL,
        &vhdHandle);

    if (opStatus != ERROR_SUCCESS)
    {
        wprintf(L"OpenVirtualDisk fail\n");
        goto Cleanup;
    }

    opStatus = QueryChangesVirtualDisk(
        vhdHandle,
        ChangeTrackingId,
        0,
        32212254720,
        QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
        pRctRanges,
        &rctRangeCnt,
        &processedLength
        );

    wprintf(L"rctRangeCnt : %lu\n", rctRangeCnt);
    wprintf(L"processedLength : %llu\n", processedLength);

    for (i = 0; i < rctRangeCnt; i++)
    {
        wprintf(L"ByteOffset : %lld   ByteLength : %lld\n", pRctRanges[i].ByteOffset, pRctRanges[i].ByteLength);
    }

    if (opStatus != ERROR_SUCCESS)
    {
        wprintf(L"QueryChangesVirtualDisk fail\n");
        goto Cleanup;
    }

Cleanup:

    if (opStatus == ERROR_SUCCESS)
    {
        wprintf(L"success\n");
    }
    else
    {
        wprintf(L"error = %u\n", opStatus);
    }

    if (vhdHandle != INVALID_HANDLE_VALUE)
    {
        CloseHandle(vhdHandle);
    }

    if (diskInfo != NULL)
    {
        free(diskInfo);
    }

    if (pRctRanges != NULL)
    {
        for (i = 0; i < rctRangeCnt; i++)
        {
            free(&pRctRanges[i]);
        }
    }

    return opStatus;
}