Merged powerToys master into Launcher master

This commit is contained in:
Alekhya Reddy
2020-04-08 11:49:32 -07:00
373 changed files with 33739 additions and 7151 deletions

View File

@@ -1,6 +1,8 @@
#include "pch.h"
#include "auto_start_helper.h"
#include "general_settings.h"
#include <Lmcons.h>
#include <comdef.h>
@@ -35,7 +37,7 @@
const DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\' + User Name + '\0'
const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
bool enable_auto_start_task_for_this_user()
bool create_auto_start_task_for_this_user(bool runEvelvated)
{
HRESULT hr = S_OK;
@@ -217,8 +219,7 @@ bool enable_auto_start_task_for_this_user()
hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
// Run the task with the highest available privileges.
if (IsUserAnAdmin())
if (runEvelvated)
{
hr = pPrincipal->put_RunLevel(_TASK_RUNLEVEL::TASK_RUNLEVEL_HIGHEST);
}
@@ -231,16 +232,19 @@ bool enable_auto_start_task_for_this_user()
}
// ------------------------------------------------------
// Save the task in the PowerToys folder.
hr = pTaskFolder->RegisterTaskDefinition(
_bstr_t(wstrTaskName.c_str()),
pTask,
TASK_CREATE_OR_UPDATE,
_variant_t(username_domain),
_variant_t(),
TASK_LOGON_INTERACTIVE_TOKEN,
_variant_t(L""),
&pRegisteredTask);
ExitOnFailure(hr, "Error saving the Task : %x", hr);
{
_variant_t SDDL_FULL_ACCESS_FOR_EVERYONE = L"D:(A;;FA;;;WD)";
hr = pTaskFolder->RegisterTaskDefinition(
_bstr_t(wstrTaskName.c_str()),
pTask,
TASK_CREATE_OR_UPDATE,
_variant_t(username_domain),
_variant_t(),
TASK_LOGON_INTERACTIVE_TOKEN,
SDDL_FULL_ACCESS_FOR_EVERYONE,
&pRegisteredTask);
ExitOnFailure(hr, "Error saving the Task : %x", hr);
}
LExit:
if (pService)
@@ -261,7 +265,7 @@ LExit:
return (SUCCEEDED(hr));
}
bool disable_auto_start_task_for_this_user()
bool delete_auto_start_task_for_this_user()
{
HRESULT hr = S_OK;
@@ -313,13 +317,7 @@ bool disable_auto_start_task_for_this_user()
if (SUCCEEDED(hr))
{
// Task exists, try disabling it.
hr = pExistingRegisteredTask->put_Enabled(VARIANT_FALSE);
pExistingRegisteredTask->Release();
if (SUCCEEDED(hr))
{
// Function disable. Sounds like a success.
ExitFunction();
}
hr = pTaskFolder->DeleteTask(_bstr_t(wstrTaskName.c_str()), 0);
}
}

View File

@@ -1,4 +1,5 @@
#pragma once
bool is_auto_start_task_active_for_this_user();
bool enable_auto_start_task_for_this_user();
bool disable_auto_start_task_for_this_user();
bool create_auto_start_task_for_this_user(bool runEvelvated);
bool delete_auto_start_task_for_this_user();

View File

