http://blog.youkuaiyun.com/jhqin/article/details/6766311
前言:
VID和PID常被用于厂家的软件加密,只有在系统中检测到某VID和PID的设备时,软件才能运行。因此获取某一类型设备或者全部设备的VID和PID集合至关重要。获取设备VID和PID的一般流程是通过设备接口类GUID创建设备信息集,然后从设备接口详细信息中获取设备路径,再调用HidD_GetAttributes从属性中读取VID和PID。该方法的缺点是需要事先知道设备接口类GUID,且每次只能获取一个设备接口类的VID和PID集合。本方法既可以指定设备安装类GUID和/或设备接口类GUID,也可以两者都不指定而直接创建设备信息集,然后通过设备信息数据获取设备实例ID,并直接从设备实例ID中提取出VID和PID,巧妙地避开了对设备IO的读写。
下载:
源代码:
WDK_VidPidQuery.h
- /* ----------------------------------------------------------
- 文件名称:WDK_VidPidQuery.h
- 作者:秦建辉
- MSN:splashcn@msn.com
- QQ:36748897
- 开发环境:
- Visual Studio V2010
- WinDDK 7600.16385.1
- 版本历史:
- V1.0 2011年09月10日
- 结合设备安装类GUID和设备接口类GUID获取设备VIDPID
- 接口函数:
- WDK_WhoAllVidPid
- WDK_isExistVidPid
- ------------------------------------------------------------ */
- #pragma once
- #include <windows.h>
- #ifndef MACRO_HIDD_VIDPID
- #define MACRO_HIDD_VIDPID
- typedef struct _HIDD_VIDPID
- {
- USHORT VendorID;
- USHORT ProductID;
- } HIDD_VIDPID;
- #endif
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- /*
- 功能:获取系统所有设备的VIDPID
- 入口参数:
- [out] pVidPid:存储返回的VIDPID,会自动过滤掉重复的VIDPID
- [in] iCapacity:存储单元的容量,建议为32
- [in] SetupClassGuid:设备安装类GUID,默认为NULL
- [in] InterfaceClassGuid:设备接口类GUID,默认为NULL
- 返回值:
- 获取到的VID和PID数目
- 优点:
- 直接通过设备实例ID提取VIDPID,从而无需获取设备路径来读写IO。
- */
- INT WINAPI WDK_WhoAllVidPid( HIDD_VIDPID* pVidPid, INT iCapacity, const GUID* SetupClassGuid = NULL, const GUID* InterfaceClassGuid = NULL );
- /*
- 功能:判断指定的VIDPID是否存在于列表中
- 入口参数:
- [in] VendorID:要查找的VID
- [in] ProductID:要查找的PID
- [in] pVidPid:用来检索的VIDPID库
- [in] iSize:VIDPID库大小
- 返回值:
- TRUE:存在
- FALSE:不存在
- */
- BOOL WINAPI WDK_isExistVidPid( USHORT VendorID, USHORT ProductID, const HIDD_VIDPID* pVidPid, INT iSize );
- #ifdef __cplusplus
- }
- #endif
/* ----------------------------------------------------------
文件名称:WDK_VidPidQuery.h
作者:秦建辉
MSN:splashcn@msn.com
QQ:36748897
开发环境:
Visual Studio V2010
WinDDK 7600.16385.1
版本历史:
V1.0 2011年09月10日
结合设备安装类GUID和设备接口类GUID获取设备VIDPID
接口函数:
WDK_WhoAllVidPid
WDK_isExistVidPid
------------------------------------------------------------ */
#pragma once
#include <windows.h>
#ifndef MACRO_HIDD_VIDPID
#define MACRO_HIDD_VIDPID
typedef struct _HIDD_VIDPID
{
USHORT VendorID;
USHORT ProductID;
} HIDD_VIDPID;
#endif
#ifdef __cplusplus
extern "C"
{
#endif
/*
功能:获取系统所有设备的VIDPID
入口参数:
[out] pVidPid:存储返回的VIDPID,会自动过滤掉重复的VIDPID
[in] iCapacity:存储单元的容量,建议为32
[in] SetupClassGuid:设备安装类GUID,默认为NULL
[in] InterfaceClassGuid:设备接口类GUID,默认为NULL
返回值:
获取到的VID和PID数目
优点:
直接通过设备实例ID提取VIDPID,从而无需获取设备路径来读写IO。
*/
INT WINAPI WDK_WhoAllVidPid( HIDD_VIDPID* pVidPid, INT iCapacity, const GUID* SetupClassGuid = NULL, const GUID* InterfaceClassGuid = NULL );
/*
功能:判断指定的VIDPID是否存在于列表中
入口参数:
[in] VendorID:要查找的VID
[in] ProductID:要查找的PID
[in] pVidPid:用来检索的VIDPID库
[in] iSize:VIDPID库大小
返回值:
TRUE:存在
FALSE:不存在
*/
BOOL WINAPI WDK_isExistVidPid( USHORT VendorID, USHORT ProductID, const HIDD_VIDPID* pVidPid, INT iSize );
#ifdef __cplusplus
}
#endif
WDK_VidPidQuery.cpp
- #include "WDK_VidPidQuery.h"
- #include <tchar.h>
- #include <setupapi.h>
- #pragma comment (lib, "Setupapi.lib")
- #define DeviceInstanceIdSize 256 // 设备实例ID最大长度
- // 获取系统的VID和PID集合
- INT WINAPI WDK_WhoAllVidPid( HIDD_VIDPID* pVidPid, INT iCapacity, const GUID* SetupClassGuid, const GUID* InterfaceClassGuid )
- {
- // 检测入口参数
- if (pVidPid == NULL || iCapacity <= 0) return 0;
- // 根据设备安装类GUID创建空的设备信息集合
- HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList( SetupClassGuid, NULL );
- if (DeviceInfoSet == INVALID_HANDLE_VALUE) return -1;
- // 根据设备安装类GUID获取设备信息集合
- HDEVINFO hDevInfo;
- if(InterfaceClassGuid == NULL)
- hDevInfo = SetupDiGetClassDevsEx( NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE | DIGCF_PRESENT, DeviceInfoSet, NULL, NULL );
- else
- hDevInfo = SetupDiGetClassDevsEx( InterfaceClassGuid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT, DeviceInfoSet, NULL, NULL );
- if (hDevInfo == INVALID_HANDLE_VALUE) return -1;
- // 存储得到的VID和PID数目
- INT iTotal = 0;
- // 存储设备实例ID
- TCHAR DeviceInstanceId[DeviceInstanceIdSize];
- // 存储设备信息数据
- SP_DEVINFO_DATA DeviceInfoData;
- DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
- // 获取设备信息数据
- DWORD DeviceIndex = 0;
- while (SetupDiEnumDeviceInfo( hDevInfo, DeviceIndex++, &DeviceInfoData))
- {
- // 获取设备实例ID
- if (SetupDiGetDeviceInstanceId(hDevInfo, &DeviceInfoData, DeviceInstanceId, DeviceInstanceIdSize, NULL))
- {
- // 从设备实例ID中提取VID和PID
- TCHAR* pVidIndex = _tcsstr(DeviceInstanceId, TEXT("VID_"));
- if (pVidIndex == NULL) continue;
- TCHAR* pPidIndex = _tcsstr(pVidIndex + 4, TEXT("PID_"));
- if (pPidIndex == NULL) continue;
- USHORT VendorID = _tcstoul(pVidIndex + 4, NULL, 16);
- USHORT ProductID = _tcstoul(pPidIndex + 4, NULL, 16);
- // 剔除重复的VID和PID
- if (!WDK_isExistVidPid( VendorID, ProductID, pVidPid, iTotal ))
- {
- pVidPid[iTotal].VendorID = VendorID;
- pVidPid[iTotal].ProductID = ProductID;
- if (++iTotal >= iCapacity) break;
- }
- }
- }
- return iTotal;
- }
- // 判断VID和PID是否已经存在
- BOOL WINAPI WDK_isExistVidPid( USHORT VendorID, USHORT ProductID, const HIDD_VIDPID* pVidPid, INT iSize )
- {
- if (pVidPid != NULL)
- {
- for (INT i = 0; i < iSize; i++)
- {
- if (pVidPid[i].VendorID == VendorID && pVidPid[i].ProductID == ProductID)
- return TRUE;
- }
- }
- return FALSE;
- }