Skip to content

Commit

Permalink
Windows Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
kwhat committed Apr 13, 2024
1 parent fec4617 commit 5944f6c
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 97 deletions.
71 changes: 9 additions & 62 deletions src/windows/dispatch_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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();

Expand All @@ -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;
Expand All @@ -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); }
Expand Down Expand Up @@ -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); }
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
16 changes: 8 additions & 8 deletions src/windows/dispatch_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@
#include <stdbool.h>
#include <windows.h>

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);
97 changes: 70 additions & 27 deletions src/windows/input_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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:
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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:
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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();
Expand All @@ -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;
}
Expand Down

0 comments on commit 5944f6c

Please sign in to comment.