通过U盘的盘符找到USB设备

1.判断磁盘的类型
if (GetDriveType(szRootPathName) != DRIVE_REMOVABLE)
{
m_csErrorMsg.Format(_T(“该磁盘不是可移动磁盘”));
}

csLogicDisk.Format(_T("\\\\.\\%c:"), csDiskSymbol[0]);   

HANDLE   hVolume = CreateFile(csLogicDisk, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if (hVolume == INVALID_HANDLE_VALUE)
{
    return false;
}

2.通过DeviceIoControl获取设备根据盘符得到第一个STORAGE_DEVICE_NUMBER --> sdnDiskDeviceNum
if (!DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdnDiskDeviceNum, sizeof(sdnDiskDeviceNum), &dwBytesReturned, NULL))
{
return false;
}

3.枚举磁盘设备,GUID_DEVINTERFACE_DISK,

依次用到

SetupDiGetClassDevs, SetupDiEnumDeviceInterfaces, SetupDiGetDeviceInterfaceDetail

—HDEVINFO hDevInfo = SetupDiGetClassDevs(pGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

—SetupDiEnumDeviceInterfaces(hDevInfo, NULL, pGuid, index, &DevInterfaceData)

—SetupDiGetDeviceInterfaceDetail(hDevInfo, &DevInterfaceData, pDevInterfaceDetailData, dwRequiredSize, &dwRequiredSize, &DevInfoData)

4.再次调用CreateFile,这次的文件名是来自于SetupDiGetDeviceInterfaceDetail返回的buffer的path

HANDLE hDrive = CreateFile(pDevInterfaceDetailData->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

5.通过DeviceIoControl获取设备根据盘符得到第二个STORAGE_DEVICE_NUMBER --> sdnDeviceInfoByEnumDevice

DeviceIoControl(hDrive,
IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL,
0,
&sdnDeviceInfoByEnumDevice,
sizeof(sdnDeviceInfoByEnumDevice),
&dwBytesReturned2,
NULL
)

6.比较两个STORAGE_DEVICE_NUMBER是否相同

typedef struct _STORAGE_DEVICE_NUMBER {
DEVICE_TYPE DeviceType;
ULONG DeviceNumber;
ULONG PartitionNumber;
} STORAGE_DEVICE_NUMBER, *PSTORAGE_DEVICE_NUMBER;
比较前面的两个成员就可以了,第三个成员可能不一样,前面两个成员就可以确定是同一个设备了.

7.获取ID

DWORD dwInstanceParent = 0;
CM_Get_Parent(&dwInstanceParent, dwInstance, 0);

WCHAR buffer[256] = { 0 };
CM_Get_Device_ID(dwInstanceParent, buffer, sizeof(buffer), 0); // 得到设备ID,如 USB\VID_17EF&PID_3801\907117000F7F

参数dwInstance来自与枚举设备的时候找到相同设备时SP_DEVINFO_DATA这个结构里面的 DevInst成员

获取到的ID像这样的 : USB\VID_17EF&PID_3801\907117000F7F
对应 设备管理器->USB大容量存储设备->详细信息->设备实例路径

下面是整个实现的函数,传入盘符,得到设备实例路径,粗略实测是有效的,

//需要的头文件等:

#include “stdafx.h”

#include <setupapi.h> //SetupDi系列函数
#include <winioctl.h>

#include <cfgmgr32.h>

#pragma comment(lib, “setupapi.lib”)

static GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10L, 0x6530, 0x11D2,{ 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
//<usbiodef.h>里面有,不包含头文件时直接自己写一个

// 功能:通过U盘盘符得到U盘的ID 包含pid, vid
// 入口参数:
// [out] csDeviceID:设备ID信息, 如 USB\VID_17EF&PID_3801\907117000F7F
// [in] csDiskSymbol:可移动设备的盘符 单个字母 如 H
// 返回值:
// 成功返回true
// 失败返回false

bool GetDiskDeviceIDBySymbol(CString csDiskSymbol, CString& csDeviceID)
{

CString m_csErrorMsg;
//判断该盘符对应的磁盘类型
WCHAR szRootPathName[] = _T("X:\\");  
szRootPathName[0] = csDiskSymbol[0];
UINT uDriveType = GetDriveType(szRootPathName);
if (uDriveType != DRIVE_REMOVABLE)
{
    m_csErrorMsg.Format(_T("该磁盘不是可移动磁盘"));
    return false;
}

//得到设备的文件名 如  \\.\X:
WCHAR szDeviceName[] = _T("X:");   // "X:"    
szDeviceName[0] = csDiskSymbol[0];
CString csLogicDisk;
csLogicDisk.Format(_T("\\\\.\\%c:"), csDiskSymbol[0]);   
HANDLE   hVolume = CreateFile(csLogicDisk, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if (hVolume == INVALID_HANDLE_VALUE)
{
    m_csErrorMsg.Format(_T("CreateFile fail, error code:%d"), GetLastError());
    return false;
}

//通过DeviceIoControl获取设备的STORAGE_DEVICE_NUMBER
STORAGE_DEVICE_NUMBER  sdnDiskDeviceNum;  //包含有关设备的信息。
DWORD  dwBytesReturned = 0;
if (!DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdnDiskDeviceNum, sizeof(sdnDiskDeviceNum), &dwBytesReturned, NULL))
{
    m_csErrorMsg.Format(_T("DeviceIoControl fail, error code:%d"), GetLastError());
    return false;
}
CloseHandle(hVolume);
if (sdnDiskDeviceNum.DeviceNumber == -1)
{
    m_csErrorMsg.Format(_T("DeviceNumber = -1, error code:%d"), GetLastError());
    return false;
}

//
//已根据盘符得到设备的STORAGE_DEVICE_NUMBER,然后枚举USB设备,找到相同的STORAGE_DEVICE_NUMBER的设备, (只需比较DeviceNumber和DeviceType)
const GUID* pGuid = &GUID_DEVINTERFACE_DISK;   //GUID_DEVINTERFACE_DISK GUID_DEVINTERFACE_USB_DEVICE
HDEVINFO hDevInfo = SetupDiGetClassDevs(pGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
    m_csErrorMsg.Format(_T("SetupDiGetClassDevs, error code:%d"), GetLastError());
    return false;
}

SP_DEVINFO_DATA                  DevInfoData;
DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
SP_DEVICE_INTERFACE_DATA         DevInterfaceData;
DevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

PSP_DEVICE_INTERFACE_DETAIL_DATA pDevInterfaceDetailData = NULL;  //SetupDiGetDeviceInterfaceDetail用于存放信息,需要根据实际大小动态分配

DWORD dwRequiredSize = 0;    //保存SetupDiGetDeviceInterfaceDetail返回的实际需要的缓存区大小
DWORD dwInstance = 0;        //设备Instance

//枚举所有设备
DWORD index = 0;
while (SetupDiEnumDeviceInterfaces(hDevInfo, NULL, pGuid, index, &DevInterfaceData))
{
    //先直接调用函数,目的是获取第一个设备所需要的缓存区大小dwRequiredSize;
    SetupDiGetDeviceInterfaceDetail(hDevInfo, &DevInterfaceData, NULL, 0, &dwRequiredSize, &DevInfoData);

    //得到大小后分配内存
    pDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(dwRequiredSize);
    pDevInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

    //再次调用获取信息
    if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &DevInterfaceData, pDevInterfaceDetailData, dwRequiredSize, &dwRequiredSize, &DevInfoData))
    {
        m_csErrorMsg.Format(_T("SetupDiGetDeviceInterfaceDetail, error code:%d"), GetLastError());
        free(pDevInterfaceDetailData);
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return false;
    }

    HANDLE hDrive = CreateFile(pDevInterfaceDetailData->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hDrive == INVALID_HANDLE_VALUE)
    {
        m_csErrorMsg.Format(_T("CreateFile INVALID_HANDLE_VALUE, error code:%d"), GetLastError());
        free(pDevInterfaceDetailData);
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return false;
    }

    STORAGE_DEVICE_NUMBER sdnDeviceInfoByEnumDevice; //每次枚举时获取的设备信息
    DWORD dwBytesReturned2 = 0;
    if (DeviceIoControl(hDrive,
        IOCTL_STORAGE_GET_DEVICE_NUMBER,
        NULL,
        0,
        &sdnDeviceInfoByEnumDevice,
        sizeof(sdnDeviceInfoByEnumDevice),
        &dwBytesReturned2,
        NULL
        ))
    {
        // 比较由盘符获取的DeviceNumber,DeviceType与枚举时获取的DeviceNumber,DeviceType,相同则说明盘符对应此USB设备
        if (sdnDiskDeviceNum.DeviceNumber == sdnDeviceInfoByEnumDevice.DeviceNumber &&
            sdnDiskDeviceNum.DeviceType == sdnDeviceInfoByEnumDevice.DeviceType)
        {
            dwInstance = DevInfoData.DevInst;
        }
    }
    free(pDevInterfaceDetailData);
    CloseHandle(hDrive);
    ++index;
}
if (index == 0)
{
    m_csErrorMsg.Format(_T("SetupDiEnumDeviceInterfaces, error code:%d"), GetLastError());
    SetupDiDestroyDeviceInfoList(hDevInfo);
    return false;
}
m_csErrorMsg.Format(_T("SetupDiEnumDeviceInterfaces, error code:%d"), GetLastError());
//获取InstanceParent
DWORD dwInstanceParent = 0;
CM_Get_Parent(&dwInstanceParent, dwInstance, 0);

WCHAR buffer[256] = { 0 };
CM_Get_Device_ID(dwInstanceParent, buffer, sizeof(buffer), 0); // 得到设备ID,如 USB\VID_17EF&PID_3801\907117000F7F

SetupDiDestroyDeviceInfoList(hDevInfo);
csDeviceID.Format(_T("%s"), buffer);    //找到的设备的ID, 我也不知道有没有可能两个设备这个ID是相同的
csDeviceID.MakeUpper();
return true;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值