@@ -101,7 +101,7 @@ GeneralSettings get_settings()
for (auto& [name, powertoy] : modules())
{
settings.isModulesEnabledMap[name] = powertoy.is_enabled();
settings.isModulesEnabledMap[name] = powertoy->is_enabled();
}
return settings;
@@ -115,6 +115,8 @@ json::JsonObject get_general_settings()
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"startup", json::JsonValueType::Boolean))
{
const bool startup = general_configs.GetNamedBoolean(L"startup");
@@ -124,18 +126,33 @@ void apply_general_settings(const json::JsonObject& general_configs)
}
else
{
const bool current_startup = is_auto_start_task_active_for_this_user();
if (current_startup != startup)
if (startup)
{
if (startup)
if (is_process_elevated())
{
enable_auto_start_task_for_this_user();
delete_auto_start_task_for_this_user();
create_auto_start_task_for_this_user(general_configs.GetNamedBoolean(L"run_elevated", false));
}
else
{
disable_auto_start_task_for_this_user();
if (!is_auto_start_task_active_for_this_user())
{
delete_auto_start_task_for_this_user();
create_auto_start_task_for_this_user(false);
run_as_elevated = false;
}
else if (!general_configs.GetNamedBoolean(L"run_elevated", false))
{
delete_auto_start_task_for_this_user();
create_auto_start_task_for_this_user(false);
}
}
}
else
{
delete_auto_start_task_for_this_user();
}
}
}
if (json::has(general_configs, L"enabled"))
@@ -153,7 +170,7 @@ void apply_general_settings(const json::JsonObject& general_configs)
{
continue;
}
const bool module_inst_enabled = modules().at(name).is_enabled();
const bool module_inst_enabled = modules().at(name)->is_enabled();
const bool target_enabled = value.GetBoolean();
if (module_inst_enabled == target_enabled)
{
@@ -161,15 +178,15 @@ void apply_general_settings(const json::JsonObject& general_configs)
}
if (target_enabled)
{
modules().at(name).enable();
modules().at(name)->enable();
}
else
{
modules().at(name).disable();
modules().at(name)->disable();
}
}
}
run_as_elevated = general_configs.GetNamedBoolean(L"run_elevated", false);
if (json::has(general_configs, L"theme", json::JsonValueType::String))
{
settings_theme = general_configs.GetNamedString(L"theme");
@@ -182,45 +199,41 @@ void apply_general_settings(const json::JsonObject& general_configs)
void start_initial_powertoys()
{
bool only_enable_some_powertoys = false;
std::unordered_set<std::wstring> powertoys_to_enable;
std::unordered_set<std::wstring> powertoys_to_disable;
json::JsonObject general_settings;
try
{
general_settings = load_general_settings();
json::JsonObject enabled = general_settings.GetNamedObject(L"enabled");
for (const auto& enabled_element : enabled)
if (general_settings.HasKey(L"enabled"))
{
if (enabled_element.Value().GetBoolean())
json::JsonObject enabled = general_settings.GetNamedObject(L"enabled");
for (const auto& disabled_element : enabled)
{
// Enable this powertoy.
powertoys_to_enable.emplace(enabled_element.Key());
if (!disabled_element.Value().GetBoolean())
{
powertoys_to_disable.emplace(disabled_element.Key());
}
}
}
only_enable_some_powertoys = true;
}
catch (...)
{
// Couldn't read the general settings correctly.
// Load all powertoys.
// TODO: notify user about invalid json config
only_enable_some_powertoys = false;
}
catch (...) { }
for (auto& [name, powertoy] : modules())
if (powertoys_to_disable.empty())
{
if (only_enable_some_powertoys)
for (auto& [name, powertoy] : modules())
{
if (powertoys_to_enable.find(name) != powertoys_to_enable.end())
{
powertoy.enable();
}
powertoy->enable();
}
else
}
else
{
for (auto& [name, powertoy] : modules())
{
powertoy.enable();
if (powertoys_to_disable.find(name) == powertoys_to_disable.end())
{
powertoy->enable();
}
}
}
}

View File

@@ -7,7 +7,7 @@ struct GeneralSettings
bool isPackaged;
bool isStartupEnabled;
std::wstring startupDisabledReason;
std::unordered_map<std::wstring, bool> isModulesEnabledMap;
std::map<std::wstring, bool> isModulesEnabledMap;
bool isElevated;
bool isRunElevated;
bool isAdmin;

View File

@@ -25,12 +25,15 @@
#if _DEBUG && _WIN64
#include "unhandled_exception_handler.h"
#endif
#include <common/notifications/fancyzones_notifications.h>
extern "C" IMAGE_DOS_HEADER __ImageBase;
namespace localized_strings
{
const wchar_t MSI_VERSION_IS_ALREADY_RUNNING[] = L"An older version of PowerToys is already running.";
const wchar_t OLDER_MSIX_UNINSTALLED[] = L"An older MSIX version of PowerToys was uninstalled.";
const wchar_t GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT[] = L"An update to PowerToys is available. Visit our GitHub page to get ";
const wchar_t GITHUB_NEW_VERSION_AGREE[] = L"Visit";
}
@@ -39,6 +42,8 @@ namespace
{
const wchar_t MSI_VERSION_MUTEX_NAME[] = L"Local\\PowerToyRunMutex";
const wchar_t MSIX_VERSION_MUTEX_NAME[] = L"Local\\PowerToyMSIXRunMutex";
const wchar_t PT_URI_PROTOCOL_SCHEME[] = L"powertoys://";
}
void chdir_current_executable()
@@ -116,7 +121,7 @@ std::future<void> check_github_updates()
std::wstring contents = GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT;
contents += new_version->version_string;
contents += L'.';
notifications::show_toast_with_activations(contents, {}, { notifications::link_button{ GITHUB_NEW_VERSION_AGREE, new_version->release_page_uri.ToString() } });
notifications::show_toast_with_activations(std::move(contents), {}, { notifications::link_button{ GITHUB_NEW_VERSION_AGREE, new_version->release_page_uri.ToString().c_str() } });
}
void github_update_checking_worker()
@@ -144,12 +149,11 @@ void github_update_checking_worker()
state.save();
}
}
void alert_already_running()
void open_menu_from_another_instance()
{
MessageBoxW(nullptr,
GET_RESOURCE_STRING(IDS_ANOTHER_INSTANCE_RUNNING).c_str(),
GET_RESOURCE_STRING(IDS_POWERTOYS).c_str(),
MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND);
HWND hwnd_main = FindWindow(L"PToyTrayIconWindow", NULL);
PostMessage(hwnd_main, WM_COMMAND, ID_SETTINGS_MENU_COMMAND, NULL);
}
int runner(bool isProcessElevated)
@@ -167,6 +171,27 @@ int runner(bool isProcessElevated)
int result = -1;
try
{
std::thread{ [] {
github_update_checking_worker();
} }.detach();
if (winstore::running_as_packaged())
{
std::thread{ [] {
start_msi_uninstallation_sequence();
} }.detach();
}
else
{
std::thread{[] {
if(uninstall_previous_msix_version_async().get())
{
notifications::show_toast(localized_strings::OLDER_MSIX_UNINSTALLED);
}
}}.detach();
}
notifications::register_background_toast_handler();
chdir_current_executable();
@@ -176,7 +201,10 @@ int runner(bool isProcessElevated)
L"shortcut_guide.dll",
L"fancyzones.dll",
L"PowerRenameExt.dll",
L"Wox.Launcher.dll"
L"Wox.Launcher.dll",
L"ImageResizerExt.dll",
L"powerpreview.dll",
L"WindowWalker.dll"
};
for (auto& file : std::filesystem::directory_iterator(L"modules/"))
{
@@ -187,7 +215,7 @@ int runner(bool isProcessElevated)
try
{
auto module = load_powertoy(file.path().wstring());
modules().emplace(module.get_name(), std::move(module));
modules().emplace(module->get_name(), std::move(module));
}
catch (...)
{
@@ -215,17 +243,22 @@ int runner(bool isProcessElevated)
enum class SpecialMode
{
None,
Win32ToastNotificationCOMServer
Win32ToastNotificationCOMServer,
ToastNotificationHandler
};
SpecialMode should_run_in_special_mode()
SpecialMode should_run_in_special_mode(const int n_cmd_args, LPWSTR* cmd_arg_list)
{
int nArgs;
LPWSTR* szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
for (size_t i = 1; i < nArgs; ++i)
for (size_t i = 1; i < n_cmd_args; ++i)
{
if (!wcscmp(notifications::TOAST_ACTIVATED_LAUNCH_ARG, szArglist[i]))
if (!wcscmp(notifications::TOAST_ACTIVATED_LAUNCH_ARG, cmd_arg_list[i]))
{
return SpecialMode::Win32ToastNotificationCOMServer;
}
else if (n_cmd_args == 2 && !wcsncmp(PT_URI_PROTOCOL_SCHEME, cmd_arg_list[i], wcslen(PT_URI_PROTOCOL_SCHEME)))
{
return SpecialMode::ToastNotificationHandler;
}
}
return SpecialMode::None;
@@ -237,14 +270,42 @@ int win32_toast_notification_COM_server_mode()
return 0;
}
enum class toast_notification_handler_result
{
exit_success,
exit_error
};
toast_notification_handler_result toast_notification_handler(const std::wstring_view param)
{
if (param == L"cant_drag_elevated_disable/")
{
return disable_cant_drag_elevated_warning() ? toast_notification_handler_result::exit_success : toast_notification_handler_result::exit_error;
}
else
{
return toast_notification_handler_result::exit_error;
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
winrt::init_apartment();
switch (should_run_in_special_mode())
int n_cmd_args = 0;
LPWSTR* cmd_arg_list = CommandLineToArgvW(GetCommandLineW(), &n_cmd_args);
switch (should_run_in_special_mode(n_cmd_args, cmd_arg_list))
{
case SpecialMode::Win32ToastNotificationCOMServer:
return win32_toast_notification_COM_server_mode();
case SpecialMode::ToastNotificationHandler:
switch (toast_notification_handler(cmd_arg_list[1] + wcslen(PT_URI_PROTOCOL_SCHEME)))
{
case toast_notification_handler_result::exit_error:
return 1;
case toast_notification_handler_result::exit_success:
return 0;
}
case SpecialMode::None:
// continue as usual
break;
@@ -259,7 +320,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
if (!msix_mutex)
{
// The MSIX version is already running.
alert_already_running();
open_menu_from_another_instance();
return 0;
}
@@ -276,7 +337,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
msi_mutex = create_msi_mutex();
if (!msi_mutex)
{
alert_already_running();
open_menu_from_another_instance();
return 0;
}
}
@@ -294,7 +355,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
if (!msi_mutex)
{
// The MSI version is already running.
alert_already_running();
open_menu_from_another_instance();
return 0;
}
@@ -305,7 +366,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
if (!msix_mutex)
{
// The MSIX version is already running.
alert_already_running();
open_menu_from_another_instance();
return 0;
}
else
@@ -318,17 +379,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
int result = 0;
try
{
std::thread{ [] {
github_update_checking_worker();
} }.detach();
if (winstore::running_as_packaged())
{
std::thread{ [] {
start_msi_uninstallation_sequence();
} }.detach();
}
// Singletons initialization order needs to be preserved, first events and
// then modules to guarantee the reverse destruction order.
SystemMenuHelperInstace();
@@ -337,12 +387,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
auto general_settings = load_general_settings();
int rvalue = 0;
bool isProcessElevated = is_process_elevated();
if (isProcessElevated ||
general_settings.GetNamedBoolean(L"run_elevated", false) == false ||
strcmp(lpCmdLine, "--dont-elevate") == 0)
const bool elevated = is_process_elevated();
if ((elevated ||
general_settings.GetNamedBoolean(L"run_elevated", false) == false ||
strcmp(lpCmdLine, "--dont-elevate") == 0))
{
result = runner(isProcessElevated);
result = runner(elevated);
}
else
{

View File

@@ -3,9 +3,9 @@
#include "lowlevel_keyboard_event.h"
#include <algorithm>
std::unordered_map<std::wstring, PowertoyModule>& modules()
std::map<std::wstring, PowertoyModule>& modules()
{
static std::unordered_map<std::wstring, PowertoyModule> modules;
static std::map<std::wstring, PowertoyModule> modules;
return modules;
}
@@ -37,3 +37,24 @@ json::JsonObject PowertoyModule::json_config() const
module->get_config(result.data(), &size);
return json::JsonObject::Parse(result);
}
PowertoyModule::PowertoyModule(PowertoyModuleIface* module, HMODULE handle) :
handle(handle), module(module)
{
if (!module)
{
throw std::runtime_error("Module not initialized");
}
auto want_signals = module->get_events();
if (want_signals)
{
for (; *want_signals; ++want_signals)
{
powertoys_events().register_receiver(*want_signals, module);
}
}
if (SystemMenuHelperInstace().HasCustomConfig(module))
{
powertoys_events().register_system_menu_action(module);
}
}

View File

@@ -8,7 +8,6 @@
#include <vector>
#include <functional>
class PowertoyModule;
#include <common/json.h>
struct PowertoyModuleDeleter
@@ -36,84 +35,19 @@ struct PowertoyModuleDLLDeleter
class PowertoyModule
{
public:
PowertoyModule(PowertoyModuleIface* module, HMODULE handle) :
handle(handle), module(module)
{
if (!module)
{
throw std::runtime_error("Module not initialized");
}
name = module->get_name();
auto want_signals = module->get_events();
if (want_signals)
{
for (; *want_signals; ++want_signals)
{
powertoys_events().register_receiver(*want_signals, module);
}
}
if (SystemMenuHelperInstace().HasCustomConfig(module))
{
powertoys_events().register_system_menu_action(module);
}
}
PowertoyModule(PowertoyModuleIface* module, HMODULE handle);
const std::wstring& get_name() const
inline PowertoyModuleIface* operator->()
{
return name;
return module.get();
}
json::JsonObject json_config() const;
const std::wstring get_config() const
{
std::wstring result;
int size = 0;
module->get_config(nullptr, &size);
wchar_t* buffer = new wchar_t[size];
if (module->get_config(buffer, &size))
{
result.assign(buffer);
}
delete[] buffer;
return result;
}
void set_config(const std::wstring& config)
{
module->set_config(config.c_str());
}
void call_custom_action(const std::wstring& action)
{
module->call_custom_action(action.c_str());
}
intptr_t signal_event(const std::wstring& signal_event, intptr_t data)
{
return module->signal_event(signal_event.c_str(), data);
}
bool is_enabled()
{
return module->is_enabled();
}
void enable()
{
module->enable();
}
void disable()
{
module->disable();
}
private:
std::unique_ptr<HMODULE, PowertoyModuleDLLDeleter> handle;
std::unique_ptr<PowertoyModuleIface, PowertoyModuleDeleter> module;
std::wstring name;
};
PowertoyModule load_powertoy(const std::wstring& filename);
std::unordered_map<std::wstring, PowertoyModule>& modules();
std::map<std::wstring, PowertoyModule>& modules();

View File

@@ -48,9 +48,11 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<TargetName>PowerToys</TargetName>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<TargetName>PowerToys</TargetName>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>

View File

@@ -68,7 +68,7 @@ void dispatch_json_action_to_module(const json::JsonObject& powertoys_configs)
else if (modules().find(name) != modules().end())
{
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());
}
}
}
@@ -77,7 +77,7 @@ void send_json_config_to_module(const std::wstring& module_key, const std::wstri
{
if (modules().find(module_key) != modules().end())
{
modules().at(module_key).set_config(settings.c_str());
modules().at(module_key)->set_config(settings.c_str());
}
}

View File

@@ -5,7 +5,7 @@
#pragma comment(lib, "DbgHelp.lib")
#include <string>
#include <sstream>
#include <signal.h>
#include <csignal>
static IMAGEHLP_SYMBOL64* p_symbol = (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH * sizeof(WCHAR));
static IMAGEHLP_LINE64 line;