如何获取卷 GUID 路径所属的物理设备?

Posted

技术标签:

【中文标题】如何获取卷 GUID 路径所属的物理设备?【英文标题】:How to get the physical device that a volume GUID path belongs to? 【发布时间】:2019-09-06 16:24:30 【问题描述】:

我需要使用 winapi 将卷 GUID 路径转换为物理驱动器路径。

我使用FindFirstVolume/FindNextVolume 列出了我电脑上的卷,我得到以下输出:

First volume found: \\?\Volume42f73c69-4b40-11e9-a0b2-806e6f6e6963\
Found next volume:  \\?\Volume8aef5fee-0000-0000-0000-100000000000\
Found next volume:  \\?\Volume8aef5fee-0000-0000-0000-90c30b000000\
Found next volume:  \\?\Volume8aef5fee-0000-0000-0000-501f1e000000\
Found next volume:  \\?\Volumeec716472-e587-11e8-a031-806e6f6e6963\
Search finished: [18] There are no more files.

我需要知道每个卷所属的物理设备,例如\\.\PHYSICALDRIVE1

这是我的代码:

/* This program attempts to list the volumes and get the corresponding physical device for each one */

#include <stdio.h>
#include <windows.h>

HANDLE openDevice(const char *deviceID);
BOOL getAllVolumes();

/* Main function
   * Access the device
   * Get all volume GUID paths
   * Close handler
*/
int main()

    char *deviceID = "\\\\.\\PHYSICALDRIVE1";
    HANDLE hDevice = openDevice(deviceID);
    if (hDevice != INVALID_HANDLE_VALUE)  /* success */
        fprintf(stderr, "Device %s opened.\n", deviceID);
        /* find all volumes in the device and get the corresponding device to each one */
        BOOL result = getAllVolumes();
        CloseHandle(hDevice); /* close the handler to the device */
    

    return 0;


HANDLE openDevice(const char *deviceID)

    /* Access the device */
    HANDLE hDevice = CreateFileA(
        deviceID, /* device id (get it with `$ wmic DISKDRIVE`) */
        FILE_READ_DATA | FILE_WRITE_DATA, /* read/write access */
        FILE_SHARE_READ | FILE_SHARE_WRITE, /* shared */
        NULL, /* default security attributes */
        OPEN_EXISTING, /* only open if the device exists */
        0, /* file attributes */
        NULL); /* do not copy file attributes */

    if (hDevice == INVALID_HANDLE_VALUE)  /* cannot open the physical drive */
        DWORD errorCode = GetLastError();
        fprintf(stderr, "Cannot open the device %s: [%lu]\n", deviceID, errorCode); /* print the error code and message */
    

    return hDevice;


BOOL getAllVolumes()

    char volumePath[512] = 0;
    fprintf(stderr, "Attempt to find first volume...\n");
    HANDLE searchHandlerDevice = FindFirstVolume(volumePath, sizeof(volumePath));
    fprintf(stderr, "Done. Retrieving results...\n");
    if (searchHandlerDevice == INVALID_HANDLE_VALUE) 
        DWORD errorCode = GetLastError();
        fprintf(stderr, "Cannot find a volume: [%lu]\n", errorCode); /* print the error code and message */
        return FALSE;
     else 
        fprintf(stdout, "First volume found: %s\n", volumePath);
    

    /* find the other volumes */
    while (FindNextVolume(searchHandlerDevice, volumePath, sizeof(volumePath))) 
        fprintf(stdout, "Found volume: %s\n", volumePath);
    

    /* searching failed */
    DWORD errorCode = GetLastError();
    fprintf(stderr, "Search failed: [%lu]\n", errorCode); /* print the error code and message */

    /* close the search */
    BOOL result = FindVolumeClose(searchHandlerDevice);
    if (!result) 
        fprintf(stderr, "Search failed: [%lu]\n", errorCode); /* print the error code */
    

    return result;

【问题讨论】:

@RbMm, FindNextVolumeW 添加反斜杠以保持一致性,因为它在连接挂载点中是必需的,否则打开没有尾随反斜杠的连接(例如SetCurrentDirectoryW)将打开卷设备而不是文件系统根目录。我们还从GetVolumeNameForVolumeMountPointW 获取带有尾部反斜杠的卷名。 SetVolumeMountPointW 也需要它并将其传递到一个联结点(但不是 DOS 驱动器安装点,因为对象符号链接必须以卷设备为目标)。 @RbMm,也就是说,我认为他们在保持一致性方面走错了路。在需要时添加反斜杠应该是内部实现细节。 另外,如果一个卷跨越多个磁盘,IOCTL_STORAGE_GET_DEVICE_NUMBER 将(或应该?)失败,在这种情况下,我们需要IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 列出所有磁盘范围。然而,新的存储空间的实现方式不同。它将卷(未分配 GUID 名称)组合到一个新的磁盘设备中,可见卷使用这个单个磁盘。 @RbMm,我有空闲时间,所以我从 VM 中的两个磁盘创建了一个跨接卷。正如我所料,为卷获取IOCTL_STORAGE_GET_DEVICE_NUMBER 失败,ERROR_INVALID_FUNCTION(即STATUS_INVALID_DEVICE_REQUEST)。我必须从IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 获取磁盘号。 @RbMm,这两个磁盘没有分区,即我们只有磁盘本身的“Partition0”符号链接,例如"\Device\Harddisk3\Partition0" -> "\Device\Harddisk3\DR3"。磁盘管理管理单元显示有关其他操作系统可访问性的警告。 【参考方案1】:

嗯,我在DiskDrive 课程中找到了答案。它代表运行 Windows 操作系统的计算机所看到的物理磁盘驱动器。

【讨论】:

以上是关于如何获取卷 GUID 路径所属的物理设备?的主要内容,如果未能解决你的问题,请参考以下文章

在 Windows XP 上获取现有 USB 设备的 GUID

c# 如何获取上一级物理路径

如何获取Cisco设备OID值来监控各种物理及逻辑状态信息

如何在 Linux 上获取磁盘信息?

如何将挂载点的卷 GUID 转换为实际路径?

如何获取物理驱动器的卷 ID?