mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-08 12:18:50 +02:00
Do not run elevated by default (#884)
Make the runner not run as elevated by default. Add a setting for "run PowerToys as elevated" and buttons to restart the process with the different elevation levels.
This commit is contained in:
committed by
GitHub
parent
fd8fc679be
commit
619ed234a9
@@ -171,49 +171,49 @@ WindowState get_window_state(HWND hwnd) {
|
|||||||
return RESTORED;
|
return RESTORED;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_process_elevated() {
|
bool is_process_elevated() {
|
||||||
HANDLE token = nullptr;
|
HANDLE token = nullptr;
|
||||||
bool elevated = false;
|
bool elevated = false;
|
||||||
|
|
||||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
|
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
|
||||||
TOKEN_ELEVATION elevation;
|
TOKEN_ELEVATION elevation;
|
||||||
DWORD size;
|
DWORD size;
|
||||||
if (GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size)) {
|
if (GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size)) {
|
||||||
elevated = (elevation.TokenIsElevated != 0);
|
elevated = (elevation.TokenIsElevated != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token) {
|
if (token) {
|
||||||
CloseHandle(token);
|
CloseHandle(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
return elevated;
|
return elevated;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool drop_elevated_privileges() {
|
bool drop_elevated_privileges() {
|
||||||
HANDLE token = nullptr;
|
HANDLE token = nullptr;
|
||||||
LPCTSTR lpszPrivilege = SE_SECURITY_NAME;
|
LPCTSTR lpszPrivilege = SE_SECURITY_NAME;
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT | WRITE_OWNER, &token)) {
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT | WRITE_OWNER, &token)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PSID medium_sid = NULL;
|
PSID medium_sid = NULL;
|
||||||
if (!::ConvertStringSidToSid(SDDL_ML_MEDIUM, &medium_sid)) {
|
if (!::ConvertStringSidToSid(SDDL_ML_MEDIUM, &medium_sid)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOKEN_MANDATORY_LABEL label = { 0 };
|
TOKEN_MANDATORY_LABEL label = { 0 };
|
||||||
label.Label.Attributes = SE_GROUP_INTEGRITY;
|
label.Label.Attributes = SE_GROUP_INTEGRITY;
|
||||||
label.Label.Sid = medium_sid;
|
label.Label.Sid = medium_sid;
|
||||||
DWORD size = (DWORD)sizeof(TOKEN_MANDATORY_LABEL) + ::GetLengthSid(medium_sid);
|
DWORD size = (DWORD)sizeof(TOKEN_MANDATORY_LABEL) + ::GetLengthSid(medium_sid);
|
||||||
|
|
||||||
BOOL result = SetTokenInformation(token, TokenIntegrityLevel, &label, size);
|
BOOL result = SetTokenInformation(token, TokenIntegrityLevel, &label, size);
|
||||||
LocalFree(medium_sid);
|
LocalFree(medium_sid);
|
||||||
CloseHandle(token);
|
CloseHandle(token);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring get_process_path(DWORD pid) noexcept {
|
std::wstring get_process_path(DWORD pid) noexcept {
|
||||||
auto process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, TRUE, pid);
|
auto process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, TRUE, pid);
|
||||||
std::wstring name;
|
std::wstring name;
|
||||||
@@ -225,12 +225,93 @@ std::wstring get_process_path(DWORD pid) noexcept {
|
|||||||
}
|
}
|
||||||
name.resize(name_length);
|
name.resize(name_length);
|
||||||
CloseHandle(process);
|
CloseHandle(process);
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring get_process_path(HWND window) noexcept {
|
bool run_elevated(const std::wstring& file, const std::wstring& params) {
|
||||||
const static std::wstring app_frame_host = L"ApplicationFrameHost.exe";
|
SHELLEXECUTEINFOW exec_info = { 0 };
|
||||||
|
exec_info.cbSize = sizeof(SHELLEXECUTEINFOW);
|
||||||
|
exec_info.lpVerb = L"runas";
|
||||||
|
exec_info.lpFile = file.c_str();
|
||||||
|
exec_info.lpParameters = params.c_str();
|
||||||
|
exec_info.hwnd = 0;
|
||||||
|
exec_info.fMask = SEE_MASK_NOCLOSEPROCESS;
|
||||||
|
exec_info.lpDirectory = 0;
|
||||||
|
exec_info.hInstApp = 0;
|
||||||
|
|
||||||
|
if (ShellExecuteExW(&exec_info)) {
|
||||||
|
return exec_info.hProcess != nullptr;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run_non_elevated(const std::wstring& file, const std::wstring& params) {
|
||||||
|
auto executable_args = file;
|
||||||
|
if (!params.empty()) {
|
||||||
|
executable_args += L" " + params;
|
||||||
|
}
|
||||||
|
|
||||||
|
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::make_unique<char[]>(size);
|
||||||
|
auto pptal = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(pproc_buffer.get());
|
||||||
|
|
||||||
|
if (!InitializeProcThreadAttributeList(pptal, 1, 0, &size)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE process_handle = process.get();
|
||||||
|
if (!pptal || !UpdateProcThreadAttribute(pptal,
|
||||||
|
0,
|
||||||
|
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
|
||||||
|
&process_handle,
|
||||||
|
sizeof(process_handle),
|
||||||
|
nullptr,
|
||||||
|
nullptr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
STARTUPINFOEX siex = { 0 };
|
||||||
|
siex.lpAttributeList = pptal;
|
||||||
|
siex.StartupInfo.cb = sizeof(siex);
|
||||||
|
|
||||||
|
PROCESS_INFORMATION process_info = { 0 };
|
||||||
|
auto succedded = CreateProcessW(file.c_str(),
|
||||||
|
const_cast<LPWSTR>(executable_args.c_str()),
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
FALSE,
|
||||||
|
EXTENDED_STARTUPINFO_PRESENT,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
&siex.StartupInfo,
|
||||||
|
&process_info);
|
||||||
|
if (process_info.hProcess) {
|
||||||
|
CloseHandle(process_info.hProcess);
|
||||||
|
}
|
||||||
|
if (process_info.hThread) {
|
||||||
|
CloseHandle(process_info.hThread);
|
||||||
|
}
|
||||||
|
return succedded;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring get_process_path(HWND window) noexcept {
|
||||||
|
const static std::wstring app_frame_host = L"ApplicationFrameHost.exe";
|
||||||
DWORD pid{};
|
DWORD pid{};
|
||||||
GetWindowThreadProcessId(window, &pid);
|
GetWindowThreadProcessId(window, &pid);
|
||||||
auto name = get_process_path(pid);
|
auto name = get_process_path(pid);
|
||||||
@@ -254,19 +335,29 @@ std::wstring get_process_path(HWND window) noexcept {
|
|||||||
if (new_pid != pid) {
|
if (new_pid != pid) {
|
||||||
return get_process_path(new_pid);
|
return get_process_path(new_pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring get_product_version() {
|
std::wstring get_product_version() {
|
||||||
static std::wstring version = std::to_wstring(VERSION_MAJOR) +
|
static std::wstring version = std::to_wstring(VERSION_MAJOR) +
|
||||||
L"." + std::to_wstring(VERSION_MINOR) +
|
L"." + std::to_wstring(VERSION_MINOR) +
|
||||||
L"." + std::to_wstring(VERSION_REVISION) +
|
L"." + std::to_wstring(VERSION_REVISION) +
|
||||||
L"." + std::to_wstring(VERSION_BUILD);
|
L"." + std::to_wstring(VERSION_BUILD);
|
||||||
|
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::wstring get_resource_string(UINT resource_id, HINSTANCE instance, const wchar_t* fallback) {
|
||||||
|
wchar_t* text_ptr;
|
||||||
|
auto length = LoadStringW(instance, resource_id, reinterpret_cast<wchar_t*>(&text_ptr), 0);
|
||||||
|
if (length == 0) {
|
||||||
|
return fallback;
|
||||||
|
} else {
|
||||||
|
return { text_ptr, static_cast<std::size_t>(length) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::wstring get_module_filename(HMODULE mod)
|
std::wstring get_module_filename(HMODULE mod)
|
||||||
{
|
{
|
||||||
wchar_t buffer[MAX_PATH + 1];
|
wchar_t buffer[MAX_PATH + 1];
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -51,6 +52,12 @@ bool is_process_elevated();
|
|||||||
// Drops the elevated privilages if present
|
// Drops the elevated privilages if present
|
||||||
bool drop_elevated_privileges();
|
bool drop_elevated_privileges();
|
||||||
|
|
||||||
|
// Run command as elevated user, returns true if succeeded
|
||||||
|
bool run_elevated(const std::wstring& file, const std::wstring& params);
|
||||||
|
|
||||||
|
// Run command as non-elevated user, returns true if succeeded
|
||||||
|
bool run_non_elevated(const std::wstring& file, const std::wstring& params);
|
||||||
|
|
||||||
// Get the executable path or module name for modern apps
|
// Get the executable path or module name for modern apps
|
||||||
std::wstring get_process_path(DWORD pid) noexcept;
|
std::wstring get_process_path(DWORD pid) noexcept;
|
||||||
// Get the executable path or module name for modern apps
|
// Get the executable path or module name for modern apps
|
||||||
@@ -60,3 +67,11 @@ std::wstring get_product_version();
|
|||||||
|
|
||||||
std::wstring get_module_filename(HMODULE mod = nullptr);
|
std::wstring get_module_filename(HMODULE mod = nullptr);
|
||||||
std::wstring get_module_folderpath(HMODULE mod = nullptr);
|
std::wstring get_module_folderpath(HMODULE mod = nullptr);
|
||||||
|
|
||||||
|
// Get a string from the resource file
|
||||||
|
std::wstring get_resource_string(UINT resource_id, HINSTANCE instance, const wchar_t* fallback);
|
||||||
|
// Wrapper for getting a string from the resource file. Returns the resource id text when fails.
|
||||||
|
// Requires that
|
||||||
|
// extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
// is added to the .cpp file.
|
||||||
|
#define GET_RESOURCE_STRING(resource_id) get_resource_string(resource_id, reinterpret_cast<HINSTANCE>(&__ImageBase), L#resource_id)
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <common/windows_colors.h>
|
#include <common/windows_colors.h>
|
||||||
|
|
||||||
static std::wstring settings_theme = L"system";
|
static std::wstring settings_theme = L"system";
|
||||||
|
static bool run_as_elevated = false;
|
||||||
|
|
||||||
json::JsonObject load_general_settings() {
|
json::JsonObject load_general_settings() {
|
||||||
auto loaded = PTSettingsHelper::load_general_settings();
|
auto loaded = PTSettingsHelper::load_general_settings();
|
||||||
@@ -13,6 +14,7 @@ json::JsonObject load_general_settings() {
|
|||||||
if (settings_theme != L"dark" && settings_theme != L"light") {
|
if (settings_theme != L"dark" && settings_theme != L"light") {
|
||||||
settings_theme = L"system";
|
settings_theme = L"system";
|
||||||
}
|
}
|
||||||
|
run_as_elevated = loaded.GetNamedBoolean(L"run_elevated", false);
|
||||||
return loaded;
|
return loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,6 +29,9 @@ json::JsonObject get_general_settings() {
|
|||||||
}
|
}
|
||||||
result.SetNamedValue(L"enabled", std::move(enabled));
|
result.SetNamedValue(L"enabled", std::move(enabled));
|
||||||
|
|
||||||
|
bool is_elevated = is_process_elevated();
|
||||||
|
result.SetNamedValue(L"is_elevated", json::value(is_elevated));
|
||||||
|
result.SetNamedValue(L"run_elevated", json::value(run_as_elevated));
|
||||||
result.SetNamedValue(L"theme", json::value(settings_theme));
|
result.SetNamedValue(L"theme", json::value(settings_theme));
|
||||||
result.SetNamedValue(L"system_theme", json::value(WindowsColors::is_dark_mode() ? L"dark" : L"light"));
|
result.SetNamedValue(L"system_theme", json::value(WindowsColors::is_dark_mode() ? L"dark" : L"light"));
|
||||||
result.SetNamedValue(L"powertoys_version", json::value(get_product_version()));
|
result.SetNamedValue(L"powertoys_version", json::value(get_product_version()));
|
||||||
@@ -68,6 +73,7 @@ void apply_general_settings(const json::JsonObject& general_configs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
run_as_elevated = general_configs.GetNamedBoolean(L"run_elevated", false);
|
||||||
if (json::has(general_configs, L"theme", json::JsonValueType::String)) {
|
if (json::has(general_configs, L"theme", json::JsonValueType::String)) {
|
||||||
settings_theme = general_configs.GetNamedString(L"theme");
|
settings_theme = general_configs.GetNamedString(L"theme");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <common/json.h>
|
#include <common/json.h>
|
||||||
|
|
||||||
|
json::JsonObject load_general_settings();
|
||||||
json::JsonObject get_general_settings();
|
json::JsonObject get_general_settings();
|
||||||
void apply_general_settings(const json::JsonObject & general_configs);
|
void apply_general_settings(const json::JsonObject & general_configs);
|
||||||
void start_initial_powertoys();
|
void start_initial_powertoys();
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#include "lowlevel_keyboard_event.h"
|
#include "lowlevel_keyboard_event.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "general_settings.h"
|
#include "general_settings.h"
|
||||||
|
#include "restart_elevated.h"
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
#include <common/dpi_aware.h>
|
#include <common/dpi_aware.h>
|
||||||
|
|
||||||
@@ -14,6 +16,9 @@
|
|||||||
#include "unhandled_exception_handler.h"
|
#include "unhandled_exception_handler.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
|
||||||
|
|
||||||
void chdir_current_executable() {
|
void chdir_current_executable() {
|
||||||
// Change current directory to the path of the executable.
|
// Change current directory to the path of the executable.
|
||||||
WCHAR executable_path[MAX_PATH];
|
WCHAR executable_path[MAX_PATH];
|
||||||
@@ -24,16 +29,7 @@ void chdir_current_executable() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
|
int runner() {
|
||||||
WCHAR username[UNLEN + 1];
|
|
||||||
DWORD username_length = UNLEN + 1;
|
|
||||||
GetUserNameW(username, &username_length);
|
|
||||||
auto runner_mutex = CreateMutexW(NULL, TRUE, (std::wstring(L"Local\\PowerToyRunMutex") + username).c_str());
|
|
||||||
if (runner_mutex == NULL || GetLastError() == ERROR_ALREADY_EXISTS) {
|
|
||||||
// The app is already running
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPIAware::EnableDPIAwarenessForThisProcess();
|
DPIAware::EnableDPIAwarenessForThisProcess();
|
||||||
|
|
||||||
#if _DEBUG && _WIN64
|
#if _DEBUG && _WIN64
|
||||||
@@ -46,12 +42,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
start_tray_icon();
|
start_tray_icon();
|
||||||
int result;
|
int result;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Singletons initialization order needs to be preserved, first events and
|
|
||||||
// then modules to guarantee the reverse destruction order.
|
|
||||||
powertoys_events();
|
|
||||||
modules();
|
|
||||||
|
|
||||||
chdir_current_executable();
|
chdir_current_executable();
|
||||||
// Load Powertyos DLLS
|
// Load Powertyos DLLS
|
||||||
// For now only load known DLLs
|
// For now only load known DLLs
|
||||||
@@ -76,11 +66,59 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
Trace::EventLaunch(get_product_version());
|
Trace::EventLaunch(get_product_version());
|
||||||
|
|
||||||
result = run_message_loop();
|
result = run_message_loop();
|
||||||
} catch (std::runtime_error& err) {
|
} catch (std::runtime_error & err) {
|
||||||
std::string err_what = err.what();
|
std::string err_what = err.what();
|
||||||
MessageBoxW(NULL, std::wstring(err_what.begin(),err_what.end()).c_str(), L"Error", MB_OK | MB_ICONERROR);
|
MessageBoxW(NULL, std::wstring(err_what.begin(), err_what.end()).c_str(), L"Error", MB_OK | MB_ICONERROR);
|
||||||
result = -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
Trace::UnregisterProvider();
|
Trace::UnregisterProvider();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
|
||||||
|
WCHAR username[UNLEN + 1];
|
||||||
|
DWORD username_length = UNLEN + 1;
|
||||||
|
GetUserNameW(username, &username_length);
|
||||||
|
auto runner_mutex = CreateMutexW(NULL, TRUE, (std::wstring(L"Local\\PowerToyRunMutex") + username).c_str());
|
||||||
|
if (runner_mutex == NULL || GetLastError() == ERROR_ALREADY_EXISTS) {
|
||||||
|
// The app is already running
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
try {
|
||||||
|
// Singletons initialization order needs to be preserved, first events and
|
||||||
|
// then modules to guarantee the reverse destruction order.
|
||||||
|
SystemMenuHelperInstace();
|
||||||
|
powertoys_events();
|
||||||
|
modules();
|
||||||
|
|
||||||
|
auto general_settings = load_general_settings();
|
||||||
|
int rvalue = 0;
|
||||||
|
if (is_process_elevated() ||
|
||||||
|
general_settings.GetNamedBoolean(L"run_elevated", false) == false ||
|
||||||
|
strcmp(lpCmdLine, "--dont-elevate") == 0) {
|
||||||
|
result = runner();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
schedule_restart_as_elevated();
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::runtime_error & err) {
|
||||||
|
std::string err_what = err.what();
|
||||||
|
MessageBoxW(NULL, std::wstring(err_what.begin(), err_what.end()).c_str(), GET_RESOURCE_STRING(IDS_ERROR).c_str(), MB_OK | MB_ICONERROR);
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
ReleaseMutex(runner_mutex);
|
||||||
|
CloseHandle(runner_mutex);
|
||||||
|
if (is_restart_scheduled()) {
|
||||||
|
if (restart_if_scheduled() == false) {
|
||||||
|
auto text = is_process_elevated() ? GET_RESOURCE_STRING(IDS_COULDNOT_RESTART_NONELEVATED) :
|
||||||
|
GET_RESOURCE_STRING(IDS_COULDNOT_RESTART_ELEVATED);
|
||||||
|
MessageBoxW(NULL, text.c_str(), GET_RESOURCE_STRING(IDS_ERROR).c_str(), MB_OK | MB_ICONERROR);
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stop_tray_icon();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#define APPICON 101
|
#define APPICON 101
|
||||||
#define ID_TRAY_MENU 102
|
#define ID_TRAY_MENU 102
|
||||||
|
#define IDS_COULDNOT_RESTART_NONELEVATED 103
|
||||||
|
#define IDS_COULDNOT_RESTART_ELEVATED 104
|
||||||
|
#define IDS_ERROR 105
|
||||||
#define ID_EXIT_MENU_COMMAND 40001
|
#define ID_EXIT_MENU_COMMAND 40001
|
||||||
#define ID_SETTINGS_MENU_COMMAND 40002
|
#define ID_SETTINGS_MENU_COMMAND 40002
|
||||||
#define ID_ABOUT_MENU_COMMAND 40003
|
#define ID_ABOUT_MENU_COMMAND 40003
|
||||||
|
|||||||
37
src/runner/restart_elevated.cpp
Normal file
37
src/runner/restart_elevated.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "restart_elevated.h"
|
||||||
|
#include "common/common.h"
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
None,
|
||||||
|
RestartAsElevated,
|
||||||
|
RestartAsNonElevated
|
||||||
|
};
|
||||||
|
static State state = None;
|
||||||
|
|
||||||
|
void schedule_restart_as_elevated() {
|
||||||
|
state = RestartAsElevated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void schedule_restart_as_non_elevated() {
|
||||||
|
state = RestartAsNonElevated;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_restart_scheduled() {
|
||||||
|
return state != None;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool restart_if_scheduled() {
|
||||||
|
// Make sure we have enough room, even for the long (\\?\) paths
|
||||||
|
constexpr DWORD exe_path_size = 0xFFFF;
|
||||||
|
auto exe_path = std::make_unique<wchar_t[]>(exe_path_size);
|
||||||
|
GetModuleFileNameW(nullptr, exe_path.get(), exe_path_size);
|
||||||
|
switch (state) {
|
||||||
|
case RestartAsElevated:
|
||||||
|
return run_elevated(exe_path.get(), {});
|
||||||
|
case RestartAsNonElevated:
|
||||||
|
return run_non_elevated(exe_path.get(), L"--dont-elevate");
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/runner/restart_elevated.h
Normal file
5
src/runner/restart_elevated.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
void schedule_restart_as_elevated();
|
||||||
|
void schedule_restart_as_non_elevated();
|
||||||
|
bool is_restart_scheduled();
|
||||||
|
bool restart_if_scheduled();
|
||||||
Binary file not shown.
@@ -63,7 +63,7 @@
|
|||||||
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
<UACExecutionLevel>AsInvoker</UACExecutionLevel>
|
||||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||||
</Link>
|
</Link>
|
||||||
<Manifest>
|
<Manifest>
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
<UACExecutionLevel>AsInvoker</UACExecutionLevel>
|
||||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||||
</Link>
|
</Link>
|
||||||
<Manifest>
|
<Manifest>
|
||||||
@@ -106,6 +106,7 @@
|
|||||||
<ClCompile Include="powertoys_events.cpp" />
|
<ClCompile Include="powertoys_events.cpp" />
|
||||||
<ClCompile Include="powertoy_module.cpp" />
|
<ClCompile Include="powertoy_module.cpp" />
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
|
<ClCompile Include="restart_elevated.cpp" />
|
||||||
<ClCompile Include="settings_window.cpp" />
|
<ClCompile Include="settings_window.cpp" />
|
||||||
<ClCompile Include="system_menu_helper.cpp" />
|
<ClCompile Include="system_menu_helper.cpp" />
|
||||||
<ClCompile Include="trace.cpp" />
|
<ClCompile Include="trace.cpp" />
|
||||||
@@ -121,6 +122,7 @@
|
|||||||
<ClInclude Include="powertoys_events.h" />
|
<ClInclude Include="powertoys_events.h" />
|
||||||
<ClInclude Include="powertoy_module.h" />
|
<ClInclude Include="powertoy_module.h" />
|
||||||
<ClInclude Include="resource.h" />
|
<ClInclude Include="resource.h" />
|
||||||
|
<ClInclude Include="restart_elevated.h" />
|
||||||
<ClInclude Include="settings_window.h" />
|
<ClInclude Include="settings_window.h" />
|
||||||
<ClInclude Include="system_menu_helper.h" />
|
<ClInclude Include="system_menu_helper.h" />
|
||||||
<ClInclude Include="trace.h" />
|
<ClInclude Include="trace.h" />
|
||||||
|
|||||||
@@ -36,6 +36,9 @@
|
|||||||
<ClCompile Include="system_menu_helper.cpp">
|
<ClCompile Include="system_menu_helper.cpp">
|
||||||
<Filter>Utils</Filter>
|
<Filter>Utils</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="restart_elevated.cpp">
|
||||||
|
<Filter>Utils</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
@@ -73,6 +76,9 @@
|
|||||||
<ClInclude Include="system_menu_helper.h">
|
<ClInclude Include="system_menu_helper.h">
|
||||||
<Filter>Utils</Filter>
|
<Filter>Utils</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="restart_elevated.h">
|
||||||
|
<Filter>Utils</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Utils">
|
<Filter Include="Utils">
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "tray_icon.h"
|
#include "tray_icon.h"
|
||||||
#include "general_settings.h"
|
#include "general_settings.h"
|
||||||
#include "common/windows_colors.h"
|
#include "common/windows_colors.h"
|
||||||
|
#include "common/common.h"
|
||||||
|
#include "restart_elevated.h"
|
||||||
|
|
||||||
#include <common/json.h>
|
#include <common/json.h>
|
||||||
|
|
||||||
@@ -48,10 +50,25 @@ void dispatch_json_action_to_module(const json::JsonObject& powertoys_configs)
|
|||||||
for (const auto& powertoy_element : powertoys_configs)
|
for (const auto& powertoy_element : powertoys_configs)
|
||||||
{
|
{
|
||||||
const std::wstring name{ powertoy_element.Key().c_str() };
|
const std::wstring name{ powertoy_element.Key().c_str() };
|
||||||
if (modules().find(name) != modules().end())
|
// Currently, there is only one custom action in the general settings screen,
|
||||||
|
// so it has to be the "restart as (non-)elevated" button.
|
||||||
|
if (name == L"general")
|
||||||
|
{
|
||||||
|
if (is_process_elevated())
|
||||||
|
{
|
||||||
|
schedule_restart_as_non_elevated();
|
||||||
|
PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
schedule_restart_as_elevated();
|
||||||
|
PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (modules().find(name) != modules().end())
|
||||||
{
|
{
|
||||||
const auto element = powertoy_element.Value().Stringify();
|
const auto element = powertoy_element.Value().Stringify();
|
||||||
modules().at(name).call_custom_action(element.c_str());
|
modules().at(name).call_custom_action(element.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,10 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
Shell_NotifyIcon(NIM_DELETE, &tray_icon_data);
|
if (tray_icon_created) {
|
||||||
|
Shell_NotifyIcon(NIM_DELETE, &tray_icon_data);
|
||||||
|
tray_icon_created = false;
|
||||||
|
}
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
break;
|
break;
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
@@ -171,3 +174,9 @@ void start_tray_icon() {
|
|||||||
tray_icon_created = Shell_NotifyIcon(NIM_ADD, &tray_icon_data) == TRUE;
|
tray_icon_created = Shell_NotifyIcon(NIM_ADD, &tray_icon_data) == TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stop_tray_icon() {
|
||||||
|
if (tray_icon_created) {
|
||||||
|
SendMessage(tray_icon_hwnd, WM_CLOSE, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
// Start the Tray Icon
|
// Start the Tray Icon
|
||||||
void start_tray_icon();
|
void start_tray_icon();
|
||||||
|
// Stop the Tray Icon
|
||||||
|
void stop_tray_icon();
|
||||||
// Open the Settings Window
|
// Open the Settings Window
|
||||||
void open_settings_window();
|
void open_settings_window();
|
||||||
// Callback type to be called by the tray icon loop
|
// Callback type to be called by the tray icon loop
|
||||||
|
|||||||
@@ -29,7 +29,11 @@ export class CustomActionSettingsControl extends BaseSettingsControl {
|
|||||||
public render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
<Label>{this.state.property_values.display_name}</Label>
|
{
|
||||||
|
this.state.property_values.display_name ?
|
||||||
|
<Label>{this.state.property_values.display_name}</Label>
|
||||||
|
: null
|
||||||
|
}
|
||||||
{
|
{
|
||||||
this.state.property_values.value ?
|
this.state.property_values.value ?
|
||||||
<Text styles ={{
|
<Text styles ={{
|
||||||
|
|||||||
@@ -3,16 +3,21 @@ import { Stack, Text, PrimaryButton, Label, Link, loadTheme } from 'office-ui-fa
|
|||||||
import { BoolToggleSettingsControl } from './BoolToggleSettingsControl'
|
import { BoolToggleSettingsControl } from './BoolToggleSettingsControl'
|
||||||
import { ChoiceGroupSettingsControl } from './ChoiceGroupSettingsControl'
|
import { ChoiceGroupSettingsControl } from './ChoiceGroupSettingsControl'
|
||||||
import { Separator } from 'office-ui-fabric-react/lib/Separator';
|
import { Separator } from 'office-ui-fabric-react/lib/Separator';
|
||||||
|
import { CustomActionSettingsControl } from './CustomActionSettingsControl';
|
||||||
|
|
||||||
export class GeneralSettings extends React.Component <any, any> {
|
export class GeneralSettings extends React.Component <any, any> {
|
||||||
references: any = {};
|
references: any = {};
|
||||||
startup_reference: any;
|
startup_reference: any;
|
||||||
|
elevated_reference: any;
|
||||||
|
restart_reference: any;
|
||||||
theme_reference: any;
|
theme_reference: any;
|
||||||
parent_on_change: Function;
|
parent_on_change: Function;
|
||||||
constructor(props: any) {
|
constructor(props: any) {
|
||||||
super(props);
|
super(props);
|
||||||
this.references={};
|
this.references={};
|
||||||
this.startup_reference=null;
|
this.startup_reference=null;
|
||||||
|
this.elevated_reference=null;
|
||||||
|
this.restart_reference=null;
|
||||||
this.parent_on_change = props.on_change;
|
this.parent_on_change = props.on_change;
|
||||||
this.state = {
|
this.state = {
|
||||||
settings_key: props.settings_key,
|
settings_key: props.settings_key,
|
||||||
@@ -38,6 +43,7 @@ export class GeneralSettings extends React.Component <any, any> {
|
|||||||
let result : any = {};
|
let result : any = {};
|
||||||
result[this.state.settings_key]= {
|
result[this.state.settings_key]= {
|
||||||
startup: this.startup_reference.get_value().value,
|
startup: this.startup_reference.get_value().value,
|
||||||
|
run_elevated: this.elevated_reference.get_value().value,
|
||||||
theme: this.theme_reference.get_value().value,
|
theme: this.theme_reference.get_value().value,
|
||||||
enabled: enabled
|
enabled: enabled
|
||||||
};
|
};
|
||||||
@@ -120,6 +126,34 @@ export class GeneralSettings extends React.Component <any, any> {
|
|||||||
on_change={this.parent_on_change}
|
on_change={this.parent_on_change}
|
||||||
ref={(input) => {this.startup_reference=input;}}
|
ref={(input) => {this.startup_reference=input;}}
|
||||||
/>
|
/>
|
||||||
|
<BoolToggleSettingsControl
|
||||||
|
setting={{display_name: 'By default, run PowerToys with elevated privileges', value: this.state.settings.general.run_elevated}}
|
||||||
|
on_change={this.parent_on_change}
|
||||||
|
ref={(input) => {this.elevated_reference=input;}}
|
||||||
|
/>
|
||||||
|
<CustomActionSettingsControl
|
||||||
|
setting={{
|
||||||
|
display_name: '',
|
||||||
|
value: this.state.settings.general.is_elevated ?
|
||||||
|
'PowerToys is currently running with elevated privileges. You can restart it to run non-elevated only for this session, without changing the default setting.' :
|
||||||
|
'PowerToys is currently running without elevated privileges. You can restart it to run elevated only for this session, without changing the default setting.',
|
||||||
|
button_text: this.state.settings.general.is_elevated ?
|
||||||
|
'Restart without elevated privileges' :
|
||||||
|
'Restart with elevated privileges'
|
||||||
|
}}
|
||||||
|
action_name={'restart_elevation'}
|
||||||
|
action_callback={(action_name: any, value:any) => {
|
||||||
|
(window as any).output_from_webview(JSON.stringify({
|
||||||
|
action: {
|
||||||
|
general: {
|
||||||
|
action_name,
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
ref={(input) => {this.restart_reference=input;}}
|
||||||
|
/>
|
||||||
<ChoiceGroupSettingsControl
|
<ChoiceGroupSettingsControl
|
||||||
setting={{display_name: 'Chose Settings color',
|
setting={{display_name: 'Chose Settings color',
|
||||||
value: this.state.settings.general.theme,
|
value: this.state.settings.general.theme,
|
||||||
|
|||||||
2
src/settings/settings-html/dist/bundle.js
vendored
2
src/settings/settings-html/dist/bundle.js
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user