DWORD QueryChangesVirtualDisk(
HANDLE VirtualDiskHandle,
PCWSTR ChangeTrackingId,
ULONG64 ByteOffset,
ULONG64 ByteLength,
QUERY_CHANGES_VIRTUAL_DISK_FLAG Flags,
PQUERY_CHANGES_VIRTUAL_DISK_RANGE Ranges,
PULONG RangeCount,
PULONG64 ProcessedLength
);
I am trying to get difference between two virtual disk or two Resillent Change Tracking ID (RCT)
but RangeCount
always return as 0
I opened virtual disk file (vhdx) with two enum parameter VIRTUAL_DISK_ACCESS_GET_INFO
, OPEN_VIRTUAL_DISK_FLAG_NONE
opStatus = OpenVirtualDisk(
&storageType,
VirtualDiskPath,
VIRTUAL_DISK_ACCESS_GET_INFO,
OPEN_VIRTUAL_DISK_FLAG_NONE,
NULL,
&vhdHandle ); // output handle
then use QueryChangesVirtualDisk()
opStatus = QueryChangesVirtualDisk(
vhdHandle,
ChangeTrackingId,
0,
32212254720,
QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
pRctRanges,
&rctRangeCnt,
&processedLength
);
OpenVirtualDisk()
QueryChangesVirtualDisk()
Both function did not return error but in every case RangeCount
always has a value of 0
There is definitely a difference between virtual disk file and RCT ID
please give me some advice
#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;
}
The problem is that you pass a null-pointer for the Ranges
argument and zero for RangeCount
.
For Ranges
you're supposed to pass a pointer to the first element or an array of QUERY_CHANGES_VIRTUAL_DISK_RANGE
elements, and the RangeCount
should be initialized to the number of elements in that array.
When the QueryChangesVirtualDisk
function returns it will have modified RangeCount
to be the number of initialized elements in the Ranges
array.
From the documentation you linked to, about the RangeCount
argument:
On input, the value indicates the number of
QUERY_CHANGES_VIRTUAL_DISK_RANGE
structures that the array that theRanges
parameter points to can hold. On output, the value contains the number ofQUERY_CHANGES_VIRTUAL_DISK_RANGE
structures that the method placed in the array.
In short: The function doesn't create this array for you, you must do it before you call the function.