fix(windows-host): IDD-push resilience — driver-death recovery, reopenable control device, full interface discovery
Batch A of the audit's medium tier (M1+M2+M3): - M1 driver-death detection: a dead WUDFHost stops publishing, which at the ring is indistinguishable from an idle desktop — SDR sessions streamed a frozen frame forever (next_frame's 20 s bail is unreachable once anything presented). The ChannelBroker's process handle now doubles as a liveness probe (SYNCHRONIZE at OpenProcess); while no fresh frame arrives, try_consume polls it (rate-limited) and fails the capturer, landing in the session's bounded in-place rebuild. - M2 reopenable control device: the manager's OnceLock-cached handle is now a retire/reopen DeviceSlot — a gone-classified IOCTL failure (driver upgrade / WUDFHost restart; pinger, create, or REMOVE) retires the handle and the next use reopens + re-handshakes. Retired handles are deliberately kept alive forever: bare-HANDLE holders (pinger, ChannelBroker) rely on never-closed, and a retired handle only fails IOCTLs. CLEAR_ALL runs on the FIRST open only (a reopen races live-ish sessions); acquire retries the monitor create once after a reopen. The JOIN path now probes the active monitor's WUDFHost pid and preempts a DEAD monitor instead of handing the rebuilding session its stale target — without this the whole recovery chain starved to the rebuild budget. - M3 interface discovery: enumerate ALL interface instances with an SPINT_ACTIVE filter (a Code-10 devnode at index 0 no longer shadows the live interface), HDEVINFO behind RAII (error paths leaked one per probe), the raw device handle wrapped before GET_INFO (leaked on handshake failure), and the detail-sizing result guarded before the cbSize write. - pf-driver-proto: SetFrameChannelRequest doc now states the real adopt-on-success contract (the old wording invited a driver-side close-on-error — a cross-process double-close against the host's reap). - install: pf_vdisplay_present() passes /connected so a phantom devnode can't suppress creating a live ROOT node. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -324,10 +324,17 @@ fn read_inf_text(path: &Path) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Is a punktfunk virtual-display device already enumerated? Matches the device ID / description, which
|
||||
/// Is a punktfunk virtual-display device already enumerated AND connected? `/connected` is
|
||||
/// load-bearing: without it a PHANTOM (disconnected) devnode left by an earlier uninstall satisfies
|
||||
/// this check, the install skips creating a live ROOT node, and every session then fails "driver not
|
||||
/// installed" (the host enumerates present devices only). Matches the device ID / description, which
|
||||
/// are NOT localized, so the substring check is locale-safe.
|
||||
fn pf_vdisplay_present() -> bool {
|
||||
let lo = run_capture("pnputil", &["/enum-devices", "/class", "Display"]).to_ascii_lowercase();
|
||||
let lo = run_capture(
|
||||
"pnputil",
|
||||
&["/enum-devices", "/connected", "/class", "Display"],
|
||||
)
|
||||
.to_ascii_lowercase();
|
||||
lo.contains("pf_vdisplay") || lo.contains("punktfunk virtual display")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user