From 02075d5d3a7b451b800613e520f0d30f91b544fb Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Wed, 4 Feb 2026 02:39:50 +0100 Subject: [PATCH 01/14] Update amdocl.bat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SAFE mode: Registry modifications are performed only if automatic registry backup (EnablePeriodicBackup) is active. If it’s not enabled, the script offers the user the option to turn it on before proceeding, reducing the risk of irreversible changes. - Improved diagnostics / extended echo: Echo messages provide clearer feedback for added keys, already registered DLLs, and operations skipped in SAFE mode. Enhances transparency of actions without repeating information. --- amdocl.bat | 137 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 43 deletions(-) diff --git a/amdocl.bat b/amdocl.bat index 749c183..2a6333f 100644 --- a/amdocl.bat +++ b/amdocl.bat @@ -23,18 +23,70 @@ if %errorlevel% neq 0 ( exit /b 1 ) -SETLOCAL EnableDelayedExpansion +REM ============================================================ +REM Check Windows version (Vista+ required for registry backup) +REM ============================================================ +for /f "tokens=4 delims=. " %%v in ('ver') do set WINVER=%%v +if %WINVER% lss 6 ( + echo WARNING: Automatic registry backup not supported before Windows Vista. + set "REGBKOK=0" +) else ( + REM ======================================================== + REM Check automatic registry backup (EnablePeriodicBackup DWORD) + REM ======================================================== + set "REGBKOK=0" + + reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" >nul 2>&1 + if errorlevel 1 ( + echo WARNING: Configuration Manager key missing. SAFE mode enforced. + set "REGBKOK=0" + ) else ( + reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" /v EnablePeriodicBackup >nul 2>&1 + if %errorlevel% equ 0 ( + REM check if value is 0x0 (disabled) otherwise consider enabled + reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" /v EnablePeriodicBackup | findstr /I "0x0" >nul 2>&1 + if %errorlevel%==0 ( + set "REGBKOK=0" + ) else ( + set "REGBKOK=1" + ) + ) + ) + + if %REGBKOK%==0 ( + echo WARNING: Automatic registry backup is not enabled. + set "INPUT=" + set /P "INPUT=Do you want to enable it now? (Y/N): " + if /I "%INPUT%"=="Y" ( + reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" /v EnablePeriodicBackup /t REG_DWORD /d 1 /f >nul 2>&1 + if %errorlevel%==0 ( + echo Backup registry mechanism enabled. + set "REGBKOK=1" + ) else ( + echo Failed to enable backup, proceeding with SAFE operations only. + ) + ) else ( + echo Backup not enabled. Only safe operations will run. + ) + ) + + if %REGBKOK%==1 (echo Registry backup active.) else (echo Registry backup inactive, SAFE mode.) +) +REM ============================================================ +REM Main script variables +REM ============================================================ +SETLOCAL EnableDelayedExpansion SET ROOTKEY64=HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenCL\Vendors SET ROOTKEY32=HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors +REM Display current drivers 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 ) || echo (none) echo: - echo Currently installed OpenCL Client Drivers - 32bit echo ================================================== reg query %ROOTKEY32% >nul 2>&1 && ( @@ -42,48 +94,43 @@ reg query %ROOTKEY32% >nul 2>&1 && ( ) || echo (none) echo: -echo This script will now attempt to find and install unregistered OpenCL AMD drivers (Fast Scan). +REM This script will now attempt to find and install unregistered OpenCL AMD drivers (Fast Scan). set "INPUT=" set /P "INPUT=Do you want to continue? (Y/N): " if /I "!INPUT!"=="Y" ( echo: - goto :scanFilesFast ) else ( goto :exit ) -:scanFilesFast +REM ============================================================ +REM Fast Scan - standard directories (recursive registration) +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 +for %%D in ("%SYSTEMROOT%\System32" "%SYSTEMROOT%\SysWOW64") do ( + if exist "%%~D" ( + echo Scanning '%%~D' for 'amdocl*.dll' files, please wait... + pushd "%%~D" + call :registerMissingClientDriver + popd + echo: + ) +) -echo: echo Fast Scan complete. echo: - -echo This script will now attempt a Full Scan (PATH). set "INPUT=" -set /P "INPUT=Do you want to continue? (Y/N): " -if /I "!INPUT!"=="Y" ( - goto :scanFilesFull -) else ( - goto :complete -) +set /P "INPUT=Do you want to perform a Full PATH scan? (Y/N): " +if /I not "%INPUT%"=="Y" goto :complete -:scanFilesFull -echo Now scanning your PATH for 'amdocl*.dll' files... +echo: +echo Now scanning PATH for 'amdocl*.dll' files... echo: -for %%A in ("%path:;=";"%") do ( +for %%A in ("%PATH:;=";"%") do ( if "%%~A" neq "" ( if exist "%%~A\" ( pushd "%%~A" >nul 2>&1 @@ -104,19 +151,18 @@ echo Done. pause goto :exit -:exit -exit /b 0 - REM ============================================================ -REM Register missing client drivers +REM Register missing client drivers (non-destructive) +REM - recursive search, whitelist + versioned variants, diagnostics +REM - skips destructive operations if registry backup not active REM ============================================================ :registerMissingClientDriver for /r %%f in (amdocl*.dll) do ( - set FILE=%%~dpnxf - set NAME=%%~nxf + set "FILE=%%~dpnxf" + set "NAME=%%~nxf" + set "VALID=" REM Accept fixed names and versioned variants (only real AMD files) - set "VALID=" if /I "!NAME!"=="amdocl.dll" ( set "VALID=1" ) else if /I "!NAME!"=="amdocl64.dll" ( @@ -126,7 +172,6 @@ for /r %%f in (amdocl*.dll) do ( ) 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" ) @@ -144,12 +189,11 @@ for /r %%f in (amdocl*.dll) do ( if !ERRORLEVEL! == 0 ( set "ROOTKEY=!ROOTKEY64!" ) else ( - REM Default to 32-bit if not matched above set "ROOTKEY=!ROOTKEY32!" ) ) - REM Ensure root key exists + REM Ensure root key exists (with diagnostic) reg query !ROOTKEY! >nul 2>&1 if !ERRORLEVEL! neq 0 ( reg add !ROOTKEY! /f >nul 2>&1 @@ -160,20 +204,27 @@ for /r %%f in (amdocl*.dll) do ( ) ) - 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 ( - echo Registered: !FILE! + REM Register DLL if missing (respect SAFE gating) + if "!REGBKOK!"=="1" ( + 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 ( + echo Registered: !FILE! + ) else ( + echo ERROR: Failed to register !FILE! + ) ) else ( - echo ERROR: Failed to register !FILE! + echo Already present: !FILE! ) ) else ( - echo Already present: !FILE! + echo SAFE mode: registry modification skipped for !FILE! (backup not active) ) ) REM Reset VALID for next iteration set "VALID=" ) goto :eof + +:exit +exit /b 0 From 6089964a2b55ab14503cced531f8bc6306a756d2 Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Wed, 4 Feb 2026 03:14:03 +0100 Subject: [PATCH 02/14] Update amdocl-fix.ps1 SAFE mode / registry gating: - Destructive registry operations only executed if evidence of automatic registry backups is present (RegBack files or scheduled task). - Offers user the option to enable RegBack automatically (EnablePeriodicBackup DWORD + RegIdleBackup task). Diagnostics / transparency: - Messages for skipped destructive actions, invalid signatures, removed or moved entries, and successful registrations. - Provides clearer feedback on registry reconciliation and DLL registration. DLL handling improvements: - Accepts any amdocl*.dll variant, including custom-built ICDs. - Bitness detection simplified and stabilized; ensures 32/64-bit registry placement is consistent. Additional safety: - Authenticode signature verification added (optional $AllowUnsigned for legacy GPUs). - Non-destructive unless SAFE mode permits. --- amdocl-fix.ps1 | 329 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 222 insertions(+), 107 deletions(-) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index 3a7bb22..ae497ef 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -3,24 +3,28 @@ # 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. +# 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. +# Unsigned DLLs are allowed to prevent accidental removal, the user can override it with -AllowUnsigned:$false . # 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). + param( [switch]$AllowUnsigned = $true ) -$roots = @( - "HKLM:\SOFTWARE\Khronos\OpenCL\Vendors", - "HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors" -) +# ------------------------- +# Configuration +# ------------------------- +$roots = @{ + 64 = "HKLM:\SOFTWARE\Khronos\OpenCL\Vendors" + 32 = "HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors" +} $scanDirs = @( "$env:WINDIR\System32", @@ -28,141 +32,252 @@ $scanDirs = @( "$env:WINDIR\System32\DriverStore\FileRepository" ) -$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 Get-DllBitness { - param([string]$Path) +function Test-RegistryBackupEnabled { + <# + Heuristic: check RegBack files and scheduled task RegIdleBackup. + Returns $true if RegBack appears available (files present & non-zero) or + if the RegIdleBackup scheduled task exists; otherwise $false. + #> + $windir = $env:WINDIR + if (-not $windir) { return $false } + + $regBackPath = Join-Path -Path $windir -ChildPath "System32\config\RegBack" + if (Test-Path $regBackPath) { + $expected = @('SAM','SECURITY','SOFTWARE','SYSTEM','DEFAULT') + try { + $allPresent = $true + foreach ($name in $expected) { + $f = Join-Path $regBackPath $name + if (-not (Test-Path $f)) { $allPresent = $false; break } + $size = (Get-Item $f -ErrorAction SilentlyContinue).Length + if (-not $size -or $size -eq 0) { $allPresent = $false; break } + } + if ($allPresent) { return $true } + } catch { } + } + + # Check scheduled task RegIdleBackup (best-effort) 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() - $br.Close(); $fs.Close() - switch ($machine) { - 0x8664 { return 64 } - 0x014C { return 32 } - default { return $null } - } - } catch { return $null } + $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 Safe-Remove { - param($root,$name) - try { Remove-ItemProperty -Path $root -Name $name -Force } - catch { $global:hadErrors = $true } +function Try-EnableRegistryBackup { + <# + Try to enable RegBack behaviour using two common methods: + 1) create/ensure EnablePeriodicBackup DWORD = 1 under: + HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager + 2) enable & start scheduled task RegIdleBackup (if present) + Returns $true if afterwards RegBack files are present (heuristic); otherwise $false. + #> + + if (-not (Test-IsAdmin)) { + Write-Host "Admin privileges required to enable registry backup automatically. Re-run as Administrator to allow automatic enabling." -ForegroundColor Yellow + return $false + } + + $success = $false + + # 1) Try to set EnablePeriodicBackup DWORD + try { + $cfgKey = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" + if (-not (Test-Path $cfgKey)) { + # create parent key if missing + New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name "Configuration Manager" -Force -ErrorAction SilentlyContinue | Out-Null + } + # set EnablePeriodicBackup = 1 + New-ItemProperty -Path $cfgKey -Name "EnablePeriodicBackup" -PropertyType DWord -Value 1 -Force -ErrorAction SilentlyContinue | Out-Null + Write-Host "Set EnablePeriodicBackup = 1 in $cfgKey (attempted)." -ForegroundColor Cyan + } catch { + Write-Host "Failed to set EnablePeriodicBackup: $_" -ForegroundColor Yellow + } + + Start-Sleep -Seconds 1 + + # 2) Try to enable & run scheduled task RegIdleBackup + 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: $_" -ForegroundColor Yellow + } + } else { + Write-Host "Scheduled task 'RegIdleBackup' not found on this system." -ForegroundColor Yellow + } + } catch { + Write-Host "Scheduled task check failed: $_" -ForegroundColor Yellow + } + + # wait a few seconds to let the task (if started) write RegBack files + Start-Sleep -Seconds 4 + + # re-check RegBack folder + $windir = $env:WINDIR + $regBackPath = Join-Path -Path $windir -ChildPath "System32\config\RegBack" + if (Test-Path $regBackPath) { + $expected = @('SAM','SECURITY','SOFTWARE','SYSTEM','DEFAULT') + try { + $allPresent = $true + foreach ($name in $expected) { + $f = Join-Path $regBackPath $name + if (-not (Test-Path $f)) { $allPresent = $false; break } + $size = (Get-Item $f -ErrorAction SilentlyContinue).Length + if (-not $size -or $size -eq 0) { $allPresent = $false; break } + } + if ($allPresent) { Write-Host "Registry backup (RegBack) files detected." -ForegroundColor Green; $success = $true } + } catch { } + } + + return $success } -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 Get-DllBitness { + param([string]$Path) + try { + $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 ($m) { 0x8664 {64} 0x014C {32} default {$null} } + } catch { $null } } -function Is-SignatureAcceptable { - param($sig, $AllowUnsigned) +function Is-AcceptableSignature { + param($sig) + if ($sig -eq $null) { return $false } if ($sig.Status -eq 'Valid') { return $true } - if ($AllowUnsigned -and ($sig.Status -eq 'NotSigned' -or $sig.Status -eq 'Unknown')) { - return $true - } + if ($AllowUnsigned -and $sig.Status -in 'NotSigned','Unknown') { return $true } 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 +function Ensure-Registry { + param($bit,$dll) + $root = $roots[$bit.ToString()] + if (-not (Test-Path $root)) { New-Item -Path $root -Force | Out-Null } + if (-not (Get-ItemProperty -Path $root -Name $dll -ErrorAction SilentlyContinue)) { + New-ItemProperty -Path $root -Name $dll -Value 0 -PropertyType DWord -Force | Out-Null + Write-Host "[+ $bit bit] Registered: $dll" -ForegroundColor Cyan } } -# 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 +# ------------------------- +# Main flow: check registry backup availability +# ------------------------- +$RegistryBackupEnabled = Test-RegistryBackupEnabled +if (-not $RegistryBackupEnabled) { + Write-Host "Registry automatic backup (RegBack) not detected." -ForegroundColor Yellow + $ans = Read-Host "Attempt to enable automatic registry backup now? This will try to set EnablePeriodicBackup and run RegIdleBackup. (Y/N)" + if ($ans -match '^[Yy]$') { + $ok = Try-EnableRegistryBackup + if ($ok) { + $RegistryBackupEnabled = $true + } 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 +} else { + Write-Host "Registry automatic backup (RegBack) appears available — destructive registry fixes allowed." -ForegroundColor Green +} + +# ------------------------- +# Registry reconciliation (non-destructive unless $RegistryBackupEnabled) +# ------------------------- +Write-Host "`nScanning registry for invalid or misplaced entries..." -ForegroundColor Cyan + +foreach ($bit in 64,32) { + $root = $roots[$bit.ToString()] + 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 + + # If registry backups not detected/confirmed, skip destructive checks + if (-not $RegistryBackupEnabled) { + Write-Host "SKIP (no registry backup): $dll" -ForegroundColor Yellow 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 (Test-Path $dll)) { + Write-Host "Removed (missing): $dll" -ForegroundColor Yellow + Remove-ItemProperty -Path $root -Name $dll -Force -ErrorAction SilentlyContinue continue } - $bit = Get-DllBitness $dll - if ($bit -eq $null) { - Write-Host "Removed: $dll (architecture not detected)" -ForegroundColor Yellow - Safe-Remove $root $dll + + $sig = Get-AuthenticodeSignature $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 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 - } - continue + + $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 + Ensure-Registry $realBit $dll } - 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 +# ------------------------- +# Register DLLs from standard locations +# ------------------------- +Write-Host "`nRegistering AMD OpenCL DLLs from standard locations..." -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 + $sig = Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue + if (-not (Is-AcceptableSignature $sig)) { continue } + $bit = Get-DllBitness $_.FullName + if ($bit) { Ensure-Registry $bit $_.FullName } } } -if ($hadErrors) { - Write-Host "`nCompleted with warnings." -ForegroundColor Yellow -} else { - Write-Host "`nCompleted." -ForegroundColor Green -} - +# ------------------------- # 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 - $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 } | +# ------------------------- +Write-Host "`nDo you want to scan PATH directories as well? (Y/N)" -ForegroundColor Yellow +if ((Read-Host) -match '^[Yy]$') { + foreach ($p in ($env:PATH -split ';' | Where-Object { Test-Path $_ })) { + Get-ChildItem -Path $p -Filter "amdocl*.dll" -ErrorAction SilentlyContinue | ForEach-Object { - Register-OpenCLDLL -dllPath $_.FullName -AllowUnsigned:$AllowUnsigned + $sig = Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue + if (-not (Is-AcceptableSignature $sig)) { continue } + $bit = Get-DllBitness $_.FullName + if ($bit) { Ensure-Registry $bit $_.FullName } } } - Write-Host "`nPATH scan completed." -ForegroundColor Cyan -} else { - Write-Host "`nPATH scan skipped." } +Write-Host "`nCompleted." -ForegroundColor Green Read-Host "Press Enter to exit" From a377be42d8c4aec1335c4b8cec057b96548ffd7a Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Wed, 4 Feb 2026 04:20:48 +0100 Subject: [PATCH 03/14] Update README.md - Reworded main paragraph highlighting detection, SysWOW64 handling, PATH scan, status output, versioned/custom ICD support, and registry writes gated on automatic backups. - Updated PowerShell section to emphasize added features only: signature verification, precise 32/64-bit detection, safe cleanup/relocation of invalid entries, DriverStore handling, more detailed output, and optional automatic registry backup enabling. - Clarified -AllowUnsigned option behavior for PowerShell script. - Minor wording improvements for clarity and flow. --- README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) 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) From a1e49bfda9ca684a69615937a2618a0d64c8cfb7 Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Wed, 4 Feb 2026 05:05:40 +0100 Subject: [PATCH 04/14] Update amdocl-fix.ps1 --- amdocl-fix.ps1 | 168 +++++++++++++++++++++---------------------------- 1 file changed, 73 insertions(+), 95 deletions(-) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index ae497ef..ae3eed6 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -6,13 +6,16 @@ # 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. -# Unsigned DLLs are allowed to prevent accidental removal, the user can override it with -AllowUnsigned:$false . -# Tested on a couple of dated AMD GPUs (R5 M330, R5 M430), feedback and contributions are welcome. +# 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, +# while providing detailed and transparent status output. +# +# Unsigned DLLs are allowed by default to avoid removing valid but unusual ICDs. +# The user can override this behavior with -AllowUnsigned:$false. # # 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. param( [switch]$AllowUnsigned = $true @@ -26,6 +29,16 @@ $roots = @{ 32 = "HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors" } +# Normalize registry roots defensively (avoid null/empty paths) +$NormalizedRoots = @{} +foreach ($k in $roots.Keys) { + $v = $roots[$k] + if (-not [string]::IsNullOrWhiteSpace($v)) { + $NormalizedRoots[$k] = $v + } +} +$roots = $NormalizedRoots + $scanDirs = @( "$env:WINDIR\System32", "$env:WINDIR\SysWOW64", @@ -37,120 +50,70 @@ $scanDirs = @( # ------------------------- function Test-IsAdmin { $id = [Security.Principal.WindowsIdentity]::GetCurrent() - $p = New-Object Security.Principal.WindowsPrincipal($id) + $p = New-Object Security.Principal.WindowsPrincipal($id) return $p.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } function Test-RegistryBackupEnabled { - <# - Heuristic: check RegBack files and scheduled task RegIdleBackup. - Returns $true if RegBack appears available (files present & non-zero) or - if the RegIdleBackup scheduled task exists; otherwise $false. - #> $windir = $env:WINDIR if (-not $windir) { return $false } - $regBackPath = Join-Path -Path $windir -ChildPath "System32\config\RegBack" + $regBackPath = Join-Path $windir "System32\config\RegBack" if (Test-Path $regBackPath) { $expected = @('SAM','SECURITY','SOFTWARE','SYSTEM','DEFAULT') try { - $allPresent = $true foreach ($name in $expected) { $f = Join-Path $regBackPath $name - if (-not (Test-Path $f)) { $allPresent = $false; break } - $size = (Get-Item $f -ErrorAction SilentlyContinue).Length - if (-not $size -or $size -eq 0) { $allPresent = $false; break } + if (-not (Test-Path $f)) { return $false } + if ((Get-Item $f -ErrorAction SilentlyContinue).Length -le 0) { return $false } } - if ($allPresent) { return $true } + return $true } catch { } } - # Check scheduled task RegIdleBackup (best-effort) try { - $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 } + if (Get-ScheduledTask -TaskName 'RegIdleBackup' -ErrorAction SilentlyContinue) { return $true } + if (Get-ScheduledTask -TaskPath "\Microsoft\Windows\Registry\" -ErrorAction SilentlyContinue | + Where-Object { $_.TaskName -eq 'RegIdleBackup' }) { return $true } } catch { } return $false } function Try-EnableRegistryBackup { - <# - Try to enable RegBack behaviour using two common methods: - 1) create/ensure EnablePeriodicBackup DWORD = 1 under: - HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager - 2) enable & start scheduled task RegIdleBackup (if present) - Returns $true if afterwards RegBack files are present (heuristic); otherwise $false. - #> - if (-not (Test-IsAdmin)) { - Write-Host "Admin privileges required to enable registry backup automatically. Re-run as Administrator to allow automatic enabling." -ForegroundColor Yellow + Write-Host "Administrator privileges required to enable registry backups automatically." -ForegroundColor Yellow return $false } - $success = $false - - # 1) Try to set EnablePeriodicBackup DWORD try { $cfgKey = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" if (-not (Test-Path $cfgKey)) { - # create parent key if missing - New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name "Configuration Manager" -Force -ErrorAction SilentlyContinue | Out-Null + New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" ` + -Name "Configuration Manager" -Force | Out-Null } - # set EnablePeriodicBackup = 1 - New-ItemProperty -Path $cfgKey -Name "EnablePeriodicBackup" -PropertyType DWord -Value 1 -Force -ErrorAction SilentlyContinue | Out-Null - Write-Host "Set EnablePeriodicBackup = 1 in $cfgKey (attempted)." -ForegroundColor Cyan + New-ItemProperty -Path $cfgKey -Name "EnablePeriodicBackup" ` + -PropertyType DWord -Value 1 -Force | Out-Null + Write-Host "Set EnablePeriodicBackup = 1 (attempted)." -ForegroundColor Cyan } catch { - Write-Host "Failed to set EnablePeriodicBackup: $_" -ForegroundColor Yellow + Write-Host "Failed to set EnablePeriodicBackup." -ForegroundColor Yellow } - Start-Sleep -Seconds 1 - - # 2) Try to enable & run scheduled task RegIdleBackup 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' } + $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: $_" -ForegroundColor Yellow - } - } else { - Write-Host "Scheduled task 'RegIdleBackup' not found on this system." -ForegroundColor Yellow + Enable-ScheduledTask -InputObject $task -ErrorAction SilentlyContinue + Start-ScheduledTask -InputObject $task -ErrorAction SilentlyContinue + Write-Host "Triggered RegIdleBackup scheduled task." -ForegroundColor Cyan } - } catch { - Write-Host "Scheduled task check failed: $_" -ForegroundColor Yellow - } + } catch { } - # wait a few seconds to let the task (if started) write RegBack files Start-Sleep -Seconds 4 - - # re-check RegBack folder - $windir = $env:WINDIR - $regBackPath = Join-Path -Path $windir -ChildPath "System32\config\RegBack" - if (Test-Path $regBackPath) { - $expected = @('SAM','SECURITY','SOFTWARE','SYSTEM','DEFAULT') - try { - $allPresent = $true - foreach ($name in $expected) { - $f = Join-Path $regBackPath $name - if (-not (Test-Path $f)) { $allPresent = $false; break } - $size = (Get-Item $f -ErrorAction SilentlyContinue).Length - if (-not $size -or $size -eq 0) { $allPresent = $false; break } - } - if ($allPresent) { Write-Host "Registry backup (RegBack) files detected." -ForegroundColor Green; $success = $true } - } catch { } - } - - return $success + return (Test-RegistryBackupEnabled) } function Get-DllBitness { @@ -163,13 +126,17 @@ function Get-DllBitness { $fs.Seek($pe + 4,'Begin') | Out-Null $m = $br.ReadUInt16() $br.Close(); $fs.Close() - switch ($m) { 0x8664 {64} 0x014C {32} default {$null} } + switch ($m) { + 0x8664 { 64 } + 0x014C { 32 } + default { $null } + } } catch { $null } } function Is-AcceptableSignature { param($sig) - if ($sig -eq $null) { return $false } + if (-not $sig) { return $false } if ($sig.Status -eq 'Valid') { return $true } if ($AllowUnsigned -and $sig.Status -in 'NotSigned','Unknown') { return $true } return $false @@ -177,8 +144,19 @@ function Is-AcceptableSignature { function Ensure-Registry { param($bit,$dll) + $root = $roots[$bit.ToString()] - if (-not (Test-Path $root)) { New-Item -Path $root -Force | Out-Null } + if ([string]::IsNullOrWhiteSpace($root)) { return } + + if (-not (Test-Path $root)) { + try { + New-Item -Path $root -Force | Out-Null + } catch { + Write-Host "Failed to create registry root: $root" -ForegroundColor Yellow + return + } + } + if (-not (Get-ItemProperty -Path $root -Name $dll -ErrorAction SilentlyContinue)) { New-ItemProperty -Path $root -Name $dll -Value 0 -PropertyType DWord -Force | Out-Null Write-Host "[+ $bit bit] Registered: $dll" -ForegroundColor Cyan @@ -186,42 +164,42 @@ function Ensure-Registry { } # ------------------------- -# Main flow: check registry backup availability +# Main: registry backup gate # ------------------------- $RegistryBackupEnabled = Test-RegistryBackupEnabled if (-not $RegistryBackupEnabled) { - Write-Host "Registry automatic backup (RegBack) not detected." -ForegroundColor Yellow - $ans = Read-Host "Attempt to enable automatic registry backup now? This will try to set EnablePeriodicBackup and run RegIdleBackup. (Y/N)" + Write-Host "Registry automatic backup not detected." -ForegroundColor Yellow + $ans = Read-Host "Attempt to enable automatic registry backup now? (Y/N)" if ($ans -match '^[Yy]$') { - $ok = Try-EnableRegistryBackup - if ($ok) { + if (Try-EnableRegistryBackup) { $RegistryBackupEnabled = $true } else { - Write-Host "Automatic enabling failed or RegBack files not created. Destructive registry operations will be SKIPPED." -ForegroundColor Yellow + Write-Host "Backup not confirmed; destructive operations will be skipped." -ForegroundColor Yellow } } else { - Write-Host "Proceeding without enabling registry backups; destructive registry operations will be SKIPPED." -ForegroundColor Yellow + Write-Host "Proceeding in SAFE mode (no destructive registry changes)." -ForegroundColor Yellow } } else { - Write-Host "Registry automatic backup (RegBack) appears available — destructive registry fixes allowed." -ForegroundColor Green + Write-Host "Registry automatic backup detected — destructive fixes allowed." -ForegroundColor Green } # ------------------------- -# Registry reconciliation (non-destructive unless $RegistryBackupEnabled) +# Registry reconciliation # ------------------------- Write-Host "`nScanning registry for invalid or misplaced entries..." -ForegroundColor Cyan foreach ($bit in 64,32) { $root = $roots[$bit.ToString()] + 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 registry backups not detected/confirmed, skip destructive checks if (-not $RegistryBackupEnabled) { - Write-Host "SKIP (no registry backup): $dll" -ForegroundColor Yellow + Write-Host "SAFE mode: skipped $dll" -ForegroundColor Yellow continue } @@ -233,7 +211,7 @@ foreach ($bit in 64,32) { $sig = Get-AuthenticodeSignature $dll -ErrorAction SilentlyContinue if (-not (Is-AcceptableSignature $sig)) { - Write-Host "Removed (invalid signature): $dll" -ForegroundColor Yellow + Write-Host "Removed (signature): $dll" -ForegroundColor Yellow Remove-ItemProperty -Path $root -Name $dll -Force -ErrorAction SilentlyContinue continue } @@ -248,7 +226,7 @@ foreach ($bit in 64,32) { } # ------------------------- -# Register DLLs from standard locations +# Standard locations scan # ------------------------- Write-Host "`nRegistering AMD OpenCL DLLs from standard locations..." -ForegroundColor Cyan @@ -257,7 +235,7 @@ foreach ($dir in $scanDirs) { Get-ChildItem -Path $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | ForEach-Object { $sig = Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue - if (-not (Is-AcceptableSignature $sig)) { continue } + if (-not (Is-AcceptableSignature $sig)) { return } $bit = Get-DllBitness $_.FullName if ($bit) { Ensure-Registry $bit $_.FullName } } @@ -272,7 +250,7 @@ if ((Read-Host) -match '^[Yy]$') { Get-ChildItem -Path $p -Filter "amdocl*.dll" -ErrorAction SilentlyContinue | ForEach-Object { $sig = Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue - if (-not (Is-AcceptableSignature $sig)) { continue } + if (-not (Is-AcceptableSignature $sig)) { return } $bit = Get-DllBitness $_.FullName if ($bit) { Ensure-Registry $bit $_.FullName } } From 4ec47af5cae03bf1fdf4899edde38026e9cc3743 Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Wed, 4 Feb 2026 05:17:21 +0100 Subject: [PATCH 05/14] Update amdocl.bat --- amdocl.bat | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/amdocl.bat b/amdocl.bat index 2a6333f..fc35d0b 100644 --- a/amdocl.bat +++ b/amdocl.bat @@ -11,14 +11,11 @@ echo: REM ============================================================ REM Privilege check REM ============================================================ -net session >nul 2>&1 -if %errorlevel% neq 0 ( +whoami /groups | find "S-1-5-32-544" >nul 2>&1 +if errorlevel 1 ( 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 ) From 9cd2ef7cca49e06ee22296b06d5703f644cb7b12 Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Wed, 4 Feb 2026 05:21:43 +0100 Subject: [PATCH 06/14] Update amdocl.bat --- amdocl.bat | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/amdocl.bat b/amdocl.bat index fc35d0b..74e7980 100644 --- a/amdocl.bat +++ b/amdocl.bat @@ -11,14 +11,24 @@ echo: REM ============================================================ REM Privilege check REM ============================================================ -whoami /groups | find "S-1-5-32-544" >nul 2>&1 -if errorlevel 1 ( - echo Execution stopped - echo ================= - echo This script requires administrator rights. - pause - exit /b 1 -) +net session >nul 2>&1 +if %errorlevel% neq 0 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 + REM ============================================================ REM Check Windows version (Vista+ required for registry backup) From c87a8147085f307c7759a96696b00a4258925302 Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Wed, 4 Feb 2026 05:27:00 +0100 Subject: [PATCH 07/14] Update amdocl.bat --- amdocl.bat | 87 ++++++++++++++++++++++++------------------------------ 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/amdocl.bat b/amdocl.bat index 74e7980..0d2203d 100644 --- a/amdocl.bat +++ b/amdocl.bat @@ -3,17 +3,16 @@ cls 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 SysWOW64 handling, PATH scan, versioned DLLs, duplicate prevention echo Inspired by https://stackoverflow.com/a/28407851 -echo: -echo: +echo. +echo. REM ============================================================ REM Privilege check REM ============================================================ net session >nul 2>&1 if %errorlevel% neq 0 goto :noAdmin - goto :continue :noAdmin @@ -29,20 +28,16 @@ exit /b 1 :continue - REM ============================================================ REM Check Windows version (Vista+ required for registry backup) REM ============================================================ for /f "tokens=4 delims=. " %%v in ('ver') do set WINVER=%%v +if not defined WINVER set WINVER=10 if %WINVER% lss 6 ( echo WARNING: Automatic registry backup not supported before Windows Vista. set "REGBKOK=0" ) else ( - REM ======================================================== - REM Check automatic registry backup (EnablePeriodicBackup DWORD) - REM ======================================================== set "REGBKOK=0" - reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" >nul 2>&1 if errorlevel 1 ( echo WARNING: Configuration Manager key missing. SAFE mode enforced. @@ -50,7 +45,6 @@ if %WINVER% lss 6 ( ) else ( reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" /v EnablePeriodicBackup >nul 2>&1 if %errorlevel% equ 0 ( - REM check if value is 0x0 (disabled) otherwise consider enabled reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" /v EnablePeriodicBackup | findstr /I "0x0" >nul 2>&1 if %errorlevel%==0 ( set "REGBKOK=0" @@ -77,7 +71,11 @@ if %WINVER% lss 6 ( ) ) - if %REGBKOK%==1 (echo Registry backup active.) else (echo Registry backup inactive, SAFE mode.) + if %REGBKOK%==1 ( + echo Registry backup active. + ) else ( + echo Registry backup inactive, SAFE mode. + ) ) REM ============================================================ @@ -93,65 +91,61 @@ echo ================================================== 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 ) || echo (none) -echo: +echo. -REM This script will now attempt to find and install unregistered OpenCL AMD drivers (Fast Scan). +REM Prompt to continue set "INPUT=" set /P "INPUT=Do you want to continue? (Y/N): " -if /I "!INPUT!"=="Y" ( - echo: -) else ( - goto :exit -) +if /I "%INPUT%" neq "Y" goto :exit +echo. REM ============================================================ REM Fast Scan - standard directories (recursive registration) REM ============================================================ echo Running AMD OpenCL Driver Auto Detection echo ======================================== -echo: - +echo. for %%D in ("%SYSTEMROOT%\System32" "%SYSTEMROOT%\SysWOW64") do ( if exist "%%~D" ( echo Scanning '%%~D' for 'amdocl*.dll' files, please wait... pushd "%%~D" call :registerMissingClientDriver popd - echo: + echo. ) ) - echo Fast Scan complete. -echo: +echo. + +REM Prompt for full PATH scan set "INPUT=" set /P "INPUT=Do you want to perform a Full PATH scan? (Y/N): " -if /I not "%INPUT%"=="Y" goto :complete +if /I "%INPUT%" neq "Y" goto :complete +echo. -echo: +REM ============================================================ +REM Full PATH scan +REM ============================================================ echo Now scanning 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 - ) +echo. +for %%A in (%PATH%) do ( + if exist "%%A" ( + pushd "%%A" >nul 2>&1 + if !ERRORLEVEL! == 0 ( + call :registerMissingClientDriver + popd ) ) ) - -echo: +echo. echo Full Scan complete. -echo: +echo. :complete echo Done. @@ -159,9 +153,7 @@ pause goto :exit REM ============================================================ -REM Register missing client drivers (non-destructive) -REM - recursive search, whitelist + versioned variants, diagnostics -REM - skips destructive operations if registry backup not active +REM Register missing client drivers REM ============================================================ :registerMissingClientDriver for /r %%f in (amdocl*.dll) do ( @@ -200,10 +192,10 @@ for /r %%f in (amdocl*.dll) do ( ) ) - REM Ensure root key exists (with diagnostic) - reg query !ROOTKEY! >nul 2>&1 + REM Ensure root key exists + reg query "!ROOTKEY!" >nul 2>&1 if !ERRORLEVEL! neq 0 ( - reg add !ROOTKEY! /f >nul 2>&1 + reg add "!ROOTKEY!" /f >nul 2>&1 if !ERRORLEVEL! == 0 ( echo Added Key: !ROOTKEY! ) else ( @@ -213,9 +205,9 @@ for /r %%f in (amdocl*.dll) do ( REM Register DLL if missing (respect SAFE gating) if "!REGBKOK!"=="1" ( - reg query !ROOTKEY! /v "!FILE!" >nul 2>&1 + 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 + reg add "!ROOTKEY!" /v "!FILE!" /t REG_DWORD /d 0 /f >nul 2>&1 if !ERRORLEVEL! == 0 ( echo Registered: !FILE! ) else ( @@ -228,7 +220,6 @@ for /r %%f in (amdocl*.dll) do ( echo SAFE mode: registry modification skipped for !FILE! (backup not active) ) ) - REM Reset VALID for next iteration set "VALID=" ) goto :eof From e4e54f122ae1b7e09e4e38904ac3856a80a6709f Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:18:59 +0100 Subject: [PATCH 08/14] Improve safety and robustness of batch OpenCL ICD registration - More robust detection of administrative privileges and Windows version. - Explicit handling of SysWOW64 in addition to System32. - Improved 32/64-bit ICD registration heuristics to reduce misclassification. - Support for versioned AMD OpenCL DLL variants already used by some drivers. - Prevention of duplicate registry entries. - Introduction of a SAFE mode that skips registry modifications when automatic registry backups are not available or enabled. - Restored and expanded user-facing output to clearly report detections, registrations, skipped operations, and SAFE mode status. --- amdocl.bat | 200 ++++++++++++++++++++++++++++------------------------- 1 file changed, 106 insertions(+), 94 deletions(-) diff --git a/amdocl.bat b/amdocl.bat index 0d2203d..02793b2 100644 --- a/amdocl.bat +++ b/amdocl.bat @@ -1,9 +1,10 @@ @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) -echo SysWOW64 handling, PATH scan, versioned DLLs, duplicate prevention echo Inspired by https://stackoverflow.com/a/28407851 echo. echo. @@ -12,7 +13,7 @@ REM ============================================================ REM Privilege check REM ============================================================ net session >nul 2>&1 -if %errorlevel% neq 0 goto :noAdmin +if errorlevel 1 goto :noAdmin goto :continue :noAdmin @@ -27,200 +28,211 @@ 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 + +echo Detected Windows major version: %WINVER% +echo. REM ============================================================ -REM Check Windows version (Vista+ required for registry backup) +REM Registry backup detection (Vista+ only) REM ============================================================ -for /f "tokens=4 delims=. " %%v in ('ver') do set WINVER=%%v -if not defined WINVER set WINVER=10 +set "REGBKOK=0" + if %WINVER% lss 6 ( echo WARNING: Automatic registry backup not supported before Windows Vista. - set "REGBKOK=0" + echo SAFE mode will be enforced. ) else ( - set "REGBKOK=0" + echo Checking automatic registry backup configuration... reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" >nul 2>&1 - if errorlevel 1 ( - echo WARNING: Configuration Manager key missing. SAFE mode enforced. - set "REGBKOK=0" - ) else ( - reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" /v EnablePeriodicBackup >nul 2>&1 - if %errorlevel% equ 0 ( - reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" /v EnablePeriodicBackup | findstr /I "0x0" >nul 2>&1 - if %errorlevel%==0 ( - set "REGBKOK=0" - ) else ( + 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 ( + 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" ( - reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" /v EnablePeriodicBackup /t REG_DWORD /d 1 /f >nul 2>&1 - if %errorlevel%==0 ( - echo Backup registry mechanism enabled. + 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, proceeding with SAFE operations only. + echo Failed to enable backup. + echo Proceeding in SAFE mode only. ) ) else ( - echo Backup not enabled. Only safe operations will run. + echo. + echo Backup not enabled by user. + echo Proceeding in SAFE mode only. ) ) - if %REGBKOK%==1 ( + echo. + if "!REGBKOK!"=="1" ( echo Registry backup active. + echo Full registry operations are allowed. ) else ( - echo Registry backup inactive, SAFE mode. + echo Registry backup inactive. + echo SAFE mode active: registry writes will be skipped. ) ) +echo. + REM ============================================================ REM Main script variables REM ============================================================ -SETLOCAL EnableDelayedExpansion -SET ROOTKEY64=HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenCL\Vendors -SET ROOTKEY32=HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors +set ROOTKEY64=HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenCL\Vendors +set ROOTKEY32=HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors -REM Display current drivers +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 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. -REM Prompt to continue +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%" neq "Y" goto :exit +if /I "!INPUT!" neq "Y" goto :exit +echo. echo. REM ============================================================ -REM Fast Scan - standard directories (recursive registration) +REM Fast Scan - standard locations REM ============================================================ echo Running AMD OpenCL Driver Auto Detection echo ======================================== echo. -for %%D in ("%SYSTEMROOT%\System32" "%SYSTEMROOT%\SysWOW64") do ( + +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 Fast Scan complete. echo. - -REM Prompt for full PATH scan -set "INPUT=" -set /P "INPUT=Do you want to perform a Full PATH scan? (Y/N): " -if /I "%INPUT%" neq "Y" goto :complete echo. REM ============================================================ -REM Full PATH scan +REM PATH scan REM ============================================================ -echo Now scanning PATH for 'amdocl*.dll' files... +echo This script can now scan your PATH for additional AMD OpenCL drivers. echo. -for %%A in (%PATH%) do ( - if exist "%%A" ( - pushd "%%A" >nul 2>&1 - if !ERRORLEVEL! == 0 ( +set "INPUT=" +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 Full Scan complete. echo. :complete echo Done. +echo. pause goto :exit 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" +for /r %%F in (amdocl*.dll) do ( + set "FILE=%%~fF" + set "NAME=%%~nxF" set "VALID=" - REM Accept fixed names and versioned variants (only real AMD files) - 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 ( - 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 ( - 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 ( + if errorlevel 1 ( reg add "!ROOTKEY!" /f >nul 2>&1 - if !ERRORLEVEL! == 0 ( - echo Added Key: !ROOTKEY! - ) else ( - echo ERROR: Failed to add key !ROOTKEY! - ) + echo Added Key: !ROOTKEY! ) - REM Register DLL if missing (respect SAFE gating) + REM Register only if SAFE allows if "!REGBKOK!"=="1" ( reg query "!ROOTKEY!" /v "!FILE!" >nul 2>&1 - if !ERRORLEVEL! neq 0 ( + if errorlevel 1 ( reg add "!ROOTKEY!" /v "!FILE!" /t REG_DWORD /d 0 /f >nul 2>&1 - if !ERRORLEVEL! == 0 ( - echo Registered: !FILE! - ) else ( - echo ERROR: Failed to register !FILE! - ) + echo Registered: !FILE! ) else ( echo Already present: !FILE! ) ) else ( - echo SAFE mode: registry modification skipped for !FILE! (backup not active) + echo SAFE mode active: registry write skipped for !FILE! ) + echo. ) - set "VALID=" ) goto :eof From 391c28d0abfab7ce5aae4c6e901b92510a0c3dc5 Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:25:16 +0100 Subject: [PATCH 09/14] Update amdocl.bat Using fsutil instead o net session for more reliable privilege check --- amdocl.bat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/amdocl.bat b/amdocl.bat index 02793b2..47aefc1 100644 --- a/amdocl.bat +++ b/amdocl.bat @@ -10,9 +10,9 @@ echo. echo. REM ============================================================ -REM Privilege check +REM Privilege check (robust, UAC-safe) REM ============================================================ -net session >nul 2>&1 +fsutil dirty query %systemdrive% >nul 2>&1 if errorlevel 1 goto :noAdmin goto :continue From 896bec2de20e0bdded0b755d83abf49b8abe95a9 Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:49:09 +0100 Subject: [PATCH 10/14] Update amdocl-fix.ps1 --- amdocl-fix.ps1 | 206 +++++++++++++++++++++++-------------------------- 1 file changed, 96 insertions(+), 110 deletions(-) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index ae3eed6..199b2f7 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -17,29 +17,24 @@ # # Tested on older AMD GPUs (R5 M330, R5 M430). Feedback and contributions are welcome. + param( [switch]$AllowUnsigned = $true ) +Write-Host "AMD OpenCL ICD Fix (PowerShell Edition)" +Write-Host "=====================================" +Write-Host "" + # ------------------------- # Configuration # ------------------------- -$roots = @{ +$Roots = @{ 64 = "HKLM:\SOFTWARE\Khronos\OpenCL\Vendors" 32 = "HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors" } -# Normalize registry roots defensively (avoid null/empty paths) -$NormalizedRoots = @{} -foreach ($k in $roots.Keys) { - $v = $roots[$k] - if (-not [string]::IsNullOrWhiteSpace($v)) { - $NormalizedRoots[$k] = $v - } -} -$roots = $NormalizedRoots - -$scanDirs = @( +$ScanDirs = @( "$env:WINDIR\System32", "$env:WINDIR\SysWOW64", "$env:WINDIR\System32\DriverStore\FileRepository" @@ -55,60 +50,41 @@ function Test-IsAdmin { } 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 { } + $regBack = Join-Path $env:WINDIR "System32\config\RegBack" + if (Test-Path $regBack) { + foreach ($hive in 'SAM','SECURITY','SOFTWARE','SYSTEM','DEFAULT') { + $f = Join-Path $regBack $hive + if (-not (Test-Path $f)) { return $false } + if ((Get-Item $f).Length -le 0) { return $false } + } + return $true } try { - if (Get-ScheduledTask -TaskName 'RegIdleBackup' -ErrorAction SilentlyContinue) { return $true } - if (Get-ScheduledTask -TaskPath "\Microsoft\Windows\Registry\" -ErrorAction SilentlyContinue | - Where-Object { $_.TaskName -eq 'RegIdleBackup' }) { return $true } - } catch { } - - return $false -} - -function Try-EnableRegistryBackup { - if (-not (Test-IsAdmin)) { - Write-Host "Administrator privileges required to enable registry backups automatically." -ForegroundColor Yellow + return [bool](Get-ScheduledTask -TaskName RegIdleBackup -ErrorAction SilentlyContinue) + } catch { return $false } +} +function Try-EnableRegistryBackup { + Write-Host "Attempting to enable automatic registry backup..." 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 | Out-Null + $cfg = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" + if (-not (Test-Path $cfg)) { + New-Item -Path (Split-Path $cfg) -Name "Configuration Manager" -Force | Out-Null } - New-ItemProperty -Path $cfgKey -Name "EnablePeriodicBackup" ` - -PropertyType DWord -Value 1 -Force | Out-Null - Write-Host "Set EnablePeriodicBackup = 1 (attempted)." -ForegroundColor Cyan + New-ItemProperty -Path $cfg -Name EnablePeriodicBackup -Value 1 -PropertyType DWord -Force | Out-Null } catch { - Write-Host "Failed to set EnablePeriodicBackup." -ForegroundColor Yellow + Write-Host "Failed to configure registry backup." -ForegroundColor Yellow + return $false } 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' } - } + $task = Get-ScheduledTask -TaskName RegIdleBackup -ErrorAction SilentlyContinue if ($task) { - Enable-ScheduledTask -InputObject $task -ErrorAction SilentlyContinue - Start-ScheduledTask -InputObject $task -ErrorAction SilentlyContinue - Write-Host "Triggered RegIdleBackup scheduled task." -ForegroundColor Cyan + Enable-ScheduledTask $task | Out-Null + Start-ScheduledTask $task | Out-Null } } catch { } @@ -118,123 +94,131 @@ function Try-EnableRegistryBackup { function Get-DllBitness { param([string]$Path) + + $fs = $null + $br = $null try { $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 ($m) { + switch ($br.ReadUInt16()) { 0x8664 { 64 } 0x014C { 32 } default { $null } } - } catch { $null } + } catch { + $null + } finally { + if ($br) { $br.Dispose() } + if ($fs) { $fs.Dispose() } + } } function Is-AcceptableSignature { - param($sig) - if (-not $sig) { return $false } - if ($sig.Status -eq 'Valid') { return $true } - if ($AllowUnsigned -and $sig.Status -in 'NotSigned','Unknown') { return $true } + param($Sig) + if (-not $Sig) { return $false } + if ($Sig.Status -eq 'Valid') { return $true } + if ($AllowUnsigned -and $Sig.Status -in 'NotSigned','Unknown') { return $true } return $false } function Ensure-Registry { - param($bit,$dll) + param($Bit,$DllPath) - $root = $roots[$bit.ToString()] - if ([string]::IsNullOrWhiteSpace($root)) { return } + $Root = $Roots[$Bit] + if (-not $Root) { return } - if (-not (Test-Path $root)) { - try { - New-Item -Path $root -Force | Out-Null - } catch { - Write-Host "Failed to create registry root: $root" -ForegroundColor Yellow - return - } + if (-not (Test-Path $Root)) { + New-Item -Path $Root -Force | Out-Null + Write-Host "Created registry key: $Root" } - if (-not (Get-ItemProperty -Path $root -Name $dll -ErrorAction SilentlyContinue)) { - New-ItemProperty -Path $root -Name $dll -Value 0 -PropertyType DWord -Force | Out-Null - Write-Host "[+ $bit bit] Registered: $dll" -ForegroundColor Cyan + if (-not (Get-ItemPropertyValue -Path $Root -Name $DllPath -ErrorAction SilentlyContinue)) { + New-ItemProperty -Path $Root -Name $DllPath -Value 0 -PropertyType DWord -Force | Out-Null + Write-Host "[+ $Bit-bit] Registered: $DllPath" -ForegroundColor Cyan + } else { + Write-Host "[= $Bit-bit] Already registered: $DllPath" } } # ------------------------- -# Main: registry backup gate +# Admin + backup gate # ------------------------- +if (-not (Test-IsAdmin)) { + Write-Host "ERROR: Administrator privileges required." -ForegroundColor Red + Read-Host "Press Enter to exit" + exit 1 +} + $RegistryBackupEnabled = Test-RegistryBackupEnabled -if (-not $RegistryBackupEnabled) { - Write-Host "Registry automatic backup not detected." -ForegroundColor Yellow - $ans = Read-Host "Attempt to enable automatic registry backup now? (Y/N)" - if ($ans -match '^[Yy]$') { - if (Try-EnableRegistryBackup) { - $RegistryBackupEnabled = $true - } else { - Write-Host "Backup not confirmed; destructive operations will be skipped." -ForegroundColor Yellow - } +if ($RegistryBackupEnabled) { + Write-Host "Registry backup detected. Full operations enabled." -ForegroundColor Green +} else { + Write-Host "WARNING: Registry backup not detected." -ForegroundColor Yellow + $ans = Read-Host "Enable automatic registry backup now? (Y/N)" + if ($ans -match '^[Yy]$' -and (Try-EnableRegistryBackup)) { + $RegistryBackupEnabled = $true + Write-Host "Registry backup confirmed." -ForegroundColor Green } else { - Write-Host "Proceeding in SAFE mode (no destructive registry changes)." -ForegroundColor Yellow + Write-Host "SAFE mode active: registry will not be modified." -ForegroundColor Yellow } -} else { - Write-Host "Registry automatic backup detected — destructive fixes allowed." -ForegroundColor Green } # ------------------------- # Registry reconciliation # ------------------------- -Write-Host "`nScanning registry for invalid or misplaced entries..." -ForegroundColor Cyan - +Write-Host "" +Write-Host "Scanning existing OpenCL ICD registry entries..." foreach ($bit in 64,32) { - $root = $roots[$bit.ToString()] - if ([string]::IsNullOrWhiteSpace($root)) { continue } + $root = $Roots[$bit] if (-not (Test-Path $root)) { continue } - $props = (Get-ItemProperty -Path $root -ErrorAction SilentlyContinue).PSObject.Properties + $props = (Get-ItemProperty $root).PSObject.Properties | + Where-Object { $_.MemberType -eq 'NoteProperty' } + foreach ($p in $props) { $dll = $p.Name if ($dll -notlike "*amdocl*.dll") { continue } if (-not $RegistryBackupEnabled) { - Write-Host "SAFE mode: skipped $dll" -ForegroundColor Yellow + Write-Host "SAFE: skipped $dll" continue } if (-not (Test-Path $dll)) { Write-Host "Removed (missing): $dll" -ForegroundColor Yellow - Remove-ItemProperty -Path $root -Name $dll -Force -ErrorAction SilentlyContinue + Remove-ItemProperty -Path $root -Name $dll -Force continue } - $sig = Get-AuthenticodeSignature $dll -ErrorAction SilentlyContinue + $sig = Get-AuthenticodeSignature $dll if (-not (Is-AcceptableSignature $sig)) { Write-Host "Removed (signature): $dll" -ForegroundColor Yellow - Remove-ItemProperty -Path $root -Name $dll -Force -ErrorAction SilentlyContinue + Remove-ItemProperty -Path $root -Name $dll -Force continue } $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 + Write-Host "Moved to $realBit-bit hive: $dll" -ForegroundColor Yellow + Remove-ItemProperty -Path $root -Name $dll -Force Ensure-Registry $realBit $dll } } } # ------------------------- -# Standard locations scan +# Standard scan # ------------------------- -Write-Host "`nRegistering AMD OpenCL DLLs from standard locations..." -ForegroundColor Cyan - -foreach ($dir in $scanDirs) { +Write-Host "" +Write-Host "Scanning standard locations for AMD OpenCL DLLs..." +foreach ($dir in $ScanDirs) { if (-not (Test-Path $dir)) { continue } - Get-ChildItem -Path $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | + Get-ChildItem $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | ForEach-Object { - $sig = Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue + $sig = Get-AuthenticodeSignature $_.FullName if (-not (Is-AcceptableSignature $sig)) { return } $bit = Get-DllBitness $_.FullName if ($bit) { Ensure-Registry $bit $_.FullName } @@ -242,14 +226,15 @@ foreach ($dir in $scanDirs) { } # ------------------------- -# Optional PATH scan +# PATH scan # ------------------------- -Write-Host "`nDo you want to scan PATH directories as well? (Y/N)" -ForegroundColor Yellow -if ((Read-Host) -match '^[Yy]$') { +Write-Host "" +$ans = Read-Host "Scan PATH directories as well? (Y/N)" +if ($ans -match '^[Yy]$') { foreach ($p in ($env:PATH -split ';' | Where-Object { Test-Path $_ })) { - Get-ChildItem -Path $p -Filter "amdocl*.dll" -ErrorAction SilentlyContinue | + Get-ChildItem $p -Filter "amdocl*.dll" -ErrorAction SilentlyContinue | ForEach-Object { - $sig = Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue + $sig = Get-AuthenticodeSignature $_.FullName if (-not (Is-AcceptableSignature $sig)) { return } $bit = Get-DllBitness $_.FullName if ($bit) { Ensure-Registry $bit $_.FullName } @@ -257,5 +242,6 @@ if ((Read-Host) -match '^[Yy]$') { } } -Write-Host "`nCompleted." -ForegroundColor Green +Write-Host "" +Write-Host "Completed." -ForegroundColor Green Read-Host "Press Enter to exit" From 79bb92f26120efd9ef346d6b531ee2066fc061c1 Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Fri, 6 Feb 2026 00:04:30 +0100 Subject: [PATCH 11/14] Update amdocl-fix.ps1 --- amdocl-fix.ps1 | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index 199b2f7..6c6578c 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -40,6 +40,11 @@ $ScanDirs = @( "$env:WINDIR\System32\DriverStore\FileRepository" ) +# ------------------------- +# Dedup table (prevents duplicate registrations in same run) +# ------------------------- +$Global:RegisteredSeen = [System.Collections.Generic.HashSet[string]]::new() + # ------------------------- # Helpers # ------------------------- @@ -135,12 +140,28 @@ function Ensure-Registry { Write-Host "Created registry key: $Root" } - if (-not (Get-ItemPropertyValue -Path $Root -Name $DllPath -ErrorAction SilentlyContinue)) { - New-ItemProperty -Path $Root -Name $DllPath -Value 0 -PropertyType DWord -Force | Out-Null - Write-Host "[+ $Bit-bit] Registered: $DllPath" -ForegroundColor Cyan - } else { + # dedup in-memory + if ($Global:RegisteredSeen.Contains($DllPath)) { + Write-Host "[=] Skipping duplicate (already processed): $DllPath" + return + } + + # safe property check + $props = (Get-ItemProperty -Path $Root -ErrorAction SilentlyContinue).PSObject.Properties + $exists = $props | Where-Object { $_.Name -eq $DllPath } | Select-Object -First 1 + + if ($exists) { Write-Host "[= $Bit-bit] Already registered: $DllPath" + } else { + try { + New-ItemProperty -Path $Root -Name $DllPath -Value 0 -PropertyType DWord -Force | Out-Null + Write-Host "[+ $Bit-bit] Registered: $DllPath" -ForegroundColor Cyan + } catch { + Write-Host "Failed to register $DllPath under $Root: $_" -ForegroundColor Yellow + } } + + $Global:RegisteredSeen.Add($DllPath) | Out-Null } # ------------------------- From 4510bac0958d35515bd29a0c613260ac427c2063 Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Fri, 6 Feb 2026 01:49:39 +0100 Subject: [PATCH 12/14] Update amdocl-fix.ps1 --- amdocl-fix.ps1 | 115 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 34 deletions(-) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index 6c6578c..44e04ec 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -1,5 +1,3 @@ -# 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) # @@ -17,15 +15,28 @@ # # Tested on older AMD GPUs (R5 M330, R5 M430). Feedback and contributions are welcome. - param( [switch]$AllowUnsigned = $true ) -Write-Host "AMD OpenCL ICD Fix (PowerShell Edition)" -Write-Host "=====================================" +Write-Host "OpenCL Driver (ICD) Fix for AMD GPUs" +Write-Host "Original batch by Patrick Trumpis (https://github.com/ptrumpis/OpenCL-AMD-GPU)" +Write-Host "PowerShell implementation by TantalusDrive (https://github.com/TantalusDrive)" +Write-Host "==================================================" Write-Host "" +# ------------------------- +# Runtime counters +# ------------------------- +$Stats = @{ + RemovedMissing = 0 + RemovedSignature = 0 + Moved = 0 + Registered = 0 + AlreadyRegistered = 0 + SkippedDuplicate = 0 +} + # ------------------------- # Configuration # ------------------------- @@ -40,9 +51,6 @@ $ScanDirs = @( "$env:WINDIR\System32\DriverStore\FileRepository" ) -# ------------------------- -# Dedup table (prevents duplicate registrations in same run) -# ------------------------- $Global:RegisteredSeen = [System.Collections.Generic.HashSet[string]]::new() # ------------------------- @@ -73,7 +81,7 @@ function Test-RegistryBackupEnabled { } function Try-EnableRegistryBackup { - Write-Host "Attempting to enable automatic registry backup..." + Write-Host "[INFO] Attempting to enable automatic registry backup..." try { $cfg = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" if (-not (Test-Path $cfg)) { @@ -81,7 +89,7 @@ function Try-EnableRegistryBackup { } New-ItemProperty -Path $cfg -Name EnablePeriodicBackup -Value 1 -PropertyType DWord -Force | Out-Null } catch { - Write-Host "Failed to configure registry backup." -ForegroundColor Yellow + Write-Host "[WARN] Failed to configure registry backup." return $false } @@ -113,9 +121,8 @@ function Get-DllBitness { 0x014C { 32 } default { $null } } - } catch { - $null - } finally { + } catch { $null } + finally { if ($br) { $br.Dispose() } if ($fs) { $fs.Dispose() } } @@ -137,27 +144,28 @@ function Ensure-Registry { if (-not (Test-Path $Root)) { New-Item -Path $Root -Force | Out-Null - Write-Host "Created registry key: $Root" + Write-Host "[INFO] Created registry key: $Root" } - # dedup in-memory if ($Global:RegisteredSeen.Contains($DllPath)) { - Write-Host "[=] Skipping duplicate (already processed): $DllPath" + Write-Host "[SKIP] Duplicate already processed: $DllPath" + $Stats.SkippedDuplicate++ return } - # safe property check $props = (Get-ItemProperty -Path $Root -ErrorAction SilentlyContinue).PSObject.Properties $exists = $props | Where-Object { $_.Name -eq $DllPath } | Select-Object -First 1 if ($exists) { - Write-Host "[= $Bit-bit] Already registered: $DllPath" + Write-Host "[OK] $Bit-bit already registered" + $Stats.AlreadyRegistered++ } else { try { New-ItemProperty -Path $Root -Name $DllPath -Value 0 -PropertyType DWord -Force | Out-Null - Write-Host "[+ $Bit-bit] Registered: $DllPath" -ForegroundColor Cyan + Write-Host "[ADD] $Bit-bit → $DllPath" + $Stats.Registered++ } catch { - Write-Host "Failed to register $DllPath under $Root: $_" -ForegroundColor Yellow + Write-Host "[WARN] Failed to register $DllPath under ${Root}: $_" } } @@ -168,22 +176,22 @@ function Ensure-Registry { # Admin + backup gate # ------------------------- if (-not (Test-IsAdmin)) { - Write-Host "ERROR: Administrator privileges required." -ForegroundColor Red - Read-Host "Press Enter to exit" + Write-Host "[FATAL] Administrator privileges required." exit 1 } $RegistryBackupEnabled = Test-RegistryBackupEnabled + if ($RegistryBackupEnabled) { - Write-Host "Registry backup detected. Full operations enabled." -ForegroundColor Green + Write-Host "Registry backup detected — full remediation allowed." } else { - Write-Host "WARNING: Registry backup not detected." -ForegroundColor Yellow + Write-Host "[WARN] Registry backup not detected." $ans = Read-Host "Enable automatic registry backup now? (Y/N)" if ($ans -match '^[Yy]$' -and (Try-EnableRegistryBackup)) { $RegistryBackupEnabled = $true - Write-Host "Registry backup confirmed." -ForegroundColor Green + Write-Host "[OK] Registry backup confirmed." } else { - Write-Host "SAFE mode active: registry will not be modified." -ForegroundColor Yellow + Write-Host "[SAFE MODE] Risky operations disabled." } } @@ -191,7 +199,8 @@ if ($RegistryBackupEnabled) { # Registry reconciliation # ------------------------- Write-Host "" -Write-Host "Scanning existing OpenCL ICD registry entries..." +Write-Host "[PHASE] Registry reconciliation" + foreach ($bit in 64,32) { $root = $Roots[$bit] if (-not (Test-Path $root)) { continue } @@ -200,32 +209,36 @@ foreach ($bit in 64,32) { Where-Object { $_.MemberType -eq 'NoteProperty' } foreach ($p in $props) { + $dll = $p.Name if ($dll -notlike "*amdocl*.dll") { continue } if (-not $RegistryBackupEnabled) { - Write-Host "SAFE: skipped $dll" + Write-Host "[SAFE] Skipped $dll" continue } if (-not (Test-Path $dll)) { - Write-Host "Removed (missing): $dll" -ForegroundColor Yellow + Write-Host "[REMOVE] Missing → $dll" Remove-ItemProperty -Path $root -Name $dll -Force + $Stats.RemovedMissing++ continue } $sig = Get-AuthenticodeSignature $dll if (-not (Is-AcceptableSignature $sig)) { - Write-Host "Removed (signature): $dll" -ForegroundColor Yellow + Write-Host "[REMOVE] Signature rejected → $dll" Remove-ItemProperty -Path $root -Name $dll -Force + $Stats.RemovedSignature++ continue } $realBit = Get-DllBitness $dll if ($realBit -and $realBit -ne $bit) { - Write-Host "Moved to $realBit-bit hive: $dll" -ForegroundColor Yellow + Write-Host "[MOVE] $dll → $realBit-bit hive" Remove-ItemProperty -Path $root -Name $dll -Force Ensure-Registry $realBit $dll + $Stats.Moved++ } } } @@ -234,13 +247,22 @@ foreach ($bit in 64,32) { # Standard scan # ------------------------- Write-Host "" -Write-Host "Scanning standard locations for AMD OpenCL DLLs..." +Write-Host "[PHASE] Fast scan" + foreach ($dir in $ScanDirs) { if (-not (Test-Path $dir)) { continue } + + Write-Host "[SCAN] $dir" + Get-ChildItem $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | ForEach-Object { + $sig = Get-AuthenticodeSignature $_.FullName - if (-not (Is-AcceptableSignature $sig)) { return } + if (-not (Is-AcceptableSignature $sig)) { + Write-Host "[SKIP] Signature rejected → $($_.FullName)" + return + } + $bit = Get-DllBitness $_.FullName if ($bit) { Ensure-Registry $bit $_.FullName } } @@ -251,18 +273,43 @@ foreach ($dir in $ScanDirs) { # ------------------------- Write-Host "" $ans = Read-Host "Scan PATH directories as well? (Y/N)" + if ($ans -match '^[Yy]$') { + + Write-Host "[PHASE] PATH scan, please wait ..." + foreach ($p in ($env:PATH -split ';' | Where-Object { Test-Path $_ })) { + + Write-Host "[SCAN] $p" + Get-ChildItem $p -Filter "amdocl*.dll" -ErrorAction SilentlyContinue | ForEach-Object { + $sig = Get-AuthenticodeSignature $_.FullName - if (-not (Is-AcceptableSignature $sig)) { return } + if (-not (Is-AcceptableSignature $sig)) { + Write-Host "[SKIP] Signature rejected → $($_.FullName)" + return + } + $bit = Get-DllBitness $_.FullName if ($bit) { Ensure-Registry $bit $_.FullName } } } } +# ------------------------- +# Final summary +# ------------------------- +Write-Host "" +Write-Host "========== SUMMARY ==========" +Write-Host "Removed missing : $($Stats.RemovedMissing)" +Write-Host "Removed signature : $($Stats.RemovedSignature)" +Write-Host "Moved entries : $($Stats.Moved)" +Write-Host "Registered new : $($Stats.Registered)" +Write-Host "Already registered : $($Stats.AlreadyRegistered)" +Write-Host "Duplicates skipped : $($Stats.SkippedDuplicate)" +Write-Host "=============================" + Write-Host "" Write-Host "Completed." -ForegroundColor Green Read-Host "Press Enter to exit" From 0ccd3114675c4086a8a8294a589799eb5dec91f7 Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Fri, 6 Feb 2026 01:50:24 +0100 Subject: [PATCH 13/14] Update amdocl-fix.ps1 --- amdocl-fix.ps1 | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index 44e04ec..61015a1 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -1,9 +1,3 @@ -# 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, # while providing detailed and transparent status output. @@ -14,6 +8,9 @@ # 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 From 6e329f514e430a9d861f66fd9eff0a79ee877b44 Mon Sep 17 00:00:00 2001 From: Carlo <236701476+TantalusDrive@users.noreply.github.com> Date: Fri, 6 Feb 2026 16:40:02 +0100 Subject: [PATCH 14/14] Update amdocl-fix.ps1 --- amdocl-fix.ps1 | 361 ++++++++++++++++++++++++++++--------------------- 1 file changed, 205 insertions(+), 156 deletions(-) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index 61015a1..fdef43c 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -1,38 +1,32 @@ -# 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, -# while providing detailed and transparent status output. -# -# Unsigned DLLs are allowed by default to avoid removing valid but unusual ICDs. -# The user can override this behavior with -AllowUnsigned:$false. +# 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. # # 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) +# Licensed under the MIT License. +# See LICENSE file in the repository root for full terms. param( - [switch]$AllowUnsigned = $true + [switch]$AllowUnsigned ) +# 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 batch by Patrick Trumpis (https://github.com/ptrumpis/OpenCL-AMD-GPU)" -Write-Host "PowerShell implementation by TantalusDrive (https://github.com/TantalusDrive)" -Write-Host "==================================================" +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 "" - -# ------------------------- -# Runtime counters -# ------------------------- -$Stats = @{ - RemovedMissing = 0 - RemovedSignature = 0 - Moved = 0 - Registered = 0 - AlreadyRegistered = 0 - SkippedDuplicate = 0 -} # ------------------------- # Configuration @@ -48,7 +42,17 @@ $ScanDirs = @( "$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 @@ -60,43 +64,72 @@ function Test-IsAdmin { } function Test-RegistryBackupEnabled { - $regBack = Join-Path $env:WINDIR "System32\config\RegBack" - if (Test-Path $regBack) { - foreach ($hive in 'SAM','SECURITY','SOFTWARE','SYSTEM','DEFAULT') { - $f = Join-Path $regBack $hive - if (-not (Test-Path $f)) { return $false } - if ((Get-Item $f).Length -le 0) { return $false } - } - return $true + $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 { - return [bool](Get-ScheduledTask -TaskName RegIdleBackup -ErrorAction SilentlyContinue) - } catch { - return $false - } + # 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 { - Write-Host "[INFO] Attempting to enable automatic registry backup..." + 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 { - $cfg = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager" - if (-not (Test-Path $cfg)) { - New-Item -Path (Split-Path $cfg) -Name "Configuration Manager" -Force | Out-Null + $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 $cfg -Name EnablePeriodicBackup -Value 1 -PropertyType DWord -Force | 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 "[WARN] Failed to configure registry backup." - return $false + Write-Host "Failed to set EnablePeriodicBackup: $($_.Exception.Message)" -ForegroundColor Yellow } + Start-Sleep -Seconds 1 + try { - $task = Get-ScheduledTask -TaskName RegIdleBackup -ErrorAction SilentlyContinue + $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) { - Enable-ScheduledTask $task | Out-Null - Start-ScheduledTask $task | Out-Null + 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 { } + } catch { + Write-Host "Scheduled task check failed: $($_.Exception.Message)" -ForegroundColor Yellow + } Start-Sleep -Seconds 4 return (Test-RegistryBackupEnabled) @@ -104,209 +137,225 @@ function Try-EnableRegistryBackup { function Get-DllBitness { param([string]$Path) - - $fs = $null - $br = $null try { $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 - switch ($br.ReadUInt16()) { - 0x8664 { 64 } - 0x014C { 32 } - default { $null } + $m = $br.ReadUInt16() + $br.Close(); $fs.Close() + switch ($m) { + 0x8664 { return 64 } + 0x014C { return 32 } + default { return $null } } - } catch { $null } - finally { - if ($br) { $br.Dispose() } - if ($fs) { $fs.Dispose() } - } + } catch { return $null } } function Is-AcceptableSignature { - param($Sig) - if (-not $Sig) { return $false } - if ($Sig.Status -eq 'Valid') { return $true } - if ($AllowUnsigned -and $Sig.Status -in 'NotSigned','Unknown') { return $true } + 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 Ensure-Registry { - param($Bit,$DllPath) + param($bit, $dllPath) - $Root = $Roots[$Bit] - if (-not $Root) { return } + $root = $Roots[$bit] + if ([string]::IsNullOrWhiteSpace($root)) { return } - if (-not (Test-Path $Root)) { - New-Item -Path $Root -Force | Out-Null - Write-Host "[INFO] Created registry key: $Root" + 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 + } } - if ($Global:RegisteredSeen.Contains($DllPath)) { - Write-Host "[SKIP] Duplicate already processed: $DllPath" - $Stats.SkippedDuplicate++ + 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 + $props = (Get-ItemProperty -Path $root -ErrorAction SilentlyContinue).PSObject.Properties + $exists = $props | Where-Object { $_.Name -eq $dllPath } | Select-Object -First 1 if ($exists) { - Write-Host "[OK] $Bit-bit already registered" - $Stats.AlreadyRegistered++ + $script:countAlready++ + Write-Host "Already present: $dllPath" } else { try { - New-ItemProperty -Path $Root -Name $DllPath -Value 0 -PropertyType DWord -Force | Out-Null - Write-Host "[ADD] $Bit-bit → $DllPath" - $Stats.Registered++ + New-ItemProperty -Path $root -Name $dllPath -Value 0 -PropertyType DWord -Force -ErrorAction Stop | Out-Null + $script:countRegistered++ + Write-Host "Registered: $dllPath" } catch { - Write-Host "[WARN] Failed to register $DllPath under ${Root}: $_" + # <<-- 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 + $Global:RegisteredSeen.Add($dllPath) | Out-Null } # ------------------------- -# Admin + backup gate +# Admin + RegBack gate (announce -> ask -> proceed) # ------------------------- if (-not (Test-IsAdmin)) { - Write-Host "[FATAL] Administrator privileges required." + 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 } -$RegistryBackupEnabled = Test-RegistryBackupEnabled +Write-Host "Administrator privileges confirmed." -ForegroundColor Cyan +Write-Host "" +$RegistryBackupEnabled = Test-RegistryBackupEnabled if ($RegistryBackupEnabled) { - Write-Host "Registry backup detected — full remediation allowed." + Write-Host "Registry backup active. Full registry operations are allowed." -ForegroundColor Green } else { - Write-Host "[WARN] Registry backup not detected." - $ans = Read-Host "Enable automatic registry backup now? (Y/N)" - if ($ans -match '^[Yy]$' -and (Try-EnableRegistryBackup)) { - $RegistryBackupEnabled = $true - Write-Host "[OK] Registry backup confirmed." + 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 "[SAFE MODE] Risky operations disabled." + Write-Host "Proceeding without enabling registry backups; destructive registry operations will be SKIPPED." -ForegroundColor Yellow } } # ------------------------- -# Registry reconciliation +# Registry reconciliation (non-destructive unless $RegistryBackupEnabled) # ------------------------- Write-Host "" -Write-Host "[PHASE] Registry reconciliation" +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 $root).PSObject.Properties | - Where-Object { $_.MemberType -eq 'NoteProperty' } - + $props = (Get-ItemProperty -Path $root -ErrorAction SilentlyContinue).PSObject.Properties foreach ($p in $props) { - $dll = $p.Name if ($dll -notlike "*amdocl*.dll") { continue } if (-not $RegistryBackupEnabled) { - Write-Host "[SAFE] Skipped $dll" + Write-Host "SAFE mode: skipped $dll" -ForegroundColor Yellow continue } if (-not (Test-Path $dll)) { - Write-Host "[REMOVE] Missing → $dll" - Remove-ItemProperty -Path $root -Name $dll -Force - $Stats.RemovedMissing++ + Write-Host "Removed (missing): $dll" -ForegroundColor Yellow + Remove-ItemProperty -Path $root -Name $dll -Force -ErrorAction SilentlyContinue + $countRemovedMissing++ continue } - $sig = Get-AuthenticodeSignature $dll + $sig = Get-AuthenticodeSignature -FilePath $dll -ErrorAction SilentlyContinue if (-not (Is-AcceptableSignature $sig)) { - Write-Host "[REMOVE] Signature rejected → $dll" - Remove-ItemProperty -Path $root -Name $dll -Force - $Stats.RemovedSignature++ + Write-Host "Removed (invalid signature): $dll" -ForegroundColor Yellow + Remove-ItemProperty -Path $root -Name $dll -Force -ErrorAction SilentlyContinue + $countRemovedSignature++ continue } $realBit = Get-DllBitness $dll if ($realBit -and $realBit -ne $bit) { - Write-Host "[MOVE] $dll → $realBit-bit hive" - Remove-ItemProperty -Path $root -Name $dll -Force + Write-Host "Moved ($($realBit) bit): $dll" -ForegroundColor Yellow + Remove-ItemProperty -Path $root -Name $dll -Force -ErrorAction SilentlyContinue + $countMoved++ Ensure-Registry $realBit $dll - $Stats.Moved++ } } } # ------------------------- -# Standard scan +# Register DLLs from standard locations # ------------------------- Write-Host "" -Write-Host "[PHASE] Fast scan" - -foreach ($dir in $ScanDirs) { - if (-not (Test-Path $dir)) { continue } - - Write-Host "[SCAN] $dir" - - Get-ChildItem $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | - ForEach-Object { - - $sig = Get-AuthenticodeSignature $_.FullName - if (-not (Is-AcceptableSignature $sig)) { - Write-Host "[SKIP] Signature rejected → $($_.FullName)" - return +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 "`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 } + } } - - $bit = Get-DllBitness $_.FullName - if ($bit) { Ensure-Registry $bit $_.FullName } - } + } + Write-Host "`nFast Scan complete." -ForegroundColor Cyan } # ------------------------- -# PATH scan +# Optional PATH scan (announce -> ask -> proceed) # ------------------------- Write-Host "" -$ans = Read-Host "Scan PATH directories as well? (Y/N)" - -if ($ans -match '^[Yy]$') { - - Write-Host "[PHASE] PATH scan, please wait ..." - - foreach ($p in ($env:PATH -split ';' | Where-Object { Test-Path $_ })) { - - Write-Host "[SCAN] $p" - - Get-ChildItem $p -Filter "amdocl*.dll" -ErrorAction SilentlyContinue | +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 ($p in $pathDirs) { + Write-Host "Scanning: $p" + Get-ChildItem -Path $p -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | ForEach-Object { - - $sig = Get-AuthenticodeSignature $_.FullName - if (-not (Is-AcceptableSignature $sig)) { - Write-Host "[SKIP] Signature rejected → $($_.FullName)" - return + $sig = Get-AuthenticodeSignature -FilePath $_.FullName -ErrorAction SilentlyContinue + if (Is-AcceptableSignature $sig) { + $bit = Get-DllBitness $_.FullName + if ($bit) { Ensure-Registry $bit $_.FullName } } - - $bit = Get-DllBitness $_.FullName - if ($bit) { Ensure-Registry $bit $_.FullName } } } + Write-Host "`nFull Scan complete." -ForegroundColor Cyan } # ------------------------- -# Final summary +# Summary # ------------------------- Write-Host "" Write-Host "========== SUMMARY ==========" -Write-Host "Removed missing : $($Stats.RemovedMissing)" -Write-Host "Removed signature : $($Stats.RemovedSignature)" -Write-Host "Moved entries : $($Stats.Moved)" -Write-Host "Registered new : $($Stats.Registered)" -Write-Host "Already registered : $($Stats.AlreadyRegistered)" -Write-Host "Duplicates skipped : $($Stats.SkippedDuplicate)" +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 "" -Write-Host "Completed." -ForegroundColor Green + +if ($hadErrors) { + Write-Host "Completed with warnings." -ForegroundColor Yellow +} else { + Write-Host "Completed." -ForegroundColor Green +} + Read-Host "Press Enter to exit"