in host/AzureRecoveryLib/win32/WinUtils.cpp [261:422]
DWORD GetVolumeDiskExtents(const std::string& volumeGuid, disk_extents_t& diskExtents)
{
TRACE_FUNC_BEGIN;
DWORD dwRet = ERROR_SUCCESS;
HANDLE hVolume = INVALID_HANDLE_VALUE;
DWORD dwBytesReturned = 0;
DWORD cbInBuff = 0;
PVOLUME_DISK_EXTENTS pVolDiskExt = NULL;
std::string volumeName = volumeGuid;
if (volumeName.empty())
{
TRACE_ERROR("%s:Line %d: ERROR: Volume Name can not be empty.\n", __FUNCTION__, __LINE__);
return ERROR_INVALID_PARAMETER;
}
do {
//Remove trailing "\" if exist.
if (volumeName[volumeName.length() - 1] == '\\')
volumeName.erase(volumeName.length() - 1);
//Get the volume handle
HANDLE hVolume = INVALID_HANDLE_VALUE;
hVolume = CreateFile(
volumeName.c_str(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT,
NULL
);
if (hVolume == INVALID_HANDLE_VALUE)
{
dwRet = GetLastError();
TRACE_ERROR("%s:Line %d: Could not open the volume- %s. CreateFile failed with Error Code - %lu \n",
__FUNCTION__, __LINE__,
volumeName.c_str(),
dwRet);
break;
}
// Allocate default buffer sizes.
// If the volume is created on basic disk then there will be only one disk extent for the volume,
// and this default buffer will be enough to accomodate extent info.
cbInBuff = sizeof(VOLUME_DISK_EXTENTS);
pVolDiskExt = (PVOLUME_DISK_EXTENTS)malloc(cbInBuff);
if (NULL == pVolDiskExt)
{
dwRet = ERROR_OUTOFMEMORY;
TRACE_ERROR("%s:Line %d: Out of memory\n", __FUNCTION__, __LINE__);
break;
}
if (!DeviceIoControl(
hVolume,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL,
0,
pVolDiskExt,
cbInBuff,
&dwBytesReturned,
NULL
))
{
dwRet = GetLastError();
if (dwRet == ERROR_MORE_DATA)
{
// If the volume is created on dynamic disk then there will be
// posibility that more than one extent exist for the volume.
// Calculate the size required to accomodate all extents.
cbInBuff = FIELD_OFFSET(VOLUME_DISK_EXTENTS, Extents) +
pVolDiskExt->NumberOfDiskExtents * sizeof(DISK_EXTENT);
// Re-allocate the memory to new size
pVolDiskExt = (PVOLUME_DISK_EXTENTS)realloc(pVolDiskExt, cbInBuff);
if (NULL == pVolDiskExt)
{
dwRet = ERROR_OUTOFMEMORY;
TRACE_ERROR("%s:Line %d: Out of memory\n", __FUNCTION__, __LINE__);
break;
}
if (!DeviceIoControl(
hVolume,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL,
0,
pVolDiskExt,
cbInBuff,
&dwBytesReturned,
NULL
))
{
dwRet = GetLastError();
TRACE_ERROR("%s:Line %d: Could not get the volume disk extents. DeviceIoControl failed with Error %lu\n",
__FUNCTION__,
__LINE__,
dwRet);
break;
}
else
{
dwRet = ERROR_SUCCESS;
}
}
else
{
TRACE_ERROR("%s:Line %d: Could not get the volume disk extents. DeviceIoControl failed with Error %lu\n",
__FUNCTION__,
__LINE__,
dwRet);
break;
}
}
//Fill disk_extents_t structure with retrieved disk extents
for (DWORD i_extent = 0; i_extent < pVolDiskExt->NumberOfDiskExtents; i_extent++)
{
//Here disk_id will be a signature if disk is MBR type, a GUID if GPT type.
std::string disk_id;
dwRet = GetDiskId(pVolDiskExt->Extents[i_extent].DiskNumber, disk_id);
if (ERROR_SUCCESS != dwRet)
{
TRACE_ERROR("%s:Line %d: Could not get the disk signature/guid of disk# %lu\n",
__FUNCTION__,
__LINE__,
pVolDiskExt->Extents[i_extent].DiskNumber
);
break;
}
disk_extent extent(
disk_id,
pVolDiskExt->Extents[i_extent].StartingOffset.QuadPart,
pVolDiskExt->Extents[i_extent].ExtentLength.QuadPart
);
std::stringstream extentOut;
extentOut << "Disk-Id: " << extent.disk_id
<< ", Offset: " << extent.offset
<< ", Length: " << extent.length;
TRACE_INFO("Extent Info: %s\n", extentOut.str().c_str());
diskExtents.push_back(extent);
}
} while (false);
if (NULL != pVolDiskExt)
free(pVolDiskExt);
if (INVALID_HANDLE_VALUE != hVolume)
CloseHandle(hVolume);
TRACE_FUNC_END;
return dwRet;
}