shell32 patch 23e

Martin Fuchs martin-fuchs at gmx.net
Thu Mar 18 16:39:26 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()
- Remove unnecessary double quotation marks and command line arguments
- FIXME comment for len paramater in SHELL_ArgifyW()

Quotation mark handling is from Ge van Geldorp <ge at gse.nl>.


Index: shlexec.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.34
diff -u -p -d -r1.34 shlexec.c
--- shlexec.c	18 Mar 2004 04:04:29 -0000	1.34
+++ shlexec.c	18 Mar 2004 22:37:53 -0000
@@ -71,11 +71,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;
+    LPVOID  pv;
+    PWSTR   res = out;
+    PCWSTR  cmd;
 
     while (*fmt)
     {
@@ -87,30 +92,82 @@ 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) == '"')
+			{
+			    strcpyW(res, cmd);
+			    res += strlenW(cmd);
+			}
+			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 +178,9 @@ static BOOL SHELL_ArgifyW(WCHAR* res, in
         else
             *res++ = *fmt++;
     }
+
     *res = '\0';
+
     return done;
 }
 
@@ -332,7 +391,7 @@ static UINT SHELL_FindExecutableByOperat
  *              on the operation)
  */
 static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
-                                 LPWSTR lpResult, LPWSTR key, void **env)
+                                 LPWSTR lpResult, int resultLen, LPWSTR key, void **env)
 {
     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};
@@ -477,8 +536,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 */
@@ -609,8 +680,10 @@ static unsigned dde_connect(WCHAR* key, 
     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;
 }
 
@@ -706,7 +779,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);
 
     TRACE("returning %s\n", debugstr_w(lpResult));
     if (lpDirectory)
@@ -863,7 +936,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);
     if (retval > 32)  /* Found */
     {
         WCHAR wszQuotedCmd[MAX_PATH+2];





More information about the wine-patches mailing list