[PATCH] ntdll: split out sort and handle win64 cdecl

Marcus Meissner meissner at suse.de
Thu Apr 15 16:43:36 CDT 2010


Hi,

qsort() calls a cdecl routine, but Win64 cdecl is sadly
not UNIX cdecl... So we need a wrapper.

Hope this kind of ifdef magic is acceptable, I don't want
it for win32.

Ciao, Marcus
---
 dlls/ntdll/Makefile.in    |    1 +
 dlls/ntdll/sort.c         |  167 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/string.c       |   31 --------
 dlls/ntdll/tests/string.c |   23 ++++++
 4 files changed, 191 insertions(+), 31 deletions(-)
 create mode 100644 dlls/ntdll/sort.c

diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index c51776b..f9ef4f7 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -44,6 +44,7 @@ C_SRCS = \
 	signal_powerpc.c \
 	signal_sparc.c \
 	signal_x86_64.c \
+	sort.c \
 	string.c \
 	sync.c \
 	tape.c \
diff --git a/dlls/ntdll/sort.c b/dlls/ntdll/sort.c
new file mode 100644
index 0000000..a392ece
--- /dev/null
+++ b/dlls/ntdll/sort.c
@@ -0,0 +1,167 @@
+/*
+ * NTDLL sorting and hashing functions
+ *
+ * Copyright 2000 Alexandre Julliard
+ * Copyright 2000 Jon Griffiths
+ * Copyright 2003 Thomas Mertes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+#include "wine/list.h"
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <search.h>
+
+#include "windef.h"
+#include "windef.h"
+#include "winternl.h"
+#include "ntdll_misc.h"
+
+#include "wine/debug.h"
+
+
+WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
+
+#ifdef _WIN64
+/* Helper function for glibc qsort which uses UNIX cdecl
+ * to call Windows cdecl which is different on Win64. */
+struct _compare_entry {
+	struct list entry;
+	void *base;
+	size_t size;
+	int(__cdecl *compar)(const void *, const void *);
+};
+static struct list compare_entries = LIST_INIT( compare_entries );
+
+static int NTDLL_compar (const void*a, const void*b)
+{
+    struct _compare_entry *entry;
+
+    LIST_FOR_EACH_ENTRY( entry, &compare_entries, struct _compare_entry, entry )
+    {
+	if (((intptr_t)a >= ((intptr_t)entry->base)) &&
+	    ((intptr_t)a <  ((intptr_t)entry->base + entry->size))
+	)
+	    return entry->compar(a,b);
+    }
+    ERR("(%p,%p), did not find entry in compare queue?\n", a, b);
+    return 0;
+}
+
+
+/*********************************************************************
+ *                  bsearch   (NTDLL.@)
+ */
+void * __cdecl NTDLL_bsearch( const void *key, const void *base, size_t nmemb,
+                              size_t size, int (__cdecl *compar)(const void *, const void *) )
+{
+    struct _compare_entry *entry;
+    void *result;
+
+    entry = RtlAllocateHeap(GetProcessHeap(), 0, sizeof (*entry));
+    entry->base = (void*)base;
+    entry->compar = compar;
+    entry->size = size*nmemb;
+    list_add_head( &compare_entries, &entry->entry );
+
+    result = bsearch( key, base, nmemb, size, NTDLL_compar );
+
+    list_remove( &entry->entry );
+    RtlFreeHeap(GetProcessHeap(), 0, entry);
+    return result;
+}
+
+/*********************************************************************
+ *                  qsort   (NTDLL.@)
+ */
+void __cdecl NTDLL_qsort( void *base, size_t nmemb, size_t size,
+                          int(__cdecl *compar)(const void *, const void *) )
+{
+    struct _compare_entry *entry;
+
+    entry = RtlAllocateHeap(GetProcessHeap(), 0, sizeof (*entry));
+    entry->base = base;
+    entry->compar = compar;
+    entry->size = size*nmemb;
+    list_add_head( &compare_entries, &entry->entry );
+
+    qsort( base, nmemb, size, NTDLL_compar );
+
+    list_remove( &entry->entry );
+    RtlFreeHeap(GetProcessHeap(), 0, entry);
+}
+
+
+/*********************************************************************
+ *                  _lfind   (NTDLL.@)
+ */
+void * __cdecl _lfind( const void *key, const void *base, unsigned int *nmemb,
+                       size_t size, int(__cdecl *compar)(const void *, const void *) )
+{
+    size_t n = *nmemb;
+    void *result;
+
+    struct _compare_entry *entry;
+
+    entry = RtlAllocateHeap(GetProcessHeap(), 0, sizeof (*entry));
+    entry->base = (void*)base;
+    entry->compar = compar;
+    entry->size = size*n;
+    list_add_head( &compare_entries, &entry->entry );
+
+    result = lfind( key, base, &n, size, NTDLL_compar );
+
+    list_remove( &entry->entry );
+    RtlFreeHeap(GetProcessHeap(), 0, entry);
+    return result;
+}
+#else
+/*********************************************************************
+ *                  bsearch   (NTDLL.@)
+ */
+void * __cdecl NTDLL_bsearch( const void *key, const void *base, size_t nmemb,
+                              size_t size, int (__cdecl *compar)(const void *, const void *) )
+{
+    return bsearch( key, base, nmemb, size, compar );
+}
+
+/*********************************************************************
+ *                  qsort   (NTDLL.@)
+ */
+void __cdecl NTDLL_qsort( void *base, size_t nmemb, size_t size,
+                          int(__cdecl *compar)(const void *, const void *) )
+{
+    qsort( base, nmemb, size, compar );
+}
+
+
+/*********************************************************************
+ *                  _lfind   (NTDLL.@)
+ */
+void * __cdecl _lfind( const void *key, const void *base, unsigned int *nmemb,
+                       size_t size, int(__cdecl *compar)(const void *, const void *) )
+{
+    size_t n = *nmemb;
+
+    return lfind( key, base, &n, size, compar );
+}
+#endif
diff --git a/dlls/ntdll/string.c b/dlls/ntdll/string.c
index c9ca3ce..716dbdf 100644
--- a/dlls/ntdll/string.c
+++ b/dlls/ntdll/string.c
@@ -83,37 +83,6 @@ void * __cdecl NTDLL_memset( void *dst, int c, size_t n )
 
 
 /*********************************************************************
- *                  bsearch   (NTDLL.@)
- */
-void * __cdecl NTDLL_bsearch( const void *key, const void *base, size_t nmemb,
-                              size_t size, int (*compar)(const void *, const void *) )
-{
-    return bsearch( key, base, nmemb, size, compar );
-}
-
-
-/*********************************************************************
- *                  qsort   (NTDLL.@)
- */
-void __cdecl NTDLL_qsort( void *base, size_t nmemb, size_t size,
-                          int(*compar)(const void *, const void *) )
-{
-    qsort( base, nmemb, size, compar );
-}
-
-
-/*********************************************************************
- *                  _lfind   (NTDLL.@)
- */
-void * __cdecl _lfind( const void *key, const void *base, unsigned int *nmemb,
-                       size_t size, int(*compar)(const void *, const void *) )
-{
-    size_t n = *nmemb;
-    return lfind( key, base, &n, size, compar );
-}
-
-
-/*********************************************************************
  *                  strcat   (NTDLL.@)
  */
 char * __cdecl NTDLL_strcat( char *dst, const char *src )
