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;
}
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))

View File

@ -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();