Author: dchapyshev
Date: Mon Sep 19 11:28:20 2016
New Revision: 72740
URL:
http://svn.reactos.org/svn/reactos?rev=72740&view=rev
Log:
[KERNEL32] Sync other functions with Wine 1.9.17
* Fixes 1 test for kernel32:locale
Modified:
trunk/reactos/dll/win32/kernel32/winnls/string/lang.c
Modified: trunk/reactos/dll/win32/kernel32/winnls/string/lang.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/winnls/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/winnls/string/lang.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/winnls/string/lang.c [iso-8859-1] Mon Sep 19 11:28:20
2016
@@ -141,6 +141,100 @@
static LCID lcid_LC_PAPER;
static LCID lcid_LC_MEASUREMENT;
static LCID lcid_LC_TELEPHONE;
+
+static const WCHAR iCalendarTypeW[] =
{'i','C','a','l','e','n','d','a','r','T','y','p','e',0};
+static const WCHAR iCountryW[] =
{'i','C','o','u','n','t','r','y',0};
+static const WCHAR iCurrDigitsW[] =
{'i','C','u','r','r','D','i','g','i','t','s',0};
+static const WCHAR iCurrencyW[] =
{'i','C','u','r','r','e','n','c','y',0};
+static const WCHAR iDateW[] =
{'i','D','a','t','e',0};
+static const WCHAR iDigitsW[] =
{'i','D','i','g','i','t','s',0};
+static const WCHAR iFirstDayOfWeekW[] =
{'i','F','i','r','s','t','D','a','y','O','f','W','e','e','k',0};
+static const WCHAR iFirstWeekOfYearW[] =
{'i','F','i','r','s','t','W','e','e','k','O','f','Y','e','a','r',0};
+static const WCHAR iLDateW[] =
{'i','L','D','a','t','e',0};
+static const WCHAR iLZeroW[] =
{'i','L','Z','e','r','o',0};
+static const WCHAR iMeasureW[] =
{'i','M','e','a','s','u','r','e',0};
+static const WCHAR iNegCurrW[] =
{'i','N','e','g','C','u','r','r',0};
+static const WCHAR iNegNumberW[] =
{'i','N','e','g','N','u','m','b','e','r',0};
+static const WCHAR iPaperSizeW[] =
{'i','P','a','p','e','r','S','i','z','e',0};
+static const WCHAR iTLZeroW[] =
{'i','T','L','Z','e','r','o',0};
+static const WCHAR iTimePrefixW[] =
{'i','T','i','m','e','P','r','e','f','i','x',0};
+static const WCHAR iTimeW[] =
{'i','T','i','m','e',0};
+static const WCHAR s1159W[] =
{'s','1','1','5','9',0};
+static const WCHAR s2359W[] =
{'s','2','3','5','9',0};
+static const WCHAR sCountryW[] =
{'s','C','o','u','n','t','r','y',0};
+static const WCHAR sCurrencyW[] =
{'s','C','u','r','r','e','n','c','y',0};
+static const WCHAR sDateW[] =
{'s','D','a','t','e',0};
+static const WCHAR sDecimalW[] =
{'s','D','e','c','i','m','a','l',0};
+static const WCHAR sGroupingW[] =
{'s','G','r','o','u','p','i','n','g',0};
+static const WCHAR sLanguageW[] =
{'s','L','a','n','g','u','a','g','e',0};
+static const WCHAR sListW[] =
{'s','L','i','s','t',0};
+static const WCHAR sLongDateW[] =
{'s','L','o','n','g','D','a','t','e',0};
+static const WCHAR sMonDecimalSepW[] =
{'s','M','o','n','D','e','c','i','m','a','l','S','e','p',0};
+static const WCHAR sMonGroupingW[] =
{'s','M','o','n','G','r','o','u','p','i','n','g',0};
+static const WCHAR sMonThousandSepW[] =
{'s','M','o','n','T','h','o','u','s','a','n','d','S','e','p',0};
+static const WCHAR sNativeDigitsW[] =
{'s','N','a','t','i','v','e','D','i','g','i','t','s',0};
+static const WCHAR sNegativeSignW[] =
{'s','N','e','g','a','t','i','v','e','S','i','g','n',0};
+static const WCHAR sPositiveSignW[] =
{'s','P','o','s','i','t','i','v','e','S','i','g','n',0};
+static const WCHAR sShortDateW[] =
{'s','S','h','o','r','t','D','a','t','e',0};
+static const WCHAR sThousandW[] =
{'s','T','h','o','u','s','a','n','d',0};
+static const WCHAR sTimeFormatW[] =
{'s','T','i','m','e','F','o','r','m','a','t',0};
+static const WCHAR sTimeW[] =
{'s','T','i','m','e',0};
+static const WCHAR sYearMonthW[] =
{'s','Y','e','a','r','M','o','n','t','h',0};
+static const WCHAR NumShapeW[] =
{'N','u','m','s','h','a','p','e',0};
+
+static struct registry_value
+{
+ DWORD lctype;
+ const WCHAR *name;
+ WCHAR *cached_value;
+} registry_values[] =
+{
+ { LOCALE_ICALENDARTYPE, iCalendarTypeW },
+ { LOCALE_ICURRDIGITS, iCurrDigitsW },
+ { LOCALE_ICURRENCY, iCurrencyW },
+ { LOCALE_IDIGITS, iDigitsW },
+ { LOCALE_IFIRSTDAYOFWEEK, iFirstDayOfWeekW },
+ { LOCALE_IFIRSTWEEKOFYEAR, iFirstWeekOfYearW },
+ { LOCALE_ILZERO, iLZeroW },
+ { LOCALE_IMEASURE, iMeasureW },
+ { LOCALE_INEGCURR, iNegCurrW },
+ { LOCALE_INEGNUMBER, iNegNumberW },
+ { LOCALE_IPAPERSIZE, iPaperSizeW },
+ { LOCALE_ITIME, iTimeW },
+ { LOCALE_S1159, s1159W },
+ { LOCALE_S2359, s2359W },
+ { LOCALE_SCURRENCY, sCurrencyW },
+ { LOCALE_SDATE, sDateW },
+ { LOCALE_SDECIMAL, sDecimalW },
+ { LOCALE_SGROUPING, sGroupingW },
+ { LOCALE_SLIST, sListW },
+ { LOCALE_SLONGDATE, sLongDateW },
+ { LOCALE_SMONDECIMALSEP, sMonDecimalSepW },
+ { LOCALE_SMONGROUPING, sMonGroupingW },
+ { LOCALE_SMONTHOUSANDSEP, sMonThousandSepW },
+ { LOCALE_SNEGATIVESIGN, sNegativeSignW },
+ { LOCALE_SPOSITIVESIGN, sPositiveSignW },
+ { LOCALE_SSHORTDATE, sShortDateW },
+ { LOCALE_STHOUSAND, sThousandW },
+ { LOCALE_STIME, sTimeW },
+ { LOCALE_STIMEFORMAT, sTimeFormatW },
+ { LOCALE_SYEARMONTH, sYearMonthW },
+ /* The following are not listed under MSDN as supported,
+ * but seem to be used and also stored in the registry.
+ */
+ { LOCALE_ICOUNTRY, iCountryW },
+ { LOCALE_IDATE, iDateW },
+ { LOCALE_ILDATE, iLDateW },
+ { LOCALE_ITLZERO, iTLZeroW },
+ { LOCALE_SCOUNTRY, sCountryW },
+ { LOCALE_SABBREVLANGNAME, sLanguageW },
+ /* The following are used in XP and later */
+ { LOCALE_IDIGITSUBSTITUTION, NumShapeW },
+ { LOCALE_SNATIVEDIGITS, sNativeDigitsW },
+ { LOCALE_ITIMEMARKPOSN, iTimePrefixW }
+};
+
+static RTL_CRITICAL_SECTION cache_section = { NULL, -1, 0, 0, 0, 0 };
#ifndef __REACTOS__
/* Copy Ascii string to Unicode without using codepages */
@@ -491,107 +585,6 @@
return lang;
}
-/******************************************************************************
- * get_locale_value_name
- *
- * Gets the registry value name for a given lctype.
- */
-static const WCHAR *get_locale_value_name( DWORD lctype )
-{
- static const WCHAR iCalendarTypeW[] =
{'i','C','a','l','e','n','d','a','r','T','y','p','e',0};
- static const WCHAR iCountryW[] =
{'i','C','o','u','n','t','r','y',0};
- static const WCHAR iCurrDigitsW[] =
{'i','C','u','r','r','D','i','g','i','t','s',0};
- static const WCHAR iCurrencyW[] =
{'i','C','u','r','r','e','n','c','y',0};
- static const WCHAR iDateW[] =
{'i','D','a','t','e',0};
- static const WCHAR iDigitsW[] =
{'i','D','i','g','i','t','s',0};
- static const WCHAR iFirstDayOfWeekW[] =
{'i','F','i','r','s','t','D','a','y','O','f','W','e','e','k',0};
- static const WCHAR iFirstWeekOfYearW[] =
{'i','F','i','r','s','t','W','e','e','k','O','f','Y','e','a','r',0};
- static const WCHAR iLDateW[] =
{'i','L','D','a','t','e',0};
- static const WCHAR iLZeroW[] =
{'i','L','Z','e','r','o',0};
- static const WCHAR iMeasureW[] =
{'i','M','e','a','s','u','r','e',0};
- static const WCHAR iNegCurrW[] =
{'i','N','e','g','C','u','r','r',0};
- static const WCHAR iNegNumberW[] =
{'i','N','e','g','N','u','m','b','e','r',0};
- static const WCHAR iPaperSizeW[] =
{'i','P','a','p','e','r','S','i','z','e',0};
- static const WCHAR iTLZeroW[] =
{'i','T','L','Z','e','r','o',0};
- static const WCHAR iTimePrefixW[] =
{'i','T','i','m','e','P','r','e','f','i','x',0};
- static const WCHAR iTimeW[] =
{'i','T','i','m','e',0};
- static const WCHAR s1159W[] =
{'s','1','1','5','9',0};
- static const WCHAR s2359W[] =
{'s','2','3','5','9',0};
- static const WCHAR sCountryW[] =
{'s','C','o','u','n','t','r','y',0};
- static const WCHAR sCurrencyW[] =
{'s','C','u','r','r','e','n','c','y',0};
- static const WCHAR sDateW[] =
{'s','D','a','t','e',0};
- static const WCHAR sDecimalW[] =
{'s','D','e','c','i','m','a','l',0};
- static const WCHAR sGroupingW[] =
{'s','G','r','o','u','p','i','n','g',0};
- static const WCHAR sLanguageW[] =
{'s','L','a','n','g','u','a','g','e',0};
- static const WCHAR sListW[] =
{'s','L','i','s','t',0};
- static const WCHAR sLongDateW[] =
{'s','L','o','n','g','D','a','t','e',0};
- static const WCHAR sMonDecimalSepW[] =
{'s','M','o','n','D','e','c','i','m','a','l','S','e','p',0};
- static const WCHAR sMonGroupingW[] =
{'s','M','o','n','G','r','o','u','p','i','n','g',0};
- static const WCHAR sMonThousandSepW[] =
{'s','M','o','n','T','h','o','u','s','a','n','d','S','e','p',0};
- static const WCHAR sNativeDigitsW[] =
{'s','N','a','t','i','v','e','D','i','g','i','t','s',0};
- static const WCHAR sNegativeSignW[] =
{'s','N','e','g','a','t','i','v','e','S','i','g','n',0};
- static const WCHAR sPositiveSignW[] =
{'s','P','o','s','i','t','i','v','e','S','i','g','n',0};
- static const WCHAR sShortDateW[] =
{'s','S','h','o','r','t','D','a','t','e',0};
- static const WCHAR sThousandW[] =
{'s','T','h','o','u','s','a','n','d',0};
- static const WCHAR sTimeFormatW[] =
{'s','T','i','m','e','F','o','r','m','a','t',0};
- static const WCHAR sTimeW[] =
{'s','T','i','m','e',0};
- static const WCHAR sYearMonthW[] =
{'s','Y','e','a','r','M','o','n','t','h',0};
- static const WCHAR NumShapeW[] =
{'N','u','m','s','h','a','p','e',0};
-
- switch (lctype)
- {
- /* These values are used by SetLocaleInfo and GetLocaleInfo, and
- * the values are stored in the registry, confirmed under Windows.
- */
- case LOCALE_ICALENDARTYPE: return iCalendarTypeW;
- case LOCALE_ICURRDIGITS: return iCurrDigitsW;
- case LOCALE_ICURRENCY: return iCurrencyW;
- case LOCALE_IDIGITS: return iDigitsW;
- case LOCALE_IFIRSTDAYOFWEEK: return iFirstDayOfWeekW;
- case LOCALE_IFIRSTWEEKOFYEAR: return iFirstWeekOfYearW;
- case LOCALE_ILZERO: return iLZeroW;
- case LOCALE_IMEASURE: return iMeasureW;
- case LOCALE_INEGCURR: return iNegCurrW;
- case LOCALE_INEGNUMBER: return iNegNumberW;
- case LOCALE_IPAPERSIZE: return iPaperSizeW;
- case LOCALE_ITIME: return iTimeW;
- case LOCALE_S1159: return s1159W;
- case LOCALE_S2359: return s2359W;
- case LOCALE_SCURRENCY: return sCurrencyW;
- case LOCALE_SDATE: return sDateW;
- case LOCALE_SDECIMAL: return sDecimalW;
- case LOCALE_SGROUPING: return sGroupingW;
- case LOCALE_SLIST: return sListW;
- case LOCALE_SLONGDATE: return sLongDateW;
- case LOCALE_SMONDECIMALSEP: return sMonDecimalSepW;
- case LOCALE_SMONGROUPING: return sMonGroupingW;
- case LOCALE_SMONTHOUSANDSEP: return sMonThousandSepW;
- case LOCALE_SNEGATIVESIGN: return sNegativeSignW;
- case LOCALE_SPOSITIVESIGN: return sPositiveSignW;
- case LOCALE_SSHORTDATE: return sShortDateW;
- case LOCALE_STHOUSAND: return sThousandW;
- case LOCALE_STIME: return sTimeW;
- case LOCALE_STIMEFORMAT: return sTimeFormatW;
- case LOCALE_SYEARMONTH: return sYearMonthW;
-
- /* The following are not listed under MSDN as supported,
- * but seem to be used and also stored in the registry.
- */
- case LOCALE_ICOUNTRY: return iCountryW;
- case LOCALE_IDATE: return iDateW;
- case LOCALE_ILDATE: return iLDateW;
- case LOCALE_ITLZERO: return iTLZeroW;
- case LOCALE_SCOUNTRY: return sCountryW;
- case LOCALE_SABBREVLANGNAME: return sLanguageW;
-
- /* The following are used in XP and later */
- case LOCALE_IDIGITSUBSTITUTION: return NumShapeW;
- case LOCALE_SNATIVEDIGITS: return sNativeDigitsW;
- case LOCALE_ITIMEMARKPOSN: return iTimePrefixW;
- }
- return NULL;
-}
-
/******************************************************************************
* get_registry_locale_info
@@ -599,7 +592,7 @@
* Retrieve user-modified locale info from the registry.
* Return length, 0 on error, -1 if not found.
*/
-static INT get_registry_locale_info( LPCWSTR value, LPWSTR buffer, INT len )
+static INT get_registry_locale_info( struct registry_value *registry_value, LPWSTR
buffer, INT len )
{
DWORD size;
INT ret;
@@ -609,54 +602,103 @@
KEY_VALUE_PARTIAL_INFORMATION *info;
static const int info_size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
- if (!(hkey = create_registry_key())) return -1;
-
- RtlInitUnicodeString( &nameW, value );
- size = info_size + len * sizeof(WCHAR);
-
- if (!(info = HeapAlloc( GetProcessHeap(), 0, size )))
- {
+ RtlEnterCriticalSection( &cache_section );
+
+ if (!registry_value->cached_value)
+ {
+ if (!(hkey = create_registry_key()))
+ {
+ RtlLeaveCriticalSection( &cache_section );
+ return -1;
+ }
+
+ RtlInitUnicodeString( &nameW, registry_value->name );
+ size = info_size + len * sizeof(WCHAR);
+
+ if (!(info = HeapAlloc( GetProcessHeap(), 0, size )))
+ {
+ NtClose( hkey );
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ RtlLeaveCriticalSection( &cache_section );
+ return 0;
+ }
+
+ status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, info,
size, &size );
+
+ /* try again with a bigger buffer when we have to return the correct size */
+ if (status == STATUS_BUFFER_OVERFLOW && !buffer && size >
info_size)
+ {
+ KEY_VALUE_PARTIAL_INFORMATION *new_info;
+ if ((new_info = HeapReAlloc( GetProcessHeap(), 0, info, size )))
+ {
+ info = new_info;
+ status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
info, size, &size );
+ }
+ }
+
NtClose( hkey );
- SetLastError( ERROR_NOT_ENOUGH_MEMORY );
- return 0;
- }
-
- status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, info, size,
&size );
-
- if (!status)
- {
- ret = (size - info_size) / sizeof(WCHAR);
- /* append terminating null if needed */
- if (!ret || ((WCHAR *)info->Data)[ret-1])
- {
- if (ret < len || !buffer) ret++;
+
+ if (!status)
+ {
+ INT length = (size - info_size) / sizeof(WCHAR);
+ LPWSTR cached_value;
+
+ if (!length || ((WCHAR *)&info->Data)[length-1])
+ length++;
+
+ cached_value = HeapAlloc( GetProcessHeap(), 0, length * sizeof(WCHAR) );
+
+ if (!cached_value)
+ {
+ HeapFree( GetProcessHeap(), 0, info );
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ RtlLeaveCriticalSection( &cache_section );
+ return 0;
+ }
+
+ memcpy( cached_value, info->Data, (length-1) * sizeof(WCHAR) );
+ cached_value[length-1] = 0;
+ HeapFree( GetProcessHeap(), 0, info );
+ registry_value->cached_value = cached_value;
+ }
+ else
+ {
+ if (status == STATUS_BUFFER_OVERFLOW && !buffer)
+ {
+ ret = (size - info_size) / sizeof(WCHAR);
+ }
+ else if (status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ ret = -1;
+ }
else
{
- SetLastError( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( RtlNtStatusToDosError(status) );
ret = 0;
}
- }
- if (ret && buffer)
- {
- memcpy( buffer, info->Data, (ret-1) * sizeof(WCHAR) );
- buffer[ret-1] = 0;
- }
- }
- else if (status == STATUS_BUFFER_OVERFLOW && !buffer)
- {
- ret = (size - info_size) / sizeof(WCHAR) + 1;
- }
- else if (status == STATUS_OBJECT_NAME_NOT_FOUND)
- {
- ret = -1;
- }
- else
- {
- SetLastError( RtlNtStatusToDosError(status) );
- ret = 0;
- }
- NtClose( hkey );
- HeapFree( GetProcessHeap(), 0, info );
+ HeapFree( GetProcessHeap(), 0, info );
+ RtlLeaveCriticalSection( &cache_section );
+ return ret;
+ }
+ }
+
+ ret = lstrlenW( registry_value->cached_value ) + 1;
+
+ if (buffer)
+ {
+ if (ret > len)
+ {
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
+ ret = 0;
+ }
+ else
+ {
+ lstrcpyW( buffer, registry_value->cached_value );
+ }
+ }
+
+ RtlLeaveCriticalSection( &cache_section );
+
return ret;
}
@@ -694,7 +736,8 @@
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
- if (lctype & LOCALE_RETURN_GENITIVE_NAMES )
+ if (((lctype & ~LOCALE_LOCALEINFOFLAGSMASK) == LOCALE_SSHORTTIME) ||
+ (lctype & LOCALE_RETURN_GENITIVE_NAMES))
{
SetLastError( ERROR_INVALID_FLAGS );
return 0;
@@ -743,6 +786,20 @@
}
/******************************************************************************
+ * get_locale_registry_value
+ *
+ * Gets the registry value name and cache for a given lctype.
+ */
+static struct registry_value *get_locale_registry_value( DWORD lctype )
+{
+ int i;
+ for (i=0; i < sizeof(registry_values)/sizeof(registry_values[0]); i++)
+ if (registry_values[i].lctype == lctype)
+ return ®istry_values[i];
+ return NULL;
+}
+
+/******************************************************************************
* GetLocaleInfoW (KERNEL32.@)
*
* See GetLocaleInfoA.
@@ -783,7 +840,7 @@
if (!(lcflags & LOCALE_NOUSEROVERRIDE) &&
lcid == convert_default_lcid( LOCALE_USER_DEFAULT, lctype ))
{
- const WCHAR *value = get_locale_value_name(lctype);
+ struct registry_value *value = get_locale_registry_value(lctype);
if (value)
{
@@ -950,14 +1007,14 @@
*/
BOOL WINAPI SetLocaleInfoW( LCID lcid, LCTYPE lctype, LPCWSTR data )
{
- const WCHAR *value;
+ struct registry_value *value;
static const WCHAR intlW[] = {'i','n','t','l',0 };
UNICODE_STRING valueW;
NTSTATUS status;
HANDLE hkey;
lctype &= 0xffff;
- value = get_locale_value_name( lctype );
+ value = get_locale_registry_value( lctype );
if (!data || !value)
{
@@ -971,16 +1028,21 @@
return FALSE;
}
- TRACE("setting %x (%s) to %s\n", lctype, debugstr_w(value),
debugstr_w(data) );
+ TRACE("setting %x (%s) to %s\n", lctype, debugstr_w(value->name),
debugstr_w(data) );
/* FIXME: should check that data to set is sane */
/* FIXME: profile functions should map to registry */
- WriteProfileStringW( intlW, value, data );
+ WriteProfileStringW( intlW, value->name, data );
if (!(hkey = create_registry_key())) return FALSE;
- RtlInitUnicodeString( &valueW, value );
+ RtlInitUnicodeString( &valueW, value->name );
status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, (PVOID)data,
(strlenW(data)+1)*sizeof(WCHAR) );
+
+ RtlEnterCriticalSection( &cache_section );
+ HeapFree( GetProcessHeap(), 0, value->cached_value );
+ value->cached_value = NULL;
+ RtlLeaveCriticalSection( &cache_section );
if (lctype == LOCALE_SSHORTDATE || lctype == LOCALE_SLONGDATE)
{
@@ -1011,12 +1073,17 @@
else
lctype = LOCALE_ILDATE;
- value = get_locale_value_name( lctype );
-
- WriteProfileStringW( intlW, value, szBuff );
-
- RtlInitUnicodeString( &valueW, value );
+ value = get_locale_registry_value( lctype );
+
+ WriteProfileStringW( intlW, value->name, szBuff );
+
+ RtlInitUnicodeString( &valueW, value->name );
status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, szBuff, sizeof(szBuff) );
+
+ RtlEnterCriticalSection( &cache_section );
+ HeapFree( GetProcessHeap(), 0, value->cached_value );
+ value->cached_value = NULL;
+ RtlLeaveCriticalSection( &cache_section );
}
NtClose( hkey );
@@ -1095,6 +1162,9 @@
switch (lcid)
{
+ case LOCALE_INVARIANT:
+ /* keep as-is */
+ break;
case LOCALE_SYSTEM_DEFAULT:
lcid = GetSystemDefaultLCID();
break;
@@ -1426,7 +1496,11 @@
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);
+ if (lparam)
+ {
+ static int once;
+ if (!once++) FIXME("unsupported lparam %lx\n", lparam);
+ }
if (!src || !srclen || dstlen < 0)
{
@@ -1756,20 +1830,21 @@
}
/******************************************************************************
- * CompareStringW (KERNEL32.@)
- *
- * See CompareStringA.
- */
-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;
+ * CompareStringEx (KERNEL32.@)
+ */
+INT WINAPI CompareStringEx(LPCWSTR locale, DWORD flags, LPCWSTR str1, INT len1,
+ LPCWSTR str2, INT len2, LPNLSVERSIONINFO version, LPVOID
reserved, LPARAM lParam)
+{
+ DWORD supported_flags =
NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|SORT_STRINGSORT
+ |NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|LOCALE_USE_CP_ACP;
+ DWORD semistub_flags = NORM_LINGUISTIC_CASING|LINGUISTIC_IGNORECASE|0x10000000;
/* 0x10000000 is related to diacritics in Arabic, Japanese, and Hebrew */
INT ret;
-
+ static int once;
+
+ if (version) FIXME("unexpected version parameter\n");
+ if (reserved) FIXME("unexpected reserved value\n");
+ if (lParam) FIXME("unexpected lParam\n");
if (!str1 || !str2)
{
@@ -1777,7 +1852,7 @@
return 0;
}
- if (flags & ~supported_flags)
+ if (flags & ~(supported_flags|semistub_flags))
{
SetLastError(ERROR_INVALID_FLAGS);
return 0;
@@ -1785,8 +1860,8 @@
if (flags & semistub_flags)
{
- FIXME("semi-stub behavior for flag(s) 0x%x\n", flags &
semistub_flags);
- semistub_flags &= ~flags;
+ if (!once++)
+ FIXME("semi-stub behavior for flag(s) 0x%x\n", flags &
semistub_flags);
}
if (len1 < 0) len1 = strlenW(str1);
@@ -1797,6 +1872,17 @@
if (ret) /* need to translate result */
return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
return CSTR_EQUAL;
+}
+
+/******************************************************************************
+ * CompareStringW (KERNEL32.@)
+ *
+ * See CompareStringA.
+ */
+INT WINAPI CompareStringW(LCID lcid, DWORD flags,
+ LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
+{
+ return CompareStringEx(NULL, flags, str1, len1, str2, len2, NULL, NULL, 0);
}
/******************************************************************************
@@ -1883,7 +1969,7 @@
str2W = buf2W;
}
- ret = CompareStringW(lcid, flags, str1W, len1W, str2W, len2W);
+ ret = CompareStringEx(NULL, flags, str1W, len1W, str2W, len2W, NULL, NULL, 0);
if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
if (str2W != buf2W) HeapFree(GetProcessHeap(), 0, str2W);
@@ -1897,7 +1983,7 @@
HANDLE hkey;
RtlInitUnicodeString( &keyName, szKeyName );
- InitializeObjectAttributes(&attr, &keyName, OBJ_CASE_INSENSITIVE, hRootKey,
NULL);
+ InitializeObjectAttributes(&attr, &keyName, 0, hRootKey, NULL);
if (NtOpenKey( &hkey, KEY_READ, &attr ) != STATUS_SUCCESS)
hkey = 0;
@@ -2041,7 +2127,7 @@
if (NLS_RegEnumValue( hKey, ulIndex, szNumber, sizeof(szNumber),
szValue, sizeof(szValue) ))
{
- BOOL bInstalled = szValue[0] == '1' ? TRUE : FALSE;
+ BOOL bInstalled = szValue[0] == '1';
LGRPID lgrpid = strtoulW( szNumber, NULL, 16 );
TRACE("grpid %s (%sinstalled)\n", debugstr_w(szNumber),