【问题标题】:Find current connected USB storage path in C++在 C++ 中查找当前连接的 USB 存储路径
【发布时间】:2018-02-28 09:16:09
【问题描述】:

我的环境:

Qt 5.3.1
Windows 10

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

【问题讨论】:

    标签: windows qt winapi mingw


    【解决方案1】:

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

    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_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】:

      首先我们需要枚举所有支持接口GUID_DEVINTERFACE_DISK的设备。然后我们可以在这个界面上打开文件并查询STORAGE_ADAPTER_DESCRIPTORSTORAGE_DEVICE_DESCRIPTOR并查找

      总线类型

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

      我们也可以在接口字符串中查找 EnumeratorName - 这是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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-29
        • 1970-01-01
        • 2013-12-22
        • 2010-09-07
        相关资源
        最近更新 更多