Find current connected USB storage path in C++

前端 未结 2 1422
無奈伤痛
無奈伤痛 2021-01-16 10:14

My Env:

Qt 5.3.1
Windows 10

I need to find the path of mounted USB storage devices. Through the path, I can copy the files via Qt. I know t

2条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-01-16 10:37

    first we need enumerate all devices which support interface GUID_DEVINTERFACE_DISK. then we can open file on this interface and query for it STORAGE_ADAPTER_DESCRIPTOR or STORAGE_DEVICE_DESCRIPTOR and look for

    BusType

    Specifies a value of type STORAGE_BUS_TYPE that indicates the type of the bus to which the device is connected.

    for usb this will be 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(&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(&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;
            }
        }
    }
    

    also we can look for EnumeratorName in interface string - are this is USBSTOR. fast end simply:

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

    search for \USBSTOR# substring in interface name. or more correct - get Device_InstanceId from interface name and query it for 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;
    }
    

提交回复
热议问题