[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:
Katayama Hirofumi MZ
2026-06-24 20:35:37 +09:00
committed by GitHub
parent afbc922405
commit 546297fe86
17 changed files with 531 additions and 5 deletions
+1
View File
@@ -8,6 +8,7 @@
*/
#include "kbswitch.h"
#include <shlobj.h>
#include <shlwapi.h>
#include <shlwapi_undoc.h>
#include <undocuser.h>
#include <imm.h>
+1
View File
@@ -42,6 +42,7 @@
#include <ui/rosctrls.h>
#include <windowsx.h>
#include <shlwapi.h>
#include <shlwapi_undoc.h>
#include <process.h>
#undef SubclassWindow
+1 -1
View File
@@ -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);
}
+1 -1
View File
@@ -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);
+4
View File
@@ -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
+11
View File
@@ -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()
+302
View File
@@ -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;
}
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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"
+3
View File
@@ -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}")
+1 -1
View File
@@ -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()
+1
View File
@@ -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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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
+8
View File
@@ -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);
+25
View File
@@ -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*
*/