Files
punktfunk/crates/pf-win-display/src/lib.rs
T
enricobuehler f40c90aa23 refactor(host/inject/win-display): the Win32 unsafe surface is the FFI call, not the function
`spawn_in_active_session` existed only to launder `spawn_inner`'s `unsafe fn` marker — and its
own comment said why that marker was empty: the callee "has no caller-side preconditions, it
validates the session/token itself and owns every handle it opens". A marker that documents the
absence of a contract is not a contract. The two collapse into one safe fn whose `unsafe` now sits
on the eight Win32 calls, each with the proof it actually needs.

Kept `unsafe fn` exactly where a caller CAN break something: `merged_env_block` (a `*const u16`
block it must trust), `spawn_host` (a borrowed job `HANDLE`), `desktop_name` (an `HDESK`),
`inject_following_desktop` (a live synthetic-pointer device). Those bodies gain explicit blocks
instead — `merged_env_block`'s pointer walk is the one place here where the proof is load-bearing
rather than restating a signature, and it now says why the scan cannot run off the block's end.

With those four files at zero, all three crates take `deny(unsafe_op_in_unsafe_fn)` at the root,
next to the `undocumented_unsafe_blocks` deny they already had. The pair matters: alone, the older
deny is satisfied by an `unsafe fn` body, which needs no blocks at all and so can hide an unproven
FFI call. The workspace lint stays `warn` — it is a ratchet over the encoder backends still to be
cleared, and a crate that reaches zero should not be able to drift back silently.

Windows E0133 214 -> 182 (the remainder is the ash/AMF-dense encode backends). Verified on the
Intel box .47 and on Linux .21: no errors, no `unused_unsafe`, no dead-code fallout.
2026-07-28 22:31:11 +02:00

52 lines
2.9 KiB
Rust

//! Windows display-topology helpers (plan §W6), extracted from the host's `windows/{win_display,
//! monitor_devnode,display_events}.rs` so the IDD-push capturer (`pf-capture`) and the pf-vdisplay
//! backend (the host) depend on them as a leaf PEER instead of the capturer reaching back into the
//! orchestrator. Windows-only; compiles to an empty lib elsewhere.
//!
//! - [`win_display`]: CCD/GDI path activation, mode-setting, HDR advanced-colour toggles, and the
//! source-desktop geometry the capturer duplicates.
//! - [`monitor_devnode`]: PnP monitor devnode enable/disable (the parallel-display isolation lever).
//! - [`display_events`]: the `WM_DISPLAYCHANGE` / device-arrival watch that lets a capture stall say
//! whether an OS display event coincided with it.
// `win_display` has denied both unsafe-proof lints since its CCD helpers stopped being `unsafe fn`;
// hoist that to the crate root so the smaller modules (`input_desktop`, `monitor_devnode`,
// `display_events`) and any future one are covered by default rather than by remembering to opt in.
#![deny(clippy::undocumented_unsafe_blocks)]
#![deny(unsafe_op_in_unsafe_fn)]
#[cfg(target_os = "windows")]
pub mod display_events;
/// Bind display-config writes to the input desktop so a UAC / lock screen can't refuse them.
#[cfg(target_os = "windows")]
mod input_desktop;
#[cfg(target_os = "windows")]
pub mod monitor_devnode;
/// Cross-crate "topology churn in flight" latch (pure std — no Windows surface, so unconditionally
/// compiled and unit-tested on every platform).
pub mod topology_churn;
#[cfg(target_os = "windows")]
pub mod win_display;
/// `Some((own_session, console_session))` when this process is NOT in the active console session —
/// the state where every `SetDisplayConfig`/CDS write fails `ERROR_ACCESS_DENIED`, GDI reads
/// describe the wrong session's displays, and input compose kicks go nowhere (the lid-closed /
/// non-console field failure mode). The IDD-push capturer uses it to phrase a diagnostic when the
/// driver won't attach. (A byte-copy of the host's `interactive::console_session_mismatch`: it lives
/// here too so `pf-capture` gets it as a leaf peer instead of reaching into the orchestrator.)
#[cfg(target_os = "windows")]
pub fn console_session_mismatch() -> Option<(u32, u32)> {
use windows::Win32::System::RemoteDesktop::{
ProcessIdToSessionId, WTSGetActiveConsoleSessionId,
};
use windows::Win32::System::Threading::GetCurrentProcessId;
let mut own: u32 = 0;
// SAFETY: `own` is a live local out-param for this synchronous call; no pointer escapes it.
if unsafe { ProcessIdToSessionId(GetCurrentProcessId(), &mut own) }.is_err() {
return None;
}
// SAFETY: takes no arguments and returns the console session id by value.
let console = unsafe { WTSGetActiveConsoleSessionId() };
(console != 0xFFFF_FFFF && own != console).then_some((own, console))
}