Fix environment passing in ShellExecute

Francois Gouget fgouget at codeweavers.com
Tue Jun 15 12:37:41 CDT 2004


The symptom is that you get an error message that says libwine.so.1 
could not be loaded. This happens for instance when Internet Explorer 
uses ShellExecute() to start 'icwconn1.exe'.

What happens is that ShellExecute decides to look for icwconn1.exe using 
SHELL_FindExecutable() and gets a pointer to a Unicode environment block 
in the bargain.

It then calls the execfunc() function pointer passing it a pointer to 
that Unicode environment block. In the case that interests us 
execfunc==SHELL_ExecuteW() which calls CreateProcessW() but does not set 
the CREATE_UNICODE_ENVIRONMENT flag. This results in the child getting 
and environment that looks something like:

H
O
M
E
=
/
...

Where each line is supposed to be a separate environment variable. Of 
course LD_LIBRARY_PATH is long gone and the child process miserably 
fails to start.

The fix:

In the prototype of execfunc the environment block is defined as a 
void*, probably because the author thought it could either be an Ascii 
or a Unicode environment block. But the caller has no way to know what 
the callee expects, and anyway all we ever pass to that function is a 
Unicode environment block.

So this patch specifies that SHELL_ExecuteW32() (i.e. typeof(execfunc)) 
always takes a Unicode environment and adjusts various prototypes 
accordingly. It also modifies SHELL_ExecuteW() to pass the 
CREATE_UNICODE_ENVIRONMENT flag to CreateProcessW().

Changelog:

  * dlls/shell32/shell.c
    dlls/shell32/shell32_main.h
    dlls/shell32/shlexec.c

    Francois Gouget <fgouget at codeweavers.com>
    SHELL_ExecuteW() passes a Unicode environment to CreateProcessW() so 
it must specify the CREATE_UNICODE_ENVIRONMENT flag. Also the 
SHELL_ExecuteW32() functions will always be called with a Unicode 
environment so adjust their prototype accordingly.


-- 
Francois Gouget
fgouget at codeweavers.com

-------------- next part --------------
Index: dlls/shell32/shell.c
===================================================================
RCS file: /var/cvs/wine/dlls/shell32/shell.c,v
retrieving revision 1.60
diff -u -r1.60 shell.c
--- a/dlls/shell32/shell.c	18 Mar 2004 04:04:29 -0000	1.60
+++ b/dlls/shell32/shell.c	15 Jun 2004 15:24:27 -0000
@@ -611,7 +611,7 @@
 /*************************************************************************
  *           SHELL_Execute16 [Internal]
  */
-static UINT SHELL_Execute16(const WCHAR *lpCmd, void *env, BOOL shWait,
+static UINT SHELL_Execute16(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
 			    LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
     UINT ret;
Index: dlls/shell32/shell32_main.h
===================================================================
RCS file: /var/cvs/wine/dlls/shell32/shell32_main.h,v
retrieving revision 1.87
diff -u -r1.87 shell32_main.h
--- a/dlls/shell32/shell32_main.h	19 Apr 2004 19:26:57 -0000	1.87
+++ b/dlls/shell32/shell32_main.h	15 Jun 2004 15:25:46 -0000
@@ -228,13 +228,13 @@
 #define HINSTANCE_32(h16)	((HINSTANCE)(ULONG_PTR)(h16))
 #define HINSTANCE_16(h32)	(LOWORD(h32))
 
-typedef UINT (*SHELL_ExecuteW32)(const WCHAR *lpCmd, void *env, BOOL shWait,
+typedef UINT (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
 			    LPSHELLEXECUTEINFOW sei, LPSHELLEXECUTEINFOW sei_out);
 
 BOOL WINAPI ShellExecuteExW32(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc);
 
 UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
-                          LPWSTR lpResult, int resultLen, LPWSTR key, void **env, LPITEMIDLIST pidl, LPCWSTR args);
+                          LPWSTR lpResult, int resultLen, LPWSTR key, WCHAR **env, LPITEMIDLIST pidl, LPCWSTR args);
 
 extern WCHAR swShell32Name[MAX_PATH];
 
Index: dlls/shell32/shlexec.c
===================================================================
RCS file: /var/cvs/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.50
diff -u -r1.50 shlexec.c
--- a/dlls/shell32/shlexec.c	15 Jun 2004 00:44:14 -0000	1.50
+++ b/dlls/shell32/shlexec.c	15 Jun 2004 15:26:43 -0000
@@ -298,7 +298,7 @@
  *	SHELL_ExecuteW [Internal]
  *
  */
-static UINT SHELL_ExecuteW(const WCHAR *lpCmd, void *env, BOOL shWait,
+static UINT SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
 			    LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
     STARTUPINFOW  startup;
@@ -318,7 +318,7 @@
     startup.cb = sizeof(STARTUPINFOW);
     startup.dwFlags = STARTF_USESHOWWINDOW;
     startup.wShowWindow = psei->nShow;
-    if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, 0,
+    if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT,
                        env, *psei->lpDirectory? psei->lpDirectory: NULL, &startup, &info))
     {
         /* Give 30 seconds to the app to come up, if desired. Probably only needed
@@ -416,7 +416,7 @@
  * On entry: szName is a filename (probably without path separators).
  * On exit: if szName found in "App Path", place full path in lpResult, and return true
  */
-static BOOL SHELL_TryAppPathW( LPCWSTR szName, LPWSTR lpResult, void**env)
+static BOOL SHELL_TryAppPathW( LPCWSTR szName, LPWSTR lpResult, WCHAR **env)
 {
     static const WCHAR wszKeyAppPaths[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',
 	'\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','A','p','p',' ','P','a','t','h','s','\\',0};
@@ -513,7 +513,7 @@
  *              on the operation)
  */
 UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
-                                 LPWSTR lpResult, int resultLen, LPWSTR key, void **env, LPITEMIDLIST pidl, LPCWSTR args)
+                                 LPWSTR lpResult, int resultLen, LPWSTR key, WCHAR **env, LPITEMIDLIST pidl, LPCWSTR args)
 {
     static const WCHAR wWindows[] = {'w','i','n','d','o','w','s',0};
     static const WCHAR wPrograms[] = {'p','r','o','g','r','a','m','s',0};
@@ -734,7 +734,7 @@
  *
  */
 static unsigned dde_connect(WCHAR* key, WCHAR* start, WCHAR* ddeexec,
-                            const WCHAR* lpFile, void *env,
+                            const WCHAR* lpFile, WCHAR *env,
 			    LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc,
 			    LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
@@ -828,7 +828,7 @@
 /*************************************************************************
  *	execute_from_key [Internal]
  */
-static UINT execute_from_key(LPWSTR key, LPCWSTR lpFile, void *env, LPCWSTR szCommandline,
+static UINT execute_from_key(LPWSTR key, LPCWSTR lpFile, WCHAR *env, LPCWSTR szCommandline,
 			     SHELL_ExecuteW32 execfunc,
 			     LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
@@ -945,7 +945,7 @@
     WCHAR wszApplicationName[MAX_PATH+2], wszParameters[1024], wszDir[MAX_PATH];
     SHELLEXECUTEINFOW sei_tmp;	/* modifiable copy of SHELLEXECUTEINFO struct */
     WCHAR wfileName[MAX_PATH];
-    void *env;
+    WCHAR *env;
     WCHAR lpstrProtocol[256];
     LPCWSTR lpFile;
     UINT retval = 31;


More information about the wine-patches mailing list