From: André Hentschel Subject: kernel32: Implement LCMapStringEx with tests (new approach) Message-Id: <4F9AD71C.8080302@dawncrow.de> Date: Fri, 27 Apr 2012 19:27:56 +0200 --- dlls/kernel32/kernel32.spec | 1 + dlls/kernel32/locale.c | 47 +++++++++++++++++++++++++++++++++++++---- dlls/kernel32/tests/locale.c | 42 +++++++++++++++++++++++++++++++++--- include/winnls.h | 13 +++++++++++ 4 files changed, 94 insertions(+), 9 deletions(-) diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 10d6da5..d9ae383 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -803,6 +803,7 @@ @ stdcall -i386 -private -register K32Thk1632Prolog() krnl386.exe16.K32Thk1632Prolog @ stdcall LCIDToLocaleName(long ptr long long) @ stdcall LCMapStringA(long long str long ptr long) +@ stdcall LCMapStringEx(wstr long wstr long ptr long ptr ptr long) @ stdcall LCMapStringW(long long wstr long ptr long) @ stdcall LZClose(long) # @ stub LZCloseFile diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c index 02a351c..c0db681 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c @@ -2467,16 +2467,37 @@ BOOL WINAPI GetStringTypeExA( LCID locale, DWORD type, LPCSTR src, INT count, LP return GetStringTypeA(locale, type, src, count, chartype); } - /************************************************************************* - * LCMapStringW (KERNEL32.@) + * LCMapStringEx (KERNEL32.@) * - * See LCMapStringA. + * Map characters in a locale sensitive string. + * + * PARAMS + * name [I] Locale name for the conversion. + * flags [I] Flags controlling the mapping (LCMAP_ constants from "winnls.h") + * src [I] String to map + * srclen [I] Length of src in chars, or -1 if src is NUL terminated + * dst [O] Destination for mapped string + * dstlen [I] Length of dst in characters + * version [I] reserved, must be NULL + * reserved [I] reserved, must be NULL + * lparam [I] reserved, must be 0 + * + * RETURNS + * Success: The length of the mapped string in dst, including the NUL terminator. + * Failure: 0. Use GetLastError() to determine the cause. */ -INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen, - LPWSTR dst, INT dstlen) +INT WINAPI LCMapStringEx(LPCWSTR name, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen, + LPNLSVERSIONINFO version, LPVOID reserved, LPARAM lparam) { LPWSTR dst_ptr; + LCID lcid; + + if (version) FIXME("unsupported version structure %p\n", version); + if (reserved) FIXME("unsupported reserved pointer %p\n", reserved); + if (lparam) FIXME("unsupported lparam %lx\n", lparam); + + lcid = LocaleNameToLCID(name, 0); if (!src || !srclen || dstlen < 0) { @@ -2599,6 +2620,22 @@ INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen, } /************************************************************************* + * LCMapStringW (KERNEL32.@) + * + * See LCMapStringA. + */ +INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen, + LPWSTR dst, INT dstlen) +{ + WCHAR locale[LOCALE_NAME_MAX_LENGTH]; + + if (!LCIDToLocaleName(lcid, locale, LOCALE_NAME_MAX_LENGTH, 0)) + return 0; + + return LCMapStringEx(locale, flags, src, srclen, dst, dstlen, NULL, NULL, 0); +} + +/************************************************************************* * LCMapStringA (KERNEL32.@) * * Map characters in a locale sensitive string. diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 63cace1..3f6b7f0 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -36,6 +36,11 @@ #include "winerror.h" #include "winnls.h" +static const WCHAR upper_case[] = {'\t','J','U','S','T','!',' ','A',',',' ','T','E','S','T',';',' ','S','T','R','I','N','G',' ','1','/','*','+','-','.','\r','\n',0}; +static const WCHAR lower_case[] = {'\t','j','u','s','t','!',' ','a',',',' ','t','e','s','t',';',' ','s','t','r','i','n','g',' ','1','/','*','+','-','.','\r','\n',0}; +static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0}; +static const WCHAR fooW[] = {'f','o','o',0}; + static inline unsigned int strlenW( const WCHAR *str ) { const WCHAR *s = str; @@ -71,6 +76,7 @@ static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROC, DWORD, static BOOL (WINAPI *pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROC, LGRPID, DWORD, LONG_PTR); static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROC, DWORD, LONG_PTR); static BOOL (WINAPI *pEnumSystemLocalesEx)(LOCALE_ENUMPROCEX, DWORD, LPARAM, LPVOID); +static INT (WINAPI *pLCMapStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPWSTR, INT, LPNLSVERSIONINFO, LPVOID, LPARAM); static LCID (WINAPI *pLocaleNameToLCID)(LPCWSTR, DWORD); static INT (WINAPI *pLCIDToLocaleName)(LCID, LPWSTR, INT, DWORD); static INT (WINAPI *pFoldStringA)(DWORD, LPCSTR, INT, LPSTR, INT); @@ -85,6 +91,7 @@ static void InitFunctionPointers(void) pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA"); pLocaleNameToLCID = (void*)GetProcAddress(hKernel32, "LocaleNameToLCID"); pLCIDToLocaleName = (void*)GetProcAddress(hKernel32, "LCIDToLocaleName"); + pLCMapStringEx = (void*)GetProcAddress(hKernel32, "LCMapStringEx"); pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA"); pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW"); pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup"); @@ -1486,15 +1493,41 @@ static void test_LCMapStringA(void) "unexpected error code %d\n", GetLastError()); } +static void test_LCMapStringEx(void) +{ + int ret; + WCHAR buf[256]; + + if (!pLCMapStringEx) + { + win_skip( "LCMapStringEx not available\n" ); + return; + } + + /* test reserved parameters */ + ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE, + upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 1); + ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n", + ret, GetLastError(), lstrlenW(upper_case) + 1); + ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n"); + + ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE, + upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, (void*)1, 0); + ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n", + ret, GetLastError(), lstrlenW(upper_case) + 1); + ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n"); + + /* crashes on native */ + if(0) + ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE, + upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), (void*)1, NULL, 0); +} + static void test_LCMapStringW(void) { int ret, ret2; WCHAR buf[256], buf2[256]; char *p_buf = (char *)buf, *p_buf2 = (char *)buf2; - static const WCHAR upper_case[] = {'\t','J','U','S','T','!',' ','A',',',' ','T','E','S','T',';',' ','S','T','R','I','N','G',' ','1','/','*','+','-','.','\r','\n',0}; - static const WCHAR lower_case[] = {'\t','j','u','s','t','!',' ','a',',',' ','t','e','s','t',';',' ','s','t','r','i','n','g',' ','1','/','*','+','-','.','\r','\n',0}; - static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0}; - static const WCHAR fooW[] = {'f','o','o',0}; ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE, upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR)); @@ -2997,6 +3030,7 @@ START_TEST(locale) test_CompareStringA(); test_LCMapStringA(); test_LCMapStringW(); + test_LCMapStringEx(); test_LocaleNames(); test_FoldStringA(); test_FoldStringW(); diff --git a/include/winnls.h b/include/winnls.h index c7da119..021c3ac 100644 --- a/include/winnls.h +++ b/include/winnls.h @@ -667,6 +667,19 @@ typedef struct _currencyfmtW DECL_WINELIB_TYPE_AW(CURRENCYFMT) DECL_WINELIB_TYPE_AW(LPCURRENCYFMT) +typedef struct _nlsversioninfo { + DWORD dwNLSVersionInfoSize; + DWORD dwNLSVersion; + DWORD dwDefinedVersion; +} NLSVERSIONINFO, *LPNLSVERSIONINFO; + +typedef struct _nlsversioninfoex { + DWORD dwNLSVersionInfoSize; + DWORD dwNLSVersion; + DWORD dwDefinedVersion; + DWORD dwEffectiveId; + GUID guidCustomVersion; +} NLSVERSIONINFOEX, *LPNLSVERSIONINFOEX; /* Define a bunch of callback types */ -- Best Regards, André Hentschel