Win32OperatingSystem.st
branchjv
changeset 18120 e3a375d5f6a8
parent 18117 eb433f2c42b2
parent 17632 0f6674a899a0
child 18339 fc6fd2a3fc53
--- a/Win32OperatingSystem.st	Tue Feb 04 21:09:59 2014 +0100
+++ b/Win32OperatingSystem.st	Wed Apr 01 10:20:10 2015 +0100
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
 "
  COPYRIGHT (c) 1988 by Claus Gittinger
  COPYRIGHT (c) 1998-2004 by eXept Software AG
@@ -12,9 +14,12 @@
 "
 "{ Package: 'stx:libbasic' }"
 
+"{ NameSpace: Smalltalk }"
+
 AbstractOperatingSystem subclass:#Win32OperatingSystem
 	instanceVariableNames:''
-	classVariableNames:'Initialized HostName DomainName CurrentDirectory'
+	classVariableNames:'Initialized HostName DomainName CurrentDirectory LastOsTimeLow
+		LastOsTimeHi LastTimeInfoIsLocal LastTimeInfo'
 	poolDictionaries:'Win32Constants'
 	category:'OS-Windows'
 !
@@ -48,6 +53,32 @@
 	privateIn:Win32OperatingSystem
 !
 
+SharedPool subclass:#PECOFFConstants
+	instanceVariableNames:''
+	classVariableNames:'PE_Signature_OFFSET_OFFSET PE_Signature COFF_HEADER_SIZE
+		COFF_HEADER_Machine_OFFSET IMAGE_FILE_MACHINE_UNKNOWN
+		IMAGE_FILE_MACHINE_AM33 IMAGE_FILE_MACHINE_AMD64
+		IMAGE_FILE_MACHINE_ARM IMAGE_FILE_MACHINE_ARMNT
+		IMAGE_FILE_MACHINE_ARM64 IMAGE_FILE_MACHINE_EBC
+		IMAGE_FILE_MACHINE_I386 IMAGE_FILE_MACHINE_IA64
+		IMAGE_FILE_MACHINE_M32R IMAGE_FILE_MACHINE_MIPS16
+		IMAGE_FILE_MACHINE_MIPSFPU IMAGE_FILE_MACHINE_MIPSFPU16
+		IMAGE_FILE_MACHINE_POWERPC IMAGE_FILE_MACHINE_POWEPCFP
+		IMAGE_FILE_MACHINE_R4000 IMAGE_FILE_MACHINE_SH3
+		IMAGE_FILE_MACHINE_SH3DSP IMAGE_FILE_MACHINE_SH4
+		IMAGE_FILE_MACHINE_SH5 IMAGE_FILE_MACHINE_THUMB
+		IMAGE_FILE_MACHINE_WCEMIPSV2'
+	poolDictionaries:''
+	privateIn:Win32OperatingSystem
+!
+
+Object subclass:#PECOFFFileHeader
+	instanceVariableNames:'file data'
+	classVariableNames:''
+	poolDictionaries:'Win32OperatingSystem::PECOFFConstants'
+	privateIn:Win32OperatingSystem
+!
+
 Object subclass:#PerformanceData
 	instanceVariableNames:'objectArray perfTime perfFreq perfTime100nSec'
 	classVariableNames:'PerformanceText CounterIndexTextDictionary
@@ -113,7 +144,7 @@
 !
 
 Object subclass:#RegistryEntry
-	instanceVariableNames:'path handle'
+	instanceVariableNames:'path handle isNew'
 	classVariableNames:'Lobby HKEY_CLASSES_ROOT HKEY_CURRENT_USER HKEY_LOCAL_MACHINE
 		HKEY_USERS HKEY_PERFORMANCE_DATA HKEY_CURRENT_CONFIG
 		HKEY_DYN_DATA HKEY_PERFORMANCE_TEXT HKEY_PERFORMANCE_NLSTEXT'
@@ -128,7 +159,7 @@
 	privateIn:Win32OperatingSystem
 !
 
-OSHandle subclass:#Win32IOHandle
+Win32Handle subclass:#Win32IOHandle
 	instanceVariableNames:''
 	classVariableNames:'Lobby'
 	poolDictionaries:''
@@ -453,6 +484,7 @@
 
 #define _HANDLEVal(o)        (HANDLE)(__externalAddressVal(o))
 #define _SETHANDLEVal(o, v)  (__externalAddressVal(o) = (v))
+HANDLE _get_osfhandle(int);
 
 #if defined(__BORLANDC__)
 
