diff --git a/src/external/cocotron b/src/external/cocotron index 33dbfb6cf..af0be962f 160000 --- a/src/external/cocotron +++ b/src/external/cocotron @@ -1 +1 @@ -Subproject commit 33dbfb6cf6467eee0d4a9c0f61c7c7abdabf14d4 +Subproject commit af0be962f534affff373cb4411f9d5952d4feaab diff --git a/src/external/corefoundation b/src/external/corefoundation index 5bb4863d3..0df921f1d 160000 --- a/src/external/corefoundation +++ b/src/external/corefoundation @@ -1 +1 @@ -Subproject commit 5bb4863d34a3038821eb593b5f53fe176f47955f +Subproject commit 0df921f1db7d60a4aa6d6fe144303ad047f884c5 diff --git a/src/frameworks/ApplicationServices/HIServices/CMakeLists.txt b/src/frameworks/ApplicationServices/HIServices/CMakeLists.txt index 10c1b6c94..563858ab6 100644 --- a/src/frameworks/ApplicationServices/HIServices/CMakeLists.txt +++ b/src/frameworks/ApplicationServices/HIServices/CMakeLists.txt @@ -3,6 +3,8 @@ project(HIServices) set(DYLIB_COMPAT_VERSION "1.0.0") set(DYLIB_CURRENT_VERSION "628.0.0") +include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/libcxx/include) + add_framework(HIServices FAT CURRENT_VERSION @@ -11,8 +13,12 @@ add_framework(HIServices SOURCES src/HIServices.c + src/Processes.cpp DEPENDENCIES - CoreFoundation + CoreFoundation system + cxx + LaunchServices + CoreGraphics ) diff --git a/src/frameworks/ApplicationServices/HIServices/include/HIServices/HIServices.h b/src/frameworks/ApplicationServices/HIServices/include/HIServices/HIServices.h index eb06e7e11..43ba36b5d 100644 --- a/src/frameworks/ApplicationServices/HIServices/include/HIServices/HIServices.h +++ b/src/frameworks/ApplicationServices/HIServices/include/HIServices/HIServices.h @@ -20,5 +20,18 @@ #ifndef _HIServices_H_ #define _HIServices_H_ +#include +#include "Processes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +OSStatus SetApplicationIsDaemon(Boolean daemon); +Boolean GetApplicationIsDaemon(void); + +#ifdef __cplusplus +} +#endif #endif diff --git a/src/frameworks/CoreServices/include/CoreServices/Processes.h b/src/frameworks/ApplicationServices/HIServices/include/HIServices/Processes.h similarity index 100% rename from src/frameworks/CoreServices/include/CoreServices/Processes.h rename to src/frameworks/ApplicationServices/HIServices/include/HIServices/Processes.h diff --git a/src/frameworks/ApplicationServices/HIServices/src/HIServices.c b/src/frameworks/ApplicationServices/HIServices/src/HIServices.c index ccad12afa..e8bf5db75 100644 --- a/src/frameworks/ApplicationServices/HIServices/src/HIServices.c +++ b/src/frameworks/ApplicationServices/HIServices/src/HIServices.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include const CFStringRef kAXUIElementCopyHierarchyArrayAttributesKey = CFSTR("AXCHAA"); const CFStringRef kAXUIElementCopyHierarchyMaxArrayCountKey = CFSTR("AXCHMAC"); @@ -33,12 +35,29 @@ const CFStringRef kAXUIElementCopyHierarchyTruncateStringsKey = CFSTR("AXTRUNC") CFStringRef kAXTrustedCheckOptionPrompt = CFSTR("AXTrustedCheckOptionPrompt"); static int verbose = 0; +static Boolean g_isDaemon = FALSE; __attribute__((constructor)) static void initme(void) { verbose = getenv("STUB_VERBOSE") != NULL; } +OSStatus SetApplicationIsDaemon(Boolean daemon) +{ + g_isDaemon = daemon; + if (daemon) + CGSSetDenyWindowServerConnections(TRUE); + + _LSSetApplicationLaunchServicesServerConnectionStatus(daemon ? 2 : 0, NULL); + + return noErr; +} + +Boolean GetApplicationIsDaemon(void) +{ + return g_isDaemon; +} + void* AXAPIEnabled(void) { if (verbose) puts("STUB: AXAPIEnabled called"); @@ -351,12 +370,6 @@ void* CopyLabelColorAndName(void) return NULL; } -void* CopyProcessName(void) -{ - if (verbose) puts("STUB: CopyProcessName called"); - return NULL; -} - void* CoreAppearanceGetFontCGStyleRef(void) { if (verbose) puts("STUB: CoreAppearanceGetFontCGStyleRef called"); @@ -1509,30 +1522,6 @@ void* DesktopPictureSetValue(void) return NULL; } -void* ExitToShell(void) -{ - if (verbose) puts("STUB: ExitToShell called"); - return NULL; -} - -void* GetApplicationIsDaemon(void) -{ - if (verbose) puts("STUB: GetApplicationIsDaemon called"); - return NULL; -} - -void* GetCurrentProcess(void) -{ - if (verbose) puts("STUB: GetCurrentProcess called"); - return NULL; -} - -void* GetFrontProcess(void) -{ - if (verbose) puts("STUB: GetFrontProcess called"); - return NULL; -} - void* GetGlobalIconImagesCacheMaxEntriesAndMaxDataSize(void) { if (verbose) puts("STUB: GetGlobalIconImagesCacheMaxEntriesAndMaxDataSize called"); @@ -1551,36 +1540,6 @@ void* GetIconRefVariant(void) return NULL; } -void* GetNextProcess(void) -{ - if (verbose) puts("STUB: GetNextProcess called"); - return NULL; -} - -void* GetProcessBundleLocation(void) -{ - if (verbose) puts("STUB: GetProcessBundleLocation called"); - return NULL; -} - -void* GetProcessForPID(void) -{ - if (verbose) puts("STUB: GetProcessForPID called"); - return NULL; -} - -void* GetProcessInformation(void) -{ - if (verbose) puts("STUB: GetProcessInformation called"); - return NULL; -} - -void* GetProcessPID(void) -{ - if (verbose) puts("STUB: GetProcessPID called"); - return NULL; -} - void* HIS_XPC_CFNotificationCenterPostNotification(void) { if (verbose) puts("STUB: HIS_XPC_CFNotificationCenterPostNotification called"); @@ -2121,24 +2080,6 @@ void* IsProcessManagerInitialized(void) return NULL; } -void* IsProcessVisible(void) -{ - if (verbose) puts("STUB: IsProcessVisible called"); - return NULL; -} - -void* KillProcess(void) -{ - if (verbose) puts("STUB: KillProcess called"); - return NULL; -} - -void* LaunchApplication(void) -{ - if (verbose) puts("STUB: LaunchApplication called"); - return NULL; -} - void* LaunchProcess(void) { if (verbose) puts("STUB: LaunchProcess called"); @@ -2289,12 +2230,6 @@ void* PlotIconRefInContext(void) return NULL; } -void* ProcessInformationCopyDictionary(void) -{ - if (verbose) puts("STUB: ProcessInformationCopyDictionary called"); - return NULL; -} - void* SXArbitrationAddQueuedOutputRequest(void) { if (verbose) puts("STUB: SXArbitrationAddQueuedOutputRequest called"); @@ -2331,36 +2266,12 @@ void* SXArbitrationRegisterOutputStopped(void) return NULL; } -void* SameProcess(void) -{ - if (verbose) puts("STUB: SameProcess called"); - return NULL; -} - void* SerializeCFType(void) { if (verbose) puts("STUB: SerializeCFType called"); return NULL; } -void* SetApplicationIsDaemon(void) -{ - if (verbose) puts("STUB: SetApplicationIsDaemon called"); - return NULL; -} - -void* SetFrontProcess(void) -{ - if (verbose) puts("STUB: SetFrontProcess called"); - return NULL; -} - -void* SetFrontProcessWithOptions(void) -{ - if (verbose) puts("STUB: SetFrontProcessWithOptions called"); - return NULL; -} - void* SetGlobalIconImagesCacheMaxEntriesAndMaxDataSize(void) { if (verbose) puts("STUB: SetGlobalIconImagesCacheMaxEntriesAndMaxDataSize called"); @@ -2385,24 +2296,12 @@ void* ShowHideDrag(void) return NULL; } -void* ShowHideProcess(void) -{ - if (verbose) puts("STUB: ShowHideProcess called"); - return NULL; -} - void* StartIPCPing(void) { if (verbose) puts("STUB: StartIPCPing called"); return NULL; } -void* TransformProcessType(void) -{ - if (verbose) puts("STUB: TransformProcessType called"); - return NULL; -} - void* TranslationCopyDestinationType(void) { if (verbose) puts("STUB: TranslationCopyDestinationType called"); @@ -2475,12 +2374,6 @@ void* UnserializeCFType(void) return NULL; } -void* WakeUpProcess(void) -{ - if (verbose) puts("STUB: WakeUpProcess called"); - return NULL; -} - void* _AXCopyActionDescription(void) { if (verbose) puts("STUB: _AXCopyActionDescription called"); diff --git a/src/frameworks/CoreServices/src/CarbonCore/Processes.cpp b/src/frameworks/ApplicationServices/HIServices/src/Processes.cpp similarity index 96% rename from src/frameworks/CoreServices/src/CarbonCore/Processes.cpp rename to src/frameworks/ApplicationServices/HIServices/src/Processes.cpp index 1a26080be..235720bea 100644 --- a/src/frameworks/CoreServices/src/CarbonCore/Processes.cpp +++ b/src/frameworks/ApplicationServices/HIServices/src/Processes.cpp @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with Darling. If not, see . */ -#include +#include #include #include #include @@ -30,13 +30,14 @@ along with Darling. If not, see . #include #include #include -#include "UserBreak.h" #define STUB() // TODO #ifndef PATH_MAX # define PATH_MAX 4096 #endif +// TODO: 99% of these should be rewritten to call LaunchServices instead + // CFStringRef kCFBundleExecutableKey = CFSTR("kCFBundleExecutableKey"); // CFStringRef kCFBundleNameKey = CFSTR("kCFBundleNameKey"); // CFStringRef kCFBundleIdentifierKey = CFSTR("kCFBundleIdentifierKey"); @@ -243,9 +244,3 @@ OSErr WakeUpProcess(const ProcessSerialNumber* psn) return noErr; } -void DebugStr(ConstStr255Param msg) -{ - std::cerr.write((const char*) &msg[1], msg[0]); - std::cerr << std::endl; - doUserBreak(); -} diff --git a/src/frameworks/CoreServices/CMakeLists.txt b/src/frameworks/CoreServices/CMakeLists.txt index c4fcb0017..bd5d2ba0a 100644 --- a/src/frameworks/CoreServices/CMakeLists.txt +++ b/src/frameworks/CoreServices/CMakeLists.txt @@ -26,7 +26,6 @@ add_framework(CoreServices VERSION "A" SOURCES constants.m - CoreServicesPriv.cpp DEPENDENCIES FSEvents LaunchServices diff --git a/src/frameworks/CoreServices/CoreServicesPriv.h b/src/frameworks/CoreServices/CoreServicesPriv.h deleted file mode 120000 index 780330e7d..000000000 --- a/src/frameworks/CoreServices/CoreServicesPriv.h +++ /dev/null @@ -1 +0,0 @@ -include/CoreServices/CoreServicesPriv.h \ No newline at end of file diff --git a/src/frameworks/CoreServices/include/CoreServices/CoreServices.h b/src/frameworks/CoreServices/include/CoreServices/CoreServices.h index 5646319a2..16b22df09 100644 --- a/src/frameworks/CoreServices/include/CoreServices/CoreServices.h +++ b/src/frameworks/CoreServices/include/CoreServices/CoreServices.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/src/frameworks/CoreServices/include/LaunchServices/LaunchServices.h b/src/frameworks/CoreServices/include/LaunchServices/LaunchServices.h index 7d69718f8..aa73fbb77 100644 --- a/src/frameworks/CoreServices/include/LaunchServices/LaunchServices.h +++ b/src/frameworks/CoreServices/include/LaunchServices/LaunchServices.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include @@ -85,10 +85,6 @@ OSStatus LSGetExtensionInfo(UniCharCount inNameLen, const UniChar* inNameBuffer, OSStatus LSSetExtensionHiddenForRef(const FSRef *inRef, Boolean hide); OSStatus LSSetExtensionHiddenForURL(CFURLRef inURL, Boolean hide); -extern CFStringRef _kLSBundlePathKey; -extern CFStringRef _kLSDisplayNameKey; -extern CFStringRef _kLSExecutablePathKey; - CFTypeRef _LSCopyApplicationInformationItem(int /* hopefully */, CFTypeRef asn, CFStringRef what); CFDictionaryRef _LSCopyApplicationInformation(int, CFTypeRef asn, int); diff --git a/src/frameworks/CoreServices/include/LaunchServices/LaunchServicesPriv.h b/src/frameworks/CoreServices/include/LaunchServices/LaunchServicesPriv.h new file mode 100644 index 000000000..e4145022c --- /dev/null +++ b/src/frameworks/CoreServices/include/LaunchServices/LaunchServicesPriv.h @@ -0,0 +1,79 @@ +#ifndef LAUNCH_SERVICES_PRIV_H_ +#define LAUNCH_SERVICES_PRIV_H_ +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum +{ + _kLSDefaultSessionID = -2, +}; + +enum +{ + /***** MASTER SERVICE COMMANDS *****/ + // IN: + // clientversion, session + // OUT: + // serverversion, endpoint + _kLSXPCHello = 0x64, + + /***** ENDPOINT COMMANDS *****/ + // OUT: + // bool success + // dictionary result + _kLSXPCWeirdCheckIn = 0x1F9, + // IN: + // dictionary info + // mach_port_name_t deathport + // OUT: + // bool success + // dictionary result (appInfo) + _kLSXPCCheckIn = 0x1F4, +}; + +extern const CFStringRef _kLSArchitecturePowerPCValue; +extern const CFStringRef _kLSArchitecturePowerPC64Value; +extern const CFStringRef _kLSArchitecturei386Value; +extern const CFStringRef _kLSArchitecturex86_64Value; +extern const CFStringRef _kLSArchitectureUnknownValue; + +extern const CFStringRef _kLSArchitectureKey; + +extern const CFStringRef _kLSPIDKey; +extern const CFStringRef _kLSExecutablePathKey; +extern const CFStringRef _kLSCheckInTimeKey; +extern const CFStringRef _kLSDisplayNameKey; +extern const CFStringRef _kLSArchitectureKey; +extern const CFStringRef _kLSBundlePathKey; +extern const CFStringRef _kLSApplicationTypeKey; + +extern const CFStringRef _kLSASNKey; + +extern const CFStringRef _kLSApplicationForegroundTypeKey; +extern const CFStringRef _kLSApplicationBackgroundOnlyTypeKey; + +extern const CFStringRef _kLSExecutableFormatKey; +extern const CFStringRef _kLSExecutableFormatMachOKey; +extern const CFStringRef _kLSExecutableFormatCFMKey; + +// Example call: +// _LSApplicationCheckIn(_kLSDefaultSessionID, CFBundleGetInfoDictionary(CFBundleGetMainBundle())) +// Normally to be called from -[NSApplication init] +CFDictionaryRef _LSApplicationCheckIn(int sessionID, CFDictionaryRef applicationInfo); + +CFTypeRef _LSGetCurrentApplicationASN(void); +OSStatus _LSSetApplicationInformationItem(int sessionID, LSASNRef asn, CFStringRef key, CFStringRef value, CFDictionaryRef *info); + +typedef bool (^LSServerConnectionAllowedBlock) ( CFDictionaryRef optionsRef ); +void _LSSetApplicationLaunchServicesServerConnectionStatus(uint64_t flags, LSServerConnectionAllowedBlock block); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/frameworks/CoreServices/src/CarbonCore/CMakeLists.txt b/src/frameworks/CoreServices/src/CarbonCore/CMakeLists.txt index 3c812bb37..3e30957b5 100644 --- a/src/frameworks/CoreServices/src/CarbonCore/CMakeLists.txt +++ b/src/frameworks/CoreServices/src/CarbonCore/CMakeLists.txt @@ -14,7 +14,6 @@ set(CarbonCore_SRCS DriverSynchronization.cpp DriverServices.cpp Components.cpp - Processes.cpp OpenTransport.cpp Timer.cpp TextCommon.cpp @@ -26,6 +25,7 @@ set(CarbonCore_SRCS MacErrors.cpp UserBreak.cpp Debugging.cpp + CoreServicesPriv.cpp ) set(DYLIB_COMPAT_VERSION "1.0.0") diff --git a/src/frameworks/CoreServices/CoreServicesPriv.cpp b/src/frameworks/CoreServices/src/CarbonCore/CoreServicesPriv.cpp similarity index 65% rename from src/frameworks/CoreServices/CoreServicesPriv.cpp rename to src/frameworks/CoreServices/src/CarbonCore/CoreServicesPriv.cpp index 8a323a295..5883ade5a 100644 --- a/src/frameworks/CoreServices/CoreServicesPriv.cpp +++ b/src/frameworks/CoreServices/src/CarbonCore/CoreServicesPriv.cpp @@ -1,10 +1,11 @@ -#include "CoreServicesPriv.h" +#include // TODO: Security.framework expects this symbol to be available in // /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/CarbonCore Boolean _CSCheckFix(CFStringRef str) { + // Checks whether given issue number is fixed in this release or something return 0; } diff --git a/src/frameworks/CoreServices/src/CarbonCore/Debugging.cpp b/src/frameworks/CoreServices/src/CarbonCore/Debugging.cpp index 5020d8198..4c7df934d 100644 --- a/src/frameworks/CoreServices/src/CarbonCore/Debugging.cpp +++ b/src/frameworks/CoreServices/src/CarbonCore/Debugging.cpp @@ -61,3 +61,9 @@ UInt32 TaskLevel(void) return 0; } +void DebugStr(ConstStr255Param msg) +{ + std::cerr.write((const char*) &msg[1], msg[0]); + std::cerr << std::endl; + doUserBreak(); +} diff --git a/src/frameworks/CoreServices/src/LaunchServices/CMakeLists.txt b/src/frameworks/CoreServices/src/LaunchServices/CMakeLists.txt index 21285e960..3639eb31e 100644 --- a/src/frameworks/CoreServices/src/LaunchServices/CMakeLists.txt +++ b/src/frameworks/CoreServices/src/LaunchServices/CMakeLists.txt @@ -9,6 +9,8 @@ add_framework(LaunchServices LaunchServices.cpp LSApplicationProxy.m LSApplicationWorkspace.m + LaunchServicesNew.cpp + constants.c DEPENDENCIES CoreFoundation Foundation @@ -17,3 +19,5 @@ add_framework(LaunchServices system CarbonCore ) + +add_subdirectory(launchservicesd) diff --git a/src/frameworks/CoreServices/src/LaunchServices/LaunchServices.cpp b/src/frameworks/CoreServices/src/LaunchServices/LaunchServices.cpp index 7bc9a4f5f..1016c289d 100644 --- a/src/frameworks/CoreServices/src/LaunchServices/LaunchServices.cpp +++ b/src/frameworks/CoreServices/src/LaunchServices/LaunchServices.cpp @@ -261,10 +261,6 @@ OSStatus LSGetExtensionInfo(UniCharCount inNameLen, const UniChar* inNameBuffer, // TODO: See https://gist.github.com/zorgiepoo/d751cba19a0167a589a2 -CFStringRef _kLSBundlePathKey = CFSTR("LSBundlePath"); -CFStringRef _kLSDisplayNameKey = CFSTR("LSDisplayName"); -CFStringRef _kLSExecutablePathKey = CFSTR("LSExecutablePath"); - CFTypeRef _LSCopyApplicationInformationItem(int /* hopefully */, CFTypeRef asn, CFStringRef what) { return NULL; @@ -275,11 +271,6 @@ CFDictionaryRef _LSCopyApplicationInformation(int, CFTypeRef asn, int) return NULL; } -LSASNRef _LSASNCreateWithPid(CFAllocatorRef allocator, pid_t pid) -{ - return NULL; -} - /* OSStatus _LSOpenURLsWithRole(CFArrayRef inURLs, LSRolesMask inRole, void *unknown) { diff --git a/src/frameworks/CoreServices/src/LaunchServices/LaunchServicesNew.cpp b/src/frameworks/CoreServices/src/LaunchServices/LaunchServicesNew.cpp new file mode 100644 index 000000000..3b7c59b42 --- /dev/null +++ b/src/frameworks/CoreServices/src/LaunchServices/LaunchServicesNew.cpp @@ -0,0 +1,244 @@ +/* +This file is part of Darling. + +Copyright (C) 2020 Lubos Dolezel + +Darling is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Darling 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 Darling. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static xpc_connection_t g_lsdConnection, g_endpointConnection; + +static xpc_connection_t getLSDConnection(); +static xpc_object_t createCommandDictionary(uint64_t command); +static mach_port_name_t deathPort(); +static CFTypeRef g_ourASN; + +static CFStringRef g_applicationType = _kLSApplicationForegroundTypeKey; +static LSServerConnectionAllowedBlock g_connectionAllowedBlock = nullptr; + +CFDictionaryRef _LSApplicationCheckIn(int sessionID, CFDictionaryRef applicationInfo) +{ + if (g_connectionAllowedBlock && !g_connectionAllowedBlock(applicationInfo)) + return nullptr; + + CFMutableDictionaryRef modAppInfo = CFDictionaryCreateMutableCopy(nullptr, 0, applicationInfo); + + if (!CFDictionaryContainsValue(modAppInfo, _kLSArchitectureKey)) + { +#if defined(__x86_64__) + CFDictionaryAddValue(modAppInfo, _kLSArchitectureKey, _kLSArchitecturex86_64Value); +#elif defined(__i386__) + CFDictionaryAddValue(modAppInfo, _kLSArchitectureKey, _kLSArchitecturei386Value); +#elif defined(__ppc__) + CFDictionaryAddValue(modAppInfo, _kLSArchitectureKey, _kLSArchitecturePowerPCValue); +#elif defined(__ppc64__) + CFDictionaryAddValue(modAppInfo, _kLSArchitectureKey, _kLSArchitecturePowerPC64Value); +#else + CFDictionaryAddValue(modAppInfo, _kLSArchitectureKey, _kLSArchitectureUnknownValue); +#endif + } + + if (!CFDictionaryContainsValue(modAppInfo, _kLSExecutablePathKey)) + { + CFStringRef path = CFStringCreateWithFileSystemRepresentation(nullptr, _CFProcessPath()); + CFDictionaryAddValue(modAppInfo, _kLSExecutablePathKey, path); + CFRelease(path); + } + + if (!CFDictionaryContainsValue(modAppInfo, _kLSPIDKey)) + { + // Are we supposed to set this one if not present? + long pid = getpid(); + CFNumberRef num = CFNumberCreate(nullptr, kCFNumberLongType, &pid); + CFDictionaryAddValue(modAppInfo, _kLSPIDKey, num); + CFRelease(num); + } + + if (!CFDictionaryContainsValue(modAppInfo, _kLSDisplayNameKey) && + !CFDictionaryContainsValue(modAppInfo, _kCFBundleDisplayNameKey) && + !CFDictionaryContainsValue(modAppInfo, kCFBundleNameKey)) + { + // TODO: Generate app name from bundle path / process path etc. + } + + if (!CFDictionaryContainsValue(modAppInfo, _kLSCheckInTimeKey)) + { + CFDateRef now = CFDateCreate(nullptr, CFAbsoluteTimeGetCurrent()); + CFDictionaryAddValue(modAppInfo, _kLSCheckInTimeKey, now); + CFRelease(now); + } + + if (!CFDictionaryContainsValue(modAppInfo, _kLSApplicationTypeKey)) + { + CFDictionaryAddValue(modAppInfo, _kLSApplicationTypeKey, g_applicationType); + } + + xpc_object_t dict = createCommandDictionary(_kLSXPCCheckIn); + + xpc_object_t info = _CFXPCCreateXPCObjectFromCFObject(modAppInfo); + CFRelease(modAppInfo); + + xpc_dictionary_set_value(dict, "info", info); + xpc_release(info); + + xpc_dictionary_set_mach_send(dict, "deathport", deathPort()); + xpc_object_t reply = xpc_connection_send_message_with_reply_sync(getLSDConnection(), dict); + xpc_release(dict); + + if (reply && reply != XPC_ERROR_CONNECTION_INTERRUPTED && reply != XPC_ERROR_CONNECTION_INVALID) + { + if (!xpc_dictionary_get_bool(reply, "success")) + { + std::cerr << "LaunchServices: check-in failed\n"; + return nullptr; + } + + CFDictionaryRef result = (CFDictionaryRef) _CFXPCCreateCFObjectFromXPCObject(xpc_dictionary_get_value(reply, "result")); + g_ourASN = CFDictionaryGetValue(result, _kLSASNKey); + CFRetain(g_ourASN); + + // Is this really what should be returned? + return result; + } + else + { + std::cerr << "LaunchServices: check-in operation didn't execute\n"; + } + + return nullptr; +} + +CFTypeRef _LSGetCurrentApplicationASN(void) +{ + return g_ourASN; +} + +OSStatus _LSSetApplicationInformationItem(int sessionID, LSASNRef asn, CFStringRef key, CFStringRef value, CFDictionaryRef *info) +{ + // TODO: This talks to lsd to change the property of *any* app + return unimpErr; +} + +void _LSSetApplicationLaunchServicesServerConnectionStatus(uint64_t flags, LSServerConnectionAllowedBlock block) +{ + // TODO + if (flags & 2) // Called from ApplicationServices/HIServices - this disables connecting to lsd??? + g_applicationType = _kLSApplicationBackgroundOnlyTypeKey; + + if (g_connectionAllowedBlock) + Block_release(g_connectionAllowedBlock); + + g_connectionAllowedBlock = nullptr; + if (block) + g_connectionAllowedBlock = Block_copy(block); +} + +LSASNRef _LSASNCreateWithPid(CFAllocatorRef allocator, pid_t pid) +{ + long lpid = pid; + return CFNumberCreate(nullptr, kCFNumberLongType, &lpid); +} + +static mach_port_name_t deathPort() +{ + static dispatch_once_t onceDeathPort; + static mach_port_name_t port; + dispatch_once(&onceDeathPort, ^{ + kern_return_t kr; + kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); + + if (kr == KERN_SUCCESS) + mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND); + }); + + return port; +} + +static xpc_connection_t getLSDConnection() +{ + static dispatch_once_t once; + dispatch_once(&once, ^{ + if (const char* env = getenv("SCDontUseServer"); env != nullptr && atoi(env) != 0) + return; + + const char* serviceName = "com.apple.coreservices.launchservicesd"; + if (const char* altName = getenv("__LSXPCSERVICENAME"); altName != nullptr) + serviceName = altName; + + xpc_connection_t master = xpc_connection_create_mach_service(serviceName, + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 0); + + xpc_connection_set_event_handler(master, ^(xpc_object_t peer) { + if (peer == 0) + { + // TODO: + std::cerr << "LaunchServices: Cannot connect to lsd\n"; + return; + } + g_lsdConnection = (xpc_connection_t) xpc_retain(peer); + + xpc_object_t dict = createCommandDictionary(_kLSXPCHello); + xpc_object_t reply = xpc_connection_send_message_with_reply_sync(g_lsdConnection, dict); + xpc_release(dict); + + if (reply == XPC_ERROR_CONNECTION_INTERRUPTED || reply == XPC_ERROR_CONNECTION_INVALID) + { + std::cerr << "LaunchServices: lsd connection broken\n"; + return; + } + if (!xpc_dictionary_get_bool(reply, "success")) + { + std::cerr << "LaunchServices: lsd hello failed\n"; + return; + } + xpc_object_t result = xpc_dictionary_get_value(reply, "result"); + xpc_object_t ep = xpc_dictionary_get_value(result, "endpoint"); + + if (xpc_get_type(ep) == XPC_TYPE_ENDPOINT) + { + xpc_connection_t conn = g_endpointConnection = xpc_connection_create_from_endpoint((xpc_endpoint_t) ep); + xpc_connection_set_target_queue(conn, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + xpc_connection_set_event_handler(conn, ^(xpc_object_t conn) { + // TODO? + }); + xpc_connection_resume(conn); + } + + xpc_release(reply); + }); + xpc_connection_resume(master); + }); + + return g_endpointConnection; +} + +static xpc_object_t createCommandDictionary(uint64_t command) +{ + xpc_object_t dict = xpc_dictionary_create(nullptr, nullptr, 0); + xpc_dictionary_set_int64(dict, "command", command); + return dict; +} diff --git a/src/frameworks/CoreServices/src/LaunchServices/constants.c b/src/frameworks/CoreServices/src/LaunchServices/constants.c new file mode 100644 index 000000000..5f3deace9 --- /dev/null +++ b/src/frameworks/CoreServices/src/LaunchServices/constants.c @@ -0,0 +1,25 @@ +#include +#include + +const CFStringRef _kLSArchitecturePowerPCValue = CFSTR("ppc"); +const CFStringRef _kLSArchitecturePowerPC64Value = CFSTR("ppc64"); +const CFStringRef _kLSArchitecturei386Value = CFSTR("i386"); +const CFStringRef _kLSArchitecturex86_64Value = CFSTR("x86_64"); +const CFStringRef _kLSArchitectureUnknownValue = CFSTR("unknown"); + +const CFStringRef _kLSPIDKey = CFSTR("LSPID"); +const CFStringRef _kLSExecutablePathKey = CFSTR("LSExecutablePath"); +const CFStringRef _kLSCheckInTimeKey = CFSTR("LSCheckInTime"); +const CFStringRef _kLSDisplayNameKey = CFSTR("LSDisplayName"); +const CFStringRef _kLSArchitectureKey = CFSTR("LSArchitecture"); +const CFStringRef _kLSBundlePathKey = CFSTR("LSBundlePath"); + +const CFStringRef _kLSApplicationTypeKey = CFSTR("ApplicationType"); +const CFStringRef _kLSApplicationForegroundTypeKey = CFSTR("Foreground"); +const CFStringRef _kLSApplicationBackgroundOnlyTypeKey = CFSTR("BackgroundOnly"); + +const CFStringRef _kLSExecutableFormatKey = CFSTR("LSExecutableFormat"); +const CFStringRef _kLSExecutableFormatMachOKey = CFSTR("LSExecutableMachOFormat"); +const CFStringRef _kLSExecutableFormatCFMKey = CFSTR("LSExecutableCFMFormat"); + +const CFStringRef _kLSASNKey = CFSTR("LSASN"); diff --git a/src/frameworks/CoreServices/src/LaunchServices/launchservicesd/CMakeLists.txt b/src/frameworks/CoreServices/src/LaunchServices/launchservicesd/CMakeLists.txt new file mode 100644 index 000000000..9b8a21da1 --- /dev/null +++ b/src/frameworks/CoreServices/src/LaunchServices/launchservicesd/CMakeLists.txt @@ -0,0 +1,10 @@ +project(lslaunchservicesdd) + +set(sources + launchservicesd.cpp +) + +add_darling_executable(launchservicesd ${sources}) + +target_link_libraries(launchservicesd system CoreServices sqlite3 cxx) +install(TARGETS launchservicesd DESTINATION libexec/darling/System/Library/CoreServices) diff --git a/src/frameworks/CoreServices/src/LaunchServices/launchservicesd/com.apple.coreservices.launchservicesd.plist b/src/frameworks/CoreServices/src/LaunchServices/launchservicesd/com.apple.coreservices.launchservicesd.plist new file mode 100644 index 000000000..c88a7fcae --- /dev/null +++ b/src/frameworks/CoreServices/src/LaunchServices/launchservicesd/com.apple.coreservices.launchservicesd.plist @@ -0,0 +1,21 @@ + + + + + Label + com.apple.coreservices.launchservicesd + MachServices + + com.apple.coreservices.launchservicesd + + + POSIXSpawnType + Adaptive + ProgramArguments + + /System/Library/CoreServices/launchservicesd + + RunAtLoad + + + diff --git a/src/frameworks/CoreServices/src/LaunchServices/launchservicesd/launchservicesd.cpp b/src/frameworks/CoreServices/src/LaunchServices/launchservicesd/launchservicesd.cpp new file mode 100644 index 000000000..ee1389a2c --- /dev/null +++ b/src/frameworks/CoreServices/src/LaunchServices/launchservicesd/launchservicesd.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +#define DATABASE_VERSION 1 + +static void connectionCallback(xpc_connection_t connection); +static void handleMessage(xpc_connection_t connection, xpc_object_t msg); + +sqlite3* g_database; + +static const char* MONITORED_DIRECTORIES[] = { + "/Applications", + "/System/Applications" + "/System/Library/Frameworks" +}; + +int main(int argc, const char** argv) +{ + if (int err = sqlite3_open("/var/cache/launchservices.db", &g_database); err != SQLITE_OK) + { + std::cerr << "SQLite error: " << sqlite3_errstr(err) << std::endl; + exit(1); + } + + // xpc_main(connectionCallback); + // Our xpc_main() isn't done yet, so we do this manually + + dispatch_queue_t server_queue = dispatch_queue_create("xpc service", NULL); + + xpc_connection_t listener = xpc_connection_create_mach_service("com.apple.coreservices.launchservicesd", + server_queue, XPC_CONNECTION_MACH_SERVICE_LISTENER); + + xpc_connection_set_event_handler(listener, ^(xpc_object_t peer) { + if (xpc_get_type(peer) == XPC_TYPE_CONNECTION) + connectionCallback(xpc_connection_t(peer)); + }); + xpc_connection_resume(listener); + + dispatch_main(); + return 0; +} + +static void connectionCallback(xpc_connection_t connection) +{ + pid_t pid = xpc_connection_get_pid(connection); + xpc_connection_set_event_handler(connection, ^(xpc_object_t msg) { + handleMessage(connection, msg); + }); + xpc_connection_resume(connection); +} + +static void handleMessage(xpc_connection_t connection, xpc_object_t msg) +{ + xpc_type_t type = xpc_get_type(msg); + + if (type == XPC_TYPE_DICTIONARY) + { + xpc_object_t reply = xpc_dictionary_create_reply(msg); + + xpc_connection_send_message(connection, reply); + } +}