[PATCH] kernel32: Implement FindStringOrdinal.

Zhiyi Zhang zzhang at codeweavers.com
Tue Oct 30 01:31:57 CDT 2018


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46035
Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 .../api-ms-win-core-libraryloader-l1-1-0.spec |  2 +-
 .../api-ms-win-core-libraryloader-l1-1-1.spec |  2 +-
 .../api-ms-win-core-libraryloader-l1-2-0.spec |  2 +-
 dlls/kernel32/kernel32.spec                   |  2 +-
 dlls/kernel32/locale.c                        | 49 +++++++++++++
 dlls/kernel32/tests/locale.c                  | 70 +++++++++++++++++++
 dlls/kernelbase/kernelbase.spec               |  2 +-
 include/libloaderapi.h                        |  1 +
 8 files changed, 125 insertions(+), 5 deletions(-)

diff --git a/dlls/api-ms-win-core-libraryloader-l1-1-0/api-ms-win-core-libraryloader-l1-1-0.spec b/dlls/api-ms-win-core-libraryloader-l1-1-0/api-ms-win-core-libraryloader-l1-1-0.spec
index 7d1fcac9e2..a011bee54f 100644
--- a/dlls/api-ms-win-core-libraryloader-l1-1-0/api-ms-win-core-libraryloader-l1-1-0.spec
+++ b/dlls/api-ms-win-core-libraryloader-l1-1-0/api-ms-win-core-libraryloader-l1-1-0.spec
@@ -7,7 +7,7 @@
 @ stub EnumResourceTypesExA
 @ stub EnumResourceTypesExW
 @ stdcall FindResourceExW(long wstr wstr long) kernel32.FindResourceExW
-@ stub FindStringOrdinal
+@ stdcall FindStringOrdinal(long wstr long wstr long long) kernel32.FindStringOrdinal
 @ stdcall FreeLibrary(long) kernel32.FreeLibrary
 @ stdcall FreeLibraryAndExitThread(long long) kernel32.FreeLibraryAndExitThread
 @ stdcall FreeResource(long) kernel32.FreeResource
diff --git a/dlls/api-ms-win-core-libraryloader-l1-1-1/api-ms-win-core-libraryloader-l1-1-1.spec b/dlls/api-ms-win-core-libraryloader-l1-1-1/api-ms-win-core-libraryloader-l1-1-1.spec
index 9c0bed10f6..eea8f235c8 100644
--- a/dlls/api-ms-win-core-libraryloader-l1-1-1/api-ms-win-core-libraryloader-l1-1-1.spec
+++ b/dlls/api-ms-win-core-libraryloader-l1-1-1/api-ms-win-core-libraryloader-l1-1-1.spec
@@ -7,7 +7,7 @@
 @ stub EnumResourceTypesExA
 @ stub EnumResourceTypesExW
 @ stdcall FindResourceExW(long wstr wstr long) kernel32.FindResourceExW
-@ stub FindStringOrdinal
+@ stdcall FindStringOrdinal(long wstr long wstr long long) kernel32.FindStringOrdinal
 @ stdcall FreeLibrary(long) kernel32.FreeLibrary
 @ stdcall FreeLibraryAndExitThread(long long) kernel32.FreeLibraryAndExitThread
 @ stdcall FreeResource(long) kernel32.FreeResource
diff --git a/dlls/api-ms-win-core-libraryloader-l1-2-0/api-ms-win-core-libraryloader-l1-2-0.spec b/dlls/api-ms-win-core-libraryloader-l1-2-0/api-ms-win-core-libraryloader-l1-2-0.spec
index 7d1fcac9e2..a011bee54f 100644
--- a/dlls/api-ms-win-core-libraryloader-l1-2-0/api-ms-win-core-libraryloader-l1-2-0.spec
+++ b/dlls/api-ms-win-core-libraryloader-l1-2-0/api-ms-win-core-libraryloader-l1-2-0.spec
@@ -7,7 +7,7 @@
 @ stub EnumResourceTypesExA
 @ stub EnumResourceTypesExW
 @ stdcall FindResourceExW(long wstr wstr long) kernel32.FindResourceExW
-@ stub FindStringOrdinal
+@ stdcall FindStringOrdinal(long wstr long wstr long long) kernel32.FindStringOrdinal
 @ stdcall FreeLibrary(long) kernel32.FreeLibrary
 @ stdcall FreeLibraryAndExitThread(long long) kernel32.FreeLibraryAndExitThread
 @ stdcall FreeResource(long) kernel32.FreeResource
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index c38b8f81f5..74af2a4570 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -511,7 +511,7 @@
 @ stdcall FindResourceExA(long str str long)
 @ stdcall FindResourceExW(long wstr wstr long)
 @ stdcall FindResourceW(long wstr wstr)
