in host/common/win32/portablehelpersmajor.cpp [6616:6756]
DWORD GetVolumeDiskExtents(const std::string& volName, disk_extents_t& extents)
{
DWORD dwRet = ERROR_SUCCESS;
HANDLE hVolume = INVALID_HANDLE_VALUE;
DWORD dwBytesReturned = 0;
DWORD cbInBuff = 0;
PVOLUME_DISK_EXTENTS pVolDiskExt = NULL;
std::string volumeName = volName;
if (volumeName.empty())
{
DebugPrintf(SV_LOG_ERROR, "%s:Line %d: ERROR: Volume Name can not be empty.\n", __FUNCTION__, __LINE__);
return ERROR_INVALID_PARAMETER;
}
do {
//Get the volume guid name of the volume/mountpoint. The \\?\Volume{guid} will be used to open the volume handle.
if (!FormatVolumeNameToGuid(volumeName))
{
DebugPrintf(SV_LOG_ERROR, "%s:Line %d: Could not get volume guid name for the volume: %s.\n", __FUNCTION__, __LINE__, volumeName.c_str());
dwRet = ERROR_INVALID_PARAMETER;
break;
}
//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();
DebugPrintf(SV_LOG_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;
DebugPrintf(SV_LOG_FATAL, "%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;
DebugPrintf(SV_LOG_FATAL, "%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();
DebugPrintf(SV_LOG_ERROR, "%s:Line %d: Cloud not get the volume disk extents. DeviceIoControl failed with Error %lu\n", __FUNCTION__, __LINE__, dwRet);
break;
}
else
{
dwRet = ERROR_SUCCESS;
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "%s:Line %d: Cloud 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 (int i_extent = 0; i_extent < pVolDiskExt->NumberOfDiskExtents; i_extent++)
{
std::stringstream diskName;
diskName << "\\\\.\\PhysicalDrive" << pVolDiskExt->Extents[i_extent].DiskNumber;
//Here disk_id will be a signature if disk is MBR type, a GUID if GPT type.
std::string storage_type, vg_name, disk_id;
VolumeSummary::FormatLabel lable;
VolumeSummary::Vendor vendor;
GetDiskAttributes(diskName.str(), storage_type, lable, vendor, vg_name, disk_id);
disk_extent extent(
disk_id,
pVolDiskExt->Extents[i_extent].StartingOffset.QuadPart,
pVolDiskExt->Extents[i_extent].ExtentLength.QuadPart
);
extents.push_back(extent);
}
} while (false);
if (NULL != pVolDiskExt)
free(pVolDiskExt);
if (INVALID_HANDLE_VALUE != hVolume)
CloseHandle(hVolume);
return dwRet;
}