main.cpp
1 #include "pch.h" 2 #include <common/Telemetry/EtwTrace/EtwTrace.h> 3 #include <common/utils/EventWaiter.h> 4 #include <common/utils/window.h> 5 #include <common/utils/ProcessWaiter.h> 6 #include <common/utils/winapi_error.h> 7 #include <common/utils/logger_helper.h> 8 #include <common/utils/UnhandledExceptionHandler.h> 9 #include <common/utils/gpo.h> 10 #include <keyboardmanager/common/KeyboardManagerConstants.h> 11 #include <keyboardmanager/KeyboardManagerEngineLibrary/KeyboardManager.h> 12 #include <keyboardmanager/KeyboardManagerEngineLibrary/trace.h> 13 #include <common/interop/shared_constants.h> 14 15 const std::wstring instanceMutexName = L"Local\\PowerToys_KBMEngine_InstanceMutex"; 16 17 int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/, 18 _In_opt_ HINSTANCE /*hPrevInstance*/, 19 _In_ PWSTR lpCmdLine, 20 _In_ int /*nCmdShow*/) 21 { 22 winrt::init_apartment(); 23 LoggerHelpers::init_logger(KeyboardManagerConstants::ModuleName, L"Engine", LogSettings::keyboardManagerLoggerName); 24 25 Shared::Trace::ETWTrace trace; 26 trace.UpdateState(true); 27 28 if (powertoys_gpo::getConfiguredKeyboardManagerEnabledValue() == powertoys_gpo::gpo_rule_configured_disabled) 29 { 30 Logger::warn(L"Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator."); 31 return 0; 32 } 33 34 InitUnhandledExceptionHandler(); 35 36 auto mutex = CreateMutex(nullptr, true, instanceMutexName.c_str()); 37 if (mutex == nullptr) 38 { 39 Logger::error(L"Failed to create mutex. {}", get_last_error_or_default(GetLastError())); 40 } 41 42 if (GetLastError() == ERROR_ALREADY_EXISTS) 43 { 44 Logger::warn(L"KBM engine instance is already running"); 45 return 0; 46 } 47 48 Trace::RegisterProvider(); 49 50 std::wstring pid = std::wstring(lpCmdLine); 51 52 auto mainThreadId = GetCurrentThreadId(); 53 54 EventWaiter ev; 55 ev.start(CommonSharedConstants::TERMINATE_KBM_SHARED_EVENT, [&](DWORD) { 56 PostThreadMessage(mainThreadId, WM_QUIT, 0, 0); 57 }); 58 59 if (!pid.empty()) 60 { 61 ProcessWaiter::OnProcessTerminate(pid, [mainThreadId](int err) { 62 if (err != ERROR_SUCCESS) 63 { 64 Logger::error(L"Failed to wait for parent process exit. {}", get_last_error_or_default(err)); 65 } 66 else 67 { 68 Logger::trace(L"PowerToys runner exited."); 69 } 70 71 Logger::trace(L"Exiting KeyboardManager engine"); 72 PostThreadMessage(mainThreadId, WM_QUIT, 0, 0); 73 }); 74 } 75 76 auto kbm = KeyboardManager(); 77 if (kbm.HasRegisteredRemappings()) 78 kbm.StartLowlevelKeyboardHook(); 79 80 auto StartHookFunc = [&kbm]() { 81 kbm.StartLowlevelKeyboardHook(); 82 }; 83 84 run_message_loop({}, {}, { { KeyboardManager::StartHookMessageID, StartHookFunc } }); 85 86 kbm.StopLowlevelKeyboardHook(); 87 Trace::UnregisterProvider(); 88 89 trace.Flush(); 90 91 return 0; 92 }