https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a83fedcbfa981f17ab1fb…
commit a83fedcbfa981f17ab1fbd99045f2bdc7d71812e
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Wed Aug 9 08:23:33 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Wed Aug 9 08:23:33 2023 +0900
[SHLWAPI][SHLWAPI_APITEST][SDK] SHGetIniStringW/SHSetIniStringW (#5547)
Follow-up to #5531. These two functions are necessary for INI file property bag
support.
- Implement SHGetIniStringW and SHSetIniStringW.
- Strengthen SHPropertyBag testcase of shlwapi_apitest.
CORE-9283
---
dll/win32/shlwapi/ordinal.c | 104 +++++++++++++++++++++
.../rostests/apitests/shlwapi/SHPropertyBag.cpp | 50 ++++++++++
sdk/include/reactos/shlwapi_undoc.h | 6 ++
3 files changed, 160 insertions(+)
diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c
index f43408d9479..a151d4dce00 100644
--- a/dll/win32/shlwapi/ordinal.c
+++ b/dll/win32/shlwapi/ordinal.c
@@ -47,6 +47,9 @@
#include "commdlg.h"
#include "mlang.h"
#include "mshtmhst.h"
+#ifdef __REACTOS__
+ #include <shlwapi_undoc.h>
+#endif
#include "wine/unicode.h"
#include "wine/debug.h"
@@ -3288,6 +3291,37 @@ BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD
fdwSound)
DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
DWORD outLen, LPCWSTR filename)
{
+#ifdef __REACTOS__
+ WCHAR szSection[MAX_PATH + 2];
+ WCHAR szWideBuff[MAX_PATH];
+ CHAR szUtf7Buff[MAX_PATH];
+
+ TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName), debugstr_w(keyName),
+ out, outLen, debugstr_w(filename));
+
+ if (outLen == 0)
+ return 0;
+
+ /* Try ".W"-appended section name. See also SHSetIniStringW. */
+ lstrcpynW(szSection, appName, _countof(szSection) - 2);
+ lstrcatW(szSection, L".W");
+ GetPrivateProfileStringW(szSection, keyName, NULL, szWideBuff, _countof(szWideBuff),
filename);
+ if (szWideBuff[0] == UNICODE_NULL) /* It's empty or not found */
+ {
+ /* Try the normal section name */
+ return GetPrivateProfileStringW(appName, keyName, NULL, out, outLen, filename);
+ }
+
+ /* Okay, now ".W" version is valid. Its value is a UTF-7 string in UTF-16
*/
+
+ /* szWideBuff --> szUtf7Buff */
+ SHUnicodeToAnsiCP(CP_ACP, szWideBuff, szUtf7Buff, _countof(szUtf7Buff));
+ szUtf7Buff[_countof(szUtf7Buff) - 1] = ANSI_NULL;
+
+ /* szUtf7Buff --> out */
+ SHAnsiToUnicodeCP(CP_UTF7, szUtf7Buff, out, outLen);
+ out[outLen - 1] = UNICODE_NULL;
+#else
INT ret;
WCHAR *buf;
@@ -3310,10 +3344,27 @@ DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName,
LPWSTR out,
*out = 0;
HeapFree(GetProcessHeap(), 0, buf);
+#endif
return strlenW(out);
}
+#ifdef __REACTOS__
+static BOOL Is7BitClean(LPCWSTR psz)
+{
+ if (!psz)
+ return TRUE;
+
+ while (*psz)
+ {
+ if (*psz > 0x7F)
+ return FALSE;
+ ++psz;
+ }
+ return TRUE;
+}
+#endif
+
/*************************************************************************
* @ [SHLWAPI.295]
*
@@ -3333,10 +3384,63 @@ DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName,
LPWSTR out,
BOOL WINAPI SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str,
LPCWSTR filename)
{
+#ifdef __REACTOS__
+ WCHAR szSection[MAX_PATH + 2];
+ WCHAR szWideBuff[MAX_PATH];
+ CHAR szUtf7Buff[MAX_PATH];
+
+ TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str),
+ debugstr_w(filename));
+
+ /* Write a normal profile string. If str was NULL, then key will be deleted */
+ if (!WritePrivateProfileStringW(appName, keyName, str, filename))
+ return FALSE;
+
+ if (Is7BitClean(str))
+ {
+ /* Delete ".A" version */
+ lstrcpynW(szSection, appName, _countof(szSection) - 2);
+ lstrcatW(szSection, L".A");
+ WritePrivateProfileStringW(szSection, keyName, NULL, filename);
+
+ /* Delete ".W" version */
+ lstrcpynW(szSection, appName, _countof(szSection) - 2);
+ lstrcatW(szSection, L".W");
+ WritePrivateProfileStringW(szSection, keyName, NULL, filename);
+
+ return TRUE;
+ }
+
+ /* Now str is not 7-bit clean. It needs UTF-7 encoding in UTF-16.
+ We write ".A" and ".W"-appended sections. */
+
+ /* str --> szUtf7Buff */
+ SHUnicodeToAnsiCP(CP_UTF7, str, szUtf7Buff, _countof(szUtf7Buff));
+ szUtf7Buff[_countof(szUtf7Buff) - 1] = ANSI_NULL;
+
+ /* szUtf7Buff --> szWideBuff */
+ SHAnsiToUnicodeCP(CP_ACP, szUtf7Buff, szWideBuff, _countof(szWideBuff));
+ szWideBuff[_countof(szWideBuff) - 1] = UNICODE_NULL;
+
+ /* Write ".A" version */
+ lstrcpynW(szSection, appName, _countof(szSection) - 2);
+ lstrcatW(szSection, L".A");
+ if (!WritePrivateProfileStringW(szSection, keyName, str, filename))
+ return FALSE;
+
+ /* Write ".W" version */
+ lstrcpynW(szSection, appName, _countof(szSection) - 2);
+ lstrcatW(szSection, L".W");
+ if (!WritePrivateProfileStringW(szSection, keyName, szWideBuff, filename))
+ return FALSE;
+
+ return TRUE;
+#else
TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str),
debugstr_w(filename));
return WritePrivateProfileStringW(appName, keyName, str, filename);
+#endif
}
/*************************************************************************
diff --git a/modules/rostests/apitests/shlwapi/SHPropertyBag.cpp
b/modules/rostests/apitests/shlwapi/SHPropertyBag.cpp
index 365c4478f19..2593cf66c6d 100644
--- a/modules/rostests/apitests/shlwapi/SHPropertyBag.cpp
+++ b/modules/rostests/apitests/shlwapi/SHPropertyBag.cpp
@@ -638,10 +638,60 @@ static void SHPropertyBag_OnRegKey(void)
RegCloseKey(hKey);
}
+static void SHPropertyBag_SHSetIniStringW(void)
+{
+ WCHAR szIniFile[MAX_PATH];
+ WCHAR szValue[MAX_PATH];
+ BOOL bRet;
+ DWORD dwRet;
+
+ ExpandEnvironmentStringsW(L"%TEMP%\\SHSetIniString.ini", szIniFile,
_countof(szIniFile));
+
+ DeleteFileW(szIniFile);
+
+ trace("%ls\n", szIniFile);
+
+ bRet = SHSetIniStringW(L"TestSection", L"Key",
L"Value", szIniFile);
+ ok_int(bRet, TRUE);
+
+ WritePrivateProfileStringW(NULL, NULL, NULL, szIniFile);
+
+ dwRet = SHGetIniStringW(L"TestSection", L"Key", szValue,
_countof(szValue), szIniFile);
+ ok_long(dwRet, 5);
+ ok_wstr(szValue, L"Value");
+
+ bRet = SHSetIniStringW(L"TestSection", L"Key", NULL, szIniFile);
+ ok_int(bRet, TRUE);
+
+ WritePrivateProfileStringW(NULL, NULL, NULL, szIniFile);
+
+ dwRet = SHGetIniStringW(L"TestSection", L"Key", szValue,
_countof(szValue), szIniFile);
+ ok_long(dwRet, 0);
+ ok_wstr(szValue, L"");
+
+ bRet = SHSetIniStringW(L"TestSection", L"Key",
L"ABC\x3042\x3044\x3046\x2665", szIniFile);
+ ok_int(bRet, TRUE);
+
+ WritePrivateProfileStringW(NULL, NULL, NULL, szIniFile);
+
+ dwRet = SHGetIniStringW(L"TestSection", L"Key", szValue,
_countof(szValue), szIniFile);
+ ok_long(dwRet, 7);
+ ok_wstr(szValue, L"ABC\x3042\x3044\x3046\x2665");
+
+ szValue[0] = 0x3000;
+ szValue[1] = UNICODE_NULL;
+ dwRet = SHGetIniStringW(L"TestSection", L"NotExistentKey",
szValue, _countof(szValue), szIniFile);
+ ok_long(dwRet, 0);
+ ok_wstr(szValue, L"");
+
+ DeleteFileW(szIniFile);
+}
+
START_TEST(SHPropertyBag)
{
SHPropertyBag_ReadTest();
SHPropertyBag_WriteTest();
SHPropertyBag_OnMemory();
SHPropertyBag_OnRegKey();
+ SHPropertyBag_SHSetIniStringW();
}
diff --git a/sdk/include/reactos/shlwapi_undoc.h b/sdk/include/reactos/shlwapi_undoc.h
index 29aae083047..a2677a639ce 100644
--- a/sdk/include/reactos/shlwapi_undoc.h
+++ b/sdk/include/reactos/shlwapi_undoc.h
@@ -179,6 +179,12 @@ HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR
buf, DWORD si
#define SHLoadRegUIString SHLoadRegUIStringA
#endif
+DWORD WINAPI
+SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out, DWORD outLen, LPCWSTR
filename);
+
+BOOL WINAPI
+SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str, LPCWSTR filename);
+
int
WINAPIV
ShellMessageBoxWrapW(