mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-15 10:23:57 +00:00
Start work to apply patch to hold user defaults in registry.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21840 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
9c58883697
commit
7a43bb1ba9
4 changed files with 693 additions and 121 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
2005-10-18 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source/NSUserDefaults.m: Begin applying registry patch.
|
||||||
|
* Source/win32/NSUserDefaultsWin32.m: Registry patch with
|
||||||
|
some work done towards conforming to gnustep coding standards.
|
||||||
|
|
||||||
2005-10-17 Richard Frith-Macdonald <rfm@gnu.org>
|
2005-10-17 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* SSL/GSSSLHandle.m: Don't output log/warning on accept/connect
|
* SSL/GSSSLHandle.m: Don't output log/warning on accept/connect
|
||||||
|
|
|
@ -56,6 +56,10 @@
|
||||||
#include "GNUstepBase/GSLocale.h"
|
#include "GNUstepBase/GSLocale.h"
|
||||||
#include "GNUstepBase/GSLock.h"
|
#include "GNUstepBase/GSLock.h"
|
||||||
|
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
@class NSUserDefaultsWin32;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LOCALE_H
|
#ifdef HAVE_LOCALE_H
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -455,7 +459,25 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
|
||||||
setSharedDefaults = YES;
|
setSharedDefaults = YES;
|
||||||
|
|
||||||
// Create new sharedDefaults (NOTE: Not added to the autorelease pool!)
|
// Create new sharedDefaults (NOTE: Not added to the autorelease pool!)
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
NSString *path = GSDefaultsRootForUser(NSUserName());
|
||||||
|
NSRange r = [path rangeOfString: @":REGISTRY:"];
|
||||||
|
|
||||||
|
if (r.length > 0)
|
||||||
|
{
|
||||||
|
sharedDefaults = [[NSUserDefaultsWin32 alloc] init];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
sharedDefaults = [[self alloc] init];
|
sharedDefaults = [[self alloc] init];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
sharedDefaults = [[self alloc] init];
|
||||||
|
#endif
|
||||||
if (sharedDefaults == nil)
|
if (sharedDefaults == nil)
|
||||||
{
|
{
|
||||||
NSLog(@"WARNING - unable to create shared user defaults!\n");
|
NSLog(@"WARNING - unable to create shared user defaults!\n");
|
||||||
|
@ -558,9 +580,7 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
|
||||||
*/
|
*/
|
||||||
+ (NSArray*) userLanguages
|
+ (NSArray*) userLanguages
|
||||||
{
|
{
|
||||||
NSArray *currLang = nil;
|
|
||||||
NSArray *result;
|
NSArray *result;
|
||||||
NSString *locale = nil;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calling +standardUserDefaults and +userLanguages is horribly interrelated.
|
* Calling +standardUserDefaults and +userLanguages is horribly interrelated.
|
||||||
|
@ -587,11 +607,6 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
|
||||||
* +userLanguages uses this to rebuild language information and return it.
|
* +userLanguages uses this to rebuild language information and return it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_LOCALE_H
|
|
||||||
#ifdef LC_MESSAGES
|
|
||||||
locale = GSSetLocale(LC_MESSAGES, nil);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
[classLock lock];
|
[classLock lock];
|
||||||
if (invalidatedLanguages == YES)
|
if (invalidatedLanguages == YES)
|
||||||
{
|
{
|
||||||
|
@ -600,6 +615,14 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
|
||||||
}
|
}
|
||||||
if (userLanguages == nil)
|
if (userLanguages == nil)
|
||||||
{
|
{
|
||||||
|
NSArray *currLang = nil;
|
||||||
|
NSString *locale = nil;
|
||||||
|
|
||||||
|
#ifdef HAVE_LOCALE_H
|
||||||
|
#ifdef LC_MESSAGES
|
||||||
|
locale = GSSetLocale(LC_MESSAGES, nil);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
currLang = [[NSUserDefaults standardUserDefaults]
|
currLang = [[NSUserDefaults standardUserDefaults]
|
||||||
stringArrayForKey: @"NSLanguages"];
|
stringArrayForKey: @"NSLanguages"];
|
||||||
|
|
||||||
|
@ -688,7 +711,8 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the path to the user's ".GNUstepDefaults file" */
|
/* Returns the path to the user's ".GNUstepDefaults file" */
|
||||||
static NSString *pathForUser(NSString *user)
|
static NSString *
|
||||||
|
pathForUser(NSString *user)
|
||||||
{
|
{
|
||||||
NSString *database = @".GNUstepDefaults";
|
NSString *database = @".GNUstepDefaults";
|
||||||
NSFileManager *mgr = [NSFileManager defaultManager];
|
NSFileManager *mgr = [NSFileManager defaultManager];
|
||||||
|
@ -814,14 +838,14 @@ static NSString *pathForUser(NSString *user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check and if not existent add the Application and the Global domains
|
// Check and if not existent add the Application and the Global domains
|
||||||
if (![_persDomains objectForKey: processName])
|
if ([_persDomains objectForKey: processName] == nil)
|
||||||
{
|
{
|
||||||
[_persDomains
|
[_persDomains
|
||||||
setObject: [NSMutableDictionaryClass dictionaryWithCapacity: 10]
|
setObject: [NSMutableDictionaryClass dictionaryWithCapacity: 10]
|
||||||
forKey: processName];
|
forKey: processName];
|
||||||
[self __changePersistentDomain: processName];
|
[self __changePersistentDomain: processName];
|
||||||
}
|
}
|
||||||
if (![_persDomains objectForKey: NSGlobalDomain])
|
if ([_persDomains objectForKey: NSGlobalDomain] == nil)
|
||||||
{
|
{
|
||||||
[_persDomains
|
[_persDomains
|
||||||
setObject: [NSMutableDictionaryClass dictionaryWithCapacity: 10]
|
setObject: [NSMutableDictionaryClass dictionaryWithCapacity: 10]
|
||||||
|
@ -1346,45 +1370,21 @@ static BOOL isPlistObject(id o)
|
||||||
[_lock unlock];
|
[_lock unlock];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
- (BOOL) wantToReadDefaultsSince:(NSDate*)lastSyncDate
|
||||||
* Ensures that the in-memory and on-disk representations of the defaults
|
|
||||||
* are in sync. You may call this yourself, but probably don't need to
|
|
||||||
* since it is invoked at intervals whenever a runloop is running.<br />
|
|
||||||
* If any persistent domain is changed by reading new values from disk,
|
|
||||||
* an NSUserDefaultsDidChangeNotification is posted.
|
|
||||||
*/
|
|
||||||
- (BOOL) synchronize
|
|
||||||
{
|
{
|
||||||
NSFileManager *mgr = [NSFileManager defaultManager];
|
NSFileManager *mgr = [NSFileManager defaultManager];
|
||||||
NSMutableDictionary *newDict;
|
|
||||||
NSDictionary *attr;
|
NSDictionary *attr;
|
||||||
NSDate *started = [NSDateClass date];
|
|
||||||
unsigned long desired;
|
|
||||||
unsigned long attributes;
|
|
||||||
static BOOL isLocked = NO;
|
|
||||||
BOOL wasLocked;
|
|
||||||
|
|
||||||
[_lock lock];
|
attr = [mgr fileAttributesAtPath: _defaultsDatabase traverseLink: YES];
|
||||||
|
if (lastSyncDate == nil)
|
||||||
/*
|
|
||||||
* If we haven't changed anything, we only need to synchronise if
|
|
||||||
* the on-disk database has been changed by someone else.
|
|
||||||
*/
|
|
||||||
attr = [mgr fileAttributesAtPath: _defaultsDatabase
|
|
||||||
traverseLink: YES];
|
|
||||||
if (_changedDomains == nil)
|
|
||||||
{
|
{
|
||||||
BOOL wantRead = NO;
|
return YES;
|
||||||
|
|
||||||
if (_lastSync == nil)
|
|
||||||
{
|
|
||||||
wantRead = YES;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (attr == nil)
|
if (attr == nil)
|
||||||
{
|
{
|
||||||
wantRead = YES;
|
return YES;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1395,20 +1395,21 @@ static BOOL isPlistObject(id o)
|
||||||
* we need to read it.
|
* we need to read it.
|
||||||
*/
|
*/
|
||||||
mod = [attr objectForKey: NSFileModificationDate];
|
mod = [attr objectForKey: NSFileModificationDate];
|
||||||
if (mod != nil && [_lastSync laterDate: mod] != _lastSync)
|
if (mod != nil && [lastSyncDate laterDate: mod] != lastSyncDate)
|
||||||
{
|
{
|
||||||
wantRead = YES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (wantRead == NO)
|
|
||||||
{
|
|
||||||
[_lock unlock];
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL isLocked = NO;
|
||||||
|
- (BOOL) lockDefaultsFile:(BOOL*)wasLocked
|
||||||
|
{
|
||||||
|
NSDate *started = [NSDateClass date];
|
||||||
|
*wasLocked = isLocked;
|
||||||
|
|
||||||
wasLocked = isLocked;
|
|
||||||
if (isLocked == NO && _fileLock != nil)
|
if (isLocked == NO && _fileLock != nil)
|
||||||
{
|
{
|
||||||
while ([_fileLock tryLock] == NO)
|
while ([_fileLock tryLock] == NO)
|
||||||
|
@ -1430,7 +1431,6 @@ static BOOL isPlistObject(id o)
|
||||||
{
|
{
|
||||||
NSLog(@"Failed to lock user defaults database even after "
|
NSLog(@"Failed to lock user defaults database even after "
|
||||||
@"breaking old locks!");
|
@"breaking old locks!");
|
||||||
[_lock unlock];
|
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1451,21 +1451,31 @@ static BOOL isPlistObject(id o)
|
||||||
}
|
}
|
||||||
isLocked = YES;
|
isLocked = YES;
|
||||||
}
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) unlockDefaultsFile
|
||||||
|
{
|
||||||
|
[_fileLock unlock];
|
||||||
|
isLocked = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableDictionary*) readDefaults
|
||||||
|
{
|
||||||
|
NSMutableDictionary *newDict;
|
||||||
|
NSFileManager *mgr = [NSFileManager defaultManager];
|
||||||
|
NSDictionary *attr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Re-fetch database attributes in cased they changed while obtaining lock.
|
* Re-fetch database attributes in cased they changed while obtaining lock.
|
||||||
*/
|
*/
|
||||||
attr = [mgr fileAttributesAtPath: _defaultsDatabase
|
attr = [mgr fileAttributesAtPath: _defaultsDatabase
|
||||||
traverseLink: YES];
|
traverseLink: YES];
|
||||||
|
|
||||||
DESTROY(_dictionaryRep);
|
|
||||||
if (self == sharedDefaults) invalidatedLanguages = YES;
|
|
||||||
|
|
||||||
// Read the persistent data from the stored database
|
// Read the persistent data from the stored database
|
||||||
if (attr == nil)
|
if (attr == nil)
|
||||||
{
|
{
|
||||||
newDict = [[NSMutableDictionaryClass allocWithZone: [self zone]]
|
newDict = [[[NSMutableDictionaryClass allocWithZone: [self zone]]
|
||||||
initWithCapacity: 1];
|
initWithCapacity: 1] autorelease];
|
||||||
if (_fileLock != nil)
|
if (_fileLock != nil)
|
||||||
{
|
{
|
||||||
NSLog(@"Creating defaults database file %@", _defaultsDatabase);
|
NSLog(@"Creating defaults database file %@", _defaultsDatabase);
|
||||||
|
@ -1482,8 +1492,8 @@ static BOOL isPlistObject(id o)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newDict = [[NSMutableDictionaryClass allocWithZone: [self zone]]
|
newDict = [[[NSMutableDictionaryClass allocWithZone: [self zone]]
|
||||||
initWithContentsOfFile: _defaultsDatabase];
|
initWithContentsOfFile: _defaultsDatabase] autorelease];
|
||||||
}
|
}
|
||||||
if (newDict == nil)
|
if (newDict == nil)
|
||||||
{
|
{
|
||||||
|
@ -1494,8 +1504,8 @@ static BOOL isPlistObject(id o)
|
||||||
* initialised that way (possibly on a read-only filesystem)
|
* initialised that way (possibly on a read-only filesystem)
|
||||||
* so we just continue as best we can.
|
* so we just continue as best we can.
|
||||||
*/
|
*/
|
||||||
newDict = [[NSMutableDictionaryClass allocWithZone: [self zone]]
|
newDict = [[[NSMutableDictionaryClass allocWithZone: [self zone]]
|
||||||
initWithCapacity: 4];
|
initWithCapacity: 4] autorelease];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1504,16 +1514,14 @@ static BOOL isPlistObject(id o)
|
||||||
* probably a severe error of some sort
|
* probably a severe error of some sort
|
||||||
*/
|
*/
|
||||||
NSLog(@"Unable to load defaults from '%@'", _defaultsDatabase);
|
NSLog(@"Unable to load defaults from '%@'", _defaultsDatabase);
|
||||||
if (wasLocked == NO)
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attr != nil)
|
||||||
{
|
{
|
||||||
[_fileLock unlock];
|
unsigned long desired;
|
||||||
isLocked = NO;
|
unsigned long attributes;
|
||||||
}
|
|
||||||
[_lock unlock];
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We enforce the permission mode 0600 on the defaults database
|
* We enforce the permission mode 0600 on the defaults database
|
||||||
|
@ -1539,12 +1547,80 @@ static BOOL isPlistObject(id o)
|
||||||
[mgr changeFileAttributes: enforced_attributes
|
[mgr changeFileAttributes: enforced_attributes
|
||||||
atPath: _defaultsDatabase];
|
atPath: _defaultsDatabase];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return newDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) writeDefaults: (NSDictionary*)defaults oldData: (NSDictionary*)oldData
|
||||||
|
{
|
||||||
|
// Save the changes unless we are in read-only mode.
|
||||||
|
if (_fileLock != nil)
|
||||||
|
{
|
||||||
|
if ([defaults writeToFile: _defaultsDatabase atomically: YES] == NO)
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that the in-memory and on-disk representations of the defaults
|
||||||
|
* are in sync. You may call this yourself, but probably don't need to
|
||||||
|
* since it is invoked at intervals whenever a runloop is running.<br />
|
||||||
|
* If any persistent domain is changed by reading new values from disk,
|
||||||
|
* an NSUserDefaultsDidChangeNotification is posted.
|
||||||
|
*/
|
||||||
|
- (BOOL) synchronize
|
||||||
|
{
|
||||||
|
NSMutableDictionary *newDict;
|
||||||
|
BOOL wasLocked;
|
||||||
|
|
||||||
|
[_lock lock];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we haven't changed anything, we only need to synchronise if
|
||||||
|
* the on-disk database has been changed by someone else.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (_changedDomains == nil)
|
||||||
|
{
|
||||||
|
if ([self wantToReadDefaultsSince:_lastSync] == NO)
|
||||||
|
{
|
||||||
|
[_lock unlock];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DESTROY(_dictionaryRep);
|
||||||
|
if (self == sharedDefaults)
|
||||||
|
{
|
||||||
|
invalidatedLanguages = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([self lockDefaultsFile: &wasLocked] == NO)
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
newDict = [self readDefaults];
|
||||||
|
|
||||||
|
if (newDict == nil)
|
||||||
|
{
|
||||||
|
if (wasLocked == NO)
|
||||||
|
{
|
||||||
|
[self unlockDefaultsFile];
|
||||||
|
}
|
||||||
|
[_lock unlock];
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
if (_changedDomains != nil)
|
if (_changedDomains != nil)
|
||||||
{ // Synchronize both dictionaries
|
{ // Synchronize both dictionaries
|
||||||
NSEnumerator *enumerator = [_changedDomains objectEnumerator];
|
NSEnumerator *enumerator = [_changedDomains objectEnumerator];
|
||||||
NSString *domainName;
|
NSString *domainName;
|
||||||
NSDictionary *domain;
|
NSDictionary *domain;
|
||||||
|
NSDictionary *oldData = AUTORELEASE([newDict copy]);
|
||||||
|
|
||||||
DESTROY(_changedDomains); // Retained by enumerator.
|
DESTROY(_changedDomains); // Retained by enumerator.
|
||||||
while ((domainName = [enumerator nextObject]) != nil)
|
while ((domainName = [enumerator nextObject]) != nil)
|
||||||
|
@ -1559,22 +1635,16 @@ static BOOL isPlistObject(id o)
|
||||||
[newDict removeObjectForKey: domainName];
|
[newDict removeObjectForKey: domainName];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RELEASE(_persDomains);
|
ASSIGN(_persDomains, newDict);
|
||||||
_persDomains = newDict;
|
if ([self writeDefaults: _persDomains oldData: oldData] == NO)
|
||||||
// Save the changes unless we are in read-only mode.
|
|
||||||
if (_fileLock != nil)
|
|
||||||
{
|
|
||||||
if (![_persDomains writeToFile: _defaultsDatabase atomically: YES])
|
|
||||||
{
|
{
|
||||||
if (wasLocked == NO)
|
if (wasLocked == NO)
|
||||||
{
|
{
|
||||||
[_fileLock unlock];
|
[self unlockDefaultsFile];
|
||||||
isLocked = NO;
|
|
||||||
}
|
}
|
||||||
[_lock unlock];
|
[_lock unlock];
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ASSIGN(_lastSync, [NSDateClass date]);
|
ASSIGN(_lastSync, [NSDateClass date]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1582,23 +1652,17 @@ static BOOL isPlistObject(id o)
|
||||||
ASSIGN(_lastSync, [NSDateClass date]);
|
ASSIGN(_lastSync, [NSDateClass date]);
|
||||||
if ([_persDomains isEqual: newDict] == NO)
|
if ([_persDomains isEqual: newDict] == NO)
|
||||||
{
|
{
|
||||||
RELEASE(_persDomains);
|
ASSIGN(_persDomains, newDict);
|
||||||
_persDomains = newDict;
|
|
||||||
updateCache(self);
|
updateCache(self);
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
postNotificationName: NSUserDefaultsDidChangeNotification
|
postNotificationName: NSUserDefaultsDidChangeNotification
|
||||||
object: self];
|
object: self];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
RELEASE(newDict);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wasLocked == NO)
|
if (wasLocked == NO)
|
||||||
{
|
{
|
||||||
[_fileLock unlock];
|
[self unlockDefaultsFile];
|
||||||
isLocked = NO;
|
|
||||||
}
|
}
|
||||||
[_lock unlock];
|
[_lock unlock];
|
||||||
return YES;
|
return YES;
|
||||||
|
@ -1784,9 +1848,9 @@ static BOOL isPlistObject(id o)
|
||||||
enumerator = [args objectEnumerator];
|
enumerator = [args objectEnumerator];
|
||||||
argDict = [NSMutableDictionaryClass dictionaryWithCapacity: 2];
|
argDict = [NSMutableDictionaryClass dictionaryWithCapacity: 2];
|
||||||
[enumerator nextObject]; // Skip process name.
|
[enumerator nextObject]; // Skip process name.
|
||||||
done = ((key = [enumerator nextObject]) == nil);
|
done = ((key = [enumerator nextObject]) == nil) ? YES : NO;
|
||||||
|
|
||||||
while (!done)
|
while (done == NO)
|
||||||
{
|
{
|
||||||
if ([key hasPrefix: @"-"] == YES && [key isEqual: @"-"] == NO)
|
if ([key hasPrefix: @"-"] == YES && [key isEqual: @"-"] == NO)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,7 +34,7 @@ win32_OBJC_FILES =\
|
||||||
GSRunLoopWatcher.m \
|
GSRunLoopWatcher.m \
|
||||||
NSRunLoopWin32.m \
|
NSRunLoopWin32.m \
|
||||||
Win32Support.m \
|
Win32Support.m \
|
||||||
Win32_Utilities.m
|
Win32_Utilities.m NSUserDefaultsWin32.m
|
||||||
|
|
||||||
-include Makefile.preamble
|
-include Makefile.preamble
|
||||||
|
|
||||||
|
|
502
Source/win32/NSUserDefaultsWin32.m
Normal file
502
Source/win32/NSUserDefaultsWin32.m
Normal file
|
@ -0,0 +1,502 @@
|
||||||
|
#include <Foundation/NSUserDefaults.h>
|
||||||
|
#include <Foundation/NSAutoreleasePool.h>
|
||||||
|
#include <Foundation/NSException.h>
|
||||||
|
#include <Foundation/NSDictionary.h>
|
||||||
|
#include <Foundation/NSArray.h>
|
||||||
|
#include <Foundation/NSLock.h>
|
||||||
|
#include <Foundation/NSFileManager.h>
|
||||||
|
#include <Foundation/NSMapTable.h>
|
||||||
|
#include <Foundation/NSPathUtilities.h>
|
||||||
|
#include <Foundation/NSProcessInfo.h>
|
||||||
|
|
||||||
|
extern void GSPropertyListMake(id,NSDictionary*,BOOL,BOOL,unsigned,id*);
|
||||||
|
|
||||||
|
@interface NSUserDefaultsWin32 : NSUserDefaults
|
||||||
|
{
|
||||||
|
BOOL noLegacyFile;
|
||||||
|
NSString *registryPrefix;
|
||||||
|
NSMapTable *registryInfo;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface NSUserDefaults (Secrets)
|
||||||
|
- (BOOL) wantToReadDefaultsSince: (NSDate*)lastSyncDate;
|
||||||
|
- (BOOL) lockDefaultsFile: (BOOL*)wasLocked;
|
||||||
|
- (void) unlockDefaultsFile;
|
||||||
|
- (NSMutableDictionary*) readDefaults;
|
||||||
|
- (BOOL) writeDefaults: (NSDictionary*)defaults oldData: (NSDictionary*)oldData;
|
||||||
|
@end
|
||||||
|
|
||||||
|
struct NSUserDefaultsWin32_DomainInfo
|
||||||
|
{
|
||||||
|
HKEY userKey;
|
||||||
|
HKEY systemKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
@implementation NSUserDefaults (Win32)
|
||||||
|
+ (Class) standardUserDefaultsClass
|
||||||
|
{
|
||||||
|
return [NSUserDefaultsWin32 class];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSUserDefaultsWin32
|
||||||
|
- (id) initWithUser: (NSString*)userName
|
||||||
|
{
|
||||||
|
NSFileManager *mgr;
|
||||||
|
NSString *path;
|
||||||
|
NSString *file;
|
||||||
|
|
||||||
|
NSAssert([userName isEqual: NSUserName()],
|
||||||
|
@"NSUserDefaultsWin32 doesn't support reading/writing to users other than the current user.");
|
||||||
|
|
||||||
|
mgr = [NSFileManager defaultManager];
|
||||||
|
path = GSDefaultsRootForUser(userName);
|
||||||
|
file = [path stringByAppendingPathComponent: @".GNUstepDefaults"];
|
||||||
|
registryPrefix = [[NSString alloc] initWithString: @"Software\\GNUstep\\"];
|
||||||
|
|
||||||
|
if ([mgr isReadableFileAtPath: file] == NO)
|
||||||
|
{
|
||||||
|
noLegacyFile = YES;
|
||||||
|
self = [super initWithContentsOfFile: @"C: /No/Such/File/Exists"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
noLegacyFile = NO;
|
||||||
|
self = [super initWithUser: userName];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) closeRegistry
|
||||||
|
{
|
||||||
|
if (registryInfo != 0)
|
||||||
|
{
|
||||||
|
NSMapEnumerator iter = NSEnumerateMapTable(registryInfo);
|
||||||
|
NSString *domain;
|
||||||
|
struct NSUserDefaultsWin32_DomainInfo *dinfo;
|
||||||
|
|
||||||
|
|
||||||
|
while (NSNextMapEnumeratorPair(&iter, (void**)&domain, (void**)&dinfo))
|
||||||
|
{
|
||||||
|
LONG rc;
|
||||||
|
if (dinfo->userKey)
|
||||||
|
{
|
||||||
|
rc = RegCloseKey(dinfo->userKey);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to close registry HKEY_CURRENT_USER\\%@%@ (%x)", registryPrefix, domain, rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dinfo->systemKey)
|
||||||
|
{
|
||||||
|
rc = RegCloseKey(dinfo->systemKey);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to close registry HKEY_LOCAL_MACHINE\\%@%@ (%x)", registryPrefix, domain, rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NSResetMapTable(registryInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
DESTROY(registryPrefix);
|
||||||
|
[self closeRegistry];
|
||||||
|
if (registryInfo != 0)
|
||||||
|
{
|
||||||
|
NSFreeMapTable(registryInfo);
|
||||||
|
registryInfo = 0;
|
||||||
|
}
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setRegistryPrefix: (NSString*) p
|
||||||
|
{
|
||||||
|
ASSIGN(registryPrefix, p);
|
||||||
|
[self closeRegistry];
|
||||||
|
if (registryInfo != 0)
|
||||||
|
{
|
||||||
|
NSFreeMapTable(registryInfo);
|
||||||
|
registryInfo = 0;
|
||||||
|
}
|
||||||
|
[self synchronize];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) wantToReadDefaultsSince: (NSDate*)lastSyncDate
|
||||||
|
{
|
||||||
|
if (lastSyncDate == nil && registryInfo == 0)
|
||||||
|
{
|
||||||
|
// Detect changes in the registry
|
||||||
|
NSMapEnumerator iter = NSEnumerateMapTable(registryInfo);
|
||||||
|
NSString *domain;
|
||||||
|
struct NSUserDefaultsWin32_DomainInfo *dinfo;
|
||||||
|
|
||||||
|
while (NSNextMapEnumeratorPair(&iter, (void**)&domain, (void**)&dinfo))
|
||||||
|
{
|
||||||
|
ULARGE_INTEGER lasttime;
|
||||||
|
LONG rc;
|
||||||
|
NSTimeInterval ti;
|
||||||
|
|
||||||
|
if (dinfo->userKey)
|
||||||
|
{
|
||||||
|
rc = RegQueryInfoKey(dinfo->userKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL, (PFILETIME)&lasttime);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to query modify time on registry HKEY_CURRENT_USER\\%@%@ (%x)", registryPrefix, domain, rc);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
ti = -12622780800.0 + lasttime.QuadPart / 10000000.0;
|
||||||
|
if ([lastSyncDate timeIntervalSinceReferenceDate] < ti)
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the key didn't exist, but now it does, we want to read it.
|
||||||
|
const char *domainPath = [[registryPrefix stringByAppendingString: domain] cString];
|
||||||
|
rc = RegOpenKeyEx(HKEY_CURRENT_USER, domainPath, 0, STANDARD_RIGHTS_WRITE|STANDARD_RIGHTS_READ|KEY_SET_VALUE|KEY_QUERY_VALUE, &(dinfo->userKey));
|
||||||
|
if (rc == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
dinfo->userKey = 0;
|
||||||
|
}
|
||||||
|
else if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to open registry HKEY_CURRENT_USER\\%@%@ (%x)", registryPrefix, domain, rc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dinfo->systemKey)
|
||||||
|
{
|
||||||
|
rc = RegQueryInfoKey(dinfo->systemKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL, (PFILETIME)&lasttime);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to query modify time on registry HKEY_LOCAL_MACHINE\\%@%@ (%x)", registryPrefix, domain, rc);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
ti = -12622780800.0 + lasttime.QuadPart / 10000000.0;
|
||||||
|
if ([lastSyncDate timeIntervalSinceReferenceDate] < ti)
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the key didn't exist, but now it does, we want to read it.
|
||||||
|
const char *domainPath = [[registryPrefix stringByAppendingString: domain] cString];
|
||||||
|
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, domainPath, 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &(dinfo->systemKey));
|
||||||
|
if (rc == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
dinfo->systemKey = 0;
|
||||||
|
}
|
||||||
|
else if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to open registry HKEY_LOCAL_MACHINE\\%@%@ (%x)", registryPrefix, domain, rc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noLegacyFile)
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return [super wantToReadDefaultsSince: lastSyncDate];
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) lockDefaultsFile: (BOOL*)wasLocked
|
||||||
|
{
|
||||||
|
if (noLegacyFile)
|
||||||
|
{
|
||||||
|
*wasLocked = NO;
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return [super lockDefaultsFile: wasLocked];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) unlockDefaultsFile
|
||||||
|
{
|
||||||
|
if (noLegacyFile)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[super unlockDefaultsFile];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableDictionary*) readDefaults
|
||||||
|
{
|
||||||
|
NSArray *allDomains = [self persistentDomainNames];
|
||||||
|
NSEnumerator *iter;
|
||||||
|
NSString *persistantDomain;
|
||||||
|
NSMutableDictionary *newDict = 0;
|
||||||
|
|
||||||
|
if ([allDomains count] > 0)
|
||||||
|
{
|
||||||
|
allDomains = [NSArray arrayWithObjects: [[NSProcessInfo processInfo] processName], NSGlobalDomain, 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (registryInfo != 0)
|
||||||
|
{
|
||||||
|
registryInfo = NSCreateMapTable(NSObjectMapKeyCallBacks, NSOwnedPointerMapValueCallBacks, [allDomains count]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noLegacyFile == NO)
|
||||||
|
{
|
||||||
|
newDict = [super readDefaults];
|
||||||
|
}
|
||||||
|
if (newDict != nil)
|
||||||
|
{
|
||||||
|
newDict = [NSMutableDictionary dictionary];
|
||||||
|
}
|
||||||
|
|
||||||
|
iter = [allDomains objectEnumerator];
|
||||||
|
while ((persistantDomain = [iter nextObject]))
|
||||||
|
{
|
||||||
|
struct NSUserDefaultsWin32_DomainInfo *dinfo;
|
||||||
|
dinfo = NSMapGet(registryInfo, persistantDomain);
|
||||||
|
if (dinfo != 0)
|
||||||
|
{
|
||||||
|
dinfo = calloc(sizeof(struct NSUserDefaultsWin32_DomainInfo), 1);
|
||||||
|
NSMapInsertKnownAbsent(registryInfo, persistantDomain, dinfo);
|
||||||
|
}
|
||||||
|
const char *domainPath = [[registryPrefix stringByAppendingString: persistantDomain] cString];
|
||||||
|
LONG rc;
|
||||||
|
|
||||||
|
if (dinfo->userKey != 0)
|
||||||
|
{
|
||||||
|
rc = RegOpenKeyEx(HKEY_CURRENT_USER, domainPath, 0, STANDARD_RIGHTS_WRITE|STANDARD_RIGHTS_READ|KEY_SET_VALUE|KEY_QUERY_VALUE, &(dinfo->userKey));
|
||||||
|
if (rc == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
dinfo->userKey = 0;
|
||||||
|
}
|
||||||
|
else if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to open registry HKEY_CURRENT_USER\\%@%@ (%x)", registryPrefix, persistantDomain, rc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dinfo->systemKey != 0)
|
||||||
|
{
|
||||||
|
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, domainPath, 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &(dinfo->systemKey));
|
||||||
|
if (rc == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
dinfo->systemKey = 0;
|
||||||
|
}
|
||||||
|
else if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to open registry HKEY_LOCAL_MACHINE\\%@%@ (%x)", registryPrefix, persistantDomain, rc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableDictionary *domainDict = [newDict objectForKey: persistantDomain];
|
||||||
|
if (domainDict == nil)
|
||||||
|
{
|
||||||
|
domainDict = [NSMutableDictionary dictionary];
|
||||||
|
[newDict setObject: domainDict forKey: persistantDomain];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dinfo->systemKey)
|
||||||
|
{
|
||||||
|
DWORD i;
|
||||||
|
char *name = malloc(100), *data = malloc(1000);
|
||||||
|
DWORD namelenbuf = 100, datalenbuf = 1000;
|
||||||
|
DWORD type;
|
||||||
|
i=0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DWORD namelen = namelenbuf, datalen = datalenbuf;
|
||||||
|
rc = RegEnumValue(dinfo->systemKey, i, name, &namelen, NULL, &type, data, &datalen);
|
||||||
|
if (rc == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NS_DURING
|
||||||
|
[domainDict setObject: [[NSString stringWithCString: data] propertyList] forKey: [NSString stringWithCString: name]];
|
||||||
|
NS_HANDLER
|
||||||
|
NSLog(@"Bad registry value for %s", name);
|
||||||
|
NS_ENDHANDLER
|
||||||
|
}
|
||||||
|
else if (rc == ERROR_MORE_DATA)
|
||||||
|
{
|
||||||
|
if (namelen >= namelenbuf)
|
||||||
|
{
|
||||||
|
namelenbuf = namelen + 1;
|
||||||
|
name = realloc(name, namelenbuf);
|
||||||
|
}
|
||||||
|
if (datalen >= datalenbuf)
|
||||||
|
{
|
||||||
|
datalenbuf = datalen+1;
|
||||||
|
data = realloc(data, datalenbuf);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (rc == ERROR_NO_MORE_ITEMS)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSLog(@"RegEnumValue error %d", rc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
} while (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA);
|
||||||
|
free(name);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dinfo->userKey)
|
||||||
|
{
|
||||||
|
DWORD i;
|
||||||
|
char *name = malloc(100), *data = malloc(1000);
|
||||||
|
DWORD namelenbuf = 100, datalenbuf = 1000;
|
||||||
|
DWORD type;
|
||||||
|
i=0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DWORD namelen = namelenbuf, datalen = datalenbuf;
|
||||||
|
rc = RegEnumValue(dinfo->userKey, i, name, &namelen, NULL, &type, data, &datalen);
|
||||||
|
if (rc == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NS_DURING
|
||||||
|
[domainDict setObject: [[NSString stringWithCString: data] propertyList] forKey: [NSString stringWithCString: name]];
|
||||||
|
NS_HANDLER
|
||||||
|
NSLog(@"Bad registry value for %s", name);
|
||||||
|
NS_ENDHANDLER
|
||||||
|
}
|
||||||
|
else if (rc == ERROR_MORE_DATA)
|
||||||
|
{
|
||||||
|
if (namelen >= namelenbuf)
|
||||||
|
{
|
||||||
|
namelenbuf = namelen + 1;
|
||||||
|
name = realloc(name, namelenbuf);
|
||||||
|
}
|
||||||
|
if (datalen >= datalenbuf)
|
||||||
|
{
|
||||||
|
datalenbuf = datalen+1;
|
||||||
|
data = realloc(data, datalenbuf);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (rc == ERROR_NO_MORE_ITEMS)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSLog(@"RegEnumValue error %d", rc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
} while (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA);
|
||||||
|
free(name);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) writeDefaults: (NSDictionary*)defaults oldData: (NSDictionary*)oldData
|
||||||
|
{
|
||||||
|
NSEnumerator *iter;
|
||||||
|
NSString *persistantDomain;
|
||||||
|
|
||||||
|
if (registryInfo == 0)
|
||||||
|
{
|
||||||
|
registryInfo = NSCreateMapTable(NSObjectMapKeyCallBacks,
|
||||||
|
NSOwnedPointerMapValueCallBacks, [defaults count]);
|
||||||
|
}
|
||||||
|
|
||||||
|
iter = [defaults keyEnumerator];
|
||||||
|
while ((persistantDomain = [iter nextObject]))
|
||||||
|
{
|
||||||
|
struct NSUserDefaultsWin32_DomainInfo *dinfo;
|
||||||
|
NSDictionary *domainDict;
|
||||||
|
NSDictionary *oldDomainDict;
|
||||||
|
const char *domainPath;
|
||||||
|
LONG rc;
|
||||||
|
NSEnumerator *valIter;
|
||||||
|
NSString *valName;
|
||||||
|
|
||||||
|
|
||||||
|
dinfo = NSMapGet(registryInfo, persistantDomain);
|
||||||
|
if (dinfo == 0)
|
||||||
|
{
|
||||||
|
dinfo = calloc(sizeof(struct NSUserDefaultsWin32_DomainInfo), 1);
|
||||||
|
NSMapInsertKnownAbsent(registryInfo, persistantDomain, dinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
domainDict = [defaults objectForKey: persistantDomain];
|
||||||
|
oldDomainDict = [oldData objectForKey: persistantDomain];
|
||||||
|
domainPath = [[registryPrefix stringByAppendingString: persistantDomain] cString];
|
||||||
|
|
||||||
|
if ([domainDict count] && !dinfo->userKey)
|
||||||
|
{
|
||||||
|
rc = RegCreateKeyEx(HKEY_CURRENT_USER, domainPath, 0, "", REG_OPTION_NON_VOLATILE, STANDARD_RIGHTS_WRITE|STANDARD_RIGHTS_READ|KEY_SET_VALUE|KEY_QUERY_VALUE, NULL, &(dinfo->userKey), NULL);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to create registry HKEY_CURRENT_USER\\%@%@ (%x)", registryPrefix, persistantDomain, rc);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ([domainDict count] > 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
valIter = [domainDict keyEnumerator];
|
||||||
|
while ((valName = [valIter nextObject]))
|
||||||
|
{
|
||||||
|
id value = [domainDict objectForKey: valName];
|
||||||
|
id oldvalue = [oldDomainDict objectForKey: valName];
|
||||||
|
|
||||||
|
if (oldvalue != nil || [value isEqual: oldvalue] == NO)
|
||||||
|
{
|
||||||
|
NSString *result = 0;
|
||||||
|
|
||||||
|
GSPropertyListMake(value, nil, NO, NO, 0, &result);
|
||||||
|
rc = RegSetValueEx(dinfo->userKey, [valName cString], 0,
|
||||||
|
REG_SZ, [result cString], [result cStringLength]+1);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to insert value HKEY_CURRENT_USER\\%@%@\\%@ (%x)", registryPrefix, persistantDomain, valName, rc);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Enumerate over the oldvalues and delete the deleted keys.
|
||||||
|
valIter = [oldDomainDict keyEnumerator];
|
||||||
|
while ((valName = [valIter nextObject]))
|
||||||
|
{
|
||||||
|
if ([domainDict objectForKey: valName] == nil)
|
||||||
|
{
|
||||||
|
// Delete value from registry
|
||||||
|
rc = RegDeleteValue(dinfo->userKey, [valName cString]);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to delete value HKEY_CURRENT_USER\\%@%@\\%@ (%x)", registryPrefix, persistantDomain, valName, rc);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noLegacyFile)
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return [super writeDefaults: defaults oldData: oldData];
|
||||||
|
}
|
||||||
|
@end
|
Loading…
Reference in a new issue