Mercurial > minori
diff dep/animia/src/util/osx.cc @ 162:61b76c7b656a
dep/animia: add os x launchservices method
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Fri, 17 Nov 2023 16:49:57 -0500 |
parents | |
children | 44c5e6dd9488 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dep/animia/src/util/osx.cc Fri Nov 17 16:49:57 2023 -0500 @@ -0,0 +1,86 @@ +/* A wrapper around multiple LaunchServices things */ + +#include "animia/util/osx.h" + +#include <CoreFoundation/CoreFoundation.h> + +#include <iostream> + +namespace animia::internal::osx::util { + +#define RDSymbolNameStr(symbol) (CFSTR("_"#symbol)) + +static constexpr int kLaunchServicesMagicConstant = -2; // or -1, dunno the difference + +typedef CFTypeRef (*LSASNCreateWithPidSpec)(CFAllocatorRef, pid_t); +typedef CFDictionaryRef (*LSCopyApplicationInformationSpec)(int, CFTypeRef, CFArrayRef); + +static LSCopyApplicationInformationSpec LSCopyApplicationInformation = nullptr; +static LSASNCreateWithPidSpec LSASNCreateWithPid = nullptr; + +static CFStringRef (kLSDisplayNameKey) = nullptr; +static CFStringRef (kLSPIDKey) = nullptr; + +static CFStringRef (kLaunchServicesBundleID) = CFSTR("com.apple.LaunchServices"); + +static bool FindLaunchServicesPrivateSymbols() { + CFBundleRef launch_services_bundle = CFBundleGetBundleWithIdentifier(kLaunchServicesBundleID); + if (!launch_services_bundle) + return false; + + LSCopyApplicationInformation = (LSCopyApplicationInformationSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, RDSymbolNameStr(LSCopyApplicationInformation)); + if (!LSCopyApplicationInformation) + return false; + + LSASNCreateWithPid = (LSASNCreateWithPidSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, RDSymbolNameStr(LSASNCreateWithPid)); + if (!LSASNCreateWithPid) + return false; + + kLSDisplayNameKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, RDSymbolNameStr(kLSDisplayNameKey)); + if (!kLSDisplayNameKey) + return false; + + kLSPIDKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, RDSymbolNameStr(kLSPIDKey)); + if (!kLSPIDKey) + return false; + + return true; +} + +bool LaunchServicesGetProcessName(pid_t pid, std::string& result) { + if (!LSCopyApplicationInformation || !LSASNCreateWithPid) + if (!FindLaunchServicesPrivateSymbols()) + return false; + + CFTypeRef asn = LSASNCreateWithPid(kCFAllocatorDefault, pid); + + CFArrayRef request_array = CFArrayCreate(NULL, (const void **)kLSDisplayNameKey, 1, NULL); + + CFDictionaryRef dictionary = LSCopyApplicationInformation(kLaunchServicesMagicConstant, asn, request_array); + + CFRelease(request_array); + if (!dictionary) + return false; + + CFStringRef str; + if (!CFDictionaryGetValueIfPresent(dictionary, kLSDisplayNameKey, (CFTypeRef*)&str) || !str) { + CFRelease(dictionary); + return false; + } + CFRetain(str); + + CFRelease(dictionary); + + result.reserve(CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1); + + if (!CFStringGetCString(str, &result.front(), result.length(), result.length())) { + CFRelease(str); + return false; + } + + CFRelease(str); + + return true; +} + +}