2 * Copyright (c) 2015 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@
24 /* CFApplicationPreferences.c
25 Copyright (c) 1998-2014, Apple Inc. All rights reserved.
26 Responsibility: David Smith
29 #include <CoreFoundation/CFPreferences.h>
30 #include "CFInternal.h"
31 #include <CoreFoundation/CFUniChar.h>
32 #include <CoreFoundation/CFNumber.h>
33 #include <CoreFoundation/CFString.h>
34 #include <CoreFoundation/CFLocale.h>
35 #include <CoreFoundation/CFNumberFormatter.h>
36 #include <CoreFoundation/CFDateFormatter.h>
37 #include <sys/types.h>
38 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
42 static Boolean
_CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferences
*self
);
43 void _CFPreferencesDomainSetMultiple(CFPreferencesDomainRef domain
, CFDictionaryRef dict
);
44 static void updateDictRep(_CFApplicationPreferences
*self
);
45 static void _CFApplicationPreferencesSetSearchList(_CFApplicationPreferences
*self
, CFArrayRef newSearchList
);
46 Boolean
_CFApplicationPreferencesContainsDomainNoLock(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
);
47 static CFTypeRef
_CFApplicationPreferencesCreateValueForKey2(_CFApplicationPreferences
*self
, CFStringRef defaultName
);
49 // 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
51 CFPropertyListRef
CFPreferencesCopyAppValue(CFStringRef key
, CFStringRef appName
) {
52 _CFApplicationPreferences
*standardPrefs
;
53 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
54 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
56 standardPrefs
= _CFStandardApplicationPreferences(appName
);
57 return standardPrefs
? _CFApplicationPreferencesCreateValueForKey2(standardPrefs
, key
) : NULL
;
60 CF_EXPORT Boolean
CFPreferencesAppBooleanValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
61 CFPropertyListRef value
;
62 Boolean result
, valid
;
64 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
65 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
67 if (!keyExistsAndHasValidFormat
) {
68 keyExistsAndHasValidFormat
= &valid
;
70 value
= CFPreferencesCopyAppValue(key
, appName
);
72 *keyExistsAndHasValidFormat
= false;
75 typeID
= CFGetTypeID(value
);
76 if (typeID
== CFStringGetTypeID()) {
77 if (CFStringCompare((CFStringRef
)value
, CFSTR("true"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
|| CFStringCompare((CFStringRef
)value
, CFSTR("YES"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
78 *keyExistsAndHasValidFormat
= true;
80 } else if (CFStringCompare((CFStringRef
)value
, CFSTR("false"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
|| CFStringCompare((CFStringRef
)value
, CFSTR("NO"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
81 *keyExistsAndHasValidFormat
= true;
84 *keyExistsAndHasValidFormat
= false;
87 } else if (typeID
== CFNumberGetTypeID()) {
88 if (CFNumberIsFloatType((CFNumberRef
)value
)) {
89 *keyExistsAndHasValidFormat
= false;
93 *keyExistsAndHasValidFormat
= true;
94 CFNumberGetValue((CFNumberRef
)value
, kCFNumberIntType
, &i
);
95 result
= (i
== 0) ? false : true;
97 } else if (typeID
== CFBooleanGetTypeID()) {
98 result
= (value
== kCFBooleanTrue
);
99 *keyExistsAndHasValidFormat
= true;
103 *keyExistsAndHasValidFormat
= false;
109 CF_PRIVATE CFIndex
CFPreferencesAppIntegerValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
110 CFPropertyListRef value
;
114 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
115 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
117 value
= CFPreferencesCopyAppValue(key
, appName
);
118 if (!keyExistsAndHasValidFormat
) {
119 keyExistsAndHasValidFormat
= &valid
;
122 *keyExistsAndHasValidFormat
= false;
125 typeID
= CFGetTypeID(value
);
126 if (typeID
== CFStringGetTypeID()) {
127 SInt32 charIndex
= 0;
129 CFStringInlineBuffer buf
;
131 CFStringInitInlineBuffer((CFStringRef
)value
, &buf
, CFRangeMake(0, CFStringGetLength((CFStringRef
)value
)));
132 success
= __CFStringScanInteger(&buf
, NULL
, &charIndex
, false, &intVal
);
133 *keyExistsAndHasValidFormat
= (success
&& charIndex
== CFStringGetLength((CFStringRef
)value
));
134 result
= (*keyExistsAndHasValidFormat
) ? intVal
: 0;
135 } else if (typeID
== CFNumberGetTypeID()) {
136 *keyExistsAndHasValidFormat
= !CFNumberIsFloatType((CFNumberRef
)value
);
137 if (*keyExistsAndHasValidFormat
) {
138 CFNumberGetValue((CFNumberRef
)value
, kCFNumberCFIndexType
, &result
);
145 *keyExistsAndHasValidFormat
= false;
151 Boolean
CFPreferencesGetAppBooleanValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
152 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
153 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
154 return CFPreferencesAppBooleanValue(key
, appName
, keyExistsAndHasValidFormat
);
157 CFIndex
CFPreferencesGetAppIntegerValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
158 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
159 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
160 return CFPreferencesAppIntegerValue(key
, appName
, keyExistsAndHasValidFormat
);
163 void CFPreferencesSetAppValue(CFStringRef key
, CFTypeRef value
, CFStringRef appName
) {
164 _CFApplicationPreferences
*standardPrefs
;
165 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
166 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
168 standardPrefs
= _CFStandardApplicationPreferences(appName
);
170 if (value
) _CFApplicationPreferencesSet(standardPrefs
, key
, value
);
171 else _CFApplicationPreferencesRemove(standardPrefs
, key
);
176 static CFLock_t __CFApplicationPreferencesLock
= CFLockInit
; // Locks access to __CFStandardUserPreferences
177 static CFMutableDictionaryRef __CFStandardUserPreferences
= NULL
; // Mutable dictionary; keys are app names, values are _CFApplicationPreferences
179 Boolean
CFPreferencesAppSynchronize(CFStringRef appName
) {
180 _CFApplicationPreferences
*standardPrefs
;
182 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
184 // Do not call _CFStandardApplicationPreferences(), as we do not want to create the preferences only to synchronize
185 __CFLock(&__CFApplicationPreferencesLock
);
186 if (__CFStandardUserPreferences
) {
187 standardPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
);
189 standardPrefs
= NULL
;
192 result
= standardPrefs
? _CFApplicationPreferencesSynchronizeNoLock(standardPrefs
) : _CFSynchronizeDomainCache();
193 __CFUnlock(&__CFApplicationPreferencesLock
);
197 void CFPreferencesFlushCaches(void) {
198 CFAllocatorRef alloc
= __CFPreferencesAllocator();
199 __CFLock(&__CFApplicationPreferencesLock
);
200 if (__CFStandardUserPreferences
) {
201 _CFApplicationPreferences
**prefsArray
, *prefsBuf
[32];
202 CFIndex idx
, count
= CFDictionaryGetCount(__CFStandardUserPreferences
);
204 prefsArray
= prefsBuf
;
206 prefsArray
= (_CFApplicationPreferences
**)CFAllocatorAllocate(alloc
, count
* sizeof(_CFApplicationPreferences
*), 0);
208 CFDictionaryGetKeysAndValues(__CFStandardUserPreferences
, NULL
, (const void **)prefsArray
);
210 __CFUnlock(&__CFApplicationPreferencesLock
);
211 // DeallocateApplicationPreferences needs the lock
212 for (idx
= 0; idx
< count
; idx
++) {
213 _CFApplicationPreferences
*appPrefs
= prefsArray
[idx
];
214 _CFApplicationPreferencesSynchronize(appPrefs
);
215 _CFDeallocateApplicationPreferences(appPrefs
);
217 __CFLock(&__CFApplicationPreferencesLock
);
219 CFRelease(__CFStandardUserPreferences
);
220 __CFStandardUserPreferences
= NULL
;
221 if(prefsArray
!= prefsBuf
) CFAllocatorDeallocate(alloc
, prefsArray
);
223 __CFUnlock(&__CFApplicationPreferencesLock
);
224 _CFPreferencesPurgeDomainCache();
227 // quick message to indicate that the given domain has changed, and we should go through and invalidate any dictReps that involve this domain.
228 void _CFApplicationPreferencesDomainHasChanged(CFPreferencesDomainRef changedDomain
) {
229 CFAllocatorRef alloc
= __CFPreferencesAllocator();
230 __CFLock(&__CFApplicationPreferencesLock
);
231 if(__CFStandardUserPreferences
) { // only grovel over the prefs if there's something there to grovel
232 _CFApplicationPreferences
**prefsArray
, *prefsBuf
[32];
233 CFIndex idx
, count
= CFDictionaryGetCount(__CFStandardUserPreferences
);
235 prefsArray
= prefsBuf
;
237 prefsArray
= (_CFApplicationPreferences
**)CFAllocatorAllocate(alloc
, count
* sizeof(_CFApplicationPreferences
*), 0);
239 CFDictionaryGetKeysAndValues(__CFStandardUserPreferences
, NULL
, (const void **)prefsArray
);
240 // For this operation, giving up the lock is the last thing we want to do, so use the modified flavor of _CFApplicationPreferencesContainsDomain
241 for(idx
= 0; idx
< count
; idx
++) {
242 _CFApplicationPreferences
*appPrefs
= prefsArray
[idx
];
243 if(_CFApplicationPreferencesContainsDomainNoLock(appPrefs
, changedDomain
)) {
244 updateDictRep(appPrefs
);
247 if(prefsArray
!= prefsBuf
) _CFAllocatorDeallocateGC(alloc
, prefsArray
);
249 __CFUnlock(&__CFApplicationPreferencesLock
);
253 // Begin ported code from NSUserDefaults.m
256 static void updateDictRep(_CFApplicationPreferences
*self
) {
257 if (self
->_dictRep
) {
258 CFRelease(self
->_dictRep
);
259 self
->_dictRep
= NULL
;
263 static void __addKeysAndValues(const void *key
, const void *value
, void *context
) {
264 CFDictionarySetValue((CFMutableDictionaryRef
)context
, key
, value
);
267 static CFMutableDictionaryRef
computeDictRep(_CFApplicationPreferences
*self
, Boolean skipC0C0A
) {
268 CFAllocatorRef alloc
= __CFPreferencesAllocator();
269 CFMutableArrayRef searchList
= self
->_search
;
271 CFIndex cnt
= CFArrayGetCount(searchList
);
272 CFDictionaryRef subdomainDict
;
273 CFMutableDictionaryRef dictRep
;
275 dictRep
= CFDictionaryCreateMutable(alloc
, 0, &kCFTypeDictionaryKeyCallBacks
, & kCFTypeDictionaryValueCallBacks
);
276 _CFDictionarySetCapacity(dictRep
, 260); // avoid lots of rehashing
278 // For each subdomain triplet in the domain, iterate over dictionaries, adding them if necessary to the dictRep
279 for (idx
= cnt
; idx
--;) {
280 CFPreferencesDomainRef domain
= (CFPreferencesDomainRef
)CFArrayGetValueAtIndex(searchList
, idx
);
282 if (!domain
) continue;
284 subdomainDict
= _CFPreferencesDomainDeepCopyDictionary(domain
);
286 CFDictionaryApplyFunction(subdomainDict
, __addKeysAndValues
, dictRep
);
287 CFRelease(subdomainDict
);
293 CFTypeRef
_CFApplicationPreferencesSearchDownToDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef stopper
, CFStringRef key
) {
298 void _CFApplicationPreferencesUpdate(_CFApplicationPreferences
*self
) {
299 __CFLock(&__CFApplicationPreferencesLock
);
301 __CFUnlock(&__CFApplicationPreferencesLock
);
304 CF_EXPORT CFDictionaryRef
_CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences
*self
);
306 CF_PRIVATE CFDictionaryRef
__CFApplicationPreferencesCopyCurrentState(void) {
307 _CFApplicationPreferences
*self
= _CFStandardApplicationPreferences(kCFPreferencesCurrentApplication
);
308 CFDictionaryRef result
= _CFApplicationPreferencesCopyRepresentation(self
);
312 // CACHING here - we will only return a value as current as the last time computeDictRep() was called
313 static CFTypeRef
_CFApplicationPreferencesCreateValueForKey2(_CFApplicationPreferences
*self
, CFStringRef defaultName
) {
315 __CFLock(&__CFApplicationPreferencesLock
);
316 if (!self
->_dictRep
) {
317 self
->_dictRep
= computeDictRep(self
, true);
319 result
= (self
->_dictRep
) ? (CFTypeRef
)CFDictionaryGetValue(self
->_dictRep
, defaultName
) : NULL
;
323 __CFUnlock(&__CFApplicationPreferencesLock
);
328 void _CFApplicationPreferencesSet(_CFApplicationPreferences
*self
, CFStringRef defaultName
, CFTypeRef value
) {
329 CFPreferencesDomainRef applicationDomain
;
331 __CFLock(&__CFApplicationPreferencesLock
);
332 applicationDomain
= _CFPreferencesStandardDomain(self
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
333 if(applicationDomain
) {
334 _CFPreferencesDomainSet(applicationDomain
, defaultName
, value
);
335 if (CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), applicationDomain
)) {
336 // Expensive; can't we just check the relevant value throughout the appropriate sets of domains? -- REW, 7/19/99
340 __CFUnlock(&__CFApplicationPreferencesLock
);
343 void _CFApplicationPreferencesRemove(_CFApplicationPreferences
*self
, CFStringRef defaultName
) {
344 CFPreferencesDomainRef appDomain
;
346 __CFLock(&__CFApplicationPreferencesLock
);
347 appDomain
= _CFPreferencesStandardDomain(self
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
349 _CFPreferencesDomainSet(appDomain
, defaultName
, NULL
);
350 if (CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), appDomain
)) {
351 // If key exists, it will be in the _dictRep (but possibly overridden)
355 __CFUnlock(&__CFApplicationPreferencesLock
);
358 static Boolean
_CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferences
*self
) {
359 Boolean success
= _CFSynchronizeDomainCache();
364 Boolean
_CFApplicationPreferencesSynchronize(_CFApplicationPreferences
*self
) {
366 __CFLock(&__CFApplicationPreferencesLock
);
367 result
= _CFApplicationPreferencesSynchronizeNoLock(self
);
368 __CFUnlock(&__CFApplicationPreferencesLock
);
372 // appName should not be kCFPreferencesCurrentApplication going in to this call
373 _CFApplicationPreferences
*_CFApplicationPreferencesCreateWithUser(CFStringRef userName
, CFStringRef appName
) {
374 CFAllocatorRef alloc
= __CFPreferencesAllocator();
375 _CFApplicationPreferences
*self
= (_CFApplicationPreferences
*)CFAllocatorAllocate(alloc
, sizeof(_CFApplicationPreferences
), 0);
377 self
->_dictRep
= NULL
;
378 self
->_appName
= (CFStringRef
)CFRetain(appName
);
379 self
->_search
= CFArrayCreateMutable(alloc
, 0, &kCFTypeArrayCallBacks
);
380 if (!self
->_search
) {
381 CFAllocatorDeallocate(alloc
, self
);
389 // Do NOT release the domain after adding it to the array; domain_expression should not return a retained object -- REW, 8/26/99
390 #define ADD_DOMAIN(domain_expression) domain = domain_expression; if (domain) {CFArrayAppendValue(search, domain);}
391 void _CFApplicationPreferencesSetStandardSearchList(_CFApplicationPreferences
*appPreferences
) {
392 /* Here is how the domains end up in priority order in a search list. Only a subset of these are setup by default.
394 this app, this user, managed
395 this app, any user, managed
396 this app, this user, this host
397 this app, this user, any host (AppDomain)
398 suiteN, this user, this host
399 suiteN, this user, any host
401 suite0, this user, this host
402 suite0, this user, any host
403 any app, this user, this host
404 any app, this user, any host (GlobalDomain)
405 NSUserDefaults backwards-compat ICU domain
406 this app, any user, this host
407 this app, any user, any host
408 suiteN, any user, this host
409 suiteN, any user, any host
411 suite0, any user, this host
412 suite0, any user, any host
413 any app, any user, this host
414 any app, any user, any host
417 CFPreferencesDomainRef domain
;
418 CFMutableArrayRef search
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
420 // couldn't allocate memory!
424 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
));
425 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
));
426 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
));
427 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
));
428 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
));
429 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
));
430 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
));
431 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
));
433 _CFApplicationPreferencesSetSearchList(appPreferences
, search
);
439 CF_PRIVATE _CFApplicationPreferences
*_CFStandardApplicationPreferences(CFStringRef appName
) {
440 _CFApplicationPreferences
*appPreferences
;
441 // CFAssert(appName != kCFPreferencesAnyApplication, __kCFLogAssertion, "Cannot use any of the CFPreferences...App... functions with an appName of kCFPreferencesAnyApplication");
442 __CFLock(&__CFApplicationPreferencesLock
);
443 if (!__CFStandardUserPreferences
) {
444 __CFStandardUserPreferences
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, & kCFTypeDictionaryKeyCallBacks
, NULL
);
446 if (!__CFStandardUserPreferences
) {
448 __CFUnlock(&__CFApplicationPreferencesLock
);
451 if ((appPreferences
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
)) == NULL
) {
452 appPreferences
= _CFApplicationPreferencesCreateWithUser(kCFPreferencesCurrentUser
, appName
);
453 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPreferences
);
454 __CFUnlock(&__CFApplicationPreferencesLock
);
455 _CFApplicationPreferencesSetStandardSearchList(appPreferences
);
457 __CFUnlock(&__CFApplicationPreferencesLock
);
459 return appPreferences
;
462 // Exclusively for Foundation's use
463 void _CFApplicationPreferencesSetCacheForApp(_CFApplicationPreferences
*appPrefs
, CFStringRef appName
) {
464 __CFLock(&__CFApplicationPreferencesLock
);
465 if (!__CFStandardUserPreferences
) {
466 __CFStandardUserPreferences
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, NULL
);
467 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPrefs
);
468 __CFUnlock(&__CFApplicationPreferencesLock
);
470 _CFApplicationPreferences
*oldPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
);
471 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPrefs
);
472 __CFUnlock(&__CFApplicationPreferencesLock
);
474 _CFDeallocateApplicationPreferences(oldPrefs
);
480 void _CFDeallocateApplicationPreferences(_CFApplicationPreferences
*self
) {
481 CFAllocatorRef alloc
= __CFPreferencesAllocator();
482 _CFApplicationPreferences
*cachedPrefs
= NULL
;
483 __CFLock(&__CFApplicationPreferencesLock
);
485 // Get us out of the cache before destroying!
486 if (__CFStandardUserPreferences
) {
487 cachedPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, self
->_appName
);
489 if (cachedPrefs
== self
) {
490 CFDictionaryRemoveValue(__CFStandardUserPreferences
, self
->_appName
);
493 if (self
->_dictRep
) CFRelease(self
->_dictRep
);
494 CFRelease(self
->_search
);
495 CFRelease(self
->_appName
);
496 CFAllocatorDeallocate(alloc
, self
);
497 __CFUnlock(&__CFApplicationPreferencesLock
);
502 CFDictionaryRef
_CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences
*self
) {
503 CFDictionaryRef dict
;
504 __CFLock(&__CFApplicationPreferencesLock
);
505 if (!self
->_dictRep
) {
506 self
->_dictRep
= computeDictRep(self
, true);
508 if (self
->_dictRep
) {
509 CFRetain(self
->_dictRep
);
511 dict
= self
->_dictRep
;
512 __CFUnlock(&__CFApplicationPreferencesLock
);
516 static void _CFApplicationPreferencesSetSearchList(_CFApplicationPreferences
*self
, CFArrayRef newSearchList
) {
518 __CFLock(&__CFApplicationPreferencesLock
);
519 CFArrayRemoveAllValues(self
->_search
);
520 count
= CFArrayGetCount(newSearchList
);
521 for (idx
= 0; idx
< count
; idx
++) {
522 CFArrayAppendValue(self
->_search
, CFArrayGetValueAtIndex(newSearchList
, idx
));
525 __CFUnlock(&__CFApplicationPreferencesLock
);
528 void CFPreferencesAddSuitePreferencesToApp(CFStringRef appName
, CFStringRef suiteName
) {
529 _CFApplicationPreferences
*appPrefs
;
531 appPrefs
= _CFStandardApplicationPreferences(appName
);
532 _CFApplicationPreferencesAddSuitePreferences(appPrefs
, suiteName
);
535 void _CFApplicationPreferencesAddSuitePreferences(_CFApplicationPreferences
*appPrefs
, CFStringRef suiteName
) {
536 CFPreferencesDomainRef domain
;
540 // Find where to insert the new suite
541 __CFLock(&__CFApplicationPreferencesLock
);
542 domain
= _CFPreferencesStandardDomain(appPrefs
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
544 range
.length
= CFArrayGetCount(appPrefs
->_search
);
545 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
546 __CFUnlock(&__CFApplicationPreferencesLock
);
547 idx
++; // We want just below the app domain. Coincidentally, this gives us the top of the list if the app domain has been removed.
548 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
550 __CFLock(&__CFApplicationPreferencesLock
);
551 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
552 __CFUnlock(&__CFApplicationPreferencesLock
);
555 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
557 __CFLock(&__CFApplicationPreferencesLock
);
558 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
559 __CFUnlock(&__CFApplicationPreferencesLock
);
563 // Now the AnyUser domains
564 domain
= _CFPreferencesStandardDomain(appPrefs
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
565 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
566 if (idx
== kCFNotFound
) {
567 // Someone blew away the app domain. For the any user case, we look for right below the global domain
568 domain
= _CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
569 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
570 if (idx
== kCFNotFound
) {
571 // Try the "any host" choice
572 domain
= _CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
573 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
574 if (idx
== kCFNotFound
) {
575 // We give up; put the new domains at the bottom
576 idx
= CFArrayGetCount(appPrefs
->_search
) - 1;
581 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
583 __CFLock(&__CFApplicationPreferencesLock
);
584 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
585 __CFUnlock(&__CFApplicationPreferencesLock
);
587 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
);
589 __CFLock(&__CFApplicationPreferencesLock
);
590 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
591 __CFUnlock(&__CFApplicationPreferencesLock
);
593 __CFLock(&__CFApplicationPreferencesLock
);
594 updateDictRep(appPrefs
);
595 __CFUnlock(&__CFApplicationPreferencesLock
);
598 void CFPreferencesRemoveSuitePreferencesFromApp(CFStringRef appName
, CFStringRef suiteName
) {
599 _CFApplicationPreferences
*appPrefs
;
601 appPrefs
= _CFStandardApplicationPreferences(appName
);
603 _CFApplicationPreferencesRemoveSuitePreferences(appPrefs
, suiteName
);
606 void _CFApplicationPreferencesRemoveSuitePreferences(_CFApplicationPreferences
*appPrefs
, CFStringRef suiteName
) {
607 CFPreferencesDomainRef domain
;
609 __CFLock(&__CFApplicationPreferencesLock
);
610 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
611 __CFUnlock(&__CFApplicationPreferencesLock
);
612 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
614 __CFLock(&__CFApplicationPreferencesLock
);
615 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
616 __CFUnlock(&__CFApplicationPreferencesLock
);
617 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
619 __CFLock(&__CFApplicationPreferencesLock
);
620 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
621 __CFUnlock(&__CFApplicationPreferencesLock
);
622 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
624 __CFLock(&__CFApplicationPreferencesLock
);
625 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
);
626 __CFUnlock(&__CFApplicationPreferencesLock
);
627 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
630 void _CFApplicationPreferencesAddDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
, Boolean addAtTop
) {
631 __CFLock(&__CFApplicationPreferencesLock
);
633 CFArrayInsertValueAtIndex(self
->_search
, 0, domain
);
635 CFArrayAppendValue(self
->_search
, domain
);
638 __CFUnlock(&__CFApplicationPreferencesLock
);
641 Boolean
_CFApplicationPreferencesContainsDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
648 __CFLock(&__CFApplicationPreferencesLock
);
649 result
= CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), domain
);
650 __CFUnlock(&__CFApplicationPreferencesLock
);
654 Boolean
_CFApplicationPreferencesContainsDomainNoLock(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
656 result
= CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), domain
);
660 void _CFApplicationPreferencesRemoveDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
663 __CFLock(&__CFApplicationPreferencesLock
);
665 range
.length
= CFArrayGetCount(self
->_search
);
666 while ((idx
= CFArrayGetFirstIndexOfValue(self
->_search
, range
, domain
)) != kCFNotFound
) {
667 CFArrayRemoveValueAtIndex(self
->_search
, idx
);
668 range
.location
= idx
;
669 range
.length
= range
.length
- idx
- 1;
672 __CFUnlock(&__CFApplicationPreferencesLock
);