mirror of
https://github.com/reactos/reactos.git
synced 2025-02-21 16:04:57 +00:00
[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
This commit is contained in:
parent
ff63ef3c55
commit
bfcbda227f
6 changed files with 790 additions and 15 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ list(APPEND SOURCE
|
|||
PathResolve.cpp
|
||||
SHCreateFileExtractIconW.cpp
|
||||
SHParseDisplayName.cpp
|
||||
ShellExecCmdLine.cpp
|
||||
ShellExecuteEx.cpp
|
||||
ShellState.cpp
|
||||
menu.cpp
|
||||
|
|
582
modules/rostests/apitests/shell32/ShellExecCmdLine.cpp
Normal file
582
modules/rostests/apitests/shell32/ShellExecCmdLine.cpp
Normal file
|
@ -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");
|
||||
}
|
|
@ -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 },
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue