通过设备路径或句柄获取USB磁盘驱动器号



我的目标是编写一个c-dll(用MinGW编译),它能够搜索连接到计算机的某些型号的USB棒,并提供序列号,供应商ID,产品ID和驱动器号。我在网上搜索了几个小时,但没有找到适合我的方法。

我正在使用Setup Api来获取所有连接的USB设备的列表。对于每个USB设备,我得到一个路径,看起来像这样:?usb#vid_048d&pid_1172#00000020370220#{a5dcbf10-6530-11d2-901f-00c04fb951ed}从该字符串中,我可以获得我正在寻找的供应商ID,产品ID和序列号。

我的问题是现在确定与此设备路径相关的USB驱动器的驱动器号。在我的互联网研究中,我多次发现以下方法(例如在这里http://oroboro.com/usb-serial-number/):找到设备路径后,必须由CreateFile打开USB驱动器。该函数返回的句柄可以通过DeviceIOControl函数与IOCTL_STORAGE_GET_DEVICE_NUMBER函数获取设备号。之后,CreateFile功能可用于打开每个驱动器号(从a:开始),并尝试以与上述相同的方式获取设备号。一旦再次找到相同的设备号,就建立设备路径和驱动器号之间的关系。

我的问题是IOCTL_STORAGE_GET_DEVICE_NUMBER呼叫不工作。DeviceIOControl函数返回错误码50,表示"不支持请求"。

我无法在u盘的设备路径和驱动器号之间创建链接。我已经尝试了几个IOCTL_STORAGE and IOCTL_VOLUME电话,但没有一个适用于我尝试的USB棒。我还在另一个论坛上读到人们对DeviceIOControl函数的结果有问题。它在一些pc上返回了期望的结果,而在另一些pc上却出现了问题。有没有别的方法可以达到我的目标?

我已经查看了注册表,在那里我也可以找到所需的数据。但是我又遇到了在设备路径和驱动器号之间创建连接的问题。我不想使用WMI。我读到MinGW还没有真正支持它。我用c#实现了所有这一切,在那里很容易获得所需的信息,但现在我还需要一个用非托管代码创建的,可用于替换Delphi项目中也包含的C -dll。

对于解决我的问题的任何建议,我都将感激不尽。

最诚挚的问候,Florian

如果有人感兴趣,这里是代码。带有注释"//这里是我想要获取设备号的地方!!"的位置是如果设备号请求有效的话,将被使用的位置。

typedef struct ty_TUSB_Device
{
    PSP_DEVICE_INTERFACE_DETAIL_DATA    deviceDetailData;
    char                                devicePath[300];
}TUSB_Device;
int
GetUSBDevices (TUSB_Device *devList[], int size)
{
    HANDLE      hHCDev;
    HDEVINFO                         deviceInfo;
    SP_DEVICE_INTERFACE_DATA         deviceInfoData;
    ULONG                            index;
    ULONG                            requiredLength;
    int                              devCount = 0;
    //SP_DEVINFO_DATA                DevInfoData;


    // Now iterate over host controllers using the new GUID based interface
    //
    deviceInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_USB_DEVICE,
                                     NULL,
                                     NULL,
                                     (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
    if (deviceInfo != INVALID_HANDLE_VALUE)
    {
        deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
        for (index=0;
             SetupDiEnumDeviceInterfaces(deviceInfo,
                                         0,
                                         (LPGUID)&GUID_DEVINTERFACE_USB_DEVICE,
                                         index,
                                         &deviceInfoData);
             index++)
        {
            SetupDiGetDeviceInterfaceDetail(deviceInfo,
                                            &deviceInfoData,
                                            NULL,
                                            0,
                                            &requiredLength,
                                            NULL);
            //allocate memory for pointer to TUSB_Device structure
            devList[devCount] = malloc(sizeof(TUSB_Device));
            devList[devCount]->deviceDetailData = GlobalAlloc(GPTR, requiredLength);
            devList[devCount]->deviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
            SetupDiGetDeviceInterfaceDetail(deviceInfo,
                                            &deviceInfoData,
                                            devList[devCount]->deviceDetailData,
                                            requiredLength,
                                            &requiredLength,
                                            NULL);
            //open the usb device
            hHCDev = CreateFile(devList[devCount]->deviceDetailData->DevicePath,
                                GENERIC_WRITE,
                                FILE_SHARE_WRITE,
                                NULL,
                                OPEN_EXISTING,
                                0,
                                NULL);

            // If the handle is valid, then we've successfully found a usb device
            //
            if (hHCDev != INVALID_HANDLE_VALUE)
            {
                strncpy(devList[devCount]->devicePath, devList[devCount]->deviceDetailData->DevicePath, sizeof(devList[devCount]->devicePath));
                //HERE IS WHERE I WOULD LIKE TO GET THE DEVICE NUMBER!!!
                CloseHandle(hHCDev);
                devCount++;
            }
            //GlobalFree(devList[devCount]->deviceDetailData);
        }
        SetupDiDestroyDeviceInfoList(deviceInfo);
    }
    return devCount;
}

我知道我的问题是什么了。从我在网上看到的,似乎有其他人有和我一样的问题,所以我将发布我的解决方案。

整个要点是,使用SetupApi可以为USB设备获得明显不同的路径值。所有的路径值都可以用来获得该设备的句柄,但是对于该句柄可以做什么有明显的不同。我的失败是使用GUID_DEVINTERFACE_USB_DEVICE来列出设备。我发现,当我使用GUID_DEVINTERFACE_DISK时,我得到一个不同的路径值,允许我请求设备号。这样我就能得到驱动器号的链接。使用GUID_DEVINTERFACE_DISK获取的路径值也包含序列号,但不包含供应商和产品id。但是由于两个路径值都包含序列,因此同时获取它们并建立关系是没有问题的。

我在Windows XP、7和8上测试了代码,运行良好。只需要调整上面代码样例中的FileCreate代码(将GENERIC_WRITE替换为0),否则需要管理员权限或兼容模式

我没有试图找出这些不同的GUID值真正代表什么。在这方面有更深入知识的人可能会提供更好的解释。

最诚挚的问候,Florian

最新更新