+ 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);