[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
This commit is contained in:
Katayama Hirofumi MZ 2023-08-09 08:23:33 +09:00 committed by GitHub
parent 70e05170cf
commit a83fedcbfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 160 additions and 0 deletions

View file

@ -47,6 +47,9 @@
#include "commdlg.h" #include "commdlg.h"
#include "mlang.h" #include "mlang.h"
#include "mshtmhst.h" #include "mshtmhst.h"
#ifdef __REACTOS__
#include <shlwapi_undoc.h>
#endif
#include "wine/unicode.h" #include "wine/unicode.h"
#include "wine/debug.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 WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
DWORD outLen, LPCWSTR filename) 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; INT ret;
WCHAR *buf; WCHAR *buf;
@ -3310,10 +3344,27 @@ DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
*out = 0; *out = 0;
HeapFree(GetProcessHeap(), 0, buf); HeapFree(GetProcessHeap(), 0, buf);
#endif
return strlenW(out); 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] * @ [SHLWAPI.295]
* *
@ -3333,10 +3384,63 @@ DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
BOOL WINAPI SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str, BOOL WINAPI SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str,
LPCWSTR filename) 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), TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str),
debugstr_w(filename)); debugstr_w(filename));
return WritePrivateProfileStringW(appName, keyName, str, filename); return WritePrivateProfileStringW(appName, keyName, str, filename);
#endif
} }
/************************************************************************* /*************************************************************************

View file

@ -638,10 +638,60 @@ static void SHPropertyBag_OnRegKey(void)
RegCloseKey(hKey); 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) START_TEST(SHPropertyBag)
{ {
SHPropertyBag_ReadTest(); SHPropertyBag_ReadTest();
SHPropertyBag_WriteTest(); SHPropertyBag_WriteTest();
SHPropertyBag_OnMemory(); SHPropertyBag_OnMemory();
SHPropertyBag_OnRegKey(); SHPropertyBag_OnRegKey();
SHPropertyBag_SHSetIniStringW();
} }

View file

@ -179,6 +179,12 @@ HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD si
#define SHLoadRegUIString SHLoadRegUIStringA #define SHLoadRegUIString SHLoadRegUIStringA
#endif #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 int
WINAPIV WINAPIV
ShellMessageBoxWrapW( ShellMessageBoxWrapW(