Files
PowerToys/src/runner/quick_access_host.cpp

309 lines
10 KiB
C++
Raw Normal View History

Settings Flyout improvement (#43840) <!-- 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 This pull request introduces the new Quick Access feature to PowerToys by integrating its host process management into the runner and system tray. The changes add the Quick Access host implementation, update project and build files to include it, and modify the runner and tray icon logic to launch and interact with the Quick Access UI. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43694 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [x] **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 - [ ] **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 <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/7390a706-171c-479f-a4a2-999b18cfc65f" /> <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/99e99bc9-b1a3-46c6-b648-81e3048dec1b" /> <img width="490" height="350" alt="image" src="https://github.com/user-attachments/assets/2cce4ad6-a54e-4587-87b7-fdc7fba1f54f" /> <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com> Signed-off-by: Shuai Yuan <shuai.yuan.zju@gmail.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-01-07 16:38:09 +08:00
#include "pch.h"
#include "quick_access_host.h"
#include <mutex>
#include <string>
#include <vector>
#include <rpc.h>
#include <new>
#include <memory>
#include <common/logger/logger.h>
#include <common/utils/process_path.h>
#include <common/interop/two_way_pipe_message_ipc.h>
#include <wil/resource.h>
extern void receive_json_send_to_main_thread(const std::wstring& msg);
namespace
{
wil::unique_handle quick_access_process;
Feat: New tray-icon that adapts to theme change (#33321) <!-- 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 This idea comes from @Shomnipotence. It replaces the old tray icon with a new outlined design and adapts to windows' theme changes. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] **Closes:** #xxx - [ ] **Communication:** I've discussed this with core contributors already. If 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 This should be obvious enough with the video https://github.com/microsoft/PowerToys/assets/42881734/fb8f44c3-5dc0-452a-98c1-636d20b60635 <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed 1. Start powertoys, it loads the tray icon of the current theme. 2. Switch theme in windows settings, it dynamically adapts. --------- Co-authored-by: Niels Laute <niels.laute@live.nl> Co-authored-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2026-01-08 14:23:59 +08:00
wil::unique_handle quick_access_job;
Settings Flyout improvement (#43840) <!-- 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 This pull request introduces the new Quick Access feature to PowerToys by integrating its host process management into the runner and system tray. The changes add the Quick Access host implementation, update project and build files to include it, and modify the runner and tray icon logic to launch and interact with the Quick Access UI. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43694 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [x] **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 - [ ] **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 <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/7390a706-171c-479f-a4a2-999b18cfc65f" /> <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/99e99bc9-b1a3-46c6-b648-81e3048dec1b" /> <img width="490" height="350" alt="image" src="https://github.com/user-attachments/assets/2cce4ad6-a54e-4587-87b7-fdc7fba1f54f" /> <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com> Signed-off-by: Shuai Yuan <shuai.yuan.zju@gmail.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-01-07 16:38:09 +08:00
wil::unique_handle show_event;
wil::unique_handle exit_event;
std::wstring show_event_name;
std::wstring exit_event_name;
std::wstring runner_pipe_name;
std::wstring app_pipe_name;
std::unique_ptr<TwoWayPipeMessageIPC> quick_access_ipc;
std::mutex quick_access_mutex;
bool is_process_active_locked()
{
if (!quick_access_process)
{
return false;
}
DWORD exit_code = 0;
if (!GetExitCodeProcess(quick_access_process.get(), &exit_code))
{
Logger::warn(L"QuickAccessHost: failed to read Quick Access process exit code. error={}.", GetLastError());
return false;
}
return exit_code == STILL_ACTIVE;
}
void reset_state_locked()
{
if (quick_access_ipc)
{
quick_access_ipc->end();
quick_access_ipc.reset();
}
quick_access_process.reset();
Feat: New tray-icon that adapts to theme change (#33321) <!-- 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 This idea comes from @Shomnipotence. It replaces the old tray icon with a new outlined design and adapts to windows' theme changes. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] **Closes:** #xxx - [ ] **Communication:** I've discussed this with core contributors already. If 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 This should be obvious enough with the video https://github.com/microsoft/PowerToys/assets/42881734/fb8f44c3-5dc0-452a-98c1-636d20b60635 <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed 1. Start powertoys, it loads the tray icon of the current theme. 2. Switch theme in windows settings, it dynamically adapts. --------- Co-authored-by: Niels Laute <niels.laute@live.nl> Co-authored-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2026-01-08 14:23:59 +08:00
quick_access_job.reset();
Settings Flyout improvement (#43840) <!-- 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 This pull request introduces the new Quick Access feature to PowerToys by integrating its host process management into the runner and system tray. The changes add the Quick Access host implementation, update project and build files to include it, and modify the runner and tray icon logic to launch and interact with the Quick Access UI. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43694 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [x] **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 - [ ] **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 <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/7390a706-171c-479f-a4a2-999b18cfc65f" /> <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/99e99bc9-b1a3-46c6-b648-81e3048dec1b" /> <img width="490" height="350" alt="image" src="https://github.com/user-attachments/assets/2cce4ad6-a54e-4587-87b7-fdc7fba1f54f" /> <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com> Signed-off-by: Shuai Yuan <shuai.yuan.zju@gmail.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-01-07 16:38:09 +08:00
show_event.reset();
exit_event.reset();
show_event_name.clear();
exit_event_name.clear();
runner_pipe_name.clear();
app_pipe_name.clear();
}
std::wstring build_event_name(const wchar_t* suffix)
{
std::wstring name = L"Local\\PowerToysQuickAccess_";
name += std::to_wstring(GetCurrentProcessId());
if (suffix)
{
name += suffix;
}
return name;
}
std::wstring build_command_line(const std::wstring& exe_path)
{
std::wstring command_line = L"\"";
command_line += exe_path;
command_line += L"\" --show-event=\"";
command_line += show_event_name;
command_line += L"\" --exit-event=\"";
command_line += exit_event_name;
command_line += L"\"";
if (!runner_pipe_name.empty())
{
command_line.append(L" --runner-pipe=\"");
command_line += runner_pipe_name;
command_line += L"\"";
}
if (!app_pipe_name.empty())
{
command_line.append(L" --app-pipe=\"");
command_line += app_pipe_name;
command_line += L"\"";
}
return command_line;
}
}
namespace QuickAccessHost
{
bool is_running()
{
std::scoped_lock lock(quick_access_mutex);
return is_process_active_locked();
}
void start()
{
Logger::info(L"QuickAccessHost::start() called");
std::scoped_lock lock(quick_access_mutex);
if (is_process_active_locked())
{
Logger::info(L"QuickAccessHost::start: process already active");
return;
}
reset_state_locked();
show_event_name = build_event_name(L"_Show");
exit_event_name = build_event_name(L"_Exit");
show_event.reset(CreateEventW(nullptr, FALSE, FALSE, show_event_name.c_str()));
if (!show_event)
{
Logger::error(L"QuickAccessHost: failed to create show event. error={}.", GetLastError());
reset_state_locked();
return;
}
exit_event.reset(CreateEventW(nullptr, FALSE, FALSE, exit_event_name.c_str()));
if (!exit_event)
{
Logger::error(L"QuickAccessHost: failed to create exit event. error={}.", GetLastError());
reset_state_locked();
return;
}
runner_pipe_name = L"\\\\.\\pipe\\powertoys_quick_access_runner_";
app_pipe_name = L"\\\\.\\pipe\\powertoys_quick_access_ui_";
UUID temp_uuid;
wchar_t* uuid_chars = nullptr;
if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS)
{
Logger::warn(L"QuickAccessHost: failed to create UUID for pipe names. error={}.", GetLastError());
}
else if (UuidToString(&temp_uuid, reinterpret_cast<RPC_WSTR*>(&uuid_chars)) != RPC_S_OK)
{
Logger::warn(L"QuickAccessHost: failed to convert UUID to string. error={}.", GetLastError());
}
if (uuid_chars != nullptr)
{
runner_pipe_name += std::wstring(uuid_chars);
app_pipe_name += std::wstring(uuid_chars);
RpcStringFree(reinterpret_cast<RPC_WSTR*>(&uuid_chars));
uuid_chars = nullptr;
}
else
{
const std::wstring fallback_suffix = std::to_wstring(GetTickCount64());
runner_pipe_name += fallback_suffix;
app_pipe_name += fallback_suffix;
}
HANDLE token_handle = nullptr;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token_handle))
{
Logger::error(L"QuickAccessHost: failed to open process token. error={}.", GetLastError());
reset_state_locked();
return;
}
wil::unique_handle token(token_handle);
quick_access_ipc.reset(new (std::nothrow) TwoWayPipeMessageIPC(runner_pipe_name, app_pipe_name, receive_json_send_to_main_thread));
if (!quick_access_ipc)
{
Logger::error(L"QuickAccessHost: failed to allocate IPC instance.");
reset_state_locked();
return;
}
try
{
[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
2026-08-03 22:46:44 +08:00
interop_auth::CallerPolicy qa_caller_policy;
qa_caller_policy.enabled = true;
qa_caller_policy.expectedDirectory = get_module_folderpath() + L"\\WinUI3Apps";
qa_caller_policy.allowedBasenames = { L"PowerToys.QuickAccess.exe" };
qa_caller_policy.expectedVersion = interop_auth::GetOwnModuleVersion();
qa_caller_policy.requireMicrosoftSignature = true;
qa_caller_policy.logReject = [](const interop_auth::AuthResult& r) {
Logger::warn(L"Rejected unauthenticated Quick Access pipe client: pid={} image='{}' reason={}",
r.pid,
r.imagePath,
r.reasonCode);
};
quick_access_ipc->start(token.get(), qa_caller_policy);
Settings Flyout improvement (#43840) <!-- 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 This pull request introduces the new Quick Access feature to PowerToys by integrating its host process management into the runner and system tray. The changes add the Quick Access host implementation, update project and build files to include it, and modify the runner and tray icon logic to launch and interact with the Quick Access UI. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43694 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [x] **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 - [ ] **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 <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/7390a706-171c-479f-a4a2-999b18cfc65f" /> <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/99e99bc9-b1a3-46c6-b648-81e3048dec1b" /> <img width="490" height="350" alt="image" src="https://github.com/user-attachments/assets/2cce4ad6-a54e-4587-87b7-fdc7fba1f54f" /> <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com> Signed-off-by: Shuai Yuan <shuai.yuan.zju@gmail.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-01-07 16:38:09 +08:00
}
catch (...)
{
Logger::error(L"QuickAccessHost: failed to start IPC server for Quick Access.");
reset_state_locked();
return;
}
const std::wstring exe_path = get_module_folderpath() + L"\\WinUI3Apps\\PowerToys.QuickAccess.exe";
if (GetFileAttributesW(exe_path.c_str()) == INVALID_FILE_ATTRIBUTES)
{
Logger::warn(L"QuickAccessHost: missing Quick Access executable at {}", exe_path);
reset_state_locked();
return;
}
const std::wstring command_line = build_command_line(exe_path);
std::vector<wchar_t> command_line_buffer(command_line.begin(), command_line.end());
command_line_buffer.push_back(L'\0');
STARTUPINFOW startup_info{};
startup_info.cb = sizeof(startup_info);
PROCESS_INFORMATION process_info{};
Feat: New tray-icon that adapts to theme change (#33321) <!-- 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 This idea comes from @Shomnipotence. It replaces the old tray icon with a new outlined design and adapts to windows' theme changes. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] **Closes:** #xxx - [ ] **Communication:** I've discussed this with core contributors already. If 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 This should be obvious enough with the video https://github.com/microsoft/PowerToys/assets/42881734/fb8f44c3-5dc0-452a-98c1-636d20b60635 <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed 1. Start powertoys, it loads the tray icon of the current theme. 2. Switch theme in windows settings, it dynamically adapts. --------- Co-authored-by: Niels Laute <niels.laute@live.nl> Co-authored-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2026-01-08 14:23:59 +08:00
BOOL created = CreateProcessW(exe_path.c_str(), command_line_buffer.data(), nullptr, nullptr, FALSE, CREATE_SUSPENDED, nullptr, nullptr, &startup_info, &process_info);
Settings Flyout improvement (#43840) <!-- 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 This pull request introduces the new Quick Access feature to PowerToys by integrating its host process management into the runner and system tray. The changes add the Quick Access host implementation, update project and build files to include it, and modify the runner and tray icon logic to launch and interact with the Quick Access UI. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43694 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [x] **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 - [ ] **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 <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/7390a706-171c-479f-a4a2-999b18cfc65f" /> <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/99e99bc9-b1a3-46c6-b648-81e3048dec1b" /> <img width="490" height="350" alt="image" src="https://github.com/user-attachments/assets/2cce4ad6-a54e-4587-87b7-fdc7fba1f54f" /> <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com> Signed-off-by: Shuai Yuan <shuai.yuan.zju@gmail.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-01-07 16:38:09 +08:00
if (!created)
{
Logger::error(L"QuickAccessHost: failed to launch Quick Access host. error={}.", GetLastError());
reset_state_locked();
return;
}
quick_access_process.reset(process_info.hProcess);
Feat: New tray-icon that adapts to theme change (#33321) <!-- 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 This idea comes from @Shomnipotence. It replaces the old tray icon with a new outlined design and adapts to windows' theme changes. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] **Closes:** #xxx - [ ] **Communication:** I've discussed this with core contributors already. If 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 This should be obvious enough with the video https://github.com/microsoft/PowerToys/assets/42881734/fb8f44c3-5dc0-452a-98c1-636d20b60635 <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed 1. Start powertoys, it loads the tray icon of the current theme. 2. Switch theme in windows settings, it dynamically adapts. --------- Co-authored-by: Niels Laute <niels.laute@live.nl> Co-authored-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2026-01-08 14:23:59 +08:00
// Assign to job object to ensure the process is killed if the runner exits unexpectedly (e.g. debugging stop)
quick_access_job.reset(CreateJobObjectW(nullptr, nullptr));
if (quick_access_job)
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
if (!SetInformationJobObject(quick_access_job.get(), JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
{
Logger::warn(L"QuickAccessHost: failed to set job object information. error={}", GetLastError());
}
else
{
if (!AssignProcessToJobObject(quick_access_job.get(), quick_access_process.get()))
{
Logger::warn(L"QuickAccessHost: failed to assign process to job object. error={}", GetLastError());
}
}
}
else
{
Logger::warn(L"QuickAccessHost: failed to create job object. error={}", GetLastError());
}
ResumeThread(process_info.hThread);
Settings Flyout improvement (#43840) <!-- 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 This pull request introduces the new Quick Access feature to PowerToys by integrating its host process management into the runner and system tray. The changes add the Quick Access host implementation, update project and build files to include it, and modify the runner and tray icon logic to launch and interact with the Quick Access UI. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43694 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [x] **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 - [ ] **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 <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/7390a706-171c-479f-a4a2-999b18cfc65f" /> <img width="290" height="420" alt="image" src="https://github.com/user-attachments/assets/99e99bc9-b1a3-46c6-b648-81e3048dec1b" /> <img width="490" height="350" alt="image" src="https://github.com/user-attachments/assets/2cce4ad6-a54e-4587-87b7-fdc7fba1f54f" /> <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com> Signed-off-by: Shuai Yuan <shuai.yuan.zju@gmail.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-01-07 16:38:09 +08:00
CloseHandle(process_info.hThread);
}
void show()
{
start();
std::scoped_lock lock(quick_access_mutex);
if (show_event)
{
if (!SetEvent(show_event.get()))
{
Logger::warn(L"QuickAccessHost: failed to signal show event. error={}.", GetLastError());
}
}
}
void stop()
{
Logger::info(L"QuickAccessHost::stop() called");
std::unique_lock lock(quick_access_mutex);
if (exit_event)
{
SetEvent(exit_event.get());
}
if (quick_access_process)
{
const DWORD wait_result = WaitForSingleObject(quick_access_process.get(), 2000);
Logger::info(L"QuickAccessHost::stop: WaitForSingleObject result={}", wait_result);
if (wait_result == WAIT_TIMEOUT)
{
Logger::warn(L"QuickAccessHost: Quick Access process did not exit in time, terminating.");
if (!TerminateProcess(quick_access_process.get(), 0))
{
Logger::error(L"QuickAccessHost: failed to terminate Quick Access process. error={}.", GetLastError());
}
else
{
Logger::info(L"QuickAccessHost: TerminateProcess succeeded.");
WaitForSingleObject(quick_access_process.get(), 5000);
}
}
else if (wait_result == WAIT_FAILED)
{
Logger::error(L"QuickAccessHost: failed while waiting for Quick Access process. error={}.", GetLastError());
}
}
reset_state_locked();
}
}