#FEATURE by cg
authorClaus Gittinger <cg@exept.de>
Mon, 23 Mar 2020 16:11:42 +0100
changeset 25339 3fb3b8bd0b19
parent 25338 7ebc001a5a1b
child 25340 9230ffff3935
#FEATURE by cg class: Win32OperatingSystem class changed: #characterEncoderForConsoleOutput
Win32OperatingSystem.st
--- a/Win32OperatingSystem.st	Fri Mar 20 13:00:25 2020 +0100
+++ b/Win32OperatingSystem.st	Mon Mar 23 16:11:42 2020 +0100
@@ -1733,7 +1733,7 @@
         "/ should handle more codePages via GetConsoleOutputCP
         outputEncoder := CharacterEncoder encoderNamed:('cp%1' bindWith:cp).
         outputEncoder isNullEncoder ifTrue:[
-            ('no encoder for CP%1' bindWith:cp) _errorPrintCR.
+            "/ ('no encoder for cp%1' bindWith:cp) _errorPrintCR.
             "/ should we fallback here???
         ] ifFalse:[
             ConsoleOutputEncoder := outputEncoder
@@ -5158,8 +5158,10 @@
 
 %{
     HANDLE h;
+    char _pathNameBuffer[MAXPATHLEN+1];
+    wchar_t _wPathNameBuffer[MAXPATHLEN+1];
     char *name;
-    wchar_t _wPathName[MAXPATHLEN+1];
+    wchar_t wName;
     OBJ *ap;
     int numAttrib;
     int i, l;
@@ -5167,8 +5169,13 @@
 
     if (__isStringLike(pathName)) {
 	name = __stringVal(pathName);
+	if (strlen(name) < MAXPATHLEN) {
+	    strncpy(_pathNameBuffer, name, sizeof(_pathNameBuffer));
+	    name = _pathNameBuffer;
+	} // else: CreateA will use object's string (and execute uninterruptable)
     } else if (__isUnicode16String(pathName)) {
-	_makeWchar(pathName, _wPathName, sizeof(_wPathName));
+	_makeWchar(pathName, _wPathNameBuffer, sizeof(_wPathNameBuffer));
+	wName = _wPathNameBuffer;
     } else {
 	fileHandle = nil;
 	argumentError = @symbol(badPathName);
@@ -5242,7 +5249,7 @@
     if (__isStringLike(pathName)) {
 	h = CreateFileA(name, access, share, 0 /* sa */, create, attr, 0 /* hTempl */);
     } else {
-	h = CreateFileW(_wPathName, access, share, 0 /* sa */, create, attr, 0 /* hTempl */);
+	h = CreateFileW(wName, access, share, 0 /* sa */, create, attr, 0 /* hTempl */);
     }
 
     if (h != INVALID_HANDLE_VALUE) {
@@ -5310,9 +5317,9 @@
     if (__isStringLike(fullPathName)) {
 #ifdef DO_WRAP_CALLS
 	{
-	    char _aPathName[MAXPATHLEN];
-
-	    strncpy(_aPathName, __stringVal(fullPathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
+	    char _aPathName[MAXPATHLEN+1];
+
+	    strncpy(_aPathName, __stringVal(fullPathName), MAXPATHLEN); _aPathName[MAXPATHLEN] = '\0';
 	    do {
 		// do not cast to INT - will loose sign bit then!
 		success = (int)STX_API_NOINT_CALL1( "RemoveDirectoryA", RemoveDirectoryA, _aPathName);
@@ -8968,25 +8975,25 @@
 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|
 
     DomainName notNil ifTrue:[
-        ^ DomainName
+	^ DomainName
     ].
 
     domainName := self primGetComputerName:2.
 
     domainName isEmptyOrNil ifTrue:[
-        domainName := self getEnvironment:'DOMAIN'.
-        domainName isNil ifTrue:[
-            domainName := self getEnvironment:'DOMAINNAME'.
-        ].
+	domainName := self getEnvironment:'DOMAIN'.
+	domainName isNil ifTrue:[
+	    domainName := self getEnvironment:'DOMAINNAME'.
+	].
     ].
 
     domainName isEmptyOrNil ifTrue:[
-        ^ 'unknown'.
+	^ 'unknown'.
     ].
     DomainName := domainName.     "cache only, if it is fixed"
 
@@ -10297,16 +10304,16 @@
 primGetComputerName:whatEnum
     "return the domain or hostname we are running on:
        typedef enum _COMPUTER_NAME_FORMAT {
-          ComputerNameNetBIOS,             // 0
-          ComputerNameDnsHostname,         // 1
-          ComputerNameDnsDomain,           // 2
-          ComputerNameDnsFullyQualified,   // 3
-          ComputerNamePhysicalNetBIOS,
-          ComputerNamePhysicalDnsHostname,
-          ComputerNamePhysicalDnsDomain,
-          ComputerNamePhysicalDnsFullyQualified,
-          ComputerNameMax                 // 7
-        } COMPUTER_NAME_FORMAT; "
+	  ComputerNameNetBIOS,             // 0
+	  ComputerNameDnsHostname,         // 1
+	  ComputerNameDnsDomain,           // 2
+	  ComputerNameDnsFullyQualified,   // 3
+	  ComputerNamePhysicalNetBIOS,
+	  ComputerNamePhysicalDnsHostname,
+	  ComputerNamePhysicalDnsDomain,
+	  ComputerNamePhysicalDnsFullyQualified,
+	  ComputerNameMax                 // 7
+	} COMPUTER_NAME_FORMAT; "
 
 %{  /* STACK: 2048 */
     // Note: GetComputerNameExA can fail in certain locales!
@@ -10315,21 +10322,21 @@
     DWORD buffSize = sizeof(bufferA);
 
     if (GetComputerNameA(bufferA, &buffSize) == TRUE) {
-        RETURN(__MKSTRING_L(bufferA, buffSize));
+	RETURN(__MKSTRING_L(bufferA, buffSize));
     }
 #else
     WCHAR buffer[512];
     DWORD buffSize = sizeof(buffer)/sizeof(buffer[0]);
 
     if (GetComputerNameExW((COMPUTER_NAME_FORMAT)__intVal(whatEnum), buffer, &buffSize) == TRUE) {
-        RETURN(__mkStringOrU16String_maxlen(buffer, buffSize));
-    }
-#endif
-%}.
-
-    "
-     0 to: 7 collect:[:i|    
-        OperatingSystem primGetComputerName:i
+	RETURN(__mkStringOrU16String_maxlen(buffer, buffSize));
+    }
+#endif
+%}.
+
+    "
+     0 to: 7 collect:[:i|
+	OperatingSystem primGetComputerName:i
      ]
     "
 
@@ -11401,8 +11408,8 @@
 dateFormat
     "Answer the date format string to be used dep. on the OS system value for date format.
      One of DfMDY = Month-Day-Year
-            DfDMY = Day-Month-Year
-            DfYMD = Year-Month-Day
+	    DfDMY = Day-Month-Year
+	    DfYMD = Year-Month-Day
      is mapped to the ST/X dateFormatString %(mon)-%(day)-%(year)"
 
     |separatorString code|
@@ -11417,7 +11424,7 @@
     ^ '%(day)', separatorString, '%(mon)', separatorString, '%(year)'
 
     "
-     self dateFormat 
+     self dateFormat
      Date today printStringFormat:(self dateFormat)
     "
 
@@ -11428,8 +11435,8 @@
 dateFormatCode
     "Answer the current system value for date format.
      Answer DfMDY = Month-Day-Year = 0
-            DfDMY = Day-Month-Year = 1
-            DfYMD = Year-Month-Day = 2
+	    DfDMY = Day-Month-Year = 1
+	    DfYMD = Year-Month-Day = 2
     "
 
     "/ this is somewhat outdated, but windows maps the initProfile query to
@@ -11503,8 +11510,8 @@
 
 language
     "Answer the current system value for country name.
-     Notice that windows uses a different format (iso 639-2/b ???), 
-     where the first two chars correspond to the standard iso language, 
+     Notice that windows uses a different format (iso 639-2/b ???),
+     where the first two chars correspond to the standard iso language,
      and the 3 third char represents the territory (somehow).
      US-english which is 'en-us', is in windows ENU,
      GB-english which is 'en-gb', is in windows ENG,
@@ -11539,8 +11546,8 @@
 
     answer := self primGetProfileInt: 'Intl' keyName: aKeyName default:(-1 asUnsigned32).
     ^ answer = -1 asUnsigned32
-        ifTrue: [ defaultValue ]
-        ifFalse: [ answer ]
+	ifTrue: [ defaultValue ]
+	ifFalse: [ answer ]
 
     "
      self queryNationalProfileInt: 'iDate' default: 0
@@ -11557,12 +11564,12 @@
     | extString result |
 
     extString := String new: 80.
-    result := self 
-                primGetProfileString:'Intl' keyName:aKeyName default:''
-                returnedString:extString
-                size:(extString size).
+    result := self
+		primGetProfileString:'Intl' keyName:aKeyName default:''
+		returnedString:extString
+		size:(extString size).
     result > 0 ifTrue: [
-        ^ extString copyFrom: 1 to: result
+	^ extString copyFrom: 1 to: result
     ].
     ^ defaultValue
 
@@ -11701,16 +11708,16 @@
     "commands to try for speech output"
 
     ^ #(
-        "/ triples are:
-        "/      -command
-        "/      -commandline for default voice
-        "/      -commandline for specific voice
-        "/      -commandline for Speech Synthesis Markup Language (SSML) voice
-        ('powershell'
-         'powershell -Command "Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak(''%2'');"'
-         'powershell -Command "Add-Type -AssemblyName System.Speech; $S=(New-Object System.Speech.Synthesis.SpeechSynthesizer);$S.SelectVoice(''%1'');$S.Speak(''%2'');"'
-         'powershell -Command "Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).SpeakSsml(''%2'');"'
-        )
+	"/ triples are:
+	"/      -command
+	"/      -commandline for default voice
+	"/      -commandline for specific voice
+	"/      -commandline for Speech Synthesis Markup Language (SSML) voice
+	('powershell'
+	 'powershell -Command "Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak(''%2'');"'
+	 'powershell -Command "Add-Type -AssemblyName System.Speech; $S=(New-Object System.Speech.Synthesis.SpeechSynthesizer);$S.SelectVoice(''%1'');$S.Speak(''%2'');"'
+	 'powershell -Command "Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).SpeakSsml(''%2'');"'
+	)
     )
 
     "
@@ -11727,26 +11734,26 @@
 'powershell -Command "Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak(''hello'');"'
 
      OperatingSystem
-        executeCommand:
+	executeCommand:
 'powershell -Command "Add-Type -AssemblyName System.Speech;$S = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer;$S.voice;"'
-        outputTo:Transcript
+	outputTo:Transcript
 
      OperatingSystem
-        executeCommand:
+	executeCommand:
 'powershell -Command "Add-Type -AssemblyName System.Speech;$S = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer;$S.GetInstalledVoices();"'
-        outputTo:Transcript
+	outputTo:Transcript
 
      OperatingSystem
-        executeCommand:
+	executeCommand:
 'powershell -Command "Add-Type -AssemblyName System.Speech; foreach ($v in (New-Object System.Speech.Synthesis.SpeechSynthesizer).GetInstalledVoices() ){ Write-Host $v.VoiceInfo.Name }"'
-        outputTo:Transcript
+	outputTo:Transcript
 END"
 !
 
 voiceInfo
     "return a list of available (OS-specific) voice names plus info.
      For each available voice, a triple is returned, containing:
-        voiceName language_territory comment/description
+	voiceName language_territory comment/description
 
      the language_territory (of the form en_EN / en_US etc.) gives a hint,
      for which language the voice is best used.
@@ -11754,21 +11761,21 @@
      For now, this is experimental and will be enhanced to ask the OS..."
 
     ^ #(
-        ('default'                  'en_US' 'the default system voice')
-
-        #('Microsoft Zira Desktop'   'en_US' 'Isn''t it nice to have a computer that will talk to you?')
-        #('Microsoft Hazel Desktop'  'en_GB' 'Isn''t it nice to have a computer that will talk to you?')
-        #('Microsoft Hedda Desktop'  'de_DE' 'Danke, daß Sie mir zuhören')
-        #('Microsoft Helena Desktop' 'es_ES' 'holla mondo')
-        #('Microsoft Irina Desktop'  'ru_RU' 'привет мир')
-        #('Microsoft Elsa Desktop'     'it_IT' 'ciao mondo')
-        #('Microsoft Hortense Desktop' 'fr_FR' 'bonjour monde')
-        #('Microsoft Helia Desktop'  'pt_PT' 'olá mundo')
-        #('Microsoft Hanhan Desktop' 'zh_TW' '你好世界')
-        #('Microsoft Tracy Desktop'  'zh_HK' '你好世界')
-        #('Microsoft Huihui Desktop' 'zh_CN' '你好世界')
-        #('Microsoft Haruka Desktop' 'ja_JP' 'こんにちは世界')
-     )     
+	('default'                  'en_US' 'the default system voice')
+
+	#('Microsoft Zira Desktop'   'en_US' 'Isn''t it nice to have a computer that will talk to you?')
+	#('Microsoft Hazel Desktop'  'en_GB' 'Isn''t it nice to have a computer that will talk to you?')
+	#('Microsoft Hedda Desktop'  'de_DE' 'Danke, daß Sie mir zuhören')
+	#('Microsoft Helena Desktop' 'es_ES' 'holla mondo')
+	#('Microsoft Irina Desktop'  'ru_RU' 'привет мир')
+	#('Microsoft Elsa Desktop'     'it_IT' 'ciao mondo')
+	#('Microsoft Hortense Desktop' 'fr_FR' 'bonjour monde')
+	#('Microsoft Helia Desktop'  'pt_PT' 'olá mundo')
+	#('Microsoft Hanhan Desktop' 'zh_TW' '你好世界')
+	#('Microsoft Tracy Desktop'  'zh_HK' '你好世界')
+	#('Microsoft Huihui Desktop' 'zh_CN' '你好世界')
+	#('Microsoft Haruka Desktop' 'ja_JP' 'こんにちは世界')
+     )
 
 "<<END
      OperatingSystem voiceInfo
@@ -11785,18 +11792,18 @@
      OperatingSystem speak:'ciao mondo' voiceName:'Microsoft Elsa Desktop'
      OperatingSystem speak:'olá mundo' voiceName:'Microsoft Helia Desktop'
      OperatingSystem speak:'привет мир'  voiceName:'Microsoft Irina Desktop'
-     OperatingSystem speak:'こんにちは世界' voiceName:'Microsoft Haruka Desktop'   "Kon'nichiwa sekai" 
-     OperatingSystem speak:'你好世界' voiceName:'Microsoft Hanhan Desktop'      "Nǐ hǎo shìjiè"  
-     OperatingSystem speak:'你好世界' voiceName:'Microsoft Huihui Desktop'      "Nǐ hǎo shìjiè"  
-     OperatingSystem speak:'hello' voiceName:'Microsoft Huihui Desktop'      "Nǐ hǎo shìjiè"  
+     OperatingSystem speak:'こんにちは世界' voiceName:'Microsoft Haruka Desktop'   "Kon'nichiwa sekai"
+     OperatingSystem speak:'你好世界' voiceName:'Microsoft Hanhan Desktop'      "Nǐ hǎo shìjiè"
+     OperatingSystem speak:'你好世界' voiceName:'Microsoft Huihui Desktop'      "Nǐ hǎo shìjiè"
+     OperatingSystem speak:'hello' voiceName:'Microsoft Huihui Desktop'      "Nǐ hǎo shìjiè"
 
     Do do:
 
      OperatingSystem
-        executeCommand:
+	executeCommand:
 'powershell -Command "Add-Type -AssemblyName System.Speech; foreach ($v in (New-Object System.Speech.Synthesis.SpeechSynthesizer).GetInstalledVoices() ){ Write-Host $v.VoiceInfo.Name; Write-Host $v.VoiceInfo.Culture }"'
-        outputTo:Transcript
-END 
+	outputTo:Transcript
+END
 ! !
 
 !Win32OperatingSystem class methodsFor:'system management'!
@@ -20168,6 +20175,7 @@
 
     char host[NI_MAXHOST];
     char service[NI_MAXSERV];
+    char sockAddrLocal[1024];
     char *hp = NULL, *sp = NULL;
     int hsz = 0, ssz = 0;
     int ret;
@@ -20196,10 +20204,19 @@
     sockAddrSize = __byteArraySize(socketAddress);
     sockAddrSize -= nInstBytes;
 
+    if (sockAddrSize > sizeof(sockAddrLocal)) {
+	error = @symbol(badArgument1);
+	goto err;
+    }
+    bp = (char *)(__byteArrayVal(socketAddress));
+    bp += nInstBytes;
+    memcpy(sockAddrLocal, bp, sockAddrSize);
+
     if (!__isSmallInteger(flags)) {
 	error = @symbol(badArgument5);
 	goto err;
     }
+
     __flags = __intVal(flags);
 
 #if defined(NI_NUMERICHOST)
@@ -20214,12 +20231,11 @@
 	do {
 	    __threadErrno = 0;
 	    // do not cast to INT - will loose sign bit then!
-	    ret = (int)(STX_WSA_NOINT_CALL7( "getnameinfo", getnameinfo, (struct sockaddr *)bp, (INT)sockAddrSize, hp, (INT)hsz, sp, (INT)ssz, (INT)__flags));
+	    ret = (int)(STX_WSA_NOINT_CALL7( "getnameinfo", getnameinfo, (struct sockaddr *)sockAddrLocal, (INT)sockAddrSize, hp, (INT)hsz, sp, (INT)ssz, (INT)__flags));
 	} while ((ret < 0) && (__threadErrno == EINTR));
 # else
 	__BEGIN_INTERRUPTABLE__
-	ret = getnameinfo((struct sockaddr *)bp, sockAddrSize,
-			  hp, hsz, sp, ssz, __flags);
+	ret = getnameinfo((struct sockaddr *)sockAddrLocal, sockAddrSize, hp, hsz, sp, ssz, __flags);
 	__END_INTERRUPTABLE__
 # endif
     } while (ret != 0 && __threadErrno == EINTR);