Win32OperatingSystem.st
changeset 11253 ea6152cdf700
parent 11247 f4206a7664bb
child 11258 5117e5bd0dc3
--- a/Win32OperatingSystem.st	Tue Oct 21 13:05:50 2008 +0200
+++ b/Win32OperatingSystem.st	Tue Oct 21 13:47:41 2008 +0200
@@ -14,7 +14,7 @@
 
 AbstractOperatingSystem subclass:#Win32OperatingSystem
 	instanceVariableNames:''
-	classVariableNames:'HostName DomainName CurrentDirectory'
+	classVariableNames:'Initialized HostName DomainName CurrentDirectory'
 	poolDictionaries:''
 	category:'OS-Windows'
 !
@@ -187,7 +187,6 @@
 # define NO_GETADAPTERSINFO
 #endif
 
-
 #define USE_H_ERRNO
 
 # if defined(i386) || defined(__i386__)
@@ -569,6 +568,12 @@
 %}
 ! !
 
+!Win32OperatingSystem primitiveVariables!
+%{
+static int coInitialized = 0;
+%}
+! !
+
 !Win32OperatingSystem class methodsFor:'documentation'!
 
 copyright
@@ -694,6 +699,33 @@
 
 !Win32OperatingSystem class methodsFor:'initialization'!
 
+coInitialize
+%{
+    HRESULT hres;
+
+    if( ! coInitialized ) {
+#ifdef NO_NT4_0_COMPATIBILITY
+	FARPROC CoInitializeEx_entry = (FARPROC) CoInitializeEx;
+#else
+	FARPROC CoInitializeEx_entry = __get_ole32_functionAddress("CoInitializeEx");
+#endif /* NO_NT4_0_COMPATIBILITY */
+	hres = (*CoInitializeEx_entry)(NULL, COINIT_MULTITHREADED);
+	if (! SUCCEEDED(hres)) {
+	    console_fprintf(stderr, "OperatingSystem [info]: Could not open the COM library hres = %08x\n", hres );
+	    goto error;
+	}
+	coInitialized = 1;
+#ifdef COM_DEBUG
+	console_fprintf(stderr, "OperatingSystem [info]: COM initialized\n" );
+#endif
+    }
+    RETURN (self );
+
+error: ;
+%}.
+    self primitiveFailed
+!
+
 initOSType
     "internal - see if running under win-NT/XP/2k
      (as opposed to win-95/98/ME)"
@@ -716,12 +748,17 @@
 initialize
     "initialize the class"
 
-    ObjectMemory addDependent:self.
-    HostName := nil.
-    DomainName := nil.
-    LastErrorNumber := nil.
-    PipeFailed := false.
-    self initOSType
+    "/ attention: must be ok to be called twice during startup.
+    Initialized == nil ifTrue:[
+	Initialized := true.
+	ObjectMemory addDependent:self.
+	HostName := nil.
+	DomainName := nil.
+	LastErrorNumber := nil.
+	PipeFailed := false.
+	self initOSType.
+	self coInitialize.
+    ].
 
     "Modified: 13.9.1997 / 10:47:32 / cg"
 !
@@ -737,7 +774,8 @@
 	DomainName := nil.
 	LastErrorNumber := nil.
 	PipeFailed := false.
-	self initOSType
+	self initOSType.
+	self coInitialize.
     ]
 
     "Modified: 22.4.1996 / 13:10:43 / cg"
@@ -3793,98 +3831,66 @@
 
     |resolvedPath|
 
