Added patch to quote program name in ShellExecute[Ex] when it contains spaces.

This commit is contained in:
Erich E. Hoover 2015-01-19 23:39:56 -07:00
parent 2a8899bd4f
commit 69032a489b
5 changed files with 196 additions and 1 deletions

View File

@ -37,7 +37,7 @@ Wine. All those differences are also documented on the
Included bug fixes and improvements
===================================
**Bugfixes and features included in the next upcoming release [12]:**
**Bugfixes and features included in the next upcoming release [13]:**
* Add stubs for D3DXCreateAnimationController interface
* Anno 1602 installer depends on Windows 98 behavior of SHFileOperationW ([Wine Bug #37916](https://bugs.winehq.org/show_bug.cgi?id=37916))
@ -47,6 +47,7 @@ Included bug fixes and improvements
* Fix init of LONGLONG variable with a negative value in TGA decoder
* Fix wrong colors in Wolfenstein (2009) ([Wine Bug #34692](https://bugs.winehq.org/show_bug.cgi?id=34692))
* Graphical issues in Inquisitor ([Wine Bug #32490](https://bugs.winehq.org/show_bug.cgi?id=32490))
* Multiple applications start wrong executable if whitespace present in name ([Wine Bug #19666](https://bugs.winehq.org/show_bug.cgi?id=19666))
* Port Royale doesn't display ocean correctly ([Wine Bug #17913](https://bugs.winehq.org/show_bug.cgi?id=17913))
* Scrolling causes mouse and screen to lock in Call to Power II ([Wine Bug #34559](https://bugs.winehq.org/show_bug.cgi?id=34559))
* Support for DDS file format in D3DXSaveTextureToFileInMemory ([Wine Bug #26898](https://bugs.winehq.org/show_bug.cgi?id=26898))

1
debian/changelog vendored
View File

@ -4,6 +4,7 @@ wine-staging (1.7.35) UNRELEASED; urgency=low
* Automatically enable fallback method to apply patches when running from inside of a git subdirectory.
* Synchronize CSMT patchset with https://github.com/stefand/wine.
* Several improvements to make nvcuvid (CUDA video decoding) better compatible with x86_64.
* Added patch to quote program name in ShellExecute[Ex] when it contains spaces.
* Added patch to implement support for DDS file format in D3DXSaveTextureToFileInMemory.
* Added patch to avoid appending duplicate NULL character when importing keys with regedit.
* Added patch for IConnectionPoint/INetworkListManagerEvents stub interface.

View File

@ -148,6 +148,7 @@ patch_enable_all ()
enable_shell32_Default_Folder_ACLs="$1"
enable_shell32_Default_Path="$1"
enable_shell32_Icons="$1"
enable_shell32_Quoted_ShellExecute="$1"
enable_shell32_RunDLL_CallEntry16="$1"
enable_shell32_SHCreateSessionKey="$1"
enable_shell32_SHFileOperation="$1"
@ -468,6 +469,9 @@ patch_enable ()
shell32-Icons)
enable_shell32_Icons="$2"
;;
shell32-Quoted_ShellExecute)
enable_shell32_Quoted_ShellExecute="$2"
;;
shell32-RunDLL_CallEntry16)
enable_shell32_RunDLL_CallEntry16="$2"
;;
@ -2559,6 +2563,21 @@ if test "$enable_shell32_Icons" -eq 1; then
) >> "$patchlist"
fi
# Patchset shell32-Quoted_ShellExecute
# |
# | This patchset fixes the following Wine bugs:
# | * [#19666] Multiple applications start wrong executable if whitespace present in name
# |
# | Modified files:
# | * dlls/shell32/shlexec.c, dlls/shell32/tests/shlexec.c
# |
if test "$enable_shell32_Quoted_ShellExecute" -eq 1; then
patch_apply shell32-Quoted_ShellExecute/0001-shell32-Quote-program-name-in-ShellExecuteEx-if-it-c.patch
(
echo '+ { "Stefan Leichter", "shell32: Quote program name in ShellExecuteEx if it contains spaces.", 1 },';
) >> "$patchlist"
fi
# Patchset shell32-RunDLL_CallEntry16
# |
# | This patchset fixes the following Wine bugs:

View File

@ -0,0 +1,173 @@
From bed6c718ccc09100c20527dde2801c94f7776108 Mon Sep 17 00:00:00 2001
From: Stefan Leichter <Stefan.Leichter@camline.com>
Date: Mon, 5 Jan 2015 00:18:14 -0700
Subject: shell32: Quote program name in ShellExecuteEx if it contains spaces.
---
dlls/shell32/shlexec.c | 33 +++++++++++++++++++++++----------
dlls/shell32/tests/shlexec.c | 32 ++++++++++++++++++++++++++++++--
2 files changed, 53 insertions(+), 12 deletions(-)
diff --git a/dlls/shell32/shlexec.c b/dlls/shell32/shlexec.c
index 2d9690a..df0f11c 100644
--- a/dlls/shell32/shlexec.c
+++ b/dlls/shell32/shlexec.c
@@ -1558,6 +1558,7 @@ static void do_error_dialog( UINT_PTR retval, HWND hwnd )
*/
static BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
{
+ static const WCHAR wQuote[] = {'\"',0};
static const WCHAR wSpace[] = {' ',0};
static const WCHAR wWww[] = {'w','w','w',0};
static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0};
@@ -1580,6 +1581,7 @@ static BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
LPCWSTR lpFile;
UINT_PTR retval = SE_ERR_NOASSOC;
BOOL appKnownSingular = FALSE;
+ BOOL needs_quote;
/* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
sei_tmp = *sei;
@@ -1802,32 +1804,35 @@ static BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
}
else
{
- /* If the executable name is not quoted, we have to use this search loop here,
- that in CreateProcess() is not sufficient because it does not handle shell links. */
+ /* FIXME: what versions support this? Fails on 2000/XP
+ * If the executable name is not quoted, we have to use this search loop here,
+ * that in CreateProcess() is not sufficient because it does not handle shell links. */
WCHAR buffer[MAX_PATH], xlpFile[MAX_PATH];
- LPWSTR space, s;
+ LPWSTR space;
- LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/;
- for(s=beg; (space=strchrW(s, ' ')); s=space+1) {
- int idx = space-sei_tmp.lpFile;
- memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR));
+ lstrcpynW(buffer, wszApplicationName, sizeof(buffer)/sizeof(WCHAR));
+ space = buffer + strlenW(buffer);
+ do
+ {
+ int idx = space-buffer;
buffer[idx] = '\0';
/*FIXME This finds directory paths if the targeted file name contains spaces. */
if (SearchPathW(*sei_tmp.lpDirectory? sei_tmp.lpDirectory: NULL, buffer, wszExe, sizeof(xlpFile)/sizeof(xlpFile[0]), xlpFile, NULL))
{
/* separate out command from parameter string */
- LPCWSTR p = space + 1;
+ LPCWSTR p = wszApplicationName + idx;
while(isspaceW(*p))
++p;
strcpyW(wszParameters, p);
- *space = '\0';
+ wszApplicationName[idx] = '\0';
break;
}
}
+ while((space=strrchrW(buffer, ' ')));
lpFile = sei_tmp.lpFile;
}
@@ -1836,6 +1841,9 @@ static BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
wcmd = wcmdBuffer;
len = lstrlenW(wszApplicationName) + 1;
+ needs_quote = NULL != strstrW(wszApplicationName,wSpace);
+ if (needs_quote)
+ len += 2;
if (sei_tmp.lpParameters[0])
len += 1 + lstrlenW(wszParameters);
if (len > wcmdLen)
@@ -1843,7 +1851,12 @@ static BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
wcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
wcmdLen = len;
}
- strcpyW(wcmd, wszApplicationName);
+
+ wcmd[0] = 0;
+ if (needs_quote) strcatW(wcmd, wQuote);
+ strcatW(wcmd, wszApplicationName);
+ if (needs_quote) strcatW(wcmd, wQuote);
+
if (sei_tmp.lpParameters[0]) {
strcatW(wcmd, wSpace);
strcatW(wcmd, wszParameters);
diff --git a/dlls/shell32/tests/shlexec.c b/dlls/shell32/tests/shlexec.c
index f81794e..2b3947e 100644
--- a/dlls/shell32/tests/shlexec.c
+++ b/dlls/shell32/tests/shlexec.c
@@ -857,6 +857,7 @@ static const char* testfiles[]=
"%s\\masked",
"%s\\test file.sde",
"%s\\test file.exe",
+ "%s\\test file two.exe",
"%s\\test2.exe",
"%s\\simple.shlexec",
"%s\\drawback_file.noassoc",
@@ -931,7 +932,7 @@ static void test_lpFile_parsed(void)
/* existing "drawback_file.noassoc" prevents finding "drawback_file.noassoc foo.shlexec" on wine */
sprintf(fileA, "%s\\drawback_file.noassoc foo.shlexec", tmpdir);
rc=shell_execute(NULL, fileA, NULL, NULL);
- todo_wine ok(rc > 32, "%s failed: rc=%lu\n", shell_call, rc);
+ ok(rc > 32, "%s failed: rc=%lu\n", shell_call, rc);
/* if quoted, existing "drawback_file.noassoc" not prevents finding "drawback_file.noassoc foo.shlexec" on wine */
sprintf(fileA, "\"%s\\drawback_file.noassoc foo.shlexec\"", tmpdir);
@@ -1547,7 +1548,7 @@ static void test_filename(void)
"%s failed: rc=%ld err=%u\n", shell_call,
rc, GetLastError());
}
- else todo_wine
+ else
{
ok(rc==test->rc, "%s failed: rc=%ld err=%u\n", shell_call,
rc, GetLastError());
@@ -2094,6 +2095,7 @@ static void test_exes(void)
{
char filename[MAX_PATH];
char params[1024];
+ DWORD retval;
INT_PTR rc;
sprintf(params, "shlexec \"%s\" Exec", child_file);
@@ -2120,6 +2122,32 @@ static void test_exes(void)
{
win_skip("Skipping shellexecute of file with unassociated extension\n");
}
+
+ /* the directory with the test programs contain "test file.exe"
+ * and "test file two.exe". Check we do not start the first
+ * when we specify to start the second (see bug 19666)
+ */
+ sprintf(filename, "%s\\test file.exe", tmpdir);
+ retval = CopyFileA(argv0, filename, FALSE);
+ ok(retval, "CopyFile(\"%s\",\"%s\",FALSE) failed\n", argv0, filename);
+ sprintf(filename, "%s\\test file two.exe", tmpdir);
+ retval = CopyFileA(argv0, filename, FALSE);
+ ok(retval, "CopyFile(\"%s\",\"%s\",FALSE) failed\n", argv0, filename);
+ rc=shell_execute_ex(SEE_MASK_NOZONECHECKS, NULL, filename, params, NULL, NULL);
+ ok(rc > 32, "%s returned %lu\n", shell_call, rc);
+ okChildInt("argcA", 4);
+ okChildString("argvA0", filename);
+ okChildString("argvA3", "Exec");
+
+ /* check quoted filename */
+ sprintf(filename, "\"%s\\test file two.exe\"", tmpdir);
+ rc=shell_execute_ex(SEE_MASK_NOZONECHECKS, NULL, filename, params, NULL, NULL);
+ ok(rc > 32, "%s returned %lu\n", shell_call, rc);
+ okChildInt("argcA", 4);
+ /* strip the quotes for the compare */
+ sprintf(filename, "%s\\test file two.exe", tmpdir);
+ okChildString("argvA0", filename);
+ okChildString("argvA3", "Exec");
}
typedef struct
--
1.9.1

View File

@ -0,0 +1 @@
Fixes: [19666] Multiple applications start wrong executable if whitespace present in name