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  }