Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NDIS_Driver_Fix/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*
!.gitignore
!fix-ndis-drivers.ps1
!config.json
14 changes: 14 additions & 0 deletions NDIS_Driver_Fix/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"info": "Fix unsigned NDIS drivers in HLK by copying signed drivers from backup folders",
"based_on_issue": "https://github.com/HCK-CI/AutoHCK/issues/819",
"download_url": "",
"file_name": "fix-ndis-drivers.ps1",
"install_cmd": "powershell",
"install_args": "-ExecutionPolicy Bypass -File @sw_path@\\fix-ndis-drivers.ps1",
"install_dest": "studio",
"install_time": {
"kit": "after",
"driver": "before"
}
}

180 changes: 180 additions & 0 deletions NDIS_Driver_Fix/fix-ndis-drivers.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# NDIS Driver Fix Script
# This script fixes unsigned NDIS drivers issue in HLK/WLK by copying signed drivers from ntndis* source folders
# Reference: https://github.com/HCK-CI/AutoHCK/issues/819
#
# Problem: After HLK installation, drivers in NDISTest65\bin\protocol are unsigned
# Solution: Copy signed versions from NDISTest\bin\ntndis*\ folders

$ErrorActionPreference = 'Stop'

Write-Output "=========================================="
Write-Output "NDIS Driver Fix Script"
Write-Output "=========================================="
Write-Output ""

# Base path for HLK installation
$hlkBasePath = "C:\Program Files (x86)\Windows Kits\10\Hardware Lab Kit\Tests\amd64\NetHlk"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The HLK base path is hardcoded. This will cause the script to fail if the Hardware Lab Kit is installed in a different location or on a different drive. It's more robust to determine this path dynamically by querying the registry, with a fallback to the default path if the registry key is not found. I'd also recommend adding a check to ensure the path exists before proceeding.

$kitRootPath = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" -Name "KitsRoot10" -ErrorAction SilentlyContinue).KitsRoot10
$hlkBasePath = if ($kitRootPath) {
    Join-Path $kitRootPath "Hardware Lab Kit\Tests\amd64\NetHlk"
}
else {
    Write-Warning "Could not find HLK installation path in registry. Falling back to default."
    "C:\Program Files (x86)\Windows Kits\10\Hardware Lab Kit\Tests\amd64\NetHlk"
}

if (-not (Test-Path $hlkBasePath)) {
    Write-Error "HLK path not found at '$hlkBasePath'. Script cannot continue."
}


# Function to check if a driver file is signed
function Test-DriverSigned {
param (
[string]$FilePath
)

if (-not (Test-Path $FilePath)) {
return $false
}

try {
$signature = Get-AuthenticodeSignature -FilePath $FilePath
return ($signature.Status -eq 'Valid')
}
catch {
return $false
}
}

# Function to find and copy signed driver from ntndis* folders
function Copy-SignedDriver {
param (
[string]$DriverName,
[string]$DestinationPath,
[array]$SourceFolders
)

foreach ($folder in $SourceFolders) {
$sourceDriverPath = Join-Path $folder.FullName $DriverName

if (Test-Path $sourceDriverPath) {
# Check if source driver is signed
$isSourceSigned = Test-DriverSigned -FilePath $sourceDriverPath

if ($isSourceSigned) {
Write-Output " [COPY] $DriverName from $($folder.Name)"
Copy-Item -Path $sourceDriverPath -Destination $DestinationPath -Force -Verbose
return $true
}
}
}

return $false
}

# Fix NDIS Test 6.5 drivers
Write-Output "Checking NDIS Test 6.5 drivers..."
$ndisTest65Path = Join-Path $hlkBasePath "NDISTest65\bin\protocol"
$ndisTestBinPath = Join-Path $hlkBasePath "NDISTest\bin"

