kernel32: Implement LCMapStringEx with tests (new approach)

André Hentschel nerv at dawncrow.de
Fri Apr 27 12:27:56 CDT 2012


---
 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


More information about the wine-patches mailing list