diff --git a/ext/toolchain/commands1.py b/ext/toolchain/commands1.py index 71b29b03..50f97b3c 100644 --- a/ext/toolchain/commands1.py +++ b/ext/toolchain/commands1.py @@ -41,7 +41,7 @@ class Toolchain: cmd_opt_dict = { 'about' : ['', []], 'setup' : ['g:', ['generator=']], - 'configure' : ['g:dr', ['generator=', 'debug', 'release', 'mac-sdk=']], + 'configure' : ['g:dr', ['generator=', 'debug', 'release', 'mac-sdk=', 'mac-identity=']], 'build' : ['dr', ['debug', 'release']], 'clean' : ['dr', ['debug', 'release']], 'update' : ['', []], @@ -57,7 +57,7 @@ class Toolchain: 'genlist' : ['', []], 'reset' : ['', []], 'signwin' : ['', ['pfx=', 'pwd=', 'dist']], - 'signmac' : ['', ['identity=']] + 'signmac' : ['', []] } # aliases to valid commands @@ -244,6 +244,9 @@ class InternalCommands: # by default, unknown macSdk = None + # by default, unknown + macIdentity = None + # cryptoPP dir with version number cryptoPPDir = 'cryptopp562' @@ -384,14 +387,31 @@ class InternalCommands: self.ensure_setup_latest() if sys.platform == "darwin": + config = self.getConfig() + if self.macSdk: - sdkDir = self.getMacSdkDir() - if not os.path.exists(sdkDir): - raise Exception("Mac SDK not found at: " + sdkDir) - - os.environ["MACOSX_DEPLOYMENT_TARGET"] = self.macSdk - else: + config.set('hm', 'macSdk', self.macSdk) + elif config.has_option("hm", "macSdk"): + self.macSdk = config.get('hm', 'macSdk') + + if self.macIdentity: + config.set('hm', 'macIdentity', self.macIdentity) + elif config.has_option("hm", "macIdentity"): + self.macIdentity = config.get('hm', 'macIdentity') + + self.write_config(config) + + if not self.macSdk: raise Exception("Arg missing: --mac-sdk "); + + if not self.macIdentity: + raise Exception("Arg missing: --mac-identity "); + + sdkDir = self.getMacSdkDir() + if not os.path.exists(sdkDir): + raise Exception("Mac SDK not found at: " + sdkDir) + + os.environ["MACOSX_DEPLOYMENT_TARGET"] = self.macSdk # default is release if target == '': @@ -434,11 +454,6 @@ class InternalCommands: sdkDir = self.getMacSdkDir() cmake_args += " -DCMAKE_OSX_SYSROOT=" + sdkDir cmake_args += " -DCMAKE_OSX_DEPLOYMENT_TARGET=" + self.macSdk - - # store the sdk version for the build command - config = self.getConfig() - config.set('cmake', 'mac_sdk', self.macSdk) - self.write_config(config) # if not visual studio, use parent dir sourceDir = generator.getSourceDir() @@ -464,6 +479,11 @@ class InternalCommands: if generator.cmakeName.find('Eclipse') != -1: self.fixCmakeEclipseBug() + # manually change .xcodeproj to add code sign for + # synmacph project and specify its info.plist + if generator.cmakeName.find('Xcode') != -1: + self.fixXcodeProject(target) + if err != 0: raise Exception('CMake encountered error: ' + str(err)) @@ -538,6 +558,59 @@ class InternalCommands: file.truncate() file.close() + def fixXcodeProject(self, target): + print "Fixing Xcode project..." + + insertContent = ( + "CODE_SIGN_IDENTITY = '%s';\n" + "INFOPLIST_FILE = %s/src/cmd/synmacph/Info.plist;\n") % ( + self.macIdentity, + os.getcwd() + ) + + dir = self.getBuildDir(target) + file = open(dir + '/synergy.xcodeproj/project.pbxproj', 'r+') + contents = file.readlines() + + buildConfigurationsFound = None + releaseConfigRefFound = None + releaseBuildSettingsFound = None + fixed = None + releaseConfigRef = ""; + + for line in contents: + if buildConfigurationsFound: + matchObj = re.search(r'\s*(.*)\s*\/\*\s*Release\s*\*\/,', line, re.I) + if matchObj: + releaseConfigRef = matchObj.group(1) + releaseConfigRefFound = True + break + elif buildConfigurationsFound == None: + if 'PBXNativeTarget "synmacph" */ = {' in line: + buildConfigurationsFound = True + + if not releaseConfigRefFound: + raise Exception("Release config ref not found.") + + for n, line in enumerate(contents): + if releaseBuildSettingsFound == None: + if releaseConfigRef + '/* Release */ = {' in line: + releaseBuildSettingsFound = True + elif fixed == None: + if 'buildSettings = {' in line: + contents[n] = line + insertContent + fixed = True + + if not fixed: + raise Exception("Xcode project was not fixed.") + + file.seek(0) + for line in contents: + file.write(line) + file.truncate() + file.close() + return + def persist_cmake(self): # even though we're running `cmake --version`, we're only doing this for the 0 return # code; we don't care about the version, since CMakeLists worrys about this for us. @@ -609,6 +682,8 @@ class InternalCommands: targets += [self.defaultTarget,] self.ensure_setup_latest() + + self.loadConfig() # allow user to skip core compile if self.enableMakeCore: @@ -618,13 +693,20 @@ class InternalCommands: if self.enableMakeGui: self.makeGui(targets) + def loadConfig(self): + config = self.getConfig() + + if config.has_option("hm", "macSdk"): + self.macSdk = config.get("hm", "macSdk") + + if config.has_option("hm", "macIdentity"): + self.macIdentity = config.get("hm", "macIdentity") + def makeCore(self, targets): generator = self.getGeneratorFromConfig().cmakeName - config = self.getConfig() - if config.has_option("cmake", "mac_sdk"): - self.macSdk = config.get("cmake", "mac_sdk") + if self.macSdk: os.environ["MACOSX_DEPLOYMENT_TARGET"] = self.macSdk if generator.find('Unix Makefiles') != -1: @@ -686,6 +768,11 @@ class InternalCommands: shutil.copy(targetDir + "/synergyc", bundleBinDir) shutil.copy(targetDir + "/synergys", bundleBinDir) shutil.copy(targetDir + "/syntool", bundleBinDir) + + launchServicesDir = dir + "/Synergy.app/Contents/Library/LaunchServices/" + if not os.path.exists(launchServicesDir): + os.makedirs(launchServicesDir) + shutil.copy(targetDir + "/synmacph", launchServicesDir) if self.enableMakeGui: # use qt to copy libs to bundle so no dependencies are needed. do not create a @@ -715,10 +802,14 @@ class InternalCommands: frameworkRootDir + "/" + dir + "/Contents/Info.plist", target + "/" + dir + "/Resources/") - def signmac(self, identity): + def signmac(self): + self.loadConfig() + if not self.macIdentity: + raise Exception("run config with --mac-identity") + self.try_chdir("bin") err = os.system( - 'codesign --deep -fs "' + identity + '" Synergy.app') + 'codesign --deep -fs "' + self.macIdentity + '" Synergy.app') self.restore_chdir() if err != 0: @@ -1623,6 +1714,8 @@ class CommandHandler: self.qtDir = a elif o == '--mac-sdk': self.ic.macSdk = a + elif o == '--mac-identity': + self.ic.macIdentity = a def about(self): self.ic.about() @@ -1721,9 +1814,4 @@ class CommandHandler: self.ic.signwin(pfx, pwd, dist) def signmac(self): - idenity = None - for o, a in self.opts: - if o == '--identity': - identity = a - - self.ic.signmac(identity) + self.ic.signmac() diff --git a/src/cmd/CMakeLists.txt b/src/cmd/CMakeLists.txt index 6b2fa3c3..488cf09e 100644 --- a/src/cmd/CMakeLists.txt +++ b/src/cmd/CMakeLists.txt @@ -23,3 +23,7 @@ add_subdirectory(syntool) if (WIN32) add_subdirectory(synergyp) endif() + +if (APPLE) + add_subdirectory(synmacph) +endif() diff --git a/src/cmd/synmacph/CMakeLists.txt b/src/cmd/synmacph/CMakeLists.txt new file mode 100644 index 00000000..180a3405 --- /dev/null +++ b/src/cmd/synmacph/CMakeLists.txt @@ -0,0 +1,39 @@ +# synergy -- mouse and keyboard sharing utility +# Copyright (C) 2014 Bolton Software Ltd. +# +# This package is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# found in the file COPYING that should have accompanied this file. +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +file(GLOB sources "*.c" "*.plist") + +include_directories( + ../ +) + +add_executable(synmacph ${sources}) + +get_target_property(current_property synmacph LINK_FLAGS) + +set(OTHER_LINK_FLAGS "-sectcreate __TEXT __info_plist ${root_dir}/src/cmd/synmacph/Info.plist -sectcreate __TEXT __launchd_plist ${root_dir}/src/cmd/synmacph/Launchd.plist") + +if (NOT ${current_property}) + set_target_properties(synmacph PROPERTIES LINK_FLAGS ${OTHER_LINK_FLAGS}) +endif() + +target_link_libraries(synmacph) + +if (CONF_CPACK) + install(TARGETS + synmacph + COMPONENT core + DESTINATION bin) +endif() \ No newline at end of file diff --git a/src/cmd/synmacph/Info.plist b/src/cmd/synmacph/Info.plist new file mode 100644 index 00000000..fcbc5a88 --- /dev/null +++ b/src/cmd/synmacph/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + synmacph + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + synmacph + CFBundleVersion + 1.5 + SMAuthorizedClients + + anchor apple generic and identifier "synergy" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = SP58PFWX5L) + + + diff --git a/src/cmd/synmacph/Launchd.plist b/src/cmd/synmacph/Launchd.plist new file mode 100644 index 00000000..d56cca85 --- /dev/null +++ b/src/cmd/synmacph/Launchd.plist @@ -0,0 +1,14 @@ + + + + + Label + synmacph + RunAtLoad + + LaunchOnlyOnce + + KeepAlive + + + diff --git a/src/cmd/synmacph/synmacph.c b/src/cmd/synmacph/synmacph.c new file mode 100644 index 00000000..e8d117a1 --- /dev/null +++ b/src/cmd/synmacph/synmacph.c @@ -0,0 +1,34 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2014 Bolton Software Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +int main(int argc, const char * argv[]) +{ + #pragma unused(argc) + #pragma unused(argv) + + system("sudo sqlite3 /Library/Application\\ Support/com.apple.TCC/TCC.db 'delete from access where client like \"%Synergy.app%\"'"); + + (void) sleep(10); + + return EXIT_SUCCESS; +} + diff --git a/src/gui/gui.pro b/src/gui/gui.pro index e10bb90b..eb5ec372 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -1,98 +1,102 @@ -QT += widgets network -TEMPLATE = app -TARGET = synergy -DEPENDPATH += . \ - res -INCLUDEPATH += . \ - src -FORMS += res/MainWindowBase.ui \ - res/AboutDialogBase.ui \ - res/ServerConfigDialogBase.ui \ - res/ScreenSettingsDialogBase.ui \ - res/ActionDialogBase.ui \ - res/HotkeyDialogBase.ui \ - res/SettingsDialogBase.ui \ - res/SetupWizardBase.ui -SOURCES += src/main.cpp \ - src/MainWindow.cpp \ - src/AboutDialog.cpp \ - src/ServerConfig.cpp \ - src/ServerConfigDialog.cpp \ - src/ScreenSetupView.cpp \ - src/Screen.cpp \ - src/ScreenSetupModel.cpp \ - src/NewScreenWidget.cpp \ - src/TrashScreenWidget.cpp \ - src/ScreenSettingsDialog.cpp \ - src/BaseConfig.cpp \ - src/HotkeyDialog.cpp \ - src/ActionDialog.cpp \ - src/Hotkey.cpp \ - src/Action.cpp \ - src/KeySequence.cpp \ - src/KeySequenceWidget.cpp \ - src/SettingsDialog.cpp \ - src/AppConfig.cpp \ - src/QSynergyApplication.cpp \ - src/VersionChecker.cpp \ - src/SetupWizard.cpp \ - src/IpcClient.cpp \ - src/IpcReader.cpp \ - src/Ipc.cpp \ - src/SynergyLocale.cpp \ - src/QUtility.cpp \ - src/PremiumAuth.cpp -HEADERS += src/MainWindow.h \ - src/AboutDialog.h \ - src/ServerConfig.h \ - src/ServerConfigDialog.h \ - src/ScreenSetupView.h \ - src/Screen.h \ - src/ScreenSetupModel.h \ - src/NewScreenWidget.h \ - src/TrashScreenWidget.h \ - src/ScreenSettingsDialog.h \ - src/BaseConfig.h \ - src/HotkeyDialog.h \ - src/ActionDialog.h \ - src/Hotkey.h \ - src/Action.h \ - src/KeySequence.h \ - src/KeySequenceWidget.h \ - src/SettingsDialog.h \ - src/AppConfig.h \ - src/QSynergyApplication.h \ - src/VersionChecker.h \ - src/SetupWizard.h \ - src/IpcClient.h \ - src/IpcReader.h \ - src/Ipc.h \ - src/SynergyLocale.h \ - src/QUtility.h \ - src/PremiumAuth.h -RESOURCES += res/Synergy.qrc -RC_FILE = res/win/Synergy.rc -macx { - QMAKE_INFO_PLIST = res/mac/Info.plist - TARGET = Synergy - QSYNERGY_ICON.files = res/mac/Synergy.icns - QSYNERGY_ICON.path = Contents/Resources - QMAKE_BUNDLE_DATA += QSYNERGY_ICON - LIBS += -framework \ - ApplicationServices -} -debug { - OBJECTS_DIR = tmp/debug - MOC_DIR = tmp/debug - RCC_DIR = tmp/debug -} -release { - OBJECTS_DIR = tmp/release - MOC_DIR = tmp/release - RCC_DIR = tmp/release -} -win32 { - Debug:DESTDIR = ../../bin/Debug - Release:DESTDIR = ../../bin/Release -} -else:DESTDIR = ../../bin +QT += widgets network +TEMPLATE = app +TARGET = synergy +DEPENDPATH += . \ + res +INCLUDEPATH += . \ + src +FORMS += res/MainWindowBase.ui \ + res/AboutDialogBase.ui \ + res/ServerConfigDialogBase.ui \ + res/ScreenSettingsDialogBase.ui \ + res/ActionDialogBase.ui \ + res/HotkeyDialogBase.ui \ + res/SettingsDialogBase.ui \ + res/SetupWizardBase.ui +SOURCES += src/main.cpp \ + src/MainWindow.cpp \ + src/AboutDialog.cpp \ + src/ServerConfig.cpp \ + src/ServerConfigDialog.cpp \ + src/ScreenSetupView.cpp \ + src/Screen.cpp \ + src/ScreenSetupModel.cpp \ + src/NewScreenWidget.cpp \ + src/TrashScreenWidget.cpp \ + src/ScreenSettingsDialog.cpp \ + src/BaseConfig.cpp \ + src/HotkeyDialog.cpp \ + src/ActionDialog.cpp \ + src/Hotkey.cpp \ + src/Action.cpp \ + src/KeySequence.cpp \ + src/KeySequenceWidget.cpp \ + src/SettingsDialog.cpp \ + src/AppConfig.cpp \ + src/QSynergyApplication.cpp \ + src/VersionChecker.cpp \ + src/SetupWizard.cpp \ + src/IpcClient.cpp \ + src/IpcReader.cpp \ + src/Ipc.cpp \ + src/SynergyLocale.cpp \ + src/QUtility.cpp \ + src/PremiumAuth.cpp +HEADERS += src/MainWindow.h \ + src/AboutDialog.h \ + src/ServerConfig.h \ + src/ServerConfigDialog.h \ + src/ScreenSetupView.h \ + src/Screen.h \ + src/ScreenSetupModel.h \ + src/NewScreenWidget.h \ + src/TrashScreenWidget.h \ + src/ScreenSettingsDialog.h \ + src/BaseConfig.h \ + src/HotkeyDialog.h \ + src/ActionDialog.h \ + src/Hotkey.h \ + src/Action.h \ + src/KeySequence.h \ + src/KeySequenceWidget.h \ + src/SettingsDialog.h \ + src/AppConfig.h \ + src/QSynergyApplication.h \ + src/VersionChecker.h \ + src/SetupWizard.h \ + src/IpcClient.h \ + src/IpcReader.h \ + src/Ipc.h \ + src/SynergyLocale.h \ + src/QUtility.h \ + src/PremiumAuth.h +RESOURCES += res/Synergy.qrc +RC_FILE = res/win/Synergy.rc +macx { + HEADERS += src/AXDatabaseCleaner.h + OBJECTIVE_SOURCES += src/AXDatabaseCleaner.mm + QMAKE_INFO_PLIST = res/mac/Info.plist + TARGET = Synergy + QSYNERGY_ICON.files = res/mac/Synergy.icns + QSYNERGY_ICON.path = Contents/Resources + QMAKE_BUNDLE_DATA += QSYNERGY_ICON + LIBS += -framework ApplicationServices \ + -framework ServiceManagement \ + -framework Security \ + -framework cocoa +} +debug { + OBJECTS_DIR = tmp/debug + MOC_DIR = tmp/debug + RCC_DIR = tmp/debug +} +release { + OBJECTS_DIR = tmp/release + MOC_DIR = tmp/release + RCC_DIR = tmp/release +} +win32 { + Debug:DESTDIR = ../../bin/Debug + Release:DESTDIR = ../../bin/Release +} +else:DESTDIR = ../../bin diff --git a/src/gui/res/mac/Info.plist b/src/gui/res/mac/Info.plist index f2180455..5635d68c 100644 --- a/src/gui/res/mac/Info.plist +++ b/src/gui/res/mac/Info.plist @@ -12,5 +12,10 @@ Synergy CFBundleIdentifier synergy + SMPrivilegedExecutables + + synmacph + anchor apple generic and identifier "synmacph" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = SP58PFWX5L) + diff --git a/src/gui/src/AXDatabaseCleaner.h b/src/gui/src/AXDatabaseCleaner.h new file mode 100644 index 00000000..0f8b544b --- /dev/null +++ b/src/gui/src/AXDatabaseCleaner.h @@ -0,0 +1,30 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2014 Bolton Software Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +class AXDatabaseCleaner { +public: + AXDatabaseCleaner(); + ~AXDatabaseCleaner(); + + void loadPrivilegeHelper(); + +private: + class Private; + Private* d; +}; diff --git a/src/gui/src/AXDatabaseCleaner.mm b/src/gui/src/AXDatabaseCleaner.mm new file mode 100644 index 00000000..fc057fdf --- /dev/null +++ b/src/gui/src/AXDatabaseCleaner.mm @@ -0,0 +1,78 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2014 Bolton Software Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#import "AXDatabaseCleaner.h" +#import +#import +#import + +const NSString* const label = @"synmacph"; + +class AXDatabaseCleaner::Private { +public: + NSAutoreleasePool* autoReleasePool; + AuthorizationRef authRef; +}; + +AXDatabaseCleaner::AXDatabaseCleaner() +{ + d = new Private; + + d->autoReleasePool = [[NSAutoreleasePool alloc] init]; +} + +AXDatabaseCleaner::~AXDatabaseCleaner() +{ + [d->autoReleasePool release]; + delete d; +} + +void AXDatabaseCleaner::loadPrivilegeHelper() +{ + OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &d->authRef); + if (status != errAuthorizationSuccess) { + assert(NO); + d->authRef = NULL; + } + + AuthorizationItem authItem = {kSMRightBlessPrivilegedHelper, 0, NULL, 0}; + AuthorizationRights authRights = {1, &authItem}; + AuthorizationFlags flags = kAuthorizationFlagDefaults + | kAuthorizationFlagInteractionAllowed + | kAuthorizationFlagPreAuthorize + | kAuthorizationFlagExtendRights; + + BOOL result = NO; + NSError* error = nil; + + status = AuthorizationCopyRights(d->authRef, &authRights, kAuthorizationEmptyEnvironment, flags, NULL); + if (status != errAuthorizationSuccess) { + error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + } + else { + CFErrorRef cfError; + result = (BOOL)SMJobBless(kSMDomainSystemLaunchd, (CFStringRef)label, d->authRef, &cfError); + + if (!result) { + error = CFBridgingRelease(cfError); + } + } + + if (!result) { + assert(error != nil); + NSLog(@"bless error: domain= %@ / code= %d", [error domain], (int) [error code]); + } +} diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index ac891865..12bbc852 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -31,6 +31,7 @@ #if defined(Q_OS_MAC) #include +#include "AXDatabaseCleaner.h" #endif class QThreadImpl : public QThread @@ -136,11 +137,24 @@ bool checkMacAssistiveDevices() // show up there automatically, but will be unchecked. const void* keys[] = { kAXTrustedCheckOptionPrompt }; - const void* values[] = { kCFBooleanTrue }; + const void* falseValue[] = { kCFBooleanFalse }; + const void* trueValue[] = { kCFBooleanTrue }; - CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); - bool result = AXIsProcessTrustedWithOptions(options); - CFRelease(options); + CFDictionaryRef optionsWithoutPrompt = CFDictionaryCreate(NULL, keys, falseValue, 1, NULL, NULL); + CFDictionaryRef optionsWithPrompt = CFDictionaryCreate(NULL, keys, trueValue, 1, NULL, NULL); + bool result; + + result = AXIsProcessTrustedWithOptions(optionsWithoutPrompt); + if (!result) { + // call privilege help tool + AXDatabaseCleaner axdc; + axdc.loadPrivilegeHelper(); + + result = AXIsProcessTrustedWithOptions(optionsWithPrompt); + } + + CFRelease(optionsWithoutPrompt); + CFRelease(optionsWithPrompt); return result;