@@ -512,41 +544,26 @@
 
 !Win32OperatingSystem primitiveFunctions!
 %{
-
-/* isWindows-NT flag:
- *  1 for NT based systemes, such as NT,XP or 2k
- *  0 for w95 based systems, such as w95/w98/ME
- */
-static int __isWinNT = 0;
-
 #define __wait wait
 
-
 static int
-_canAccessIOWithoutBlocking (aFD, readMode)
-int aFD;
-int readMode;
+_canAccessIOWithoutBlocking (HANDLE handle, int readMode)
 {
     struct timeval tv;
     fd_set         fds;
     int            n;
     int winErrNo;
 
-/* we use the osfhandle insteat of the fd !! WHY ?? (I do not know)
-   but otherwise it not works
-*/
-    int sock = (int) _get_osfhandle (aFD);
-
-    FD_ZERO( & fds );
-    FD_SET ( sock, & fds );
+    FD_ZERO(&fds);
+    FD_SET (handle, &fds);
 
     tv.tv_sec  = 0;
     tv.tv_usec = 0;
 
     if (readMode) {
-	n = select (sock + 1, & fds, NULL, NULL, & tv);
+	n = select (1 , &fds, NULL, NULL, &tv);  // first parameter to select is ignored in windows
     } else {
-	n = select (sock + 1, NULL, & fds, NULL, & tv);
+	n = select (1, NULL, &fds, NULL, &tv);
     }
 
     if (n == 0) {
@@ -554,29 +571,24 @@
     }
 
     if (n > 0) {
-	return ((FD_ISSET (sock, & fds)) ? 1 : 0);
+	return (FD_ISSET(handle, &fds) ? 1 : 0);
     }
 
     winErrNo = WSAGetLastError();
     switch (winErrNo) {
 	case WSAENOTSOCK:
 	    if (readMode) {
-
 		DWORD  w = 0;
-		HANDLE h = (HANDLE) _get_osfhandle (aFD);
-
-		if (PeekNamedPipe (h, 0, 0, 0, & w, 0)) {
-		    if( !__isWinNT || w > 0 )
-			return (1);
-
-		    return (0);
+
+		if (PeekNamedPipe (handle, 0, 0, 0, & w, 0)) {
+		    return (w > 0);
 		}
 #if 0
 		console_fprintf(stderr, "_canAccessIOWithoutBlocking non Socket\n");
 #endif
 		return (-1);
 	    }
-	    /* in writeMode we return allways true for none-sockets */
+	    /* in writeMode we return always true for none-sockets */
 	    return (1);
 
 	case WSAEINPROGRESS:
@@ -639,27 +651,31 @@
     return __get_functionAddress(&libHandle, "ole32.DLL", functionName);
 }
 
-/*
- * The difference between the Windows epoch (1601-01-01 00:00:00)
- * and the Unix epoch (1970-01-01 00:00:00) in milliseconds is: 11644473600000L
- */
-void
-TimetToFileTime( time_t t, LPFILETIME pft )
-{
-    LONGLONG ll = Int32x32To64(t, 10000000) + 116444736000000000;
-    pft->dwLowDateTime = (DWORD) ll;
-    pft->dwHighDateTime = ll >>32;
-}
-
 OBJ
 FileTimeToOsTime(LPFILETIME pft)
 {
     LONGLONG lTime = ((LONGLONG)pft->dwHighDateTime << 32) + pft->dwLowDateTime;
-    lTime = (lTime / 10000) - 11644473600000L;
+    lTime = (lTime / 10000);    // convert multiple of 100ns to milliseconds
 
     return(__MKLARGEINT64(1, (unsigned INT)(lTime & 0xFFFFFFFF), (unsigned INT)(lTime >> 32)));
 }
 
+int
+OsTimeToFileTime(OBJ tLow, OBJ tHigh, LPFILETIME pft) {
+    LONGLONG lTime;
+    UINT low = __unsignedLongIntVal(tLow);
+    UINT hi = __unsignedLongIntVal(tHigh);
+
+    if (hi == 0 && !__isSmallInteger(tHigh))
+	return(0);      // conversion error
+
+    lTime = ((LONGLONG)hi << 32) + (LONGLONG)low;
+    lTime = lTime * 10000;      // convert to multiple of 100ns
+
+    pft->dwHighDateTime = (UINT)(lTime >> 32);
+    pft->dwLowDateTime = (UINT)(lTime & 0xFFFFFFFF);
+    return(1);
+}
 
 %}
 ! !
@@ -814,10 +830,7 @@
     self primitiveFailed
 !
 
-initOSType
-    "internal - see if running under win-NT/XP/2k
-     (as opposed to win-95/98/ME)"
-
+getOSVersion
 %{  /* NOCONTEXT */
     OSVERSIONINFO osvi;
 
@@ -825,11 +838,7 @@
     osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
     GetVersionEx (&osvi);
 
-    if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-	__isWinNT = 1;
-    } else {
-	__isWinNT = 0;
-    }
+    RETURN(__mkSmallInteger(osvi.dwPlatformId));
 %}.
 !
 
@@ -837,14 +846,13 @@
     "initialize the class"
 
     "/ attention: must be ok to be called twice during startup.
-    Initialized == nil ifTrue:[
+    Initialized isNil ifTrue:[
 	Initialized := true.
 	ObjectMemory addDependent:self.
 	HostName := nil.
 	DomainName := nil.
 	LastErrorNumber := nil.
 	PipeFailed := false.
-	self initOSType.
 	self coInitialize.
     ].
 
@@ -862,7 +870,6 @@
 	DomainName := nil.
 	LastErrorNumber := nil.
 	PipeFailed := false.
-	self initOSType.
 	self coInitialize.
     ]
 
@@ -1606,6 +1613,112 @@
     result = 0 ifTrue: [ ^self error ].
 ! !
 
+!Win32OperatingSystem class methodsFor:'directory access'!
+
+linkInfoFor:osPathname fileSize:fileSize fileAttributes:osFileAttributes osCrtTime:osCrtTime osAccTime:osAccTime osModTime:osModTime
+    |type modeBits crtTime accTime modTime|
+
+%{
+    DWORD  __fileAttr = __unsignedLongIntVal( osFileAttributes );
+    int    __modeBits = 0;
+
+    if (__fileAttr & FILE_ATTRIBUTE_DIRECTORY) {
+	type = @symbol(directory);
+	__modeBits = 0777;   /* executable and WRITABLE - refer to comment in #isWritable: */
+    } else if (__fileAttr & FILE_ATTRIBUTE_REPARSE_POINT) {
+	type = @symbol(symbolicLink);
+	__modeBits = 0777;   /* even in UNIX symlinks have 0777 */
+    } else {
+	type = @symbol(regular);
+	if (__fileAttr & FILE_ATTRIBUTE_READONLY) {
+	    __modeBits = 0444;
+	} else {
+	    __modeBits = 0666;
+	}
+    }
+    modeBits = __mkSmallInteger(__modeBits);
+
+%}.
+    osCrtTime isNil
+	ifTrue: [crtTime := Timestamp now]
+	ifFalse:[crtTime := Timestamp new fromOSTime:(osCrtTime - OperatingSystem osTimeOf19700101)].
+
+    osAccTime isNil
+	ifTrue: [accTime := Timestamp now]
+	ifFalse:[accTime := Timestamp new fromOSTime:(osAccTime - OperatingSystem osTimeOf19700101)].
+
+    osModTime isNil
+	ifTrue: [modTime := accTime]
+	ifFalse:[modTime := Timestamp new fromOSTime:(osModTime - OperatingSystem osTimeOf19700101)].
+
+    ^ FileStatusInfo
+		type:type
+		mode:modeBits
+		uid:nil
+		gid:nil
+		size:fileSize
+		id:0
+		accessed:accTime
+		modified:modTime
+		created:crtTime
+		sourcePath:(osPathname asSingleByteStringIfPossible)
+		fullName:nil
+		alternativeName:nil.
+!
+
+nextLinkInfoFrom:aDirectoryStream dirPointer:dirPointer
+    "return the next FileStatusInfo or nil at the end"
+
+    |resultInfo error fileSize osPathname osModTime osCrtTime osAccTime osFileAttributes|
+
+%{
+    HANDLE d;
+    WIN32_FIND_DATAW data;
+    int rslt;
+
+    if ((dirPointer != nil)
+    && __isExternalAddressLike(dirPointer)) {
+	// __INST(lastErrorNumber) = nil;
+	d = __externalAddressVal(dirPointer);
+
+	do {
+	    __threadErrno = 0;
+	    rslt = STX_API_NOINT_CALL2( "FindNextFileW", FindNextFileW, d, &data );
+	} while ((rslt < 0) && (__threadErrno == EINTR));
+
+	if (rslt > 0) {
+	    fileSize  = __MKLARGEINT64(1, data.nFileSizeLow, data.nFileSizeHigh);
+	    osPathname = __MKU16STRING( data.cFileName );
+	    osFileAttributes = __mkSmallInteger( data.dwFileAttributes );
+
+	    osCrtTime = FileTimeToOsTime(&data.ftCreationTime);
+	    osAccTime = FileTimeToOsTime(&data.ftLastAccessTime);
+	    osModTime = FileTimeToOsTime(&data.ftLastWriteTime);
+
+	} else {
+	    error = __mkSmallInteger( __threadErrno );
+	}
+    }
+%}.
+    (error notNil and:[error ~~ 0]) ifTrue:[
+	^ StreamIOError newException
+	    errorCode:error;
+	    osErrorHolder:(OperatingSystem errorHolderForNumber:error);
+	    parameter:aDirectoryStream;
+	    raiseRequest
+    ].
+
+    osPathname isNil ifTrue:[^ nil].
+
+    ^ self
+	linkInfoFor:osPathname
+	fileSize:fileSize
+	fileAttributes:osFileAttributes
+	osCrtTime:osCrtTime
+	osAccTime:osAccTime
+	osModTime:osModTime
+! !
+
 !Win32OperatingSystem class methodsFor:'error messages'!
 
 currentErrorNumber
@@ -1633,12 +1746,9 @@
 %{
     /* claus:
      * I made this primitive code, since errnos are not
-     * standard across unixes
+     * standard across operating systems
      */
 
-    typ = @symbol(defaultOsErrorSignal);
-    sym = @symbol(ERROR_OTHER);
-
     if (__isSmallInteger(errNr) || (__unsignedLongIntVal(errNr) > 0)) {
       int __eno = __unsignedLongIntVal(errNr);
 
@@ -2485,10 +2595,20 @@
     }
 %}.
     holder := OSErrorHolder new.
-    holder errorSymbol:sym errorCategory:typ.
+    sym isNil ifTrue:[
+	sym := #ERROR_OTHER.
+	errNr notNil ifTrue:[
+	    "keep symbols as symbols"
+	    holder parameter:(errNr isString ifTrue:[errNr] ifFalse:[errNr asString]).
+	].
+    ].
+    holder errorSymbol:sym errorCategory:(typ ? #defaultOsErrorSignal).
     ^ holder
 
-    "
+
+    "
+     OperatingSystem errorHolderForNumber:4
+     OperatingSystem errorHolderForNumber:#badArgument
      self errorHolderForNumber:16777296
      self errorHolderForNumber:(self errorNumberFor:#EPERM)
      self errorHolderForNumber:(self errorNumberFor:#EIO)
@@ -3317,10 +3437,19 @@
 !
 
 commandAndArgsForOSCommand:aCommandString
-    "get a shell and shell arguments for command execution"
+    "get a shell and shell arguments for command execution.
+     If aCommandString is a String, the commandString is passed to a shell for execution
+     - see the description of 'sh -c' in your UNIX manual ('cmd.com' in your MSDOS manual).
+     If aCommandString is an Array, the first element is the command to be executed,
+     and the other elements are the arguments to the command. No shell is invoked in this case."
 
     |shell args wDir cmdName path hasRedirection|
 
+    aCommandString isNonByteCollection ifTrue:[
+	"easy: the caller does not want a shell to be executed"
+	^ Array with:aCommandString first with:(aCommandString asStringWith:' ').
+    ].
+
     "/
     "/ 'x:\WINNT\System32\cmd /c <command>'
     "/ or 'x:\WINDOWS\System32\cmd /c <command>'
@@ -3638,13 +3767,8 @@
 	lpsiStartInfo.dwXCountChars     = 0;
 	lpsiStartInfo.dwYCountChars     = 0;
 	lpsiStartInfo.dwFillAttribute   = 0;
-	if (0 /*__isWinNT*/) {
-	    lpsiStartInfo.dwFlags           = STARTF_USESTDHANDLES;
-	    lpsiStartInfo.wShowWindow       = SW_SHOWDEFAULT;
-	} else {
-	    lpsiStartInfo.dwFlags           = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES /*| STARTF_USEPOSITION*/;
-	    lpsiStartInfo.wShowWindow       = SW_HIDE /*SW_SHOWDEFAULT*/;
-	}
+	lpsiStartInfo.dwFlags           = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES /*| STARTF_USEPOSITION*/;
+	lpsiStartInfo.wShowWindow       = SW_HIDE /*SW_SHOWDEFAULT*/;
 	lpsiStartInfo.cbReserved2       = 0;
 	lpsiStartInfo.lpReserved2       = NULL;
 	lpsiStartInfo.hStdInput         = NULL;
@@ -3659,11 +3783,7 @@
 	if (flagsOrNil != nil) {
 	    fdwCreate = __longIntVal(flagsOrNil);
 	} else {
-	    if (0 /* __isWinNT */)
-		fdwCreate = 0; //IDLE_PRIORITY_CLASS;
-	    else
-		fdwCreate = CREATE_NEW_CONSOLE; //|IDLE_PRIORITY_CLASS; // DETACHED_PROCESS; // NORMAL_PRIORITY_CLASS ;
-
+	    fdwCreate = CREATE_NEW_CONSOLE; //|IDLE_PRIORITY_CLASS; // DETACHED_PROCESS; // NORMAL_PRIORITY_CLASS ;
 	    if (newPgrp == true) {
 		fdwCreate |= CREATE_NEW_PROCESS_GROUP;
 	    }
@@ -3969,8 +4089,10 @@
 
     "start executing the OS command as specified by the argument, aCommandString
      as a separate process; do not wait for the command to finish.
-     The commandString is passed to a shell for execution - see the description of
-     'sh -c' in your UNIX manual ('cmd.com' in your MSDOS manual).
+     If aCommandString is a String, the commandString is passed to a shell for execution
+     - see the description of 'sh -c' in your UNIX manual ('cmd.com' in your MSDOS manual).
+     If aCommandString is an Array, the first element is the command to be executed,
+     and the other elements are the arguments to the command. No shell is invoked in this case.
      The command gets stdIn, stdOut and stdErr assigned from the arguments;
      each may be nil.
 
@@ -4015,7 +4137,10 @@
 
     "blocking at current prio (i.e. only higher prio threads execute):
 
-     OperatingSystem executeCommand:'ls -l > out'.
+     OperatingSystem executeCommand:'dir > out'.
+     OperatingSystem executeCommand:'tree /A' outputTo:Transcript.
+     OperatingSystem executeCommand:#('c:\windows\system32\tree.com' '/A' '/F') outputTo:Transcript.
+     OperatingSystem executeCommand:#('c:\windows\system32\where.exe' '/T' '*.dll') outputTo:Transcript.
     "
 
     "non-blocking (lower prio threads continue):
@@ -4414,9 +4539,7 @@
     "copy the directory named 'sourcePathName' and all contained files/directories to 'destination'.
      Return true if successful."
 
-    ^ false
-
-    "Modified: / 4.6.1998 / 04:29:49 / cg"
+    ^ OperatingSystem executeCommand:('xcopy %1 %2 /s /e /h' bindWith:sourcePathName with:destination)
 !
 
 removeDirectory:fullPathName
@@ -4870,22 +4993,28 @@
     openFilenameStructureExternalAddress is an integer representing it's address"
 
     | rslt |
+
 %{  /* STACK: 32000*/
 
-    INT __address;
+    void *__address;
     int __rslt;
 
-    __address = __intVal(openFilenameStructureExternalAddress);
-    // do not cast to INT - will loose sign bit then!
-    __rslt = __STX_API_CALL1( "GetOpenFileName", (void *)GetOpenFileName, (void *)(__address));
-
-    if (__rslt == TRUE) {
-	rslt = true;
-    } else {
-	rslt = false;
-    }
-%}.
+    if (__isExternalAddressLike(openFilenameStructureExternalAddress)
+     || __isExternalBytesLike(openFilenameStructureExternalAddress)){
+	__address = __externalAddressVal(openFilenameStructureExternalAddress);
+	__rslt = __STX_API_CALL1( "GetOpenFileName", (void *)GetOpenFileName, __address);
+
+	if (__rslt == TRUE) {
+	    rslt = true;
+	} else {
+	    rslt = false;
+	}
+    }
+%}.
+    rslt isNil ifTrue:[ self primitiveFailed ].
     ^ rslt
+
+    "Modified (format): / 11-02-2014 / 21:18:02 / cg"
 !
 
 getSaveFilename: openFilenameStructureExternalAddress
@@ -4897,20 +5026,25 @@
 
 %{  /* STACK: 32000*/
 
-    INT __address;
+    void  *__address;
     int __rslt;
 
-    __address = __intVal(openFilenameStructureExternalAddress);
-    // do not cast to INT - will loose sign bit then!
-    __rslt = __STX_API_CALL1( "GetSaveFileName", (void *)GetSaveFileName, (void *)(__address));
-
-    if (__rslt == TRUE) {
-	rslt = true;
-    } else {
-	rslt = false;
-    }
-%}.
+    if (__isExternalAddressLike(openFilenameStructureExternalAddress)
+     || __isExternalBytesLike(openFilenameStructureExternalAddress)){
+	__address = __externalAddressVal(openFilenameStructureExternalAddress);
+	__rslt = __STX_API_CALL1( "GetSaveFileName", (void *)GetSaveFileName, __address);
+
+	if (__rslt == TRUE) {
+	    rslt = true;
+	} else {
+	    rslt = false;
+	}
+    }
+%}.
+    rslt isNil ifTrue:[ self primitiveFailed ].
     ^ rslt
+
+    "Modified: / 11-02-2014 / 21:18:20 / cg"
 ! !
 
 !Win32OperatingSystem class methodsFor:'file queries'!
@@ -5302,6 +5436,22 @@
     ^ 'nul:'
 !
 
+getObjectFileInfoFor:aStringOrFilename
+    "Return and info object for given executable or shared object
+     or throw an error if given file is not a valid an executable now
+     shared object.
+
+     The info object returned is OS-specific, however it responds to at
+     least
+        #isFor32BitArchitecture
+        #isFor64BitArchitecture ... returns true, if the given object is for
+                                     32bit, 64bit architecture respectively
+    "
+    ^ PECOFFFileHeader fromFile: aStringOrFilename
+
+    "Created: / 18-03-2015 / 09:52:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
 getShortPathName:aPathName
     "get the full (long, not 8.3) version of aPathName"
 
@@ -5835,12 +5985,18 @@
     ].
     mode notNil ifTrue:[
 	atime isNil ifTrue:[
+	    "/ rebias to 1970 by subtracting the number of millis from 1.1.1601 to 1.1.1970
+	    aOsTime := aOsTime - self osTimeOf19700101.
 	    atime := Timestamp new fromOSTime:aOsTime.
 	].
 	mtime isNil ifTrue:[
+	    "/ rebias to 1970 by subtracting the number of millis from 1.1.1601 to 1.1.1970
+	    mOsTime := mOsTime - self osTimeOf19700101.
 	    mtime := Timestamp new fromOSTime:mOsTime.
 	].
 	ctime isNil ifTrue:[
+	    "/ rebias to 1970 by subtracting the number of millis from 1.1.1601 to 1.1.1970
+	    cOsTime := cOsTime - self osTimeOf19700101.
 	    ctime := Timestamp new fromOSTime:cOsTime.
 	].
 	fileName notNil ifTrue:[
@@ -5849,19 +6005,15 @@
 	alternativeName notNil ifTrue:[
 	    alternativeName := alternativeName asSingleByteStringIfPossible
 	].
+
 	info := FileStatusInfo
-		    type:type
-		    mode:mode
-		    uid:uid
-		    gid:gid
+		    type:type mode:mode
+		    uid:uid gid:gid
 		    size:size
 		    id:id
-		    accessed:atime
-		    modified:mtime
-		    created:ctime
+		    accessed:atime modified:mtime created:ctime
 		    sourcePath:aPathName
-		    fullName:fileName
-		    alternativeName:alternativeName.
+		    fullName:fileName alternativeName:alternativeName.
 	^ info
    ].
    ^ nil
@@ -6607,12 +6759,9 @@
 !
 
 enableChildSignalInterrupts
-    "enable childSignal interrupts
-     (SIGCHLD, if the architecture supports it).
-     After enabling, these signals will send the message
-     'childSignalInterrupt' to the ChildSignalInterruptHandler object."
-
-    self enableSignal:(self sigCHLD)
+    "childSignal interrupts are not supported in windows"
+
+    ^ self
 !
 
 enableIOInterruptsOn:fd
@@ -7076,7 +7225,7 @@
     rslt := self
 		primDuplicateHandle_hSourcProcessHandle:hMe
 		hSourceHandle:aHandle
-		hTargetProcesshandle:targetProcessHandle
+		hTargetProcesshandle:targetProcessHandle ? hMe
 		lpTargetHandle:spaceForTargetHandle
 		dwDesiredAccess:0
 		bInheritHandle:false
@@ -7084,7 +7233,7 @@
 
     rslt ifFalse:[
 	spaceForTargetHandle free.
-	self primitiveFailed.
+	self primitiveFailed:self primGetLastError.
 	^ nil
     ].
 
@@ -7289,6 +7438,17 @@
     "
 !
 
+isValidHandle:anExternalAddress
+    |newHandle|
+
+    newHandle := self duplicateHandle:anExternalAddress to:nil.
+    newHandle isNil ifTrue:[
+	^ false.
+    ].
+"/    self closeHandle:newHandle.
+    ^ true.
+!
+
 playSound:fileName
     self playSound:fileName mode:1
 
@@ -7571,53 +7731,56 @@
 getDomainName
     "return the DNS domain this host is in.
      Notice:
-	not all systems support this; on some, 'unknown' is returned."
+        not all systems support this; on some, 'unknown' is returned."
 
     |domainName idx hostName k|
 
     DomainName notNil ifTrue:[
-	^ DomainName
+        ^ DomainName
     ].
 
     "/ sometimes, we can extract the domainName from the hostName ...
     hostName := self getHostName.
     hostName notEmptyOrNil ifTrue:[
-	idx := hostName indexOf:$..
-	idx ~~ 0 ifTrue:[
-	    domainName := hostName copyFrom:idx+1.
-	]
+        idx := hostName indexOf:$..
+        idx ~~ 0 ifTrue:[
+            domainName := hostName copyFrom:idx+1.
+        ]
     ].
 
     domainName isNil ifTrue:[
-	domainName := self getEnvironment:'DOMAIN'.
-	domainName isNil ifTrue:[
-	    domainName := self getEnvironment:'DOMAINNAME'.
-	].
-
-	domainName isNil ifTrue:[
-	    "/ ok, search the registry ...
-	    "/ under NT and later, it is found there ...
-	    k := RegistryEntry key:'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters'.
-	    k notNil ifTrue:[
-		domainName := k valueNamed:'Domain'.
-		k close.
-	    ].
-	].
-
-	domainName isNil ifTrue:[
-	    "/ under Win95/Win98, it is found there ...
-	    k := RegistryEntry key:'HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP'.
-	    k notNil ifTrue:[
-		domainName := k valueNamed:'Domain'.
-		k close.
-	    ]
-	].
-
-	domainName isNil ifTrue:[
-	    'Win32OperatingSystem [warning]: cannot find out domainName' errorPrintCR.
-	    domainName := 'unknown'.
-	].
-	DomainName := domainName.     "cache only, if it is fixed"
+        domainName := self getEnvironment:'DOMAIN'.
+        domainName isNil ifTrue:[
+            domainName := self getEnvironment:'DOMAINNAME'.
+        ].
+
+        domainName isNil ifTrue:[
+            "/ ok, search the registry ...
+            "/ under NT and later, it is found there ...
+            k := RegistryEntry key:'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters'.
+            k notNil ifTrue:[
+                domainName := k valueNamed:'Domain'.
+                k close.
+            ].
+        ].
+
+        domainName isNil ifTrue:[
+            "/ under Win95/Win98, it is found there ...
+            k := RegistryEntry key:'HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP'.
+            k notNil ifTrue:[
+                domainName := k valueNamed:'Domain'.
+                k close.
+            ]
+        ].
+
+        domainName isNil ifTrue:[
+            "/ only warn once - the warning can be ignored, if you do not use the domain name
+            ObjectMemory debugPrinting ifTrue:[
+                'Win32OperatingSystem [warning]: cannot find out domainName' infoPrintCR.
+            ].        
+            domainName := 'unknown'.
+        ].
+        DomainName := domainName.     "cache only, if it is fixed"
     ].
     ^ domainName
 
@@ -8613,7 +8776,7 @@
 hasConsole
     "return true, if there is some kind of console available
      (i.e. for proper stdIn, stdOut and stdErr handling).
-     This only returns false when running únder windows, and
+     This only returns false when running únder windows, and
      the system is running as a pure windows application.
      If false, the miniDebugger is useless and not used."
 
@@ -8638,11 +8801,7 @@
 isMSWINDOWSNTlike
     "This returns true if running in a Windows-NT system."
 
-%{   /* NOCONTEXT */
-     if (__isWinNT)
-	RETURN(true);
-%}.
-     ^ false.
+     ^ true.
 !
 
 isMSWINDOWSlike
@@ -8661,60 +8820,62 @@
     |error|
 
 %{
-    HANDLE processHandle;
+    HANDLE processHandle, processHandleToClose = 0;
     int err;
+    DWORD exitCode;
 
     if (__isExternalAddressLike(processHandleOrPid) ) {
-	DWORD exitCode;
-
 	processHandle = _HANDLEVal(processHandleOrPid);
-
 	if (processHandle == 0) {
 	    error = @symbol(invalidParameter);
-	} else {
-	    /* check if the handle still refers to a running process */
-	    if (GetExitCodeProcess(processHandle, &exitCode) != 0) {
-		if (exitCode == STILL_ACTIVE) {
-		    RETURN(true);
-		} else {
-		    RETURN(false);
-		}
-	    } else {
-		goto checkError;
-	    }
-       }
+	    goto out;
+	}
     } else if( __isSmallInteger(processHandleOrPid) ) {
 	// assume, that synchronize needs less privilege...
-	processHandle = OpenProcess(SYNCHRONIZE, FALSE, __smallIntegerVal(processHandleOrPid));
-	if (processHandle) {
-	    CloseHandle(processHandle);
+	processHandle = processHandleToClose = OpenProcess(SYNCHRONIZE, FALSE, __smallIntegerVal(processHandleOrPid));
+	if (!processHandle) {
+	    goto checkError;
+	}
+    } else {
+	error = @symbol(invalidParameter);
+	goto out;
+    }
+
+    /* check if the handle still refers to a running process */
+    if (GetExitCodeProcess(processHandle, &exitCode) != 0) {
+	if (processHandleToClose)
+	    CloseHandle(processHandleToClose);
+	if (exitCode == STILL_ACTIVE) {
 	    RETURN(true);
-	}
+	} else {
+	    RETURN(false);
+	}
+    } else if (processHandleToClose) {
+	CloseHandle(processHandleToClose);
+    }
 
 checkError:
-	err = GetLastError();
-	// we do not have access to the process (so pid does exist ;-))
-	if (err == ERROR_ACCESS_DENIED) {
-	    RETURN(true);
-	}
-	// pid does not exist
-	if (err == ERROR_INVALID_PARAMETER) {
-	    RETURN(false);
-	}
-
-	// any other error - raise signal
-	__threadErrno = __WIN32_ERR(err);
-	error = __mkSmallInteger(__threadErrno);
-    } else {
-	error = @symbol(invalidParameter);
-    }
+    err = GetLastError();
+    // we do not have access to the process (so pid does exist ;-))
+    if (err == ERROR_ACCESS_DENIED) {
+	RETURN(true);
+    }
+    // pid does not exist
+    if (err == ERROR_INVALID_PARAMETER) {
+	RETURN(false);
+    }
+
+    // any other error - raise signal
+    __threadErrno = __WIN32_ERR(err);
+    error = __mkSmallInteger(__threadErrno);
+out:;
 %}.
 
     self primitiveFailed:error.
 
     "
       self isProcessIdPresent:(self getProcessId)
-      self isProcessIdPresent:4711
+      self isProcessIdPresent:10196
       self isProcessIdPresent:512
       self isProcessIdPresent:'abc'
     "
@@ -10149,9 +10310,12 @@
 
 !Win32OperatingSystem class methodsFor:'time and date'!
 
-computeOSTimeFromUTCYear:y month:m day:d hour:h minute:min second:s millisecond:millis
+computeOSTimeFromYear:y month:m day:d hour:h minute:min second:s millisecond:millis utc:utcBoolean
     "return the OS-dependent time for the given time and day.
-     The arguments are assumed to be in UTC time."
+     The arguments are assumed to be in localtime including
+     any daylight saving adjustings."
+
+    |osTime|
 
 %{
     if (__bothSmallInteger(y, m)
@@ -10170,73 +10334,76 @@
 	sysTime.wMonth = __intVal(m);
 	sysTime.wDay = __intVal(d);
 
-	if (SystemTimeToFileTime(&sysTime, &fileTime) == 0)
+	if (sysTime.wYear < 1602) goto outOfRange;   // not 1601 - so we don't have to care for timezone
+	if (sysTime.wYear > 9999) goto outOfRange;
+
+	if (utcBoolean != true) {
+	    // adjust for local time
+
+	    // TzSpecificLocalTimeToSystemTime() is not supported in Win2000
+	    // - but we do not support Win2k any longer as of 2014
+#ifdef __BORLANDC__
+	    {
+		typedef BOOL (WINAPI *P_TzSpecificLocalTimeToSystemTime)(LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME);
+		static P_TzSpecificLocalTimeToSystemTime pTzSpecificLocalTimeToSystemTime;
+
+		if (pTzSpecificLocalTimeToSystemTime == NULL) {
+		    pTzSpecificLocalTimeToSystemTime =
+			(P_TzSpecificLocalTimeToSystemTime)
+			    GetProcAddress ( GetModuleHandle ("kernel32.dll"),
+							      "TzSpecificLocalTimeToSystemTime");
+		}
+		if (!pTzSpecificLocalTimeToSystemTime(0, &sysTime, &sysTime))
+		    goto error;
+	    }
+#else
+	    if (!TzSpecificLocalTimeToSystemTime(0, &sysTime, &sysTime))
+		goto error;
+#endif
+	}
+
+	if (! SystemTimeToFileTime(&sysTime, &fileTime))
 	    goto error;
 
-	RETURN(FileTimeToOsTime(&fileTime));
-    }
-error:;
-%}.
+	osTime = FileTimeToOsTime(&fileTime);
+    }
+outOfRange: ;
+error: ;
+%}.
+    osTime notNil ifTrue:[
+	"/ rebias to 1970 by subtracting the number of millis from 1.1.1601 to 1.1.1970
+	^ osTime - self osTimeOf19700101.
+    ].
+
     "Error, some invalid date ot time"
     ^ TimeConversionError raiseRequest
 
     "
      OperatingSystem computeOSTimeFromUTCYear:1970 month:1 day:1 hour:0 minute:0 second:0 millisecond:0
