我正在尝试创建系统中所有(固定)磁盘的分区及其卷的列表(例如:PhyiscalDrive0,分区1,C:\;PhyiscalDrive0,分区2,D:\;...) 。我已经通过SetupApi和IOCTL_STORAGE_GET_DEVICE_NUMBER获得了已安装磁盘的列表,以及分区的数量。
我遇到的问题是如何找出安装到特定分区的驱动器号(例如,物理驱动器的分区 1 的含义是 C:\)?
感谢之前的任何帮助,
威利·K.
您可能想要使用的 API 是 存储管理 API。这提供了一种查询您想要的任何内容的方法。特别是,驱动器号是 MSFT_Volume 类的一部分。该 API 对于 C++ 来说并不是最友好的,这就是为什么我不提供示例查询,但这里有一个 sample 展示了如何编写查询。
通过设置 API 获取驱动器后,您需要获取有关分区的信息(通过 IOCTL_DISK_GET_DRIVE_LAYOUT_EX),尤其是它们的起始偏移量和长度。 这是我在库 libwindevblk (libwindevblk) 中使用的代码:
BOOL FindVolume(int diskno, PSMI_DEVBLK_ENTRY pDevBlkEntry)
{
HANDLE vol;
BOOL success;
TCHAR szNextVolName[MAX_PATH+1];
TCHAR szNextVolNameNoBSlash[MAX_PATH+1];
vol = FindFirstVolume(szNextVolName, MAX_PATH);
success = (vol != INVALID_HANDLE_VALUE);
while (success)
{
//We are now enumerating volumes. In order for this function to work, we need to get partitions that compose this volume
HANDLE volH;
PVOLUME_DISK_EXTENTS vde;
DWORD bret;
//For this CreateFile, volume must be without trailing backslash
StringCchCopy(szNextVolNameNoBSlash, MAX_PATH, szNextVolName);
szNextVolNameNoBSlash[_tcslen(szNextVolNameNoBSlash) - 1] = _T('\0');
volH = CreateFile(szNextVolNameNoBSlash,
FILE_READ_ATTRIBUTES | SYNCHRONIZE | FILE_TRAVERSE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0);
if (volH != INVALID_HANDLE_VALUE)
{
bret = sizeof(VOLUME_DISK_EXTENTS) + 256 * sizeof(DISK_EXTENT);
vde = (PVOLUME_DISK_EXTENTS)malloc(bret);
if (DeviceIoControl(volH, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, (void *)vde, bret, &bret, NULL))
{
for (unsigned i = 0; i < vde->NumberOfDiskExtents; i++)
{
if (vde->Extents[i].DiskNumber == diskno &&
vde->Extents[i].StartingOffset.QuadPart == pDevBlkEntry->StartingOffset.QuadPart &&
vde->Extents[i].ExtentLength.QuadPart == pDevBlkEntry->PartitionLength.QuadPart)
{
CHAR szVolumeName[MAX_PATH + 1] = { 0 };
CHAR szFileSystemName[MAX_PATH + 1] = { 0 };
DWORD dwSerialNumber = 0;
DWORD dwMaxFileNameLength = 0;
DWORD dwFileSystemFlags = 0;
if (GetVolumeInformation(szNextVolName,
szVolumeName, _countof(szVolumeName),
&dwSerialNumber,
&dwMaxFileNameLength,
&dwFileSystemFlags,
szFileSystemName,
_countof(szFileSystemName)))
{
_tcsncpy(pDevBlkEntry->szRootPathName, szNextVolName, MAX_PATH);
_tcsncpy(pDevBlkEntry->szVolumeName, szVolumeName, MAX_PATH);
_tcsncpy(pDevBlkEntry->szFileSystemName, szFileSystemName, MAX_PATH);
pDevBlkEntry->dwSerialNumber = dwSerialNumber;
pDevBlkEntry->dwFileSystemFlags = dwFileSystemFlags;
}
else
{
DWORD dwErr = GetLastError();
printf("%lu", dwErr);
}
DWORD length = 0;
TCHAR pathnames[MAX_PATH + 1] = { 0 };
if (GetVolumePathNamesForVolumeName(szNextVolName, (LPTSTR)pathnames, MAX_PATH, &length))
{
_tcsncpy(pDevBlkEntry->szVolumePathName, pathnames, MAX_PATH);
}
free(vde);
CloseHandle(volH);
FindVolumeClose(vol);
return TRUE;
}
}//for
}
free(vde);
CloseHandle(volH);
}
success = FindNextVolume(vol, szNextVolName, MAX_PATH) != 0;
}
FindVolumeClose(vol);
return FALSE;
}