[KERNEL32] Sync other functions with Wine 1.9.17

* Fixes 1 test for kernel32:locale

svn path=/trunk/; revision=72740
This commit is contained in:
Dmitry Chapyshev
2016-09-19 11:28:20 +00:00
parent b44173c769
commit ab60ef617a
+251 -165
View File
@@ -142,6 +142,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 */
static inline void strcpynAtoW( WCHAR *dst, const char *src, size_t n )
@@ -491,107 +585,6 @@ LANGID WINAPI GetSystemDefaultUILanguage(void)
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 @@ static const WCHAR *get_locale_value_name( DWORD lctype )
* 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 @@ static INT get_registry_locale_info( LPCWSTR value, LPWSTR buffer, INT len )
KEY_VALUE_PARTIAL_INFORMATION *info;
static const int info_size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
if (!(hkey = create_registry_key())) return -1;
RtlEnterCriticalSection( &cache_section );
RtlInitUnicodeString( &nameW, value );
size = info_size + len * sizeof(WCHAR);
if (!(info = HeapAlloc( GetProcessHeap(), 0, size )))
if (!registry_value->cached_value)
{
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 (!(hkey = create_registry_key()))
{
if (ret < len || !buffer) ret++;
else
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 )))
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
ret = 0;
info = new_info;
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, info, size, &size );
}
}
if (ret && buffer)
NtClose( hkey );
if (!status)
{
memcpy( buffer, info->Data, (ret-1) * sizeof(WCHAR) );
buffer[ret-1] = 0;
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( RtlNtStatusToDosError(status) );
ret = 0;
}
HeapFree( GetProcessHeap(), 0, info );
RtlLeaveCriticalSection( &cache_section );
return ret;
}
}
else if (status == STATUS_BUFFER_OVERFLOW && !buffer)
ret = lstrlenW( registry_value->cached_value ) + 1;
if (buffer)
{
ret = (size - info_size) / sizeof(WCHAR) + 1;
if (ret > len)
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
ret = 0;
}
else
{
lstrcpyW( buffer, registry_value->cached_value );
}
}
else if (status == STATUS_OBJECT_NAME_NOT_FOUND)
{
ret = -1;
}
else
{
SetLastError( RtlNtStatusToDosError(status) );
ret = 0;
}
NtClose( hkey );
HeapFree( GetProcessHeap(), 0, info );
RtlLeaveCriticalSection( &cache_section );
return ret;
}
@@ -694,7 +736,8 @@ INT WINAPI GetLocaleInfoA( LCID lcid, LCTYPE lctype, LPSTR buffer, INT len )
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;
@@ -742,6 +785,20 @@ static int get_value_base_by_lctype( LCTYPE lctype )
return lctype == LOCALE_ILANGUAGE || lctype == LOCALE_IDEFAULTLANGUAGE ? 16 : 10;
}
/******************************************************************************
* 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 &registry_values[i];
return NULL;
}
/******************************************************************************
* GetLocaleInfoW (KERNEL32.@)
*
@@ -783,7 +840,7 @@ INT WINAPI GetLocaleInfoW( LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len )
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 SetLocaleInfoA(LCID lcid, LCTYPE lctype, LPCSTR data)
*/
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,17 +1028,22 @@ BOOL WINAPI SetLocaleInfoW( LCID lcid, LCTYPE lctype, LPCWSTR data )
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)
{
/* Set I-value from S value */
@@ -1011,12 +1073,17 @@ BOOL WINAPI SetLocaleInfoW( LCID lcid, LCTYPE lctype, LPCWSTR data )
else
lctype = LOCALE_ILDATE;
value = get_locale_value_name( lctype );
value = get_locale_registry_value( lctype );
WriteProfileStringW( intlW, value, szBuff );
WriteProfileStringW( intlW, value->name, szBuff );
RtlInitUnicodeString( &valueW, value );
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 @@ LCID WINAPI ConvertDefaultLocale( LCID lcid )
switch (lcid)
{
case LOCALE_INVARIANT:
/* keep as-is */
break;
case LOCALE_SYSTEM_DEFAULT:
lcid = GetSystemDefaultLCID();
break;
@@ -1426,7 +1496,11 @@ INT WINAPI LCMapStringEx(LPCWSTR name, DWORD flags, LPCWSTR src, INT srclen, LPW
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 @@ INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen,
}
/******************************************************************************
* CompareStringW (KERNEL32.@)
*
* See CompareStringA.
* CompareStringEx (KERNEL32.@)
*/
INT WINAPI CompareStringW(LCID lcid, DWORD flags,
LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
INT WINAPI CompareStringEx(LPCWSTR locale, DWORD flags, LPCWSTR str1, INT len1,
LPCWSTR str2, INT len2, LPNLSVERSIONINFO version, LPVOID reserved, LPARAM lParam)
{
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;
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 @@ INT WINAPI CompareStringW(LCID lcid, DWORD flags,
return 0;
}
if (flags & ~supported_flags)
if (flags & ~(supported_flags|semistub_flags))
{
SetLastError(ERROR_INVALID_FLAGS);
return 0;
@@ -1785,8 +1860,8 @@ INT WINAPI CompareStringW(LCID lcid, DWORD flags,
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);
@@ -1799,6 +1874,17 @@ INT WINAPI CompareStringW(LCID lcid, DWORD flags,
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);
}
/******************************************************************************
* CompareStringA (KERNEL32.@)
*
@@ -1883,7 +1969,7 @@ INT WINAPI CompareStringA(LCID lcid, DWORD flags,
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 @@ static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
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 @@ static BOOL NLS_EnumSystemLanguageGroups(ENUMLANGUAGEGROUP_CALLBACKS *lpProcs)
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),