Skip to content

Commit a83fedc

Browse files
authored
[SHLWAPI][SHLWAPI_APITEST][SDK] SHGetIniStringW/SHSetIniStringW (reactos#5547)
Follow-up to reactos#5531. These two functions are necessary for INI file property bag support. - Implement SHGetIniStringW and SHSetIniStringW. - Strengthen SHPropertyBag testcase of shlwapi_apitest. CORE-9283
1 parent 70e0517 commit a83fedc

File tree

3 files changed

+160
-0
lines changed

3 files changed

+160
-0
lines changed

dll/win32/shlwapi/ordinal.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
#include "commdlg.h"
4848
#include "mlang.h"
4949
#include "mshtmhst.h"
50+
#ifdef __REACTOS__
51+
#include <shlwapi_undoc.h>
52+
#endif
5053
#include "wine/unicode.h"
5154
#include "wine/debug.h"
5255

@@ -3288,6 +3291,37 @@ BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
32883291
DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
32893292
DWORD outLen, LPCWSTR filename)
32903293
{
3294+
#ifdef __REACTOS__
3295+
WCHAR szSection[MAX_PATH + 2];
3296+
WCHAR szWideBuff[MAX_PATH];
3297+
CHAR szUtf7Buff[MAX_PATH];
3298+
3299+
TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName), debugstr_w(keyName),
3300+
out, outLen, debugstr_w(filename));
3301+
3302+
if (outLen == 0)
3303+
return 0;
3304+
3305+
/* Try ".W"-appended section name. See also SHSetIniStringW. */
3306+
lstrcpynW(szSection, appName, _countof(szSection) - 2);
3307+
lstrcatW(szSection, L".W");
3308+
GetPrivateProfileStringW(szSection, keyName, NULL, szWideBuff, _countof(szWideBuff), filename);
3309+
if (szWideBuff[0] == UNICODE_NULL) /* It's empty or not found */
3310+
{
3311+
/* Try the normal section name */
3312+
return GetPrivateProfileStringW(appName, keyName, NULL, out, outLen, filename);
3313+
}
3314+
3315+
/* Okay, now ".W" version is valid. Its value is a UTF-7 string in UTF-16 */
3316+
3317+
/* szWideBuff --> szUtf7Buff */
3318+
SHUnicodeToAnsiCP(CP_ACP, szWideBuff, szUtf7Buff, _countof(szUtf7Buff));
3319+
szUtf7Buff[_countof(szUtf7Buff) - 1] = ANSI_NULL;
3320+
3321+
/* szUtf7Buff --> out */
3322+
SHAnsiToUnicodeCP(CP_UTF7, szUtf7Buff, out, outLen);
3323+
out[outLen - 1] = UNICODE_NULL;
3324+
#else
32913325
INT ret;
32923326
WCHAR *buf;
32933327

@@ -3310,10 +3344,27 @@ DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
33103344
*out = 0;
33113345

33123346
HeapFree(GetProcessHeap(), 0, buf);
3347+
#endif
33133348

33143349
return strlenW(out);
33153350
}
33163351

3352+
#ifdef __REACTOS__
3353+
static BOOL Is7BitClean(LPCWSTR psz)
3354+
{
3355+
if (!psz)
3356+
return TRUE;
3357+
3358+
while (*psz)
3359+
{
3360+
if (*psz > 0x7F)
3361+
return FALSE;
3362+
++psz;
3363+
}
3364+
return TRUE;
3365+
}
3366+
#endif
3367+
33173368
/*************************************************************************
33183369
* @ [SHLWAPI.295]
33193370
*
@@ -3333,10 +3384,63 @@ DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
33333384
BOOL WINAPI SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str,
33343385
LPCWSTR filename)
33353386
{
3387+
#ifdef __REACTOS__
3388+
WCHAR szSection[MAX_PATH + 2];
3389+
WCHAR szWideBuff[MAX_PATH];
3390+
CHAR szUtf7Buff[MAX_PATH];
3391+
3392+
TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str),
3393+
debugstr_w(filename));
3394+
3395+
/* Write a normal profile string. If str was NULL, then key will be deleted */
3396+
if (!WritePrivateProfileStringW(appName, keyName, str, filename))
3397+
return FALSE;
3398+
3399+
if (Is7BitClean(str))
3400+
{
3401+
/* Delete ".A" version */
3402+
lstrcpynW(szSection, appName, _countof(szSection) - 2);
3403+
lstrcatW(szSection, L".A");
3404+
WritePrivateProfileStringW(szSection, keyName, NULL, filename);
3405+
3406+
/* Delete ".W" version */
3407+
lstrcpynW(szSection, appName, _countof(szSection) - 2);
3408+
lstrcatW(szSection, L".W");
3409+
WritePrivateProfileStringW(szSection, keyName, NULL, filename);
3410+
3411+
return TRUE;
3412+
}
3413+
3414+
/* Now str is not 7-bit clean. It needs UTF-7 encoding in UTF-16.
3415+
We write ".A" and ".W"-appended sections. */
3416+
3417+
/* str --> szUtf7Buff */
3418+
SHUnicodeToAnsiCP(CP_UTF7, str, szUtf7Buff, _countof(szUtf7Buff));
3419+
szUtf7Buff[_countof(szUtf7Buff) - 1] = ANSI_NULL;
3420+
3421+
/* szUtf7Buff --> szWideBuff */
3422+
SHAnsiToUnicodeCP(CP_ACP, szUtf7Buff, szWideBuff, _countof(szWideBuff));
3423+
szWideBuff[_countof(szWideBuff) - 1] = UNICODE_NULL;
3424+
3425+
/* Write ".A" version */
3426+
lstrcpynW(szSection, appName, _countof(szSection) - 2);
3427+
lstrcatW(szSection, L".A");
3428+
if (!WritePrivateProfileStringW(szSection, keyName, str, filename))
3429+
return FALSE;
3430+
3431+
/* Write ".W" version */
3432+
lstrcpynW(szSection, appName, _countof(szSection) - 2);
3433+
lstrcatW(szSection, L".W");
3434+
if (!WritePrivateProfileStringW(szSection, keyName, szWideBuff, filename))
3435+
return FALSE;
3436+
3437+
return TRUE;
3438+
#else
33363439
TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str),
33373440
debugstr_w(filename));
33383441

