手机接入检测及驱动安装判断

#pragma once

#include <string>
#include <vector>
#include <set>

#include <windows.h>
#include <Setupapi.h>
#include <cfgmgr32.h>

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

typedef std::set<std::wstring>  set_wstring;

//
// device operation definitions
//

int detect_phone_device(const std::set<std::wstring>& phone_compatible_ids, 
						const std::set<std::wstring>& phone_hardware_ids, 
						std::wstring& phone_instance_id);
bool is_device_driver_installed(const std::wstring &instance_id);



//
//  Implementions
//
int detect_phone_device(const std::set<std::wstring>& phone_compatible_ids, 
						const std::set<std::wstring>& phone_hardware_ids, 
						std::wstring& phone_instance_id)
{

	DWORD rc = -1;
	//获取设备信息句柄
	HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, L"USB" ,NULL,DIGCF_ALLCLASSES|DIGCF_PRESENT);
	//获取设备信息数据
	SP_DEVINFO_DATA deviceInfoData;
	deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	//对USB设备集进行枚举
	std::vector<std::wstring> compatible_ids;
	for(int i = 0;SetupDiEnumDeviceInfo(hDevInfo,i,&deviceInfoData);i++)			
	{
		std::wstring compatible_id;
		
		//首先获取兼容id
		DWORD dataType= 0;
		DWORD buffSize = 0;
		rc = SetupDiGetDeviceRegistryProperty(hDevInfo,&deviceInfoData,SPDRP_COMPATIBLEIDS,&dataType,NULL,buffSize,&buffSize);
		if(!rc){
			int err = GetLastError();
			if(err != ERROR_INSUFFICIENT_BUFFER)
				//return rc; 
				continue;
		}
		LPTSTR szCompatibleID = (LPTSTR)LocalAlloc(LPTR,buffSize+1);
		rc = SetupDiGetDeviceRegistryProperty(hDevInfo,&deviceInfoData,SPDRP_COMPATIBLEIDS,&dataType,(PBYTE)szCompatibleID ,buffSize,&buffSize);
		//szCompatibleID  即是兼容ID
		compatible_id = szCompatibleID;
		LocalFree(szCompatibleID);

		compatible_ids.push_back(compatible_id);

		//通常情况下,如果兼容ID等于"usb\\class_ff&subclass_42" ,一般就可以直接知道属于是手机设备
		//(但是兼容ID的大小写不确定)
		if(phone_compatible_ids.find(compatible_id) != phone_compatible_ids.end()){
			//兼容id号匹配成功,直接获取instance id
			std::wstring instance_id;
			LPTSTR szInstanceID = NULL;
			DWORD iBuffSize = 0;
			SetupDiGetDeviceInstanceId(hDevInfo,&deviceInfoData,szInstanceID ,iBuffSize,&iBuffSize );	//获取实例ID的buff需要的大小, hDevInfoSet和deviceInfoData
			int err = GetLastError();	
			if(err != ERROR_INSUFFICIENT_BUFFER)
				return -1; 
			szInstanceID = (LPTSTR)LocalAlloc(LPTR,buffSize*sizeof(WCHAR));
			SetupDiGetDeviceInstanceId(hDevInfo,&deviceInfoData,szInstanceID ,iBuffSize ,&iBuffSize );	//获取实例ID
			instance_id = szInstanceID;
			LocalFree(szInstanceID);
			phone_instance_id = instance_id;//copy to phone_instance_id

			rc = 0;
			return rc;
			//break;
		}
	}
	
	//如果 兼容ID 不是 "usb\\class_ff&subclass_42" ,则可以匹配硬件ID,获取硬件ID的方法和获取兼容ID的方法类似:
	//硬件ID 的样子一般的格式是: VID_1234&PID_4321  (1234,4321根据设备有差异,其中VID代表Vendor ID(厂家ID) , PID代表Product ID(产品ID)),
	//VID基本一个厂商. 这个需要收集,但是网上好像有一些VID_PID大全可以满足一般使用.
	//(其中VID只能判断厂商,有些手机生产商也有别的设备产品,比如索尼有手机也有相机,所以需要进一步详细判断.

	std::vector<std::wstring> hardware_ids;
	for(int i = 0;SetupDiEnumDeviceInfo(hDevInfo,i,&deviceInfoData);i++)		
	{
		std::wstring  hardware_id;

		DWORD dataType= 0;
		DWORD buffSize = 0;
		rc = SetupDiGetDeviceRegistryProperty(hDevInfo,&deviceInfoData,SPDRP_HARDWAREID,&dataType,NULL,buffSize,&buffSize);
		int err = GetLastError();
		if(err != ERROR_INSUFFICIENT_BUFFER)
			//return rc; 
			continue;
		LPTSTR szHardwareID = (LPTSTR)LocalAlloc(LPTR,buffSize+1);
		rc = SetupDiGetDeviceRegistryProperty(hDevInfo,&deviceInfoData,SPDRP_HARDWAREID,&dataType,(PBYTE)szHardwareID ,buffSize,&buffSize);
		//szHardwareID 即是硬件ID
		hardware_id = szHardwareID;
		LocalFree(szHardwareID);
		hardware_ids.push_back(hardware_id);
	
		if(phone_hardware_ids.find(hardware_id) != phone_hardware_ids.end()){
				//如果硬件id匹配成功,获取instance id
			std::wstring instance_id;
			LPTSTR szInstanceID = NULL;
			DWORD iBuffSize = 0;
			SetupDiGetDeviceInstanceId(hDevInfo,&deviceInfoData,szInstanceID ,iBuffSize,&iBuffSize );	//获取实例ID的buff需要的大小, hDevInfoSet和deviceInfoData
			int err = GetLastError();	
			if(err != ERROR_INSUFFICIENT_BUFFER)
				return -1; 
			szInstanceID = (LPTSTR)LocalAlloc(LPTR,buffSize*sizeof(WCHAR));
			SetupDiGetDeviceInstanceId(hDevInfo,&deviceInfoData,szInstanceID ,iBuffSize ,&iBuffSize );	//获取实例ID
			instance_id = szInstanceID;
			LocalFree(szInstanceID);
			phone_instance_id = instance_id;//copy to phone_instance_id

			rc = 0;
			return rc;
		}

	}

	//手机设备要记录下该设备的 "实例ID" ,
	//std::vector<std::wstring> instance_ids;
	//for(int i = 0;SetupDiEnumDeviceInfo(hDevInfo,i,&deviceInfoData);i++)
	//{
	//	LPTSTR szInstanceID = NULL;
	//	WORD iBuffSize = 0;
	//	SetupDiGetDeviceInstanceId(hDevInfo,&deviceInfoData,szInstanceID ,iBuffSize,&iBuffSize );	//获取实例ID的buff需要的大小, hDevInfoSet和deviceInfoData
	//	int err = GetLastError();	
	//	if(err != ERROR_INSUFFICIENT_BUFFER)
	//		return -1; 
	//	szInstanceID = (LPTSTR)LocalAlloc(LPTR,buffSize*sizeof(WCHAR));
	//	SetupDiGetDeviceInstanceId(hDevInfo,&deviceInfoData,szInstanceID ,iBuffSize ,&iBuffSize );	//获取实例ID
	//	instance_ids.push_back(szInstanceID);
	//	LocalFree(szInstanceID);
	//}

	rc = 0;
	return rc;
}

