Add 64bit specific files.

This commit is contained in:
Gregoro John Casamento 2019-03-14 10:45:32 -04:00
parent 532b85c7a9
commit 7f3fe7f1f5
10 changed files with 6839 additions and 1 deletions

View file

@ -40,6 +40,7 @@ ifeq ($(GNUSTEP_MAKEFILES),)
$(error You need to set GNUSTEP_MAKEFILES before compiling!)
endif
# export GNUSTEP_TARGET_OS=mingw64
GNUSTEP_CORE_SOFTWARE = YES
export GNUSTEP_CORE_SOFTWARE
RPM_DISABLE_RELOCATABLE = YES

View file

@ -84,7 +84,7 @@ ifeq ($(GNUSTEP_TARGET_OS), mingw32)
libgnustep-base_SUBPROJECTS += win32
else
ifeq ($(GNUSTEP_TARGET_OS), mingw64)
libgnustep-base_SUBPROJECTS += win32
libgnustep-base_SUBPROJECTS += win64
else
libgnustep-base_SUBPROJECTS += unix
endif

45
Source/win64/GNUmakefile Normal file
View file

@ -0,0 +1,45 @@
#
# src makefile for the GNUstep Base Library
#
# Copyright (C) 1997 Free Software Foundation, Inc.
#
# Written by: Scott Christley <scottc@net-community.com>
#
# This file is part of the GNUstep Base Library.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
#
PACKAGE_NAME = gnustep-base
GNUSTEP_LOCAL_ADDITIONAL_MAKEFILES=../../base.make
include $(GNUSTEP_MAKEFILES)/common.make
include ../../config.mak
SUBPROJECT_NAME = win32
win32_OBJC_FILES =\
GSFileHandle.m \
GSRunLoopCtxt.m \
NSMessagePort.m \
NSMessagePortNameServer.m \
NSStream.m \
NSUserDefaults.m \
-include Makefile.preamble
include $(GNUSTEP_MAKEFILES)/subproject.make
-include Makefile.postamble

