Ejemplo n.º 1
0
wxCFEventLoop::~wxCFEventLoop()
{
    CFRunLoopRemoveObserver(m_runLoop, m_commonModeRunLoopObserver, kCFRunLoopCommonModes);
    CFRunLoopRemoveObserver(m_runLoop, m_defaultModeRunLoopObserver, kCFRunLoopDefaultMode);

    CFRelease(m_defaultModeRunLoopObserver);
    CFRelease(m_commonModeRunLoopObserver);
}
Ejemplo n.º 2
0
static void *hook_thread_proc(void *arg) {
	int *status = (int *) arg;
	*status = UIOHOOK_FAILURE;

	bool accessibilityEnabled = false;

	// FIXME Move to osx_input_helper.h after testing.
	#ifdef USE_WEAK_IMPORT
	// Check and make sure assistive devices is enabled.
	if (AXIsProcessTrustedWithOptions != NULL) {
		// New accessibility API 10.9 and later.
		const void * keys[] = { kAXTrustedCheckOptionPrompt };
		const void * values[] = { kCFBooleanTrue };

		CFDictionaryRef options = CFDictionaryCreate(
				kCFAllocatorDefault,
				keys,
				values,
				sizeof(keys) / sizeof(*keys),
				&kCFCopyStringDictionaryKeyCallBacks,
				&kCFTypeDictionaryValueCallBacks);

		accessibilityEnabled = AXIsProcessTrustedWithOptions(options);
	}
	else {
		// Old accessibility check 10.8 and older.
		accessibilityEnabled = AXAPIEnabled();
	}
	#else
	// Dynamically load the application services framework for examination.
	const char *dlError = NULL;
	void *libApplicaitonServices = dlopen("/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices", RTLD_LAZY);
	dlError = dlerror();
	if (libApplicaitonServices != NULL && dlError == NULL) {
		// Check for the new function AXIsProcessTrustedWithOptions().
		*(void **) (&AXIsProcessTrustedWithOptions_t) = dlsym(libApplicaitonServices, "AXIsProcessTrustedWithOptions");
		dlError = dlerror();
		if (AXIsProcessTrustedWithOptions_t != NULL && dlError == NULL) {
			// Check for property kAXTrustedCheckOptionPrompt
			CFStringRef kAXTrustedCheckOptionPrompt_t = (CFStringRef) dlsym(libApplicaitonServices, "kAXTrustedCheckOptionPrompt");
			dlError = dlerror();
			if (kAXTrustedCheckOptionPrompt_t != NULL && dlError == NULL) {
				// New accessibility API 10.9 and later.
				// FIXME This is causing a segfault on 10.9 probably due to an invalid pointer type.
				const void * keys[] = { kAXTrustedCheckOptionPrompt_t };
				const void * values[] = { kCFBooleanTrue };

				CFDictionaryRef options = CFDictionaryCreate(
						kCFAllocatorDefault,
						keys,
						values,
						sizeof(keys) / sizeof(*keys),
						&kCFCopyStringDictionaryKeyCallBacks,
						&kCFTypeDictionaryValueCallBacks);

				accessibilityEnabled = (*AXIsProcessTrustedWithOptions_t)(options);
			}
		}
		else {
			logger(LOG_LEVEL_DEBUG,	"%s [%u]: Falling back to AXAPIEnabled(). (%s)\n",
					__FUNCTION__, __LINE__, dlError);

			// Check for the fallback function AXAPIEnabled().
			*(void **) (&AXAPIEnabled_t) = dlsym(libApplicaitonServices, "AXAPIEnabled");
			dlError = dlerror();
			if (AXAPIEnabled_t != NULL && dlError == NULL) {
				// Old accessibility check 10.8 and older.
				accessibilityEnabled = (*AXAPIEnabled_t)();
			}
			else {
				// Could not load the AXAPIEnabled function!
				logger(LOG_LEVEL_ERROR,	"%s [%u]: Failed to locate AXAPIEnabled()! (%s)\n",
						__FUNCTION__, __LINE__, dlError);
			}
		}

		dlclose(libApplicaitonServices);
	}
	else {
		// Could not load the ApplicationServices framework!
		logger(LOG_LEVEL_ERROR,	"%s [%u]: Failed to lazy load the ApplicationServices framework! (%s)\n",
				__FUNCTION__, __LINE__, dlError);
	}
	#endif

	if (accessibilityEnabled == true) {
		logger(LOG_LEVEL_DEBUG,	"%s [%u]: Accessibility API is enabled.\n",
				__FUNCTION__, __LINE__);

		// Setup the event mask to listen for.
		CGEventMask event_mask =	CGEventMaskBit(kCGEventKeyDown) |
									CGEventMaskBit(kCGEventKeyUp) |
									CGEventMaskBit(kCGEventFlagsChanged) |

									CGEventMaskBit(kCGEventLeftMouseDown) |
									CGEventMaskBit(kCGEventLeftMouseUp) |
									CGEventMaskBit(kCGEventLeftMouseDragged) |

									CGEventMaskBit(kCGEventRightMouseDown) |
									CGEventMaskBit(kCGEventRightMouseUp) |
									CGEventMaskBit(kCGEventRightMouseDragged) |

									CGEventMaskBit(kCGEventOtherMouseDown) |
									CGEventMaskBit(kCGEventOtherMouseUp) |
									CGEventMaskBit(kCGEventOtherMouseDragged) |

									CGEventMaskBit(kCGEventMouseMoved) |
									CGEventMaskBit(kCGEventScrollWheel);

		#ifdef USE_DEBUG
		event_mask |= CGEventMaskBit(kCGEventNull);
		#endif

		CFMachPortRef event_port = CGEventTapCreate(
										kCGSessionEventTap,				// kCGHIDEventTap
										kCGHeadInsertEventTap,			// kCGTailAppendEventTap
										kCGEventTapOptionListenOnly,	// kCGEventTapOptionDefault See Bug #22
										event_mask,
										hook_event_proc,
										NULL
									);


		if (event_port != NULL) {
			logger(LOG_LEVEL_DEBUG,	"%s [%u]: CGEventTapCreate Successful.\n",
					__FUNCTION__, __LINE__);

			event_source = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, event_port, 0);
			if (event_source != NULL) {
				logger(LOG_LEVEL_DEBUG,	"%s [%u]: CFMachPortCreateRunLoopSource successful.\n",
						__FUNCTION__, __LINE__);

				event_loop = CFRunLoopGetCurrent();
				if (event_loop != NULL) {
					logger(LOG_LEVEL_DEBUG,	"%s [%u]: CFRunLoopGetCurrent successful.\n",
							__FUNCTION__, __LINE__);

					// Initialize Native Input Functions.
					load_input_helper();


					// Create run loop observers.
					CFRunLoopObserverRef observer = CFRunLoopObserverCreate(
														kCFAllocatorDefault,
														kCFRunLoopEntry | kCFRunLoopExit, //kCFRunLoopAllActivities,
														true,
														0,
														hook_status_proc,
														NULL
													);

					if (observer != NULL) {
						// Set the exit status.
						*status = UIOHOOK_SUCCESS;

						start_message_port_runloop();

						CFRunLoopAddSource(event_loop, event_source, kCFRunLoopDefaultMode);
						CFRunLoopAddObserver(event_loop, observer, kCFRunLoopDefaultMode);

						CFRunLoopRun();

						// Lock back up until we are done processing the exit.
						CFRunLoopRemoveObserver(event_loop, observer, kCFRunLoopDefaultMode);
						CFRunLoopRemoveSource(event_loop, event_source, kCFRunLoopDefaultMode);
						CFRunLoopObserverInvalidate(observer);

						stop_message_port_runloop();
					}
					else {
						// We cant do a whole lot of anything if we cant
						// create run loop observer.

						logger(LOG_LEVEL_ERROR,	"%s [%u]: CFRunLoopObserverCreate failure!\n",
								__FUNCTION__, __LINE__);

						// Set the exit status.
						*status = UIOHOOK_ERROR_OBSERVER_CREATE;
					}

					// Cleanup Native Input Functions.
					unload_input_helper();
				}
				else {
					logger(LOG_LEVEL_ERROR,	"%s [%u]: CFRunLoopGetCurrent failure!\n",
							__FUNCTION__, __LINE__);

					// Set the exit status.
					*status = UIOHOOK_ERROR_GET_RUNLOOP;
				}

				// Clean up the event source.
				CFRelease(event_source);
			}
			else {
				logger(LOG_LEVEL_ERROR,	"%s [%u]: CFMachPortCreateRunLoopSource failure!\n",
					__FUNCTION__, __LINE__);

				// Set the exit status.
				*status = UIOHOOK_ERROR_CREATE_RUN_LOOP_SOURCE;
			}

			// Stop the CFMachPort from receiving any more messages.
			CFMachPortInvalidate(event_port);
			CFRelease(event_port);
		}
		else {
			logger(LOG_LEVEL_ERROR,	"%s [%u]: Failed to create event port!\n",
					__FUNCTION__, __LINE__);

			// Set the exit status.
			*status = UIOHOOK_ERROR_EVENT_PORT;
		}
	}
	else {
		logger(LOG_LEVEL_ERROR,	"%s [%u]: Accessibility API is disabled!\n",
				__FUNCTION__, __LINE__);

		// Set the exit status.
		*status = UIOHOOK_ERROR_AXAPI_DISABLED;
	}

	logger(LOG_LEVEL_DEBUG,	"%s [%u]: Something, something, something, complete.\n",
			__FUNCTION__, __LINE__);

	// Make sure we signal that we have passed any exception throwing code.
	pthread_mutex_unlock(&hook_control_mutex);

	pthread_exit(status);
}