https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4c1e83d5145c2433a21533e3d098107422bea8b6

commit 4c1e83d5145c2433a21533e3d098107422bea8b6
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Tue Feb 21 09:17:47 2023 +0900
Commit:     GitHub <[email protected]>
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 
<[email protected]>
+ */
+
+#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"@SHLoadRegUIString.dll%EmptyEnvVar%,-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 }
 };

Reply via email to