2409
Source/win64/GSFileHandle.m Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,617 @@
/**
* The GSRunLoopCtxt stores context information to handle polling for
* events. This information is associated with a particular runloop
* mode, and persists throughout the life of the runloop instance.
*
* NB. This class is private to NSRunLoop and must not be subclassed.
*/
#import "common.h"
#import "Foundation/NSError.h"
#import "Foundation/NSNotification.h"
#import "Foundation/NSNotificationQueue.h"
#import "Foundation/NSPort.h"
#import "Foundation/NSStream.h"
#import "../GSRunLoopCtxt.h"
#import "../GSRunLoopWatcher.h"
#import "../GSPrivate.h"
#define FDCOUNT 1024
static SEL wRelSel;
static SEL wRetSel;
static IMP wRelImp;
static IMP wRetImp;
static void
wRelease(NSMapTable* t, void* w)
{
(*wRelImp)((id)w, wRelSel);
}
static void
wRetain(NSMapTable* t, const void* w)
{
(*wRetImp)((id)w, wRetSel);
}
static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
{
wRetain,
wRelease,
0
};
@implementation GSRunLoopCtxt
+ (void) initialize
{
wRelSel = @selector(release);
wRetSel = @selector(retain);
wRelImp = [[GSRunLoopWatcher class] instanceMethodForSelector: wRelSel];
wRetImp = [[GSRunLoopWatcher class] instanceMethodForSelector: wRetSel];
}
- (void) dealloc
{
RELEASE(mode);
GSIArrayEmpty(performers);
NSZoneFree(performers->zone, (void*)performers);
GSIArrayEmpty(timers);
NSZoneFree(timers->zone, (void*)timers);
GSIArrayEmpty(watchers);
NSZoneFree(watchers->zone, (void*)watchers);
if (handleMap != 0)
{
NSFreeMapTable(handleMap);
}
if (winMsgMap != 0)
{
NSFreeMapTable(winMsgMap);
}
GSIArrayEmpty(_trigger);
NSZoneFree(_trigger->zone, (void*)_trigger);
[super dealloc];
}
/**
* Remove any callback for the specified event which is set for an
* uncompleted poll operation.<br />
* This is called by nested event loops on contexts in outer loops
* when they handle an event ... removing the event from the outer
* loop ensures that it won't get handled twice, once by the inner
* loop and once by the outer one.
*/
- (void) endEvent: (void*)data
for: (GSRunLoopWatcher*)watcher
{
if (completed == NO)
{
unsigned i = GSIArrayCount(_trigger);
while (i-- > 0)
{
GSIArrayItem item = GSIArrayItemAtIndex(_trigger, i);
if (item.obj == (id)watcher)
{
GSIArrayRemoveItemAtIndex(_trigger, i);
}
}
switch (watcher->type)
{
case ET_RPORT:
case ET_HANDLE:
NSMapRemove(handleMap, data);
break;
case ET_WINMSG:
NSMapRemove(winMsgMap, data);
break;
case ET_TRIGGER:
// Already handled
break;
default:
NSLog(@"Ending an event of unexpected type (%d)", watcher->type);
break;
}
}
}
/**
* Mark this poll context as having completed, so that if we are
* executing a re-entrant poll, the enclosing poll operations
* know they can stop what they are doing because an inner
* operation has done the job.
*/
- (void) endPoll
{
completed = YES;
}
- (id) init
{
[NSException raise: NSInternalInconsistencyException
format: @"-init may not be called for GSRunLoopCtxt"];
return nil;
}
- (id) initWithMode: (NSString*)theMode extra: (void*)e
{
self = [super init];
if (self != nil)
{
NSZone *z;
mode = [theMode copy];
extra = e;
z = [self zone];
performers = NSZoneMalloc(z, sizeof(GSIArray_t));
timers = NSZoneMalloc(z, sizeof(GSIArray_t));
watchers = NSZoneMalloc(z, sizeof(GSIArray_t));
_trigger = NSZoneMalloc(z, sizeof(GSIArray_t));
GSIArrayInitWithZoneAndCapacity(performers, z, 8);
GSIArrayInitWithZoneAndCapacity(timers, z, 8);
GSIArrayInitWithZoneAndCapacity(watchers, z, 8);
GSIArrayInitWithZoneAndCapacity(_trigger, z, 8);
handleMap = NSCreateMapTable(NSIntegerMapKeyCallBacks,
WatcherMapValueCallBacks, 0);
winMsgMap = NSCreateMapTable(NSIntegerMapKeyCallBacks,
WatcherMapValueCallBacks, 0);
}
return self;
}
/*
* If there is a generic watcher (watching hwnd == 0),
* loop through all events, and send them to the correct
* watcher (if there are any) and then process the rest right here.
* Return a flag to say whether any messages were handled.
*/
- (BOOL) processAllWindowsMessages:(int)num_winMsgs within: (NSArray*)contexts
{
MSG msg;
GSRunLoopWatcher *generic = nil;
unsigned i;
BOOL handled = NO;
if (num_winMsgs > 0)
{
generic = NSMapGet(winMsgMap,0);
}
if (generic != nil && generic->_invalidated == NO)
{
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (num_winMsgs > 0)
{
HANDLE handle;
GSRunLoopWatcher *watcher;
handle = msg.hwnd;
watcher = (GSRunLoopWatcher*)NSMapGet(winMsgMap,
(void*)handle);
if (watcher == nil || watcher->_invalidated == YES)
{
handle = 0; // Generic
watcher
= (GSRunLoopWatcher*)NSMapGet(winMsgMap, (void*)handle);
}
if (watcher != nil && watcher->_invalidated == NO)
{
i = [contexts count];
while (i-- > 0)
{
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
if (c != self)
{
[c endEvent: (void*)handle for: watcher];
}
}
handled = YES;
/*
* The watcher is still valid - so call the
* receiver's event handling method.
*/
[watcher->receiver receivedEvent: watcher->data
type: watcher->type
extra: (void*)&msg
forMode: mode];
continue;
}
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
if (num_winMsgs > 0)
{
unsigned num = num_winMsgs;
NSMapEnumerator hEnum;
HANDLE handle;
GSRunLoopWatcher *watcher;
hEnum = NSEnumerateMapTable(winMsgMap);
while (NSNextMapEnumeratorPair(&hEnum, &handle, (void**)&watcher))
{
if (watcher->_invalidated == NO)
{
while (PeekMessage(&msg, handle, 0, 0, PM_REMOVE))
{
i = [contexts count];
while (i-- > 0)
{
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
if (c != self)
{
[c endEvent: (void*)handle for: watcher];
}
}
handled = YES;
[watcher->receiver receivedEvent: watcher->data
type: watcher->type
extra: (void*)&msg
forMode: mode];
}
}
num--;
}
NSEndMapTableEnumeration(&hEnum);
}
}
return handled;
}
- (BOOL) pollUntil: (int)milliseconds within: (NSArray*)contexts
{
GSRunLoopThreadInfo *threadInfo = GSRunLoopInfoForThread(nil);
NSMapEnumerator hEnum;
GSRunLoopWatcher *watcher;
HANDLE handleArray[MAXIMUM_WAIT_OBJECTS-1];
int num_handles;
int num_winMsgs;
unsigned count;
unsigned i;
void *handle;
int wait_timeout;
DWORD wait_return;
BOOL immediate = NO;
BOOL existingMessages = NO;
// Set timeout how much time should wait
if (milliseconds >= 0)
{
wait_timeout = milliseconds;
}
else
{
wait_timeout = INFINITE;
}
NSResetMapTable(handleMap);
NSResetMapTable(winMsgMap);
GSIArrayRemoveAllItems(_trigger);
i = GSIArrayCount(watchers);
num_handles = 1; // One handle for signals from other threads
num_winMsgs = 0;
while (i-- > 0)
{
GSRunLoopWatcher *info;
BOOL trigger;
info = GSIArrayItemAtIndex(watchers, i).obj;
if (info->_invalidated == YES)
{
GSIArrayRemoveItemAtIndex(watchers, i);
}
else if ([info runLoopShouldBlock: &trigger] == NO)
{
if (trigger == YES)
{
immediate = YES;
GSIArrayAddItem(_trigger, (GSIArrayItem)(id)info);
}
}
else
{
HANDLE handle;
switch (info->type)
{
case ET_HANDLE:
handle = (HANDLE)(size_t)info->data;
NSMapInsert(handleMap, (void*)handle, info);
num_handles++;
break;
case ET_RPORT:
{
id port = info->receiver;
NSInteger port_hd_size = FDCOUNT;
NSInteger port_hd_count = FDCOUNT;
NSInteger port_hd_buffer[FDCOUNT];
NSInteger *port_hd_array = port_hd_buffer;
[port getFds: port_hd_array count: &port_hd_count];
while (port_hd_count > port_hd_size)
{
if (port_hd_array != port_hd_buffer) free(port_hd_array);
port_hd_size = port_hd_count;
port_hd_count = port_hd_size;
port_hd_array = malloc(sizeof(NSInteger)*port_hd_size);
[port getFds: port_hd_array count: &port_hd_count];
}
NSDebugMLLog(@"NSRunLoop", @"listening to %d port handles",
port_hd_count);
while (port_hd_count--)
{
NSMapInsert(handleMap,
(void*)(size_t) port_hd_array[port_hd_count],
info);
num_handles++;
}
if (port_hd_array != port_hd_buffer) free(port_hd_array);
}
break;
case ET_WINMSG:
handle = (HANDLE)(size_t)info->data;
NSMapInsert(winMsgMap, (void*)handle, info);
num_winMsgs++;
break;
case ET_TRIGGER:
break;
}
}
}
/*
* If there are notifications in the 'idle' queue, we try an
* instantaneous select so that, if there is no input pending,
* we can service the queue. Similarly, if a task has completed,
* we need to deliver its notifications.
*/
if (GSPrivateCheckTasks() || GSPrivateNotifyMore(mode) || immediate == YES)
{
wait_timeout = 0;
}
handleArray[0] = threadInfo->event; // Signal from other thread
num_handles = NSCountMapTable(handleMap) + 1;
if (num_handles >= MAXIMUM_WAIT_OBJECTS)
{
NSLog(@"Too many handles to wait for ... only using %d of %d",
MAXIMUM_WAIT_OBJECTS-1, num_handles);
num_handles = MAXIMUM_WAIT_OBJECTS-1;
}
count = num_handles - 1; // Count of handles excluding thread event
if (count > 0)
{
i = 1 + (fairStart++ % count);
hEnum = NSEnumerateMapTable(handleMap);
while (count-- > 0
&& NSNextMapEnumeratorPair(&hEnum, &handle, (void**)&watcher))
{
if (i >= num_handles)
{
i = 1;
}
handleArray[i++] = (HANDLE)handle;
}
NSEndMapTableEnumeration(&hEnum);
}
completed = NO;
/* Clear all the windows messages first before we wait,
* since MsgWaitForMultipleObjects only signals on NEW messages
*/
if ([self processAllWindowsMessages: num_winMsgs within: contexts] == YES)
{
// Processed something ... no need to wait.
wait_timeout = 0;
num_winMsgs = 0;
existingMessages = YES;
}
if (num_winMsgs > 0)
{
NSDebugMLLog(@"NSRunLoop",
@"wait for messages and %d handles for %d milliseconds",
num_handles, wait_timeout);
/*
* Wait for signalled events or window messages.
*/
wait_return = MsgWaitForMultipleObjects(num_handles, handleArray,
NO, wait_timeout, QS_ALLINPUT);
}
else if (num_handles > 0)
{
NSDebugMLLog(@"NSRunLoop",
@"wait for %d handles for %d milliseconds", num_handles, wait_timeout);
/*
* We are not interested in windows messages ... just wait for
* signalled events.
*/
wait_return = WaitForMultipleObjects(num_handles, handleArray,
NO, wait_timeout);
}
else
{
NSDebugMLLog(@"NSRunLoop",
@"wait for %d milliseconds", wait_timeout);
SleepEx(wait_timeout, TRUE);
wait_return = WAIT_TIMEOUT;
}
// check wait errors
if (WAIT_FAILED == wait_return
|| (wait_return >= WAIT_ABANDONED_0
&& wait_return < WAIT_ABANDONED_0 + num_handles))
{
int i;
BOOL found = NO;
NSDebugMLLog(@"NSRunLoop", @"WaitForMultipleObjects() error in "
@"-pollUntil:within: %@", [NSError _last]);
/*
* Check each handle in turn until either we find one which has an
* event signalled, or we find the one which caused the original
* wait to fail ... so the callback routine for that handle can
* deal with the problem.
*/
for (i = 0; i < num_handles; i++)
{
handleArray[0] = handleArray[i];
wait_return = WaitForMultipleObjects(1, handleArray, NO, 0);
if (wait_return != WAIT_TIMEOUT)
{
wait_return = WAIT_OBJECT_0;
found = YES;
break;
}
}
if (found == NO)
{
NSLog(@"WaitForMultipleObjects() error in "
@"-pollUntil:within: %@", [NSError _last]);
abort ();
}
}
/*
* Trigger any watchers which are set up to trigger for every runloop wait.
*/
count = GSIArrayCount(_trigger);
completed = NO;
while (count-- > 0)
{
GSRunLoopWatcher *watcher;
watcher = (GSRunLoopWatcher*)GSIArrayItemAtIndex(_trigger, count).obj;
if (watcher->_invalidated == NO)
{
NSDebugMLLog(@"NSRunLoop", @"trigger watcher %@", watcher);
i = [contexts count];
while (i-- > 0)
{
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
if (c != self)
{
[c endEvent: (void*)watcher for: watcher];
}
}
/*
* The watcher is still valid - so call its
* receivers event handling method.
*/
[watcher->receiver receivedEvent: watcher->data
type: watcher->type
extra: watcher->data
forMode: mode];
}
GSPrivateNotifyASAP(mode);
}
if (WAIT_TIMEOUT == wait_return)
{
// there is no event to handle
if (existingMessages)
{
NSDebugMLLog(@"NSRunLoop", @"processed windows messages");
}
else
{
NSDebugMLLog(@"NSRunLoop", @"timeout without events");
completed = YES;
return NO;
}
}
else if (WAIT_OBJECT_0 + num_handles == wait_return)
{
// one or more windows message
NSDebugMLLog(@"NSRunLoop", @"processing windows messages");
[self processAllWindowsMessages: num_winMsgs within: contexts];
}
else if ((i = wait_return - WAIT_OBJECT_0) >= 0 && i < num_handles)
{
/* Look the event that WaitForMultipleObjects() says is ready;
* get the corresponding fd for that handle event and notify
* the corresponding object for the ready fd.
*/
NSDebugMLLog(@"NSRunLoop", @"Handle signalled %d", i);
handle = handleArray[i];
if (handle == threadInfo->event)
{
watcher = nil;
NSDebugMLLog(@"NSRunLoop", @"Fire perform on thread");
[threadInfo fire];
}
else
{
watcher = (GSRunLoopWatcher*)NSMapGet(handleMap, (void*)handle);
NSDebugMLLog(@"NSRunLoop", @"Fire watcher %@", watcher);
}
if (watcher != nil && watcher->_invalidated == NO)
{
i = [contexts count];
while (i-- > 0)
{
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
if (c != self)
{
[c endEvent: (void*)handle for: watcher];
}
}
/*
* The watcher is still valid - so call its receivers
* event handling method.
*/
[watcher->receiver receivedEvent: watcher->data
type: watcher->type
extra: (void*)handle
forMode: mode];
}
}
else
{
NSDebugMLLog(@"NSRunLoop", @"unexpected result %d", wait_return);
GSPrivateNotifyASAP(mode);
completed = NO;
return NO;
}
GSPrivateNotifyASAP(mode);
completed = YES;
return YES;
}
+ (BOOL) awakenedBefore: (NSDate*)when
{
GSRunLoopThreadInfo *threadInfo = GSRunLoopInfoForThread(nil);
NSTimeInterval ti = (when == nil) ? 0.0 : [when timeIntervalSinceNow];
int milliseconds = (ti <= 0.0) ? 0 : (int)(ti*1000);
HANDLE h = threadInfo->event;
if (WaitForMultipleObjects(1, &h, NO, milliseconds) != WAIT_TIMEOUT)
{
NSDebugMLLog(@"NSRunLoop", @"Fire perform on thread");
[threadInfo fire];
return YES;
}
return NO;
}
@end

View file

@ -0,0 +1,67 @@
#
# Makefile.preamble
#
# Copyright (C) 1997 Free Software Foundation, Inc.
#
# Author: Scott Christley <scottc@net-community.com>
#
# This file is part of the GNUstep Base Library.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# If you are interested in a warranty or support for this source code,
# contact Scott Christley at scottc@net-community.com
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; see the file COPYING.LIB.
# If not, write to the Free Software Foundation,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Makefile.preamble
#
# Project specific makefile variables
#
# Do not put any Makefile rules in this file, instead they should
# be put into Makefile.postamble.
#
#
# Flags dealing with compiling and linking
#
# Additional flags to pass to the preprocessor
ADDITIONAL_CPPFLAGS = $(DEFS) \
$(WARN_FLAGS)
# Additional flags to pass to the Objective-C compiler
#ADDITIONAL_OBJCFLAGS =
ifeq ($(GNUSTEP_TARGET_OS),mingw32)
ADDITIONAL_OBJCFLAGS += -DBUILD_libgnustep_base_DLL=1
else ifeq ($(GNUSTEP_TARGET_OS),mingw64)
ADDITIONAL_OBJCFLAGS += -DBUILD_libgnustep_base_DLL=1
else ifeq ($(GNUSTEP_TARGET_OS),cygwin)
ADDITIONAL_OBJCFLAGS += -DBUILD_libgnustep_base_DLL=1
endif
# Additional flags to pass to the C compiler
ADDITIONAL_CFLAGS =
# Additional include directories the compiler should search
ADDITIONAL_INCLUDE_DIRS = -I../$(GNUSTEP_TARGET_DIR) -I../
ifeq ($(FOUNDATION_LIB),gnu)
ADDITIONAL_INCLUDE_DIRS += -I../../Headers
endif
# Additional LDFLAGS to pass to the linker
ADDITIONAL_LDFLAGS =

1156
Source/win64/NSMessagePort.m Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,433 @@
/* Implementation of message port subclass of NSPortNameServer
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
<title>NSMessagePortNameServer class reference</title>
$Date$ $Revision$
*/
#include "common.h"
#include "Foundation/NSPortNameServer.h"
#include "Foundation/NSAutoreleasePool.h"
#include "Foundation/NSDebug.h"
#include "Foundation/NSError.h"
#include "Foundation/NSException.h"
#include "Foundation/NSLock.h"
#include "Foundation/NSMapTable.h"
#include "Foundation/NSPathUtilities.h"
#include "Foundation/NSPort.h"
#include "Foundation/NSFileManager.h"
#include "Foundation/NSValue.h"
#include "Foundation/NSThread.h"
#include "Foundation/NSUserDefaults.h"
#include "GNUstepBase/GSMime.h"
#include "../GSPrivate.h"
#include "../GSPortPrivate.h"
#define UNISTR(X) \
((const unichar*)[(X) cStringUsingEncoding: NSUnicodeStringEncoding])
static NSRecursiveLock *serverLock = nil;
static NSMessagePortNameServer *defaultServer = nil;
static NSMapTable *portToNamesMap;
static NSString *registry;
static HKEY key;
static SECURITY_ATTRIBUTES security;
@interface NSMessagePortNameServer (private)
+ (NSString *) _query: (NSString *)name;
+ (NSString *) _translate: (NSString *)name;
@end
/**
* Subclass of [NSPortNameServer] taking/returning instances of [NSMessagePort].
* Port removal functionality is not supported; if you want to cancel a service,
* you have to destroy the port (invalidate the [NSMessagePort] given to
* [NSPortNameServer-registerPort:forName:]).
*/
@implementation NSMessagePortNameServer
- (void) atExit
{
NSMapEnumerator mEnum;
NSMessagePort *port;
NSString *name;
mEnum = NSEnumerateMapTable(portToNamesMap);
while (NSNextMapEnumeratorPair(&mEnum, (void *)&port, (void *)&name))
{
[defaultServer removePort: port];
}
NSEndMapTableEnumeration(&mEnum);
DESTROY(portToNamesMap);
DESTROY(serverLock);
RegCloseKey(key);
}
+ (void) initialize
{
if (self == [NSMessagePortNameServer class])
{
int rc;
serverLock = [NSRecursiveLock new];
portToNamesMap = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, 0);
[self registerAtExit];
security.nLength = sizeof(SECURITY_ATTRIBUTES);
security.lpSecurityDescriptor = 0; // Default
security.bInheritHandle = FALSE;
registry = @"Software\\GNUstepNSMessagePort";
rc = RegCreateKeyExW(
HKEY_CURRENT_USER,
UNISTR(registry),
0,
(LPWSTR) L"",
REG_OPTION_VOLATILE,
STANDARD_RIGHTS_WRITE|STANDARD_RIGHTS_READ|KEY_SET_VALUE
|KEY_QUERY_VALUE|KEY_NOTIFY,
&security,
&key,
NULL);
if (rc == ERROR_SUCCESS)
{
rc = RegFlushKey(key);
if (rc != ERROR_SUCCESS)
{
NSLog(@"Failed to flush registry HKEY_CURRENT_USER\\%@ (%x)",
registry, rc);
}
}
else
{
NSLog(@"Failed to create registry HKEY_CURRENT_USER\\%@ (%x)",
registry, rc);
}
}
}
/**
* Obtain single instance for this host.
*/
+ (id) sharedInstance
{
if (defaultServer == nil)
{
[serverLock lock];
if (defaultServer == nil)
{
defaultServer = (NSMessagePortNameServer *)NSAllocateObject(self,
0, NSDefaultMallocZone());
}
[serverLock unlock];
}
return defaultServer;
}
+ (NSString *) _query: (NSString *)name
{
NSString *mailslotName;
NSString *translatedName;
NSString *mailslotPath;
unsigned char buf[1024];
unsigned char *ptr = buf;
DWORD max = 1024;
DWORD len = 1024;
DWORD type;
HANDLE h;
int rc;
translatedName = [[self class] _translate: name];
#if 1
/* FIXME ... wierd hack.
* It appears that RegQueryValueExW does not always read from the registry,
* but will in fact return cached results (even if you close and re-open the
* registry key between the calls to RegQueryValueExW). This is a problem
* if we look up a server which is not running, and then try to look it up
* again when it is running, or if we have one address recorded but the server
* has been restarted and is using a new address.
* I couldn't find any mention of this behavior ... but accidentally discovered
* that a call to OutputDebugStringW stops it ... presumably something in the
* debug system invalidates whatever registry caching is being done.
* Anyway, on my XP SP2 system, this next line is needed to fix things.
*
* You can test this by running a GNUstep application without starting
* gdnc beforehand. If the bug is occurring, the app will try to start gdnc
* then poll to connect to it, and after 5 seconds will abort because it
* hasn't seen the gdnc port registered even though gdnc did start.
* If the hack has fixed the bug, the app will just pause briefly during
* startup (as it starts gdnc) and then continue when it finds the server
* port.
*/
OutputDebugStringW(L"");
#endif
rc = RegQueryValueExW(
key,
UNISTR(translatedName),
(LPDWORD)0,
&type,
(LPBYTE)ptr,
&len);
while (rc == ERROR_MORE_DATA)
{
if (ptr != buf)
{
free(ptr);
}
max += 1024;
ptr = malloc(max);
len = max;
rc = RegQueryValueExW(
key,
UNISTR(translatedName),
(LPDWORD)0,
&type,
(LPBYTE)ptr,
&len);
}
if (rc != ERROR_SUCCESS)
{
if (ptr != buf)
{
free(ptr);
}
return nil;
}
mailslotName = [NSString stringWithUTF8String: (const char *) ptr];
if (ptr != buf)
{
free(ptr);
}
/*
* See if we can open the port mailslot ... if not, the query returned
* an old name, and we can remove it.
*/
mailslotPath = [NSString stringWithFormat:
@"\\\\.\\mailslot\\GNUstep\\NSMessagePort\\%@", mailslotName];
h = CreateFileW(
UNISTR(mailslotPath),
GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
&security,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE)0);
if (h == INVALID_HANDLE_VALUE)
{
NSDebugLLog(@"NSMessagePortNameServer",
@"Failed to open mailslot (%@) for write on port named %@ - %@",
mailslotPath, name, [NSError _last]);
//RegDeleteValueW(key, UNISTR(n));
return nil;
}
else
{
CloseHandle(h); // OK
return mailslotName;
}
}
+ (NSString *) _translate: (NSString *)name
{
NSData *data;
/*
* Make sure name is representable in the registry ...
* assume base64 encoded strings are valid.
*/
data = [name dataUsingEncoding: NSUTF8StringEncoding];
data = [GSMimeDocument encodeBase64: data];
name = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
AUTORELEASE(name);
return name;
}
- (NSPort*) portForName: (NSString *)name
{
return [self portForName: name onHost: @""];
}
- (NSPort*) portForName: (NSString *)name
onHost: (NSString *)host
{
NSString *n;
NSDebugLLog(@"NSMessagePortNameServer",
@"portForName: %@ host: %@", name, host);
if ([host length] != 0)
{
[NSException raise: NSInvalidArgumentException
format: @"Attempt to contact a named host using a "
@"message port name server. This name server can only be used "
@"to contact processes owned by the same user on the local host "
@"(host name must be an empty string). To contact processes "
@"owned by other users or on other hosts you must use an instance "
@"of the NSSocketPortNameServer class."];
}
n = [[self class] _query: name];
if (n == nil)
{
NSDebugLLog(@"NSMessagePortNameServer", @"got no port for %@", name);
return nil;
}
else
{
NSDebugLLog(@"NSMessagePortNameServer", @"got %@ for %@", n, name);
return AUTORELEASE([NSMessagePort newWithName: n]);
}
}
- (BOOL) registerPort: (NSPort *)port
forName: (NSString *)name
{
NSMutableArray *a;
NSString *n;
int rc;
const unsigned char *str;
NSDebugLLog(@"NSMessagePortNameServer", @"register %@ as %@\n", port, name);
if ([port isKindOfClass: [NSMessagePort class]] == NO)
{
[NSException raise: NSInvalidArgumentException
format: @"Attempted to register a non-NSMessagePort (%@)",
port];
return NO;
}
if ([[self class] _query: name] != nil)
{
NSDebugLLog(@"NSMessagePortNameServer", @"fail, is a live port");
return NO;
}
n = [[self class] _translate: name];
str = (const unsigned char *) [[(NSMessagePort*)port name] UTF8String];
rc = RegSetValueExW(
key,
UNISTR(n),
0,
REG_BINARY,
str,
strlen((const char*) str)+1);
NSDebugLLog(@"NSMessagePortNameServer", @"Set port '%s' for %@", str, n);
if (rc == ERROR_SUCCESS)
{
rc = RegFlushKey(key);
if (rc != ERROR_SUCCESS)
{
NSLog(@"Failed to flush registry HKEY_CURRENT_USER\\%@\\%@ (%x)",
registry, n, rc);
}
}
else
{
NSLog(@"Failed to insert HKEY_CURRENT_USER\\%@\\%@ (%x) %@",
registry, n, rc, [NSError _last]);
return NO;
}
[serverLock lock];
a = NSMapGet(portToNamesMap, port);
if (a != nil)
{
a = [[NSMutableArray alloc] init];
NSMapInsert(portToNamesMap, port, a);
RELEASE(a);
}
[a addObject: [name copy]];
[serverLock unlock];
return YES;
}
- (BOOL) removePortForName: (NSString *)name
{
NSString *n;
NSDebugLLog(@"NSMessagePortNameServer", @"removePortForName: %@", name);
n = [[self class] _translate: name];
(void)RegDeleteValueW(key, UNISTR(n));
return YES;
}
- (NSArray *) namesForPort: (NSPort *)port
{
NSMutableArray *a;
[serverLock lock];
a = NSMapGet(portToNamesMap, port);
a = [a copy];
[serverLock unlock];
return AUTORELEASE(a);
}
- (BOOL) removePort: (NSPort *)port
{
NSMutableArray *a;
int i;
NSDebugLLog(@"NSMessagePortNameServer", @"removePort: %@", port);
[serverLock lock];
a = NSMapGet(portToNamesMap, port);
for (i = 0; i < [a count]; i++)
{
[self removePort: port forName: [a objectAtIndex: i]];
}
NSMapRemove(portToNamesMap, port);
[serverLock unlock];
return YES;
}
- (BOOL) removePort: (NSPort*)port forName: (NSString*)name
{
NSDebugLLog(@"NSMessagePortNameServer",
@"removePort: %@ forName: %@", port, name);
if ([self portForName: name onHost: @""] == port)
{
return [self removePortForName: name];
}
return NO;
}
@end