-    invalid:
-     OperatingSystem computeOSTimeFromUTCYear:1970 month:1 day:1 hour:24 minute:0 second:0 millisecond:0
-    "
-
-    "Modified: / 07-07-2010 / 16:56:21 / cg"
-!
-
-computeOSTimeFromYear:y month:m day:d hour:h minute:min seconds:s millis:millis
-    "return the OS-dependent time for the given time and day.
-     The arguments are assumed to be in localtime including
-     any daylight saving adjustings."
-
-%{
-    if (__bothSmallInteger(y, m)
-     && __bothSmallInteger(d, h)
-     && __bothSmallInteger(min, s)
-     && __isSmallInteger(millis)) {
-	SYSTEMTIME sysTime;
-	FILETIME fileTime;
-
-	sysTime.wHour = __intVal(h);
-	sysTime.wMinute = __intVal(min);
-	sysTime.wSecond = __intVal(s);
-	sysTime.wMilliseconds = __intVal(millis);
-
-	sysTime.wYear = __intVal(y);
-	sysTime.wMonth = __intVal(m);
-	sysTime.wDay = __intVal(d);
-
-#if 0
-	/* Sorry, but this function is not supported in Win2000
-	   - we use LocalFileTimeToFileTime */
-	if (TzSpecificLocalTimeToSystemTime(0, &sysTime, &sysTime) == 0)
-	    goto error;
-#endif
-	if (SystemTimeToFileTime(&sysTime, &fileTime) == 0)
-	    goto error;
-	if (LocalFileTimeToFileTime(&fileTime, &fileTime) == 0)
-	    goto error;
-
-	RETURN(FileTimeToOsTime(&fileTime));
-    }
-error:;
-%}.
-    "Error, some invalid date ot time"
-    ^ TimeConversionError raiseRequest
-
-    "
-     OperatingSystem computeOSTimeFromUTCYear:1970 month:1 day:1 hour:0 minute:0 second:0 millisecond:0
-     OperatingSystem computeOSTimeFromYear:1970 month:1 day:1 hour:0 minute:0 seconds:0 millis:0
+     OperatingSystem computeOSTimeFromYear:1970 month:1 day:1 hour:0 minute:0 second:0 millisecond:0
+     OperatingSystem computeOSTimeFromYear:2014 month:7 day:1 hour:0 minute:0 second:0 millisecond:0
     "
 
     "Modified: / 07-07-2010 / 16:56:56 / cg"
 !
 
+epochEndOSTime
+    "private interface for timestamp to ask the OS what the maximum time
+     (in milliseconds since the Unix epoch, 1.1.1970) is.
+     Windows has a 64 Unix 100ns osTime internally, which goes from 0 (1601)
+     to 16r7FFFFFFFFFFFFFFF."
+
+    ^ (16r7FFFFFFFFFFFFFFF // 10000) - self osTimeOf19700101
+!
+
+epochStartOSTime
+    "private interface for timestamp to ask the OS what the minimum time
+     (in milliseconds since the Unix epoch, 1.1.1970) is.
+     Windows epoch starts at 1.1.1601."
+
+    ^ self osTimeOf19700101 negated
+!
+
 getMicrosecondTime
     "This returns a microsecond timer value.
      The returned value is a 64bit value
@@ -10308,20 +10475,24 @@
     "This returns the OS time.
      The base of the returned value is not consistent across
      different OS's - some return the number of millis since jan, 1st 1970;
-     others since 1900. The Time classes are prepared for this, and
-     converts as appropriate (by using my fromOSTime: conversion methods).
-
-     Dont use this method in application code since it is an internal (private)
+     others since 1600. Here, the original value of the OS is rebiased to 1.1.1970,
+     meaning that the returned value has the number of seconds since 1970 subtracted,
+     so the returned value is consistent across ST/X's running on different systems.
+
+     Don't use this method in application code since it is an internal (private)
      interface. For compatibility with ST-80, use Time>>millisecondClockValue.
      or use instances of Time, Date or Timestamp to work with."
 
+    |osTime|
+
 %{
     FILETIME fileTime;
 
     GetSystemTimeAsFileTime(&fileTime);
-
-    RETURN(FileTimeToOsTime(&fileTime));
-%}.
+    osTime = FileTimeToOsTime(&fileTime);
+%}.
+    "/ rebias to 1970 by subtracting the number of millis from 1.1.1601 to 1.1.1970
+    ^ osTime - self osTimeOf19700101.
 
     "
      OperatingSystem getOSTime.
@@ -10334,6 +10505,17 @@
     "get information about the OS's timezone setting. See documentation in
      AbstractOperatingSystem::TimeZoneInformation for details"
 
+    ^ self getTimezoneInformationForYear:nil.
+
+    "
+     self getTimezoneInformation
+    "
+!
+
+getTimezoneInformationForYear:anIntegerOrNil
+    "get information about the OS's timezone setting. See documentation in
+     AbstractOperatingSystem::TimeZoneInformation for details"
+
     |error bias standardName
      standardDate_y standardDate_m standardDate_d standardDate_wd
      standardDate_h standardDate_min standardDate_s
@@ -10348,47 +10530,88 @@
     DWORD retVal;
     WCHAR nm[33];
 
-    retVal = GetTimeZoneInformation(&tzInfo);
-    switch (retVal) {
-	case TIME_ZONE_ID_INVALID:
+    if (anIntegerOrNil == nil) {
+	retVal = GetTimeZoneInformation(&tzInfo);
+	switch (retVal) {
+	    case TIME_ZONE_ID_STANDARD:
+	    case TIME_ZONE_ID_DAYLIGHT:
+	    case TIME_ZONE_ID_UNKNOWN:
+		break;
+
+	    default:
+	    case TIME_ZONE_ID_INVALID:
+		error = __mkSmallInteger(__WIN32_ERR(GetLastError()));
+		goto out;
+	}
+    } else if (__isSmallInteger(anIntegerOrNil)) {
+	int year = __intVal(anIntegerOrNil);
+#ifdef __BORLANDC__
+	{
+	    typedef BOOL (WINAPI *P_GetTimeZoneInformationForYear)(
+					USHORT,
+					LPTIME_ZONE_INFORMATION, // - should be, but is not defined: PDYNAMIC_TIME_ZONE_INFORMATION,
+					LPTIME_ZONE_INFORMATION);
+	    static P_GetTimeZoneInformationForYear pGetTimeZoneInformationForYear;
+
+	    if (pGetTimeZoneInformationForYear == NULL) {
+		pGetTimeZoneInformationForYear =
+		    (P_GetTimeZoneInformationForYear)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetTimeZoneInformationForYear");
+		if (pGetTimeZoneInformationForYear == NULL) {
+		    pGetTimeZoneInformationForYear = false;
+		}
+	    }
+	    if (pGetTimeZoneInformationForYear == false) {
+		error = __mkSmallInteger(@symbol(primitiveFailed));
+		goto out;
+	    } else {
+		if (!pGetTimeZoneInformationForYear(year, NULL, &tzInfo)) {
+		    error = __mkSmallInteger(__WIN32_ERR(GetLastError()));
+		    goto out;
+		}
+	    }
+	}
+#else
+	if (!GetTimeZoneInformationForYear(year, NULL, &tzInfo)) {
 	    error = __mkSmallInteger(__WIN32_ERR(GetLastError()));
-	    break;
-
-	case TIME_ZONE_ID_UNKNOWN:
-	case TIME_ZONE_ID_STANDARD:
-	case TIME_ZONE_ID_DAYLIGHT:
-	default:
-	    bias = __mkSmallInteger(tzInfo.Bias);
-	    memmove(nm, tzInfo.StandardName, 32*sizeof(WCHAR));
-	    nm[32] = 0;
-	    standardName = __MKU16STRING(nm);
-	    standardDate_y = __mkSmallInteger(tzInfo.StandardDate.wYear);
-	    standardDate_m = __mkSmallInteger(tzInfo.StandardDate.wMonth);
-	    standardDate_d = __mkSmallInteger(tzInfo.StandardDate.wDay);
-	    standardDate_wd = __mkSmallInteger(tzInfo.StandardDate.wDayOfWeek);
-	    standardDate_h = __mkSmallInteger(tzInfo.StandardDate.wHour);
-	    standardDate_min = __mkSmallInteger(tzInfo.StandardDate.wMinute);
-	    standardDate_s = __mkSmallInteger(tzInfo.StandardDate.wSecond);
-	    standardBias =  __mkSmallInteger(tzInfo.StandardBias);
-	    memmove(nm, tzInfo.DaylightName, 32*sizeof(WCHAR));
-	    nm[32] = 0;
-	    daylightName = __MKU16STRING(nm);
-	    daylightDate_y = __mkSmallInteger(tzInfo.DaylightDate.wYear);
-	    daylightDate_m = __mkSmallInteger(tzInfo.DaylightDate.wMonth);
-	    daylightDate_d = __mkSmallInteger(tzInfo.DaylightDate.wDay);
-	    daylightDate_wd = __mkSmallInteger(tzInfo.DaylightDate.wDayOfWeek);
-	    daylightDate_h = __mkSmallInteger(tzInfo.DaylightDate.wHour);
-	    daylightDate_min = __mkSmallInteger(tzInfo.DaylightDate.wMinute);
-	    daylightDate_s = __mkSmallInteger(tzInfo.DaylightDate.wSecond);
-	    daylightBias =  __mkSmallInteger(tzInfo.DaylightBias);
-	    break;
-    }
+	    goto out;
+	}
+#endif
+    } else {
+	error = @symbol(badArgument);
+	goto out;
+    }
+
+    bias = __mkSmallInteger(tzInfo.Bias);
+    memmove(nm, tzInfo.StandardName, 32*sizeof(WCHAR));
+    nm[32] = 0;
+    standardName = __MKU16STRING(nm);
+    standardDate_y = __mkSmallInteger(tzInfo.StandardDate.wYear);
+    standardDate_m = __mkSmallInteger(tzInfo.StandardDate.wMonth);
+    standardDate_d = __mkSmallInteger(tzInfo.StandardDate.wDay);
+    standardDate_wd = __mkSmallInteger(tzInfo.StandardDate.wDayOfWeek);
+    standardDate_h = __mkSmallInteger(tzInfo.StandardDate.wHour);
+    standardDate_min = __mkSmallInteger(tzInfo.StandardDate.wMinute);
+    standardDate_s = __mkSmallInteger(tzInfo.StandardDate.wSecond);
+    standardBias =  __mkSmallInteger(tzInfo.StandardBias);
+    memmove(nm, tzInfo.DaylightName, 32*sizeof(WCHAR));
+    nm[32] = 0;
+    daylightName = __MKU16STRING(nm);
+    daylightDate_y = __mkSmallInteger(tzInfo.DaylightDate.wYear);
+    daylightDate_m = __mkSmallInteger(tzInfo.DaylightDate.wMonth);
+    daylightDate_d = __mkSmallInteger(tzInfo.DaylightDate.wDay);
+    daylightDate_wd = __mkSmallInteger(tzInfo.DaylightDate.wDayOfWeek);
+    daylightDate_h = __mkSmallInteger(tzInfo.DaylightDate.wHour);
+    daylightDate_min = __mkSmallInteger(tzInfo.DaylightDate.wMinute);
+    daylightDate_s = __mkSmallInteger(tzInfo.DaylightDate.wSecond);
+    daylightBias =  __mkSmallInteger(tzInfo.DaylightBias);
+
+out:;
 %}.
     error notNil ifTrue:[
-	self primitiveFailed.
-    ].
-
-    info := AbstractOperatingSystem::TimeZoneInfo new.
+	self primitiveFailed:error.
+    ].
+
+    info := self timeZoneInfoClass new.
     info
 	bias:bias
 	name:standardName standardBias:standardBias
@@ -10406,7 +10629,20 @@
     ^ info
 
     "
-     self getTimezoneInformation
+     self getTimezoneInformationForYear:2014
+     self getTimezoneInformationForYear:2015
+     self getTimezoneInformationForYear:1977
+     self getTimezoneInformationForYear:nil
+    "
+!
+
+osTimeOf19700101
+    "the number of millis from 1.1.1601 to 1.1.1970"
+
+    ^ 11644473600000
+
+    "
+      self computeOSTimeFromUTCYear:1970 month:1 day:1 hour:0 minute:0 second:0 millisecond:0
     "
 !
 
@@ -10438,30 +10674,33 @@
     "
 !
 
-timeInfoFromSeconds:osSeconds milliseconds:osMilliseconds localTime:isLocalTime
-    "return a timeInfo structure containing values for the given
-     OS-second value.
+timeInfoFromSeconds:osSeconds milliseconds:osMilliSeconds localTime:isLocalTime
+    "return a timeInfo structure containing values for the given OS-millisecond value.
      An internal helper"
 
