[PATCH] wshom: Split the command line before passing it to ShellExecuteEx.

Hans Leidekker hans at codeweavers.com
Fri Nov 2 05:34:59 CDT 2018


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/wshom.ocx/shell.c       | 34 ++++++++++++++++++++++++--
 dlls/wshom.ocx/tests/wshom.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/dlls/wshom.ocx/shell.c b/dlls/wshom.ocx/shell.c
index 1aa353a17a..ca4f7ff899 100644
--- a/dlls/wshom.ocx/shell.c
+++ b/dlls/wshom.ocx/shell.c
@@ -1218,12 +1218,37 @@ static inline BOOL is_optional_argument(const VARIANT *arg)
     return V_VT(arg) == VT_ERROR && V_ERROR(arg) == DISP_E_PARAMNOTFOUND;
 }
 
+static WCHAR *split_command( BSTR cmd, WCHAR **params )
+{
+    WCHAR *ret, *ptr;
+    BOOL in_quotes = FALSE;
+
+    if (!(ret = heap_alloc((strlenW(cmd) + 1) * sizeof(WCHAR)))) return NULL;
+    strcpyW( ret, cmd );
+
+    *params = NULL;
+    for (ptr = ret; *ptr; ptr++)
+    {
+        if (*ptr == '"') in_quotes = !in_quotes;
+        else if (*ptr == ' ' && !in_quotes)
+        {
+            *ptr = 0;
+            *params = ptr + 1;
+            break;
+        }
+    }
+
+    return ret;
+}
+
 static HRESULT WINAPI WshShell3_Run(IWshShell3 *iface, BSTR cmd, VARIANT *style, VARIANT *wait, DWORD *exit_code)
 {
     SHELLEXECUTEINFOW info;
     int waitforprocess;
+    WCHAR *file, *params;
     VARIANT s;
     HRESULT hr;
+    BOOL ret;
 
     TRACE("(%s %s %s %p)\n", debugstr_w(cmd), debugstr_variant(style), debugstr_variant(wait), exit_code);
 
@@ -1251,13 +1276,18 @@ static HRESULT WINAPI WshShell3_Run(IWshShell3 *iface, BSTR cmd, VARIANT *style,
         waitforprocess = V_I4(&w);
     }
 
+    if (!(file = split_command(cmd, &params))) return E_OUTOFMEMORY;
+
     memset(&info, 0, sizeof(info));
     info.cbSize = sizeof(info);
     info.fMask = waitforprocess ? SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS : SEE_MASK_DEFAULT;
-    info.lpFile = cmd;
+    info.lpFile = file;
+    info.lpParameters = params;
     info.nShow = V_I4(&s);
 
-    if (!ShellExecuteExW(&info))
+    ret = ShellExecuteExW(&info);
+    heap_free( file );
+    if (!ret)
     {
         TRACE("ShellExecute failed, %d\n", GetLastError());
         return HRESULT_FROM_WIN32(GetLastError());
diff --git a/dlls/wshom.ocx/tests/wshom.c b/dlls/wshom.ocx/tests/wshom.c
index 18ff4d6228..c1f9519ff8 100644
--- a/dlls/wshom.ocx/tests/wshom.c
+++ b/dlls/wshom.ocx/tests/wshom.c
@@ -66,6 +66,17 @@ static void test_wshshell(void)
     static const WCHAR path2W[] = {'P','A','T','H',0};
     static const WCHAR dummydirW[] = {'d','e','a','d','p','a','r','r','o','t',0};
     static const WCHAR emptyW[] = {'e','m','p','t','y',0};
+    static const WCHAR cmdexeW[] = {'\\','c','m','d','.','e','x','e',0};
+    static const WCHAR testdirW[] = {'w','s','h','o','m',' ','t','e','s','t',' ','d','i','r',0};
+    static const WCHAR paramsW[] =
+        {' ','/','c',' ','r','d',' ','/','s',' ','/','q',' ','c',':','\\','n','o','s','u','c','h','d','i','r',0};
+    static const WCHAR cmdW[] =
+        {'c','m','d','.','e','x','e',' ','/','c',' ','r','d',' ','/','s',' ','/','q',' ','c',':','\\',
+         'n','o','s','u','c','h','d','i','r',0};
+    static const WCHAR cmd2W[] =
+        {'"','c','m','d','.','e','x','e',' ','"',' ','/','c',' ','r','d',' ','/','s',' ','/','q',' ','c',':','\\',
+         'n','o','s','u','c','h','d','i','r',0};
+    WCHAR path[MAX_PATH], path2[MAX_PATH], buf[MAX_PATH];
     IWshEnvironment *env;
     IWshExec *shexec;
     IWshShell3 *sh3;
@@ -82,7 +93,7 @@ static void test_wshshell(void)
     EXCEPINFO ei;
     VARIANT arg, res, arg2;
     BSTR str, ret;
-    DWORD retval;
+    DWORD retval, attrs;
     UINT err;
 
     hr = CoCreateInstance(&CLSID_WshShell, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
@@ -238,9 +249,53 @@ static void test_wshshell(void)
     hr = IWshShell3_Run(sh3, str, &arg, &arg2, &retval);
     ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
     ok(retval == 10, "got %u\n", retval);
+    SysFreeString(str);
+
+    V_VT(&arg2) = VT_BOOL;
+    V_BOOL(&arg2) = VARIANT_TRUE;
 
+    retval = 0xdeadbeef;
+    str = SysAllocString(cmdW);
+    hr = IWshShell3_Run(sh3, str, &arg, &arg2, &retval);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    todo_wine ok(retval == ERROR_FILE_NOT_FOUND, "got %u\n", retval);
     SysFreeString(str);
 
+    retval = 0xdeadbeef;
+    str = SysAllocString(cmd2W);
+    hr = IWshShell3_Run(sh3, str, &arg, &arg2, &retval);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    todo_wine ok(retval == ERROR_FILE_NOT_FOUND, "got %u\n", retval);
+    SysFreeString(str);
+
+    GetSystemDirectoryW(path, ARRAY_SIZE(path));
+    lstrcatW(path, cmdexeW);
+    attrs = GetFileAttributesW(path);
+    ok(attrs != INVALID_FILE_ATTRIBUTES, "cmd.exe not found\n");
+
+    /* copy cmd.exe to a path with spaces */
+    GetTempPathW(ARRAY_SIZE(path2), path2);
+    lstrcatW(path2, testdirW);
+    CreateDirectoryW(path2, NULL);
+    lstrcatW(path2, cmdexeW);
+    CopyFileW(path, path2, FALSE);
+
+    buf[0] = '"';
+    lstrcpyW(buf + 1, path2);
+    buf[lstrlenW(buf)] = '"';
+    lstrcpyW(buf + lstrlenW(path2) + 2, paramsW);
+
+    retval = 0xdeadbeef;
+    str = SysAllocString(buf);
+    hr = IWshShell3_Run(sh3, str, &arg, &arg2, &retval);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    todo_wine ok(retval == ERROR_FILE_NOT_FOUND, "got %u\n", retval);
+    SysFreeString(str);
+
+    DeleteFileW(path2);
+    path2[lstrlenW(path2) - lstrlenW(cmdexeW)] = 0;
+    RemoveDirectoryW(path2);
+
     /* current directory */
     if (0) /* crashes on native */
         hr = IWshShell3_get_CurrentDirectory(sh3, NULL);
-- 
2.11.0




More information about the wine-devel mailing list