-# @ stub FindStringOrdinal
+@ stdcall FindStringOrdinal(long wstr long wstr long long)
 @ stdcall FindVolumeClose(ptr)
 @ stdcall FindVolumeMountPointClose(ptr)
 @ stdcall FlsAlloc(ptr)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index 4d1eac6ebe..e62b849d09 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -5999,3 +5999,52 @@ INT WINAPI FindNLSStringEx(const WCHAR *localename, DWORD flags, const WCHAR *sr
 
     return -1;
 }
+
+/******************************************************************************
+ *           FindStringOrdinal (KERNEL32.@)
+ */
+
+INT WINAPI FindStringOrdinal(DWORD flag, const WCHAR *src, INT src_size, const WCHAR *val, INT val_size,
+                             BOOL ignore_case)
+{
+    INT offset, inc, count;
+    TRACE("%#x %s %d %s %d %d\n", flag, wine_dbgstr_w(src), src_size, wine_dbgstr_w(val), val_size, ignore_case);
+
+    if (!src || !val)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return -1;
+    }
+
+    if (flag != FIND_FROMSTART && flag != FIND_FROMEND && flag != FIND_STARTSWITH && flag != FIND_ENDSWITH)
+    {
+        SetLastError(ERROR_INVALID_FLAGS);
+        return -1;
+    }
+
+    if (src_size == -1) src_size = strlenW(src);
+    if (val_size == -1) val_size = strlenW(val);
+
+    src_size -= val_size;
+    if (src_size < 0)
+    {
+        SetLastError(NO_ERROR);
+        return -1;
+    }
+
+    count = flag & (FIND_FROMSTART | FIND_FROMEND) ? src_size + 1 : 1;
+    offset = flag & (FIND_FROMSTART | FIND_STARTSWITH) ? 0 : src_size;
+    inc = flag & (FIND_FROMSTART | FIND_STARTSWITH) ? 1 : -1;
+    while (count--)
+    {
+        if (CompareStringOrdinal(src + offset, val_size, val, val_size, ignore_case) == CSTR_EQUAL)
+        {
+            SetLastError(NO_ERROR);
+            return offset;
+        }
+        offset += inc;
+    }
+
+    SetLastError(NO_ERROR);
+    return -1;
+}
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index d3eb2ecf15..3357d0db9e 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -107,6 +107,7 @@ static INT (WINAPI *pFindNLSStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPCWSTR, INT
 static LANGID (WINAPI *pSetThreadUILanguage)(LANGID);
 static LANGID (WINAPI *pGetThreadUILanguage)(VOID);
 static INT (WINAPI *pNormalizeString)(NORM_FORM, LPCWSTR, INT, LPWSTR, INT);
+static INT (WINAPI *pFindStringOrdinal)(DWORD, LPCWSTR lpStringSource, INT, LPCWSTR, INT, BOOL);
 
 static void InitFunctionPointers(void)
 {
@@ -143,6 +144,7 @@ static void InitFunctionPointers(void)
   X(SetThreadUILanguage);
   X(GetThreadUILanguage);
   X(NormalizeString);
+  X(FindStringOrdinal);
 
   mod = GetModuleHandleA("ntdll");
   X(RtlUpcaseUnicodeChar);
@@ -5496,6 +5498,73 @@ static void test_FindNLSStringEx(void)
     }
 }
 
