Hans Leidekker : ws2_32: Call the completion routine in GetAddrInfoExW.

Alexandre Julliard julliard at winehq.org
Fri Sep 27 15:56:30 CDT 2019


Module: wine
Branch: master
Commit: c3bcf83d14e79bc8202d7d22fe773842a42240fc
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=c3bcf83d14e79bc8202d7d22fe773842a42240fc

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Fri Sep 27 12:47:28 2019 +0200

ws2_32: Call the completion routine in GetAddrInfoExW.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ws2_32/socket.c     | 20 ++++++++++----
 dlls/ws2_32/tests/sock.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+), 6 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index d82172aa5b..aa0a164ff9 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -6997,6 +6997,7 @@ static struct WS_addrinfo *addrinfo_WtoA(const struct WS_addrinfoW *ai)
 struct getaddrinfo_args
 {
     OVERLAPPED *overlapped;
+    LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine;
     ADDRINFOEXW **result;
     char *nodename;
     char *servname;
@@ -7007,6 +7008,7 @@ static void WINAPI getaddrinfo_callback(TP_CALLBACK_INSTANCE *instance, void *co
     struct getaddrinfo_args *args = context;
     OVERLAPPED *overlapped = args->overlapped;
     HANDLE event = overlapped->hEvent;
+    LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine = args->completion_routine;
     struct WS_addrinfo *res;
     int ret;
 
@@ -7023,10 +7025,12 @@ static void WINAPI getaddrinfo_callback(TP_CALLBACK_INSTANCE *instance, void *co
     HeapFree(GetProcessHeap(), 0, args);
 
     overlapped->Internal = ret;
+    if (completion_routine) completion_routine(ret, 0, overlapped);
     if (event) SetEvent(event);
 }
 
-static int WS_getaddrinfoW(const WCHAR *nodename, const WCHAR *servname, const struct WS_addrinfo *hints, ADDRINFOEXW **res, OVERLAPPED *overlapped)
+static int WS_getaddrinfoW(const WCHAR *nodename, const WCHAR *servname, const struct WS_addrinfo *hints, ADDRINFOEXW **res,
+                           OVERLAPPED *overlapped, LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine)
 {
     int ret = EAI_MEMORY, len, i;
     char *nodenameA = NULL, *servnameA = NULL;
@@ -7082,8 +7086,15 @@ static int WS_getaddrinfoW(const WCHAR *nodename, const WCHAR *servname, const s
     {
         struct getaddrinfo_args *args;
 
+        if (overlapped->hEvent && completion_routine)
+        {
+            ret = WSAEINVAL;
+            goto end;
+        }
+
         if (!(args = HeapAlloc(GetProcessHeap(), 0, sizeof(*args)))) goto end;
         args->overlapped = overlapped;
+        args->completion_routine = completion_routine;
         args->result = res;
         args->nodename = nodenameA;
         args->servname = servnameA;
@@ -7096,7 +7107,6 @@ static int WS_getaddrinfoW(const WCHAR *nodename, const WCHAR *servname, const s
             goto end;
         }
 
-
         if (local_nodenameW != nodename)
             HeapFree(GetProcessHeap(), 0, local_nodenameW);
         WSASetLastError(ERROR_IO_PENDING);
@@ -7138,12 +7148,10 @@ int WINAPI GetAddrInfoExW(const WCHAR *name, const WCHAR *servname, DWORD namesp
         FIXME("Unsupported hints\n");
     if (timeout)
         FIXME("Unsupported timeout\n");
-    if (completion_routine)
-        FIXME("Unsupported completion_routine\n");
     if (handle)
         FIXME("Unsupported cancel handle\n");
 
-    ret = WS_getaddrinfoW(name, servname, NULL, result, overlapped);
+    ret = WS_getaddrinfoW(name, servname, NULL, result, overlapped, completion_routine);
     if (ret) return ret;
     if (handle) *handle = (HANDLE)0xdeadbeef;
     return 0;
@@ -7181,7 +7189,7 @@ int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hin
 
     *res = NULL;
     if (hints) hintsA = addrinfo_WtoA(hints);
-    ret = WS_getaddrinfoW(nodename, servname, hintsA, &resex, NULL);
+    ret = WS_getaddrinfoW(nodename, servname, hintsA, &resex, NULL, NULL);
     WS_freeaddrinfo(hintsA);
     if (ret) return ret;
 
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index e97cd381d0..e4b57cfdda 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -7617,11 +7617,36 @@ static void test_GetAddrInfoW(void)
     ok(result2 == NULL, "got %p\n", result2);
 }
 
+static struct completion_routine_test
+{
+    WSAOVERLAPPED  *overlapped;
+    DWORD           error;
+    ADDRINFOEXW   **result;
+    HANDLE          event;
+    DWORD           called;
+} completion_routine_test;
+
+static void CALLBACK completion_routine(DWORD error, DWORD byte_count, WSAOVERLAPPED *overlapped)
+{
+    struct completion_routine_test *test = &completion_routine_test;
+
+    ok(error == test->error, "got %u\n", error);
+    ok(!byte_count, "got %u\n", byte_count);
+    ok(overlapped == test->overlapped, "got %p\n", overlapped);
+    ok(overlapped->Internal == test->error, "got %lu\n", overlapped->Internal);
+    ok(overlapped->Pointer == test->result, "got %p\n", overlapped->Pointer);
+    ok(overlapped->hEvent == NULL, "got %p\n", overlapped->hEvent);
+
+    test->called++;
+    SetEvent(test->event);
+}
+
 static void test_GetAddrInfoExW(void)
 {
     static const WCHAR empty[] = {0};
     static const WCHAR localhost[] = {'l','o','c','a','l','h','o','s','t',0};
     static const WCHAR winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
+    static const WCHAR nxdomain[] = {'n','x','d','o','m','a','i','n','.','w','i','n','e','h','q','.','o','r','g',0};
     ADDRINFOEXW *result;
     OVERLAPPED overlapped;
     HANDLE event;
@@ -7706,6 +7731,53 @@ static void test_GetAddrInfoExW(void)
     todo_wine_if(ret != WAIT_TIMEOUT) /* Remove when abowe todo_wines are fixed */
     ok(ret == WAIT_TIMEOUT, "wait failed\n");
 
+    /* event + completion routine */
+    result = (void*)0xdeadbeef;
+    memset(&overlapped, 0xcc, sizeof(overlapped));
+    overlapped.hEvent = event;
+    ResetEvent(event);
+    ret = pGetAddrInfoExW(localhost, NULL, NS_DNS, NULL, NULL, &result, NULL, &overlapped, completion_routine, NULL);
+    ok(ret == WSAEINVAL, "GetAddrInfoExW failed with %d\n", WSAGetLastError());
+
+    /* completion routine, existing domain */
+    result = (void *)0xdeadbeef;
+    overlapped.hEvent = NULL;
+    completion_routine_test.overlapped = &overlapped;
+    completion_routine_test.error = ERROR_SUCCESS;
+    completion_routine_test.result = &result;
+    completion_routine_test.event = event;
+    completion_routine_test.called = 0;
+    ResetEvent(event);
+    ret = pGetAddrInfoExW(winehq, NULL, NS_DNS, NULL, NULL, &result, NULL, &overlapped, completion_routine, NULL);
+    ok(ret == ERROR_IO_PENDING, "GetAddrInfoExW failed with %d\n", WSAGetLastError());
+    ok(!result, "result != NULL\n");
+    ok(WaitForSingleObject(event, 1000) == WAIT_OBJECT_0, "wait failed\n");
+    ret = pGetAddrInfoExOverlappedResult(&overlapped);
+    ok(!ret, "overlapped result is %d\n", ret);
+    ok(overlapped.hEvent == NULL, "hEvent changed %p\n", overlapped.hEvent);
+    ok(overlapped.Internal == ERROR_SUCCESS, "overlapped.Internal = %lx\n", overlapped.Internal);
+    ok(overlapped.Pointer == &result, "overlapped.Pointer != &result\n");
+    ok(completion_routine_test.called == 1, "got %u\n", completion_routine_test.called);
+    pFreeAddrInfoExW(result);
+
+    /* completion routine, non-existing domain */
+    result = (void *)0xdeadbeef;
+    completion_routine_test.overlapped = &overlapped;
+    completion_routine_test.error = WSAHOST_NOT_FOUND;
+    completion_routine_test.called = 0;
+    ResetEvent(event);
+    ret = pGetAddrInfoExW(nxdomain, NULL, NS_DNS, NULL, NULL, &result, NULL, &overlapped, completion_routine, NULL);
+    ok(ret == ERROR_IO_PENDING, "GetAddrInfoExW failed with %d\n", WSAGetLastError());
+    ok(!result, "result != NULL\n");
+    ok(WaitForSingleObject(event, 1000) == WAIT_OBJECT_0, "wait failed\n");
+    ret = pGetAddrInfoExOverlappedResult(&overlapped);
+    ok(ret == WSAHOST_NOT_FOUND, "overlapped result is %d\n", ret);
+    ok(overlapped.hEvent == NULL, "hEvent changed %p\n", overlapped.hEvent);
+    ok(overlapped.Internal == WSAHOST_NOT_FOUND, "overlapped.Internal = %lx\n", overlapped.Internal);
+    ok(overlapped.Pointer == &result, "overlapped.Pointer != &result\n");
+    ok(completion_routine_test.called == 1, "got %u\n", completion_routine_test.called);
+    ok(result == NULL, "got %p\n", result);
+
     WSACloseEvent(event);
 }
 




More information about the wine-cvs mailing list