shell32 patch 23e

Martin Fuchs martin-fuchs at gmx.net
Thu Mar 25 14:27:37 CST 2004


Changelog:
- fix handling of %2, %3, ... and lower case format characters in SHELL_ArgifyW()
- move "%I" expansion from ShellExecuteEx() into common function SHELL_ArgifyW()
- pass buffer length to SHELL_FindExecutable()
- FIXME comment for len paramater in SHELL_ArgifyW()

Quotation mark handling is from Ge van Geldorp <ge at gse.nl>:
- Add double quotation marks unless we already have them (e.g.: "%1" %* for exefile)
- Remove unnecessary double quotation marks and command line arguments


Index: shell32_main.h
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_main.h,v
retrieving revision 1.83
diff -u -p -d -r1.83 shell32_main.h
--- shell32_main.h	22 Mar 2004 20:43:07 -0000	1.83
+++ shell32_main.h	25 Mar 2004 20:56:09 -0000
@@ -233,6 +233,9 @@ typedef UINT (*SHELL_ExecuteW32)(const W
 
 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);
+
 extern WCHAR swShell32Name[MAX_PATH];
 
 #endif
Index: shelllink.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shelllink.c,v
retrieving revision 1.62
diff -u -p -d -r1.62 shelllink.c
--- shelllink.c	22 Mar 2004 22:58:37 -0000	1.62
+++ shelllink.c	25 Mar 2004 20:56:10 -0000
@@ -652,20 +652,29 @@ static HRESULT WINAPI IPersistStream_fnS
 	IStream*         stm,
 	BOOL             fClearDirty)
 {
+    static const WCHAR wOpen[] = {'o','p','e','n',0};
+
     LINK_HEADER header;
-    ULONG    count;
-    HRESULT    r;
+    WCHAR   exePath[MAX_PATH];
+    ULONG   count;
+    HRESULT r;
 
-	_ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
+    _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
 
     TRACE("(%p) %p %x\n", This, stm, fClearDirty);
 
+    *exePath = '\0';
+
+    if (This->sPath)
+	SHELL_FindExecutable(NULL, This->sPath, wOpen, exePath, MAX_PATH, NULL, NULL, NULL, NULL);
+
     /* if there's no PIDL, generate one */
     if( ! This->pPidl )
     {
-        if( ! This->sPath )
+        if( !*exePath )
             return E_FAIL;
-        This->pPidl = ILCreateFromPathW( This->sPath );
+
+        This->pPidl = ILCreateFromPathW(exePath);
     }
 
     memset(&header, 0, sizeof(header));
@@ -712,10 +721,7 @@ static HRESULT WINAPI IPersistStream_fnS
         }
     }
 
-    TRACE("Path = %s\n", debugstr_w(This->sPath));
-    if( ! This->sPath )
-        return E_FAIL;
-    Stream_WriteLocationInfo( stm, This->sPath );
+    Stream_WriteLocationInfo( stm, exePath );
 
     TRACE("Description = %s\n", debugstr_w(This->sDescription));
     if( This->sDescription )
Index: shlexec.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.35
diff -u -p -d -r1.35 shlexec.c
--- shlexec.c	19 Mar 2004 01:52:30 -0000	1.35
+++ shlexec.c	25 Mar 2004 20:56:10 -0000
@@ -54,6 +54,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(exec);
 
 static const WCHAR wszOpen[] = {'o','p','e','n',0};
 static const WCHAR wszExe[] = {'.','e','x','e',0};
+static const WCHAR wszILPtr[] = {':','%','p',0};
 static const WCHAR wszShell[] = {'\\','s','h','e','l','l','\\',0};
 
 
