From 69032a489b70511259eec8afd8327c6c0a9bd69a Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Mon, 19 Jan 2015 23:39:56 -0700 Subject: [PATCH] Added patch to quote program name in ShellExecute[Ex] when it contains spaces. --- README.md | 3 +- debian/changelog | 1 + patches/patchinstall.sh | 19 ++ ...ogram-name-in-ShellExecuteEx-if-it-c.patch | 173 ++++++++++++++++++ .../shell32-Quoted_ShellExecute/definition | 1 + 5 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 patches/shell32-Quoted_ShellExecute/0001-shell32-Quote-program-name-in-ShellExecuteEx-if-it-c.patch create mode 100644 patches/shell32-Quoted_ShellExecute/definition diff --git a/README.md b/README.md index 9ff747ac..5824a909 100644 --- a/README.md +++ b/README.md @@ -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)) diff --git a/debian/changelog b/debian/changelog index 02a4f16d..8a94f851 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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. diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index c0008253..90b03682 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -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: diff --git a/patches/shell32-Quoted_ShellExecute/0001-shell32-Quote-program-name-in-ShellExecuteEx-if-it-c.patch b/patches/shell32-Quoted_ShellExecute/0001-shell32-Quote-program-name-in-ShellExecuteEx-if-it-c.patch new file mode 100644 index 00000000..8378b371 --- /dev/null +++ b/patches/shell32-Quoted_ShellExecute/0001-shell32-Quote-program-name-in-ShellExecuteEx-if-it-c.patch @@ -0,0 +1,173 @@ +From bed6c718ccc09100c20527dde2801c94f7776108 Mon Sep 17 00:00:00 2001 +From: Stefan Leichter +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 + diff --git a/patches/shell32-Quoted_ShellExecute/definition b/patches/shell32-Quoted_ShellExecute/definition new file mode 100644 index 00000000..b01dc013 --- /dev/null +++ b/patches/shell32-Quoted_ShellExecute/definition @@ -0,0 +1 @@ +Fixes: [19666] Multiple applications start wrong executable if whitespace present in name