/
githubmirror
/
PowerToys
Обзор
Документация
Войти
/
githubmirror
/
PowerToys
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/modules/Workspaces/WorkspacesSnapshotTool/SnapshotUtils.cpp
210 строк
8 KB
Kai Tao
Workspaces: PWA apps should not necessarily configure profile to launch. (#39971)
17 июн 2025, 10:39
Не верифицирован
17 июн 2025, 10:39
c487638
Код
Авторство
О чём код?
#include "pch.h" #include "SnapshotUtils.h" #include <common/utils/elevation.h> #include <common/utils/process_path.h> #include <common/utils/resources.h> #include <common/notifications/NotificationUtil.h> #include <workspaces-common/WindowEnumerator.h> #include <workspaces-common/WindowFilter.h> #include <WorkspacesLib/AppUtils.h> #include <WorkspacesLib/PwaHelper.h> #include <WorkspacesLib/WindowUtils.h> #include <WindowProperties/WorkspacesWindowPropertyUtils.h> #include "Generated Files/resource.h" #pragma comment(lib, "ntdll.lib") namespace SnapshotUtils { namespace NonLocalizable { const std::wstring ApplicationFrameHost = L"ApplicationFrameHost.exe"; } bool IsProcessElevated(DWORD processID) { wil::unique_handle hProcess{ OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processID) }; wil::unique_handle token; if (OpenProcessToken(hProcess.get(), TOKEN_QUERY, &token)) { TOKEN_ELEVATION elevation; DWORD size; if (GetTokenInformation(token.get(), TokenElevation, &elevation, sizeof(elevation), &size)) { return elevation.TokenIsElevated != 0; } } return false; } std::vector<WorkspacesData::WorkspacesProject::Application> GetApps(bool isGuidNeeded, const std::function<unsigned int(HWND)> getMonitorNumberFromWindowHandle, const std::function<WorkspacesData::WorkspacesProject::Monitor::MonitorRect(unsigned int)> getMonitorRect) { Utils::PwaHelper pwaHelper{}; std::vector<WorkspacesData::WorkspacesProject::Application> apps{}; auto installedApps = Utils::Apps::GetAppsList(); auto windows = WindowEnumerator::Enumerate(WindowFilter::Filter); for (const auto window : windows) { if (WindowFilter::FilterPopup(window)) { continue; } // filter by window rect size RECT rect = WindowUtils::GetWindowRect(window); if (rect.right - rect.left <= 0 || rect.bottom - rect.top <= 0) { continue; } // filter by window title std::wstring title = WindowUtils::GetWindowTitle(window); if (title.empty()) { continue; } Logger::info("Try to get window app:{}", reinterpret_cast<void*>(window)); DWORD pid{}; GetWindowThreadProcessId(window, &pid); // filter by app path std::wstring processPath = get_process_path(window); if (processPath.empty()) { // When PT runs not as admin, it can't get the process path of the window of the elevated process. // Notify the user that running as admin is required to process elevated windows. if (!is_process_elevated() && IsProcessElevated(pid)) { auto notificationUtil = std::make_unique<notifications::NotificationUtil>(); notificationUtil->WarnIfElevationIsRequired(GET_RESOURCE_STRING(IDS_PROJECTS), GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED), GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_LEARN_MORE), GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_DIALOG_DONT_SHOW_AGAIN)); } continue; } if (WindowUtils::IsExcludedByDefault(window, processPath)) { continue; } // fix for the packaged apps that are not caught when minimized, e.g. Settings, Microsoft ToDo, ... if (processPath.ends_with(NonLocalizable::ApplicationFrameHost)) { for (auto otherWindow : windows) { DWORD otherPid{}; GetWindowThreadProcessId(otherWindow, &otherPid); // searching for the window with the same title but different PID if (pid != otherPid && title == WindowUtils::GetWindowTitle(otherWindow)) { processPath = get_process_path(otherPid); break; } } } auto data = Utils::Apps::GetApp(processPath, pid, installedApps); if (!data.has_value() || data->name.empty()) { Logger::info(L"Installed app not found:{},{}", reinterpret_cast<void*>(window), processPath); continue; } if (!data->IsSteamGame() && !WindowUtils::HasThickFrame(window)) { // Only care about steam games if it has no thick frame to remain consistent with // the behavior as before. continue; } Logger::info(L"Found app for window:{},{}", reinterpret_cast<void*>(window), processPath); auto appData = data.value(); bool isEdge = appData.IsEdge(); bool isChrome = appData.IsChrome(); if (isEdge || isChrome) { auto windowAumid = Utils::GetAUMIDFromWindow(window); std::optional<std::wstring> pwaAppId{}; if (isEdge) { pwaAppId = pwaHelper.GetEdgeAppId(windowAumid); } else if (isChrome) { pwaAppId = pwaHelper.GetChromeAppId(windowAumid); } if (pwaAppId.has_value()) { auto pwaName = pwaHelper.SearchPwaName(pwaAppId.value(), windowAumid); Logger::info(L"Found {} PWA app with name {}, appId: {}", (isEdge ? L"Edge" : (isChrome ? L"Chrome" : L"unknown")), pwaName, pwaAppId.value()); appData.pwaAppId = pwaAppId.value(); appData.name = pwaName + L" (" + appData.name + L")"; // If it's pwa app, appUserModelId should be their own pwa id. appData.appUserModelId = windowAumid; } } bool isMinimized = WindowUtils::IsMinimized(window); unsigned int monitorNumber = getMonitorNumberFromWindowHandle(window); if (isMinimized) { // set the screen area as position, the values we get for the minimized windows are out of the screens' area WorkspacesData::WorkspacesProject::Monitor::MonitorRect monitorRect = getMonitorRect(monitorNumber); rect.left = monitorRect.left; rect.top = monitorRect.top; rect.right = monitorRect.left + monitorRect.width; rect.bottom = monitorRect.top + monitorRect.height; } std::wstring guid = isGuidNeeded ? WorkspacesWindowProperties::GetGuidFromHwnd(window) : L""; WorkspacesData::WorkspacesProject::Application app{ .id = guid, .name = appData.name, .title = title, .path = appData.installPath, .packageFullName = appData.packageFullName, .appUserModelId = appData.appUserModelId, .pwaAppId = appData.pwaAppId, .commandLineArgs = L"", .version = L"1", .isElevated = IsProcessElevated(pid), .canLaunchElevated = appData.canLaunchElevated, .isMinimized = isMinimized, .isMaximized = WindowUtils::IsMaximized(window), .position = WorkspacesData::WorkspacesProject::Application::Position{ .x = rect.left, .y = rect.top, .width = rect.right - rect.left, .height = rect.bottom - rect.top, }, .monitor = monitorNumber, }; apps.push_back(app); } return apps; } }