shell32: Fix ShellExecute()'s handling of file URLs.
This commit is contained in:
parent
eee9b8ee12
commit
53e4ddc399
|
@ -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))
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue