[KERNEL32] Sync GetStringTypeW with Wine
[reactos.git] / reactos / dll / win32 / kernel32 / winnls / string / lang.c
index 565962a..4ac3cec 100644 (file)
@@ -33,6 +33,8 @@ DEBUG_CHANNEL(nls);
 extern int wine_fold_string(int flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen);
 extern int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen);
 extern int wine_compare_string(int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2);
+extern DWORD GetLocalisedText(DWORD dwResId, WCHAR *lpszDest, DWORD dwDestSize);
+#define NLSRC_OFFSET 5000 /* FIXME */
 
 extern HMODULE kernel32_handle;
 
@@ -54,6 +56,7 @@ static const WCHAR szLangGroupsKeyName[] = {
     'L','a','n','g','u','a','g','e',' ','G','r','o','u','p','s',0
 };
 
+#ifndef __REACTOS__
 /* Charset to codepage map, sorted by name. */
 static const struct charset_entry
 {
@@ -114,7 +117,7 @@ static const struct charset_entry
     { "KOI8U", 21866 },
     { "UTF8", CP_UTF8 }
 };
-
+#endif
 
 struct locale_name
 {
@@ -139,6 +142,7 @@ static LCID lcid_LC_PAPER;
 static LCID lcid_LC_MEASUREMENT;
 static LCID lcid_LC_TELEPHONE;
 
+#ifndef __REACTOS__
 /* Copy Ascii string to Unicode without using codepages */
 static inline void strcpynAtoW( WCHAR *dst, const char *src, size_t n )
 {
@@ -149,7 +153,7 @@ static inline void strcpynAtoW( WCHAR *dst, const char *src, size_t n )
     }
     if (n) *dst = 0;
 }
-
+#endif
 
 /***********************************************************************
  *             get_lcid_codepage
@@ -1251,6 +1255,12 @@ BOOL WINAPI GetStringTypeW( DWORD type, LPCWSTR src, INT count, LPWORD chartype
         C2_OTHERNEUTRAL        /* LRE, LRO, RLE, RLO, PDF */
     };
 