-    |year month day hours minutes seconds utcOffset dstOffset
-     dst yDay weekDay info reason|
-
-%{
-    UINT t;
-    FILETIME fileTime, localFileTime;
-    SYSTEMTIME sysTime;
-
-    t = __longIntVal(osSeconds);
+    |year month day hour minute second millis utcOffset isDst
+     dst yDay weekDay info reason tLow tHigh t error |
+
+    t := (osSeconds * 1000) + osMilliSeconds + self osTimeOf19700101.
+    tLow := (t bitAnd:16rFFFFFFFF).
+    tHigh := t bitShift:-32.
+
+%{
+    FILETIME fileTime;
+    SYSTEMTIME sysTime, *sysTimePtr;
+    INT _utcOffset, _stdUtcOffset;
 
     /* try cache */
     {
-	OBJ lastSeconds, lastTimeInfo;
-
-	lastSeconds = @global(LastTimeInfoSeconds);
-	if (lastSeconds
-	 && (__longIntVal(lastSeconds) == t)
-	 && (@global(LastTimeInfoMilliseconds) == osMilliseconds)
-	 && (@global(LastTimeInfoIsLocal) == isLocalTime)
+	OBJ lastOsTimeLow, lastOsTimeHi, lastTimeInfo;
+
+	lastOsTimeLow = @global(LastOsTimeLow);
+	lastOsTimeHi = @global(LastOsTimeHi);
+	if (__isInteger(lastOsTimeLow)
+	     && (__unsignedLongIntVal(lastOsTimeLow) == __unsignedLongIntVal(tLow))
+	     && lastOsTimeHi
+	     && (__unsignedLongIntVal(lastOsTimeHi) == __unsignedLongIntVal(tHigh))
+	     && (@global(LastTimeInfoIsLocal) == isLocalTime)
 	) {
 	    lastTimeInfo = @global(LastTimeInfo);
 	    if (lastTimeInfo != nil) {
@@ -10470,43 +10709,117 @@
 	}
     }
 
-    TimetToFileTime((time_t)t, &fileTime);
-
-    if (isLocalTime == true) {
+    if (!OsTimeToFileTime(tLow, tHigh, &fileTime))
+	goto out;
+    if (!FileTimeToSystemTime(&fileTime, &sysTime))
+	goto out;
+
+    if (isLocalTime == false) { // easy: UTC time
+	sysTimePtr = &sysTime;
+	utcOffset = __mkSmallInteger(0);
+	isDst = false;
+    } else {  // local time: have to convert and find out about DST
 	TIME_ZONE_INFORMATION tzInfo;
-	int tzState;
 	LONGLONG longTime;
-
-	FileTimeToLocalFileTime(&fileTime, &localFileTime);
-	FileTimeToSystemTime(&localFileTime, &sysTime);
-
+	SYSTEMTIME localSysTime;
+	FILETIME localFileTime;
+
+	sysTimePtr = &localSysTime;
+
+	if (!SystemTimeToTzSpecificLocalTime(NULL, &sysTime, &localSysTime))
+	    goto out;
+	if (!SystemTimeToFileTime(&localSysTime, &localFileTime))
+	    goto out;
+
+	// all the rest is computing the UTC offset and whether DST applies
 	longTime = ((LONGLONG)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime;
 	longTime -= ((LONGLONG)localFileTime.dwHighDateTime << 32) + localFileTime.dwLowDateTime;
-	utcOffset = __mkSmallInteger((INT)(longTime / 10000000));
-
-	if ((tzState = GetTimeZoneInformation(&tzInfo)) < 0) {
-	    reason = @symbol(getTimeZoneFailed);
-	    goto error;
-	}
-	dstOffset = __mkSmallInteger((tzInfo.Bias + tzInfo.DaylightBias) * 60);
-    } else {
-	FileTimeToSystemTime(&fileTime, &sysTime);
-	utcOffset = __mkSmallInteger(0);
-    }
-
-    hours = __mkSmallInteger(sysTime.wHour);
-    minutes = __mkSmallInteger(sysTime.wMinute);
-    seconds = __mkSmallInteger(sysTime.wSecond);
-
-    year = __mkSmallInteger(sysTime.wYear);
-    month = __mkSmallInteger(sysTime.wMonth);
-    day = __mkSmallInteger(sysTime.wDay);
-
-    weekDay = __mkSmallInteger(sysTime.wDayOfWeek == 0 ? 7 : sysTime.wDayOfWeek);
-error:;
-%}.
+
+	// utcOffset is the difference from UTC to local time including possible DST
+	_utcOffset = longTime / 10000000;
+	utcOffset = __mkSmallInteger(_utcOffset);
+
+# ifdef __BORLANDC__
+	{
+	    typedef BOOL (WINAPI *P_GetTimeZoneInformationForYear)(
+					USHORT,
+					LPTIME_ZONE_INFORMATION, // - should be, but is not defined: PDYNAMIC_TIME_ZONE_INFORMATION,
+					LPTIME_ZONE_INFORMATION);
+	    static P_GetTimeZoneInformationForYear pGetTimeZoneInformationForYear;
+
+	    if (pGetTimeZoneInformationForYear == NULL) {
+		pGetTimeZoneInformationForYear =
+		    (P_GetTimeZoneInformationForYear)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetTimeZoneInformationForYear");
+		if (pGetTimeZoneInformationForYear == NULL) {
+		    // ignore this error and fall back to GetTimeZoneInformation()
+		    reason = @symbol(NoGetTimeZoneInformationForYear);
+		    pGetTimeZoneInformationForYear = false;
+		}
+	    }
+	    if (pGetTimeZoneInformationForYear != false) {
+		if (pGetTimeZoneInformationForYear(localSysTime.wYear, NULL, &tzInfo)) {
+		    _stdUtcOffset = (tzInfo.Bias + tzInfo.StandardBias) * 60;
+		    isDst = (_stdUtcOffset != _utcOffset) ? true : false;
+		} else {
+		    // ignore this error and fall back to GetTimeZoneInformation()
+		    reason = @symbol(GetTimeZoneInformationForYearFailed);
+		    error = __mkSmallInteger(__WIN32_ERR(GetLastError()));
+		}
+	    }
+	}
+# else
+	if (GetTimeZoneInformationForYear(localSysTime.wYear, NULL, &tzInfo)) {
+	    _stdUtcOffset = (tzInfo.Bias + tzInfo.StandardBias) * 60;
+	    isDst = (_stdUtcOffset != _utcOffset) ? true : false;
+	} else {
+	    // ignore this error and fall back to GetTimeZoneInformation()
+	    reason = @symbol(GetTimeZoneInformationForYearFailed);
+	    error = __mkSmallInteger(__WIN32_ERR(GetLastError()));
+	}
+# endif
+	// this code is a fallback for WIN XP
+	if (isDst == nil) {
+	    DWORD retVal = GetTimeZoneInformation(&tzInfo);
+	    switch (retVal) {
+		case TIME_ZONE_ID_STANDARD:
+		case TIME_ZONE_ID_DAYLIGHT:
+		case TIME_ZONE_ID_UNKNOWN:
+		    // nonDstOffset is the difference from UTC to local time without DST
+		    _stdUtcOffset = (tzInfo.Bias + tzInfo.StandardBias) * 60;
+		    isDst = (_stdUtcOffset != _utcOffset) ? true : false;
+		    break;
+
+		// these are errors, which may occur, if the
+		// Windows OS has not been setupm correctly.
+		// We ignore these errors here, but we don't know if DST applies.
+		// Assume that there is no DST.
+		default:
+		case TIME_ZONE_ID_INVALID:
+		    isDst = false;
+		    reason = @symbol(TIME_ZONE_ID_INVALID);
+		    error = __mkSmallInteger(__WIN32_ERR(GetLastError()));
+		    break;
+	    }
+	}  // End WINXP backward compatibility
+    }
+
+    hour = __mkSmallInteger(sysTimePtr->wHour);
+    minute = __mkSmallInteger(sysTimePtr->wMinute);
+    second = __mkSmallInteger(sysTimePtr->wSecond);
+
+    year = __mkSmallInteger(sysTimePtr->wYear);
+    month = __mkSmallInteger(sysTimePtr->wMonth);
+    day = __mkSmallInteger(sysTimePtr->wDay);
+
+    millis = __mkSmallInteger(sysTimePtr->wMilliseconds);
+
+    weekDay = __mkSmallInteger(sysTimePtr->wDayOfWeek == 0 ? 7 : sysTimePtr->wDayOfWeek);
+out:;
+%}.
+"/    '--> REASON: ' errorPrint. reason errorPrintCR. '--> ERROR: ' errorPrint. error errorPrintCR.
+
     year isNil ifTrue:[
-	^ self primitiveFailed
+	TimeConversionError raiseErrorString:' - out of range'.
     ].
 
     info := self timeInfoClass new.
@@ -10514,48 +10827,33 @@
 	year:year
 	month:month
 	day:day
-	hours:hours
-	minutes:minutes
-	seconds:seconds
-	milliseconds:osMilliseconds
+	hours:hour
+	minutes:minute
+	seconds:second
+	milliseconds:millis
 	utcOffset:utcOffset
-	dst:(utcOffset = dstOffset)
+	dst:isDst
 	dayInYear:yDay
 	dayInWeek:weekDay.
 
     LastTimeInfo := info.
-    LastTimeInfoSeconds := osSeconds.
-    LastTimeInfoMilliseconds := osMilliseconds.
+    LastOsTimeLow := tLow.
+    LastOsTimeHi := tHigh.
     LastTimeInfoIsLocal := isLocalTime.
 
     ^ info
 
     "
-     OperatingSystem timeInfoFromSeconds:0 milliseconds:0 localTime:false
-     OperatingSystem timeInfoFromSeconds:0 milliseconds:0 localTime:false
-     OperatingSystem timeInfoFromSeconds:3600 milliseconds:0 localTime:true
-     OperatingSystem timeInfoFromSeconds:Timestamp now utcSecondsSince1970 milliseconds:0 localTime:true
-     OperatingSystem timeInfoFromSeconds:Timestamp now utcSecondsSince1970 milliseconds:0 localTime:false
+    self assert:(Timestamp year:1994 month:2 day:1 hour:12 minute:0 second:0) timeInfo dst not
+
+    DST in MEZ in 1994:
+      self assert:(Timestamp year:1994 month:7 day:1 hour:12 minute:0 second:0) timeInfo dst
+
+     no DST in MEZ in 1970:
+      self assert:(Timestamp year:1977 month:7 day:1 hour:12 minute:0 second:0) timeInfo dst not
     "
 
     "Modified: / 06-07-2006 / 18:18:56 / cg"
-!
-
-utcOffset
-    "return the difference between UTC (Greenwich Mean Time) and the local time in seconds.
-     If daylight saving time applies to ourself, take that into account.
-
-     Add utcOffset to convert from local time to UTC time.
-     Subtract utcOffset to convert from UTC time to local time.
-
-     If utcOffset is negative, the local timezone is east of Greenwich.
-     If utcOffset is positive, the local timezone is west of Greenwich."
-
-    ^ self getTimezoneInformation utcOffset
-
-    "
-     OperatingSystem utcOffset -> -7200
-    "
 ! !
 
 !Win32OperatingSystem class methodsFor:'users & groups'!
@@ -10982,95 +11280,81 @@
 
     |pid status code core|
 %{
+//#define PROCESSDEBUG_CHILDPROCESSWAIT
+
     int endStatus;
+    DWORD exitCode;
 
     if (__isExternalAddressLike(pidToWait) ) {
 	HANDLE __pidToWait = _HANDLEVal(pidToWait);
-	int t;
 
 #ifdef PROCESSDEBUG_CHILDPROCESSWAIT
 	console_printf("childProcessWait %x b %d\n",__pidToWait,blocking==true);
 #endif
-	t = (blocking==true) ? INFINITE : 0;
-
+
+	if (blocking == true) {
 #ifdef DO_WRAP_CALLS
-	if (t == 0) {
-	    /* no need for WRAP-call; does not block */
-	    endStatus = WaitForSingleObject(__pidToWait, t);
-	    if (endStatus < 0) {
-		__threadErrno = __WIN32_ERR(GetLastError());
-	    }
-	} else {
 	    do {
 		__threadErrno = 0;
 		// do not cast to INT - will loose sign bit then!
-		endStatus = STX_API_CALL2( "WaitForSingleObject", WaitForSingleObject, __pidToWait, t);
+		endStatus = STX_API_CALL2( "WaitForSingleObject", WaitForSingleObject, __pidToWait, INFINITE);
 	    } while ((endStatus < 0) && (__threadErrno == EINTR));
-	}
-#else
-	endStatus = WaitForSingleObject(__pidToWait, t);
-	if (endStatus < 0) {
-	    __threadErrno = __WIN32_ERR(GetLastError());
-	}
-#endif
-	if ( endStatus == WAIT_TIMEOUT ) {
-	    if (blocking==true)
-		status = @symbol(timeout);
-	    else {
-		status = @symbol(continue);
+#else
+	    endStatus = WaitForSingleObject(__pidToWait, INFINITE);
+	    if (endStatus < 0) {
+		__threadErrno = __WIN32_ERR(GetLastError());
+	    }
+#endif
+	    if (endStatus == WAIT_TIMEOUT) {
+		if (blocking==true)
+		    status = @symbol(timeout);
+		else {
+		    status = @symbol(continue);
 #ifdef PROCESSDEBUG_CHILDPROCESSWAIT
-		console_printf("ret nil\n");
+		    console_printf("ret nil\n");
+#endif
+		    RETURN(nil);
+		}
+	    } else if (endStatus == WAIT_OBJECT_0) {
+
+	    }
+	}
+
+#ifdef PROCESSDEBUG_CHILDPROCESSWAIT
+	console_printf("GetExitCodeProcess\n");
+#endif
+
+	if (GetExitCodeProcess(__pidToWait, &exitCode)) {
+	    if (exitCode == STILL_ACTIVE) {
+#ifdef PROCESSDEBUG_CHILDPROCESSWAIT
+		console_printf("exitCode: STILL_ACTIVE\n");
 #endif
 		RETURN(nil);
 	    }
-	} else {
-	    status = @symbol(exit);
-#ifdef PROCESSDEBUG_CHILDPROCESSWAIT
-	    console_printf("exit\n");
-#endif
-	    if (endStatus == WAIT_OBJECT_0) {
-		DWORD exitCode;
-
-		if (GetExitCodeProcess(__pidToWait, &exitCode)) {
-#ifdef PROCESSDEBUG_CHILDPROCESSWAIT
-		    console_printf("exitCode: %d\n", exitCode);
-#endif
-		    if (exitCode == STILL_ACTIVE) {
-			RETURN(nil);
-		    }
 #ifdef PROCESSDEBUG_CHILDPROCESSWAIT
-		    console_printf("exit %d\n", exitCode);
-#endif
-		    code = __mkSmallInteger(exitCode);
-		} else {
+	    console_printf("exitCode %d\n", exitCode);
+#endif
+	    status = @symbol(exit);
+	    code = __mkSmallInteger(exitCode);
+	    core = false;
+	    pid = pidToWait;
+	} else {
+	    code = __mkSmallInteger(GetLastError());
 #ifdef PROCESSDEBUG_CHILDPROCESSWAIT
-		    console_printf("GetExitCodeProcess failed\n");
-#endif
-		    code = __mkSmallInteger(GetLastError());
-		}
-	    } else {
-		code = __mkSmallInteger(-1);
-	    }
-	}
-	core = false;
-	pid = pidToWait;
+	    console_printf("GetExitCodeProcess failed: error=%d\n", GetLastError());
+#endif
+	}
     }
 %}.
 
     (status isNil or:[pid isNil]) ifTrue:[
-	^ self primitiveFailed
+	^ self primitiveFailed:code
     ].
 
 "/ Transcript show:'pid: '; show:pid; show:' status: '; show:status;
 "/ show:' code: '; show:code; show:' core:'; showCR:core.
 
     ^ OSProcessStatus pid:pid status:status code:code core:core
-
-    "
-     OperatingSystem childProcessWait:false
-    "
-
-    "Created: 5.1.1996 / 16:39:14 / stefan"
 !
 
 numAvailableForReadOn:fd
@@ -11079,29 +11363,71 @@
     ^ (self readCheck:fd) ifTrue:[1] ifFalse:[0]
 !
 
-selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray withTimeOut:millis
-    "wait for any fd in readFdArray (an Array of integers) to become ready for
-     reading, writeFdArray to become ready for writing, or exceptFdArray to
-     arrive exceptional data (i.e. out-of-band data).
-     Timeout after t milliseconds or, if the timeout time is 0, immediately..
+selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray
+  readableInto:readableResultFdArray writableInto:writableResultFdArray exceptionInto:exceptionResultFdArray
+  withTimeOut:millis
+    "wait for any fd in readFdArray (an Array of integers) to become ready for reading,
+     writeFdArray to become ready for writing,
+     or exceptFdArray to arrive exceptional data (i.e. out-of-band data).
+     Timeout after t milliseconds or - if the timeout time is 0 - immediately..
      Empty fd-sets will always wait. Zero time can be used to poll file-
      descriptors (i.e. to check if I/O possible without blocking).
-     Return first ready fd if I/O ok, nil if timed-out or interrupted."
-
-%{
+     The corresponding filedescriptors which are ready are returned in readableResultFdArray,
+     writableResultFdArray and exceptionResultFdArray respectively.
+
+     Return the (overall) number of selected filedescriptors.
+     readableResultFdArray, writableResultFdArray and exceptionResultFdArray will
+     get a nil-value stored into the slot after the last valid fileDescriptor;
+     Thus, the caller can simply scan these arrays upTo the end or a nil value."
+
+%{
+//#define SELECTDEBUGWIN32
+//#define SELECT3DEBUGWIN32
 #define MAXHANDLE 128
-
-    int i;
+    int i, idx;
     INT t;
-    OBJ fd, retFd;
-    int ret;
-    int numHandles = 0;
+    int numHandles;
     DWORD res;
     HANDLE hArray[MAXHANDLE+1];
-    int    retArray[MAXHANDLE];
-    int    readCount;
-    int    writeCount;
-    int    exceptCount;
+    int retArray[MAXHANDLE];
+    int readCount, writeCount, exceptCount;
+    int resultSizeReadable = 0, resultSizeWritable = 0, resultSizeException = 0;
+    int cntR = 0, cntW = 0, cntE = 0, cntAll = 0;
+    int *pcntR = &cntR, *pcntW = &cntW, *pcntE = &cntE;
+    fd_set readFds;
+    fd_set writeFds;
+    int hasSockets;
+    int hasPipes;
+    int pass = 1;       // perform up to 2 passes
+
+    if (readableResultFdArray != nil) {
+	if (! __isArrayLike(readableResultFdArray)) {
+	    goto fail;
+	}
+	resultSizeReadable = __arraySize(readableResultFdArray);
+    }
+    if (writableResultFdArray != nil) {
+	if (! __isArrayLike(writableResultFdArray)) {
+	    goto fail;
+	}
+	resultSizeWritable = __arraySize(writableResultFdArray);
+	if (readableResultFdArray == writableResultFdArray) {
+	    // allow common result set for read/write/except
+	    pcntW = &cntR;
+	}
+    }
+    if (exceptionResultFdArray != nil) {
+	if (! __isArrayLike(exceptionResultFdArray)) {
+	    goto fail;
+	}
+	resultSizeException = __arraySize(exceptionResultFdArray);
+	if (exceptionResultFdArray == readableResultFdArray) {
+	    // allow common result set for read/write/except
+	    pcntE = &cntR;
+	} else if (exceptionResultFdArray == writableResultFdArray) {
+	    pcntE = &cntW;
+	}
+    }
 
     if (__isNonNilObject(readFdArray)) {
 	if (! __isArrayLike(readFdArray)) goto fail;
@@ -11124,54 +11450,64 @@
 	exceptCount = 0;
     }
 
-    for (i = 0; (i < readCount) && (numHandles < MAXHANDLE);i++) {
-	fd = __ArrayInstPtr(readFdArray)->a_element[i];
+pollAgain:
+    FD_ZERO(&readFds);
+    FD_ZERO(&writeFds);
+    numHandles = hasSockets = hasPipes = 0;
+
+    for (i = 0; (i < readCount) && (numHandles < MAXHANDLE); i++) {
+	OBJ fd = __arrayVal(readFdArray)[i];
 
 	if (fd != nil) {
-	    if (__isExternalAddressLike(fd)) {
+	    if (__Class(fd) == @global(Win32SocketHandle)) {
+		FD_SET (_HANDLEVal(fd), &readFds);
+		hasSockets++;
+	    } else if (__isSmallInteger(fd)) {
+		DWORD canRead;
+		if (PeekNamedPipe(_get_osfhandle(__intVal(fd)), 0, 0, 0, &canRead, 0)) {
+		    if (canRead > 0) {
+			if (*pcntR < resultSizeReadable) {
+			    __arrayVal(readableResultFdArray)[*pcntR] = fd;
+			}
+			(*pcntR)++; cntAll++;
+		    }
+		} else {
+		    @global(LastErrorNumber) = __mkSmallInteger(EBADF);
+		    RETURN (__mkSmallInteger(-1));
+		}
+		hasPipes++;
+	    } else {
 		hArray  [numHandles] = _HANDLEVal(fd);
 		retArray[numHandles] = i;
 		++numHandles;
-	    } else {
-		int canRead = _canReadWithoutBlocking (__intVal(fd) );
-
-		if (canRead > 0 ) {
-		    RETURN (fd);
-		} else {
-		    if (canRead < 0 ) {
-			@global(LastErrorNumber) = __mkSmallInteger(EBADF);
-			RETURN ( @symbol(error) );
-		    }
-		}
-	    }
-	}
-    }
-
-    for (i = 0; (i < writeCount) && (numHandles < MAXHANDLE);i++) {
-	fd = __ArrayInstPtr(writeFdArray)->a_element[i];
+	    }
+	}
+    }
+
+    for (i = 0; (i < writeCount) && (numHandles < MAXHANDLE); i++) {
+	OBJ fd = __arrayVal(writeFdArray)[i];
 
 	if (fd != nil) {
-	    if (__isExternalAddressLike(fd)) {
+	    if (__Class(fd) == @global(Win32SocketHandle)) {
+		FD_SET (_HANDLEVal(fd), &writeFds);
+		hasSockets++;
+	    } else if (__isSmallInteger(fd)) {
+		// kludge: assume that pipes can alway be written
+	       if (*pcntW < resultSizeWritable) {
+		    __arrayVal(writableResultFdArray)[*pcntW] = fd;
+		}
+		(*pcntW)++; cntAll++;
+		// there is no pipe to check
+	    } else {
 		hArray  [numHandles] = _HANDLEVal(fd);
 		retArray[numHandles] = i + 10000;
 		++numHandles;
-	    } else {
-		int canWrite = _canWriteWithoutBlocking (__intVal(fd) );
-
-		if (canWrite > 0 ) {
-		    RETURN (fd);
-		} else {
-		    if (canWrite < 0 ) {
-			@global(LastErrorNumber) = __mkSmallInteger(EBADF);
-			RETURN ( @symbol(error) );
-		    }
-		}
-	    }
-	}
-    }
-
-    for (i = 0; (i < exceptCount) && (numHandles < MAXHANDLE);i++) {
-	fd = __ArrayInstPtr(exceptFdArray)->a_element[i];
+	    }
+	}
+    }
+
+    for (i = 0; (i < exceptCount) && (numHandles < MAXHANDLE); i++) {
+	OBJ fd = __arrayVal(exceptFdArray)[i];
 
 	if (fd != nil) {
 	    if (__isExternalAddressLike(fd)) {
@@ -11182,130 +11518,181 @@
 	}
     }
 
-    if (__isSmallInteger(millis)) {
-	t = __intVal(millis);
-
-	if (t <= 0 && numHandles == 0) {
-	    RETURN (nil);
-	}
+    if (hasSockets) {
+	struct timeval tv = {0, 0};
+	int nReady;
+
+#ifdef SELECT3DEBUGWIN32
+	console_printf("select hasSockets = %d\n", hasSockets);
+#endif
+	nReady = select(1 , &readFds, &writeFds, NULL, &tv);  // first parameter to select is ignored in windows
+	if (nReady < 0) {
+#ifdef SELECTDEBUGWIN32
+	    console_printf("error in select %d %d\n", nReady, GetLastError());
+#endif
+	    @global(LastErrorNumber) = __mkSmallInteger(EBADF);
+	    RETURN (__mkSmallInteger(-1));
+	}
+	if (nReady > 0) {
+#ifdef SELECT3DEBUGWIN32
+	    console_printf("select nReady %d of %d\n", nReady, hasSockets);
+#endif
+	    for (i = 0; i < readCount; i++) {
+		OBJ fd = __arrayVal(readFdArray)[i];
+		if ((__Class(fd) == @global(Win32SocketHandle)) && FD_ISSET(_HANDLEVal(fd), &readFds)) {
+		    if (*pcntR < resultSizeReadable) {
+			__arrayVal(readableResultFdArray)[*pcntR] = fd;
+			__STORE(readableResultFdArray, fd);
+		    }
+		    (*pcntR)++; cntAll++;
+		}
+	    }
+	    for (i = 0; i < writeCount; i++) {
+		OBJ fd = __arrayVal(writeFdArray)[i];
+		if ((__Class(fd) == @global(Win32SocketHandle)) && FD_ISSET(_HANDLEVal(fd), &writeFds)) {
+		    if (*pcntW < resultSizeWritable) {
+			__arrayVal(writableResultFdArray)[*pcntW] = fd;
+			__STORE(writableResultFdArray, fd);
+		    }
+		    (*pcntW)++; cntAll++;
+		}
+	    }
+	}
+    }
+    if (pass > 1)       // perform maximum 2 passes
+	goto done;
+
+    if (cntAll) {
+	// check for other handles and return immediately, no timeout
+	t = 0;
     } else {
-	t = INFINITE;
+	if (__isSmallInteger(millis)) {
+	    t = __intVal(millis);
+
+	    if (t <= 0 && numHandles == 0) {
+		RETURN (__mkSmallInteger(0));
+	    }
+	} else {
+	    t = INFINITE;
+	}
+    }
+
+    if (numHandles == 0 && t == 0) {
+	// nothing to do and no wait
+	goto done;
     }
 
 #ifdef SELECT3DEBUGWIN32
-    console_printf("wait Handles = %d timeout = %d\n",numHandles, t);
-#endif
-
-    res = __vmWait (numHandles, hArray, MAXHANDLE, t);
+    console_printf("wait numhandles = %d timeout = %d\n", numHandles, t);
+#endif
+
+    res = __vmWait(numHandles, hArray, MAXHANDLE, t);
+
+    if (res == WAIT_TIMEOUT) {
+#ifdef SELECT3DEBUGWIN32
+	console_printf("- timeOut; ret nil\n" );
+#endif
+	if (t != 0 && (hasSockets || hasPipes)) {
+	    // if not a single handle is ready, poll sockets an pipes again
+	    pass = 2;
+	    goto pollAgain;
+	}
+	goto done;
+    }
+
+    if (res == WAIT_FAILED) {
+#ifdef SELECT2DEBUGWIN32
+	console_printf("- error %d (last %d); ret -1\n", __threadErrno, GetLastError());
+#endif
+	if (__threadErrno == EINTR) {
+	    @global(LastErrorNumber) = nil;
+	    RETURN (__mkSmallInteger(0));
+	} else {
+	    if (@global(InfoPrinting) == true) {
+//                console_fprintf(stderr, "Win32OS [info]: select errno = %d (last %d)\n", __threadErrno, GetLastError());
+		console_printf("Win32OS [info]: select errno = %d (last %d)\n", __threadErrno, GetLastError());
+	    }
+	    @global(LastErrorNumber) = __mkSmallInteger(EBADF);
+	    RETURN (__mkSmallInteger(-1));
+	}
+    }
 
     if (numHandles) {
-	if (res == WAIT_FAILED) {
-#ifdef SELECT2DEBUGWIN32
-	    console_printf("- error %d; ret nil\n",GetLastError());
-#endif
-	    if (__threadErrno == EINTR) {
-		__threadErrno = 0;
-		@global(LastErrorNumber) = nil;
-	    } else {
-		__threadErrno = EBADF;
-		if (@global(InfoPrinting) == true) {
-		    console_fprintf(stderr, "Win32OS [info]: select errno = %d\n", __threadErrno);
-		}
-		@global(LastErrorNumber) = __mkSmallInteger(__threadErrno);
-		RETURN ( @symbol(error) );
-	    }
-	    RETURN ( nil );
-	}
-
-	if (res == WAIT_TIMEOUT) {
-#ifdef SELECT3DEBUGWIN32
-	    console_printf("- timeOut; ret nil\n" );
-#endif
-	    goto polling;
-	}
-
 	if (res == numHandles) {
+	    // vmwait() added an IRQ event to the handles, and this one has been triggered
 	    if (1 /* @global(InfoPrinting) == true */) {
 		console_fprintf(stderr, "Win32OS [info]: plugIn event has been handled\n");
 	    }
-	    __threadErrno = 0;
-	    @global(LastErrorNumber) = nil;
-	    RETURN ( nil );
-	}
-	if ((res < 0) || (res > numHandles)) {
-#ifdef SELECTDEBUGWIN32
+	    goto done;
+	}
+	if ((res < 0) || (res >= numHandles)) {
 	    console_printf("- res=%d error1 %d\n", res, GetLastError());
-#endif
-	    __threadErrno = 0;
-	    @global(LastErrorNumber) = nil;
-	    RETURN ( nil );
-	}
-
-	ret = res;
-
-	if (ret < numHandles) {
-	    int fd = retArray[ret];
-
-	    @global(LastErrorNumber) = nil;
+	    goto done;
+	}
+
+	idx = retArray[res];
+	cntAll++;
 
 #ifdef SELECTDEBUGWIN32
-	    if (ret) console_printf("wait Handles %d %d ret\n", ret, fd);
-#endif
-	    if (fd < 10000) {
-		RETURN ( __ArrayInstPtr(readFdArray)->a_element[fd] );
-	    }
-	    if (fd < 20000) {
-		RETURN ( __ArrayInstPtr(writeFdArray)->a_element[fd-10000] );
-	    }
-	    RETURN ( __ArrayInstPtr(exceptFdArray)->a_element[fd-20000] );
-	}
-	console_fprintf(stderr, "Win32OS [info]: wait Handles ret = %d error2 %d\n", ret, GetLastError());
-	goto fail;
-    } else {
-
-polling:
-
-	for (i=0; i < readCount;i++) {
-	    fd = __ArrayInstPtr(readFdArray)->a_element[i];
-
-	    if (fd != nil) {
-		if (! __isExternalAddressLike(fd)) {
-		    int canRead = _canReadWithoutBlocking (__intVal(fd));
-
-		    if (canRead > 0 ) {
-			RETURN (fd);
-		    } else {
-			if (canRead < 0 ) {
-			    @global(LastErrorNumber) = __mkSmallInteger(EBADF);
-			    RETURN ( @symbol(error) );
-			}
-		    }
-		}
-	    }
-	}
-
-	for (i=0; i < writeCount;i++) {
-	    fd = __ArrayInstPtr(writeFdArray)->a_element[i];
-
-	    if (fd != nil) {
-		if (! __isExternalAddressLike(fd)) {
-		    int canWrite = _canWriteWithoutBlocking (__intVal(fd));
-
-		    if (canWrite > 0 ) {
-			RETURN (fd);
-		    } else {
-			if (canWrite < 0 ) {
-			    @global(LastErrorNumber) = __mkSmallInteger(EBADF);
-			    RETURN ( @symbol(error) );
-			}
-		    }
-		}
-	    }
-	}
-
-	@global(LastErrorNumber) = nil;
-	RETURN ( nil );
-    }
+	console_printf("wait Handles res %d idx %d numHandles %d --- ", res, idx, numHandles);
+#endif
+	if (idx < 10000) {
+	    if (*pcntR < resultSizeReadable) {
+		OBJ temp = __arrayVal(readFdArray)[idx];
+		__arrayVal(readableResultFdArray)[*pcntR] = temp;
+		__STORE(readableResultFdArray, temp);
+#ifdef SELECTDEBUGWIN32
+		console_printf("read ready: %x\n", __externalAddressVal(temp));
+#endif
+		(*pcntR)++;
+	    }
+	} else if (idx < 20000) {
+	    if (*pcntW < resultSizeWritable) {
+		OBJ temp = __arrayVal(writeFdArray)[idx-10000];
+		__arrayVal(writableResultFdArray)[*pcntW] = temp;
+		__STORE(writableResultFdArray, temp);
+#ifdef SELECTDEBUGWIN32
+		console_printf("write ready: %x\n", temp);
+#endif
+		(*pcntW)++;
+	    }
+	} else {
+	    if (*pcntE < resultSizeException) {
+		OBJ temp = __arrayVal(exceptFdArray)[idx-20000];
+		__arrayVal(exceptionResultFdArray)[*pcntE] = temp;
+		__STORE(exceptionResultFdArray, temp);
+#ifdef SELECTDEBUGWIN32
+		console_printf("except ready: %x\n", temp);
+#endif
+		(*pcntE)++;
+	    }
+#ifdef SELECTDEBUGWIN32
+	    else
+		console_printf("cntE: %d, resultSizeException: %d\n", *pcntE, resultSizeException);
+#endif
+	}
+    }
+    if (t != 0 && (hasSockets || hasPipes)) {
+	// back after timeout, maybe some sockets or pipes die wake up
+	// in the meantime?
+	pass = 2;
+	goto pollAgain;
+    }
+
+done:
+    /* add a delimiter */
+    if (*pcntR < resultSizeReadable) {
+	__arrayVal(readableResultFdArray)[*pcntR] = nil;
+    }
+    if (*pcntW < resultSizeWritable) {
+	__arrayVal(writableResultFdArray)[*pcntW] = nil;
+    }
+    if (*pcntE < resultSizeException) {
+	__arrayVal(exceptionResultFdArray)[*pcntE] = nil;
+    }
+
+    @global(LastErrorNumber) = nil;
+    RETURN (__mkSmallInteger(cntAll));
 
 fail: ;
 %}.
@@ -11326,7 +11713,7 @@
      Ignored in windows. Windows calls operate in their own thread,
      so non-blocking mode doesn't make sense."
 
-    ^ true 
+    ^ true
 !
 
 waitForMultipleObjects:fdOrHandleArray withTimeout:millis
@@ -11343,27 +11730,31 @@
     INT t;
     int res;
     HANDLE hArray[MAXHANDLE];
-    INT i, count;
+    int idxArray[MAXHANDLE];
+    INT i, count, hIdx;
 
     if (! __isArrayLike(fdOrHandleArray)) {
 	goto fail;
     }
     count = __arraySize(fdOrHandleArray);
 
-    for (i=0; i<count; i++) {
+    for (hIdx=0, i=0; i<count; i++) {
 	OBJ fdOrHandle = __ArrayInstPtr(fdOrHandleArray)->a_element[i];
 	HANDLE h;
 
-	if (__isExternalAddressLike(fdOrHandle)) {
-	    h = _HANDLEVal(fdOrHandle);
-	} else {
-	    if (__isSmallInteger(fdOrHandle)) {
-		h = (HANDLE) _get_osfhandle (__intVal(fdOrHandle));
+	if (fdOrHandle != nil) {
+	    if (__isExternalAddressLike(fdOrHandle)) {
+		h = _HANDLEVal(fdOrHandle);
 	    } else {
-		goto fail;
-	    }
-	}
-	hArray[i] = h;
+		if (__isSmallInteger(fdOrHandle)) {
+		    h = (HANDLE) _get_osfhandle (__intVal(fdOrHandle));
+		} else {
+		    goto fail;
+		}
+	    }
+	    hArray[hIdx] = h;
+	    idxArray[hIdx++] = i;
+	}
     }
 
     if (__isSmallInteger(millis)) {
@@ -11373,25 +11764,29 @@
     }
 
 #ifdef DO_WRAP_CALLS
-    do {
-	__threadErrno = 0;
-	// do not cast to INT - will loose sign bit then!
-	res = STX_API_CALL4( "WaitForMultipleObjects", WaitForMultipleObjects, count, hArray, FALSE, t);
-    } while ((res < 0) && (__threadErrno == EINTR));
-#else
-    res = WaitForMultipleObjects(count, hArray, FALSE, t);
-    if (res < 0) {
-	__threadErrno = __WIN32_ERR(GetLastError());
-    }
-#endif
+    if (t != 0) {
+	do {
+	    __threadErrno = 0;
+	    // do not cast to INT - will loose sign bit then!
+	    res = STX_API_CALL4( "WaitForMultipleObjects", WaitForMultipleObjects, hIdx, hArray, FALSE, t);
+	} while ((res < 0) && (__threadErrno == EINTR));
+    } else
+#endif
+    {
+	res = WaitForMultipleObjects(hIdx, hArray, FALSE, t);
+	if (res < 0) {
+	    __threadErrno = __WIN32_ERR(GetLastError());
+	}
+    }
+
     if (res == WAIT_FAILED) {
 	RETURN (nil);
     }
     if (res == WAIT_TIMEOUT) {
 	RETURN (nil);
     }
-    if ((res >= WAIT_OBJECT_0) && (res < (WAIT_OBJECT_0+count))) {
-	RETURN (__ArrayInstPtr(fdOrHandleArray)->a_element[res-WAIT_OBJECT_0]);
+    if ((res >= WAIT_OBJECT_0) && (res < (WAIT_OBJECT_0+hIdx))) {
+	RETURN (__arrayVal(fdOrHandleArray)[idxArray[res-WAIT_OBJECT_0]]);
     }
 
     RETURN (nil);
@@ -11813,6 +12208,10 @@
     ^ size
 !
 
+sourcePath
+    ^ sourcePath
+!
+
 statusChangeTime
     "return statusChanged"
 
@@ -12029,6 +12428,11 @@
 
 isUnknown
     ^ type == #unknown
+!
+
+isValid
+    "answer true if the fileInfo is valid"
+    ^ type notNil
 ! !
 
 !Win32OperatingSystem::OSProcessStatus class methodsFor:'documentation'!
@@ -12172,6 +12576,12 @@
     "Modified: 30.4.1996 / 18:27:03 / cg"
 !
 
+isError
+    "true if process terminated with error"
+
+    ^ status == #exit and:[code ~= 0]
+!
+
 stillAlive
     "true if process is still alive"
 
@@ -12189,6 +12599,155 @@
     "Modified: 28.12.1995 / 14:13:41 / stefan"
 ! !
 
+!Win32OperatingSystem::PECOFFConstants class methodsFor:'documentation'!
+
+documentation
+"
+    COFF machine type IDs.
+
+    [author:]
+        Jan Vrany
+
+    [instance variables:]
+
+    [class variables:]
+
+    [see also:]
+        Microsoft Portable Executable and Common Object File Format Specification,
+        section 6. Machine Types
+
+"
+! !
+
+!Win32OperatingSystem::PECOFFConstants class methodsFor:'initialization'!
+
+initialize
+    "Invoked at system start or when the class is dynamically loaded."
+
+    "/ See Microsoft Portable Executable and Common Object File Format Specification,
+    "/ section 4
+
+    PE_Signature_OFFSET_OFFSET := 16r3C.
+    PE_Signature := #[80 69 0 0].
+
+    "/ See Microsoft Portable Executable and Common Object File Format Specification,
+    "/ section 5
+
+    COFF_HEADER_SIZE := 20.
+    COFF_HEADER_Machine_OFFSET := 0.          
+
+    "/ See Microsoft Portable Executable and Common Object File Format Specification,
+    "/ section 6
+
+    IMAGE_FILE_MACHINE_UNKNOWN := 16r0.
+    IMAGE_FILE_MACHINE_AM33 := 16r1D3.
+    IMAGE_FILE_MACHINE_AMD64 := 16r8664.
+    IMAGE_FILE_MACHINE_ARM := 16r1C0.
+    IMAGE_FILE_MACHINE_ARMNT := 16r1C4.
+    IMAGE_FILE_MACHINE_ARM64 := 16rAA64.
+    IMAGE_FILE_MACHINE_EBC := 16rEBC.
+    IMAGE_FILE_MACHINE_I386 := 16r14C.
+    IMAGE_FILE_MACHINE_IA64 := 16r200.
+    IMAGE_FILE_MACHINE_M32R := 16r9041.
+    IMAGE_FILE_MACHINE_MIPS16 := 16r266.
+    IMAGE_FILE_MACHINE_MIPSFPU := 16r366.
+    IMAGE_FILE_MACHINE_MIPSFPU16 := 16r466.
+    IMAGE_FILE_MACHINE_POWERPC := 16r1F0.
+    IMAGE_FILE_MACHINE_POWEPCFP := 16r1F1. 
+    IMAGE_FILE_MACHINE_R4000 := 16r166.
+    IMAGE_FILE_MACHINE_SH3 := 16r1A2. 
+    IMAGE_FILE_MACHINE_SH3DSP := 16r1A3. 
+    IMAGE_FILE_MACHINE_SH4 := 16r1A6. 
+    IMAGE_FILE_MACHINE_SH5 := 16r1A8.
+    IMAGE_FILE_MACHINE_THUMB := 16r1C2. 
+    IMAGE_FILE_MACHINE_WCEMIPSV2 := 16r169.
+
+    "Modified: / 16-03-2015 / 13:34:57 / jv"
+    "Modified: / 16-03-2015 / 18:14:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!Win32OperatingSystem::PECOFFFileHeader class methodsFor:'documentation'!
+
+documentation
+"
+    Inteances of COFFFileHeader provides an access to various
+    information about executables / .dlls on Windows
+
+    [author:]
+        Jan Vrany <jan.vrany@fit.cvut.cz>
+
+    [instance variables:]
+
+    [class variables:]
+
+    [see also:]
+        Microsoft Portable Executable and Common Object File Format Specification
+
+"
+! !
+
+!Win32OperatingSystem::PECOFFFileHeader class methodsFor:'instance creation'!
+
+fromFile: aStringOrFilename
+    "Returns a COFFFileHeader of given file.
+     If the given file is not a regular file or
+     of it's not an PE file them an error is thrown."
+
+    ^ self new initializeOnFile: aStringOrFilename
+
+    "Created: / 16-03-2015 / 14:33:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!Win32OperatingSystem::PECOFFFileHeader methodsFor:'accessing'!
+
+machine
+   ^ data wordAt: COFF_HEADER_Machine_OFFSET + 1 MSB: false
+
+    "Created: / 16-03-2015 / 14:29:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!Win32OperatingSystem::PECOFFFileHeader methodsFor:'initialization'!
+
+initializeOnFile: aStringOrFilename
+    file := aStringOrFilename asFilename.
+    file exists ifFalse:[ 
+        self error:'Given file does not exist'.
+        ^ nil
+    ].
+    file isRegularFile ifFalse:[ 
+        self error:'Given file is not a regular file'.
+        ^ nil
+    ].
+    file readingFileDo:[ :s |
+        | sig |    
+        s binary.
+        s position: PE_Signature_OFFSET_OFFSET.
+        s position: (s nextUnsignedLongMSB: false).
+        sig := s next: PE_Signature size.
+        sig = PE_Signature ifFalse:[ 
+            self error: 'Given file is not a valid PE file (no valid PE signature found)'.
+            ^ nil
+        ].
+        data := s next: COFF_HEADER_SIZE
+    ].
+
+    "Created: / 16-03-2015 / 14:34:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!Win32OperatingSystem::PECOFFFileHeader methodsFor:'queries'!
+
+isFor32BitArchitecture
+    ^ { IMAGE_FILE_MACHINE_I386 . IMAGE_FILE_MACHINE_ARM . IMAGE_FILE_MACHINE_ARMNT } includes: self machine
+
+    "Created: / 18-03-2015 / 09:54:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+isFor64BitArchitecture
+    ^ { IMAGE_FILE_MACHINE_AMD64 . IMAGE_FILE_MACHINE_IA64 . IMAGE_FILE_MACHINE_ARM64 } includes: self machine
+
+    "Created: / 18-03-2015 / 09:57:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !Win32OperatingSystem::PerformanceData class methodsFor:'accessing'!
 
 counterIndexTextDictionary
@@ -12276,8 +12835,8 @@
     "
 	VISTA:
 
-	Wer versucht unter Vista die Registy HKEY_PERFORMANCE_DATA abzufragen wird zunächst enttäuscht.
-	Die UAC UserAccessControl verhindern dies nämlich (selbs für den admin).
+	Wer versucht unter Vista die Registy HKEY_PERFORMANCE_DATA abzufragen wird zunächst enttäuscht.
+	Die UAC UserAccessControl verhindern dies nämlich (selbs für den admin).
 
 	Um dies zu umgehen:
 
@@ -14215,7 +14774,7 @@
 key:aKeyNamePath
     "retrieve an entry by full path name (starting at a root)"
 
-    ^ self key:aKeyNamePath createIfAbsent:false
+    ^ self key:aKeyNamePath flags:nil createIfAbsent:false
 
     "
      self key:'HKEY_LOCAL_MACHINE'
@@ -14231,6 +14790,47 @@
 key:aKeyNamePath createIfAbsent:createIfAbsent
     "retrieve an entry by full path name (starting at a root)"
 
+    ^ self key:aKeyNamePath flags:nil createIfAbsent:createIfAbsent
+
+    "
+     self key:'HKEY_LOCAL_MACHINE'
+     self key:'HKEY_LOCAL_MACHINE\Software'
+     self key:'HKEY_LOCAL_MACHINE\Software\Borland\'
+     self key:'HKEY_LOCAL_MACHINE\Software\eXept\Smalltalk/X\3.2.5\Directory'
+     (self key:'HKEY_CLASSES_ROOT\MicrosoftWorks.WordProcessor\CLSID') valueNamed:''
+    "
+
+    "Created: / 19-01-2011 / 15:59:21 / cg"
+!
+
+key:aKeyNamePath flags:flags
+    "retrieve an entry by full path name (starting at a root).
+     flags may be one of:
+	#KEY_WOW64_64KEY to force access to the 64Bit Windows key,
+	#KEY_WOW64_32KEY to force access to the 32Bit Windows key,
+	or nil, to access the key (32/64) for the current application"
+
+    ^ self key:aKeyNamePath flags:flags createIfAbsent:false
+
+    "
+     self key:'HKEY_LOCAL_MACHINE'
+     self key:'HKEY_LOCAL_MACHINE\Software'
+     self key:'HKEY_LOCAL_MACHINE\Software\Borland\'
+     self key:'HKEY_LOCAL_MACHINE\Software\eXept\Smalltalk/X\3.2.5\Directory'
+     (self key:'HKEY_CURRENT_USER\Console' flags:#KEY_WOW64_64KEY) subKeys
+     (self key:'HKEY_CURRENT_USER\Console' flags:#KEY_WOW64_32KEY) subKeys
+    "
+
+    "Modified: / 19-01-2011 / 15:59:36 / cg"
+!
+
+key:aKeyNamePath flags:flags createIfAbsent:createIfAbsent
+    "retrieve an entry by full path name (starting at a root).
+     flags may be one of:
+	#KEY_WOW64_64KEY to force access to the 64Bit Windows key,
+	#KEY_WOW64_32KEY to force access to the 32Bit Windows key,
+	or nil, to access the key (32/64) for the current application"
+
     |idx first rest root|
 
     HKEY_CLASSES_ROOT isNil ifTrue:[self initialize].
@@ -14259,7 +14859,7 @@
     Error handle:[:ex |
 	^ nil
     ] do:[
-	^ root subKeyNamed:rest createIfAbsent:createIfAbsent.
+	^ root subKeyNamed:rest flags:flags createIfAbsent:createIfAbsent.
     ].
 
     "
@@ -14267,7 +14867,7 @@
      self key:'HKEY_LOCAL_MACHINE\Software'
      self key:'HKEY_LOCAL_MACHINE\Software\Borland\'
      self key:'HKEY_LOCAL_MACHINE\Software\eXept\Smalltalk/X\3.2.5\Directory'
-     (self key:'HKEY_CLASSES_ROOT\MicrosoftWorks.WordProcessor\CLSID') valueNamed:''
+     (self key:'HKEY_CLASSES_ROOT\MicrosoftWorks.WordProcessor\CLSID' flags:#KEY_WOW64_64KEY) valueNamed:''
     "
 
     "Created: / 19-01-2011 / 15:59:21 / cg"
@@ -14474,6 +15074,12 @@
     ^ handle address
 !
 
+isNew
+    "answer true, if this key hats just be created, false if it did already exist"
+
+    ^ isNew ? false
+!
+
 name
     "return the keys name component (subKey name within my
      parent key)"
@@ -14498,78 +15104,121 @@
      If it already exists, return it.
      Return nil if the new key cannot be created."
 
-    |newEntry subHandle errorNumber|
-
-%{
-    HKEY myKey, subKey = 0;
-    int _retVal;
-
-    if (__isExternalAddressLike(__INST(handle))
-     && __isStringLike(subKeyString)) {
-	myKey = (HKEY)__externalAddressVal(__INST(handle));
-	if ((_retVal = RegCreateKeyA(myKey, __stringVal(subKeyString), &subKey)) == ERROR_SUCCESS) {
-	    subHandle = __MKEXTERNALADDRESS(subKey);
-	} else {
-	    if ((_retVal != ERROR_PATH_NOT_FOUND)
-	     && (_retVal != ERROR_FILE_NOT_FOUND)) {
-		errorNumber = __MKSMALLINT(_retVal);
-	    }
-	}
-    }
-%}.
-    subHandle notNil ifTrue:[
-	newEntry := self class basicNew
-			setHandle:subHandle
-			path:(path , self class separator asString , subKeyString).
-	newEntry registerForFinalization.
-	^ newEntry.
-    ].
-    errorNumber notNil ifTrue:[
-	(OperatingSystem errorHolderForNumber:errorNumber) reportError.
-    ].
-    ^ nil
+    ^ self subKeyNamed:subKeyString flags:nil createIfAbsent:true
 
     "
      |top sub|
 
-     top := self key:'HKEY_LOCAL_MACHINE'.
+     top := self key:'HKEY_CURRENT_USER'.
      sub := top createSubKeyNamed:'FooBarBaz'.
     "
 !
 
+createSubKeyNamed:subKeyString flags:flags
+    "create a new key below mySelf and return a new registry entry for it.
+     If it already exists, return it.
+     Return nil if the new key cannot be created.
+     flags may be one of:
+	#KEY_WOW64_64KEY to force access to the 64Bit Windows key,
+	#KEY_WOW64_32KEY to force access to the 32Bit Windows key,
+	or nil, to access the key (32/64) for the current application"
+
+
+    ^ self subKeyNamed:subKeyString flags:flags createIfAbsent:true
+
+    "
+     |top sub|
+
+     top := self key:'HKEY_CURRENT_USER'.
+     sub := top createSubKeyNamed:'FooBarBaz' flags:nil.
+    "
+!
+
 deleteSubKeyNamed:subKeyString
     "delete a key below mySelf.
      Return true on success."
 
-    |errorNumber|
-
-%{
-    HKEY myKey;
+    ^ self deleteSubKeyNamed:subKeyString flags:nil
+
+    "
+     |top sub|
+
+     top := self key:'HKEY_CURRENT_USER'.
+     sub := top createSubKeyNamed:'FooBarBaz'.
+     top deleteSubKeyNamed:'FooBarBaz'.
+    "
+!
+
+deleteSubKeyNamed:subKeyString flags:flags
+    "delete a key below mySelf.
+     Return true on success.
+     flags may be one of:
+        #KEY_WOW64_64KEY to force access to the 64Bit Windows key,
+        #KEY_WOW64_32KEY to force access to the 32Bit Windows key,
+        or nil, to access the key (32/64) for the current application.
+
+     CAVEAT: due to a missing library entry in the BCC system,
+             the flags are currently ignored"
+
+    |subKeyStringZ errorNumber|
+
+    subKeyStringZ := subKeyString asUnicode16StringZ.
+
+%{
+#ifndef KEY_WOW64_64KEY
+// this is missing in BCC header files
+# define KEY_WOW64_64KEY    0x0100
+# define KEY_WOW64_32KEY    0x0200
+#endif
+
+    HKEY myKey, subKey = 0;
     int _retVal;
+    int _flags = 0;
+
+    if (flags != nil) {
+        if (flags == @symbol(KEY_WOW64_64KEY)) {
+            _flags = KEY_WOW64_64KEY;
+        } else if (flags == @symbol(KEY_WOW64_32KEY)) {
+            _flags = KEY_WOW64_32KEY;
+        } else {
+            errorNumber = @symbol(badArgument2);
+            goto out;
+        }
+    }
 
     if (__isExternalAddressLike(__INST(handle))
-     && __isStringLike(subKeyString)) {
-	myKey = (HKEY)__externalAddressVal(__INST(handle));
-	if ((_retVal = RegDeleteKeyA(myKey, __stringVal(subKeyString))) == ERROR_SUCCESS) {
-	    RETURN (true);
-	}
-	if ((_retVal != ERROR_PATH_NOT_FOUND)
-	 && (_retVal != ERROR_FILE_NOT_FOUND)) {
-	    errorNumber = __MKSMALLINT(_retVal);
-	}
-    }
-%}.
+     && __isUnicode16String(subKeyStringZ)) {
+        myKey = (HKEY)__externalAddressVal(__INST(handle));
+#ifdef __BORLANDC__
+        _retVal = RegDeleteKeyW(myKey, __unicode16StringVal(subKeyStringZ));
+#else
+        _retVal = RegDeleteKeyExW(myKey,
+                    __unicode16StringVal(subKeyStringZ),
+                    _flags,
+                    0); // reserved
+#endif
+        if (_retVal == ERROR_SUCCESS) {
+            RETURN (true);
+        }
+        if ((_retVal != ERROR_PATH_NOT_FOUND)
+         && (_retVal != ERROR_FILE_NOT_FOUND)) {
+            errorNumber = __MKSMALLINT(_retVal);
+        }
+    }
+out:;
+%}.
+
     errorNumber notNil ifTrue:[
-	(OperatingSystem errorHolderForNumber:errorNumber) reportError.
+        (OperatingSystem errorHolderForNumber:errorNumber) reportError.
     ].
     ^ false
 
     "
      |top sub|
 
-     top := self key:'HKEY_LOCAL_MACHINE'.
+     top := self key:'HKEY_CURRENT_USER'.
      sub := top createSubKeyNamed:'FooBarBaz'.
-     top deleteSubKeyNamed:'FooBarBaz'.
+     top deleteSubKeyNamed:'FooBarBaz' flags:nil.
     "
 !
 
@@ -14584,24 +15233,24 @@
     int _retVal;
 
     if (__isExternalAddressLike(__INST(handle)) && __isStringLike(hostName)) {
-	myKey = (HKEY)__externalAddressVal(__INST(handle));
-	if ((_retVal = RegConnectRegistryA(__stringVal(hostName), myKey, &remoteKey)) == ERROR_SUCCESS) {
-	    remoteHandle = __MKEXTERNALADDRESS(remoteKey);
-	} else {
-	    if ((_retVal != ERROR_PATH_NOT_FOUND)
-	     && (_retVal != ERROR_FILE_NOT_FOUND)) {
-		errorNumber = __MKSMALLINT(_retVal);
-	    }
-	}
+        myKey = (HKEY)__externalAddressVal(__INST(handle));
+        if ((_retVal = RegConnectRegistryA(__stringVal(hostName), myKey, &remoteKey)) == ERROR_SUCCESS) {
+            remoteHandle = __MKEXTERNALADDRESS(remoteKey);
+        } else {
+            if ((_retVal != ERROR_PATH_NOT_FOUND)
+             && (_retVal != ERROR_FILE_NOT_FOUND)) {
+                errorNumber = __MKSMALLINT(_retVal);
+            }
+        }
     }
 %}.
     remoteHandle notNil ifTrue:[
-	newEntry := self class basicNew setHandle:remoteHandle path:path.
-	newEntry registerForFinalization.
-	^ newEntry.
+        newEntry := self class basicNew setHandle:remoteHandle path:path.
+        newEntry registerForFinalization.
+        ^ newEntry.
     ].
     errorNumber notNil ifTrue:[
-	(OperatingSystem errorHolderForNumber:errorNumber) reportError.
+        (OperatingSystem errorHolderForNumber:errorNumber) reportError.
     ].
     ^ nil
 
@@ -14648,30 +15297,30 @@
 
     if (__isExternalAddressLike(__INST(handle))
      && __isSmallInteger(subKeyIndex)) {
-	myKey = (HKEY)__externalAddressVal(__INST(handle));
-	if ((_retVal = RegEnumKeyExA(myKey, __intVal(subKeyIndex),
-			 nameBuffer, &nameSize,
-			 NULL,
-			 classNameBuffer, &classNameSize,
-			 &modificationTime)) == ERROR_SUCCESS) {
-	    nameBuffer[nameSize] = '\0';
-	    classNameBuffer[classNameSize] = '\0';
-	    subKeyName = __MKSTRING(nameBuffer);
-	    subKeyClassName = __MKSTRING(classNameBuffer);
-	} else {
-	    if ((_retVal != ERROR_PATH_NOT_FOUND)
-	     && (_retVal != ERROR_FILE_NOT_FOUND)
-	     && (_retVal != ERROR_NO_MORE_ITEMS)) {
-		errorNumber = __MKSMALLINT(_retVal);
-	    }
-	}
+        myKey = (HKEY)__externalAddressVal(__INST(handle));
+        if ((_retVal = RegEnumKeyExA(myKey, __intVal(subKeyIndex),
+                         nameBuffer, &nameSize,
+                         NULL,
+                         classNameBuffer, &classNameSize,
+                         &modificationTime)) == ERROR_SUCCESS) {
+            nameBuffer[nameSize] = '\0';
+            classNameBuffer[classNameSize] = '\0';
+            subKeyName = __MKSTRING(nameBuffer);
+            subKeyClassName = __MKSTRING(classNameBuffer);
+        } else {
+            if ((_retVal != ERROR_PATH_NOT_FOUND)
+             && (_retVal != ERROR_FILE_NOT_FOUND)
+             && (_retVal != ERROR_NO_MORE_ITEMS)) {
+                errorNumber = __MKSMALLINT(_retVal);
+            }
+        }
     }
 %}.
     subKeyName notNil ifTrue:[
-	^ self subKeyNamed:subKeyName.
+        ^ self subKeyNamed:subKeyName.
     ].
     errorNumber notNil ifTrue:[
-	(OperatingSystem errorHolderForNumber:errorNumber) reportError.
+        (OperatingSystem errorHolderForNumber:errorNumber) reportError.
     ].
     ^ nil
 
@@ -14687,38 +15336,7 @@
     "return a new registry entry below mySelf with the given subKey.
      Return nil if no such key exists"
 
-    |newEntry subHandle errorNumber|
-
-%{
-    HKEY myKey, subKey = 0;
-    int _retVal;
-
-    if (__isExternalAddressLike(__INST(handle))
-     && __isStringLike(subKeyString)) {
-	myKey = (HKEY)__externalAddressVal(__INST(handle));
-	_retVal = RegOpenKeyA(myKey, __stringVal(subKeyString), &subKey);
-	if (_retVal == ERROR_SUCCESS) {
-	    subHandle = __MKEXTERNALADDRESS(subKey);
-	} else {
-	    if ((_retVal != ERROR_PATH_NOT_FOUND)
-	     && (_retVal != ERROR_FILE_NOT_FOUND)) {
-		errorNumber = __MKSMALLINT(_retVal);
-	    }
-	}
-    }
-%}.
-    subHandle notNil ifTrue:[
-	newEntry := self class basicNew
-			setHandle:subHandle
-			path:((path ? '?') , self class separator asString , subKeyString).
-
-	newEntry registerForFinalization.
-	^ newEntry.
-    ].
-    errorNumber notNil ifTrue:[
-	(OperatingSystem errorHolderForNumber:errorNumber) reportError.
-    ].
-    ^ nil
+    ^ self subKeyNamed:subKeyString flags:nil createIfAbsent:false
 
     "
      |top sub|
@@ -14733,16 +15351,116 @@
      If no such key exists and createIfAbsent is true, the key is created.
      Otherwise, nil is returned"
 
-    |k|
-
-    (k := self subKeyNamed:subKeyString) isNil ifTrue:[
-	createIfAbsent ifTrue:[
-	    ^ self createSubKeyNamed:subKeyString
-	].
-    ].
-    ^ k
-
-    "Created: / 19-01-2011 / 15:58:45 / cg"
+    ^ self subKeyNamed:subKeyString flags:nil createIfAbsent:createIfAbsent
+!
+
+subKeyNamed:subKeyString flags:flags
+    "return a new registry entry below mySelf with the given subKey.
+     Return nil if no such key exists.
+     flags may be one of:
+	#KEY_WOW64_64KEY to force access to the 64Bit Windows key,
+	#KEY_WOW64_32KEY to force access to the 32Bit Windows key,
+	or nil, to access the key (32/64) for the current application"
+
+
+    ^ self subKeyNamed:subKeyString flags:flags createIfAbsent:false
+!
+
+subKeyNamed:subKeyString flags:flags createIfAbsent:createIfAbsent
+    "return a new registry entry below mySelf with the given subKey.
+     If no such key exists and createIfAbsent is true, the key is created.
+     Otherwise, nil is returned.
+     flags may be one of:
+        #KEY_WOW64_64KEY to force access to the 64Bit Windows key,
+        #KEY_WOW64_32KEY to force access to the 32Bit Windows key,
+        or nil, to access the key (32/64) for the current application"
+
+    |subKeyStringZ newEntry subHandle errorNumber disposition|
+
+    subKeyStringZ := subKeyString asUnicode16StringZ.
+
+%{
+#ifndef KEY_WOW64_64KEY
+// this is missing in BCC header files
+# define KEY_WOW64_64KEY    0x0100
+# define KEY_WOW64_32KEY    0x0200
+#endif
+
+    HKEY myKey, subKey = 0;
+    int _retVal;
+    int _flags = 0;
+    int _disposition = 0;
+
+    if (flags != nil) {
+        if (flags == @symbol(KEY_WOW64_64KEY)) {
+            _flags = KEY_WOW64_64KEY;
+        } else if (flags == @symbol(KEY_WOW64_32KEY)) {
+            _flags = KEY_WOW64_32KEY;
+        } else {
+            errorNumber = @symbol(badArgument2);
+            goto out;
+        }
+    }
+
+    if (__isExternalAddressLike(__INST(handle))
+        && __isUnicode16String(subKeyStringZ)) {
+        myKey = (HKEY)__externalAddressVal(__INST(handle));
+        if (createIfAbsent == true) {
+            _retVal = RegCreateKeyExW(myKey,
+                        __unicode16StringVal(subKeyStringZ),
+                        0,      // reserved
+                        NULL,   // class
+                        0,      // options
+                        KEY_ALL_ACCESS|_flags,   // rights
+                        NULL,   // securityAttributes - handle cannot be inherited
+                        &subKey,
+                        &_disposition);  // disposition (created vs. opened)
+            disposition = _disposition == REG_CREATED_NEW_KEY ? true : false;
+        } else {
+            _retVal = RegOpenKeyExW(myKey,
+                        __unicode16StringVal(subKeyStringZ),
+                        0,
+                        KEY_ALL_ACCESS|_flags,
+                        &subKey);
+            disposition = false;
+        }
+        if (_retVal == ERROR_SUCCESS) {
+            subHandle = __MKEXTERNALADDRESS(subKey);
+        } else {
+            if ((_retVal != ERROR_PATH_NOT_FOUND)
+             && (_retVal != ERROR_FILE_NOT_FOUND)) {
+                errorNumber = __MKSMALLINT(_retVal);
+            }
+        }
+    }
+out:;
+%}.
+    subHandle notNil ifTrue:[
+        newEntry := self class basicNew
+                        setHandle:subHandle
+                        path:((path ? '?') , self class separator asString , subKeyString)
+                        isNew:disposition.
+
+        newEntry registerForFinalization.
+        ^ newEntry.
+    ].
+    errorNumber notNil ifTrue:[
+        (OperatingSystem errorHolderForNumber:errorNumber) reportError.
+    ].
+    ^ nil
+
+    "
+     |top sub|
+
+     top := self key:'HKEY_LOCAL_MACHINE'.
+     sub := top subKeyNamed:'Software' flags:nil createIfAbsent:false
+
+     |top sub|
+
+     top := self key:'HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit'.
+     top valueNamed:'CurrentVersion'.
+     sub := top subKeyNamed:'1.8' flags:#KEY_WOW64_64KEY createIfAbsent:false.
+    "
 ! !
 
 !Win32OperatingSystem::RegistryEntry methodsFor:'accessing values'!
@@ -14783,18 +15501,18 @@
 
     if (__isExternalAddressLike(__INST(handle))
      && __isStringLike(aValueName)) {
-	myKey = (HKEY)__externalAddressVal(__INST(handle));
-	if ((_retVal = RegDeleteValueA(myKey, __stringVal(aValueName))) == ERROR_SUCCESS) {
-	    RETURN (true);
-	}
-	if ((_retVal != ERROR_PATH_NOT_FOUND)
-	 && (_retVal != ERROR_FILE_NOT_FOUND)) {
-	    errorNumber = __MKSMALLINT(_retVal);
-	}
+        myKey = (HKEY)__externalAddressVal(__INST(handle));
+        if ((_retVal = RegDeleteValueA(myKey, __stringVal(aValueName))) == ERROR_SUCCESS) {
+            RETURN (true);
+        }
+        if ((_retVal != ERROR_PATH_NOT_FOUND)
+         && (_retVal != ERROR_FILE_NOT_FOUND)) {
+            errorNumber = __MKSMALLINT(_retVal);
+        }
     }
 %}.
     errorNumber notNil ifTrue:[
-	(OperatingSystem errorHolderForNumber:errorNumber) reportError.
+        (OperatingSystem errorHolderForNumber:errorNumber) reportError.
     ].
     ^ false
 !
@@ -14814,25 +15532,25 @@
 
     if (__isExternalAddressLike(__INST(handle))
      && __isSmallInteger(valueIndex)) {
-	myKey = (HKEY)__externalAddressVal(__INST(handle));
-	if ((_retVal = RegEnumValueA(myKey, __intVal(valueIndex),
-			 nameBuffer, &nameSize,
-			 NULL,
-			 &valueType,
-			 NULL, NULL)) == ERROR_SUCCESS) {
-	    nameBuffer[nameSize] = '\0';
-	    valueName = __MKSTRING(nameBuffer);
-	} else {
-	    if ((_retVal != ERROR_PATH_NOT_FOUND)
-	     && (_retVal != ERROR_FILE_NOT_FOUND)
-	     && (_retVal != ERROR_NO_MORE_ITEMS)) {
-		errorNumber = __MKSMALLINT(_retVal);
-	    }
-	}
+        myKey = (HKEY)__externalAddressVal(__INST(handle));
+        if ((_retVal = RegEnumValueA(myKey, __intVal(valueIndex),
+                         nameBuffer, &nameSize,
+                         NULL,
+                         &valueType,
+                         NULL, NULL)) == ERROR_SUCCESS) {
+            nameBuffer[nameSize] = '\0';
+            valueName = __MKSTRING(nameBuffer);
+        } else {
+            if ((_retVal != ERROR_PATH_NOT_FOUND)
+             && (_retVal != ERROR_FILE_NOT_FOUND)
+             && (_retVal != ERROR_NO_MORE_ITEMS)) {
+                errorNumber = __MKSMALLINT(_retVal);
+            }
+        }
     }
 %}.
     errorNumber notNil ifTrue:[
-	(OperatingSystem errorHolderForNumber:errorNumber) reportError.
+        (OperatingSystem errorHolderForNumber:errorNumber) reportError.
     ].
     ^ valueName
 
@@ -14846,11 +15564,11 @@
 
 valueNamed:aValueName
     "retrieve a value; the returned object depends upon the type:
-	REG_BINARY      -> ByteArray
-	REG_SZ          -> String
-	REG_MULTI_SZ    -> Array of strings
-	REG_DWORD       -> Integer
-	REG_NONE        -> nil
+        REG_BINARY      -> ByteArray
+        REG_SZ          -> String
+        REG_MULTI_SZ    -> Array of strings
+        REG_DWORD       -> Integer
+        REG_NONE        -> nil
     "
 
     |stringArray retVal errorNumber|
@@ -14859,9 +15577,9 @@
     HKEY myKey;
     DWORD valueType;
     union {
-	DWORD dWord;
-	unsigned char dWordBytes[4];
-	unsigned char smallDataBuffer[1024*128];
+        DWORD dWord;
+        unsigned char dWordBytes[4];
+        unsigned char smallDataBuffer[1024*128];
     } quickData;
     int val;
     DWORD dataSize = sizeof(quickData);
@@ -14877,166 +15595,166 @@
 
     if (__isExternalAddressLike(__INST(handle))
      && __isStringLike(aValueName)) {
-	int ret;
-
-	myKey = (HKEY)__externalAddressVal(__INST(handle));
-
-	/*
-	 * try to get it with one call ...
-	 */
-	ret = RegQueryValueEx(myKey, __stringVal(aValueName),
-			 NULL,
-			 &valueType,
-			 (char *)&quickData,
-			 &dataSize);
+        int ret;
+
+        myKey = (HKEY)__externalAddressVal(__INST(handle));
+
+        /*
+         * try to get it with one call ...
+         */
+        ret = RegQueryValueEx(myKey, __stringVal(aValueName),
+                         NULL,
+                         &valueType,
+                         (char *)&quickData,
+                         &dataSize);
 #if 0
-	console_printf("dataSize=%d\n", dataSize);
-#endif
-	while (ret == ERROR_MORE_DATA) {
+        console_printf("dataSize=%d\n", dataSize);
+#endif
+        while (ret == ERROR_MORE_DATA) {
 #if 0
-	    console_printf("ERROR_MORE_DATA dataSize=%d\n", dataSize);
-	    console_printf("valueType=%d\n", valueType);
-#endif
-	    /*
-	     * nope - need another one ...
-	     */
-	    if (myKey = HKEY_PERFORMANCE_DATA) {
-		dataSize = dataSize * 2;
-	    }
-	    switch (valueType) {
-		case REG_BINARY:
-		case REG_MULTI_SZ:
-		    dataBuffer = malloc(dataSize);;
-		    break;
-		case REG_SZ:
-		    dataBuffer = malloc(dataSize);
-		    break;
-		default:
-		    console_printf("RegistryEntry [warning]: unhandled valueType: %d\n", valueType);
-		    break;
-	    }
-	    if (dataBuffer) {
-		ret = RegQueryValueEx(myKey, __stringVal(aValueName),
-				 NULL,
-				 &valueType,
-				 dataBuffer,
-				 &dataSize);
-	    } else {
-		break;
-	    }
-	    if (myKey != HKEY_PERFORMANCE_DATA) {
-		if (ret != ERROR_SUCCESS) break;
-	    }
-	}
-
-	if (ret == ERROR_SUCCESS) {
+            console_printf("ERROR_MORE_DATA dataSize=%d\n", dataSize);
+            console_printf("valueType=%d\n", valueType);
+#endif
+            /*
+             * nope - need another one ...
+             */
+            if (myKey = HKEY_PERFORMANCE_DATA) {
+                dataSize = dataSize * 2;
+            }
+            switch (valueType) {
+                case REG_BINARY:
+                case REG_MULTI_SZ:
+                    dataBuffer = malloc(dataSize);;
+                    break;
+                case REG_SZ:
+                    dataBuffer = malloc(dataSize);
+                    break;
+                default:
+                    console_printf("RegistryEntry [warning]: unhandled valueType: %d\n", valueType);
+                    break;
+            }
+            if (dataBuffer) {
+                ret = RegQueryValueEx(myKey, __stringVal(aValueName),
+                                 NULL,
+                                 &valueType,
+                                 dataBuffer,
+                                 &dataSize);
+            } else {
+                break;
+            }
+            if (myKey != HKEY_PERFORMANCE_DATA) {
+                if (ret != ERROR_SUCCESS) break;
+            }
+        }
+
+        if (ret == ERROR_SUCCESS) {
 #if 0
-	    console_printf("ERROR_SUCCESS dataSize=%d\n", dataSize);
-	    console_printf("valueType=%d\n", valueType);
-#endif
-	    switch (valueType) {
-		case REG_NONE:
-		    /* RETURN (@symbol(none));  */
-		    retVal = nil;
-		    break;
-
-		case REG_BINARY:
-		    retVal = __MKBYTEARRAY(dataBuffer ? dataBuffer : quickData.smallDataBuffer, dataSize);
-		    break;
-
-		case REG_SZ:
-		case REG_EXPAND_SZ:
+            console_printf("ERROR_SUCCESS dataSize=%d\n", dataSize);
+            console_printf("valueType=%d\n", valueType);
+#endif
+            switch (valueType) {
+                case REG_NONE:
+                    /* RETURN (@symbol(none));  */
+                    retVal = nil;
+                    break;
+
+                case REG_BINARY:
+                    retVal = __MKBYTEARRAY(dataBuffer ? dataBuffer : quickData.smallDataBuffer, dataSize);
+                    break;
+
+                case REG_SZ:
+                case REG_EXPAND_SZ:
 #ifdef USE_UNICODE
-		    retVal = __MKU16STRING(dataBuffer ? dataBuffer : quickData.smallDataBuffer);
-#else
-		    retVal = __MKSTRING(dataBuffer ? dataBuffer : quickData.smallDataBuffer);
-#endif
-		    break;
+                    retVal = __MKU16STRING(dataBuffer ? dataBuffer : quickData.smallDataBuffer);
+#else
+                    retVal = __MKSTRING(dataBuffer ? dataBuffer : quickData.smallDataBuffer);
+#endif
+                    break;
 
 #if 0
-		case REG_DWORD:
-		    /* int in native format */
-		    retVal = __MKUINT(quickData.dWord);
-		    break;
-#endif
-		case REG_DWORD_LITTLE_ENDIAN:
-		    val = quickData.dWordBytes[3];
-		    val = (val << 8) | quickData.dWordBytes[2];
-		    val = (val << 8) | quickData.dWordBytes[1];
-		    val = (val << 8) | quickData.dWordBytes[0];
-		    retVal = __MKUINT(val);
-		    break;
-
-		case REG_DWORD_BIG_ENDIAN:
-		    val = quickData.dWordBytes[0];
-		    val = (val << 8) | quickData.dWordBytes[1];
-		    val = (val << 8) | quickData.dWordBytes[2];
-		    val = (val << 8) | quickData.dWordBytes[3];
-		    retVal = __MKUINT(val);
-		    break;
-
-		case REG_MULTI_SZ:
-		    {
-			CHAR *cp, *cp0;
-			int ns, i;
-
-			cp0 = dataBuffer ? dataBuffer : quickData.smallDataBuffer;
+                case REG_DWORD:
+                    /* int in native format */
+                    retVal = __MKUINT(quickData.dWord);
+                    break;
+#endif
+                case REG_DWORD_LITTLE_ENDIAN:
+                    val = quickData.dWordBytes[3];
+                    val = (val << 8) | quickData.dWordBytes[2];
+                    val = (val << 8) | quickData.dWordBytes[1];
+                    val = (val << 8) | quickData.dWordBytes[0];
+                    retVal = __MKUINT(val);
+                    break;
+
+                case REG_DWORD_BIG_ENDIAN:
+                    val = quickData.dWordBytes[0];
+                    val = (val << 8) | quickData.dWordBytes[1];
+                    val = (val << 8) | quickData.dWordBytes[2];
+                    val = (val << 8) | quickData.dWordBytes[3];
+                    retVal = __MKUINT(val);
+                    break;
+
+                case REG_MULTI_SZ:
+                    {
+                        CHAR *cp, *cp0;
+                        int ns, i;
+
+                        cp0 = dataBuffer ? dataBuffer : quickData.smallDataBuffer;
 #if 0
-			console_printf("**************\n");
-			for (i=0;i<50;i++) {
-			  console_printf("%x ", cp0[i]);
-			}
-			console_printf("\n");
-			for (i=0;i<50;i++) {
-			  if (cp0[i] == 0)
-			    console_printf("\n");
-			  else
-			    console_printf("%c", cp0[i]);
-			}
-			console_printf("\n");
-			console_printf("**************\n");
-#endif
-			cp = cp0;
-			ns = 0;
-			while (*cp) {
-			    while (*cp++) ;;
-			    ns++;
-			}
-			stringArray = __ARRAY_NEW_INT(ns);
-
-			i = 0;
-			while (*cp0) {
-			    OBJ s;
-			    CHAR *cp;
-
-			    cp = cp0;
-			    while (*cp++) ;;
+                        console_printf("**************\n");
+                        for (i=0;i<50;i++) {
+                          console_printf("%x ", cp0[i]);
+                        }
+                        console_printf("\n");
+                        for (i=0;i<50;i++) {
+                          if (cp0[i] == 0)
+                            console_printf("\n");
+                          else
+                            console_printf("%c", cp0[i]);
+                        }
+                        console_printf("\n");
+                        console_printf("**************\n");
+#endif
+                        cp = cp0;
+                        ns = 0;
+                        while (*cp) {
+                            while (*cp++) ;;
+                            ns++;
+                        }
+                        stringArray = __ARRAY_NEW_INT(ns);
+
+                        i = 0;
+                        while (*cp0) {
+                            OBJ s;
+                            CHAR *cp;
+
+                            cp = cp0;
+                            while (*cp++) ;;
 #ifdef USE_UNICODE
-			    s = __MKU16STRING(cp0); __ArrayInstPtr(stringArray)->a_element[i] = s; __STORE(stringArray, s);
-#else
-			    s = __MKSTRING(cp0); __ArrayInstPtr(stringArray)->a_element[i] = s; __STORE(stringArray, s);
-#endif
-			    cp0 = cp;
-			    i++;
-			}
-			retVal = stringArray;
-			break;
-		    }
-		default:
-		    console_printf("RegistryEntry [warning]: unhandled valueType: %d\n", valueType);
-		    break;
-	    }
-	} else {
-	    if ((ret != ERROR_PATH_NOT_FOUND)
-	     && (ret != ERROR_FILE_NOT_FOUND)) {
-		errorNumber = __MKSMALLINT(ret);
-	    }
-	}
+                            s = __MKU16STRING(cp0); __ArrayInstPtr(stringArray)->a_element[i] = s; __STORE(stringArray, s);
+#else
+                            s = __MKSTRING(cp0); __ArrayInstPtr(stringArray)->a_element[i] = s; __STORE(stringArray, s);
+#endif
+                            cp0 = cp;
+                            i++;
+                        }
+                        retVal = stringArray;
+                        break;
+                    }
+                default:
+                    console_printf("RegistryEntry [warning]: unhandled valueType: %d\n", valueType);
+                    break;
+            }
+        } else {
+            if ((ret != ERROR_PATH_NOT_FOUND)
+             && (ret != ERROR_FILE_NOT_FOUND)) {
+                errorNumber = __MKSMALLINT(ret);
+            }
+        }
     }
     if (dataBuffer) free(dataBuffer);
 %}.
     errorNumber notNil ifTrue:[
-	(OperatingSystem errorHolderForNumber:errorNumber) reportError.
+        (OperatingSystem errorHolderForNumber:errorNumber) reportError.
     ].
 
     ^ retVal
@@ -15051,11 +15769,11 @@
 
 valueNamed:aValueName put:datum
     "store a value; the value type depends upon the stored value:
-	ByteArray       -> REG_BINARY
-	String          -> REG_SZ
-	Array of string -> REG_MULTI_SZ
-	Integer         -> REG_DWORD
-	nil             -> REG_NONE
+        ByteArray       -> REG_BINARY
+        String          -> REG_SZ
+        Array of string -> REG_MULTI_SZ
+        Integer         -> REG_DWORD
+        nil             -> REG_NONE
     "
 
     |data stringArray errorNumber|
@@ -15069,99 +15787,99 @@
 
     if (__isExternalAddressLike(__INST(handle))
      && __isStringLike(aValueName)) {
-	int ret;
-	OBJ cls;
-
-	myKey = (HKEY)__externalAddressVal(__INST(handle));
-
-	if (datum == nil) {
-	    valueType = REG_NONE;
-	    dataSize = 0;
-	} else if (__isSmallInteger(datum)) {
-	    valueType = REG_DWORD;
-	    val = __intVal(datum);
-	    dataPointer = (unsigned char *)(&val);
-	    dataSize = sizeof(val);
-	} else if (__isStringLike(datum)) {
-	    valueType = REG_SZ;
-	    dataPointer = __stringVal(datum);
-	    dataSize = __stringSize(datum) + 1;
-	} else if (__Class(datum) == ByteArray) {
-	    valueType = REG_BINARY;
-	    dataPointer = __ByteArrayInstPtr(datum)->ba_element;
-	    dataSize = __byteArraySize(datum);
-	} else if (__Class(datum) == LargeInteger) {
-	    valueType = REG_DWORD;
-	    val = __longIntVal(datum);
-	    if (val) {
-		dataPointer = (unsigned char *)(&val);
-		dataSize = sizeof(val);
-	    } else {
-		datumOk = 0;
-	    }
-	} else if (__Class(datum) == Array) {
-	    int i = 0, ns = 0, totalSize = 0;
-
-	    valueType = REG_MULTI_SZ;
-
-	    /*
-	     * must allocate a local buffer
-	     * find size ...
-	     */
-	    for (i=0; i<__arraySize(datum); i++) {
-		OBJ s = __ArrayInstPtr(datum)->a_element[i];
-
-		if (__isStringLike(s)) {
-		    totalSize += __stringSize(s) + 1;
-		} else {
-		    datumOk = 0;
-		    break;
-		}
-		ns++;
-	    }
-	    if (datumOk) {
-		char *cp;
-
-		/*
-		 * allocate and fill...
-		 */
-		totalSize ++;
-		dataPointer = (char *)(malloc(totalSize));
-		mustFreeData = 1;
-		cp = dataPointer;
-		for (i=0; i<__arraySize(datum); i++) {
-		    OBJ s = __ArrayInstPtr(datum)->a_element[i];
-
-		    strcpy(cp, __stringVal(s));
-		    cp += __stringSize(s);
-		    *cp++ = '\0';
-		}
-		*cp++ = '\0';
-		dataSize = totalSize;
-	    }
-	} else {
-	    datumOk = 0;
-	}
-
-	if (datumOk) {
-	    ret = RegSetValueExA(myKey, __stringVal(aValueName),
-				0, valueType,
-				dataPointer, dataSize);
-	    if (mustFreeData) {
-		free(dataPointer);
-	    }
-	    if (ret == ERROR_SUCCESS) {
-		RETURN (true);
-	    }
-	    if ((ret != ERROR_PATH_NOT_FOUND)
-	     && (ret != ERROR_FILE_NOT_FOUND)) {
-		errorNumber = __MKSMALLINT(ret);
-	    }
-	}
+        int ret;
+        OBJ cls;
+
+        myKey = (HKEY)__externalAddressVal(__INST(handle));
+
+        if (datum == nil) {
+            valueType = REG_NONE;
+            dataSize = 0;
+        } else if (__isSmallInteger(datum)) {
+            valueType = REG_DWORD;
+            val = __intVal(datum);
+            dataPointer = (unsigned char *)(&val);
+            dataSize = sizeof(val);
+        } else if (__isStringLike(datum)) {
+            valueType = REG_SZ;
+            dataPointer = __stringVal(datum);
+            dataSize = __stringSize(datum) + 1;
+        } else if (__Class(datum) == ByteArray) {
+            valueType = REG_BINARY;
+            dataPointer = __ByteArrayInstPtr(datum)->ba_element;
+            dataSize = __byteArraySize(datum);
+        } else if (__Class(datum) == LargeInteger) {
+            valueType = REG_DWORD;
+            val = __longIntVal(datum);
+            if (val) {
+                dataPointer = (unsigned char *)(&val);
+                dataSize = sizeof(val);
+            } else {
+                datumOk = 0;
+            }
+        } else if (__Class(datum) == Array) {
+            int i = 0, ns = 0, totalSize = 0;
+
+            valueType = REG_MULTI_SZ;
+
+            /*
+             * must allocate a local buffer
+             * find size ...
+             */
+            for (i=0; i<__arraySize(datum); i++) {
+                OBJ s = __ArrayInstPtr(datum)->a_element[i];
+
+                if (__isStringLike(s)) {
+                    totalSize += __stringSize(s) + 1;
+                } else {
+                    datumOk = 0;
+                    break;
+                }
+                ns++;
+            }
+            if (datumOk) {
+                char *cp;
+
+                /*
+                 * allocate and fill...
+                 */
+                totalSize ++;
+                dataPointer = (char *)(malloc(totalSize));
+                mustFreeData = 1;
+                cp = dataPointer;
+                for (i=0; i<__arraySize(datum); i++) {
+                    OBJ s = __ArrayInstPtr(datum)->a_element[i];
+
+                    strcpy(cp, __stringVal(s));
+                    cp += __stringSize(s);
+                    *cp++ = '\0';
+                }
+                *cp++ = '\0';
+                dataSize = totalSize;
+            }
+        } else {
+            datumOk = 0;
+        }
+
+        if (datumOk) {
+            ret = RegSetValueExA(myKey, __stringVal(aValueName),
+                                0, valueType,
+                                dataPointer, dataSize);
+            if (mustFreeData) {
+                free(dataPointer);
+            }
+            if (ret == ERROR_SUCCESS) {
+                RETURN (true);
+            }
+            if ((ret != ERROR_PATH_NOT_FOUND)
+             && (ret != ERROR_FILE_NOT_FOUND)) {
+                errorNumber = __MKSMALLINT(ret);
+            }
+        }
     }
 %}.
     errorNumber notNil ifTrue:[
-	(OperatingSystem errorHolderForNumber:errorNumber) reportError.
+        (OperatingSystem errorHolderForNumber:errorNumber) reportError.
     ].
     ^ false
 
@@ -15307,9 +16025,9 @@
     HKEY myKey;
 
     if (__isExternalAddressLike(__INST(handle))) {
-	myKey = (HKEY)(__externalAddressVal(__INST(handle)));
-	__INST(handle) = nil;
-	RegCloseKey(myKey);
+        myKey = (HKEY)(__externalAddressVal(__INST(handle)));
+        __INST(handle) = nil;
+        RegCloseKey(myKey);
     }
 %}
 !
