diff --git a/dlls/wshom.ocx/shell.c b/dlls/wshom.ocx/shell.c index 1aa353a17a3..ca4f7ff8996 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, ¶ms))) 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 18ff4d62281..c1f9519ff8c 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);