mirror of
https://github.com/reactos/reactos.git
synced 2025-05-19 17:14:32 +00:00
[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:
parent
70e05170cf
commit
a83fedcbfa
3 changed files with 160 additions and 0 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in a new issue