From 1e8f21094842696989ef382d59ba43fef80b1a9e Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Tue, 16 Jun 2026 08:26:10 +0000 Subject: [PATCH] docs(windows-secure-desktop): steps 1/3/4/5/6 live-validated; soak results Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/windows-secure-desktop.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/docs/windows-secure-desktop.md b/docs/windows-secure-desktop.md index 674c7f7..40180bd 100644 --- a/docs/windows-secure-desktop.md +++ b/docs/windows-secure-desktop.md @@ -1,8 +1,11 @@ # Windows secure-desktop capture — two-process design -Status: **steps 1–5 implemented (compiles on the 4090); live validation pending.** The WGC animation -fix ships and works (host in user-mode); this doc is the plan for adding **secure-desktop (UAC / lock -/ login) coverage** on top of it, since WGC and the secure desktop need conflicting process tokens. +Status: **steps 1, 3, 4, 5, 6 implemented and live-validated on the RTX 4090 (2026-06-16).** The +two-process path works end to end (host as SYSTEM): the user-session WGC helper relays video, the mux +switches to the host's DDA on the secure desktop, and a dead helper is rebuilt automatically. Only the +SendInput retry-refactor (step 2) and a *real* UAC/lock smoke test remain. The earlier user-mode WGC +animation fix still ships; this is the SYSTEM-mode design that adds secure-desktop (UAC/lock/login) +coverage, since WGC and the secure desktop need conflicting process tokens. Implemented so far: - **Step 1 — DesktopWatcher** (`capture/desktop_watch.rs`): polls the input-desktop name → atomic @@ -27,11 +30,17 @@ Implemented so far: DDA capture itself is pre-proven by the single-process secure path (commit `f4b4a6c`); step 5's new surface is the mux, which the toggle exercises directly. -Remaining: **step 6** (helper relaunch watchdog on console connect/disconnect + crash, then a -lock/unlock+UAC soak) and **step 2** (SendInput retry-on-failure refactor — input works today via the -existing path; this hardens it across the desktop boundary). Also a **final user-driven smoke test**: -trigger a *real* UAC/lock on the box during a session and confirm the dialog appears on the client -(the box's UAC auto-elevates admins, so a real prompt can't be triggered headless over SSH). +- Step 6: the helper relaunch watchdog. Force-killing the helper PID mid-stream triggered exactly one + `WGC helper exited — rebuilt output + helper fails=1` and the stream recovered — client-rs decoded + 645 frames continuously across the kill. A ~30s mux soak (2s toggle) ran 16 switches with 0 rebuilds + / 0 early-ends / 465 frames decoded. (Recovery rebuilds the whole output, not a same-target respawn, + which storm-failed with "no DXGI output for target N yet" after an abrupt kill.) + +Remaining: **step 2** (SendInput retry-on-failure refactor — input works today via the existing path; +this hardens it across the desktop boundary) and a **final user-driven smoke test**: trigger a *real* +UAC/lock on the box during a session and confirm the dialog appears on the client (the box's UAC +auto-elevates admins, so a real prompt can't be triggered headless over SSH; the mux switch itself is +proven by the timed toggle, and DDA-on-Winlogon capture by the single-process secure path). > **Note:** the two-process path requires the host to run as SYSTEM (`run.cmd.sysbak` → `-s -i 1`). > As SYSTEM, WASAPI loopback audio (session 0) does not capture the user session's audio — a known