使用SetupDI* API列举系统中的设备

原创 2006年06月15日 21:28:00
Instroduction
在Windows系统中提供一组有用的函数来撷取以安装设备(Device)的信息与增加或解除设备(Device)的安装。在本文中,我将显示如何使用SetupDIXXX与CM_XXX 等API来列举本机上的设备。
在范例程序中并无复杂的画面,只有一个简单的TreeViewListView控件。TreeLivew控件用来显示所有安装的设备名称,ListView控件则用来显示在TreeView控件中所指定项目的相关信息。所有设备的相关信息(例如:名称,资源与图示等)都是从SetupDiXXX API中所取得的。

SetupDiXXX

设定安装程序接口(Setup Application Programming Interface)提供一组函数来让您的设定安装程序能执行安装的动作或取得设备的相关信息,类别(Class)与它的GUID值。
首先要取的所列举的设备的位图(Bitmap),我们可以呼叫以下的函数:
SetupDiGetClassImageList([OUT]CLASSIMAGELIST_DATA ClassImageListData);
呼叫这个函数会取得每一个已安装设备的位图并建立位图串行。
SetupDiDestroyClassImageList([IN] PSP_CLASSIMAGELIST_DATA
                                                            ClassImageListData);
呼叫这个函数会释放之前呼叫SetupDiGetClassImageList所占有的资源。
SetupDiGetClassImageIndex([IN] PSP_CLASSIMAGELIST_DATA
                                                                       ClassImageListData,
                                           [IN] LPGUID ClassGuid,
                                           [OUT] PINT ImageIndex);
呼叫这个函数会取得每一个已安装设备的位图的索引值。
hDevInfo = SetupDiGetClassDevs(0L, 0L, _hDlg, DIGCF_PRESENT |
                                                    DIGCF_ALLCLASSES | DIGCF_PROFILE);
取得设备的信息。首次呼叫时,第一个参数与第二个参数将它们设为”0,而第三个参数则设定DIGCF_ALLCLASSES旗标,设定此旗标代表要取得所有设备的信息。如果有设定此旗标此时第一个参数将会被忽略。
Geting the Info
呼叫SetupDiEnumDeviceInfo来列举本机上所有的设备。
SetupDiEnumDeviceInfo(hDevInfo, wIndex, &spDevInfoData))
第一个参数为之前呼叫SetupDiGetDevs函数所传回的代码(Handle)。第二个参数为以”0”为基底的索引值,第三个参数为指向SP_DEVINFO_DATA结构的指针。使用此结构时须先设定结构大小。
                spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
SetupDiGetDeviceRegistryProperty(hDevInfo,
                                        &spDevInfoData,
// Supplies one of the following values, indicating the property to be retrieved.
                                        SPDRP_CLASS,
                                        0L,
                                        (PBYTE)szBuf,
                                        2048,
                                        0);
呼叫SetupDiGetDeviceRegistreProperty函数从Registry中取得设备名称。第三个参数为指定要取得何种信息。
Device Resource

在系统中所有的设备会与类别设备结合在一起。请参下图。这个类别可以是GUID(可以在Registry中寻获)或是设备的描述。例如:”Ports”类别是描述(COMLPT)

要取得目前的设备的结构(Configuartion)我们可以呼叫CM_Get_First_Log_Conf函数来取得。然后呼叫CM_Get_Next_res_Des来取得目前设备结构的描述,重复呼叫直到浏览完所有的结构为止。

当此函数成功执行后,我们接着呼叫CM_Get_Res_Des_Data函数来取的资源的数据。

要安装驱动程序,我们可以透过Service API来达成,如果要安装WDM的程序,此时呼叫SetupDiGetINFClass函数先取得此驱动的GUID值,在呼叫SetupDiCreateDeviceInfoList来建立一个新的设备。如下列片断程序代码:
    if (!SetupDiGetINFClass(szINFName, &guid, className, MAX_CLASS_NAME_LEN, 0)){
        ShowErrorMsg(_hDlg, GetLastError(), "SetupDiGetINFClass");
        return 0;
    };
    hDevInfo = SetupDiCreateDeviceInfoList(&guid, 0);
    if (hDevInfo == (void*)-1) {
        ShowErrorMsg(_hDlg, GetLastError(), "SetupDiCreateDeviceInfoList");
        return 0;
    };
    spDevData.cbSize = sizeof(SP_DEVINFO_DATA);
    if (!SetupDiCreateDeviceInfo(hDevInfo,
                                 className,
                                 &guid,
                                 0L, 0L, DICD_GENERATE_ID,
                                 &spDevData))
                         
                         
                         
