shell32 patch 23 d

Martin Fuchs martin-fuchs at gmx.net
Mon Mar 15 17:24:05 CST 2004


> > Alexandre - is there any thing wrong with this patch?
> 
> Yes there has to be something wrong, you create a sei_tmp structure
> but you never actually use it. I'm not sure what your intent was.

OK, this version should now make clear what's the intent:


Changelog:
- expand environment strings in command, parameter and directory strings of
  ShellExecuteExW32()
  The SHELLEXECUTEINFO copy's content is altered and passed on
  to the worker functions like dde_connect() and SHELL_ExecuteW().
  The return values are returned using the original 'psei' pointer.


Index: shell.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell.c,v
retrieving revision 1.59
diff -u -p -d -r1.59 shell.c
--- shell.c	12 Feb 2004 20:04:23 -0000	1.59
+++ shell.c	15 Mar 2004 23:22:05 -0000
@@ -611,13 +611,14 @@ DWORD WINAPI RegEnumKey16( HKEY hkey, DW
 /*************************************************************************
  *           SHELL_Execute16 [Internal]
  */
-static UINT SHELL_Execute16(WCHAR *lpCmd, void* env, LPSHELLEXECUTEINFOW seiW, BOOL shWait)
+static UINT SHELL_Execute16(const WCHAR *lpCmd, void *env, BOOL shWait,
+			    LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
     UINT ret;
     char sCmd[MAX_PATH];
     WideCharToMultiByte(CP_ACP, 0, lpCmd, -1, sCmd, MAX_PATH, NULL, NULL);
-    ret = WinExec16(sCmd, seiW->nShow);
-    seiW->hInstApp = HINSTANCE_32(ret);
+    ret = WinExec16(sCmd, (UINT16)psei->nShow);
+    psei_out->hInstApp = HINSTANCE_32(ret);
     return ret;
 }
 
Index: shell32_main.h
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_main.h,v
retrieving revision 1.81
diff -u -p -d -r1.81 shell32_main.h
--- shell32_main.h	11 Feb 2004 06:21:45 -0000	1.81
+++ shell32_main.h	15 Mar 2004 23:22:05 -0000
@@ -228,8 +228,10 @@ inline static WCHAR * __SHCloneStrAtoW(W
 #define HINSTANCE_32(h16)	((HINSTANCE)(ULONG_PTR)(h16))
 #define HINSTANCE_16(h32)	(LOWORD(h32))
 
-typedef UINT (*SHELL_ExecuteW32)(WCHAR *lpCmd, void *env, LPSHELLEXECUTEINFOW sei, BOOL shWait);
-BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc);
+typedef UINT (*SHELL_ExecuteW32)(const WCHAR *lpCmd, void *env, BOOL shWait,
+			    LPSHELLEXECUTEINFOW sei, LPSHELLEXECUTEINFOW sei_out);
+
+BOOL WINAPI ShellExecuteExW32(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc);
 
 extern WCHAR swShell32Name[MAX_PATH];
 extern char sShell32Name[MAX_PATH];
Index: shlexec.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.33
diff -u -p -d -r1.33 shlexec.c
--- shlexec.c	4 Mar 2004 20:34:38 -0000	1.33
+++ shlexec.c	15 Mar 2004 23:22:06 -0000
@@ -129,19 +129,20 @@ static BOOL SHELL_ArgifyW(WCHAR* res, in
  *	SHELL_ExecuteW [Internal]
  *
  */
-static UINT SHELL_ExecuteW(WCHAR *lpCmd, void *env, LPSHELLEXECUTEINFOW sei, BOOL shWait)
+static UINT SHELL_ExecuteW(const WCHAR *lpCmd, void *env, BOOL shWait,
+			    LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
     STARTUPINFOW  startup;
     PROCESS_INFORMATION info;
     UINT retval = 31;
 
-    TRACE("Execute %s from directory %s\n", debugstr_w(lpCmd), debugstr_w(sei->lpDirectory));
+    TRACE("Execute %s from directory %s\n", debugstr_w(lpCmd), debugstr_w(psei->lpDirectory));
     ZeroMemory(&startup,sizeof(STARTUPINFOW));
     startup.cb = sizeof(STARTUPINFOW);
     startup.dwFlags = STARTF_USESHOWWINDOW;
-    startup.wShowWindow = sei->nShow;
-    if (CreateProcessW(NULL, lpCmd, NULL, NULL, FALSE, 0,
-                       env, sei->lpDirectory, &startup, &info))
+    startup.wShowWindow = psei->nShow;
+    if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, 0,
+                       env, *psei->lpDirectory? psei->lpDirectory: NULL, &startup, &info))
     {
         /* Give 30 seconds to the app to come up, if desired. Probably only needed
            when starting app immediately before making a DDE connection. */
@@ -149,8 +150,8 @@ static UINT SHELL_ExecuteW(WCHAR *lpCmd,
             if (WaitForInputIdle( info.hProcess, 30000 ) == -1)
                 WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
         retval = 33;
-        if(sei->fMask & SEE_MASK_NOCLOSEPROCESS)
-            sei->hProcess = info.hProcess;
+        if (psei->fMask & SEE_MASK_NOCLOSEPROCESS)
+            psei_out->hProcess = info.hProcess;
         else
             CloseHandle( info.hProcess );
         CloseHandle( info.hThread );
@@ -163,7 +164,7 @@ static UINT SHELL_ExecuteW(WCHAR *lpCmd,
 
     TRACE("returning %u\n", retval);
 
-    sei->hInstApp = (HINSTANCE)retval;
+    psei_out->hInstApp = (HINSTANCE)retval;
     return retval;
 }
 
@@ -535,7 +536,8 @@ static HDDEDATA CALLBACK dde_cb(UINT uTy
  */
 static unsigned dde_connect(WCHAR* key, WCHAR* start, WCHAR* ddeexec,
                             const WCHAR* lpFile, void *env,
-                            LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
+			    SHELL_ExecuteW32 execfunc,
+			    LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
     static const WCHAR wApplication[] = {'\\','a','p','p','l','i','c','a','t','i','o','n',0};
     static const WCHAR wTopic[] = {'\\','t','o','p','i','c',0};
@@ -579,7 +581,7 @@ static unsigned dde_connect(WCHAR* key, 
     {
         static const WCHAR wIfexec[] = {'\\','i','f','e','x','e','c',0};
         TRACE("Launching '%s'\n", debugstr_w(start));
-        ret = execfunc(start, env, sei, TRUE);
+        ret = execfunc(start, env, TRUE, psei, psei_out);
         if (ret < 32)
         {
             TRACE("Couldn't launch\n");
@@ -616,7 +618,8 @@ static unsigned dde_connect(WCHAR* key, 
  *	execute_from_key [Internal]
  */
 static UINT execute_from_key(LPWSTR key, LPCWSTR lpFile, void *env,
-                             LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
+			     SHELL_ExecuteW32 execfunc,
+			     LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
     WCHAR cmd[1024] = {0};
     LONG cmdlen = sizeof(cmd);
@@ -640,7 +643,7 @@ static UINT execute_from_key(LPWSTR key,
         if (RegQueryValueW(HKEY_CLASSES_ROOT, key, param, &paramlen) == ERROR_SUCCESS)
         {
             TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(param));
-            retval = dde_connect(key, cmd, param, lpFile, env, sei, execfunc);
+            retval = dde_connect(key, cmd, param, lpFile, env, execfunc, psei, psei_out);
         }
         else
         {
@@ -648,7 +651,7 @@ static UINT execute_from_key(LPWSTR key,
             cmdlen /= sizeof(WCHAR);
             cmd[cmdlen] = '\0';
             SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile);
-            retval = execfunc(param, env, sei, FALSE);
+            retval = execfunc(param, env, FALSE, psei, psei_out);
         }
     }
     else TRACE("ooch\n");
@@ -721,7 +724,10 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
     static const WCHAR wWww[] = {'w','w','w',0};
     static const WCHAR wFile[] = {'f','i','l','e',0};
     static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0};
-    WCHAR wszApplicationName[MAX_PATH+2],wszCommandline[1024],wszPidl[20],wfileName[MAX_PATH];
+
+    WCHAR wszApplicationName[MAX_PATH+2], wszCommandline[1024], wszDir[MAX_PATH];
+    SHELLEXECUTEINFOW sei_tmp;	/* modifyable copy of SHELLEXECUTEINFO struct */
+    WCHAR wszPidl[20], wfileName[MAX_PATH];
     LPWSTR pos;
     void *env;
     int gap, len;
@@ -729,49 +735,67 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
     LPCWSTR lpFile;
     UINT retval = 31;
     WCHAR wcmd[1024];
+    WCHAR buffer[MAX_PATH];
     BOOL done;
 
+    /* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
+    memcpy(&sei_tmp, sei, sizeof(sei_tmp));
+
     TRACE("mask=0x%08lx hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n",
-            sei->fMask, sei->hwnd, debugstr_w(sei->lpVerb),
-            debugstr_w(sei->lpFile), debugstr_w(sei->lpParameters),
-            debugstr_w(sei->lpDirectory), sei->nShow,
-            (sei->fMask & SEE_MASK_CLASSNAME) ? debugstr_w(sei->lpClass) : "not used");
+            sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
+            debugstr_w(sei_tmp.lpFile), debugstr_w(sei_tmp.lpParameters),
+            debugstr_w(sei_tmp.lpDirectory), sei_tmp.nShow,
+            (sei_tmp.fMask & SEE_MASK_CLASSNAME) ? debugstr_w(sei_tmp.lpClass) : "not used");
 
     sei->hProcess = NULL;
-    ZeroMemory(wszApplicationName,MAX_PATH);
-    if (sei->lpFile)
-        strcpyW(wszApplicationName, sei->lpFile);
 
-    ZeroMemory(wszCommandline,1024);
-    if (sei->lpParameters)
-        strcpyW(wszCommandline, sei->lpParameters);
+    /* make copies of all path/command strings */
+    if (sei_tmp.lpFile)
+	strcpyW(wszApplicationName, sei_tmp.lpFile);
+    else
+	*wszApplicationName = '\0';
 
-    if (sei->fMask & (SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY |
+    if (sei_tmp.lpParameters)
+	strcpyW(wszCommandline, sei_tmp.lpParameters);
+    else
+	*wszCommandline = '\0';
+
+    if (sei_tmp.lpDirectory)
+	strcpyW(wszDir, sei_tmp.lpDirectory);
+    else
+	*wszDir = '\0';
+
+    /* adjust string pointers to point to the new buffers */
+    sei_tmp.lpFile = wszApplicationName;
+    sei_tmp.lpParameters = wszCommandline;
+    sei_tmp.lpDirectory = wszDir;
+
+    if (sei_tmp.fMask & (SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY |
         SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT |
         SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI | SEE_MASK_UNICODE |
         SEE_MASK_NO_CONSOLE | SEE_MASK_ASYNCOK | SEE_MASK_HMONITOR ))
     {
-        FIXME("flags ignored: 0x%08lx\n", sei->fMask);
+        FIXME("flags ignored: 0x%08lx\n", sei_tmp.fMask);
     }
 
     /* process the IDList */
-    if ( (sei->fMask & SEE_MASK_INVOKEIDLIST) == SEE_MASK_INVOKEIDLIST) /*0x0c*/
+    if ((sei_tmp.fMask & SEE_MASK_INVOKEIDLIST) == SEE_MASK_INVOKEIDLIST) /*0x0c*/
     {
         wszApplicationName[0] = '"';
-        SHGetPathFromIDListW(sei->lpIDList,wszApplicationName + 1);
+        SHGetPathFromIDListW(sei_tmp.lpIDList, wszApplicationName+1);
         strcatW(wszApplicationName, wQuote);
-        TRACE("-- idlist=%p (%s)\n", sei->lpIDList, debugstr_w(wszApplicationName));
+        TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName));
     }
     else
     {
-        if (sei->fMask & SEE_MASK_IDLIST )
+        if (sei_tmp.fMask & SEE_MASK_IDLIST)
         {
 	    static const WCHAR wI[] = {'%','I',0}, wP[] = {':','%','p',0};
             pos = strstrW(wszCommandline, wI);
             if (pos)
             {
                 LPVOID pv;
-                HGLOBAL hmem = SHAllocShared ( sei->lpIDList, ILGetSize(sei->lpIDList), 0);
+                HGLOBAL hmem = SHAllocShared(sei_tmp.lpIDList, ILGetSize(sei_tmp.lpIDList), 0);
                 pv = SHLockShared(hmem,0);
                 sprintfW(wszPidl,wP,pv );
                 SHUnlockShared(pv);
@@ -784,14 +808,14 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
         }
     }
 
-    if (sei->fMask & (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY))
+    if (sei_tmp.fMask & (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY))
     {
 	/* launch a document by fileclass like 'WordPad.Document.1' */
         /* the Commandline contains 'c:\Path\wordpad.exe "%1"' */
         /* FIXME: szCommandline should not be of a fixed size. Fixed to 1024, MAX_PATH is way too short! */
-        HCR_GetExecuteCommandW((sei->fMask & SEE_MASK_CLASSKEY) ? sei->hkeyClass : NULL,
-                               (sei->fMask & SEE_MASK_CLASSNAME) ? sei->lpClass: NULL,
-                               (sei->lpVerb) ? sei->lpVerb : wszOpen,
+        HCR_GetExecuteCommandW((sei_tmp.fMask & SEE_MASK_CLASSKEY) ? sei_tmp.hkeyClass : NULL,
+                               (sei_tmp.fMask & SEE_MASK_CLASSNAME) ? sei_tmp.lpClass: NULL,
+                               (sei_tmp.lpVerb) ? sei_tmp.lpVerb : wszOpen,
                                wszCommandline, sizeof(wszCommandline)/sizeof(WCHAR));
 
         /* FIXME: get the extension of lpFile, check if it fits to the lpClass */
@@ -804,15 +828,27 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
             strcatW(wcmd, wSpace);
             strcatW(wcmd, wszApplicationName);
         }
-        retval = execfunc(wcmd, NULL, sei, FALSE);
+        retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
         if (retval > 32)
             return TRUE;
         else
             return FALSE;
     }
 
+    /* expand environment strings */
+    if (ExpandEnvironmentStringsW(sei_tmp.lpFile, buffer, MAX_PATH))
+	lstrcpyW(wszApplicationName, buffer);
+
+    if (*sei_tmp.lpParameters)
+        if (ExpandEnvironmentStringsW(sei_tmp.lpParameters, buffer, MAX_PATH))
+	    lstrcpyW(wszCommandline, buffer);
+
+    if (*sei_tmp.lpDirectory)
+	if (ExpandEnvironmentStringsW(sei_tmp.lpDirectory, buffer, MAX_PATH))
+	    lstrcpyW(wszDir, buffer);
+
     /* Else, try to execute the filename */
-    TRACE("execute:'%s','%s'\n", debugstr_w(wszApplicationName), debugstr_w(wszCommandline));
+    TRACE("execute:'%s','%s','%s'\n", debugstr_w(wszApplicationName), debugstr_w(wszCommandline), debugstr_w(wszDir));
 
     strcpyW(wfileName, wszApplicationName);
     lpFile = wfileName;
@@ -821,13 +857,13 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
         strcatW(wszApplicationName, wszCommandline);
     }
 
-    retval = execfunc(wszApplicationName, NULL, sei, FALSE);
+    retval = execfunc(wszApplicationName, NULL, FALSE, &sei_tmp, sei);
     if (retval > 32)
         return TRUE;
 
     /* Else, try to find the executable */
     wcmd[0] = '\0';
-    retval = SHELL_FindExecutable(sei->lpDirectory, lpFile, sei->lpVerb, wcmd, lpstrProtocol, &env);
+    retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, lpstrProtocol, &env);
     if (retval > 32)  /* Found */
     {
         WCHAR wszQuotedCmd[MAX_PATH+2];
@@ -841,11 +877,11 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
             strcatW(wszQuotedCmd, wSpace);
             strcatW(wszQuotedCmd, wszCommandline);
         }
-        TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName), debugstr_w(sei->lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(lpstrProtocol));
+        TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName), debugstr_w(sei_tmp.lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(lpstrProtocol));
         if (*lpstrProtocol)
-            retval = execute_from_key(lpstrProtocol, wszApplicationName, env, sei, execfunc);
+            retval = execute_from_key(lpstrProtocol, wszApplicationName, env, execfunc, &sei_tmp, sei);
         else
-            retval = execfunc(wszQuotedCmd, env, sei, FALSE);
+            retval = execfunc(wszQuotedCmd, env, FALSE, &sei_tmp, sei);
         if (env) HeapFree( GetProcessHeap(), 0, env );
     }
     else if (PathIsURLW((LPWSTR)lpFile))    /* File not found, check for URL */
@@ -866,7 +902,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
         strncpyW(lpstrProtocol, lpFile, iSize);
         lpstrProtocol[iSize] = '\0';
         strcatW(lpstrProtocol, wShell);
-        strcatW(lpstrProtocol, sei->lpVerb? sei->lpVerb: wszOpen);
+        strcatW(lpstrProtocol, sei_tmp.lpVerb? sei_tmp.lpVerb: wszOpen);
         strcatW(lpstrProtocol, wCommand);
 
         /* Remove File Protocol from lpFile */
@@ -876,7 +912,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
             lpFile += iSize;
             while (*lpFile == ':') lpFile++;
         }
-        retval = execute_from_key(lpstrProtocol, lpFile, NULL, sei, execfunc);
+        retval = execute_from_key(lpstrProtocol, lpFile, NULL, execfunc, &sei_tmp, sei);
     }
     /* Check if file specified is in the form www.??????.*** */
     else if (!strncmpiW(lpFile, wWww, 3))
@@ -885,7 +921,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
         WCHAR lpstrTmpFile[256];
         strcpyW(lpstrTmpFile, wHttp);
         strcatW(lpstrTmpFile, lpFile);
-        retval = (UINT)ShellExecuteW(sei->hwnd, sei->lpVerb, lpstrTmpFile, NULL, NULL, 0);
+        retval = (UINT)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
     }
 
     TRACE("retval %u\n", retval);






More information about the wine-patches mailing list