@echo off
setlocal EnableExtensions EnableDelayedExpansion

rem ==========================================================
rem  One-click scheduled task: disable Windows system proxy on
rem  any user logon (WinInet, per-user registry).
rem
rem  Usage:
rem    Double-click              -> Install / update tasks
rem    Run with argument uninstall -> Uninstall tasks
rem ==========================================================

set "TASK_FOLDER=\Gemod"
set "TASK_EVENT=%TASK_FOLDER%\ProxyOff_OnLogonAnyUser"

rem Use ProgramData so the script exists for all users.
set "BASE_DIR=%ProgramData%\Gemod"
set "PS1=%BASE_DIR%\proxy-off.ps1"
set "XML=%TEMP%\gemod-proxyoff-task.xml"
set "XMLWRITER=%TEMP%\gemod-write-proxyoff-xml.ps1"

rem Creating a SYSTEM task requires admin. Self-elevate via UAC when needed.
net session >nul 2>&1
if errorlevel 1 (
  echo [INFO] Admin privileges required. Requesting elevation...
  if "%~1"=="" (
    powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -FilePath '%~f0' -Verb RunAs"
  ) else (
    powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -FilePath '%~f0' -ArgumentList '%*' -Verb RunAs"
  )
  exit /b 0
)

if /I "%~1"=="uninstall" goto :UNINSTALL

echo [1/3] Generating proxy-off script...
if not exist "%BASE_DIR%" mkdir "%BASE_DIR%" >nul 2>&1

> "%PS1%" echo $ErrorActionPreference = 'SilentlyContinue'
>> "%PS1%" echo $log = Join-Path (Split-Path $MyInvocation.MyCommand.Path -Parent) 'proxy-off.log'
>> "%PS1%" echo $dts = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
>> "%PS1%" echo # If Gemod is running, it owns the proxy; skip (avoids racing Gemod at logon).
>> "%PS1%" echo if (Get-Process -Name @('Gemod','Gemod-x86','Win7VergeLite') -ErrorAction SilentlyContinue) { try { Add-Content -LiteralPath $log -Value ^($dts + ' SKIP gemod-family-running'^) } catch {} ; exit 0 }
>> "%PS1%" echo $dts = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
>> "%PS1%" echo Add-Content -LiteralPath $log -Value ^($dts + ' RUN disable-proxy'^) -ErrorAction SilentlyContinue
>> "%PS1%" echo $rel = 'Software\Microsoft\Windows\CurrentVersion\Internet Settings'
>> "%PS1%" echo function Disable-ProxyForSid([string]$sid) {
>> "%PS1%" echo ^  try {
>> "%PS1%" echo ^    $k = "Registry::HKEY_USERS\$sid\$rel"
>> "%PS1%" echo ^    Set-ItemProperty -Path $k -Name ProxyEnable -Type DWord -Value 0
>> "%PS1%" echo ^    Remove-ItemProperty -Path $k -Name AutoConfigURL -ErrorAction SilentlyContinue
>> "%PS1%" echo ^  } catch {}
>> "%PS1%" echo }
>> "%PS1%" echo.
>> "%PS1%" echo # Try console user first (works when running as SYSTEM)
>> "%PS1%" echo try ^{ $user = (Get-WmiObject Win32_ComputerSystem).UserName ^} catch ^{ $user = $null ^}
>> "%PS1%" echo if ($user) {
>> "%PS1%" echo ^  try {
>> "%PS1%" echo ^    $sid = (New-Object System.Security.Principal.NTAccount($user)).Translate([System.Security.Principal.SecurityIdentifier]).Value
>> "%PS1%" echo ^    Disable-ProxyForSid $sid
>> "%PS1%" echo ^  } catch {}
>> "%PS1%" echo }
>> "%PS1%" echo.
>> "%PS1%" echo # Also apply to all currently loaded user hives (safe no-op for system hives)
>> "%PS1%" echo try ^{
>> "%PS1%" echo ^  Get-ChildItem Registry::HKEY_USERS ^| ForEach-Object { $_.PSChildName } ^| Where-Object { $_ -match '^S-1-5-21-' -and $_ -notmatch '_Classes$' } ^| ForEach-Object { Disable-ProxyForSid $_ }
>> "%PS1%" echo ^} catch {}
>> "%PS1%" echo.
rem WinInet refresh block (inlined; no external scripts\*.ps1 required)
>> "%PS1%" echo.
>> "%PS1%" echo # Refresh WinInet ^(same effect as IE 'Apply'^)
>> "%PS1%" echo try ^{
>> "%PS1%" echo ^  Add-Type -Namespace Wininet -Name NativeMethods -MemberDefinition @"
>> "%PS1%" echo using System;
>> "%PS1%" echo using System.Runtime.InteropServices;
>> "%PS1%" echo public static class NativeMethods ^{
>> "%PS1%" echo ^  [DllImport^("wininet.dll^", SetLastError=true^)]
>> "%PS1%" echo ^  public static extern bool InternetSetOption^(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength^);
>> "%PS1%" echo }
>> "%PS1%" echo ^"@ -ErrorAction SilentlyContinue
>> "%PS1%" echo ^  [void][WinInet.NativeMethods]::InternetSetOption^([IntPtr]::Zero, 39, [IntPtr]::Zero, 0^)
>> "%PS1%" echo ^  [void][WinInet.NativeMethods]::InternetSetOption^([IntPtr]::Zero, 37, [IntPtr]::Zero, 0^)
>> "%PS1%" echo } catch {}

