dllmain.cpp
1 // dllmain.cpp : Defines the entry point for the DLL application. 2 #include "pch.h" 3 4 #include <interface/powertoy_module_interface.h> 5 #include "trace.h" 6 #include <common/SettingsAPI/settings_objects.h> 7 #include <common/utils/resources.h> 8 #include <common/interop/shared_constants.h> 9 #include <common/utils/logger_helper.h> 10 #include <common/utils/winapi_error.h> 11 12 BOOL APIENTRY DllMain(HMODULE /*hModule*/, 13 DWORD ul_reason_for_call, 14 LPVOID /*lpReserved*/) 15 { 16 switch (ul_reason_for_call) 17 { 18 case DLL_PROCESS_ATTACH: 19 Trace::RegisterProvider(); 20 break; 21 case DLL_THREAD_ATTACH: 22 break; 23 case DLL_THREAD_DETACH: 24 break; 25 case DLL_PROCESS_DETACH: 26 Trace::UnregisterProvider(); 27 break; 28 } 29 30 return TRUE; 31 } 32 33 // The PowerToy name that will be shown in the settings. 34 const static wchar_t* MODULE_NAME = L"MouseJump"; 35 // Add a description that will we shown in the module settings page. 36 const static wchar_t* MODULE_DESC = L"Quickly move the mouse long distances"; 37 38 namespace 39 { 40 const wchar_t JSON_KEY_PROPERTIES[] = L"properties"; 41 const wchar_t JSON_KEY_WIN[] = L"win"; 42 const wchar_t JSON_KEY_ALT[] = L"alt"; 43 const wchar_t JSON_KEY_CTRL[] = L"ctrl"; 44 const wchar_t JSON_KEY_SHIFT[] = L"shift"; 45 const wchar_t JSON_KEY_CODE[] = L"code"; 46 const wchar_t JSON_KEY_ACTIVATION_SHORTCUT[] = L"activation_shortcut"; 47 } 48 49 // Implement the PowerToy Module Interface and all the required methods. 50 class MouseJump : public PowertoyModuleIface 51 { 52 private: 53 // The PowerToy state. 54 bool m_enabled = false; 55 56 // Hotkey to invoke the module 57 58 HANDLE m_hProcess; 59 60 // Time to wait for process to close after sending WM_CLOSE signal 61 static const int MAX_WAIT_MILLISEC = 10000; 62 63 Hotkey m_hotkey; 64 65 // Handle to event used to invoke MouseJump 66 HANDLE m_hInvokeEvent; 67 68 // Handle to event used to terminate MouseJump 69 HANDLE m_hTerminateEvent; 70 71 void parse_hotkey(PowerToysSettings::PowerToyValues& settings) 72 { 73 auto settingsObject = settings.get_raw_json(); 74 if (settingsObject.GetView().Size()) 75 { 76 try 77 { 78 auto jsonHotkeyObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ACTIVATION_SHORTCUT); 79 m_hotkey.win = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_WIN); 80 m_hotkey.alt = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_ALT); 81 m_hotkey.shift = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_SHIFT); 82 m_hotkey.ctrl = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_CTRL); 83 m_hotkey.key = static_cast<unsigned char>(jsonHotkeyObject.GetNamedNumber(JSON_KEY_CODE)); 84 } 85 catch (...) 86 { 87 Logger::error("Failed to initialize Mouse Jump start shortcut"); 88 } 89 } 90 else 91 { 92 Logger::info("MouseJump settings are empty"); 93 } 94 95 if (!m_hotkey.key) 96 { 97 Logger::info("MouseJump is going to use default shortcut"); 98 m_hotkey.win = true; 99 m_hotkey.alt = false; 100 m_hotkey.shift = true; 101 m_hotkey.ctrl = false; 102 m_hotkey.key = 'D'; 103 } 104 } 105 106 bool is_process_running() 107 { 108 return WaitForSingleObject(m_hProcess, 0) == WAIT_TIMEOUT; 109 } 110 111 void launch_process() 112 { 113 Logger::trace(L"Starting MouseJump process"); 114 unsigned long powertoys_pid = GetCurrentProcessId(); 115 116 std::wstring executable_args = L""; 117 executable_args.append(std::to_wstring(powertoys_pid)); 118 119 SHELLEXECUTEINFOW sei{ sizeof(sei) }; 120 sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI }; 121 sei.lpFile = L"PowerToys.MouseJumpUI.exe"; 122 sei.nShow = SW_SHOWNORMAL; 123 sei.lpParameters = executable_args.data(); 124 if (ShellExecuteExW(&sei)) 125 { 126 Logger::trace("Successfully started the Mouse Jump process"); 127 } 128 else 129 { 130 Logger::error(L"Mouse Jump failed to start. {}", get_last_error_or_default(GetLastError())); 131 } 132 133 m_hProcess = sei.hProcess; 134 } 135 136 // Load initial settings from the persisted values. 137 void init_settings() 138 { 139 try 140 { 141 // Load and parse the settings file for this PowerToy. 142 PowerToysSettings::PowerToyValues settings = 143 PowerToysSettings::PowerToyValues::load_from_settings_file(get_key()); 144 145 parse_hotkey(settings); 146 } 147 catch (std::exception&) 148 { 149 Logger::warn(L"An exception occurred while loading the settings file"); 150 // Error while loading from the settings file. Let default values stay as they are. 151 } 152 } 153 154 public: 155 // Constructor 156 MouseJump() 157 { 158 LoggerHelpers::init_logger(MODULE_NAME, L"ModuleInterface", LogSettings::mouseJumpLoggerName); 159 m_hInvokeEvent = CreateDefaultEvent(CommonSharedConstants::MOUSE_JUMP_SHOW_PREVIEW_EVENT); 160 m_hTerminateEvent = CreateDefaultEvent(CommonSharedConstants::TERMINATE_MOUSE_JUMP_SHARED_EVENT); 161 init_settings(); 162 }; 163 164 ~MouseJump() 165 { 166 if (m_enabled) 167 { 168 } 169 m_enabled = false; 170 } 171 172 // Destroy the powertoy and free memory 173 virtual void destroy() override 174 { 175 Logger::trace("MouseJump::destroy()"); 176 delete this; 177 } 178 179 // Return the display name of the powertoy, this will be cached by the runner 180 virtual const wchar_t* get_name() override 181 { 182 return MODULE_NAME; 183 } 184 185 // Return the non localized key of the powertoy, this will be cached by the runner 186 virtual const wchar_t* get_key() override 187 { 188 return MODULE_NAME; 189 } 190 191 // Return the configured status for the gpo policy for the module 192 virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override 193 { 194 return powertoys_gpo::getConfiguredMouseJumpEnabledValue(); 195 } 196 197 // Return JSON with the configuration options. 198 virtual bool get_config(wchar_t* buffer, int* buffer_size) override 199 { 200 HINSTANCE hinstance = reinterpret_cast<HINSTANCE>(&__ImageBase); 201 202 // Create a Settings object. 203 PowerToysSettings::Settings settings(hinstance, get_name()); 204 settings.set_description(MODULE_DESC); 205 206 settings.set_overview_link(L"https://aka.ms/PowerToysOverview_MouseUtilities/#mouse-jump"); 207 208 return settings.serialize_to_buffer(buffer, buffer_size); 209 } 210 211 // Signal from the Settings editor to call a custom action. 212 // This can be used to spawn more complex editors. 213 virtual void call_custom_action(const wchar_t* /*action*/) override 214 { 215 } 216 217 // Called by the runner to pass the updated settings values as a serialized JSON. 218 virtual void set_config(const wchar_t* config) override 219 { 220 try 221 { 222 // Parse the input JSON string. 223 PowerToysSettings::PowerToyValues values = 224 PowerToysSettings::PowerToyValues::from_json_string(config, get_key()); 225 226 parse_hotkey(values); 227 values.save_to_settings_file(); 228 } 229 catch (std::exception&) 230 { 231 // Improper JSON. 232 } 233 } 234 235 // Enable the powertoy 236 virtual void enable() 237 { 238 Logger::trace("MouseJump::enable()"); 239 ResetEvent(m_hInvokeEvent); 240 launch_process(); 241 m_enabled = true; 242 Trace::EnableJumpTool(true); 243 } 244 245 // Disable the powertoy 246 virtual void disable() 247 { 248 Logger::trace("MouseJump::disable()"); 249 if (m_enabled) 250 { 251 ResetEvent(m_hInvokeEvent); 252 SetEvent(m_hTerminateEvent); 253 WaitForSingleObject(m_hProcess, 1500); 254 TerminateProcess(m_hProcess, 1); 255 } 256 257 m_enabled = false; 258 Trace::EnableJumpTool(false); 259 } 260 261 virtual bool on_hotkey(size_t /*hotkeyId*/) override 262 { 263 if (m_enabled) 264 { 265 Logger::trace(L"MouseJump hotkey pressed"); 266 Trace::InvokeJumpTool(); 267 if (!is_process_running()) 268 { 269 launch_process(); 270 } 271 272 SetEvent(m_hInvokeEvent); 273 return true; 274 } 275 276 return false; 277 } 278 279 virtual size_t get_hotkeys(Hotkey* hotkeys, size_t buffer_size) override 280 { 281 if (m_hotkey.key) 282 { 283 if (hotkeys && buffer_size >= 1) 284 { 285 hotkeys[0] = m_hotkey; 286 } 287 288 return 1; 289 } 290 else 291 { 292 return 0; 293 } 294 } 295 296 // Returns if the powertoys is enabled 297 virtual bool is_enabled() override 298 { 299 return m_enabled; 300 } 301 302 // Returns whether the PowerToys should be enabled by default 303 virtual bool is_enabled_by_default() const override 304 { 305 return false; 306 } 307 308 }; 309 310 extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create() 311 { 312 return new MouseJump(); 313 }