使用SetupDI* API列舉系統中的設備

原文連接地址:https://blog.csdn.net/clteng/article/details/801012?utm_source=blogxgwz8函數

在Windows系統中提供一組有用的函數來擷取以安裝設備(Device)的信息與增長或解除設備(Device)的安裝。在本文中,我將顯示如何使用SetupDIXXX與CM_XXX 等API來列舉本機上的設備。
在範例程序中並沒有複雜的畫面,只有一個簡單的TreeView與ListView控件。TreeLivew控件用來顯示全部安裝的設備名稱,ListView控件則用來顯示在TreeView控件中所指定項目的相關信息。全部設備的相關信息(例如:名稱,資源與圖示等)都是從SetupDiXXX API中所取得的。
SetupDiXXXoop

設定安裝程序接口(Setup Application Programming Interface)提供一組函數來讓您的設定安裝程序能執行安裝的動做或取得設備的相關信息,類別(Class)與它的GUID值。
首先要取的所列舉的設備的位圖(Bitmap),咱們能夠呼叫如下的函數:ui

1 WINSETUPAPI BOOL SetupDiGetClassImageList(
2   PSP_CLASSIMAGELIST_DATA ClassImageListData
3 );

呼叫這個函數會取得每個已安裝設備的位圖並創建位圖串行。spa

1 BOOL SetupDiDestroyDeviceInfoList(
2   HDEVINFO DeviceInfoSet
3 );

呼叫這個函數會釋放以前呼叫SetupDiGetClassImageList所佔有的資源。.net

1 WINSETUPAPI BOOL SetupDiGetClassImageIndex(
2   PSP_CLASSIMAGELIST_DATA ClassImageListData,
3   const GUID              *ClassGuid,
4   PINT                    ImageIndex
5 );

呼叫這個函數會取得每個已安裝設備的位圖的索引值。指針

1 hDevInfo = SetupDiGetClassDevs(0L, 0L, _hDlg, DIGCF_PRESENT |
2                                                     DIGCF_ALLCLASSES | DIGCF_PROFILE);

取得設備的信息。首次呼叫時,第一個參數與第二個參數將它們設爲」0」,而第三個參數則設定DIGCF_ALLCLASSES旗標,設定此旗標表明要取得全部設備的信息。若是有設定此旗標此時第一個參數將會被忽略。
Geting the Info
呼叫SetupDiEnumDeviceInfo來列舉本機上全部的設備。code

1 SetupDiEnumDeviceInfo(hDevInfo, wIndex, &spDevInfoData))

第一個參數爲以前呼叫SetupDiGetDevs函數所傳回的代碼(Handle)。第二個參數爲以」0」爲基底的索引值,第三個參數爲指向SP_DEVINFO_DATA結構的指針。使用此結構時須先設定結構大小。blog

1                 spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2 SetupDiGetDeviceRegistryProperty(hDevInfo,
3                                         &spDevInfoData,
4 // Supplies one of the following values, indicating the property to be retrieved.
5                                         SPDRP_CLASS,
6                                         0L,
7                                         (PBYTE)szBuf,
8                                         2048,
9                                         0);

呼叫SetupDiGetDeviceRegistreProperty函數從Registry中取得設備名稱。第三個參數爲指定要取得何種信息。
Device Resource
在系統中全部的設備會與類別設備結合在一塊兒。請參下圖。這個類別能夠是GUID(能夠在Registry中尋獲)或是設備的描述。例如:」Ports」類別是描述(COM與LPT)。索引


要取得目前的設備的結構(Configuartion)咱們能夠呼叫CM_Get_First_Log_Conf函數來取得。而後呼叫CM_Get_Next_res_Des來取得目前設備結構的描述,重複呼叫直到瀏覽完全部的結構爲止。接口

當此函數成功執行後,咱們接着呼叫CM_Get_Res_Des_Data函數來取的資源的數據。


要安裝驅動程序,咱們能夠透過Service API來達成,若是要安裝WDM的程序,此時呼叫SetupDiGetINFClass函數先取得此驅動的GUID值,在呼叫SetupDiCreateDeviceInfoList來創建一個新的設備。以下列片段程序代碼:

 1     if (!SetupDiGetINFClass(szINFName, &guid, className, MAX_CLASS_NAME_LEN, 0)){
 2         ShowErrorMsg(_hDlg, GetLastError(), "SetupDiGetINFClass");
 3         return 0;
 4     };
 5     hDevInfo = SetupDiCreateDeviceInfoList(&guid, 0);
 6     if (hDevInfo == (void*)-1) {
 7         ShowErrorMsg(_hDlg, GetLastError(), "SetupDiCreateDeviceInfoList");
 8         return 0;
 9     };
10     spDevData.cbSize = sizeof(SP_DEVINFO_DATA);
11     if (!SetupDiCreateDeviceInfo(hDevInfo,
12                                  className,
13                                  &guid,
14                                  0L, 0L, DICD_GENERATE_ID,
15                                  &spDevData))
16 17 18

接下來咱們要呼叫SetupDiSetDeviceRegistryProperty函數來設定Registry中的內容。設定完成後,呼叫SetupDiCallClassInstaller函數依據Registry的內容來安裝驅動程序。最後呼叫UpdateDriverForPlugAndPlayDevices函數來更新設備串行的內容。

 1 if (!SetupDiSetDeviceRegistryProperty(hDevInfo,
 2                                        &spDevData,
 3                                        SPDRP_HARDWAREID,
 4                                        (PBYTE)pHID,
 5                            (strlen(_szHardware[wLoop])*2*sizeof(char)))) {
 6             ShowErrorMsg(_hDlg, GetLastError(), "SetupDiSetDeviceRegistryProperty");
 7             SetupDiDestroyDeviceInfoList(hDevInfo);
 8             LocalFree(pHID);
 9             return 0;
10         };
11         if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE,
12                                        hDevInfo, &spDevData)) {
13             ShowErrorMsg(_hDlg, GetLastError(), "SetupDiCallClassInstaller");
14             SetupDiDestroyDeviceInfoList(hDevInfo);
15             LocalFree(pHID);
16             return 0;
17         };
18         bRebootRequired = 0;
19         if (!UpdateDriverForPlugAndPlayDevices(0L, _szHardware[wLoop],
20 21 22
相關文章
相關標籤/搜索