2019-09-05 00:26:26 +08:00
|
|
|
#include "pch.h"
|
|
|
|
#include <ShellScalingApi.h>
|
|
|
|
#include <lmcons.h>
|
|
|
|
#include <filesystem>
|
|
|
|
#include "tray_icon.h"
|
|
|
|
#include "powertoy_module.h"
|
|
|
|
#include "lowlevel_keyboard_event.h"
|
|
|
|
#include "trace.h"
|
|
|
|
#include "general_settings.h"
|
2019-12-17 01:36:52 +08:00
|
|
|
#include "restart_elevated.h"
|
|
|
|
#include "resource.h"
|
2019-09-05 00:26:26 +08:00
|
|
|
|
2019-12-17 16:21:46 +08:00
|
|
|
#include <common/common.h>
|
2019-11-08 02:56:32 +08:00
|
|
|
#include <common/dpi_aware.h>
|
|
|
|
|
2020-02-18 23:11:01 +08:00
|
|
|
#include <common/msi_to_msix_upgrade_lib/msi_to_msix_upgrade.h>
|
2020-02-05 00:41:00 +08:00
|
|
|
#include <common/winstore.h>
|
|
|
|
#include <common/notifications.h>
|
2020-02-20 22:04:56 +08:00
|
|
|
#include <common/timeutil.h>
|
|
|
|
|
|
|
|
#include "update_state.h"
|
|
|
|
|
|
|
|
#include <winrt/Windows.System.h>
|
2020-02-05 00:41:00 +08:00
|
|
|
|
2019-09-05 00:26:26 +08:00
|
|
|
#if _DEBUG && _WIN64
|
|
|
|
#include "unhandled_exception_handler.h"
|
|
|
|
#endif
|
2020-03-24 22:17:25 +08:00
|
|
|
#include <common/notifications/fancyzones_notifications.h>
|
2019-09-05 00:26:26 +08:00
|
|
|
|
2019-12-17 01:36:52 +08:00
|
|
|
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
|
|
|
|
2020-02-18 23:11:01 +08:00
|
|
|
namespace localized_strings
|
|
|
|
{
|
|
|
|
const wchar_t MSI_VERSION_IS_ALREADY_RUNNING[] = L"An older version of PowerToys is already running.";
|
2020-02-20 22:04:56 +08:00
|
|
|
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";
|
2020-02-18 23:11:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
const wchar_t MSI_VERSION_MUTEX_NAME[] = L"Local\\PowerToyRunMutex";
|
|
|
|
const wchar_t MSIX_VERSION_MUTEX_NAME[] = L"Local\\PowerToyMSIXRunMutex";
|
2020-03-24 22:17:25 +08:00
|
|
|
|
|
|
|
const wchar_t PT_URI_PROTOCOL_SCHEME[] = L"powertoys://";
|
2020-02-18 23:11:01 +08:00
|
|
|
}
|
|
|
|
|
2019-12-27 00:26:11 +08:00
|
|
|
void chdir_current_executable()
|
|
|
|
{
|
|
|
|
// Change current directory to the path of the executable.
|
|
|
|
WCHAR executable_path[MAX_PATH];
|
|
|
|
GetModuleFileName(NULL, executable_path, MAX_PATH);
|
|
|
|
PathRemoveFileSpec(executable_path);
|
|
|
|
if (!SetCurrentDirectory(executable_path))
|
|
|
|
{
|
|
|
|
show_last_error_message(L"Change Directory to Executable Path", GetLastError());
|
|
|
|
}
|
2019-09-05 00:26:26 +08:00
|
|
|
}
|
|
|
|
|
2020-02-18 23:11:01 +08:00
|
|
|
wil::unique_mutex_nothrow create_runner_mutex(const bool msix_version)
|
|
|
|
{
|
|
|
|
wchar_t username[UNLEN + 1];
|
|
|
|
DWORD username_length = UNLEN + 1;
|
|
|
|
GetUserNameW(username, &username_length);
|
|
|
|
wil::unique_mutex_nothrow result{ CreateMutexW(nullptr, TRUE, (std::wstring(msix_version ? MSIX_VERSION_MUTEX_NAME : MSI_VERSION_MUTEX_NAME) + username).c_str()) };
|
|
|
|
|
|
|
|
return GetLastError() == ERROR_ALREADY_EXISTS ? wil::unique_mutex_nothrow{} : std::move(result);
|
|
|
|
}
|
|
|
|
|
2020-02-21 18:12:04 +08:00
|
|
|
wil::unique_mutex_nothrow create_msi_mutex()
|
|
|
|
{
|
|
|
|
return create_runner_mutex(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
wil::unique_mutex_nothrow create_msix_mutex()
|
|
|
|
{
|
|
|
|
return create_runner_mutex(true);
|
|
|
|
}
|
|
|
|
|
2020-02-18 23:11:01 +08:00
|
|
|
bool start_msi_uninstallation_sequence()
|
|
|
|
{
|
|
|
|
const auto package_path = get_msi_package_path();
|
|
|
|
|
|
|
|
if (package_path.empty())
|
|
|
|
{
|
|
|
|
// No MSI version detected
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!offer_msi_uninstallation())
|
|
|
|
{
|
|
|
|
// User declined to uninstall or opted for "Don't show again"
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::wstring action_runner_path{ winrt::Windows::ApplicationModel::Package::Current().InstalledLocation().Path() };
|
|
|
|
action_runner_path += L"\\action_runner.exe";
|
|
|
|
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
|
|
|
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS };
|
|
|
|
sei.lpFile = action_runner_path.c_str();
|
|
|
|
sei.nShow = SW_SHOWNORMAL;
|
|
|
|
sei.lpParameters = L"-uninstall_msi";
|
|
|
|
ShellExecuteExW(&sei);
|
|
|
|
WaitForSingleObject(sei.hProcess, INFINITE);
|
|
|
|
DWORD exit_code = 0;
|
|
|
|
GetExitCodeProcess(sei.hProcess, &exit_code);
|
|
|
|
CloseHandle(sei.hProcess);
|
|
|
|
return exit_code == 0;
|
|
|
|
}
|
|
|
|
|
2020-02-20 22:04:56 +08:00
|
|
|
std::future<void> check_github_updates()
|
|
|
|
{
|
|
|
|
const auto new_version = co_await check_for_new_github_release_async();
|
|
|
|
if (!new_version)
|
|
|
|
{
|
|
|
|
co_return;
|
|
|
|
}
|
|
|
|
using namespace localized_strings;
|
|
|
|
|
|
|
|
std::wstring contents = GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT;
|
|
|
|
contents += new_version->version_string;
|
|
|
|
contents += L'.';
|
2020-03-24 22:17:25 +08:00
|
|
|
notifications::show_toast_with_activations(std::move(contents), {}, { notifications::link_button{ GITHUB_NEW_VERSION_AGREE, new_version->release_page_uri.ToString().c_str() } });
|
2020-02-20 22:04:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void github_update_checking_worker()
|
|
|
|
{
|
|
|
|
const int64_t update_check_period_minutes = 60 * 24;
|
|
|
|
|
|
|
|
auto state = UpdateState::load();
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
int64_t sleep_minutes_till_next_update = 0;
|
|
|
|
if (state.github_update_last_checked_date.has_value())
|
|
|
|
{
|
|
|
|
int64_t last_checked_minutes_ago = timeutil::diff::in_minutes(timeutil::now(), *state.github_update_last_checked_date);
|
|
|
|
if (last_checked_minutes_ago < 0)
|
|
|
|
{
|
|
|
|
last_checked_minutes_ago = update_check_period_minutes;
|
|
|
|
}
|
|
|
|
sleep_minutes_till_next_update = max(0, update_check_period_minutes - last_checked_minutes_ago);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::minutes(sleep_minutes_till_next_update));
|
|
|
|
|
|
|
|
check_github_updates().get();
|
|
|
|
state.github_update_last_checked_date.emplace(timeutil::now());
|
|
|
|
state.save();
|
|
|
|
}
|
|
|
|
}
|
2020-02-21 18:12:04 +08:00
|
|
|
void alert_already_running()
|
|
|
|
{
|
|
|
|
MessageBoxW(nullptr,
|
|
|
|
GET_RESOURCE_STRING(IDS_ANOTHER_INSTANCE_RUNNING).c_str(),
|
|
|
|
GET_RESOURCE_STRING(IDS_POWERTOYS).c_str(),
|
|
|
|
MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND);
|
|
|
|
}
|
|
|
|
|
2020-02-12 18:03:40 +08:00
|
|
|
int runner(bool isProcessElevated)
|
2019-12-27 00:26:11 +08:00
|
|
|
{
|
|
|
|
DPIAware::EnableDPIAwarenessForThisProcess();
|
|
|
|
|
|
|
|
#if _DEBUG && _WIN64
|
|
|
|
//Global error handlers to diagnose errors.
|
|
|
|
//We prefer this not not show any longer until there's a bug to diagnose.
|
|
|
|
//init_global_error_handlers();
|
|
|
|
#endif
|
|
|
|
Trace::RegisterProvider();
|
|
|
|
start_tray_icon();
|
2020-02-18 23:11:01 +08:00
|
|
|
|
|
|
|
int result = -1;
|
2019-12-27 00:26:11 +08:00
|
|
|
try
|
|
|
|
{
|
2020-03-12 15:59:10 +08:00
|
|
|
std::thread{ [] {
|
|
|
|
github_update_checking_worker();
|
|
|
|
} }.detach();
|
|
|
|
|
|
|
|
if (winstore::running_as_packaged())
|
|
|
|
{
|
|
|
|
std::thread{ [] {
|
|
|
|
start_msi_uninstallation_sequence();
|
|
|
|
} }.detach();
|
|
|
|
}
|
|
|
|
|
2020-02-26 04:04:19 +08:00
|
|
|
notifications::register_background_toast_handler();
|
2020-02-18 23:11:01 +08:00
|
|
|
|
2019-12-27 00:26:11 +08:00
|
|
|
chdir_current_executable();
|
|
|
|
// Load Powertyos DLLS
|
|
|
|
// For now only load known DLLs
|
|
|
|
std::unordered_set<std::wstring> known_dlls = {
|
|
|
|
L"shortcut_guide.dll",
|
|
|
|
L"fancyzones.dll",
|
2020-03-12 06:53:49 +08:00
|
|
|
L"PowerRenameExt.dll",
|
Merge ImageResizer into master (#1469)
* Import Image Resizer for Windows
* getting code analysis and stylecop hooked in
* upgrading to 4.7.2
* adding copyright
* getting stuff to work
headers and trailing commas
adding braces
updated encoder
* Revert "getting stuff to work"
This reverts commit 5310866120f3c59dc51395dd8f1c6a3b8db57f93.
* update to .net 4.7.2
* access modifier
* zero errors
* Fixed unit tests not running issue
* Fixed ImageResizer.Test stylecop warning
* Formatted ShellExtensions project with clang-format
* Fixed annotation warnings
* Suppressed 6031 and 26812 warnings for specific lines
* Shifting ImageResizer projects to PowerToys solution (#1054)
* Shifted ImageResizer projects to PowerToys solution: Builds, all tests pass, ImageResizer C# project works independently
* Deleted extra files
* Deleted nuget config file and fixed code analysis paths
* Convert ImageResizer to a PowerToy (#1073)
* Updated vcxproj file with common project references and cpp version flags
* Added module template code to dllmain and updated headers for successful build
* Removed unnecessary include
* Added dll to runner and add fixes to show up in PT Settings
* Added settings file
* Added support for enabling/disabling based on PowerRename codebase
* Fixed missing braces
* Fixed call_custom_action
* Add ImageResizer to msi installer (dev/imageResizer) (#1094)
* Updated vcxproj file with common project references and cpp version flags
* Added module template code to dllmain and updated headers for successful build
* Removed unnecessary include
* Added dll to runner and add fixes to show up in PT Settings
* Added settings file
* Added support for enabling/disabling based on PowerRename codebase
* Fixed solution file configurations
* Removed Any CPU from ImageResizer csprojs
* Renamed registry writing and removed build time registry addition
* Added ImageResizer installation details to msi
* Fixed comment on conditions to close explorer.exe
* Sync dev/imageResizer with master (#1105)
* tweaking language
* adjusting elevated permission verbiage to match Windows
* npm audit fix to update stuff
* slight bump for fabric ui
* Remove unwanted files (#1037)
Add temp build files to gitignore
* Ensure previous search and replace texts are evaluated and updated in the UI at startup (#1043)
Ensure stored settings get evaluated after initial enumeration
There was a bug where the list view was not getting updated with the results of the search and replace on launch when we are using a stored search or replace text from a previous session.
* adding fancy zone opacity setting, enhancement #631 (#1008)
* adding fancy zone opacity setting, enhancement #631
* applying zone opacity setting to all zones during zone selection
* changing opacity setting to percentage
* runner: show message box when restarting with different elevation fails (#1061)
Also make the message box appear on top of the settings window.
* Fix misaligned display of zones in layout priview and grid editor (#1010)
Fix misaligned display of zones in layout preview and grid editor
* MSIX: Extract MSIX building functionality from msix_reinstall.ps1 to a separate script (#1068)
* MSIX: label PowerToys as Preview (#1090)
* MSIX: Code sign msixbundle (#1093)
* Update to MSIX README.md (#1095)
* Update README.md
few adjustments
* Update README.md
* Update README.md
* adding in privacy statement, removing About in dialog (#1087)
* adding in privacy statement, removing About in dialog
* added Preview
* Revert "Fix misaligned display of zones in layout priview and grid editor (#1010)" (#1097)
This reverts commit d03690cffd6503ae6d5d1b359cca5fc89c4bad38.
* Fix reversed order of zones in layout (#1071)
* Shifted three functions to common (#1101)
Co-authored-by: Clint Rutkas <clint@rutkas.com>
Co-authored-by: Enrico Giordani <enricogior@users.noreply.github.com>
Co-authored-by: Chris Davis <chrisdavis@outlook.com>
Co-authored-by: Yosef Durr <yodurr@microsoft.com>
Co-authored-by: Bartosz Sosnowski <bzoz@users.noreply.github.com>
Co-authored-by: vldmr11080 <57061786+vldmr11080@users.noreply.github.com>
Co-authored-by: yuyoyuppe <yuyoyuppe@users.noreply.github.com>
* Revert "Sync dev/imageResizer with master (#1105)"
This reverts commit db7f15541f452f20296cce6c8b06a06e49c3671e.
* Added icon to Resize pictures context menu entry (dev/imageResizer) (#1113)
* Updated vcxproj file with common project references and cpp version flags
* Added module template code to dllmain and updated headers for successful build
* Removed unnecessary include
* Added dll to runner and add fixes to show up in PT Settings
* Added settings file
* Added support for enabling/disabling based on PowerRename codebase
* Fixed solution file configurations
* Removed Any CPU from ImageResizer csprojs
* Renamed registry writing and removed build time registry addition
* Added ImageResizer installation details to msi
* Shifted to MII, TODO: Fix position
* Incorporated ImageResizer Icon in context menu entry
* Fixed typo
* Merged with dev/imageResizer
* Renamed Advanced Options to Settings and removed About tab (dev/imageResizer) (#1123)
* Removed about tab, renamed advanced opt to settings, changed assembly info
* Restored Resource designer file
* Reverted changes on AssemblyInfo
* MSI: Fix ImageResizer menu item position (dev/imageResizer) (#1114)
* Updated vcxproj file with common project references and cpp version flags
* Added module template code to dllmain and updated headers for successful build
* Removed unnecessary include
* Added dll to runner and add fixes to show up in PT Settings
* Added settings file
* Added support for enabling/disabling based on PowerRename codebase
* Fixed solution file configurations
* Removed Any CPU from ImageResizer csprojs
* Renamed registry writing and removed build time registry addition
* Added ImageResizer installation details to msi
* Shifted to MII, TODO: Fix position
* Incorporated ImageResizer Icon in context menu entry
* Changed registry entries to SystemFileAssociations and added index changes in InsertMenuItem
* Fixed extra newline
* Fixed merge conflict
* Refactor ImageResizer code base naming to match PowerRename (#1121)
* Created empty README file
* Renamed dll project
* Removed ShellExtensions references in src
* Fixed ImageResizerUI assembly name and added changes to MSI
* added the helper functions
* localized dllmain powerrename
* localized powerRenameExt
* localized the settings file
* built the proj
* Modified resourceIDs for strings in the table
* added common as a reference project
* Removed get_res_string_wchar and used the get_resource_string() function instead which returns a wstring typecast into wchar*
* Added new lines to the end of the file
* Removed string resources from the settings.cpp file
* rebuilt project PowerRename
* moved app name to constructor to init only once
* updated formatting of common.cpp
* reverting formatting of files
* Removed some IDs from resource file. Changed SHIFT to Shift
* Localizing C# Project of FancyZones (FancyZonesEditor) (#199) (#1122)
* removed hardcoded strings from CanvasEditorWindow.xaml
* removed hardcoded strings from GridEditorWindow.xaml
* loc
* Localized MainWindow
* reverting MainWindow.xaml as it is not rendering the window as expected
* Changed the resource settings from internal to public
* the culture is set based on the culture of the system UI set in the system settings
* Removed the french resource files used for testing
* Localized canvasWindow and mainwindow
* Removed setting the UI culture explicitly as it would be implicitly set to the culture of system UI
* Removed redundant header file
* Localize the Shortcut guide PowerToy (#199) (#1126)
* Localized shortcut_guide.cpp
* localized overlay_window.cpp
* formatting changes
* Localize overlay window
* removed the README link from the set of localized resources
* Typo: changed upper to lower
* Localize C++ Projects of FancyZones (#1130)
* localized dllmain.cpp of fancyzones project
* localized FancyZones.cpp
* format fancyzones.rc file
* Moved SuperFancyZones back to being a string instead of having it in the resource file as it is the window class name
* reverted changes for window name
* Formatted fancyzones rc file
* Align zone dimensions from layout preview with those from grid editor (#1115)
* MSIX: add a dedicated .rc for UWPUI which joins both UI and DLL .rc's (#1139)
* Runner: fix restarting with same elevation (#1133)
* MSIX: reinstall script uses bundle instead of .msi to be able to reinstall in all cases
* Telemetry: add WebView init failure errors
* Settings: initialize COM security to allow communication between elevated Settings and WebView
* Common: implement on_scope_exit helper and typed_storage
* Changes for #1140 and #569 (#1152)
* MSIX build instructions adjustmnet (#1170)
* MSIX: hide the "Run at Startup" option if running as packaged
* MSIX: update identity name and publisher (#1176)
* Runner: fix startup task state setting for MSIX (#1181)
* Add ImageResizer to MSIX installer and make the code MSIX-compatible (#1219)
* Removed ImageResizer.exe location registry key
* Added working resize pictures to MSIX context menu without icon
* Fixed missing icon on MSIX build
* Added comments
* Changed to single context handler entry
* Made changes as per PR comments
* Localize ImageResizer (#1261)
* Removed hardcoded strings
* Added resource dlls to MSIX installer
* Save ImageResizer settings in JSON format (#1258)
* Combined settings files
* Added JSON settings functionality in PowerToys format with thread safety
* Reverting changes to csproj file
* Removed settings.settings and designer file and added target sdk tools to fix warning
* Added NewtonSoft Json package
* Added 3 tests
* Added propertychanged test
* Removed unused libraries
* Removed additional allocation statements in test
* Added comments on test
* Added one-time setup code
* Added Newtonsoft.Json.dll to MSI and MSIX installer
* Fixed copyright header
* Fixed folder location in MSIX
* Renamed jsonMutex to _jsonMutex
* Fixed line endings
* Created private setup functions and added Arrange, Act, Assert comments
* Created private setup functions and added Arrange, Act, Assert comments
* Suppressed copyright warning on AppFixture and enabled treat warnings as errors
* Added comments on Reload/AppFixture and added constructor andispose
* Added telemetry to ImageResizer Shell Extension code (dev/imageResizer) (#1272)
* Added telemetry to C++ ImageResizerExt
* Added Register and unregister calls
* Changed default enable setting
* Set startup location to center of the screen (ImageResizer) (#1452)
* Added ImageResizer resources.dlls to the MSI installer (#1448)
* Implemented fix for foreground issue for ImageResizer (#1434)
* Fixed conflict in installer README.md file
* Fixed conflict in bundle.js
* Auto-generate AssemblyInfo in ImageResizer (#1467)
* Updated assembly info
* Added auto-generation of AssemblyInfo.cs
* Fixed minor issues
* Remove the License file since Notice.md have been added
* Fix errors due to resolving merge conflicts
Co-authored-by: Brice Lambson <brice@bricelam.net>
Co-authored-by: Clint Rutkas <clint@rutkas.com>
Co-authored-by: Arjun Balgovind <arbalgov@microsoft.com>
Co-authored-by: Enrico Giordani <enricogior@users.noreply.github.com>
Co-authored-by: Chris Davis <chrisdavis@outlook.com>
Co-authored-by: Yosef Durr <yodurr@microsoft.com>
Co-authored-by: Bartosz Sosnowski <bzoz@users.noreply.github.com>
Co-authored-by: vldmr11080 <57061786+vldmr11080@users.noreply.github.com>
Co-authored-by: yuyoyuppe <yuyoyuppe@users.noreply.github.com>
Co-authored-by: Alekhya Kommuru <alkommur@microsoft.com>
Co-authored-by: Alekhya <reddykalekhya@gmail.com>
Co-authored-by: yuyoyuppe <a.yuyoyuppe@gmail.com>
Co-authored-by: Udit Singh <udsing@microsoft.com>
2020-03-13 00:02:34 +08:00
|
|
|
L"ImageResizerExt.dll",
|
2020-03-18 06:19:36 +08:00
|
|
|
L"powerpreview.dll",
|
|
|
|
L"WindowWalker.dll"
|
2019-12-27 00:26:11 +08:00
|
|
|
};
|
|
|
|
for (auto& file : std::filesystem::directory_iterator(L"modules/"))
|
|
|
|
{
|
|
|
|
if (file.path().extension() != L".dll")
|
|
|
|
continue;
|
|
|
|
if (known_dlls.find(file.path().filename()) == known_dlls.end())
|
|
|
|
continue;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
auto module = load_powertoy(file.path().wstring());
|
2020-03-13 17:55:15 +08:00
|
|
|
modules().emplace(module->get_name(), std::move(module));
|
2019-12-27 00:26:11 +08:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Start initial powertoys
|
|
|
|
start_initial_powertoys();
|
2019-09-05 00:26:26 +08:00
|
|
|
|
2020-02-12 18:03:40 +08:00
|
|
|
Trace::EventLaunch(get_product_version(), isProcessElevated);
|
2019-09-05 00:26:26 +08:00
|
|
|
|
2019-12-27 00:26:11 +08:00
|
|
|
result = run_message_loop();
|
|
|
|
}
|
|
|
|
catch (std::runtime_error& err)
|
|
|
|
{
|
|
|
|
std::string err_what = err.what();
|
2020-01-10 01:17:42 +08:00
|
|
|
MessageBoxW(nullptr, std::wstring(err_what.begin(), err_what.end()).c_str(), GET_RESOURCE_STRING(IDS_ERROR).c_str(), MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
|
2019-12-27 00:26:11 +08:00
|
|
|
result = -1;
|
|
|
|
}
|
|
|
|
Trace::UnregisterProvider();
|
|
|
|
return result;
|
2019-09-05 00:26:26 +08:00
|
|
|
}
|
2019-12-17 01:36:52 +08:00
|
|
|
|
2020-02-26 04:04:19 +08:00
|
|
|
// If the PT runner is launched as part of some action and manually by a user, e.g. being activated as a COM server
|
|
|
|
// for background toast notification handling, we should execute corresponding code flow instead of the main code flow.
|
|
|
|
enum class SpecialMode
|
|
|
|
{
|
|
|
|
None,
|
2020-03-24 22:17:25 +08:00
|
|
|
Win32ToastNotificationCOMServer,
|
|
|
|
ToastNotificationHandler
|
2020-02-26 04:04:19 +08:00
|
|
|
};
|
|
|
|
|
2020-03-24 22:17:25 +08:00
|
|
|
SpecialMode should_run_in_special_mode(const int n_cmd_args, LPWSTR* cmd_arg_list)
|
2020-02-26 04:04:19 +08:00
|
|
|
{
|
2020-03-24 22:17:25 +08:00
|
|
|
for (size_t i = 1; i < n_cmd_args; ++i)
|
2020-02-26 04:04:19 +08:00
|
|
|
{
|
2020-03-24 22:17:25 +08:00
|
|
|
if (!wcscmp(notifications::TOAST_ACTIVATED_LAUNCH_ARG, cmd_arg_list[i]))
|
|
|
|
{
|
2020-02-26 04:04:19 +08:00
|
|
|
return SpecialMode::Win32ToastNotificationCOMServer;
|
2020-03-24 22:17:25 +08:00
|
|
|
}
|
|
|
|
else if (n_cmd_args == 2 && !wcsncmp(PT_URI_PROTOCOL_SCHEME, cmd_arg_list[i], wcslen(PT_URI_PROTOCOL_SCHEME)))
|
|
|
|
{
|
|
|
|
return SpecialMode::ToastNotificationHandler;
|
|
|
|
}
|
2020-02-26 04:04:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return SpecialMode::None;
|
|
|
|
}
|
|
|
|
|
|
|
|
int win32_toast_notification_COM_server_mode()
|
|
|
|
{
|
|
|
|
notifications::run_desktop_app_activator_loop();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-03-24 22:17:25 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-27 00:26:11 +08:00
|
|
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
|
|
|
{
|
2020-02-26 04:04:19 +08:00
|
|
|
winrt::init_apartment();
|
|
|
|
|
2020-03-24 22:17:25 +08:00
|
|
|
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))
|
2020-02-26 04:04:19 +08:00
|
|
|
{
|
|
|
|
case SpecialMode::Win32ToastNotificationCOMServer:
|
|
|
|
return win32_toast_notification_COM_server_mode();
|
2020-03-24 22:17:25 +08:00
|
|
|
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;
|
|
|
|
}
|
2020-02-26 04:04:19 +08:00
|
|
|
case SpecialMode::None:
|
|
|
|
// continue as usual
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-02-21 18:12:04 +08:00
|
|
|
wil::unique_mutex_nothrow msi_mutex;
|
|
|
|
wil::unique_mutex_nothrow msix_mutex;
|
|
|
|
|
|
|
|
if (winstore::running_as_packaged())
|
2019-12-27 00:26:11 +08:00
|
|
|
{
|
2020-02-21 18:12:04 +08:00
|
|
|
msix_mutex = create_msix_mutex();
|
|
|
|
if (!msix_mutex)
|
|
|
|
{
|
|
|
|
// The MSIX version is already running.
|
|
|
|
alert_already_running();
|
|
|
|
return 0;
|
|
|
|
}
|
2020-02-18 23:11:01 +08:00
|
|
|
|
2020-02-21 18:12:04 +08:00
|
|
|
// Check if the MSI version is running, if not, hold the
|
|
|
|
// mutex to prevent the old MSI versions to start.
|
|
|
|
msi_mutex = create_msi_mutex();
|
|
|
|
if (!msi_mutex)
|
|
|
|
{
|
|
|
|
// The MSI version is running, warn the user and offer to uninstall it.
|
|
|
|
const bool declined_uninstall = !start_msi_uninstallation_sequence();
|
|
|
|
if (declined_uninstall)
|
|
|
|
{
|
|
|
|
// Check again if the MSI version is still running.
|
|
|
|
msi_mutex = create_msi_mutex();
|
|
|
|
if (!msi_mutex)
|
|
|
|
{
|
|
|
|
alert_already_running();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Older MSI versions are not aware of the MSIX mutex, therefore
|
|
|
|
// hold the MSI mutex to prevent an old instance to start.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2020-02-18 23:11:01 +08:00
|
|
|
{
|
2020-02-21 18:12:04 +08:00
|
|
|
// Check if another instance of the MSI version is already running.
|
|
|
|
msi_mutex = create_msi_mutex();
|
|
|
|
if (!msi_mutex)
|
|
|
|
{
|
|
|
|
// The MSI version is already running.
|
|
|
|
alert_already_running();
|
|
|
|
return 0;
|
|
|
|
}
|
2020-02-18 23:11:01 +08:00
|
|
|
|
2020-02-21 18:12:04 +08:00
|
|
|
// Check if an instance of the MSIX version is already running.
|
|
|
|
// Note: this check should always be negative since the MSIX version
|
|
|
|
// is holding both mutexes.
|
|
|
|
msix_mutex = create_msix_mutex();
|
|
|
|
if (!msix_mutex)
|
2020-02-18 23:11:01 +08:00
|
|
|
{
|
2020-02-21 18:12:04 +08:00
|
|
|
// The MSIX version is already running.
|
|
|
|
alert_already_running();
|
2020-02-18 23:11:01 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2020-02-21 18:12:04 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// The MSIX version isn't running, release the mutex.
|
|
|
|
msix_mutex.reset(nullptr);
|
|
|
|
}
|
2020-02-18 23:11:01 +08:00
|
|
|
}
|
|
|
|
|
2019-12-27 00:26:11 +08:00
|
|
|
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();
|
2019-12-17 01:36:52 +08:00
|
|
|
|
2019-12-27 00:26:11 +08:00
|
|
|
auto general_settings = load_general_settings();
|
|
|
|
int rvalue = 0;
|
2020-03-24 22:17:25 +08:00
|
|
|
const bool elevated = is_process_elevated();
|
|
|
|
if ((elevated ||
|
|
|
|
general_settings.GetNamedBoolean(L"run_elevated", false) == false ||
|
|
|
|
strcmp(lpCmdLine, "--dont-elevate") == 0))
|
2019-12-27 00:26:11 +08:00
|
|
|
{
|
2020-03-24 22:17:25 +08:00
|
|
|
result = runner(elevated);
|
2019-12-27 00:26:11 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
schedule_restart_as_elevated();
|
|
|
|
result = 0;
|
|
|
|
}
|
2019-12-17 01:36:52 +08:00
|
|
|
}
|
2019-12-27 00:26:11 +08:00
|
|
|
catch (std::runtime_error& err)
|
|
|
|
{
|
|
|
|
std::string err_what = err.what();
|
2020-01-10 01:17:42 +08:00
|
|
|
MessageBoxW(nullptr, std::wstring(err_what.begin(), err_what.end()).c_str(), GET_RESOURCE_STRING(IDS_ERROR).c_str(), MB_OK | MB_ICONERROR);
|
2019-12-27 00:26:11 +08:00
|
|
|
result = -1;
|
2019-12-17 01:36:52 +08:00
|
|
|
}
|
2020-02-21 18:12:04 +08:00
|
|
|
|
|
|
|
// We need to release the mutexes to be able to restart the application
|
|
|
|
if (msi_mutex)
|
|
|
|
{
|
|
|
|
msi_mutex.reset(nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msix_mutex)
|
|
|
|
{
|
|
|
|
msix_mutex.reset(nullptr);
|
|
|
|
}
|
|
|
|
|
2019-12-27 00:26:11 +08:00
|
|
|
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);
|
2020-01-10 01:17:42 +08:00
|
|
|
MessageBoxW(nullptr, text.c_str(), GET_RESOURCE_STRING(IDS_ERROR).c_str(), MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
|
|
|
|
|
|
|
|
restart_same_elevation();
|
2019-12-27 00:26:11 +08:00
|
|
|
result = -1;
|
|
|
|
}
|
2019-12-17 01:36:52 +08:00
|
|
|
}
|
2019-12-27 00:26:11 +08:00
|
|
|
stop_tray_icon();
|
|
|
|
return result;
|
2019-12-17 01:36:52 +08:00
|
|
|
}
|