@@ -71,11 +72,16 @@ static const WCHAR wszShell[] = {'\\','s
  * %L seems to be %1 as long filename followed by the 8+3 variation
  * %S ???
  * %* all following parameters (see batfile)
+ *
+ * FIXME: use 'len'
  */
-static BOOL SHELL_ArgifyW(WCHAR* res, int len, const WCHAR* fmt, const WCHAR* lpFile)
+static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lpFile, LPITEMIDLIST pidl, LPCWSTR args)
 {
-    WCHAR       xlpFile[1024];
-    BOOL        done = FALSE;
+    WCHAR   xlpFile[1024];
+    BOOL    done = FALSE;
+    PWSTR   res = out;
+    PCWSTR  cmd;
+    LPVOID  pv;
 
     while (*fmt)
     {
@@ -87,30 +93,84 @@ static BOOL SHELL_ArgifyW(WCHAR* res, in
             case '%':
                 *res++ = '%';
                 break;
-            case '1':
-            case '*':
-                if (!done || (*fmt == '1'))
-                {
-                    if (SearchPathW(NULL, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL))
-                    {
-                        strcpyW(res, xlpFile);
-                        res += strlenW(xlpFile);
-                    }
-                    else
-                    {
-                        strcpyW(res, lpFile);
-                        res += strlenW(lpFile);
-                    }
-                }
+
+              case '2':
+              case '3':
+	      case '4':
+	      case '5':
+              case '6':
+              case '7':
+	      case '8':
+	      case '9':
+	      case '0':
+              case '*':
+		if (args)
+		{
+		    if (*fmt == '*')
+		    {
+			*res++ = '"';
+			while(*args)
+			    *res++ = *args++;
+			*res++ = '"';
+		    }
+		    else
+		    {
+			while(*args && !isspace(*args))
+			    *res++ = *args++;
+
+			while(isspace(*args))
+			    ++args;
+		    }
+		}
+		else
+		{
+              case '1':
+		    if (!done || (*fmt == '1'))
+		    {
+			/*FIXME Is the call to SearchPathW() really needed? We already have separated out the parameter string in args. */
+			if (SearchPathW(NULL, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL))
+			    cmd = xlpFile;
+			else
+			    cmd = lpFile;
+
+			/* Add double quotation marks unless we already have them (e.g.: "%1" %* for exefile) */
+			if (res==out || res[-1]!='"')
+			{
+			    *res++ = '"';
+			    strcpyW(res, cmd);
+			    res += strlenW(cmd);
+			    *res++ = '"';
+			}
+			else
+			{
+			    strcpyW(res, cmd);
+			    res += strlenW(cmd);
+			}
+		    }
+		}
                 break;
+
             /*
              * IE uses this alot for activating things such as windows media
              * player. This is not verified to be fully correct but it appears
              * to work just fine.
              */
-            case 'L':
-                strcpyW(res,lpFile);
-                res += strlenW(lpFile);
+              case 'l':
+              case 'L':
+		if (lpFile) {
+		    strcpyW(res, lpFile);
+		    res += strlenW(lpFile);
+		}
+                break;
+
+              case 'i':
+              case 'I':
+		if (pidl) {
+		    HGLOBAL hmem = SHAllocShared(pidl, ILGetSize(pidl), 0);
+		    pv = SHLockShared(hmem, 0);
+		    res += sprintfW(res, wszILPtr, pv);
+		    SHUnlockShared(pv);
+		}
                 break;
 
             default: FIXME("Unknown escape sequence %%%c\n", *fmt);
@@ -121,7 +181,9 @@ static BOOL SHELL_ArgifyW(WCHAR* res, in
         else
             *res++ = *fmt++;
     }
+
     *res = '\0';
+
     return done;
 }
 
@@ -343,8 +405,8 @@ static UINT SHELL_FindExecutableByOperat
  *              command (it'll be used afterwards for more information
  *              on the operation)
  */
-static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
-                                 LPWSTR lpResult, LPWSTR key, void **env)
+UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
+                                 LPWSTR lpResult, int resultLen, LPWSTR key, void **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};
@@ -489,8 +551,20 @@ static UINT SHELL_FindExecutable(LPCWSTR
 	}
 
 	if (retval > 32)
-        {
-            SHELL_ArgifyW(lpResult, 1024 /*FIXME*/, command, xlpFile);
+	{
+	    SHELL_ArgifyW(lpResult, resultLen, command, xlpFile, pidl, args);
+
+	    /* Remove double quotation marks and command line arguments */
+	    if (*lpResult == '"')
+	    {
+		WCHAR *p = lpResult;
+		while (*(p + 1) != '"')
+		{
+		    *p = *(p + 1);
+		    p++;
+		}
+		*p = '\0';
+	    }
 	}
     }
     else /* Check win.ini */
@@ -548,7 +622,7 @@ static HDDEDATA CALLBACK dde_cb(UINT uTy
  */
 static unsigned dde_connect(WCHAR* key, WCHAR* start, WCHAR* ddeexec,
                             const WCHAR* lpFile, void *env,
-			    SHELL_ExecuteW32 execfunc,
+			    LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc,
 			    LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
     static const WCHAR wApplication[] = {'\\','a','p','p','l','i','c','a','t','i','o','n',0};
@@ -615,21 +689,23 @@ static unsigned dde_connect(WCHAR* key, 
         }
     }
 
-    SHELL_ArgifyW(res, sizeof(res)/sizeof(WCHAR), exec, lpFile);
+    SHELL_ArgifyW(res, sizeof(res)/sizeof(WCHAR), exec, lpFile, pidl, szCommandline);
     TRACE("%s %s => %s\n", debugstr_w(exec), debugstr_w(lpFile), debugstr_w(res));
 
     ret = (DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * sizeof(WCHAR), hConv, 0L, 0,
                                 XTYP_EXECUTE, 10000, &tid) != DMLERR_NO_ERROR) ? 31 : 33;
     DdeDisconnect(hConv);
