fix: use DiInstallDriver API for WinUSB driver installation
pnputil rejects unsigned INF, installer_x64.exe is not a CLI tool. Switch to calling Windows DiInstallDriverW from newdev.dll directly, which can install unsigned drivers with a user confirmation dialog. Uses DIIRFLAG_FORCE_INF flag to force INF installation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2ab910d5ca
commit
cc1edfc89d
@ -118,8 +118,7 @@ jobs:
|
||||
$kpWheel = Get-ChildItem "local_service_win" -Filter "KneronPLUS*.whl" -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||
if ($kpWheel) { Copy-Item $kpWheel.FullName "$base\installer\payload\scripts\" }
|
||||
New-Item -ItemType Directory -Force -Path "$base\installer\payload\drivers\amd64"
|
||||
Copy-Item "local_service_win\LocalAPI\win_driver\installer_x64.exe" "$base\installer\payload\drivers\"
|
||||
Copy-Item "local_service_win\LocalAPI\win_driver\kneron_kl520.inf" "$base\installer\payload\drivers\"
|
||||
Copy-Item "$base\server\scripts\drivers\kneron_winusb.inf" "$base\installer\payload\drivers\"
|
||||
Copy-Item "local_service_win\LocalAPI\win_driver\amd64\WdfCoInstaller01011.dll" "$base\installer\payload\drivers\amd64\"
|
||||
Copy-Item "local_service_win\LocalAPI\win_driver\amd64\winusbcoinstaller2.dll" "$base\installer\payload\drivers\amd64\"
|
||||
|
||||
|
||||
3
.github/workflows/build-installer.yaml
vendored
3
.github/workflows/build-installer.yaml
vendored
@ -118,8 +118,7 @@ jobs:
|
||||
$kpWheel = Get-ChildItem "local_service_win" -Filter "KneronPLUS*.whl" -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||
if ($kpWheel) { Copy-Item $kpWheel.FullName "$base\installer\payload\scripts\" }
|
||||
New-Item -ItemType Directory -Force -Path "$base\installer\payload\drivers\amd64"
|
||||
Copy-Item "local_service_win\LocalAPI\win_driver\installer_x64.exe" "$base\installer\payload\drivers\"
|
||||
Copy-Item "local_service_win\LocalAPI\win_driver\kneron_kl520.inf" "$base\installer\payload\drivers\"
|
||||
Copy-Item "$base\server\scripts\drivers\kneron_winusb.inf" "$base\installer\payload\drivers\"
|
||||
Copy-Item "local_service_win\LocalAPI\win_driver\amd64\WdfCoInstaller01011.dll" "$base\installer\payload\drivers\amd64\"
|
||||
Copy-Item "local_service_win\LocalAPI\win_driver\amd64\winusbcoinstaller2.dll" "$base\installer\payload\drivers\amd64\"
|
||||
|
||||
|
||||
@ -137,9 +137,8 @@ installer-payload: build-server-tray ## Stage payload files for GUI installer
|
||||
fi
|
||||
@# Copy WinUSB driver files (for Windows installer)
|
||||
@mkdir -p installer/payload/drivers/amd64
|
||||
@if [ -d "../local_service_win/LocalAPI/win_driver" ]; then \
|
||||
cp ../local_service_win/LocalAPI/win_driver/installer_x64.exe installer/payload/drivers/; \
|
||||
cp ../local_service_win/LocalAPI/win_driver/kneron_kl520.inf installer/payload/drivers/; \
|
||||
cp server/scripts/drivers/kneron_winusb.inf installer/payload/drivers/
|
||||
@if [ -d "../local_service_win/LocalAPI/win_driver/amd64" ]; then \
|
||||
cp ../local_service_win/LocalAPI/win_driver/amd64/WdfCoInstaller01011.dll installer/payload/drivers/amd64/; \
|
||||
cp ../local_service_win/LocalAPI/win_driver/amd64/winusbcoinstaller2.dll installer/payload/drivers/amd64/; \
|
||||
echo " WinUSB driver files bundled."; \
|
||||
|
||||
@ -8,6 +8,8 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func platformDefaultDir() string {
|
||||
@ -86,42 +88,67 @@ func installLibusb(installDir string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// installWinUSBDriver extracts the Kneron driver installer from the payload
|
||||
// and runs it to install the WinUSB driver for Kneron USB devices.
|
||||
// The installer_x64.exe is a libwdi-based tool that handles driver signing
|
||||
// automatically (self-signed certificate), which pnputil cannot do with
|
||||
// unsigned INF files.
|
||||
// installWinUSBDriver extracts the WinUSB driver INF and co-installer files
|
||||
// from the payload, then uses the Windows SetupAPI (DiInstallDriver) to install
|
||||
// the driver. DiInstallDriver can install unsigned drivers — Windows will show
|
||||
// a security prompt asking the user to confirm.
|
||||
func installWinUSBDriver(installDir string) {
|
||||
driverDir := filepath.Join(installDir, "drivers")
|
||||
os.MkdirAll(driverDir, 0755)
|
||||
|
||||
// Extract the Kneron driver installer from payload
|
||||
installerPath := filepath.Join(driverDir, "installer_x64.exe")
|
||||
data, err := payloadFS.ReadFile("payload/drivers/installer_x64.exe")
|
||||
if err != nil {
|
||||
return // not bundled, skip
|
||||
}
|
||||
if err := os.WriteFile(installerPath, data, 0755); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Also extract the INF + co-installer files (installer_x64.exe needs them in the same directory)
|
||||
driverFiles := map[string]string{
|
||||
"payload/drivers/kneron_kl520.inf": filepath.Join(driverDir, "kneron_kl520.inf"),
|
||||
"payload/drivers/amd64/WdfCoInstaller01011.dll": filepath.Join(driverDir, "amd64", "WdfCoInstaller01011.dll"),
|
||||
"payload/drivers/amd64/winusbcoinstaller2.dll": filepath.Join(driverDir, "amd64", "winusbcoinstaller2.dll"),
|
||||
}
|
||||
os.MkdirAll(filepath.Join(driverDir, "amd64"), 0755)
|
||||
|
||||
// Extract driver files from embedded payload
|
||||
driverFiles := map[string]string{
|
||||
"payload/drivers/kneron_winusb.inf": filepath.Join(driverDir, "kneron_winusb.inf"),
|
||||
"payload/drivers/amd64/WdfCoInstaller01011.dll": filepath.Join(driverDir, "amd64", "WdfCoInstaller01011.dll"),
|
||||
"payload/drivers/amd64/winusbcoinstaller2.dll": filepath.Join(driverDir, "amd64", "winusbcoinstaller2.dll"),
|
||||
}
|
||||
|
||||
for src, dst := range driverFiles {
|
||||
if d, e := payloadFS.ReadFile(src); e == nil {
|
||||
os.WriteFile(dst, d, 0644)
|
||||
data, err := payloadFS.ReadFile(src)
|
||||
if err != nil {
|
||||
return // driver files not bundled, skip
|
||||
}
|
||||
if err := os.WriteFile(dst, data, 0644); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Run the Kneron driver installer (libwdi-based, handles signing automatically)
|
||||
cmd := exec.Command(installerPath)
|
||||
cmd.Dir = driverDir
|
||||
cmd.CombinedOutput() // best effort — non-fatal, may trigger UAC prompt
|
||||
infPath := filepath.Join(driverDir, "kneron_winusb.inf")
|
||||
|
||||
// Use DiInstallDriver from newdev.dll to pre-install the driver.
|
||||
// This works with unsigned INF files — Windows shows a trust dialog.
|
||||
diInstallDriver(infPath)
|
||||
}
|
||||
|
||||
// diInstallDriver calls Windows DiInstallDriver API to install a driver INF.
|
||||
// Flags: DIIRFLAG_FORCE_INF (0x00000002) forces the specified INF to be installed
|
||||
// even if it's unsigned, showing a Windows Security prompt to the user.
|
||||
func diInstallDriver(infPath string) {
|
||||
newdev, err := syscall.LoadDLL("newdev.dll")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer newdev.Release()
|
||||
|
||||
proc, err := newdev.FindProc("DiInstallDriverW")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
infPathUTF16, err := syscall.UTF16PtrFromString(infPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
const DIIRFLAG_FORCE_INF = 0x00000002
|
||||
// DiInstallDriverW(hwndParent, InfPath, Flags, NeedReboot)
|
||||
proc.Call(
|
||||
0, // hwndParent = NULL (no parent window)
|
||||
uintptr(unsafe.Pointer(infPathUTF16)),
|
||||
DIIRFLAG_FORCE_INF,
|
||||
0, // NeedReboot = NULL (don't care)
|
||||
)
|
||||
// Best effort — ignore errors. The user may decline the security prompt.
|
||||
}
|
||||
|
||||
func checkLibusbInstalled() bool {
|
||||
|
||||
@ -94,17 +94,16 @@ if ($kpWheel) {
|
||||
Write-Host " KneronPLUS wheel not found, skipping." -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# Copy WinUSB driver files (Kneron official installer + INF + co-installers)
|
||||
# Copy WinUSB driver files (INF + co-installers)
|
||||
New-Item -ItemType Directory -Force -Path installer\payload\drivers\amd64 | Out-Null
|
||||
$winDriverBase = Join-Path $repoRoot "local_service_win\LocalAPI\win_driver"
|
||||
if (Test-Path $winDriverBase) {
|
||||
Copy-Item (Join-Path $winDriverBase "installer_x64.exe") installer\payload\drivers\
|
||||
Copy-Item (Join-Path $winDriverBase "kneron_kl520.inf") installer\payload\drivers\
|
||||
Copy-Item (Join-Path $winDriverBase "amd64\WdfCoInstaller01011.dll") installer\payload\drivers\amd64\
|
||||
Copy-Item (Join-Path $winDriverBase "amd64\winusbcoinstaller2.dll") installer\payload\drivers\amd64\
|
||||
Copy-Item server\scripts\drivers\kneron_winusb.inf installer\payload\drivers\
|
||||
$winDriverDir = Join-Path $repoRoot "local_service_win\LocalAPI\win_driver\amd64"
|
||||
if (Test-Path $winDriverDir) {
|
||||
Copy-Item (Join-Path $winDriverDir "WdfCoInstaller01011.dll") installer\payload\drivers\amd64\
|
||||
Copy-Item (Join-Path $winDriverDir "winusbcoinstaller2.dll") installer\payload\drivers\amd64\
|
||||
Write-Host " WinUSB driver files bundled." -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " WinUSB driver files not found, skipping." -ForegroundColor Yellow
|
||||
Write-Host " WinUSB co-installer DLLs not found, skipping." -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
$fileCount = (Get-ChildItem -Recurse installer\payload -File).Count
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user