@@ -65,6 +65,24 @@ static void initialize_modifiers() {
6565 if (GetKeyState (VK_SCROLL ) < 0 ) { set_modifier_mask (MASK_SCROLL_LOCK ); }
6666}
6767
68+ #ifdef USE_EPOCH_TIME
69+ static uint64_t get_unix_timestamp () {
70+ FILETIME system_time ;
71+
72+ // Get the local system time in UTC.
73+ GetSystemTimeAsFileTime (& system_time );
74+
75+ // Convert the local system time to a Unix epoch in MS.
76+ // milliseconds = 100-nanoseconds / 10000
77+ uint64_t timestamp = (((uint64_t ) system_time .dwHighDateTime << 32 ) | system_time .dwLowDateTime ) / 10000 ;
78+
79+ // Convert Windows epoch to Unix epoch. (1970 - 1601 in milliseconds)
80+ timestamp -= 11644473600000 ;
81+
82+ return timestamp ;
83+ }
84+ #endif
85+
6886void unregister_running_hooks () {
6987 // Stop the event hook and any timer still running.
7088 if (win_event_hhook != NULL ) {
@@ -88,15 +106,22 @@ LRESULT CALLBACK keyboard_hook_event_proc(int nCode, WPARAM wParam, LPARAM lPara
88106 bool consumed = false;
89107
90108 KBDLLHOOKSTRUCT * kbhook = (KBDLLHOOKSTRUCT * ) lParam ;
109+
110+ #ifdef USE_EPOCH_TIME
111+ uint64_t timestamp = get_unix_timestamp ();
112+ #else
113+ uint64_t timestamp = kbhook -> time ;
114+ #endif
115+
91116 switch (wParam ) {
92117 case WM_KEYDOWN :
93118 case WM_SYSKEYDOWN :
94- consumed = dispatch_key_press (kbhook );
119+ consumed = dispatch_key_press (timestamp , kbhook );
95120 break ;
96121
97122 case WM_KEYUP :
98123 case WM_SYSKEYUP :
99- consumed = dispatch_key_release (kbhook );
124+ consumed = dispatch_key_release (timestamp , kbhook );
100125 break ;
101126
102127 default :
@@ -121,30 +146,37 @@ LRESULT CALLBACK mouse_hook_event_proc(int nCode, WPARAM wParam, LPARAM lParam)
121146 bool consumed = false;
122147
123148 MSLLHOOKSTRUCT * mshook = (MSLLHOOKSTRUCT * ) lParam ;
149+
150+ #ifdef USE_EPOCH_TIME
151+ uint64_t timestamp = get_unix_timestamp ();
152+ #else
153+ uint64_t timestamp = mshook -> time ;
154+ #endif
155+
124156 switch (wParam ) {
125157 case WM_LBUTTONDOWN :
126158 set_modifier_mask (MASK_BUTTON1 );
127- consumed = dispatch_button_press (mshook , MOUSE_BUTTON1 );
159+ consumed = dispatch_button_press (timestamp , mshook , MOUSE_BUTTON1 );
128160 break ;
129161
130162 case WM_RBUTTONDOWN :
131163 set_modifier_mask (MASK_BUTTON2 );
132- consumed = dispatch_button_press (mshook , MOUSE_BUTTON2 );
164+ consumed = dispatch_button_press (timestamp , mshook , MOUSE_BUTTON2 );
133165 break ;
134166
135167 case WM_MBUTTONDOWN :
136168 set_modifier_mask (MASK_BUTTON3 );
137- consumed = dispatch_button_press (mshook , MOUSE_BUTTON3 );
169+ consumed = dispatch_button_press (timestamp , mshook , MOUSE_BUTTON3 );
138170 break ;
139171
140172 case WM_XBUTTONDOWN :
141173 case WM_NCXBUTTONDOWN :
142174 if (HIWORD (mshook -> mouseData ) == XBUTTON1 ) {
143175 set_modifier_mask (MASK_BUTTON4 );
144- consumed = dispatch_button_press (mshook , MOUSE_BUTTON4 );
176+ consumed = dispatch_button_press (timestamp , mshook , MOUSE_BUTTON4 );
145177 } else if (HIWORD (mshook -> mouseData ) == XBUTTON2 ) {
146178 set_modifier_mask (MASK_BUTTON5 );
147- consumed = dispatch_button_press (mshook , MOUSE_BUTTON5 );
179+ consumed = dispatch_button_press (timestamp , mshook , MOUSE_BUTTON5 );
148180 } else {
149181 // Extra mouse buttons.
150182 uint16_t button = HIWORD (mshook -> mouseData );
@@ -156,34 +188,34 @@ LRESULT CALLBACK mouse_hook_event_proc(int nCode, WPARAM wParam, LPARAM lParam)
156188 set_modifier_mask (MOUSE_BUTTON5 );
157189 }
158190
159- consumed = dispatch_button_press (mshook , button );
191+ consumed = dispatch_button_press (timestamp , mshook , button );
160192 }
161193 break ;
162194
163195
164196 case WM_LBUTTONUP :
165197 unset_modifier_mask (MASK_BUTTON1 );
166- consumed = dispatch_button_release (mshook , MOUSE_BUTTON1 );
198+ consumed = dispatch_button_release (timestamp , mshook , MOUSE_BUTTON1 );
167199 break ;
168200
169201 case WM_RBUTTONUP :
170202 unset_modifier_mask (MASK_BUTTON2 );
171- consumed = dispatch_button_release (mshook , MOUSE_BUTTON2 );
203+ consumed = dispatch_button_release (timestamp , mshook , MOUSE_BUTTON2 );
172204 break ;
173205
174206 case WM_MBUTTONUP :
175207 unset_modifier_mask (MASK_BUTTON3 );
176- consumed = dispatch_button_release (mshook , MOUSE_BUTTON3 );
208+ consumed = dispatch_button_release (timestamp , mshook , MOUSE_BUTTON3 );
177209 break ;
178210
179211 case WM_XBUTTONUP :
180212 case WM_NCXBUTTONUP :
181213 if (HIWORD (mshook -> mouseData ) == XBUTTON1 ) {
182214 unset_modifier_mask (MASK_BUTTON4 );
183- consumed = dispatch_button_release (mshook , MOUSE_BUTTON4 );
215+ consumed = dispatch_button_release (timestamp , mshook , MOUSE_BUTTON4 );
184216 } else if (HIWORD (mshook -> mouseData ) == XBUTTON2 ) {
185217 unset_modifier_mask (MASK_BUTTON5 );
186- consumed = dispatch_button_release (mshook , MOUSE_BUTTON5 );
218+ consumed = dispatch_button_release (timestamp , mshook , MOUSE_BUTTON5 );
187219 } else {
188220 // Extra mouse buttons.
189221 uint16_t button = HIWORD (mshook -> mouseData );
@@ -195,24 +227,21 @@ LRESULT CALLBACK mouse_hook_event_proc(int nCode, WPARAM wParam, LPARAM lParam)
195227 unset_modifier_mask (MOUSE_BUTTON5 );
196228 }
197229
198- consumed = dispatch_button_release (mshook , MOUSE_BUTTON5 );
230+ consumed = dispatch_button_release (timestamp , mshook , MOUSE_BUTTON5 );
199231 }
200232 break ;
201233
202234 case WM_MOUSEMOVE :
203- consumed = dispatch_mouse_move (mshook );
235+ consumed = dispatch_mouse_move (timestamp , mshook );
204236 break ;
205237
206238 case WM_MOUSEWHEEL :
207- consumed = dispatch_mouse_wheel (mshook , WHEEL_VERTICAL_DIRECTION );
239+ consumed = dispatch_mouse_wheel (timestamp , mshook , WHEEL_VERTICAL_DIRECTION );
208240 break ;
209241
210- /* For horizontal scroll wheel support.
211- * NOTE Windows >= Vista
212- * case 0x020E:
213- */
242+ // For horizontal scroll wheel support Windows >= Vista
214243 case WM_MOUSEHWHEEL :
215- consumed = dispatch_mouse_wheel (mshook , WHEEL_HORIZONTAL_DIRECTION );
244+ consumed = dispatch_mouse_wheel (timestamp , mshook , WHEEL_HORIZONTAL_DIRECTION );
216245 break ;
217246
218247 default :
@@ -286,15 +315,15 @@ UIOHOOK_API int hook_run() {
286315 __FUNCTION__ , __LINE__ );
287316
288317 hInst = GetModuleHandle (NULL );
289- if (hInst != NULL ) {
290- // Initialize native input helper functions.
291- load_input_helper ();
292- } else {
318+ if (hInst == NULL ) {
293319 logger (LOG_LEVEL_ERROR , "%s [%u]: Could not determine hInst for SetWindowsHookEx()! (%#lX)\n" ,
294320 __FUNCTION__ , __LINE__ , (unsigned long ) GetLastError ());
295321
296- status = UIOHOOK_ERROR_GET_MODULE_HANDLE ;
322+ return UIOHOOK_ERROR_GET_MODULE_HANDLE ;
297323 }
324+
325+ // Initialize native input helper functions.
326+ load_input_helper ();
298327 }
299328
300329 // Create the native hooks.
@@ -325,6 +354,13 @@ UIOHOOK_API int hook_run() {
325354 // Set the exit status.
326355 status = UIOHOOK_SUCCESS ;
327356
357+ // Get the local system time in UNIX epoch form.
358+ #ifdef USE_EPOCH_TIME
359+ uint64_t timestamp = get_unix_timestamp ();
360+ #else
361+ uint64_t timestamp = GetMessageTime ();
362+ #endif
363+
328364 // Windows does not have a hook start event or callback so we need to
329365 // manually fake it.
330366 dispatch_hook_enable ();
@@ -346,9 +382,16 @@ UIOHOOK_API int hook_run() {
346382 // Unregister any hooks that may still be installed.
347383 unregister_running_hooks ();
348384
385+ // Get the local system time in UNIX epoch form.
386+ #ifdef USE_EPOCH_TIME
387+ uint64_t timestamp = get_unix_timestamp ();
388+ #else
389+ uint64_t timestamp = GetMessageTime ();
390+ #endif
391+
349392 // We must explicitly call the cleanup handler because Windows does not
350393 // provide a thread cleanup method like POSIX pthread_cleanup_push/pop.
351- dispatch_hook_disable ();
394+ dispatch_hook_disable (timestamp );
352395
353396 return status ;
354397}
0 commit comments