WinWorkstation.st
branchjv
changeset 7743 fa3c8eb0bc1d
parent 7716 3dba89415c91
child 7994 42a7e4c6503d
--- a/WinWorkstation.st	Wed Dec 14 23:35:42 2016 +0000
+++ b/WinWorkstation.st	Thu Dec 15 20:11:12 2016 +0000
@@ -6674,9 +6674,22 @@
 
 displayName
     "return the display-connections display name.
-     For Windows, a dummy name is returned"
-
-    ^ 'local'
+     For Windows, a name of window station is returned"
+    | err |
+
+%{
+    if (__isExternalAddress(__INST(displayId))) {
+        HANDLE station = (HANDLE)__externalAddressVal(__INST(displayId));
+        char   stationName[256];
+        DWORD  stationNameLen = 0;        
+
+        stationName[255] = '\0';
+        if ( GetUserObjectInformation ( station, UOI_NAME, stationName, 255, &stationNameLen)) {
+            RETURN( __MKSTRING(stationName));
+        }
+    }
+%}.
+    self primitiveFailed: err
 !
 
 focusFollowsMouse:aBoolean
@@ -15314,16 +15327,68 @@
 %}
 !
 
-primInitializeFor:aDisplayName
-    "initialize the receiver for a connection to a display;
-     the argument, aDisplayName may be nil (for the default display)
-     or the name of the display server as hostname:number
-     (not yet under WIN32)"
-
-%{  /* NOCONTEXT */
-
-    RETURN ( __MKSMALLINT(1) );
-%}.
+primInitializeFor:stationNameOrNil
+    "Initialize the receiver for a connection to given window station. 
+     It the argument `stationNameOrNil` is nil, then it connects
+     to process default window station. 
+
+     Return an external address for window station handle or nil if
+     requested window station is not an interactive one (i.e, one
+     cannot initialize Win32Workstation on non-interactive window 
+     station).
+
+     See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687096(v=vs.85).aspx
+     "
+
+     | errcode |
+
+%{
+    HWINSTA station;
+    if (stationNameOrNil == nil) {
+        station = GetProcessWindowStation();
+        if (station == NULL) {
+            errcode = __MKINT( GetLastError() );
+            goto err;
+        }
+        /*
+         * Check we're connected to "WinSta0" station, only this
+         * one is interactive one.
+         */
+        char stationName[8];
+        int  stationNameLen;
+        if ( GetUserObjectInformation ( station, UOI_NAME, stationName, 9, &stationNameLen) ) {
+            if (strncmp(stationName, "WinSta0", 8) == 0) {
+                RETURN ( __MKEXTERNALADDRESS ( station ) );        
+            }         
+        }    
+        RETURN ( nil );
+
+    } else if (__isStringLike( stationNameOrNil)) {
+        if (strncmp(__stringVal(stationNameOrNil), "WinSta0", 8) == 0) {
+            /* 
+             * We're explicitly asked to connect to "WinSta0" station. 
+             * This could be hand for example when Smalltalk is running as
+             * a service on non-interactive session and want to open 
+             * a window to inform user. Maybe, maybe not. Anyway, do our best
+             * here.
+             */
+            station = OpenWindowStation("WinSta0", TRUE, NULL);
+            if (station == NULL) {
+                errcode = __MKINT( GetLastError() );
+                goto err;
+            }
+            if ( ! SetProcessWindowStation(station) ) {
+                errcode = __MKINT( GetLastError() );
+                goto err;            
+            }
+            RETURN ( __MKEXTERNALADDRESS ( station ) );        
+        }
+        RETURN ( nil );
+    }
+    err:;
+%}.
+    self primitiveFailed: errcode
+
 !
 
 reinitialize