@@ -15348,6 +16066,14 @@
     "Created: / 19.5.1999 / 22:27:05 / cg"
 !
 
+setHandle:aHandle path:aPathString isNew:disposition
+    handle := aHandle.
+    path := aPathString.
+    isNew := disposition.
+
+    "Created: / 19.5.1999 / 22:27:05 / cg"
+!
+
 setupForHandleValue:integerHandleValue
     "not normally used - given an integer address,
      return a registry entry. This is provided to
@@ -15359,7 +16085,7 @@
 
     key = (HKEY)__longIntVal(integerHandleValue);
     if (! key) {
-	RETURN (nil);
+        RETURN (nil);
     }
 
     t = __MKEXTERNALADDRESS(key); __INST(handle) = t; __STORE(self, t);
@@ -15413,14 +16139,6 @@
 "
 ! !
 
-!Win32OperatingSystem::Win32IOHandle methodsFor:'finalization'!
-
-finalize
-    "a handle was garbage collected - close the underlying file"
-
-    self closeFile
-! !
-
 !Win32OperatingSystem::Win32IOHandle methodsFor:'io'!
 
 readBytes:count into:aByteBuffer startingAt:firstIndex
@@ -15790,21 +16508,8 @@
 close
     "close the file"
 
-    self closeFile.
+    self closeHandle.
     self unregisterForFinalization.
