@mukea/uiohook-napi 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -0
  3. package/binding.gyp +85 -0
  4. package/dist/index.d.ts +194 -0
  5. package/dist/index.js +206 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/prebuild-test-noop.d.ts +0 -0
  8. package/dist/prebuild-test-noop.js +3 -0
  9. package/dist/prebuild-test-noop.js.map +1 -0
  10. package/libuiohook/include/uiohook.h +457 -0
  11. package/libuiohook/src/darwin/input_helper.c +535 -0
  12. package/libuiohook/src/darwin/input_helper.h +203 -0
  13. package/libuiohook/src/darwin/input_hook.c +1436 -0
  14. package/libuiohook/src/darwin/post_event.c +303 -0
  15. package/libuiohook/src/darwin/system_properties.c +479 -0
  16. package/libuiohook/src/logger.c +40 -0
  17. package/libuiohook/src/logger.h +32 -0
  18. package/libuiohook/src/windows/input_helper.c +913 -0
  19. package/libuiohook/src/windows/input_helper.h +146 -0
  20. package/libuiohook/src/windows/input_hook.c +722 -0
  21. package/libuiohook/src/windows/post_event.c +248 -0
  22. package/libuiohook/src/windows/system_properties.c +231 -0
  23. package/libuiohook/src/x11/input_helper.c +1846 -0
  24. package/libuiohook/src/x11/input_helper.h +108 -0
  25. package/libuiohook/src/x11/input_hook.c +1116 -0
  26. package/libuiohook/src/x11/post_event.c +427 -0
  27. package/libuiohook/src/x11/system_properties.c +494 -0
  28. package/package.json +60 -0
  29. package/prebuilds/darwin/darwin-arm64/@mukea+uiohook-napi.node +0 -0
  30. package/prebuilds/darwin/darwin-x64/@mukea+uiohook-napi.node +0 -0
  31. package/prebuilds/linux/linux-arm64/@mukea+uiohook-napi.node +0 -0
  32. package/prebuilds/linux/linux-x64/@mukea+uiohook-napi.node +0 -0
  33. package/prebuilds/windows/win32-x64/@mukea+uiohook-napi.node +0 -0
  34. package/src/lib/addon.c +337 -0
  35. package/src/lib/napi_helpers.c +51 -0
  36. package/src/lib/napi_helpers.h +53 -0
  37. package/src/lib/uiohook_worker.c +200 -0
  38. package/src/lib/uiohook_worker.h +12 -0