1485
Source/win64/NSStream.m Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,625 @@
#import "common.h"
#import "Foundation/NSUserDefaults.h"
#import "Foundation/NSAutoreleasePool.h"
#import "Foundation/NSException.h"
#import "Foundation/NSDictionary.h"
#import "Foundation/NSArray.h"
#import "Foundation/NSLock.h"
#import "Foundation/NSFileManager.h"
#import "Foundation/NSMapTable.h"
#import "Foundation/NSPathUtilities.h"
#import "Foundation/NSProcessInfo.h"
#define UNISTR(X) \
((const unichar*)[(X) cStringUsingEncoding: NSUnicodeStringEncoding])
extern void GSPropertyListMake(id,NSDictionary*,BOOL,BOOL,unsigned,id*);
@interface NSUserDefaults (Private)
- (id) initWithContentsOfFile: (NSString*)fielName;
@end
@interface NSUserDefaultsWin32 : NSUserDefaults
{
NSString *registryPrefix;
NSMapTable *registryInfo;
}
@end
@interface NSUserDefaults (Secrets)
- (id) initWithContentsOfFile: (NSString*)aPath;
- (BOOL) lockDefaultsFile: (BOOL*)wasLocked;
- (void) unlockDefaultsFile;
- (NSMutableDictionary*) readDefaults;
- (BOOL) wantToReadDefaultsSince: (NSDate*)lastSyncDate;
- (BOOL) writeDefaults: (NSDictionary*)defaults oldData: (NSDictionary*)oldData;
@end
struct NSUserDefaultsWin32_DomainInfo
{
HKEY userKey;
HKEY systemKey;
};
@implementation NSUserDefaultsWin32
- (void) dealloc
{
DESTROY(registryPrefix);
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)
{
NSString *dPath;
dPath = [registryPrefix stringByAppendingString: domain];
NSLog(@"Failed to close registry HKEY_CURRENT_USER\\%@ (%x)",
dPath, rc);
}
}
if (dinfo->systemKey)
{
rc = RegCloseKey(dinfo->systemKey);
if (rc != ERROR_SUCCESS)
{
NSString *dPath;
dPath = [registryPrefix stringByAppendingString: domain];
NSLog(@"Failed to close registry HKEY_LOCAL_MACHINE\\%@ (%x)",
dPath, rc);
}
}
}
NSEndMapTableEnumeration(&iter);
NSResetMapTable(registryInfo);
NSFreeMapTable(registryInfo);
registryInfo = 0;
}
[super dealloc];
}
- (id) initWithUser: (NSString*)userName
{
NSString *path;
NSRange r;
NSAssert([userName isEqual: NSUserName()],
@"NSUserDefaultsWin32 doesn't support reading/writing to users other than the current user.");
path = GSDefaultsRootForUser(userName);
r = [path rangeOfString: @":REGISTRY:"];
NSAssert(r.length > 0,
@"NSUserDefaultsWin32 should only be used if defaults directory is :REGISTRY:");
path = [path substringFromIndex: NSMaxRange(r)];
if ([path length] == 0)
{
path = @"Software\\GNUstep\\";
}
else if ([path hasSuffix: @"\\"] == NO)
{
path = [path stringByAppendingString: @"\\"];
}
registryPrefix = RETAIN(path);
self = [super initWithContentsOfFile: @":REGISTRY:"];
return self;
}
- (BOOL) lockDefaultsFile: (BOOL*)wasLocked
{
*wasLocked = NO;
return YES;
}
- (NSMutableDictionary*) readDefaults
{
NSArray *allDomains;
NSEnumerator *iter;
NSString *persistentDomain;
NSMutableDictionary *newDict = nil;
allDomains = [self persistentDomainNames];
if ([allDomains count] == 0)
{
allDomains = [NSArray arrayWithObjects:
[[NSProcessInfo processInfo] processName],
NSGlobalDomain,
nil];
}
if (registryInfo == 0)
{
registryInfo = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSOwnedPointerMapValueCallBacks, [allDomains count]);
}
newDict = [NSMutableDictionary dictionary];
iter = [allDomains objectEnumerator];
while ((persistentDomain = [iter nextObject]) != nil)
{
NSMutableDictionary *domainDict;
struct NSUserDefaultsWin32_DomainInfo *dinfo;
NSString *dPath;
LONG rc;
dinfo = NSMapGet(registryInfo, persistentDomain);
if (dinfo == 0)
{
dinfo = calloc(sizeof(struct NSUserDefaultsWin32_DomainInfo), 1);
NSMapInsertKnownAbsent(registryInfo, persistentDomain, dinfo);
}
dPath = [registryPrefix stringByAppendingString: persistentDomain];
if (dinfo->userKey == 0)
{
rc = RegOpenKeyExW(HKEY_CURRENT_USER,
UNISTR(dPath),
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)",
dPath, rc);
return nil;
}
}
if (dinfo->systemKey == 0)
{
rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
UNISTR(dPath),
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)",
dPath, rc);
return nil;
}
}
domainDict = [newDict objectForKey: persistentDomain];
if (domainDict == nil)
{
domainDict = [NSMutableDictionary dictionary];
[newDict setObject: domainDict forKey: persistentDomain];
}
if (dinfo->systemKey)
{
DWORD i = 0;
unichar *name = malloc(200);
unichar *data = malloc(1000);
DWORD namelenbuf = 100, datalenbuf = 1000;
DWORD type;
do
{
DWORD namelen = namelenbuf, datalen = datalenbuf;
rc = RegEnumValueW(dinfo->systemKey,
i,
name,
&namelen,
NULL,
&type,
(void*)data,
&datalen);
if (rc == ERROR_SUCCESS)
{
NS_DURING
{
id v;
NSString *k;
switch (type)
{
case REG_SZ:
{
int datacharlen = datalen / 2;
if (datacharlen > 0 && data[datacharlen-1] == 0)
datacharlen--;
v = [NSString stringWithCharacters: data
length: datacharlen];
}
break;
case REG_BINARY:
{
v = [NSString stringWithCString: (char*)data
encoding: NSASCIIStringEncoding];
}
break;
default:
NSLog(@"Bad registry type %d for '%S'", type, name);
v = 0;
}
v = [v propertyList];
if (v)
{
k = [NSString stringWithCharacters: name
length: namelen];
[domainDict setObject: v forKey: k];
}
}
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 * sizeof(unichar));
}
if (datalen >= datalenbuf)
{
datalenbuf = datalen + 1;
data = realloc(data, datalenbuf);
}
continue;
}
else if (rc == ERROR_NO_MORE_ITEMS)
{
break;
}
else
{
NSLog(@"RegEnumValueW error %d", rc);
break;
}
i++;
} while (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA);
free(name);
free(data);
}
if (dinfo->userKey)
{
DWORD i = 0;
unichar *name = malloc(200);
unichar *data = malloc(1000);
DWORD namelenbuf = 100, datalenbuf = 1000;
DWORD type;
do
{
DWORD namelen = namelenbuf, datalen = datalenbuf;
// RegEnumValueW returns the data as a wide string
// but returns the length in bytes.
// To add insult to injury, datalen includes the terminating
// NULL character, unless there isn't enough room, in which
// case it doesn't.
rc = RegEnumValueW(dinfo->userKey,
i,
name,
&namelen,
NULL,
&type,
(void*)data,
&datalen);
if (rc == ERROR_SUCCESS)
{
NS_DURING
{
id v;
NSString *k;
switch (type)
{
case REG_SZ:
{
int datacharlen = datalen / 2;
if (datacharlen > 0 && data[datacharlen-1] == 0)
datacharlen--;
v = [NSString stringWithCharacters: data
length: datacharlen];
}
break;
case REG_BINARY:
{
v = [NSString stringWithCString: (char*)data
encoding: NSASCIIStringEncoding];
}
break;
default:
NSLog(@"Bad registry type %d for '%S'", type, name);
v = 0;
}
v = [v propertyList];
if (v)
{
k = [NSString stringWithCharacters: name
length: namelen];
[domainDict setObject: v forKey: k];
}
}
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 * sizeof(unichar));
}
if (datalen >= datalenbuf)
{
datalenbuf = datalen + 1;
data = realloc(data, datalenbuf);
}
continue;
}
else if (rc == ERROR_NO_MORE_ITEMS)
{
break;
}
else
{
NSLog(@"RegEnumValueW error %d", rc);
break;
}
i++;
} while (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA);
free(name);
free(data);
}
}
return newDict;
}
- (void) unlockDefaultsFile
{
return;
}
- (BOOL) wantToReadDefaultsSince: (NSDate*)lastSyncDate
{
if (lastSyncDate != nil && registryInfo != 0)
{
// Detect changes in the registry
NSMapEnumerator iter;
NSString *domain;
struct NSUserDefaultsWin32_DomainInfo *dinfo;
iter = NSEnumerateMapTable(registryInfo);
while (NSNextMapEnumeratorPair(&iter, (void**)&domain, (void**)&dinfo))
{
ULARGE_INTEGER lasttime;
LONG rc;
NSTimeInterval ti;
NSString *dPath;
dPath = [registryPrefix stringByAppendingString: domain];
if (dinfo->userKey)
{
rc = RegQueryInfoKey(dinfo->userKey,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL,NULL, NULL, (PFILETIME)&lasttime);
if (rc != ERROR_SUCCESS)
{
NSString *dName = [@"HKEY_CURRENT_USER\\"
stringByAppendingString: dPath];
NSLog(@"Failed to query modify time on registry %@ (%x)",
dName, rc);
NSEndMapTableEnumeration(&iter);
return YES;
}
ti = -12622780800.0 + lasttime.QuadPart / 10000000.0;
if ([lastSyncDate timeIntervalSinceReferenceDate] < ti)
{
NSEndMapTableEnumeration(&iter);
return YES;
}
}
else
{
// If the key didn't exist, but now it does, we want to read it.
rc = RegOpenKeyExW(HKEY_CURRENT_USER,
UNISTR(dPath),
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)
{
NSString *dName = [@"HKEY_CURRENT_USER\\"
stringByAppendingString: dPath];
NSLog(@"Failed to open registry %@ (%x)", dName, rc);
}
else
{
NSEndMapTableEnumeration(&iter);
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 time on HKEY_LOCAL_MACHINE\\%@ (%x)",
dPath, rc);
NSEndMapTableEnumeration(&iter);
return YES;
}
ti = -12622780800.0 + lasttime.QuadPart / 10000000.0;
if ([lastSyncDate timeIntervalSinceReferenceDate] < ti)
{
NSEndMapTableEnumeration(&iter);
return YES;
}
}
else
{
// If the key didn't exist, but now it does, we want to read it.
rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
UNISTR(dPath),
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)",
dPath, rc);
}
else
{
NSEndMapTableEnumeration(&iter);
return YES;
}
}
}
NSEndMapTableEnumeration(&iter);
return NO;
}
return YES;
}
- (BOOL) writeDefaults: (NSDictionary*)defaults oldData: (NSDictionary*)oldData
{
NSEnumerator *iter;
NSString *persistentDomain;
if (registryInfo == 0)
{
registryInfo = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSOwnedPointerMapValueCallBacks, [defaults count]);
}
iter = [defaults keyEnumerator];
while ((persistentDomain = [iter nextObject]) != nil)
{
struct NSUserDefaultsWin32_DomainInfo *dinfo;
NSDictionary *domainDict;
NSDictionary *oldDomainDict;
NSString *dPath;
LONG rc;
NSEnumerator *valIter;
NSString *valName;
dinfo = NSMapGet(registryInfo, persistentDomain);
if (dinfo == 0)
{
dinfo = calloc(sizeof(struct NSUserDefaultsWin32_DomainInfo), 1);
NSMapInsertKnownAbsent(registryInfo, persistentDomain, dinfo);
}
domainDict = [defaults objectForKey: persistentDomain];
oldDomainDict = [oldData objectForKey: persistentDomain];
dPath = [registryPrefix stringByAppendingString: persistentDomain];
if ([domainDict count] == 0)
{
continue;
}
if (dinfo->userKey == 0)
{
rc = RegCreateKeyExW(HKEY_CURRENT_USER,
UNISTR(dPath),
0,
(LPWSTR) L"",
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)",
dPath, rc);
return NO;
}
}
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 = nil;
const unichar *ptr;
GSPropertyListMake(value, nil, NO, NO, 0, &result);
ptr = UNISTR(result);
rc = RegSetValueExW(dinfo->userKey,
UNISTR(valName),
0,
REG_SZ,
(void*)ptr,
2*(wcslen(ptr) + 1));
if (rc != ERROR_SUCCESS)
{
NSLog(@"Failed to insert HKEY_CURRENT_USER\\%@\\%@ (%x)",
dPath, valName, rc);
return NO;
}
}
}
// Enumerate over the oldvalues and delete the deleted keys.
valIter = [oldDomainDict keyEnumerator];
while ((valName = [valIter nextObject]) != nil)
{
if ([domainDict objectForKey: valName] == nil)
{
// Delete value from registry
rc = RegDeleteValueW(dinfo->userKey, UNISTR(valName));
if (rc != ERROR_SUCCESS)
{
NSLog(@"Failed to delete HKEY_CURRENT_USER\\%@\\%@ (%x)",
dPath, valName, rc);
return NO;
}
}
}
}
return YES;
}
@end