mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-15 06:54:46 +00:00
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)
|
||||
# @ stub CompareCalendarDates
|
||||
@ stdcall -import CompareFileTime(ptr ptr)
|
||||
@ stdcall CompareStringA(long long str long str long)
|
||||
@ stdcall CompareStringW(long long wstr long wstr long)
|
||||
@ stdcall CompareStringEx(wstr long wstr long wstr long ptr ptr long)
|
||||
@ stdcall -import CompareStringA(long long str long str long)
|
||||
@ stdcall -import CompareStringEx(wstr long wstr long wstr long ptr ptr long)
|
||||
@ stdcall -import CompareStringOrdinal(wstr long wstr long long)
|
||||
@ stdcall -import CompareStringW(long long wstr long wstr long)
|
||||
@ stdcall -import ConnectNamedPipe(long ptr)
|
||||
@ stub ConsoleMenuControl
|
||||
@ stub ConsoleSubst
|
||||
|
@ -502,8 +502,8 @@
|
|||
@ stub FindNextVolumeMountPointA
|
||||
@ stub FindNextVolumeMountPointW
|
||||
@ stdcall FindNextVolumeW(long ptr long)
|
||||
# @ stub FindNLSString
|
||||
@ stdcall FindNLSStringEx(wstr long wstr long wstr long ptr ptr ptr long)
|
||||
@ stdcall -import FindNLSString(long long wstr long wstr long ptr)
|
||||
@ stdcall -import FindNLSStringEx(wstr long wstr long wstr long ptr ptr ptr long)
|
||||
@ stdcall FindResourceA(long str str)
|
||||
@ stdcall FindResourceExA(long str str long)
|
||||
@ stdcall -import FindResourceExW(long wstr wstr long)
|
||||
|
|
|
@ -445,153 +445,6 @@ FoldStringA_exit:
|
|||
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)
|
||||
{
|
||||
UNICODE_STRING keyName;
|
||||
|
@ -1900,54 +1753,3 @@ BOOL WINAPI GetFileMUIInfo(DWORD flags, PCWSTR path, FILEMUIINFO *info, DWORD *s
|
|||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
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
|
||||
@ stdcall CompareFileTime(ptr ptr)
|
||||
# @ stub CompareObjectHandles
|
||||
@ stdcall CompareStringA(long long str long str long) kernel32.CompareStringA
|
||||
@ stdcall CompareStringEx(wstr long wstr long wstr long ptr ptr long) kernel32.CompareStringEx
|
||||
@ stdcall CompareStringA(long long str long str long)
|
||||
@ stdcall CompareStringEx(wstr long wstr long wstr long ptr ptr 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 ContinueDebugEvent(long long long)
|
||||
@ stdcall ConvertDefaultLocale(long)
|
||||
|
@ -362,8 +362,8 @@
|
|||
@ stdcall FindFirstFreeAce(ptr ptr)
|
||||
@ stdcall FindFirstStreamW(wstr long ptr long) kernel32.FindFirstStreamW
|
||||
@ stdcall FindFirstVolumeW(ptr long) kernel32.FindFirstVolumeW
|
||||
@ stub FindNLSString
|
||||
@ stdcall FindNLSStringEx(wstr long wstr long wstr long ptr ptr ptr long) kernel32.FindNLSStringEx
|
||||
@ stdcall FindNLSString(long long wstr long wstr long ptr)
|
||||
@ stdcall FindNLSStringEx(wstr long wstr long wstr long ptr ptr ptr long)
|
||||
@ stdcall FindNextChangeNotification(long)
|
||||
@ stdcall FindNextFileA(long ptr) kernel32.FindNextFileA
|
||||
# @ 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
|
||||
* 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.@)
|
||||
*/
|
||||
|
@ -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.@)
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue