fix(packaging/windows): Windows 11 22H2 floor + tray install task + stale console-port fixes
The OS floor is now enforced at install time (MinVersion=10.0.22621 with an explanatory [Messages] override): pf-vdisplay is built against IddCx 1.10, and on Windows 10 (incl. LTSC) / Win11 21H2 the device fails start with Code 10 STATUS_DEVICE_POWER_FAILURE (field-reported). Docs (site requirements/install/ windows-host pages + README) state the floor; new docs-site Security page. Installer also gains the trayicon task (punktfunk-tray.exe file + HKLM Run key, post-install launch as the signed-in user, upgrade taskkill + uninstall --quit/taskkill choreography before file deletion), and the wizard/cleanup text/port sweeps move off the stale :3000 web-console references to :47992 (cleanups sweep both for upgrades from old installs). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -49,7 +49,7 @@ protocol, FEC, and crypto, linked into the host and every client over a stable C
|
||||
| **Core** — `punktfunk-core` + C ABI (protocol · FEC · crypto · QUIC) | ✅ Complete & hardened |
|
||||
| **GameStream host** → stock Moonlight | ✅ Live end-to-end: pairing, RTSP, audio, per-client virtual output at native resolution, GPU zero-copy NVENC, gamepads |
|
||||
| **Native protocol** — `punktfunk/1` | ✅ Validated live: QUIC control + GF(2¹⁶) FEC/AES-GCM data plane, PIN pairing, mDNS discovery, mid-stream mode renegotiation |
|
||||
| **Windows host** (x64) | 🟡 Implemented & shipping as a signed installer: DXGI/WGC capture · its own all-Rust IddCx **virtual display** (secure-desktop capable) · GPU encode (NVENC on NVIDIA, AMF/QSV on AMD/Intel, software H.264 without a GPU) · WASAPI audio · bundled virtual-gamepad drivers (no ViGEmBus) · HDR incl. Vulkan-game HDR. NVIDIA live-validated; AMD/Intel CI-green |
|
||||
| **Windows host** (Windows 11 22H2+, x64) | 🟡 Implemented & shipping as a signed installer: DXGI/WGC capture · its own all-Rust IddCx **virtual display** (secure-desktop capable) · GPU encode (NVENC on NVIDIA, AMF/QSV on AMD/Intel, software H.264 without a GPU) · WASAPI audio · bundled virtual-gamepad drivers (no ViGEmBus) · HDR incl. Vulkan-game HDR. NVIDIA live-validated; AMD/Intel CI-green |
|
||||
| **macOS / iOS / tvOS client** (`clients/apple`) | ✅ Streaming live: VideoToolbox decode, controllers incl. DualSense, discovery, pairing, speed test |
|
||||
| **Linux client** (`clients/linux`, GTK4) | ✅ Streaming live: FFmpeg + VAAPI zero-copy decode, PipeWire audio, SDL3 controllers; ships as Flatpak/apt/rpm/Arch |
|
||||
| **Android client** (`clients/android`, phone + TV) | ✅ Streaming live: AMediaCodec decode + HDR10, AAudio audio, controllers, discovery, pairing |
|
||||
@@ -82,7 +82,7 @@ Windows host also ships as a signed installer (all-vendor: NVIDIA, AMD, Intel).
|
||||
| **Ubuntu / Debian** (apt) | `sudo apt install punktfunk-host` *(after adding the repo)* | [Ubuntu — GNOME](https://docs.punktfunk.unom.io/docs/ubuntu-gnome) · [KDE](https://docs.punktfunk.unom.io/docs/ubuntu-kde) |
|
||||
| **Fedora / Bazzite** (rpm-ostree) | `rpm-ostree install punktfunk punktfunk-web` *(or the bootc image)* | [Fedora — KDE](https://docs.punktfunk.unom.io/docs/fedora-kde) · [Bazzite](https://docs.punktfunk.unom.io/docs/bazzite) |
|
||||
| **Arch / Steam Deck** (PKGBUILD / sysext) | `makepkg -si` *(Arch)* · sysext `.raw` *(SteamOS)* | [packaging/arch](packaging/arch/README.md) |
|
||||
| **Windows** (x64) | signed `setup.exe` from the package registry | [Windows Host](https://docs.punktfunk.unom.io/docs/windows-host) |
|
||||
| **Windows** (11 22H2+, x64) | signed `setup.exe` from the package registry | [Windows Host](https://docs.punktfunk.unom.io/docs/windows-host) |
|
||||
|
||||
`punktfunk-host` is the streaming host; `punktfunk-web` is the browser console (pairing + status).
|
||||
After install, run `punktfunk-host serve` inside your desktop session (the secure native default;
|
||||
|
||||
@@ -45,7 +45,10 @@ interactive session for secure-desktop capture (why MSIX is unusable - see
|
||||
| `packaging/windows/drivers/pf-dualsense/` `pf-xusb/` | `build-gamepad-drivers.ps1` (sign the workspace build) | `pf_{dualsense,xusb}.{dll,inf,cat}` + shared `.cer` |
|
||||
| `packaging/windows/pf-vkhdr-layer/` | `pack-host-installer.ps1` (`cargo build --release`) | `pf_vkhdr_layer.dll` + `.json` |
|
||||
| `web/` | `scripts/windows/build-web.ps1` (`bun run build`) | self-contained `.output` |
|
||||
| `packaging/windows/nvenc/nvenc.def` | `gen-nvenc-importlib.ps1` (llvm-dlltool) | `nvencodeapi.lib` (link import, no GPU/SDK) |
|
||||
|
||||
(NVENC needs no build artifact: its entry points are resolved at runtime from the driver's
|
||||
`nvEncodeAPI64.dll` — a link-time import would prevent the all-vendor exe from starting on
|
||||
AMD/Intel-only machines.)
|
||||
|
||||
## 3. The driver workspace - `packaging/windows/drivers/`
|
||||
|
||||
@@ -118,8 +121,9 @@ needs, on the runner:
|
||||
to the runner default). *History:* LLVM 21.1.2 was briefly pinned (`C:\llvm-21`) to dodge a
|
||||
bindgen-0.71 layout-test overflow on clang 22; the 0.72 bump retired that pin, so there's now one
|
||||
toolchain for both driver builds (the pack and `windows-drivers.yml`).
|
||||
- NVENC import lib synthesised from a 2-export `.def` via `llvm-dlltool` (`gen-nvenc-importlib.ps1`) -
|
||||
no GPU or NVIDIA SDK at build time.
|
||||
- NVENC needs nothing at build time: the entry points are runtime-loaded from the driver's
|
||||
`nvEncodeAPI64.dll` (`encode/windows/nvenc.rs` `load_api`). A link-time import would stop the
|
||||
all-vendor exe from even starting on AMD/Intel-only machines.
|
||||
- `FFMPEG_DIR` (the BtbN gpl-shared x64 tree) for the AMD/Intel AMF/QSV link; NASM + CMake +
|
||||
`CMAKE_POLICY_VERSION_MINIMUM=3.5` for the CMake-from-source deps (aws-lc, opus).
|
||||
- **Gotcha:** `CARGO_HOME` must be an ASCII path (a non-ASCII username breaks SDL3's MSVC precompiled
|
||||
@@ -143,6 +147,13 @@ tasks** (all default-checked): install the pf-vdisplay driver, install the gamep
|
||||
HDR Vulkan layer, start the service. Silent install: `/VERYSILENT` (omit a task with
|
||||
`/MERGETASKS="!installdriver"`).
|
||||
|
||||
**OS floor: Windows 11 22H2 (build 22621)** — `MinVersion=10.0.22621`, with a `[Messages]
|
||||
WinVersionTooLowError` override naming the requirement. pf-vdisplay is built against **IddCx 1.10**
|
||||
(the 1.10 `IddCxStub`, HDR `*2` DDIs, FP16 caps; no runtime `IddCxGetVersion` downgrade), which first
|
||||
shipped in Windows 11 22H2 — on Windows 10 (incl. LTSC) / Windows 11 21H2 the driver package installs
|
||||
but the device fails start with Code 10 `STATUS_DEVICE_POWER_FAILURE` (field-reported on Windows 10
|
||||
LTSC, 2026-07). The installer gate turns that late failure into an upfront message.
|
||||
|
||||
Install-time work runs from `punktfunk-host.exe` subcommands, **not** locale-parsed PowerShell *files* -
|
||||
the `[Run]` section calls `driver install [--gamepad] --dir <stage>` and `web setup --app-dir <app>
|
||||
[--password-file <f>]` (`crates/punktfunk-host/src/windows/install.rs`). This is the ANSI-codepage
|
||||
|
||||
@@ -82,12 +82,18 @@ query.
|
||||
|
||||
**IDD-push is the universal primary path.** Capture comes straight from the driver's shared keyed-mutex
|
||||
texture ring (`capture/windows/idd_push.rs`) — no Desktop Duplication, no `win32u` reparenting hook. The
|
||||
host creates the ring; the driver opens it (permissive `D:(A;;GA;;;WD)` SDDL). The generation-tagged
|
||||
`latest = gen<<40 | seq<<8 | slot` stale-ring reject kills the HDR-flip garbage frame; a host-owned
|
||||
3-slot `OUT_RING` rotated per frame is the texture-ownership contract that enables `pipeline_depth=2`
|
||||
(convert/copy on the 3D engine overlapping NVENC on the ASIC). It captures the **secure desktop**
|
||||
(Winlogon/UAC/lock) directly (validated 2026-06-25), so there is no separate secure capturer in the
|
||||
primary path.
|
||||
host creates the ring as a **sealed channel** (proto v2, `design/idd-push-security.md`): the header,
|
||||
frame-ready event, and ring textures are **unnamed** (nothing to enumerate, open by name, or squat), and
|
||||
the host `DuplicateHandle`s them into the driver's WUDFHost and delivers the handle *values* over the
|
||||
SYSTEM+admins-only control device (`IOCTL_SET_FRAME_CHANNEL`), so only the two endpoint processes can
|
||||
ever reach a frame — DDA's isolation property in user mode. (The objects keep a `D:(A;;GA;;;SY)(A;;GA;;;LS)`
|
||||
DACL as defense-in-depth; it is no longer the isolation boundary. This supersedes the earlier named-ring
|
||||
scheme, which was world-openable `Global\pfvd-*` (`D:(A;;GA;;;WD)`) then SY+LS-scoped.) The
|
||||
generation-tagged `latest = gen<<40 | seq<<8 | slot` stale-ring reject kills the HDR-flip garbage frame;
|
||||
a host-owned 3-slot `OUT_RING` rotated per frame is the texture-ownership contract that enables
|
||||
`pipeline_depth=2` (convert/copy on the 3D engine overlapping NVENC on the ASIC). It captures the
|
||||
**secure desktop** (Winlogon/UAC/lock) directly (validated 2026-06-25), so there is no separate secure
|
||||
capturer in the primary path.
|
||||
|
||||
- **Open-time fallback:** `IddPushCapturer::open` waits a bounded ~4 s for a *first frame* (not just
|
||||
`DRV_STATUS_OPENED`); on attach failure it returns the keepalive back so `capture.rs` opens **DDA** on
|
||||
@@ -120,10 +126,12 @@ loss-recovery by query (only Windows direct-NVENC overrides it; the GameStream l
|
||||
### 2.5 Host↔driver ABI & the `pf-vdisplay` driver
|
||||
|
||||
`pf-driver-proto` is one `no_std` crate in both build graphs. It owns the **frame plane** (`FrameToken`
|
||||
+ `Global\pfvd-*` names), the **control plane** (a fresh interface GUID — *not* SudoVDA's `e5bcc234`;
|
||||
contiguous `0x900` IOCTL ops; a `GET_INFO` version handshake the host **asserts** + bails on mismatch),
|
||||
and the **gamepad SHM** (`XusbShm`/`PadShm` incl. `device_type`). `bytemuck`-`Pod` + `size_of` **and**
|
||||
`offset_of!` asserts make ABI drift a **compile error**.
|
||||
+ `SharedHeader`; since proto v2 the frame objects are **unnamed** — no `Global\pfvd-*` names — and are
|
||||
delivered by handle duplication over `IOCTL_SET_FRAME_CHANNEL`, the *sealed channel*:
|
||||
`design/idd-push-security.md`), the **control plane** (a fresh interface GUID — *not* SudoVDA's
|
||||
`e5bcc234`; contiguous `0x900` IOCTL ops; a `GET_INFO` version handshake the host **asserts** + bails on
|
||||
mismatch), and the **gamepad SHM** (`XusbShm`/`PadShm` incl. `device_type`). `bytemuck`-`Pod` +
|
||||
`size_of` **and** `offset_of!` asserts make ABI drift a **compile error**.
|
||||
|
||||
The driver (`packaging/windows/drivers/pf-vdisplay/src/`) is an all-Rust UMDF IddCx driver on
|
||||
`windows-drivers-rs` + the `iddcx` `wdk-sys` subset; the STEP 0–8 build is the checklist in §6.3, its
|
||||
@@ -200,8 +208,10 @@ These are expensive empirical wins; keep them intact when touching the code:
|
||||
the hot-loop `KeyedMutexGuard`, and the driver's `pod_init!`; all box-validated, clean `sc stop` in
|
||||
~1 s). The driver already has the deny. Revisit D1-host as a final discipline pass (staged per-module)
|
||||
if desired.
|
||||
5. **M6 scaffolding cleanup** — delete the bring-up diagnostics (`spawn_observer`/`DebugBlock` in
|
||||
`idd_push.rs`) and, once full parity is proven on glass, the host monoliths.
|
||||
5. **M6 scaffolding cleanup** — the bring-up diagnostics (`spawn_observer`/`DebugBlock` in
|
||||
`idd_push.rs`) were deleted with the sealed-channel change (they were the last fixed-name
|
||||
`Global\` objects on the frame path); once full parity is proven on glass, the host monoliths
|
||||
remain.
|
||||
|
||||
**Explicitly NOT doing (stability decision): E1 — driver `DeviceContext` ownership + per-`IDDCX_MONITOR`
|
||||
`EvtCleanupCallback`.** The current process-global design is *sound*: IddCx DDIs receive only an
|
||||
@@ -260,7 +270,7 @@ Local pre-push checks (this Linux box can't compile the Windows paths):
|
||||
cargo test -p pf-driver-proto # the ABI crate (cross-platform)
|
||||
cargo check -p punktfunk-host # Linux paths; win_* mods are #[cfg(windows)]
|
||||
cargo clippy -p punktfunk-host --all-targets -- -D warnings
|
||||
# Windows host clippy (on the box): PUNKTFUNK_NVENC_LIB_DIR=C:\t\nvenc;
|
||||
# Windows host clippy (on the box; NVENC needs no import lib — runtime-loaded):
|
||||
# cargo clippy -p punktfunk-host --features nvenc --target x86_64-pc-windows-msvc -- -D warnings
|
||||
# Driver build (on the box): cd packaging/windows/drivers; Version_Number=10.0.26100.0;
|
||||
# LIBCLANG_PATH='C:\Program Files\LLVM\bin'; cargo build
|
||||
|
||||
@@ -19,6 +19,9 @@ mid-stream. You flip between Gaming Mode and Desktop with Bazzite's normal Steam
|
||||
> pure desktop machine, [Ubuntu/Fedora KDE](/docs/ubuntu-kde) or [GNOME](/docs/ubuntu-gnome) are
|
||||
> simpler.
|
||||
|
||||
> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of
|
||||
> the machine, so keep it on a trusted LAN or VPN and require pairing.
|
||||
|
||||
## Install
|
||||
|
||||
The host ships as an RPM in punktfunk's **Gitea RPM registry** (public), so a Bazzite / Fedora
|
||||
|
||||
@@ -10,6 +10,9 @@ systemd service and uses KWin to create per-client virtual displays, captured ze
|
||||
> Validated live on **Fedora 44 KDE Plasma** with an RTX 4090: KWin virtual output + full
|
||||
> zero-copy capture. Everything below is the reproducible flow — paste it on a fresh box.
|
||||
|
||||
> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of
|
||||
> the machine, so keep it on a trusted LAN or VPN and require pairing.
|
||||
|
||||
The setup has three parts: **NVIDIA driver** → **host RPM** → **KWin streaming session**.
|
||||
|
||||
## 1. NVIDIA driver (RPM Fusion akmod)
|
||||
|
||||
@@ -6,7 +6,11 @@ description: Install the punktfunk host — on Linux from its package registry,
|
||||
On Linux, the package registries are the real distribution channel. Pick your distro, add the repo, and
|
||||
install with your native package manager. Each row links to the full per-distro guide (add the repo,
|
||||
first-run steps, the web console) — those are the source of truth, so this page doesn't duplicate them.
|
||||
On **Windows** (NVIDIA), the host ships as a signed installer instead — see [Windows](#windows-nvidia).
|
||||
On **Windows**, the host ships as a signed installer instead — see [Windows](#windows).
|
||||
|
||||
> **First, read [Security & Safe Use](/docs/security).** A streaming host is remote control of the
|
||||
> machine. It's built for trusted local networks — don't expose it to the internet, and be thoughtful
|
||||
> about which machine you host on (especially on Windows).
|
||||
|
||||
## Pick your distro
|
||||
|
||||
@@ -26,10 +30,10 @@ tracks new builds automatically.
|
||||
> at the **canary** channel instead (`canary` apt distribution / `*-canary` rpm group). See
|
||||
> [Release Channels](/docs/channels).
|
||||
|
||||
## Windows (NVIDIA)
|
||||
## Windows
|
||||
|
||||
punktfunk also runs as a native host on **Windows 10/11 (x64) with an NVIDIA GPU**, shipped as a
|
||||
signed installer — see [Windows Host](/docs/windows-host) for what it includes and its limitations.
|
||||
punktfunk also runs as a native host on **Windows 11 22H2+ (x64)**, shipped as a signed
|
||||
installer — see [Windows Host](/docs/windows-host) for what it includes and its limitations.
|
||||
|
||||
1. From the [packages page](https://git.unom.io/unom/-/packages) (generic group), download the newest
|
||||
**`punktfunk-host-setup-<ver>.exe`** and its matching **`.cer`**.
|
||||
@@ -53,7 +57,7 @@ fallback without one. More detail — including the CLI `punktfunk-host service
|
||||
|
||||
## What the packages are
|
||||
|
||||
- **`punktfunk-host`** — the streaming host. Install this on your Linux + NVIDIA gaming machine.
|
||||
- **`punktfunk-host`** — the streaming host. Install this on your Linux gaming machine.
|
||||
- **`punktfunk-web`** — the browser management console (pairing + status). Recommended alongside the
|
||||
host; on RPM list it explicitly (`rpm-ostree install punktfunk punktfunk-web`).
|
||||
- **`punktfunk-client`** — the GTK4 desktop client, for streaming *to* a Linux box (also shipped via
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"pages": [
|
||||
"index",
|
||||
"how-it-works",
|
||||
"security",
|
||||
"quickstart",
|
||||
"install",
|
||||
"---Host Setup---",
|
||||
|
||||
@@ -5,16 +5,20 @@ description: From nothing to streaming — set up a host and connect your first
|
||||
|
||||
This is the shortest path to a working stream. Each step links to the details.
|
||||
|
||||
> A streaming host is remote control of the machine, so it's built for **trusted local networks** — keep
|
||||
> it on your LAN or a VPN and don't expose it to the internet. Two minutes on
|
||||
> [Security & Safe Use](/docs/security) before you start is worth it.
|
||||
|
||||
## 1. Set up the host
|
||||
|
||||
On your Linux + NVIDIA machine, follow the guide for your system:
|
||||
On your Linux gaming machine (NVIDIA, AMD, or Intel GPU), follow the guide for your system:
|
||||
|
||||
- [Ubuntu — GNOME](/docs/ubuntu-gnome)
|
||||
- [Ubuntu — KDE Plasma](/docs/ubuntu-kde)
|
||||
- [Fedora — KDE Plasma](/docs/fedora-kde)
|
||||
- [Bazzite — gamescope / Steam](/docs/bazzite)
|
||||
|
||||
Each one covers the NVIDIA driver, the dependencies, and how to build and run the host. Check the
|
||||
Each one covers the GPU driver, the dependencies, and how to build and run the host. Check the
|
||||
[Requirements](/docs/requirements) first if you're not sure your machine is a fit.
|
||||
|
||||
## 2. Start the host
|
||||
|
||||
@@ -20,8 +20,9 @@ environments it supports today, each with its own guide:
|
||||
Other wlroots compositors (Sway/Hyprland) also work but aren't a primary target. If your desktop isn't
|
||||
listed, the host still needs one of these compositor backends to create a virtual display.
|
||||
|
||||
> **Windows host:** punktfunk also runs as a native host on **Windows 10/11 (x64)** — a signed
|
||||
> installer that registers a service and bundles a virtual-display driver. It encodes on NVIDIA
|
||||
> **Windows host:** punktfunk also runs as a native host on **Windows 11 22H2 or newer (x64)** — a
|
||||
> signed installer that registers a service and bundles a virtual-display driver (whose driver-
|
||||
> framework needs make 22H2 the hard floor — Windows 10 is not supported). It encodes on NVIDIA
|
||||
> (NVENC), AMD (AMF), or Intel (QSV), with a software fallback, and is newer than the Linux host; see
|
||||
> [Windows Host](/docs/windows-host).
|
||||
|
||||
@@ -63,10 +64,16 @@ Minimum compositor versions (newer is fine):
|
||||
## Network
|
||||
|
||||
- Host and client on the **same network** — a LAN, or a VPN that puts them on one subnet. punktfunk
|
||||
assumes a trusted local network; it's not built to be exposed to the public internet.
|
||||
assumes a trusted local network; it's **not built to be exposed to the public internet — don't
|
||||
port-forward it.** To stream from outside your home, use a VPN so the remote client is on the same
|
||||
private subnet.
|
||||
- For best results, a wired or fast Wi-Fi link. The host can run a built-in **speed test** to pick a
|
||||
bitrate for your link (see [Configuration](/docs/configuration)).
|
||||
|
||||
> **Before you set up a host, read [Security & Safe Use](/docs/security).** A streaming host is
|
||||
> remote control of the machine — it's important to understand what that exposes, why to keep it on a
|
||||
> trusted network, and how pairing protects you.
|
||||
|
||||
## A client
|
||||
|
||||
You also need something to stream *to* — see [Connect a Client](/docs/clients). There are native
|
||||
|
||||
@@ -91,7 +91,8 @@ session unit — see [Bazzite](/docs/bazzite).
|
||||
|
||||
On Windows the host runs as a `LocalSystem` service that launches into the interactive session, so it
|
||||
captures the secure desktop (UAC / lock screen) and survives reboots with nobody logged in — the same
|
||||
model Sunshine/Apollo use.
|
||||
model Sunshine/Apollo use. Because it runs at that privilege level, keep it on a trusted network and be
|
||||
deliberate about which machine you host on — see [Security & Safe Use](/docs/security).
|
||||
|
||||
The easy path is the **signed installer**: download `punktfunk-host-setup-<ver>.exe` from the package
|
||||
registry ([`punktfunk-host-windows`](https://git.unom.io/unom/-/packages)) and run it. It drops the host
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
---
|
||||
title: Security & Safe Use
|
||||
description: What a streaming host actually exposes, why to keep it on a trusted network, and how punktfunk protects you.
|
||||
---
|
||||
|
||||
Read this before you put a host on a network you don't fully control. punktfunk is built to be secure
|
||||
**on a trusted local network**, and that's the setting we support today. This page is upfront about what
|
||||
a streaming host is, what protects it, and where the honest limits are.
|
||||
|
||||
> **The short version**
|
||||
> - **Keep the host on a network you trust** — your home LAN, or a private VPN that puts host and client
|
||||
> on the same subnet. **Do not port-forward it to the public internet.**
|
||||
> - **A streaming host is remote control of the machine.** Anyone who can stream to it sees the screen
|
||||
> and can move the mouse, type, and act as a controller — the same as sitting at the keyboard.
|
||||
> - **Pairing is the security boundary.** Require pairing (the default), pick a strong console
|
||||
> password, and review your paired devices from time to time.
|
||||
> - **Be thoughtful about *which* machine you run it on** — especially on Windows, where the host runs
|
||||
> with high system privileges so it can do its job. Prefer a dedicated or gaming PC over one holding
|
||||
> your most sensitive data.
|
||||
|
||||
## What a streaming host really is
|
||||
|
||||
Low-latency desktop and game streaming means two things travel over the network: **the screen goes
|
||||
out, and input comes back in.** A paired client doesn't just watch — it drives. Its mouse, keyboard,
|
||||
and controller are injected into the host's desktop, so **for anything it can reach, a streaming client
|
||||
is equivalent to a person sitting at that machine.**
|
||||
|
||||
That's the feature. It's also the risk to understand:
|
||||
|
||||
- The host can capture the **secure desktop** — UAC elevation prompts and the lock screen — so a
|
||||
connected client can see and interact with those too. (This is what lets you unlock and administer a
|
||||
headless box remotely; it's the same capability Sunshine and Apollo provide.)
|
||||
- Injected input isn't sandboxed to a game. Whoever is streaming can alt-tab, open a terminal, read
|
||||
files, or change settings — whatever the logged-in session can do.
|
||||
|
||||
This is true of **every** remote-access and game-streaming tool, not just punktfunk. The takeaway isn't
|
||||
"don't use it" — it's "treat access to your host the way you'd treat handing someone your unlocked
|
||||
keyboard." The rest of this page is about making sure only people you intend can get that access.
|
||||
|
||||
## Keep it on a trusted network
|
||||
|
||||
**punktfunk assumes a trusted local network. It is not designed, tested, or hardened to be exposed to
|
||||
the public internet — do not port-forward it.** There is no WAN-hardening story yet: no rate-limited
|
||||
public authentication gateway, no DDoS protection, no assumption that hostile traffic is constantly
|
||||
probing the ports. Exposing the streaming ports directly to the internet puts an interactive
|
||||
control surface for your machine in front of the entire world.
|
||||
|
||||
If you want to stream from outside your home, tunnel in instead of opening up:
|
||||
|
||||
- **Use a VPN** — WireGuard, Tailscale, or your router's built-in VPN. This puts your remote client on
|
||||
the *same private subnet* as the host, so from punktfunk's point of view it's still a local
|
||||
connection, and the tunnel (not punktfunk) handles internet-facing authentication and encryption.
|
||||
Discovery, pairing, and streaming then work exactly as they do at home.
|
||||
- **Don't** map a router port to the host. A port-forward turns "trusted LAN service" into
|
||||
"internet-facing service" with none of the protections that implies.
|
||||
|
||||
A note for **portable machines**: the installer opens the streaming ports on the firewall for *all*
|
||||
network profiles, including Public. That's convenient at home but means that if you take a laptop host
|
||||
onto an untrusted network — a café, a hotel, a conference — other devices on that network can reach the
|
||||
ports and attempt to pair. Pairing still protects you (an attacker who doesn't know the PIN can't get
|
||||
in), but the safest habit is to stop the host service, or firewall it off, when you're on a network you
|
||||
don't control.
|
||||
|
||||
## What actually protects you
|
||||
|
||||
punktfunk has **no accounts and no cloud**. Trust is established directly, device-to-device, and then
|
||||
pinned. The layers, from the outside in:
|
||||
|
||||
- **Pairing is required by default.** A new device can't stream until it completes a one-time
|
||||
**PIN pairing ceremony** (SPAKE2): the host shows a 4-digit PIN, you enter it on the client, and the
|
||||
exchange cryptographically binds both identities. An attacker who doesn't know the PIN gets a
|
||||
*single online guess* — no offline cracking, no dictionary attack. See
|
||||
[Pairing & Trust](/docs/pairing).
|
||||
- **Identities are pinned.** After pairing, the client remembers the host's certificate fingerprint and
|
||||
the host stores the client's. Reconnects are automatic and mutually authenticated; if a host's
|
||||
fingerprint ever changes, the client refuses to auto-trust it and forces re-pairing.
|
||||
- **The admin surface is loopback-only.** The management API's read-only status is reachable by paired
|
||||
clients over the LAN (authenticated by their certificate), but every state-changing action — arming
|
||||
pairing, removing devices, session control — is honored **only from the local machine** (the web
|
||||
console connects over loopback). It is never exposed to the network.
|
||||
- **The web console has its own password.** On Windows it's set during install (a strong random default)
|
||||
and stored readable only by Administrators and SYSTEM.
|
||||
|
||||
**GameStream / Moonlight compatibility is the weak-crypto path — trusted LAN only.** To interoperate
|
||||
with stock Moonlight clients, punktfunk can speak the legacy GameStream protocol, which pairs over
|
||||
plain HTTP and uses older encryption. It is **opt-in** (`serve --gamestream`) and appropriate only on a
|
||||
network you fully trust. The default native `punktfunk/1` protocol is the secure path (modern AEAD
|
||||
crypto, pinned identities); leave GameStream off unless you specifically need Moonlight.
|
||||
|
||||
## Choosing which machine to host on
|
||||
|
||||
We've put real work into hardening the host — sealed capture and gamepad channels, no kernel drivers,
|
||||
loopback-gated admin, pinned trust — and we'll keep at it. But security is also about *blast radius*:
|
||||
if a host is ever compromised, or you misconfigure trust, what does the attacker get? So pick the
|
||||
machine with that in mind.
|
||||
|
||||
### The Windows host runs with high privileges
|
||||
|
||||
To capture the secure desktop (UAC, lock screen) and stream across reboots with nobody logged in, the
|
||||
Windows host installs a service that runs as **`LocalSystem` (SYSTEM)** — the highest local privilege on
|
||||
Windows. This is the same design Sunshine and Apollo use, and it's what makes headless, log-in-optional
|
||||
streaming possible. It also means the host is a high-value component: a compromise of the host, or a
|
||||
device you paired that you shouldn't have, is a foothold at the most powerful level of that machine.
|
||||
|
||||
We mitigate this deliberately:
|
||||
|
||||
- **Zero kernel drivers.** The virtual display and all three virtual gamepads are **user-mode (UMDF)**
|
||||
drivers, so a driver bug is contained to a restricted service account — never ring-0, never
|
||||
full-system. (This is why punktfunk dropped ViGEmBus.)
|
||||
- **Sealed internal channels.** The desktop-frame ring and the gamepad input/output channels are
|
||||
passed between the host and its drivers as duplicated handles to unnamed objects, so another local
|
||||
service can't open them by name to read your screen or forge controller input. (Details:
|
||||
[`idd-push-security.md`](https://git.unom.io/unom/punktfunk/src/branch/main/design/idd-push-security.md)
|
||||
and [`gamepad-channel-sealing.md`](https://git.unom.io/unom/punktfunk/src/branch/main/design/gamepad-channel-sealing.md).)
|
||||
- **Secrets are locked down.** The management token, the host identity key, and the console password
|
||||
are stored with Administrators/SYSTEM-only permissions.
|
||||
|
||||
**The honest floor still applies.** None of this defends against an attacker who is *already* an
|
||||
administrator or SYSTEM on the box — at that level they own the machine regardless of punktfunk. And a
|
||||
virtual display is a real monitor: any process already running in your desktop session can capture it
|
||||
through the ordinary OS screen-capture APIs, exactly as it could capture a physical monitor. That floor
|
||||
is the same for every virtual-display streaming stack.
|
||||
|
||||
**Recommendation:** run the Windows host on a **dedicated or gaming PC**, not on a machine that also
|
||||
holds your most sensitive material (work laptop, financial records, the box with your password vault).
|
||||
A gaming rig you stream from is a great fit; your primary secrets machine is not.
|
||||
|
||||
### The Linux host runs as your desktop user
|
||||
|
||||
The Linux host runs inside your normal desktop session as your **regular user account**, not root — so a
|
||||
worst-case compromise is scoped to that user rather than the whole system. The same network guidance
|
||||
applies: keep it on a trusted LAN or a VPN, require pairing, and don't expose it to the internet.
|
||||
|
||||
## A short hardening checklist
|
||||
|
||||
- **Require pairing** — it's the default; don't run `--open` / `--allow-tofu` except on a network you
|
||||
fully trust and control.
|
||||
- **Use a strong console password** and keep it out of shared documents.
|
||||
- **Stay on a trusted network** — LAN or VPN. Never port-forward to the internet.
|
||||
- **Leave GameStream off** unless you specifically need Moonlight compatibility.
|
||||
- **Review paired devices** in the web console periodically; remove anything you don't recognize.
|
||||
- **Keep the host updated** — security fixes ship in new builds.
|
||||
- **On portable hosts**, stop the service when you're on an untrusted network.
|
||||
|
||||
## For the technically curious
|
||||
|
||||
The deeper security design lives in the repository, and it's candid about residual limits:
|
||||
|
||||
- [`design/idd-push-security.md`](https://git.unom.io/unom/punktfunk/src/branch/main/design/idd-push-security.md) — the sealed frame channel (why the Windows capture path is isolated), and its honest floor.
|
||||
- [`design/gamepad-channel-sealing.md`](https://git.unom.io/unom/punktfunk/src/branch/main/design/gamepad-channel-sealing.md) — the sealed gamepad channel.
|
||||
- [`design/security-review-2026-06-28.md`](https://git.unom.io/unom/punktfunk/src/branch/main/design/security-review-2026-06-28.md) and [`design/security-review.md`](https://git.unom.io/unom/punktfunk/src/branch/main/design/security-review.md) — the standing security reviews.
|
||||
|
||||
Found a security issue? Please report it privately rather than opening a public issue.
|
||||
@@ -12,6 +12,9 @@ desktop-class SteamOS box is a natural always-on streaming host. The **Steam Dec
|
||||
device we can test on today, so it's what these instructions are validated against; the same
|
||||
on-device build works on any SteamOS 3 system.
|
||||
|
||||
> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of
|
||||
> the machine, so keep it on a trusted LAN or VPN and require pairing.
|
||||
|
||||
SteamOS is an immutable, read-only Arch base, so the host isn't a system package. Instead a single
|
||||
script builds the host **natively inside a Debian-trixie distrobox** (ABI-matched to SteamOS's
|
||||
FFmpeg/glibc — the binary then runs natively on SteamOS) and wires it up as systemd user services.
|
||||
|
||||
@@ -73,6 +73,17 @@ Then log out and back in. On other distros this is `sudo usermod -aG input $USER
|
||||
concurrent native sessions (up to 4 by default); heavy load is usually bitrate-bound, so
|
||||
lower the bitrate first.
|
||||
|
||||
## Windows: "punktfunk Virtual Display" shows Code 10 in Device Manager
|
||||
|
||||
Sessions end with *"pf-vdisplay driver interface not found"* and Device Manager shows the
|
||||
**punktfunk Virtual Display** device failed with **Code 10** (`STATUS_DEVICE_POWER_FAILURE`).
|
||||
|
||||
This means your Windows version is too old. The virtual-display driver requires the **IddCx 1.10**
|
||||
driver framework, which first shipped in **Windows 11 22H2 (build 22621)** — on Windows 10
|
||||
(including LTSC) and Windows 11 21H2 the driver installs but cannot start. Reinstalling won't help;
|
||||
the fix is updating to Windows 11 22H2 or newer. (Current installers refuse to run on older
|
||||
Windows for this reason; if you see this, the host was likely installed with an older installer.)
|
||||
|
||||
## Still stuck?
|
||||
|
||||
Run the host with `RUST_LOG=info` (or `debug`) and check `journalctl --user -u punktfunk-host` for the
|
||||
|
||||
@@ -6,7 +6,9 @@ description: Set up a punktfunk host on Ubuntu with the GNOME desktop (Mutter).
|
||||
Set up a punktfunk host on **Ubuntu** (Desktop or Server) running **GNOME**. The host uses GNOME's
|
||||
Mutter compositor to create a per-client virtual display. Tested on Ubuntu 24.04+ and GNOME 48+.
|
||||
|
||||
> New to this? Skim [Requirements](/docs/requirements) first.
|
||||
> New to this? Skim [Requirements](/docs/requirements) first, and read
|
||||
> [Security & Safe Use](/docs/security) — a streaming host is remote control of the machine, so keep it
|
||||
> on a trusted LAN or VPN and require pairing.
|
||||
|
||||
## 1. NVIDIA driver
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@ description: Set up a punktfunk host on Ubuntu with KDE Plasma (KWin).
|
||||
Set up a punktfunk host on **Ubuntu** running **KDE Plasma**. The host uses KDE's KWin compositor to
|
||||
create a per-client virtual display. Needs **KWin 6.5.6 or newer**.
|
||||
|
||||
> New to this? Skim [Requirements](/docs/requirements) first.
|
||||
> New to this? Skim [Requirements](/docs/requirements) first, and read
|
||||
> [Security & Safe Use](/docs/security) — a streaming host is remote control of the machine, so keep it
|
||||
> on a trusted LAN or VPN and require pairing.
|
||||
|
||||
## 1. NVIDIA driver
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Windows Host"
|
||||
description: "Run the Punktfunk streaming host on a Windows PC — a first-class, all-vendor, virtual-display host."
|
||||
---
|
||||
|
||||
Set up a Punktfunk host on a **Windows 10/11 PC** and stream its desktop or games to any Punktfunk or
|
||||
Set up a Punktfunk host on a **Windows 11 PC (22H2 or newer)** and stream its desktop or games to any Punktfunk or
|
||||
[Moonlight](/docs/moonlight) client. A signed installer registers a Windows service that streams at the
|
||||
client's **exact resolution and refresh** via Punktfunk's own **virtual display** — including
|
||||
**HDR10** (10-bit BT.2020 PQ) when your Windows desktop is in HDR mode. The virtual display is created
|
||||
@@ -12,13 +12,22 @@ the secure desktop (UAC prompts, the lock screen).
|
||||
|
||||
> New to this? Skim [Requirements](/docs/requirements) first.
|
||||
|
||||
> **Read [Security & Safe Use](/docs/security) before you set this up.** The Windows host runs as a
|
||||
> `LocalSystem` service (so it can capture the secure desktop and stream headless), which makes it a
|
||||
> high-privilege component — keep it on a trusted network, never expose it to the internet, and prefer
|
||||
> a dedicated or gaming PC over a machine that holds your most sensitive data.
|
||||
|
||||
> This page is about the Windows **host** — streaming *from* a Windows PC. To stream *to* a Windows PC,
|
||||
> see the [Windows client](/docs/clients#windows-desktop-client).
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Windows 10 or 11, x64.** ARM64 is not built (no ARM64 NVIDIA driver, and the virtual-display
|
||||
driver is x64-only).
|
||||
- **Windows 11 22H2 (build 22621) or newer, x64.** Windows 10 — including LTSC — and Windows 11
|
||||
21H2 are **not supported**: the virtual-display driver needs the IddCx 1.10 driver framework,
|
||||
which first shipped in Windows 11 22H2. On older Windows the driver installs but can't start
|
||||
("punktfunk Virtual Display" shows **Code 10** in Device Manager and streaming fails); the
|
||||
installer therefore refuses to run there. ARM64 is not built either (no ARM64 NVIDIA driver, and
|
||||
the virtual-display driver is x64-only).
|
||||
- **A GPU for hardware encode** — the host auto-detects the vendor:
|
||||
- **NVIDIA** → NVENC
|
||||
- **AMD** → AMF
|
||||
@@ -96,6 +105,13 @@ prompts, the lock screen) and keep streaming across reboots with nobody logged i
|
||||
Sunshine and Apollo use. Service registration, firewall rules, and the supervisor all live in
|
||||
`punktfunk-host service install`; the installer just lays the exe down and calls it elevated.
|
||||
|
||||
Running as SYSTEM is what makes headless, log-in-optional streaming work — and it's why the host is a
|
||||
high-privilege component worth being deliberate about. punktfunk mitigates this with **zero kernel
|
||||
drivers** (the virtual display and gamepads are user-mode UMDF drivers), **sealed internal channels**
|
||||
between the host and its drivers, and Administrators/SYSTEM-only permissions on its secrets. See
|
||||
[Security & Safe Use](/docs/security) for the full picture, including why we recommend not hosting on
|
||||
your most sensitive machine.
|
||||
|
||||
### One core, Windows backends
|
||||
|
||||
Most of Punktfunk is platform-agnostic. `punktfunk-core` (protocol, FEC, crypto, session, transport,
|
||||
|
||||
@@ -5,6 +5,19 @@ generic package registry (`punktfunk-host-windows`) by `.gitea/workflows/windows
|
||||
|
||||
> Full picture (drivers-from-source, toolchain, CI, dev loop): **[`design/windows-build-and-packaging.md`](../../design/windows-build-and-packaging.md)**. This README is the `packaging/windows/` file index.
|
||||
|
||||
## Windows 11 22H2+ only (no Windows 10)
|
||||
|
||||
The installer refuses anything below **Windows 11 22H2 (build 22621)** — `MinVersion=10.0.22621` in
|
||||
`punktfunk-host.iss`, with a `[Messages]` override naming the requirement. The floor comes from the
|
||||
**pf-vdisplay** driver: it is built against the **IddCx 1.10** class extension (the HDR `*2` DDIs +
|
||||
the FP16 adapter cap, linked via the 1.10 `IddCxStub`, no runtime `IddCxGetVersion` downgrade), and
|
||||
IddCx 1.10 first shipped in Windows 11 22H2. On older Windows — **all of Windows 10 including LTSC,
|
||||
and Windows 11 21H2** — the driver *package* installs fine, but the device then fails to start with
|
||||
**Code 10 `STATUS_DEVICE_POWER_FAILURE`** in Device Manager and every session dies with "pf-vdisplay
|
||||
driver interface not found". Gating the installer turns that late, confusing failure into an upfront
|
||||
message. (Down-level SDR-only support would need a runtime IddCx version check in the driver —
|
||||
tracked as a possible future feature, not planned.)
|
||||
|
||||
## x64 only (no ARM64)
|
||||
|
||||
Unlike the client (which ships x64 + ARM64 MSIX), the host is **x64-only by design**. It is coupled to
|
||||
@@ -112,7 +125,6 @@ fresh install uses the generated random console password — read it from
|
||||
| `drivers/` | The all-Rust IddCx **driver source** workspace: the `pf-vdisplay` crate on `wdk-sys` / windows-drivers-rs + the owned `pf-driver-proto` ABI + `wdk-iddcx` / `wdk-probe`, plus `deploy-dev.ps1` (build/sign/install for dev). |
|
||||
| `reset-pf-vdisplay.ps1` | **Dev:** recover a wedged driver — stop host → reap ghost monitor nodes → reload the adapter → start host (no reboot). See *Dev iteration* below. |
|
||||
| `redeploy-pf-vdisplay.ps1` | **Dev:** one-shot redeploy — (optional) build → stop host → `deploy-dev.ps1 -Install` → reload adapter → start host. |
|
||||
| `nvenc/nvenc.def`, `nvenc/gen-nvenc-importlib.ps1` | Synthesise `nvencodeapi.lib` for the `--features nvenc` link (llvm-dlltool / lib.exe). |
|
||||
| `pf-vkhdr-layer/` | **HDR Vulkan layer** (standalone `cdylib`): lets Vulkan games (Doom: The Dark Ages, etc.) enable HDR over the virtual display by advertising the HDR surface formats the NVIDIA/AMD ICDs hide on an indirect display. Built by the packer, laid into `{app}\vklayer`, registered under `HKLM64\…\Khronos\Vulkan\ImplicitLayers` (opt-out *Install the HDR Vulkan layer* task). Self-gated on the display's HDR state. See its README. |
|
||||
|
||||
> **Drivers are built from source, not vendored.** All three (pf-vdisplay + the gamepad pf-dualsense /
|
||||
@@ -154,14 +166,10 @@ the recovery. From a Linux box drive either over SSH, e.g.
|
||||
## Build locally (Windows, MSVC + Windows SDK + Inno Setup)
|
||||
|
||||
```powershell
|
||||
# 1. import lib for the nvenc link
|
||||
pwsh -File packaging\windows\nvenc\gen-nvenc-importlib.ps1 -OutDir C:\t\nvenc
|
||||
$env:PUNKTFUNK_NVENC_LIB_DIR = 'C:\t\nvenc'
|
||||
|
||||
# 2. build the host
|
||||
# 1. build the host (NVENC needs no import lib — its entry points are runtime-loaded)
|
||||
cargo build --release -p punktfunk-host --features nvenc
|
||||
|
||||
# 3. pack (self-signed unless MSIX_CERT_PFX_B64/MSIX_CERT_PASSWORD are set; -NoDriver to skip pf-vdisplay)
|
||||
# 2. pack (self-signed unless MSIX_CERT_PFX_B64/MSIX_CERT_PASSWORD are set; -NoDriver to skip pf-vdisplay)
|
||||
pwsh -File packaging\windows\pack-host-installer.ps1 -Version 0.0.0-dev -TargetDir C:\t\release -OutDir C:\t\out
|
||||
```
|
||||
|
||||
|
||||
@@ -85,7 +85,12 @@ DefaultGroupName=punktfunk
|
||||
DisableProgramGroupPage=yes
|
||||
UsePreviousAppDir=yes
|
||||
PrivilegesRequired=admin
|
||||
MinVersion=10.0
|
||||
; HARD floor: Windows 11 22H2 (build 22621). The pf-vdisplay driver is built against IddCx 1.10
|
||||
; (HDR *2 DDIs + FP16 caps, no runtime downgrade) — on anything older (all of Windows 10 incl.
|
||||
; LTSC, Windows 11 21H2) the driver package installs but the device fails to start with Code 10
|
||||
; STATUS_DEVICE_POWER_FAILURE, and the host can't stream. Gate the install instead; the message
|
||||
; is customized in [Messages] below.
|
||||
MinVersion=10.0.22621
|
||||
ArchitecturesAllowed=x64
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
OutputDir={#OutputDir}
|
||||
@@ -113,6 +118,12 @@ UninstallDisplayIcon={app}\punktfunk.ico
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Messages]
|
||||
; Shown when MinVersion rejects the OS — name the actual requirement instead of Inno's generic
|
||||
; "requires Windows version 10.0.22621" (users on Windows 10 LTSC hit this; see the pf-vdisplay
|
||||
; IddCx 1.10 note at MinVersion above).
|
||||
WinVersionTooLowError=punktfunk host requires Windows 11 22H2 (build 22621) or newer.%n%nIts virtual display driver needs the IddCx 1.10 framework, which is not available on older Windows — including all editions of Windows 10 (LTSC too) and Windows 11 21H2.
|
||||
|
||||
[Tasks]
|
||||
#ifdef WithDriver
|
||||
Name: "installdriver"; Description: "Install the pf-vdisplay virtual display driver (required for native-resolution streaming)"
|
||||
@@ -134,9 +145,16 @@ Name: "installhdrlayer"; Description: "Install the HDR Vulkan layer (lets Vulkan
|
||||
; host (the common Windows setup); unchecked = the secure native-only host (punktfunk clients only).
|
||||
Name: "gamestream"; Description: "Enable GameStream (Moonlight) compatibility - lets stock Moonlight clients connect (uses legacy plain-HTTP pairing; for trusted LANs)"
|
||||
Name: "startservice"; Description: "Start the punktfunk host service now (also starts on every boot)"
|
||||
; The per-user status tray (punktfunk-tray.exe): shows running/stopped/failed at a glance and
|
||||
; offers open-console / start / stop / restart without a terminal. HKLM Run = every user who signs
|
||||
; in to this host box gets one (each session keeps exactly one via a Local\ mutex).
|
||||
Name: "trayicon"; Description: "Show the punktfunk status icon in the notification area at sign-in"
|
||||
|
||||
[Files]
|
||||
Source: "{#BinDir}\punktfunk-host.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
; The status tray companion (windows-subsystem, embeds its own icons). Installed unconditionally
|
||||
; (small); only STARTED/registered when the trayicon task is selected.
|
||||
Source: "{#BinDir}\punktfunk-tray.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "{#HostEnv}"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "{#Readme}"; DestDir: "{app}"; DestName: "README.txt"; Flags: ignoreversion
|
||||
; The branded icon, referenced by UninstallDisplayIcon (Apps & features shows it for the entry).
|
||||
@@ -184,6 +202,10 @@ Source: "{#VkLayerDir}\pf_vkhdr_layer.json"; DestDir: "{app}\vklayer"; Flags: ig
|
||||
#endif
|
||||
|
||||
[Registry]
|
||||
; Auto-start the status tray at sign-in (all users of this host box; uninsdeletevalue removes it
|
||||
; with the app). Operators who moved --mgmt-bind can append --mgmt-addr/--mgmt-port here.
|
||||
Root: HKLM64; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; \
|
||||
ValueName: "PunktfunkTray"; ValueData: """{app}\punktfunk-tray.exe"""; Flags: uninsdeletevalue; Tasks: trayicon
|
||||
#ifdef WithVkLayer
|
||||
; Register the HDR Vulkan implicit layer system-wide. The 64-bit Vulkan loader reads
|
||||
; HKLM64\SOFTWARE\Khronos\Vulkan\ImplicitLayers; the value NAME is the manifest path and the DWORD
|
||||
@@ -222,12 +244,22 @@ Filename: "{app}\punktfunk-host.exe"; Parameters: "service start"; WorkingDir: "
|
||||
#ifdef WithWeb
|
||||
; Provision the console AFTER the host service is up (so the mgmt token exists): write the ACL'd
|
||||
; login password, register the PunktfunkWeb scheduled task (boot, SYSTEM, restart-on-failure),
|
||||
; open TCP 3000, and start it. {code:WebSetupParams} appends -PasswordFile only on a fresh install.
|
||||
; open TCP 47992, and start it. {code:WebSetupParams} appends -PasswordFile only on a fresh install.
|
||||
Filename: "{app}\punktfunk-host.exe"; Parameters: "web setup {code:WebSetupParams}"; WorkingDir: "{app}"; \
|
||||
StatusMsg: "Setting up the punktfunk web console..."; Flags: runhidden waituntilterminated
|
||||
#endif
|
||||
; Launch the status tray as the SIGNED-IN user (not the elevated install user) right away, so the
|
||||
; icon appears without waiting for the next sign-in.
|
||||
Filename: "{app}\punktfunk-tray.exe"; Flags: runasoriginaluser nowait skipifsilent; Tasks: trayicon
|
||||
|
||||
[UninstallRun]
|
||||
; Quit the tray FIRST - it is this exe being deleted, so it must not be running. --quit closes the
|
||||
; current session's instance (an elevated caller may message a medium-IL window; UIPI only blocks
|
||||
; low->high); the taskkill then reaps instances in OTHER signed-in sessions. [UninstallRun] runs
|
||||
; before file deletion, so a raced survivor only means a delete-on-reboot leftover, nothing worse.
|
||||
; (runasoriginaluser is not valid in [UninstallRun] - both entries run elevated, which is fine.)
|
||||
Filename: "{app}\punktfunk-tray.exe"; Parameters: "--quit"; Flags: runhidden waituntilterminated; RunOnceId: "PunktfunkTrayQuit"
|
||||
Filename: "{sys}\taskkill.exe"; Parameters: "/F /IM punktfunk-tray.exe"; Flags: runhidden waituntilterminated; RunOnceId: "PunktfunkTrayKill"
|
||||
Filename: "{app}\punktfunk-host.exe"; Parameters: "service uninstall"; Flags: runhidden waituntilterminated; RunOnceId: "PunktfunkHostServiceUninstall"
|
||||
; Remove the punktfunk drivers we installed (pf-vdisplay devnode + driver package, then the gamepad
|
||||
; driver packages). AFTER service uninstall so the host no longer holds the devices. Unconditional
|
||||
@@ -241,7 +273,7 @@ Filename: "{app}\punktfunk-host.exe"; Parameters: "driver uninstall --gamepad";
|
||||
; Stop + remove the PunktfunkWeb task and its firewall rule (leaves %ProgramData%\punktfunk config,
|
||||
; like the host uninstall does).
|
||||
Filename: "powershell.exe"; \
|
||||
Parameters: "-NoProfile -ExecutionPolicy Bypass -Command ""Stop-ScheduledTask -TaskName PunktfunkWeb -ErrorAction SilentlyContinue; Get-NetTCPConnection -LocalPort 3000 -State Listen -ErrorAction SilentlyContinue | ForEach-Object {{ Stop-Process -Id $_.OwningProcess -Force -ErrorAction SilentlyContinue }; Unregister-ScheduledTask -TaskName PunktfunkWeb -Confirm:$false -ErrorAction SilentlyContinue; Get-NetFirewallRule -DisplayName 'punktfunk web console (*' -ErrorAction SilentlyContinue | Remove-NetFirewallRule"""; \
|
||||
Parameters: "-NoProfile -ExecutionPolicy Bypass -Command ""Stop-ScheduledTask -TaskName PunktfunkWeb -ErrorAction SilentlyContinue; Get-NetTCPConnection -LocalPort 47992,3000 -State Listen -ErrorAction SilentlyContinue | ForEach-Object {{ Stop-Process -Id $_.OwningProcess -Force -ErrorAction SilentlyContinue }; Unregister-ScheduledTask -TaskName PunktfunkWeb -Confirm:$false -ErrorAction SilentlyContinue; Get-NetFirewallRule -DisplayName 'punktfunk web console (*' -ErrorAction SilentlyContinue | Remove-NetFirewallRule"""; \
|
||||
Flags: runhidden waituntilterminated; RunOnceId: "PunktfunkWebCleanup"
|
||||
#endif
|
||||
|
||||
@@ -300,7 +332,7 @@ begin
|
||||
FreshWebInstall := not FileExists(WebPasswordPath);
|
||||
WebPwPage := CreateInputQueryPage(wpSelectTasks,
|
||||
'Web console', 'Set the punktfunk web console login password',
|
||||
'The management console is served on http://this-computer:3000 and is login-gated. Keep the ' +
|
||||
'The management console is served on https://this-computer:47992 and is login-gated. Keep the ' +
|
||||
'secure password generated below (it is shown again on the final page) or enter your own - you ' +
|
||||
'can change it later in %ProgramData%\punktfunk\web-password.');
|
||||
WebPwPage.Add('Console password:', False); { visible, so the admin can read the generated default }
|
||||
@@ -329,7 +361,7 @@ procedure CurPageChanged(CurPageID: Integer);
|
||||
begin
|
||||
if (CurPageID = wpFinished) and FreshWebInstall then
|
||||
WizardForm.FinishedLabel.Caption := WizardForm.FinishedLabel.Caption + #13#10#13#10 +
|
||||
'Web console: http://<this-PC-IP>:3000' + #13#10 +
|
||||
'Web console: https://<this-PC-IP>:47992' + #13#10 +
|
||||
'Login password: ' + Trim(WebPwPage.Values[0]);
|
||||
end;
|
||||
|
||||
@@ -344,6 +376,17 @@ begin
|
||||
end;
|
||||
#endif
|
||||
|
||||
{ On upgrade a running tray locks punktfunk-tray.exe - kill every session's instance so the copy
|
||||
can overwrite it (the [Run] entry / next sign-in relaunches the new build). Best-effort; a fresh
|
||||
install is a no-op. }
|
||||
procedure StopTrays;
|
||||
var
|
||||
ResultCode: Integer;
|
||||
begin
|
||||
Exec(ExpandConstant('{sys}\taskkill.exe'), '/F /IM punktfunk-tray.exe', '',
|
||||
SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||
end;
|
||||
|
||||
{ On upgrade the running service locks punktfunk-host.exe (and the supervisor would respawn it from
|
||||
the OLD binary), so stop it and WAIT for STOPPED before files are copied. Best-effort; a fresh
|
||||
install is a no-op (the service doesn't exist yet). }
|
||||
@@ -361,10 +404,11 @@ begin
|
||||
end;
|
||||
|
||||
#ifdef WithWeb
|
||||
{ Stop a running web console + free :3000 BEFORE the file copy, so the old server doesn't lock
|
||||
.output / web-run.cmd / bun.exe and the new task can bind. Killing the :3000 listener owner is
|
||||
runtime-agnostic (an early install may have run node, the current one runs bun). `web setup`
|
||||
repeats this idempotently after the copy. Best-effort; a fresh install is a no-op. }
|
||||
{ Stop a running web console + free its port BEFORE the file copy, so the old server doesn't lock
|
||||
.output / web-run.cmd / bun.exe and the new task can bind. Killing the listener owner is
|
||||
runtime-agnostic (an early install may have run node on :3000, the current one runs bun on
|
||||
:47992 - sweep both). `web setup` repeats this idempotently after the copy. Best-effort; a
|
||||
fresh install is a no-op. }
|
||||
procedure StopWebConsole;
|
||||
var
|
||||
ResultCode: Integer;
|
||||
@@ -373,7 +417,7 @@ begin
|
||||
'-NoProfile -ExecutionPolicy Bypass -Command "' +
|
||||
'$ErrorActionPreference=''SilentlyContinue''; ' +
|
||||
'Stop-ScheduledTask -TaskName PunktfunkWeb; ' +
|
||||
'Get-NetTCPConnection -LocalPort 3000 -State Listen | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force }"',
|
||||
'Get-NetTCPConnection -LocalPort 47992,3000 -State Listen | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force }"',
|
||||
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||
end;
|
||||
#endif
|
||||
@@ -383,6 +427,7 @@ begin
|
||||
if CurStep = ssInstall then
|
||||
begin
|
||||
StopHostServiceAndWait;
|
||||
StopTrays; { upgrade-safe: unlock punktfunk-tray.exe before the copy }
|
||||
#ifdef WithWeb
|
||||
StopWebConsole; { upgrade-safe: free :3000 + unlock the web files before the copy }
|
||||
{ Stash the chosen password for `web setup` (fresh install only); the temp copy is auto-cleaned. }
|
||||
|
||||
Reference in New Issue
Block a user