+static void test_FindStringOrdinal(void)
+{
+    static const WCHAR abc123aBcW[] = {'a', 'b', 'c', '1', '2', '3', 'a', 'B', 'c', 0};
+    static const WCHAR abcW[] = {'a', 'b', 'c', 0};
+    static const WCHAR aBcW[] = {'a', 'B', 'c', 0};
+    static const WCHAR aaaW[] = {'a', 'a', 'a', 0};
+    static const struct
+    {
+        DWORD flag;
+        const WCHAR *src;
+        INT src_size;
+        const WCHAR *val;
+        INT val_size;
+        BOOL ignore_case;
+        INT ret;
+        DWORD err;
+    }
+    tests[] =
+    {
+        /* Invalid */
+        {1, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, abcW, ARRAY_SIZE(abcW) - 1, FALSE, -1, ERROR_INVALID_FLAGS},
+        {FIND_FROMSTART, NULL, ARRAY_SIZE(abc123aBcW) - 1, abcW, ARRAY_SIZE(abcW) - 1, FALSE, -1,
+         ERROR_INVALID_PARAMETER},
+        {FIND_FROMSTART, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, NULL, ARRAY_SIZE(abcW) - 1, FALSE, -1,
+         ERROR_INVALID_PARAMETER},
+        {FIND_FROMSTART, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, NULL, 0, FALSE, -1, ERROR_INVALID_PARAMETER},
+        {FIND_FROMSTART, NULL, 0, abcW, ARRAY_SIZE(abcW) - 1, FALSE, -1, ERROR_INVALID_PARAMETER},
+        {FIND_FROMSTART, NULL, 0, NULL, 0, FALSE, -1, ERROR_INVALID_PARAMETER},
+        /* Case-insensitive */
+        {FIND_FROMSTART, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, abcW, ARRAY_SIZE(abcW) - 1, FALSE, 0, NO_ERROR},
+        {FIND_FROMEND, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, abcW, ARRAY_SIZE(abcW) - 1, FALSE, 0, NO_ERROR},
+        {FIND_STARTSWITH, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, abcW, ARRAY_SIZE(abcW) - 1, FALSE, 0, NO_ERROR},
+        {FIND_ENDSWITH, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, abcW, ARRAY_SIZE(abcW) - 1, FALSE, -1, NO_ERROR},
+        /* Case-sensitive */
+        {FIND_FROMSTART, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, aBcW, ARRAY_SIZE(aBcW) - 1, TRUE, 0, NO_ERROR},
+        {FIND_FROMEND, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, aBcW, ARRAY_SIZE(aBcW) - 1, TRUE, 6, NO_ERROR},
+        {FIND_STARTSWITH, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, aBcW, ARRAY_SIZE(aBcW) - 1, TRUE, 0, NO_ERROR},
+        {FIND_ENDSWITH, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, aBcW, ARRAY_SIZE(aBcW) - 1, TRUE, 6, NO_ERROR},
+        /* Other */
+        {FIND_FROMSTART, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, aaaW, ARRAY_SIZE(aaaW) - 1, FALSE, -1, NO_ERROR},
+        {FIND_FROMSTART, abc123aBcW, -1, abcW, ARRAY_SIZE(abcW) - 1, FALSE, 0, NO_ERROR},
+        {FIND_FROMSTART, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, abcW, -1, FALSE, 0, NO_ERROR},
+        {FIND_FROMSTART, abc123aBcW, 0, abcW, ARRAY_SIZE(abcW) - 1, FALSE, -1, NO_ERROR},
+        {FIND_FROMSTART, abc123aBcW, ARRAY_SIZE(abc123aBcW) - 1, abcW, 0, FALSE, 0, NO_ERROR},
+        {FIND_FROMSTART, abc123aBcW, 0, abcW, 0, FALSE, 0, NO_ERROR},
+    };
+    INT ret;
+    DWORD err;
+    INT i;
+
+    if (!pFindStringOrdinal)
+    {
+        win_skip("FindStringOrdinal is not available.\n");
+        return;
+    }
+
+    for (i = 0; i < ARRAY_SIZE(tests); i++)
+    {
+        SetLastError(0xdeadbeef);
+        ret = pFindStringOrdinal(tests[i].flag, tests[i].src, tests[i].src_size, tests[i].val, tests[i].val_size,
+                                 tests[i].ignore_case);
+        err = GetLastError();
+        ok(ret == tests[i].ret, "Item %d expected %d, got %d\n", i, tests[i].ret, ret);
+        ok(err == tests[i].err, "Item %d expected %#x, got %#x\n", i, tests[i].err, err);
+    }
+}
+
 static void test_SetThreadUILanguage(void)
 {
     LANGID res;
@@ -5746,6 +5815,7 @@ START_TEST(locale)
   test_GetThreadPreferredUILanguages();
   test_GetUserPreferredUILanguages();
   test_FindNLSStringEx();
+  test_FindStringOrdinal();
   test_SetThreadUILanguage();
   test_NormalizeString();
   /* this requires collation table patch to make it MS compatible */
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index 9e51ae44e0..f3b4fd131f 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -373,7 +373,7 @@
 # @ stub FindPackagesByPackageFamily
 @ stdcall FindResourceExW(long wstr wstr long) kernel32.FindResourceExW
 @ stdcall FindResourceW(long wstr wstr) kernel32.FindResourceW
-@ stub FindStringOrdinal
+@ stdcall FindStringOrdinal(long wstr long wstr long long) kernel32.FindStringOrdinal
 @ stdcall FindVolumeClose(ptr) kernel32.FindVolumeClose
 @ stdcall FlsAlloc(ptr) kernel32.FlsAlloc
 @ stdcall FlsFree(long) kernel32.FlsFree
diff --git a/include/libloaderapi.h b/include/libloaderapi.h
index 8f112a7d60..abb848f6e9 100644
--- a/include/libloaderapi.h
+++ b/include/libloaderapi.h
@@ -28,6 +28,7 @@ typedef void *DLL_DIRECTORY_COOKIE, **PDLL_DIRECTORY_COOKIE;
 WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(const WCHAR *);
 WINBASEAPI BOOL WINAPI RemoveDllDirectory(DLL_DIRECTORY_COOKIE);
 WINBASEAPI BOOL WINAPI SetDefaultDllDirectories(DWORD);
+WINBASEAPI INT WINAPI FindStringOrdinal(DWORD, const WCHAR *, INT, const WCHAR *, INT, BOOL);
 
 #ifdef __cplusplus
 }
-- 
2.19.1




More information about the wine-devel mailing list