diff --git a/dll/win32/shell32/shlexec.cpp b/dll/win32/shell32/shlexec.cpp index 292c8db8292..ed66c540efd 100644 --- a/dll/win32/shell32/shlexec.cpp +++ b/dll/win32/shell32/shlexec.cpp @@ -2124,6 +2124,39 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc) *end = L'\0'; lpFile = wfileName; } + /* We have to test sei instead of sei_tmp because sei_tmp had its + * input fMask modifed above in SHELL_translate_idlist. + * This code is needed to handle the case where we only have an + * lpIDList with multiple CLSID/PIDL's (not 'My Computer' only) */ + else if ((sei->fMask & SEE_MASK_IDLIST) == SEE_MASK_IDLIST) + { + WCHAR buffer[MAX_PATH], xlpFile[MAX_PATH]; + LPWSTR space, s; + + LPWSTR beg = wszApplicationName; + for(s = beg; (space = const_cast(strchrW(s, L' '))); s = space + 1) + { + int idx = space - sei_tmp.lpFile; + memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR)); + buffer[idx] = '\0'; + + if (SearchPathW(*sei_tmp.lpDirectory ? sei_tmp.lpDirectory : NULL, + buffer, L".exe", _countof(xlpFile), xlpFile, NULL)) + { + /* separate out command from parameter string */ + LPCWSTR p = space + 1; + + while(isspaceW(*p)) + ++p; + + strcpyW(wszParameters, p); + *space = L'\0'; + + break; + } + } + lpFile = sei_tmp.lpFile; + } else { lpFile = sei_tmp.lpFile; diff --git a/modules/rostests/apitests/shell32/ShellExecuteEx.cpp b/modules/rostests/apitests/shell32/ShellExecuteEx.cpp index d239467d859..28be800183e 100644 --- a/modules/rostests/apitests/shell32/ShellExecuteEx.cpp +++ b/modules/rostests/apitests/shell32/ShellExecuteEx.cpp @@ -467,6 +467,48 @@ static void test_properties() ok_ptr(info.hInstApp, (HINSTANCE)2); } +static void test_sei_lpIDList() +{ + /* This tests ShellExecuteEx with lpIDList for explorer C:\ */ + + /* ITEMIDLIST for CLSID of 'My Computer' followed by PIDL for 'C:\' */ + BYTE lpitemidlist[30] = { 0x14, 0, 0x1f, 0, 0xe0, 0x4f, 0xd0, 0x20, 0xea, + 0x3a, 0x69, 0x10, 0xa2, 0xd8, 0x08, 0, 0x2b, 0x30, 0x30, 0x9d, // My Computer + 0x8, 0, 0x23, 0x43, 0x3a, 0x5c, 0x5c, 0, 0, 0,}; // C:\\ + NUL-NUL ending + BYTE *lpBytes; + lpBytes = lpitemidlist; + + SHELLEXECUTEINFOW ShellExecInfo; + BOOL Result; + STARTUPINFOW si; + PROCESS_INFORMATION pi; + HWND hWnd; + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + ZeroMemory(&ShellExecInfo, sizeof(ShellExecInfo)); + ShellExecInfo.cbSize = sizeof(ShellExecInfo); + ShellExecInfo.fMask = SEE_MASK_IDLIST; + ShellExecInfo.hwnd = NULL; + ShellExecInfo.nShow = SW_SHOWNORMAL; + ShellExecInfo.lpFile = NULL; + ShellExecInfo.lpDirectory = NULL; + ShellExecInfo.lpIDList = lpBytes; + + Result = ShellExecuteExW(&ShellExecInfo); + ok(Result == TRUE, "ShellExecuteEx lpIDList 'C:\\' failed.\n"); + trace("sei_lpIDList returned: %s.\n", Result ? "SUCCESS" : "FAILURE"); + if (Result) + { + Sleep(700); + // Terminate Window + hWnd = FindWindowW(L"CabinetWClass", L"Local Disk (C:)"); + PostMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0); + } +} + START_TEST(ShellExecuteEx) { DoAppPathTest(); @@ -475,4 +517,7 @@ START_TEST(ShellExecuteEx) DoWaitForWindow(CLASSNAME, CLASSNAME, TRUE, TRUE); Sleep(100); + + test_sei_lpIDList(); + }