From 35c61fee64f8a870ace7240e4debc88d9f409cba Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Wed, 29 Jul 2026 13:24:18 +0200 Subject: [PATCH] chore(client): the windows-rs pin moves a month forward, onto the SDK-metadata bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The July 2026 windows-rs brings a reconciler keyed-child-order fix (#4728), widget validation (#4727), a DPI collision fix (#4751), icon elements (#4736), multi-window support (#4730) and scroll virtualization (#4710) — the re-render fixes the Windows client has been working around at the architecture level. All three pinned deps (windows-reactor, windows, windows-reactor-setup) move together so windows-core stays unified across the swap-chain hand-off, and pf-client-core moves with them. The bulk of the diff is #4689: windows/windows-sys now generate straight from the Windows SDK, so the `Win32_*` namespace features became one feature per SDK header (winuser, dxgi, d3d11, …), the PascalCase namespace modules became header-named modules, struct-returning COM methods take explicit out-params and return HRESULT, Win32 functions return their raw BOOL/HANDLE instead of Result, and flag constants are plain integers. Both crates' Win32 code is rewritten to that shape; behaviour is unchanged on every path. Riding along, all already stale before the bump: the README and the three Windows workflows stop claiming windows-reactor's build.rs needs CARGO_WORKSPACE_DIR (that build.rs no longer exists — staging moved to windows-reactor-setup via OUT_DIR); the README layout section stops describing modules that moved into the session binary long ago and gains the manual smoke checklist; the notices generator learns the SPDX for crates that ship license files without a `license` field, which turns windows-reactor-setup's UNKNOWN into MIT OR Apache-2.0; and the crate records its real rust-version (1.96) instead of inheriting the workspace's 1.82. Verified: cargo check/clippy/fmt clean on punktfunk-client-windows, pf-client-core and punktfunk-client-session; both bins build; --discover finds the LAN hosts; the GUI shell comes up (WinAppSDK bootstrap intact under the new reactor-setup). Co-Authored-By: Claude Fable 5 --- .gitea/workflows/windows-host.yml | 5 +- .gitea/workflows/windows-msix.yml | 8 +- .gitea/workflows/windows.yml | 7 +- Cargo.lock | 98 +++++++++++++----------- THIRD-PARTY-NOTICES.txt | 11 ++- clients/windows/Cargo.toml | 65 ++++++++-------- clients/windows/README.md | 40 +++++++--- clients/windows/src/app/mod.rs | 38 +++++---- clients/windows/src/deeplink.rs | 64 ++++++++-------- clients/windows/src/gpu.rs | 35 +++++---- clients/windows/src/main.rs | 8 +- clients/windows/src/shell_window.rs | 13 +++- crates/pf-client-core/Cargo.toml | 25 +++--- crates/pf-client-core/src/clipboard.rs | 43 +++++++---- crates/pf-client-core/src/video_d3d11.rs | 61 ++++++++------- scripts/gen-third-party-notices.py | 11 ++- 16 files changed, 306 insertions(+), 226 deletions(-) diff --git a/.gitea/workflows/windows-host.yml b/.gitea/workflows/windows-host.yml index 60ad28fa..3da96fb0 100644 --- a/.gitea/workflows/windows-host.yml +++ b/.gitea/workflows/windows-host.yml @@ -123,10 +123,9 @@ jobs: shell: pwsh run: | # CARGO_TARGET_DIR=C:\t dodges the MAX_PATH wall in the CMake-from-source crates (aws-lc, - # opus) the host pulls; CARGO_WORKSPACE_DIR mirrors the client workflows. Both via GITHUB_ENV - # (pwsh Out-File utf8 = no BOM, unlike Windows PowerShell 5.1 — keeps the first line clean). + # opus) the host pulls; via GITHUB_ENV (pwsh Out-File utf8 = no BOM, unlike Windows + # PowerShell 5.1 — keeps the first line clean). "CARGO_TARGET_DIR=C:\t" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 - "CARGO_WORKSPACE_DIR=$env:GITHUB_WORKSPACE" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 # audiopus_sys' vendored opus declares cmake_minimum_required < 3.5, which CMake 4.x # refuses outright. Green runs today only survive on the cached configure output — a # target-dir purge (the runner's disk-cleanup task) would fail the fresh configure, as diff --git a/.gitea/workflows/windows-msix.yml b/.gitea/workflows/windows-msix.yml index 2532377f..cbd50853 100644 --- a/.gitea/workflows/windows-msix.yml +++ b/.gitea/workflows/windows-msix.yml @@ -92,11 +92,9 @@ jobs: - name: Configure + version shell: pwsh run: | - # windows-reactor's build.rs unwraps CARGO_WORKSPACE_DIR; CARGO_TARGET_DIR (per-arch, short) - # dodges the MAX_PATH wall in the CMake-from-source crates (see windows.yml). FFMPEG_DIR - # selects the arch's import libs + is read by pack-msix.ps1 for the runtime DLLs. All via - # GITHUB_ENV. - "CARGO_WORKSPACE_DIR=$env:GITHUB_WORKSPACE" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + # CARGO_TARGET_DIR (per-arch, short) dodges the MAX_PATH wall in the CMake-from-source + # crates (see windows.yml). FFMPEG_DIR selects the arch's import libs + is read by + # pack-msix.ps1 for the runtime DLLs. All via GITHUB_ENV. "CARGO_TARGET_DIR=${{ matrix.td }}" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 "FFMPEG_DIR=${{ matrix.ffmpeg }}" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 # pf-ffvk's bindgen needs Vulkan headers (arch-independent; provisioned alongside FFmpeg). diff --git a/.gitea/workflows/windows.yml b/.gitea/workflows/windows.yml index 9039a34f..9cc4b9b3 100644 --- a/.gitea/workflows/windows.yml +++ b/.gitea/workflows/windows.yml @@ -22,8 +22,6 @@ # The MSVC/WinUI/FFmpeg toolchain (cargo/rustup on ASCII paths, NASM, CMake, LLVM, the x64 FFmpeg, # CARGO_HOME, CMAKE_POLICY_VERSION_MINIMUM, …) is baked into the runner's daemon env. Per-checkout # / per-arch vars are set in a step: -# - CARGO_WORKSPACE_DIR windows-reactor's build.rs unwraps it + stages the Win App SDK -# NuGets/winmd under it (from GITHUB_WORKSPACE). # - CARGO_TARGET_DIR=C:\t… the runner's host workdir is buried deep under # C:\Windows\System32\config\systemprofile\.cache\act\\hostexecutor\, # so the default target\ path blows past Windows' MAX_PATH (260) inside the @@ -34,8 +32,8 @@ # - FFMPEG_DIR per-arch FFmpeg import libs (x64 vs arm64 tree). # # Steps use `shell: pwsh` (PowerShell 7) deliberately: Windows PowerShell 5.1's -# `Out-File -Encoding utf8` prepends a UTF-8 BOM that corrupts the first GITHUB_ENV line (the -# CARGO_WORKSPACE_DIR var silently never gets set -> reactor build.rs panics). pwsh writes no BOM. +# `Out-File -Encoding utf8` prepends a UTF-8 BOM that corrupts the first GITHUB_ENV line (that +# var silently never gets set). pwsh writes no BOM. # The runner's daemon wrapper puts C:\Program Files\PowerShell\7 on PATH so the job finds pwsh. name: windows # One pending run per workflow+ref: a newer push supersedes the queued/running one and cancels @@ -105,7 +103,6 @@ jobs: - name: Configure + toolchain versions shell: pwsh run: | - "CARGO_WORKSPACE_DIR=$env:GITHUB_WORKSPACE" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 # Per-arch short target root (dodges MAX_PATH; keeps the two legs from sharing target\). $td = if ('${{ matrix.target }}' -eq 'aarch64-pc-windows-msvc') { 'C:\t-a64' } else { 'C:\t' } "CARGO_TARGET_DIR=$td" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 diff --git a/Cargo.lock b/Cargo.lock index 3aa8debc..e2c08ec2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2890,7 +2890,7 @@ dependencies = [ "tracing", "ureq", "wasapi", - "windows 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", ] [[package]] @@ -3376,7 +3376,7 @@ dependencies = [ "serde_json", "tracing", "tracing-subscriber", - "windows 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", "windows-reactor", "windows-reactor-setup", "winresource", @@ -5420,12 +5420,12 @@ dependencies = [ [[package]] name = "windows" version = "0.62.2" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ - "windows-collections 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-future 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-numerics 0.3.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-collections 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-future 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-numerics 0.3.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", "windows-reference", "windows-time", ] @@ -5442,9 +5442,20 @@ dependencies = [ [[package]] name = "windows-collections" version = "0.3.2" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ - "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", +] + +[[package]] +name = "windows-composition" +version = "0.0.0" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" +dependencies = [ + "windows-collections 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-numerics 0.3.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-time", ] [[package]] @@ -5463,13 +5474,13 @@ dependencies = [ [[package]] name = "windows-core" version = "0.62.2" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ - "windows-implement 0.60.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-interface 0.59.3 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-result 0.4.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-strings 0.5.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-implement 0.60.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-interface 0.59.3 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-result 0.4.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-strings 0.5.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", ] [[package]] @@ -5486,11 +5497,11 @@ dependencies = [ [[package]] name = "windows-future" version = "0.3.2" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ - "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-threading 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-threading 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", ] [[package]] @@ -5507,7 +5518,7 @@ dependencies = [ [[package]] name = "windows-implement" version = "0.60.2" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ "proc-macro2", "quote", @@ -5528,7 +5539,7 @@ dependencies = [ [[package]] name = "windows-interface" version = "0.59.3" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ "proc-macro2", "quote", @@ -5544,7 +5555,7 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-link" version = "0.2.1" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" [[package]] name = "windows-numerics" @@ -5559,38 +5570,39 @@ dependencies = [ [[package]] name = "windows-numerics" version = "0.3.1" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ - "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", ] [[package]] name = "windows-reactor" version = "0.0.0" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ "rustc-hash", - "windows-collections 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-future 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-numerics 0.3.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-collections 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-composition", + "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-future 0.3.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-numerics 0.3.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", "windows-reference", - "windows-threading 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-threading 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", "windows-time", ] [[package]] name = "windows-reactor-setup" version = "0.0.0" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" [[package]] name = "windows-reference" version = "0.1.0" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ - "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", "windows-time", ] @@ -5606,9 +5618,9 @@ dependencies = [ [[package]] name = "windows-result" version = "0.4.1" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ - "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", ] [[package]] @@ -5634,9 +5646,9 @@ dependencies = [ [[package]] name = "windows-strings" version = "0.5.1" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ - "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", ] [[package]] @@ -5744,18 +5756,18 @@ dependencies = [ [[package]] name = "windows-threading" version = "0.2.1" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ - "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", ] [[package]] name = "windows-time" version = "0.1.0" -source = "git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f#a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" +source = "git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc#acb5a1a7441033d9312b16842af02eb0c2b403dc" dependencies = [ - "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", - "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f)", + "windows-core 0.62.2 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", + "windows-link 0.2.1 (git+https://github.com/microsoft/windows-rs?rev=acb5a1a7441033d9312b16842af02eb0c2b403dc)", ] [[package]] diff --git a/THIRD-PARTY-NOTICES.txt b/THIRD-PARTY-NOTICES.txt index 1420ab34..1077ffce 100644 --- a/THIRD-PARTY-NOTICES.txt +++ b/THIRD-PARTY-NOTICES.txt @@ -7,7 +7,11 @@ below. Each is distributed under its own permissive license; the full license te follow the manifest. This file is generated by scripts/gen-third-party-notices.py (or `cargo about`, see about.toml) — do not edit by hand. +<<<<<<< HEAD Total third-party crates: 561 +======= +Total third-party crates: 562 +>>>>>>> d0c7bae1 (chore(client): the windows-rs pin moves a month forward, onto the SDK-metadata bindings) ---------------------------------------------------------------------------- VENDORED THIRD-PARTY SOURCE (inside first-party crates) @@ -497,6 +501,7 @@ MANIFEST (crate version — SPDX license — source) windows 0.62.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs windows-collections 0.3.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs windows-collections 0.3.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs + windows-composition 0.0.0 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs windows-core 0.62.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs windows-core 0.62.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs windows-future 0.3.2 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs @@ -510,7 +515,7 @@ MANIFEST (crate version — SPDX license — source) windows-numerics 0.3.1 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs windows-numerics 0.3.1 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs windows-reactor 0.0.0 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs - windows-reactor-setup 0.0.0 — UNKNOWN + windows-reactor-setup 0.0.0 — MIT OR Apache-2.0 windows-reference 0.1.0 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs windows-result 0.4.1 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs windows-result 0.4.1 — MIT OR Apache-2.0 — https://github.com/microsoft/windows-rs @@ -15197,7 +15202,7 @@ SOFTWARE. ---------------------------------------------------------------------------- -The following license (license-apache-2.0) applies to: windows 0.62.2, windows-collections 0.3.2, windows-core 0.62.2, windows-future 0.3.2, windows-implement 0.60.2, windows-interface 0.59.3, windows-link 0.2.1, windows-numerics 0.3.1, windows-reactor 0.0.0, windows-reactor-setup 0.0.0, windows-reference 0.1.0, windows-result 0.4.1, windows-strings 0.5.1, windows-sys 0.45.0, windows-sys 0.52.0, windows-sys 0.59.0, windows-sys 0.60.2, windows-sys 0.61.2, windows-targets 0.42.2, windows-targets 0.52.6, windows-targets 0.53.5, windows-threading 0.2.1, windows-time 0.1.0, windows_aarch64_gnullvm 0.42.2, windows_aarch64_gnullvm 0.52.6, windows_aarch64_gnullvm 0.53.1, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.52.6, windows_aarch64_msvc 0.53.1, windows_i686_gnu 0.42.2, windows_i686_gnu 0.52.6, windows_i686_gnu 0.53.1, windows_i686_gnullvm 0.52.6, windows_i686_gnullvm 0.53.1, windows_i686_msvc 0.42.2, windows_i686_msvc 0.52.6, windows_i686_msvc 0.53.1, windows_x86_64_gnu 0.42.2, windows_x86_64_gnu 0.52.6, windows_x86_64_gnu 0.53.1, windows_x86_64_gnullvm 0.42.2, windows_x86_64_gnullvm 0.52.6, windows_x86_64_gnullvm 0.53.1, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.52.6, windows_x86_64_msvc 0.53.1 +The following license (license-apache-2.0) applies to: windows 0.62.2, windows-collections 0.3.2, windows-composition 0.0.0, windows-core 0.62.2, windows-future 0.3.2, windows-implement 0.60.2, windows-interface 0.59.3, windows-link 0.2.1, windows-numerics 0.3.1, windows-reactor 0.0.0, windows-reactor-setup 0.0.0, windows-reference 0.1.0, windows-result 0.4.1, windows-strings 0.5.1, windows-sys 0.45.0, windows-sys 0.52.0, windows-sys 0.59.0, windows-sys 0.60.2, windows-sys 0.61.2, windows-targets 0.42.2, windows-targets 0.52.6, windows-targets 0.53.5, windows-threading 0.2.1, windows-time 0.1.0, windows_aarch64_gnullvm 0.42.2, windows_aarch64_gnullvm 0.52.6, windows_aarch64_gnullvm 0.53.1, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.52.6, windows_aarch64_msvc 0.53.1, windows_i686_gnu 0.42.2, windows_i686_gnu 0.52.6, windows_i686_gnu 0.53.1, windows_i686_gnullvm 0.52.6, windows_i686_gnullvm 0.53.1, windows_i686_msvc 0.42.2, windows_i686_msvc 0.52.6, windows_i686_msvc 0.53.1, windows_x86_64_gnu 0.42.2, windows_x86_64_gnu 0.52.6, windows_x86_64_gnu 0.53.1, windows_x86_64_gnullvm 0.42.2, windows_x86_64_gnullvm 0.52.6, windows_x86_64_gnullvm 0.53.1, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.52.6, windows_x86_64_msvc 0.53.1 ---------------------------------------------------------------------------- Apache License Version 2.0, January 2004 @@ -15403,7 +15408,7 @@ Apache License ---------------------------------------------------------------------------- -The following license (license-mit) applies to: windows 0.62.2, windows-collections 0.3.2, windows-core 0.62.2, windows-future 0.3.2, windows-implement 0.60.2, windows-interface 0.59.3, windows-link 0.2.1, windows-numerics 0.3.1, windows-reactor 0.0.0, windows-reactor-setup 0.0.0, windows-reference 0.1.0, windows-result 0.4.1, windows-strings 0.5.1, windows-sys 0.45.0, windows-sys 0.52.0, windows-sys 0.59.0, windows-sys 0.60.2, windows-sys 0.61.2, windows-targets 0.42.2, windows-targets 0.52.6, windows-targets 0.53.5, windows-threading 0.2.1, windows-time 0.1.0, windows_aarch64_gnullvm 0.42.2, windows_aarch64_gnullvm 0.52.6, windows_aarch64_gnullvm 0.53.1, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.52.6, windows_aarch64_msvc 0.53.1, windows_i686_gnu 0.42.2, windows_i686_gnu 0.52.6, windows_i686_gnu 0.53.1, windows_i686_gnullvm 0.52.6, windows_i686_gnullvm 0.53.1, windows_i686_msvc 0.42.2, windows_i686_msvc 0.52.6, windows_i686_msvc 0.53.1, windows_x86_64_gnu 0.42.2, windows_x86_64_gnu 0.52.6, windows_x86_64_gnu 0.53.1, windows_x86_64_gnullvm 0.42.2, windows_x86_64_gnullvm 0.52.6, windows_x86_64_gnullvm 0.53.1, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.52.6, windows_x86_64_msvc 0.53.1 +The following license (license-mit) applies to: windows 0.62.2, windows-collections 0.3.2, windows-composition 0.0.0, windows-core 0.62.2, windows-future 0.3.2, windows-implement 0.60.2, windows-interface 0.59.3, windows-link 0.2.1, windows-numerics 0.3.1, windows-reactor 0.0.0, windows-reactor-setup 0.0.0, windows-reference 0.1.0, windows-result 0.4.1, windows-strings 0.5.1, windows-sys 0.45.0, windows-sys 0.52.0, windows-sys 0.59.0, windows-sys 0.60.2, windows-sys 0.61.2, windows-targets 0.42.2, windows-targets 0.52.6, windows-targets 0.53.5, windows-threading 0.2.1, windows-time 0.1.0, windows_aarch64_gnullvm 0.42.2, windows_aarch64_gnullvm 0.52.6, windows_aarch64_gnullvm 0.53.1, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.52.6, windows_aarch64_msvc 0.53.1, windows_i686_gnu 0.42.2, windows_i686_gnu 0.52.6, windows_i686_gnu 0.53.1, windows_i686_gnullvm 0.52.6, windows_i686_gnullvm 0.53.1, windows_i686_msvc 0.42.2, windows_i686_msvc 0.52.6, windows_i686_msvc 0.53.1, windows_x86_64_gnu 0.42.2, windows_x86_64_gnu 0.52.6, windows_x86_64_gnu 0.53.1, windows_x86_64_gnullvm 0.42.2, windows_x86_64_gnullvm 0.52.6, windows_x86_64_gnullvm 0.53.1, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.52.6, windows_x86_64_msvc 0.53.1 ---------------------------------------------------------------------------- MIT License diff --git a/clients/windows/Cargo.toml b/clients/windows/Cargo.toml index 54c55922..b867bb0f 100644 --- a/clients/windows/Cargo.toml +++ b/clients/windows/Cargo.toml @@ -3,7 +3,9 @@ name = "punktfunk-client-windows" description = "Native Windows punktfunk/1 client — WinUI 3 (windows-reactor) shell, SDL3 gamepads; streaming runs in the spawned punktfunk-session binary" version.workspace = true edition.workspace = true -rust-version.workspace = true +# Not workspace-inherited (1.82): windows-reactor at the pinned rev declares rust-version 1.95+ +# and edition 2024. rust-toolchain.toml pins 1.96, so this records reality rather than raising it. +rust-version = "1.96" license.workspace = true authors.workspace = true repository.workspace = true @@ -41,40 +43,39 @@ punktfunk-core = { path = "../../crates/punktfunk-core", features = ["quic"] } # nothing enables it and the C++ is never compiled. pf-client-core = { path = "../../crates/pf-client-core", default-features = false } -# WinUI 3 UI via windows-reactor (a declarative React-like framework backed by WinUI). Its -# `build.rs` downloads the Windows App SDK NuGets and stages the bootstrap DLL + resources.pri -# next to the exe; it requires `CARGO_WORKSPACE_DIR` to be set in the build env. Unpublished -# (version 0.0.0) and fast-moving, so pinned to a verified commit. -windows-reactor = { git = "https://github.com/microsoft/windows-rs", rev = "a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" } -# Win32 / Direct3D11 / DXGI for the SwapChainPanel composition swapchain. Pulled from the SAME +# WinUI 3 UI via windows-reactor (a declarative React-like framework backed by WinUI). +# Unpublished (version 0.0.0) and fast-moving, so pinned to a verified commit. Pin bumped +# 2026-07-29 (from the 2026-07-01 rev) for: reconciler keyed-child-order fix (#4728), widget +# validation (#4727), DPI collision fix (#4751), icon elements (#4736), multi-window (#4730), +# scroll virtualization (#4710). All three windows-rs deps here MUST share this rev, and it +# must match pf-client-core's `windows` pin, so the workspace builds ONE windows-rs. +windows-reactor = { git = "https://github.com/microsoft/windows-rs", rev = "acb5a1a7441033d9312b16842af02eb0c2b403dc" } +# Win32 / DXGI for the GPU picker and the shell's window plumbing. Pulled from the SAME # windows-rs commit as windows-reactor so their `windows-core` unifies — the `IDXGISwapChain1` # we hand to `SwapChainPanelHandle::set_swap_chain` must satisfy reactor's `windows_core::Interface`. -windows = { git = "https://github.com/microsoft/windows-rs", rev = "a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f", features = [ - "Win32_Foundation", - "Win32_Graphics_Dxgi", - "Win32_Graphics_Dxgi_Common", +# Features are header-named since the in-house-metadata rework (#4689) — one feature per SDK +# header, replacing the old `Win32_*` namespace features. +windows = { git = "https://github.com/microsoft/windows-rs", rev = "acb5a1a7441033d9312b16842af02eb0c2b403dc", features = [ # GetCurrentPackageFullName — the packaged-run probe guarding the explicit # AppUserModelID (main.rs; MSIX identity must win over the dev-run tag). - "Win32_Storage_Packaging_Appx", - "Win32_Graphics_Direct3D", - "Win32_Graphics_Direct3D11", - "Win32_Graphics_Direct3D_Fxc", - "Win32_Graphics_Gdi", - # IShellLinkW + IPersistFile for the "Create shortcut" writer, and COPYDATASTRUCT for the - # link hand-off between instances (deeplink.rs). - "Win32_System_Com", - "Win32_System_DataExchange", - "Win32_System_Console", - "Win32_System_LibraryLoader", - "Win32_System_Threading", - "Win32_UI_HiDpi", - "Win32_UI_Input_KeyboardAndMouse", - # Win32 window subclassing (SetWindowSubclass/DefSubclassProc) — the stream input hooks - # subclass the WinUI window + its content-island children to swallow WM_SETCURSOR so the - # local cursor stays hidden while the pointer is locked (WinUI otherwise re-asserts the arrow - # on every pointer move, defeating a one-shot ShowCursor(false)). - "Win32_UI_Shell", - "Win32_UI_WindowsAndMessaging", + "appmodel", + # CoCreateInstance/CoInitializeEx (+ objbase/objidl/wtypesbase below) for the + # "Create shortcut" writer (deeplink.rs). + "combaseapi", + # SetWindowSubclass/DefSubclassProc — the deep-link WM_COPYDATA subclass hook. + "commctrl", + "consoleapi", + "dxgi", + "errhandlingapi", + "libloaderapi", + "objbase", + "objidl", + # SetCurrentProcessExplicitAppUserModelID + ShellLink/IShellLinkW. + "shobjidl_core", + "synchapi", + "winerror", + # Windowing, messages, icons — and COPYDATASTRUCT, which lives in winuser now too. + "winuser", ] } # FFmpeg — used only to enumerate which codecs this client can decode (probe::decodable_codecs), @@ -98,7 +99,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] } # to the exe — the new-model replacement for the old windows-reactor build.rs; same pinned rev. [target.'cfg(windows)'.build-dependencies] winresource = "0.1" -windows-reactor-setup = { git = "https://github.com/microsoft/windows-rs", rev = "a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" } +windows-reactor-setup = { git = "https://github.com/microsoft/windows-rs", rev = "acb5a1a7441033d9312b16842af02eb0c2b403dc" } [lints] workspace = true diff --git a/clients/windows/README.md b/clients/windows/README.md index 32c49568..5a56d11b 100644 --- a/clients/windows/README.md +++ b/clients/windows/README.md @@ -42,8 +42,9 @@ A stock [Moonlight](https://moonlight-stream.org/) client also works over GameSt ## Build from source Windows-only (the crate builds as a stub on other platforms so the workspace stays green). You need -the MSVC toolchain, an `FFMPEG_DIR` FFmpeg tree, and CMake (SDL3 builds from source). windows-reactor's -`build.rs` downloads the Windows App SDK NuGets and needs `CARGO_WORKSPACE_DIR` set. +the MSVC toolchain, an `FFMPEG_DIR` FFmpeg tree, and CMake (SDL3 builds from source). The Windows +App SDK runtime bootstrap is staged next to the exe by `windows-reactor-setup` from this crate's +own `build.rs` — no extra environment needed. ```sh cargo build -p punktfunk-client-windows --target x86_64-pc-windows-msvc @@ -59,22 +60,43 @@ punktfunk-client --headless --speed-test --connect host[:port] # probe burst ## Layout +Decode/present/input live in the spawned `punktfunk-session` binary (`clients/session`), not here — +this crate is the shell that discovers, pairs, and launches it. + ``` src/ main.rs entry point + CLI paths (--discover · --headless · --speed-test) + bin/punktfunk-console.rs the couch/HTPC Start-menu entry (re-execs with --console) app/ WinUI 3 shell (windows-reactor), one module per screen: mod (root/router) · hosts · connect · pair · speed · settings · - licenses · stream · style (shared cards/pills/monograms) - present.rs · gpu.rs SwapChainPanel D3D11 composition swapchain; shared D3D11 device - video.rs FFmpeg HEVC decode (D3D11VA zero-copy + software fallback) - audio.rs WASAPI render + mic capture - gamepad.rs SDL3 controllers + rumble/lightbar/DualSense feedback - input.rs Win32 low-level hooks → host input (pointer lock · click-to-capture) - session.rs session lifecycle over the NativeClient connector (+ speed probe) + library · help · licenses · stream · style (shared cards/pills) + deeplink.rs punktfunk:// activation, single-instance hand-off, shortcut writer + spawn.rs punktfunk-session child process + its stdout event contract + shell_window.rs hide/restore the shell HWND around a session + gpu.rs DXGI adapter enumeration for the GPU picker trust.rs · discovery.rs persistent identity, TOFU/PIN pairing, mDNS browse + probe.rs · wol.rs speed probe · Wake-on-LAN + logfile.rs log tee to %LOCALAPPDATA% packaging/ MSIX manifest, signing, pack script ``` +## Manual smoke checklist + +The windows-reactor pin is a moving target and WinUI regressions rarely show up in `cargo check` — +walk this after a reactor bump or a change to the render/state architecture: + +- **Hosts** — discovery populates tiles; tile hover fill; "…" menu → Forget and Rename; + add-host modal connects; WOL wait screen cancels. +- **Settings** — every section renders; combos still show their selection after a section + switch AND a scope switch (the historic blank-combo reconciler bug); profile create / + rename / delete (with confirm); colour swatches repaint; the Overridden marker appears on + edit and clears on Reset; GPU combo lists adapters. +- **Pair** — PIN entry pairs (the typed PIN must reach the Connect click — `use_ref` mirror path). +- **Session** — connect → session spawns → HUD stats tick; Ctrl+Alt+Shift+Q releases the pointer; + shell window restores on exit. +- **Shell** — speed test completes; library grid loads; `punktfunk://` deep link routes (second + instance hands off and exits); window icon appears; screen-entrance animations play. + ## Related - **[Documentation](https://docs.punktfunk.unom.io)** — quick start, pairing, troubleshooting diff --git a/clients/windows/src/app/mod.rs b/clients/windows/src/app/mod.rs index dde744ad..e7e994a2 100644 --- a/clients/windows/src/app/mod.rs +++ b/clients/windows/src/app/mod.rs @@ -190,9 +190,9 @@ pub fn run(identity: (String, String), gamepad: GamepadService) -> windows_react /// window icon-less and exposes no handle before `App::render` blocks, so a short background /// poll finds our own window by its (unique) title. fn apply_window_icon_when_ready() { - use windows::Win32::Foundation::{LPARAM, WPARAM}; - use windows::Win32::System::LibraryLoader::GetModuleHandleW; - use windows::Win32::UI::WindowsAndMessaging::{ + use windows::Win32::libloaderapi::GetModuleHandleW; + use windows::Win32::minwindef::{LPARAM, WPARAM}; + use windows::Win32::winuser::{ FindWindowW, GetSystemMetrics, LoadImageW, SendMessageW, ICON_BIG, ICON_SMALL, IMAGE_ICON, LR_DEFAULTCOLOR, SM_CXICON, SM_CXSMICON, WM_SETICON, }; @@ -203,27 +203,35 @@ fn apply_window_icon_when_ready() { // of them dereference caller memory, and the loop gives up after 100 tries. .spawn(|| unsafe { for _ in 0..100 { - if let Ok(hwnd) = FindWindowW(None, windows::core::w!("Punktfunk")) { - let Ok(module) = GetModuleHandleW(None) else { + let hwnd = FindWindowW(None, windows::core::w!("Punktfunk")); + if !hwnd.0.is_null() { + let module = GetModuleHandleW(None); + if module.0.is_null() { return; - }; + } // Small (title bar) and big (Alt-Tab) at their native metrics, both from // the multi-size .ico so nothing is scaled at draw time. + // MAKEINTRESOURCE(1): the "pointer" IS the resource ordinal — not a + // dangling pointer, and `ptr::dangling()` (an alignment-based address) + // would name a different resource. + #[allow(clippy::manual_dangling_ptr)] + let ordinal_1 = windows::core::PCWSTR(1 as *const u16); for (which, metric) in [(ICON_SMALL, SM_CXSMICON), (ICON_BIG, SM_CXICON)] { let px = GetSystemMetrics(metric); - if let Ok(icon) = LoadImageW( - Some(module.into()), - windows::core::PCWSTR(1 as *const u16), - IMAGE_ICON, + let icon = LoadImageW( + Some(module), + ordinal_1, + IMAGE_ICON as u32, px, px, - LR_DEFAULTCOLOR, - ) { + LR_DEFAULTCOLOR as u32, + ); + if !icon.0.is_null() { SendMessageW( hwnd, - WM_SETICON, - Some(WPARAM(which as usize)), - Some(LPARAM(icon.0 as isize)), + WM_SETICON as u32, + WPARAM(which as usize), + LPARAM(icon.0 as isize), ); } } diff --git a/clients/windows/src/deeplink.rs b/clients/windows/src/deeplink.rs index 9bc020ad..87ea4a40 100644 --- a/clients/windows/src/deeplink.rs +++ b/clients/windows/src/deeplink.rs @@ -13,12 +13,11 @@ use std::sync::atomic::{AtomicIsize, Ordering}; use std::sync::Mutex; -use windows::Win32::Foundation::{HWND, LPARAM, LRESULT, WPARAM}; -use windows::Win32::System::Threading::{CreateMutexW, ReleaseMutex}; -use windows::Win32::UI::Shell::{DefSubclassProc, SetWindowSubclass}; -// COPYDATASTRUCT lives with the other data-exchange types, not with the message constant. -use windows::Win32::System::DataExchange::COPYDATASTRUCT; -use windows::Win32::UI::WindowsAndMessaging::{FindWindowW, SendMessageW, WM_COPYDATA}; +use windows::Win32::commctrl::{DefSubclassProc, SetWindowSubclass}; +use windows::Win32::minwindef::{LPARAM, LRESULT, WPARAM}; +use windows::Win32::synchapi::{CreateMutexW, ReleaseMutex}; +use windows::Win32::windef::HWND; +use windows::Win32::winuser::{FindWindowW, SendMessageW, COPYDATASTRUCT, WM_COPYDATA}; /// The single-instance mutex. Named per the design; deliberately not `Global\` — one shell per /// user session is the rule, and a second desktop user gets their own. @@ -59,19 +58,18 @@ pub(crate) fn claim_primary() -> bool { // SAFETY: `CreateMutexW` takes a static wide name literal and no pointer we own; the handle it // returns is stored in `MUTEX` and released once in `release_primary`. unsafe { - let handle = match CreateMutexW(None, true, MUTEX_NAME) { - Ok(h) => h, - // Without the mutex we cannot tell primary from secondary; behaving as primary is - // the safe answer — a second window is a nuisance, a dropped launch is a bug. - Err(e) => { - tracing::warn!(error = %e, "single instance mutex; continuing as primary"); - return true; - } - }; + let handle = CreateMutexW(None, true, MUTEX_NAME); + // Without the mutex we cannot tell primary from secondary; behaving as primary is + // the safe answer — a second window is a nuisance, a dropped launch is a bug. + if handle.0.is_null() { + let e = windows::Win32::errhandlingapi::GetLastError(); + tracing::warn!(error = e, "single instance mutex; continuing as primary"); + return true; + } // ERROR_ALREADY_EXISTS means someone else created it first — `CreateMutexW` still // hands back a valid handle, so ask the OS what actually happened. - let already = windows::Win32::Foundation::GetLastError() - == windows::Win32::Foundation::ERROR_ALREADY_EXISTS; + let already = windows::Win32::errhandlingapi::GetLastError() + == windows::Win32::winerror::ERROR_ALREADY_EXISTS as u32; if already { return false; } @@ -87,7 +85,7 @@ pub(crate) fn release_primary() { // SAFETY: `raw` is the handle `claim_primary` stored, taken out of the atomic by `swap` so // this runs at most once even if two threads race here. unsafe { - let _ = ReleaseMutex(windows::Win32::Foundation::HANDLE(raw as *mut _)); + let _ = ReleaseMutex(windows::Win32::winnt::HANDLE(raw as *mut _)); } } } @@ -104,7 +102,8 @@ pub(crate) fn forward_to_primary(url: &str) -> bool { // local that outlives the call because `SendMessage` is synchronous — the receiver has // finished with the buffer before it returns, which is precisely why this is not `Post`. unsafe { - if let Ok(hwnd) = FindWindowW(None, windows::core::w!("Punktfunk")) { + let hwnd = FindWindowW(None, windows::core::w!("Punktfunk")); + if !hwnd.0.is_null() { let data = COPYDATASTRUCT { dwData: COPYDATA_URL, cbData: (wide.len() * 2) as u32, @@ -114,9 +113,9 @@ pub(crate) fn forward_to_primary(url: &str) -> bool { // copied it, which only a synchronous send guarantees. SendMessageW( hwnd, - WM_COPYDATA, - Some(WPARAM(0)), - Some(LPARAM(&data as *const _ as isize)), + WM_COPYDATA as u32, + WPARAM(0), + LPARAM(&data as *const _ as isize), ); tracing::info!(attempt, "handed the link to the running shell"); return true; @@ -138,7 +137,8 @@ pub(crate) fn install_receiver() { // SAFETY: `FindWindowW` takes static literals, and `SetWindowSubclass` is given // our own `wnd_proc` plus a plain id; the window handle is one the OS just returned. unsafe { - if let Ok(hwnd) = FindWindowW(None, windows::core::w!("Punktfunk")) { + let hwnd = FindWindowW(None, windows::core::w!("Punktfunk")); + if !hwnd.0.is_null() { // Subclassing (rather than replacing the window proc) is what lets the // WinUI window keep behaving as itself; the same mechanism the stream // input hooks already use. @@ -162,7 +162,7 @@ unsafe extern "system" fn wnd_proc( _id: usize, _data: usize, ) -> LRESULT { - if msg == WM_COPYDATA { + if msg == WM_COPYDATA as u32 { // SAFETY: for `WM_COPYDATA` the OS marshals the sender's `COPYDATASTRUCT` and its buffer // into THIS process and keeps both valid for the duration of the handler — that is the // guarantee this relies on, not the sender's honesty, which is why a hostile sender can at @@ -207,11 +207,11 @@ pub(crate) fn queue(url: String) { /// it valid across updates, since the install path changes and the alias doesn't. pub(crate) fn write_shortcut(label: &str, url: &str) -> Result { use windows::core::{Interface, HSTRING}; - use windows::Win32::System::Com::{ - CoCreateInstance, CoInitializeEx, IPersistFile, CLSCTX_INPROC_SERVER, - COINIT_APARTMENTTHREADED, - }; - use windows::Win32::UI::Shell::{IShellLinkW, ShellLink}; + use windows::Win32::combaseapi::{CoCreateInstance, CoInitializeEx}; + use windows::Win32::objbase::COINIT_APARTMENTTHREADED; + use windows::Win32::objidl::IPersistFile; + use windows::Win32::shobjidl_core::{IShellLinkW, ShellLink}; + use windows::Win32::wtypesbase::CLSCTX_INPROC_SERVER; let desktop = std::env::var("USERPROFILE") .map(|p| std::path::PathBuf::from(p).join("Desktop")) @@ -224,20 +224,24 @@ pub(crate) fn write_shortcut(label: &str, url: &str) -> Result String { - // SAFETY: a read-only COM call on the live `adapter` borrow, filling a descriptor returned by - // value; `&IDXGIAdapter` is a reference-counted wrapper, so the borrow IS the liveness. + // SAFETY: a read-only COM call on the live `adapter` borrow, filling a zeroed local + // descriptor through the out-param, checked before the descriptor is read; `&IDXGIAdapter` + // is a reference-counted wrapper, so the borrow IS the liveness. unsafe { - adapter - .GetDesc() - .map(|d| { - String::from_utf16_lossy(&d.Description) - .trim_end_matches('\0') - .to_string() - }) - .unwrap_or_else(|_| "".into()) + let mut d: windows::Win32::dxgi::DXGI_ADAPTER_DESC = std::mem::zeroed(); + if adapter.GetDesc(&mut d).is_ok() { + String::from_utf16_lossy(&d.Description) + .trim_end_matches('\0') + .to_string() + } else { + "".into() + } } } @@ -59,10 +60,14 @@ pub fn adapter_names() -> Vec { let mut names: Vec = Vec::new(); for a in all_adapters() { let desc1 = a - .cast::() - // SAFETY: a read-only COM call on the adapter just cast, filling a descriptor by value. - .and_then(|a1| unsafe { a1.GetDesc1() }) - .ok(); + .cast::() + .ok() + // SAFETY: a read-only COM call on the adapter just cast, filling a zeroed local + // descriptor through the out-param, discarded unless the call reports success. + .and_then(|a1| unsafe { + let mut d: windows::Win32::dxgi::DXGI_ADAPTER_DESC1 = std::mem::zeroed(); + a1.GetDesc1(&mut d).is_ok().then_some(d) + }); let name = adapter_name(&a); // Forensics for the next duplicate/oddity report — which adapters DXGI actually // returned, and whether the repeats share a LUID (one adapter enumerated twice) diff --git a/clients/windows/src/main.rs b/clients/windows/src/main.rs index e740f00f..80644027 100644 --- a/clients/windows/src/main.rs +++ b/clients/windows/src/main.rs @@ -55,7 +55,7 @@ fn main() { // parent console; it allocates nothing and dereferences no caller memory, and failure (no parent // console) is ignored by design. unsafe { - use windows::Win32::System::Console::{AttachConsole, ATTACH_PARENT_PROCESS}; + use windows::Win32::consoleapi::{AttachConsole, ATTACH_PARENT_PROCESS}; let _ = AttachConsole(ATTACH_PARENT_PROCESS); } set_app_user_model_id(); @@ -172,9 +172,9 @@ fn main() { /// processes are left alone. Must run before any window exists. #[cfg(windows)] fn set_app_user_model_id() { - use windows::Win32::Foundation::APPMODEL_ERROR_NO_PACKAGE; - use windows::Win32::Storage::Packaging::Appx::GetCurrentPackageFullName; - use windows::Win32::UI::Shell::SetCurrentProcessExplicitAppUserModelID; + use windows::Win32::appmodel::GetCurrentPackageFullName; + use windows::Win32::shobjidl_core::SetCurrentProcessExplicitAppUserModelID; + use windows::Win32::winerror::APPMODEL_ERROR_NO_PACKAGE; // SAFETY: `GetCurrentPackageFullName` is called with `len = 0` and no buffer, which is the // documented identity PROBE — it writes nothing and only reports whether this process is // packaged; `SetCurrentProcessExplicitAppUserModelID` takes a static wide literal. diff --git a/clients/windows/src/shell_window.rs b/clients/windows/src/shell_window.rs index 24c528a2..c0a58fa9 100644 --- a/clients/windows/src/shell_window.rs +++ b/clients/windows/src/shell_window.rs @@ -10,8 +10,8 @@ //! `stream::window_dpi`. use std::sync::atomic::{AtomicIsize, Ordering}; -use windows::Win32::Foundation::{HWND, RECT}; -use windows::Win32::UI::WindowsAndMessaging::{ +use windows::Win32::windef::{HWND, RECT}; +use windows::Win32::winuser::{ FindWindowW, GetWindowRect, IsWindow, SetForegroundWindow, ShowWindow, SW_HIDE, SW_SHOW, }; @@ -29,7 +29,10 @@ fn shell_hwnd() -> Option { return Some(h); } } - let h = FindWindowW(None, windows::core::w!("Punktfunk")).ok()?; + let h = FindWindowW(None, windows::core::w!("Punktfunk")); + if h.0.is_null() { + return None; + } SHELL_HWND.store(h.0 as isize, Ordering::Relaxed); Some(h) } @@ -68,6 +71,8 @@ pub(crate) fn position() -> Option<(i32, i32)> { let h = shell_hwnd()?; let mut r = RECT::default(); // SAFETY: `h` is the validated shell window handle and `r` is a live local the call fills. - unsafe { GetWindowRect(h, &mut r).ok()? }; + if !unsafe { GetWindowRect(h, &mut r) }.as_bool() { + return None; + } Some((r.left, r.top)) } diff --git a/crates/pf-client-core/Cargo.toml b/crates/pf-client-core/Cargo.toml index 51376757..da91cb08 100644 --- a/crates/pf-client-core/Cargo.toml +++ b/crates/pf-client-core/Cargo.toml @@ -58,19 +58,20 @@ sdl3 = { version = "0.18", features = ["hidapi", "build-from-source"] } # D3D11VA decode (video_d3d11.rs): device/adapter selection, DXVA probes, and the shared # NT-handle hand-off ring. Same pinned rev as clients/windows so the workspace builds ONE # windows-rs. -windows = { git = "https://github.com/microsoft/windows-rs", rev = "a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f", features = [ - "Win32_Foundation", - "Win32_Graphics_Direct3D", - "Win32_Graphics_Direct3D11", - "Win32_Graphics_Dxgi", - "Win32_Graphics_Dxgi_Common", - # IDXGIResource1::CreateSharedHandle takes an optional SECURITY_ATTRIBUTES — the - # method itself is feature-gated behind this. - "Win32_Security", +windows = { git = "https://github.com/microsoft/windows-rs", rev = "acb5a1a7441033d9312b16842af02eb0c2b403dc", features = [ + # Features are header-named since windows-rs generates from the SDK headers directly + # (#4689) — one feature per header, replacing the old `Win32_*` namespace features. + "d3d11", + "d3dcommon", + "dxgi", + "handleapi", + # IDXGIResource1::CreateSharedHandle takes an optional SECURITY_ATTRIBUTES. + "minwinbase", + # The GlobalAlloc block the clipboard takes ownership of (clipboard.rs). + "winbase", # The OS-clipboard bridge (clipboard.rs): Open/Get/SetClipboardData + the sequence - # number, and the GlobalAlloc block the clipboard takes ownership of. - "Win32_System_DataExchange", - "Win32_System_Memory", + # number — all in winuser now. + "winuser", ] } [features] diff --git a/crates/pf-client-core/src/clipboard.rs b/crates/pf-client-core/src/clipboard.rs index cdaa50be..c3a7454b 100644 --- a/crates/pf-client-core/src/clipboard.rs +++ b/crates/pf-client-core/src/clipboard.rs @@ -278,14 +278,14 @@ mod os { use super::{MIME_PNG, MIME_TEXT}; use anyhow::{anyhow, bail, Result}; use windows::core::PCWSTR; - use windows::Win32::Foundation::{HANDLE, HGLOBAL}; - use windows::Win32::System::DataExchange::{ + use windows::Win32::minwindef::HGLOBAL; + use windows::Win32::winbase::{ + GlobalAlloc, GlobalLock, GlobalSize, GlobalUnlock, GMEM_MOVEABLE, + }; + use windows::Win32::winuser::{ CloseClipboard, EmptyClipboard, GetClipboardData, GetClipboardSequenceNumber, IsClipboardFormatAvailable, OpenClipboard, RegisterClipboardFormatW, SetClipboardData, }; - use windows::Win32::System::Memory::{ - GlobalAlloc, GlobalLock, GlobalSize, GlobalUnlock, GMEM_MOVEABLE, - }; const CF_UNICODETEXT: u32 = 13; @@ -307,7 +307,7 @@ mod os { // A retry loop: another app can hold the clipboard for a moment. for _ in 0..10 { // SAFETY: takes no pointer; `None` is the documented "associate with no window" argument. - if unsafe { OpenClipboard(None) }.is_ok() { + if unsafe { OpenClipboard(None) }.as_bool() { return Ok(Clip); } std::thread::sleep(std::time::Duration::from_millis(10)); @@ -331,18 +331,18 @@ mod os { pub fn is_concealed() -> bool { let fmt = registered("ExcludeClipboardContentFromMonitorProcessing"); // SAFETY: a scalar format id in, a status out; reads nothing through a pointer. - unsafe { IsClipboardFormatAvailable(fmt) }.is_ok() + unsafe { IsClipboardFormatAvailable(fmt) }.as_bool() } /// The wire kinds the current clipboard can supply, with size hints where they're free. pub fn available_kinds() -> Vec<(&'static str, u64)> { let mut out = Vec::new(); // SAFETY: as above — a scalar format id, status out. - if unsafe { IsClipboardFormatAvailable(CF_UNICODETEXT) }.is_ok() { + if unsafe { IsClipboardFormatAvailable(CF_UNICODETEXT) }.as_bool() { out.push((MIME_TEXT, 0)); } // SAFETY: as above — a scalar format id, status out. - if unsafe { IsClipboardFormatAvailable(png_format()) }.is_ok() { + if unsafe { IsClipboardFormatAvailable(png_format()) }.as_bool() { out.push((MIME_PNG, 0)); } out @@ -354,8 +354,10 @@ mod os { match mime { MIME_TEXT => { // SAFETY: the clipboard is open (the `Clip` guard); the handle returned is BORROWED from the clipboard and stays valid while it is open, so it is never freed here. - let h = unsafe { GetClipboardData(CF_UNICODETEXT) }?; - let g = HGLOBAL(h.0); + let g: HGLOBAL = unsafe { GetClipboardData(CF_UNICODETEXT) }; + if g.0.is_null() { + bail!("clipboard text unavailable"); + } // SAFETY: `g` is that borrowed clipboard handle; `GlobalLock` yields a pointer valid until the matching `GlobalUnlock` below. let p = unsafe { GlobalLock(g) } as *const u16; if p.is_null() { @@ -378,8 +380,10 @@ mod os { } MIME_PNG => { // SAFETY: as the text path — the handle is borrowed from the open clipboard, never freed here. - let h = unsafe { GetClipboardData(png_format()) }?; - let g = HGLOBAL(h.0); + let g: HGLOBAL = unsafe { GetClipboardData(png_format()) }; + if g.0.is_null() { + bail!("clipboard png unavailable"); + } // SAFETY: `g` is that borrowed handle; the pointer is valid until the matching unlock. let p = unsafe { GlobalLock(g) } as *const u8; if p.is_null() { @@ -411,10 +415,15 @@ mod os { }; let _clip = Clip::open()?; // SAFETY: no arguments; the clipboard is open and owned by this thread via the `Clip` guard. - unsafe { EmptyClipboard() }?; + if !unsafe { EmptyClipboard() }.as_bool() { + bail!("clipboard clear failed"); + } // The clipboard OWNS this block once SetClipboardData succeeds — do not free it. // SAFETY: a size in, an owned moveable handle out — ownership passes to the clipboard at `SetClipboardData` below. - let g = unsafe { GlobalAlloc(GMEM_MOVEABLE, payload.len()) }?; + let g = unsafe { GlobalAlloc(GMEM_MOVEABLE as u32, payload.len()) }; + if g.0.is_null() { + bail!("clipboard alloc failed"); + } // SAFETY: `g` is the handle just allocated; the pointer is valid until the matching unlock. let p = unsafe { GlobalLock(g) } as *mut u8; if p.is_null() { @@ -425,7 +434,9 @@ mod os { // SAFETY: releases the lock taken above, before the handle is handed to the clipboard. let _ = unsafe { GlobalUnlock(g) }; // SAFETY: ownership of `g` transfers to the clipboard here, which is why nothing frees it afterwards. - unsafe { SetClipboardData(fmt, Some(HANDLE(g.0))) }?; + if unsafe { SetClipboardData(fmt, Some(g)) }.0.is_null() { + bail!("clipboard set failed"); + } Ok(()) } } diff --git a/crates/pf-client-core/src/video_d3d11.rs b/crates/pf-client-core/src/video_d3d11.rs index 45f975be..2a0160c1 100644 --- a/crates/pf-client-core/src/video_d3d11.rs +++ b/crates/pf-client-core/src/video_d3d11.rs @@ -43,9 +43,7 @@ use ffmpeg_next as ffmpeg; use std::ffi::c_void; use std::ptr; use windows::core::{Interface, GUID}; -use windows::Win32::Foundation::{HANDLE, RECT}; -use windows::Win32::Graphics::Direct3D::{D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1}; -use windows::Win32::Graphics::Direct3D11::{ +use windows::Win32::d3d11::{ D3D11CreateDevice, ID3D11Device, ID3D11DeviceContext, ID3D11Multithread, ID3D11Texture2D, ID3D11VideoContext1, ID3D11VideoDevice, ID3D11VideoProcessor, ID3D11VideoProcessorEnumerator, ID3D11VideoProcessorOutputView, D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, @@ -57,19 +55,20 @@ use windows::Win32::Graphics::Direct3D11::{ D3D11_VIDEO_USAGE_PLAYBACK_NORMAL, D3D11_VPIV_DIMENSION_TEXTURE2D, D3D11_VPOV_DIMENSION_TEXTURE2D, }; -use windows::Win32::Graphics::Dxgi::Common::{ - DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, - DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020, DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601, - DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709, DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020, - DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020, DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601, - DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709, DXGI_FORMAT, DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_NV12, DXGI_FORMAT_P010, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_RATIONAL, - DXGI_SAMPLE_DESC, -}; -use windows::Win32::Graphics::Dxgi::{ +use windows::Win32::d3dcommon::{D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1}; +use windows::Win32::dxgi::{ CreateDXGIFactory1, IDXGIAdapter1, IDXGIFactory1, IDXGIKeyedMutex, IDXGIResource1, - DXGI_ADAPTER_FLAG_SOFTWARE, DXGI_SHARED_RESOURCE_READ, DXGI_SHARED_RESOURCE_WRITE, + DXGI_ADAPTER_DESC1, DXGI_ADAPTER_FLAG_SOFTWARE, DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, + DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020, + DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601, DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709, + DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020, DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020, + DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601, DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709, + DXGI_FORMAT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_NV12, DXGI_FORMAT_P010, + DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_RATIONAL, DXGI_SAMPLE_DESC, DXGI_SHARED_RESOURCE_READ, + DXGI_SHARED_RESOURCE_WRITE, }; +use windows::Win32::windef::RECT; +use windows::Win32::winnt::HANDLE; /// Ring of shareable hand-off textures. Bounds how many decoded-but-unpresented frames can /// exist without a slot being rewritten under an in-flight older frame: the pump's decoded @@ -298,12 +297,14 @@ fn create_device(luid: Option<[u8; 8]>) -> Result<(ID3D11Device, ID3D11DeviceCon let Ok(adapter) = (unsafe { factory.EnumAdapters1(i) }) else { break; }; - // SAFETY: a COM call on the adapter just enumerated, filling a descriptor returned by - // value. - let Ok(desc) = (unsafe { adapter.GetDesc1() }) else { + // SAFETY: `DXGI_ADAPTER_DESC1` is plain-old-data, so all-zeroes is a valid value. + let mut desc: DXGI_ADAPTER_DESC1 = unsafe { std::mem::zeroed() }; + // SAFETY: a COM call on the adapter just enumerated, filling the zeroed local descriptor + // through the out-param; checked before the descriptor is read. + if unsafe { adapter.GetDesc1(&mut desc) }.is_err() { continue; - }; - if desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE.0 as u32 != 0 { + } + if desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE as u32 != 0 { continue; // WARP can't hardware-decode; software decode covers that box anyway } if fallback.is_none() { @@ -334,16 +335,17 @@ fn create_device(luid: Option<[u8; 8]>) -> Result<(ID3D11Device, ID3D11DeviceCon unsafe { D3D11CreateDevice( &adapter, - windows::Win32::Graphics::Direct3D::D3D_DRIVER_TYPE_UNKNOWN, - None, - D3D11_CREATE_DEVICE_VIDEO_SUPPORT | D3D11_CREATE_DEVICE_BGRA_SUPPORT, + windows::Win32::d3dcommon::D3D_DRIVER_TYPE_UNKNOWN, + windows::Win32::minwindef::HINSTANCE(std::ptr::null_mut()), + (D3D11_CREATE_DEVICE_VIDEO_SUPPORT | D3D11_CREATE_DEVICE_BGRA_SUPPORT) as u32, Some(&[D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0]), - D3D11_SDK_VERSION, + D3D11_SDK_VERSION as u32, Some(&mut device), None, Some(&mut context), ) } + .ok() .context("D3D11CreateDevice")?; let device = device.ok_or_else(|| anyhow!("D3D11CreateDevice returned no device"))?; let context = context.ok_or_else(|| anyhow!("D3D11CreateDevice returned no context"))?; @@ -376,7 +378,7 @@ impl Drop for Slot { // SAFETY: `self.handle` is the shared-texture NT handle this slot owns; `Drop` runs once, // so it is closed exactly once and never used after. unsafe { - let _ = windows::Win32::Foundation::CloseHandle(self.handle); + let _ = windows::Win32::handleapi::CloseHandle(self.handle); } } } @@ -451,10 +453,10 @@ impl SharedRing { }, Usage: D3D11_USAGE_DEFAULT, // RENDER_TARGET: the video processor's output view renders into it. - BindFlags: (D3D11_BIND_SHADER_RESOURCE.0 | D3D11_BIND_RENDER_TARGET.0) as u32, + BindFlags: (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) as u32, CPUAccessFlags: 0, - MiscFlags: (D3D11_RESOURCE_MISC_SHARED_NTHANDLE.0 - | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX.0) as u32, + MiscFlags: (D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) + as u32, }; let mut slots = Vec::with_capacity(RING_SLOTS); for _ in 0..RING_SLOTS { @@ -462,6 +464,7 @@ impl SharedRing { // SAFETY: a `?`-checked `CreateTexture2D` on the live device, over a fully-initialized // stack descriptor and a live `Option` out-param. unsafe { device.CreateTexture2D(&desc, None, Some(&mut tex)) } + .ok() .context("create shared hand-off texture")?; let tex: ID3D11Texture2D = tex.expect("CreateTexture2D succeeded"); let mutex: IDXGIKeyedMutex = @@ -473,7 +476,7 @@ impl SharedRing { let handle = unsafe { resource.CreateSharedHandle( None, - (DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE).0, + DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE as u32, None, ) } @@ -494,6 +497,7 @@ impl SharedRing { Some(&mut out_view), ) } + .ok() .context("CreateVideoProcessorOutputView")?; let out_view = out_view.expect("output view created"); slots.push(Slot { @@ -735,6 +739,7 @@ impl D3d11vaDecoder { let mut in_view = None; video_device .CreateVideoProcessorInputView(&src, &ring.enumerator, &iv_desc, Some(&mut in_view)) + .ok() .context("CreateVideoProcessorInputView")?; let in_view = in_view.expect("input view created"); diff --git a/scripts/gen-third-party-notices.py b/scripts/gen-third-party-notices.py index e99e5211..53a5fa4a 100755 --- a/scripts/gen-third-party-notices.py +++ b/scripts/gen-third-party-notices.py @@ -45,6 +45,13 @@ def find_license_files(pkg_dir): return out +# Crates that ship license-mit/license-apache-2.0 files but omit the `license` field in +# their Cargo.toml (publish = false upstream), so `cargo metadata` reports no SPDX for them. +LICENSE_OVERRIDES = { + "windows-reactor-setup": "MIT OR Apache-2.0", +} + + # Third-party source trees VENDORED inside first-party workspace crates — the # workspace-member skip in main() hides them from `cargo metadata`, so they are listed # here explicitly: (label, license file relative to the repo root, source URL). @@ -146,7 +153,7 @@ def main(): w("MANIFEST (crate version — SPDX license — source)") w("-" * 76) for p in pkgs: - lic = p.get("license") or (("file: " + p["license_file"]) if p.get("license_file") else "UNKNOWN") + lic = p.get("license") or LICENSE_OVERRIDES.get(p["name"]) or (("file: " + p["license_file"]) if p.get("license_file") else "UNKNOWN") repo = p.get("repository") or "" w(f' {p["name"]} {p["version"]} — {lic}' + (f' — {repo}' if repo else "")) w("") @@ -156,7 +163,7 @@ def main(): w("Crates whose package did not embed a license file (SPDX + source only)") w("-" * 76) for p in no_text: - lic = p.get("license") or "UNKNOWN" + lic = p.get("license") or LICENSE_OVERRIDES.get(p["name"]) or "UNKNOWN" repo = p.get("repository") or "" w(f' {p["name"]} {p["version"]} — {lic}' + (f' — {repo}' if repo else "")) w("")