Private/Resolve-WUDriverDetails.ps1

function Resolve-WUDriverDetails {
    <#
    .SYNOPSIS
        Resolves OEM driver references to actual driver information.
 
    .DESCRIPTION
        Takes OEM INF references (like oem116.inf) and returns detailed information
        about the actual driver including manufacturer, device name, hardware IDs,
        and associated devices.
 
    .PARAMETER OemInfName
        The OEM INF filename (e.g., "oem116.inf")
 
    .PARAMETER LogPath
        Path to the log file for detailed logging.
 
    .EXAMPLE
        $driverInfo = Resolve-WUDriverDetails -OemInfName "oem116.inf" -LogPath $LogPath
 
    .NOTES
        Returns detailed driver information for better troubleshooting.
        This is a private function used internally by the WindowsUpdateTools module.
    #>


    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$OemInfName,
        [string]$LogPath
    )

    $driverInfo = [PSCustomObject]@{
        OemInf = $OemInfName
        OriginalName = "Unknown"
        ProviderName = "Unknown"
        ClassName = "Unknown"
        ClassGuid = "Unknown"
        DriverVersion = "Unknown"
        DriverDate = "Unknown"
        IsSigned = $false
        SignerName = "Unknown"
        InfPath = $null
        HardwareIDs = @()
        AssociatedDevices = @()
        DeviceDescriptions = @()
        ErrorMessage = $null
        ResolvedSuccessfully = $false
    }

    try {
        Write-WULog -Message "Resolving driver details for: $OemInfName" -LogPath $LogPath

        # Method 1: Use pnputil to get basic driver information (fastest and most reliable)
        try {
            $pnpOutput = & pnputil.exe /enum-drivers 2>$null | Out-String
            
            # Find the section for our OEM INF
            $lines = $pnpOutput -split "`n"
            $inDriverSection = $false
            $currentDriver = @{}
            
            foreach ($line in $lines) {
                $line = $line.Trim()
                
                if ($line -match "Published Name:\s*(.+)") {
                    if ($inDriverSection -and $currentDriver.Count -gt 0) {
                        # We've moved to a new driver, process the previous one if it was ours
                        break
                    }
                    $inDriverSection = $matches[1].Trim() -eq $OemInfName
                    if ($inDriverSection) {
                        $currentDriver = @{}
                    }
                }
                
                if ($inDriverSection -and $line) {
                    if ($line -match "Original Name:\s*(.+)") {
                        $driverInfo.OriginalName = $matches[1].Trim()
                    }
                    elseif ($line -match "Provider Name:\s*(.+)") {
                        $driverInfo.ProviderName = $matches[1].Trim()
                    }
                    elseif ($line -match "Class Name:\s*(.+)") {
                        $driverInfo.ClassName = $matches[1].Trim()
                    }
                    elseif ($line -match "Class GUID:\s*(.+)") {
                        $driverInfo.ClassGuid = $matches[1].Trim()
                    }
                    elseif ($line -match "Driver Version:\s*(.+)") {
                        $versionInfo = $matches[1].Trim() -split '\s+'
                        if ($versionInfo.Length -ge 1) { $driverInfo.DriverDate = $versionInfo[0] }
                        if ($versionInfo.Length -ge 2) { $driverInfo.DriverVersion = $versionInfo[1] }
                    }
                    elseif ($line -match "Signer Name:\s*(.+)") {
                        $signerName = $matches[1].Trim()
                        $driverInfo.SignerName = $signerName
                        
                        # Enhanced signature detection logic
                        # Consider driver signed if:
                        # 1. Signer is explicitly Microsoft
                        # 2. Signer contains Microsoft in the name
                        # 3. Signer is not "Not signed" or empty
                        # 4. Has Windows Hardware Quality Labs (WHQL) signature
                        if ($signerName -eq "Microsoft Windows" -or 
                            $signerName -eq "Microsoft Corporation" -or
                            $signerName -like "*Microsoft*" -or
                            $signerName -like "*WHQL*" -or
                            $signerName -like "*Windows Hardware Compatibility*" -or
                            ($signerName -ne "Not signed" -and $signerName -ne "" -and $signerName -ne "Unknown")) {
                            $driverInfo.IsSigned = $true
                        } else {
                            $driverInfo.IsSigned = $false
                        }
                        
                        Write-WULog -Message "Driver signature analysis for $OemInfName`: Signer='$signerName', Considered signed: $($driverInfo.IsSigned)" -LogPath $LogPath
                    }
                }
            }

            if ($driverInfo.OriginalName -ne "Unknown") {
                $driverInfo.ResolvedSuccessfully = $true
                Write-WULog -Message "Successfully resolved $OemInfName via pnputil" -LogPath $LogPath
                Write-WULog -Message " Provider: $($driverInfo.ProviderName), Class: $($driverInfo.ClassName)" -LogPath $LogPath
                Write-WULog -Message " Signature: $($driverInfo.IsSigned) by '$($driverInfo.SignerName)'" -LogPath $LogPath
            }
        }
        catch {
            Write-WULog -Message "pnputil method failed for $OemInfName`: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
        }

        # Method 2: Additional signature verification using Get-AuthenticodeSignature (if available)
        if ($driverInfo.ResolvedSuccessfully) {
            try {
                $infPath = Join-Path "$env:WINDIR\INF" $OemInfName
                if (Test-Path $infPath) {
                    $signature = Get-AuthenticodeSignature -FilePath $infPath -ErrorAction SilentlyContinue
                    if ($signature) {
                        $authenticodeValid = $signature.Status -eq 'Valid'
                        $authenticodeSigner = if ($signature.SignerCertificate) { 
                            $signature.SignerCertificate.Subject 
                        } else { 
                            "No certificate" 
                        }
                        
                        Write-WULog -Message "Authenticode verification for $OemInfName`: Status=$($signature.Status), Signer='$authenticodeSigner'" -LogPath $LogPath
                        
                        # Cross-validate with pnputil results
                        if ($authenticodeValid -and -not $driverInfo.IsSigned) {
                            Write-WULog -Message "SIGNATURE VERIFICATION: pnputil reported unsigned but Authenticode shows valid signature" -Level Warning -LogPath $LogPath
                            $driverInfo.IsSigned = $true
                            $driverInfo.SignerName = $authenticodeSigner
                        } elseif (-not $authenticodeValid -and $driverInfo.IsSigned) {
                            Write-WULog -Message "SIGNATURE VERIFICATION: pnputil reported signed but Authenticode shows invalid/missing signature" -Level Warning -LogPath $LogPath
                            # Trust pnputil over Authenticode for driver store entries
                        }
                    }
                }
            }
            catch {
                Write-WULog -Message "Authenticode signature verification failed for $OemInfName`: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
            }
        }

        # Method 3: Try to read the INF file directly for additional details
        $infPath = Join-Path "$env:WINDIR\INF" $OemInfName
        $driverInfo.InfPath = $infPath
        
        if (Test-Path $infPath) {
            try {
                $infContent = Get-Content $infPath -ErrorAction Stop
                
                # Parse INF file for device descriptions and hardware IDs
                $currentSection = ""
                $strings = @{}
                
                foreach ($line in $infContent) {
                    $line = $line.Trim()
                    
                    # Track current section
                    if ($line -match '^\[(.+)\]') {
                        $currentSection = $matches[1]
                        continue
                    }
                    
                    # Collect string definitions
                    if ($currentSection -eq "Strings" -and $line -match '^([^=]+)\s*=\s*"([^"]+)"') {
                        $strings[$matches[1].Trim()] = $matches[2].Trim()
                    }
                    
                    # Look for device descriptions in manufacturer sections
                    if ($line -match '"([^"]+)"\s*=\s*[^,]+,\s*(.+)') {
                        $deviceDesc = $matches[1].Trim()
                        $hwIdRaw = $matches[2].Trim().Trim('"')
                        
                        if ($deviceDesc -and $deviceDesc -notin $driverInfo.DeviceDescriptions) {
                            $driverInfo.DeviceDescriptions += $deviceDesc
                        }
                        
                        if ($hwIdRaw -and $hwIdRaw -notlike '*%*' -and $hwIdRaw -notin $driverInfo.HardwareIDs) {
                            $driverInfo.HardwareIDs += $hwIdRaw
                        }
                    }
                    
                    # Look for hardware IDs in install sections
                    if ($line -match 'HardwareIds\s*=\s*(.+)') {
                        $hwIds = $matches[1] -split ',' | ForEach-Object { $_.Trim().Trim('"') }
                        foreach ($hwId in $hwIds) {
                            if ($hwId -and $hwId -notlike '*%*' -and $hwId -notin $driverInfo.HardwareIDs) {
                                $driverInfo.HardwareIDs += $hwId
                            }
                        }
                    }
                }
                
                # Resolve string references in device descriptions
                for ($i = 0; $i -lt $driverInfo.DeviceDescriptions.Count; $i++) {
                    $desc = $driverInfo.DeviceDescriptions[$i]
                    if ($desc -match '%(.+)%') {
                        $stringKey = $matches[1]
                        if ($strings.ContainsKey($stringKey)) {
                            $driverInfo.DeviceDescriptions[$i] = $strings[$stringKey]
                        }
                    }
                }
                
                Write-WULog -Message "Enhanced $OemInfName with INF file details" -LogPath $LogPath
            }
            catch {
                Write-WULog -Message "Could not parse INF file for $OemInfName`: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
            }
        }

        # Method 3: Find associated devices using hardware IDs
        if ($driverInfo.HardwareIDs.Count -gt 0) {
            try {
                $devices = Get-CimInstance -ClassName Win32_PnPEntity -ErrorAction SilentlyContinue
                foreach ($device in $devices) {
                    if ($device.HardwareID) {
                        foreach ($hwId in $driverInfo.HardwareIDs) {
                            if ($device.HardwareID -contains $hwId) {
                                $deviceObj = [PSCustomObject]@{
                                    Name = $device.Name
                                    DeviceID = $device.DeviceID
                                    Status = $device.Status
                                    Present = $device.Present
                                    Manufacturer = $device.Manufacturer
                                }
                                
                                # Avoid duplicates
                                $exists = $driverInfo.AssociatedDevices | Where-Object { $_.DeviceID -eq $deviceObj.DeviceID }
                                if (-not $exists) {
                                    $driverInfo.AssociatedDevices += $deviceObj
                                }
                            }
                        }
                    }
                }
                
                if ($driverInfo.AssociatedDevices.Count -gt 0) {
                    Write-WULog -Message "Found $($driverInfo.AssociatedDevices.Count) associated devices for $OemInfName" -LogPath $LogPath
                }
            }
            catch {
                Write-WULog -Message "Could not enumerate devices for $OemInfName`: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
            }
        }

        # Log the resolved information
        Write-WULog -Message "Driver resolution complete for $OemInfName`:" -LogPath $LogPath
        Write-WULog -Message " Original Name: $($driverInfo.OriginalName)" -LogPath $LogPath
        Write-WULog -Message " Provider: $($driverInfo.ProviderName)" -LogPath $LogPath
        Write-WULog -Message " Class: $($driverInfo.ClassName)" -LogPath $LogPath
        Write-WULog -Message " Version: $($driverInfo.DriverVersion)" -LogPath $LogPath
        Write-WULog -Message " Date: $($driverInfo.DriverDate)" -LogPath $LogPath
        Write-WULog -Message " Signed: $($driverInfo.IsSigned)" -LogPath $LogPath
        Write-WULog -Message " Signer: $($driverInfo.SignerName)" -LogPath $LogPath
        Write-WULog -Message " Device Descriptions: $($driverInfo.DeviceDescriptions.Count)" -LogPath $LogPath
        Write-WULog -Message " Hardware IDs: $($driverInfo.HardwareIDs.Count)" -LogPath $LogPath
        Write-WULog -Message " Associated Devices: $($driverInfo.AssociatedDevices.Count)" -LogPath $LogPath

    }
    catch {
        $driverInfo.ErrorMessage = $_.Exception.Message
        Write-WULog -Message "Error resolving driver $OemInfName`: $($_.Exception.Message)" -Level Error -LogPath $LogPath
    }

    return $driverInfo
}