[SHLWAPI][SHLWAPI_APITEST] Expand string in SHLoadIndirectString (#5084)

- shlwapi!SHLoadIndirectString expands the environmental strings if the first character was '@'.
- Implement SHLoadRegUIStringA function.
CORE-10667
This commit is contained in:
Katayama Hirofumi MZ 2023-02-21 09:17:47 +09:00 committed by GitHub
parent acd3148c1a
commit 4c1e83d514
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 138 additions and 2 deletions

View file

@ -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]
*/

View file

@ -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)

View file

@ -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, ',');

View file

@ -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)

View file

@ -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@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"@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");
}

View file

@ -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 }
};