dist/temp/WindowsUpdateTools/Private/Resolve-WUDynamicUpdatesIssues.ps1

function Resolve-WUDynamicUpdatesIssues {
    <#
    .SYNOPSIS
        Resolves Dynamic Updates configuration and download failures.
 
    .DESCRIPTION
        Fixes Dynamic Updates failures including:
        - 0x80070057: WU internal configuration property failures
        - 0x80004005: Download update failures
        - CopyFileBufferedSynchronousIo registry issues
        - Windows Update component corruption
 
    .PARAMETER LogPath
        Path to the log file for detailed logging.
 
    .EXAMPLE
        $result = Resolve-WUDynamicUpdatesIssues -LogPath "C:\Logs\wu.log"
 
    .NOTES
        This is a private function used internally by the WindowsUpdateTools module.
        Requires Administrator privileges for service and registry modification.
        Returns an object with Success, ActionsPerformed, and RebootRequired properties.
    #>


    [CmdletBinding()]
    param(
        [string]$LogPath
    )

    # Initialize result object
    $result = [PSCustomObject]@{
        Success = $false
        RebootRequired = $false
        ActionsPerformed = @()
        IssuesResolved = 0
        ErrorMessage = $null
        ServicesReset = $false
        RegistryFixed = $false
        ComponentsCleared = $false
    }

    Write-WULog -Message "Starting Dynamic Updates issues remediation" -LogPath $LogPath

    try {
        # Step 1: Stop Windows Update services
        Write-WULog -Message "Step 1: Stopping Windows Update services..." -LogPath $LogPath
        $services = @('wuauserv', 'bits', 'cryptsvc', 'msiserver')
        $stoppedServices = @()

        foreach ($service in $services) {
            try {
                $serviceObj = Get-Service -Name $service -ErrorAction SilentlyContinue
                if ($serviceObj -and $serviceObj.Status -eq 'Running') {
                    Stop-Service -Name $service -Force -ErrorAction Stop
                    $stoppedServices += $service
                    Write-WULog -Message "Stopped service: $service" -LogPath $LogPath
                }
            }
            catch {
                Write-WULog -Message "Failed to stop service $service`: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
            }
        }

        if ($stoppedServices.Count -gt 0) {
            $result.ActionsPerformed += "Stopped Windows Update services ($($stoppedServices -join ', '))"
            $result.ServicesReset = $true
        }

        # Step 2: Fix Dynamic Updates registry configuration
        Write-WULog -Message "Step 2: Applying Dynamic Updates registry fixes..." -LogPath $LogPath
        try {
            # Create OSUpgrade registry path if it doesn't exist
            $osUpgradePath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\OSUpgrade"
            if (-not (Test-Path $osUpgradePath)) {
                New-Item -Path $osUpgradePath -Force | Out-Null
                Write-WULog -Message "Created OSUpgrade registry path" -LogPath $LogPath
            }

            # Add CopyFileBufferedSynchronousIo fix for 24H2 compatibility
            New-ItemProperty -Path $osUpgradePath -Name "CopyFileBufferedSynchronousIo" -Value 1 -PropertyType DWord -Force | Out-Null
            Write-WULog -Message "Applied CopyFileBufferedSynchronousIo registry fix" -LogPath $LogPath
            $result.ActionsPerformed += "Applied CopyFileBufferedSynchronousIo registry fix"
            $result.RegistryFixed = $true
            $result.IssuesResolved++

            # Ensure AllowOSUpgrade is enabled
            New-ItemProperty -Path $osUpgradePath -Name "AllowOSUpgrade" -Value 1 -PropertyType DWord -Force | Out-Null
            Write-WULog -Message "Enabled AllowOSUpgrade registry setting" -LogPath $LogPath

            # Fix ReservationsAllowed for Windows 11 24H2
            New-ItemProperty -Path $osUpgradePath -Name "ReservationsAllowed" -Value 1 -PropertyType DWord -Force | Out-Null
            Write-WULog -Message "Enabled ReservationsAllowed for Windows 11 24H2" -LogPath $LogPath

        }
        catch {
            Write-WULog -Message "Error applying registry fixes: $($_.Exception.Message)" -Level Error -LogPath $LogPath
            $result.ErrorMessage = "Registry fix failed: $($_.Exception.Message)"
        }

        # Step 3: Clear Windows Update cache and components
        Write-WULog -Message "Step 3: Clearing Windows Update cache components..." -LogPath $LogPath
        try {
            # Remove SoftwareDistribution folder
            $softwareDistPath = "C:\Windows\SoftwareDistribution"
            if (Test-Path $softwareDistPath) {
                $distSize = (Get-ChildItem -Path $softwareDistPath -Recurse -File -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum
                Remove-Item -Path $softwareDistPath -Recurse -Force -ErrorAction Stop
                Write-WULog -Message "Removed SoftwareDistribution folder ($([math]::Round($distSize / 1MB, 1)) MB)" -LogPath $LogPath
                $result.ActionsPerformed += "Cleared SoftwareDistribution cache"
                $result.ComponentsCleared = $true
                $result.IssuesResolved++
            }

            # Remove catroot2 folder
            $catroot2Path = "C:\Windows\System32\catroot2"
            if (Test-Path $catroot2Path) {
                $catrootSize = (Get-ChildItem -Path $catroot2Path -Recurse -File -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum
                Remove-Item -Path $catroot2Path -Recurse -Force -ErrorAction Stop
                Write-WULog -Message "Removed catroot2 folder ($([math]::Round($catrootSize / 1MB, 1)) MB)" -LogPath $LogPath
                $result.ActionsPerformed += "Cleared catroot2 cache"
            }

        }
        catch {
            Write-WULog -Message "Error clearing Windows Update cache: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
        }

        # Step 4: Clear Dynamic Updates specific cache
        Write-WULog -Message "Step 4: Clearing Dynamic Updates specific cache..." -LogPath $LogPath
        try {
            $duCachePaths = @(
                "$env:WINDIR\SoftwareDistribution\Download",
                "$env:WINDIR\System32\config\systemprofile\AppData\Local\Microsoft\Windows\INetCache",
                "$env:WINDIR\Temp\MoSetup"
            )

            foreach ($cachePath in $duCachePaths) {
                if (Test-Path $cachePath) {
                    try {
                        $cacheFiles = Get-ChildItem -Path $cachePath -Force -ErrorAction SilentlyContinue
                        if ($cacheFiles) {
                            Remove-Item -Path "$cachePath\*" -Recurse -Force -ErrorAction SilentlyContinue
                            Write-WULog -Message "Cleared Dynamic Updates cache: $cachePath" -LogPath $LogPath
                        }
                    }
                    catch {
                        Write-WULog -Message "Could not clear all files in $cachePath" -Level Warning -LogPath $LogPath
                    }
                }
            }

            $result.ActionsPerformed += "Cleared Dynamic Updates cache files"
        }
        catch {
            Write-WULog -Message "Error clearing Dynamic Updates cache: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
        }

        # Step 5: Reset Windows Update Agent authorization
        Write-WULog -Message "Step 5: Resetting Windows Update Agent authorization..." -LogPath $LogPath
        try {
            # Reset authorization tokens
            & cmd.exe /c "net stop wuauserv" 2>&1 | Out-Null
            & cmd.exe /c "net stop bits" 2>&1 | Out-Null
            
            # Remove authorization cache
            $authCachePath = "$env:WINDIR\SoftwareDistribution\AuthCabs"
            if (Test-Path $authCachePath) {
                Remove-Item -Path $authCachePath -Recurse -Force -ErrorAction SilentlyContinue
                Write-WULog -Message "Cleared Windows Update authorization cache" -LogPath $LogPath
            }

            $result.ActionsPerformed += "Reset Windows Update Agent authorization"
        }
        catch {
            Write-WULog -Message "Error resetting Windows Update authorization: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
        }

        # Step 6: Re-register Windows Update DLLs related to Dynamic Updates
        Write-WULog -Message "Step 6: Re-registering Dynamic Updates related DLLs..." -LogPath $LogPath
        try {
            $duDlls = @(
                'wuapi.dll',
                'wuaueng.dll', 
                'wuaueng1.dll',
                'wucltui.dll',
                'wups.dll',
                'wups2.dll',
                'wuweb.dll'
            )

            $registeredCount = 0
            Push-Location "$env:WINDIR\System32"
            
            foreach ($dll in $duDlls) {
                try {
                    & regsvr32.exe $dll /s
                    if ($LASTEXITCODE -eq 0) {
                        $registeredCount++
                    }
                }
                catch {
                    Write-WULog -Message "Failed to register $dll" -Level Warning -LogPath $LogPath
                }
            }
            
            Pop-Location
            Write-WULog -Message "Re-registered $registeredCount/$($duDlls.Count) Dynamic Updates DLLs" -LogPath $LogPath
            $result.ActionsPerformed += "Re-registered Dynamic Updates DLLs"
        }
        catch {
            Write-WULog -Message "Error re-registering DLLs: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
            Pop-Location
        }

        # Step 7: Fix Group Policy interference
        Write-WULog -Message "Step 7: Checking for Group Policy interference..." -LogPath $LogPath
        try {
            $gpoUpdatePath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"
            if (Test-Path $gpoUpdatePath) {
                # Check for policies that might block Dynamic Updates
                $problematicPolicies = @(
                    "DoNotConnectToWindowsUpdateInternetLocations",
                    "DisableWindowsUpdateAccess",
                    "NoAutoUpdate"
                )

                foreach ($policy in $problematicPolicies) {
                    $policyValue = Get-ItemProperty -Path $gpoUpdatePath -Name $policy -ErrorAction SilentlyContinue
                    if ($policyValue -and $policyValue.$policy -eq 1) {
                        Write-WULog -Message "Found potentially blocking Group Policy: $policy" -Level Warning -LogPath $LogPath
                        # Don't automatically change GPO settings, just log them
                    }
                }

                # Check AU path for Dynamic Updates blocks
                $auPath = "$gpoUpdatePath\AU"
                if (Test-Path $auPath) {
                    $noAutoUpdate = Get-ItemProperty -Path $auPath -Name "NoAutoUpdate" -ErrorAction SilentlyContinue
                    if ($noAutoUpdate -and $noAutoUpdate.NoAutoUpdate -eq 1) {
                        Write-WULog -Message "Automatic Updates are disabled via Group Policy - this may block Dynamic Updates" -Level Warning -LogPath $LogPath
                    }
                }
            }

            $result.ActionsPerformed += "Checked Group Policy configuration"
        }
        catch {
            Write-WULog -Message "Error checking Group Policy: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
        }

        # Step 8: Restart Windows Update services
        Write-WULog -Message "Step 8: Restarting Windows Update services..." -LogPath $LogPath
        $restartedServices = @()

        foreach ($service in $services) {
            try {
                $serviceObj = Get-Service -Name $service -ErrorAction SilentlyContinue
                if ($serviceObj -and $serviceObj.Status -eq 'Stopped') {
                    Start-Service -Name $service -ErrorAction Stop
                    $restartedServices += $service
                    Write-WULog -Message "Started service: $service" -LogPath $LogPath
                }
            }
            catch {
                Write-WULog -Message "Failed to start service $service`: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
            }
        }

        if ($restartedServices.Count -gt 0) {
            $result.ActionsPerformed += "Restarted Windows Update services ($($restartedServices -join ', '))"
        }

        # Step 9: Trigger Windows Update detection to test Dynamic Updates
        Write-WULog -Message "Step 9: Testing Dynamic Updates functionality..." -LogPath $LogPath
        try {
            # Use USOClient to trigger a detection scan
            & USOClient.exe StartInteractiveScan 2>&1 | Out-Null
            if ($LASTEXITCODE -eq 0) {
                Write-WULog -Message "Triggered Windows Update detection scan" -LogPath $LogPath
                $result.ActionsPerformed += "Triggered update detection test"
            }
        }
        catch {
            Write-WULog -Message "Could not trigger update detection: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
        }

        # Determine overall success
        if ($result.RegistryFixed -and $result.ComponentsCleared -and $result.ActionsPerformed.Count -gt 0) {
            $result.Success = $true
            Write-WULog -Message "Dynamic Updates issues remediation completed successfully" -LogPath $LogPath
        }

    }
    catch {
        $result.ErrorMessage = $_.Exception.Message
        Write-WULog -Message "Critical error during Dynamic Updates remediation: $($_.Exception.Message)" -Level Error -LogPath $LogPath
    }

    # Summary
    Write-WULog -Message "Dynamic Updates remediation summary:" -LogPath $LogPath
    Write-WULog -Message " Success: $($result.Success)" -LogPath $LogPath
    Write-WULog -Message " Registry fixed: $($result.RegistryFixed)" -LogPath $LogPath
    Write-WULog -Message " Components cleared: $($result.ComponentsCleared)" -LogPath $LogPath
    Write-WULog -Message " Services reset: $($result.ServicesReset)" -LogPath $LogPath
    Write-WULog -Message " Issues resolved: $($result.IssuesResolved)" -LogPath $LogPath

    if ($result.ActionsPerformed.Count -gt 0) {
        Write-WULog -Message "Actions completed:" -LogPath $LogPath
        foreach ($action in $result.ActionsPerformed) {
            Write-WULog -Message " - $action" -LogPath $LogPath
        }
    }

    if ($result.Success) {
        Write-WULog -Message "RECOMMENDATION: Try Windows 11 24H2 upgrade again - Dynamic Updates should now work properly" -LogPath $LogPath
    }

    return $result
}