https://git.reactos.org/?p=reactos.git;a=commitdiff;h=bfcbda227f99c1b59e8ed7...
commit bfcbda227f99c1b59e8ed71f5e0f59f793d496a1 Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Sun Aug 5 20:39:17 2018 +0900 Commit: Hermès BÉLUSCA - MAÏTO hermes.belusca-maito@reactos.org CommitDate: Sun Aug 5 13:39:17 2018 +0200
[SHELL32] Fix handling of multiple parameters in the 'Run' dialog (#665)
The "Run" dialog failed when multiple parameters wee specified. We use instead a newly-created ShellExecCmdLine() helper function to fix the problem (as found via API-tracing on Windows). Note that ShellExecCmdLine() starts to be exported with Vista+.
- Implement ShellExecCmdLine() function in shell32. - Add URL support. - Fix RunDlgProc function in shell32. - Add a testcase for ShellExecCmdLine() function.
CORE-14790 --- dll/win32/shell32/dialogs/dialogs.cpp | 25 +- dll/win32/shell32/shlexec.cpp | 180 +++++++ modules/rostests/apitests/shell32/CMakeLists.txt | 1 + .../rostests/apitests/shell32/ShellExecCmdLine.cpp | 582 +++++++++++++++++++++ modules/rostests/apitests/shell32/testlist.c | 2 + sdk/include/reactos/undocshell.h | 15 + 6 files changed, 790 insertions(+), 15 deletions(-)
diff --git a/dll/win32/shell32/dialogs/dialogs.cpp b/dll/win32/shell32/dialogs/dialogs.cpp index 168b066e28..77c1bdf5cc 100644 --- a/dll/win32/shell32/dialogs/dialogs.cpp +++ b/dll/win32/shell32/dialogs/dialogs.cpp @@ -527,7 +527,6 @@ static INT_PTR CALLBACK RunDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARA HWND htxt = GetDlgItem(hwnd, IDC_RUNDLG_EDITPATH); INT ic; WCHAR *psz, *parent = NULL; - SHELLEXECUTEINFOW sei; NMRUNFILEDLGW nmrfd;
ic = GetWindowTextLengthW(htxt); @@ -537,9 +536,6 @@ static INT_PTR CALLBACK RunDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARA return TRUE; }
- ZeroMemory(&sei, sizeof(sei)); - sei.cbSize = sizeof(sei); - /* * Allocate a new MRU entry, we need to add two characters * for the terminating "\1" part, then the NULL character. @@ -552,10 +548,7 @@ static INT_PTR CALLBACK RunDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARA }
GetWindowTextW(htxt, psz, ic + 1); - - sei.hwnd = hwnd; - sei.nShow = SW_SHOWNORMAL; - sei.lpFile = psz; + StrTrimW(psz, L" \t");
/* * The precedence is the following: first the user-given @@ -563,12 +556,13 @@ static INT_PTR CALLBACK RunDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARA * directory is computed if the RFF_CALCDIRECTORY is set, * otherwise no current directory is defined. */ + LPCWSTR pszStartDir; if (prfdp->lpstrDirectory) - sei.lpDirectory = prfdp->lpstrDirectory; + pszStartDir = prfdp->lpstrDirectory; else if (prfdp->uFlags & RFF_CALCDIRECTORY) - sei.lpDirectory = parent = RunDlg_GetParentDir(sei.lpFile); + pszStartDir = parent = RunDlg_GetParentDir(psz); else - sei.lpDirectory = NULL; + pszStartDir = NULL;
/* Hide the dialog for now on, we will show it up in case of retry */ ShowWindow(hwnd, SW_HIDE); @@ -585,9 +579,9 @@ static INT_PTR CALLBACK RunDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARA nmrfd.hdr.code = RFN_VALIDATE; nmrfd.hdr.hwndFrom = hwnd; nmrfd.hdr.idFrom = 0; - nmrfd.lpFile = sei.lpFile; - nmrfd.lpDirectory = sei.lpDirectory; - nmrfd.nShow = sei.nShow; + nmrfd.lpFile = psz; + nmrfd.lpDirectory = pszStartDir; + nmrfd.nShow = SW_SHOWNORMAL;
lRet = SendMessageW(prfdp->hwndOwner, WM_NOTIFY, 0, (LPARAM)&nmrfd.hdr);
@@ -598,7 +592,8 @@ static INT_PTR CALLBACK RunDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARA break;
case RF_OK: - if (ShellExecuteExW(&sei)) + if (SUCCEEDED(ShellExecCmdLine(hwnd, psz, pszStartDir, SW_SHOWNORMAL, NULL, + SECL_ALLOW_NONEXE))) { /* Call again GetWindowText in case the contents of the edit box has changed? */ GetWindowTextW(htxt, psz, ic + 1); diff --git a/dll/win32/shell32/shlexec.cpp b/dll/win32/shell32/shlexec.cpp index 478a3c20b4..55b3d051fe 100644 --- a/dll/win32/shell32/shlexec.cpp +++ b/dll/win32/shell32/shlexec.cpp @@ -21,11 +21,13 @@ */
#include "precomp.h" +#include <undocshell.h>
WINE_DEFAULT_DEBUG_CHANNEL(exec);
static const WCHAR wszOpen[] = L"open"; static const WCHAR wszExe[] = L".exe"; +static const WCHAR wszCom[] = L".com";
#define SEE_MASK_CLASSALL (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)
@@ -2322,3 +2324,181 @@ OpenAs_RunDLLA(HWND hwnd, HINSTANCE hinst, LPCSTR cmdline, int cmdshow) OpenAs_RunDLLW(hwnd, hinst, pszCmdLineW, cmdshow); SHFree(pszCmdLineW); } + +/*************************************************************************/ + +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); +} diff --git a/modules/rostests/apitests/shell32/CMakeLists.txt b/modules/rostests/apitests/shell32/CMakeLists.txt index 545d2cc26e..8201a6f12e 100644 --- a/modules/rostests/apitests/shell32/CMakeLists.txt +++ b/modules/rostests/apitests/shell32/CMakeLists.txt @@ -18,6 +18,7 @@ list(APPEND SOURCE PathResolve.cpp SHCreateFileExtractIconW.cpp SHParseDisplayName.cpp + ShellExecCmdLine.cpp ShellExecuteEx.cpp ShellState.cpp menu.cpp diff --git a/modules/rostests/apitests/shell32/ShellExecCmdLine.cpp b/modules/rostests/apitests/shell32/ShellExecCmdLine.cpp new file mode 100644 index 0000000000..c540321a65 --- /dev/null +++ b/modules/rostests/apitests/shell32/ShellExecCmdLine.cpp @@ -0,0 +1,582 @@ +/* + * PROJECT: ReactOS API tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Test for ShellExecCmdLine + * PROGRAMMERS: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com + */ +#include "shelltest.h" +#include <shlwapi.h> +#include <strsafe.h> + +#define NDEBUG +#include <debug.h> +#include <stdio.h> + +//#define ShellExecCmdLine ShellExecCmdLine + +#ifndef SECL_NO_UI + #define SECL_NO_UI 0x2 + #define SECL_LOG_USAGE 0x8 + #define SECL_USE_IDLIST 0x10 + #define SECL_ALLOW_NONEXE 0x20 + #define SECL_RUNAS 0x40 +#endif + +#ifdef ShellExecCmdLine + +#define shell32_hInstance GetModuleHandle(NULL) +#define IDS_FILE_NOT_FOUND (-1) + +static const WCHAR wszOpen[] = L"open"; +static const WCHAR wszExe[] = L".exe"; +static const WCHAR wszCom[] = L".com"; + +static __inline void __SHCloneStrW(WCHAR **target, const WCHAR *source) +{ + *target = (WCHAR *)SHAlloc((lstrlenW(source) + 1) * sizeof(WCHAR) ); + lstrcpyW(*target, source); +} + +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); +} +#else + typedef HRESULT (WINAPI *SHELLEXECCMDLINE)(HWND, LPCWSTR, LPCWSTR, INT, LPVOID, DWORD); + SHELLEXECCMDLINE g_pShellExecCmdLine = NULL; +#endif + +typedef struct TEST_ENTRY +{ + INT lineno; + HRESULT hr; + BOOL bAllowNonExe; + LPCWSTR pwszWindowClass; + LPCWSTR pwszCommand; + LPCWSTR pwszStartDir; +} TEST_ENTRY; + +static const char s_testfile1[] = "Test File.txt"; +static const char s_testfile2[] = "Test File.bat"; +static char s_notepad[] = "notepad.exe"; + +static const TEST_ENTRY s_entries[] = +{ + // NULL + { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, NULL }, + { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, L"." }, + { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, L"system32" }, + { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, L"C:\Program Files" }, + { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, NULL }, + { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, L"." }, + { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, L"system32" }, + { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, L"C:\Program Files" }, + // notepad + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", NULL }, + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", L"." }, + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", L"system32" }, + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", L"C:\Program Files" }, + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad "Test File.txt"", NULL }, + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad "Test File.txt"", L"." }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", NULL }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", L"." }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", L"system32" }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", L"C:\Program Files" }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad "Test File.txt"", NULL }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad "Test File.txt"", L"." }, + // notepad.exe + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", NULL }, + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", L"." }, + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", L"system32" }, + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", L"C:\Program Files" }, + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe "Test File.txt"", NULL }, + { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe "Test File.txt"", L"." }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", NULL }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", L"." }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", L"system32" }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", L"C:\Program Files" }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe "Test File.txt"", NULL }, + { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe "Test File.txt"", L"." }, + // C:\notepad.exe + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\notepad.exe", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\notepad.exe", L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\notepad.exe", L"system32" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\notepad.exe", L"C:\Program Files" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\notepad.exe "Test File.txt"", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\notepad.exe "Test File.txt"", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\notepad.exe", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\notepad.exe", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\notepad.exe", L"system32" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\notepad.exe", L"C:\Program Files" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\notepad.exe "Test File.txt"", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\notepad.exe "Test File.txt"", L"." }, + // "notepad" + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad"", NULL }, + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad"", L"." }, + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad"", L"system32" }, + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad"", L"C:\Program Files" }, + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad" "Test File.txt"", NULL }, + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad" "Test File.txt"", L"." }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad"", NULL }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad"", L"." }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad"", L"system32" }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad"", L"C:\Program Files" }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad" "Test File.txt"", NULL }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad" "Test File.txt"", L"." }, + // "notepad.exe" + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad.exe"", NULL }, + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad.exe"", L"." }, + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad.exe"", L"system32" }, + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad.exe"", L"C:\Program Files" }, + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad.exe" "Test File.txt"", NULL }, + { __LINE__, S_OK, FALSE, L"Notepad", L""notepad.exe" "Test File.txt"", L"." }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad.exe"", NULL }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad.exe"", L"." }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad.exe"", L"system32" }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad.exe"", L"C:\Program Files" }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad.exe" "Test File.txt"", NULL }, + { __LINE__, S_OK, TRUE, L"Notepad", L""notepad.exe" "Test File.txt"", L"." }, + // test program.exe + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", L"system32" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", L"C:\Program Files" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe "Test File.txt"", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe "Test File.txt"", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", L"system32" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", L"C:\Program Files" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe "Test File.txt"", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe "Test File.txt"", L"." }, + // "test program" + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program"", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program"", L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program"", L"system32" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program"", L"C:\Program Files" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program" "Test File.txt"", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program" "Test File.txt"", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program"", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program"", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program"", L"system32" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program"", L"C:\Program Files" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program" "Test File.txt"", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program" "Test File.txt"", L"." }, + // "test program.exe" + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program.exe"", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program.exe"", L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program.exe"", L"system32" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program.exe"", L"C:\Program Files" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program.exe" "Test File.txt"", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""test program.exe" "Test File.txt"", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program.exe"", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program.exe"", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program.exe"", L"system32" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program.exe"", L"C:\Program Files" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program.exe" "Test File.txt"", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""test program.exe" "Test File.txt"", L"." }, + // invalid program + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", L"system32" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", L"C:\Program Files" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program "Test File.txt"", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program "Test File.txt"", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", L"system32" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", L"C:\Program Files" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program "Test File.txt"", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program "Test File.txt"", L"." }, + // "invalid program.exe" + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""invalid program.exe"", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""invalid program.exe"", L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""invalid program.exe"", L"system32" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""invalid program.exe"", L"C:\Program Files" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""invalid program.exe" "Test File.txt"", NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L""invalid program.exe" "Test File.txt"", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""invalid program.exe"", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""invalid program.exe"", L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""invalid program.exe"", L"system32" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""invalid program.exe"", L"C:\Program Files" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""invalid program.exe" "Test File.txt"", NULL }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L""invalid program.exe" "Test File.txt"", L"." }, +}; + +static void DoEntry(const TEST_ENTRY *pEntry) +{ + HRESULT hr; + DWORD dwSeclFlags; + + if (pEntry->bAllowNonExe) + dwSeclFlags = SECL_NO_UI | SECL_ALLOW_NONEXE; + else + dwSeclFlags = SECL_NO_UI; + + _SEH2_TRY + { +#ifdef ShellExecCmdLine + hr = ShellExecCmdLine(NULL, pEntry->pwszCommand, pEntry->pwszStartDir, + SW_SHOWNORMAL, NULL, dwSeclFlags); +#else + hr = (*g_pShellExecCmdLine)(NULL, pEntry->pwszCommand, pEntry->pwszStartDir, + SW_SHOWNORMAL, NULL, dwSeclFlags); +#endif + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + hr = 0xDEADFACE; + } + _SEH2_END; + + ok(hr == pEntry->hr, "Line %d: hr expected 0x%lX, was 0x%lX\n", pEntry->lineno, pEntry->hr, hr); + +#define RETRY_COUNT 5 +#define RETRY_INTERVAL 250 + if (SUCCEEDED(hr) && pEntry->pwszWindowClass) + { + BOOL bFound = FALSE; + Sleep(RETRY_INTERVAL / 2); + for (int i = 0; i < RETRY_COUNT; ++i) + { + HWND hwnd = FindWindowW(pEntry->pwszWindowClass, NULL); + if (hwnd) + { + bFound = TRUE; + SendMessage(hwnd, WM_CLOSE, 0, 0); + break; + } + Sleep(RETRY_INTERVAL); + } + ok(bFound, "Line %d: The window not found\n", pEntry->lineno); + } +#undef RETRY_COUNT +#undef RETRY_INTERVAL +} + +START_TEST(ShellExecCmdLine) +{ + using namespace std; + +#ifndef ShellExecCmdLine + HMODULE hShell32 = GetModuleHandleA("shell32"); + g_pShellExecCmdLine = (SHELLEXECCMDLINE)GetProcAddress(hShell32, (LPCSTR)(INT_PTR)265); + if (!g_pShellExecCmdLine) + { + skip("ShellExecCmdLine is not found\n"); + return; + } +#endif + + // s_testfile1 + FILE *fp = fopen(s_testfile1, "wb"); + ok(fp != NULL, "failed to create a test file\n"); + fclose(fp); + + // s_testfile2 + fp = fopen(s_testfile2, "wb"); + ok(fp != NULL, "failed to create a test file\n"); + if (fp) + { + fprintf(fp, "echo OK\n"); + } + fclose(fp); + + for (size_t i = 0; i < _countof(s_entries); ++i) + { + DoEntry(&s_entries[i]); + } + + WCHAR buf0[MAX_PATH]; + WCHAR buf1[MAX_PATH]; + WCHAR buf2[MAX_PATH]; + TEST_ENTRY additionals[] = + { + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf0, NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf0, L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf0, L"system32" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf1, NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf1, L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf1, L"system32" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf2, NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf2, L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf2, L"system32" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf0, NULL }, // FIXME + { __LINE__, S_OK, TRUE, L"Notepad", buf0, L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf0, L"system32" }, // FIXME + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf1, NULL }, // FIXME + { __LINE__, S_OK, TRUE, L"Notepad", buf1, L"." }, + { __LINE__, S_OK, TRUE, L"Notepad", buf1, L"system32" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf2, NULL }, // FIXME + { __LINE__, S_OK, TRUE, L"Notepad", buf2, L"." }, + { __LINE__, S_OK, TRUE, L"Notepad", buf2, L"system32" }, + }; + + wsprintfW(buf0, L"%hs", s_testfile1); + wsprintfW(buf1, L""%hs"", s_testfile1); + wsprintfW(buf2, L""%hs" "Test File.txt"", s_testfile1); + for (size_t i = 0; i < _countof(additionals); ++i) + { + DoEntry(&additionals[i]); + } + + TEST_ENTRY additionals2[] = + { + { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf0, NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf0, L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf0, L"system32" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf1, NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf1, L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf1, L"system32" }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf2, NULL }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf2, L"." }, + { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf2, L"system32" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf0, NULL }, // FIXME + { __LINE__, S_OK, TRUE, NULL, buf0, L"." }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf0, L"system32" }, // FIXME + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf1, NULL }, // FIXME + { __LINE__, S_OK, TRUE, NULL, buf1, L"." }, + { __LINE__, S_OK, TRUE, NULL, buf1, L"system32" }, + { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf2, NULL }, // FIXME + { __LINE__, S_OK, TRUE, NULL, buf2, L"." }, + { __LINE__, S_OK, TRUE, NULL, buf2, L"system32" }, + }; + + wsprintfW(buf0, L"%hs", s_testfile2); + wsprintfW(buf1, L""%hs"", s_testfile2); + wsprintfW(buf2, L""%hs" "Test File.txt"", s_testfile2); + for (size_t i = 0; i < _countof(additionals2); ++i) + { + DoEntry(&additionals2[i]); + } + + char path[MAX_PATH]; + ok((INT_PTR)FindExecutableA("notepad.exe", NULL, s_notepad) >= 32, "FindExecutableA failed\n"); + ok(GetModuleFileNameA(NULL, path, _countof(path)), "GetModuleFileNameA failed\n"); + char *pch = strrchr(path, '\'); + + if (pch == NULL) + { + skip("pch == NULL\n"); + } + else + { + // create "My Directory" + strcpy(pch, "\My Directory"); + if (GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES) + ok(CreateDirectoryA(path, NULL), "CreateDirectoryA failed\n"); + + // create "My Directory\Notepad.exe" as clone of Notepad.exe + strcpy(pch, "\My Directory\Notepad.exe"); + ok(CopyFileA(s_notepad, path, FALSE), "CopyFileA failed\n"); + + wsprintfW(buf0, L"%hs", path); + wsprintfW(buf1, L""%hs"", path); + wsprintfW(buf2, L""%hs" "Test File.txt"", path); + TEST_ENTRY additionals3[] = + { + { __LINE__, S_OK, FALSE, NULL, buf0, NULL }, + { __LINE__, S_OK, FALSE, NULL, buf0, L"." }, + { __LINE__, S_OK, FALSE, NULL, buf0, L"system32" }, + { __LINE__, S_OK, FALSE, NULL, buf1, NULL }, + { __LINE__, S_OK, FALSE, NULL, buf1, L"." }, + { __LINE__, S_OK, FALSE, NULL, buf1, L"system32" }, + { __LINE__, S_OK, FALSE, NULL, buf2, NULL }, + { __LINE__, S_OK, FALSE, NULL, buf2, L"." }, + { __LINE__, S_OK, FALSE, NULL, buf2, L"system32" }, + { __LINE__, S_OK, TRUE, NULL, buf0, NULL }, + { __LINE__, S_OK, TRUE, NULL, buf0, L"." }, + { __LINE__, S_OK, TRUE, NULL, buf0, L"system32" }, + { __LINE__, S_OK, TRUE, NULL, buf1, NULL }, + { __LINE__, S_OK, TRUE, NULL, buf1, L"." }, + { __LINE__, S_OK, TRUE, NULL, buf1, L"system32" }, + { __LINE__, S_OK, TRUE, NULL, buf2, NULL }, + { __LINE__, S_OK, TRUE, NULL, buf2, L"." }, + { __LINE__, S_OK, TRUE, NULL, buf2, L"system32" }, + }; + for (size_t i = 0; i < _countof(additionals3); ++i) + { + DoEntry(&additionals3[i]); + } + + DeleteFileA(path); + + strcpy(pch, "\My Directory"); + RemoveDirectory(path); + } + + // clean up + ok(DeleteFileA(s_testfile1), "failed to delete the test file\n"); + ok(DeleteFileA(s_testfile2), "failed to delete the test file\n"); +} diff --git a/modules/rostests/apitests/shell32/testlist.c b/modules/rostests/apitests/shell32/testlist.c index b2e1b78876..1b5339ea5e 100644 --- a/modules/rostests/apitests/shell32/testlist.c +++ b/modules/rostests/apitests/shell32/testlist.c @@ -15,6 +15,7 @@ extern void func_menu(void); extern void func_OpenAs_RunDLL(void); extern void func_PathResolve(void); extern void func_SHCreateFileExtractIconW(void); +extern void func_ShellExecCmdLine(void); extern void func_ShellExecuteEx(void); extern void func_ShellState(void); extern void func_SHParseDisplayName(void); @@ -33,6 +34,7 @@ const struct test winetest_testlist[] = { "OpenAs_RunDLL", func_OpenAs_RunDLL }, { "PathResolve", func_PathResolve }, { "SHCreateFileExtractIconW", func_SHCreateFileExtractIconW }, + { "ShellExecCmdLine", func_ShellExecCmdLine }, { "ShellExecuteEx", func_ShellExecuteEx }, { "ShellState", func_ShellState }, { "SHParseDisplayName", func_SHParseDisplayName }, diff --git a/sdk/include/reactos/undocshell.h b/sdk/include/reactos/undocshell.h index 24d6e82f55..c2a0b37c6b 100644 --- a/sdk/include/reactos/undocshell.h +++ b/sdk/include/reactos/undocshell.h @@ -546,6 +546,21 @@ WORD WINAPI ArrangeWindows( WORD cKids, CONST HWND * lpKids);
+/* Flags for ShellExecCmdLine */ +#define SECL_NO_UI 0x2 +#define SECL_LOG_USAGE 0x8 +#define SECL_USE_IDLIST 0x10 +#define SECL_ALLOW_NONEXE 0x20 +#define SECL_RUNAS 0x40 + +HRESULT WINAPI ShellExecCmdLine( + HWND hwnd, + LPCWSTR pwszCommand, + LPCWSTR pwszStartDir, + int nShow, + LPVOID pUnused, + DWORD dwSeclFlags); + /* RegisterShellHook types */ #define RSH_DEREGISTER 0 #define RSH_REGISTER 1