33393442
return WritePrivateProfileStringW(appName, keyName, str, filename);
3443+
#endif
33403444
}
33413445

33423446
/*************************************************************************

modules/rostests/apitests/shlwapi/SHPropertyBag.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,10 +638,60 @@ static void SHPropertyBag_OnRegKey(void)
638638
RegCloseKey(hKey);
639639
}
640640

641+
static void SHPropertyBag_SHSetIniStringW(void)
642+
{
643+
WCHAR szIniFile[MAX_PATH];
644+
WCHAR szValue[MAX_PATH];
645+
BOOL bRet;
646+
DWORD dwRet;
647+
648+
ExpandEnvironmentStringsW(L"%TEMP%\\SHSetIniString.ini", szIniFile, _countof(szIniFile));
649+
650+
DeleteFileW(szIniFile);
651+
652+
trace("%ls\n", szIniFile);
653+
654+
bRet = SHSetIniStringW(L"TestSection", L"Key", L"Value", szIniFile);
655+
ok_int(bRet, TRUE);
656+
657+
WritePrivateProfileStringW(NULL, NULL, NULL, szIniFile);
658+
659+
dwRet = SHGetIniStringW(L"TestSection", L"Key", szValue, _countof(szValue), szIniFile);
660+
ok_long(dwRet, 5);
661+
ok_wstr(szValue, L"Value");
662+
663+
bRet = SHSetIniStringW(L"TestSection", L"Key", NULL, szIniFile);
664+
ok_int(bRet, TRUE);
665+
666+
WritePrivateProfileStringW(NULL, NULL, NULL, szIniFile);
667+
668+
dwRet = SHGetIniStringW(L"TestSection", L"Key", szValue, _countof(szValue), szIniFile);
669+
ok_long(dwRet, 0);
670+
ok_wstr(szValue, L"");
671+
672+
bRet = SHSetIniStringW(L"TestSection", L"Key", L"ABC\x3042\x3044\x3046\x2665", szIniFile);
673+
ok_int(bRet, TRUE);
674+
675+
WritePrivateProfileStringW(NULL, NULL, NULL, szIniFile);
676+
677+
dwRet = SHGetIniStringW(L"TestSection", L"Key", szValue, _countof(szValue), szIniFile);
678+
ok_long(dwRet, 7);
679+
ok_wstr(szValue, L"ABC\x3042\x3044\x3046\x2665");
680+
681+
szValue[0] = 0x3000;
682+
szValue[1] = UNICODE_NULL;
683+
dwRet = SHGetIniStringW(L"TestSection", L"NotExistentKey", szValue, _countof(szValue), szIniFile);
684+
ok_long(dwRet, 0);
685+
ok_wstr(szValue, L"");
686+
687+
DeleteFileW(szIniFile);
688+
}
689+
641690
START_TEST(SHPropertyBag)
642691
{
643692
SHPropertyBag_ReadTest();
644693
SHPropertyBag_WriteTest();
645694
SHPropertyBag_OnMemory();
646695
SHPropertyBag_OnRegKey();
696+
SHPropertyBag_SHSetIniStringW();
647697
}

sdk/include/reactos/shlwapi_undoc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,12 @@ HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD si
179179
#define SHLoadRegUIString SHLoadRegUIStringA
180180
#endif
181181

182+
DWORD WINAPI
183+
SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out, DWORD outLen, LPCWSTR filename);
184+
185+
BOOL WINAPI
186+
SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str, LPCWSTR filename);
187+
182188
int
183189
WINAPIV
184190
ShellMessageBoxWrapW(

0 commit comments

Comments
 (0)