From: Donat Enikeev Subject: locale: [1/1] patch - 0x10000000 flag is NORM_STOP_ON_NULL (plus test fix and win2k case) Message-Id: <3702811428397337@web20g.yandex.ru> Date: Tue, 07 Apr 2015 12:02:17 +0300 Hi all, Following Marvin-bot message, re-did tests (by analogy with existing part of test_CompareStringEx. 2015-04-07 - added win2k test case Original patch and explanations: https://source.winehq.org/patches/data/110600 --de From 7e5dabe053cbb3ad4891dd68789fab5c96344a51 Mon Sep 17 00:00:00 2001 From: Donat Enikeev Date: Tue, 7 Apr 2015 11:55:31 +0300 Subject: 0x10000000 flag is NORM_STOP_ON_NULL (tests enxtended, win2k case) --- dlls/kernel32/locale.c | 12 ++++----- dlls/kernel32/tests/locale.c | 61 ++++++++++++++++++++++++++++++++++++++++++++ include/winnls.h | 1 + 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c index 9896872..8b190fb 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c @@ -3244,9 +3244,9 @@ 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 */ + |NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|LOCALE_USE_CP_ACP|NORM_STOP_ON_NULL; + DWORD semistub_flags = NORM_LINGUISTIC_CASING|LINGUISTIC_IGNORECASE; + INT ret; if (version) FIXME("unexpected version parameter\n"); @@ -3266,10 +3266,10 @@ INT WINAPI CompareStringEx(LPCWSTR locale, DWORD flags, LPCWSTR str1, INT len1, } if (flags & semistub_flags) - FIXME("semi-stub behavor for flag(s) 0x%x\n", flags & semistub_flags); + FIXME("semi-stub behaviour for flag(s) 0x%x\n", flags & semistub_flags); - if (len1 < 0) len1 = strlenW(str1); - if (len2 < 0) len2 = strlenW(str2); + if (len1 < 0 || (flags & NORM_STOP_ON_NULL) ) len1 = strlenW(str1); + if (len2 < 0 || (flags & NORM_STOP_ON_NULL) ) len2 = strlenW(str2); ret = wine_compare_string(flags, str1, len1, str2, len2); diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 95e0ac6..2e83d24 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -1742,19 +1742,46 @@ static void test_CompareStringA(void) /* WinXP handles embedded NULLs differently than earlier versions */ ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10); + /* Windows 10 - LESS */ ok(ret == CSTR_LESS_THAN || ret == CSTR_EQUAL, "aLuZkUtZ vs aLuZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret); ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10); + /* Windows 10 - LESS */ ok(ret == CSTR_LESS_THAN || ret == CSTR_EQUAL, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret); ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1); + /* Windows 10 - EQUAL */ ok(ret == CSTR_EQUAL, "a vs a expected CSTR_EQUAL, got %d\n", ret); ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2); + /* Windows 10 - GREATER */ ok(ret == CSTR_EQUAL || /* win2k */ ret == CSTR_GREATER_THAN, "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret); + /* Testing NORM_STOP_ON_NULL flag*/ + ret = CompareStringA(lcid, NORM_STOP_ON_NULL, "don\0a", -1, "don\0b", -1); + ok(ret == CSTR_EQUAL, + "With str length autodetect (-1) and NORM_STOP_ON_NULL flag - strings `don\\0a` and `don\\0b` expected CSTR_EQUAL , got %d\n", ret); + + ret = CompareStringA(lcid, NORM_STOP_ON_NULL, "don\0a", -1, "don\0b", 5); + ok(ret == CSTR_EQUAL, + "With NORM_STOP_ON_NULL flag - strings `don\\0a` (-1) and `don\\0b` (5) expected CSTR_EQUAL , got %d\n", ret); + + ret = CompareStringA(lcid, NORM_STOP_ON_NULL, "don\0a", 5, "don\0b", 5); + ok(ret == CSTR_EQUAL, + "With NORM_STOP_ON_NULL flag - strings `don\\0a` (-1) and `don\\0b` (5) expected CSTR_EQUAL , got %d\n", ret); + + ret = CompareStringA(lcid, 0 , "don\0a", 5, "don\0b", 5); + ok( + ret == CSTR_EQUAL || /* win2k */ + ret == CSTR_LESS_THAN, + "Without NORM_STOP_ON_NULL flag - strings `don\\0a` (5) and `don\\0b` (5) expected CSTR_LESS_THAN, got %d\n", ret); + + ret = CompareStringA(lcid, 0 , "don\0a", 5, "don\0b", -1); + ok(ret == CSTR_GREATER_THAN, + "Without NORM_STOP_ON_NULL flag - strings `don\\0a` (5) and `don\\0b` (-1) expected CSTR_GREATER_THAN, got %d\n", ret); + ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2); todo_wine ok(ret != CSTR_EQUAL, "\\2 vs \\1 expected unequal\n"); @@ -1976,6 +2003,40 @@ static void test_CompareStringEx(void) } } + /* NORM_STOP_ON_NULL flag tests*/ + + const WCHAR a[] = {'d','o','n',0,'a','t',0}; // don\0at + const WCHAR b[] = {'d','o','n',0,'_','_',0}; // don\0__ + MultiByteToWideChar(CP_ACP, 0,"ru-RU", -1, locale, sizeof(locale) / sizeof(WCHAR)); + + ret = pCompareStringEx(locale, NORM_STOP_ON_NULL, a, -1, b, -1, NULL, NULL, 0); + ok(ret == CSTR_EQUAL, + "NORM_STOP_ON_NULL flag, though its equal to length autodetect (-1) - strings `don\\0at` (-1) and `don\\__` (-1) expected CSTR_EQUAL for locale %ls, got %d\n",locale,ret); + + ret = pCompareStringEx(locale, 0, a, -1, b, -1, NULL, NULL, 0); + ok(ret == CSTR_EQUAL, + "NORM_STOP_ON_NULL is not set, strings considered as null terminated - so strings `don\\0at` (-1) and `don\\__` (-1) expected CSTR_EQUAL, got %d\n", ret); + + ret = pCompareStringEx(locale, NORM_STOP_ON_NULL, a, 6, b, 6, NULL, NULL, 0); + ok(ret == CSTR_EQUAL, + "NORM_STOP_ON_NULL flag, and lengths are defined expl - so strings `don\\0at` (6) and `don\\__` (6) are expected CSTR_EQUAL due to flag, got %d\n", ret); + + ret = pCompareStringEx(locale, NORM_STOP_ON_NULL, a, 6, b, -1, NULL, NULL, 0); + ok(ret == CSTR_EQUAL, + "NORM_STOP_ON_NULL flag, and length is defined expl for one string - anyway strings `don\\0at` (6) and `don\\__` (-1) are expected CSTR_EQUAL due to flag, got %d\n", ret); + + const WCHAR c[] = {'d','O','n',0,'A','t',0}; // dOn\0At + + ret = pCompareStringEx(locale, NORM_STOP_ON_NULL | NORM_IGNORECASE, a, -1, c, -1, NULL, NULL, 0); + ok(ret == CSTR_EQUAL, + "NORM_STOP_ON_NULL | NORM_IGNORECASE flags, though its equal to length autodetect (-1) - so strings `don\\0at` (-1) and `dOn\\At` (-1) expected CSTR_EQUAL, got %d\n", ret); + + ret = pCompareStringEx(locale, NORM_STOP_ON_NULL | NORM_IGNORECASE, a, 6, c, 6, NULL, NULL, 0); + ok(ret == CSTR_EQUAL, + "NORM_STOP_ON_NULL | NORM_IGNORECASE flags, and lengths are defined explicitely - so strings `don\\0at` (-1) and `dOn\\At` (-1) expected CSTR_EQUAL, got %d\n", ret); + + /* end of NORM_STOP_ON_NULL test */ + } static void test_LCMapStringA(void) diff --git a/include/winnls.h b/include/winnls.h index b1ce0cd..be9a0b6 100644 --- a/include/winnls.h +++ b/include/winnls.h @@ -352,6 +352,7 @@ static const WCHAR LOCALE_NAME_SYSTEM_DEFAULT[] = {'!','s','y','s','-','d','e',' #define NORM_IGNOREKANATYPE 0x00010000 #define NORM_IGNOREWIDTH 0x00020000 #define NORM_LINGUISTIC_CASING 0x08000000 +#define NORM_STOP_ON_NULL 0x10000000 #define CP_ACP 0 #define CP_OEMCP 1 -- 2.1.0