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

This commit is contained in:
Francois Gouget 2012-10-10 00:54:07 +02:00 committed by Alexandre Julliard
parent eee9b8ee12
commit 53e4ddc399
2 changed files with 53 additions and 39 deletions

View File

@ -1504,7 +1504,7 @@ static UINT_PTR SHELL_quote_and_execute( LPCWSTR wcmd, LPCWSTR wszParameters, LP
return retval; 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 wShell[] = {'\\','s','h','e','l','l','\\',0};
static const WCHAR wCommand[] = {'\\','c','o','m','m','a','n','d',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, psei->lpVerb && *psei->lpVerb ? psei->lpVerb: wszOpen);
strcatW(lpstrProtocol, wCommand); 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, retval = execute_from_key(lpstrProtocol, lpFile, NULL, psei->lpParameters,
wcmd, execfunc, psei, psei_out); wcmd, execfunc, psei, psei_out);
HeapFree(GetProcessHeap(), 0, lpstrProtocol); 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 wSpace[] = {' ',0};
static const WCHAR wWww[] = {'w','w','w',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 WCHAR wHttp[] = {'h','t','t','p',':','/','/',0};
static const DWORD unsupportedFlags = static const DWORD unsupportedFlags =
SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY | SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY |
@ -1724,21 +1716,39 @@ static BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
dwApplicationNameLen ); dwApplicationNameLen );
} }
/* expand environment strings */ /* convert file URLs */
len = ExpandEnvironmentStringsW(sei_tmp.lpFile, NULL, 0); if (UrlIsFileUrlW(sei_tmp.lpFile))
if (len>0)
{ {
LPWSTR buf; 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); HeapFree(GetProcessHeap(), 0, wszApplicationName);
dwApplicationNameLen = len+1; dwApplicationNameLen = lstrlenW(buf) + 1;
wszApplicationName = buf; wszApplicationName = buf;
/* appKnownSingular unmodified */
sei_tmp.lpFile = wszApplicationName; 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) 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 */ 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.??????.*** */ /* Check if file specified is in the form www.??????.*** */
else if (!strncmpiW(lpFile, wWww, 3)) else if (!strncmpiW(lpFile, wWww, 3))

View File

@ -1637,34 +1637,37 @@ typedef struct
static fileurl_tests_t fileurl_tests[]= static fileurl_tests_t fileurl_tests[]=
{ {
/* How many slashes does it take... */ /* How many slashes does it take... */
{"file:", "%s\\test file.shlexec", URL_SUCCESS, 0x1}, {"file:", "%s\\test file.shlexec", URL_SUCCESS, 0},
{"file:/", "%s\\test file.shlexec", URL_SUCCESS, 0x1}, {"file:/", "%s\\test file.shlexec", URL_SUCCESS, 0},
{"file://", "%s\\test file.shlexec", URL_SUCCESS, 0x1}, {"file://", "%s\\test file.shlexec", URL_SUCCESS, 0},
{"file:///", "%s\\test file.shlexec", URL_SUCCESS, 0x1}, {"file:///", "%s\\test file.shlexec", URL_SUCCESS, 0},
{"File:///", "%s\\test file.shlexec", URL_SUCCESS, 0x1}, {"File:///", "%s\\test file.shlexec", URL_SUCCESS, 0},
{"file:////", "%s\\test file.shlexec", URL_SUCCESS, 0x1}, {"file:////", "%s\\test file.shlexec", URL_SUCCESS, 0},
{"file://///", "%s\\test file.shlexec", 0, 0x1}, {"file://///", "%s\\test file.shlexec", 0, 0},
/* Test with Windows-style paths */ /* Test with Windows-style paths */
{"file:///", "%s\\test file.shlexec", URL_SUCCESS | USE_COLON, 0x1}, {"file:///", "%s\\test file.shlexec", URL_SUCCESS | USE_COLON, 0},
{"file:///", "%s\\test file.shlexec", URL_SUCCESS | USE_BSLASH, 0x1}, {"file:///", "%s\\test file.shlexec", URL_SUCCESS | USE_BSLASH, 0},
/* Check handling of hostnames */ /* Check handling of hostnames */
{"file://localhost/", "%s\\test file.shlexec", URL_SUCCESS, 0x1}, {"file://localhost/", "%s\\test file.shlexec", URL_SUCCESS, 0},
{"file://localhost:80/", "%s\\test file.shlexec", 0, 0x1}, {"file://localhost:80/", "%s\\test file.shlexec", 0, 0},
{"file://LocalHost/", "%s\\test file.shlexec", URL_SUCCESS, 0x1}, {"file://LocalHost/", "%s\\test file.shlexec", URL_SUCCESS, 0},
{"file://127.0.0.1/", "%s\\test file.shlexec", 0, 0x1}, {"file://127.0.0.1/", "%s\\test file.shlexec", 0, 0},
{"file://::1/", "%s\\test file.shlexec", 0, 0x1}, {"file://::1/", "%s\\test file.shlexec", 0, 0},
{"file://notahost/", "%s\\test file.shlexec", 0, 0x1}, {"file://notahost/", "%s\\test file.shlexec", 0, 0},
/* Environment variables are not expanded in URLs */ /* Environment variables are not expanded in URLs */
{"%urlprefix%", "%s\\test file.shlexec", 0, 0x1}, {"%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} {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 filename[MAX_PATH], fileurl[MAX_PATH], longtmpdir[MAX_PATH];
char command[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)); get_long_path_name(tmpdir, longtmpdir, sizeof(longtmpdir)/sizeof(*longtmpdir));
SetEnvironmentVariable("urlprefix", "file:///"); SetEnvironmentVariable("urlprefix", "file:///");
SetEnvironmentVariable("urlenvvar", "test");
test=fileurl_tests; test=fileurl_tests;
while (test->basename) 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); ok(rc == SE_ERR_FNF, "FindExecutable(%s) failed: bad rc=%lu\n", fileurl, rc);
/* Then ShellExecute() */ /* 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) if (bad_shellexecute)
{ {
win_skip("shell32 is too old (likely 4.72). Skipping the file URL tests\n"); 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("urlprefix", NULL);
SetEnvironmentVariable("urlenvvar", NULL);
} }
static void test_find_executable(void) static void test_find_executable(void)
@ -2639,7 +2643,7 @@ START_TEST(shlexec)
test_argify(); test_argify();
test_lpFile_parsed(); test_lpFile_parsed();
test_filename(); test_filename();
test_fileurl(); test_fileurls();
test_find_executable(); test_find_executable();
test_lnks(); test_lnks();
test_exes(); test_exes();