@@ -0,0 +1,479 @@
1
+ /* libUIOHook: Cross-platform keyboard and mouse hooking from userland.
2
+ * Copyright (C) 2006-2023 Alexander Barker. All Rights Reserved.
3
+ * https://github.com/kwhat/libuiohook/
4
+ *
5
+ * libUIOHook is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Lesser General Public License as published
7
+ * by the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * libUIOHook is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public License
16
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ #ifdef USE_CARBON_LEGACY
20
+ #include <Carbon/Carbon.h>
21
+ #endif
22
+
23
+ #if defined(USE_APPLICATION_SERVICES) || defined(USE_IOKIT)
24
+ #include <CoreFoundation/CoreFoundation.h>
25
+ #endif
26
+
27
+ #ifdef USE_IOKIT
28
+ #include <IOKit/hidsystem/event_status_driver.h>
29
+ #include <IOKit/hidsystem/IOHIDLib.h>
30
+ #include <IOKit/hidsystem/IOHIDParameter.h>
31
+ #endif
32
+
33
+ #include <stdbool.h>
34
+ #include <uiohook.h>
35
+
36
+ #include "logger.h"
37
+ #include "input_helper.h"
38
+
39
+ #ifdef USE_IOKIT
40
+ static io_connect_t connection;
41
+ #endif
42
+
43
+ #define MOUSE_ACCELERATION_MULTIPLIER 65536
44
+
45
+ /* The following function was contributed by Anthony Liguori Jan 18 2015.
46
+ * https://github.com/kwhat/libuiohook/pull/18
47
+ */
48
+ UIOHOOK_API screen_data* hook_create_screen_info(unsigned char *count) {
49
+ CGError status = kCGErrorFailure;
50
+ screen_data* screens = NULL;
51
+
52
+ // Initialize count to zero.
53
+ *count = 0;
54
+
55
+ // Allocate memory to hold each display id. We will just allocate our MAX
56
+ // because its only about 1K of memory.
57
+ // TODO This can probably be realistically cut to something like 16 or 32....
58
+ // If you have more than 32 monitors, send me a picture and make a donation ;)
59
+ CGDirectDisplayID *display_ids = malloc(sizeof(CGDirectDisplayID) * UCHAR_MAX);
60
+ if (display_ids != NULL) {
61
+ // NOTE Pass UCHAR_MAX to make sure uint32_t doesn't overflow uint8_t.
62
+ // TOOD Test/Check whether CGGetOnlineDisplayList is more suitable...
63
+ status = CGGetActiveDisplayList(UCHAR_MAX, display_ids, (uint32_t *) count);
64
+
65
+ // If there is no error and at least one monitor.
66
+ if (status == kCGErrorSuccess && *count > 0) {
67
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: CGGetActiveDisplayList: %li.\n",
68
+ __FUNCTION__, __LINE__, *count);
69
+
70
+ // Allocate memory for the number of screens found.
71
+ screens = malloc(sizeof(screen_data) * (*count));
72
+ if (screens != NULL) {
73
+ for (uint8_t i = 0; i < *count; i++) {
74
+ //size_t width = CGDisplayPixelsWide(display_ids[i]);
75
+ //size_t height = CGDisplayPixelsHigh(display_ids[i]);
76
+ CGRect boundsDisp = CGDisplayBounds(display_ids[i]);
77
+ if (boundsDisp.size.width > 0 && boundsDisp.size.height > 0) {
78
+ screens[i] = (screen_data) {
79
+ .number = i + 1,
80
+ //TODO: make sure we follow the same convention for the origin
81
+ //in all other platform implementations (upper-left)
82
+ //TODO: document the approach with examples in order to show different
83
+ //cases -> different resolutions (secondary monitors origin might be
84
+ //negative)
85
+ .x = boundsDisp.origin.x,
86
+ .y = boundsDisp.origin.y,
87
+ .width = boundsDisp.size.width,
88
+ .height = boundsDisp.size.height
89
+ };
90
+ }
91
+ }
92
+ }
93
+ } else {
94
+ logger(LOG_LEVEL_WARN, "%s [%u]: multiple_get_screen_info failed: %ld. Fallback.\n",
95
+ __FUNCTION__, __LINE__, status);
96
+
97
+ size_t width = CGDisplayPixelsWide(CGMainDisplayID());
98
+ size_t height = CGDisplayPixelsHigh(CGMainDisplayID());
99
+
100
+ if (width > 0 && height > 0) {
101
+ screens = malloc(sizeof(screen_data));
102
+
103
+ if (screens != NULL) {
104
+ *count = 1;
105
+ screens[0] = (screen_data) {
106
+ .number = 1,
107
+ .x = 0,
108
+ .y = 0,
109
+ .width = width,
110
+ .height = height
111
+ };
112
+ }
113
+ }
114
+ }
115
+
116
+ // Free the id's after we are done.
117
+ free(display_ids);
118
+ }
119
+
120
+ return screens;
121
+ }
122
+
123
+ /*
124
+ * Apple's documentation is not very good. I was finally able to find this
125
+ * information after many hours of googling. Value is the slider value in the
126
+ * system preferences. That value * 15 is the rate in MS. 66 / the value is the
127
+ * chars per second rate.
128
+ *
129
+ * Value MS Char/Sec
130
+ *
131
+ * 1 15 66 * Out of standard range *
132
+ * 2 30 33
133
+ * 6 90 11
134
+ * 12 180 5.5
135
+ * 30 450 2.2
136
+ * 60 900 1.1
137
+ * 90 1350 0.73
138
+ * 120 1800 0.55
139
+ *
140
+ * V = MS / 15
141
+ * V = 66 / CharSec
142
+ *
143
+ * MS = V * 15
144
+ * MS = (66 / CharSec) * 15
145
+ *
146
+ * CharSec = 66 / V
147
+ * CharSec = 66 / (MS / 15)
148
+ */
149
+ UIOHOOK_API long int hook_get_auto_repeat_rate() {
150
+ #if defined(USE_APPLICATION_SERVICES) || defined(USE_IOKIT) || defined(USE_CARBON_LEGACY)
151
+ bool successful = false;
152
+ SInt64 rate;
153
+ #endif
154
+
155
+ long int value = -1;
156
+
157
+ #ifdef USE_APPLICATION_SERVICES
158
+ if (!successful) {
159
+ CFTypeRef pref_val = CFPreferencesCopyValue(CFSTR("KeyRepeat"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
160
+ if (pref_val != NULL) {
161
+ if (CFGetTypeID(pref_val) == CFNumberGetTypeID() && CFNumberGetValue((CFNumberRef) pref_val, kCFNumberSInt64Type, &rate)) {
162
+ // This is the slider value, we must multiply by 15 to convert to milliseconds.
163
+ value = (long) rate * 15;
164
+ successful = true;
165
+
166
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: CFPreferencesCopyValue KeyRepeat: %li.\n",
167
+ __FUNCTION__, __LINE__, rate);
168
+ }
169
+
170
+ CFRelease(pref_val);
171
+ }
172
+ }
173
+ #endif
174
+
175
+ #ifdef USE_IOKIT
176
+ if (!successful) {
177
+ CFTypeRef cf_type = NULL;
178
+ kern_return_t kern_return = IOHIDCopyCFTypeParameter(connection, CFSTR(kIOHIDKeyRepeatKey), &cf_type);
179
+ if (kern_return == kIOReturnSuccess) {
180
+ if (cf_type != NULL) {
181
+ if (CFGetTypeID(cf_type) == CFNumberGetTypeID()) {
182
+ if (CFNumberGetValue((CFNumberRef) cf_type, kCFNumberSInt64Type, &rate)) {
183
+ /* This is in some undefined unit of time that if we happen
184
+ * to multiply by 900 gives us the time in milliseconds. We
185
+ * add 0.5 to the result so that when we cast to long we
186
+ * actually get a rounded result. Saves the math.h depend.
187
+ *
188
+ * 900 * 33,333,333 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 30 * Fast *
189
+ * 900 * 100,000,000 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 90
190
+ * 900 * 200,000,000 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 180
191
+ * 900 * 500,000,000 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 450
192
+ * 900 * 1,000,000,000 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 900
193
+ * 900 * 1,500,000,000 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 1350
194
+ * 900 * 2,000,000,000 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 1800 * Slow *
195
+ */
196
+ value = (long) (900 * rate / 1000.0 / 1000.0 / 1000.0 + 0.5);
197
+ successful = true;
198
+
199
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: IORegistryEntryCreateCFProperty kIOHIDKeyRepeatKey: %li.\n",
200
+ __FUNCTION__, __LINE__, value);
201
+ }
202
+ }
203
+
204
+ CFRelease(cf_type);
205
+ }
206
+ }
207
+ }
208
+ #endif
209
+
210
+ #ifdef USE_CARBON_LEGACY
211
+ if (!successful) {
212
+ // Apple documentation states that value is in 'ticks'. I am not sure
213
+ // what that means, but it looks a lot like the arbitrary slider value.
214
+ rate = LMGetKeyRepThresh();
215
+ if (rate > -1) {
216
+ /* This is the slider value, we must multiply by 15 to convert to
217
+ * milliseconds.
218
+ */
219
+ value = (long) rate * 15;
220
+ successful = true;
221
+
222
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: LMGetKeyRepThresh: %li.\n",
223
+ __FUNCTION__, __LINE__, value);
224
+ }
225
+ }
226
+ #endif
227
+
228
+ return value;
229
+ }
230
+
231
+ UIOHOOK_API long int hook_get_auto_repeat_delay() {
232
+ #if defined(USE_APPLICATION_SERVICES) || defined(USE_IOKIT) || defined(USE_CARBON_LEGACY)
233
+ bool successful = false;
234
+ SInt64 delay;
235
+ #endif
236
+
237
+ long int value = -1;
238
+
239
+ #ifdef USE_APPLICATION_SERVICES
240
+ if (!successful) {
241
+ CFTypeRef pref_val = CFPreferencesCopyValue(CFSTR("InitialKeyRepeat"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
242
+ if (pref_val != NULL) {
243
+ if (CFGetTypeID(pref_val) == CFNumberGetTypeID() && CFNumberGetValue((CFNumberRef) pref_val, kCFNumberSInt64Type, &delay)) {
244
+ // This is the slider value, we must multiply by 15 to convert to milliseconds.
245
+ value = (long) delay * 15;
246
+ successful = true;
247
+
248
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: CFPreferencesCopyValue InitialKeyRepeat: %li.\n",
249
+ __FUNCTION__, __LINE__, value);
250
+ }
251
+
252
+ CFRelease(pref_val);
253
+ }
254
+ }
255
+ #endif
256
+
257
+ #ifdef USE_IOKIT
258
+ if (!successful) {
259
+ CFTypeRef cf_type = NULL;
260
+ kern_return_t kern_return = IOHIDCopyCFTypeParameter(connection, CFSTR(kIOHIDInitialKeyRepeatKey), &cf_type);
261
+ if (kern_return == kIOReturnSuccess) {
262
+ if (cf_type != NULL) {
263
+ if (CFGetTypeID(cf_type) == CFNumberGetTypeID()) {
264
+ if (CFNumberGetValue((CFNumberRef) cf_type, kCFNumberSInt64Type, &delay)) {
265
+ /* This is in some undefined unit of time that if we happen
266
+ * to multiply by 900 gives us the time in milliseconds. We
267
+ * add 0.5 to the result so that when we cast to long we
268
+ * actually get a rounded result. Saves the math.h depend.
269
+ *
270
+ * 900 * 250,000,000 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 225 * Fast *
271
+ * 900 * 416,666,666 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 375
272
+ * 900 * 583,333,333 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 525
273
+ * 900 * 1,133,333,333 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 1020
274
+ * 900 * 1,566,666,666 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 1410
275
+ * 900 * 2,000,000,000 / 1000.0 / 1000.0 / 1000.0 + 0.5 == 1800 * Slow *
276
+ */
277
+ value = (long) (900 * delay / 1000.0 / 1000.0 / 1000.0 + 0.5);
278
+ successful = true;
279
+
280
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: IORegistryEntryCreateCFProperty kIOHIDInitialKeyRepeatKey: %li.\n",
281
+ __FUNCTION__, __LINE__, delay);
282
+ }
283
+ }
284
+
285
+ CFRelease(cf_type);
286
+ }
287
+ }
288
+ }
289
+ #endif
290
+
291
+ #ifdef USE_CARBON_LEGACY
292
+ if (!successful) {
293
+ // Apple documentation states that value is in 'ticks'. I am not sure
294
+ // what that means, but it looks a lot like the arbitrary slider value.
295
+ delay = LMGetKeyThresh();
296
+ if (delay > -1) {
297
+ // This is the slider value, we must multiply by 15 to convert to
298
+ // milliseconds.
299
+ value = (long) delay * 15;
300
+ successful = true;
301
+
302
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: LMGetKeyThresh: %li.\n",
303
+ __FUNCTION__, __LINE__, value);
304
+ }
305
+ }
306
+ #endif
307
+
308
+ return value;
309
+ }
310
+
311
+ UIOHOOK_API long int hook_get_pointer_acceleration_multiplier() {
312
+ // OS X doesn't currently have an acceleration multiplier so we are using the constant from IOHIDGetMouseAcceleration.
313
+ long int value = MOUSE_ACCELERATION_MULTIPLIER;
314
+ if (hook_get_pointer_sensitivity() < 0) {
315
+ value = 0;
316
+ }
317
+
318
+ return value;
319
+ }
320
+
321
+ UIOHOOK_API long int hook_get_pointer_acceleration_threshold() {
322
+ // OS X doesn't currently have an acceleration threshold so we are using 1 as a placeholder.
323
+ long int value = 1;
324
+ if (hook_get_pointer_sensitivity() < 0) {
325
+ value = 0;
326
+ }
327
+
328
+ return value;
329
+ }
330
+
331
+ UIOHOOK_API long int hook_get_pointer_sensitivity() {
332
+ #if defined(USE_APPLICATION_SERVICES) || defined(USE_IOKIT)
333
+ bool successful = false;
334
+ Float32 sensitivity;
335
+ #endif
336
+
337
+ long int value = -1;
338
+
339
+ #ifdef USE_APPLICATION_SERVICES
340
+ if (!successful) {
341
+ CFTypeRef pref_val = CFPreferencesCopyValue(CFSTR("com.apple.mouse.scaling"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
342
+ if (pref_val != NULL) {
343
+ if (CFGetTypeID(pref_val) == CFNumberGetTypeID() && CFNumberGetValue((CFNumberRef) pref_val, kCFNumberFloat32Type, &sensitivity)) {
344
+ value = (long) (sensitivity * MOUSE_ACCELERATION_MULTIPLIER);
345
+
346
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: CFPreferencesCopyValue com.apple.mouse.scaling: %li.\n",
347
+ __FUNCTION__, __LINE__, value);
348
+ }
349
+
350
+ CFRelease(pref_val);
351
+ }
352
+ }
353
+ #endif
354
+
355
+ #ifdef USE_IOKIT
356
+ if (!successful) {
357
+ CFTypeRef cf_type = NULL;
358
+ kern_return_t kern_return = IOHIDCopyCFTypeParameter(connection, CFSTR(kIOHIDMouseAccelerationTypeKey), &cf_type);
359
+ if (kern_return == kIOReturnSuccess) {
360
+ if (cf_type != NULL) {
361
+ if (CFGetTypeID(cf_type) == CFNumberGetTypeID()) {
362
+ if (CFNumberGetValue((CFNumberRef) cf_type, kCFNumberFloat32Type, &sensitivity)) {
363
+ value = (long) sensitivity;
364
+ successful = true;
365
+
366
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: IOHIDCopyCFTypeParameter kIOHIDMouseAccelerationTypeKey: %li.\n",
367
+ __FUNCTION__, __LINE__, value);
368
+ }
369
+ }
370
+
371
+ CFRelease(cf_type);
372
+ }
373
+ }
374
+ }
375
+ #endif
376
+
377
+ return value;
378
+ }
379
+
380
+ UIOHOOK_API long int hook_get_multi_click_time() {
381
+ #if defined(USE_APPLICATION_SERVICES) || defined(USE_IOKIT) || defined(USE_CARBON_LEGACY)
382
+ bool successful = false;
383
+ Float64 time;
384
+ #endif
385
+
386
+ long int value = -1;
387
+
388
+ #ifdef USE_APPLICATION_SERVICES
389
+ if (!successful) {
390
+ CFTypeRef pref_val = CFPreferencesCopyValue(CFSTR("com.apple.mouse.doubleClickThreshold"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
391
+ if (pref_val != NULL) {
392
+ if (CFGetTypeID(pref_val) == CFNumberGetTypeID() && CFNumberGetValue((CFNumberRef) pref_val, kCFNumberFloat64Type, &time)) {
393
+ /* This appears to be the time in seconds */
394
+ value = (long) (time * 1000);
395
+
396
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: CFPreferencesCopyValue: %li.\n",
397
+ __FUNCTION__, __LINE__, value);
398
+ }
399
+
400
+ CFRelease(pref_val);
401
+ }
402
+ }
403
+ #endif
404
+
405
+ #ifdef USE_IOKIT
406
+ if (!successful) {
407
+ CFTypeRef cf_type = NULL;
408
+ kern_return_t kern_return = IOHIDCopyCFTypeParameter(connection, CFSTR(kIOHIDClickTimeKey), &cf_type);
409
+ if (kern_return == kIOReturnSuccess) {
410
+ if (cf_type != NULL) {
411
+ if (CFGetTypeID(cf_type) == CFNumberGetTypeID()) {
412
+ if (CFNumberGetValue((CFNumberRef) cf_type, kCFNumberFloat64Type, &time)) {
413
+ /* This appears to be the time in nanoseconds */
414
+ value = (long) (time / 1000 / 1000);
415
+ successful = true;
416
+
417
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: IORegistryEntryCreateCFProperty: %li.\n",
418
+ __FUNCTION__, __LINE__, value);
419
+ }
420
+ }
421
+
422
+ CFRelease(cf_type);
423
+ }
424
+ }
425
+ }
426
+ #endif
427
+
428
+ #ifdef USE_CARBON_LEGACY
429
+ if (!successful) {
430
+ // Apple documentation states that value is in 'ticks'. I am not sure
431
+ // what that means, but it looks a lot like the arbitrary slider value.
432
+ time = GetDblTime();
433
+ if (time > -1) {
434
+ // This is the slider value, we must multiply by 15 to convert to
435
+ // milliseconds.
436
+ value = (long) time * 15;
437
+ successful = true;
438
+
439
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: GetDblTime: %li.\n",
440
+ __FUNCTION__, __LINE__, value);
441
+ }
442
+ }
443
+ #endif
444
+
445
+ return value;
446
+ }
447
+
448
+
449
+ // Create a shared object constructor.
450
+ __attribute__ ((constructor))
451
+ void on_library_load() {
452
+ #ifdef USE_IOKIT
453
+ io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass));
454
+ if (service) {
455
+ kern_return_t kren_ret = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &connection);
456
+ if (kren_ret != kIOReturnSuccess) {
457
+ logger(LOG_LEVEL_INFO, "%s [%u]: IOServiceOpen failure (%#X)!\n",
458
+ __FUNCTION__, __LINE__, kren_ret);
459
+ }
460
+ }
461
+ #endif
462
+ }
463
+
464
+ // Create a shared object destructor.
465
+ __attribute__ ((destructor))
466
+ void on_library_unload() {
467
+ // Disable the event hook.
468
+ //hook_stop();
469
+
470
+ #ifdef USE_IOKIT
471
+ if (connection) {
472
+ kern_return_t kren_ret = IOServiceClose(connection);
473
+ if (kren_ret != kIOReturnSuccess) {
474
+ logger(LOG_LEVEL_INFO, "%s [%u]: IOServiceClose failure (%#X) %#X!\n",
475
+ __FUNCTION__, __LINE__, kren_ret, kIOReturnError);
476
+ }
477
+ }
478
+ #endif
479
+ }
@@ -0,0 +1,40 @@
1
+ /* libUIOHook: Cross-platform keyboard and mouse hooking from userland.
2
+ * Copyright (C) 2006-2023 Alexander Barker. All Rights Reserved.
3
+ * https://github.com/kwhat/libuiohook/
4
+ *
5
+ * libUIOHook is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Lesser General Public License as published
7
+ * by the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * libUIOHook is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public License
16
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ #include <stdarg.h>
20
+ #include <stdbool.h>
21
+ #include <stdint.h>
22
+ #include <stdio.h>
23
+ #include <uiohook.h>
24
+
25
+ #include "logger.h"
26
+
27
+ static bool default_logger(unsigned int level, const char *format, ...) {
28
+ return false;
29
+ }
30
+
31
+ // Current logger function pointer, should never be null.
32
+ logger_t logger = &default_logger;
33
+
34
+ UIOHOOK_API void hook_set_logger_proc(logger_t logger_proc) {
35
+ if (logger_proc == NULL) {
36
+ logger = &default_logger;
37
+ } else {
38
+ logger = logger_proc;
39
+ }
40
+ }
@@ -0,0 +1,32 @@
1
+ /* libUIOHook: Cross-platform keyboard and mouse hooking from userland.
2
+ * Copyright (C) 2006-2023 Alexander Barker. All Rights Reserved.
3
+ * https://github.com/kwhat/libuiohook/
4
+ *
5
+ * libUIOHook is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Lesser General Public License as published
7
+ * by the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * libUIOHook is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public License
16
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ #ifndef _included_logger
20
+ #define _included_logger
21
+
22
+ #include <uiohook.h>
23
+ #include <stdbool.h>
24
+
25
+ #ifndef __FUNCTION__
26
+ #define __FUNCTION__ __func__
27
+ #endif
28
+
29
+ // logger(level, message)
30
+ extern logger_t logger;
31
+
32
+ #endif