2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 /* CFApplicationPreferences.c
24 Copyright 1998-2002, Apple, Inc. All rights reserved.
25 Responsibility: Chris Parker
28 #include <CoreFoundation/CFPreferences.h>
29 #include "CFInternal.h"
30 #include <CoreFoundation/CFUniChar.h>
31 #include <CoreFoundation/CFNumber.h>
32 #include <CoreFoundation/CFString.h>
33 #include <CoreFoundation/CFLocale.h>
34 #include <CoreFoundation/CFNumberFormatter.h>
35 #include <CoreFoundation/CFDateFormatter.h>
36 #include <sys/types.h>
41 static Boolean
_CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferences
*self
);
42 void _CFPreferencesDomainSetMultiple(CFPreferencesDomainRef domain
, CFDictionaryRef dict
);
43 static void updateDictRep(_CFApplicationPreferences
*self
);
44 static void _CFApplicationPreferencesSetSearchList(_CFApplicationPreferences
*self
, CFArrayRef newSearchList
);
45 Boolean
_CFApplicationPreferencesContainsDomainNoLock(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
);
46 static CFTypeRef
_CFApplicationPreferencesCreateValueForKey2(_CFApplicationPreferences
*self
, CFStringRef defaultName
);
48 // Right now, nothing is getting destroyed pretty much ever. We probably don't want this to be the case, but it's very tricky - domains live in the cache as well as a given application's preferences, and since they're not CFTypes, there's no reference count. Also, it's not clear we ever want domains destroyed. When they're synchronized, they clear their internal state (to force reading from the disk again), so they're not very big.... REW, 12/17/98
50 CFPropertyListRef
CFPreferencesCopyAppValue(CFStringRef key
, CFStringRef appName
) {
51 _CFApplicationPreferences
*standardPrefs
;
52 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
53 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
55 standardPrefs
= _CFStandardApplicationPreferences(appName
);
56 return standardPrefs
? _CFApplicationPreferencesCreateValueForKey2(standardPrefs
, key
) : NULL
;
59 CF_EXPORT Boolean
CFPreferencesAppBooleanValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
60 CFPropertyListRef value
;
61 Boolean result
, valid
;
63 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
64 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
66 if (!keyExistsAndHasValidFormat
) {
67 keyExistsAndHasValidFormat
= &valid
;
69 value
= CFPreferencesCopyAppValue(key
, appName
);
71 *keyExistsAndHasValidFormat
= false;
74 typeID
= CFGetTypeID(value
);
75 if (typeID
== CFStringGetTypeID()) {
76 if (CFStringCompare((CFStringRef
)value
, CFSTR("true"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
|| CFStringCompare((CFStringRef
)value
, CFSTR("YES"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
77 *keyExistsAndHasValidFormat
= true;
79 } else if (CFStringCompare((CFStringRef
)value
, CFSTR("false"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
|| CFStringCompare((CFStringRef
)value
, CFSTR("NO"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
80 *keyExistsAndHasValidFormat
= true;
83 *keyExistsAndHasValidFormat
= false;
86 } else if (typeID
== CFNumberGetTypeID()) {
87 if (CFNumberIsFloatType((CFNumberRef
)value
)) {
88 *keyExistsAndHasValidFormat
= false;
92 *keyExistsAndHasValidFormat
= true;
93 CFNumberGetValue((CFNumberRef
)value
, kCFNumberIntType
, &i
);
94 result
= (i
== 0) ? false : true;
96 } else if (typeID
== CFBooleanGetTypeID()) {
97 result
= (value
== kCFBooleanTrue
);
98 *keyExistsAndHasValidFormat
= true;
102 *keyExistsAndHasValidFormat
= false;
108 __private_extern__ CFIndex
CFPreferencesAppIntegerValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
109 CFPropertyListRef value
;
113 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
114 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
116 value
= CFPreferencesCopyAppValue(key
, appName
);
117 if (!keyExistsAndHasValidFormat
) {
118 keyExistsAndHasValidFormat
= &valid
;
121 *keyExistsAndHasValidFormat
= false;
124 typeID
= CFGetTypeID(value
);
125 if (typeID
== CFStringGetTypeID()) {
126 SInt32 charIndex
= 0;
128 CFStringInlineBuffer buf
;
130 CFStringInitInlineBuffer((CFStringRef
)value
, &buf
, CFRangeMake(0, CFStringGetLength((CFStringRef
)value
)));
131 success
= __CFStringScanInteger(&buf
, NULL
, &charIndex
, false, &intVal
);
132 *keyExistsAndHasValidFormat
= (success
&& charIndex
== CFStringGetLength((CFStringRef
)value
));
133 result
= (*keyExistsAndHasValidFormat
) ? intVal
: 0;
134 } else if (typeID
== CFNumberGetTypeID()) {
135 *keyExistsAndHasValidFormat
= !CFNumberIsFloatType((CFNumberRef
)value
);
136 if (*keyExistsAndHasValidFormat
) {
137 CFNumberGetValue((CFNumberRef
)value
, kCFNumberCFIndexType
, &result
);
144 *keyExistsAndHasValidFormat
= false;
150 Boolean
CFPreferencesGetAppBooleanValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
151 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
152 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
153 return CFPreferencesAppBooleanValue(key
, appName
, keyExistsAndHasValidFormat
);
156 CFIndex
CFPreferencesGetAppIntegerValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
157 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
158 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
159 return CFPreferencesAppIntegerValue(key
, appName
, keyExistsAndHasValidFormat
);
162 void CFPreferencesSetAppValue(CFStringRef key
, CFTypeRef value
, CFStringRef appName
) {
163 _CFApplicationPreferences
*standardPrefs
;
164 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
165 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
167 standardPrefs
= _CFStandardApplicationPreferences(appName
);
169 if (value
) _CFApplicationPreferencesSet(standardPrefs
, key
, value
);
170 else _CFApplicationPreferencesRemove(standardPrefs
, key
);
175 static CFSpinLock_t __CFApplicationPreferencesLock
= CFSpinLockInit
; // Locks access to __CFStandardUserPreferences
176 static CFMutableDictionaryRef __CFStandardUserPreferences
= NULL
; // Mutable dictionary; keys are app names, values are _CFApplicationPreferences
178 Boolean
CFPreferencesAppSynchronize(CFStringRef appName
) {
179 _CFApplicationPreferences
*standardPrefs
;
181 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
183 // Do not call _CFStandardApplicationPreferences(), as we do not want to create the preferences only to synchronize
184 __CFSpinLock(&__CFApplicationPreferencesLock
);
185 if (__CFStandardUserPreferences
) {
186 standardPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
);
188 standardPrefs
= NULL
;
191 result
= standardPrefs
? _CFApplicationPreferencesSynchronizeNoLock(standardPrefs
) : _CFSynchronizeDomainCache();
192 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
196 void CFPreferencesFlushCaches(void) {
197 CFAllocatorRef alloc
= __CFPreferencesAllocator();
198 __CFSpinLock(&__CFApplicationPreferencesLock
);
199 if (__CFStandardUserPreferences
) {
200 _CFApplicationPreferences
**prefsArray
, *prefsBuf
[32];
201 CFIndex idx
, count
= CFDictionaryGetCount(__CFStandardUserPreferences
);
203 prefsArray
= prefsBuf
;
205 prefsArray
= (_CFApplicationPreferences
**)CFAllocatorAllocate(alloc
, count
* sizeof(_CFApplicationPreferences
*), 0);
207 CFDictionaryGetKeysAndValues(__CFStandardUserPreferences
, NULL
, (const void **)prefsArray
);
209 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
210 // DeallocateApplicationPreferences needs the lock
211 for (idx
= 0; idx
< count
; idx
++) {
212 _CFApplicationPreferences
*appPrefs
= prefsArray
[idx
];
213 _CFApplicationPreferencesSynchronize(appPrefs
);
214 _CFDeallocateApplicationPreferences(appPrefs
);
216 __CFSpinLock(&__CFApplicationPreferencesLock
);
218 CFRelease(__CFStandardUserPreferences
);
219 __CFStandardUserPreferences
= NULL
;
220 if(prefsArray
!= prefsBuf
) CFAllocatorDeallocate(alloc
, prefsArray
);
222 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
223 _CFPreferencesPurgeDomainCache();
226 // quick message to indicate that the given domain has changed, and we should go through and invalidate any dictReps that involve this domain.
227 void _CFApplicationPreferencesDomainHasChanged(CFPreferencesDomainRef changedDomain
) {
228 CFAllocatorRef alloc
= __CFPreferencesAllocator();
229 __CFSpinLock(&__CFApplicationPreferencesLock
);
230 if(__CFStandardUserPreferences
) { // only grovel over the prefs if there's something there to grovel
231 _CFApplicationPreferences
**prefsArray
, *prefsBuf
[32];
232 CFIndex idx
, count
= CFDictionaryGetCount(__CFStandardUserPreferences
);
234 prefsArray
= prefsBuf
;
236 prefsArray
= (_CFApplicationPreferences
**)CFAllocatorAllocate(alloc
, count
* sizeof(_CFApplicationPreferences
*), 0);
238 CFDictionaryGetKeysAndValues(__CFStandardUserPreferences
, NULL
, (const void **)prefsArray
);
239 // For this operation, giving up the lock is the last thing we want to do, so use the modified flavor of _CFApplicationPreferencesContainsDomain
240 for(idx
= 0; idx
< count
; idx
++) {
241 _CFApplicationPreferences
*appPrefs
= prefsArray
[idx
];
242 if(_CFApplicationPreferencesContainsDomainNoLock(appPrefs
, changedDomain
)) {
243 updateDictRep(appPrefs
);
246 if(prefsArray
!= prefsBuf
) _CFAllocatorDeallocateGC(alloc
, prefsArray
);
248 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
252 // Begin ported code from NSUserDefaults.m
255 static void updateDictRep(_CFApplicationPreferences
*self
) {
256 if (self
->_dictRep
) {
257 CFRelease(self
->_dictRep
);
258 self
->_dictRep
= NULL
;
262 static void __addKeysAndValues(const void *key
, const void *value
, void *context
) {
263 CFDictionarySetValue((CFMutableDictionaryRef
)context
, key
, value
);
266 static CFMutableDictionaryRef
computeDictRep(_CFApplicationPreferences
*self
, Boolean skipC0C0A
) {
267 CFAllocatorRef alloc
= __CFPreferencesAllocator();
268 CFMutableArrayRef searchList
= self
->_search
;
270 CFIndex cnt
= CFArrayGetCount(searchList
);
271 CFDictionaryRef subdomainDict
;
272 CFMutableDictionaryRef dictRep
;
274 dictRep
= CFDictionaryCreateMutable(alloc
, 0, &kCFTypeDictionaryKeyCallBacks
, & kCFTypeDictionaryValueCallBacks
);
275 _CFDictionarySetCapacity(dictRep
, 260); // avoid lots of rehashing
277 // For each subdomain triplet in the domain, iterate over dictionaries, adding them if necessary to the dictRep
278 for (idx
= cnt
; idx
--;) {
279 CFPreferencesDomainRef domain
= (CFPreferencesDomainRef
)CFArrayGetValueAtIndex(searchList
, idx
);
281 if (!domain
) continue;
283 subdomainDict
= _CFPreferencesDomainDeepCopyDictionary(domain
);
285 CFDictionaryApplyFunction(subdomainDict
, __addKeysAndValues
, dictRep
);
286 CFRelease(subdomainDict
);
292 CFTypeRef
_CFApplicationPreferencesSearchDownToDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef stopper
, CFStringRef key
) {
297 void _CFApplicationPreferencesUpdate(_CFApplicationPreferences
*self
) {
298 __CFSpinLock(&__CFApplicationPreferencesLock
);
300 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
303 CF_EXPORT CFDictionaryRef
_CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences
*self
);
305 __private_extern__ CFDictionaryRef
__CFApplicationPreferencesCopyCurrentState(void) {
306 _CFApplicationPreferences
*self
= _CFStandardApplicationPreferences(kCFPreferencesCurrentApplication
);
307 CFDictionaryRef result
= _CFApplicationPreferencesCopyRepresentation(self
);
311 // CACHING here - we will only return a value as current as the last time computeDictRep() was called
312 static CFTypeRef
_CFApplicationPreferencesCreateValueForKey2(_CFApplicationPreferences
*self
, CFStringRef defaultName
) {
314 __CFSpinLock(&__CFApplicationPreferencesLock
);
315 if (!self
->_dictRep
) {
316 self
->_dictRep
= computeDictRep(self
, true);
318 result
= (self
->_dictRep
) ? (CFTypeRef
)CFDictionaryGetValue(self
->_dictRep
, defaultName
) : NULL
;
322 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
327 void _CFApplicationPreferencesSet(_CFApplicationPreferences
*self
, CFStringRef defaultName
, CFTypeRef value
) {
328 CFPreferencesDomainRef applicationDomain
;
330 __CFSpinLock(&__CFApplicationPreferencesLock
);
331 applicationDomain
= _CFPreferencesStandardDomain(self
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
332 if(applicationDomain
) {
333 _CFPreferencesDomainSet(applicationDomain
, defaultName
, value
);
334 if (CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), applicationDomain
)) {
335 // Expensive; can't we just check the relevant value throughout the appropriate sets of domains? -- REW, 7/19/99
339 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
342 void _CFApplicationPreferencesRemove(_CFApplicationPreferences
*self
, CFStringRef defaultName
) {
343 CFPreferencesDomainRef appDomain
;
345 __CFSpinLock(&__CFApplicationPreferencesLock
);
346 appDomain
= _CFPreferencesStandardDomain(self
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
348 _CFPreferencesDomainSet(appDomain
, defaultName
, NULL
);
349 if (CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), appDomain
)) {
350 // If key exists, it will be in the _dictRep (but possibly overridden)
354 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
357 static Boolean
_CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferences
*self
) {
358 Boolean success
= _CFSynchronizeDomainCache();
363 Boolean
_CFApplicationPreferencesSynchronize(_CFApplicationPreferences
*self
) {
365 __CFSpinLock(&__CFApplicationPreferencesLock
);
366 result
= _CFApplicationPreferencesSynchronizeNoLock(self
);
367 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
371 // appName should not be kCFPreferencesCurrentApplication going in to this call
372 _CFApplicationPreferences
*_CFApplicationPreferencesCreateWithUser(CFStringRef userName
, CFStringRef appName
) {
373 CFAllocatorRef alloc
= __CFPreferencesAllocator();
374 _CFApplicationPreferences
*self
= (_CFApplicationPreferences
*)CFAllocatorAllocate(alloc
, sizeof(_CFApplicationPreferences
), 0);
376 self
->_dictRep
= NULL
;
377 self
->_appName
= (CFStringRef
)CFRetain(appName
);
378 self
->_search
= CFArrayCreateMutable(alloc
, 0, &kCFTypeArrayCallBacks
);
379 if (!self
->_search
) {
380 CFAllocatorDeallocate(alloc
, self
);
388 // Do NOT release the domain after adding it to the array; domain_expression should not return a retained object -- REW, 8/26/99
389 #define ADD_DOMAIN(domain_expression) domain = domain_expression; if (domain) {CFArrayAppendValue(search, domain);}
390 void _CFApplicationPreferencesSetStandardSearchList(_CFApplicationPreferences
*appPreferences
) {
391 /* Here is how the domains end up in priority order in a search list. Only a subset of these are setup by default.
393 this app, this user, managed
394 this app, any user, managed
395 this app, this user, this host
396 this app, this user, any host (AppDomain)
397 suiteN, this user, this host
398 suiteN, this user, any host
400 suite0, this user, this host
401 suite0, this user, any host
402 any app, this user, this host
403 any app, this user, any host (GlobalDomain)
404 NSUserDefaults backwards-compat ICU domain
405 this app, any user, this host
406 this app, any user, any host
407 suiteN, any user, this host
408 suiteN, any user, any host
410 suite0, any user, this host
411 suite0, any user, any host
412 any app, any user, this host
413 any app, any user, any host
416 CFPreferencesDomainRef domain
;
417 CFMutableArrayRef search
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
419 // couldn't allocate memory!
423 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
));
424 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
));
425 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
));
426 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
));
427 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
));
428 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
));
429 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
));
430 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
));
432 _CFApplicationPreferencesSetSearchList(appPreferences
, search
);
438 __private_extern__ _CFApplicationPreferences
*_CFStandardApplicationPreferences(CFStringRef appName
) {
439 _CFApplicationPreferences
*appPreferences
;
440 // CFAssert(appName != kCFPreferencesAnyApplication, __kCFLogAssertion, "Cannot use any of the CFPreferences...App... functions with an appName of kCFPreferencesAnyApplication");
441 __CFSpinLock(&__CFApplicationPreferencesLock
);
442 if (!__CFStandardUserPreferences
) {
443 __CFStandardUserPreferences
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, & kCFTypeDictionaryKeyCallBacks
, NULL
);
445 if (!__CFStandardUserPreferences
) {
447 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
450 if ((appPreferences
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
)) == NULL
) {
451 appPreferences
= _CFApplicationPreferencesCreateWithUser(kCFPreferencesCurrentUser
, appName
);
452 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPreferences
);
453 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
454 _CFApplicationPreferencesSetStandardSearchList(appPreferences
);
456 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
458 return appPreferences
;
461 // Exclusively for Foundation's use
462 void _CFApplicationPreferencesSetCacheForApp(_CFApplicationPreferences
*appPrefs
, CFStringRef appName
) {
463 __CFSpinLock(&__CFApplicationPreferencesLock
);
464 if (!__CFStandardUserPreferences
) {
465 __CFStandardUserPreferences
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, NULL
);
466 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPrefs
);
467 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
469 _CFApplicationPreferences
*oldPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
);
470 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPrefs
);
471 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
473 _CFDeallocateApplicationPreferences(oldPrefs
);
479 void _CFDeallocateApplicationPreferences(_CFApplicationPreferences
*self
) {
480 CFAllocatorRef alloc
= __CFPreferencesAllocator();
481 _CFApplicationPreferences
*cachedPrefs
= NULL
;
482 __CFSpinLock(&__CFApplicationPreferencesLock
);
484 // Get us out of the cache before destroying!
485 if (__CFStandardUserPreferences
) {
486 cachedPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, self
->_appName
);
488 if (cachedPrefs
== self
) {
489 CFDictionaryRemoveValue(__CFStandardUserPreferences
, self
->_appName
);
492 if (self
->_dictRep
) CFRelease(self
->_dictRep
);
493 CFRelease(self
->_search
);
494 CFRelease(self
->_appName
);
495 CFAllocatorDeallocate(alloc
, self
);
496 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
501 CFDictionaryRef
_CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences
*self
) {
502 CFDictionaryRef dict
;
503 __CFSpinLock(&__CFApplicationPreferencesLock
);
504 if (!self
->_dictRep
) {
505 self
->_dictRep
= computeDictRep(self
, true);
507 if (self
->_dictRep
) {
508 CFRetain(self
->_dictRep
);
510 dict
= self
->_dictRep
;
511 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
515 static void _CFApplicationPreferencesSetSearchList(_CFApplicationPreferences
*self
, CFArrayRef newSearchList
) {
517 __CFSpinLock(&__CFApplicationPreferencesLock
);
518 CFArrayRemoveAllValues(self
->_search
);
519 count
= CFArrayGetCount(newSearchList
);
520 for (idx
= 0; idx
< count
; idx
++) {
521 CFArrayAppendValue(self
->_search
, CFArrayGetValueAtIndex(newSearchList
, idx
));
524 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
527 void CFPreferencesAddSuitePreferencesToApp(CFStringRef appName
, CFStringRef suiteName
) {
528 _CFApplicationPreferences
*appPrefs
;
530 appPrefs
= _CFStandardApplicationPreferences(appName
);
531 _CFApplicationPreferencesAddSuitePreferences(appPrefs
, suiteName
);
534 void _CFApplicationPreferencesAddSuitePreferences(_CFApplicationPreferences
*appPrefs
, CFStringRef suiteName
) {
535 CFPreferencesDomainRef domain
;
539 // Find where to insert the new suite
540 __CFSpinLock(&__CFApplicationPreferencesLock
);
541 domain
= _CFPreferencesStandardDomain(appPrefs
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
543 range
.length
= CFArrayGetCount(appPrefs
->_search
);
544 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
545 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
546 idx
++; // We want just below the app domain. Coincidentally, this gives us the top of the list if the app domain has been removed.
547 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
549 __CFSpinLock(&__CFApplicationPreferencesLock
);
550 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
551 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
554 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
556 __CFSpinLock(&__CFApplicationPreferencesLock
);
557 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
558 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
562 // Now the AnyUser domains
563 domain
= _CFPreferencesStandardDomain(appPrefs
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
564 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
565 if (idx
== kCFNotFound
) {
566 // Someone blew away the app domain. For the any user case, we look for right below the global domain
567 domain
= _CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
568 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
569 if (idx
== kCFNotFound
) {
570 // Try the "any host" choice
571 domain
= _CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
572 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
573 if (idx
== kCFNotFound
) {
574 // We give up; put the new domains at the bottom
575 idx
= CFArrayGetCount(appPrefs
->_search
) - 1;
580 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
582 __CFSpinLock(&__CFApplicationPreferencesLock
);
583 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
584 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
586 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
);
588 __CFSpinLock(&__CFApplicationPreferencesLock
);
589 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
590 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
592 __CFSpinLock(&__CFApplicationPreferencesLock
);
593 updateDictRep(appPrefs
);
594 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
597 void CFPreferencesRemoveSuitePreferencesFromApp(CFStringRef appName
, CFStringRef suiteName
) {
598 _CFApplicationPreferences
*appPrefs
;
600 appPrefs
= _CFStandardApplicationPreferences(appName
);
602 _CFApplicationPreferencesRemoveSuitePreferences(appPrefs
, suiteName
);
605 void _CFApplicationPreferencesRemoveSuitePreferences(_CFApplicationPreferences
*appPrefs
, CFStringRef suiteName
) {
606 CFPreferencesDomainRef domain
;
608 __CFSpinLock(&__CFApplicationPreferencesLock
);
609 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
610 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
611 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
613 __CFSpinLock(&__CFApplicationPreferencesLock
);
614 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
615 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
616 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
618 __CFSpinLock(&__CFApplicationPreferencesLock
);
619 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
620 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
621 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
623 __CFSpinLock(&__CFApplicationPreferencesLock
);
624 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
);
625 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
626 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
629 void _CFApplicationPreferencesAddDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
, Boolean addAtTop
) {
630 __CFSpinLock(&__CFApplicationPreferencesLock
);
632 CFArrayInsertValueAtIndex(self
->_search
, 0, domain
);
634 CFArrayAppendValue(self
->_search
, domain
);
637 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
640 Boolean
_CFApplicationPreferencesContainsDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
647 __CFSpinLock(&__CFApplicationPreferencesLock
);
648 result
= CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), domain
);
649 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
653 Boolean
_CFApplicationPreferencesContainsDomainNoLock(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
655 result
= CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), domain
);
659 void _CFApplicationPreferencesRemoveDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
662 __CFSpinLock(&__CFApplicationPreferencesLock
);
664 range
.length
= CFArrayGetCount(self
->_search
);
665 while ((idx
= CFArrayGetFirstIndexOfValue(self
->_search
, range
, domain
)) != kCFNotFound
) {
666 CFArrayRemoveValueAtIndex(self
->_search
, idx
);
667 range
.location
= idx
;
668 range
.length
= range
.length
- idx
- 1;
671 __CFSpinUnlock(&__CFApplicationPreferencesLock
);