想要实现类似设备管理器的功能,其实也不是很难,无非就是调用一些API函数,就像本文描述的,采用的API函数就是SetupDi系列的函数。不过这类函数有很多,具体的请参见MSDN,而实现设备启用、停用仅需要用到的就只有5个函数:
SetupDiGetClassDevs // 获取设备信息集
SetupDiEnumDeviceInfo // 从设备信息集中枚举每个设备的具体信息
SetupDiGetDeviceRegistryProperty // 从注册表中读取PnP设备的属性
SetupDiSetClassInstallParams // 设置(包括取消)设备类的安装参数
SetupDiCallClassInstaller // 安装指定设备
以上函数均在setupapi.h头文件中声明,该头文件包含在setupapi.lib函数库中(使用以上函数前需要声明这个头文件)。
接下来就是如何实现设备的启用与停用。
从原理上讲,设备的启用与停用其实就是对该设备进行重安装。
首先,我们需要声明两个变量用来保存指定设备类的属性信息:
HDEVINFO m_hDevInfo; // 类似设备句柄,以下暂且称为设备句柄
SP_DEVINFO_DATA m_DeviceInfoData; // 设备详细属性信息
然后调用SetupDiGetClassDevs函数获取设备句柄的值。(在这个函数中,需要指定设备类的GUID,如果不清楚这个GUID,可以在相应的安装文件.inf中查找。注意:是设备类的GUID,不是设备的GUID!)
接着循环使用SetupDiEnumDeviceInfo函数枚举对应设备类中的设备,并使用SetupDiGetDeviceRegistryProperty函数获取得到的设备的详细信息,进行判断是否为所需的设备(判断的方式有多种,具体参考MSDN,本文采用设备描述进行判断)。
一旦枚举结束(即枚举不成功,而且用GetLastError()可以得到错误码259)即可退出循环。当然如果找到设备,即可break退出。
如果找到对应的设备,就调用SetupDiSetClassInstallParams函数设置安装的属性。这里有个注意的地方需要详细说明一下:
SetupDiSetClassInstallParams的函数原型如下:
WINSETUPAPI BOOL WINAPI
SetupDiSetClassInstallParams(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
IN PSP_CLASSINSTALL_HEADER ClassInstallParams, OPTIONAL
IN DWORD ClassInstallParamsSize
);
注意第三个参数PSP_CLASSINSTALL_HEADER ClassInstallParams,
这里我们不采用这个结构,而是采用另外一个结构:SP_PROPCHANGE_PARAMS
并在这个结构中,
设置ClassInstallHeader字段中(我们发现这个字段也是一个结构,就是PSP_CLASSINSTALL_HEADER结构)的InstallFunction字段值为DIF_PROPERTYCHANGE,
设置StateChange值为DICS_ENABLE(该值为启用,若是停用则为DICS_DISABLE)
然后采用强行转换将其转为PSP_CLASSINSTALL_HEADER结构。
最后,调用SetupDiCallClassInstaller函数执行设备的安装(即:启用或者停用),注意该函数第一个参数值应为DIF_PROPERTYCHANGE。
从设备管理器中,可以验证我们的做法。
ON_WM_DEVICECHANGE() 消息可以检测到设备插拔
BOOL CDirverDemoDlg::OnDeviceChange( UINT nEventType, DWORD dwData )
{
m_mobileDevice.Analysis();
if(nEventType == DBT_DEVICEARRIVAL) //插入事件
//AfxMessageBox(_T("插入设置")) ;
if(nEventType == DBT_DEVICEREMOVECOMPLETE) //弹出事件
//AfxMessageBox(_T("弹出设置")) ;
return TRUE;
}
Windows设备的具体属性
#define SPDRP_DEVICEDESC (0x00000000)
// DeviceDesc (R/W)
//设备描述,如:Realtek RTL8139 Family PCI Fast Ethernet NIC,Intel(R) PRO/100 VE Network Connection
#define SPDRP_HARDWAREID (0x00000001)
// HardwareID (R/W)
//硬件ID(如:PCI/VEN_10EC&DEV_8139&SUBSYS_813910EC&REV_10,PCI/VEN_10EC&DEV_8139&SUBSYS_813910EC&REV_10, PCI/VEN_8086&DEV_1039&SUBSYS_026A1014&REV_81)
#define SPDRP_COMPATIBLEIDS (0x00000002)
// CompatibleIDs (R/W)
(如:PCI/VEN_10EC&DEV_8139&REV_10,PCI、VEN_8086&DEV_1039&REV_81)
#define SPDRP_NTDEVICEPATHS (0x00000003)
// Unsupported, DO NOT USE
#define SPDRP_SERVICE (0x00000004)
// Service (R/W)
(如:rtl8139、E100B)
#define SPDRP_CONFIGURATION (0x00000005)
// Configuration (R)
(如:其它)
#define SPDRP_CONFIGURATIONVECTOR (0x00000006)
// ConfigurationVector (R)
(如:其它)
#define SPDRP_CLASS (0x00000007)
// Class (R--tied to ClassGUID)
(如:Net)
#define SPDRP_CLASSGUID (0x00000008)
// ClassGUID (R/W)
//设备的类别标识(如:网卡{4D36E972-E325-11CE-BFC1-08002BE10318})
#define SPDRP_DRIVER (0x00000009)
// Driver (R/W)
//(如:{4D36E972-E325-11CE-BFC1-08002BE10318}/0016)
#define SPDRP_CONFIGFLAGS (0x0000000A)
// ConfigFlags (R/W)
(如:其它)
#define SPDRP_MFG (0x0000000B)
// Mfg (R/W)
//供应商的名称
#define SPDRP_FRIENDLYNAME (0x0000000C)
// FriendlyName (R/W)
//直观的名字
#define SPDRP_LOCATION_INFORMATION (0x0000000D)
// LocationInformation (R/W)
//本地环境属性(如:PCI 总线 2、设备 10、功能 0)
#define SPDRP_PHYSICAL_DEVICE_OBJECT_NAME (0x0000000E)
// PhysicalDeviceObjectName (R)
//(如:/Device/NTPNP_PCI0012)
#define SPDRP_CAPABILITIES (0x0000000F)
// Capabilities (R)
(如:其它)
#define SPDRP_UI_NUMBER (0x00000010)
// UiNumber (R)
(如:其它)
#define SPDRP_UPPERFILTERS (0x00000011)
// UpperFilters (R/W)
(如:其它)
#define SPDRP_LOWERFILTERS (0x00000012)
// LowerFilters (R/W)
(如:其它)
#define SPDRP_MAXIMUM_PROPERTY (0x00000013)
// Upper bound on ordinals
(如:其它)
GUID_DEVCLASS_FDC 软盘控制器
GUID_DEVCLASS_DISPLAY 显示卡
GUID_DEVCLASS_CDROM 光驱
GUID_DEVCLASS_KEYBOARD 键盘
GUID_DEVCLASS_COMPUTER 计算机
GUID_DEVCLASS_SYSTEM 系统
GUID_DEVCLASS_DISKDRIVE 磁盘驱动器
GUID_DEVCLASS_MEDIA 声音、视频和游戏控制器
GUID_DEVCLASS_MODEMMODEM
GUID_DEVCLASS_MOUSE 鼠标和其他指针设备
GUID_DEVCLASS_NET 网络设备器
GUID_DEVCLASS_USB 通用串行总线控制器
GUID_DEVCLASS_FLOPPYDISK 软盘驱动器
GUID_DEVCLASS_UNKNOWN 未知设备
GUID_DEVCLASS_SCSIADAPTER SCSI 和 RAID 控制器
GUID_DEVCLASS_HDCIDE ATA/ATAPI 控制器
GUID_DEVCLASS_PORTS端口 (COM 和 LPT)
GUID_DEVCLASS_MONITOR 监视器