# Auto-Logon einrichten — schliesst die letzte Luecke der Boot-Pipeline.
#
# WOZU: `OilTradingServer` und `HyperliquidDashboard` haengen an einem LOGON-
# Trigger. Nach einem Windows-Update-Reboot laeuft nichts, bis sich jemand
# anmeldet — real in der Nacht zum 2026-07-20 passiert (Reboot 01:30, Server bis
# 07:42 tot, nur der broker-seitige SL schuetzte, -95,48 EUR). Ein Task ohne
# angemeldete Sitzung hilft NICHT: der Bot braucht das laufende MT5-TERMINAL,
# und das ist eine GUI-Anwendung — es braucht eine echte Desktop-Sitzung.
#
# ⚠⚠ WARUM SYSINTERNALS UND NICHT DIE REGISTRY. Der verbreitete Weg schreibt
# das Passwort als `DefaultPassword` im KLARTEXT nach HKLM\...\Winlogon — dort
# kann es jeder lokale Administrator und jedes Backup-Image lesen. Sysinternals
# `Autologon` legt es als verschluesseltes LSA-Secret ab.
#
# ⚠ RESTRISIKO, das bleibt: nach dem Reboot steht eine ANGEMELDETE Sitzung mit
# offenem MT5 und Live-Broker-Verbindung da. Schritt 2 sperrt deshalb den
# Bildschirm — aber nur nach einem Auto-Logon, nicht nach jeder Anmeldung
# (s. `autologon_lock.ps1`).
#
# AUFRUF (Fenster muss ALS ADMINISTRATOR laufen):
#   powershell -ExecutionPolicy Bypass -File tools\autologon_einrichten.ps1
#
# ⚠ Das Passwort steht NICHT in dieser Datei und wird nirgends gespeichert —
#   es wird im GUI-Dialog von Autologon eingegeben.
#
# ⚠⚠ ZWEI FEHLER AUS DEM ERSTEN VERSUCH (2026-08-07), hier behoben:
#   1. `$ErrorActionPreference = 'Stop'` PLUS `schtasks /Delete` auf eine noch
#      nicht existierende Aufgabe = das Skript brach ab, BEVOR /Create lief.
#      Native Programme schreiben nach stderr, und PowerShell macht daraus unter
#      'Stop' einen Abbruch. Jetzt wird vorher geprueft, ob es sie ueberhaupt gibt.
#   2. Die Erfolgsmeldung log: fehlendes `DefaultPassword` wurde als
#      "LSA-Secret ✅" gemeldet — dabei war schlicht GAR NICHTS gesetzt. Jetzt
#      ist `AutoAdminLogon = 1` die Bedingung, und erst danach wird ueberhaupt
#      ueber die Speicherart geurteilt.

# AUFRUF-VARIANTEN:
#   ... -File tools\autologon_einrichten.ps1            GUI-Dialog (Standard)
#   ... -File tools\autologon_einrichten.ps1 -Direkt    ohne Dialog, Passwort
#                                                       wird hier abgefragt
# ⚠ `-Direkt` ist der zuverlaessige Weg. Der Dialog OEFFNET sich zwar
# (Fenstertitel "Autologon - Sysinternals", verifiziert), muss aber mit ENABLE
# bestaetigt werden — wird er nur geschlossen, passiert nichts.
# ⚠ Abwaegung bei `-Direkt`: Autologon 3.10 nimmt Benutzer/Domaene/Passwort als
# Argumente. Das Passwort steht damit fuer den Moment des Aufrufs in der
# Kommandozeile des Kindprozesses (fuer Administratoren kurz sichtbar). Es wird
# NICHT in eine Datei geschrieben, nicht in die PowerShell-History (Read-Host)
# und landet anschliessend als verschluesseltes LSA-Secret — nicht im Klartext
# in der Registry.
param([switch]$Direkt)

$ErrorActionPreference = 'Stop'
$hier = Split-Path -Parent $MyInvocation.MyCommand.Path
$k = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon'
$t = 'OilAutoLogonLock'