接下来我们要呼叫SetupDiSetDeviceRegistryProperty函数来设定Registry中的内容。设定完成后,呼叫SetupDiCallClassInstaller函数依据Registry的内容来安装驱动程序。最后呼叫UpdateDriverForPlugAndPlayDevices函数来更新设备串行的内容。
if (!SetupDiSetDeviceRegistryProperty(hDevInfo,
                                       &spDevData,
                                       SPDRP_HARDWAREID,
                                       (PBYTE)pHID,
                           (strlen(_szHardware[wLoop])*2*sizeof(char)))) {
            ShowErrorMsg(_hDlg, GetLastError(), "SetupDiSetDeviceRegistryProperty");
            SetupDiDestroyDeviceInfoList(hDevInfo);
            LocalFree(pHID);
            return 0;
        };
        if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE,
                                       hDevInfo, &spDevData)) {
            ShowErrorMsg(_hDlg, GetLastError(), "SetupDiCallClassInstaller");
            SetupDiDestroyDeviceInfoList(hDevInfo);
            LocalFree(pHID);
            return 0;
        };
        bRebootRequired = 0;
        if (!UpdateDriverForPlugAndPlayDevices(0L, _szHardware[wLoop],
                         
                         
                         
本文就此结束,希望对您会有帮助。原始程序,我已放在http://www.codeproject.com/useritems/SimpleSetup.asp中,如果有兴趣请自行下载。

如何安装一个设备驱动程序[转]

本质上,安装驱动需要依靠UpdateDriverForPlugAndPlayDevices这个函数。它需要的参数其实不多,主要是INF文件路径等。BOOL WINAPIUpdateDriverForP...
  • immcss
  • immcss
  • 2009年08月06日 14:02
  • 3808

C++程序安装卸载WDM驱动

编译环境:VS2012 + WIN8 64 测试环境:VM WIN7 测试对象:WDM驱动 (sys文件 和 inf文件) 项目类型:Win32 Console Application 代码如下...
  • whatday
  • whatday
  • 2013年07月31日 21:56
  • 8615

代码实现利用inf文件安装硬件驱动

代码参考了网上资料并进行了整理: #include "stdafx.h" #include // Make all functions UNICODE safe. #include // f...
  • anda0109
  • anda0109
  • 2015年12月05日 12:36
  • 2905

SetupDiCallClassInstaller处理流程

MS将于今年10月推出win10 RS3 RTM版,并要求OEM厂商的驱动程序必须支持新的D/C/H/U驱动框架(微软爸爸一声令下,苦了我们)。其中的"C"项要求过滤驱动的inf文件必须以扩展INF(...
  • lixiangminghate
  • lixiangminghate
  • 2017年08月24日 23:31
  • 368

整理SetupDixxx函数

前几天写了两篇关于Pnp管理器的博文,在继续写相关博文前我想整理一下Pnp管理器在用户态导出的功能,也就是我们熟悉的windows设备管理器。为什么说windows设备管理器是Pnp管理器导出在用户态...
  • lixiangminghate
  • lixiangminghate
  • 2016年07月02日 18:05
  • 1378

用SetUpDi系列函数获得系统设备信息

用SetupDi系列函数可以获得系统中一些设备的信息。1  SetupDiGetClassDevs函数       MSDN中这样描述:The SetupDiGetClassDevs function...
  • danxuezx
  • danxuezx
  • 2009年12月27日 12:04
  • 13819

设备接口列举(备忘)常用手法

一般列举设备驱动都是安装程序需要完成的工作 HDEVINFO SetupDiCreateDeviceInfoList(     IN LPGUID ClassGuid, OPTIONAL    ...
  • rocispeng
  • rocispeng
  • 2012年11月06日 18:38
  • 727

安装驱动程序(1)----驱动预安装

前面toaster驱动程序的安装都是通过手动安装的方式,把sys/inf等文件安装到系统中。说实话,这么复杂的过程除了开发者,其他人能流畅的安装上驱动还真是天方夜谭了。如果读者曾在电脑城买过电脑配件,...
  • lixiangminghate
  • lixiangminghate
  • 2016年07月31日 16:00
  • 1805

C++程序安装卸载WDM驱动

编译环境:VS2012 + WIN8 64 测试环境:VM WIN7 测试对象:WDM驱动 (sys文件 和 inf文件) 项目类型:Win32 Console Application 代码如下...
  • whatday
  • whatday
  • 2013年07月31日 21:56
  • 8615

根据GUID类别获取设备信息

BOOL EnumClassDevice( const GUID * InterfaceClassGuid, vector &sDevPath) { HDEVINFO DeviceInfoSet;...
  • md521
  • md521
  • 2012年11月14日 10:48
  • 3758
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用SetupDI* API列举系统中的设备
举报原因:
原因补充:

(最多只允许输入30个字)