mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-09-01 19:51:34 +02:00
dev/migrie/f/fallbackv2-impl
8 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ed7595f3a7 |
Harden IPC pipe ownership and shutdown lifecycle (#48902)
## Summary of the Pull Request The two-way named-pipe IPC server (`TwoWayPipeMessageIPC`, shared by the runner, Settings, and Quick Access host) created every pipe instance without `FILE_FLAG_FIRST_PIPE_INSTANCE`. If a pipe with the same name already existed — for example a leftover instance from a previous run or another process — `CreateNamedPipe` would quietly create an *additional* instance and share the name instead of owning it. This makes `start_named_pipe_server` create the **first** instance with `FILE_FLAG_FIRST_PIPE_INSTANCE`, so `CreateNamedPipe` fails fast on a name collision and the server is the authoritative owner of its pipe name. ## PR Checklist - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized (N/A — no user-facing strings) - [x] **Dev docs:** Added/updated (N/A) - [x] **New binaries:** Added on the required places (N/A — no new binaries) ## Detailed Description of the Pull Request / Additional comments - The flag is applied **only** to the first instance. Subsequent instances continue to omit it, so the existing `PIPE_UNLIMITED_INSTANCES` behavior is fully preserved. - The change is contained to a single function in `src/common/interop/two_way_pipe_message_ipc.cpp`. Public signatures and the `PowerToys.Interop` ABI are unchanged, so the runner, Settings, and Quick Access host all benefit without any code changes on their side. ## Validation Steps Performed - The existing `Common.Interop.UnitTests` `TestSend` exercises the modified first-instance code path (`Start()` → `start_named_pipe_server`) and continues to pass — a full IPC round-trip still works. - Verified the updated `CreateNamedPipe` open-mode logic compiles cleanly. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 49797c8c-784d-47e6-bc0f-53464eecec4b |
||
|
|
1980ca5ece |
[Runner][Interop] Authenticate Settings/Quick Access named-pipe clients before dispatch (CWE-732/CWE-862) (#49527)
## Summary of the Pull Request
The Runner is the **server** for the two-way named pipes it uses to talk
to `PowerToys.Settings.exe` and the Quick Access host, and it dispatched
privileged JSON commands (`killrunner`, `restart_elevation`,
`module_status`, `powertoys`, `language`, ...) **without authenticating
the caller**. When PowerToys runs elevated ("Run as administrator"), the
pipe DACL grants the shared **Logon SID**, so **any same-user Medium-IL
process could connect and inject commands** — a local privilege
escalation (CWE-732 / CWE-862). The pipe DACL cannot distinguish the
legitimate Medium-IL Settings child from a same-user attacker (identical
user SID, integrity level, and logon session), so this PR authenticates
the connecting process's **binary identity** before any dispatch.
## PR Checklist
- [x] **Tests:** Added/updated and all pass (native gate tests + C#
regression)
- [x] **Localization:** No new end-user-facing strings (only a
diagnostic runner log line)
- [x] **New binaries:** None — the new code compiles into the existing
`PowerToys.Interop` and `runner` binaries; tests were added to the
existing `Common.Utils.UnitTests` project
## Detailed Description of the Pull Request / Additional comments
New `src/common/interop/pipe_caller_auth.{h,cpp}` adds
`interop_auth::AuthenticateClient`, invoked from
`TwoWayPipeMessageIPC::handle_pipe_connection` **before** a message is
queued (fail-closed). A connecting client is accepted only if it is:
- under the **Runner-relative install directory**
(`get_module_folderpath()\WinUI3Apps`, so it adapts to installed and
dev-build layouts),
- an **allow-listed basename** (`PowerToys.Settings.exe` /
`PowerToys.QuickAccess.exe`),
- the Runner's **exact file version** (anti-downgrade), and
- **Microsoft Authenticode-signed**.
The signature is anchored to the **LOCAL MACHINE root store**
(`HCCE_LOCAL_MACHINE` +
`CertVerifyCertificateChainPolicy(AUTHENTICODE)`) rather than
`WinVerifyTrust`'s default user+machine union: the Runner runs as the
same user as a potential attacker and would otherwise trust a forged
signer added to `CurrentUser\Root`. Verdicts are cached per `(pid,
process-creation-time, policy)` with a short TTL so the check isn't
re-run on every message (each `send` opens a new connection). Rejections
are logged.
The gate is added via an **additive** `start(HANDLE, CallerPolicy)`
overload; the managed `start(nullptr)` path is unchanged (gate
disabled), so there is **no ABI break** to `PowerToys.Interop`.
`PIPE_REJECT_REMOTE_CLIENTS` is also set. In **Debug** builds only the
signature check is relaxed (directory/basename/version stay enforced) so
local unsigned builds still connect; the relaxation is compiled out of
Release.
**Scope:** this PR covers the two elevated Runner-server pipes (Settings
+ Quick Access), which are the actual EoP surface. The reverse
Runner->Settings response direction, the duplicated Workspaces
transport, and the AdvancedPaste/PowerDisplay module pipes are
intentionally out of scope and can be handled as follow-ups.
## Validation Steps Performed
**Automated**
- **Native unit tests** (`Common.Utils.UnitTests`,
`PipeCallerAuthTests`): legitimate self-caller accepted; wrong
basename/directory rejected with the reject-log callback firing; version
reading. 6/6 pass.
- **C# regression** (`Microsoft.Interop.Tests.TestSend`): managed
gate-disabled round-trip still works.
- **Builds:** runner Debug + Release, `PowerToys.Interop` Debug +
Release, and the test project all build/link clean.
**Official signed build (validates the Release-only signature path that
local Debug builds skip)**
- Queued the internal "PowerToys Signed YAML Release Build" for this
branch — **green** (`result: succeeded`). The produced installers are
Authenticode `Valid`, signer `Microsoft Corporation`.
**Manual testing on the signed installer (elevated Runner) — passed**
- Installed the signed build and ran the Runner **as administrator**.
Settings and Quick Access open and are fully functional; settings apply,
module toggles work, and the hotkey-conflict request/response
round-trips.
- **No** `Rejected unauthenticated ...` lines during legitimate use →
the genuine signed `PowerToys.Settings.exe` is accepted by the
machine-root signature + version + directory checks (verified in
`RunnerLogs\runner-log_*.log`, requests dispatched normally).
- **Security (negative) check:** a non-elevated `powershell.exe`
discovered the runner pipe via the pipe namespace and attempted
`{"killrunner":true}`; the write failed ("Pipe is broken") because the
Runner rejected the caller and disconnected before dispatch.
`PowerToys.exe` stayed running and logged: `Rejected unauthenticated
Settings pipe client: pid=... image='...\powershell.exe'
reason=bad-directory`.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1d8f85ec-aaee-468a-9348-ba79b059cbaf
|
||
|
|
d127511c7d |
Fix runner APPLICATION_HANG_QUIESCE: handle WM_ENDSESSION and skip blocking shutdown cleanup (#48363)
## Summary The runner WndProc (`tray_icon_window_proc`) does not handle `WM_QUERYENDSESSION` / `WM_ENDSESSION`, **and** its `WM_DESTROY` teardown performs blocking cross-process cleanup. Both contribute to the Watson failure `APPLICATION_HANG_QUIESCE_cfffffff_PowerToys.exe!run_message_loop` on OS shutdown, sign-out, or restart: 1. Without a `WM_ENDSESSION` handler, `DefWindowProc` returns `0` without posting a quit message, so `run_message_loop` stays parked in `GetMessageW` until the OS quiesce timeout (~5 s) force-terminates the process. 2. Even once teardown starts, `WM_DESTROY` calls `close_settings_window()`, which blocks up to 1.5 s on `WaitForSingleObject` against `PowerToys.Settings.exe` (`src/runner/settings_window.cpp:712`), plus `Shell_NotifyIcon(NIM_DELETE)` during Explorer teardown. The Windows [shutdown guidance](https://learn.microsoft.com/windows/win32/shutdown/shutting-down) is explicit that handlers must not block. This PR fixes both issues for the always-on runner. Rollout to module-owned windows is intentionally separate and tracked in #49539. > Supersedes #48378 (same Watson bucket) by combining its no-blocking-cleanup fix with a reusable helper and unit tests. The cleanup-skip insight is credited to @yeelam-gordon. Related (same failure class, different binary): #41260. ## Root cause `src/runner/tray_icon.cpp` → `tray_icon_window_proc` had no case for `WM_QUERYENDSESSION` / `WM_ENDSESSION`, and `WM_DESTROY` unconditionally ran cross-process cleanup. On a full Windows session end, the OS delivers `WM_ENDSESSION` to child applications and reaps them independently, so the runner's waits consume the quiesce budget without helping shutdown complete. ## Fix ### 1. Explicitly stateless helper in `src/common/utils/window.h` `handle_stateless_session_end_message`: - `WM_QUERYENDSESSION` → returns `TRUE`. The name makes clear that this helper is only for processes with no unsaved user state. - `WM_ENDSESSION(TRUE)` → calls `DestroyWindow(window)`, driving the existing `WM_DESTROY → PostQuitMessage(0)` path so `run_message_loop` unwinds. - `WM_ENDSESSION(FALSE)` → leaves the window alone because another application cancelled shutdown. - The optional `out_system_session_ending` flag is set only when the full Windows session is ending. `ENDSESSION_CLOSEAPP` still closes the runner but leaves the flag false so Restart Manager requests retain normal child-process cleanup. Stateful modules must implement their own save/permission behavior rather than adopt this helper. `tray_icon_window_proc` calls it at the top of dispatch and returns immediately when the message is handled. ### 2. Skip blocking cleanup only for a full Windows session end `WM_DESTROY` branches on `g_system_session_ending`: - **User-initiated close or Restart Manager `ENDSESSION_CLOSEAPP`:** unchanged full cleanup (`Shell_NotifyIcon(NIM_DELETE)`, `close_settings_window()`, and `QuickAccessHost::stop()`). - **Full OS shutdown, sign-out, or restart:** posts `WM_QUIT` without waiting on child processes the OS is already reaping in parallel. ### Scope and follow-up This PR intentionally fixes the highest-volume contributor: the always-on runner. Native module processes with their own windows/message loops require module-specific review before adopting the pattern; that inventory and rollout is tracked in #49539. ### Why not centralize handling inside `run_message_loop`? `WM_QUERYENDSESSION` / `WM_ENDSESSION` invoke the WndProc directly during `GetMessage`; they do not appear as a `MSG` returned to the loop. Handling must therefore live in, or be called from, each relevant WndProc. ## Tests 8 focused tests in `src/common/UnitTests-CommonUtils/Window.Tests.cpp`: | Test | Guards | |---|---| | `HandleStatelessSessionEndMessage_QueryEndSession_AllowsShutdown` | `WM_QUERYENDSESSION` returns `TRUE`. | | `HandleStatelessSessionEndMessage_EndSessionCancelled_DoesNotTearDown` | `WM_ENDSESSION(FALSE)` does not destroy the window. | | `HandleStatelessSessionEndMessage_EndSessionConfirmed_TearsDownAndExitsLoop` | `WM_ENDSESSION(TRUE)` destroys the window and exits before the longer timer fallback. | | `HandleStatelessSessionEndMessage_UnrelatedMessage_NotHandled` | Unrelated messages fall through untouched. | | `HandleStatelessSessionEndMessage_EndSessionConfirmed_SignalsSystemSessionEnding` | A full session end enables the no-wait teardown path. | | `HandleStatelessSessionEndMessage_CloseApp_DoesNotSignalSystemSessionEnding` | Restart Manager closes the window while retaining normal child cleanup. | | `HandleStatelessSessionEndMessage_EndSessionCancelled_DoesNotSignalSystemSessionEnding` | Cancelled shutdown does not flag teardown. | | `HandleStatelessSessionEndMessage_QueryEndSession_DoesNotSignalSystemSessionEnding` | The query phase does not flag teardown. | **Build:** `runner.vcxproj` and `UnitTests-CommonUtils.vcxproj` build clean (`x64|Release`). The 8 focused tests pass. ## Manual validation 1. Build PowerToys and start the runner. 2. Initiate a sign-off (`logoff`) or restart. 3. Confirm Event Viewer (`Windows Logs → Application`) shows no `Application Hang` event for `PowerToys.exe`. 4. Right-click tray → Exit: confirm Settings.exe and the Quick Access host shut down gracefully and no ghost tray icon remains. (#48378 additionally captured real logoff/restart runs showing `WM_ENDSESSION → WM_DESTROY` completing in 1–8 ms with no hang events—the same full-session path used here.) ## Quality checklist - [x] Linked work item: AB#55588441 - [x] Module follow-up: #49539 - [x] Cross-references #41260; supersedes #48378 - [x] Unit tests (8 in `Window.Tests.cpp`) - [x] No new binaries - [x] Localization: no end-user strings changed - [x] Shared helper documents its stateless contract Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8d70b986-081a-43dd-bbfd-7e6351baef7a |
||
|
|
f81689de3a |
[PowerDisplay] Drop redundant hardcoded PlatformToolset (inherit Cpp.Build.props) (#49370)
## Summary Remove the redundant hardcoded `<PlatformToolset>v143</PlatformToolset>` from two C++ projects so they inherit the toolset from the shared `Cpp.Build.props` like every other project. ## Why `Cpp.Build.props` is force-imported into **every** C++ project via `Directory.Build.props`: ```xml <ForceImportBeforeCppProps>$(RepoRoot)Cpp.Build.props</ForceImportBeforeCppProps> ``` MSBuild imports it during `Microsoft.Cpp.props` — i.e. *after* each project's own PropertyGroups — and it sets the toolset for the whole repo: ```xml <PlatformToolset>v143</PlatformToolset> <PlatformToolset Condition="'$(VisualStudioVersion)' == '18.0'">v145</PlatformToolset> ``` Two projects set `<PlatformToolset>v143</PlatformToolset>` directly in their Configuration PropertyGroups: - `src/modules/powerdisplay/PowerDisplayModuleInterface/PowerDisplayModuleInterface.vcxproj` (Debug + Release) - `src/common/UnitTests-CommonUtils/UnitTests-CommonUtils.vcxproj` That value was dead config — the force-imported prop already overrode it to `v145` on VS2026 (v18). The other module interfaces (Awake, FancyZones, …) don't set `PlatformToolset` at all; these two were just over-specified VS-template projects. ## Change Delete the redundant `PlatformToolset` lines so both projects inherit from `Cpp.Build.props`. ## Validation Built both projects locally with VS2026 (v18), Release x64, with no `PlatformToolset` in the vcxproj: - Both resolve to the `v145` toolset (MSVC `14.51`, `VC\v180`) via the force-imported prop. - Both produce their DLLs with no errors (`PowerToys.PowerDisplayModuleInterface.dll`, `Common.Utils.UnitTests.dll`). ## Risk Very low — no change to the produced binaries (effective toolset is unchanged); this just removes dead config and makes these two projects consistent with the rest of the repo. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
8a7933c0b2 |
Migrate spdlog from submodule to vcpkg (#48039)
## Summary Migrate `deps/spdlog` from a git submodule to **vcpkg manifest mode** with an overlay port pinned to the **exact same commit** (`gabime/spdlog@616866fc`). Replaces the polyfill shim added in #47910 with a proper port-level patch. This is the follow-up to PR #47928, which I closed after @zadjii-msft / @DHowett clarified that the intended direction was a single combined "move to vcpkg **and** apply a patch file" (one change, not two stepping stones). ## Guidance honored Per @zadjii-msft (offline): - ✅ Convert each submodule to vcpkg **one at a time** — this PR is **spdlog only**. `deps/expected-lite` stays a submodule (separate PR next). - ✅ Atomic commit per dep (multiple commits on the branch for review traceability; squash on merge gives the requested single commit). - ✅ **Don't bump the version.** Only variable changed: submodule → vcpkg. Same commit (`616866fc`, v1.8.5 + 38) the submodule pointed at. Per @DHowett ([review](https://github.com/microsoft/PowerToys/pull/48039#pullrequestreview-4338835150)): - ✅ No vcpkg submodule — vswhere-first detection via a Terminal-style `steps-install-vcpkg.yml` template; three-tier `VcpkgRoot` fallback (env var → VS-shipped → runtime clone pinned to manifest baseline). ## Design - **Repo-root manifest**: `vcpkg.json` declares only `spdlog`, with `builtin-baseline` pinned. `vcpkg-configuration.json` registers `deps/vcpkg-overlays/` as overlay-ports. - **Overlay port** `deps/vcpkg-overlays/spdlog/`: `vcpkg_from_github(REF 616866fc...)` with bundled fmt preserved (`-DSPDLOG_FMT_EXTERNAL=OFF`); the MSVC 14.51 fix from #47910 carried as a proper vcpkg patch on `include/spdlog/fmt/bundled/format.h`. - **vcpkg integration is global** (set in `Cpp.Build.props`, imported via `ForceImportBeforeCppProps` for every `.vcxproj`). An earlier attempt to make vcpkg per-project-opt-in via `deps/spdlog.props` failed because ~85 PowerToys `.vcxproj` files import `spdlog.props` AFTER `Microsoft.Cpp.targets`, by which point `vcpkg.props`' `ClCompile` hook is dead-on-arrival. The trade-off (every C++ project invokes `vcpkg install` once at build time, ~0.5 s on cache hits, manifest declares only spdlog so install set is fixed) is documented in the expanded `Cpp.Build.props` comment. - **`deps/spdlog.props`** is now a thin shim that only sets the historical `SPDLOG_*` preprocessor defines for source-compat. - **`Cpp.Build.targets`** is a new file imported via `ForceImportAfterCppTargets` to load `vcpkg.targets` after `Microsoft.Cpp.targets`. A fail-fast `<Target>` errors with a clear message if `vcpkg.props` can't be found at the resolved `VcpkgRoot`. - **Removes** `deps/spdlog-msvc-fix/` polyfill, in-tree wrapper `src/logging/`, spdlog submodule, the single `<ProjectReference>` in `logger.vcxproj`, plus 3 `.slnf` refs and 2 `.slnx` refs (`PowerToys.slnx` + `installer/PowerToysSetup.slnx`), plus 3 hard-coded `..\deps\spdlog\include` entries in `<AdditionalIncludeDirectories>`. - **CI**: new reusable `.pipelines/v2/templates/steps-install-vcpkg.yml` (vswhere-first, manifest-baseline-pinned fallback clone, respects `useVSPreview`). Gated `Cache@2` for `%LOCALAPPDATA%\vcpkg\archives` keyed on overlay-port contents. Same vcpkg detection added to `tools\build\build-essentials.ps1` for local devs. ## Verification Local build matrix (all 4 configs of `logger.vcxproj` and a representative late-import consumer): | Config | Result | Notes | |--------|--------|-------| | Release \| x64 | ✅ | vcpkg install ~21 s, `logger.lib` produced | | Debug \| x64 | ✅ | **Validates patch fixes the actual MSVC 14.51 bug** (`_ITERATOR_DEBUG_LEVEL > 0` → `_SECURE_SCL`) | | Release \| ARM64 | ✅ | vcpkg cross-installs `arm64-windows-static` spdlog in ~16 s | | Debug \| ARM64 | ✅ | **Previously DISABLED for the in-tree spdlog** (per `<Build Solution="Debug\|ARM64" Project="false" />` in `PowerToysSetup.slnx`); this migration FIXES that latent gap | | FancyZonesLib (Release \| x64) | ✅ | Late-import-pattern consumer; previously broke in v2 | Full PowerToys CI (x64 + arm64 + CmdPal SDK + all GitHub Actions checks) green. **Consumer audit**: 72 `.vcxproj` files reference `logger.vcxproj`; all 72 also import `deps/spdlog.props`. No transitive-link breakage. ## Out of scope (intentional) - `deps/expected-lite` migration — next PR per "one-at-a-time" rule. - Remote vcpkg binary cache (Azure Artifacts NuGet feed). Local pipeline `Cache@2` works for now, but a remote feed survives across pipelines and is the long-term answer. Happy to split this into a follow-up. ## Notes for review - Patch in the overlay port is identical content to PR #47928's patch but regenerated with LF line endings (vcpkg's `vcpkg_apply_patches` is strict; no `--ignore-whitespace`). - Once PowerToys eventually bumps spdlog past v1.14 (which ships fmt 10.2 and drops the affected code path), the overlay port can be deleted and we can use upstream vcpkg's `spdlog` directly. - Re. official-release pipelines and terrapin / less-restricted network isolation: VS-shipped vcpkg is the primary path (no network); the fallback clone is only exercised when VS doesn't ship vcpkg. Happy to wire terrapin into the fallback as a follow-up if the official build template needs it. Closes the work tracked in #47928 (which was closed unmerged). --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Dustin L. Howett <dustin@howett.net> |
||
|
|
05cd66c9bc |
[Dev][Build] .NET 10 Upgrade (#41280)
## Summary of the Pull Request .NET 10 Upgrade. Requires Visual Studio 2026. ## PR Checklist - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments - Upgraded target framework from `net9.0` to `net10.0` across all projects - Removed redundant package references now included by default in .NET 10 - Updated package versions to .NET 10 releases - Modernized regex usage with source generators for better performance - Added `vbcscompiler` to the spell-check allowlist (`.github/actions/spell-check/expect.txt`) ## Validation Steps Performed <!-- START COPILOT CODING AGENT TIPS --> --- 🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. [Learn more about Advanced Security.](https://gh.io/cca-advanced-security) --------- Co-authored-by: Jeroen van Warmerdam <jeronevw@hotmail.com> Co-authored-by: Copilot <copilot@github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> |
||
|
|
67a4d344d6 |
[Deps] Upgrade Microsoft.Windows.CppWinRT to 2.0.250303.1 (#45420)
This PR upgrades the **Microsoft.Windows.CppWinRT** NuGet package from version **2.0.240111.5** to **2.0.250303.1** across the entire PowerToys solution. |
||
|
|
27ba536872 |
UT: Add ut to protect common utils codes (#45290)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request As title <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] Closes: #xxx <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed Tests should be picked up and run and pass |