Francois Gouget : shell32: Fix ShellExecute()'s handling of file URLs.

Alexandre Julliard julliard at winehq.org
Wed Oct 10 15:07:51 CDT 2012


Module: wine
Branch: master
Commit: 53e4ddc399cef1f044fb25bdb19a478ced6178d7
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=53e4ddc399cef1f044fb25bdb19a478ced6178d7

Author: Francois Gouget <fgouget at codeweavers.com>
Date:   Wed Oct 10 00:54:07 2012 +0200

shell32: Fix ShellExecute()'s handling of file URLs.

---

 dlls/shell32/shlexec.c       |   46 +++++++++++++++++++++++++----------------
 dlls/shell32/tests/shlexec.c |   46 ++++++++++++++++++++++-------------------
 2 files changed, 53 insertions(+), 39 deletions(-)

diff --git a/dlls/shell32/shlexec.c b/dlls/shell32/shlexec.c
index a714fe8..5799ab0 100644
--- a/dlls/shell32/shlexec.c
+++ b/dlls/shell32/shlexec.c
@@ -1504,7 +1504,7 @@ static UINT_PTR SHELL_quote_and_execute( LPCWSTR wcmd, LPCWSTR wszParameters, LP
     return retval;
 }
 
-static UINT_PTR SHELL_execute_url( LPCWSTR lpFile, LPCWSTR wFile, LPCWSTR wcmd, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc )
+static UINT_PTR SHELL_execute_url( LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc )
 {
     static const WCHAR wShell[] = {'\\','s','h','e','l','l','\\',0};
     static const WCHAR wCommand[] = {'\\','c','o','m','m','a','n','d',0};
@@ -1534,13 +1534,6 @@ static UINT_PTR SHELL_execute_url( LPCWSTR lpFile, LPCWSTR wFile, LPCWSTR wcmd,
     strcatW(lpstrProtocol, psei->lpVerb && *psei->lpVerb ? psei->lpVerb: wszOpen);
     strcatW(lpstrProtocol, wCommand);
 
-    /* Remove File Protocol from lpFile */
-    /* In the case file://path/file     */
-    if (!strncmpiW(lpFile, wFile, iSize))
-    {
-        lpFile += iSize;
-        while (*lpFile == ':') lpFile++;
-    }
     retval = execute_from_key(lpstrProtocol, lpFile, NULL, psei->lpParameters,
                               wcmd, execfunc, psei, psei_out);
     HeapFree(GetProcessHeap(), 0, lpstrProtocol);
@@ -1567,7 +1560,6 @@ static BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
 {
     static const WCHAR wSpace[] = {' ',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};
     static const DWORD unsupportedFlags =
         SEE_MASK_INVOKEIDLIST  | SEE_MASK_ICON         | SEE_MASK_HOTKEY |
@@ -1724,21 +1716,39 @@ static BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
                                                    dwApplicationNameLen );
     }
 
-    /* expand environment strings */
-    len = ExpandEnvironmentStringsW(sei_tmp.lpFile, NULL, 0);
-    if (len>0)
+    /* convert file URLs */
+    if (UrlIsFileUrlW(sei_tmp.lpFile))
     {
         LPWSTR buf;
-        buf = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
+        DWORD size;
+
+        size = MAX_PATH;
+        buf = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
+        if (FAILED(PathCreateFromUrlW(sei_tmp.lpFile, buf, &size, 0)))
+            return SE_ERR_OOM;
 
-        ExpandEnvironmentStringsW(sei_tmp.lpFile, buf, len+1);
         HeapFree(GetProcessHeap(), 0, wszApplicationName);
-        dwApplicationNameLen = len+1;
+        dwApplicationNameLen = lstrlenW(buf) + 1;
         wszApplicationName = buf;
-        /* appKnownSingular unmodified */
-
         sei_tmp.lpFile = wszApplicationName;
     }
+    else /* or expand environment strings (not both!) */
+    {
+        len = ExpandEnvironmentStringsW(sei_tmp.lpFile, NULL, 0);
+        if (len>0)
+        {
+            LPWSTR buf;
+            buf = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
+
+            ExpandEnvironmentStringsW(sei_tmp.lpFile, buf, len + 1);
+            HeapFree(GetProcessHeap(), 0, wszApplicationName);
+            dwApplicationNameLen = len + 1;
+            wszApplicationName = buf;
+            /* appKnownSingular unmodified */
+
+            sei_tmp.lpFile = wszApplicationName;
+        }
+    }
 
     if (*sei_tmp.lpDirectory)
     {
@@ -1889,7 +1899,7 @@ static BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
     }
     else if (PathIsURLW(lpFile))    /* File not found, check for URL */
     {
-        retval = SHELL_execute_url( lpFile, wFile, wcmd, &sei_tmp, sei, execfunc );
+        retval = SHELL_execute_url( lpFile, wcmd, &sei_tmp, sei, execfunc );
     }
     /* Check if file specified is in the form www.??????.*** */
     else if (!strncmpiW(lpFile, wWww, 3))
diff --git a/dlls/shell32/tests/shlexec.c b/dlls/shell32/tests/shlexec.c
index 8d164a6..e3d5676 100644
--- a/dlls/shell32/tests/shlexec.c
+++ b/dlls/shell32/tests/shlexec.c
@@ -1637,34 +1637,37 @@ typedef struct
 static fileurl_tests_t fileurl_tests[]=
 {
     /* How many slashes does it take... */
-    {"file:", "%s\\test file.shlexec", URL_SUCCESS, 0x1},
-    {"file:/", "%s\\test file.shlexec", URL_SUCCESS, 0x1},
-    {"file://", "%s\\test file.shlexec", URL_SUCCESS, 0x1},
-    {"file:///", "%s\\test file.shlexec", URL_SUCCESS, 0x1},
-    {"File:///", "%s\\test file.shlexec", URL_SUCCESS, 0x1},
-    {"file:////", "%s\\test file.shlexec", URL_SUCCESS, 0x1},
-    {"file://///", "%s\\test file.shlexec", 0, 0x1},
+    {"file:", "%s\\test file.shlexec", URL_SUCCESS, 0},
+    {"file:/", "%s\\test file.shlexec", URL_SUCCESS, 0},
+    {"file://", "%s\\test file.shlexec", URL_SUCCESS, 0},
+    {"file:///", "%s\\test file.shlexec", URL_SUCCESS, 0},
+    {"File:///", "%s\\test file.shlexec", URL_SUCCESS, 0},
+    {"file:////", "%s\\test file.shlexec", URL_SUCCESS, 0},
+    {"file://///", "%s\\test file.shlexec", 0, 0},
 
     /* Test with Windows-style paths */
-    {"file:///", "%s\\test file.shlexec", URL_SUCCESS | USE_COLON, 0x1},
-    {"file:///", "%s\\test file.shlexec", URL_SUCCESS | USE_BSLASH, 0x1},
+    {"file:///", "%s\\test file.shlexec", URL_SUCCESS | USE_COLON, 0},
+    {"file:///", "%s\\test file.shlexec", URL_SUCCESS | USE_BSLASH, 0},
 
     /* Check handling of hostnames */
-    {"file://localhost/", "%s\\test file.shlexec", URL_SUCCESS, 0x1},
-    {"file://localhost:80/", "%s\\test file.shlexec", 0, 0x1},
-    {"file://LocalHost/", "%s\\test file.shlexec", URL_SUCCESS, 0x1},
-    {"file://127.0.0.1/", "%s\\test file.shlexec", 0, 0x1},
-    {"file://::1/", "%s\\test file.shlexec", 0, 0x1},
-    {"file://notahost/", "%s\\test file.shlexec", 0, 0x1},
+    {"file://localhost/", "%s\\test file.shlexec", URL_SUCCESS, 0},
+    {"file://localhost:80/", "%s\\test file.shlexec", 0, 0},
+    {"file://LocalHost/", "%s\\test file.shlexec", URL_SUCCESS, 0},
+    {"file://127.0.0.1/", "%s\\test file.shlexec", 0, 0},
+    {"file://::1/", "%s\\test file.shlexec", 0, 0},
+    {"file://notahost/", "%s\\test file.shlexec", 0, 0},
 
     /* Environment variables are not expanded in URLs */
     {"%urlprefix%", "%s\\test file.shlexec", 0, 0x1},
-    {"file:///", "%s\\%%urlenvvar%% file.shlexec", 0, 0x1},
+    {"file:///", "%%TMPDIR%%\\test file.shlexec", 0, 0},
+
+    /* Test shortcuts vs. URLs */
+    {"file://///", "%s\\test_shortcut_shlexec.lnk", 0, 0x1d},
 
     {NULL, NULL, 0, 0}
 };
 
-static void test_fileurl(void)
+static void test_fileurls(void)
 {
     char filename[MAX_PATH], fileurl[MAX_PATH], longtmpdir[MAX_PATH];
     char command[MAX_PATH];
@@ -1681,7 +1684,6 @@ static void test_fileurl(void)
 
     get_long_path_name(tmpdir, longtmpdir, sizeof(longtmpdir)/sizeof(*longtmpdir));
     SetEnvironmentVariable("urlprefix", "file:///");
-    SetEnvironmentVariable("urlenvvar", "test");
 
     test=fileurl_tests;
     while (test->basename)
@@ -1705,7 +1707,10 @@ static void test_fileurl(void)
         ok(rc == SE_ERR_FNF, "FindExecutable(%s) failed: bad rc=%lu\n", fileurl, rc);
 
         /* Then ShellExecute() */
-        rc = shell_execute(NULL, fileurl, NULL, NULL);
+        if ((test->todo & 0x10) == 0)
+            rc = shell_execute(NULL, fileurl, NULL, NULL);
+        else todo_wait
+            rc = shell_execute(NULL, fileurl, NULL, NULL);
         if (bad_shellexecute)
         {
             win_skip("shell32 is too old (likely 4.72). Skipping the file URL tests\n");
@@ -1750,7 +1755,6 @@ static void test_fileurl(void)
     }
 
     SetEnvironmentVariable("urlprefix", NULL);
-    SetEnvironmentVariable("urlenvvar", NULL);
 }
 
 static void test_find_executable(void)
@@ -2639,7 +2643,7 @@ START_TEST(shlexec)
     test_argify();
     test_lpFile_parsed();
     test_filename();
-    test_fileurl();
+    test_fileurls();
     test_find_executable();
     test_lnks();
     test_exes();




More information about the wine-cvs mailing list