From 157e18b215ce0f5334c4f2ca895447a28d650d16 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Mon, 20 Jan 2025 08:50:26 +0900 Subject: [PATCH] [SHELL32][SHELL32_APITEST][SDK] Implement StrRStrA/W (#7621) Implementing missing features... JIRA issue: CORE-19278 - Move function definitions from stubs.cpp to utils.cpp. - Add prototypes to . --- dll/win32/shell32/stubs.cpp | 22 ----- dll/win32/shell32/utils.cpp | 82 ++++++++++++++++ .../rostests/apitests/shell32/CMakeLists.txt | 1 + modules/rostests/apitests/shell32/StrRStr.cpp | 97 +++++++++++++++++++ modules/rostests/apitests/shell32/testlist.c | 2 + sdk/include/reactos/undocshell.h | 12 +++ 6 files changed, 194 insertions(+), 22 deletions(-) create mode 100644 modules/rostests/apitests/shell32/StrRStr.cpp diff --git a/dll/win32/shell32/stubs.cpp b/dll/win32/shell32/stubs.cpp index 8967dd49ab8..5698b7dc0c8 100644 --- a/dll/win32/shell32/stubs.cpp +++ b/dll/win32/shell32/stubs.cpp @@ -235,28 +235,6 @@ RealDriveTypeFlags(INT iDrive, BOOL bUnknown) return 1; } -/* - * Unimplemented - */ -EXTERN_C LPWSTR -WINAPI -StrRStrW(LPWSTR lpSrc, LPWSTR lpLast, LPWSTR lpSearch) -{ - FIXME("StrRStrW() stub\n"); - return NULL; -} - -/* - * Unimplemented - */ -EXTERN_C LPWSTR -WINAPI -StrRStrA(LPSTR lpSrc, LPSTR lpLast, LPSTR lpSearch) -{ - FIXME("StrRStrA() stub\n"); - return NULL; -} - /* * Unimplemented */ diff --git a/dll/win32/shell32/utils.cpp b/dll/win32/shell32/utils.cpp index 1f4ff07a88e..831d52d3c1e 100644 --- a/dll/win32/shell32/utils.cpp +++ b/dll/win32/shell32/utils.cpp @@ -13,6 +13,88 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell); +static PCSTR StrEndNA(_In_ PCSTR psz, _In_ INT_PTR cch) +{ + PCSTR pch, pchEnd = &psz[cch]; + for (pch = psz; *pch && pch < pchEnd; pch = CharNextA(pch)) + ; + if (pchEnd < pch) // A double-byte character detected at last? + pch -= 2; // The width of a double-byte character is 2 + return pch; +} + +static PCWSTR StrEndNW(_In_ PCWSTR psz, _In_ INT_PTR cch) +{ + PCWSTR pch, pchEnd = &psz[cch]; + for (pch = psz; *pch && pch < pchEnd; ++pch) + ; + return pch; +} + +/************************************************************************* + * StrRStrA [SHELL32.389] + */ +EXTERN_C +PSTR WINAPI +StrRStrA( + _In_ PCSTR pszSrc, + _In_opt_ PCSTR pszLast, + _In_ PCSTR pszSearch) +{ + INT cchSearch = lstrlenA(pszSearch); + + PCSTR pchEnd = pszLast ? pszLast : &pszSrc[lstrlenA(pszSrc)]; + if (pchEnd == pszSrc) + return NULL; + + INT_PTR cchEnd = pchEnd - pszSrc; + for (;;) + { + --pchEnd; + --cchEnd; + if (!pchEnd) + break; + if (!StrCmpNA(pchEnd, pszSearch, cchSearch) && pchEnd == StrEndNA(pszSrc, cchEnd)) + break; + if (pchEnd == pszSrc) + return NULL; + } + + return const_cast(pchEnd); +} + +/************************************************************************* + * StrRStrW [SHELL32.392] + */ +EXTERN_C +PWSTR WINAPI +StrRStrW( + _In_ PCWSTR pszSrc, + _In_opt_ PCWSTR pszLast, + _In_ PCWSTR pszSearch) +{ + INT cchSearch = lstrlenW(pszSearch); + + PCWSTR pchEnd = pszLast ? pszLast : &pszSrc[lstrlenW(pszSrc)]; + if (pchEnd == pszSrc) + return NULL; + + INT_PTR cchEnd = pchEnd - pszSrc; + for (;;) + { + --pchEnd; + --cchEnd; + if (!pchEnd) + break; + if (!StrCmpNW(pchEnd, pszSearch, cchSearch) && pchEnd == StrEndNW(pszSrc, cchEnd)) + break; + if (pchEnd == pszSrc) + return NULL; + } + + return const_cast(pchEnd); +} + HWND CStubWindow32::FindStubWindow(UINT Type, LPCWSTR Path) { diff --git a/modules/rostests/apitests/shell32/CMakeLists.txt b/modules/rostests/apitests/shell32/CMakeLists.txt index aff71a65c90..cb6c11bcf8e 100644 --- a/modules/rostests/apitests/shell32/CMakeLists.txt +++ b/modules/rostests/apitests/shell32/CMakeLists.txt @@ -47,6 +47,7 @@ list(APPEND SOURCE SHGetUserDisplayName.cpp SHLimitInputEdit.cpp SHSetUnreadMailCountW.cpp + StrRStr.cpp menu.cpp shelltest.cpp) diff --git a/modules/rostests/apitests/shell32/StrRStr.cpp b/modules/rostests/apitests/shell32/StrRStr.cpp new file mode 100644 index 00000000000..a78181f791f --- /dev/null +++ b/modules/rostests/apitests/shell32/StrRStr.cpp @@ -0,0 +1,97 @@ +/* + * PROJECT: ReactOS API tests + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: Test for StrRStrA/W + * COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + */ + +#include "shelltest.h" +#include + +typedef PSTR (WINAPI *FN_StrRStrA)(PCSTR, PCSTR, PCSTR pszSearch); +typedef PWSTR (WINAPI *FN_StrRStrW)(PCWSTR, PCWSTR, PCWSTR pszSearch); + +static VOID TEST_StrRStrA(VOID) +{ + PCSTR psz, pch; + PSTR ret; + FN_StrRStrA StrRStrA = (FN_StrRStrA)GetProcAddress(GetModuleHandleW(L"shell32"), MAKEINTRESOURCEA(389)); + + if (!StrRStrA) + { + skip("StrRStrA not found\n"); + return; + } + + psz = "ABCBC"; + ret = StrRStrA(psz, NULL, "BC"); + ok_ptr(ret, psz + 3); + + psz = "ABCBC"; + pch = &psz[2]; + ret = StrRStrA(psz, pch, "BC"); + ok_ptr(ret, &psz[1]); + + psz = "ABCBC"; + ret = StrRStrA(psz, psz, "BC"); + ok(!ret, "ret was '%s'\n", ret); + + psz = "ABCBC"; + pch = &psz[lstrlenA(psz)]; + ret = StrRStrA(psz, pch, "BC"); + ok_ptr(ret, psz + 3); +} + +static VOID TEST_StrRStrW(VOID) +{ + PCWSTR psz, pch; + PWSTR ret; + FN_StrRStrW StrRStrW = (FN_StrRStrW)GetProcAddress(GetModuleHandleW(L"shell32"), MAKEINTRESOURCEA(392)); + + if (!StrRStrW) + { + skip("StrRStrW not found\n"); + return; + } + + psz = L"ABCBC"; + ret = StrRStrW(psz, NULL, L"BC"); + ok_ptr(ret, psz + 3); + + psz = L"ABCBC"; + pch = &psz[2]; + ret = StrRStrW(psz, pch, L"BC"); + ok_ptr(ret, &psz[1]); + + psz = L"ABCBC"; + ret = StrRStrW(psz, psz, L"BC"); + ok(!ret, "ret was '%S'\n", ret); + + psz = L"ABCBC"; + pch = &psz[lstrlenW(psz)]; + ret = StrRStrW(psz, pch, L"BC"); + ok_ptr(ret, psz + 3); +} + +static BOOL IsWindowsServer2003SP2OrGreater(VOID) +{ + return IsWindowsVersionOrGreater(5, 2, 2); +} + +START_TEST(StrRStr) +{ + if (IsWindowsVistaOrGreater()) + { + skip("Vista+\n"); + return; + } + + if (!IsWindowsServer2003SP2OrGreater()) + { + skip("Before 2K3 SP3\n"); + return; + } + + TEST_StrRStrA(); + TEST_StrRStrW(); +} diff --git a/modules/rostests/apitests/shell32/testlist.c b/modules/rostests/apitests/shell32/testlist.c index daa699a8e32..fc879889ebe 100644 --- a/modules/rostests/apitests/shell32/testlist.c +++ b/modules/rostests/apitests/shell32/testlist.c @@ -51,6 +51,7 @@ extern void func_SHShouldShowWizards(void); extern void func_SHSimpleIDListFromPath(void); extern void func_SHRestricted(void); extern void func_SHSetUnreadMailCountW(void); +extern void func_StrRStr(void); const struct test winetest_testlist[] = { @@ -102,6 +103,7 @@ const struct test winetest_testlist[] = { "SHSimpleIDListFromPath", func_SHSimpleIDListFromPath }, { "SHRestricted", func_SHRestricted }, { "SHSetUnreadMailCountW", func_SHSetUnreadMailCountW }, + { "StrRStr", func_StrRStr }, { 0, 0 } }; diff --git a/sdk/include/reactos/undocshell.h b/sdk/include/reactos/undocshell.h index beb840c89e2..797979334ee 100644 --- a/sdk/include/reactos/undocshell.h +++ b/sdk/include/reactos/undocshell.h @@ -794,6 +794,18 @@ BOOL WINAPI GUIDFromStringW( _In_ PCWSTR psz, _Out_ LPGUID pguid); +PSTR WINAPI +StrRStrA( + _In_ PCSTR pszSrc, + _In_opt_ PCSTR pszLast, + _In_ PCSTR pszSearch); + +PWSTR WINAPI +StrRStrW( + _In_ PCWSTR pszSrc, + _In_opt_ PCWSTR pszLast, + _In_ PCWSTR pszSearch); + LPSTR WINAPI SheRemoveQuotesA(LPSTR psz); LPWSTR WINAPI SheRemoveQuotesW(LPWSTR psz);