--- 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!