$id = [Security.Principal.WindowsIdentity]::GetCurrent()
if (-not (New-Object Security.Principal.WindowsPrincipal($id)).IsInRole(
        [Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Write-Host "  ABBRUCH: Dieses Fenster hat keine Administratorrechte." -ForegroundColor Red
    exit 1
}

$exe = Join-Path $hier 'autologon\Autologon64.exe'
if (-not (Test-Path $exe)) { $exe = Join-Path $hier 'autologon\Autologon.exe' }
if (-not (Test-Path $exe)) {
    Write-Host "  ABBRUCH: Autologon.exe fehlt unter tools\autologon\." -ForegroundColor Red
    exit 1
}

Write-Host "=================================================================="
Write-Host "  SCHRITT 1 - Auto-Logon aktivieren (verschluesseltes LSA-Secret)"
Write-Host "=================================================================="
Write-Host "  Benutzer: $env:USERNAME     Domaene: $env:COMPUTERNAME (lokal)"
# Aktivierung ohne Dialog — als Funktion, damit sie auch als Rueckfall nach
# einem abgebrochenen Dialog aufgerufen werden kann (sonst muesste der Nutzer
# das Skript ein drittes Mal starten).
function Invoke-DirektAktivierung {
    # ⚠ Read-Host -AsSecureString: die Eingabe erscheint nicht auf dem Schirm
    # und landet nicht in der PowerShell-History.
    $sec = Read-Host "  Passwort fuer $env:USERNAME (Eingabe bleibt unsichtbar)" -AsSecureString
    $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($sec)
    try {
        $pw = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
        if (-not $pw) {
            Write-Host "  Kein Passwort eingegeben." -ForegroundColor Red
            return $false
        }
        Write-Host "  Aktiviere Auto-Logon ..."
        # ⚠⚠ ZWEI FEHLER AUS DEM VORIGEN VERSUCH, hier behoben:
        #  (a) `& $exe ...` WARTET BEI GUI-ANWENDUNGEN NICHT — das Skript las die
        #      Registry, bevor Autologon ueberhaupt fertig war.
        #  (b) `$null = ... 2>&1` hat die Rueckmeldung VERSCHLUCKT. Genau die
        #      Information, die zur Diagnose noetig war, wurde weggeworfen.
        # Jetzt: warten, Exit-Code auswerten, Ausgabe zeigen.
        $log = Join-Path $env:TEMP 'autologon_out.txt'
        $p = Start-Process -FilePath $exe `
                -ArgumentList $env:USERNAME, $env:COMPUTERNAME, $pw `
                -Wait -PassThru -RedirectStandardOutput $log `
                -RedirectStandardError "$log.err" -WindowStyle Hidden
        Write-Host "  Autologon ExitCode: $($p.ExitCode)"
        foreach ($f in @($log, "$log.err")) {
            if ((Test-Path $f) -and (Get-Item $f).Length -gt 0) {
                Write-Host "  Ausgabe: $((Get-Content $f -Raw).Trim())"
            }
            Remove-Item $f -EA SilentlyContinue
        }
        return $true
    } finally {
        # Klartext so kurz wie moeglich im Speicher halten
        [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
        Remove-Variable pw -ErrorAction SilentlyContinue
    }
}

Write-Host ""
if ($Direkt) {
    if (-not (Invoke-DirektAktivierung)) { exit 1 }
} else {
    Write-Host "  Es oeffnet sich gleich der Autologon-Dialog." -ForegroundColor Cyan
    Write-Host "  --> Passwort eintragen und auf ENABLE klicken." -ForegroundColor Cyan
    Write-Host "  (Nur schliessen reicht NICHT - dann passiert nichts."
    Write-Host "   Zuverlaessiger: Skript mit  -Direkt  aufrufen.)"
    Write-Host ""
    Start-Process -FilePath $exe -ArgumentList '/accepteula' -Wait
}

# ── Ergebnis ehrlich pruefen ────────────────────────────────────────────
$an = (Get-ItemProperty -Path $k -Name AutoAdminLogon -EA SilentlyContinue).AutoAdminLogon
$user = (Get-ItemProperty -Path $k -Name DefaultUserName -EA SilentlyContinue).DefaultUserName
$klartext = (Get-ItemProperty -Path $k -Name DefaultPassword -EA SilentlyContinue).DefaultPassword
$aktiv = ($an -eq '1')

Write-Host ""
Write-Host "  AutoAdminLogon  : $(if ($an) { $an } else { '(nicht gesetzt)' })"
Write-Host "  DefaultUserName : $(if ($user) { $user } else { '(nicht gesetzt)' })"

# ⚠ RUECKFALL statt Sackgasse: schlaegt der Dialog-Weg fehl, wird hier direkt
# angeboten, es ohne Dialog zu erledigen — sonst muesste das Skript ein drittes
# Mal von Hand gestartet werden (real zweimal passiert).
if (-not $aktiv -and -not $Direkt) {
    Write-Host ""
    Write-Host "  ==> Der Dialog wurde ohne 'Enable' geschlossen." -ForegroundColor Yellow
    $a = Read-Host "      Jetzt ohne Dialog erledigen? (j/n)"
    if ($a -match '^[jJyY]') {
        if (Invoke-DirektAktivierung) {
            $an = (Get-ItemProperty -Path $k -Name AutoAdminLogon -EA SilentlyContinue).AutoAdminLogon
            $user = (Get-ItemProperty -Path $k -Name DefaultUserName -EA SilentlyContinue).DefaultUserName
            $klartext = (Get-ItemProperty -Path $k -Name DefaultPassword -EA SilentlyContinue).DefaultPassword
            $aktiv = ($an -eq '1')
            Write-Host ""
            Write-Host "  AutoAdminLogon  : $(if ($an) { $an } else { '(nicht gesetzt)' })"
            Write-Host "  DefaultUserName : $(if ($user) { $user } else { '(nicht gesetzt)' })"
        }
    }
}

# ── Letzter Ausweg: Registry-Weg ────────────────────────────────────────
# ⚠⚠ BEWUSST ALS LETZTE OPTION und nur nach ausdruecklicher Zustimmung. Hier
# landet das Passwort im KLARTEXT unter HKLM\...\Winlogon\DefaultPassword —
# lesbar fuer jeden lokalen Administrator und in jedem Backup-Image. Der einzige
# Vorteil: er funktioniert immer, ohne Fremdprogramm. Wenn Autologon (der
# sichere Weg) partout nicht greift, ist das die Alternative — die Entscheidung
# gehoert dem Nutzer, nicht dem Skript.
if (-not $aktiv) {
    Write-Host ""
    Write-Host "  ==> AUTO-LOGON IST NICHT AKTIV." -ForegroundColor Yellow
    Write-Host "      Sysinternals Autologon hat nichts geschrieben."
    Write-Host ""
    Write-Host "  ALTERNATIVE: der Registry-Weg." -ForegroundColor Cyan
    Write-Host "  ⚠ Dabei steht das Passwort im KLARTEXT in der Registry" -ForegroundColor Yellow
    Write-Host "    (HKLM\...\Winlogon\DefaultPassword). Jeder lokale Admin und"
    Write-Host "    jedes Backup-Image kann es lesen. Er funktioniert dafuer immer."
    $a = Read-Host "      Registry-Weg jetzt verwenden? (j/n)"
    if ($a -notmatch '^[jJyY]') {
        Write-Host "      Abgebrochen. Schritt 2 uebersprungen."
        exit 1
    }
    $sec = Read-Host "  Passwort fuer $env:USERNAME (Eingabe bleibt unsichtbar)" -AsSecureString
    $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($sec)
    try {
        $pw2 = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
        if (-not $pw2) { Write-Host "  Kein Passwort." -ForegroundColor Red; exit 1 }
        Set-ItemProperty -Path $k -Name AutoAdminLogon    -Value '1'              -Type String
        Set-ItemProperty -Path $k -Name DefaultUserName   -Value $env:USERNAME    -Type String
        Set-ItemProperty -Path $k -Name DefaultDomainName -Value $env:COMPUTERNAME -Type String
        Set-ItemProperty -Path $k -Name DefaultPassword   -Value $pw2            -Type String
    } finally {
        [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
        Remove-Variable pw2 -EA SilentlyContinue
    }
    $an = (Get-ItemProperty -Path $k -Name AutoAdminLogon -EA SilentlyContinue).AutoAdminLogon
    $aktiv = ($an -eq '1')
    Write-Host ""
    Write-Host "  AutoAdminLogon  : $an"
}

if (-not $aktiv) {
    Write-Host "  ==> Auch das hat nicht gegriffen. Schritt 2 uebersprungen." -ForegroundColor Red
    exit 1
}

# ⚠⚠ NEU EINLESEN, NICHT den alten Wert wiederverwenden. Beim ersten Bau stand
# hier eine stale Variable aus der Zeit VOR dem Registry-Schreiben — die Ausgabe
# widersprach sich dann direkt: erst korrekt "steht jetzt im KLARTEXT", zwei
# Zeilen spaeter "nicht im Klartext (LSA-Secret) ✅". DRITTER Fall derselben
# Fehlerklasse in diesem Skript (Erfolg melden, wo keiner ist bzw. wo das
# Gegenteil zutrifft). Der Zustand wird deshalb immer frisch gelesen.
$klartext = (Get-ItemProperty -Path $k -Name DefaultPassword -EA SilentlyContinue).DefaultPassword
Write-Host ""
if ($klartext) {
    Write-Host "  SPEICHERART: ⚠ Passwort im KLARTEXT in der Registry." -ForegroundColor Yellow
    Write-Host "    Entfernen (deaktiviert damit auch den Auto-Logon):"
    Write-Host "      Remove-ItemProperty -Path '$k' -Name DefaultPassword"
} else {
    Write-Host "  SPEICHERART: verschluesseltes LSA-Secret ✅" -ForegroundColor Green
}

if ($klartext) {
    Write-Host "  DefaultPassword : ⚠ KLARTEXT in der Registry!" -ForegroundColor Yellow
} else {
    Write-Host "  DefaultPassword : nicht im Klartext (LSA-Secret) ✅" -ForegroundColor Green
}

# ── Schritt 2: Bildschirmsperre nach dem Auto-Logon ─────────────────────
Write-Host ""
Write-Host "=================================================================="
Write-Host "  SCHRITT 2 - Bildschirm nach dem Auto-Logon sperren"
Write-Host "=================================================================="

# ⚠ Erst pruefen, dann loeschen. `schtasks /Delete` auf eine fehlende Aufgabe
# schreibt nach stderr und wuerde unter $ErrorActionPreference='Stop' abbrechen.
$vorhanden = $false
try {
    $null = & schtasks /Query /TN $t 2>&1
    $vorhanden = ($LASTEXITCODE -eq 0)
} catch { $vorhanden = $false }
if ($vorhanden) {
    $null = & schtasks /Delete /TN $t /F 2>&1
    Write-Host "  alte Aufgabe entfernt"
}

$lock = Join-Path $hier 'autologon_lock.ps1'
$cmd = "powershell -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$lock`""
$null = & schtasks /Create /TN $t /SC ONLOGON /RU "$env:USERNAME" /DELAY 0000:30 /TR $cmd /F 2>&1
if ($LASTEXITCODE -eq 0) {
    Write-Host "  Aufgabe '$t' angelegt." -ForegroundColor Green
    Write-Host "  Sperrt 30 s nach der Anmeldung - aber NUR, wenn der Rechner"
    Write-Host "  gerade gebootet hat. Nach manueller Anmeldung passiert nichts."
    Write-Host "  Die Sitzung laeuft weiter: MT5 und beide Server arbeiten."
} else {
    Write-Host "  ⚠ Aufgabe konnte nicht angelegt werden (Code $LASTEXITCODE)." -ForegroundColor Yellow
}

Write-Host ""
Write-Host "  Rueckgaengig:"
Write-Host "    $exe /accepteula        (dann Disable)"
Write-Host "    schtasks /Delete /TN $t /F"
