int main() { // Disable the logger. hook_set_logger_proc(&logger_proc); // Retrieves the keyboard auto repeat rate. long int repeat_rate = hook_get_auto_repeat_rate(); if (repeat_rate >= 0) { fprintf(stdout, "Auto Repeat Rate:\t%ld\n", repeat_rate); } else { fprintf(stderr, "Failed to aquire keyboard auto repeat rate!\n"); } // Retrieves the keyboard auto repeat delay. long int repeat_delay = hook_get_auto_repeat_delay(); if (repeat_delay >= 0) { fprintf(stdout, "Auto Repeat Delay:\t%ld\n", repeat_delay); } else { fprintf(stderr, "Failed to acquire keyboard auto repeat delay!\n"); } // Retrieves the mouse acceleration multiplier. long int acceleration_multiplier = hook_get_pointer_acceleration_multiplier(); if (acceleration_multiplier >= 0) { fprintf(stdout, "Mouse Acceleration Multiplier:\t%ld\n", acceleration_multiplier); } else { fprintf(stderr, "Failed to acquire mouse acceleration multiplier!\n"); } // Retrieves the mouse acceleration threshold. long int acceleration_threshold = hook_get_pointer_acceleration_threshold(); if (acceleration_threshold >= 0) { fprintf(stdout, "Mouse Acceleration Threshold:\t%ld\n", acceleration_threshold); } else { fprintf(stderr, "Failed to acquire mouse acceleration threshold!\n"); } // Retrieves the mouse sensitivity. long int sensitivity = hook_get_pointer_sensitivity(); if (sensitivity >= 0) { fprintf(stdout, "Mouse Sensitivity:\t%ld\n", sensitivity); } else { fprintf(stderr, "Failed to acquire keyboard auto repeat rate!\n"); } // Retrieves the double/triple click interval. long int click_time = hook_get_multi_click_time(); if (click_time >= 0) { fprintf(stdout, "Multi-Click Time:\t%ld\n", click_time); } else { fprintf(stderr, "Failed to acquire keyboard auto repeat rate!\n"); } return EXIT_SUCCESS; }
// JNI exit point, This is executed when the Java virtual machine detaches from the native library. JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { // Grab the currently JNI interface pointer so we can cleanup the // system properties set on load. JNIEnv *env = NULL; if ((*jvm)->GetEnv(jvm, (void **)(&env), jni_version) == JNI_OK) { // Clear java properties from native sources. jni_ClearProperties(env); } else { // It is not critical that these values are cleared so no exception // will be thrown. jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to call jni_ClearProperties()!\n", __FUNCTION__, __LINE__); } jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: JNI Unloaded.\n", __FUNCTION__, __LINE__); // Unset the hook callback function to dispatch events. hook_set_dispatch_proc(NULL); // Unset Java logger for native code messages. hook_set_logger_proc(NULL); if (env != NULL) { jni_DestroyGlobals(env); } }
int hook_enable() { // Lock the thread control mutex. This will be unlocked when the // thread has finished starting, or when it has fully stopped. #ifdef _WIN32 WaitForSingleObject(hook_control_mutex, INFINITE); #else pthread_mutex_lock(&hook_control_mutex); #endif // Set the initial status. int status = UIOHOOK_FAILURE; #ifndef _WIN32 // Create the thread attribute. pthread_attr_t hook_thread_attr; pthread_attr_init(&hook_thread_attr); // Get the policy and priority for the thread attr. int policy; pthread_attr_getschedpolicy(&hook_thread_attr, &policy); int priority = sched_get_priority_max(policy); #endif #if defined(_WIN32) DWORD hook_thread_id; DWORD *hook_thread_status = malloc(sizeof(DWORD)); hook_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) hook_thread_proc, hook_thread_status, 0, &hook_thread_id); if (hook_thread != INVALID_HANDLE_VALUE) { #else int *hook_thread_status = malloc(sizeof(int)); if (pthread_create(&hook_thread, &hook_thread_attr, hook_thread_proc, hook_thread_status) == 0) { #endif #if defined(_WIN32) // Attempt to set the thread priority to time critical. if (SetThreadPriority(hook_thread, THREAD_PRIORITY_TIME_CRITICAL) == 0) { logger_proc(LOG_LEVEL_WARN, "%s [%u]: Could not set thread priority %li for thread %#p! (%#lX)\n", __FUNCTION__, __LINE__, (long) THREAD_PRIORITY_TIME_CRITICAL, hook_thread , (unsigned long) GetLastError()); } #elif (defined(__APPLE__) && defined(__MACH__)) || _POSIX_C_SOURCE >= 200112L // Some POSIX revisions do not support pthread_setschedprio so we will // use pthread_setschedparam instead. struct sched_param param = { .sched_priority = priority }; if (pthread_setschedparam(hook_thread, SCHED_OTHER, ¶m) != 0) { logger_proc(LOG_LEVEL_WARN, "%s [%u]: Could not set thread priority %i for thread 0x%lX!\n", __FUNCTION__, __LINE__, priority, (unsigned long) hook_thread); } #else // Raise the thread priority using glibc pthread_setschedprio. if (pthread_setschedprio(hook_thread, priority) != 0) { logger_proc(LOG_LEVEL_WARN, "%s [%u]: Could not set thread priority %i for thread 0x%lX!\n", __FUNCTION__, __LINE__, priority, (unsigned long) hook_thread); } #endif // Wait for the thread to indicate that it has passed the // initialization portion by blocking until either a EVENT_HOOK_ENABLED // event is received or the thread terminates. // NOTE This unlocks the hook_control_mutex while we wait. #ifdef _WIN32 WaitForSingleObject(hook_control_cond, INFINITE); #else pthread_cond_wait(&hook_control_cond, &hook_control_mutex); #endif #ifdef _WIN32 if (WaitForSingleObject(hook_running_mutex, 0) != WAIT_TIMEOUT) { #else if (pthread_mutex_trylock(&hook_running_mutex) == 0) { #endif // Lock Successful; The hook is not running but the hook_control_cond // was signaled! This indicates that there was a startup problem! // Get the status back from the thread. #ifdef _WIN32 WaitForSingleObject(hook_thread, INFINITE); GetExitCodeThread(hook_thread, hook_thread_status); #else pthread_join(hook_thread, (void **) &hook_thread_status); status = *hook_thread_status; #endif } else { // Lock Failure; The hook is currently running and wait was signaled // indicating that we have passed all possible start checks. We can // always assume a successful startup at this point. status = UIOHOOK_SUCCESS; } free(hook_thread_status); logger_proc(LOG_LEVEL_DEBUG, "%s [%u]: Thread Result: (%#X).\n", __FUNCTION__, __LINE__, status); } else { status = UIOHOOK_ERROR_THREAD_CREATE; } // Make sure the control mutex is unlocked. #ifdef _WIN32 ReleaseMutex(hook_control_mutex); #else pthread_mutex_unlock(&hook_control_mutex); #endif return status; } int main() { // Lock the thread control mutex. This will be unlocked when the // thread has finished starting, or when it has fully stopped. #ifdef _WIN32 // Create event handles for the thread hook. hook_running_mutex = CreateMutex(NULL, FALSE, TEXT("hook_running_mutex")); hook_control_mutex = CreateMutex(NULL, FALSE, TEXT("hook_control_mutex")); hook_control_cond = CreateEvent(NULL, TRUE, FALSE, TEXT("hook_control_cond")); #else pthread_mutex_init(&hook_running_mutex, NULL); pthread_mutex_init(&hook_control_mutex, NULL); pthread_cond_init(&hook_control_cond, NULL); #endif // Set the logger callback for library output. hook_set_logger_proc(&logger_proc); // Set the event callback for uiohook events. hook_set_dispatch_proc(&dispatch_proc); // Start the hook and block. // NOTE If EVENT_HOOK_ENABLED was delivered, the status will always succeed. int status = hook_enable(); switch (status) { case UIOHOOK_SUCCESS: // We no longer block, so we need to explicitly wait for the thread to die. #ifdef _WIN32 WaitForSingleObject(hook_thread, INFINITE); #else #if defined(__APPLE__) && defined(__MACH__) // NOTE Darwin requires that you start your own runloop from main. CFRunLoopRun(); #endif pthread_join(hook_thread, NULL); #endif break; // System level errors. case UIOHOOK_ERROR_OUT_OF_MEMORY: logger_proc(LOG_LEVEL_ERROR, "Failed to allocate memory. (%#X)\n", status); break; // X11 specific errors. case UIOHOOK_ERROR_X_OPEN_DISPLAY: logger_proc(LOG_LEVEL_ERROR, "Failed to open X11 display. (%#X)\n", status); break; case UIOHOOK_ERROR_X_RECORD_NOT_FOUND: logger_proc(LOG_LEVEL_ERROR, "Unable to locate XRecord extension. (%#X)\n", status); break; case UIOHOOK_ERROR_X_RECORD_ALLOC_RANGE: logger_proc(LOG_LEVEL_ERROR, "Unable to allocate XRecord range. (%#X)\n", status); break; case UIOHOOK_ERROR_X_RECORD_CREATE_CONTEXT: logger_proc(LOG_LEVEL_ERROR, "Unable to allocate XRecord context. (%#X)\n", status); break; case UIOHOOK_ERROR_X_RECORD_ENABLE_CONTEXT: logger_proc(LOG_LEVEL_ERROR, "Failed to enable XRecord context. (%#X)\n", status); break; // Windows specific errors. case UIOHOOK_ERROR_SET_WINDOWS_HOOK_EX: logger_proc(LOG_LEVEL_ERROR, "Failed to register low level windows hook. (%#X)\n", status); break; // Darwin specific errors. case UIOHOOK_ERROR_AXAPI_DISABLED: logger_proc(LOG_LEVEL_ERROR, "Failed to enable access for assistive devices. (%#X)\n", status); break; case UIOHOOK_ERROR_CREATE_EVENT_PORT: logger_proc(LOG_LEVEL_ERROR, "Failed to create apple event port. (%#X)\n", status); break; case UIOHOOK_ERROR_CREATE_RUN_LOOP_SOURCE: logger_proc(LOG_LEVEL_ERROR, "Failed to create apple run loop source. (%#X)\n", status); break; case UIOHOOK_ERROR_GET_RUNLOOP: logger_proc(LOG_LEVEL_ERROR, "Failed to acquire apple run loop. (%#X)\n", status); break; case UIOHOOK_ERROR_CREATE_OBSERVER: logger_proc(LOG_LEVEL_ERROR, "Failed to create apple run loop observer. (%#X)\n", status); break; // Default error. case UIOHOOK_FAILURE: default: logger_proc(LOG_LEVEL_ERROR, "An unknown hook error occurred. (%#X)\n", status); break; } #ifdef _WIN32 // Create event handles for the thread hook. CloseHandle(hook_thread); CloseHandle(hook_running_mutex); CloseHandle(hook_control_mutex); CloseHandle(hook_control_cond); #else pthread_mutex_destroy(&hook_running_mutex); pthread_mutex_destroy(&hook_control_mutex); pthread_cond_destroy(&hook_control_cond); #endif return status; }
// JNI entry point, This is executed when the Java virtual machine attaches to the native library. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { /* Grab the currently running virtual machine so we can attach to it in * functions that are not called from java. */ jvm = vm; JNIEnv *env = NULL; if ((*jvm)->GetEnv(jvm, (void **)(&env), jni_version) == JNI_OK) { // Create all the global class references onload to prevent class loader // issues with JNLP and some IDE's. if (jni_CreateGlobals(env) != JNI_OK) { #ifndef USE_QUIET fprintf(stderr, "%s [%u]: CreateJNIGlobals() failed!\n", __FUNCTION__, __LINE__); #endif jni_ThrowFatalError(env, "Failed to locate one or more required classes."); } #ifndef USE_QUIET jclass PrintStream_class = (*env)->FindClass(env, "java/io/PrintStream"); jfieldID out_id = (*env)->GetStaticFieldID(env, java_lang_System->cls, "out", "Ljava/io/PrintStream;"); if (PrintStream_class != NULL && out_id != NULL) { jmethodID println_id = (*env)->GetMethodID(env, PrintStream_class, "println", "(Ljava/lang/String;)V"); jobject out = (*env)->GetStaticObjectField(env, PrintStream_class, out_id); if (println_id != NULL && out_id != NULL) { jstring copyright = (*env)->NewStringUTF(env, "\n" "JNativeHook: Global keyboard and mouse hooking for Java.\n" "Copyright (C) 2006-2014 Alexander Barker. All Rights Received.\n" "https://github.com/kwhat/jnativehook/\n" "\n" "JNativeHook is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU Lesser General Public License as published\n" "by the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "JNativeHook is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU Lesser General Public License\n" "along with this program. If not, see <http://www.gnu.org/licenses/>.\n"); (*env)->CallVoidMethod(env, out, println_id, copyright); } } #endif // Set Java logger for native code messages. hook_set_logger_proc(&jni_Logger); // Set java properties from native sources. jni_SetProperties(env); // Set the hook callback function to dispatch events. hook_set_dispatch_proc(&jni_EventDispatcher); } else { #ifndef USE_QUIET fprintf(stderr, "%s [%u]: GetEnv() failed!\n", __FUNCTION__, __LINE__); #endif jni_ThrowFatalError(env, "Failed to acquire JNI interface pointer"); } jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: JNI Loaded.\n", __FUNCTION__, __LINE__); return jni_version; }
int main() { // Disable the logger. hook_set_logger_proc(&logger_proc); // Retrieves an array of screen data for each available monitor. uint8_t count = 0; screen_data *screens = hook_create_screen_info(&count); if (screens != NULL) { fprintf(stdout, "Found %d Monitors:\n", count); for (int i = 0; i < count; i++) { fprintf(stdout, "\tNumber:\t\t%d\n", screens[i].number); fprintf(stdout, "\tOffset X:\t%d\n", screens[i].x); fprintf(stdout, "\tOffset Y:\t%d\n", screens[i].y); fprintf(stdout, "\tWidth:\t\t%d\n", screens[i].width); fprintf(stdout, "\tHeight:\t\t%d\n", screens[i].height); fprintf(stdout, "\n"); } // You are responsible for freeing the memory returned by hook_create_screen_info. free(screens); } else { fprintf(stderr, "Failed to aquire screen information!\n"); } // Retrieves the keyboard auto repeat rate. long int repeat_rate = hook_get_auto_repeat_rate(); if (repeat_rate >= 0) { fprintf(stdout, "Auto Repeat Rate:\t%ld\n", repeat_rate); } else { fprintf(stderr, "Failed to aquire keyboard auto repeat rate!\n"); } // Retrieves the keyboard auto repeat delay. long int repeat_delay = hook_get_auto_repeat_delay(); if (repeat_delay >= 0) { fprintf(stdout, "Auto Repeat Delay:\t%ld\n", repeat_delay); } else { fprintf(stderr, "Failed to aquire keyboard auto repeat delay!\n"); } // Retrieves the mouse acceleration multiplier. long int acceleration_multiplier = hook_get_pointer_acceleration_multiplier(); if (acceleration_multiplier >= 0) { fprintf(stdout, "Mouse Acceleration Multiplier:\t%ld\n", acceleration_multiplier); } else { fprintf(stderr, "Failed to aquire mouse acceleration multiplier!\n"); } // Retrieves the mouse acceleration threshold. long int acceleration_threshold = hook_get_pointer_acceleration_threshold(); if (acceleration_threshold >= 0) { fprintf(stdout, "Mouse Acceleration Threshold:\t%ld\n", acceleration_threshold); } else { fprintf(stderr, "Failed to aquire mouse acceleration threshold!\n"); } // Retrieves the mouse sensitivity. long int sensitivity = hook_get_pointer_sensitivity(); if (sensitivity >= 0) { fprintf(stdout, "Mouse Sensitivity:\t%ld\n", sensitivity); } else { fprintf(stderr, "Failed to aquire keyboard auto repeat rate!\n"); } // Retrieves the double/triple click interval. long int click_time = hook_get_multi_click_time(); if (click_time >= 0) { fprintf(stdout, "Multi-Click Time:\t%ld\n", click_time); } else { fprintf(stderr, "Failed to aquire keyboard auto repeat rate!\n"); } return EXIT_SUCCESS; }