ShellExecute placeholder patch

Duane Clark dclark at akamail.com
Fri Jul 5 13:03:59 CDT 2002


As the comment to ShellExecute states, there can be placeholders in 
commandlines retrieved from the registry. For example, MS Installer has 
this string:
[Software\\CLASSES\\Msi.Package\\shell\\Open\\command] 1024260663
@="\"C:\\WINDOWS\\SYSTEM\\msiexec.exe\" /i \"%1\" %*"

The placeholders need to be filled in before passing the command to 
CreateProcessA, and this patch attempts to do that. The escaped 
characters have already been unescaped once before this routine gets it 
(at least this applies to the escaped quotes). It allows the PKZip 
installer to run, though the installation now fails later when 
apparently trying to create file associations.

A resemblance to build_argv() is not accidental, but all mistakes are of 
course mine.

Changelog: Fill in placeholders in ShellExecuteA.

-------------- next part --------------
Index: dlls/shell32/shellord.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shellord.c,v
retrieving revision 1.99
diff -u -r1.99 shellord.c
--- dlls/shell32/shellord.c	3 Jul 2002 21:07:36 -0000	1.99
+++ dlls/shell32/shellord.c	5 Jul 2002 03:46:34 -0000
@@ -926,6 +926,72 @@
 {	FIXME("0x%08lx 0x%08lx stub\n",x,z);
 	return 0;
 }
+
+/***********************************************************************
+ *           make_cmdline
+ *
+ *    This routine copies command to cmdline, replacing %1 or %* with
+ *    param. 
+ */
+int make_cmdline( char *cmdline, int size, char *command, char *param )
+{
+    char *s,*d,*p;
+    int in_quotes,in_quotep,bcount;
+    int i;
+    
+    if ((i=strlen(command)+strlen(param)-2) > size) {
+        ERR("Command too long, needed %d bytes\n", i);
+        return i;
+    }
+     
+    s=command;
+    d=cmdline;
+    p=param;
+    bcount=0;
+    in_quotes=0;
+    while (*s) {
+        if (*s=='\\') {
+            *d++=*s++;
+            bcount++;
+        } else if (*s=='"') {
+            if ((bcount & 1)==0) {
+                /* an unescaped quote */
+                in_quotes=!in_quotes;
+            }
+            *d++=*s++;
+            bcount=0;
+        } else if (s[0]=='%' && (s[1]=='*' || (s[1]>='1'))) {
+            if (in_quotes && *p=='"') {
+                /* already in a quote, so skip this quote pair */
+                in_quotep=1;
+                p++;
+            }
+            else
+                in_quotep=0;
+            while (*p) {
+                if (in_quotep && *p=='"') 
+                    break;
+                *d++=*p++;
+            }
+            s+=2;
+            bcount=0;
+        } else {
+            *d++=*s++;
+            bcount=0;
+        }
+    }
+    /* Append any remaining param */
+    if (*p) {
+        *d++=' ';
+        while (*p)
+            *d++=*p++;
+    }
+    
+    *d=0;
+    return 0;
+}
+
+
 /*************************************************************************
  * ShellExecuteEx				[SHELL32.291]
  *
@@ -1049,7 +1115,9 @@
                 size = 1023;
                 if (!RegQueryValueA(HKEY_LOCAL_MACHINE,key,buffer,&size))
                 {
-                    sprintf(cmdline,"%s \"%s\"",buffer,szApplicationName);
+                    TRACE("Using command : %s  parameter: %s\n",
+                       debugstr_a(buffer), debugstr_a(szApplicationName));
+                    make_cmdline(cmdline, 1023, buffer, szApplicationName);
                     if (CreateProcessA(NULL,cmdline,  NULL, NULL, FALSE, 0,
                                    NULL, sei->lpDirectory, &startup, &info))
                         failed = FALSE;


More information about the wine-patches mailing list