if (Test-Path $ndisTest65Path) {
Write-Output "Found NDISTest65 path: $ndisTest65Path"

# Check if drivers in protocol folder are signed
$protocolDrivers = Get-ChildItem -Path $ndisTest65Path -Filter "*.sys" -ErrorAction SilentlyContinue
$unsignedCount = 0
$unsignedDrivers = @()

foreach ($driver in $protocolDrivers) {
$isSigned = Test-DriverSigned -FilePath $driver.FullName
if (-not $isSigned) {
Write-Output " [UNSIGNED] $($driver.Name)"
$unsignedCount++
$unsignedDrivers += $driver
}
else {
Write-Output " [SIGNED] $($driver.Name)"
}
}
Comment on lines +73 to +86

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Appending elements to an array using += inside a loop is inefficient as it recreates the array on each addition. A more idiomatic and performant approach in PowerShell is to capture the output of the loop directly. This avoids the overhead of repeated array copying.

    $unsignedDrivers = @(foreach ($driver in $protocolDrivers) {
        $isSigned = Test-DriverSigned -FilePath $driver.FullName
        if (-not $isSigned) {
            Write-Output "  [UNSIGNED] $($driver.Name)"
            $driver # Output the driver object to be collected in the array
        }
        else {
            Write-Output "  [SIGNED] $($driver.Name)"
        }
    })
    $unsignedCount = $unsignedDrivers.Count


if ($unsignedCount -gt 0) {
Write-Output ""
Write-Output "Found $unsignedCount unsigned driver(s), attempting to fix..."
Write-Output "Looking for signed drivers in: $ndisTestBinPath"

# Get all ntndis* subdirectories as source
$ntndisfolders = Get-ChildItem -Path $ndisTestBinPath -Directory -Filter "ntndis*" -ErrorAction SilentlyContinue

if ($ntndisfolders.Count -eq 0) {
Write-Output " [ERROR] No ntndis* folders found in $ndisTestBinPath"
}
else {
Write-Output " Found $($ntndisfolders.Count) ntndis* source folders"

$fixedCount = 0
foreach ($unsignedDriver in $unsignedDrivers) {
$driverFixed = Copy-SignedDriver -DriverName $unsignedDriver.Name -DestinationPath $unsignedDriver.FullName -SourceFolders $ntndisfolders

if ($driverFixed) {
$fixedCount++
}
else {
Write-Output " [WARNING] Could not find signed version of $($unsignedDriver.Name)"
}
}

Write-Output ""
Write-Output "Fixed $fixedCount out of $unsignedCount unsigned driver(s)"
}
}
else {
Write-Output "All drivers are properly signed!"
}
}
else {
Write-Output "NDISTest65 path not found: $ndisTest65Path"
}

Write-Output ""
Write-Output "=========================================="

# Check NDIS Test drivers (source folders with signed drivers)
Write-Output "Checking NDIS Test source drivers (ntndis* folders)..."
$ndisTestPath = Join-Path $hlkBasePath "NDISTest\bin"

if (Test-Path $ndisTestPath) {
Write-Output "Found NDISTest path: $ndisTestPath"

# Get all ntndis* subdirectories
$ndisFolders = Get-ChildItem -Path $ndisTestPath -Directory -Filter "ntndis*" -ErrorAction SilentlyContinue

if ($ndisFolders.Count -eq 0) {
Write-Output "No ntndis* folders found"
}
else {
Write-Output "Found $($ndisFolders.Count) NDIS version folder(s) (these should contain signed drivers)"

foreach ($folder in $ndisFolders) {
Write-Output ""
Write-Output "Checking: $($folder.Name)"

$driverFiles = Get-ChildItem -Path $folder.FullName -Filter "*.sys" -ErrorAction SilentlyContinue

if ($driverFiles.Count -eq 0) {
Write-Output " No driver files found"
continue
}

foreach ($driver in $driverFiles) {
$isSigned = Test-DriverSigned -FilePath $driver.FullName
if ($isSigned) {
Write-Output " [SIGNED] $($driver.Name) "
}
else {
Write-Output " [UNSIGNED] $($driver.Name) (unexpected!)"
}
}
}
}
}
else {
Write-Output "NDISTest path not found: $ndisTestPath"
}

Write-Output ""
Write-Output "=========================================="
Write-Output "NDIS Driver Fix Script Completed"
Write-Output "=========================================="
Write-Output ""

# Wait a few seconds to ensure output is visible
Start-Sleep -Seconds 5
Comment on lines +178 to +179

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Start-Sleep at the end of the script introduces an unconditional 5-second delay. This is likely unnecessary for automated execution (as suggested by the config.json) and can slow down processes. If a pause is required for interactive debugging, it's better to use Read-Host 'Press Enter to continue...' and perhaps make it conditional (e.g., based on a script parameter). For purely automated runs, this can be removed.