+
+/*************************************************************************/
+
+static LPCWSTR
+SplitParams(LPCWSTR psz, LPWSTR pszArg0, size_t cchArg0)
+{
+ LPCWSTR pch;
+ size_t ich = 0;
+ if (*psz == L'"')
+ {
+ // 1st argument is quoted. the string in quotes is quoted 1st argument.
+ // [pch] --> [pszArg0+ich]
+ for (pch = psz + 1; *pch && ich + 1 < cchArg0; ++ich, ++pch)
+ {
+ if (*pch == L'"' && pch[1] == L'"')
+ {
+ // doubled double quotations found!
+ pszArg0[ich] = L'"';
+ }
+ else if (*pch == L'"')
+ {
+ // single double quotation found!
+ ++pch;
+ break;
+ }
+ else
+ {
+ // otherwise
+ pszArg0[ich] = *pch;
+ }
+ }
+ }
+ else
+ {
+ // 1st argument is unquoted. non-space sequence is 1st argument.
+ // [pch] --> [pszArg0+ich]
+ for (pch = psz; *pch && !iswspace(*pch) && ich + 1 < cchArg0; ++ich, ++pch)
+ {
+ pszArg0[ich] = *pch;
+ }
+ }
+ pszArg0[ich] = 0;
+
+ // skip space
+ while (iswspace(*pch))
+ ++pch;
+
+ return pch;
+}
+
+HRESULT WINAPI ShellExecCmdLine(
+ HWND hwnd,
+ LPCWSTR pwszCommand,
+ LPCWSTR pwszStartDir,
+ int nShow,
+ LPVOID pUnused,
+ DWORD dwSeclFlags)
+{
+ SHELLEXECUTEINFOW info;
+ DWORD dwSize, dwError, dwType, dwFlags = SEE_MASK_DOENVSUBST | SEE_MASK_NOASYNC;
+ LPCWSTR pszVerb = NULL;
+ WCHAR szFile[MAX_PATH], szFile2[MAX_PATH];
+ HRESULT hr;
+ LPCWSTR pchParams;
+ LPWSTR lpCommand = NULL;
+
+ if (pwszCommand == NULL)
+ RaiseException(EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE,
+ 1, (ULONG_PTR*)pwszCommand);
+
+ __SHCloneStrW(&lpCommand, pwszCommand);
+ StrTrimW(lpCommand, L" \t");
+
+ if (dwSeclFlags & SECL_NO_UI)
+ dwFlags |= SEE_MASK_FLAG_NO_UI;
+ if (dwSeclFlags & SECL_LOG_USAGE)
+ dwFlags |= SEE_MASK_FLAG_LOG_USAGE;
+ if (dwSeclFlags & SECL_USE_IDLIST)
+ dwFlags |= SEE_MASK_INVOKEIDLIST;
+
+ if (dwSeclFlags & SECL_RUNAS)
+ {
+ dwSize = 0;
+ hr = AssocQueryStringW(0, ASSOCSTR_COMMAND, lpCommand, L"RunAs", NULL, &dwSize);
+ if (SUCCEEDED(hr) && dwSize != 0)
+ {
+ pszVerb = L"runas";
+ }
+ }
+
+ if (UrlIsFileUrlW(lpCommand))
+ {
+ StringCchCopyW(szFile, _countof(szFile), lpCommand);
+ pchParams = NULL;
+ }
+ else
+ {
+ pchParams = SplitParams(lpCommand, szFile, _countof(szFile));
+ if (SearchPathW(NULL, szFile, NULL, _countof(szFile2), szFile2, NULL) ||
+ SearchPathW(NULL, szFile, wszExe, _countof(szFile2), szFile2, NULL) ||
+ SearchPathW(NULL, szFile, wszCom, _countof(szFile2), szFile2, NULL) ||
+ SearchPathW(pwszStartDir, szFile, NULL, _countof(szFile2), szFile2, NULL) ||
+ SearchPathW(pwszStartDir, szFile, wszExe, _countof(szFile2), szFile2, NULL) ||
+ SearchPathW(pwszStartDir, szFile, wszCom, _countof(szFile2), szFile2, NULL))
+ {
+ StringCchCopyW(szFile, _countof(szFile), szFile2);
+ pchParams = NULL;
+ }
+ else if (SearchPathW(NULL, lpCommand, NULL, _countof(szFile2), szFile2, NULL) ||
+ SearchPathW(NULL, lpCommand, wszExe, _countof(szFile2), szFile2, NULL) ||
+ SearchPathW(NULL, lpCommand, wszCom, _countof(szFile2), szFile2, NULL) ||
+ SearchPathW(pwszStartDir, lpCommand, NULL, _countof(szFile2), szFile2, NULL) ||
+ SearchPathW(pwszStartDir, lpCommand, wszExe, _countof(szFile2), szFile2, NULL) ||
+ SearchPathW(pwszStartDir, lpCommand, wszCom, _countof(szFile2), szFile2, NULL))
+ {
+ StringCchCopyW(szFile, _countof(szFile), szFile2);
+ pchParams = NULL;
+ }
+
+ if (!(dwSeclFlags & SECL_ALLOW_NONEXE))
+ {
+ if (!GetBinaryTypeW(szFile, &dwType))
+ {
+ SHFree(lpCommand);
+
+ if (!(dwSeclFlags & SECL_NO_UI))
+ {
+ WCHAR szText[128 + MAX_PATH], szFormat[128];
+ LoadStringW(shell32_hInstance, IDS_FILE_NOT_FOUND, szFormat, _countof(szFormat));
+ StringCchPrintfW(szText, _countof(szText), szFormat, szFile);
+ MessageBoxW(hwnd, szText, NULL, MB_ICONERROR);
+ }
+ return CO_E_APPNOTFOUND;
+ }
+ }
+ else
+ {
+ if (GetFileAttributesW(szFile) == INVALID_FILE_ATTRIBUTES)
+ {
+ SHFree(lpCommand);
+
+ if (!(dwSeclFlags & SECL_NO_UI))
+ {
+ WCHAR szText[128 + MAX_PATH], szFormat[128];
+ LoadStringW(shell32_hInstance, IDS_FILE_NOT_FOUND, szFormat, _countof(szFormat));
+ StringCchPrintfW(szText, _countof(szText), szFormat, szFile);
+ MessageBoxW(hwnd, szText, NULL, MB_ICONERROR);
+ }
+ return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+ }
+ }
+ }
+
+ ZeroMemory(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.fMask = dwFlags;
+ info.hwnd = hwnd;
+ info.lpVerb = pszVerb;
+ info.lpFile = szFile;
+ info.lpParameters = (pchParams && *pchParams) ? pchParams : NULL;
+ info.lpDirectory = pwszStartDir;
+ info.nShow = nShow;
+ if (ShellExecuteExW(&info))
+ {
+ if (info.lpIDList)
+ CoTaskMemFree(info.lpIDList);
+
+ SHFree(lpCommand);
+
+ return S_OK;
+ }
+
+ dwError = GetLastError();
+
+ SHFree(lpCommand);
+
+ return HRESULT_FROM_WIN32(dwError);
+}