void CFPreferencesFlushCaches(void) {
    CFAllocatorRef alloc = __CFPreferencesAllocator();
    __CFLock(&__CFApplicationPreferencesLock);
    if (__CFStandardUserPreferences)  {
        _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);

        __CFUnlock(&__CFApplicationPreferencesLock);
        // DeallocateApplicationPreferences needs the lock
        for (idx = 0; idx < count; idx ++) {
            _CFApplicationPreferences *appPrefs = prefsArray[idx];
            _CFApplicationPreferencesSynchronize(appPrefs);
            _CFDeallocateApplicationPreferences(appPrefs);
        }
        __CFLock(&__CFApplicationPreferencesLock);

        CFRelease(__CFStandardUserPreferences);
        __CFStandardUserPreferences = NULL;
        if(prefsArray != prefsBuf) CFAllocatorDeallocate(alloc, prefsArray);
    }
    __CFUnlock(&__CFApplicationPreferencesLock);
    _CFPreferencesPurgeDomainCache();
}
Example #2
0
CF_PRIVATE CFErrorRef _CFErrorFromStreamError(CFAllocatorRef alloc, CFStreamError *streamError) {
    CFErrorRef result;
    Boolean canUpCall;
    
    __CFLock(&(CFNetworkSupport.lock));
    if (!__CFBitIsSet(CFNetworkSupport.flags, kTriedToLoad)) initializeCFNetworkSupport();
    canUpCall = (CFNetworkSupport._CFErrorCreateWithStreamError != NULL);
    __CFUnlock(&(CFNetworkSupport.lock));

    if (canUpCall) {
        result = CFNETWORK_CALL(_CFErrorCreateWithStreamError, (alloc, streamError));
    } else {
        if (streamError->domain == kCFStreamErrorDomainPOSIX) {
            return CFErrorCreate(alloc, kCFErrorDomainPOSIX, streamError->error, NULL);
        } else if (streamError->domain == kCFStreamErrorDomainMacOSStatus) {
            return CFErrorCreate(alloc, kCFErrorDomainOSStatus, streamError->error, NULL);
        } else {
            CFStringRef key = CFSTR("CFStreamErrorDomainKey");
            CFNumberRef value = CFNumberCreate(alloc, kCFNumberCFIndexType, &streamError->domain);
            CFDictionaryRef dict = CFDictionaryCreate(alloc, (const void **)(&key), (const void **)(&value), 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
            result = CFErrorCreate(alloc, CFSTR("BogusCFStreamErrorCompatibilityDomain"), streamError->error, dict);
            CFRelease(value);
            CFRelease(dict);
        }
    }
    return result;
}
Example #3
0
CF_PRIVATE CFStreamError _CFStreamErrorFromError(CFErrorRef error) {
    CFStreamError result;
    Boolean canUpCall;
    
    __CFLock(&(CFNetworkSupport.lock));
    if (!__CFBitIsSet(CFNetworkSupport.flags, kTriedToLoad)) initializeCFNetworkSupport();
    canUpCall = (CFNetworkSupport._CFStreamErrorFromCFError != NULL);
    __CFUnlock(&(CFNetworkSupport.lock));

    if (canUpCall) {
        result = CFNETWORK_CALL(_CFStreamErrorFromCFError, (error));
    } else {
        CFStringRef domain = CFErrorGetDomain(error); 
        if (CFEqual(domain, kCFErrorDomainPOSIX)) {
            result.domain = kCFStreamErrorDomainPOSIX;
        } else if (CFEqual(domain, kCFErrorDomainOSStatus)) {
            result.domain = kCFStreamErrorDomainMacOSStatus;
        } else if (CFEqual(domain, kCFErrorDomainMach)) {
            result.domain = 11; // kCFStreamErrorDomainMach, but that symbol is in CFNetwork
        } else {
            result.domain = kCFStreamErrorDomainCustom;
        }
        result.error = CFErrorGetCode(error);
    }
    return result;
}
Boolean _CFApplicationPreferencesSynchronize(_CFApplicationPreferences *self) {
    Boolean result;
    __CFLock(&__CFApplicationPreferencesLock);
    result = _CFApplicationPreferencesSynchronizeNoLock(self);
    __CFUnlock(&__CFApplicationPreferencesLock);
    return result;
}
CF_PRIVATE Boolean _CFSynchronizeDomainCache(void) {
    Boolean result = true;
    __CFLock(&domainCacheLock);
    if (domainCache) {
        CFDictionaryApplyFunction(domainCache, __CFPreferencesPerformSynchronize, &result);
    }
    __CFUnlock(&domainCacheLock);
    return result;
}
CF_PRIVATE void _CFPreferencesPurgeDomainCache(void) {
    _CFSynchronizeDomainCache();
    __CFLock(&domainCacheLock);
    if (domainCache) {
        CFRelease(domainCache);
        domainCache = NULL;
    }
    __CFUnlock(&domainCacheLock);
}
CFPreferencesDomainRef _CFPreferencesStandardDomain(CFStringRef  domainName, CFStringRef  userName, CFStringRef  hostName) {
    CFPreferencesDomainRef domain;
    CFStringRef  domainKey;
    Boolean shouldReleaseDomain = true;
     domainKey = _CFPreferencesStandardDomainCacheKey(domainName, userName, hostName);
    __CFLock(&domainCacheLock);
    if (!domainCache) {
        CFAllocatorRef alloc = __CFPreferencesAllocator();
        domainCache = CFDictionaryCreateMutable(alloc, 0, & kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    }
    domain = (CFPreferencesDomainRef)CFDictionaryGetValue(domainCache, domainKey);
    __CFUnlock(&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);
        }
	__CFLock(&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);
        }
	__CFUnlock(&domainCacheLock);
    }
    CFRelease(domainKey);
    return domain;
}
void _CFApplicationPreferencesAddDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain, Boolean addAtTop) {
    __CFLock(&__CFApplicationPreferencesLock);
    if (addAtTop) {
        CFArrayInsertValueAtIndex(self->_search, 0, domain);
    } else {
        CFArrayAppendValue(self->_search, domain);
    }
    updateDictRep(self);
    __CFUnlock(&__CFApplicationPreferencesLock);
}
static void _CFApplicationPreferencesSetSearchList(_CFApplicationPreferences *self, CFArrayRef newSearchList) {
    CFIndex idx, count;
    __CFLock(&__CFApplicationPreferencesLock);
    CFArrayRemoveAllValues(self->_search);
    count = CFArrayGetCount(newSearchList);
    for (idx = 0; idx < count; idx ++) {
        CFArrayAppendValue(self->_search, CFArrayGetValueAtIndex(newSearchList, idx));
    }
    updateDictRep(self);
    __CFUnlock(&__CFApplicationPreferencesLock);
}
CF_INLINE CFDictionaryRef URLPropertyDictForPOSIXMode(SInt32 mode) {
    static CFMutableDictionaryRef _propertyDict = NULL;
    CFNumberRef num = CFNumberCreate(__CFPreferencesAllocator(), kCFNumberSInt32Type, &mode);
    __CFLock(&_propDictLock);
    if (!_propertyDict) {
        _propertyDict = CFDictionaryCreateMutable(__CFPreferencesAllocator(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    }
    CFDictionarySetValue(_propertyDict, kCFURLFilePOSIXMode, num);
    CFRelease(num);
    return _propertyDict;
}
Boolean _CFApplicationPreferencesContainsDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain) {
    Boolean result;

    if (!domain) {
        return false;
    }

    __CFLock(&__CFApplicationPreferencesLock);
    result = CFArrayContainsValue(self->_search, CFRangeMake(0, CFArrayGetCount(self->_search)), domain);
    __CFUnlock(&__CFApplicationPreferencesLock);
    return result;
}
static CFTypeRef fetchXMLValue(CFTypeRef context, void *xmlDomain, CFStringRef key) {
    _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain;
    CFTypeRef result;
 
    // Never reload if we've looked at the file system within the last 5 seconds.
    __CFLock(&domain->_lock);
    if (domain->_domainDict == NULL) _loadXMLDomainIfStale((CFURLRef )context, domain);
    result = CFDictionaryGetValue(domain->_domainDict, key);
    if (result) CFRetain(result); 
    __CFUnlock(&domain->_lock);

    return result;
}
// CACHING here - we will only return a value as current as the last time computeDictRep() was called
static CFTypeRef _CFApplicationPreferencesCreateValueForKey2(_CFApplicationPreferences *self, CFStringRef defaultName) {
    CFTypeRef result;
    __CFLock(&__CFApplicationPreferencesLock);
    if (!self->_dictRep) {
        self->_dictRep = computeDictRep(self, true);
    }
    result = (self->_dictRep) ? (CFTypeRef )CFDictionaryGetValue(self->_dictRep, defaultName) : NULL;
    if (result) {
        CFRetain(result);
    }
    __CFUnlock(&__CFApplicationPreferencesLock);
    return result;
}
CF_EXPORT
CFDictionaryRef _CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences *self) {
    CFDictionaryRef dict;
    __CFLock(&__CFApplicationPreferencesLock);
    if (!self->_dictRep) {
        self->_dictRep = computeDictRep(self, true);
    }
    if (self->_dictRep) {
        CFRetain(self->_dictRep);
    }
    dict = self->_dictRep;
    __CFUnlock(&__CFApplicationPreferencesLock);
    return dict;
}
void _CFApplicationPreferencesRemove(_CFApplicationPreferences *self, CFStringRef defaultName) {
    CFPreferencesDomainRef appDomain;

    __CFLock(&__CFApplicationPreferencesLock);
    appDomain = _CFPreferencesStandardDomain(self->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
    if(appDomain) {
        _CFPreferencesDomainSet(appDomain, defaultName, NULL);
        if (CFArrayContainsValue(self->_search, CFRangeMake(0, CFArrayGetCount(self->_search)), appDomain)) {
            // If key exists, it will be in the _dictRep (but possibly overridden)
            updateDictRep(self);
        }
    }
    __CFUnlock(&__CFApplicationPreferencesLock);
}
void _CFApplicationPreferencesRemoveDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain) {
    CFIndex idx;
    CFRange range;
    __CFLock(&__CFApplicationPreferencesLock);
    range.location = 0;
    range.length = CFArrayGetCount(self->_search);
    while ((idx = CFArrayGetFirstIndexOfValue(self->_search, range, domain)) != kCFNotFound) {
        CFArrayRemoveValueAtIndex(self->_search, idx);
        range.location = idx;
        range.length  = range.length - idx - 1;
    }
    updateDictRep(self);
    __CFUnlock(&__CFApplicationPreferencesLock);
}
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;
}
void _CFApplicationPreferencesSet(_CFApplicationPreferences *self, CFStringRef defaultName, CFTypeRef value) {
    CFPreferencesDomainRef applicationDomain;

    __CFLock(&__CFApplicationPreferencesLock);
    applicationDomain = _CFPreferencesStandardDomain(self->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
    if(applicationDomain) {
        _CFPreferencesDomainSet(applicationDomain, defaultName, value);
        if (CFArrayContainsValue(self->_search, CFRangeMake(0, CFArrayGetCount(self->_search)), applicationDomain)) {
            // Expensive; can't we just check the relevant value throughout the appropriate sets of domains? -- REW, 7/19/99
            updateDictRep(self);
        }
    }
    __CFUnlock(&__CFApplicationPreferencesLock);
}
void _CFApplicationPreferencesRemoveSuitePreferences(_CFApplicationPreferences *appPrefs, CFStringRef suiteName) {
    CFPreferencesDomainRef domain;

    __CFLock(&__CFApplicationPreferencesLock);
    domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
    __CFUnlock(&__CFApplicationPreferencesLock);
    if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain);

    __CFLock(&__CFApplicationPreferencesLock);
    domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
    __CFUnlock(&__CFApplicationPreferencesLock);
    if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain);

    __CFLock(&__CFApplicationPreferencesLock);
    domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesAnyHost);
    __CFUnlock(&__CFApplicationPreferencesLock);
    if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain);

    __CFLock(&__CFApplicationPreferencesLock);
    domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
    __CFUnlock(&__CFApplicationPreferencesLock);
    if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain);
}
// Exclusively for Foundation's use
void _CFApplicationPreferencesSetCacheForApp(_CFApplicationPreferences *appPrefs, CFStringRef appName) {
    __CFLock(&__CFApplicationPreferencesLock);
    if (!__CFStandardUserPreferences) {
        __CFStandardUserPreferences = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL);
        CFDictionarySetValue(__CFStandardUserPreferences, appName, appPrefs);
        __CFUnlock(&__CFApplicationPreferencesLock);
    } else {
        _CFApplicationPreferences *oldPrefs = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName);
        CFDictionarySetValue(__CFStandardUserPreferences, appName, appPrefs);
        __CFUnlock(&__CFApplicationPreferencesLock);
        if (oldPrefs) {
            _CFDeallocateApplicationPreferences(oldPrefs);
        }
    }
}
Example #21
0
static void
createPair(CFAllocatorRef alloc, CFStringRef host, UInt32 port, CFSocketNativeHandle sock, const CFSocketSignature* sig, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream)
{
    if (readStream)
        *readStream = NULL;
        
    if (writeStream)
        *writeStream = NULL;

    __CFLock(&(CFNetworkSupport.lock));
    if (!__CFBitIsSet(CFNetworkSupport.flags, kTriedToLoad)) initializeCFNetworkSupport();
    __CFUnlock(&(CFNetworkSupport.lock));

    CFNETWORK_CALL(_CFSocketStreamCreatePair, (alloc, host, port, sock, sig, readStream, writeStream));
}
static void __CFMessagePortDeallocate(CFTypeRef cf) {
    CFMessagePortRef ms = (CFMessagePortRef)cf;
    __CFMessagePortSetIsDeallocing(ms);
    CFMessagePortInvalidate(ms);
    // Delay cleanup of _replies until here so that invalidation during
    // SendRequest does not cause _replies to disappear out from under that function.
    if (NULL != ms->_replies) {
	CFRelease(ms->_replies);
    }
    if (NULL != ms->_name) {
	CFRelease(ms->_name);
    }
    if (NULL != ms->_port) {
	if (__CFMessagePortExtraMachRef(ms)) {
	    mach_port_mod_refs(mach_task_self(), CFMachPortGetPort(ms->_port), MACH_PORT_RIGHT_SEND, -1);
	    mach_port_mod_refs(mach_task_self(), CFMachPortGetPort(ms->_port), MACH_PORT_RIGHT_RECEIVE, -1);
	}
	CFMachPortInvalidate(ms->_port);
	CFRelease(ms->_port);
    }

    // A remote message port for a local message port in the same process will get the
    // same mach port, and the remote port will keep the mach port from being torn down,
    // thus keeping the remote port from getting any sort of death notification and
    // auto-invalidating; so we manually implement the 'auto-invalidation' here by
    // tickling each remote port to check its state after any message port is destroyed,
    // but most importantly after local message ports are destroyed.
    __CFLock(&__CFAllMessagePortsLock);
    CFMessagePortRef *remotePorts = NULL;
    CFIndex cnt = 0;
    if (NULL != __CFAllRemoteMessagePorts) {
	cnt = CFDictionaryGetCount(__CFAllRemoteMessagePorts);
	remotePorts = CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(CFMessagePortRef), __kCFAllocatorGCScannedMemory);
	CFDictionaryGetKeysAndValues(__CFAllRemoteMessagePorts, NULL, (const void **)remotePorts);
	for (CFIndex idx = 0; idx < cnt; idx++) {
	    CFRetain(remotePorts[idx]);
	}
    }
    __CFUnlock(&__CFAllMessagePortsLock);
    if (remotePorts) {
	for (CFIndex idx = 0; idx < cnt; idx++) {
	    // as a side-effect, this will auto-invalidate the CFMessagePort if the CFMachPort is invalid
	    CFMessagePortIsValid(remotePorts[idx]);
	    CFRelease(remotePorts[idx]);
	}
	CFAllocatorDeallocate(kCFAllocatorSystemDefault, remotePorts);
    }
}
static Boolean synchronizeXMLDomain(CFTypeRef context, void *xmlDomain) {
    _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain;
    CFMutableDictionaryRef cachedDict;
    CFMutableArrayRef changedKeys;
    SInt32 idx,  count;
    Boolean success, tryAgain;
    
    __CFLock(&domain->_lock);
    cachedDict = domain->_domainDict;
    changedKeys = domain->_dirtyKeys;
    count = CFArrayGetCount(changedKeys);
    
    if (count == 0) {
        // no changes were made to this domain; just remove it from the cache to guarantee it will be taken from disk next access
        if (cachedDict) {
            CFRelease(cachedDict);
            domain->_domainDict = NULL;
        }
        __CFUnlock(&domain->_lock);
        return true;
    }

    domain->_domainDict = NULL; // This forces a reload.  Note that we now have a retain on cachedDict
    do {
        _loadXMLDomainIfStale((CFURLRef )context, domain);
        // now cachedDict holds our changes; domain->_domainDict has the latest version from the disk
        for (idx = 0; idx < count; idx ++) {
            CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(changedKeys, idx);
            CFTypeRef value = CFDictionaryGetValue(cachedDict, key);
            if (value)
                CFDictionarySetValue(domain->_domainDict, key, value);
            else
                CFDictionaryRemoveValue(domain->_domainDict, key);
        }
        success = _writeXMLFile((CFURLRef )context, domain->_domainDict, domain->_isWorldReadable, &tryAgain);
        if (tryAgain) {
            __CFMilliSleep(50);
        }
    } while (tryAgain);
    CFRelease(cachedDict);
    if (success) {
	CFArrayRemoveAllValues(domain->_dirtyKeys);
    }
    domain->_lastReadTime = CFAbsoluteTimeGetCurrent();
    __CFUnlock(&domain->_lock);
    return success;
}
Boolean CFPreferencesAppSynchronize(CFStringRef appName) {
    _CFApplicationPreferences *standardPrefs;
    Boolean result;
    CFAssert1(appName != NULL, __kCFLogAssertion, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__);
    
    // Do not call _CFStandardApplicationPreferences(), as we do not want to create the preferences only to synchronize
    __CFLock(&__CFApplicationPreferencesLock);
    if (__CFStandardUserPreferences)  {
        standardPrefs = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName);
    } else {
        standardPrefs = NULL;
    }

    result = standardPrefs ? _CFApplicationPreferencesSynchronizeNoLock(standardPrefs) : _CFSynchronizeDomainCache();
    __CFUnlock(&__CFApplicationPreferencesLock);
    return result;
}
void _CFDeallocateApplicationPreferences(_CFApplicationPreferences *self) {
    CFAllocatorRef alloc = __CFPreferencesAllocator();
    _CFApplicationPreferences *cachedPrefs = NULL;
    __CFLock(&__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);
    __CFUnlock(&__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);
}
CF_PRIVATE _CFApplicationPreferences *_CFStandardApplicationPreferences(CFStringRef appName) {
    _CFApplicationPreferences *appPreferences;
//    CFAssert(appName != kCFPreferencesAnyApplication, __kCFLogAssertion, "Cannot use any of the CFPreferences...App... functions with an appName of kCFPreferencesAnyApplication");
    __CFLock(&__CFApplicationPreferencesLock);
    if (!__CFStandardUserPreferences)  {
        __CFStandardUserPreferences = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, & kCFTypeDictionaryKeyCallBacks, NULL);
    }
    if (!__CFStandardUserPreferences) {
        // Couldn't create
        __CFUnlock(&__CFApplicationPreferencesLock);
        return NULL;
    }
    if ((appPreferences = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName)) == NULL ) {
        appPreferences = _CFApplicationPreferencesCreateWithUser(kCFPreferencesCurrentUser, appName);
        CFDictionarySetValue(__CFStandardUserPreferences, appName, appPreferences);
        __CFUnlock(&__CFApplicationPreferencesLock);
        _CFApplicationPreferencesSetStandardSearchList(appPreferences);
    } else {
        __CFUnlock(&__CFApplicationPreferencesLock);
    }
    return appPreferences;
}
// 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();
    __CFLock(&__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) CFAllocatorDeallocate(alloc, prefsArray);
    }
    __CFUnlock(&__CFApplicationPreferencesLock);
}
static void getXMLKeysAndValues(CFAllocatorRef alloc, CFTypeRef context, void *xmlDomain, void **buf[], CFIndex *numKeyValuePairs) {
    _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain;
    CFIndex count;
    __CFLock(&domain->_lock);
    if (!domain->_domainDict) {
        _loadXMLDomainIfStale((CFURLRef )context, domain);
    }
    count = CFDictionaryGetCount(domain->_domainDict);
    if (buf) {
        void **values;
        if (count <= *numKeyValuePairs) {
            values = *buf + count;
            CFDictionaryGetKeysAndValues(domain->_domainDict, (const void **)*buf, (const void **)values);
        } else if (alloc != kCFAllocatorNull) {
	    *buf = (void**) CFAllocatorReallocate(alloc, (*buf ? *buf : NULL), count * 2 * sizeof(void *), 0);
            if (*buf) {
                values = *buf + count;
                CFDictionaryGetKeysAndValues(domain->_domainDict, (const void **)*buf, (const void **)values);
            }
        }
    }
    *numKeyValuePairs = count;
    __CFUnlock(&domain->_lock);
}
CF_PRIVATE 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
    __CFLock(&domainCacheLock);
    if (!domainCache) {
        __CFUnlock(&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);
    __CFUnlock(&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;
}