ShellExecute IE compatibility problems

Francois Gouget fgouget at
Thu Apr 8 19:03:37 CDT 2004

This patch fixes two IE compatibility problems.

The first one is a mundane issue. IE calls ShellExecuteEx with a NULL 
verb. Our implementation fails when it should use some sophisticated 
algorithm described in the MSDN to choose a default verb. Well most of 
the time we just want 'open' anyway so that's what this patch does. I've 
left it as an exercise to the reader to head over to the MSDN and 
implement the series of fallbacks we're supposed to implement.

The other one is much more interesting. One thing that was puzzling me 
is that IE makes calls like ShellExecute("\"foo.pdf\""). Notice the 
extra quotes. These extra quotes make the call fail on Wine. I checked 
that on NT and got the same result as on Wine: a failure. Yet further 
investigation showed that IE really expected this to work.

What happens is that IE first calls SHLWAPI.276, i.e. WhichPlatform(). 
If WhichPlatform() returns 2, then IE adds extra quotes, otherwise it 
doesn't. And WhichPlatform() returns 2 if shell32.dll has the
DllGetVersion() entry point.

On the NT box I used for testing I had shell32.dll 4.0 which does not 
have this entry point, and that shell32.dll happened to refuse filenames 
with the extra quotes. On an XP test machine I had shell32.dll 
which did have DllGetEntryPoint and which accepted the extra quotes.

A further check showed that on XP ShellExecute("\"notepad.exe\"") works 
just fine. So, unless we want to throw back our shell32.dll 
implementation to the stone age, we must really accept the extra quotes 
in ShellExecuteEx().

Once this patch is applied it should be possible to click on a file, 
e.g. a PDF, an have IE invoke the appropriate external application 
(assuming it is installed).


  * dlls/shell32/shlexec.c

    Francois Gouget <fgouget at>

    Fix two IE compatibility issues:
    - If the verb is NULL, use 'open'.
    - The filename may have surrounding quotes. Strip them and proceed 
as usual.

Francois Gouget
fgouget at

-------------- next part --------------
Index: dlls/shell32/shlexec.c
RCS file: /var/cvs/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.40
diff -u -r1.40 shlexec.c
--- a/dlls/shell32/shlexec.c	7 Apr 2004 03:49:51 -0000	1.40
+++ b/dlls/shell32/shlexec.c	8 Apr 2004 23:12:53 -0000
@@ -917,6 +911,7 @@
     static const WCHAR wQuote[] = {'"',0};
     static const WCHAR wSpace[] = {' ',0};
+    static const WCHAR wOpen[] = {'o','p','e','n',0};
     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};
@@ -948,10 +943,27 @@
     /* make copies of all path/command strings */
     if (sei_tmp.lpFile)
-	strcpyW(wszApplicationName, sei_tmp.lpFile);
+    {
+        int len=lstrlenW(sei_tmp.lpFile);
+        if (sei_tmp.lpFile[0]=='\"' && sei_tmp.lpFile[len-1]=='\"') {
+            lstrcpynW(wszApplicationName,sei_tmp.lpFile+1,sizeof(wszApplicationName)/sizeof(*wszApplicationName));
+            wszApplicationName[len-2]='\0';
+        } else {
+            lstrcpynW(wszApplicationName,sei_tmp.lpFile,sizeof(wszApplicationName)/sizeof(*wszApplicationName));
+        }
+    }
 	*wszApplicationName = '\0';
+    if (!sei_tmp.lpVerb)
+    {
+        /* Determining the real verb to use is much more complex than that.
+         * See the MSDN.
+         */
+        FIXME("lpVerb==NULL, using 'open'\n");
+        sei_tmp.lpVerb=wOpen;
+    }
     if (sei_tmp.lpParameters)
 	strcpyW(wszCommandline, sei_tmp.lpParameters);

More information about the wine-patches mailing list