universal-intel-wifi-bt-driver-updater.ps1
|
<#PSScriptInfo .VERSION 2026.06.0006 .GUID b3a72f1e-9c4d-4b8a-a1f2-83d5e6c09f12 .NAME universal-intel-wifi-bt-driver-updater .AUTHOR Marcin Grygiel .COMPANYNAME FirstEver.tech .COPYRIGHT (c) 2025-2026 Marcin Grygiel / FirstEver.tech. All rights reserved. .TAGS Universal Intel Wi-Fi Bluetooth Drivers Updater CAB Windows Automation .LICENSEURI https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/blob/main/LICENSE .PROJECTURI https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater .ICONURI https://raw.githubusercontent.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/main/icon.png .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES v2026.06.0006 - Bug fixes: added missing USB BT PID 0043 (AX211) to supported device list. Fixed incorrect Legacy flag shown for PCI Bluetooth devices when USB has a newer version. Fixed PCI legacy fallback in scanner (dead code corrected in v4.5 scanner). Author line in Show-FinalCredits aligned with Show-Header. v2026.06.0006 - Added support for Intel Bluetooth PCI Enumerator devices. Detects PCI\VEN_8086&DEV_xxxx hardware IDs. Uses shared CAB package (intel-bt-<version>_pci.cab) for all PCI devices. Updated banner: version 2026.06.0006, author line, removed GitHub visit line. All comments are now in English. #> <# .SYNOPSIS Detects and installs the latest Intel Wi-Fi and Bluetooth drivers. .DESCRIPTION Automatically detects, downloads, and installs the latest Intel Wi-Fi (Wi-Fi 5/6/6E/7) and Bluetooth drivers (both USB and PCI variants) for your specific hardware. Compares installed driver versions against the latest available release, then downloads and installs the correct CAB driver package(s). Security: full SHA-256 hash verification and Microsoft WHCP digital signature validation before installation. Automatic System Restore Point created before any changes. Requires Administrator privileges (auto-elevates if needed) and internet access to GitHub. Downloads are verified before installation - no unverified files are ever installed. Supports silent unattended deployment via -quiet flag. Usage: .\universal-intel-wifi-bt-driver-updater.ps1 [options] Options: -help, -? Display this help and exit. -version, -v Display the tool version and exit. -auto, -a All prompts are answered with Yes, no user interaction required. -quiet, -q Run in completely silent mode (no console window). Implies -auto. -beta Use beta database for new hardware testing. -debug, -d Enable debug output. -skipverify, -s Skip script self-hash verification. Use only for testing. Logging: All actions are logged to %ProgramData%\wifi_bt_update.log. .PARAMETER version Display the tool version and exit. .PARAMETER auto Run in automatic mode - all prompts are answered with Yes. .PARAMETER quiet Run in completely silent mode with no console window. Implies -auto. .PARAMETER beta Use the beta database for testing new hardware support. .PARAMETER debug Enable debug output. .PARAMETER skipverify Skip the script self-hash verification. .EXAMPLE .\universal-intel-wifi-bt-driver-updater.ps1 Runs the updater interactively. .EXAMPLE .\universal-intel-wifi-bt-driver-updater.ps1 -auto Runs without any user prompts. .EXAMPLE .\universal-intel-wifi-bt-driver-updater.ps1 -quiet Runs completely silently. Suitable for MDM deployment. .NOTES Author: Marcin Grygiel / FirstEver.tech License: MIT All actions are logged to %ProgramData%\wifi_bt_update.log. This tool is not affiliated with Intel Corporation. Drivers are sourced from official Intel / Windows Update servers. Use at your own risk. .LINK https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater #> # ============================================= # COMMAND-LINE PARAMETERS - MANUAL PARSING # ============================================= $rawArgs = $args $Help = $false $Version = $false $AutoMode = $false $Debug = $false $SkipVerification = $false $QuietMode = $false $Beta = $false $Developer = $false $allowedSwitches = @( '-help', '-?', '-version', '-v', '-auto', '-a', '-beta', '-developer', '-debug', '-d', '-skipverify', '-s', '-quiet', '-q' ) for ($i = 0; $i -lt $rawArgs.Count; $i++) { $arg = $rawArgs[$i] if ($arg -match '^-') { if ($allowedSwitches -notcontains $arg) { Clear-Host Write-Host "" Write-Host " Unknown parameter: $arg" Write-Host " Use -help or -? to see available options." Write-Host "" exit 1 } switch -Regex ($arg) { '^-help$' { $Help = $true } '^-version$|^-v$' { $Version = $true } '^-auto$|^-a$' { $AutoMode = $true } '^-beta$' { $Beta = $true } '^-developer$' { $Developer = $true } '^-debug$|^-d$' { $Debug = $true } '^-skipverify$|^-s$' { $SkipVerification = $true } '^-quiet$|^-q$' { $QuietMode = $true } } } else { Clear-Host Write-Host "" Write-Host " Positional arguments are not allowed." Write-Host " Use -help or -? to see available options." Write-Host "" exit 1 } } if ($QuietMode) { $newArgs = @() $hasAuto = $false foreach ($arg in $rawArgs) { if ($arg -match '^-quiet$|^-q$') { # skip } else { $newArgs += $arg if ($arg -match '^-auto$|^-a$') { $hasAuto = $true } } } if (-not $hasAuto) { $newArgs += '-auto' } $scriptPath = $MyInvocation.MyCommand.Path $argString = ($newArgs -join ' ') Start-Process -FilePath "powershell.exe" -ArgumentList "-WindowStyle Hidden -File `"$scriptPath`" $argString" exit 0 } [bool]$DebugMode = $Debug [bool]$SkipSelfHashVerification = $SkipVerification # ============================================= # SCRIPT VERSION # ============================================= $ScriptVersion = "2026.06.0006" # ============================================= $isSFX = $MyInvocation.ScriptName -like "$env:SystemRoot\Temp\universal-intel-wifi-bt-driver-updater*" if ($ScriptVersion -match '^(\d+\.\d+)-(\d{4}\.\d{2}\.\d+)$') { $DisplayVersion = "$($matches[1]) ($($matches[2]))" } else { $DisplayVersion = $ScriptVersion } if ($Help) { Get-Help $MyInvocation.MyCommand.Path exit 0 } if ($Version) { Clear-Host Write-Host "" Write-Host " Universal Intel Wi-Fi and Bluetooth Drivers Updater version $DisplayVersion" Write-Host "" exit 0 } # ============================================= # AUTO-ELEVATE IF NOT ADMIN # ============================================= $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) $isAdmin = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $isAdmin) { Clear-Host Write-Host "" Write-Host " Administrator privileges required. Restarting with elevation..." -ForegroundColor Yellow Write-Host "" $scriptPath = $MyInvocation.MyCommand.Path $argList = if ($rawArgs.Count -gt 0) { $rawArgs -join " " } else { "" } try { Start-Process -FilePath "powershell.exe" -ArgumentList "-NoExit -File `"$scriptPath`" $argList" -Verb RunAs } catch { Clear-Host Write-Host "" Write-Host " Elevation failed. Please run the script as Administrator manually." -ForegroundColor Red Write-Host "" pause exit 1 } exit 0 } # ============================================= # ELEVATED CONTEXT - CONSOLE SETUP # ============================================= Write-Host "Running with administrator privileges. Applying console settings..." -ForegroundColor Green $Host.UI.RawUI.BackgroundColor = "Black" try { [console]::WindowWidth = 75 [console]::WindowHeight = 58 [console]::BufferWidth = [console]::WindowWidth } catch { Write-Host "Failed to set console size: $_" -ForegroundColor Red } # ============================================= # CONFIGURATION # ============================================= $githubBaseUrl = "https://raw.githubusercontent.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/main/data/" $githubArchiveWiFi = "https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/releases/download/archive-wifi/" $githubArchiveBT = "https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/releases/download/archive-bt/" $wifiLatestUrl = $githubBaseUrl + "intel-wifi-driver-latest.md" $btLatestUrl = $githubBaseUrl + "intel-bt-driver-latest.md" $supportMessageUrl = $githubBaseUrl + "intel-wifi-bt-message.txt" if ($Developer) { $wifiLatestUrl = $githubBaseUrl + "intel-wifi-driver-dev.md" $btLatestUrl = $githubBaseUrl + "intel-bt-driver-dev.md" Write-Host "" Write-Host " [DEVELOPER MODE] Using development databases." -ForegroundColor Magenta Write-Host "" } elseif ($Beta) { $wifiLatestUrl = $githubBaseUrl + "intel-wifi-driver-beta.md" $btLatestUrl = $githubBaseUrl + "intel-bt-driver-beta.md" Write-Host "" Write-Host " [BETA MODE] Using beta databases." -ForegroundColor Yellow Write-Host "" } $tempDir = Join-Path $env:SystemRoot "Temp\IntelWiFiBT" # ============================================= # GLOBAL STATE # ============================================= $global:InstallationErrors = @() $global:ScriptStartTime = Get-Date $global:NewVersionLaunched = $false $logFile = Join-Path $env:ProgramData "wifi_bt_update.log" # ============================================= # VERSION MANAGEMENT FUNCTIONS # ============================================= function Get-VersionNumber { param([string]$Version) if ($Version -match '^(\d{4})\.(\d{2})\.(\d+)$') { return [int]$matches[3] } throw "Cannot parse version: $Version" } function Compare-Versions { param([string]$Version1, [string]$Version2) $ver1Num = Get-VersionNumber -Version $Version1 $ver2Num = Get-VersionNumber -Version $Version2 if ($ver1Num -eq $ver2Num) { return 0 } if ($ver1Num -lt $ver2Num) { return -1 } return 1 } # ============================================= # LOGGING FUNCTIONS # ============================================= function Write-Log { param([string]$Message, [string]$Type = "INFO") $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $logEntry = "[$timestamp] [$Type] $Message" try { Add-Content -Path $logFile -Value $logEntry -ErrorAction SilentlyContinue } catch { } if ($Type -eq "ERROR") { $global:InstallationErrors += $Message Write-Host " ERROR: $Message" -ForegroundColor Red } } function Write-DebugMessage { param([string]$Message, [string]$Color = "Gray") Write-Log -Message $Message -Type "DEBUG" if ($DebugMode) { Write-Host " DEBUG: $Message" -ForegroundColor $Color } } function Show-FinalSummary { $duration = (Get-Date) - $global:ScriptStartTime if ($global:InstallationErrors.Count -gt 0) { Write-Host "`n Completed with $($global:InstallationErrors.Count) error(s)." -ForegroundColor Red Write-Host " See $logFile for details." -ForegroundColor Red } else { Write-Host "`n Operation completed successfully." -ForegroundColor Green } Write-Log "Script execution completed in $([math]::Round($duration.TotalMinutes, 2)) minutes with $($global:InstallationErrors.Count) errors" } # ============================================= # COLOR LINE PARSING FUNCTION # ============================================= function Write-ColorLine { param([string]$Line) $validColors = [Enum]::GetNames([ConsoleColor]) $currentFg = $Host.UI.RawUI.ForegroundColor $currentBg = $Host.UI.RawUI.BackgroundColor $segments = @() $position = 0 $length = $Line.Length while ($position -lt $length) { $openBracket = $Line.IndexOf('[', $position) if ($openBracket -eq -1) { $text = $Line.Substring($position) if ($text) { $segments += [PSCustomObject]@{ Text = $text; Foreground = $currentFg; Background = $currentBg } } break } if ($openBracket -gt $position) { $text = $Line.Substring($position, $openBracket - $position) if ($text) { $segments += [PSCustomObject]@{ Text = $text; Foreground = $currentFg; Background = $currentBg } } } $closeBracket = $Line.IndexOf(']', $openBracket) if ($closeBracket -eq -1) { $text = $Line.Substring($openBracket) if ($text) { $segments += [PSCustomObject]@{ Text = $text; Foreground = $currentFg; Background = $currentBg } } break } $tagContent = $Line.Substring($openBracket + 1, $closeBracket - $openBracket - 1) $parts = $tagContent -split ',' $newFg = $null $newBg = $null if ($parts.Count -eq 1 -and $validColors -contains $parts[0]) { $newFg = [ConsoleColor]$parts[0] } elseif ($parts.Count -eq 2 -and $validColors -contains $parts[0] -and $validColors -contains $parts[1]) { $newFg = [ConsoleColor]$parts[0] $newBg = [ConsoleColor]$parts[1] } if ($newFg -ne $null) { if ($newBg -ne $null) { $currentBg = $newBg } $currentFg = $newFg $position = $closeBracket + 1 } else { $text = $Line.Substring($openBracket, $closeBracket - $openBracket + 1) $segments += [PSCustomObject]@{ Text = $text; Foreground = $currentFg; Background = $currentBg } $position = $closeBracket + 1 } } foreach ($seg in $segments) { Write-Host $seg.Text -NoNewline -ForegroundColor $seg.Foreground -BackgroundColor $seg.Background } Write-Host "" } function Get-KeyAndUrlFromLine { param([string]$Line) $validColors = [Enum]::GetNames([ConsoleColor]) $colorPattern = '\[(?:' + (($validColors | ForEach-Object { [regex]::Escape($_) }) -join '|') + ')(?:,(?:' + (($validColors | ForEach-Object { [regex]::Escape($_) }) -join '|') + '))?\]' $cleanLine = $Line -replace $colorPattern, '' if ($cleanLine -match 'press \[([A-Za-z])\]') { $key = $matches[1] if ($cleanLine -match '(https?://)?([a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?:/[^\s]*)?)') { $urlCandidate = $matches[0] if ($urlCandidate -notmatch '^https?://') { $urlCandidate = "https://$urlCandidate" } return @{ Key = $key; Url = $urlCandidate } } } return $null } # ============================================= # HEADER DISPLAY FUNCTION (UPDATED BANNER) # ============================================= function Show-Header { Clear-Host Write-Host "/*************************************************************************" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "**" -NoNewline -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host " UNIVERSAL INTEL WI-FI AND BLUETOOTH DRIVERS UPDATER " -NoNewline -ForegroundColor White -BackgroundColor DarkBlue Write-Host "**" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** --------------------------------------------------------------------- **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** **" -ForegroundColor Gray -BackgroundColor DarkBlue $paddedVersion = $DisplayVersion.PadRight(14) Write-Host "**" -NoNewline -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host " Tool Version: $paddedVersion " -NoNewline -ForegroundColor Yellow -BackgroundColor DarkBlue Write-Host "**" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "**" -NoNewline -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host " Author: Marcin Grygiel / GitHub.com/FirstEverTech " -NoNewline -ForegroundColor Green -BackgroundColor DarkBlue Write-Host "**" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** This tool is not affiliated with Intel Corporation. **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** Drivers are sourced from official Intel/WU servers. **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** Use at your own risk. **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "*************************************************************************/" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "" } # ============================================= # SCREEN MANAGEMENT FUNCTIONS # ============================================= function Show-Screen1 { Show-Header Write-Host " [SCREEN 1/4] INITIALIZATION AND SECURITY CHECKS" -ForegroundColor Cyan Write-Host " ===============================================" -ForegroundColor Cyan if ($DebugMode) { Write-Host " DEBUG MODE: ENABLED" -ForegroundColor Magenta } if ($SkipSelfHashVerification) { Write-Host "`n SELF-HASH VERIFICATION: DISABLED (Testing Mode)" -ForegroundColor Yellow } Write-Host "" Write-Host " Checking Windows system requirements..." -ForegroundColor Yellow try { $os = Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction Stop $build = [int]$os.BuildNumber if ($build -lt 17763) { Write-Host " [WARNING] Windows 10 LTSB 2015/2016 detected." -ForegroundColor Red Write-Host " TLS 1.2 may not work properly." -ForegroundColor Gray } else { Write-Host " Windows Build: $build" -ForegroundColor Gray Write-Host " Operating system compatibility: PASSED" -ForegroundColor Green } } catch { Write-Host " [INFO] Could not determine Windows build." -ForegroundColor Gray } Write-Host "" Write-Host " Checking .NET Framework prerequisites..." -ForegroundColor Yellow try { $netRelease = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" -Name "Release" -ErrorAction Stop if ($netRelease -ge 461808) { Write-Host " .NET Framework 4.7.2 or newer detected: PASSED" -ForegroundColor Green } else { Write-Host " [WARNING] .NET Framework older than 4.7.2" -ForegroundColor Red } } catch { Write-Host " [WARNING] .NET Framework 4.7.2+ not found or couldn't be checked" -ForegroundColor Red } Write-Host "" Write-Host " Testing GitHub connectivity..." -ForegroundColor Yellow try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $null = Invoke-WebRequest -Uri "https://raw.githubusercontent.com" -UseBasicParsing -TimeoutSec 5 -ErrorAction Stop Write-Host " Repository access verification: PASSED" -ForegroundColor Green } catch { Write-Host " [WARNING] Cannot reach GitHub servers" -ForegroundColor Red Write-Host " Self-hash verification will be skipped." -ForegroundColor Gray } Write-Host "" Write-Host " Pre-check summary..." -ForegroundColor Yellow if ($build -lt 17763 -or !$netRelease -or $netRelease -lt 461808) { Write-Host " [IMPORTANT] Some issues were detected." -ForegroundColor Yellow Write-Host "" if ($AutoMode) { $choice = "Y" Write-Host " Auto mode: automatically continuing (Y)." -ForegroundColor Cyan } else { do { $choice = Read-Host " Continue despite warnings? (Y/N)" $choice = $choice.Trim().ToUpper() if ($choice -ne 'Y' -and $choice -ne 'N') { Write-Host " Invalid input. Please enter Y or N." -ForegroundColor Red } } while ($choice -ne 'Y' -and $choice -ne 'N') } if ($choice -eq 'N') { Write-Host " Operation cancelled." -ForegroundColor Red if (-not $AutoMode) { $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } exit 0 } Write-Host " Continuing with limited functionality..." -ForegroundColor Yellow Write-Host "" } else { Write-Host " All system requirements verified successfully." -ForegroundColor Green } } function Show-Screen2 { Show-Header Write-Host " [SCREEN 2/4] HARDWARE DETECTION AND VERSION ANALYSIS" -ForegroundColor Cyan Write-Host " ====================================================" -ForegroundColor Cyan Write-Host "" } function Show-Screen3 { Show-Header Write-Host " [SCREEN 3/4] UPDATE CONFIRMATION AND SYSTEM PREPARATION" -ForegroundColor Cyan Write-Host " =======================================================" -ForegroundColor Cyan Write-Host "" Write-Host " IMPORTANT NOTICE:" -ForegroundColor Yellow Write-Host " The driver update process may take several minutes to complete." -ForegroundColor Yellow Write-Host " During installation, your Wi-Fi and/or Bluetooth connection may" -ForegroundColor Yellow Write-Host " temporarily disconnect. This is normal behavior and connectivity" -ForegroundColor Yellow Write-Host " will be restored once the installation is complete." -ForegroundColor Yellow Write-Host "" if ($AutoMode) { $response = "Y" Write-Host " Auto mode: automatically proceeding (Y)." -ForegroundColor Cyan } else { $response = Read-Host " Do you want to proceed with driver update? (Y/N)" } return $response } function Show-Screen4 { Show-Header Write-Host " [SCREEN 4/4] DOWNLOAD AND INSTALLATION PROGRESS" -ForegroundColor Cyan Write-Host " ===============================================" -ForegroundColor Cyan # Write-Host "" } # ============================================= # SELF-HASH VERIFICATION # ============================================= function Verify-ScriptHash { if ($SkipSelfHashVerification) { Write-Host " SKIPPED: Self-hash verification disabled (Testing Mode)." -ForegroundColor Yellow Write-Host "" return $true } try { Write-Host " Verifying Updater source file integrity..." -ForegroundColor Yellow $scriptPath = $null if ($PSCommandPath) { $scriptPath = $PSCommandPath } elseif ($MyInvocation.MyCommand.Path) { $scriptPath = $MyInvocation.MyCommand.Path } else { $potentialPath = Join-Path (Get-Location) "universal-intel-wifi-bt-driver-updater.ps1" if (Test-Path $potentialPath) { $scriptPath = $potentialPath } } if (-not $scriptPath -or -not (Test-Path $scriptPath)) { Write-Host " FAIL: Cannot locate script file for hash verification." -ForegroundColor Red return $false } $currentHash = $null $retryCount = 0 $maxRetries = 3 while ($retryCount -lt $maxRetries -and -not $currentHash) { try { $hashResult = Get-FileHash -Path $scriptPath -Algorithm SHA256 $currentHash = $hashResult.Hash.ToUpper() } catch { $retryCount++ if ($retryCount -eq $maxRetries) { Write-Host " FAIL: Could not calculate script hash after $maxRetries attempts." -ForegroundColor Red return $false } Start-Sleep -Milliseconds 500 } } $hashFileUrl = "https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/releases/download/v$ScriptVersion/universal-intel-wifi-bt-driver-updater-$ScriptVersion-ps1.sha256" Write-DebugMessage "Downloading hash from: $hashFileUrl" try { $expectedHashResponse = Invoke-WebRequest -Uri $hashFileUrl -UseBasicParsing -ErrorAction Stop $expectedHashLine = if ($expectedHashResponse.Content -is [byte[]]) { [System.Text.Encoding]::UTF8.GetString($expectedHashResponse.Content).Trim() } else { $expectedHashResponse.Content.ToString().Trim() } $expectedHashLine = $expectedHashLine.TrimStart([char]0xEF, [char]0xBB, [char]0xBF).Trim() $expectedHash = $null if ($expectedHashLine -match '^([A-Fa-f0-9]{64})\s+(\S+)$') { $expectedHash = $matches[1].ToUpper() } elseif ($expectedHashLine -match '^([A-Fa-f0-9]{64})$') { $expectedHash = $expectedHashLine.ToUpper() } elseif ($expectedHashLine -match '^([A-Fa-f0-9]{64})\s*\*?\s*(\S+)$') { $expectedHash = $matches[1].ToUpper() } if (-not $expectedHash) { Write-Host " FAIL: Could not parse hash from file." -ForegroundColor Red return $false } if ($currentHash -eq $expectedHash) { Write-Host " Updater hash verification: PASSED" -ForegroundColor Green Write-Host "" return $true } else { Write-Host " FAIL: Updater hash verification failed. Hash doesn't match." -ForegroundColor Red Write-Host "`n WARNING: The updater file may have been modified or corrupted!" -ForegroundColor Red Write-Host " Please download the Updater from the official source:" -ForegroundColor Red Write-Host " https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/releases" -ForegroundColor Cyan Write-Host "" Write-Host " Source: $expectedHash" -ForegroundColor Green Write-Host " Actual: $currentHash" -ForegroundColor Red return $false } } catch { Write-Host " ERROR: Could not download or parse hash file." -ForegroundColor Red Write-Host " Please download the Updater from the official source:" -ForegroundColor Red Write-Host " https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/releases" -ForegroundColor Red Write-Host "" Write-Host " Actual: $currentHash" -ForegroundColor Red return $false } } catch { Write-Host " ERROR: Could not verify script hash: $($_.Exception.Message)" -ForegroundColor Red return $false } } # ============================================= # UPDATER UPDATE CHECK # ============================================= function Get-DownloadsFolder { try { $registryPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" $downloadsGuid = "{374DE290-123F-4565-9164-39C4925E467B}" if (Test-Path $registryPath) { $downloadsValue = Get-ItemProperty -Path $registryPath -Name $downloadsGuid -ErrorAction SilentlyContinue if ($downloadsValue -and $downloadsValue.$downloadsGuid) { return [Environment]::ExpandEnvironmentVariables($downloadsValue.$downloadsGuid) } } return [Environment]::GetFolderPath("UserProfile") + "\Downloads" } catch { return [Environment]::GetFolderPath("UserProfile") + "\Downloads" } } function Check-ForUpdaterUpdates { try { Write-Host " Checking for newer updater version..." -ForegroundColor Yellow $versionFileUrl = "https://raw.githubusercontent.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/main/src/universal-intel-wifi-bt-driver-updater.ver" $latestVersionContent = Invoke-WebRequest -Uri $versionFileUrl -UseBasicParsing -ErrorAction Stop $latestVersion = $latestVersionContent.Content.Trim() $comparisonResult = Compare-Versions -Version1 $ScriptVersion -Version2 $latestVersion Write-DebugMessage "Current version: $ScriptVersion, Latest: $latestVersion, Result: $comparisonResult" if ($comparisonResult -eq 0) { Write-Host " Status: Already on latest version." -ForegroundColor Green Write-Host "" Write-Host " Starting hardware detection..." -ForegroundColor Gray Write-Host "" Start-Sleep -Seconds 3 return $true } elseif ($comparisonResult -lt 0) { Write-Host " A new version $latestVersion is available (current: $ScriptVersion)." -ForegroundColor Yellow if ($AutoMode) { $continueChoice = "Y" Write-Host " Auto mode: automatically continuing with current version (Y)." -ForegroundColor Cyan } else { do { Write-Host "" $continueChoice = Read-Host " Do you want to continue with the current version? (Y/N)" $continueChoice = $continueChoice.Trim().ToUpper() if ($continueChoice -ne 'Y' -and $continueChoice -ne 'N') { Write-Host " Invalid input. Please enter Y or N." -ForegroundColor Red } } while ($continueChoice -ne 'Y' -and $continueChoice -ne 'N') } if ($continueChoice -eq 'Y') { return $true } if ($AutoMode) { $downloadChoice = "N" } else { do { $downloadChoice = Read-Host " Do you want to download the latest version? (Y/N)" $downloadChoice = $downloadChoice.Trim().ToUpper() if ($downloadChoice -ne 'Y' -and $downloadChoice -ne 'N') { Write-Host " Invalid input. Please enter Y or N." -ForegroundColor Red } } while ($downloadChoice -ne 'Y' -and $downloadChoice -ne 'N') } if ($downloadChoice -eq 'Y') { $downloadUrl = "https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/releases/download/v$latestVersion/WiFi-BT-Updater-$latestVersion-Win10-Win11.exe" $downloadsFolder = Get-DownloadsFolder $outputPath = Join-Path $downloadsFolder "WiFi-BT-Updater-$latestVersion-Win10-Win11.exe" Write-Host " Downloading new version to: $outputPath" -ForegroundColor Yellow Write-Host "" $downloadSuccess = $false try { Invoke-WebRequest -Uri $downloadUrl -OutFile $outputPath -UseBasicParsing -ErrorAction Stop Write-Host " SUCCESS: New version downloaded successfully." -ForegroundColor Green Write-Host "`n File saved to:" -ForegroundColor Yellow Write-Host " $outputPath" -ForegroundColor Yellow $downloadSuccess = $true } catch { Write-Host " ERROR: Failed to download new version - $($_.Exception.Message)" -ForegroundColor Red Write-Host " Please download manually from: https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/releases" -ForegroundColor Red } if ($downloadSuccess) { if ($AutoMode) { $exitChoice = "Y" Write-Host " Auto mode: automatically exiting to run new version (Y)." -ForegroundColor Cyan } else { do { $exitChoice = Read-Host "`n Do you want to exit now to run the new version? (Y/N)" $exitChoice = $exitChoice.Trim().ToUpper() if ($exitChoice -ne 'Y' -and $exitChoice -ne 'N') { Write-Host " Invalid input. Please enter Y or N." -ForegroundColor Red } } while ($exitChoice -ne 'Y' -and $exitChoice -ne 'N') } if ($exitChoice -eq 'Y') { Write-Host " Starting the new version and closing current updater..." -ForegroundColor Green Write-Host "" Start-Process -FilePath $outputPath exit 100 } } } Cleanup if (-not $AutoMode) { Write-Host "`n Press any key..." $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } Show-FinalCredits $global:NewVersionLaunched = $true return $false } else { Write-Host " Status: Running a newer version than published ($ScriptVersion)." -ForegroundColor Cyan Write-Host "" Start-Sleep -Seconds 2 return $true } } catch { Write-Host " WARNING: Could not check for updates. Continuing..." -ForegroundColor Yellow Write-DebugMessage "Update check failed: $($_.Exception.Message)" return $true } } # ============================================= # TEMP DIRECTORY MANAGEMENT # ============================================= function Clear-TempDriverFolders { try { if (Test-Path $tempDir) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue Write-DebugMessage "Cleaned up temporary directory: $tempDir" } } catch { Write-DebugMessage "Error during cleanup: $_" } } function Cleanup { Write-Host "`n Cleaning up temporary files..." -ForegroundColor Yellow if (Test-Path $tempDir) { try { Get-ChildItem -Path $tempDir -Exclude "*.ps1" -Recurse | Remove-Item -Force -Recurse -ErrorAction Stop Write-Host " Temporary files cleaned successfully." -ForegroundColor Green } catch { Write-Host " Warning: Could not clean all temporary files." -ForegroundColor Yellow } } } # ============================================= # HARDWARE DETECTION FUNCTIONS # ============================================= # Supported Intel Wi-Fi DEV IDs (PCI) $supportedWiFiDEVs = @( # Wi-Fi 7 (BE) "272B", "A840", "A841", "E340", "E440", # Wi-Fi 6E (AX - 6 GHz) "2725", "51F0", "51F1", "54F0", "7A70", "7AF0", "7E40", "7F70", # Wi-Fi 6 (AX) "2723", "02F0", "06F0", "34F0", "3DF0", "43F0", "4DF0", "A0F0", "7740", # Wi-Fi 5 (AC) "2526", "30DC", "31DC", "9DF0", "A370" ) # Supported Intel Bluetooth USB PID IDs (VID_8087) $supportedBTPIDs = @("0025", "0AAA", "0026", "0029", "0032", "0033", "0043", "0036", "0037", "0038") # Supported Intel Bluetooth PCI DEV IDs (VEN_8086) $supportedBTDEVs = @("A876", "4D76", "E476", "E376") # Intel Bluetooth PCI Enumerator function Get-IntelWiFiDevice { try { $devices = Get-PnpDevice -Class "Net" -ErrorAction SilentlyContinue | Where-Object { $_.Status -eq "OK" } foreach ($device in $devices) { foreach ($hwid in $device.HardwareID) { if ($hwid -match 'PCI\\VEN_8086&DEV_([A-F0-9]{4})') { $devId = $matches[1].ToUpper() if ($supportedWiFiDEVs -contains $devId) { Write-DebugMessage "Found Intel Wi-Fi device: $devId ($($device.FriendlyName))" return [PSCustomObject]@{ DEV = $devId InstanceId = $device.InstanceId FriendlyName = $device.FriendlyName HardwareID = $hwid } } } } } } catch { Write-DebugMessage "Error scanning for Wi-Fi devices: $_" } return $null } function Get-IntelBTDevice { try { # First, scan Bluetooth class devices $devices = Get-PnpDevice -Class "Bluetooth" -ErrorAction SilentlyContinue | Where-Object { $_.Status -eq "OK" } # Fallback to scanning all devices if none found in Bluetooth class if (-not $devices -or $devices.Count -eq 0) { $devices = Get-PnpDevice -ErrorAction SilentlyContinue | Where-Object { $_.Status -eq "OK" -and ($_.HardwareID -like "*VID_8087*" -or $_.HardwareID -like "*VEN_8086*") } } foreach ($device in $devices) { foreach ($hwid in $device.HardwareID) { # USB Bluetooth (VID_8087) if ($hwid -match 'USB\\VID_8087&PID_([0-9A-F]{4})') { $btPid = $matches[1].ToUpper() if ($supportedBTPIDs -contains $btPid) { Write-DebugMessage "Found Intel USB BT device: PID=$btPid ($($device.FriendlyName))" return [PSCustomObject]@{ Type = "USB" PID = $btPid InstanceId = $device.InstanceId FriendlyName = $device.FriendlyName HardwareID = $hwid } } } # PCI Bluetooth (VEN_8086) - Intel Bluetooth PCI Enumerator if ($hwid -match 'PCI\\VEN_8086&DEV_([0-9A-F]{4})') { $devId = $matches[1].ToUpper() if ($supportedBTDEVs -contains $devId) { Write-DebugMessage "Found Intel PCI BT device: DEV=$devId ($($device.FriendlyName))" return [PSCustomObject]@{ Type = "PCI" PID = $devId # store DEV as PID for unified handling InstanceId = $device.InstanceId FriendlyName = $device.FriendlyName HardwareID = $hwid } } } } } } catch { Write-DebugMessage "Error scanning for BT devices: $_" } return $null } function Get-CurrentDriverVersion { param([string]$DeviceInstanceId) try { $device = Get-PnpDevice | Where-Object { $_.InstanceId -eq $DeviceInstanceId } if ($device) { $versionProperty = $device | Get-PnpDeviceProperty -KeyName "DEVPKEY_Device_DriverVersion" -ErrorAction SilentlyContinue if ($versionProperty -and $versionProperty.Data) { Write-DebugMessage "Got version from DEVPKEY: $($versionProperty.Data)" return $versionProperty.Data } } $driverInfo = Get-CimInstance -ClassName Win32_PnPSignedDriver | Where-Object { $_.DeviceID -eq $DeviceInstanceId -and $_.DriverVersion } | Select-Object -First 1 if ($driverInfo) { Write-DebugMessage "Got version from WMI: $($driverInfo.DriverVersion)" return $driverInfo.DriverVersion } } catch { Write-DebugMessage "Error getting driver version: $_" } return $null } # ============================================= # DATA DOWNLOAD FUNCTION # ============================================= function Get-RemoteContent { param([string]$Url) try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $cacheBuster = "t=" + (Get-Date -Format 'yyyyMMddHHmmss') if ($Url.Contains('?')) { $finalUrl = $Url + "&" + $cacheBuster } else { $finalUrl = $Url + "?" + $cacheBuster } Write-DebugMessage "Downloading: $finalUrl" $content = Invoke-WebRequest -Uri $finalUrl -UseBasicParsing -ErrorAction Stop return $content.Content } catch { Write-Log "Error downloading from: $Url - $($_.Exception.Message)" -Type "ERROR" return $null } } # ============================================= # RELEASE ASSET DOWNLOAD FUNCTION # (no cache buster - GitHub release assets are immutable) # ============================================= function Get-ReleaseAssetContent { param([string]$Url) try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Write-DebugMessage "Downloading release asset: $Url" $wc = New-Object System.Net.WebClient $wc.Headers.Add("User-Agent", "Mozilla/5.0") $rawContent = $wc.DownloadString($Url) return $rawContent } catch { Write-Log "Error downloading release asset: $Url - $($_.Exception.Message)" -Type "ERROR" return $null } } # ============================================= # VERSIONED DOWNLOAD INFO FUNCTIONS (using release assets) # ============================================= function Get-VersionedWiFiDownloadInfo { param([string]$Version) $url = "https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/releases/download/archive-wifi/intel-wifi-$Version.txt" Write-DebugMessage "Attempting to download versioned Wi-Fi driver info: $url" $content = Get-ReleaseAssetContent -Url $url if (-not $content) { Write-DebugMessage "Versioned Wi-Fi file not found for version $Version" return $null } $lines = $content -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" } $info = @{ SHA256 = $null; Link = $null; Backup = $null; Version = $Version; Date = $null } foreach ($line in $lines) { if ($line -match '^SHA256\s*=\s*([A-Fa-f0-9]{64})') { $info.SHA256 = $matches[1].ToUpper() } elseif ($line -match '^Link\s*=\s*(https?://.+)') { $info.Link = $matches[1].Trim() } elseif ($line -match '^Backup\s*=\s*(https?://.+)') { $info.Backup = $matches[1].Trim() } elseif ($line -match '^DriverVer\s*=\s*([^,]+),\s*([0-9.]+)') { $info.Date = $matches[1].Trim() } } if ($info.SHA256 -and $info.Link) { Write-DebugMessage "Versioned Wi-Fi download info loaded for version $Version" return $info } else { Write-DebugMessage "Versioned Wi-Fi file missing required fields SHA256 or Link" return $null } } function Get-VersionedBTDownloadInfo { param([string]$Version, [string]$BtPID, [string]$DeviceType = "USB") if ($DeviceType -eq "PCI") { # PCI devices use a shared CAB: intel-bt-<version>_pci.txt $url = "https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/releases/download/archive-bt/intel-bt-${Version}_pci.txt" Write-DebugMessage "Attempting to download PCI BT driver info (shared): $url" } else { # USB devices use per-PID files $url = "https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater/releases/download/archive-bt/intel-bt-${Version}_pid${BtPID}.txt" Write-DebugMessage "Attempting to download versioned BT driver info (per-PID): $url" } $content = Get-ReleaseAssetContent -Url $url if (-not $content) { Write-DebugMessage "Versioned BT file not found for $DeviceType (ID: $BtPID, version $Version)" return $null } $lines = $content -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" } $info = @{ SHA256 = $null; Link = $null; Backup = $null; Version = $Version; Date = $null } foreach ($line in $lines) { if ($line -match '^SHA256\s*=\s*([A-Fa-f0-9]{64})') { $info.SHA256 = $matches[1].ToUpper() } elseif ($line -match '^Link\s*=\s*(https?://.+)') { $info.Link = $matches[1].Trim() } elseif ($line -match '^Backup\s*=\s*(https?://.+)') { $info.Backup = $matches[1].Trim() } elseif ($line -match '^DriverVer\s*=\s*([^,]+),\s*([0-9.]+)') { $info.Date = $matches[1].Trim() } } if ($info.SHA256 -and $info.Link) { Write-DebugMessage "Versioned BT download info loaded for $DeviceType (ID: $BtPID) version $Version" return $info } else { Write-DebugMessage "Versioned BT file missing required fields SHA256 or Link" return $null } } # ============================================= # DATA PARSING FUNCTIONS (for .md files) # ============================================= function Parse-WiFiLatestMd { param([string]$Content) $result = @{ LatestVersion = $null ReleaseDate = $null Devices = @{} # DEV_xxxx -> @{ Chipset, Models, Generation, LatestVersion, ReleaseDate } } try { $lines = $Content -split "`n" foreach ($line in $lines) { $line = $line.Trim() if ($line -match '^Latest Version\s*=\s*([0-9.]+)') { $result.LatestVersion = $matches[1] Write-DebugMessage "WiFi Latest Version (global): $($result.LatestVersion)" } elseif ($line -match '^Release Date\s*=\s*(.+)') { $result.ReleaseDate = $matches[1].Trim() } elseif ($line -match '^\|\s*(DEV_[A-F0-9]{4})\s*\|\s*(.+?)\s*\|\s*(.+?)\s*\|\s*(.+?)\s*\|') { $devId = $matches[1] -replace 'DEV_', '' $chipset = $matches[2].Trim() $models = $matches[3].Trim() $gen = $matches[4].Trim() $deviceVersion = $null $deviceDate = $null if ($line -match '^\|\s*DEV_[A-F0-9]{4}\s*\|\s*.+?\s*\|\s*.+?\s*\|\s*.+?\s*\|\s*([0-9][0-9.]+)\s*\|\s*(.+?)\s*\|') { $deviceVersion = $matches[1].Trim() $deviceDate = $matches[2].Trim() Write-DebugMessage "WiFi per-device version: $devId -> $deviceVersion ($deviceDate)" } $result.Devices[$devId] = @{ Chipset = $chipset Models = $models Generation = $gen LatestVersion = $deviceVersion ReleaseDate = $deviceDate } Write-DebugMessage "WiFi device parsed: $devId -> Chipset=$chipset, Models=$models, Gen=$gen" } } } catch { Write-Log "WiFi MD parsing failed: $($_.Exception.Message)" -Type "ERROR" } return $result } function Parse-BTLatestMd { param([string]$Content) $result = @{ LatestVersion = $null ReleaseDate = $null Devices = @{} # Key can be USB PID or PCI DEV (both 4-hex) } try { $lines = $Content -split "`n" foreach ($line in $lines) { $line = $line.Trim() if ($line -match '^Latest Version\s*=\s*([0-9.]+)') { $result.LatestVersion = $matches[1] Write-DebugMessage "BT Latest Version (global): $($result.LatestVersion)" } elseif ($line -match '^Release Date\s*=\s*(.+)') { $result.ReleaseDate = $matches[1].Trim() } elseif ($line -match '^\|\s*([0-9A-Fa-f]{4})\s*\|\s*(.+?)\s*\|\s*(.+?)\s*\|\s*(.+?)\s*\|') { $btId = $matches[1].ToUpper() $chipset = $matches[2].Trim() $gen = $matches[3].Trim() $bt = $matches[4].Trim() $deviceVersion = $null $deviceDate = $null if ($line -match '^\|\s*[0-9A-Fa-f]{4}\s*\|\s*.+?\s*\|\s*.+?\s*\|\s*.+?\s*\|\s*([0-9][0-9.]+)\s*\|\s*(.+?)\s*\|') { $deviceVersion = $matches[1].Trim() $deviceDate = $matches[2].Trim() Write-DebugMessage "BT per-device version: $btId -> $deviceVersion ($deviceDate)" } $result.Devices[$btId] = @{ Chipset = $chipset Generation = $gen Bluetooth = $bt LatestVersion = $deviceVersion ReleaseDate = $deviceDate } Write-DebugMessage "BT device parsed: $btId -> $chipset BT $bt" } } } catch { Write-Log "BT MD parsing failed: $($_.Exception.Message)" -Type "ERROR" } return $result } # ============================================= # HASH VERIFICATION # ============================================= function Verify-FileHash { param( [string]$FilePath, [string]$ExpectedHash, [string]$HashType = "Primary", [string]$OriginalFileName = "" ) if (-not $ExpectedHash) { Write-Host " WARNING: No expected hash provided. Skipping verification." -ForegroundColor Yellow return $true } try { if (-not (Test-Path $FilePath)) { Write-Log "File not found for hash check: $FilePath" -Type "ERROR" return $false } $actualHash = (Get-FileHash -Path $FilePath -Algorithm SHA256).Hash Write-DebugMessage "SHA256 for $FilePath : $actualHash" } catch { Write-Log "Error calculating hash: $($_.Exception.Message)" -Type "ERROR" return $false } if ($actualHash -eq $ExpectedHash) { Write-Host " PASS: $HashType hash verification passed." -ForegroundColor Green return $true } else { $displayName = if ($OriginalFileName) { $OriginalFileName } else { Split-Path $FilePath -Leaf } Write-Host " $HashType hash verification FAILED: $displayName" -ForegroundColor Red Write-Host " Source: $ExpectedHash" -ForegroundColor Red Write-Host " Actual: $actualHash" -ForegroundColor Red Write-Log "$HashType hash mismatch for $displayName. Source: $ExpectedHash, Actual: $actualHash" -Type "ERROR" return $false } } # ============================================= # DIGITAL SIGNATURE VERIFICATION FUNCTIONS # ============================================= function Verify-FileSignature { param([string]$FilePath) try { Write-DebugMessage "Verifying digital signature for: $FilePath" $signature = Get-AuthenticodeSignature -FilePath $FilePath Write-DebugMessage "Signature status: $($signature.Status)" Write-DebugMessage "Signer: $($signature.SignerCertificate.Subject)" Write-DebugMessage "Signature Algorithm: $($signature.SignerCertificate.SignatureAlgorithm.FriendlyName)" if ($signature.Status -ne 'Valid') { Write-Log "Digital signature is not valid. Status: $($signature.Status)" -Type "ERROR" Write-Host " FAIL: Digital signature verification - Status: $($signature.Status)" -ForegroundColor Red return $false } if ($signature.SignerCertificate.Subject -notmatch 'CN=Microsoft Windows Hardware Compatibility Publisher') { Write-Log "File not signed by Microsoft Windows HW Compatibility Publisher. Signer: $($signature.SignerCertificate.Subject)" -Type "ERROR" Write-Host " FAIL: Digital signature verification - Not signed by Microsoft Windows HW Compatibility Publisher." -ForegroundColor Red return $false } if ($signature.SignerCertificate.SignatureAlgorithm.FriendlyName -notmatch 'sha256') { Write-Log "Signature not using SHA256 algorithm. Algorithm: $($signature.SignerCertificate.SignatureAlgorithm.FriendlyName)" -Type "ERROR" Write-Host " FAIL: Digital signature verification - Not using SHA256 algorithm" -ForegroundColor Red return $false } Write-Host " PASS: Digitally signed by Microsoft Windows HW Compatibility Publisher." -ForegroundColor Green Write-DebugMessage "Digital signature verification passed for $FilePath" return $true } catch { Write-Log "Error verifying digital signature: $($_.Exception.Message)" -Type "ERROR" Write-Host " FAIL: Digital signature verification - Error: $($_.Exception.Message)" -ForegroundColor Red return $false } } # ============================================= # DOWNLOAD FUNCTION # ============================================= function Download-VerifyFile { param( [string]$Url, [string]$OutFile, [string]$ExpectedHash, [string]$SourceName = "Primary" ) try { Write-Host " Downloading from $SourceName source..." -ForegroundColor Yellow Write-DebugMessage "URL: $Url" try { Invoke-WebRequest -Uri $Url -OutFile $OutFile -UseBasicParsing -ErrorAction Stop } catch { Write-Log "Download failed [$SourceName]: $($_.Exception.Message)" -Type "ERROR" return @{ Success = $false; ErrorType = "DownloadFailed" } } if (-not (Test-Path $OutFile)) { return @{ Success = $false; ErrorType = "DownloadFailed" } } if ($ExpectedHash) { Write-Host " Verifying $SourceName source file integrity..." -ForegroundColor Yellow $fileName = [System.IO.Path]::GetFileName($Url) if (-not (Verify-FileHash -FilePath $OutFile -ExpectedHash $ExpectedHash -HashType $SourceName -OriginalFileName $fileName)) { Remove-Item $OutFile -Force -ErrorAction SilentlyContinue return @{ Success = $false; ErrorType = "HashMismatch" } } } return @{ Success = $true; ErrorType = "None" } } catch { Write-Log "Unexpected error in Download-VerifyFile: $_" -Type "ERROR" return @{ Success = $false; ErrorType = "UnknownError" } } } # ============================================= # CAB EXTRACTION AND DRIVER INSTALLATION # ============================================= function Install-DriverFromCab { param( [string]$CabPath, [string]$DeviceInstanceId, [string]$DeviceType ) $extractPath = "$tempDir\extracted_$(Get-Random)" try { New-Item -ItemType Directory -Path $extractPath -Force | Out-Null Write-Host " Verifying driver digital signature..." -ForegroundColor Yellow if (-not (Verify-FileSignature -FilePath $CabPath)) { Write-Log "Driver digital signature verification failed. Aborting installation." -Type "ERROR" Write-Host " ERROR: Driver digital signature verification failed. Installation aborted." -ForegroundColor Red return $false } Write-Host " Extracting driver package..." -ForegroundColor Yellow Write-DebugMessage "Extracting $CabPath to $extractPath" $expandResult = & expand.exe "$CabPath" "$extractPath" -F:* 2>&1 if ($LASTEXITCODE -ne 0) { Write-Log "CAB extraction failed (exit $LASTEXITCODE): $expandResult" -Type "ERROR" return $false } $infFiles = Get-ChildItem -Path $extractPath -Filter "*.inf" -Recurse -ErrorAction SilentlyContinue if ($infFiles.Count -eq 0) { Write-Log "No INF files found in extracted CAB: $CabPath" -Type "ERROR" return $false } Write-DebugMessage "Found $($infFiles.Count) INF file(s): $($infFiles.Name -join ', ')" Write-Host " Staging driver to Windows driver store..." -ForegroundColor Yellow foreach ($inf in $infFiles) { $pnpOut = pnputil /add-driver "$($inf.FullName)" /install 2>&1 Write-DebugMessage "pnputil /add-driver: $pnpOut" if ($LASTEXITCODE -ne 0 -and $LASTEXITCODE -ne 3010 -and $LASTEXITCODE -ne 259) { Write-Log "pnputil /add-driver failed (exit $LASTEXITCODE)" -Type "ERROR" return $false } } if ($DeviceInstanceId) { Write-Host " Updating $DeviceType device driver..." -ForegroundColor Yellow $updateOut = pnputil /update-device "$DeviceInstanceId" /install 2>&1 Write-DebugMessage "pnputil /update-device: $updateOut" if ($LASTEXITCODE -ne 0 -and $LASTEXITCODE -ne 1 -and $LASTEXITCODE -ne 3010 -and $LASTEXITCODE -ne 259) { Write-Log "pnputil /update-device failed (exit $LASTEXITCODE)" -Type "ERROR" return $false } } Write-Host " $DeviceType driver installed successfully." -ForegroundColor Green Write-Log "$DeviceType driver installed from: $CabPath" return $true } catch { Write-Log "Error installing $DeviceType driver from CAB: $_" -Type "ERROR" return $false } finally { if (Test-Path $extractPath) { Remove-Item $extractPath -Recurse -Force -ErrorAction SilentlyContinue } } } function Install-DriverWithFallback { param( [string]$PrimaryUrl, [string]$BackupUrl, [string]$ExpectedHash, [string]$DeviceInstanceId, [string]$DeviceType, [string]$VersionLabel ) Write-Host "`n Installing $DeviceType driver ($VersionLabel)" -ForegroundColor Cyan $tempCab = "$tempDir\temp_$(Get-Random).cab" $downloadSuccess = $false $errorPhase = $null Write-Host " Attempting download from primary source..." -ForegroundColor Yellow $primaryResult = Download-VerifyFile -Url $PrimaryUrl -OutFile $tempCab -ExpectedHash $ExpectedHash -SourceName "Primary" if ($primaryResult.Success) { $downloadSuccess = $true Write-Host " SUCCESS: Primary source - download and hash verification successful." -ForegroundColor Green } else { $errorPhase = if ($primaryResult.ErrorType -eq "HashMismatch") { "1b" } else { "1a" } if ($BackupUrl) { Write-Host " Attempting download from backup source..." -ForegroundColor Yellow $backupResult = Download-VerifyFile -Url $BackupUrl -OutFile $tempCab -ExpectedHash $ExpectedHash -SourceName "Backup" if ($backupResult.Success) { $downloadSuccess = $true Write-Host " SUCCESS: Backup source - download and hash verification successful." -ForegroundColor Green } else { $errorPhase = if ($backupResult.ErrorType -eq "HashMismatch") { "2b" } else { "2a" } } } else { Write-Host " No backup source available." -ForegroundColor Red } } if (-not $downloadSuccess) { $msg = switch ($errorPhase) { "1a" { "Primary source download failed and no backup available." } "1b" { "Primary source file corrupted (hash mismatch) and no backup available." } "2a" { "Both primary and backup sources download failed." } "2b" { "Both primary and backup sources have hash mismatches." } default { "Unknown download error." } } Write-Host "`n ERROR: $msg" -ForegroundColor Red if (Test-Path $tempCab) { Remove-Item $tempCab -Force -ErrorAction SilentlyContinue } return $false } $installResult = Install-DriverFromCab -CabPath $tempCab -DeviceInstanceId $DeviceInstanceId -DeviceType $DeviceType if (Test-Path $tempCab) { Remove-Item $tempCab -Force -ErrorAction SilentlyContinue } return $installResult } # ============================================= # FINAL CREDITS FUNCTION # ============================================= function Show-FinalCredits { Clear-Host Write-Host "/*************************************************************************" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "**" -NoNewline -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host " UNIVERSAL INTEL WI-FI AND BLUETOOTH DRIVERS UPDATER " -NoNewline -ForegroundColor White -BackgroundColor DarkBlue Write-Host "**" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** --------------------------------------------------------------------- **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** **" -ForegroundColor Gray -BackgroundColor DarkBlue $paddedVersion = $DisplayVersion.PadRight(14) Write-Host "**" -NoNewline -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host " Tool Version: $paddedVersion " -NoNewline -ForegroundColor Yellow -BackgroundColor DarkBlue Write-Host "**" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "**" -NoNewline -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host " Author: Marcin Grygiel / GitHub.com/FirstEverTech " -NoNewline -ForegroundColor Green -BackgroundColor DarkBlue Write-Host "**" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** This tool is not affiliated with Intel Corporation. **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** Drivers are sourced from official Intel/WU servers. **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** Use at your own risk. **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "** **" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "*************************************************************************/" -ForegroundColor Gray -BackgroundColor DarkBlue Write-Host "" Write-Host " THANK YOU FOR USING UNIVERSAL INTEL WI-FI AND BLUETOOTH DRIVERS UPDATER" -ForegroundColor Cyan Write-Host " ========================================================================" -ForegroundColor Cyan Write-Host "" Write-Host " I hope this tool has been helpful in updating your system." -ForegroundColor Yellow Write-Host "" $keyActions = @{} $cacheBuster = "?t=$(Get-Date -Format 'yyyyMMddHHmmss')" try { $content = Invoke-WebRequest -Uri ($supportMessageUrl + $cacheBuster) -UseBasicParsing -ErrorAction Stop $lines = $content.Content -split "`r?`n" } catch { $lines = @( "[Magenta]", "[Magenta] SUPPORT THIS PROJECT", "[Magenta] ====================", "", " This project is maintained in my free time.", " Your support ensures regular updates and compatibility.", "", " Support options:", "", "[Green] - PayPal Donation:[Yellow] tinyurl.com/fet-paypal[Gray] - press [Black,Gray][P][Gray,Black] key", "[Green] - Buy Me a Coffee:[Yellow] tinyurl.com/fet-coffee[Gray] - press [Black,Gray][C][Gray,Black] key", "[Green] - GitHub Sponsors:[Yellow] tinyurl.com/fet-github[Gray] - press [Black,Gray][G][Gray,Black] key", "", " If this project helped you, please consider:", "", "[Green] - Giving it a STAR on GitHub", "[Green] - Sharing with friends and colleagues", "[Green] - Reporting issues or suggesting features", "[Green] - Supporting development financially", "", "[Magenta]", "[Magenta] CAREER OPPORTUNITY", "[Magenta] ==================", "", " I'm currently seeking new challenges where I can apply my expertise", " in solving complex IT infrastructure problems. If your organization", " struggles with system compatibility, automation, or tooling gaps,", " let's discuss how I can help.", "", "[Green] - Connect with me:[Yellow] linkedin.com/in/marcin-grygiel[Gray] - press [Black,Gray][L][Gray,Black] key" ) } foreach ($line in $lines) { Write-ColorLine $line $keyInfo = Get-KeyAndUrlFromLine -Line $line if ($keyInfo) { if ($keyInfo.Key -match '[a-zA-Z]') { $keyActions[$keyInfo.Key.ToUpper()] = $keyInfo.Url $keyActions[$keyInfo.Key.ToLower()] = $keyInfo.Url } else { $keyActions[$keyInfo.Key] = $keyInfo.Url } } } if ($AutoMode) { return } Write-Host "`n Press " -NoNewline -ForegroundColor Gray Write-Host "P" -NoNewline -ForegroundColor Yellow Write-Host "=PayPal, " -NoNewline -ForegroundColor Gray Write-Host "C" -NoNewline -ForegroundColor Yellow Write-Host "=Coffee, " -NoNewline -ForegroundColor Gray Write-Host "G" -NoNewline -ForegroundColor Yellow Write-Host "=GitHub, " -NoNewline -ForegroundColor Gray Write-Host "L" -NoNewline -ForegroundColor Yellow Write-Host "=LinkedIn, or any other key to exit." -ForegroundColor Gray $key = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") $pressed = $key.Character.ToString() if ($keyActions.ContainsKey($pressed)) { Start-Process $keyActions[$pressed] } if (-not $isSFX) { Clear-Host Write-Host "`n Thank you for using Universal Intel Wi-Fi and Bluetooth Drivers Updater!`n" -ForegroundColor Cyan } exit } # ============================================= # MAIN SCRIPT EXECUTION # ============================================= try { Show-Screen1 Write-Host "" if (-not (Verify-ScriptHash)) { Write-Host " Update process aborted for security reasons." -ForegroundColor Red Cleanup if (-not $AutoMode) { Write-Host "`n Press any key..." $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } Show-FinalCredits exit 1 } $updateCheckResult = Check-ForUpdaterUpdates if (-not $updateCheckResult) { exit 100 } Clear-TempDriverFolders New-Item -ItemType Directory -Path $tempDir -Force | Out-Null Write-DebugMessage "Created temporary directory: $tempDir" # ------------------------------------------ Show-Screen2 # ------------------------------------------ # Hardware detection Write-Host " Scanning for Intel Wi-Fi and Bluetooth devices..." -ForegroundColor Yellow Write-Host "" $wifiDevice = Get-IntelWiFiDevice $btDevice = Get-IntelBTDevice $totalFound = 0 if ($wifiDevice) { $totalFound++ } if ($btDevice) { $totalFound++ } if ($totalFound -eq 0) { Write-Host " No supported Intel Wi-Fi or Bluetooth devices found." -ForegroundColor Yellow Write-Host " Supported: Wi-Fi 5 (AC) / Wi-Fi 6 (AX) / Wi-Fi 6E (AXE) / Wi-Fi 7 (BE)" -ForegroundColor Gray Write-Host " Supported Bluetooth: USB (PID 0025,0AAA,0026,0029,0032,0033,0036,0037,0038) and PCI (DEV A876,4D76,E476,E376)" -ForegroundColor Gray Cleanup if (-not $AutoMode) { Write-Host "`n Press any key to continue..." $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } Show-FinalCredits exit } Write-Host " Found $totalFound Intel Wireless device(s)" -ForegroundColor Green Write-Host " Downloading latest driver information..." -ForegroundColor Yellow # Download databases $wifiLatestContent = $null $btLatestContent = $null if ($wifiDevice) { $wifiLatestContent = Get-RemoteContent -Url $wifiLatestUrl } if ($btDevice) { $btLatestContent = Get-RemoteContent -Url $btLatestUrl } if (($wifiDevice -and (-not $wifiLatestContent)) -or ($btDevice -and (-not $btLatestContent))) { Write-Host " Failed to download driver information. Please check your internet connection." -ForegroundColor Red Cleanup if (-not $AutoMode) { Write-Host "`n Press any key..." $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } Show-FinalCredits exit } Write-Host " Parsing driver information..." -ForegroundColor Green Write-Host "" # Parse .md files $wifiData = if ($wifiLatestContent) { Parse-WiFiLatestMd -Content $wifiLatestContent } else { $null } $btData = if ($btLatestContent) { Parse-BTLatestMd -Content $btLatestContent } else { $null } # ---- Match detected devices to database ---- $wifiInfo = $null $btInfo = $null if ($wifiDevice -and $wifiData) { $devEntry = $wifiData.Devices[$wifiDevice.DEV] if ($devEntry) { Write-Host " Found compatible device: Intel Wireless Wi-Fi (HWID: $($wifiDevice.DEV))" -ForegroundColor Green $wifiCurrentVersion = Get-CurrentDriverVersion -DeviceInstanceId $wifiDevice.InstanceId # Determine target version and date for this device $wifiDeviceVersion = $wifiData.LatestVersion $wifiDeviceDate = $wifiData.ReleaseDate if ($devEntry.LatestVersion) { $wifiDeviceVersion = $devEntry.LatestVersion $wifiDeviceDate = if ($devEntry.ReleaseDate) { $devEntry.ReleaseDate } else { $wifiData.ReleaseDate } } $wifiIsLegacy = ($wifiDeviceVersion -ne $wifiData.LatestVersion) # Try to get versioned download info $wifiDownloadBlock = $null if ($wifiDeviceVersion) { $versionedInfo = Get-VersionedWiFiDownloadInfo -Version $wifiDeviceVersion if ($versionedInfo) { $wifiDownloadBlock = @{ DEVs = [System.Collections.Generic.List[string]]::new() SHA256 = $versionedInfo.SHA256 Link = $versionedInfo.Link Backup = $versionedInfo.Backup Version = $versionedInfo.Version Date = $versionedInfo.Date } $wifiDownloadBlock.DEVs.Add("DEV_$($wifiDevice.DEV)") Write-DebugMessage "Using versioned Wi-Fi download info for version $wifiDeviceVersion" } } # If versioned info not available, log error if (-not $wifiDownloadBlock) { Write-DebugMessage "Versioned Wi-Fi download info not found for version $wifiDeviceVersion" } $wifiInfo = @{ DEV = $wifiDevice.DEV InstanceId = $wifiDevice.InstanceId Chipset = $devEntry.Chipset Models = $devEntry.Models Generation = $devEntry.Generation LatestVersion = $wifiDeviceVersion ReleaseDate = $wifiDeviceDate GlobalLatestVersion = $wifiData.LatestVersion IsLegacy = $wifiIsLegacy CurrentVersion = $wifiCurrentVersion Block = $wifiDownloadBlock } } else { Write-Host " [WARNING] Wi-Fi device DEV_$($wifiDevice.DEV) not found in database." -ForegroundColor Yellow } } if ($btDevice -and $btData) { $btId = $btDevice.PID # For USB this is PID, for PCI this is DEV (both 4-hex) $pidEntry = $btData.Devices[$btId] if ($pidEntry) { Write-Host " Found compatible device: Intel Wireless Bluetooth ($($btDevice.Type) - ID: $btId)" -ForegroundColor Green $btCurrentVersion = Get-CurrentDriverVersion -DeviceInstanceId $btDevice.InstanceId # Determine target version and date for this device $btDeviceVersion = $btData.LatestVersion $btDeviceDate = $btData.ReleaseDate if ($pidEntry.LatestVersion) { $btDeviceVersion = $pidEntry.LatestVersion $btDeviceDate = if ($pidEntry.ReleaseDate) { $pidEntry.ReleaseDate } else { $btData.ReleaseDate } } $btIsLegacy = ($btDeviceVersion -ne $btData.LatestVersion) -and ($btDevice.Type -eq "USB") # Try to get versioned download info (use DeviceType to select correct file) $btDownloadBlock = $null if ($btDeviceVersion) { $versionedInfo = Get-VersionedBTDownloadInfo -Version $btDeviceVersion -BtPID $btId -DeviceType $btDevice.Type if ($versionedInfo) { $btDownloadBlock = @{ HWIDs = [System.Collections.Generic.List[string]]::new() SHA256 = $versionedInfo.SHA256 Link = $versionedInfo.Link Backup = $versionedInfo.Backup Version = $versionedInfo.Version Date = $versionedInfo.Date } $btDownloadBlock.HWIDs.Add($btDevice.HardwareID) Write-DebugMessage "Using versioned BT download info for $($btDevice.Type) (ID: $btId) version $btDeviceVersion" } } if (-not $btDownloadBlock) { Write-DebugMessage "Versioned BT download info not found for $($btDevice.Type) ID $btId version $btDeviceVersion" } $btInfo = @{ PID = $btId Type = $btDevice.Type InstanceId = $btDevice.InstanceId Chipset = $pidEntry.Chipset Generation = $pidEntry.Generation Bluetooth = $pidEntry.Bluetooth LatestVersion = $btDeviceVersion ReleaseDate = $btDeviceDate GlobalLatestVersion = $btData.LatestVersion IsLegacy = $btIsLegacy CurrentVersion = $btCurrentVersion Block = $btDownloadBlock } } else { Write-Host " [WARNING] Bluetooth $($btDevice.Type) ID $btId not found in database." -ForegroundColor Yellow } } if (-not $wifiInfo -and -not $btInfo) { Write-Host "`n No compatible devices matched in the database." -ForegroundColor Yellow Cleanup if (-not $AutoMode) { Write-Host "`n Press any key..." $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } Show-FinalCredits exit } # ---- Platform Information display ---- Write-Host "" Write-Host " =============== Platform Information ===============" -ForegroundColor Cyan Write-Host "" $wifiNeedsUpdate = $false $btNeedsUpdate = $false if ($wifiInfo) { Write-Host " Chipset: Intel $($wifiInfo.Generation) $($wifiInfo.Chipset)" -ForegroundColor White Write-Host " Model: $($wifiInfo.Models)" -ForegroundColor Gray if ($wifiInfo.IsLegacy) { Write-Host " [LEGACY] Support ended - last available version: $($wifiInfo.LatestVersion) (current active: $($wifiInfo.GlobalLatestVersion))" -ForegroundColor DarkYellow } if ($wifiInfo.CurrentVersion) { Write-Host " Current Version: $($wifiInfo.CurrentVersion) ---> Latest Version: $($wifiInfo.LatestVersion)" -ForegroundColor Gray } else { Write-Host " Current Version: Unable to determine ---> Latest Version: $($wifiInfo.LatestVersion)" -ForegroundColor Gray } Write-Host " Driver Date: $($wifiInfo.ReleaseDate)" -ForegroundColor Yellow if ($wifiInfo.CurrentVersion) { try { $curVer = [version]$wifiInfo.CurrentVersion $latestVer = [version]$wifiInfo.LatestVersion if ($curVer -lt $latestVer) { Write-Host " Status: Update available - current: $($wifiInfo.CurrentVersion), latest: $($wifiInfo.LatestVersion)" -ForegroundColor Yellow $wifiNeedsUpdate = $true } elseif ($curVer -gt $latestVer) { Write-Host " Status: Newer version installed (may be a pre-release)." -ForegroundColor Cyan } else { Write-Host " Status: Already on latest available version." -ForegroundColor Green } } catch { if ($wifiInfo.CurrentVersion -ne $wifiInfo.LatestVersion) { Write-Host " Status: Update available - current: $($wifiInfo.CurrentVersion), latest: $($wifiInfo.LatestVersion)" -ForegroundColor Yellow $wifiNeedsUpdate = $true } else { Write-Host " Status: Already on latest available version." -ForegroundColor Green } } } else { Write-Host " Status: Driver will be installed." -ForegroundColor Yellow $wifiNeedsUpdate = $true } Write-Host "" } if ($btInfo) { if ($wifiInfo) { Write-Host " Chipset: Intel $($btInfo.Generation) $($btInfo.Chipset)" -ForegroundColor White } else { Write-Host " Chipset: Intel Standalone Bluetooth Adapter ($($btInfo.Type))" -ForegroundColor White } Write-Host " Device: Intel Wireless Bluetooth $($btInfo.Bluetooth)" -ForegroundColor Gray Write-Host " Interface: $($btInfo.Type)" -ForegroundColor Gray if ($btInfo.IsLegacy) { Write-Host " [LEGACY] Support ended - last available version: $($btInfo.LatestVersion) (current active: $($btInfo.GlobalLatestVersion))" -ForegroundColor DarkYellow } if ($btInfo.CurrentVersion) { Write-Host " Current Version: $($btInfo.CurrentVersion) ---> Latest Version: $($btInfo.LatestVersion)" -ForegroundColor Gray } else { Write-Host " Current Version: Unable to determine ---> Latest Version: $($btInfo.LatestVersion)" -ForegroundColor Gray } Write-Host " Driver Date: $($btInfo.ReleaseDate)" -ForegroundColor Yellow if ($btInfo.CurrentVersion) { try { $curVer = [version]$btInfo.CurrentVersion $latestVer = [version]$btInfo.LatestVersion if ($curVer -lt $latestVer) { Write-Host " Status: Update available - current: $($btInfo.CurrentVersion), latest: $($btInfo.LatestVersion)" -ForegroundColor Yellow $btNeedsUpdate = $true } elseif ($curVer -gt $latestVer) { Write-Host " Status: Newer version installed (may be a pre-release)." -ForegroundColor Cyan } else { Write-Host " Status: Already on latest available version." -ForegroundColor Green } } catch { if ($btInfo.CurrentVersion -ne $btInfo.LatestVersion) { Write-Host " Status: Update available - current: $($btInfo.CurrentVersion), latest: $($btInfo.LatestVersion)" -ForegroundColor Yellow $btNeedsUpdate = $true } else { Write-Host " Status: Already on latest available version." -ForegroundColor Green } } } else { Write-Host " Status: Driver will be installed." -ForegroundColor Yellow $btNeedsUpdate = $true } Write-Host "" } # ---- Update / reinstall prompt ---- $updateCount = 0 if ($wifiNeedsUpdate) { $updateCount++ } if ($btNeedsUpdate) { $updateCount++ } if ($updateCount -gt 0) { $driverWord = if ($updateCount -gt 1) { "drivers" } else { "driver" } Write-Host " A newer version of the $driverWord is available." -ForegroundColor Green if ($AutoMode) { $response = "Y" Write-Host " Auto mode: automatically installing (Y)." -ForegroundColor Cyan } else { $response = Read-Host " Do you want to install the latest $driverWord? (Y/N)" } if (-not ($response -eq "Y" -or $response -eq "y")) { Write-Host "`n Installation cancelled." -ForegroundColor Yellow Cleanup if (-not $AutoMode) { Write-Host "`n Press any key..." $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } Show-FinalCredits exit } } else { # Both up to date - offer force reinstall Write-Host " All drivers are up to date." -ForegroundColor Green if ($AutoMode) { $response = "Y" Write-Host " Auto mode: automatically forcing reinstall (Y)." -ForegroundColor Cyan } else { $response = Read-Host " Do you want to force reinstall this driver(s) anyway? (Y/N)" } if ($response -eq "Y" -or $response -eq "y") { if ($wifiInfo) { $wifiNeedsUpdate = $true } if ($btInfo) { $btNeedsUpdate = $true } } else { Write-Host "`n Installation cancelled." -ForegroundColor Yellow Cleanup if (-not $AutoMode) { Write-Host "`n Press any key..." $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } Show-FinalCredits exit } } # ------------------------------------------ $confirmResponse = Show-Screen3 # ------------------------------------------ if (-not ($confirmResponse -eq "Y" -or $confirmResponse -eq "y")) { Write-Host "`n Update cancelled." -ForegroundColor Yellow Cleanup if (-not $AutoMode) { Write-Host "`n Press any key..." $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } Show-FinalCredits exit } # System Restore Point Write-Host "`n Starting driver update process..." -ForegroundColor Green Write-Host " Creating system restore point..." -ForegroundColor Yellow try { try { $null = Enable-ComputerRestore -Drive "C:\" -ErrorAction SilentlyContinue } catch { } $restorePointDescription = "Before Intel Wi-Fi BT Driver Update - $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" $warningMessages = @() Checkpoint-Computer -Description $restorePointDescription -RestorePointType "MODIFY_SETTINGS" -WarningVariable warningMessages -WarningAction SilentlyContinue -ErrorAction Stop if ($warningMessages.Count -gt 0) { $warnText = $warningMessages -join " " if ($warnText -match "1440 minutes" -or $warnText -match "past.*minutes") { throw "RestorePointFrequencyLimit" } } Write-Host " System restore point created successfully." -ForegroundColor Green Write-Host " '$restorePointDescription'" -ForegroundColor Green Write-Host "`n Preparing for installation..." -ForegroundColor Yellow Start-Sleep -Seconds 5 } catch { $errMsg = $_.Exception.Message if ($errMsg -match "RestorePointFrequencyLimit" -or $errMsg -match "1440 minutes") { Write-Host "`n IMPORTANT NOTICE:" -ForegroundColor Yellow Write-Host " Another restore point was created within the last 24 hours." -ForegroundColor Yellow Write-Host " Windows currently cannot create more restore points." -ForegroundColor Yellow Write-Host "" if ($AutoMode) { $continueResponse = "Y" Write-Host " Auto mode: automatically continuing without restore point (Y)." -ForegroundColor Cyan } else { $continueResponse = Read-Host " Do you want to continue without creating a restore point? (Y/N)" } if (-not ($continueResponse -eq "Y" -or $continueResponse -eq "y")) { Write-Host "`n Installation cancelled." -ForegroundColor Yellow Cleanup if (-not $AutoMode) { Write-Host "`n Press any key..." $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } Show-FinalCredits exit } } else { Write-Host " WARNING: Could not create system restore point. Continuing anyway..." -ForegroundColor Yellow } Write-Host "`n Preparing for installation..." -ForegroundColor Gray Start-Sleep -Seconds 5 } # ------------------------------------------ Show-Screen4 # ------------------------------------------ $successCount = 0 # Install Wi-Fi driver if ($wifiNeedsUpdate -and $wifiInfo -and $wifiInfo.Block -and $wifiInfo.Block.Link) { $wifiResult = Install-DriverWithFallback ` -PrimaryUrl $wifiInfo.Block.Link ` -BackupUrl $wifiInfo.Block.Backup ` -ExpectedHash $wifiInfo.Block.SHA256 ` -DeviceInstanceId $wifiInfo.InstanceId ` -DeviceType "Intel Wi-Fi" ` -VersionLabel $wifiInfo.LatestVersion if ($wifiResult) { $successCount++ } } elseif ($wifiNeedsUpdate) { Write-Host "`n ERROR: No download information found for Wi-Fi driver (DEV_$($wifiInfo.DEV))." -ForegroundColor Red Write-Host " Please check versioned release files (intel-wifi-<version>.txt in archive-wifi release)." -ForegroundColor Yellow } # Install Bluetooth driver if ($btNeedsUpdate -and $btInfo -and $btInfo.Block -and $btInfo.Block.Link) { $btResult = Install-DriverWithFallback ` -PrimaryUrl $btInfo.Block.Link ` -BackupUrl $btInfo.Block.Backup ` -ExpectedHash $btInfo.Block.SHA256 ` -DeviceInstanceId $btInfo.InstanceId ` -DeviceType "Intel Bluetooth ($($btInfo.Type))" ` -VersionLabel $btInfo.LatestVersion if ($btResult) { $successCount++ } } elseif ($btNeedsUpdate) { Write-Host "`n ERROR: No download information found for Bluetooth driver (ID: $($btInfo.PID), Type: $($btInfo.Type))." -ForegroundColor Red Write-Host " Please check versioned release files (intel-bt-<version>_pid<PID>.txt or intel-bt-<version>_pci.txt in archive-bt release)." -ForegroundColor Yellow } # Summary if ($successCount -gt 0) { Write-Host "`n IMPORTANT NOTICE:" -ForegroundColor Yellow Write-Host " Computer restart may be required to complete driver installation!" -ForegroundColor Yellow $driverWord = if ($successCount -gt 1) { "drivers" } else { "driver" } Write-Host "`n Summary: Successfully installed $successCount $driverWord." -ForegroundColor Green } else { Write-Host "`n No drivers were successfully installed." -ForegroundColor Red } Cleanup Show-FinalSummary Write-Host "`n Driver update process completed." -ForegroundColor Cyan Write-Host " If you have any issues with this tool, please report them at:" Write-Host " https://github.com/FirstEverTech/Universal-Intel-WiFi-BT-Updater" -ForegroundColor Cyan if ($DebugMode) { Write-Host "`n [DEBUG MODE ENABLED - All debug messages were shown]" -ForegroundColor Magenta } if (-not $AutoMode) { Write-Host "`n Press any key to continue..." -ForegroundColor Gray $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } Show-FinalCredits exit 0 } catch { Write-Log "Unhandled error in main execution: $($_.Exception.Message)" -Type "ERROR" Write-Host " An unexpected error occurred. Please check the log file at $logFile for details." -ForegroundColor Red Cleanup if (-not $AutoMode) { Write-Host "`n Press any key..." $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } Show-FinalCredits exit 1 } |