[PATCH] kernel32: Implement CompareStringOrdinal. (try 3)

Christian Costa titan.costa at gmail.com
Tue Oct 30 03:45:55 CDT 2012


Try 3:
 - Add tests for non ASCII case.

Try 2:
 - Don't use CompareStringEx.
 - Add tests
---
 dlls/kernel32/kernel32.spec  |    1 +
 dlls/kernel32/locale.c       |   28 ++++++++++++++++++
 dlls/kernel32/tests/locale.c |   66 +++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index b7efa0f..0bd1adc 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -201,6 +201,7 @@
 @ 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 CompareStringOrdinal(wstr long wstr long long)
 @ stdcall ConnectNamedPipe(long ptr)
 @ stub ConsoleMenuControl
 @ stub ConsoleSubst
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index c41442c..07eb688 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -3047,6 +3047,34 @@ INT WINAPI CompareStringA(LCID lcid, DWORD flags,
     return ret;
 }
 
+/******************************************************************************
+ *           CompareStringOrdinal    (KERNEL32.@)
+ */
+INT WINAPI CompareStringOrdinal(const WCHAR *str1, INT len1, const WCHAR *str2, INT len2, BOOL ignore_case)
+{
+    int ret, len;
+
+    if (!str1 || !str2)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+    if (len1 < 0) len1 = strlenW(str1);
+    if (len2 < 0) len2 = strlenW(str2);
+
+    len = min(len1, len2);
+    if (ignore_case)
+        ret = strncmpiW(str1, str2, len);
+    else
+        ret = strncmpW(str1, str2, len);
+
+    if ((ret < 0) || (!ret && (len1 < len2)))
+        return CSTR_LESS_THAN;
+    else if ((ret > 0) || (!ret && (len1 > len2)))
+        return CSTR_GREATER_THAN;
+    return CSTR_EQUAL;
+}
+
 /*************************************************************************
  *           lstrcmp     (KERNEL32.@)
  *           lstrcmpA    (KERNEL32.@)
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index 0225c2b..212d667 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -87,6 +87,7 @@ static INT (WINAPI *pIdnToAscii)(DWORD, LPCWSTR, INT, LPWSTR, INT);
 static INT (WINAPI *pIdnToUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
 static INT (WINAPI *pGetLocaleInfoEx)(LPCWSTR, LCTYPE, LPWSTR, INT);
 static BOOL (WINAPI *pIsValidLocaleName)(LPCWSTR);
+static INT (WINAPI *pCompareStringOrdinal)(const WCHAR *, INT, const WCHAR *, INT, BOOL);
 
 static void InitFunctionPointers(void)
 {
@@ -106,6 +107,7 @@ static void InitFunctionPointers(void)
   pIdnToUnicode = (void*)GetProcAddress(hKernel32, "IdnToUnicode");
   pGetLocaleInfoEx = (void*)GetProcAddress(hKernel32, "GetLocaleInfoEx");
   pIsValidLocaleName = (void*)GetProcAddress(hKernel32, "IsValidLocaleName");
+  pCompareStringOrdinal = (void*)GetProcAddress(hKernel32, "CompareStringOrdinal");
 }
 
 #define eq(received, expected, label, type) \
@@ -3478,11 +3480,72 @@ static void test_IsValidLocaleName(void)
     ok(!ret, "IsValidLocaleName should have failed\n");
 }
 
+void test_CompareStringOrdinal(void)
+{
+    INT ret;
+    WCHAR test1[] = { 't','e','s','t',0 };
+    WCHAR test2[] = { 'T','e','S','t',0 };
+    WCHAR test3[] = { 't','e','s','t','3',0 };
+    WCHAR bills1[] = { 'b','i','l','l','\'','s',0 };
+    WCHAR bills2[] = { 'b','i','l','l','s',0 };
+    WCHAR coop1[] = { 'c','o','-','o','p',0 };
+    WCHAR coop2[] = { 'c','o','o','p',0 };
+    WCHAR nonascii1[] = { 0x0102,0 };
+    WCHAR nonascii2[] = { 0x0201,0 };
+
+    if (!pCompareStringOrdinal)
+    {
+        win_skip("CompareStringOrdinal not supported\n");
+        return;
+    }
+
+    /* Check errors */
+    SetLastError(0xdeadbeef);
+    ret = pCompareStringOrdinal(NULL, 0, NULL, 0, FALSE);
+    ok(!ret, "Got %u, expected 0\n", ret);
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
+    SetLastError(0xdeadbeef);
+    ret = pCompareStringOrdinal(test1, -1, NULL, 0, FALSE);
+    ok(!ret, "Got %u, expected 0\n", ret);
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
+    SetLastError(0xdeadbeef);
+    ret = pCompareStringOrdinal(NULL, 0, test1, -1, FALSE);
+    ok(!ret, "Got %u, expected 0\n", ret);
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
+
+    /* Check case */
+    ret = pCompareStringOrdinal(test1, -1, test1, -1, FALSE);
+    ok(ret == CSTR_EQUAL, "Got %u, expected %u\n", ret, CSTR_EQUAL);
+    ret = pCompareStringOrdinal(test1, -1, test2, -1, FALSE);
+    ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
+    ret = pCompareStringOrdinal(test2, -1, test1, -1, FALSE);
+    ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
+    ret = pCompareStringOrdinal(test1, -1, test2, -1, TRUE);
+    ok(ret == CSTR_EQUAL, "Got %u, expected %u\n", ret, CSTR_EQUAL);
+
+    /* Check different sizes */
+    ret = pCompareStringOrdinal(test1, 3, test2, -1, TRUE);
+    ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
+    ret = pCompareStringOrdinal(test1, -1, test2, 3, TRUE);
+    ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
+    ret = pCompareStringOrdinal(test1, 5, test3, 5, TRUE);
+    ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
+
+    /* Check ordinal behaviour */
+    ret = pCompareStringOrdinal(bills1, -1, bills2, -1, FALSE);
+    ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
+    ret = pCompareStringOrdinal(coop2, -1, coop1, -1, FALSE);
+    ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
+    ret = pCompareStringOrdinal(nonascii1, -1, nonascii2, -1, FALSE);
+    ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
+    ret = pCompareStringOrdinal(nonascii1, -1, nonascii2, -1, TRUE);
+    ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
+}
+
 START_TEST(locale)
 {
   InitFunctionPointers();
 
-
   test_EnumTimeFormatsA();
   test_EnumDateFormatsA();
   test_GetLocaleInfoA();
@@ -3512,6 +3575,7 @@ START_TEST(locale)
   test_IdnToAscii();
   test_IdnToUnicode();
   test_IsValidLocaleName();
+  test_CompareStringOrdinal();
   /* this requires collation table patch to make it MS compatible */
   if (0) test_sorting();
 }




More information about the wine-patches mailing list