您的位置:首页 > 其它

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

2016-06-10 16:23 357 查看
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

    S
9239
TORAGE_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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: