From aee5cbdfe359650556f0f9420efcdc43a81fd655 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Tue, 25 Mar 2025 08:34:02 +0900 Subject: [PATCH] [SHELL32_APITEST] Add PathProcessCommand testcase (#7815) JIRA issue: CORE-17659 --- .../rostests/apitests/shell32/CMakeLists.txt | 1 + .../apitests/shell32/PathProcessCommand.cpp | 144 ++++++++++++++++++ modules/rostests/apitests/shell32/testlist.c | 2 + 3 files changed, 147 insertions(+) create mode 100644 modules/rostests/apitests/shell32/PathProcessCommand.cpp diff --git a/modules/rostests/apitests/shell32/CMakeLists.txt b/modules/rostests/apitests/shell32/CMakeLists.txt index 491a7e65017..bea3f3ea271 100644 --- a/modules/rostests/apitests/shell32/CMakeLists.txt +++ b/modules/rostests/apitests/shell32/CMakeLists.txt @@ -25,6 +25,7 @@ list(APPEND SOURCE PathIsEqualOrSubFolder.cpp PathIsTemporary.cpp PathMakeUniqueName.cpp + PathProcessCommand.cpp PathResolve.cpp RealShellExecuteEx.cpp SHAppBarMessage.cpp diff --git a/modules/rostests/apitests/shell32/PathProcessCommand.cpp b/modules/rostests/apitests/shell32/PathProcessCommand.cpp new file mode 100644 index 00000000000..aa401b01cfe --- /dev/null +++ b/modules/rostests/apitests/shell32/PathProcessCommand.cpp @@ -0,0 +1,144 @@ +/* + * PROJECT: ReactOS API tests + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Tests for PathProcessCommand + * COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + */ + +#include "shelltest.h" +#include + +#define ok_wstri(x, y) \ + ok(_wcsicmp(x, y) == 0, "Wrong string. Expected '%S', got '%S'\n", y, x) + +typedef LONG (WINAPI *FN_PathProcessCommand)(LPCWSTR, LPWSTR, INT, DWORD); + +static FN_PathProcessCommand s_PathProcessCommand = NULL; + +static void +Test_PathProcessCommand(void) +{ + WCHAR buffer[MAX_PATH], szCalcExe[MAX_PATH]; + LONG result; + FILE *fout; + WCHAR szCurDir[MAX_PATH]; + WCHAR szFull1[MAX_PATH], szFull2[MAX_PATH], szFull3[MAX_PATH], szFull4[MAX_PATH]; + WCHAR szFull5[MAX_PATH]; + + fout = _wfopen(L"_Test.exe", L"wb"); + fclose(fout); + fout = _wfopen(L"test with spaces.exe", L"wb"); + fclose(fout); + + GetFullPathNameW(L".", _countof(szCurDir), szCurDir, NULL); + GetShortPathNameW(szCurDir, szCurDir, _countof(szCurDir)); + + lstrcpynW(szFull1, szCurDir, _countof(szFull1)); + lstrcpynW(szFull2, szCurDir, _countof(szFull2)); + lstrcpynW(szFull4, szCurDir, _countof(szFull4)); + lstrcpynW(szFull5, szCurDir, _countof(szFull5)); + + lstrcatW(szFull1, L"\\_Test.exe"); + lstrcatW(szFull2, L"\\test with spaces.exe"); + wsprintfW(szFull3, L"\"%s\"", szFull2); + lstrcatW(szFull4, L"\\_Test.exe arg1 arg2"); + lstrcatW(szFull5, L"\\_TestDir.exe"); + + CreateDirectoryW(L"_TestDir.exe", NULL); + + // Test case 1: Basic functionality (no flags) + lstrcpynW(buffer, L"<>", _countof(buffer)); + result = s_PathProcessCommand(L"_Test", buffer, _countof(buffer), 0); + ok_int(result, lstrlenW(szFull1) + 1); + ok_wstri(buffer, szFull1); + + // Test case 2: Quoted path + lstrcpynW(buffer, L"<>", _countof(buffer)); + result = s_PathProcessCommand(L"\"test with spaces\"", buffer, _countof(buffer), 0); + ok_int(result, lstrlenW(szFull2) + 1); + ok_wstri(buffer, szFull2); + + // Test case 3: Add quotes flag + lstrcpynW(buffer, L"<>", _countof(buffer)); + result = s_PathProcessCommand(L"test with spaces", buffer, _countof(buffer), PPCF_ADDQUOTES); + ok_int(result, lstrlenW(szFull3) + 1); + ok_wstri(buffer, szFull3); + + // Test case 4: Add arguments flag + lstrcpynW(buffer, L"<>", _countof(buffer)); + result = s_PathProcessCommand(L"_Test arg1 arg2", buffer, _countof(buffer), PPCF_ADDARGUMENTS); + ok_int(result, lstrlenW(szFull4) + 1); + ok_wstri(buffer, szFull4); + + // calc.exe + GetSystemDirectoryW(szCalcExe, _countof(szCalcExe)); + PathAppendW(szCalcExe, L"calc.exe"); + + // Test case 5: Longest possible flag + lstrcpynW(buffer, L"<>", _countof(buffer)); + result = s_PathProcessCommand(szCalcExe, buffer, _countof(buffer), PPCF_LONGESTPOSSIBLE); + ok_int(result, lstrlenW(szCalcExe) + 1); + ok_wstri(buffer, szCalcExe); + + // Test case 6: Buffer too small + lstrcpynW(buffer, L"<>", _countof(buffer)); + result = s_PathProcessCommand(L"_Test.exe", buffer, 5, 0); + ok_int(result, -1); + ok_wstri(buffer, L"<>"); + + // Test case 7: Null input path + lstrcpynW(buffer, L"<>", _countof(buffer)); + result = s_PathProcessCommand(NULL, buffer, _countof(buffer), 0); + ok_int(result, -1); + ok_wstri(buffer, L"<>"); + + // Test case 8: Relative path resolution + lstrcpynW(buffer, L"<>", _countof(buffer)); + result = s_PathProcessCommand(L"_Test.exe", buffer, _countof(buffer), PPCF_FORCEQUALIFY); + ok_int(result, lstrlenW(szFull1) + 1); + ok_wstri(buffer, szFull1); + + // Test case 9: No directories + lstrcpynW(buffer, L"<>", _countof(buffer)); + result = s_PathProcessCommand(L"_TestDir.exe", buffer, _countof(buffer), PPCF_NODIRECTORIES); + ok_int(result, -1); + ok_wstri(buffer, L"<>"); + + // Test case 10: With directories + lstrcpynW(buffer, L"<>", _countof(buffer)); + result = s_PathProcessCommand(L"_TestDir.exe", buffer, _countof(buffer), 0); + ok_int(result, lstrlenW(szFull5) + 1); + ok_wstri(buffer, szFull5); + + RemoveDirectoryW(L"_TestDir.exe"); + DeleteFileW(L"_Test.exe"); + DeleteFileW(L"test with spaces.exe"); +} + +START_TEST(PathProcessCommand) +{ + WCHAR szCurDir[MAX_PATH], szTempDir[MAX_PATH]; + + s_PathProcessCommand = (FN_PathProcessCommand) + GetProcAddress(GetModuleHandleW(L"shell32"), "PathProcessCommand"); + if (!s_PathProcessCommand) + { + s_PathProcessCommand = (FN_PathProcessCommand) + GetProcAddress(GetModuleHandleW(L"shell32"), MAKEINTRESOURCEA(653)); + } + if (!s_PathProcessCommand) + { + skip("PathProcessCommand not found\n"); + return; + } + + GetCurrentDirectoryW(_countof(szCurDir), szCurDir); + GetEnvironmentVariableW(L"TEMP", szTempDir, _countof(szTempDir)); + SetCurrentDirectoryW(szTempDir); + + SetEnvironmentVariableW(L"PATH", szTempDir); + + Test_PathProcessCommand(); + + SetCurrentDirectoryW(szCurDir); +} diff --git a/modules/rostests/apitests/shell32/testlist.c b/modules/rostests/apitests/shell32/testlist.c index f76eb744a5e..8df6bbc00b6 100644 --- a/modules/rostests/apitests/shell32/testlist.c +++ b/modules/rostests/apitests/shell32/testlist.c @@ -27,6 +27,7 @@ extern void func_OpenAs_RunDLL(void); extern void func_PathIsEqualOrSubFolder(void); extern void func_PathIsTemporary(void); extern void func_PathMakeUniqueName(void); +extern void func_PathProcessCommand(void); extern void func_PathResolve(void); extern void func_PIDL(void); extern void func_RealShellExecuteEx(void); @@ -84,6 +85,7 @@ const struct test winetest_testlist[] = { "PathIsEqualOrSubFolder", func_PathIsEqualOrSubFolder }, { "PathIsTemporary", func_PathIsTemporary }, { "PathMakeUniqueName", func_PathMakeUniqueName }, + { "PathProcessCommand", func_PathProcessCommand }, { "PathResolve", func_PathResolve }, { "PIDL", func_PIDL }, { "RealShellExecuteEx", func_RealShellExecuteEx },