mirror of
https://github.com/reactos/reactos.git
synced 2025-08-09 01:13:20 +00:00

Fix the shell32 apitests so that they pass on Windows Server 2003 - Windows 10. Many of these fixes are for Vista+, but the most important fixes are for ShellExecCmdLine and FindExecutable which had issues closing windows after tests and deleting test files. Failing to delete these files breaks the other test (i.e. running ShellExecCmdLine would break FindExecutable and vis-versa.)
691 lines
30 KiB
C++
691 lines
30 KiB
C++
/*
|
|
* 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>
|
|
#include <versionhelpers.h>
|
|
#include "shell32_apitest_sub.h"
|
|
#include "closewnd.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
#include <stdio.h>
|
|
|
|
#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
|
|
|
|
#define ShellExecCmdLine proxy_ShellExecCmdLine
|
|
|
|
#define shell32_hInstance GetModuleHandle(NULL)
|
|
#define IDS_FILE_NOT_FOUND (-1)
|
|
|
|
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);
|
|
}
|
|
|
|
// NOTE: You have to sync the following code to dll/win32/shell32/shlexec.cpp.
|
|
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 (szFile[0] != UNICODE_NULL && szFile[1] == L':' &&
|
|
szFile[2] == UNICODE_NULL)
|
|
{
|
|
PathAddBackslashW(szFile);
|
|
}
|
|
|
|
WCHAR szCurDir[MAX_PATH];
|
|
GetCurrentDirectoryW(_countof(szCurDir), szCurDir);
|
|
if (pwszStartDir)
|
|
{
|
|
SetCurrentDirectoryW(pwszStartDir);
|
|
}
|
|
|
|
if (PathIsRelativeW(szFile) &&
|
|
GetFullPathNameW(szFile, _countof(szFile2), szFile2, NULL) &&
|
|
PathFileExistsW(szFile2))
|
|
{
|
|
StringCchCopyW(szFile, _countof(szFile), szFile2);
|
|
}
|
|
else 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);
|
|
}
|
|
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 (pwszStartDir)
|
|
{
|
|
SetCurrentDirectoryW(szCurDir);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
#undef ShellExecCmdLine
|
|
|
|
typedef HRESULT (WINAPI *SHELLEXECCMDLINE)(HWND, LPCWSTR, LPCWSTR, INT, LPVOID, DWORD);
|
|
SHELLEXECCMDLINE g_pShellExecCmdLine = NULL;
|
|
|
|
typedef struct TEST_ENTRY
|
|
{
|
|
INT lineno;
|
|
BOOL result;
|
|
BOOL bAllowNonExe;
|
|
LPCWSTR pwszCommand;
|
|
LPCWSTR pwszStartDir;
|
|
} TEST_ENTRY;
|
|
|
|
static WCHAR s_sub_program[MAX_PATH];
|
|
static WCHAR s_win_test_exe[MAX_PATH];
|
|
static WCHAR s_sys_bat_file[MAX_PATH];
|
|
static WCHAR s_cur_dir[MAX_PATH];
|
|
|
|
static const TEST_ENTRY s_entries_1[] =
|
|
{
|
|
// NULL
|
|
{ __LINE__, 0xBADFACE, FALSE, NULL, NULL },
|
|
{ __LINE__, 0xBADFACE, FALSE, NULL, L"." },
|
|
{ __LINE__, 0xBADFACE, FALSE, NULL, L"system32" },
|
|
{ __LINE__, 0xBADFACE, FALSE, NULL, L"C:\\Program Files" },
|
|
{ __LINE__, 0xBADFACE, TRUE, NULL, NULL },
|
|
{ __LINE__, 0xBADFACE, TRUE, NULL, L"." },
|
|
{ __LINE__, 0xBADFACE, TRUE, NULL, L"system32" },
|
|
{ __LINE__, 0xBADFACE, TRUE, NULL, L"C:\\Program Files" },
|
|
// notepad
|
|
{ __LINE__, TRUE, FALSE, L"notepad", NULL },
|
|
{ __LINE__, TRUE, FALSE, L"notepad", L"." },
|
|
{ __LINE__, TRUE, FALSE, L"notepad", L"system32" },
|
|
{ __LINE__, TRUE, FALSE, L"notepad", L"C:\\Program Files" },
|
|
{ __LINE__, TRUE, FALSE, L"notepad \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, FALSE, L"notepad \"Test File.txt\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"notepad", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"notepad", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"notepad", L"system32" },
|
|
{ __LINE__, TRUE, TRUE, L"notepad", L"C:\\Program Files" },
|
|
{ __LINE__, TRUE, TRUE, L"notepad \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"notepad \"Test File.txt\"", L"." },
|
|
// notepad.exe
|
|
{ __LINE__, TRUE, FALSE, L"notepad.exe", NULL },
|
|
{ __LINE__, TRUE, FALSE, L"notepad.exe", L"." },
|
|
{ __LINE__, TRUE, FALSE, L"notepad.exe", L"system32" },
|
|
{ __LINE__, TRUE, FALSE, L"notepad.exe", L"C:\\Program Files" },
|
|
{ __LINE__, TRUE, FALSE, L"notepad.exe \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, FALSE, L"notepad.exe \"Test File.txt\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"notepad.exe", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"notepad.exe", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"notepad.exe", L"system32" },
|
|
{ __LINE__, TRUE, TRUE, L"notepad.exe", L"C:\\Program Files" },
|
|
{ __LINE__, TRUE, TRUE, L"notepad.exe \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"notepad.exe \"Test File.txt\"", L"." },
|
|
// C:\notepad.exe
|
|
{ __LINE__, FALSE, FALSE, L"C:\\notepad.exe", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"C:\\notepad.exe", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"C:\\notepad.exe", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"C:\\notepad.exe", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, FALSE, L"C:\\notepad.exe \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"C:\\notepad.exe \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"C:\\notepad.exe", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"C:\\notepad.exe", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"C:\\notepad.exe", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"C:\\notepad.exe", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, TRUE, L"C:\\notepad.exe \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"C:\\notepad.exe \"Test File.txt\"", L"." },
|
|
// "notepad"
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad\"", NULL },
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad\"", L"." },
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad\"", L"system32" },
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad\"", L"C:\\Program Files" },
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad\"", L"system32" },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad\"", L"C:\\Program Files" },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad\" \"Test File.txt\"", L"." },
|
|
// "notepad.exe"
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad.exe\"", NULL },
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad.exe\"", L"." },
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad.exe\"", L"system32" },
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad.exe\"", L"C:\\Program Files" },
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad.exe\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, FALSE, L"\"notepad.exe\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad.exe\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad.exe\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad.exe\"", L"system32" },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad.exe\"", L"C:\\Program Files" },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad.exe\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"\"notepad.exe\" \"Test File.txt\"", L"." },
|
|
// test program
|
|
{ __LINE__, FALSE, FALSE, L"test program", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"test program", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"test program", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"test program", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, FALSE, L"test program \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"test program \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"test program", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"test program", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"test program", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"test program", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, TRUE, L"test program \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"test program \"Test File.txt\"", L"." },
|
|
// test program.exe
|
|
{ __LINE__, FALSE, FALSE, L"test program.exe", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"test program.exe", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"test program.exe", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"test program.exe", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, FALSE, L"test program.exe \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"test program.exe \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"test program.exe", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"test program.exe", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"test program.exe", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"test program.exe", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, TRUE, L"test program.exe \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"test program.exe \"Test File.txt\"", L"." },
|
|
// test program.bat
|
|
{ __LINE__, FALSE, FALSE, L"test program.bat", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"test program.bat", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"test program.bat", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"test program.bat", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, FALSE, L"test program.bat \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"test program.bat \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"test program.bat", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"test program.bat", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"test program.bat", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"test program.bat", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, TRUE, L"test program.bat \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"test program.bat \"Test File.txt\"", L"." },
|
|
// "test program"
|
|
{ __LINE__, FALSE, FALSE, L"\"test program\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"test program\"", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"\"test program\"", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"\"test program\"", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, FALSE, L"\"test program\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"test program\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program\"", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program\"", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program\" \"Test File.txt\"", L"." },
|
|
// "test program.exe"
|
|
{ __LINE__, TRUE, FALSE, L"\"test program.exe\"", NULL },
|
|
{ __LINE__, TRUE, FALSE, L"\"test program.exe\"", L"." },
|
|
{ __LINE__, TRUE, FALSE, L"\"test program.exe\"", L"system32" },
|
|
{ __LINE__, TRUE, FALSE, L"\"test program.exe\"", L"C:\\Program Files" },
|
|
{ __LINE__, TRUE, FALSE, L"\"test program.exe\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, FALSE, L"\"test program.exe\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"\"test program.exe\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"\"test program.exe\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"\"test program.exe\"", L"system32" },
|
|
{ __LINE__, TRUE, TRUE, L"\"test program.exe\"", L"C:\\Program Files" },
|
|
{ __LINE__, TRUE, TRUE, L"\"test program.exe\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"\"test program.exe\" \"Test File.txt\"", L"." },
|
|
// "test program.bat"
|
|
{ __LINE__, FALSE, FALSE, L"\"test program.bat\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"test program.bat\"", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"\"test program.bat\"", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"\"test program.bat\"", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, FALSE, L"\"test program.bat\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"test program.bat\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program.bat\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program.bat\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program.bat\"", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program.bat\"", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program.bat\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"\"test program.bat\" \"Test File.txt\"", L"." },
|
|
// invalid program
|
|
{ __LINE__, FALSE, FALSE, L"invalid program", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"invalid program", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"invalid program", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"invalid program", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, FALSE, L"invalid program \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"invalid program \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"invalid program", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"invalid program", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"invalid program", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"invalid program", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, TRUE, L"invalid program \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"invalid program \"Test File.txt\"", L"." },
|
|
// \"invalid program.exe\"
|
|
{ __LINE__, FALSE, FALSE, L"\"invalid program.exe\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"invalid program.exe\"", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"\"invalid program.exe\"", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"\"invalid program.exe\"", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, FALSE, L"\"invalid program.exe\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"invalid program.exe\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"\"invalid program.exe\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"\"invalid program.exe\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"\"invalid program.exe\"", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"\"invalid program.exe\"", L"C:\\Program Files" },
|
|
{ __LINE__, FALSE, TRUE, L"\"invalid program.exe\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"\"invalid program.exe\" \"Test File.txt\"", L"." },
|
|
// My Documents
|
|
{ __LINE__, TRUE, TRUE, L"::{450d8fba-ad25-11d0-98a8-0800361b1103}", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"shell:::{450d8fba-ad25-11d0-98a8-0800361b1103}", NULL },
|
|
// shell:sendto
|
|
{ __LINE__, TRUE, TRUE, L"shell:sendto", NULL },
|
|
// https://google.com
|
|
{ __LINE__, TRUE, FALSE, L"https://google.com", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"https://google.com", NULL },
|
|
// Test File 1.txt
|
|
{ __LINE__, FALSE, FALSE, L"Test File 1.txt", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 1.txt", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 1.txt", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 1.txt", s_cur_dir },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\"", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\"", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\"", s_cur_dir },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\" \"Test File.txt\"", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"Test File 1.txt", NULL },
|
|
// { __LINE__, TRUE, TRUE, L"Test File 1.txt", L"." }, // Fails on Vista, 7, 8.1
|
|
{ __LINE__, FALSE, TRUE, L"Test File 1.txt", L"system32" },
|
|
{ __LINE__, TRUE, TRUE, L"Test File 1.txt", s_cur_dir },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 1.txt\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\"", L"system32" },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\"", s_cur_dir },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 1.txt\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\" \"Test File.txt\"", L"system32" },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\" \"Test File.txt\"", s_cur_dir },
|
|
// Test File 2.bat
|
|
{ __LINE__, FALSE, FALSE, L"Test File 2.bat", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 2.bat", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 2.bat", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 2.bat", s_cur_dir },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\"", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\"", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\"", s_cur_dir },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\" \"Test File.txt\"", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\" \"Test File.txt\"", s_cur_dir },
|
|
{ __LINE__, FALSE, TRUE, L"Test File 2.bat", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"Test File 2.bat", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"Test File 2.bat", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"Test File 2.bat", s_cur_dir },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\"", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\"", s_cur_dir },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\" \"Test File.txt\"", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\" \"Test File.txt\"", s_cur_dir },
|
|
};
|
|
|
|
static const TEST_ENTRY s_entries_2[] =
|
|
{
|
|
// Test File 1.txt (with setting path)
|
|
{ __LINE__, FALSE, FALSE, L"Test File 1.txt", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 1.txt", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 1.txt", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 1.txt", s_cur_dir },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\"", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\"", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\"", s_cur_dir },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\" \"Test File.txt\"", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 1.txt\" \"Test File.txt\"", s_cur_dir },
|
|
{ __LINE__, FALSE, TRUE, L"Test File 1.txt", NULL },
|
|
// { __LINE__, TRUE, TRUE, L"Test File 1.txt", L"." }, // Fails on Vista, 7, 8.1
|
|
{ __LINE__, FALSE, TRUE, L"Test File 1.txt", L"system32" },
|
|
{ __LINE__, TRUE, TRUE, L"Test File 1.txt", s_cur_dir },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\"", L"system32" },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\"", s_cur_dir },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\" \"Test File.txt\"", L"system32" },
|
|
{ __LINE__, TRUE, TRUE, L"\"Test File 1.txt\" \"Test File.txt\"", s_cur_dir },
|
|
// Test File 2.bat (with setting path)
|
|
{ __LINE__, FALSE, FALSE, L"Test File 2.bat", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 2.bat", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 2.bat", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"Test File 2.bat", s_cur_dir },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\"", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\"", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\"", s_cur_dir },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\" \"Test File.txt\"", L"system32" },
|
|
{ __LINE__, FALSE, FALSE, L"\"Test File 2.bat\" \"Test File.txt\"", s_cur_dir },
|
|
{ __LINE__, FALSE, TRUE, L"Test File 2.bat", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"Test File 2.bat", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"Test File 2.bat", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"Test File 2.bat", s_cur_dir },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\"", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\"", s_cur_dir },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\" \"Test File.txt\"", NULL },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\" \"Test File.txt\"", L"." },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\" \"Test File.txt\"", L"system32" },
|
|
{ __LINE__, FALSE, TRUE, L"\"Test File 2.bat\" \"Test File.txt\"", s_cur_dir },
|
|
};
|
|
|
|
static void DoEntry(const TEST_ENTRY *pEntry)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwSeclFlags;
|
|
BOOL result;
|
|
|
|
if (pEntry->bAllowNonExe)
|
|
dwSeclFlags = SECL_NO_UI | SECL_ALLOW_NONEXE;
|
|
else
|
|
dwSeclFlags = SECL_NO_UI;
|
|
|
|
_SEH2_TRY
|
|
{
|
|
if (IsReactOS())
|
|
{
|
|
hr = proxy_ShellExecCmdLine(NULL, pEntry->pwszCommand, pEntry->pwszStartDir,
|
|
SW_SHOWNORMAL, NULL, dwSeclFlags);
|
|
}
|
|
else
|
|
{
|
|
hr = (*g_pShellExecCmdLine)(NULL, pEntry->pwszCommand, pEntry->pwszStartDir,
|
|
SW_SHOWNORMAL, NULL, dwSeclFlags);
|
|
}
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = 0xBADFACE;
|
|
}
|
|
_SEH2_END;
|
|
|
|
if (hr == 0xBADFACE)
|
|
result = hr;
|
|
else
|
|
result = (hr == S_OK);
|
|
|
|
ok(result == pEntry->result, "Line %d: result expected %d, was %d\n",
|
|
pEntry->lineno, pEntry->result, result);
|
|
}
|
|
|
|
static WINDOW_LIST s_List1, s_List2;
|
|
|
|
static VOID TEST_ShellExecCmdLine(VOID)
|
|
{
|
|
GetWindowList(&s_List1);
|
|
|
|
// do tests
|
|
for (size_t i = 0; i < _countof(s_entries_1); ++i)
|
|
{
|
|
DoEntry(&s_entries_1[i]);
|
|
}
|
|
SetEnvironmentVariableW(L"PATH", s_cur_dir);
|
|
for (size_t i = 0; i < _countof(s_entries_2); ++i)
|
|
{
|
|
DoEntry(&s_entries_2[i]);
|
|
}
|
|
|
|
// Execution can be asynchronous; you have to wait for it to finish.
|
|
Sleep(2000);
|
|
|
|
// Close newly-opened window(s)
|
|
GetWindowList(&s_List2);
|
|
CloseNewWindows(&s_List1, &s_List2);
|
|
FreeWindowList(&s_List1);
|
|
FreeWindowList(&s_List2);
|
|
}
|
|
|
|
START_TEST(ShellExecCmdLine)
|
|
{
|
|
using namespace std;
|
|
|
|
if (!IsReactOS())
|
|
{
|
|
if (!IsWindowsVistaOrGreater())
|
|
{
|
|
skip("ShellExecCmdLine is not available on this platform\n");
|
|
return;
|
|
}
|
|
|
|
HMODULE hShell32 = GetModuleHandleA("shell32");
|
|
g_pShellExecCmdLine = (SHELLEXECCMDLINE)GetProcAddress(hShell32, (LPCSTR)(INT_PTR)265);
|
|
if (!g_pShellExecCmdLine)
|
|
{
|
|
skip("ShellExecCmdLine is not found\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!FindSubProgram(s_sub_program, _countof(s_sub_program)))
|
|
{
|
|
skip("shell32_apitest_sub.exe is not found\n");
|
|
return;
|
|
}
|
|
|
|
// s_win_test_exe
|
|
GetWindowsDirectoryW(s_win_test_exe, _countof(s_win_test_exe));
|
|
PathAppendW(s_win_test_exe, L"test program.exe");
|
|
SetFileAttributesW(s_win_test_exe, FILE_ATTRIBUTE_NORMAL); // Clear readonly flag if it exists.
|
|
BOOL ret = CopyFileW(s_sub_program, s_win_test_exe, FALSE);
|
|
if (!ret)
|
|
{
|
|
skip("Cannot copy test files to the system root directory. (Error: %lu)\n", GetLastError());
|
|
return;
|
|
}
|
|
|
|
FILE *fp;
|
|
|
|
// s_sys_bat_file
|
|
GetSystemDirectoryW(s_sys_bat_file, _countof(s_sys_bat_file));
|
|
PathAppendW(s_sys_bat_file, L"test program.bat");
|
|
fp = _wfopen(s_sys_bat_file, L"wb");
|
|
fclose(fp);
|
|
ok_int(PathFileExistsW(s_sys_bat_file), TRUE);
|
|
|
|
// "Test File 1.txt"
|
|
fp = fopen("Test File 1.txt", "wb");
|
|
ok(fp != NULL, "failed to create a test file\n");
|
|
fclose(fp);
|
|
ok_int(PathFileExistsA("Test File 1.txt"), TRUE);
|
|
|
|
// "Test File 2.bat"
|
|
fp = fopen("Test File 2.bat", "wb");
|
|
ok(fp != NULL, "failed to create a test file\n");
|
|
fclose(fp);
|
|
ok_int(PathFileExistsA("Test File 2.bat"), TRUE);
|
|
|
|
// s_cur_dir
|
|
GetCurrentDirectoryW(_countof(s_cur_dir), s_cur_dir);
|
|
|
|
TEST_ShellExecCmdLine();
|
|
|
|
// Some process can lock the file of s_win_test_exe
|
|
Sleep(1000);
|
|
|
|
// clean up
|
|
SetFileAttributesW(s_win_test_exe, FILE_ATTRIBUTE_NORMAL); // Clear readonly flag
|
|
ok(DeleteFileW(s_win_test_exe), "Failed to delete \"%S\".\n", s_win_test_exe);
|
|
ok(DeleteFileW(s_sys_bat_file), "Failed to delete \"%S\".\n", s_sys_bat_file);
|
|
ok(DeleteFileA("Test File 1.txt"), "Failed to delete \"Test File 1.txt\".\n");
|
|
ok(DeleteFileA("Test File 2.bat"), "Failed to delete \"Test File 2.bat\".\n");
|
|
}
|