echo [2/3] Creating/updating scheduled tasks...
set "PSEXE=%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe"
rem %PS1% has no spaces; keep ARGS quote-free to avoid XML/escaping issues.
set "ARGS=-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File %PS1%"
set "TR=%PSEXE% %ARGS%"

rem Cleanup legacy task names (older script versions).
schtasks /Delete /F /TN "%TASK_FOLDER%\ProxyOff_OnShutdown" >nul 2>&1
schtasks /Delete /F /TN "%TASK_FOLDER%\ProxyOff_OnLogoff" >nul 2>&1
schtasks /Delete /F /TN "%TASK_FOLDER%\ProxyOff_OnUser32_1074" >nul 2>&1

rem Create task via XML so we can:
rem - Trigger: ONLOGON (any user)
rem - Principal: SYSTEM, script writes HKEY_USERS\<SID> for the logged-on user
rem - Conditions: disable power constraints (run on battery too)
rem Use a temp .ps1 to generate UTF-16 XML reliably (avoid cmd/powershell quoting pitfalls).
> "%XMLWRITER%" echo $ErrorActionPreference = 'Stop'
>> "%XMLWRITER%" echo $psexe = $env:PSEXE
>> "%XMLWRITER%" echo $args  = $env:ARGS
>> "%XMLWRITER%" echo $xmlPath = $env:XML
>> "%XMLWRITER%" echo $xml = @'
>> "%XMLWRITER%" echo ^<?xml version="1.0" encoding="UTF-16"?^>
>> "%XMLWRITER%" echo ^<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"^>
>> "%XMLWRITER%" echo   ^<RegistrationInfo^>
>> "%XMLWRITER%" echo     ^<Author^>Gemod^</Author^>
>> "%XMLWRITER%" echo     ^<Description^>Disable WinInet system proxy at any user logon.^</Description^>
>> "%XMLWRITER%" echo   ^</RegistrationInfo^>
>> "%XMLWRITER%" echo   ^<Triggers^>
>> "%XMLWRITER%" echo     ^<LogonTrigger^>
>> "%XMLWRITER%" echo       ^<Enabled^>true^</Enabled^>
>> "%XMLWRITER%" echo     ^</LogonTrigger^>
>> "%XMLWRITER%" echo   ^</Triggers^>
>> "%XMLWRITER%" echo   ^<Principals^>
>> "%XMLWRITER%" echo     ^<Principal id="Author"^>
>> "%XMLWRITER%" echo       ^<UserId^>S-1-5-18^</UserId^>
rem NOTE: Some systems reject LogonType=ServiceAccount in imported XML.
rem Omitting LogonType works with SYSTEM UserId and is more compatible.
>> "%XMLWRITER%" echo       ^<RunLevel^>HighestAvailable^</RunLevel^>
>> "%XMLWRITER%" echo     ^</Principal^>
>> "%XMLWRITER%" echo   ^</Principals^>
>> "%XMLWRITER%" echo   ^<Settings^>
>> "%XMLWRITER%" echo     ^<MultipleInstancesPolicy^>IgnoreNew^</MultipleInstancesPolicy^>
>> "%XMLWRITER%" echo     ^<DisallowStartIfOnBatteries^>false^</DisallowStartIfOnBatteries^>
>> "%XMLWRITER%" echo     ^<StopIfGoingOnBatteries^>false^</StopIfGoingOnBatteries^>
>> "%XMLWRITER%" echo     ^<AllowHardTerminate^>true^</AllowHardTerminate^>
>> "%XMLWRITER%" echo     ^<StartWhenAvailable^>false^</StartWhenAvailable^>
>> "%XMLWRITER%" echo     ^<RunOnlyIfNetworkAvailable^>false^</RunOnlyIfNetworkAvailable^>
>> "%XMLWRITER%" echo     ^<IdleSettings^>
>> "%XMLWRITER%" echo       ^<StopOnIdleEnd^>false^</StopOnIdleEnd^>
>> "%XMLWRITER%" echo       ^<RestartOnIdle^>false^</RestartOnIdle^>
>> "%XMLWRITER%" echo     ^</IdleSettings^>
>> "%XMLWRITER%" echo     ^<AllowStartOnDemand^>true^</AllowStartOnDemand^>
>> "%XMLWRITER%" echo     ^<Enabled^>true^</Enabled^>
>> "%XMLWRITER%" echo     ^<Hidden^>false^</Hidden^>
>> "%XMLWRITER%" echo     ^<RunOnlyIfIdle^>false^</RunOnlyIfIdle^>
>> "%XMLWRITER%" echo     ^<WakeToRun^>false^</WakeToRun^>
>> "%XMLWRITER%" echo     ^<ExecutionTimeLimit^>PT0S^</ExecutionTimeLimit^>
>> "%XMLWRITER%" echo     ^<Priority^>4^</Priority^>
>> "%XMLWRITER%" echo   ^</Settings^>
>> "%XMLWRITER%" echo   ^<Actions Context="Author"^>
>> "%XMLWRITER%" echo     ^<Exec^>
>> "%XMLWRITER%" echo       ^<Command^>@@PSEXE@@^</Command^>
>> "%XMLWRITER%" echo       ^<Arguments^>@@ARGS@@^</Arguments^>
>> "%XMLWRITER%" echo     ^</Exec^>
>> "%XMLWRITER%" echo   ^</Actions^>
>> "%XMLWRITER%" echo ^</Task^>
>> "%XMLWRITER%" echo '@
>> "%XMLWRITER%" echo $xml = $xml.Replace('@@PSEXE@@', $psexe).Replace('@@ARGS@@', $args)
>> "%XMLWRITER%" echo Set-Content -LiteralPath $xmlPath -Value $xml -Encoding Unicode

