SetupAPI简介与设备管理
来源:互联网 发布:最新软件代理 编辑:程序博客网 时间:2024/05/17 06:06
SetupAPI简介与设备管理
SetupAPI的定位
SetupAPI是一个被用来执行安装设备的一系列操作的方法的集合,主要用于安装设备驱动(device driver),被用在类安装程序(class installers)、协安装程序(co-installers)和设备安装应用程序(device installation applications)中。
下图描绘了设备安装过程中的组件,也包括SetupAPI在其中所扮演的角色
原文请进
SetupAPI Functions Set
SetupAPI的方法集分为两大部分:
General setup functions
- 读取和处理INF文件
- 确定安装在目标系统上所需的可用空间大小
- 将文件从源介质移至所安装的目标系统的介质上,如果需要的话要求用户介入
- 创建在安装期间移动的文件的日志
- 将日志条目写入SetupAPI text logs
更多关于using-general-setup-functions
Device installation functions
- 安装驱动
- 处理DIF代码
- 管理设备信息集
- 管理驱动列表
- 管理设备接口
- 管理图标以及其它的位图
更多关于using-device-installation-functions
SetupAPI与枚举设备
从上一节中可见SetupAPI的方法集中有专门的一部分用以管理设备信息集。那么接下来,首先要做的就是最简单的功能——枚举设备信息。I
在SetupAPI中利用设备信息集(Device Information Sets)这样一种结构来组织各个设备的信息
更多关于device-information-sets
当需要获取一个或多个设备的描述信息时,必须先创建一个设备信息集,然后通过枚举列表中元素的方式获取设备信息元素(Device Information Element),进而获得所需的设备信息。
/************************************** BOOL EnumAllDevice( )* 功能 列举当前存在的设备* 返回值 是否成功**************************************/BOOL EnumAllDevice(){ HDEVINFO hDevInfo; //包含了设备的ClassGUID和设备实例句柄,大体上相当于设备信息元素(无device interface) SP_DEVINFO_DATA DeviceInfoData; DWORD i; printf("Displaying the Installed Devices\n\n"); TCHAR szGUID[] = _T("4D36E97C-E325-11CE-BFC1-08002BE10318"); GUID guid; //全局唯一标识符(GUID,Globally Unique Identifier) UuidFromString((RPC_WSTR)szGUID, &guid); //创建一个设备信息集(device information set),其中包含了我们请求的设备信息元素(device information element) //该方法只用于获取本机设备,远程计算机上的设备需要使用SetupDiGetClassDevsEx //成功则返回一个设备信息集的Handle,失败则返回INVALID_HANDLE_VALUE hDevInfo = SetupDiGetClassDevs( &guid, // 指定一个GUID(for a device setup class or a device interface class)用以过滤元素 0, // Enumerator 可为NULL 0, // hwndParent 可为NULL DIGCF_PRESENT | DIGCF_ALLCLASSES ); //列表的过滤选项,当为DIGCF_ALLCLASSES时,参数1指定的guid将不再起作用 if (hDevInfo == INVALID_HANDLE_VALUE) { return FALSE; } // 循环列举 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); //枚举设备信息列表中的元素,将元素以SP_DEVINFO_DATA结构体的方式输出 for (i=0;SetupDiEnumDeviceInfo(hDevInfo,i, &DeviceInfoData);i++) { DWORD DataT; LPTSTR buffer = NULL; DWORD buffersize = 0; // 获取详细信息 while (!SetupDiGetDeviceRegistryProperty( hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC, //属性标识,用以指示buffer输出的是哪个属性值,在此是要求输出设备描述字符串 &DataT, (PBYTE)buffer, //输出值 buffersize, &buffersize)) //所需的buff空间 { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // 内存不足,则重新分配buff空间 if (buffer) HeapFree(GetProcessHeap(), 0, buffer); buffer = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, buffersize); } else break; } // 输出 wprintf(L"GUID:{%.8X-%.4X-%.4X--%.2X%.2X-%.2X%.2X%.2X%.2X%.2X%.2X} \tDevice: %s\n", DeviceInfoData.ClassGuid.Data1, DeviceInfoData.ClassGuid.Data2, DeviceInfoData.ClassGuid.Data3, DeviceInfoData.ClassGuid.Data4[0], DeviceInfoData.ClassGuid.Data4[1], DeviceInfoData.ClassGuid.Data4[2], DeviceInfoData.ClassGuid.Data4[3], DeviceInfoData.ClassGuid.Data4[4], DeviceInfoData.ClassGuid.Data4[5], DeviceInfoData.ClassGuid.Data4[6], DeviceInfoData.ClassGuid.Data4[7], buffer); if (buffer) HeapFree(GetProcessHeap(), 0, buffer); } if ( GetLastError() != NO_ERROR && GetLastError() != ERROR_NO_MORE_ITEMS ) { return FALSE; } // 释放 SetupDiDestroyDeviceInfoList(hDevInfo); return TRUE;}
Device Setup Class 和 Device Interface Class之间的区别 在于:
To facilitate device installation, devices that are set up and configured in the same manner are grouped into a device setup class.
更多关于device-setup-class
Device Setup Class是对于设备的安装进行分类,在安装过程中具有相同方式的设备被分为一类。一个设备的Device Setup Class决定了在安装过程中哪个类安装程序(class installer)和协安装程序(co-installers)将会参与进来。
A device interface class is a way of exporting device and driver functionality to other system components, including other drivers, as well as user-mode applications. A driver can register a device interface class, then enable an instance of the class for each device object to which user-mode I/O requests might be sent.
更多关于device-interface-class
Device Interface Class是在设备的使用过程中,对具有同样功能的设备进行的分类。驱动不再为每个设备单独命名,并将该名字交由用户模式下的程序来进行I/O请求,相反,对某个设备的直接请求转化为对该类的请求,也就是说,在请求一个打印机类打印文件的时候,用户将无法预测实际上是哪一台打印机实际打印了文件(当然,我们有多台打印机)。
禁用和开启设备
无论开启或禁用,都需要调用SetupAPI中的两个函数: SetupDiSetClassInstallParams
和 SetupDiCallClassInstaller
前者 用于设置类安装参数,后者用于调用类安装程序和任何注册过的协安装程序。
BOOL SetupDiSetClassInstallParams( _In_ HDEVINFO DeviceInfoSet, _In_opt_ PSP_DEVINFO_DATA DeviceInfoData, _In_opt_ PSP_CLASSINSTALL_HEADER ClassInstallParams, _In_ DWORD ClassInstallParamsSize);
SetupDiSetClassInstallParams
函数的核心在于第三个参数。
PSP_CLASSINSTALL_HEADER
是任何类安装参数(class install parameter)的第一个成员,里面主要内容是一个 DI_FUNCTION
类型的设备安装方法(DIF,Device Installation Function),且被定义为 DIF_XXX
的形式。
这里的 ClassInstallParams
要填入的也就是一个类安装参数的指针,当然它的第一个成员必须是 PSP_CLASSINSTALL_HEADER
。参数4的size指的是整个类安装参数的大小而不仅仅是 PSP_CLASSINSTALL_HEADER
的大小。
BOOL SetupDiCallClassInstaller( _In_ DI_FUNCTION InstallFunction, _In_ HDEVINFO DeviceInfoSet, _In_opt_ PSP_DEVINFO_DATA DeviceInfoData);
这是改变设备状态的代码,如下:
BOOL StateChange( DWORD dwNewState, DWORD dwDevID, HDEVINFO hDevInfo){ SP_PROPCHANGE_PARAMS PropChangeParams; SP_DEVINFO_DATA DevInfoData = {sizeof(SP_DEVINFO_DATA)}; SP_DEVINSTALL_PARAMS devParams; //查询设备信息 if (!SetupDiEnumDeviceInfo( hDevInfo, dwDevID, &DevInfoData)) { OutputDebugString("SetupDiEnumDeviceInfo FAILED"); return FALSE; } //设置设备属性变化参数 PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; PropChangeParams.Scope = DICS_FLAG_GLOBAL; //使修改的属性保存在所有的硬件属性文件 PropChangeParams.StateChange = dwNewState; PropChangeParams.HwProfile = 0; //改变设备属性 if (!SetupDiSetClassInstallParams( hDevInfo, &DevInfoData, (SP_CLASSINSTALL_HEADER *)&PropChangeParams, sizeof(PropChangeParams))) { OutputDebugString("SetupDiSetClassInstallParams FAILED"); return FALSE; } PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; PropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC;//使修改的属性保存在指定的属性文件 PropChangeParams.StateChange = dwNewState; PropChangeParams.HwProfile = 0; //改变设备属性并调用安装服务 if (!SetupDiSetClassInstallParams( hDevInfo, &DevInfoData, (SP_CLASSINSTALL_HEADER *)&PropChangeParams, sizeof(PropChangeParams)) ||!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &DevInfoData)) { OutputDebugString("SetupDiSetClassInstallParams or SetupDiCallClassInstaller FAILED"); return TRUE; } else { //判断是否需要重新启动 devParams.cbSize = sizeof(devParams); if (!SetupDiGetDeviceInstallParams( hDevInfo, &DevInfoData, &devParams)) { OutputDebugString("SetupDiGetDeviceInstallParams FAILED"); return FALSE; } if (devParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT)) { OutputDebugString("Need Restart Computer"); return TRUE; } return TRUE; }}
这里的类安装参数为 SP_PROPCHANGE_PARAMS
结构体,其 StateChange
参数指定了状态改变的动作,有 DICS_ENABLE
、 DICS_DISABLE
、 DICS_PROPCHANGE
、 DICS_START
、 DICS_STOP
可选。
更多关于SP_PROPCHANGE_PARAMS
我们需要实现的禁用和开启,不过是将 PropChangeParams.StateChange
设为 DICS_DISABLE
和 DICS_ENABLE
。
- SetupAPI简介与设备管理
- 设备管理项目通用性研究与开发(1)项目简介
- 安全标志与设备管理
- 设备管理与维护TPM
- 存储设备管理与分区
- 设备管理
- 设备管理
- 设备管理
- 设备管理
- 设备管理
- 设备管理
- 设备管理
- 设备管理
- 设备管理
- 设备管理
- 设备管理
- 设备管理
- 设备管理
- 网络编程调参学习————三次握手中的接收缓存和通告窗口
- 引导页
- Redis学习——Redis事务
- SpringMvc @InitBinder 表单多对象精准绑定接收
- Docker的四种网络模式
- SetupAPI简介与设备管理
- centos学习:理解main函数的两个参数
- 《200行Python代码实现2048》分析
- CakePHP中的批量保存及批量更新
- 移动端屏幕适配的解决
- Thinking in java 笔记(更新中)
- Java Lambda(语言篇——lambda,方法引用,目标类型,默认方法,函数接口,变量捕获)
- 第八课、数组
- 014--利用模型的didSet属性给UI赋值