//检查指定实例id号的设备驱动是否安装
bool is_device_driver_installed(const std::wstring &instance_id){
	bool is_installed = false;
	DEVINST deviceInstance;
	if (CM_Locate_DevNode(&deviceInstance, const_cast<WCHAR*>(instance_id.c_str() ),CM_LOCATE_DEVNODE_NORMAL) == CR_SUCCESS)			//获取设备ID对应的设备实例句柄
	{ 
		DWORD status;
		DWORD problemNumber;
		//获取设备状态和设备状态细节
		if (CM_Get_DevNode_Status(&status,&problemNumber,deviceInstance,0) == CR_SUCCESS)	
		{ 
			if (!(status&DN_HAS_PROBLEM))	//判断设备是否存在问题,代表驱动已安装
			{ 
				//设备无异常,就是说驱动正常 
				is_installed = true;
			} 
			else 
			{ 
				if (problemNumber == CM_PROB_DRIVER_FAILED_PRIOR_UNLOAD || problemNumber == CM_PROB_DRIVER_FAILED_LOAD)	
				{ 
					//设备驱动加载不成功 
					is_installed = false;
				} 
				else 
				{ 
					//有不明原因,可以归结为没安装驱动 
					is_installed = false;
				} 
			} 
		} 

	} 

	return is_installed;
} 

以NOKIA 925T型号手机 的信息 ,调用测试:

        set_wstring compatible_ids, hardware_ids;
	compatible_ids.insert(L"USB\\MS_COMP_WINUSB");
	compatible_ids.insert(L"USB\\Class_ff&SubClass_ff&Prot_ff");
	compatible_ids.insert(L"USB\\Class_ff&SubClass_ff");
	compatible_ids.insert(L"USB\\Class_ff");
	//hardware ids
	hardware_ids.insert(L"USB\\VID_0421&PID_0661&MI_03");
	hardware_ids.insert(L"USB\\VID_0421&PID_0661&REV_0100&MI_03");

	std::wstring phone_instance_id;
	int rc = detect_phone_device(compatible_ids, hardware_ids, phone_instance_id);
	bool is_installed = is_device_driver_installed(phone_instance_id);



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值