代码之家  ›  专栏  ›  技术社区  ›  JustWe

在C中查找当前连接的USB存储路径++

  •  1
  • JustWe  · 技术社区  · 6 年前

    我的环境:

    Qt 5.3.1
    Windows 10
    

    我需要找到安装的USB存储设备的路径。 通过该路径,我可以通过Qt复制文件。 我知道有一个跨平台 libusb . 但是想知道任何简单的解决方案。

    2 回复  |  直到 6 年前
        1
  •  1
  •   freim    6 年前

    首先,您需要获得可移动驱动器:

    void EnumUsbDrives() {
        DWORD drv = ::GetLogicalDrives();
        if (drv == 0) return;
    
        DWORD mask = 1;
        TCHAR szDrive[] = _TEXT("?:\\");
    
        for (uint_t i = 0; i < ('Z' - 'A' + 1); i++, mask <<= 1) {
            if (drv & mask) {
                szDrive[0] = (TCHAR)(_T('A') + i);
                if (::GetDriveType(szDrive) == DRIVE_REMOVABLE) {
                    bool bUSB = IsDriveUSB(szDrive);
                    if (bUSB) {
                        // Time do to something useful
                    }
                }
            }
        }
    }
    

    函数IsDriveUSB有点复杂。我从内部图书馆里撕下了它;该函数使用自定义助手类xregistry和xstring\u nocase。它们的目的很明显,我相信用其他类似的类或API调用替换它不会有问题。

    bool IsDriveUSB (LPCTSTR szDrive) throw() {
        TCHAR szLogicalDrive[] = _TEXT("\\\\.\\x:");
        szLogicalDrive[4] = szDrive[0];
        HANDLE hDrive = ::CreateFile(szLogicalDrive, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
        if (hDrive == INVALID_HANDLE_VALUE) return false;       // Can't open drive so we have to assume the drive is fixed
    
        VOLUME_DISK_EXTENTS vde;
        DWORD dwBytesReturned = 0;
        BOOL br = ::DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &vde, sizeof(vde), &dwBytesReturned, NULL);
        ::CloseHandle(hDrive);
        if (!br) return false;      // Can't get extents info so we have to assume the drive is fixed
    
        if (vde.NumberOfDiskExtents != 1) return false;
        ULONG uPhysDrive = vde.Extents[0].DiskNumber;
        TCHAR szPhysDrive[16];
        _stprintf(szPhysDrive, _TEXT("%u"), uPhysDrive);
    
        try {
            xregistry rk(HKEY_LOCAL_MACHINE, OS.Is64bit());
            rk.open(_TEXT("SYSTEM\\CurrentControlSet\\services\\Disk\\Enum"), KEY_QUERY_VALUE);
            if (!rk.value_exists(szPhysDrive)) return false;
            xstring_nocase strInterface = rk.get_string(szPhysDrive).substring(0, 7);
            return strInterface == _TEXT("USBSTOR");
        }
        catch (...) {
            return false;
        }
    }
    
        2
  •  0
  •   RbMm    6 年前

    首先,我们需要列举所有支持接口的设备 GUID_DEVINTERFACE_DISK . 然后我们可以在这个界面上打开文件并查询它 STORAGE_ADAPTER_DESCRIPTOR STORAGE_DEVICE_DESCRIPTOR 并寻找

    BusType型

    指定类型的值 STORAGE_BUS_TYPE 这表明 设备连接到的总线类型。

    对于usb,这将是 BusTypeUsb

    static volatile UCHAR guz;
    
    CONFIGRET EnumUsbStor()
    {
        CONFIGRET err;
    
        PVOID stack = alloca(guz);
        ULONG BufferLen = 0, NeedLen = 256;
    
        union {
            PVOID buf;
            PWSTR pszDeviceInterface;
        };
    
        for(;;) 
        {
            if (BufferLen < NeedLen)
            {
                BufferLen = RtlPointerToOffset(buf = alloca((NeedLen - BufferLen) * sizeof(WCHAR)), stack) / sizeof(WCHAR);
            }
    
            switch (err = CM_Get_Device_Interface_ListW(const_cast<PGUID>(&GUID_DEVINTERFACE_DISK), 
                0, pszDeviceInterface, BufferLen, CM_GET_DEVICE_INTERFACE_LIST_PRESENT))
            {
            case CR_BUFFER_SMALL:
                if (err = CM_Get_Device_Interface_List_SizeW(&NeedLen, const_cast<PGUID>(&GUID_DEVINTERFACE_DISK), 
                    0, CM_GET_DEVICE_INTERFACE_LIST_PRESENT))
                {
            default:
                return err;
                }
                continue;
    
            case CR_SUCCESS:
    
                while (*pszDeviceInterface)
                {
                    BOOLEAN bIsUsb = FALSE;
                    HANDLE hFile = CreateFile(pszDeviceInterface, 0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
    
                    if (hFile != INVALID_HANDLE_VALUE)
                    {
                        STORAGE_PROPERTY_QUERY spq = { StorageAdapterProperty, PropertyStandardQuery }; 
                        STORAGE_ADAPTER_DESCRIPTOR sad;
    
                        ULONG n;
                        if (DeviceIoControl(hFile, IOCTL_STORAGE_QUERY_PROPERTY, &spq, sizeof(spq), &sad, sizeof(sad), &n, 0))
                        {
                            bIsUsb = sad.BusType == BusTypeUsb;
                        }
                        CloseHandle(hFile);
                    }
    
                    pszDeviceInterface += 1 + wcslen(pszDeviceInterface);
                }
                return 0;
            }
        }
    }
    

    我们还可以寻找 枚举器名称 在接口字符串中-这是 USBSTOR . 快速结束:

    wcsstr(_wcsupr(pszDeviceInterface), L"\\USBSTOR#");
    

    搜索 \USBSTOR# 接口名称中的子字符串。或更正确-获取 Device_InstanceId 从接口名称中查询 DEVPKEY_Device_EnumeratorName

    CONFIGRET IsUsbStor(DEVINST dnDevInst, BOOLEAN& bUsbStor)
    {
        ULONG cb = 0, rcb = 256;
    
        PVOID stack = alloca(guz);
        DEVPROPTYPE PropertyType;
    
        CONFIGRET status;
    
        union {
            PVOID pv;
            PWSTR EnumeratorName;
            PBYTE pb;
        };
    
        do 
        {
            if (cb < rcb)
            {
                rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
            }
    
            status = CM_Get_DevNode_PropertyW(dnDevInst, &DEVPKEY_Device_EnumeratorName, &PropertyType,
                pb, &rcb, 0);
    
            if (status == CR_SUCCESS)
            {
                if (PropertyType == DEVPROP_TYPE_STRING)
                {
                    DbgPrint("EnumeratorName = %S\n", EnumeratorName);
                    bUsbStor = !_wcsicmp(L"USBSTOR", EnumeratorName);
                }
                else
                {
                    status = CR_WRONG_TYPE;
                }
    
                break;
            }
    
        } while (status == CR_BUFFER_SMALL);
    
        return status;
    }
    
    CONFIGRET IsUsbStor(PCWSTR pszDeviceInterface, BOOLEAN& bUsbStor)
    {
        ULONG cb = 0, rcb = 256;
    
        PVOID stack = alloca(guz);
        DEVPROPTYPE PropertyType;
    
        CONFIGRET status;
    
        union {
            PVOID pv;
            PWSTR DeviceID;
            PBYTE pb;
        };
    
        do 
        {
            if (cb < rcb)
            {
                rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
            }
    
            status = CM_Get_Device_Interface_PropertyW(pszDeviceInterface, &DEVPKEY_Device_InstanceId, &PropertyType, pb, &rcb, 0);
    
            if (status == CR_SUCCESS)
            {
                if (PropertyType == DEVPROP_TYPE_STRING)
                {
                    DbgPrint("DeviceID = %S\n", DeviceID);
    
                    DEVINST dnDevInst;
    
                    status = CM_Locate_DevNodeW(&dnDevInst, DeviceID, CM_LOCATE_DEVNODE_NORMAL);
    
                    if (status == CR_SUCCESS)
                    {
                        status = IsUsbStor(dnDevInst, bUsbStor);
                    }
                }
                else
                {
                    status = CR_WRONG_TYPE;
                }
    
                break;
            }
    
        } while (status == CR_BUFFER_SMALL);
    
        return status;
    }