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

时间:2014-07-03 10:42:00

标签: ioctl

我的目标是编写一个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驱动器。该函数返回的句柄可用于通过函数DeviceIOControlIOCTL_STORAGE_GET_DEVICE_NUMBER获取设备编号。 之后,CreateFile函数可用于打开每个驱动器号(从:)开始,并尝试以与上述相同的方式获取设备号。再次找到相同的设备编号后,将显示设备路径和驱动器号之间的关系。

我的问题是IOCTL_STORAGE_GET_DEVICE_NUMBER来电不起作用。 DeviceIOControl函数返回错误代码50,表示“不支持请求”。

我无法在USB记忆棒的设备路径和驱动器号之间创建链接。我已经尝试了几次IOCTL_STORAGE and IOCTL_VOLUME次呼叫,但没有一次能够用于我试过的USB记忆棒。 我还在另一个论坛上读到,人们对DeviceIOControl函数的结果有疑问。它正在某些PC上返回所需的结果,而它正在为其他人制造麻烦。 还有另一种方法可以实现我的目标吗?

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

我很感激为解决我的问题提出任何建议。

祝你好运, 弗洛里安

如果有人感兴趣的话,这里有代码。这个评论的位置“//这里是我想要获得设备号!!!”是设备号的请求可以使用的地方。

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;
}

1 个答案:

答案 0 :(得分:0)

我发现了我的问题。从我在互联网上看到的内容看来,其他人也有类似我的问题,所以我会发布我的解决方案。

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

我使用Windows XP,7和8测试了代码,它运行正常。只能调整上面代码示例的FileCreate代码(将GENERIC_WRITE替换为0)。否则需要管理员权限或兼容性模式。

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

祝你好运, 弗洛里安