diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index f5877b1a4d..200b0b0272 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -388,6 +388,7 @@ DCOM dcomp DComposition ddf +DDLM Deact debian debugbreak @@ -1295,6 +1296,7 @@ MYTZ NAMECHANGE nameof namespace +namespaceanddescendants Navassa NCACTIVATE ncc diff --git a/installer/PowerToysSetup/PowerToys.wxs b/installer/PowerToysSetup/PowerToys.wxs index 7137f5dd53..0182c26c15 100644 --- a/installer/PowerToysSetup/PowerToys.wxs +++ b/installer/PowerToysSetup/PowerToys.wxs @@ -10,8 +10,8 @@ - - + + @@ -27,8 +27,8 @@ - - + + @@ -110,18 +110,19 @@ UninstallCommand="/silent /uninstall"> spsv; - + // Desktop may not be available on startup auto attempts = 5; for (auto i = 1; i <= attempts; i++) @@ -492,31 +492,4 @@ inline bool check_user_is_admin() freeMemory(pSID, pGroupInfo); return false; -} - -inline bool is_process_of_window_elevated(HWND window) -{ - DWORD pid = 0; - GetWindowThreadProcessId(window, &pid); - if (!pid) - { - return false; - } - - wil::unique_handle hProcess{ OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, - FALSE, - pid) }; - - 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; -} +} \ No newline at end of file diff --git a/src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp b/src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp index 5033d861e7..9b5cc732d8 100644 --- a/src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp +++ b/src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp @@ -3,11 +3,10 @@ #include #include -#include -#include #include #include #include +#include #include #include @@ -246,7 +245,30 @@ bool FancyZonesWindowUtils::IsCandidateForZoning(HWND window) bool FancyZonesWindowUtils::IsProcessOfWindowElevated(HWND window) { - return is_process_of_window_elevated(window); + DWORD pid = 0; + GetWindowThreadProcessId(window, &pid); + if (!pid) + { + return false; + } + + wil::unique_handle hProcess{ OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, + FALSE, + pid) }; + + wil::unique_handle token; + bool elevated = false; + + 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; } bool FancyZonesWindowUtils::IsExcludedByUser(const std::wstring& processPath) noexcept diff --git a/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj b/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj index 29a985d0d0..5e3406a80a 100644 --- a/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj +++ b/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj @@ -1,7 +1,7 @@  + - true @@ -171,10 +171,10 @@ - + @@ -183,12 +183,12 @@ - - + + diff --git a/src/modules/powerrename/PowerRenameUILib/packages.config b/src/modules/powerrename/PowerRenameUILib/packages.config index 6fb8530820..b2166880bb 100644 --- a/src/modules/powerrename/PowerRenameUILib/packages.config +++ b/src/modules/powerrename/PowerRenameUILib/packages.config @@ -5,5 +5,5 @@ - + \ No newline at end of file diff --git a/src/modules/powerrename/lib/PowerRenameInterfaces.h b/src/modules/powerrename/lib/PowerRenameInterfaces.h index 107be6bc86..c25333bd4d 100644 --- a/src/modules/powerrename/lib/PowerRenameInterfaces.h +++ b/src/modules/powerrename/lib/PowerRenameInterfaces.h @@ -69,7 +69,6 @@ public: IFACEMETHOD(GetSelected)(_Out_ bool* selected) = 0; IFACEMETHOD(PutSelected)(_In_ bool selected) = 0; IFACEMETHOD(GetId)(_Out_ int *id) = 0; - IFACEMETHOD(GetIconIndex)(_Out_ int* iconIndex) = 0; IFACEMETHOD(GetDepth)(_Out_ UINT* depth) = 0; IFACEMETHOD(PutDepth)(_In_ int depth) = 0; IFACEMETHOD(ShouldRenameItem)(_In_ DWORD flags, _Out_ bool* shouldRename) = 0; diff --git a/src/modules/powerrename/lib/PowerRenameItem.cpp b/src/modules/powerrename/lib/PowerRenameItem.cpp index 8106cab873..c5eccc7112 100644 --- a/src/modules/powerrename/lib/PowerRenameItem.cpp +++ b/src/modules/powerrename/lib/PowerRenameItem.cpp @@ -1,6 +1,5 @@ #include "pch.h" #include "PowerRenameItem.h" -#include int CPowerRenameItem::s_id = 0; @@ -180,16 +179,6 @@ IFACEMETHODIMP CPowerRenameItem::GetId(_Out_ int* id) return S_OK; } -IFACEMETHODIMP CPowerRenameItem::GetIconIndex(_Out_ int* iconIndex) -{ - if (m_iconIndex == -1) - { - GetIconIndexFromPath((PCWSTR)m_path, &m_iconIndex); - } - *iconIndex = m_iconIndex; - return S_OK; -} - IFACEMETHODIMP CPowerRenameItem::GetDepth(_Out_ UINT* depth) { *depth = m_depth; diff --git a/src/modules/powerrename/lib/PowerRenameItem.h b/src/modules/powerrename/lib/PowerRenameItem.h index 10610306ed..eb3cbcbd70 100644 --- a/src/modules/powerrename/lib/PowerRenameItem.h +++ b/src/modules/powerrename/lib/PowerRenameItem.h @@ -27,7 +27,6 @@ public: IFACEMETHODIMP GetSelected(_Out_ bool* selected); IFACEMETHODIMP PutSelected(_In_ bool selected); IFACEMETHODIMP GetId(_Out_ int* id); - IFACEMETHODIMP GetIconIndex(_Out_ int* iconIndex); IFACEMETHODIMP GetDepth(_Out_ UINT* depth); IFACEMETHODIMP PutDepth(_In_ int depth); IFACEMETHODIMP Reset(); diff --git a/src/runner/Resources.resx b/src/runner/Resources.resx index 9ac1b8da2f..2f5198b2d1 100644 --- a/src/runner/Resources.resx +++ b/src/runner/Resources.resx @@ -122,7 +122,4 @@ Bug report .zip file has been created on your Desktop. - - Cannot start PowerToys.Settings process non-elevated, because explorer.exe process is elevated. Consider enabling UAC. - diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp index 678a88fdbd..5d84d6847d 100644 --- a/src/runner/settings_window.cpp +++ b/src/runner/settings_window.cpp @@ -11,7 +11,6 @@ #include "restart_elevated.h" #include "UpdateUtils.h" #include "centralized_kb_hook.h" -#include "Generated Files/resource.h" #include #include @@ -21,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -199,6 +197,67 @@ void receive_json_send_to_main_thread(const std::wstring& msg) dispatch_run_on_main_ui_thread(dispatch_received_json_callback, copy); } +// Try to run the Settings process with non-elevated privileges. +BOOL run_settings_non_elevated(LPCWSTR executable_path, LPWSTR executable_args, PROCESS_INFORMATION* process_info) +{ + HWND hwnd = GetShellWindow(); + if (!hwnd) + { + return false; + } + + DWORD pid; + GetWindowThreadProcessId(hwnd, &pid); + + winrt::handle process{ OpenProcess(PROCESS_CREATE_PROCESS, FALSE, pid) }; + if (!process) + { + return false; + } + + SIZE_T size = 0; + InitializeProcThreadAttributeList(nullptr, 1, 0, &size); + auto pproc_buffer = std::unique_ptr{ new (std::nothrow) char[size] }; + auto pptal = reinterpret_cast(pproc_buffer.get()); + if (!pptal) + { + return false; + } + + if (!InitializeProcThreadAttributeList(pptal, 1, 0, &size)) + { + return false; + } + + if (!UpdateProcThreadAttribute(pptal, + 0, + PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, + &process, + sizeof(process), + nullptr, + nullptr)) + { + return false; + } + + STARTUPINFOEX siex = { 0 }; + siex.lpAttributeList = pptal; + siex.StartupInfo.cb = sizeof(siex); + + BOOL process_created = CreateProcessW(executable_path, + executable_args, + nullptr, + nullptr, + FALSE, + EXTENDED_STARTUPINFO_PRESENT, + nullptr, + nullptr, + &siex.StartupInfo, + process_info); + g_isLaunchInProgress = false; + return process_created; +} + DWORD g_settings_process_id = 0; void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::optional settings_window) @@ -296,24 +355,13 @@ void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::op if (is_process_elevated()) { - const bool explorer_is_elevated = is_process_of_window_elevated(GetShellWindow()); - if (explorer_is_elevated) + auto res = RunNonElevatedFailsafe(executable_path, executable_args, get_module_folderpath()); + process_created = res.has_value(); + if (process_created) { - MessageBoxW(nullptr, - GET_RESOURCE_STRING(IDS_CANNOT_LAUNCH_SETTINGS_NONELEVATED).c_str(), - L"PowerToys", - MB_OK | MB_ICONERROR); - } - else - { - auto res = RunNonElevatedFailsafe(executable_path, executable_args, get_module_folderpath()); - process_created = res.has_value(); - if (process_created) - { - process_info.dwProcessId = res->processID; - process_info.hProcess = res->processHandle.release(); - g_isLaunchInProgress = false; - } + process_info.dwProcessId = res->processID; + process_info.hProcess = res->processHandle.release(); + g_isLaunchInProgress = false; } } diff --git a/src/settings-ui/Settings.UI/GlobalSuppressions.cs b/src/settings-ui/Settings.UI/GlobalSuppressions.cs index 7bb4f5d3b8..e1bb2c7596 100644 --- a/src/settings-ui/Settings.UI/GlobalSuppressions.cs +++ b/src/settings-ui/Settings.UI/GlobalSuppressions.cs @@ -73,3 +73,8 @@ using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Not part of the project. WindowsAppSDK file.", Scope = "type", Target = "~T:Microsoft.WindowsAppSDK.Runtime.Packages.Singleton")] [assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1516:Elements should be separated by blank line", Justification = "Not part of the project. WindowsAppSDK file.", Scope = "type", Target = "~T:Microsoft.WindowsAppSDK.Runtime.Packages.Singleton")] [assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1516:Elements should be separated by blank line", Justification = "Not part of the project. WindowsAppSDK file.", Scope = "type", Target = "~T:Microsoft.WindowsAppSDK.Runtime.Packages.Main")] +[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "Not part of the project. WindowsAppSDK file.", Scope = "namespaceanddescendants", Target = "Microsoft.WindowsAppSDK.Runtime.Packages")] +[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1516:Elements should be separated by blank line", Justification = "Not part of the project. WindowsAppSDK file.", Scope = "namespaceanddescendants", Target = "Microsoft.WindowsAppSDK.Runtime.Packages")] +[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1403:File may only contain a single namespace", Justification = "Not part of the project. WindowsAppSDK file.", Scope = "namespaceanddescendants", Target = "Microsoft.WindowsAppSDK.Runtime.Packages.DDLM")] +[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Not part of the project. WindowsAppSDK file.", Scope = "namespaceanddescendants", Target = "Microsoft.WindowsAppSDK.Runtime.Packages.DDLM")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1636:File header copyright text should match", Justification = "Not part of the project. WindowsAppSDK file.", Scope = "module")] diff --git a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj index c721a13f83..94631ee13c 100644 --- a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj +++ b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj @@ -56,7 +56,7 @@ - +