+    if (!src)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+
     if (count == -1) count = strlenW(src) + 1;
     switch(type)
     {
@@ -1275,7 +1285,7 @@ BOOL WINAPI GetStringTypeW( DWORD type, LPCWSTR src, INT count, LPWORD chartype
             if ((c>=0x30A0)&&(c<=0x30FF)) type3 |= C3_KATAKANA;
             if ((c>=0x3040)&&(c<=0x309F)) type3 |= C3_HIRAGANA;
             if ((c>=0x4E00)&&(c<=0x9FAF)) type3 |= C3_IDEOGRAPH;
-            if ((c>=0x0600)&&(c<=0x06FF)) type3 |= C3_KASHIDA;
+            if (c == 0x0640) type3 |= C3_KASHIDA;
             if ((c>=0x3000)&&(c<=0x303F)) type3 |= C3_SYMBOL;
 
             if ((c>=0xD800)&&(c<=0xDBFF)) type3 |= C3_HIGHSURROGATE;
@@ -1750,32 +1760,39 @@ INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen,
  *
  * See CompareStringA.
  */
-INT WINAPI CompareStringW(LCID lcid, DWORD style,
+INT WINAPI CompareStringW(LCID lcid, DWORD flags,
                           LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
 {
+    static const DWORD supported_flags = NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|SORT_STRINGSORT
+                                        |NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|LOCALE_USE_CP_ACP
+                                        |NORM_LINGUISTIC_CASING|LINGUISTIC_IGNORECASE|0x10000000;
+    static DWORD semistub_flags = NORM_LINGUISTIC_CASING|LINGUISTIC_IGNORECASE|0x10000000;
+    /* 0x10000000 is related to diacritics in Arabic, Japanese, and Hebrew */
     INT ret;
 
+
     if (!str1 || !str2)
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return 0;
     }
 
-    if( style & ~(NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|
-        SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|LOCALE_USE_CP_ACP|0x10000000) )
+    if (flags & ~supported_flags)
     {
         SetLastError(ERROR_INVALID_FLAGS);
         return 0;
     }
 
-    /* this style is related to diacritics in Arabic, Japanese, and Hebrew */
-    if (style & 0x10000000)
-        WARN("Ignoring unknown style 0x10000000\n");
+    if (flags & semistub_flags)
+    {
+        FIXME("semi-stub behavior for flag(s) 0x%x\n", flags & semistub_flags);
+        semistub_flags &= ~flags;
+    }
 
     if (len1 < 0) len1 = strlenW(str1);
     if (len2 < 0) len2 = strlenW(str2);
 
-    ret = wine_compare_string(style, str1, len1, str2, len2);
+    ret = wine_compare_string(flags, str1, len1, str2, len2);
 
     if (ret) /* need to translate result */
         return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
@@ -1789,7 +1806,7 @@ INT WINAPI CompareStringW(LCID lcid, DWORD style,
  *
  * PARAMS
  *  lcid  [I] LCID for the comparison
- *  style [I] Flags for the comparison (NORM_ constants from "winnls.h").
+ *  flags [I] Flags for the comparison (NORM_ constants from "winnls.h").
  *  str1  [I] First string to compare
  *  len1  [I] Length of str1, or -1 if str1 is NUL terminated
  *  str2  [I] Second string to compare
@@ -1977,18 +1994,6 @@ static BOOL NLS_GetLanguageGroupName(LGRPID lgrpid, LPWSTR szName, ULONG nameSiz
     return bRet;
 }
 
-/* Registry keys for NLS related information */
-
-static const WCHAR szCountryListName[] = {
-       '\\','R','e','g','i','s','t','r','y','\\',
-    'M','a','c','h','i','n','e','\\','S','o','f','t','w','a','r','e','\\',
-    'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
-    'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
-    'T','e','l','e','p','h','o','n','y','\\',
-    'C','o','u','n','t','r','y',' ','L','i','s','t','\0'
-};
-
-
 /* Callback function ptrs for EnumSystemLanguageGroupsA/W */
 typedef struct
 {
@@ -3002,77 +3007,34 @@ BOOL WINAPI EnumUILanguagesW(UILANGUAGE_ENUMPROCW pUILangEnumProc, DWORD dwFlags
 static int
 NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData)
 {
-    HANDLE hKey;
-    WCHAR szPath[MAX_PATH];
-    UNICODE_STRING ValueName;
-    KEY_VALUE_PARTIAL_INFORMATION *info;
-    const int info_size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
+    LPWSTR szBuffer;
     DWORD dwSize;
-    NTSTATUS Status;
-    int Ret;
 
-    swprintf(szPath, L"\\REGISTRY\\Machine\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Country List\\%lu", Location);
+    /* FIXME: move *.nls resources out of kernel32 into locale.nls */
+    Location += NLSRC_OFFSET;
+    Location &= 0xFFFF;
 
-    hKey = NLS_RegOpenKey(0, szPath);
-    if (!hKey)
-    {
-        WARN("NLS_RegOpenKey() failed\n");
-        return 0;
-    }
+    if(cchData == 0)
+        return GetLocalisedText(Location, NULL, 0);
 
-    dwSize = info_size + cchData * sizeof(WCHAR);
+    dwSize = cchData * sizeof(WCHAR);
+    szBuffer = HeapAlloc(GetProcessHeap(), 0, dwSize);
 
-    if (!(info = HeapAlloc(GetProcessHeap(), 0, dwSize)))
+    if (!szBuffer)
     {
-        NtClose(hKey);
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return 0;
     }
 
-    RtlInitUnicodeString(&ValueName, L"Name");
-
-    Status = NtQueryValueKey(hKey, &ValueName, KeyValuePartialInformation,
-                             (LPBYTE)info, dwSize, &dwSize);
-
-    if (!Status)
-    {
-        Ret = (dwSize - info_size) / sizeof(WCHAR);
-
-        if (!Ret || ((WCHAR *)info->Data)[Ret-1])
-        {
-            if (Ret < cchData || !szFriendlyName) Ret++;
-            else
-            {
-                WARN("ERROR_INSUFFICIENT_BUFFER\n");
-                SetLastError(ERROR_INSUFFICIENT_BUFFER);
-                Ret = 0;
-            }
-        }
-
-        if (Ret && szFriendlyName)
-        {
-            memcpy(szFriendlyName, info->Data, (Ret-1) * sizeof(WCHAR));
-            szFriendlyName[Ret-1] = 0;
-        }
-    }
-    else if (Status == STATUS_BUFFER_OVERFLOW && !szFriendlyName)
-    {
-        Ret = (dwSize - info_size) / sizeof(WCHAR) + 1;
-    }
-    else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+    if(GetLocalisedText(Location, szBuffer, dwSize))
     {
-        Ret = -1;
+        memcpy(szFriendlyName, szBuffer, dwSize);
+        HeapFree(GetProcessHeap(), 0, szBuffer);
+        return strlenW(szFriendlyName) + 1;
     }
-    else
-    {
-        SetLastError(RtlNtStatusToDosError(Status));
-        Ret = 0;
-    }
-
-    NtClose(hKey);
-    HeapFree(GetProcessHeap(), 0, info);
 
-    return Ret;
+    HeapFree(GetProcessHeap(), 0, szBuffer);
+    return 0;
 }
 
 static const struct geoinfo_t *get_geoinfo_dataptr(GEOID geoid)