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;
}

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

posted @   lyshark  阅读(528)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构

loading... | loading...
博客园 - 开发者的网上家园

点击右上角即可分享
微信分享提示