-%{
-    IShellLink *psl;
+%{  /* STACK:100000 */
+
+    static IShellLink   * ipShellLink   = NULL;
+    static IPersistFile * ipPersistFile = NULL;
+
     HRESULT hres;
     WIN32_FIND_DATA wfd;
+    WORD wsz[MAX_PATH];
     char szGotPath[MAX_PATH];
-    IPersistFile *ppf;
-    static FARPROC CoInitializeEx_entry = NULL;
 
     if (! __isString(aPathName)) {
-#ifdef DEBUG_COM
 	console_fprintf(stderr, "OperatingSystem [info]: invalid argument\n");
-#endif
+	goto error;
+    }
+
+    if( ! coInitialized ) {
+	console_fprintf(stderr, "OperatingSystem [info]: com not initialized\n");
 	goto error;
     }
 
-    /*
-     * Attention: CoInitializeEx is not available on old NT4.0/W95/W98
-     */
-#ifdef NO_NT4_0_COMPATIBILITY
-    CoInitializeEx_entry = (FARPROC) CoInitializeEx;
-#else
-    if (CoInitializeEx_entry == NULL) {
-	CoInitializeEx_entry = __get_ole32_functionAddress("CoInitializeEx");
-    }
-#endif /* NO_NT4_0_COMPATIBILITY */
-
-    hres = (*CoInitializeEx_entry)(NULL, COINIT_MULTITHREADED);
-    if (! SUCCEEDED(hres)) {
-#ifdef DEBUG_COM
-	console_fprintf(stderr, "OperatingSystem [info]: Could not open the COM library\n");
-#endif
-	goto error;
-    }
-
-    hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
-			    &IID_IShellLink, (LPVOID *)&psl);
+    if ( ipShellLink == NULL ) {
+	hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+				&IID_IShellLink, (LPVOID *)&ipShellLink);
+	if (! SUCCEEDED(hres)) {
+	    console_fprintf(stderr, "OperatingSystem [info]: CoCreateInstance Error - hres = %08x\n", hres);
+	    ipShellLink = NULL;
+	    goto error;
+	}
+
+	hres = ipShellLink->lpVtbl->QueryInterface( ipShellLink, &IID_IPersistFile, & ipPersistFile );
+	if (! SUCCEEDED(hres)) {
+	    console_fprintf(stderr, "OperatingSystem [info]: QueryInterface Error - hres = %08x\n", hres);
+	    ipShellLink->lpVtbl->Release(ipShellLink);
+	    ipShellLink   = NULL;
+	    ipPersistFile = NULL;
+	    goto error;
+	}
+    }
+
+    MultiByteToWideChar(CP_ACP, 0, __stringVal(aPathName), -1, wsz, MAX_PATH);
+
+    hres = ipPersistFile->lpVtbl->Load(ipPersistFile, wsz, STGM_READ);
+
     if (SUCCEEDED(hres)) {
-	hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf);
-
+	hres = ipShellLink->lpVtbl->GetPath(ipShellLink, szGotPath, MAX_PATH,
+		    (WIN32_FIND_DATA *)&wfd, 0 /* SLGP_SHORTPATH */ );
 	if (SUCCEEDED(hres)) {
-	    WORD wsz[MAX_PATH];
-
-	    MultiByteToWideChar(CP_ACP, 0, __stringVal(aPathName), -1, wsz, MAX_PATH);
-
-	    hres = ppf->lpVtbl->Load(ppf, wsz, STGM_READ);
-	    if (SUCCEEDED(hres)) {
-#if 0
-		hres = psl->lpVtbl->Resolve(psl, 0, SLR_ANY_MATCH|SLR_NO_UI);
-#endif
-		if (SUCCEEDED(hres)) {
-		    hres = psl->lpVtbl->GetPath(psl, szGotPath, MAX_PATH,
-				(WIN32_FIND_DATA *)&wfd, 0 /* SLGP_SHORTPATH */ );
-		    if (!SUCCEEDED(hres)) {
-#ifdef DEBUG_COM
-			console_fprintf(stderr, "OperatingSystem [info]: GetPath failed!\n");
-#endif
-		    } else {
-#if 0
-			console_printf("This points to %s\n", wfd.cFileName); console_fflush(stdout);
-			console_printf("Path is %s\n", szGotPath); console_fflush(stdout);
-			if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-			    console_printf("This is a directory\n"); console_fflush(stdout);
-			}
-#endif
-			resolvedPath = __MKSTRING(szGotPath);
-#if 0
-			hres = psl->lpVtbl->GetWorkingDirectory(psl, szGotPath, MAX_PATH);
-			if (!SUCCEEDED(hres)) {
-			    console_fprintf(stderr, "GetWorkingDirectory failed!\n");
-			} else {
-			    console_printf("In Directory %s\n", szGotPath);
-			}
-#endif
-		    }
-		}
-	    } else {
-#ifdef DEBUG_COM
-	       console_fprintf(stderr, "OperatingSystem [info]: IPersistFile Load Error\n");
-#endif
-	    }
-	    ppf->lpVtbl->Release(ppf);
+	    resolvedPath = __MKSTRING(szGotPath);
 	} else {
-#ifdef DEBUG_COM
-	    console_fprintf(stderr, "OperatingSystem [info]: QueryInterface Error\n");
-#endif
-	}
-	psl->lpVtbl->Release(psl);
+#ifdef COM_DEBUG
+	    console_fprintf(stderr, "OperatingSystem [info]: GetPath failed - hres = %08x\n", hres );
+#endif
+	}
     } else {
-#ifdef DEBUG_COM
-	console_fprintf(stderr, "OperatingSystem [info]: CoCreateInstance Error - hres = %08x\n", hres);
-#endif
-    }
+#ifdef COM_DEBUG
+	console_fprintf(stderr, "OperatingSystem [info]: Load failed - hres = %08x\n", hres );
+#endif
+    }
+    /* ipPersistFile->lpVtbl->Release(ipPersistFile);  */
+
 error: ;
 %}.
     resolvedPath notNil ifTrue:[^ resolvedPath ].
