static CFURLRef _preferencesDirectoryForUserHostSafetyLevel(CFStringRef userName, CFStringRef hostName, unsigned long safeLevel) { CFAllocatorRef alloc = __CFPreferencesAllocator(); #if DEPLOYMENT_TARGET_WINDOWS CFURLRef url = NULL; CFMutableStringRef completePath = _CFCreateApplicationRepositoryPath(alloc, CSIDL_APPDATA); if (completePath) { // append "Preferences\" and make the CFURL CFStringAppend(completePath, CFSTR("Preferences\\")); url = CFURLCreateWithFileSystemPath(alloc, completePath, kCFURLWindowsPathStyle, true); CFRelease(completePath); } // Can't find a better place? Home directory then? if (url == NULL) url = CFCopyHomeDirectoryURLForUser((userName == kCFPreferencesCurrentUser) ? NULL : userName); return url; #else CFURLRef home = NULL; CFURLRef url; int levels = 0; // if (hostName != kCFPreferencesCurrentHost && hostName != kCFPreferencesAnyHost) return NULL; // Arbitrary host access not permitted if (userName == kCFPreferencesAnyUser) { if (!home) home = CFURLCreateWithFileSystemPath(alloc, CFSTR("/Library/Preferences/"), kCFURLPOSIXPathStyle, true); levels = 1; if (hostName == kCFPreferencesCurrentHost) url = home; else { url = CFURLCreateWithFileSystemPathRelativeToBase(alloc, CFSTR("Network/"), kCFURLPOSIXPathStyle, true, home); levels ++; CFRelease(home); } } else { home = CFCopyHomeDirectoryURLForUser((userName == kCFPreferencesCurrentUser) ? NULL : userName); if (home) { url = (safeLevel > 0) ? CFURLCreateWithFileSystemPathRelativeToBase(alloc, CFSTR("Library/Safe Preferences/"), kCFURLPOSIXPathStyle, true, home) : CFURLCreateWithFileSystemPathRelativeToBase(alloc, CFSTR("Library/Preferences/"), kCFURLPOSIXPathStyle, true, home); levels = 2; CFRelease(home); if (hostName != kCFPreferencesAnyHost) { home = url; url = CFURLCreateWithFileSystemPathRelativeToBase(alloc, CFSTR("ByHost/"), kCFURLPOSIXPathStyle, true, home); levels ++; CFRelease(home); } } else { url = NULL; } } return url; #endif }
CFPreferencesDomainRef _CFPreferencesDomainCreate(CFTypeRef context, const _CFPreferencesDomainCallBacks *callBacks) { CFAllocatorRef alloc = __CFPreferencesAllocator(); CFPreferencesDomainRef newDomain; CFAssert(callBacks != NULL && callBacks->createDomain != NULL && callBacks->freeDomain != NULL && callBacks->fetchValue != NULL && callBacks->writeValue != NULL, __kCFLogAssertion, "Cannot create a domain with NULL callbacks"); newDomain = (CFPreferencesDomainRef)_CFRuntimeCreateInstance(alloc, __kCFPreferencesDomainTypeID, sizeof(struct __CFPreferencesDomain) - sizeof(CFRuntimeBase), NULL); if (newDomain) { newDomain->_callBacks = callBacks; if (context) CFRetain(context); newDomain->_context = context; newDomain->_domain = callBacks->createDomain(alloc, context); } return newDomain; }
static CFDictionaryRef copyXMLDomainDictionary(CFTypeRef context, void *xmlDomain) { _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; CFDictionaryRef result; __CFLock(&domain->_lock); if(!domain->_domainDict) { _loadXMLDomainIfStale((CFURLRef)context, domain); } result = (CFDictionaryRef)CFPropertyListCreateDeepCopy(__CFPreferencesAllocator(), domain->_domainDict, kCFPropertyListImmutable); __CFUnlock(&domain->_lock); return result; }
static CFURLRef _CFPreferencesURLForStandardDomainWithSafetyLevel(CFStringRef domainName, CFStringRef userName, CFStringRef hostName, unsigned long safeLevel) { CFURLRef theURL = NULL; CFAllocatorRef prefAlloc = __CFPreferencesAllocator(); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD CFURLRef prefDir = _preferencesDirectoryForUserHostSafetyLevel(userName, hostName, safeLevel); CFStringRef appName; CFStringRef fileName; Boolean mustFreeAppName = false; if (!prefDir) return NULL; if (domainName == kCFPreferencesAnyApplication) { appName = CFSTR(".GlobalPreferences"); } else if (domainName == kCFPreferencesCurrentApplication) { CFBundleRef mainBundle = CFBundleGetMainBundle(); appName = mainBundle ? CFBundleGetIdentifier(mainBundle) : NULL; if (!appName || CFStringGetLength(appName) == 0) { appName = _CFProcessNameString(); } } else { appName = domainName; } if (userName != kCFPreferencesAnyUser) { if (hostName == kCFPreferencesAnyHost) { fileName = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR("%@.plist"), appName); } else if (hostName == kCFPreferencesCurrentHost) { CFStringRef hostID = _CFPreferencesGetByHostIdentifierString(); fileName = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR("%@.%@.plist"), appName, hostID); } else { fileName = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR("%@.%@.plist"), appName, hostName); // sketchy - this allows someone to set an arbitrary hostname. } } else { fileName = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR("%@.plist"), appName); } if (mustFreeAppName) { CFRelease(appName); } if (fileName) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD theURL = CFURLCreateWithFileSystemPathRelativeToBase(prefAlloc, fileName, kCFURLPOSIXPathStyle, false, prefDir); #elif DEPLOYMENT_TARGET_WINDOWS theURL = CFURLCreateWithFileSystemPathRelativeToBase(prefAlloc, fileName, kCFURLWindowsPathStyle, false, prefDir); #endif if (prefDir) CFRelease(prefDir); CFRelease(fileName); } #else //#error Do not know where to store NSUserDefaults on this platform #endif return theURL; }
// appName should not be kCFPreferencesCurrentApplication going in to this call _CFApplicationPreferences *_CFApplicationPreferencesCreateWithUser(CFStringRef userName, CFStringRef appName) { CFAllocatorRef alloc = __CFPreferencesAllocator(); _CFApplicationPreferences *self = (_CFApplicationPreferences*)CFAllocatorAllocate(alloc, sizeof(_CFApplicationPreferences), 0); if (self) { self->_dictRep = NULL; self->_appName = (CFStringRef)CFRetain(appName); self->_search = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks); if (!self->_search) { CFAllocatorDeallocate(alloc, self); CFRelease(appName); self = NULL; } } return self; }
static CFURLRef _preferencesDirectoryForUserHostSafetyLevel(CFStringRef userName, CFStringRef hostName, unsigned long safeLevel) { CFAllocatorRef alloc = __CFPreferencesAllocator(); #if TARGET_OS_WIN32 CFURLRef url = NULL; CFMutableStringRef completePath = _CFCreateApplicationRepositoryPath(alloc, CSIDL_APPDATA); if (completePath) { // append "Preferences\" and make the CFURL CFStringAppend(completePath, CFSTR("Preferences\\")); url = CFURLCreateWithFileSystemPath(alloc, completePath, kCFURLWindowsPathStyle, true); CFRelease(completePath); } // Can't find a better place? Home directory then? if (url == NULL) url = CFCopyHomeDirectoryURLForUser((userName == kCFPreferencesCurrentUser) ? NULL : userName); return url; #else CFURLRef location = NULL; CFKnownLocationUser user; if (userName == kCFPreferencesAnyUser) { user = _kCFKnownLocationUserAny; } else if (userName == kCFPreferencesCurrentUser) { user = _kCFKnownLocationUserCurrent; } else { user = _kCFKnownLocationUserByName; } CFURLRef base = _CFKnownLocationCreatePreferencesURLForUser(user, userName); if (hostName == kCFPreferencesCurrentHost) { location = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, CFSTR("ByHost"), kCFURLPOSIXPathStyle, true, base); } else { assert(hostName == kCFPreferencesAnyHost); location = CFRetain(base); } CFRelease(base); return location; #endif }
CFPreferencesDomainRef _CFPreferencesStandardDomain(CFStringRef domainName, CFStringRef userName, CFStringRef hostName) { CFPreferencesDomainRef domain; CFStringRef domainKey; Boolean shouldReleaseDomain = true; domainKey = _CFPreferencesStandardDomainCacheKey(domainName, userName, hostName); __CFSpinLock(&domainCacheLock); if (!domainCache) { CFAllocatorRef alloc = __CFPreferencesAllocator(); domainCache = CFDictionaryCreateMutable(alloc, 0, & kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } domain = (CFPreferencesDomainRef)CFDictionaryGetValue(domainCache, domainKey); __CFSpinUnlock(&domainCacheLock); if (!domain) { // Domain's not in the cache; load from permanent storage CFURLRef theURL = _CFPreferencesURLForStandardDomain(domainName, userName, hostName); if (theURL) { domain = _CFPreferencesDomainCreate(theURL, &__kCFXMLPropertyListDomainCallBacks); if (userName == kCFPreferencesAnyUser) { _CFPreferencesDomainSetIsWorldReadable(domain, true); } CFRelease(theURL); } __CFSpinLock(&domainCacheLock); if (domain && domainCache) { // We've just synthesized a domain & we're about to throw it in the domain cache. The problem is that someone else might have gotten in here behind our backs, so we can't just blindly set the domain (3021920). We'll need to check to see if this happened, and compensate. CFPreferencesDomainRef checkDomain = (CFPreferencesDomainRef)CFDictionaryGetValue(domainCache, domainKey); if(checkDomain) { // Someone got in here ahead of us, so we shouldn't smash the domain we're given. checkDomain is the current version, we should use that. // checkDomain was retrieved with a Get, so we don't want to over-release. shouldReleaseDomain = false; CFRelease(domain); // release the domain we synthesized earlier. domain = checkDomain; // repoint it at the domain picked up out of the cache. } else { // We must not have found the domain in the cache, so it's ok for us to put this in. CFDictionarySetValue(domainCache, domainKey, domain); } if(shouldReleaseDomain) CFRelease(domain); } __CFSpinUnlock(&domainCacheLock); } CFRelease(domainKey); return domain; }
void _CFDeallocateApplicationPreferences(_CFApplicationPreferences *self) { CFAllocatorRef alloc = __CFPreferencesAllocator(); _CFApplicationPreferences *cachedPrefs = NULL; __CFSpinLock(&__CFApplicationPreferencesLock); // Get us out of the cache before destroying! if (__CFStandardUserPreferences) { cachedPrefs = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, self->_appName); } if (cachedPrefs == self) { CFDictionaryRemoveValue(__CFStandardUserPreferences, self->_appName); } if (self->_dictRep) CFRelease(self->_dictRep); CFRelease(self->_search); CFRelease(self->_appName); CFAllocatorDeallocate(alloc, self); __CFSpinUnlock(&__CFApplicationPreferencesLock); }
static void writeXMLValue(CFTypeRef context, void *xmlDomain, CFStringRef key, CFTypeRef value) { _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; const void *existing = NULL; __CFLock(&domain->_lock); if (domain->_domainDict == NULL) { _loadXMLDomainIfStale((CFURLRef )context, domain); } // check to see if the value is the same // if (1) the key is present AND value is !NULL and equal to existing, do nothing, or // if (2) the key is not present AND value is NULL, do nothing // these things are no-ops, and should not dirty the domain if (CFDictionaryGetValueIfPresent(domain->_domainDict, key, &existing)) { if (NULL != value && (existing == value || CFEqual(existing, value))) { __CFUnlock(&domain->_lock); return; } } else { if (NULL == value) { __CFUnlock(&domain->_lock); return; } } // We must append first so key gets another retain (in case we're // about to remove it from the dictionary, and that's the sole reference) // This should be a set not an array. if (!CFArrayContainsValue(domain->_dirtyKeys, CFRangeMake(0, CFArrayGetCount(domain->_dirtyKeys)), key)) { CFArrayAppendValue(domain->_dirtyKeys, key); } if (value) { // Must copy for two reasons - we don't want mutable objects in the cache, and we don't want objects allocated from a different allocator in the cache. CFTypeRef newValue = CFPropertyListCreateDeepCopy(__CFPreferencesAllocator(), value, kCFPropertyListImmutable); CFDictionarySetValue(domain->_domainDict, key, newValue); CFRelease(newValue); } else { CFDictionaryRemoveValue(domain->_domainDict, key); } __CFUnlock(&domain->_lock); }
/* We spend a lot of time constructing these prefixes; we should cache. REW, 7/19/99 */ static CFStringRef _CFPreferencesCachePrefixForUserHost(CFStringRef userName, CFStringRef hostName) { if (userName == kCFPreferencesAnyUser && hostName == kCFPreferencesAnyHost) { return (CFStringRef)CFRetain(CFSTR("*/*/")); } CFMutableStringRef result = CFStringCreateMutable(__CFPreferencesAllocator(), 0); if (userName == kCFPreferencesCurrentUser) { userName = CFGetUserName(); CFStringAppend(result, userName); CFStringAppend(result, CFSTR("/")); } else if (userName == kCFPreferencesAnyUser) { CFStringAppend(result, CFSTR("*/")); } if (hostName == kCFPreferencesCurrentHost) { CFStringRef hostID = _CFPreferencesGetByHostIdentifierString(); CFStringAppend(result, hostID); CFStringAppend(result, CFSTR("/")); } else if (hostName == kCFPreferencesAnyHost) { CFStringAppend(result, CFSTR("*/")); } return result; }
// quick message to indicate that the given domain has changed, and we should go through and invalidate any dictReps that involve this domain. void _CFApplicationPreferencesDomainHasChanged(CFPreferencesDomainRef changedDomain) { CFAllocatorRef alloc = __CFPreferencesAllocator(); __CFSpinLock(&__CFApplicationPreferencesLock); if(__CFStandardUserPreferences) { // only grovel over the prefs if there's something there to grovel _CFApplicationPreferences **prefsArray, *prefsBuf[32]; CFIndex idx, count = CFDictionaryGetCount(__CFStandardUserPreferences); if(count < 32) { prefsArray = prefsBuf; } else { prefsArray = (_CFApplicationPreferences **)CFAllocatorAllocate(alloc, count * sizeof(_CFApplicationPreferences *), 0); } CFDictionaryGetKeysAndValues(__CFStandardUserPreferences, NULL, (const void **)prefsArray); // For this operation, giving up the lock is the last thing we want to do, so use the modified flavor of _CFApplicationPreferencesContainsDomain for(idx = 0; idx < count; idx++) { _CFApplicationPreferences *appPrefs = prefsArray[idx]; if(_CFApplicationPreferencesContainsDomainNoLock(appPrefs, changedDomain)) { updateDictRep(appPrefs); } } if(prefsArray != prefsBuf) _CFAllocatorDeallocateGC(alloc, prefsArray); } __CFSpinUnlock(&__CFApplicationPreferencesLock); }
void _CFPreferencesDomainSetDictionary(CFPreferencesDomainRef domain, CFDictionaryRef dict) { CFAllocatorRef alloc = __CFPreferencesAllocator(); CFDictionaryRef d = _CFPreferencesDomainDeepCopyDictionary(domain); CFIndex idx, count = d ? CFDictionaryGetCount(d) : 0; CFTypeRef *keys = (CFTypeRef *)CFAllocatorAllocate(alloc, count * sizeof(CFTypeRef), 0); if (d) CFDictionaryGetKeysAndValues(d, keys, NULL); for (idx = 0; idx < count; idx ++) { _CFPreferencesDomainSet(domain, (CFStringRef)keys[idx], NULL); } CFAllocatorDeallocate(alloc, keys); if (d) CFRelease(d); if (dict && (count = CFDictionaryGetCount(dict)) != 0) { CFStringRef *newKeys = (CFStringRef *)CFAllocatorAllocate(alloc, count * sizeof(CFStringRef), 0); CFDictionaryGetKeysAndValues(dict, (const void **)newKeys, NULL); for (idx = 0; idx < count; idx ++) { CFStringRef key = newKeys[idx]; _CFPreferencesDomainSet(domain, key, (CFTypeRef)CFDictionaryGetValue(dict, key)); } CFAllocatorDeallocate(alloc, newKeys); } }
// domain should already be locked. static Boolean _writeXMLFile(CFURLRef url, CFMutableDictionaryRef dict, Boolean isWorldReadable, Boolean *tryAgain) { Boolean success = false; CFAllocatorRef alloc = __CFPreferencesAllocator(); *tryAgain = false; if (CFDictionaryGetCount(dict) == 0) { // Destroy the file CFBooleanRef val = (CFBooleanRef) CFURLCreatePropertyFromResource(alloc, url, kCFURLFileExists, NULL); if (val && CFBooleanGetValue(val)) { success = CFURLDestroyResource(url, NULL); } else { success = true; } if (val) CFRelease(val); } else { CFPropertyListFormat desiredFormat = __CFPreferencesShouldWriteXML() ? kCFPropertyListXMLFormat_v1_0 : kCFPropertyListBinaryFormat_v1_0; CFDataRef data = CFPropertyListCreateData(alloc, dict, desiredFormat, 0, NULL); if (data) { SInt32 mode; #if TARGET_OS_OSX || TARGET_OS_LINUX mode = isWorldReadable ? S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH : S_IRUSR|S_IWUSR; #else mode = 0666; #endif #if TARGET_OS_OSX { // Try quick atomic way first, then fallback to slower ways and error cases CFStringRef scheme = CFURLCopyScheme(url); if (!scheme) { *tryAgain = false; CFRelease(data); return false; } else if (CFStringCompare(scheme, CFSTR("file"), 0) == kCFCompareEqualTo) { SInt32 length = CFDataGetLength(data); const void *bytes = (0 == length) ? (const void *)"" : CFDataGetBytePtr(data); Boolean atomicWriteSuccess = __CFWriteBytesToFileWithAtomicity(url, bytes, length, mode, true); if (atomicWriteSuccess) { CFRelease(scheme); *tryAgain = false; CFRelease(data); return true; } if (!atomicWriteSuccess && thread_errno() == ENOSPC) { CFRelease(scheme); *tryAgain = false; CFRelease(data); return false; } } CFRelease(scheme); } #endif success = CFURLWriteDataAndPropertiesToResource(url, data, URLPropertyDictForPOSIXMode(mode), NULL); URLPropertyDictRelease(); if (success) { CFDataRef readData; if (!CFURLCreateDataAndPropertiesFromResource(alloc, url, &readData, NULL, NULL, NULL) || !CFEqual(readData, data)) { success = false; *tryAgain = true; } if (readData) CFRelease(readData); } else { CFBooleanRef val = (CFBooleanRef) CFURLCreatePropertyFromResource(alloc, url, kCFURLFileExists, NULL); if (!val || !CFBooleanGetValue(val)) { CFURLRef tmpURL = CFURLCreateWithFileSystemPathRelativeToBase(alloc, CFSTR("."), kCFURLPOSIXPathStyle, true, url); // Just "." because url is not a directory URL CFURLRef parentURL = tmpURL ? CFURLCopyAbsoluteURL(tmpURL) : NULL; if (tmpURL) CFRelease(tmpURL); if (val) CFRelease(val); val = (CFBooleanRef) CFURLCreatePropertyFromResource(alloc, parentURL, kCFURLFileExists, NULL); if ((!val || !CFBooleanGetValue(val)) && _createDirectory(parentURL, isWorldReadable)) { // parent directory didn't exist; now it does; try again to write success = CFURLWriteDataAndPropertiesToResource(url, data, URLPropertyDictForPOSIXMode(mode), NULL); URLPropertyDictRelease(); if (success) { CFDataRef rdData; if (!CFURLCreateDataAndPropertiesFromResource(alloc, url, &rdData, NULL, NULL, NULL) || !CFEqual(rdData, data)) { success = false; *tryAgain = true; } if (rdData) CFRelease(rdData); } } if (parentURL) CFRelease(parentURL); } if (val) CFRelease(val); } CFRelease(data); } else { // ??? This should never happen CFLog(__kCFLogAssertion, CFSTR("Could not generate XML data for property list")); success = false; } } return success; }
static CFDictionaryRef copyVolatileDomainDictionary(CFTypeRef context, void *volatileDomain) { CFMutableDictionaryRef dict = (CFMutableDictionaryRef)volatileDomain; CFDictionaryRef result = (CFDictionaryRef)CFPropertyListCreateDeepCopy(__CFPreferencesAllocator(), dict, kCFPropertyListImmutable); return result; }
__private_extern__ CFArrayRef _CFPreferencesCreateDomainList(CFStringRef userName, CFStringRef hostName) { CFAllocatorRef prefAlloc = __CFPreferencesAllocator(); CFArrayRef domains; CFMutableArrayRef marray; CFStringRef *cachedDomainKeys; CFPreferencesDomainRef *cachedDomains; SInt32 idx, cnt; CFStringRef suffix; UInt32 suffixLen; CFURLRef prefDir = _preferencesDirectoryForUserHost(userName, hostName); if (!prefDir) { return NULL; } if (hostName == kCFPreferencesAnyHost) { suffix = CFStringCreateWithCString(prefAlloc, ".plist", kCFStringEncodingASCII); } else if (hostName == kCFPreferencesCurrentHost) { CFStringRef hostID = _CFPreferencesGetByHostIdentifierString(); suffix = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR(".%@.plist"), hostID); } else { suffix = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR(".%@.plist"), hostName); // sketchy - this allows someone to create a domain list for an arbitrary hostname. } suffixLen = CFStringGetLength(suffix); domains = (CFArrayRef)CFURLCreatePropertyFromResource(prefAlloc, prefDir, kCFURLFileDirectoryContents, NULL); CFRelease(prefDir); if (domains){ marray = CFArrayCreateMutableCopy(prefAlloc, 0, domains); CFRelease(domains); } else { marray = CFArrayCreateMutable(prefAlloc, 0, & kCFTypeArrayCallBacks); } for (idx = CFArrayGetCount(marray)-1; idx >= 0; idx --) { CFURLRef url = (CFURLRef)CFArrayGetValueAtIndex(marray, idx); CFStringRef string = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); if (!CFStringHasSuffix(string, suffix)) { CFArrayRemoveValueAtIndex(marray, idx); } else { CFStringRef dom = CFStringCreateWithSubstring(prefAlloc, string, CFRangeMake(0, CFStringGetLength(string) - suffixLen)); if (CFEqual(dom, CFSTR(".GlobalPreferences"))) { CFArraySetValueAtIndex(marray, idx, kCFPreferencesAnyApplication); } else { CFArraySetValueAtIndex(marray, idx, dom); } CFRelease(dom); } CFRelease(string); } CFRelease(suffix); // Now add any domains added in the cache; delete any that have been deleted in the cache __CFSpinLock(&domainCacheLock); if (!domainCache) { __CFSpinUnlock(&domainCacheLock); return marray; } cnt = CFDictionaryGetCount(domainCache); cachedDomainKeys = (CFStringRef *)CFAllocatorAllocate(prefAlloc, 2 * cnt * sizeof(CFStringRef), 0); cachedDomains = (CFPreferencesDomainRef *)(cachedDomainKeys + cnt); CFDictionaryGetKeysAndValues(domainCache, (const void **)cachedDomainKeys, (const void **)cachedDomains); __CFSpinUnlock(&domainCacheLock); suffix = _CFPreferencesCachePrefixForUserHost(userName, hostName); suffixLen = CFStringGetLength(suffix); for (idx = 0; idx < cnt; idx ++) { CFStringRef domainKey = cachedDomainKeys[idx]; CFPreferencesDomainRef domain = cachedDomains[idx]; CFStringRef domainName; CFIndex keyCount = 0; if (!CFStringHasPrefix(domainKey, suffix)) continue; domainName = CFStringCreateWithSubstring(prefAlloc, domainKey, CFRangeMake(suffixLen, CFStringGetLength(domainKey) - suffixLen)); if (CFEqual(domainName, CFSTR("*"))) { CFRelease(domainName); domainName = (CFStringRef)CFRetain(kCFPreferencesAnyApplication); } else if (CFEqual(domainName, kCFPreferencesCurrentApplication)) { CFRelease(domainName); domainName = (CFStringRef)CFRetain(_CFProcessNameString()); } CFDictionaryRef d = _CFPreferencesDomainDeepCopyDictionary(domain); keyCount = d ? CFDictionaryGetCount(d) : 0; if (keyCount) CFRelease(d); if (keyCount == 0) { // Domain was deleted SInt32 firstIndexOfValue = CFArrayGetFirstIndexOfValue(marray, CFRangeMake(0, CFArrayGetCount(marray)), domainName); if (0 <= firstIndexOfValue) { CFArrayRemoveValueAtIndex(marray, firstIndexOfValue); } } else if (!CFArrayContainsValue(marray, CFRangeMake(0, CFArrayGetCount(marray)), domainName)) { CFArrayAppendValue(marray, domainName); } CFRelease(domainName); } CFRelease(suffix); CFAllocatorDeallocate(prefAlloc, cachedDomainKeys); return marray; }
static CFStringRef __CFPreferencesDomainCopyDescription(CFTypeRef cf) { return CFStringCreateWithFormat(__CFPreferencesAllocator(), NULL, CFSTR("<Private CFType %p>\n"), cf); }
} CFRelease(domainName); } CFRelease(suffix); CFAllocatorDeallocate(prefAlloc, cachedDomainKeys); return marray; } // // CFPreferencesDomain functions // CFPreferencesDomainRef _CFPreferencesDomainCreate(CFTypeRef context, const _CFPreferencesDomainCallBacks *callBacks) { static dispatch_once_t initOnce; dispatch_once(&initOnce, ^{ __kCFPreferencesDomainTypeID = _CFRuntimeRegisterClass(&__CFPreferencesDomainClass); }); CFAllocatorRef alloc = __CFPreferencesAllocator(); CFPreferencesDomainRef newDomain; CFAssert(callBacks != NULL && callBacks->createDomain != NULL && callBacks->freeDomain != NULL && callBacks->fetchValue != NULL && callBacks->writeValue != NULL, __kCFLogAssertion, "Cannot create a domain with NULL callbacks"); newDomain = (CFPreferencesDomainRef)_CFRuntimeCreateInstance(alloc, __kCFPreferencesDomainTypeID, sizeof(struct __CFPreferencesDomain) - sizeof(CFRuntimeBase), NULL); if (newDomain) { newDomain->_callBacks = callBacks; if (context) CFRetain(context); newDomain->_context = context; newDomain->_domain = callBacks->createDomain(alloc, context); } return newDomain; } CFTypeRef _CFPreferencesDomainCreateValueForKey(CFPreferencesDomainRef domain, CFStringRef key) { return domain->_callBacks->fetchValue(domain->_context, domain->_domain, key); }
static void __CFPreferencesDomainDeallocate(CFTypeRef cf) { const struct __CFPreferencesDomain *domain = (struct __CFPreferencesDomain *)cf; CFAllocatorRef alloc = __CFPreferencesAllocator(); domain->_callBacks->freeDomain(alloc, domain->_context, domain->_domain); if (domain->_context) CFRelease(domain->_context); }