Mercurial > minori
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 161:71752dcbb49f | 162:61b76c7b656a |
|---|---|
| 1 /* A wrapper around multiple LaunchServices things */ | |
| 2 | |
| 3 #include "animia/util/osx.h" | |
| 4 | |
| 5 #include <CoreFoundation/CoreFoundation.h> | |
| 6 | |
| 7 #include <iostream> | |
| 8 | |
| 9 namespace animia::internal::osx::util { | |
| 10 | |
| 11 #define RDSymbolNameStr(symbol) (CFSTR("_"#symbol)) | |
| 12 | |
| 13 static constexpr int kLaunchServicesMagicConstant = -2; // or -1, dunno the difference | |
| 14 | |
| 15 typedef CFTypeRef (*LSASNCreateWithPidSpec)(CFAllocatorRef, pid_t); | |
| 16 typedef CFDictionaryRef (*LSCopyApplicationInformationSpec)(int, CFTypeRef, CFArrayRef); | |
| 17 | |
| 18 static LSCopyApplicationInformationSpec LSCopyApplicationInformation = nullptr; | |
| 19 static LSASNCreateWithPidSpec LSASNCreateWithPid = nullptr; | |
| 20 | |
| 21 static CFStringRef (kLSDisplayNameKey) = nullptr; | |
| 22 static CFStringRef (kLSPIDKey) = nullptr; | |
| 23 | |
| 24 static CFStringRef (kLaunchServicesBundleID) = CFSTR("com.apple.LaunchServices"); | |
| 25 | |
| 26 static bool FindLaunchServicesPrivateSymbols() { | |
| 27 CFBundleRef launch_services_bundle = CFBundleGetBundleWithIdentifier(kLaunchServicesBundleID); | |
| 28 if (!launch_services_bundle) | |
| 29 return false; | |
| 30 | |
| 31 LSCopyApplicationInformation = (LSCopyApplicationInformationSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, RDSymbolNameStr(LSCopyApplicationInformation)); | |
| 32 if (!LSCopyApplicationInformation) | |
| 33 return false; | |
| 34 | |
| 35 LSASNCreateWithPid = (LSASNCreateWithPidSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, RDSymbolNameStr(LSASNCreateWithPid)); | |
| 36 if (!LSASNCreateWithPid) | |
| 37 return false; | |
| 38 | |
| 39 kLSDisplayNameKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, RDSymbolNameStr(kLSDisplayNameKey)); | |
| 40 if (!kLSDisplayNameKey) | |
| 41 return false; | |
| 42 | |
| 43 kLSPIDKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, RDSymbolNameStr(kLSPIDKey)); | |
| 44 if (!kLSPIDKey) | |
| 45 return false; | |
| 46 | |
| 47 return true; | |
| 48 } | |
| 49 | |
| 50 bool LaunchServicesGetProcessName(pid_t pid, std::string& result) { | |
| 51 if (!LSCopyApplicationInformation || !LSASNCreateWithPid) | |
| 52 if (!FindLaunchServicesPrivateSymbols()) | |
| 53 return false; | |
| 54 | |
| 55 CFTypeRef asn = LSASNCreateWithPid(kCFAllocatorDefault, pid); | |
| 56 | |
| 57 CFArrayRef request_array = CFArrayCreate(NULL, (const void **)kLSDisplayNameKey, 1, NULL); | |
| 58 | |
| 59 CFDictionaryRef dictionary = LSCopyApplicationInformation(kLaunchServicesMagicConstant, asn, request_array); | |
| 60 | |
| 61 CFRelease(request_array); | |
| 62 if (!dictionary) | |
| 63 return false; | |
| 64 | |
| 65 CFStringRef str; | |
| 66 if (!CFDictionaryGetValueIfPresent(dictionary, kLSDisplayNameKey, (CFTypeRef*)&str) || !str) { | |
| 67 CFRelease(dictionary); | |
| 68 return false; | |
| 69 } | |
| 70 CFRetain(str); | |
| 71 | |
| 72 CFRelease(dictionary); | |
| 73 | |
| 74 result.reserve(CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1); | |
| 75 | |
| 76 if (!CFStringGetCString(str, &result.front(), result.length(), result.length())) { | |
| 77 CFRelease(str); | |
| 78 return false; | |
| 79 } | |
| 80 | |
| 81 CFRelease(str); | |
| 82 | |
| 83 return true; | |
| 84 } | |
| 85 | |
| 86 } |