diff --git a/dlls/ntdll/tests/string.c b/dlls/ntdll/tests/string.c
index cd3ae37..03c62b8 100644
--- a/dlls/ntdll/tests/string.c
+++ b/dlls/ntdll/tests/string.c
@@ -57,6 +57,9 @@ static ULONG    (WINAPIV *pwcstoul)(LPCWSTR, LPWSTR *, INT);
 static LPWSTR   (WINAPIV *p_wcschr)(LPCWSTR, WCHAR);
 static LPWSTR   (WINAPIV *p_wcsrchr)(LPCWSTR, WCHAR);
 
+static void     (__cdecl *p_qsort)(void *,size_t,size_t, int(__cdecl *compar)(const void *, const void *) );
+
+
 static void InitFunctionPtrs(void)
 {
     hntdll = LoadLibraryA("ntdll.dll");
@@ -90,6 +93,7 @@ static void InitFunctionPtrs(void)
 
 	p_wcschr= (void *)GetProcAddress(hntdll, "wcschr");
 	p_wcsrchr= (void *)GetProcAddress(hntdll, "wcsrchr");
+	p_qsort= (void *)GetProcAddress(hntdll, "qsort");
     } /* if */
 }
 
@@ -1137,6 +1141,23 @@ static void test_wcsrchr(void)
        "wcsrchr should have returned NULL\n");
 }
 
+static __cdecl int intcomparefunc(const void *a, const void*b)
+{
+	return (*(int*)a) - (*(int*)b);
+}
+
+static void test_qsort(void)
+{
+    static int arr[5] = { 23, 42, 8, 4, 16 };
+
+    p_qsort ((void*)arr, 5, sizeof(int), intcomparefunc);
+    ok(arr[0] == 4,  "badly sorted, arr[0] is %d", arr[0]);
+    ok(arr[1] == 8,  "badly sorted, arr[1] is %d", arr[1]);
+    ok(arr[2] == 16, "badly sorted, arr[2] is %d", arr[2]);
+    ok(arr[3] == 23, "badly sorted, arr[3] is %d", arr[3]);
+    ok(arr[4] == 42, "badly sorted, arr[4] is %d", arr[4]);
+}
+
 START_TEST(string)
 {
     InitFunctionPtrs();
@@ -1165,4 +1186,6 @@ START_TEST(string)
         test_atoi();
     if (patol)
         test_atol();
+    if (p_qsort)
+        test_qsort();
 }
-- 
1.6.4.2



More information about the wine-patches mailing list