C/C++实现遍历当前设备

最近需要对一个加密狗进行检测,设备信息如下:

看到 HID#Vid_3689&Pid_8762 这一段,觉得可以先遍历所有的设备:

然后再筛选出里面所有的 HID 类型的设备:

最后判断这个设备的 Pid 和 Vid 是否和黑名单匹配。

下面是代码:

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <iomanip>
#include <fstream>
#include <cstdlib>
#include <string>
#include <mutex>
#include <atlbase.h>
#include <atlconv.h>
#include <SetupAPI.h>


extern "C"{
#include <hidsdi.h> // 无法解析的外部符号 HidD_GetAttributes、HidD_GetHidGuid
}

#pragma comment(lib,"hid.lib")
#pragma comment(lib,"Setupapi.lib")

using namespace std;


void EnumHIDDevice()
{
// 获取 HID 类型设备信息集句柄
GUID HidGuid;
HidD_GetHidGuid(&HidGuid);
HDEVINFO hdev = SetupDiGetClassDevs(
&HidGuid, // 只查找 HID 类型设备(查找所有则设置为NULL,并修改 Flag 参数)
NULL, // 枚举指定类型的设备
NULL, // 设备关联的顶级窗口句柄
DIGCF_DEVICEINTERFACE | // 指定设备接口
DIGCF_PRESENT // 只返回当前系统中存在的设备
);if(hdev == INVALID_HANDLE_VALUE){cout << "SetupDiGetClassDevs failed : " << GetLastError() << endl;}

// 遍历 HID 设备
int idev = 0;
while(TRUE){
// 初始化 SP_DEVICE_INTERFACE_DATA
SP_DEVICE_INTERFACE_DATA did = {0};
did.cbSize = sizeof(did);
if(!SetupDiEnumDeviceInterfaces(
hdev, // 设备信息集句柄
NULL, // 枚举所有设备接口(不限制类型)
&HidGuid, // 接收接口GUID
idev, // 下标
&did // [OUT] 指向 SP_DEVICE_INTERFACE_DATA 结构体的指针
)){cout << "SetupDiEnumDeviceInterfaces failed : " << GetLastError() << endl;break;}


// 初始化 SP_DEVICE_INTERFACE_DETAIL_DATA
DWORD buf_didd = 256;
PSP_DEVICE_INTERFACE_DETAIL_DATA pdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR,buf_didd);
pdidd->cbSize = sizeof(*pdidd);
if(!SetupDiGetDeviceInterfaceDetail(
hdev, // 设备信息集句柄
&did, // SP_DEVICE_INTERFACE_DATA 结构体的指针
pdidd, // [OUT] SP_DEVICE_INTERFACE_DETAIL_DATA
buf_didd, // SP_DEVICE_INTERFACE_DETAIL_DATA 对应的缓冲区大小
NULL, // [OUT] SP_DEVICE_INTERFACE_DATA 缓冲区大小
NULL
)){cout << "SetupDiGetDeviceInterfaceDetail failed : " << GetLastError() << endl;}
cout << "pdidd->DevicePath = " << pdidd->DevicePath << endl;

// 创建设备
HANDLE hDevHandle = CreateFile(
pdidd->DevicePath, // 设备名称
GENERIC_READ | GENERIC_WRITE, // 访问权限
FILE_SHARE_READ | FILE_SHARE_WRITE, // 分享权限
NULL, // 返回的句柄不能被继承
OPEN_EXISTING, // 仅当设备存在时打开
FILE_ATTRIBUTE_NORMAL, // 不设置其他属性
NULL // 不设置扩展属性
);if(INVALID_HANDLE_VALUE == hDevHandle){cout << "CreateFile failed : " << GetLastError() << endl;}

// 获取设备接口的 PID、VID
HIDD_ATTRIBUTES hidAttributes = {0};
hidAttributes.Size = sizeof(hidAttributes);
if (!HidD_GetAttributes(
hDevHandle, // 设备句柄
&hidAttributes // [OUT] HIDD_ATTRIBUTES 结构体指针
)){cout << "HidD_GetAttributes failed : " << GetLastError() << endl;}

// 判断域之天加密狗:USB\\VID_3689&PID_8762
cout << "hidAttributes.ProductID = " << hidAttributes.ProductID << endl;
cout << "hidAttributes.VendorID = " << hidAttributes.VendorID << endl;
if(hidAttributes.ProductID == 8762 && hidAttributes.VendorID == 3689){
cout << "发现域之天加密狗" << endl;
}

// 清理
CloseHandle(hDevHandle);
LocalFree(pdidd);

idev++;
cout << endl;
}

// 清理
SetupDiDestroyDeviceInfoList(hdev);
}


int _tmain(int argc, _TCHAR* argv[])
{
EnumHIDDevice();

getchar();
return 0;
}

效果图:(我现在没有加密狗,自然检测不到咯 😕)