安裝虛擬PnP設備驅動程式

本質上,安裝驅動需要依靠UpdateDriverForPlugAndPlayDevices這個函數。它需要的參數其實不多,主要是INF文件路徑等。

BOOL WINAPI
UpdateDriverForPlugAndPlayDevices(
    HWND  hwndParent,
    LPCTSTR  HardwareId,
    LPCTSTR  FullInfPath,
    DWORD  InstallFlags,
    PBOOL  bRebootRequired OPTIONAL
);

執行這個函數相當於在設備管理器右鍵菜單上點擊「掃描檢測硬件改動」。
它會查找當前已經添加到系統中但可能還沒有安裝驅動程序的硬件設備。
由於沒有對應的硬件,因此我們要另想辦法,讓它能檢測到虛擬硬件的存在。
爲此,我們需要創建一設備信息塊,並將它弄到系統註冊表中去。
創建設備信息塊的函數是SetupDiCreateDeviceInfo。

WINSETUPAPI BOOL WINAPI
SetupDiCreateDeviceInfo(
    IN HDEVINFO  DeviceInfoSet,
    IN PCTSTR  DeviceName,
    IN LPGUID  ClassGuid,
    IN PCTSTR  DeviceDescription,   OPTIONAL
    IN HWND  hwndParent,   OPTIONAL
    IN DWORD  CreationFlags,
    OUT PSP_DEVINFO_DATA  DeviceInfoData   OPTIONAL
);

這個函數需要7個參數,其他的都好辦,無非是設備ID字符串,設備GUID等,還有一個用於輸出的結構體,記住填寫其中的size字段,其餘爲0就可以了。
問題是第一個參數HDEVINFO需要用另一個函數SetupDiCreateDeviceInfoList來創建。
如果GUID不想寫死,想通過INF讀取,則需要另一個函數SetupDiGetINFClass。

HDEVINFO
SetupDiCreateDeviceInfoList(
    IN LPGUID  ClassGuid,   OPTIONAL
    IN HWND  hwndParent   OPTIONAL
);
WINSETUPAPI BOOL WINAPI
SetupDiGetINFClass(
    IN PCTSTR  InfName,
    OUT LPGUID  ClassGuid,
    OUT PTSTR  ClassName,
    IN DWORD  ClassNameSize,
    OUT PDWORD  RequiredSize  OPTIONAL,
);

以上函數調用的順序是:SetupDiGetINFClass獲取GUID,
SetupDiCreateDeviceInfoList創建設備信息塊列表,
SetupDiCreateDeviceInfo創建設備信息塊。
完成這些步驟之後,我們就可以註冊設備了。
首先,我們要調用SetupDiSetDeviceRegistryProperty這個函數來設置設備在系統設備樹上的路徑,然後通過SetupDiCallClassInstaller這個函數來註冊:

WINSETUPAPI BOOL WINAPI
SetupDiSetDeviceRegistryProperty(
    IN HDEVINFO  DeviceInfoSet,
    IN OUT PSP_DEVINFO_DATA  DeviceInfoData,
    IN DWORD  Property,
    IN CONST BYTE  *PropertyBuffer,
    IN DWORD  PropertyBufferSize
);

這個函數的作用是設置驅動信息塊中的信息。
對於我們最重要的是其中的硬件ID。
這通過給第三個參數以SPDRP_HARDWAREID這個值就可以實現。
這時候,第四個參數就是指向硬件ID字符串的指針,第五個參數就是字符串的字節長度。
這個函數第一個參數要用DIF_REGISTERDEVICE填充以便註冊設備,第二項填寫設備信息塊列表,第三項則填寫設備信息塊。

WINSETUPAPI BOOL WINAPI
SetupDiCallClassInstaller(
    IN DI_FUNCTION  InstallFunction,
    IN HDEVINFO  DeviceInfoSet,
    IN PSP_DEVINFO_DATA  DeviceInfoData   OPTIONAL
);

數位簽章HLK tested and dashboard signed(簡稱WHQL簽名)、Windows 10 attestation signed(簡稱Win10簽名)差異:
https://learn.microsoft.com/zh-tw/windows-hardware/drivers/dashboard/code-signing-reqs

微軟官方PnP設備安裝工具devcon完整源代碼:
https://github.com/microsoft/Windows-driver-samples/tree/main/setup/devcon

非PNP設備通常不需要編寫INF文件,但若是用到Kmdf(Wdf.h)的程式,需要安裝KmdfLibrary到執行環境,因此需要以INF安裝,此INF內僅提供Wdf相關資訊。

Nonpnp drivers typically don’t need an INF file to install. Since we are using framework interfaces, we have to use the Kmdf coinstaller to install the framework binaries on the target machine. The Kmdf coinstaller needs a WDF specific section in the INF to get the driver service name and the version of the Kmdf library the driver is bound to. The syntax and description of the section is given below. Any non inf based driver using Kmdf library will need to have a dummy inf file with the wdf section in it. The format of the Wdf section is given below:

[Version]

Signature="$WINDOWS NT$"

[<driver name>.NT.Wdf]

KmdfService = <your driver service name here>, <driver service install subsection>

[<driver service install subsection>]

KmdfLibraryVersion = <version bound to here, in Major.minor format>

For example, for V1.0 KmdfLibraryVersion is "1.0"