2017年7月29日 星期六

windows device and driver -- SetupAPI

微軟提供的 SetupAPI 是 user mode 的一套 API, 可以做安裝 device driver 或是查詢系統上的 device 資料,刪除 device 等等

在使用 SetupAPI 前,必需要先了解 device setup class,device interface class,device information set 這些跟 windows 上裝置管理相關的概念

Device Setup Class

微軟將以相同方式安裝和設定的 device 歸類成一個個的 device setup class,例如 IDE 硬碟,usb 隨身碟,都被歸類在 disk drives device setup class

微軟為幾乎所有的裝置都定義了 device setup class,每一個 device setup class 都有對應的 GUID,可以在 Devguid.h 裡面找到其 GUID並在程式中使用,系統上的 device 也可以在 ..\CurrentControlSet\Control\Class\ClassGuid 找到該 device 的資料

Device Interface Class

Device interface class 是一組接口的定義,可以讓 device driver 將它的功能讓其他的 driver,系統元件或是 user mode 程式來使用,可以想成若是一個 driver 註冊了某個 device interface class,它就必定支援某些功能

每個 device interface class 都有對應的 GUID,微軟定義了大部分通用的 device interface class

不同類型的裝置可能會屬於同一個 device interface class,例如 usb 滑鼠或 PS/2 接口的滑鼠都屬於 GUID_DEVINTERFACE_MOUSE

drivers 通常只註冊一個 device interface class,不過也有例外,例如一個可以被 mounted 的 disk 應該註冊 GUID_DEVINTERFACE_DISK 和 MOUNTDEV_MOUNTED_DEVICE_GUID

Device Information Set

Windows 中屬於 device setup class 或 device interface class 的 device 必須要透過 device information set 和 device information element 來操作

device information set 中包含 device information element,device information element 又包含了 device devnode 的 handle 和指向 device interface list 的 pointer

我們的程式實際上看不到這些資料結構內含哪些資料,因為這是 Windows 內部使用的資料結構,我們只會拿到 device information set 的 handle 並且透過 handle 來呼叫 SetupAPI

通常是用 SetupDiGetClassDevs API 來取得 device information set 的 handle,而且 device information set 裡面的元素不是固定的,而是動態的根據不同的條件系統幫忙 create 出來的一個結構,例如用不同的 disk type 的 device setup class 參數,SetupDiGetClassDevs API 會回傳只包含 disk type 的 device information set 回來

https://docs.microsoft.com/en-us/windows-hardware/drivers/install/images/devinfosets.png

要怎麼使用 SetupAPI

了解了這些概念後,就可以使用 SetupAPI 開始對 device 做一些操作,例如想知道系統上有多少磁碟機,可以用 GUID_DEVCLASS_DISKDRIVE device setup class 當參數傳給 SetupDiGetClassDevs

SetupDiGetClassDevs 有提供 enumerator 參數可以讓 caller 做進一步篩選想選取的 device,例如可以傳 "USBSTOR" 參數,只取得 usb 磁碟機的 device information set

取得 device information set 之後,用SetupDiEnumDeviceInfo 取得每一個 device 的 SP_DEVINFO_DATA 資料結構,再用 SetupDiGetDeviceRegistryProperty 取得 device 的資訊例如 friendly name

除了取得 device 的資訊,還可以對這些 device 做更多的操作,例如想要 uninstall 某些 device,一樣取得 device information set 與各個 device 的 SP_DEVINFO_DATA 之後,可以呼叫 DiUninstallDevice,就可以將 device 移除

沒有留言:

張貼留言