mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-26 19:33:31 +00:00
[SHELL32][SHLWAPI][BROWSEUI][SHELL32_APITEST][SDK][KBSWITCH][RAPPS] Support SHEvaluateSystemCommandTemplate (#9111)
This function has an important role for new ShellExecute implementation. JIRA issue: CORE-19278 - Add evalcmd static library into dll/win32/shell32/evalcmd. - Implement SHEvaluateSystemCommandTemplate in evalcmd. - Link evalcmd to shell32 and shlwapi. - Modify shell32.spec and shlwapi.spec. - Add prototype to <shellapi.h>. - Add SHEvaluateSystemCommandTemplate testcase. - Define PathIsAbsolute inline function in <shlwapi_undoc.h> and use it.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#include "kbswitch.h"
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shlwapi_undoc.h>
|
||||
#include <undocuser.h>
|
||||
#include <imm.h>
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
#include <ui/rosctrls.h>
|
||||
#include <windowsx.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shlwapi_undoc.h>
|
||||
#include <process.h>
|
||||
#undef SubclassWindow
|
||||
|
||||
@@ -480,7 +480,7 @@ LOCATIONITEM* CSearchBar::GetAddressEditBoxLocations(WCHAR *szPath)
|
||||
|
||||
DWORD dwAttributes = GetFileAttributesW(pszPath);
|
||||
if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
PathIsAbsolute(pszPath))
|
||||
FindFiles_PathIsAbsolute(pszPath))
|
||||
{
|
||||
return BuildLocationList(&pszPath, 1);
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ static inline BOOL PathIsOnUnc(PCWSTR Path)
|
||||
return PathIsUNCW(Path); // FIXME: Verify the path starts with <\\Server\Share>[\]
|
||||
}
|
||||
|
||||
static inline bool PathIsAbsolute(PCWSTR Path)
|
||||
static inline bool FindFiles_PathIsAbsolute(PCWSTR Path)
|
||||
{
|
||||
// Note: PathIsRelativeW is too forgiving
|
||||
return PathIsOnDrive(Path) || PathIsOnUnc(Path);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
PROJECT(SHELL)
|
||||
|
||||
add_subdirectory(evalcmd)
|
||||
add_subdirectory(shelldesktop)
|
||||
add_subdirectory(shellmenu)
|
||||
add_subdirectory(shellrecyclebin)
|
||||
@@ -131,6 +132,9 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
target_compile_options(shell32 PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-Wno-overloaded-virtual>")
|
||||
endif()
|
||||
target_link_libraries(shell32 shellmenu shelldesktop wine uuid recyclebin cpprt atl_classes oldnames)
|
||||
if(DLL_EXPORT_VERSION GREATER_EQUAL 0x600)
|
||||
target_link_libraries(shell32 evalcmd)
|
||||
endif()
|
||||
add_delay_importlibs(shell32 powrprof shdocvw devmgr winspool.drv winmm mpr uxtheme ole32 oleaut32 userenv browseui version fmifs netapi32 secur32)
|
||||
add_importlibs(shell32 advapi32 gdi32 user32 comctl32 comdlg32 shlwapi shcore msvcrt kernel32 ntdll)
|
||||
add_dependencies(shell32 stdole2) # shell32_shldisp.tlb needs stdole2.tlb
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
add_library(evalcmd STATIC evalcmd.cpp)
|
||||
add_dependencies(evalcmd psdk)
|
||||
target_link_libraries(evalcmd PRIVATE pathcch_static)
|
||||
target_compile_definitions(evalcmd PRIVATE STATIC_PATHCCH)
|
||||
|
||||
if(DLL_EXPORT_VERSION GREATER_EQUAL 0x600)
|
||||
target_compile_definitions(evalcmd PRIVATE _SHELL32_)
|
||||
else()
|
||||
target_compile_definitions(evalcmd PRIVATE _SHLWAPI_)
|
||||
endif()
|
||||
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Shell
|
||||
* LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
|
||||
* PURPOSE: SHEvaluateSystemCommandTemplate
|
||||
* COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ <[email protected]>
|
||||
*/
|
||||
|
||||
#include <windef.h>
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shlguid_undoc.h>
|
||||
#include <shlobj_undoc.h>
|
||||
#include <shlwapi_undoc.h>
|
||||
#include <strsafe.h>
|
||||
#include <pathcch.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define PATH_VALID_CHARS \
|
||||
(PATH_CHAR_CLASS_DOT | PATH_CHAR_CLASS_SEMICOLON | PATH_CHAR_CLASS_COMMA | \
|
||||
PATH_CHAR_CLASS_SPACE | PATH_CHAR_CLASS_OTHER_VALID)
|
||||
|
||||
/**
|
||||
* Get the position of the arguments of a command line string as CreateProcess does.
|
||||
*/
|
||||
static PCWSTR _PathGetArgsLikeCreateProcess(PCWSTR lpString)
|
||||
{
|
||||
PCWSTR pch;
|
||||
if (*lpString == L'"')
|
||||
{
|
||||
pch = StrChrW(lpString + 1, L'"');
|
||||
if (pch)
|
||||
{
|
||||
++pch;
|
||||
if (*pch == L' ')
|
||||
++pch;
|
||||
return pch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pch = StrChrW(lpString, L' ');
|
||||
if (pch)
|
||||
return pch + 1;
|
||||
}
|
||||
return &lpString[lstrlenW(lpString)];
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
_PathCopyExeAndTrimWhiteSpaces(PWSTR pszBuff, size_t cchBuff, PCWSTR pszSrc, size_t cchSrc)
|
||||
{
|
||||
HRESULT hr = StringCchCopyNW(pszBuff, cchBuff, pszSrc, cchSrc);
|
||||
if (SUCCEEDED(hr))
|
||||
StrTrimW(pszBuff, L" \t");
|
||||
return hr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief "Program Files" contains space. It needs special handling. This function will detect it.
|
||||
*/
|
||||
static BOOL _PathMatchesSuspicious(PCWSTR lpString)
|
||||
{
|
||||
WCHAR pszPath[MAX_PATH];
|
||||
SHGetFolderPathW(NULL, CSIDL_PROGRAM_FILES, NULL, 0, pszPath);
|
||||
INT cch = lstrlenW(pszPath);
|
||||
return StrCmpNIW(lpString, pszPath, cch) == 0;
|
||||
}
|
||||
|
||||
// This function attempts to find where the "arguments" portion of a command-line path string
|
||||
static PCWSTR _PathGuessNextBestArgs(PCWSTR pszPath)
|
||||
{
|
||||
PCWSTR pSpaceStart = NULL;
|
||||
BOOL bValid = TRUE;
|
||||
|
||||
for (; *pszPath && bValid; ++pszPath)
|
||||
{
|
||||
switch (*pszPath)
|
||||
{
|
||||
case L' ':
|
||||
if (!pSpaceStart)
|
||||
pSpaceStart = pszPath;
|
||||
break;
|
||||
|
||||
case L'"':
|
||||
case L'%':
|
||||
bValid = FALSE;
|
||||
break;
|
||||
|
||||
case L'\\':
|
||||
bValid = !PathIsUNCW(pszPath);
|
||||
if (bValid)
|
||||
pSpaceStart = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
bValid = PathIsValidCharW(*pszPath, PATH_VALID_CHARS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pSpaceStart)
|
||||
{
|
||||
while (*pSpaceStart == L' ')
|
||||
++pSpaceStart;
|
||||
return pSpaceStart;
|
||||
}
|
||||
|
||||
return bValid ? pszPath : NULL;
|
||||
}
|
||||
|
||||
static VOID _MakeAppPathKey(PCWSTR pszPath, PWSTR pszDest, UINT cchDest)
|
||||
{
|
||||
HRESULT hr = PathCchCombineEx(pszDest, cchDest,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths",
|
||||
pszPath, PATHCCH_NONE);
|
||||
if (SUCCEEDED(hr))
|
||||
PathCchAddExtension(pszDest, cchDest, L".exe");
|
||||
}
|
||||
|
||||
static BOOL _GetAppPath(PCWSTR pszPath, PWSTR pszValue, DWORD cchValue)
|
||||
{
|
||||
WCHAR szSubKey[MAX_PATH];
|
||||
_MakeAppPathKey(pszPath, szSubKey, _countof(szSubKey));
|
||||
DWORD cbData = cchValue * sizeof(WCHAR);
|
||||
LSTATUS error = SHGetValueW(HKEY_LOCAL_MACHINE, szSubKey, NULL, NULL, pszValue, &cbData);
|
||||
return error == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static HRESULT _PathExeExists(_In_ PCWSTR pszPath)
|
||||
{
|
||||
WCHAR szPath[MAX_PATH];
|
||||
StringCchCopyW(szPath, _countof(szPath), pszPath);
|
||||
|
||||
DWORD dwWhich = WHICH_PIF | WHICH_COM | WHICH_EXE | WHICH_BAT | WHICH_CMD | WHICH_OPTIONAL;
|
||||
DWORD attrs;
|
||||
if (!PathFileExistsDefExtAndAttributesW(szPath, dwWhich, &attrs) ||
|
||||
(attrs & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
return CO_E_APPNOTFOUND;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
_PathFindInFolder(_In_ INT csidl, _In_ PCWSTR pszSrc, _Out_ PWSTR pszPath, _In_ UINT cchPath)
|
||||
{
|
||||
WCHAR szDir[MAX_PATH];
|
||||
HRESULT hr = SHGetFolderPathW(0, csidl, 0, 0, szDir);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = PathCchCombineEx(pszPath, cchPath, szDir, pszSrc, PATHCCH_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return _PathExeExists(pszPath);
|
||||
}
|
||||
|
||||
static HRESULT _PathFindInSystem(_Inout_ PWSTR pszPath, _In_ UINT cchPath)
|
||||
{
|
||||
WCHAR szPath[MAX_PATH];
|
||||
HRESULT hr = _PathFindInFolder(CSIDL_SYSTEM, pszPath, szPath, _countof(szPath));
|
||||
if (FAILED(hr))
|
||||
hr = _PathFindInFolder(CSIDL_WINDOWS, pszPath, szPath, _countof(szPath));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
return StringCchCopyW(pszPath, cchPath, szPath);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHEvaluateSystemCommandTemplate [SHELL32.@] (Vista+)
|
||||
* SHEvaluateSystemCommandTemplate [SHLWAPI.552] (XP SP1 and SP2)
|
||||
*
|
||||
* https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shevaluatesystemcommandtemplate
|
||||
* https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.16299.0/um/shellapi.h#L525
|
||||
*/
|
||||
EXTERN_C
|
||||
HRESULT WINAPI
|
||||
SHEvaluateSystemCommandTemplate(
|
||||
_In_ PCWSTR pszCmdTemplate,
|
||||
_Outptr_ PWSTR *ppszApplication,
|
||||
_Outptr_opt_ PWSTR *ppszCommandLine,
|
||||
_Outptr_opt_ PWSTR *ppszParameters)
|
||||
{
|
||||
HRESULT hr;
|
||||
BOOL bQuoted;
|
||||
WCHAR szExe[MAX_PATH], szProgram[MAX_PATH];
|
||||
|
||||
PCWSTR pszArgs = _PathGetArgsLikeCreateProcess(pszCmdTemplate);
|
||||
UINT cchArgs = (UINT)(pszArgs - pszCmdTemplate);
|
||||
hr = _PathCopyExeAndTrimWhiteSpaces(szExe, _countof(szExe), pszCmdTemplate, cchArgs);
|
||||
if (FAILED(hr))
|
||||
goto Exit;
|
||||
|
||||
// Unquote if necessary
|
||||
bQuoted = (szExe[0] == L'"');
|
||||
if (bQuoted)
|
||||
PathUnquoteSpacesW(szExe);
|
||||
|
||||
hr = StringCchCopyW(szProgram, _countof(szProgram), szExe);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
if (PathIsAbsolute(szExe))
|
||||
{
|
||||
if (bQuoted)
|
||||
{
|
||||
hr = _PathExeExists(szExe);
|
||||
}
|
||||
else // Not quoted
|
||||
{
|
||||
if (_PathMatchesSuspicious(szExe)) // ProgramFiles-likely?
|
||||
hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
|
||||
else
|
||||
hr = _PathExeExists(szExe);
|
||||
}
|
||||
|
||||
// Detect where the full executable path ends and the arguments start
|
||||
while (FAILED(hr))
|
||||
{
|
||||
if (bQuoted || !*pszArgs)
|
||||
break;
|
||||
|
||||
pszArgs = _PathGuessNextBestArgs(pszArgs);
|
||||
if (!pszArgs)
|
||||
break;
|
||||
|
||||
cchArgs = (UINT)(pszArgs - pszCmdTemplate);
|
||||
hr = _PathCopyExeAndTrimWhiteSpaces(szExe, _countof(szExe), pszCmdTemplate, cchArgs);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
hr = _PathExeExists(szExe);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!PathIsFileSpecW(szExe))
|
||||
{
|
||||
hr = E_ACCESSDENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (_GetAppPath(szExe, szExe, _countof(szExe)))
|
||||
{
|
||||
hr = StringCchCopyW(szProgram, _countof(szProgram), PathFindFileNameW(szExe));
|
||||
}
|
||||
else if (SHWindowsPolicyEx(POLID_UsePathEnvVarForCommandTemplates, FALSE))
|
||||
{
|
||||
hr = PathFindOnPathExW(szExe, NULL, PATH_VALID_CHARS) ? S_OK : CO_E_APPNOTFOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = _PathFindInSystem(szExe, _countof(szExe));
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
*ppszApplication = NULL;
|
||||
if (ppszCommandLine)
|
||||
*ppszCommandLine = NULL;
|
||||
if (ppszParameters)
|
||||
*ppszParameters = NULL;
|
||||
|
||||
if (!pszArgs)
|
||||
pszArgs = L"";
|
||||
|
||||
// Create output strings
|
||||
if (SUCCEEDED(hr))
|
||||
hr = SHStrDupW(szExe, ppszApplication);
|
||||
|
||||
if (SUCCEEDED(hr) && ppszCommandLine)
|
||||
{
|
||||
size_t cch = lstrlenW(szProgram) + lstrlenW(pszArgs) + 4; // 4 for '"', '"', ' ', NUL
|
||||
hr = SHCoAlloc(cch * sizeof(WCHAR), (PVOID*)ppszCommandLine);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = StringCchPrintfW(*ppszCommandLine, cch, L"\"%s\" %s", szProgram, pszArgs);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr) && ppszParameters)
|
||||
hr = SHStrDupW(pszArgs, ppszParameters);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Clean up
|
||||
if (*ppszApplication)
|
||||
{
|
||||
CoTaskMemFree(*ppszApplication);
|
||||
*ppszApplication = NULL;
|
||||
}
|
||||
if (ppszCommandLine && *ppszCommandLine)
|
||||
{
|
||||
CoTaskMemFree(*ppszCommandLine);
|
||||
*ppszCommandLine = NULL;
|
||||
}
|
||||
if (ppszParameters && *ppszParameters)
|
||||
{
|
||||
CoTaskMemFree(*ppszParameters);
|
||||
*ppszParameters = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
@@ -505,7 +505,7 @@
|
||||
@ stdcall SHEmptyRecycleBinW(long wstr long) # 2k3:285, Vista:344
|
||||
@ stub SHEnableServiceObject # 2k3:286, Vista:345
|
||||
@ stdcall SHEnumerateUnreadMailAccountsW(ptr long ptr long) # 2k3:287, Vista:346
|
||||
@ stub -version=0x600+ SHEvaluateSystemCommandTemplate # Vista:347
|
||||
@ stdcall -version=0x600+ SHEvaluateSystemCommandTemplate(wstr ptr ptr ptr) # Vista:347
|
||||
@ stdcall SHExtractIconsW(wstr long long long ptr ptr long long) user32.PrivateExtractIconsW # 2k3:288, Vista:348
|
||||
@ stdcall SHFileOperation(ptr) SHFileOperationA # 2k3:289, Vista:349
|
||||
@ stdcall SHFileOperationA(ptr) # 2k3:290, Vista:350
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
#include <winbase.h>
|
||||
#include <shlobj.h>
|
||||
#include <initguid.h>
|
||||
#include <shlwapi_undoc.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shlwapi_undoc.h>
|
||||
#include <wine/debug.h>
|
||||
|
||||
#include "shell32_main.h"
|
||||
|
||||
@@ -69,6 +69,9 @@ add_dependencies(shlwapi_autocomp psdk)
|
||||
|
||||
set_module_type(shlwapi win32dll UNICODE)
|
||||
target_link_libraries(shlwapi uuid wine crtheap cppstl)
|
||||
if(DLL_EXPORT_VERSION LESS 0x600)
|
||||
target_link_libraries(shlwapi evalcmd)
|
||||
endif()
|
||||
add_delay_importlibs(shlwapi userenv oleaut32 ole32 comctl32 comdlg32 mpr mlang urlmon shell32 winmm version)
|
||||
add_importlibs(shlwapi shcore user32 gdi32 advapi32 wininet msvcrt kernelbase kernel32 kernel32_vista ntdll)
|
||||
#add_pch(shlwapi precomp.h "${PCH_SKIP_SOURCE}")
|
||||
|
||||
@@ -545,7 +545,7 @@
|
||||
549 stdcall -noname SHCoCreateInstanceAC(ptr ptr long ptr ptr)
|
||||
550 stub -noname GetTemplateInfoFromHandle
|
||||
551 stdcall -noname IShellFolder_CompareIDs(ptr ptr ptr ptr)
|
||||
552 stdcall -stub -noname -version=0x501-0x502 SHEvaluateSystemCommandTemplate(wstr ptr ptr ptr)
|
||||
552 stdcall -noname -version=0x501-0x502 SHEvaluateSystemCommandTemplate(wstr ptr ptr ptr)
|
||||
553 stdcall IsInternetESCEnabled()
|
||||
554 stdcall -noname -stub SHGetAllAccessSA()
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <urlmon.h>
|
||||
#include <shlobj.h>
|
||||
#define NO_SHLWAPI_REG
|
||||
#include <shlwapi.h>
|
||||
#include <shlwapi_undoc.h>
|
||||
#include <wine/debug.h>
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ list(APPEND SOURCE
|
||||
SHCreateDataObject.cpp
|
||||
SHCreateFileDataObject.cpp
|
||||
SHCreateFileExtractIconW.cpp
|
||||
SHEvaluateSystemCommandTemplate.cpp
|
||||
SHGetComputerDisplayNameW.cpp
|
||||
SHGetUnreadMailCountW.cpp
|
||||
SHIsBadInterfacePtr.cpp
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* PROJECT: ReactOS api tests
|
||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||
* PURPOSE: Tests for SHEvaluateSystemCommandTemplate
|
||||
* COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ <[email protected]>
|
||||
*/
|
||||
|
||||
#include "shelltest.h"
|
||||
#include <strsafe.h>
|
||||
#include <versionhelpers.h>
|
||||
|
||||
typedef HRESULT (WINAPI *FN_SHEvaluateSystemCommandTemplate)(PCWSTR, PWSTR*, PWSTR*, PWSTR*);
|
||||
static FN_SHEvaluateSystemCommandTemplate g_fnSHEvaluateSystemCommandTemplate = NULL;
|
||||
|
||||
#define ok_wstri(x, y) \
|
||||
ok(lstrcmpiW(x, y) == 0, "Wrong string. Expected %s, got %s\n", wine_dbgstr_w(y), wine_dbgstr_w(x))
|
||||
|
||||
static BOOL TEST_Init(void)
|
||||
{
|
||||
HINSTANCE hShell32 = GetModuleHandleA("shell32");
|
||||
g_fnSHEvaluateSystemCommandTemplate = (FN_SHEvaluateSystemCommandTemplate)
|
||||
GetProcAddress(hShell32, "SHEvaluateSystemCommandTemplate");
|
||||
if (g_fnSHEvaluateSystemCommandTemplate)
|
||||
return TRUE;
|
||||
|
||||
HINSTANCE hSHLWAPI = GetModuleHandleA("shlwapi");
|
||||
g_fnSHEvaluateSystemCommandTemplate = (FN_SHEvaluateSystemCommandTemplate)
|
||||
GetProcAddress(hSHLWAPI, MAKEINTRESOURCEA(552));
|
||||
if (g_fnSHEvaluateSystemCommandTemplate)
|
||||
{
|
||||
trace("shlwapi has SHEvaluateSystemCommandTemplate\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
skip("SHEvaluateSystemCommandTemplate not found\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void TEST_notepad(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
PWSTR app, cmdline, params;
|
||||
WCHAR szPath[MAX_PATH], szQuoted[MAX_PATH], szNotepad[MAX_PATH];
|
||||
WCHAR szAnswer1[MAX_PATH], szAnswer2[MAX_PATH], szAnswer3[MAX_PATH];
|
||||
|
||||
GetSystemDirectoryW(szNotepad, _countof(szNotepad));
|
||||
StringCchCatW(szNotepad, _countof(szNotepad), L"\\notepad.exe");
|
||||
StringCchPrintfW(szAnswer1, _countof(szAnswer1), L"\"%s\"", szNotepad);
|
||||
StringCchPrintfW(szAnswer2, _countof(szAnswer2), L"\"%s\" ", szNotepad);
|
||||
StringCchPrintfW(szAnswer3, _countof(szAnswer3), L"\"%s\" /A /P", szNotepad);
|
||||
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(L"notepad.exe", &app, NULL, NULL);
|
||||
ok_hr(hr, S_OK);
|
||||
ok_wstri(app, szNotepad);
|
||||
CoTaskMemFree(app);
|
||||
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(L"notepad.exe", &app, &cmdline, NULL);
|
||||
ok_hr(hr, S_OK);
|
||||
ok_wstri(app, szNotepad);
|
||||
ok_wstri(cmdline, L"\"notepad.exe\" ");
|
||||
CoTaskMemFree(app);
|
||||
CoTaskMemFree(cmdline);
|
||||
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(L"notepad.exe", &app, &cmdline, ¶ms);
|
||||
ok_hr(hr, S_OK);
|
||||
ok_wstri(app, szNotepad);
|
||||
ok_wstri(cmdline, L"\"notepad.exe\" ");
|
||||
ok_wstri(params, L"");
|
||||
CoTaskMemFree(app);
|
||||
CoTaskMemFree(cmdline);
|
||||
CoTaskMemFree(params);
|
||||
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(L"notepad.exe", &app, NULL, ¶ms);
|
||||
ok_hr(hr, S_OK);
|
||||
ok_wstri(app, szNotepad);
|
||||
ok_wstri(params, L"");
|
||||
CoTaskMemFree(app);
|
||||
CoTaskMemFree(params);
|
||||
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(L"system32\\notepad.exe", &app, &cmdline, ¶ms);
|
||||
ok_hr(hr, E_ACCESSDENIED);
|
||||
ok(app == NULL, "app was %s\n", wine_dbgstr_w(app));
|
||||
ok(cmdline == NULL, "cmdline was %s\n", wine_dbgstr_w(cmdline));
|
||||
ok(params == NULL, "params was %s\n", wine_dbgstr_w(params));
|
||||
CoTaskMemFree(app);
|
||||
CoTaskMemFree(cmdline);
|
||||
CoTaskMemFree(params);
|
||||
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(L"notepad.exe /A /P", &app, &cmdline, ¶ms);
|
||||
ok_hr(hr, S_OK);
|
||||
ok_wstri(app, szNotepad);
|
||||
ok_wstri(cmdline, L"\"notepad.exe\" /A /P");
|
||||
ok_wstri(params, L"/A /P");
|
||||
CoTaskMemFree(app);
|
||||
CoTaskMemFree(cmdline);
|
||||
CoTaskMemFree(params);
|
||||
|
||||
StringCchCopyW(szPath, _countof(szPath), szNotepad);
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(szPath, &app, NULL, NULL);
|
||||
ok_hr(hr, S_OK);
|
||||
ok_wstri(app, szNotepad);
|
||||
CoTaskMemFree(app);
|
||||
|
||||
StringCchCopyW(szPath, _countof(szPath), szNotepad);
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(szPath, &app, NULL, ¶ms);
|
||||
ok_hr(hr, S_OK);
|
||||
ok_wstri(app, szNotepad);
|
||||
ok_wstri(params, L"");
|
||||
CoTaskMemFree(app);
|
||||
CoTaskMemFree(params);
|
||||
|
||||
StringCchCopyW(szPath, _countof(szPath), szNotepad);
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(szPath, &app, &cmdline, ¶ms);
|
||||
ok_hr(hr, S_OK);
|
||||
ok_wstri(app, szNotepad);
|
||||
ok_wstri(cmdline, szAnswer2);
|
||||
ok_wstri(params, L"");
|
||||
CoTaskMemFree(app);
|
||||
CoTaskMemFree(cmdline);
|
||||
CoTaskMemFree(params);
|
||||
|
||||
StringCchPrintfW(szQuoted, _countof(szQuoted), L"\"%s\"", szNotepad);
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(szQuoted, &app, &cmdline, ¶ms);
|
||||
ok_hr(hr, S_OK);
|
||||
ok_wstri(app, szNotepad);
|
||||
ok_wstri(cmdline, szAnswer2);
|
||||
ok_wstri(params, L"");
|
||||
CoTaskMemFree(app);
|
||||
CoTaskMemFree(cmdline);
|
||||
CoTaskMemFree(params);
|
||||
|
||||
StringCchPrintfW(szQuoted, _countof(szQuoted), L"\"%s\" /A /P", szNotepad);
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(szQuoted, &app, &cmdline, ¶ms);
|
||||
ok_hr(hr, S_OK);
|
||||
ok_wstri(app, szNotepad);
|
||||
ok_wstri(cmdline, szAnswer3);
|
||||
ok_wstri(params, L"/A /P");
|
||||
CoTaskMemFree(app);
|
||||
CoTaskMemFree(cmdline);
|
||||
CoTaskMemFree(params);
|
||||
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(L"_invalid_\\_path_", &app, &cmdline, ¶ms);
|
||||
ok_hr(hr, E_ACCESSDENIED);
|
||||
ok(app == NULL, "app was %s\n", wine_dbgstr_w(app));
|
||||
ok(cmdline == NULL, "cmdline was %s\n", wine_dbgstr_w(cmdline));
|
||||
ok(params == NULL, "params was %s\n", wine_dbgstr_w(params));
|
||||
CoTaskMemFree(app);
|
||||
CoTaskMemFree(cmdline);
|
||||
CoTaskMemFree(params);
|
||||
|
||||
hr = g_fnSHEvaluateSystemCommandTemplate(L"%SystemRoot%\\system32\\notepad.exe", &app, &cmdline, ¶ms);
|
||||
ok_hr(hr, E_ACCESSDENIED);
|
||||
ok(app == NULL, "app was %s\n", wine_dbgstr_w(app));
|
||||
ok(cmdline == NULL, "cmdline was %s\n", wine_dbgstr_w(cmdline));
|
||||
ok(params == NULL, "params was %s\n", wine_dbgstr_w(params));
|
||||
CoTaskMemFree(app);
|
||||
CoTaskMemFree(cmdline);
|
||||
CoTaskMemFree(params);
|
||||
}
|
||||
|
||||
START_TEST(SHEvaluateSystemCommandTemplate)
|
||||
{
|
||||
if (!TEST_Init())
|
||||
return;
|
||||
|
||||
TEST_notepad();
|
||||
}
|
||||
@@ -37,6 +37,7 @@ extern void func_SHCreateFileDataObject(void);
|
||||
extern void func_SHCreateFileExtractIconW(void);
|
||||
extern void func_SHDefExtractIcon(void);
|
||||
extern void func_SHEnumerateUnreadMailAccountsW(void);
|
||||
extern void func_SHEvaluateSystemCommandTemplate(void);
|
||||
extern void func_She(void);
|
||||
extern void func_ShellExec_RunDLL(void);
|
||||
extern void func_ShellExecCmdLine(void);
|
||||
@@ -95,6 +96,7 @@ const struct test winetest_testlist[] =
|
||||
{ "SHCreateFileExtractIconW", func_SHCreateFileExtractIconW },
|
||||
{ "SHDefExtractIcon", func_SHDefExtractIcon },
|
||||
{ "SHEnumerateUnreadMailAccountsW", func_SHEnumerateUnreadMailAccountsW },
|
||||
{ "SHEvaluateSystemCommandTemplate", func_SHEvaluateSystemCommandTemplate },
|
||||
{ "She", func_She },
|
||||
//{ "ShellExec_RunDLL", func_ShellExec_RunDLL }, Broke on Windows
|
||||
//{ "ShellExecCmdLine", func_ShellExecCmdLine }, Broke on Windows
|
||||
|
||||
@@ -572,6 +572,14 @@ ShellExecuteW(
|
||||
|
||||
BOOL WINAPI ShellExecuteExA(_Inout_ LPSHELLEXECUTEINFOA);
|
||||
BOOL WINAPI ShellExecuteExW(_Inout_ LPSHELLEXECUTEINFOW);
|
||||
|
||||
HRESULT WINAPI
|
||||
SHEvaluateSystemCommandTemplate(
|
||||
_In_ PCWSTR pszCmdTemplate,
|
||||
_Outptr_ PWSTR *ppszApplication,
|
||||
_Outptr_opt_ PWSTR *ppszCommandLine,
|
||||
_Outptr_opt_ PWSTR *ppszParameters);
|
||||
|
||||
int WINAPI SHFileOperationA(_Inout_ LPSHFILEOPSTRUCTA);
|
||||
int WINAPI SHFileOperationW(_Inout_ LPSHFILEOPSTRUCTW);
|
||||
void WINAPI SHFreeNameMappings(_In_opt_ HANDLE);
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
|
||||
#include <winreg.h> // For REGSAM
|
||||
|
||||
#if !defined(_INC_SHLWAPI) && !defined(__WINE_SHLWAPI_H)
|
||||
#error Please #include <shlwapi.h> first
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -536,6 +540,27 @@ SHWindowsPolicyGetValue(
|
||||
|
||||
#define E_DATATYPE_MISMATCH HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH)
|
||||
|
||||
static inline BOOL
|
||||
PathIsAbsolute(_In_ PCWSTR pszPath)
|
||||
{
|
||||
return (PathGetDriveNumberW(pszPath) != -1 && pszPath[2] == L'\\') || PathIsUNCW(pszPath);
|
||||
}
|
||||
|
||||
static inline HRESULT
|
||||
SHCoAlloc(_In_ SIZE_T cb, _Outptr_ PVOID* ppData)
|
||||
{
|
||||
*ppData = CoTaskMemAlloc(cb);
|
||||
return *ppData ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
static inline DWORD
|
||||
SHWindowsPolicyEx(_In_ REFGUID rpolid, _In_ DWORD dwDefaultValue)
|
||||
{
|
||||
DWORD dwData, cbData = sizeof(dwData);
|
||||
HRESULT hr = SHWindowsPolicyGetValue(rpolid, &dwData, &cbData);
|
||||
return (SUCCEEDED(hr) ? dwData : dwDefaultValue);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* ZoneCheck*
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user