mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Add default to enable mingw32 message ports
Do some debugging/fixing of mingw32 message ports. Still not usable. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21974 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
c52e8be2d6
commit
4f6fee1ae5
4 changed files with 271 additions and 184 deletions
|
@ -74,8 +74,7 @@ Class NSPort_concrete_class;
|
|||
{
|
||||
NSPort_abstract_class = self;
|
||||
#ifndef __MINGW32__
|
||||
/* Must be kept in sync with [NSPortNameServer
|
||||
+systemDefaultPortNameServer]. */
|
||||
/* Must be kept in sync with [NSPortNameServer +systemDefaultPortNameServer]. */
|
||||
if (GSUserDefaultsFlag(GSMacOSXCompatible) == YES
|
||||
|| [[NSUserDefaults standardUserDefaults]
|
||||
boolForKey: @"NSPortIsMessagePort"])
|
||||
|
@ -87,6 +86,11 @@ Class NSPort_concrete_class;
|
|||
NSPort_concrete_class = [NSSocketPort class];
|
||||
}
|
||||
#else
|
||||
if ([[NSUserDefaults standardUserDefaults]
|
||||
boolForKey: @"GSMailslot"] == YES)
|
||||
NSPort_concrete_class = [NSMessagePort class];
|
||||
else
|
||||
|
||||
NSPort_concrete_class = [NSSocketPort class];
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -66,6 +66,13 @@
|
|||
*/
|
||||
+ (id) systemDefaultPortNameServer
|
||||
{
|
||||
#if defined(__MINGW__)
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey: @"GSMailslot"] == YES)
|
||||
{
|
||||
return [NSMessagePortNameServer sharedInstance];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Must be kept in sync with [NSPort +initialize]. */
|
||||
if (GSUserDefaultsFlag(GSMacOSXCompatible) == YES)
|
||||
{
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#define UNISTR(X) \
|
||||
((const unichar*)[(X) cStringUsingEncoding: NSUnicodeStringEncoding])
|
||||
|
||||
extern int errno;
|
||||
|
||||
static NSRecursiveLock *serverLock = nil;
|
||||
static NSMessagePortNameServer *defaultServer = nil;
|
||||
static NSMapTable portToNamesMap;
|
||||
|
@ -68,6 +70,7 @@ static void clean_up_names(void)
|
|||
}
|
||||
NSEndMapTableEnumeration(&mEnum);
|
||||
DESTROY(arp);
|
||||
RegCloseKey(key);
|
||||
if (unknownThread == YES)
|
||||
{
|
||||
GSUnregisterCurrentThread();
|
||||
|
@ -93,18 +96,28 @@ static void clean_up_names(void)
|
|||
NSObjectMapValueCallBacks, 0);
|
||||
atexit(clean_up_names);
|
||||
|
||||
registry = @"Software\\GNUstepNSMessagePort\\";
|
||||
rc = RegCreateKeyExW(HKEY_CURRENT_USER,
|
||||
registry = @"Software\\GNUstepNSMessagePort";
|
||||
rc = RegCreateKeyExW(
|
||||
HKEY_CURRENT_USER,
|
||||
UNISTR(registry),
|
||||
0,
|
||||
L"",
|
||||
REG_OPTION_VOLATILE,
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
STANDARD_RIGHTS_WRITE|STANDARD_RIGHTS_READ|KEY_SET_VALUE
|
||||
|KEY_QUERY_VALUE,
|
||||
NULL,
|
||||
&key,
|
||||
NULL);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
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);
|
||||
|
@ -134,30 +147,53 @@ static void clean_up_names(void)
|
|||
+ (NSString *) _query: (NSString *)name
|
||||
{
|
||||
NSString *n;
|
||||
unsigned char buf[24];
|
||||
DWORD len = 24;
|
||||
NSString *p;
|
||||
unsigned char buf[25];
|
||||
DWORD len = 25;
|
||||
DWORD type;
|
||||
HANDLE h;
|
||||
int rc;
|
||||
|
||||
n = [[self class] _translate: name];
|
||||
|
||||
rc = RegQueryValueExW(key,
|
||||
rc = RegQueryValueExW(
|
||||
key,
|
||||
UNISTR(n),
|
||||
(LPDWORD)0,
|
||||
(LPDWORD)REG_BINARY,
|
||||
&type,
|
||||
(LPBYTE)buf,
|
||||
&len);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
NSLog(@"Failed to read HKEY_CURRENT_USER\\%@\\%@ (%x)",
|
||||
registry, n, rc);
|
||||
return nil;
|
||||
}
|
||||
|
||||
n = AUTORELEASE([[NSString alloc] initWithBytes: buf
|
||||
length: 24
|
||||
encoding: NSASCIIStringEncoding]);
|
||||
// Fixme ... check this is valid
|
||||
return n;
|
||||
n = [NSString stringWithUTF8String: buf];
|
||||
|
||||
/*
|
||||
* See if we can open the mailslot ... if not, the query returned
|
||||
* an old name, and we can remove it.
|
||||
*/
|
||||
p = [NSString stringWithFormat:
|
||||
@"\\\\.\\mailslot\\GNUstep\\NSMessagePort\\%@", n];
|
||||
h = CreateFileW(
|
||||
UNISTR(p),
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
(LPSECURITY_ATTRIBUTES)0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
(HANDLE)0);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
RegDeleteValueW(key, UNISTR(n));
|
||||
return nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseHandle(h); // OK
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSString *) _translate: (NSString *)name
|
||||
|
@ -190,7 +226,6 @@ static void clean_up_names(void)
|
|||
NSMutableArray *a;
|
||||
NSString *n;
|
||||
int rc;
|
||||
HKEY key;
|
||||
|
||||
NSDebugLLog(@"NSMessagePort", @"register %@ as %@\n", port, name);
|
||||
if ([port isKindOfClass: [NSMessagePort class]] == NO)
|
||||
|
@ -209,16 +244,26 @@ static void clean_up_names(void)
|
|||
|
||||
n = [[self class] _translate: name];
|
||||
|
||||
rc = RegSetValueExW(key,
|
||||
rc = RegSetValueExW(
|
||||
key,
|
||||
UNISTR(n),
|
||||
0,
|
||||
REG_SZ,
|
||||
REG_BINARY,
|
||||
[[(NSMessagePort*)port name] UTF8String],
|
||||
25);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
if (rc == ERROR_SUCCESS)
|
||||
{
|
||||
NSLog(@"Failed to insert HKEY_CURRENT_USER\\%@\\%@ (%x)",
|
||||
registry, n, rc);
|
||||
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) %s",
|
||||
registry, n, rc, GSLastErrorStr(rc));
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
|
|
@ -272,6 +272,7 @@ static unsigned wordAlign;
|
|||
static unsigned sequence = 0;
|
||||
static int ident;
|
||||
internal *this;
|
||||
NSString *path;
|
||||
|
||||
if (sequence == 0)
|
||||
{
|
||||
|
@ -296,8 +297,11 @@ static unsigned wordAlign;
|
|||
this->lock = [GSLazyRecursiveLock new];
|
||||
this->rData = [NSMutableData new];
|
||||
|
||||
path = [NSString stringWithFormat:
|
||||
@"\\\\.\\mailslot\\GNUstep\\NSMessagePort\\%@", this->name];
|
||||
|
||||
this->handle = CreateMailslotW(
|
||||
UNISTR(this->name),
|
||||
UNISTR(path),
|
||||
0, /* No max message size. */
|
||||
MAILSLOT_WAIT_FOREVER, /* No read/write timeout. */
|
||||
(LPSECURITY_ATTRIBUTES)0);
|
||||
|
@ -338,6 +342,7 @@ static unsigned wordAlign;
|
|||
if (p == nil)
|
||||
{
|
||||
internal *this;
|
||||
NSString *path;
|
||||
|
||||
_internal = NSZoneMalloc(NSDefaultMallocZone(), sizeof(internal));
|
||||
memset(_internal, '\0', sizeof(internal));
|
||||
|
@ -350,9 +355,11 @@ static unsigned wordAlign;
|
|||
this->ov.hEvent = this->event;
|
||||
this->lock = [GSLazyRecursiveLock new];
|
||||
this->wMsgs = [NSMutableArray new];
|
||||
path = [NSString stringWithFormat:
|
||||
@"\\\\.\\mailslot\\GNUstep\\NSMessagePort\\%@", this->name];
|
||||
|
||||
this->handle = CreateFileW(
|
||||
UNISTR(this->name),
|
||||
UNISTR(path),
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
(LPSECURITY_ATTRIBUTES)0,
|
||||
|
@ -456,183 +463,199 @@ static unsigned wordAlign;
|
|||
|
||||
M_LOCK(this->lock);
|
||||
|
||||
/*
|
||||
* Got something ... is it all we want?
|
||||
*/
|
||||
this->rLength += this->size;
|
||||
this->size = 0;
|
||||
|
||||
/*
|
||||
* Do next part only if we have completed a read.
|
||||
*/
|
||||
if (this->rWant > 0 && this->rLength == this->rWant)
|
||||
if (this->rWant > 0)
|
||||
{
|
||||
switch (this->rType)
|
||||
|
||||
/*
|
||||
* Have we read something?
|
||||
*/
|
||||
if (GetOverlappedResult(
|
||||
this->handle,
|
||||
&this->ov,
|
||||
&this->size,
|
||||
TRUE) == 0)
|
||||
{
|
||||
case GSP_ITEM:
|
||||
NSLog(@"GetOverlappedResult failed ...%s", GSLastErrorStr(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->rLength += this->size;
|
||||
this->size = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do next part only if we have completed a read.
|
||||
*/
|
||||
if (this->rLength == this->rWant)
|
||||
{
|
||||
switch (this->rType)
|
||||
{
|
||||
GSPortItemHeader *h;
|
||||
unsigned l;
|
||||
case GSP_ITEM:
|
||||
{
|
||||
GSPortItemHeader *h;
|
||||
unsigned l;
|
||||
|
||||
/*
|
||||
* We have read an item header - set up to read the
|
||||
* remainder of the item.
|
||||
*/
|
||||
h = (GSPortItemHeader*)[this->rData bytes];
|
||||
this->rType = GSSwapBigI32ToHost(h->type);
|
||||
l = GSSwapBigI32ToHost(h->length);
|
||||
if (this->rType == GSP_HEAD)
|
||||
{
|
||||
if (l + sizeof(GSPortItemHeader) > this->rWant)
|
||||
/*
|
||||
* We have read an item header - set up to read the
|
||||
* remainder of the item.
|
||||
*/
|
||||
h = (GSPortItemHeader*)[this->rData bytes];
|
||||
this->rType = GSSwapBigI32ToHost(h->type);
|
||||
l = GSSwapBigI32ToHost(h->length);
|
||||
if (this->rType == GSP_HEAD)
|
||||
{
|
||||
// There is more to read ... do it.
|
||||
this->rWant = l + sizeof(GSPortItemHeader);
|
||||
this->rType = GSP_HEAD;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto gsp_head;
|
||||
}
|
||||
}
|
||||
else if (this->rType == GSP_PORT)
|
||||
{
|
||||
if (l != 24)
|
||||
{
|
||||
NSLog(@"%@ - unreasonable length (%u) for port", self, l);
|
||||
[self invalidate];
|
||||
break;
|
||||
}
|
||||
this->rWant = l;
|
||||
[this->rData setLength: this->rWant];
|
||||
}
|
||||
else if (this->rType == GSP_DATA)
|
||||
{
|
||||
if (l == 0)
|
||||
{
|
||||
NSData *d;
|
||||
|
||||
/*
|
||||
* For a zero-length data chunk, we create an empty
|
||||
* data object and add it to the current message.
|
||||
*/
|
||||
d = [NSMutableData new];
|
||||
[this->rItems addObject: d];
|
||||
RELEASE(d);
|
||||
if (this->nItems == [this->rItems count])
|
||||
if (l + sizeof(GSPortItemHeader) > this->rWant)
|
||||
{
|
||||
shouldDispatch = YES;
|
||||
// There is more to read ... do it.
|
||||
this->rWant = l + sizeof(GSPortItemHeader);
|
||||
this->rType = GSP_HEAD;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto gsp_head;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (this->rType == GSP_PORT)
|
||||
{
|
||||
if (l > maxDataLength)
|
||||
if (l != 24)
|
||||
{
|
||||
NSLog(@"%@ - unreasonable length (%u) for data",
|
||||
self, l);
|
||||
NSLog(@"%@ - unreasonable length (%u) for port",
|
||||
self, l);
|
||||
[self invalidate];
|
||||
break;
|
||||
}
|
||||
this->rWant = l;
|
||||
[this->rData setLength: this->rWant];
|
||||
}
|
||||
else if (this->rType == GSP_DATA)
|
||||
{
|
||||
if (l == 0)
|
||||
{
|
||||
NSData *d;
|
||||
|
||||
/*
|
||||
* For a zero-length data chunk, we create an empty
|
||||
* data object and add it to the current message.
|
||||
*/
|
||||
d = [NSMutableData new];
|
||||
[this->rItems addObject: d];
|
||||
RELEASE(d);
|
||||
if (this->nItems == [this->rItems count])
|
||||
{
|
||||
shouldDispatch = YES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (l > maxDataLength)
|
||||
{
|
||||
NSLog(@"%@ - unreasonable length (%u) for data",
|
||||
self, l);
|
||||
[self invalidate];
|
||||
break;
|
||||
}
|
||||
this->rWant = l;
|
||||
[this->rData setLength: this->rWant];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"%@ - bad data received on port handle", self);
|
||||
[self invalidate];
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
case GSP_HEAD:
|
||||
gsp_head:
|
||||
{
|
||||
NSLog(@"%@ - bad data received on port handle", self);
|
||||
[self invalidate];
|
||||
return;
|
||||
unsigned char *b = [this->rData mutableBytes];
|
||||
GSPortItemHeader *pih;
|
||||
GSPortMsgHeader *pmh;
|
||||
NSString *n;
|
||||
NSMessagePort *p;
|
||||
unsigned l;
|
||||
NSMutableData *d;
|
||||
|
||||
pih = (GSPortItemHeader*)b;
|
||||
l = GSSwapBigI32ToHost(pih->length);
|
||||
pmh = (GSPortMsgHeader*)(b + sizeof(GSPortItemHeader));
|
||||
this->rId = GSSwapBigI32ToHost(pmh->mId);
|
||||
this->nItems = GSSwapBigI32ToHost(pmh->nItems);
|
||||
if (this->nItems == 0)
|
||||
{
|
||||
NSLog(@"%@ - unable to decode remote port", self);
|
||||
[self invalidate];
|
||||
break;
|
||||
}
|
||||
n = [[NSString alloc] initWithBytes: pmh->port
|
||||
length: 24
|
||||
encoding: NSASCIIStringEncoding];
|
||||
NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n);
|
||||
p = [NSMessagePort sendPort: n];
|
||||
RELEASE(n);
|
||||
if (p == nil)
|
||||
{
|
||||
NSLog(@"%@ - unable to decode remote port", self);
|
||||
[self invalidate];
|
||||
break;
|
||||
}
|
||||
ASSIGN(this->rPort, p);
|
||||
this->rItems
|
||||
= [NSMutableArray allocWithZone: NSDefaultMallocZone()];
|
||||
this->rItems = [this->rItems initWithCapacity: this->nItems];
|
||||
b = (unsigned char*)&pmh[1];
|
||||
l -= sizeof(GSPortMsgHeader);
|
||||
d = [[NSMutableData alloc] initWithBytes: b length: l];
|
||||
[this->rItems addObject: d];
|
||||
RELEASE(d);
|
||||
if (this->nItems == [this->rItems count])
|
||||
{
|
||||
shouldDispatch = YES;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GSP_DATA:
|
||||
{
|
||||
NSMutableData *d;
|
||||
|
||||
d = [this->rData mutableCopy];
|
||||
[this->rItems addObject: d];
|
||||
RELEASE(d);
|
||||
if (this->nItems == [this->rItems count])
|
||||
{
|
||||
shouldDispatch = YES;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GSP_PORT:
|
||||
{
|
||||
NSMessagePort *p;
|
||||
NSString *n;
|
||||
|
||||
n = [[NSString alloc] initWithBytes: [this->rData bytes]
|
||||
length: 24
|
||||
encoding: NSASCIIStringEncoding];
|
||||
NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n);
|
||||
p = [NSMessagePort sendPort: n];
|
||||
RELEASE(n);
|
||||
if (p == nil)
|
||||
{
|
||||
NSLog(@"%@ - unable to decode remote port", self);
|
||||
[self invalidate];
|
||||
break;
|
||||
}
|
||||
[this->rItems addObject: p];
|
||||
if (this->nItems == [this->rItems count])
|
||||
{
|
||||
shouldDispatch = YES;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case GSP_HEAD:
|
||||
gsp_head:
|
||||
{
|
||||
unsigned char *b = [this->rData mutableBytes];
|
||||
GSPortItemHeader *pih;
|
||||
GSPortMsgHeader *pmh;
|
||||
NSString *n;
|
||||
NSMessagePort *p;
|
||||
unsigned l;
|
||||
NSMutableData *d;
|
||||
|
||||
pih = (GSPortItemHeader*)b;
|
||||
l = GSSwapBigI32ToHost(pih->length);
|
||||
pmh = (GSPortMsgHeader*)(b + sizeof(GSPortItemHeader));
|
||||
this->rId = GSSwapBigI32ToHost(pmh->mId);
|
||||
this->nItems = GSSwapBigI32ToHost(pmh->nItems);
|
||||
if (this->nItems == 0)
|
||||
{
|
||||
NSLog(@"%@ - unable to decode remote port", self);
|
||||
[self invalidate];
|
||||
break;
|
||||
}
|
||||
n = [[NSString alloc] initWithBytes: pmh->port
|
||||
length: 24
|
||||
encoding: NSASCIIStringEncoding];
|
||||
NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n);
|
||||
p = [NSMessagePort sendPort: n];
|
||||
RELEASE(n);
|
||||
if (p == nil)
|
||||
{
|
||||
NSLog(@"%@ - unable to decode remote port", self);
|
||||
[self invalidate];
|
||||
break;
|
||||
}
|
||||
ASSIGN(this->rPort, p);
|
||||
this->rItems
|
||||
= [NSMutableArray allocWithZone: NSDefaultMallocZone()];
|
||||
this->rItems = [this->rItems initWithCapacity: this->nItems];
|
||||
b = (unsigned char*)&pmh[1];
|
||||
l -= sizeof(GSPortMsgHeader);
|
||||
d = [[NSMutableData alloc] initWithBytes: b length: l];
|
||||
[this->rItems addObject: d];
|
||||
RELEASE(d);
|
||||
if (this->nItems == [this->rItems count])
|
||||
{
|
||||
shouldDispatch = YES;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GSP_DATA:
|
||||
{
|
||||
NSMutableData *d;
|
||||
|
||||
d = [this->rData mutableCopy];
|
||||
[this->rItems addObject: d];
|
||||
RELEASE(d);
|
||||
if (this->nItems == [this->rItems count])
|
||||
{
|
||||
shouldDispatch = YES;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GSP_PORT:
|
||||
{
|
||||
NSMessagePort *p;
|
||||
NSString *n;
|
||||
|
||||
n = [[NSString alloc] initWithBytes: [this->rData bytes]
|
||||
length: 24
|
||||
encoding: NSASCIIStringEncoding];
|
||||
NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n);
|
||||
p = [NSMessagePort sendPort: n];
|
||||
RELEASE(n);
|
||||
if (p == nil)
|
||||
{
|
||||
NSLog(@"%@ - unable to decode remote port", self);
|
||||
[self invalidate];
|
||||
break;
|
||||
}
|
||||
[this->rItems addObject: p];
|
||||
if (this->nItems == [this->rItems count])
|
||||
{
|
||||
shouldDispatch = YES;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -684,14 +707,22 @@ static unsigned wordAlign;
|
|||
*/
|
||||
if ([self isValid] == YES && this->rLength < this->rWant)
|
||||
{
|
||||
int rc;
|
||||
|
||||
this->ov.Offset = 0;
|
||||
this->ov.OffsetHigh = 0;
|
||||
this->ov.hEvent = this->event;
|
||||
if (ReadFile(this->handle,
|
||||
rc = ReadFile(this->handle,
|
||||
[this->rData mutableBytes], // Store results here
|
||||
this->rWant - this->rLength,
|
||||
&this->size,
|
||||
&this->ov) == 0 && (errno = GetLastError()) != ERROR_HANDLE_EOF)
|
||||
&this->ov);
|
||||
|
||||
if (rc > 0)
|
||||
{
|
||||
[self receivedEventRead]; // Read completed synchronously
|
||||
}
|
||||
else if ((errno = GetLastError()) != ERROR_IO_PENDING)
|
||||
{
|
||||
NSLog(@"unable to read from mailslot '%@' - %s",
|
||||
this->name, GSLastErrorStr(errno));
|
||||
|
|
Loading…
Reference in a new issue