+
  error:
     DdeUninitialize(ddeInst);
+
     return ret;
 }
 
 /*************************************************************************
  *	execute_from_key [Internal]
  */
-static UINT execute_from_key(LPWSTR key, LPCWSTR lpFile, void *env,
+static UINT execute_from_key(LPWSTR key, LPCWSTR lpFile, void *env, LPCWSTR szCommandline,
 			     SHELL_ExecuteW32 execfunc,
 			     LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
@@ -655,14 +731,14 @@ 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, execfunc, psei, psei_out);
+            retval = dde_connect(key, cmd, param, lpFile, env, szCommandline, psei->lpIDList, execfunc, psei, psei_out);
         }
         else
         {
             /* Is there a replace() function anywhere? */
             cmdlen /= sizeof(WCHAR);
             cmd[cmdlen] = '\0';
-            SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile);
+            SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile, psei->lpIDList, szCommandline);
             retval = execfunc(param, env, FALSE, psei, psei_out);
         }
     }
@@ -718,7 +794,7 @@ HINSTANCE WINAPI FindExecutableW(LPCWSTR
         SetCurrentDirectoryW(lpDirectory);
     }
 
-    retval = SHELL_FindExecutable(lpDirectory, lpFile, wszOpen, lpResult, NULL, NULL);
+    retval = SHELL_FindExecutable(lpDirectory, lpFile, wszOpen, lpResult, MAX_PATH, NULL, NULL, NULL, NULL);
 
     TRACE("returning %s\n", debugstr_w(lpResult));
     if (lpDirectory)
@@ -739,10 +815,8 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
 
     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;
+    WCHAR wfileName[MAX_PATH];
     void *env;
-    int gap, len;
     WCHAR lpstrProtocol[256];
     LPCWSTR lpFile;
     UINT retval = 31;
@@ -798,27 +872,6 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
         strcatW(wszApplicationName, wQuote);
         TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName));
     }
-    else
-    {
-        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_tmp.lpIDList, ILGetSize(sei_tmp.lpIDList), 0);
-                pv = SHLockShared(hmem,0);
-                sprintfW(wszPidl,wP,pv );
-                SHUnlockShared(pv);
-
-                gap = strlenW(wszPidl);
-                len = strlenW(pos)-2;
-                memmove(pos+gap,pos+2,len*sizeof(WCHAR));
-                memcpy(pos,wszPidl,gap*sizeof(WCHAR));
-            }
-        }
-    }
 
     if (sei_tmp.fMask & (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY))
     {
@@ -834,7 +887,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
         TRACE("SEE_MASK_CLASSNAME->'%s', doc->'%s'\n", debugstr_w(wszCommandline), debugstr_w(wszApplicationName));
 
         wcmd[0] = '\0';
-        done = SHELL_ArgifyW(wcmd, sizeof(wcmd)/sizeof(WCHAR), wszCommandline, wszApplicationName);
+        done = SHELL_ArgifyW(wcmd, sizeof(wcmd)/sizeof(WCHAR), wszCommandline, wszApplicationName, sei_tmp.lpIDList, NULL);
         if (!done && wszApplicationName[0])
         {
             strcatW(wcmd, wSpace);
@@ -875,7 +928,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
 
     /* Else, try to find the executable */
     wcmd[0] = '\0';
-    retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, lpstrProtocol, &env);
+    retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, 1024, lpstrProtocol, &env, sei_tmp.lpIDList, sei_tmp.lpParameters);
     if (retval > 32)  /* Found */
     {
         WCHAR wszQuotedCmd[MAX_PATH+2];
@@ -891,7 +944,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
         }
         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, execfunc, &sei_tmp, sei);
+            retval = execute_from_key(lpstrProtocol, wszApplicationName, env, sei_tmp.lpParameters, execfunc, &sei_tmp, sei);
         else
             retval = execfunc(wszQuotedCmd, env, FALSE, &sei_tmp, sei);
         if (env) HeapFree( GetProcessHeap(), 0, env );
@@ -924,7 +977,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
             lpFile += iSize;
             while (*lpFile == ':') lpFile++;
         }
-        retval = execute_from_key(lpstrProtocol, lpFile, NULL, execfunc, &sei_tmp, sei);
+        retval = execute_from_key(lpstrProtocol, lpFile, NULL, sei_tmp.lpParameters, execfunc, &sei_tmp, sei);
     }
     /* Check if file specified is in the form www.??????.*** */
     else if (!strncmpiW(lpFile, wWww, 3))





More information about the wine-patches mailing list