feat(host/windows): force-composed-flip overlay to capture the secure desktop

The secure (Winlogon: UAC/lock/login) desktop presents via fullscreen
independent-flip/MPO — it scans out bypassing DWM composition, so DXGI Desktop
Duplication returns born-lost DXGI_ERROR_ACCESS_LOST (the client sees black; the
UAC only "flashes" during the brief composed transition). Confirmed live: stable
4090 LUID across the storm (NOT reparenting) on an FP16 HDR output, recovering
only when the screen changes.

Fix (non-input, no system-wide registry change): capture/composed_flip.rs keeps a
tiny click-through near-invisible TOPMOST LAYERED window alive on the current
input desktop. Any visible window on the output disqualifies independent-flip →
DWM composites → DDA can capture. A dedicated thread follows the input desktop
(Default↔Winlogon) and recreates the window there on each switch (a window is
bound to its desktop), re-asserting topmost + pumping messages every 200ms.
Started for the two-process stream's lifetime; gated by PUNKTFUNK_FORCE_COMPOSED
(default on, =0 to disable). Needs GENERIC_ALL on OpenInputDesktop for
DESKTOP_CREATEWINDOW (0x80070005 otherwise). Validated: overlay creates on the
Default desktop; live lock test pending.

Also includes SET_RENDER_ADAPTER (sudovda.rs, Apollo item #16): pins the IDD
render GPU to the NVENC GPU before ADD — issued + accepted live, though the
secure-desktop storm was proven to be independent-flip (stable LUID), not
reparenting, so it's correctness/hygiene here rather than this bug's fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-16 10:25:55 +00:00
parent 3e2888de26
commit ef4786387e
5 changed files with 320 additions and 0 deletions
+4
View File
@@ -2345,6 +2345,10 @@ fn virtual_stream_relay(
// The authoritative Default↔Winlogon signal (requires SYSTEM to read the Winlogon desktop name).
let watcher = crate::capture::desktop_watch::DesktopWatcher::start();
// Keep a force-composed-flip overlay alive on the input desktop so the SECURE desktop (which
// otherwise presents via fullscreen independent-flip → DDA gets born-lost ACCESS_LOST / black) is
// forced into DWM composition and becomes capturable. Held for the stream's lifetime.
let _composed_flip = crate::capture::composed_flip::ForceComposedFlip::start();
// Test hook: PUNKTFUNK_SECURE_TEST_PERIOD_MS=N drives a square-wave secure/normal toggle every N ms
// instead of the real watcher — exercises the mid-session helper↔DDA mux without a live UAC/lock
// (the real Winlogon DDA capture is already proven by the single-process secure path).