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/s... ============================================================================== --- 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),