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;
+}
+
+}