powershell -NoProfile -ExecutionPolicy Bypass -File "%XMLWRITER%"
if errorlevel 1 (
  echo [WARN] Failed to generate task XML: %XML%
)

schtasks /Create /F /TN "%TASK_EVENT%" /XML "%XML%" >nul 2>&1
if errorlevel 1 (
  echo [ERROR] Failed to create logon task even after elevation.
  echo You can run manually to see details:
  echo   schtasks /Create /F /TN "%TASK_EVENT%" /XML "%XML%" /HRESULT
)

echo [3/3] Done.
echo - Task: %TASK_EVENT%
echo - Script: %PS1%
echo - PowerShell (hidden): %TR%
echo.
pause
exit /b 0

:UNINSTALL
echo [1/2] Deleting scheduled tasks...
schtasks /Delete /F /TN "%TASK_EVENT%" >nul 2>&1
schtasks /Delete /F /TN "%TASK_FOLDER%\ProxyOff_OnShutdown" >nul 2>&1
schtasks /Delete /F /TN "%TASK_FOLDER%\ProxyOff_OnLogoff" >nul 2>&1
schtasks /Delete /F /TN "%TASK_FOLDER%\ProxyOff_OnUser32_1074" >nul 2>&1

echo [2/2] Deleting script file...
del /f /q "%PS1%" >nul 2>&1

echo Done.
pause
exit /b 0

