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:
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user