diff --git a/README.md b/README.md index 6ffdc70..b46053b 100644 --- a/README.md +++ b/README.md @@ -11,16 +11,16 @@ It will scan your system for *OpenCL Installable Client Driver (ICD)* files by A - amdocl64.dll - versioned variants (e.g. amdocl_\*.dll, amdocl64_\*.dll) -The scripts ensure proper detection and registration of the drivers, including handling SysWOW64, scanning the PATH safely, registering versioned DLLs and avoiding duplicate entries. -The PowerShell version additionally verifies DLL signatures, detects 32/64-bit bitness more reliably, safely cleans up or moves invalid entries, handles DriverStore and versioned DLLs intelligently and provides more detailed error reporting and status output. +The scripts ensure proper detection and registration of AMD OpenCL drivers, handling SysWOW64, scanning the PATH safely, providing clear status output, supporting versioned and custom ICD DLLs, avoiding duplicate registry entries, and modifies the registry only if automatic backups are detected or enabled.
+The PowerShell version adds signature verification, more precise 32/64-bit detection, safe cleanup or relocation of invalid entries, intelligent handling of DriverStore and versioned DLLs, more detailed output, and an option to enable registry backups automatically. ## Usage -## Batch script +### Batch script 1. Make sure to have the latest [AMD drivers](https://www.amd.com/en/support) installed 2. Download and execute `amdocl.bat` 3. Run the file as **Administrator** (Right click file and select `Run as Administrator`) -## PowerShell script +### PowerShell script 1. Download `amdocl-fix.ps1` and place it in a folder of your choice. 2. Make sure to run it as **Administrator**: - Right‑click the file → **Run with PowerShell** → confirm the UAC prompt. @@ -29,7 +29,11 @@ The PowerShell version additionally verifies DLL signatures, detects 32/64-bit b cd "C:\path\to\folder" .\amdocl-fix.ps1 ``` - +3. (Optional) By default, unsigned DLLs are allowed to preserve valid but unusual ICDs. To restrict registration to signed DLLs only, run: + ```powershell + .\amdocl-fix.ps1 -AllowUnsigned:$false + ``` + ## Compatibility - Windows 10, 11: fully supported - Windows 7, 8, 8.1: batch script fully supported; PowerShell script (`amdocl-fix.ps1`) requires PowerShell 5.1 or newer @@ -41,4 +45,4 @@ Inspired by StackOverflow https://stackoverflow.com/a/28407851 --- © 2023 [Patrick Trumpis](https://github.com/ptrumpis) -© 2025 [TantalusDrive](https://github.com/TantalusDrive) (Additional improvements and PowerShell version) +© 2025 [TantalusDrive](https://github.com/TantalusDrive) (Improvements and PowerShell version) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index 3a7bb22..fdef43c 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -1,46 +1,151 @@ -# PowerShell script to manage and fix AMD OpenCL ICDs -# -# Original batch concept: Patrick Trumpis (https://github.com/ptrumpis/OpenCL-AMD-GPU) -# PowerShell implementation and extensions: TantalusDrive (https://github.com/TantalusDrive) -# -# Licensed under the MIT License. -# See LICENSE file in the repository root for full terms. -# # This PowerShell script extends the original batch by safely cleaning up # invalid or misplaced registry entries and coherently registering AMD # OpenCL DLLs in the correct 32-bit or 64-bit hive, and providing detailed status output. # By default, unsigned DLLs are allowed to prevent accidental removal. # -# Tested on a couple of dated AMD GPUs (R5 M330, R5 M430), feedback and contributions are welcome. +# Risky registry operations are gated on evidence of registry backups (RegBack). +# +# Tested on older AMD GPUs (R5 M330, R5 M430). Feedback and contributions are welcome. +# +# Licensed under the MIT License. +# See LICENSE file in the repository root for full terms. param( - [switch]$AllowUnsigned = $true + [switch]$AllowUnsigned ) -$roots = @( - "HKLM:\SOFTWARE\Khronos\OpenCL\Vendors", - "HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors" -) +# preserve original default behaviour: unsigned allowed unless user explicitly passes -AllowUnsigned:$false +if (-not $PSBoundParameters.ContainsKey('AllowUnsigned')) { + $AllowUnsigned = $true +} else { + $AllowUnsigned = [bool]$AllowUnsigned +} + +Write-Host "OpenCL Driver (ICD) Fix for AMD GPUs" +Write-Host "Original work by Patrick Trumpis (https://github.com/ptrumpis/OpenCL-AMD-GPU)" +Write-Host "Improvements by TantalusDrive (https://github.com/TantalusDrive)" +Write-Host "Inspired by https://stackoverflow.com/a/28407851" +Write-Host "" +Write-Host "" + +# ------------------------- +# Configuration +# ------------------------- +$Roots = @{ + 64 = "HKLM:\SOFTWARE\Khronos\OpenCL\Vendors" + 32 = "HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors" +} -$scanDirs = @( +$ScanDirs = @( "$env:WINDIR\System32", "$env:WINDIR\SysWOW64", "$env:WINDIR\System32\DriverStore\FileRepository" ) +# ------------------------- +# Counters and dedup +# ------------------------- +[int]$countRemovedMissing = 0 +[int]$countRemovedSignature = 0 +[int]$countMoved = 0 +[int]$countRegistered = 0 +[int]$countAlready = 0 +[int]$countDuplicates = 0 +$Global:RegisteredSeen = [System.Collections.Generic.HashSet[string]]::new() $hadErrors = $false +# ------------------------- +# Helpers +# ------------------------- +function Test-IsAdmin { + $id = [Security.Principal.WindowsIdentity]::GetCurrent() + $p = New-Object Security.Principal.WindowsPrincipal($id) + return $p.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) +} + +function Test-RegistryBackupEnabled { + $windir = $env:WINDIR + if (-not $windir) { return $false } + + $regBackPath = Join-Path $windir "System32\config\RegBack" + if (Test-Path $regBackPath) { + $expected = @('SAM','SECURITY','SOFTWARE','SYSTEM','DEFAULT') + try { + foreach ($name in $expected) { + $f = Join-Path $regBackPath $name + if (-not (Test-Path $f)) { return $false } + if ((Get-Item $f -ErrorAction SilentlyContinue).Length -le 0) { return $false } + } + return $true + } catch { return $false } + } + + try { + # best-effort scheduled task check + $task = Get-ScheduledTask -TaskName 'RegIdleBackup' -ErrorAction SilentlyContinue + if ($task) { return $true } + $task2 = Get-ScheduledTask -TaskPath "\Microsoft\Windows\Registry\" -ErrorAction SilentlyContinue | + Where-Object { $_.TaskName -eq 'RegIdleBackup' } + if ($task2) { return $true } + } catch { } + + return $false +} + +function Try-EnableRegistryBackup { + if (-not (Test-IsAdmin)) { + Write-Host "Administrator privileges required to enable registry backup automatically. Re-run as Administrator to allow automatic enabling." -ForegroundColor Yellow + return $false + } + + try { + $cfgKey = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" + if (-not (Test-Path $cfgKey)) { + New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name "Configuration Manager" -Force -ErrorAction SilentlyContinue | Out-Null + } + New-ItemProperty -Path $cfgKey -Name "EnablePeriodicBackup" -PropertyType DWord -Value 1 -Force -ErrorAction SilentlyContinue | Out-Null + Write-Host "Set EnablePeriodicBackup = 1 (attempted)." -ForegroundColor Cyan + } catch { + Write-Host "Failed to set EnablePeriodicBackup: $($_.Exception.Message)" -ForegroundColor Yellow + } + + Start-Sleep -Seconds 1 + + try { + $task = Get-ScheduledTask -TaskName 'RegIdleBackup' -ErrorAction SilentlyContinue + if (-not $task) { + $task = Get-ScheduledTask -TaskPath "\Microsoft\Windows\Registry\" -ErrorAction SilentlyContinue | Where-Object { $_.TaskName -eq 'RegIdleBackup' } + } + if ($task) { + try { + Enable-ScheduledTask -InputObject $task -ErrorAction SilentlyContinue + Start-ScheduledTask -InputObject $task -ErrorAction SilentlyContinue + Write-Host "Triggered scheduled task 'RegIdleBackup' (if allowed)." -ForegroundColor Cyan + } catch { + Write-Host "Could not start/enable scheduled task 'RegIdleBackup' automatically: $($_.Exception.Message)" -ForegroundColor Yellow + } + } else { + Write-Host "Scheduled task 'RegIdleBackup' not found on this system." -ForegroundColor Yellow + } + } catch { + Write-Host "Scheduled task check failed: $($_.Exception.Message)" -ForegroundColor Yellow + } + + Start-Sleep -Seconds 4 + return (Test-RegistryBackupEnabled) +} + function Get-DllBitness { param([string]$Path) try { - $fs = [System.IO.File]::Open($Path, 'Open', 'Read', 'Read') - $br = New-Object System.IO.BinaryReader($fs) - $fs.Seek(0x3C, 'Begin') | Out-Null - $peOffset = $br.ReadInt32() - $fs.Seek($peOffset + 4, 'Begin') | Out-Null - $machine = $br.ReadUInt16() + $fs = [IO.File]::Open($Path,'Open','Read','Read') + $br = New-Object IO.BinaryReader($fs) + $fs.Seek(0x3C,'Begin') | Out-Null + $pe = $br.ReadInt32() + $fs.Seek($pe + 4,'Begin') | Out-Null + $m = $br.ReadUInt16() $br.Close(); $fs.Close() - switch ($machine) { + switch ($m) { 0x8664 { return 64 } 0x014C { return 32 } default { return $null } @@ -48,121 +153,209 @@ function Get-DllBitness { } catch { return $null } } -function Safe-Remove { - param($root,$name) - try { Remove-ItemProperty -Path $root -Name $name -Force } - catch { $global:hadErrors = $true } +function Is-AcceptableSignature { + param($sig) + if (-not $sig) { return $false } + if ($sig.Status -eq 'Valid') { return $true } + if ($AllowUnsigned -and ($sig.Status -eq 'NotSigned' -or $sig.Status -eq 'Unknown')) { return $true } + return $false } -function Safe-Add { - param($root,$name) - try { New-ItemProperty -Path $root -Name $name -Value 0 -PropertyType DWord -Force | Out-Null } - catch { $global:hadErrors = $true } -} +function Ensure-Registry { + param($bit, $dllPath) -function Is-SignatureAcceptable { - param($sig, $AllowUnsigned) - if ($sig.Status -eq 'Valid') { return $true } - if ($AllowUnsigned -and ($sig.Status -eq 'NotSigned' -or $sig.Status -eq 'Unknown')) { - return $true + $root = $Roots[$bit] + if ([string]::IsNullOrWhiteSpace($root)) { return } + + if (-not (Test-Path $root)) { + try { + New-Item -Path $root -Force | Out-Null + Write-Host "Added Key: $root" + } catch { + Write-Host "Failed to create registry key: $root - $($_.Exception.Message)" -ForegroundColor Yellow + $script:hadErrors = $true + return + } } - return $false -} -function Register-OpenCLDLL { - param([string]$dllPath, [switch]$AllowUnsigned) - if (-not (Test-Path $dllPath)) { return } - $sig = Get-AuthenticodeSignature -FilePath $dllPath - if (-not (Is-SignatureAcceptable $sig $AllowUnsigned)) { return } - $bit = Get-DllBitness $dllPath - if ($bit -eq 64) { $root = $roots[0] } - elseif ($bit -eq 32) { $root = $roots[1] } - else { return } - $exists = (Get-ItemProperty -Path $root -ErrorAction SilentlyContinue).PSObject.Properties | - Where-Object { $_.Name -eq $dllPath } - if (-not $exists) { - Safe-Add $root $dllPath - Write-Host "[+ $bit bit] Added: $dllPath" -ForegroundColor Cyan + if ($Global:RegisteredSeen.Contains($dllPath)) { + $script:countDuplicates++ + Write-Host "Already present: $dllPath (duplicate skipped)" + return } + + $props = (Get-ItemProperty -Path $root -ErrorAction SilentlyContinue).PSObject.Properties + $exists = $props | Where-Object { $_.Name -eq $dllPath } | Select-Object -First 1 + + if ($exists) { + $script:countAlready++ + Write-Host "Already present: $dllPath" + } else { + try { + New-ItemProperty -Path $root -Name $dllPath -Value 0 -PropertyType DWord -Force -ErrorAction Stop | Out-Null + $script:countRegistered++ + Write-Host "Registered: $dllPath" + } catch { + # <<-- corrected parsing error by delimiting variables with ${} + Write-Host "Failed to register ${dllPath} under ${root}: $($_.Exception.Message)" -ForegroundColor Yellow + $script:hadErrors = $true + } + } + + $Global:RegisteredSeen.Add($dllPath) | Out-Null } -# Registry cleanup: remove invalid, missing, or misplaced entries -foreach ($root in $roots) { - Write-Host "`nAnalyzing: $root" -ForegroundColor Cyan - $entries = Get-ItemProperty -Path $root -ErrorAction SilentlyContinue - if (-not $entries) { - Write-Host "No entries found or key missing." - continue +# ------------------------- +# Admin + RegBack gate (announce -> ask -> proceed) +# ------------------------- +if (-not (Test-IsAdmin)) { + Write-Host "Execution stopped" -ForegroundColor Red + Write-Host "=================" -ForegroundColor Red + Write-Host "This script requires administrator rights." + Write-Host "Please run it again as administrator (right click the file and select 'Run as administrator')." + Read-Host "Press Enter to exit" + exit 1 +} + +Write-Host "Administrator privileges confirmed." -ForegroundColor Cyan +Write-Host "" + +$RegistryBackupEnabled = Test-RegistryBackupEnabled +if ($RegistryBackupEnabled) { + Write-Host "Registry backup active. Full registry operations are allowed." -ForegroundColor Green +} else { + Write-Host "WARNING: Automatic registry backup is not enabled." -ForegroundColor Yellow + $ans = Read-Host "Attempt to enable automatic registry backup now? This will try to set EnablePeriodicBackup and trigger RegIdleBackup. (Y/N)" + if ($ans -match '^[Yy]$') { + if (Try-EnableRegistryBackup) { + $RegistryBackupEnabled = $true + Write-Host "Registry backup active. Full registry operations are allowed." -ForegroundColor Green + } else { + Write-Host "Automatic enabling failed or RegBack files not created. Destructive registry operations will be SKIPPED." -ForegroundColor Yellow + } + } else { + Write-Host "Proceeding without enabling registry backups; destructive registry operations will be SKIPPED." -ForegroundColor Yellow } - foreach ($prop in $entries.PSObject.Properties) { - $dll = $prop.Name +} + +# ------------------------- +# Registry reconciliation (non-destructive unless $RegistryBackupEnabled) +# ------------------------- +Write-Host "" +Write-Host "Scanning registry for invalid or misplaced entries..." -ForegroundColor Cyan + +foreach ($bit in 64,32) { + $root = $Roots[$bit] + if ([string]::IsNullOrWhiteSpace($root)) { continue } + if (-not (Test-Path $root)) { continue } + + $props = (Get-ItemProperty -Path $root -ErrorAction SilentlyContinue).PSObject.Properties + foreach ($p in $props) { + $dll = $p.Name if ($dll -notlike "*amdocl*.dll") { continue } - if (-not (Test-Path $dll)) { - Write-Host "Removed: $dll (file not found)" -ForegroundColor Yellow - Safe-Remove $root $dll - continue - } - $sig = Get-AuthenticodeSignature -FilePath $dll - if (-not (Is-SignatureAcceptable $sig $AllowUnsigned)) { - Write-Host "Removed: $dll (invalid signature)" -ForegroundColor Yellow - Safe-Remove $root $dll + + if (-not $RegistryBackupEnabled) { + Write-Host "SAFE mode: skipped $dll" -ForegroundColor Yellow continue } - $bit = Get-DllBitness $dll - if ($bit -eq $null) { - Write-Host "Removed: $dll (architecture not detected)" -ForegroundColor Yellow - Safe-Remove $root $dll + + if (-not (Test-Path $dll)) { + Write-Host "Removed (missing): $dll" -ForegroundColor Yellow + Remove-ItemProperty -Path $root -Name $dll -Force -ErrorAction SilentlyContinue + $countRemovedMissing++ continue } - $correctRoot = if ($bit -eq 64) { $roots[0] } else { $roots[1] } - if ($correctRoot -ne $root) { - Write-Host "Moved ($bit bit): $dll" -ForegroundColor Yellow - Safe-Remove $root $dll - $existsDest = (Get-ItemProperty -Path $correctRoot -ErrorAction SilentlyContinue).PSObject.Properties | - Where-Object { $_.Name -eq $dll } - if (-not $existsDest) { - Safe-Add $correctRoot $dll - } + + $sig = Get-AuthenticodeSignature -FilePath $dll -ErrorAction SilentlyContinue + if (-not (Is-AcceptableSignature $sig)) { + Write-Host "Removed (invalid signature): $dll" -ForegroundColor Yellow + Remove-ItemProperty -Path $root -Name $dll -Force -ErrorAction SilentlyContinue + $countRemovedSignature++ continue } - Write-Host "OK: $dll" -ForegroundColor Green - } -} - -# Register all valid DLLs found in each directory (no duplicates) -Write-Host "`nRegistering all valid AMD OpenCL DLLs from standard directories..." -ForegroundColor Cyan -foreach ($dir in $scanDirs) { - if (-not (Test-Path $dir)) { continue } - Get-ChildItem -Path $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | - Where-Object { $_.VersionInfo.FileVersionRaw } | - ForEach-Object { - Register-OpenCLDLL -dllPath $_.FullName -AllowUnsigned:$AllowUnsigned + $realBit = Get-DllBitness $dll + if ($realBit -and $realBit -ne $bit) { + Write-Host "Moved ($($realBit) bit): $dll" -ForegroundColor Yellow + Remove-ItemProperty -Path $root -Name $dll -Force -ErrorAction SilentlyContinue + $countMoved++ + Ensure-Registry $realBit $dll } + } } -if ($hadErrors) { - Write-Host "`nCompleted with warnings." -ForegroundColor Yellow +# ------------------------- +# Register DLLs from standard locations +# ------------------------- +Write-Host "" +Write-Host "This script will now attempt to find and install unregistered OpenCL AMD drivers (Fast Scan)." +$input = Read-Host "Do you want to continue? (Y/N)" +if ($input -ne 'Y' -and $input -ne 'y') { + Write-Host "`nFast Scan skipped." } else { - Write-Host "`nCompleted." -ForegroundColor Green + Write-Host "`nRunning AMD OpenCL Driver Auto Detection" + Write-Host "========================================" + foreach ($dir in $ScanDirs) { + if (-not (Test-Path $dir)) { continue } + Write-Host "Scanning '$dir' for 'amdocl*.dll' files..." + Get-ChildItem -Path $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | + ForEach-Object { + $sig = Get-AuthenticodeSignature -FilePath $_.FullName -ErrorAction SilentlyContinue + if (Is-AcceptableSignature $sig) { + $bit = Get-DllBitness $_.FullName + if ($bit) { Ensure-Registry $bit $_.FullName } + } + } + } + Write-Host "`nFast Scan complete." -ForegroundColor Cyan } -# Optional PATH scan -Write-Host "`nDo you want to include an extended scan of system PATH directories? (Recommended only for custom or unofficial DLLs)" -ForegroundColor Yellow -$input = Read-Host "Type Y to scan, anything else to skip" -if ($input -eq 'Y' -or $input -eq 'y') { - Write-Host "`nNote: DLLs found in PATH may be unofficial or obsolete." -ForegroundColor Magenta +# ------------------------- +# Optional PATH scan (announce -> ask -> proceed) +# ------------------------- +Write-Host "" +Write-Host "This script will now attempt a Full Scan (PATH)." +Write-Host "(Recommended only for custom or unofficial DLLs)" -ForegroundColor Yellow +$input = Read-Host "Do you want to continue? (Y/N)" +if ($input -ne 'Y' -and $input -ne 'y') { + Write-Host "`nFull Scan skipped." +} else { + Write-Host "`nNow scanning your PATH for 'amdocl*.dll' files, please wait..." + Write-Host "Note: DLLs found in PATH may be unofficial or obsolete." -ForegroundColor Yellow + Write-Host "===================================================" $pathDirs = ($env:PATH -split ';' | Where-Object { Test-Path $_ }) - foreach ($dir in $pathDirs) { - Get-ChildItem -Path $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | - Where-Object { $_.VersionInfo.FileVersionRaw } | + foreach ($p in $pathDirs) { + Write-Host "Scanning: $p" + Get-ChildItem -Path $p -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | ForEach-Object { - Register-OpenCLDLL -dllPath $_.FullName -AllowUnsigned:$AllowUnsigned + $sig = Get-AuthenticodeSignature -FilePath $_.FullName -ErrorAction SilentlyContinue + if (Is-AcceptableSignature $sig) { + $bit = Get-DllBitness $_.FullName + if ($bit) { Ensure-Registry $bit $_.FullName } + } } } - Write-Host "`nPATH scan completed." -ForegroundColor Cyan + Write-Host "`nFull Scan complete." -ForegroundColor Cyan +} + +# ------------------------- +# Summary +# ------------------------- +Write-Host "" +Write-Host "========== SUMMARY ==========" +Write-Host "Removed (missing) : $countRemovedMissing" +Write-Host "Removed (signature) : $countRemovedSignature" +Write-Host "Moved entries : $countMoved" +Write-Host "Registered new : $countRegistered" +Write-Host "Already registered : $countAlready" +Write-Host "Duplicates skipped : $countDuplicates" +Write-Host "=============================" +Write-Host "" + +if ($hadErrors) { + Write-Host "Completed with warnings." -ForegroundColor Yellow } else { - Write-Host "`nPATH scan skipped." + Write-Host "Completed." -ForegroundColor Green } Read-Host "Press Enter to exit" diff --git a/amdocl.bat b/amdocl.bat index 749c183..47aefc1 100644 --- a/amdocl.bat +++ b/amdocl.bat @@ -1,179 +1,240 @@ @echo off cls +setlocal EnableExtensions EnableDelayedExpansion + echo OpenCL Driver (ICD) Fix for AMD GPUs echo Original work by Patrick Trumpis (https://github.com/ptrumpis/OpenCL-AMD-GPU) echo Improvements by TantalusDrive (https://github.com/TantalusDrive) -REM SysWOW64 handling, PATH scan, versioned DLLs, duplicate prevention echo Inspired by https://stackoverflow.com/a/28407851 -echo: -echo: - -REM ============================================================ -REM Privilege check -REM ============================================================ -net session >nul 2>&1 -if %errorlevel% neq 0 ( - echo Execution stopped - echo ================= - echo This script requires administrator rights. - echo Please run it again as administrator. - echo You can right click the file and select 'Run as administrator' - echo: - pause - exit /b 1 +echo. +echo. + +REM ============================================================ +REM Privilege check (robust, UAC-safe) +REM ============================================================ +fsutil dirty query %systemdrive% >nul 2>&1 +if errorlevel 1 goto :noAdmin +goto :continue + +:noAdmin +echo. +echo Execution stopped +echo ================= +echo This script requires administrator rights. +echo Please run it again as administrator. +echo You can right click the file and select 'Run as administrator' +echo. +pause +exit /b 1 + +:continue +echo Administrator privileges confirmed. +echo. + +REM ============================================================ +REM Detect Windows major version (robust, locale-safe) +REM ============================================================ +set "WINVER=10" +for /f "tokens=1 delims=." %%v in ('wmic os get version ^| find "."') do ( + set "WINVER=%%v" + goto :ver_ok ) +:ver_ok -SETLOCAL EnableDelayedExpansion +echo Detected Windows major version: %WINVER% +echo. -SET ROOTKEY64=HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenCL\Vendors -SET ROOTKEY32=HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors +REM ============================================================ +REM Registry backup detection (Vista+ only) +REM ============================================================ +set "REGBKOK=0" + +if %WINVER% lss 6 ( + echo WARNING: Automatic registry backup not supported before Windows Vista. + echo SAFE mode will be enforced. +) else ( + echo Checking automatic registry backup configuration... + reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" >nul 2>&1 + if not errorlevel 1 ( + reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" ^ + /v EnablePeriodicBackup >nul 2>&1 + if not errorlevel 1 ( + reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" ^ + /v EnablePeriodicBackup | findstr /I "0x0" >nul + if errorlevel 1 ( + set "REGBKOK=1" + ) + ) + ) + if "!REGBKOK!"=="0" ( + echo. + echo WARNING: Automatic registry backup is not enabled. + echo Destructive registry fixes will be disabled. + echo. + set "INPUT=" + set /P "INPUT=Do you want to enable it now? (Y/N): " + if /I "!INPUT!"=="Y" ( + echo. + echo Enabling automatic registry backup... + reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" ^ + /v EnablePeriodicBackup /t REG_DWORD /d 1 /f >nul 2>&1 + if not errorlevel 1 ( + echo Backup registry mechanism enabled successfully. + set "REGBKOK=1" + ) else ( + echo Failed to enable backup. + echo Proceeding in SAFE mode only. + ) + ) else ( + echo. + echo Backup not enabled by user. + echo Proceeding in SAFE mode only. + ) + ) + + echo. + if "!REGBKOK!"=="1" ( + echo Registry backup active. + echo Full registry operations are allowed. + ) else ( + echo Registry backup inactive. + echo SAFE mode active: registry writes will be skipped. + ) +) + +echo. + +REM ============================================================ +REM Main script variables +REM ============================================================ +set ROOTKEY64=HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenCL\Vendors +set ROOTKEY32=HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors + +REM ============================================================ +REM Show current drivers +REM ============================================================ echo Currently installed OpenCL Client Drivers - 64bit echo ================================================== -reg query %ROOTKEY64% >nul 2>&1 && ( - for /f "tokens=1,*" %%A in ('reg query %ROOTKEY64%') do echo %%A - %%B +reg query "%ROOTKEY64%" >nul 2>&1 && ( + for /f "tokens=1,*" %%A in ('reg query "%ROOTKEY64%"') do echo %%A - %%B ) || echo (none) -echo: +echo. echo Currently installed OpenCL Client Drivers - 32bit echo ================================================== -reg query %ROOTKEY32% >nul 2>&1 && ( - for /f "tokens=1,*" %%A in ('reg query %ROOTKEY32%') do echo %%A - %%B +reg query "%ROOTKEY32%" >nul 2>&1 && ( + for /f "tokens=1,*" %%A in ('reg query "%ROOTKEY32%"') do echo %%A - %%B ) || echo (none) -echo: +echo. -echo This script will now attempt to find and install unregistered OpenCL AMD drivers (Fast Scan). +REM ============================================================ +REM User confirmation +REM ============================================================ +echo This script will now attempt to find and register unregistered AMD OpenCL drivers. +echo. set "INPUT=" set /P "INPUT=Do you want to continue? (Y/N): " -if /I "!INPUT!"=="Y" ( - echo: - goto :scanFilesFast -) else ( - goto :exit -) +if /I "!INPUT!" neq "Y" goto :exit +echo. +echo. -:scanFilesFast +REM ============================================================ +REM Fast Scan - standard locations +REM ============================================================ echo Running AMD OpenCL Driver Auto Detection echo ======================================== -echo: - -echo Scanning '%SYSTEMROOT%\System32' for 'amdocl*.dll' files... -cd /d %SYSTEMROOT%\System32 -call :registerMissingClientDriver - -echo: -echo Scanning '%SYSTEMROOT%\SysWOW64' for 'amdocl*.dll' files... -cd /d %SYSTEMROOT%\SysWOW64 -call :registerMissingClientDriver +echo. + +for %%D in ("%SystemRoot%\System32" "%SystemRoot%\SysWOW64") do ( + if exist "%%~D" ( + echo Scanning '%%~D' for 'amdocl*.dll' files, please wait... + echo. + pushd "%%~D" + call :registerMissingClientDriver + popd + echo. + ) +) -echo: echo Fast Scan complete. -echo: +echo. +echo. -echo This script will now attempt a Full Scan (PATH). +REM ============================================================ +REM PATH scan +REM ============================================================ +echo This script can now scan your PATH for additional AMD OpenCL drivers. +echo. set "INPUT=" -set /P "INPUT=Do you want to continue? (Y/N): " -if /I "!INPUT!"=="Y" ( - goto :scanFilesFull -) else ( - goto :complete -) - -:scanFilesFull -echo Now scanning your PATH for 'amdocl*.dll' files... -echo: - -for %%A in ("%path:;=";"%") do ( - if "%%~A" neq "" ( - if exist "%%~A\" ( - pushd "%%~A" >nul 2>&1 - if !ERRORLEVEL! == 0 ( - call :registerMissingClientDriver - popd - ) +set /P "INPUT=Do you want to perform a Full PATH scan? (Y/N): " +if /I "!INPUT!" neq "Y" goto :complete +echo. +echo Now scanning PATH for 'amdocl*.dll' files, please wait... +echo. + +for %%P in ("%PATH:;=" "%") do ( + if exist "%%~P" ( + pushd "%%~P" >nul 2>&1 + if not errorlevel 1 ( + call :registerMissingClientDriver + popd ) ) ) -echo: +echo. echo Full Scan complete. -echo: +echo. :complete echo Done. +echo. pause goto :exit -:exit -exit /b 0 - REM ============================================================ -REM Register missing client drivers +REM Register missing client drivers (non-destructive) REM ============================================================ :registerMissingClientDriver -for /r %%f in (amdocl*.dll) do ( - set FILE=%%~dpnxf - set NAME=%%~nxf - - REM Accept fixed names and versioned variants (only real AMD files) +for /r %%F in (amdocl*.dll) do ( + set "FILE=%%~fF" + set "NAME=%%~nxF" set "VALID=" - if /I "!NAME!"=="amdocl.dll" ( - set "VALID=1" - ) else if /I "!NAME!"=="amdocl64.dll" ( - set "VALID=1" - ) else if /I "!NAME!"=="amdocl12cl.dll" ( - set "VALID=1" - ) else if /I "!NAME!"=="amdocl12cl64.dll" ( - set "VALID=1" - ) else ( - REM Versioned variants used by AMD releases - echo !NAME! | findstr /C:"amdocl64_" >nul && set "VALID=1" - echo !NAME! | findstr /C:"amdocl_" >nul && set "VALID=1" - ) + + REM Accept AMD ICDs and versioned variants + echo !NAME! | findstr /I "^amdocl" >nul && set "VALID=1" if defined VALID ( echo Found: !FILE! - REM Bitness detection (prefer explicit 64, otherwise default to 32) - if /I "!NAME!"=="amdocl64.dll" ( - set "ROOTKEY=!ROOTKEY64!" - ) else if /I "!NAME!"=="amdocl12cl64.dll" ( - set "ROOTKEY=!ROOTKEY64!" - ) else ( - echo !NAME! | findstr /C:"amdocl64_" >nul - if !ERRORLEVEL! == 0 ( - set "ROOTKEY=!ROOTKEY64!" - ) else ( - REM Default to 32-bit if not matched above - set "ROOTKEY=!ROOTKEY32!" - ) - ) + REM Bitness heuristic (best possible in batch) + set "ROOTKEY=!ROOTKEY32!" + echo !NAME! | findstr /I "64" >nul && set "ROOTKEY=!ROOTKEY64!" REM Ensure root key exists - reg query !ROOTKEY! >nul 2>&1 - if !ERRORLEVEL! neq 0 ( - reg add !ROOTKEY! /f >nul 2>&1 - if !ERRORLEVEL! == 0 ( - echo Added Key: !ROOTKEY! - ) else ( - echo ERROR: Failed to add key !ROOTKEY! - ) + reg query "!ROOTKEY!" >nul 2>&1 + if errorlevel 1 ( + reg add "!ROOTKEY!" /f >nul 2>&1 + echo Added Key: !ROOTKEY! ) - REM Register DLL if missing - reg query !ROOTKEY! /v "!FILE!" >nul 2>&1 - if !ERRORLEVEL! neq 0 ( - reg add !ROOTKEY! /v "!FILE!" /t REG_DWORD /d 0 /f >nul 2>&1 - if !ERRORLEVEL! == 0 ( + REM Register only if SAFE allows + if "!REGBKOK!"=="1" ( + reg query "!ROOTKEY!" /v "!FILE!" >nul 2>&1 + if errorlevel 1 ( + reg add "!ROOTKEY!" /v "!FILE!" /t REG_DWORD /d 0 /f >nul 2>&1 echo Registered: !FILE! ) else ( - echo ERROR: Failed to register !FILE! + echo Already present: !FILE! ) ) else ( - echo Already present: !FILE! + echo SAFE mode active: registry write skipped for !FILE! ) + echo. ) - REM Reset VALID for next iteration - set "VALID=" ) goto :eof + +:exit +exit /b 0