@@ -4670,20 +4676,20 @@
 
     if (__isString(aPathName)) {
 #ifdef DO_WRAP_CALLS
-        char _aPathName[MAXPATHLEN];
-
-        strncpy(_aPathName, __stringVal(aPathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
-        do {
-            __threadErrno = 0;
-            ret = STX_API_CALL1( "GetDriveType", GetDriveType, _aPathName);
-        } while ((ret < 0) && (__threadErrno == EINTR));
-#else
-        ret = GetFileAttributes((char *) __stringVal(aPathName));
-        if (ret < 0) {
-            __threadErrno = __WIN32_ERR(GetLastError());
-        }
-#endif
-        RETURN (ret);  
+	char _aPathName[MAXPATHLEN];
+
+	strncpy(_aPathName, __stringVal(aPathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
+	do {
+	    __threadErrno = 0;
+	    ret = STX_API_CALL1( "GetDriveType", GetDriveType, _aPathName);
+	} while ((ret < 0) && (__threadErrno == EINTR));
+#else
+	ret = GetFileAttributes((char *) __stringVal(aPathName));
+	if (ret < 0) {
+	    __threadErrno = __WIN32_ERR(GetLastError());
+	}
+#endif
+	RETURN (ret);
     }
 %}.
     ^ self primitiveFailed
@@ -5601,21 +5607,21 @@
     |result|
 
     Error
-        handle:[:ex |
-            self halt:'shell execution failed'
-        ] do:[
-            |filename|
-
-            filename := aFilenameOrString asFilename.
-            result := self
-                shellExecute:nil
-                lpOperation:'open'
-                lpFile:filename pathName
-                lpParameters:nil
-                lpDirectory:filename directory pathName
-                nShowCmd:#SW_SHOWNORMAL.
-            ^ self.
-        ]
+	handle:[:ex |
+	    self halt:'shell execution failed'
+	] do:[
+	    |filename|
+
+	    filename := aFilenameOrString asFilename.
+	    result := self
+		shellExecute:nil
+		lpOperation:'open'
+		lpFile:filename pathName
+		lpParameters:nil
+		lpDirectory:filename directory pathName
+		nShowCmd:#SW_SHOWNORMAL.
+	    ^ self.
+	]
 
     "
      self openDocumentationFilename: 'C:\WINDOWS\Help\clipbrd.chm' asFilename
@@ -15655,7 +15661,7 @@
 !Win32OperatingSystem class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.349 2008-10-21 07:46:52 sr Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.350 2008-10-21 11:47:41 ca Exp $'
 ! !
 
 Win32OperatingSystem initialize!