From: André Hentschel Subject: [1/2] msvcrt: Add bsearch_s implementation by reusing code and tests from ntdll (try 2) Message-Id: <4F3806A1.6090101@dawncrow.de> Date: Sun, 12 Feb 2012 19:36:17 +0100 http://bugs.winehq.org/show_bug.cgi?id=29697 --- dlls/msvcr100/msvcr100.spec | 2 +- dlls/msvcr80/msvcr80.spec | 2 +- dlls/msvcr90/msvcr90.spec | 2 +- dlls/msvcrt/misc.c | 30 ++++++++++++++++ dlls/msvcrt/msvcrt.spec | 2 +- dlls/msvcrt/tests/misc.c | 78 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 112 insertions(+), 4 deletions(-) diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index 99d6c3d..fc40dd8 100644 --- a/dlls/msvcr100/msvcr100.spec +++ b/dlls/msvcr100/msvcr100.spec @@ -1433,7 +1433,7 @@ @ cdecl atoi(str) msvcrt.atoi @ cdecl atol(str) msvcrt.atol @ cdecl bsearch(ptr ptr long long ptr) msvcrt.bsearch -@ stub bsearch_s +@ cdecl bsearch_s(ptr ptr long long ptr ptr) msvcrt.bsearch_s @ cdecl btowc(long) msvcrt.btowc @ cdecl calloc(long long) msvcrt.calloc @ cdecl ceil(double) msvcrt.ceil diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec index ca284bf..b256280 100644 --- a/dlls/msvcr80/msvcr80.spec +++ b/dlls/msvcr80/msvcr80.spec @@ -1289,7 +1289,7 @@ @ cdecl atoi(str) msvcrt.atoi @ cdecl atol(str) msvcrt.atol @ cdecl bsearch(ptr ptr long long ptr) msvcrt.bsearch -@ stub bsearch_s +@ cdecl bsearch_s(ptr ptr long long ptr ptr) msvcrt.bsearch_s @ cdecl btowc(long) msvcrt.btowc @ cdecl calloc(long long) msvcrt.calloc @ cdecl ceil(double) msvcrt.ceil diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec index 2ede2cc..e2d1c5f 100644 --- a/dlls/msvcr90/msvcr90.spec +++ b/dlls/msvcr90/msvcr90.spec @@ -1284,7 +1284,7 @@ @ cdecl atoi(str) msvcrt.atoi @ cdecl atol(str) msvcrt.atol @ cdecl bsearch(ptr ptr long long ptr) msvcrt.bsearch -@ stub bsearch_s +@ cdecl bsearch_s(ptr ptr long long ptr ptr) msvcrt.bsearch_s @ cdecl btowc(long) msvcrt.btowc @ cdecl calloc(long long) msvcrt.calloc @ cdecl ceil(double) msvcrt.ceil diff --git a/dlls/msvcrt/misc.c b/dlls/msvcrt/misc.c index d40e38f..4880aa0 100644 --- a/dlls/msvcrt/misc.c +++ b/dlls/msvcrt/misc.c @@ -124,6 +124,36 @@ void* CDECL _lsearch(const void* match, void* start, } /********************************************************************* + * bsearch_s (msvcrt.@) + */ +void* CDECL MSVCRT_bsearch_s(const void *key, const void *base, + MSVCRT_size_t nmemb, MSVCRT_size_t size, + int (__cdecl *compare)(void *, const void *, const void *), void *ctx) +{ + ssize_t min = 0; + ssize_t max = nmemb - 1; + + if (!size || !compare) + { + *MSVCRT__errno() = MSVCRT_EINVAL; + return NULL; + } + + while (min <= max) + { + ssize_t cursor = (min + max) / 2; + int ret = compare(ctx, key,(const char *)base+(cursor*size)); + if (!ret) + return (char*)base+(cursor*size); + if (ret < 0) + max = cursor - 1; + else + min = cursor + 1; + } + return NULL; +} + +/********************************************************************* * _chkesp (MSVCRT.@) * * Trap to a debugger if the value of the stack pointer has changed. diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index 1260dfa..b103f57 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -1226,7 +1226,7 @@ @ cdecl atoi(str) ntdll.atoi @ cdecl atol(str) ntdll.atol @ cdecl bsearch(ptr ptr long long ptr) ntdll.bsearch -# stub bsearch_s(ptr ptr long long ptr ptr) +@ cdecl bsearch_s(ptr ptr long long ptr ptr) MSVCRT_bsearch_s @ cdecl btowc(long) MSVCRT_btowc @ cdecl calloc(long long) MSVCRT_calloc @ cdecl ceil(double) MSVCRT_ceil diff --git a/dlls/msvcrt/tests/misc.c b/dlls/msvcrt/tests/misc.c index 7135248..42240cc 100644 --- a/dlls/msvcrt/tests/misc.c +++ b/dlls/msvcrt/tests/misc.c @@ -26,6 +26,8 @@ static int (__cdecl *prand_s)(unsigned int *); static int (__cdecl *pmemcpy_s)(void *, MSVCRT_size_t, void*, MSVCRT_size_t); static int (__cdecl *pI10_OUTPUT)(long double, int, int, void*); static int (__cdecl *pstrerror_s)(char *, MSVCRT_size_t, int); +static void* (__cdecl *pbsearch_s)(const void *, const void *, MSVCRT_size_t, MSVCRT_size_t, + int (__cdecl *compare)(void *, const void *, const void *), void *); static int (__cdecl *p_get_doserrno)(int *); static int (__cdecl *p_get_errno)(int *); static int (__cdecl *p_set_doserrno)(int); @@ -39,6 +41,7 @@ static void init(void) pmemcpy_s = (void*)GetProcAddress(hmod, "memcpy_s"); pI10_OUTPUT = (void*)GetProcAddress(hmod, "$I10_OUTPUT"); pstrerror_s = (void *)GetProcAddress(hmod, "strerror_s"); + pbsearch_s = (void *)GetProcAddress(hmod, "bsearch_s"); p_get_doserrno = (void *)GetProcAddress(hmod, "_get_doserrno"); p_get_errno = (void *)GetProcAddress(hmod, "_get_errno"); p_set_doserrno = (void *)GetProcAddress(hmod, "_set_doserrno"); @@ -260,6 +263,80 @@ static void test_strerror_s(void) ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret); } +static int __cdecl intcomparefunc(void* ctx, const void *a, const void *b) +{ + const int *p = a, *q = b; + + ok(a != b, "must never get the same pointer\n"); + if (ctx) + ok(ctx == pbsearch_s, "Got the wrong context pointer: %p\n", ctx); + + return *p - *q; +} + +static void test_bsearch_s(void) +{ + int arr[7] = { 1, 3, 4, 8, 16, 23, 42 }; + int *x, l, i, j = 1; + + if (!pbsearch_s) + { + win_skip("bsearch_s is not available\n"); + return; + } + + errno = 0; + x = pbsearch_s(NULL, NULL, 0, 0, NULL, NULL); + ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x); + ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); + +if(0) +{ + /* crashes on native */ + errno = 0; + x = pbsearch_s(NULL, arr, j, sizeof(arr[0]), intcomparefunc, pbsearch_s); + ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x); + ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); + + errno = 0; + x = pbsearch_s(&l, NULL, j, sizeof(arr[0]), intcomparefunc, pbsearch_s); + ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x); + ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); +} + + errno = 0; + x = pbsearch_s(&l, arr, 0, sizeof(arr[0]), intcomparefunc, pbsearch_s); + ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x); + ok(errno == 0, "Expected errno to be EBADF, got %d\n", errno); + + errno = 0; + x = pbsearch_s(&l, arr, j, 0, intcomparefunc, pbsearch_s); + ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x); + ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); + + errno = 0; + x = pbsearch_s(&l, arr, j, sizeof(arr[0]), NULL, pbsearch_s); + ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x); + ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); + + errno = 0; + x = pbsearch_s(&l, arr, j, sizeof(arr[0]), intcomparefunc, NULL); + ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x); + ok(errno == 0, "Expected errno to be EBADF, got %d\n", errno); + + /* just try all array sizes */ + for (j=1;j