-!
-
-closeFile
-    "close the handle"
-
-%{
-    HANDLE h = (HANDLE)(__externalAddressVal(self));
-
-    if (h) {
-	__externalAddressVal(self) = (HANDLE)0;
-	CloseHandle(h);
-    }
-%}.
 ! !
 
 !Win32OperatingSystem::Win32NetworkResourceHandle class methodsFor:'accessing - types'!
@@ -16441,6 +17146,16 @@
     ^ pid
 ! !
 
+!Win32OperatingSystem::Win32ProcessHandle methodsFor:'comparing'!
+
+= aWin32ProcessHandle
+    ^ aWin32ProcessHandle class == self class and:[pid = aWin32ProcessHandle pid]
+!
+
+hash
+    ^ pid hash
+! !
+
 !Win32OperatingSystem::Win32ProcessHandle methodsFor:'printing & storing'!
 
 printOn:aStream
@@ -16669,7 +17384,7 @@
 
 !Win32OperatingSystem::Win32SerialPortHandle methodsFor:'release'!
 
-closeFile
+closeHandle
     "close the handle"
 
 %{
@@ -16836,25 +17551,52 @@
     "
 ! !
 
+!Win32OperatingSystem::Win32SocketHandle class methodsFor:'instance creation'!
+
+new
+    "return an initialized instance"
+
+    ^ self basicNew initialize.
+! !
+
 !Win32OperatingSystem::Win32SocketHandle class methodsFor:'queries'!
 
-getAddressInfo:hostName serviceName:serviceNameArg domain:domainArg type:typeArg protocol:protoArg flags:flags
-    "answer an Array of socket addresses for serviceName on hostName
+getAddressInfo:hostNameOrNil serviceName:serviceNameOrNil domain:domainArg type:typeArg protocol:protoArg flags:flags
+    "answer an Array of socket addresses for serviceName on hostName.
      Domain, type, protocol may be nil or specify a hint for the socket
      addresses to be returned."
 
-    |error errorString result domain type proto serviceName port|
+    |error errorString result domain type proto hostName serviceName port|
 
     domain := OperatingSystem domainCodeOf:domainArg.
     type := OperatingSystem socketTypeCodeOf:typeArg.
     proto := self protocolCodeOf:protoArg.
-    serviceNameArg notNil ifTrue:[
-	serviceName := serviceNameArg printString.      "convert integer port numbers"
-	serviceNameArg isInteger ifTrue:[
-	    port := serviceNameArg.
+    serviceNameOrNil notNil ifTrue:[
+	serviceName := serviceNameOrNil printString.      "convert integer port numbers"
+	serviceNameOrNil isInteger ifTrue:[
+	    port := serviceNameOrNil.
 	].
     ]. "ifFalse:[serviceName := nil]"
 
+
+%{
+#if 1 || !defined(AI_NUMERICHOST)
+%}.
+
+    "have to convert serviceName and hostName to single byte strings
+     until we implement getAddrInfoW() for Borland C.
+     If we really have 16-bit hostnames, this fails with #primitiveFailed"
+    hostNameOrNil notNil ifTrue:[
+	hostName := hostNameOrNil asSingleByteStringIfPossible.
+    ].  "ifFalse:[hostName := nil] is nil anyway"
+    serviceName notNil ifTrue:[
+	serviceName := serviceName asSingleByteStringIfPossible.
+    ].
+%{
+#endif // !AI_NUMERICHOST
+%}.
+
+
 %{ /* STACK:32000 */
 #if !defined(NO_SOCKET)
     char *__hostName, *__serviceName;
@@ -16867,6 +17609,10 @@
     } else if (__isStringLike(hostName)) {
 	strncpy(__hostNameCopy, __stringVal(hostName), sizeof(__hostNameCopy)-1);
 	__hostName = __hostNameCopy;
+    } else if (__isUnicode16String(hostName)) {
+	error = @symbol(unsupportedUnicodeName);
+	errorString = __MKSTRING("Unicode hostnames are not yet supported");
+	goto exitPrim;
     } else {
 	error = @symbol(badArgument1);
 	goto exitPrim;
@@ -17149,9 +17895,6 @@
 %}.
     error notNil ifTrue:[
 	|request|
-	error isSymbol ifTrue:[
-	    self primitiveFailed:error.
-	].
 	request := SocketAddressInfo new
 	    domain:domainArg;
 	    type:typeArg;
@@ -17201,18 +17944,40 @@
 	    domain:#AF_INET type:nil protocol:nil flags:nil
      self getAddressInfo:'www.google.de' serviceName:nil
 	    domain:nil type:nil protocol:nil flags:nil
-     self getAddressInfo:'smc1' serviceName:nil
+     self getAddressInfo:'exeptn' serviceName:nil
+	    domain:nil type:nil protocol:nil flags:nil
+
+     self getAddressInfo:'localhost' asUnicode16String serviceName:nil
+	    domain:nil type:nil protocol:nil flags:nil
+     self getAddressInfo:'ützlbrützl' serviceName:nil
 	    domain:nil type:nil protocol:nil flags:nil
-    "
-!
-
-getNameInfo:socketAddress wantHostName:wantHostName wantServiceName:wantServiceName datagram:useDatagram flags:flags
+     self getAddressInfo:'ützlbrützl' serviceName:nil
+	    domain:nil type:nil protocol:nil flags:nil
+     self getAddressInfo:'путин.ру' asUnicode16String serviceName:nil
+	    domain:nil type:nil protocol:nil flags:nil
+    "
+!
+
+getNameInfo:socketAddressIn wantHostName:wantHostName wantServiceName:wantServiceName datagram:useDatagram flags:flags
     "answer an Array containing the hostName and serviceName
      in socketAddress.
      This is the generic version of getHostByAddr, however, if supported by the OS,
      this returns multiple hostnames (if appropriate)"
 
-    |error errorString hostName serviceName|
+    |socketAddress error errorString hostName serviceName|
+
+    socketAddress := socketAddressIn.
+
+%{   /* STACK:32000 */
+#if !defined(NI_NUMERICHOST)
+%}.
+    "if the getNameInfo() syscall is not present (as in Borland),
+     convert mapped IPv4 to IPv6Addresses back to IPv4,
+     so that these addresses can be resolved"
+    socketAddress := socketAddress asIPv4SocketAddressIfPossible.
+%{
+#endif // !defined(NI_NUMERICHOST)
+%}.
 
 %{  /* STACK:32000 */
 
@@ -17342,6 +18107,14 @@
 		sp = servp->s_name;
 	    }
 	}
+
+	if (sa->sin_family == AF_INET6) {
+	    if (sp)
+		serviceName = __MKSTRING(sp);
+	    error = @symbol(AF_INET6);
+	    goto err;
+	}
+
 	if (hp) {
 	    struct hostent *hostp;
 	    int err;
@@ -17396,6 +18169,13 @@
 #endif
 %}.
     error notNil ifTrue:[
+	(error == #AF_INET6 or:[errorString == #noAddress]) ifTrue:[
+	    "This is a socket address of wrong size - probably an IPv6SocketAddres on a system where
+	     the getNetByAddr() syscall is not supported"
+	    ^ Array
+		with:socketAddress hostAddressString
+		with:serviceName.
+	].
 	error isSymbol ifTrue:[
 	    self primitiveFailed:error.
 	].
@@ -17420,7 +18200,62 @@
 
      self getNameInfo:(IPSocketAddress hostAddress:#[1 2 3 4])
 	 wantHostName:true wantServiceName:true datagram:false flags:0
-    "
+
+     self getNameInfo:(IPv6SocketAddress localHost port:21)
+	 wantHostName:true wantServiceName:true datagram:false flags:0
+    "
+! !
+
+!Win32OperatingSystem::Win32SocketHandle methodsFor:'initialization'!
+
+initialize
+%{ /* NOCONTEXT */
+    (SOCKET)(__externalAddressVal(self)) = INVALID_SOCKET;
+%}
+
+    "
+      self new
+      self new isValid
+    "
+! !
+
+!Win32OperatingSystem::Win32SocketHandle methodsFor:'queries'!
+
+handleType
+    ^ #socketHandle
+!
+
+isValid
+%{  /* NOCONTEXT */
+    SOCKET sock = (SOCKET)(__externalAddressVal(self));
+
+    RETURN(sock == INVALID_SOCKET ? false : true);
+%}.
+
+    "
+      self new isValid
+    "
+! !
+
+!Win32OperatingSystem::Win32SocketHandle methodsFor:'release'!
+
+closeHandle
+    "close the handle"
+
+%{ /* NOCONTEXT */
+    SOCKET sock = (SOCKET)(__externalAddressVal(self));
+
+    if (sock != INVALID_SOCKET) {
+	__externalAddressVal(self) = INVALID_SOCKET;
+	closesocket(sock);
+    }
+%}.
+! !
+
+!Win32OperatingSystem::Win32SocketHandle methodsFor:'testing'!
+
+isSocketHandle
+    ^ true
 ! !
 
 !Win32OperatingSystem::WinPointStructure class methodsFor:'instance creation'!
@@ -17488,19 +18323,20 @@
 !Win32OperatingSystem class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.489 2014-01-29 16:08:17 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.526 2015-03-20 11:28:32 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.489 2014-01-29 16:08:17 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.526 2015-03-20 11:28:32 stefan Exp $'
 !
 
 version_SVN
-    ^ '$Id: Win32OperatingSystem.st,v 1.489 2014-01-29 16:08:17 stefan Exp $'
+    ^ '$Id: Win32OperatingSystem.st,v 1.526 2015-03-20 11:28:32 stefan Exp $'
 
 ! !
 
 
 Win32OperatingSystem initialize!
+Win32OperatingSystem::PECOFFConstants initialize!
 Win32OperatingSystem::PerformanceData initialize!
 Win32OperatingSystem::RegistryEntry initialize!