main.cpp
1 #include "pch.h" 2 #include <Windows.h> 3 #include <common/utils/window.h> 4 #include <common/SettingsAPI/settings_helpers.h> 5 #include <common/utils/ProcessWaiter.h> 6 #include <common/utils/winapi_error.h> 7 #include <common/utils/UnhandledExceptionHandler.h> 8 #include <common/utils/logger_helper.h> 9 #include <common/utils/EventWaiter.h> 10 #include <common/utils/gpo.h> 11 12 #include <common/Telemetry/EtwTrace/EtwTrace.h> 13 14 #include "shortcut_guide.h" 15 #include "target_state.h" 16 #include "ShortcutGuideConstants.h" 17 #include "trace.h" 18 19 const std::wstring instanceMutexName = L"Local\\PowerToys_ShortcutGuide_InstanceMutex"; 20 21 // set current path to the executable path 22 bool SetCurrentPath() 23 { 24 TCHAR buffer[MAX_PATH] = { 0 }; 25 if (!GetModuleFileName(NULL, buffer, MAX_PATH)) 26 { 27 Logger::error(L"Failed to get module path. {}", get_last_error_or_default(GetLastError())); 28 return false; 29 } 30 31 if (!PathRemoveFileSpec(buffer)) 32 { 33 Logger::error(L"Failed to remove file from module path. {}", get_last_error_or_default(GetLastError())); 34 return false; 35 } 36 37 std::error_code err; 38 std::filesystem::current_path(buffer, err); 39 if (err.value()) 40 { 41 Logger::error("Failed to set current path. {}", err.message()); 42 return false; 43 } 44 45 return true; 46 } 47 48 int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInstance*/, _In_ PWSTR lpCmdLine, _In_ int /*nCmdShow*/) 49 { 50 winrt::init_apartment(); 51 LoggerHelpers::init_logger(ShortcutGuideConstants::ModuleKey, L"ShortcutGuide", LogSettings::shortcutGuideLoggerName); 52 53 Shared::Trace::ETWTrace trace; 54 trace.UpdateState(true); 55 56 if (powertoys_gpo::getConfiguredShortcutGuideEnabledValue() == powertoys_gpo::gpo_rule_configured_disabled) 57 { 58 Logger::warn(L"Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator."); 59 return 0; 60 } 61 62 InitUnhandledExceptionHandler(); 63 Logger::trace("Starting Shortcut Guide"); 64 65 if (!SetCurrentPath()) 66 { 67 return false; 68 } 69 70 Trace::RegisterProvider(); 71 if (std::wstring(lpCmdLine).find(L' ') != std::wstring::npos) 72 { 73 Logger::trace("Sending settings telemetry"); 74 auto settings = OverlayWindow::GetSettings(); 75 Trace::SendSettings(settings); 76 Trace::UnregisterProvider(); 77 return 0; 78 } 79 80 auto mutex = CreateMutex(nullptr, true, instanceMutexName.c_str()); 81 if (mutex == nullptr) 82 { 83 Logger::error(L"Failed to create mutex. {}", get_last_error_or_default(GetLastError())); 84 } 85 86 if (GetLastError() == ERROR_ALREADY_EXISTS) 87 { 88 Logger::warn(L"Shortcut Guide instance is already running"); 89 Trace::UnregisterProvider(); 90 return 0; 91 } 92 93 std::wstring pid = std::wstring(lpCmdLine); 94 if (!pid.empty()) 95 { 96 auto mainThreadId = GetCurrentThreadId(); 97 ProcessWaiter::OnProcessTerminate(pid, [mainThreadId](int err) { 98 if (err != ERROR_SUCCESS) 99 { 100 Logger::error(L"Failed to wait for parent process exit. {}", get_last_error_or_default(err)); 101 } 102 else 103 { 104 Logger::trace(L"PowerToys runner exited."); 105 } 106 107 Logger::trace(L"Exiting Shortcut Guide"); 108 PostThreadMessage(mainThreadId, WM_QUIT, 0, 0); 109 }); 110 } 111 112 auto hwnd = GetForegroundWindow(); 113 auto window = OverlayWindow(hwnd); 114 EventWaiter exitEventWaiter; 115 if (window.IsDisabled()) 116 { 117 Logger::trace("SG is disabled for the current foreground app. Exiting SG"); 118 Trace::UnregisterProvider(); 119 return 0; 120 } 121 else 122 { 123 auto mainThreadId = GetCurrentThreadId(); 124 exitEventWaiter.start(CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT, [mainThreadId, &window](DWORD err) { 125 if (err != ERROR_SUCCESS) 126 { 127 Logger::error(L"Failed to wait for {} event. {}", CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT, get_last_error_or_default(err)); 128 } 129 else 130 { 131 Logger::trace(L"{} event was signaled", CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT); 132 } 133 134 window.CloseWindow(HideWindowType::THE_SHORTCUT_PRESSED, mainThreadId); 135 }); 136 } 137 138 window.ShowWindow(); 139 run_message_loop(); 140 141 trace.Flush(); 142 Trace::UnregisterProvider(); 143 return 0; 144 }