https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4c1e83d5145c2433a2153…
commit 4c1e83d5145c2433a21533e3d098107422bea8b6
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Tue Feb 21 09:17:47 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Tue Feb 21 09:17:47 2023 +0900
[SHLWAPI][SHLWAPI_APITEST] Expand string in SHLoadIndirectString (#5084)
- shlwapi!SHLoadIndirectString expands the environmental strings if the first
character was '@'.
- Implement SHLoadRegUIStringA function.
CORE-10667
---
dll/win32/shlwapi/ordinal.c | 27 ++++++
dll/win32/shlwapi/shlwapi.spec | 2 +-
dll/win32/shlwapi/string.c | 10 +++
modules/rostests/apitests/shlwapi/CMakeLists.txt | 3 +-
.../rostests/apitests/shlwapi/SHLoadRegUIString.c | 96 ++++++++++++++++++++++
modules/rostests/apitests/shlwapi/testlist.c | 2 +
6 files changed, 138 insertions(+), 2 deletions(-)
diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c
index b8b93a60372..8286fe22e2f 100644
--- a/dll/win32/shlwapi/ordinal.c
+++ b/dll/win32/shlwapi/ordinal.c
@@ -4121,6 +4121,33 @@ BOOL WINAPI IsOS(DWORD feature)
return FALSE;
}
+#ifdef __REACTOS__
+/*************************************************************************
+ * @ [SHLWAPI.438]
+ */
+HRESULT WINAPI SHLoadRegUIStringA(HKEY hkey, LPCSTR value, LPSTR buf, DWORD size)
+{
+ WCHAR valueW[MAX_PATH], bufferW[MAX_PATH];
+ DWORD dwSize = ARRAY_SIZE(bufferW) * sizeof(CHAR);
+ HRESULT hr;
+
+ MultiByteToWideChar(CP_ACP, 0, value, -1, valueW, ARRAY_SIZE(valueW));
+ valueW[ARRAY_SIZE(valueW) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
+
+ if (RegQueryValueExW(hkey, valueW, NULL, NULL, (LPBYTE)bufferW, &dwSize) !=
ERROR_SUCCESS)
+ return E_FAIL;
+
+ hr = SHLoadIndirectString(bufferW, bufferW, ARRAY_SIZE(bufferW), NULL);
+ if (FAILED(hr))
+ return hr;
+
+ WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buf, size, NULL, NULL);
+ if (size > 0)
+ buf[size - 1] = ANSI_NULL; /* Avoid buffer overrun */
+ return S_OK;
+}
+#endif
+
/*************************************************************************
* @ [SHLWAPI.439]
*/
diff --git a/dll/win32/shlwapi/shlwapi.spec b/dll/win32/shlwapi/shlwapi.spec
index dd1e3cd7d1b..bcd304fda15 100644
--- a/dll/win32/shlwapi/shlwapi.spec
+++ b/dll/win32/shlwapi/shlwapi.spec
@@ -435,7 +435,7 @@
435 stdcall -noname CLSIDFromProgIDWrap(wstr ptr) ole32.CLSIDFromProgID
436 stdcall -noname CLSIDFromStringWrap(wstr ptr)
437 stdcall -noname IsOS(long)
-438 stub -noname SHLoadRegUIStringA
+438 stdcall -noname SHLoadRegUIStringA(ptr str ptr long)
439 stdcall -noname SHLoadRegUIStringW(ptr wstr ptr long)
440 stdcall -noname SHGetWebFolderFilePathA(str ptr long)
441 stdcall -noname SHGetWebFolderFilePathW(wstr ptr long)
diff --git a/dll/win32/shlwapi/string.c b/dll/win32/shlwapi/string.c
index cb6489b7030..6dc9ff8e59d 100644
--- a/dll/win32/shlwapi/string.c
+++ b/dll/win32/shlwapi/string.c
@@ -2878,6 +2878,9 @@ HRESULT WINAPI SHLoadIndirectString(LPCWSTR src, LPWSTR dst, UINT
dst_len, void
WCHAR *dllname = NULL;
HMODULE hmod = NULL;
HRESULT hr = E_FAIL;
+#ifdef __REACTOS__
+ WCHAR szExpanded[512];
+#endif
TRACE("(%s %p %08x %p)\n", debugstr_w(src), dst, dst_len, reserved);
@@ -2886,6 +2889,13 @@ HRESULT WINAPI SHLoadIndirectString(LPCWSTR src, LPWSTR dst, UINT
dst_len, void
WCHAR *index_str;
int index;
+#ifdef __REACTOS__
+ if (wcschr(src, '%') != NULL)
+ {
+ ExpandEnvironmentStringsW(src, szExpanded, ARRAY_SIZE(szExpanded));
+ src = szExpanded;
+ }
+#endif
dst[0] = 0;
dllname = StrDupW(src + 1);
index_str = strchrW(dllname, ',');
diff --git a/modules/rostests/apitests/shlwapi/CMakeLists.txt
b/modules/rostests/apitests/shlwapi/CMakeLists.txt
index 9712d77969b..47636a5cae6 100644
--- a/modules/rostests/apitests/shlwapi/CMakeLists.txt
+++ b/modules/rostests/apitests/shlwapi/CMakeLists.txt
@@ -13,6 +13,7 @@ list(APPEND SOURCE
PathUnExpandEnvStringsForUser.c
SHAreIconsEqual.c
SHLoadIndirectString.c
+ SHLoadRegUIString.c
StrFormatByteSizeW.c
testdata.rc
testlist.c)
@@ -23,6 +24,6 @@ add_rc_deps(testdata.rc
${CMAKE_CURRENT_BINARY_DIR}/shlwapi_resource_dll/shlwapi
add_executable(shlwapi_apitest ${SOURCE})
set_module_type(shlwapi_apitest win32cui)
target_link_libraries(shlwapi_apitest ${PSEH_LIB})
-add_importlibs(shlwapi_apitest shlwapi user32 msvcrt kernel32)
+add_importlibs(shlwapi_apitest shlwapi user32 advapi32 msvcrt kernel32)
add_dependencies(shlwapi_apitest shlwapi_resource_dll)
add_rostests_file(TARGET shlwapi_apitest)
diff --git a/modules/rostests/apitests/shlwapi/SHLoadRegUIString.c
b/modules/rostests/apitests/shlwapi/SHLoadRegUIString.c
new file mode 100644
index 00000000000..d761853801a
--- /dev/null
+++ b/modules/rostests/apitests/shlwapi/SHLoadRegUIString.c
@@ -0,0 +1,96 @@
+/*
+ * PROJECT: ReactOS api tests
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: Tests for SHLoadRegUIStringA/W
+ * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
+ */
+
+#include <apitest.h>
+#include <shlwapi.h>
+
+typedef HRESULT (WINAPI *FN_SHLoadRegUIStringA)(HKEY hkey, LPCSTR value, LPSTR buf, DWORD
size);
+typedef HRESULT (WINAPI *FN_SHLoadRegUIStringW)(HKEY hkey, LPCWSTR value, LPWSTR buf,
DWORD size);
+
+static FN_SHLoadRegUIStringA pSHLoadRegUIStringA = NULL;
+static FN_SHLoadRegUIStringW pSHLoadRegUIStringW = NULL;
+
+static void test_SHLoadRegUIStringA(HKEY hKey)
+{
+ HRESULT hr;
+ CHAR szBuff[MAX_PATH];
+
+ hr = pSHLoadRegUIStringA(hKey, "TestValue1", szBuff, _countof(szBuff));
+ ok_long(hr, S_OK);
+ ok_str(szBuff, "%WINDIR%\\TEST");
+
+ hr = pSHLoadRegUIStringA(hKey, "TestValue2", szBuff, _countof(szBuff));
+ ok_long(hr, S_OK);
+ ok_str(szBuff, "Test string one.");
+}
+
+static void test_SHLoadRegUIStringW(HKEY hKey)
+{
+ HRESULT hr;
+ WCHAR szBuff[MAX_PATH];
+
+ hr = pSHLoadRegUIStringW(hKey, L"TestValue1", szBuff, _countof(szBuff));
+ ok_long(hr, S_OK);
+ ok_wstr(szBuff, L"%WINDIR%\\TEST");
+
+ hr = pSHLoadRegUIStringW(hKey, L"TestValue2", szBuff, _countof(szBuff));
+ ok_long(hr, S_OK);
+ ok_wstr(szBuff, L"Test string one.");
+}
+
+BOOL extract_resource(const WCHAR* Filename, LPCWSTR ResourceName);
+
+START_TEST(SHLoadRegUIString)
+{
+ LONG error;
+ HKEY hKey;
+ DWORD cbValue;
+ static const WCHAR s_szTestValue1[] = L"%WINDIR%\\TEST";
+ static const WCHAR s_szTestValue2[] =
L"(a)SHLoadRegUIString.dll%EmptyEnvVar%,-3"%,-3";
+ HMODULE hSHLWAPI;
+
+ SetEnvironmentVariableW(L"EmptyEnvVar", L"");
+
+ /* Get procedures */
+ hSHLWAPI = GetModuleHandleW(L"shlwapi");
+ pSHLoadRegUIStringA = (FN_SHLoadRegUIStringA)GetProcAddress(hSHLWAPI, (LPCSTR)438);
+ pSHLoadRegUIStringW = (FN_SHLoadRegUIStringW)GetProcAddress(hSHLWAPI, (LPCSTR)439);
+ if (!pSHLoadRegUIStringA || !pSHLoadRegUIStringW)
+ {
+ skip("No procedure found\n");
+ return;
+ }
+
+ if (!extract_resource(L"SHLoadRegUIString.dll", MAKEINTRESOURCEW(101)))
+ {
+ skip("File 'SHLoadRegUIString.dll' cannot be extracted\n");
+ return;
+ }
+
+ /* Open registry key and write some test values */
+ error = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software", 0, KEY_READ |
KEY_WRITE, &hKey);
+ ok_long(error, ERROR_SUCCESS);
+
+ cbValue = (lstrlenW(s_szTestValue1) + 1) * sizeof(WCHAR);
+ error = RegSetValueExW(hKey, L"TestValue1", 0, REG_SZ,
(LPBYTE)s_szTestValue1, cbValue);
+ ok_long(error, ERROR_SUCCESS);
+
+ cbValue = (lstrlenW(s_szTestValue2) + 1) * sizeof(WCHAR);
+ error = RegSetValueExW(hKey, L"TestValue2", 0, REG_SZ,
(LPBYTE)s_szTestValue2, cbValue);
+ ok_long(error, ERROR_SUCCESS);
+
+ /* The main dish */
+ test_SHLoadRegUIStringA(hKey);
+ test_SHLoadRegUIStringW(hKey);
+
+ /* Delete the test values and close the key */
+ RegDeleteValueW(hKey, L"TestValue1");
+ RegDeleteValueW(hKey, L"TestValue2");
+ RegCloseKey(hKey);
+
+ DeleteFileW(L"SHLoadRegUIString.dll");
+}
diff --git a/modules/rostests/apitests/shlwapi/testlist.c
b/modules/rostests/apitests/shlwapi/testlist.c
index 6bf3fe27892..ea30af72bee 100644
--- a/modules/rostests/apitests/shlwapi/testlist.c
+++ b/modules/rostests/apitests/shlwapi/testlist.c
@@ -9,6 +9,7 @@ extern void func_PathUnExpandEnvStrings(void);
extern void func_PathUnExpandEnvStringsForUser(void);
extern void func_SHAreIconsEqual(void);
extern void func_SHLoadIndirectString(void);
+extern void func_SHLoadRegUIString(void);
extern void func_StrFormatByteSizeW(void);
const struct test winetest_testlist[] =
@@ -21,6 +22,7 @@ const struct test winetest_testlist[] =
{ "PathUnExpandEnvStringsForUser", func_PathUnExpandEnvStringsForUser },
{ "SHAreIconsEqual", func_SHAreIconsEqual },
{ "SHLoadIndirectString", func_SHLoadIndirectString },
+ { "SHLoadRegUIString", func_SHLoadRegUIString },
{ "StrFormatByteSizeW", func_StrFormatByteSizeW },
{ 0, 0 }
};