Skip to content

Instantly share code, notes, and snippets.

@jessepeterson
Last active October 23, 2023 07:32
Show Gist options
  • Save jessepeterson/a46562565affbe87789e to your computer and use it in GitHub Desktop.
Save jessepeterson/a46562565affbe87789e to your computer and use it in GitHub Desktop.
_CFPreferencesCopyApplicationMap example
/* re-implementation of the behaviour that the /usr/bin/defaults application
* uses to read sandboxed preference data */
#include <CoreFoundation/CoreFoundation.h>
#define EX_BUNDLE_ID "com.apple.mail"
#define EX_KEY "JunkMailBehavior"
// undocumented, internal CFPreferences API call
extern CFDictionaryRef _CFPreferencesCopyApplicationMap(CFStringRef userName, CFStringRef hostName);
int main()
{
CFPropertyListRef app_map;
CFArrayRef bundle_urls;
CFURLRef current_url;
CFStringRef path;
CFMutableStringRef plist_path;
CFPropertyListRef value;
app_map = _CFPreferencesCopyApplicationMap(kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
if (app_map == NULL)
{
printf("problem getting ApplicationMap\n");
return -1;
}
if (true != CFDictionaryGetValueIfPresent(app_map, CFSTR(EX_BUNDLE_ID), (const void**)&bundle_urls))
{
printf("no matching bundle ID found in ApplicationMap: %s\n", EX_BUNDLE_ID);
return -2;
}
if (CFArrayGetCount(bundle_urls) < 1)
{
printf("no URLs returned by ApplicationMap for given bundle ID\n");
return -3;
}
/* the dictionary returned by _CFPreferencesCopyApplicationMap is keyed
* by bundle id and contains an array CFURLs. it's listed by (all)
* sandbox locations first, then typical ~/Library/Preferences. for this
* example only take the first (possibly sandboxed) location */
current_url = CFArrayGetValueAtIndex(bundle_urls, 0);
path = CFURLCopyPath(current_url);
// create and assemble our plist path
plist_path = CFStringCreateMutable(kCFAllocatorDefault, 0);
CFStringAppend(plist_path, path);
CFStringAppend(plist_path, CFSTR(EX_BUNDLE_ID));
value = CFPreferencesCopyValue(CFSTR(EX_KEY), plist_path, kCFPreferencesCurrentUser, kCFPreferencesAnyUser);
printf("result of CFPreferencesCopyValue on %s of %s via ApplicationMap at path:\n", EX_KEY, EX_BUNDLE_ID);
CFShow(plist_path);
CFShow(value);
CFRelease(value);
CFRelease(plist_path);
CFRelease(path);
CFRelease(app_map);
return 0;
}
@jessepeterson
Copy link
Author

See also this tweet. It talks about _CFPreferences*WithContainer().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment