ws2_32: Implement GetAddrInfoW and FreeAddrInfoW.

Hans Leidekker hans at codeweavers.com
Fri Apr 24 09:01:56 CDT 2009


IE8 calls these functions.

 -Hans

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 9324833..b056bd3 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -3583,13 +3583,149 @@ outofmem:
 #endif
 }
 
+struct WS_addrinfoW *addrinfo_AtoW(const struct WS_addrinfo *ai)
+{
+    struct WS_addrinfoW *ret;
+
+    if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_addrinfoW)))) return NULL;
+    ret->ai_flags     = ai->ai_flags;
+    ret->ai_family    = ai->ai_family;
+    ret->ai_socktype  = ai->ai_socktype;
+    ret->ai_protocol  = ai->ai_protocol;
+    ret->ai_addrlen   = ai->ai_addrlen;
+    ret->ai_canonname = NULL;
+    ret->ai_addr      = NULL;
+    ret->ai_next      = NULL;
+    if (ai->ai_canonname)
+    {
+        int len = MultiByteToWideChar(CP_ACP, 0, ai->ai_canonname, -1, NULL, 0);
+        if (!(ret->ai_canonname = HeapAlloc(GetProcessHeap(), 0, len)))
+        {
+            HeapFree(GetProcessHeap(), 0, ret);
+            return NULL;
+        }
+        MultiByteToWideChar(CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len);
+    }
+    if (ai->ai_addr)
+    {
+        if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_sockaddr))))
+        {
+            HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
+            HeapFree(GetProcessHeap(), 0, ret);
+            return NULL;
+        }
+        memcpy(ret->ai_addr, ai->ai_addr, sizeof(struct WS_sockaddr));
+    }
+    return ret;
+}
+
+struct WS_addrinfoW *addrinfo_list_AtoW(const struct WS_addrinfo *info)
+{
+    struct WS_addrinfoW *ret, *infoW;
+
+    if (!(ret = infoW = addrinfo_AtoW(info))) return NULL;
+    while (info->ai_next)
+    {
+        if (!(infoW->ai_next = addrinfo_AtoW(info->ai_next)))
+        {
+            FreeAddrInfoW(ret);
+            return NULL;
+        }
+        infoW = infoW->ai_next;
+        info = info->ai_next;
+    }
+    return ret;
+}
+
+struct WS_addrinfo *addrinfo_WtoA(const struct WS_addrinfoW *ai)
+{
+    struct WS_addrinfo *ret;
+
+    if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_addrinfo)))) return NULL;
+    ret->ai_flags     = ai->ai_flags;
+    ret->ai_family    = ai->ai_family;
+    ret->ai_socktype  = ai->ai_socktype;
+    ret->ai_protocol  = ai->ai_protocol;
+    ret->ai_addrlen   = ai->ai_addrlen;
+    ret->ai_canonname = NULL;
+    ret->ai_addr      = NULL;
+    ret->ai_next      = NULL;
+    if (ai->ai_canonname)
+    {
+        int len = WideCharToMultiByte(CP_ACP, 0, ai->ai_canonname, -1, NULL, 0, NULL, NULL);
+        if (!(ret->ai_canonname = HeapAlloc(GetProcessHeap(), 0, len)))
+        {
+            HeapFree(GetProcessHeap(), 0, ret);
+            return NULL;
+        }
+        WideCharToMultiByte(CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len, NULL, NULL);
+    }
+    if (ai->ai_addr)
+    {
+        if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_sockaddr))))
+        {
+            HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
+            HeapFree(GetProcessHeap(), 0, ret);
+            return NULL;
+        }
+        memcpy(ret->ai_addr, ai->ai_addr, sizeof(struct WS_sockaddr));
+    }
+    return ret;
+}
+
 /***********************************************************************
  *		GetAddrInfoW		(WS2_32.@)
  */
 int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hints, PADDRINFOW *res)
 {
-    FIXME("empty stub!\n");
-    return EAI_FAIL;
+    int ret, len;
+    char *nodenameA, *servnameA = NULL;
+    struct WS_addrinfo *resA, *hintsA = NULL;
+
+    len = WideCharToMultiByte(CP_ACP, 0, nodename, -1, NULL, 0, NULL, NULL);
+    if (!(nodenameA = HeapAlloc(GetProcessHeap(), 0, len))) return EAI_MEMORY;
+    WideCharToMultiByte(CP_ACP, 0, nodename, -1, nodenameA, len, NULL, NULL);
+
+    if (servname)
+    {
+        len = WideCharToMultiByte(CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL);
+        if (!(servnameA = HeapAlloc(GetProcessHeap(), 0, len)))
+        {
+            HeapFree(GetProcessHeap(), 0, nodenameA);
+            return EAI_MEMORY;
+        }
+        WideCharToMultiByte(CP_ACP, 0, servname, -1, servnameA, len, NULL, NULL);
+    }
+
+    if (hints) hintsA = addrinfo_WtoA(hints);
+    ret = WS_getaddrinfo(nodenameA, servnameA, hintsA, &resA);
+    WS_freeaddrinfo(hintsA);
+
+    if (!ret)
+    {
+        *res = addrinfo_list_AtoW(resA);
+        WS_freeaddrinfo(resA);
+    }
+
+    HeapFree(GetProcessHeap(), 0, nodenameA);
+    HeapFree(GetProcessHeap(), 0, servnameA);
+    return ret;
+}
+
+/***********************************************************************
+ *      FreeAddrInfoW        (WS2_32.@)
+ */
+void WINAPI FreeAddrInfoW(PADDRINFOW ai)
+{
+    while (ai)
+    {
+        ADDRINFOW *next;
+        HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
+        HeapFree(GetProcessHeap(), 0, ai->ai_addr);
+        next = ai->ai_next;
+        HeapFree(GetProcessHeap(), 0, ai);
+        ai = next;
+    }
 }
 
 int WINAPI WS_getnameinfo(const SOCKADDR *sa, WS_socklen_t salen, PCHAR host,
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 23aa59c..dbd43d8 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -2310,6 +2310,32 @@ static void test_WSASendTo(void)
             "a successful call to WSASendTo()\n");
 }
 
+static void test_GetAddrInfoW(void)
+{
+    static const WCHAR port[] = {'8','0',0};
+    static const WCHAR localhost[] = {'l','o','c','a','l','h','o','s','t',0};
+
+    int ret;
+    ADDRINFOW *result, hint;
+
+    memset(&hint, 0, sizeof(ADDRINFOW));
+
+    ret = GetAddrInfoW(NULL, NULL, NULL, &result);
+    ok(ret == WSAHOST_NOT_FOUND, "got %d expected WSAHOST_NOT_FOUND\n", ret);
+
+    ret = GetAddrInfoW(localhost, NULL, NULL, &result);
+    ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    FreeAddrInfoW(result);
+
+    ret = GetAddrInfoW(localhost, port, NULL, &result);
+    ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    FreeAddrInfoW(result);
+
+    ret = GetAddrInfoW(localhost, port, &hint, &result);
+    ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    FreeAddrInfoW(result);
+}
+
 /**************** Main program  ***************/
 
 START_TEST( sock )
@@ -2353,6 +2379,7 @@ START_TEST( sock )
     test_WSASendTo();
 
     test_ipv6only();
+    test_GetAddrInfoW();
 
     Exit();
 }
diff --git a/dlls/ws2_32/ws2_32.spec b/dlls/ws2_32/ws2_32.spec
index 74e71be..a77c215 100644
--- a/dlls/ws2_32/ws2_32.spec
+++ b/dlls/ws2_32/ws2_32.spec
@@ -50,6 +50,7 @@
 
 500 stub     WEP
 
+@ stdcall FreeAddrInfoW(ptr)
 @ stdcall GetAddrInfoW(wstr wstr ptr ptr)
 @ stdcall WSApSetPostRoutine(ptr)
 @ stdcall WPUCompleteOverlappedRequest(long ptr long long ptr)



More information about the wine-patches mailing list