diff --git a/src/windows/dispatch_event.c b/src/windows/dispatch_event.c index c45aae1b..2440994d 100644 --- a/src/windows/dispatch_event.c +++ b/src/windows/dispatch_event.c @@ -44,24 +44,6 @@ UIOHOOK_API void hook_set_dispatch_proc(dispatcher_t dispatch_proc, void *user_d dispatch_data = user_data; } -#ifdef USE_EPOCH_TIME -static uint64_t get_unix_timestamp() { - FILETIME system_time; - - // Get the local system time in UTC. - GetSystemTimeAsFileTime(&system_time); - - // Convert the local system time to a Unix epoch in MS. - // milliseconds = 100-nanoseconds / 10000 - uint64_t timestamp = (((uint64_t) system_time.dwHighDateTime << 32) | system_time.dwLowDateTime) / 10000; - - // Convert Windows epoch to Unix epoch. (1970 - 1601 in milliseconds) - timestamp -= 11644473600000; - - return timestamp; -} -#endif - // Send out an event if a dispatcher was set. static void dispatch_event(uiohook_event *const event) { if (dispatch != NULL) { @@ -75,8 +57,9 @@ static void dispatch_event(uiohook_event *const event) { } } -bool dispatch_hook_enable() { +bool dispatch_hook_enable(uint64_t timestamp) { bool consumed = false; + // Initialize native input helper functions. load_input_helper(); @@ -99,14 +82,8 @@ bool dispatch_hook_enable() { return consumed; } -bool dispatch_hook_disable() { +bool dispatch_hook_disable(uint64_t timestamp) { bool consumed = false; - // Get the local system time in UNIX epoch form. - #ifdef USE_EPOCH_TIME - uint64_t timestamp = get_unix_timestamp(); - #else - uint64_t timestamp = GetMessageTime(); - #endif // Populate the hook stop event. uio_event.time = timestamp; @@ -123,13 +100,8 @@ bool dispatch_hook_disable() { return consumed; } -bool dispatch_key_press(KBDLLHOOKSTRUCT *kbhook) { +bool dispatch_key_press(uint64_t timestamp, KBDLLHOOKSTRUCT *kbhook) { bool consumed = false; - #ifdef USE_EPOCH_TIME - uint64_t timestamp = get_unix_timestamp(); - #else - uint64_t timestamp = kbhook->time; - #endif // Check and setup modifiers. if (kbhook->vkCode == VK_LSHIFT) { set_modifier_mask(MASK_SHIFT_L); } @@ -197,13 +169,8 @@ bool dispatch_key_press(KBDLLHOOKSTRUCT *kbhook) { return consumed; } -bool dispatch_key_release(KBDLLHOOKSTRUCT *kbhook) { +bool dispatch_key_release(uint64_t timestamp, KBDLLHOOKSTRUCT *kbhook) { bool consumed = false; - #ifdef USE_EPOCH_TIME - uint64_t timestamp = get_unix_timestamp(); - #else - uint64_t timestamp = kbhook->time; - #endif // Check and setup modifiers. if (kbhook->vkCode == VK_LSHIFT) { unset_modifier_mask(MASK_SHIFT_L); } @@ -241,13 +208,8 @@ bool dispatch_key_release(KBDLLHOOKSTRUCT *kbhook) { return consumed; } -bool dispatch_button_press(MSLLHOOKSTRUCT *mshook, uint16_t button) { +bool dispatch_button_press(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint16_t button) { bool consumed = false; - #ifdef USE_EPOCH_TIME - uint64_t timestamp = get_unix_timestamp(); - #else - uint64_t timestamp = mshook->time; - #endif // Track the number of clicks, the button must match the previous button. if (button == click_button && (long int) (timestamp - click_time) <= hook_get_multi_click_time()) { @@ -298,13 +260,8 @@ bool dispatch_button_press(MSLLHOOKSTRUCT *mshook, uint16_t button) { return consumed; } -bool dispatch_button_release(MSLLHOOKSTRUCT *mshook, uint16_t button) { +bool dispatch_button_release(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint16_t button) { bool consumed = false; - #ifdef USE_EPOCH_TIME - uint64_t timestamp = get_unix_timestamp(); - #else - uint64_t timestamp = mshook->time; - #endif // Populate mouse released event. uio_event.time = timestamp; @@ -364,13 +321,8 @@ bool dispatch_button_release(MSLLHOOKSTRUCT *mshook, uint16_t button) { } -bool dispatch_mouse_move(MSLLHOOKSTRUCT *mshook) { +bool dispatch_mouse_move(uint64_t timestamp, MSLLHOOKSTRUCT *mshook) { bool consumed = false; - #ifdef USE_EPOCH_TIME - uint64_t timestamp = get_unix_timestamp(); - #else - uint64_t timestamp = mshook->time; - #endif // We received a mouse move event with the mouse actually moving. // This verifies that the mouse was moved after being depressed. @@ -415,13 +367,8 @@ bool dispatch_mouse_move(MSLLHOOKSTRUCT *mshook) { return consumed; } -bool dispatch_mouse_wheel(MSLLHOOKSTRUCT *mshook, uint8_t direction) { +bool dispatch_mouse_wheel(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint8_t direction) { bool consumed = false; - #ifdef USE_EPOCH_TIME - uint64_t timestamp = get_unix_timestamp(); - #else - uint64_t timestamp = mshook->time; - #endif // Track the number of clicks. // Reset the click count and previous button. diff --git a/src/windows/dispatch_event.h b/src/windows/dispatch_event.h index 3ac9edf0..62018b73 100644 --- a/src/windows/dispatch_event.h +++ b/src/windows/dispatch_event.h @@ -19,18 +19,18 @@ #include #include -extern bool dispatch_hook_enable(); +extern bool dispatch_hook_enable(uint64_t timestamp); -extern bool dispatch_hook_disable(); +extern bool dispatch_hook_disable(uint64_t timestamp); -extern bool dispatch_key_press(KBDLLHOOKSTRUCT *kbhook); +extern bool dispatch_key_press(uint64_t timestamp, KBDLLHOOKSTRUCT *kbhook); -extern bool dispatch_key_release(KBDLLHOOKSTRUCT *kbhook); +extern bool dispatch_key_release(uint64_t timestamp, KBDLLHOOKSTRUCT *kbhook); -extern bool dispatch_button_press(MSLLHOOKSTRUCT *mshook, uint16_t button); +extern bool dispatch_button_press(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint16_t button); -extern bool dispatch_button_release(MSLLHOOKSTRUCT *mshook, uint16_t button); +extern bool dispatch_button_release(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint16_t button); -extern bool dispatch_mouse_move(MSLLHOOKSTRUCT *mshook); +extern bool dispatch_mouse_move(uint64_t timestamp, MSLLHOOKSTRUCT *mshook); -extern bool dispatch_mouse_wheel(MSLLHOOKSTRUCT *mshook, uint8_t direction); +extern bool dispatch_mouse_wheel(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint8_t direction); diff --git a/src/windows/input_hook.c b/src/windows/input_hook.c index 10e8f5b9..190d537f 100644 --- a/src/windows/input_hook.c +++ b/src/windows/input_hook.c @@ -65,6 +65,24 @@ static void initialize_modifiers() { if (GetKeyState(VK_SCROLL) < 0) { set_modifier_mask(MASK_SCROLL_LOCK); } } +#ifdef USE_EPOCH_TIME +static uint64_t get_unix_timestamp() { + FILETIME system_time; + + // Get the local system time in UTC. + GetSystemTimeAsFileTime(&system_time); + + // Convert the local system time to a Unix epoch in MS. + // milliseconds = 100-nanoseconds / 10000 + uint64_t timestamp = (((uint64_t) system_time.dwHighDateTime << 32) | system_time.dwLowDateTime) / 10000; + + // Convert Windows epoch to Unix epoch. (1970 - 1601 in milliseconds) + timestamp -= 11644473600000; + + return timestamp; +} +#endif + void unregister_running_hooks() { // Stop the event hook and any timer still running. if (win_event_hhook != NULL) { @@ -88,15 +106,22 @@ LRESULT CALLBACK keyboard_hook_event_proc(int nCode, WPARAM wParam, LPARAM lPara bool consumed = false; KBDLLHOOKSTRUCT *kbhook = (KBDLLHOOKSTRUCT *) lParam; + + #ifdef USE_EPOCH_TIME + uint64_t timestamp = get_unix_timestamp(); + #else + uint64_t timestamp = kbhook->time; + #endif + switch (wParam) { case WM_KEYDOWN: case WM_SYSKEYDOWN: - consumed = dispatch_key_press(kbhook); + consumed = dispatch_key_press(timestamp, kbhook); break; case WM_KEYUP: case WM_SYSKEYUP: - consumed = dispatch_key_release(kbhook); + consumed = dispatch_key_release(timestamp, kbhook); break; default: @@ -121,30 +146,37 @@ LRESULT CALLBACK mouse_hook_event_proc(int nCode, WPARAM wParam, LPARAM lParam) bool consumed = false; MSLLHOOKSTRUCT *mshook = (MSLLHOOKSTRUCT *) lParam; + + #ifdef USE_EPOCH_TIME + uint64_t timestamp = get_unix_timestamp(); + #else + uint64_t timestamp = mshook->time; + #endif + switch (wParam) { case WM_LBUTTONDOWN: set_modifier_mask(MASK_BUTTON1); - consumed = dispatch_button_press(mshook, MOUSE_BUTTON1); + consumed = dispatch_button_press(timestamp, mshook, MOUSE_BUTTON1); break; case WM_RBUTTONDOWN: set_modifier_mask(MASK_BUTTON2); - consumed = dispatch_button_press(mshook, MOUSE_BUTTON2); + consumed = dispatch_button_press(timestamp, mshook, MOUSE_BUTTON2); break; case WM_MBUTTONDOWN: set_modifier_mask(MASK_BUTTON3); - consumed = dispatch_button_press(mshook, MOUSE_BUTTON3); + consumed = dispatch_button_press(timestamp, mshook, MOUSE_BUTTON3); break; case WM_XBUTTONDOWN: case WM_NCXBUTTONDOWN: if (HIWORD(mshook->mouseData) == XBUTTON1) { set_modifier_mask(MASK_BUTTON4); - consumed = dispatch_button_press(mshook, MOUSE_BUTTON4); + consumed = dispatch_button_press(timestamp, mshook, MOUSE_BUTTON4); } else if (HIWORD(mshook->mouseData) == XBUTTON2) { set_modifier_mask(MASK_BUTTON5); - consumed = dispatch_button_press(mshook, MOUSE_BUTTON5); + consumed = dispatch_button_press(timestamp, mshook, MOUSE_BUTTON5); } else { // Extra mouse buttons. uint16_t button = HIWORD(mshook->mouseData); @@ -156,34 +188,34 @@ LRESULT CALLBACK mouse_hook_event_proc(int nCode, WPARAM wParam, LPARAM lParam) set_modifier_mask(MOUSE_BUTTON5); } - consumed = dispatch_button_press(mshook, button); + consumed = dispatch_button_press(timestamp, mshook, button); } break; case WM_LBUTTONUP: unset_modifier_mask(MASK_BUTTON1); - consumed = dispatch_button_release(mshook, MOUSE_BUTTON1); + consumed = dispatch_button_release(timestamp, mshook, MOUSE_BUTTON1); break; case WM_RBUTTONUP: unset_modifier_mask(MASK_BUTTON2); - consumed = dispatch_button_release(mshook, MOUSE_BUTTON2); + consumed = dispatch_button_release(timestamp, mshook, MOUSE_BUTTON2); break; case WM_MBUTTONUP: unset_modifier_mask(MASK_BUTTON3); - consumed = dispatch_button_release(mshook, MOUSE_BUTTON3); + consumed = dispatch_button_release(timestamp, mshook, MOUSE_BUTTON3); break; case WM_XBUTTONUP: case WM_NCXBUTTONUP: if (HIWORD(mshook->mouseData) == XBUTTON1) { unset_modifier_mask(MASK_BUTTON4); - consumed = dispatch_button_release(mshook, MOUSE_BUTTON4); + consumed = dispatch_button_release(timestamp, mshook, MOUSE_BUTTON4); } else if (HIWORD(mshook->mouseData) == XBUTTON2) { unset_modifier_mask(MASK_BUTTON5); - consumed = dispatch_button_release(mshook, MOUSE_BUTTON5); + consumed = dispatch_button_release(timestamp, mshook, MOUSE_BUTTON5); } else { // Extra mouse buttons. uint16_t button = HIWORD(mshook->mouseData); @@ -195,24 +227,21 @@ LRESULT CALLBACK mouse_hook_event_proc(int nCode, WPARAM wParam, LPARAM lParam) unset_modifier_mask(MOUSE_BUTTON5); } - consumed = dispatch_button_release(mshook, MOUSE_BUTTON5); + consumed = dispatch_button_release(timestamp, mshook, MOUSE_BUTTON5); } break; case WM_MOUSEMOVE: - consumed = dispatch_mouse_move(mshook); + consumed = dispatch_mouse_move(timestamp, mshook); break; case WM_MOUSEWHEEL: - consumed = dispatch_mouse_wheel(mshook, WHEEL_VERTICAL_DIRECTION); + consumed = dispatch_mouse_wheel(timestamp, mshook, WHEEL_VERTICAL_DIRECTION); break; - /* For horizontal scroll wheel support. - * NOTE Windows >= Vista - * case 0x020E: - */ + // For horizontal scroll wheel support Windows >= Vista case WM_MOUSEHWHEEL: - consumed = dispatch_mouse_wheel(mshook, WHEEL_HORIZONTAL_DIRECTION); + consumed = dispatch_mouse_wheel(timestamp, mshook, WHEEL_HORIZONTAL_DIRECTION); break; default: @@ -286,15 +315,15 @@ UIOHOOK_API int hook_run() { __FUNCTION__, __LINE__); hInst = GetModuleHandle(NULL); - if (hInst != NULL) { - // Initialize native input helper functions. - load_input_helper(); - } else { + if (hInst == NULL) { logger(LOG_LEVEL_ERROR, "%s [%u]: Could not determine hInst for SetWindowsHookEx()! (%#lX)\n", __FUNCTION__, __LINE__, (unsigned long) GetLastError()); - status = UIOHOOK_ERROR_GET_MODULE_HANDLE; + return UIOHOOK_ERROR_GET_MODULE_HANDLE; } + + // Initialize native input helper functions. + load_input_helper(); } // Create the native hooks. @@ -325,6 +354,13 @@ UIOHOOK_API int hook_run() { // Set the exit status. status = UIOHOOK_SUCCESS; + // Get the local system time in UNIX epoch form. + #ifdef USE_EPOCH_TIME + uint64_t timestamp = get_unix_timestamp(); + #else + uint64_t timestamp = GetMessageTime(); + #endif + // Windows does not have a hook start event or callback so we need to // manually fake it. dispatch_hook_enable(); @@ -346,9 +382,16 @@ UIOHOOK_API int hook_run() { // Unregister any hooks that may still be installed. unregister_running_hooks(); + // Get the local system time in UNIX epoch form. + #ifdef USE_EPOCH_TIME + uint64_t timestamp = get_unix_timestamp(); + #else + uint64_t timestamp = GetMessageTime(); + #endif + // We must explicitly call the cleanup handler because Windows does not // provide a thread cleanup method like POSIX pthread_cleanup_push/pop. - dispatch_hook_disable(); + dispatch_hook_disable(timestamp); return status; }