From 553676282a67874508e9df111b22c776c38b35cd Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Thu, 30 Jul 2026 12:30:37 +0200 Subject: [PATCH] feat(windows): the brand reads Punktfunk on every device Windows shows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Device Manager, the firewall list and the monitor name all said "punktfunk". The brand is Punktfunk. Renamed: the [Strings] blocks of all four driver INFs (device descriptions, install disks, provider, manufacturer), the `description` on every SwDeviceProfile the host creates, pf-mouse's HID manufacturer + product strings, pf-vdisplay's IddCx endpoint friendly + manufacturer names, the EDID 0xFC display-name descriptor — so Windows now shows `Generic Monitor (Punktfunk)` — and the netsh firewall rule names. The EDID edit is a single byte (0x70 -> 0x50) and needs no hand-patched checksum: Edid::generate_with already recomputes both block checksums after patching the serial. Deliberately left lowercase, because these are IDENTITIES rather than display names and renaming them would orphan installed state: * the SwDeviceCreate enumerator `w!("punktfunk")` — it IS the SWD\PUNKTFUNK\... path every pad instance id is built from * pf-paths' `join("punktfunk")` — C:\ProgramData\punktfunk * the CN=punktfunk-driver cert subject, which purge_driver_certs and both driver build scripts match by string * install.rs' `lo.contains("punktfunk virtual display")` probes, whose haystack is to_ascii_lowercase()d, so they already match the capitalised name Nothing is orphaned by the renames that DID happen either: netsh rule names, Get-NetFirewallRule -DisplayName and PowerShell's -match are all case-insensitive, so the firewall delete paths and reset-pf-vdisplay.ps1's -AdapterName / -GhostMatch defaults still reap what every release up to 0.22.1 created. Cosmetic, with two consequences worth knowing: it takes a driver rebuild + re-sign to appear at all, and an existing devnode keeps its cached FriendlyName until it is recreated. Co-Authored-By: Claude Opus 5 (1M context) --- .../src/inject/windows/dualsense_windows.rs | 6 +++--- .../src/inject/windows/dualshock4_windows.rs | 2 +- .../src/inject/windows/gamepad_windows.rs | 2 +- .../pf-inject/src/inject/windows/mouse_windows.rs | 4 ++-- .../src/inject/windows/steam_deck_windows.rs | 2 +- .../src/vdisplay/windows/pf_vdisplay.rs | 4 ++-- crates/punktfunk-host/src/windows/install.rs | 4 ++-- crates/punktfunk-host/src/windows/service.rs | 6 ++++-- .../windows/drivers/pf-gamepad/pf_gamepad.inx | 14 +++++++------- packaging/windows/drivers/pf-mouse/pf_mouse.inx | 8 ++++---- packaging/windows/drivers/pf-mouse/src/lib.rs | 4 ++-- .../windows/drivers/pf-vdisplay/pf_vdisplay.inx | 6 +++--- .../windows/drivers/pf-vdisplay/src/adapter.rs | 4 ++-- packaging/windows/drivers/pf-vdisplay/src/edid.rs | 6 ++++-- packaging/windows/drivers/pf-xusb/pf_xusb.inx | 6 +++--- packaging/windows/punktfunk-host.iss | 2 +- packaging/windows/reset-pf-vdisplay.ps1 | 12 ++++++------ 17 files changed, 48 insertions(+), 44 deletions(-) diff --git a/crates/pf-inject/src/inject/windows/dualsense_windows.rs b/crates/pf-inject/src/inject/windows/dualsense_windows.rs index c8b936ce..8079b587 100644 --- a/crates/pf-inject/src/inject/windows/dualsense_windows.rs +++ b/crates/pf-inject/src/inject/windows/dualsense_windows.rs @@ -393,7 +393,7 @@ impl WinDsIdentity { // child, no channel proof, and a pad no game ever saw. `hwid_matches_inf` pins it now. hwid: "pf_dualsense", usb_vid_pid: "VID_054C&PID_0CE6", - description: "punktfunk Virtual DualSense", + description: "Punktfunk Virtual DualSense", } } @@ -403,7 +403,7 @@ impl WinDsIdentity { instance_prefix: "pf_edge", hwid: "pf_dualsenseedge", usb_vid_pid: "VID_054C&PID_0DF2", - description: "punktfunk Virtual DualSense Edge", + description: "Punktfunk Virtual DualSense Edge", } } } @@ -644,7 +644,7 @@ pub fn deck_spike_hold(index: u8, secs: u64) -> Result<()> { // The Deck's controller interface — the promotion gate the first spike run hit // (hidapi parses MI_ from the child hwids; absent = interface 0, Steam wants 2). usb_mi: Some(2), - description: "punktfunk Virtual Steam Deck (spike)", + description: "Punktfunk Virtual Steam Deck (spike)", })?; // The spike drives a real pad channel, so it takes the same devnode-proved delivery a session // pad does — no special case, and no reason for a bring-up tool to run on the old trust. diff --git a/crates/pf-inject/src/inject/windows/dualshock4_windows.rs b/crates/pf-inject/src/inject/windows/dualshock4_windows.rs index 9d483eab..29a9667f 100644 --- a/crates/pf-inject/src/inject/windows/dualshock4_windows.rs +++ b/crates/pf-inject/src/inject/windows/dualshock4_windows.rs @@ -73,7 +73,7 @@ impl Ds4WinPad { hwid: DS4_HWID, usb_vid_pid: "VID_054C&PID_09CC", usb_mi: None, - description: "punktfunk Virtual DualShock 4", + description: "Punktfunk Virtual DualShock 4", })?; // Propagate, do NOT swallow — see below. let (hsw, instance_id) = (Some(hsw), instance_id); // Swallowing a create failure here (the previous behaviour) latched the pad slot to diff --git a/crates/pf-inject/src/inject/windows/gamepad_windows.rs b/crates/pf-inject/src/inject/windows/gamepad_windows.rs index f9937c0f..3cfe7803 100644 --- a/crates/pf-inject/src/inject/windows/gamepad_windows.rs +++ b/crates/pf-inject/src/inject/windows/gamepad_windows.rs @@ -56,7 +56,7 @@ fn create_swdevice(index: u8) -> Result<(HSWDEVICE, Option)> { .encode_utf16() .chain(std::iter::once(0)) .collect(); - let desc: Vec = "punktfunk Virtual Xbox 360 (XUSB)" + let desc: Vec = "Punktfunk Virtual Xbox 360 (XUSB)" .encode_utf16() .chain(std::iter::once(0)) .collect(); diff --git a/crates/pf-inject/src/inject/windows/mouse_windows.rs b/crates/pf-inject/src/inject/windows/mouse_windows.rs index ae6b852d..c269ea4e 100644 --- a/crates/pf-inject/src/inject/windows/mouse_windows.rs +++ b/crates/pf-inject/src/inject/windows/mouse_windows.rs @@ -66,7 +66,7 @@ impl VirtualMouse { // a mouse (nothing fingerprints them); reusing the shared profile keeps one code path. usb_vid_pid: "VID_5046&PID_4D4F", usb_mi: None, - description: "punktfunk Virtual Mouse", + description: "Punktfunk Virtual Mouse", }) { Ok((h, i)) => (Some(h), i), Err(e) => { @@ -386,7 +386,7 @@ pub fn channel_proof_probe() -> Result<()> { hwid: "pf_mouse", usb_vid_pid: "VID_5046&PID_4D4F", usb_mi: None, - description: "punktfunk Virtual Mouse (channel-proof probe)", + description: "Punktfunk Virtual Mouse (channel-proof probe)", })?; let _sw = super::gamepad_raii::SwDevice::new(hsw); let Some(instance_id) = instance_id else { diff --git a/crates/pf-inject/src/inject/windows/steam_deck_windows.rs b/crates/pf-inject/src/inject/windows/steam_deck_windows.rs index f2768977..544a7eb9 100644 --- a/crates/pf-inject/src/inject/windows/steam_deck_windows.rs +++ b/crates/pf-inject/src/inject/windows/steam_deck_windows.rs @@ -80,7 +80,7 @@ impl DeckWinPad { // token, hidapi reports interface 0, and Steam never claims the pad (the N4 // spike's run-1 failure). usb_mi: Some(2), - description: "punktfunk Virtual Steam Deck", + description: "Punktfunk Virtual Steam Deck", })?; // Propagate — swallowing latched the slot to a pad with no devnode (see the DS4 twin). let (hsw, instance_id) = (Some(hsw), instance_id); // The DATA section goes to whoever THIS devnode says is serving it — not to whatever pid diff --git a/crates/pf-vdisplay/src/vdisplay/windows/pf_vdisplay.rs b/crates/pf-vdisplay/src/vdisplay/windows/pf_vdisplay.rs index 7a8ae3a9..a165fe99 100644 --- a/crates/pf-vdisplay/src/vdisplay/windows/pf_vdisplay.rs +++ b/crates/pf-vdisplay/src/vdisplay/windows/pf_vdisplay.rs @@ -92,7 +92,7 @@ unsafe fn ioctl(h: HANDLE, code: u32, input: &[u8], output: &mut [u8]) -> Result } /// Reap the ghost (NOT-present) "punktfunk" virtual-monitor device nodes that `IddCxMonitorDeparture` -/// leaves behind. Each departed monitor leaves a not-present "Generic Monitor (punktfunk)" PDO that keeps +/// leaves behind. Each departed monitor leaves a not-present "Generic Monitor (Punktfunk)" PDO that keeps /// pinning an OS VidPN target against the IddCx adapter's fixed monitor-slot budget; once ~16 accumulate, /// `IOCTL_ADD` wedges at 0x80070490 (`ERROR_NOT_FOUND`) and every session black-screens until a manual /// reset/reboot. Removing the not-present PDOs frees the slots — the in-process equivalent of @@ -532,7 +532,7 @@ impl VdisplayDriver for PfVdisplayDriver { tracing::warn!("pf-vdisplay IOCTL_CLEAR_ALL failed on startup (continuing)"); } // CLEAR_ALL only departs the driver's own (in-process) monitor list; it can NOT remove the - // OS-side not-present "Generic Monitor (punktfunk)" PDOs that a previous host-run's monitor + // OS-side not-present "Generic Monitor (Punktfunk)" PDOs that a previous host-run's monitor // departures left behind. Reap those here so a fresh host start begins with a clean IddCx // monitor-slot budget — prevents the 0x80070490 slot-exhaustion wedge from carrying across // restarts (the reason a restart's CLEAR_ALL alone never recovered it before). diff --git a/crates/punktfunk-host/src/windows/install.rs b/crates/punktfunk-host/src/windows/install.rs index c197f5c4..68c5960e 100644 --- a/crates/punktfunk-host/src/windows/install.rs +++ b/crates/punktfunk-host/src/windows/install.rs @@ -471,7 +471,7 @@ fn web_setup(args: &[String]) -> Result<()> { "firewall", "delete", "rule", - "name=punktfunk web console (TCP 47992)", + "name=Punktfunk web console (TCP 47992)", ], ); if !run_quiet( @@ -481,7 +481,7 @@ fn web_setup(args: &[String]) -> Result<()> { "firewall", "add", "rule", - "name=punktfunk web console (TCP 47992)", + "name=Punktfunk web console (TCP 47992)", "dir=in", "action=allow", "protocol=TCP", diff --git a/crates/punktfunk-host/src/windows/service.rs b/crates/punktfunk-host/src/windows/service.rs index ff53a499..2bfcf5ea 100644 --- a/crates/punktfunk-host/src/windows/service.rs +++ b/crates/punktfunk-host/src/windows/service.rs @@ -995,7 +995,7 @@ fn add_firewall_rules(allow_public: bool) { ("UDP", "UDP", "47998-48010,9777,5353"), ]; for (suffix, proto, ports) in rules { - let name = format!("punktfunk {suffix}"); + let name = format!("Punktfunk {suffix}"); let ok = run_quiet( "netsh", &[ @@ -1028,7 +1028,9 @@ fn add_firewall_rules(allow_public: bool) { fn remove_firewall_rules() { for suffix in ["TCP", "UDP"] { - let name = format!("punktfunk {suffix}"); + // Capital P is the brand; netsh matches a rule name case-INSENSITIVELY, so this still + // reaps the lowercase rules every release up to 0.22.1 created — no orphans on upgrade. + let name = format!("Punktfunk {suffix}"); let _ = run_quiet( "netsh", &[ diff --git a/packaging/windows/drivers/pf-gamepad/pf_gamepad.inx b/packaging/windows/drivers/pf-gamepad/pf_gamepad.inx index 64d850c3..a861c3b1 100644 --- a/packaging/windows/drivers/pf-gamepad/pf_gamepad.inx +++ b/packaging/windows/drivers/pf-gamepad/pf_gamepad.inx @@ -90,13 +90,13 @@ ServiceBinary="%13%\pf_gamepad.dll" pf_gamepad.dll [Strings] -ProviderString ="punktfunk" -ManufacturerString ="punktfunk" +ProviderString ="Punktfunk" +ManufacturerString ="Punktfunk" ClassName ="HID device" -Disk_Description ="punktfunk Gamepad Installation Disk" +Disk_Description ="Punktfunk Gamepad Installation Disk" ; One per hardware id — these are what Device Manager shows. Keep them aligned with the product ; strings the driver serves per device_type (src/lib.rs `on_get_string`). -DeviceDesc ="punktfunk Virtual DualSense" -DeviceDescDS4 ="punktfunk Virtual DualShock 4" -DeviceDescEdge ="punktfunk Virtual DualSense Edge" -DeviceDescDeck ="punktfunk Virtual Steam Deck Controller" +DeviceDesc ="Punktfunk Virtual DualSense" +DeviceDescDS4 ="Punktfunk Virtual DualShock 4" +DeviceDescEdge ="Punktfunk Virtual DualSense Edge" +DeviceDescDeck ="Punktfunk Virtual Steam Deck Controller" diff --git a/packaging/windows/drivers/pf-mouse/pf_mouse.inx b/packaging/windows/drivers/pf-mouse/pf_mouse.inx index b1ac6eab..44a530dd 100644 --- a/packaging/windows/drivers/pf-mouse/pf_mouse.inx +++ b/packaging/windows/drivers/pf-mouse/pf_mouse.inx @@ -72,8 +72,8 @@ ServiceBinary="%13%\pf_mouse.dll" pf_mouse.dll [Strings] -ProviderString ="punktfunk" -ManufacturerString ="punktfunk" +ProviderString ="Punktfunk" +ManufacturerString ="Punktfunk" ClassName ="HID device" -Disk_Description ="punktfunk Mouse Installation Disk" -DeviceDesc ="punktfunk Virtual Mouse" +Disk_Description ="Punktfunk Mouse Installation Disk" +DeviceDesc ="Punktfunk Virtual Mouse" diff --git a/packaging/windows/drivers/pf-mouse/src/lib.rs b/packaging/windows/drivers/pf-mouse/src/lib.rs index a429caac..8ee3c74a 100644 --- a/packaging/windows/drivers/pf-mouse/src/lib.rs +++ b/packaging/windows/drivers/pf-mouse/src/lib.rs @@ -428,14 +428,14 @@ fn on_get_string(request: &Request) -> NTSTATUS { }; let string_id = id_val & 0xFFFF; let s: String = match string_id { - 0 | 0x000E => "punktfunk".into(), + 0 | 0x000E => "Punktfunk".into(), // (2) The SERIAL carries the channel proof — the one transport measured to reach a UMDF HID // minidriver from user mode (`HidD_GetSerialNumberString`, zero-access handle, verified on // .173). Safe HERE and only here: nothing reads the virtual mouse's serial, whereas the pads' // serials are what SDL and Steam dedup controllers on. The old value was the inert // "PFMOUSE00"; the proof text is just as inert and does the security work. 2 | 0x0010 => ChannelProof::new(CHANNEL.index(), std::process::id()).to_hid_string(), - _ => "punktfunk Virtual Mouse".into(), + _ => "Punktfunk Virtual Mouse".into(), }; let mut wide: Vec = Vec::with_capacity(s.len() * 2 + 2); for u in s.encode_utf16() { diff --git a/packaging/windows/drivers/pf-vdisplay/pf_vdisplay.inx b/packaging/windows/drivers/pf-vdisplay/pf_vdisplay.inx index 9ff89eac..4fd4bcf1 100644 --- a/packaging/windows/drivers/pf-vdisplay/pf_vdisplay.inx +++ b/packaging/windows/drivers/pf-vdisplay/pf_vdisplay.inx @@ -75,10 +75,10 @@ UMDriverCopy=12,UMDF pf_vdisplay.dll [Strings] -ManufacturerName="punktfunk" -DiskName="punktfunk Virtual Display Installation Disk" +ManufacturerName="Punktfunk" +DiskName="Punktfunk Virtual Display Installation Disk" WudfRdDisplayName="Windows Driver Foundation - User-mode Driver Framework Reflector" -DeviceName="punktfunk Virtual Display" +DeviceName="Punktfunk Virtual Display" REG_MULTI_SZ=0x00010000 REG_SZ=0x00000000 diff --git a/packaging/windows/drivers/pf-vdisplay/src/adapter.rs b/packaging/windows/drivers/pf-vdisplay/src/adapter.rs index 25c95c1a..14364147 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/adapter.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/adapter.rs @@ -82,8 +82,8 @@ pub fn init_adapter(device: WDFDEVICE) -> NTSTATUS { diag.Size = core::mem::size_of::() as u32; diag.GammaSupport = iddcx::IDDCX_FEATURE_IMPLEMENTATION::IDDCX_FEATURE_IMPLEMENTATION_NONE; diag.TransmissionType = iddcx::IDDCX_TRANSMISSION_TYPE::IDDCX_TRANSMISSION_TYPE_WIRED_OTHER; - diag.pEndPointFriendlyName = wstr!("punktfunk Virtual Display Adapter"); - diag.pEndPointManufacturerName = wstr!("punktfunk"); + diag.pEndPointFriendlyName = wstr!("Punktfunk Virtual Display Adapter"); + diag.pEndPointManufacturerName = wstr!("Punktfunk"); diag.pEndPointModelName = wstr!("Virtual Display"); // SAFETY: `version` is a stack local that outlives this `init_adapter` call; IddCxAdapterInitAsync // (below) reads through these pointers SYNCHRONOUSLY, before `version` drops — the pointer never escapes. diff --git a/packaging/windows/drivers/pf-vdisplay/src/edid.rs b/packaging/windows/drivers/pf-vdisplay/src/edid.rs index cecccd90..4bdf5c80 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/edid.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/edid.rs @@ -6,7 +6,9 @@ //! made "Use HDR" never appear for the virtual display). The base block declares EDID 1.4 + 10-bit //! digital so the panel's bit depth is unambiguous. //! -//! Identity: manufacturer "PNK" (bytes 8-9), product name "punktfunk" (the 0xFC display descriptor). The +//! Identity: manufacturer "PNK" (bytes 8-9), product name "Punktfunk" (the 0xFC display descriptor — +//! this is what Windows shows as `Generic Monitor (Punktfunk)`; byte 127's checksum is recomputed in +//! [`Edid::generate_with`], so editing the name here needs no hand-patched checksum). The //! serial-number field (base offset 0x0C, little-endian) encodes the per-monitor index so //! `parse_monitor_description` can map an EDID the OS hands back to its monitor; [`Edid::generate_with`] //! patches that serial and recomputes BOTH block checksums (base byte 127 + extension byte 255). The @@ -34,7 +36,7 @@ const BASE: [u8; 128] = [ 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x17, 0xF0, 0x0F, // display range-limits descriptor 0xFF, 0x0F, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x70, // name descriptor "punktfunk" + 0x20, 0x20, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x50, // name descriptor "Punktfunk" 0x75, 0x6E, 0x6B, 0x74, 0x66, 0x75, 0x6E, 0x6B, 0x0A, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, // empty 4th descriptor... 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/packaging/windows/drivers/pf-xusb/pf_xusb.inx b/packaging/windows/drivers/pf-xusb/pf_xusb.inx index 12febc8f..82300a1b 100644 --- a/packaging/windows/drivers/pf-xusb/pf_xusb.inx +++ b/packaging/windows/drivers/pf-xusb/pf_xusb.inx @@ -58,7 +58,7 @@ UmdfLibraryVersion=$UMDFVERSION$ ServiceBinary=%13%\pf_xusb.dll [Strings] -ProviderString = "punktfunk" +ProviderString = "Punktfunk" StdMfg = "(Standard system devices)" -DiskId1 = "punktfunk XUSB Installation Disk" -DeviceDesc = "punktfunk Virtual Xbox 360 (XUSB)" +DiskId1 = "Punktfunk XUSB Installation Disk" +DeviceDesc = "Punktfunk Virtual Xbox 360 (XUSB)" diff --git a/packaging/windows/punktfunk-host.iss b/packaging/windows/punktfunk-host.iss index b021e3bc..e2daf7b6 100644 --- a/packaging/windows/punktfunk-host.iss +++ b/packaging/windows/punktfunk-host.iss @@ -351,7 +351,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 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"""; \ + 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 #ifdef WithScripting diff --git a/packaging/windows/reset-pf-vdisplay.ps1 b/packaging/windows/reset-pf-vdisplay.ps1 index 52a066fd..dcf56c60 100644 --- a/packaging/windows/reset-pf-vdisplay.ps1 +++ b/packaging/windows/reset-pf-vdisplay.ps1 @@ -7,7 +7,7 @@ .DESCRIPTION Sustained connect/disconnect churn (e.g. a client reconnect loop x the host's 8 pipeline-build retries - ~100 ADD/REMOVE cycles) exhausts the driver's IddCx monitor slots: the per-monitor - target_ids climb, ghost "Generic Monitor (punktfunk)" device nodes pile up, and eventually + target_ids climb, ghost "Generic Monitor (Punktfunk)" device nodes pile up, and eventually IOCTL_ADD returns 0x80070490 ERROR_NOT_FOUND ("Element nicht gefunden"). Every session then fails to create a virtual output -> the client gets a hard blackscreen. A host-service restart's IOCTL_CLEAR_ALL does NOT recover it; the driver instance itself must be reloaded. @@ -16,16 +16,16 @@ 1. Stop the host service (it holds the driver's control device). 2. pnputil /remove-device the GHOST (Status != OK = not-present) punktfunk virtual-monitor nodes that accumulated - the root of the slot exhaustion. - 3. Disable + Enable the pf-vdisplay adapter (ROOT\DISPLAY\*, "punktfunk Virtual Display") to + 3. Disable + Enable the pf-vdisplay adapter (ROOT\DISPLAY\*, "Punktfunk Virtual Display") to reload the IddCx driver instance and reset its monitor list. (Restart-PnpDevice does NOT exist on this box's PowerShell, so we disable+enable explicitly.) 4. Restart the host service. Avoids a reboot on purpose (this box boots to Proxmox). .PARAMETER Service Host service name. Default PunktfunkHost. -.PARAMETER AdapterName FriendlyName substring of the IddCx adapter to cycle. Default "punktfunk +.PARAMETER AdapterName FriendlyName substring of the IddCx adapter to cycle. Default "Punktfunk Virtual Display" (NOT SudoVDA's "SudoMaker Virtual Display Adapter"). -.PARAMETER GhostMatch FriendlyName substring of the virtual monitors to reap. Default "punktfunk". +.PARAMETER GhostMatch FriendlyName substring of the virtual monitors to reap. Default "Punktfunk". .PARAMETER KeepGhosts Skip the ghost-node cleanup; only cycle the adapter. .PARAMETER NoHost Don't stop/start the host service (just reset the driver) - used by redeploy-pf-vdisplay.ps1, which manages the service itself. @@ -41,8 +41,8 @@ [CmdletBinding()] param( [string]$Service = 'PunktfunkHost', - [string]$AdapterName = 'punktfunk Virtual Display', - [string]$GhostMatch = 'punktfunk', + [string]$AdapterName = 'Punktfunk Virtual Display', + [string]$GhostMatch = 'Punktfunk', [switch]$KeepGhosts, [switch]$NoHost, [switch]$Verify,