dist/temp/WindowsUpdateTools/Private/Remove-WUProblematicDrivers.ps1

function Remove-WUProblematicDrivers {
    <#
    .SYNOPSIS
        Identifies and remediates problematic drivers that may interfere with Windows Updates and upgrades.
 
    .DESCRIPTION
        Scans for both configuration errors and Windows Setup blocking drivers. Provides specific remediation
        for drivers identified in Windows 11 upgrade compatibility scans, including handling false positives
        where signed drivers are incorrectly flagged as unsigned by Windows Setup.
 
    .PARAMETER LogPath
        Path to the log file for detailed logging.
 
    .PARAMETER RemoveAction
        Specifies the action to take for blocking drivers. Valid values:
        - 'Identify' (default): Only identify and log drivers
        - 'DisableDevice': Disable devices associated with blocking drivers
        - 'UninstallDriver': Uninstall the driver package (use with caution)
 
    .EXAMPLE
        $result = Remove-WUProblematicDrivers -LogPath "C:\Logs\wu.log"
 
    .EXAMPLE
        $result = Remove-WUProblematicDrivers -LogPath "C:\Logs\wu.log" -RemoveAction "DisableDevice"
 
    .NOTES
        This is a private function used internally by the WindowsUpdateTools module.
        Returns an object with Success, DriversRemoved, and ActionsPerformed properties.
        Uses Get-WUSetupLogsDirect internally to analyze Windows Setup logs.
    #>


    [CmdletBinding()]
    param(
        [string]$LogPath,
        [ValidateSet('Identify', 'DisableDevice', 'UninstallDriver')]
        [string]$RemoveAction = 'Identify'
    )
    
    $result = [PSCustomObject]@{
        Success = $false
        DriversRemoved = 0
        DriversDisabled = 0
        BlockingDriversFound = 0
        SignatureDiscrepancies = 0
        ActionsPerformed = @()
        BlockingDriverDetails = @()
        DeviceConfigErrors = 0
        PrinterDriversRemoved = 0
        PrinterDriversReinstalled = 0
    }

    # Helper function to clean Microsoft virtual printer drivers
    function Clean-MicrosoftPrinterDrivers {
        param(
            [string]$LogPath,
            [string]$RemoveAction
        )
        
        $removedDrivers = @()
        $targets = @(
            "Microsoft XPS Document Writer",
            "Microsoft Print To PDF"
        )

        foreach ($targetDriver in $targets) {
            # Remove any printers using this driver
            $printersUsingDriver = Get-Printer -ErrorAction SilentlyContinue | Where-Object { $_.DriverName -like "$targetDriver*" }

            foreach ($printer in $printersUsingDriver) {
                Write-WULog -Message " -> Removing printer: $($printer.Name) (Driver: $($printer.DriverName))" -LogPath $LogPath
                try {
                    Remove-Printer -Name $printer.Name -ErrorAction Stop
                    Write-WULog -Message " Successfully removed printer: $($printer.Name)" -LogPath $LogPath
                }
                catch {
                    Write-WULog -Message " Failed to remove printer: $($printer.Name) - $($_.Exception.Message)" -Level Warning -LogPath $LogPath
                }
            }

            # Remove the printer driver
            $driver = Get-PrinterDriver -ErrorAction SilentlyContinue | Where-Object { $_.Name -like "$targetDriver*" }

            if ($driver) {
                Write-WULog -Message " Removing driver: $($driver.Name)" -LogPath $LogPath
                try {
                    Remove-PrinterDriver -Name $driver.Name -ErrorAction Stop
                    Write-WULog -Message " Successfully removed driver: $($driver.Name)" -LogPath $LogPath
                    $removedDrivers += $driver.Name
                }
                catch {
                    Write-WULog -Message " Failed to remove driver: $($driver.Name) - $($_.Exception.Message)" -Level Warning -LogPath $LogPath
                }
            }
            else {
                Write-WULog -Message " Driver not found: $targetDriver" -LogPath $LogPath
            }
        }

        # Reinstall if any were removed and RemoveAction allows it
        if ($RemoveAction -ne 'Identify') {
            if ($removedDrivers -match "Microsoft Print to PDF") {
                Write-WULog -Message " Reinstalling Microsoft Print to PDF..." -LogPath $LogPath
                try {
                    Add-WindowsCapability -Online -Name "Printing.PrintToPDF~~~~0.0.1.0" -ErrorAction Stop | Out-Null
                    Write-WULog -Message " Successfully reinstalled Microsoft Print to PDF" -LogPath $LogPath
                    $result.PrinterDriversReinstalled++
                }
                catch {
                    Write-WULog -Message " Failed to reinstall Microsoft Print to PDF - $($_.Exception.Message)" -Level Warning -LogPath $LogPath
                }
            }

            if ($removedDrivers -match "Microsoft XPS Document Writer") {
                Write-WULog -Message " Reinstalling Microsoft XPS Document Writer..." -LogPath $LogPath
                try {
                    Add-WindowsCapability -Online -Name "Printing.XPSServices~~~~0.0.1.0" -ErrorAction Stop | Out-Null
                    Write-WULog -Message " Successfully reinstalled Microsoft XPS Document Writer" -LogPath $LogPath
                    $result.PrinterDriversReinstalled++
                }
                catch {
                    Write-WULog -Message " Failed to reinstall Microsoft XPS Document Writer - $($_.Exception.Message)" -Level Warning -LogPath $LogPath
                }
            }
        }

        if (-not $removedDrivers) {
            Write-WULog -Message " No matching Microsoft printer drivers found for removal" -LogPath $LogPath
        }
        else {
            $result.PrinterDriversRemoved += $removedDrivers.Count
        }

        return $removedDrivers.Count
    }
    
    try {
        Write-WULog -Message "Checking for problematic drivers and Windows Setup blocking drivers..." -LogPath $LogPath
        
        # Phase 1: Get blocking drivers using existing module function
        Write-WULog -Message "Analyzing Windows Setup logs for blocking drivers..." -LogPath $LogPath
        
        $setupAnalysis = Get-WUSetupLogsDirect -LogPath $LogPath
        $microsoftPrinterDriverDetected = $false
        
        if ($setupAnalysis.AnalysisSuccessful -and $setupAnalysis.BlockingDriverDetails.Count -gt 0) {
            Write-WULog -Message "Found $($setupAnalysis.BlockingDriverDetails.Count) blocking drivers from setup analysis" -LogPath $LogPath
            $result.BlockingDriversFound = $setupAnalysis.BlockingDriverDetails.Count
            $result.ActionsPerformed += "Analyzed Windows Setup blocking drivers"
            
            foreach ($driverDetails in $setupAnalysis.BlockingDriverDetails) {
                Write-WULog -Message "Processing blocking driver: $($driverDetails.OemInf)" -LogPath $LogPath
                
                $result.BlockingDriverDetails += $driverDetails
                
                # Check if this is a Microsoft virtual printer driver issue
                if ($driverDetails.ProviderName -eq "Microsoft" -and 
                    ($driverDetails.ClassName -like "*Print*" -or 
                     $driverDetails.OemInf -like "*print*" -or
                     $driverDetails.OemInf -like "*xps*")) {
                    $microsoftPrinterDriverDetected = $true
                    Write-WULog -Message " DETECTED: Microsoft virtual printer driver blocking upgrade" -Level Warning -LogPath $LogPath
                }
                
                # Check for signature status discrepancy (already identified in Get-WUSetupLogsDirect)
                $isSignatureDiscrepancy = $false
                if ($driverDetails.ResolvedSuccessfully -and $driverDetails.IsSigned) {
                    # Look for indicators that this was flagged as unsigned by setup but is actually signed
                    if ($driverDetails.ProviderName -eq "Microsoft" -or $driverDetails.SignerName -like "*Microsoft*") {
                        $isSignatureDiscrepancy = $true
                        $result.SignatureDiscrepancies++
                        Write-WULog -Message "SIGNATURE DISCREPANCY: $($driverDetails.OemInf) is Microsoft-signed but was flagged by Windows Setup" -Level Warning -LogPath $LogPath
                        Write-WULog -Message " Actual signature status: SIGNED by $($driverDetails.SignerName)" -LogPath $LogPath
                        Write-WULog -Message " This appears to be a Windows Setup compatibility scanner false positive" -LogPath $LogPath
                    }
                }
                
                if ($driverDetails.ResolvedSuccessfully) {
                    $signatureStatus = if ($isSignatureDiscrepancy) {
                        "SIGNED (Setup log false positive)"
                    } elseif ($driverDetails.IsSigned) {
                        "SIGNED"
                    } else {
                        "UNSIGNED"
                    }
                    
                    Write-WULog -Message " Driver details: $($driverDetails.ClassName) from $($driverDetails.ProviderName)" -LogPath $LogPath
                    Write-WULog -Message " Signature status: $signatureStatus" -LogPath $LogPath
                    Write-WULog -Message " Associated devices: $($driverDetails.AssociatedDevices.Count)" -LogPath $LogPath
                }
                
                # Perform remediation based on RemoveAction parameter
                if ($RemoveAction -ne 'Identify') {
                    if ($isSignatureDiscrepancy -and $driverDetails.IsSigned) {
                        Write-WULog -Message " RECOMMENDATION: Driver is properly signed - investigate Windows Update compatibility settings instead of removing" -Level Warning -LogPath $LogPath
                    } else {
                        # Only proceed with removal/disabling for actually problematic drivers
                        if ($driverDetails.AssociatedDevices.Count -gt 0) {
                            foreach ($device in $driverDetails.AssociatedDevices) {
                                if ($device.Present) {
                                    try {
                                        if ($RemoveAction -eq 'DisableDevice') {
                                            # Disable the device
                                            Disable-PnpDevice -InstanceId $device.InstanceId -Confirm:$false -ErrorAction Stop | Out-Null
                                            Write-WULog -Message " Disabled device: $($device.Name)" -LogPath $LogPath
                                            $result.DriversDisabled++
                                        }
                                        elseif ($RemoveAction -eq 'UninstallDriver') {
                                            # Remove the driver package (more aggressive)
                                            $null = pnputil.exe /delete-driver $driverDetails.OemInf /uninstall /force
                                            Write-WULog -Message " Uninstalled driver: $($driverDetails.OemInf)" -LogPath $LogPath
                                            $result.DriversRemoved++
                                        }
                                    }
                                    catch {
                                        Write-WULog -Message " Failed to $RemoveAction device $($device.Name): $($_.Exception.Message)" -Level Warning -LogPath $LogPath
                                    }
                                }
                            }
                        } else {
                            Write-WULog -Message " No active devices found for driver $($driverDetails.OemInf) - driver may be unused" -LogPath $LogPath
                            if ($RemoveAction -eq 'UninstallDriver') {
                                try {
                                    $null = pnputil.exe /delete-driver $driverDetails.OemInf /force
                                    Write-WULog -Message " Removed unused driver: $($driverDetails.OemInf)" -LogPath $LogPath
                                    $result.DriversRemoved++
                                }
                                catch {
                                    Write-WULog -Message " Failed to remove driver $($driverDetails.OemInf): $($_.Exception.Message)" -Level Warning -LogPath $LogPath
                                }
                            }
                        }
                    }
                }
            }
        } else {
            Write-WULog -Message "No blocking drivers found or setup analysis failed" -LogPath $LogPath
        }

        # Phase 1.5: Handle Microsoft virtual printer drivers if detected
        if ($microsoftPrinterDriverDetected) {
            Write-WULog -Message "Microsoft virtual printer drivers detected as problematic - applying specialized cleanup..." -LogPath $LogPath
            $printerDriversProcessed = Clean-MicrosoftPrinterDrivers -LogPath $LogPath -RemoveAction $RemoveAction
            if ($printerDriversProcessed -gt 0) {
                $result.ActionsPerformed += "Microsoft printer driver cleanup applied"
            }
        }
        
        # Phase 2: Check for general device configuration issues
        Write-WULog -Message "Checking for devices with configuration errors..." -LogPath $LogPath
        
        $problematicDevices = Get-CimInstance -ClassName Win32_PnPEntity | Where-Object {
            $_.ConfigManagerErrorCode -ne 0 -and $null -ne $_.ConfigManagerErrorCode
        }
        
        $result.DeviceConfigErrors = $problematicDevices.Count
        
        if ($problematicDevices) {
            Write-WULog -Message "Found $($problematicDevices.Count) devices with configuration errors" -LogPath $LogPath
            foreach ($device in $problematicDevices) {
                Write-WULog -Message "Device with config error: $($device.Name) (Error: $($device.ConfigManagerErrorCode))" -LogPath $LogPath
            }
            $result.ActionsPerformed += "Identified devices with configuration errors"
        } else {
            Write-WULog -Message "No devices with configuration errors detected" -LogPath $LogPath
        }
        
        # Determine overall success
        if ($result.BlockingDriversFound -gt 0 -or $result.DeviceConfigErrors -gt 0) {
            $result.ActionsPerformed += "Driver Analysis Completed"
            
            if ($RemoveAction -ne 'Identify' -and ($result.DriversRemoved -gt 0 -or $result.DriversDisabled -gt 0 -or $result.PrinterDriversRemoved -gt 0)) {
                $result.ActionsPerformed += "Driver Remediation Applied"
            }
        }
        
        $result.Success = $true
        
        # Summary logging
        Write-WULog -Message "Driver analysis summary:" -LogPath $LogPath
        Write-WULog -Message " Windows Setup blocking drivers: $($result.BlockingDriversFound)" -LogPath $LogPath
        Write-WULog -Message " Signature discrepancies (false positives): $($result.SignatureDiscrepancies)" -LogPath $LogPath
        Write-WULog -Message " Device configuration errors: $($result.DeviceConfigErrors)" -LogPath $LogPath
        Write-WULog -Message " Microsoft printer drivers removed: $($result.PrinterDriversRemoved)" -LogPath $LogPath
        Write-WULog -Message " Microsoft printer drivers reinstalled: $($result.PrinterDriversReinstalled)" -LogPath $LogPath
        
        if ($RemoveAction -ne 'Identify') {
            Write-WULog -Message " Drivers removed: $($result.DriversRemoved)" -LogPath $LogPath
            Write-WULog -Message " Devices disabled: $($result.DriversDisabled)" -LogPath $LogPath
        }
    }
    catch {
        Write-WULog -Message "Error during driver cleanup: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
        $result.Success = $false
    }
    
    return $result
}