kernel32: Move the CompareString functions to kernelbase.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
94a3add0ea
commit
098e71ad61
|
@ -239,10 +239,10 @@
|
||||||
@ stdcall CommConfigDialogW(wstr long ptr)
|
@ stdcall CommConfigDialogW(wstr long ptr)
|
||||||
# @ stub CompareCalendarDates
|
# @ stub CompareCalendarDates
|
||||||
@ stdcall -import CompareFileTime(ptr ptr)
|
@ stdcall -import CompareFileTime(ptr ptr)
|
||||||
@ stdcall CompareStringA(long long str long str long)
|
@ stdcall -import CompareStringA(long long str long str long)
|
||||||
@ stdcall CompareStringW(long long wstr long wstr long)
|
@ stdcall -import CompareStringEx(wstr long wstr long wstr long ptr ptr long)
|
||||||
@ stdcall CompareStringEx(wstr long wstr long wstr long ptr ptr long)
|
|
||||||
@ stdcall -import CompareStringOrdinal(wstr long wstr long long)
|
@ stdcall -import CompareStringOrdinal(wstr long wstr long long)
|
||||||
|
@ stdcall -import CompareStringW(long long wstr long wstr long)
|
||||||
@ stdcall -import ConnectNamedPipe(long ptr)
|
@ stdcall -import ConnectNamedPipe(long ptr)
|
||||||
@ stub ConsoleMenuControl
|
@ stub ConsoleMenuControl
|
||||||
@ stub ConsoleSubst
|
@ stub ConsoleSubst
|
||||||
|
@ -502,8 +502,8 @@
|
||||||
@ stub FindNextVolumeMountPointA
|
@ stub FindNextVolumeMountPointA
|
||||||
@ stub FindNextVolumeMountPointW
|
@ stub FindNextVolumeMountPointW
|
||||||
@ stdcall FindNextVolumeW(long ptr long)
|
@ stdcall FindNextVolumeW(long ptr long)
|
||||||
# @ stub FindNLSString
|
@ stdcall -import FindNLSString(long long wstr long wstr long ptr)
|
||||||
@ stdcall FindNLSStringEx(wstr long wstr long wstr long ptr ptr ptr long)
|
@ stdcall -import FindNLSStringEx(wstr long wstr long wstr long ptr ptr ptr long)
|
||||||
@ stdcall FindResourceA(long str str)
|
@ stdcall FindResourceA(long str str)
|
||||||
@ stdcall FindResourceExA(long str str long)
|
@ stdcall FindResourceExA(long str str long)
|
||||||
@ stdcall -import FindResourceExW(long wstr wstr long)
|
@ stdcall -import FindResourceExW(long wstr wstr long)
|
||||||
|
|
|
@ -445,153 +445,6 @@ FoldStringA_exit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & ~(supported_flags|semistub_flags))
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_FLAGS);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & semistub_flags)
|
|
||||||
{
|
|
||||||
if (!once++)
|
|
||||||
FIXME("semi-stub behavior for flag(s) 0x%x\n", flags & semistub_flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len1 < 0) len1 = strlenW(str1);
|
|
||||||
if (len2 < 0) len2 = strlenW(str2);
|
|
||||||
|
|
||||||
ret = wine_compare_string(flags, str1, len1, str2, len2);
|
|
||||||
|
|
||||||
if (ret) /* need to translate result */
|
|
||||||
return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
|
|
||||||
return CSTR_EQUAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* CompareStringA (KERNEL32.@)
|
|
||||||
*
|
|
||||||
* Compare two locale sensitive strings.
|
|
||||||
*
|
|
||||||
* PARAMS
|
|
||||||
* lcid [I] LCID for the comparison
|
|
||||||
* 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
|
|
||||||
* len2 [I] Length of str2, or -1 if str2 is NUL terminated
|
|
||||||
*
|
|
||||||
* RETURNS
|
|
||||||
* Success: CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN depending on whether
|
|
||||||
* str1 is less than, equal to or greater than str2 respectively.
|
|
||||||
* Failure: FALSE. Use GetLastError() to determine the cause.
|
|
||||||
*/
|
|
||||||
INT WINAPI CompareStringA(LCID lcid, DWORD flags,
|
|
||||||
LPCSTR str1, INT len1, LPCSTR str2, INT len2)
|
|
||||||
{
|
|
||||||
WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer;
|
|
||||||
WCHAR *buf2W = buf1W + 130;
|
|
||||||
LPWSTR str1W, str2W;
|
|
||||||
INT len1W = 0, len2W = 0, ret;
|
|
||||||
UINT locale_cp = CP_ACP;
|
|
||||||
|
|
||||||
if (!str1 || !str2)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (len1 < 0) len1 = strlen(str1);
|
|
||||||
if (len2 < 0) len2 = strlen(str2);
|
|
||||||
|
|
||||||
if (!(flags & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage( lcid );
|
|
||||||
|
|
||||||
if (len1)
|
|
||||||
{
|
|
||||||
if (len1 <= 130) len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 130);
|
|
||||||
if (len1W)
|
|
||||||
str1W = buf1W;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, NULL, 0);
|
|
||||||
str1W = HeapAlloc(GetProcessHeap(), 0, len1W * sizeof(WCHAR));
|
|
||||||
if (!str1W)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
MultiByteToWideChar(locale_cp, 0, str1, len1, str1W, len1W);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
len1W = 0;
|
|
||||||
str1W = buf1W;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len2)
|
|
||||||
{
|
|
||||||
if (len2 <= 130) len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 130);
|
|
||||||
if (len2W)
|
|
||||||
str2W = buf2W;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, NULL, 0);
|
|
||||||
str2W = HeapAlloc(GetProcessHeap(), 0, len2W * sizeof(WCHAR));
|
|
||||||
if (!str2W)
|
|
||||||
{
|
|
||||||
if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
|
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
MultiByteToWideChar(locale_cp, 0, str2, len2, str2W, len2W);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
len2W = 0;
|
|
||||||
str2W = buf2W;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
|
static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
|
||||||
{
|
{
|
||||||
UNICODE_STRING keyName;
|
UNICODE_STRING keyName;
|
||||||
|
@ -1900,54 +1753,3 @@ BOOL WINAPI GetFileMUIInfo(DWORD flags, PCWSTR path, FILEMUIINFO *info, DWORD *s
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* FindNLSStringEx (KERNEL32.@)
|
|
||||||
*/
|
|
||||||
|
|
||||||
INT WINAPI FindNLSStringEx(const WCHAR *localename, DWORD flags, const WCHAR *src,
|
|
||||||
INT src_size, const WCHAR *value, INT value_size,
|
|
||||||
INT *found, NLSVERSIONINFO *version_info, void *reserved,
|
|
||||||
LPARAM sort_handle)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* FIXME: this function should normalize strings before calling CompareStringEx() */
|
|
||||||
DWORD mask = flags;
|
|
||||||
int offset, inc, count;
|
|
||||||
|
|
||||||
TRACE("%s %x %s %d %s %d %p %p %p %ld\n", wine_dbgstr_w(localename), flags,
|
|
||||||
wine_dbgstr_w(src), src_size, wine_dbgstr_w(value), value_size, found,
|
|
||||||
version_info, reserved, sort_handle);
|
|
||||||
|
|
||||||
if (version_info != NULL || reserved != NULL || sort_handle != 0 ||
|
|
||||||
!IsValidLocaleName(localename) || src == NULL || src_size == 0 ||
|
|
||||||
src_size < -1 || value == NULL || value_size == 0 || value_size < -1)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (src_size == -1)
|
|
||||||
src_size = strlenW(src);
|
|
||||||
if (value_size == -1)
|
|
||||||
value_size = strlenW(value);
|
|
||||||
|
|
||||||
src_size -= value_size;
|
|
||||||
if (src_size < 0) return -1;
|
|
||||||
|
|
||||||
mask = flags & ~(FIND_FROMSTART | FIND_FROMEND | FIND_STARTSWITH | FIND_ENDSWITH);
|
|
||||||
count = flags & (FIND_FROMSTART | FIND_FROMEND) ? src_size + 1 : 1;
|
|
||||||
offset = flags & (FIND_FROMSTART | FIND_STARTSWITH) ? 0 : src_size;
|
|
||||||
inc = flags & (FIND_FROMSTART | FIND_STARTSWITH) ? 1 : -1;
|
|
||||||
while (count--)
|
|
||||||
{
|
|
||||||
if (CompareStringEx(localename, mask, src + offset, value_size, value, value_size, NULL, NULL, 0) == CSTR_EQUAL)
|
|
||||||
{
|
|
||||||
if (found)
|
|
||||||
*found = value_size;
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
offset += inc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
|
@ -153,10 +153,10 @@
|
||||||
# @ stub CommitStateAtom
|
# @ stub CommitStateAtom
|
||||||
@ stdcall CompareFileTime(ptr ptr)
|
@ stdcall CompareFileTime(ptr ptr)
|
||||||
# @ stub CompareObjectHandles
|
# @ stub CompareObjectHandles
|
||||||
@ stdcall CompareStringA(long long str long str long) kernel32.CompareStringA
|
@ stdcall CompareStringA(long long str long str long)
|
||||||
@ stdcall CompareStringEx(wstr long wstr long wstr long ptr ptr long) kernel32.CompareStringEx
|
@ stdcall CompareStringEx(wstr long wstr long wstr long ptr ptr long)
|
||||||
@ stdcall CompareStringOrdinal(wstr long wstr long long)
|
@ stdcall CompareStringOrdinal(wstr long wstr long long)
|
||||||
@ stdcall CompareStringW(long long wstr long wstr long) kernel32.CompareStringW
|
@ stdcall CompareStringW(long long wstr long wstr long)
|
||||||
@ stdcall ConnectNamedPipe(long ptr)
|
@ stdcall ConnectNamedPipe(long ptr)
|
||||||
@ stdcall ContinueDebugEvent(long long long)
|
@ stdcall ContinueDebugEvent(long long long)
|
||||||
@ stdcall ConvertDefaultLocale(long)
|
@ stdcall ConvertDefaultLocale(long)
|
||||||
|
@ -362,8 +362,8 @@
|
||||||
@ stdcall FindFirstFreeAce(ptr ptr)
|
@ stdcall FindFirstFreeAce(ptr ptr)
|
||||||
@ stdcall FindFirstStreamW(wstr long ptr long) kernel32.FindFirstStreamW
|
@ stdcall FindFirstStreamW(wstr long ptr long) kernel32.FindFirstStreamW
|
||||||
@ stdcall FindFirstVolumeW(ptr long) kernel32.FindFirstVolumeW
|
@ stdcall FindFirstVolumeW(ptr long) kernel32.FindFirstVolumeW
|
||||||
@ stub FindNLSString
|
@ stdcall FindNLSString(long long wstr long wstr long ptr)
|
||||||
@ stdcall FindNLSStringEx(wstr long wstr long wstr long ptr ptr ptr long) kernel32.FindNLSStringEx
|
@ stdcall FindNLSStringEx(wstr long wstr long wstr long ptr ptr ptr long)
|
||||||
@ stdcall FindNextChangeNotification(long)
|
@ stdcall FindNextChangeNotification(long)
|
||||||
@ stdcall FindNextFileA(long ptr) kernel32.FindNextFileA
|
@ stdcall FindNextFileA(long ptr) kernel32.FindNextFileA
|
||||||
# @ stub FindNextFileNameW
|
# @ stub FindNextFileNameW
|
||||||
|
|
|
@ -1805,6 +1805,125 @@ static int map_to_halfwidth( WCHAR c, WCHAR *dst, int dstlen )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 32-bit collation element table format:
|
||||||
|
* unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit,
|
||||||
|
* case weight - high 4 bit of low 8 bit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum weight { UNICODE_WEIGHT, DIACRITIC_WEIGHT, CASE_WEIGHT };
|
||||||
|
|
||||||
|
static unsigned int get_weight( WCHAR ch, enum weight type )
|
||||||
|
{
|
||||||
|
unsigned int ret = collation_table[collation_table[ch >> 8] + (ch & 0xff)];
|
||||||
|
if (ret == (unsigned int)-1) return ch;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case UNICODE_WEIGHT: return ret >> 16;
|
||||||
|
case DIACRITIC_WEIGHT: return (ret >> 8) & 0xff;
|
||||||
|
case CASE_WEIGHT: return (ret >> 4) & 0x0f;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void inc_str_pos( const WCHAR **str, int *len, int *dpos, int *dlen )
|
||||||
|
{
|
||||||
|
(*dpos)++;
|
||||||
|
if (*dpos == *dlen)
|
||||||
|
{
|
||||||
|
*dpos = *dlen = 0;
|
||||||
|
(*str)++;
|
||||||
|
(*len)--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int compare_weights(int flags, const WCHAR *str1, int len1,
|
||||||
|
const WCHAR *str2, int len2, enum weight type )
|
||||||
|
{
|
||||||
|
int dpos1 = 0, dpos2 = 0, dlen1 = 0, dlen2 = 0;
|
||||||
|
WCHAR dstr1[4], dstr2[4];
|
||||||
|
unsigned int ce1, ce2;
|
||||||
|
|
||||||
|
while (len1 > 0 && len2 > 0)
|
||||||
|
{
|
||||||
|
if (!dlen1) dlen1 = wine_decompose( 0, *str1, dstr1, 4 );
|
||||||
|
if (!dlen2) dlen2 = wine_decompose( 0, *str2, dstr2, 4 );
|
||||||
|
|
||||||
|
if (flags & NORM_IGNORESYMBOLS)
|
||||||
|
{
|
||||||
|
int skip = 0;
|
||||||
|
/* FIXME: not tested */
|
||||||
|
if (get_table_entry( wctype_table, dstr1[dpos1] ) & (C1_PUNCT | C1_SPACE))
|
||||||
|
{
|
||||||
|
inc_str_pos( &str1, &len1, &dpos1, &dlen1 );
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
if (get_table_entry( wctype_table, dstr2[dpos1] ) & (C1_PUNCT | C1_SPACE))
|
||||||
|
{
|
||||||
|
inc_str_pos( &str2, &len2, &dpos2, &dlen2 );
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
if (skip) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hyphen and apostrophe are treated differently depending on
|
||||||
|
* whether SORT_STRINGSORT specified or not
|
||||||
|
*/
|
||||||
|
if (type == UNICODE_WEIGHT && !(flags & SORT_STRINGSORT))
|
||||||
|
{
|
||||||
|
if (dstr1[dpos1] == '-' || dstr1[dpos1] == '\'')
|
||||||
|
{
|
||||||
|
if (dstr2[dpos2] != '-' && dstr2[dpos2] != '\'')
|
||||||
|
{
|
||||||
|
inc_str_pos( &str1, &len1, &dpos1, &dlen1 );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (dstr2[dpos2] == '-' || dstr2[dpos2] == '\'')
|
||||||
|
{
|
||||||
|
inc_str_pos( &str2, &len2, &dpos2, &dlen2 );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ce1 = get_weight( dstr1[dpos1], type );
|
||||||
|
if (!ce1)
|
||||||
|
{
|
||||||
|
inc_str_pos( &str1, &len1, &dpos1, &dlen1 );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ce2 = get_weight( dstr2[dpos2], type );
|
||||||
|
if (!ce2)
|
||||||
|
{
|
||||||
|
inc_str_pos( &str2, &len2, &dpos2, &dlen2 );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ce1 - ce2) return ce1 - ce2;
|
||||||
|
|
||||||
|
inc_str_pos( &str1, &len1, &dpos1, &dlen1 );
|
||||||
|
inc_str_pos( &str2, &len2, &dpos2, &dlen2 );
|
||||||
|
}
|
||||||
|
while (len1)
|
||||||
|
{
|
||||||
|
if (!dlen1) dlen1 = wine_decompose( 0, *str1, dstr1, 4 );
|
||||||
|
ce1 = get_weight( dstr1[dpos1], type );
|
||||||
|
if (ce1) break;
|
||||||
|
inc_str_pos( &str1, &len1, &dpos1, &dlen1 );
|
||||||
|
}
|
||||||
|
while (len2)
|
||||||
|
{
|
||||||
|
if (!dlen2) dlen2 = wine_decompose( 0, *str2, dstr2, 4 );
|
||||||
|
ce2 = get_weight( dstr2[dpos2], type );
|
||||||
|
if (ce2) break;
|
||||||
|
inc_str_pos( &str2, &len2, &dpos2, &dlen2 );
|
||||||
|
}
|
||||||
|
return len1 - len2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Note: the Internal_ functions are not documented. The number of parameters
|
/* Note: the Internal_ functions are not documented. The number of parameters
|
||||||
* should be correct, but their exact meaning may not.
|
* should be correct, but their exact meaning may not.
|
||||||
*/
|
*/
|
||||||
|
@ -2138,6 +2257,141 @@ BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumUILanguages( UILANGUAGE_ENUMPROCW pro
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CompareStringEx (kernelbase.@)
|
||||||
|
*/
|
||||||
|
INT WINAPI CompareStringEx( const WCHAR *locale, DWORD flags, const WCHAR *str1, int len1,
|
||||||
|
const WCHAR *str2, int len2, NLSVERSIONINFO *version,
|
||||||
|
void *reserved, LPARAM handle )
|
||||||
|
{
|
||||||
|
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 (handle) FIXME( "unexpected handle\n" );
|
||||||
|
|
||||||
|
if (!str1 || !str2)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & ~(supported_flags | semistub_flags))
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_INVALID_FLAGS );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & semistub_flags)
|
||||||
|
{
|
||||||
|
if (!once++) FIXME( "semi-stub behavior for flag(s) 0x%x\n", flags & semistub_flags );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len1 < 0) len1 = lstrlenW(str1);
|
||||||
|
if (len2 < 0) len2 = lstrlenW(str2);
|
||||||
|
|
||||||
|
ret = compare_weights( flags, str1, len1, str2, len2, UNICODE_WEIGHT );
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
if (!(flags & NORM_IGNORENONSPACE))
|
||||||
|
ret = compare_weights( flags, str1, len1, str2, len2, DIACRITIC_WEIGHT );
|
||||||
|
if (!ret && !(flags & NORM_IGNORECASE))
|
||||||
|
ret = compare_weights( flags, str1, len1, str2, len2, CASE_WEIGHT );
|
||||||
|
}
|
||||||
|
if (!ret) return CSTR_EQUAL;
|
||||||
|
return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CompareStringA (kernelbase.@)
|
||||||
|
*/
|
||||||
|
INT WINAPI DECLSPEC_HOTPATCH CompareStringA( LCID lcid, DWORD flags, const char *str1, int len1,
|
||||||
|
const char *str2, int len2 )
|
||||||
|
{
|
||||||
|
WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer;
|
||||||
|
WCHAR *buf2W = buf1W + 130;
|
||||||
|
LPWSTR str1W, str2W;
|
||||||
|
INT len1W = 0, len2W = 0, ret;
|
||||||
|
UINT locale_cp = CP_ACP;
|
||||||
|
|
||||||
|
if (!str1 || !str2)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (len1 < 0) len1 = strlen(str1);
|
||||||
|
if (len2 < 0) len2 = strlen(str2);
|
||||||
|
|
||||||
|
locale_cp = get_lcid_codepage( lcid, flags );
|
||||||
|
if (len1)
|
||||||
|
{
|
||||||
|
if (len1 <= 130) len1W = MultiByteToWideChar( locale_cp, 0, str1, len1, buf1W, 130 );
|
||||||
|
if (len1W) str1W = buf1W;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len1W = MultiByteToWideChar( locale_cp, 0, str1, len1, NULL, 0 );
|
||||||
|
str1W = HeapAlloc( GetProcessHeap(), 0, len1W * sizeof(WCHAR) );
|
||||||
|
if (!str1W)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
MultiByteToWideChar( locale_cp, 0, str1, len1, str1W, len1W );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len1W = 0;
|
||||||
|
str1W = buf1W;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len2)
|
||||||
|
{
|
||||||
|
if (len2 <= 130) len2W = MultiByteToWideChar( locale_cp, 0, str2, len2, buf2W, 130 );
|
||||||
|
if (len2W) str2W = buf2W;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len2W = MultiByteToWideChar( locale_cp, 0, str2, len2, NULL, 0 );
|
||||||
|
str2W = HeapAlloc( GetProcessHeap(), 0, len2W * sizeof(WCHAR) );
|
||||||
|
if (!str2W)
|
||||||
|
{
|
||||||
|
if (str1W != buf1W) HeapFree( GetProcessHeap(), 0, str1W );
|
||||||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
MultiByteToWideChar( locale_cp, 0, str2, len2, str2W, len2W );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len2W = 0;
|
||||||
|
str2W = buf2W;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = CompareStringW( lcid, flags, str1W, len1W, str2W, len2W );
|
||||||
|
|
||||||
|
if (str1W != buf1W) HeapFree( GetProcessHeap(), 0, str1W );
|
||||||
|
if (str2W != buf2W) HeapFree( GetProcessHeap(), 0, str2W );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CompareStringW (kernelbase.@)
|
||||||
|
*/
|
||||||
|
INT WINAPI DECLSPEC_HOTPATCH CompareStringW( LCID lcid, DWORD flags, const WCHAR *str1, int len1,
|
||||||
|
const WCHAR *str2, int len2 )
|
||||||
|
{
|
||||||
|
return CompareStringEx( NULL, flags, str1, len1, str2, len2, NULL, NULL, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* CompareStringOrdinal (kernelbase.@)
|
* CompareStringOrdinal (kernelbase.@)
|
||||||
*/
|
*/
|
||||||
|
@ -2422,6 +2676,64 @@ BOOL WINAPI DECLSPEC_HOTPATCH EnumTimeFormatsEx( TIMEFMT_ENUMPROCEX proc, const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* FindNLSString (kernelbase.@)
|
||||||
|
*/
|
||||||
|
INT WINAPI DECLSPEC_HOTPATCH FindNLSString( LCID lcid, DWORD flags, const WCHAR *src,
|
||||||
|
int srclen, const WCHAR *value, int valuelen, int *found )
|
||||||
|
{
|
||||||
|
WCHAR locale[LOCALE_NAME_MAX_LENGTH];
|
||||||
|
|
||||||
|
LCIDToLocaleName( lcid, locale, ARRAY_SIZE(locale), 0 );
|
||||||
|
return FindNLSStringEx( locale, flags, src, srclen, value, valuelen, found, NULL, NULL, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* FindNLSStringEx (kernelbase.@)
|
||||||
|
*/
|
||||||
|
INT WINAPI DECLSPEC_HOTPATCH FindNLSStringEx( const WCHAR *locale, DWORD flags, const WCHAR *src,
|
||||||
|
int srclen, const WCHAR *value, int valuelen, int *found,
|
||||||
|
NLSVERSIONINFO *version, void *reserved, LPARAM handle )
|
||||||
|
{
|
||||||
|
/* FIXME: this function should normalize strings before calling CompareStringEx() */
|
||||||
|
DWORD mask = flags;
|
||||||
|
int offset, inc, count;
|
||||||
|
|
||||||
|
TRACE( "%s %x %s %d %s %d %p %p %p %ld\n", wine_dbgstr_w(locale), flags,
|
||||||
|
wine_dbgstr_w(src), srclen, wine_dbgstr_w(value), valuelen, found,
|
||||||
|
version, reserved, handle );
|
||||||
|
|
||||||
|
if (version || reserved || handle || !IsValidLocaleName(locale) ||
|
||||||
|
!src || !srclen || srclen < -1 || !value || !valuelen || valuelen < -1)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (srclen == -1) srclen = lstrlenW(src);
|
||||||
|
if (valuelen == -1) valuelen = lstrlenW(value);
|
||||||
|
|
||||||
|
srclen -= valuelen;
|
||||||
|
if (srclen < 0) return -1;
|
||||||
|
|
||||||
|
mask = flags & ~(FIND_FROMSTART | FIND_FROMEND | FIND_STARTSWITH | FIND_ENDSWITH);
|
||||||
|
count = flags & (FIND_FROMSTART | FIND_FROMEND) ? srclen + 1 : 1;
|
||||||
|
offset = flags & (FIND_FROMSTART | FIND_STARTSWITH) ? 0 : srclen;
|
||||||
|
inc = flags & (FIND_FROMSTART | FIND_STARTSWITH) ? 1 : -1;
|
||||||
|
while (count--)
|
||||||
|
{
|
||||||
|
if (CompareStringEx( locale, mask, src + offset, valuelen,
|
||||||
|
value, valuelen, NULL, NULL, 0 ) == CSTR_EQUAL)
|
||||||
|
{
|
||||||
|
if (found) *found = valuelen;
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
offset += inc;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* FindStringOrdinal (kernelbase.@)
|
* FindStringOrdinal (kernelbase.@)
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue