[PATCH 1/5] ws2_32: Move getaddrinfo() and related functions to a separate file.

Zebediah Figura z.figura12 at gmail.com
Fri Apr 30 19:09:58 CDT 2021


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/ws2_32/Makefile.in      |   1 +
 dlls/ws2_32/protocol.c       | 812 ++++++++++++++++++++++++++++++++
 dlls/ws2_32/socket.c         | 890 +----------------------------------
 dlls/ws2_32/ws2_32_private.h | 167 +++++++
 4 files changed, 988 insertions(+), 882 deletions(-)
 create mode 100644 dlls/ws2_32/protocol.c
 create mode 100644 dlls/ws2_32/ws2_32_private.h

diff --git a/dlls/ws2_32/Makefile.in b/dlls/ws2_32/Makefile.in
index 9d7dfafeb3c..6312b20739d 100644
--- a/dlls/ws2_32/Makefile.in
+++ b/dlls/ws2_32/Makefile.in
@@ -6,6 +6,7 @@ EXTRALIBS = $(POLL_LIBS)
 
 C_SRCS = \
 	async.c \
+	protocol.c \
 	socket.c
 
 RC_SRCS = version.rc
diff --git a/dlls/ws2_32/protocol.c b/dlls/ws2_32/protocol.c
new file mode 100644
index 00000000000..7bf994b501f
--- /dev/null
+++ b/dlls/ws2_32/protocol.c
@@ -0,0 +1,812 @@
+/*
+ * Protocol-level socket functions
+ *
+ * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
+ * Copyright (C) 2001 Stefan Leichter
+ * Copyright (C) 2004 Hans Leidekker
+ * Copyright (C) 2005 Marcus Meissner
+ * Copyright (C) 2006-2008 Kai Blin
+ *
+ * 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 "ws2_32_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winsock);
+WINE_DECLARE_DEBUG_CHANNEL(winediag);
+
+#define MAP_OPTION(opt) { WS_##opt, opt }
+
+static const int ws_aiflag_map[][2] =
+{
+    MAP_OPTION( AI_PASSIVE ),
+    MAP_OPTION( AI_CANONNAME ),
+    MAP_OPTION( AI_NUMERICHOST ),
+#ifdef AI_NUMERICSERV
+    MAP_OPTION( AI_NUMERICSERV ),
+#endif
+#ifdef AI_V4MAPPED
+    MAP_OPTION( AI_V4MAPPED ),
+#endif
+    MAP_OPTION( AI_ALL ),
+    MAP_OPTION( AI_ADDRCONFIG ),
+};
+
+static const int ws_eai_map[][2] =
+{
+    MAP_OPTION( EAI_AGAIN ),
+    MAP_OPTION( EAI_BADFLAGS ),
+    MAP_OPTION( EAI_FAIL ),
+    MAP_OPTION( EAI_FAMILY ),
+    MAP_OPTION( EAI_MEMORY ),
+/* Note: EAI_NODATA is deprecated, but still used by Windows and Linux. We map
+ * the newer EAI_NONAME to EAI_NODATA for now until Windows changes too. */
+#ifdef EAI_NODATA
+    MAP_OPTION( EAI_NODATA ),
+#endif
+#ifdef EAI_NONAME
+    { WS_EAI_NODATA, EAI_NONAME },
+#endif
+    MAP_OPTION( EAI_SERVICE ),
+    MAP_OPTION( EAI_SOCKTYPE ),
+    { 0, 0 }
+};
+
+static const int ws_proto_map[][2] =
+{
+    MAP_OPTION( IPPROTO_IP ),
+    MAP_OPTION( IPPROTO_TCP ),
+    MAP_OPTION( IPPROTO_UDP ),
+    MAP_OPTION( IPPROTO_IPV6 ),
+    MAP_OPTION( IPPROTO_ICMP ),
+    MAP_OPTION( IPPROTO_IGMP ),
+    MAP_OPTION( IPPROTO_RAW ),
+    {WS_IPPROTO_IPV4, IPPROTO_IPIP},
+    {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
+};
+
+#define IS_IPX_PROTO(X) ((X) >= WS_NSPROTO_IPX && (X) <= WS_NSPROTO_IPX + 255)
+
+static int convert_proto_w2u( int protocol )
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(ws_proto_map); i++)
+    {
+        if (ws_proto_map[i][0] == protocol)
+            return ws_proto_map[i][1];
+    }
+
+    if (IS_IPX_PROTO(protocol))
+      return protocol;
+
+    FIXME( "unhandled Windows socket protocol %d\n", protocol );
+    return -1;
+}
+
+static int convert_proto_u2w( int protocol )
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(ws_proto_map); i++)
+    {
+        if (ws_proto_map[i][1] == protocol)
+            return ws_proto_map[i][0];
+    }
+
+    /* if value is inside IPX range just return it - the kernel simply
+     * echoes the value used in the socket() function */
+    if (IS_IPX_PROTO(protocol))
+        return protocol;
+
+    FIXME("unhandled UNIX socket protocol %d\n", protocol);
+    return -1;
+}
+
+static int convert_aiflag_w2u( int winflags )
+{
+    unsigned int i;
+    int unixflags = 0;
+
+    for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
+    {
+        if (ws_aiflag_map[i][0] & winflags)
+        {
+            unixflags |= ws_aiflag_map[i][1];
+            winflags &= ~ws_aiflag_map[i][0];
+        }
+    }
+    if (winflags)
+        FIXME( "Unhandled windows AI_xxx flags 0x%x\n", winflags );
+    return unixflags;
+}
+
+static int convert_aiflag_u2w( int unixflags )
+{
+    unsigned int i;
+    int winflags = 0;
+
+    for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
+    {
+        if (ws_aiflag_map[i][1] & unixflags)
+        {
+            winflags |= ws_aiflag_map[i][0];
+            unixflags &= ~ws_aiflag_map[i][1];
+        }
+    }
+    if (unixflags)
+        WARN( "Unhandled UNIX AI_xxx flags 0x%x\n", unixflags );
+    return winflags;
+}
+
+int convert_eai_u2w( int unixret )
+{
+    int i;
+
+    if (!unixret) return 0;
+
+    for (i = 0; ws_eai_map[i][0]; i++)
+    {
+        if (ws_eai_map[i][1] == unixret)
+            return ws_eai_map[i][0];
+    }
+
+    if (unixret == EAI_SYSTEM)
+        /* There are broken versions of glibc which return EAI_SYSTEM
+         * and set errno to 0 instead of returning EAI_NONAME. */
+        return errno ? sock_get_error( errno ) : WS_EAI_NONAME;
+
+    FIXME("Unhandled unix EAI_xxx ret %d\n", unixret);
+    return unixret;
+}
+
+static char *get_fqdn(void)
+{
+    char *ret;
+    DWORD size = 0;
+
+    GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, NULL, &size );
+    if (GetLastError() != ERROR_MORE_DATA) return NULL;
+    if (!(ret = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
+    if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, ret, &size ))
+    {
+        HeapFree( GetProcessHeap(), 0, ret );
+        return NULL;
+    }
+    return ret;
+}
+
+static BOOL addrinfo_in_list( const struct WS_addrinfo *list, const struct WS_addrinfo *ai )
+{
+    const struct WS_addrinfo *cursor = list;
+    while (cursor)
+    {
+        if (ai->ai_flags == cursor->ai_flags &&
+            ai->ai_family == cursor->ai_family &&
+            ai->ai_socktype == cursor->ai_socktype &&
+            ai->ai_protocol == cursor->ai_protocol &&
+            ai->ai_addrlen == cursor->ai_addrlen &&
+            !memcmp(ai->ai_addr, cursor->ai_addr, ai->ai_addrlen) &&
+            ((ai->ai_canonname && cursor->ai_canonname && !strcmp(ai->ai_canonname, cursor->ai_canonname))
+            || (!ai->ai_canonname && !cursor->ai_canonname)))
+        {
+            return TRUE;
+        }
+        cursor = cursor->ai_next;
+    }
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *      getaddrinfo   (ws2_32.@)
+ */
+int WINAPI WS_getaddrinfo( const char *nodename, const char *servname,
+                           const struct WS_addrinfo *hints, struct WS_addrinfo **res )
+{
+#ifdef HAVE_GETADDRINFO
+    struct addrinfo *unixaires = NULL;
+    int result;
+    struct addrinfo unixhints, *punixhints = NULL;
+    char *nodev6 = NULL, *fqdn = NULL;
+    const char *node;
+
+    *res = NULL;
+    if (!nodename && !servname)
+    {
+        SetLastError(WSAHOST_NOT_FOUND);
+        return WSAHOST_NOT_FOUND;
+    }
+
+    if (!nodename)
+        node = NULL;
+    else if (!nodename[0])
+    {
+        if (!(fqdn = get_fqdn())) return WSA_NOT_ENOUGH_MEMORY;
+        node = fqdn;
+    }
+    else
+    {
+        node = nodename;
+
+        /* Check for [ipv6] or [ipv6]:portnumber, which are supported by Windows */
+        if (!hints || hints->ai_family == WS_AF_UNSPEC || hints->ai_family == WS_AF_INET6)
+        {
+            char *close_bracket;
+
+            if (node[0] == '[' && (close_bracket = strchr(node + 1, ']')))
+            {
+                nodev6 = HeapAlloc( GetProcessHeap(), 0, close_bracket - node );
+                if (!nodev6) return WSA_NOT_ENOUGH_MEMORY;
+                lstrcpynA( nodev6, node + 1, close_bracket - node );
+                node = nodev6;
+            }
+        }
+    }
+
+    /* servname tweak required by OSX and BSD kernels */
+    if (servname && !servname[0]) servname = "0";
+
+    if (hints)
+    {
+        punixhints = &unixhints;
+
+        memset( &unixhints, 0, sizeof(unixhints) );
+        punixhints->ai_flags = convert_aiflag_w2u( hints->ai_flags );
+
+        /* zero is a wildcard, no need to convert */
+        if (hints->ai_family)
+            punixhints->ai_family = convert_af_w2u( hints->ai_family );
+        if (hints->ai_socktype)
+            punixhints->ai_socktype = convert_socktype_w2u( hints->ai_socktype );
+        if (hints->ai_protocol)
+            punixhints->ai_protocol = max( convert_proto_w2u( hints->ai_protocol ), 0 );
+
+        if (punixhints->ai_socktype < 0)
+        {
+            SetLastError( WSAESOCKTNOSUPPORT );
+            HeapFree( GetProcessHeap(), 0, fqdn );
+            HeapFree( GetProcessHeap(), 0, nodev6 );
+            return -1;
+        }
+
+        /* windows allows invalid combinations of socket type and protocol, unix does not.
+         * fix the parameters here to make getaddrinfo call always work */
+        if (punixhints->ai_protocol == IPPROTO_TCP
+                && punixhints->ai_socktype != SOCK_STREAM
+                && punixhints->ai_socktype != SOCK_SEQPACKET)
+            punixhints->ai_socktype = 0;
+        else if (punixhints->ai_protocol == IPPROTO_UDP && punixhints->ai_socktype != SOCK_DGRAM)
+            punixhints->ai_socktype = 0;
+        else if (IS_IPX_PROTO(punixhints->ai_protocol) && punixhints->ai_socktype != SOCK_DGRAM)
+            punixhints->ai_socktype = 0;
+        else if (punixhints->ai_protocol == IPPROTO_IPV6)
+            punixhints->ai_protocol = 0;
+    }
+
+    /* getaddrinfo(3) is thread safe, no need to wrap in CS */
+    result = getaddrinfo( node, servname, punixhints, &unixaires );
+
+    if (result && (!hints || !(hints->ai_flags & WS_AI_NUMERICHOST)) && node)
+    {
+        if (!fqdn && !(fqdn = get_fqdn()))
+        {
+            HeapFree( GetProcessHeap(), 0, nodev6 );
+            return WSA_NOT_ENOUGH_MEMORY;
+        }
+        if (!strcmp( fqdn, node ) || (!strncmp( fqdn, node, strlen( node ) ) && fqdn[strlen( node )] == '.'))
+        {
+            /* If it didn't work it means the host name IP is not in /etc/hosts, try again
+             * by sending a NULL host and avoid sending a NULL servname too because that
+             * is invalid */
+            ERR_(winediag)( "Failed to resolve your host name IP\n" );
+            result = getaddrinfo( NULL, servname ? servname : "0", punixhints, &unixaires );
+            if (!result && punixhints && (punixhints->ai_flags & AI_CANONNAME) && unixaires && !unixaires->ai_canonname)
+            {
+                freeaddrinfo( unixaires );
+                result = EAI_NONAME;
+            }
+        }
+    }
+    TRACE( "%s, %s %p -> %p %d\n", debugstr_a(nodename), debugstr_a(servname), hints, res, result );
+    HeapFree( GetProcessHeap(), 0, fqdn );
+    HeapFree( GetProcessHeap(), 0, nodev6 );
+
+    if (!result)
+    {
+        struct addrinfo *xuai = unixaires;
+        struct WS_addrinfo **xai = res;
+
+        *xai = NULL;
+        while (xuai)
+        {
+            struct WS_addrinfo *ai = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo) );
+            SIZE_T len;
+
+            if (!ai)
+                goto outofmem;
+
+            ai->ai_flags    = convert_aiflag_u2w( xuai->ai_flags );
+            ai->ai_family   = convert_af_u2w( xuai->ai_family );
+            /* copy whatever was sent in the hints */
+            if (hints)
+            {
+                ai->ai_socktype = hints->ai_socktype;
+                ai->ai_protocol = hints->ai_protocol;
+            }
+            else
+            {
+                ai->ai_socktype = convert_socktype_u2w( xuai->ai_socktype );
+                ai->ai_protocol = convert_proto_u2w( xuai->ai_protocol );
+            }
+            if (xuai->ai_canonname)
+            {
+                TRACE( "canon name - %s\n", debugstr_a(xuai->ai_canonname) );
+                ai->ai_canonname = HeapAlloc( GetProcessHeap(), 0, strlen( xuai->ai_canonname ) + 1 );
+                if (!ai->ai_canonname)
+                    goto outofmem;
+                strcpy( ai->ai_canonname, xuai->ai_canonname );
+            }
+            len = xuai->ai_addrlen;
+            ai->ai_addr = HeapAlloc( GetProcessHeap(), 0, len );
+            if (!ai->ai_addr)
+                goto outofmem;
+            ai->ai_addrlen = len;
+            do
+            {
+                int winlen = ai->ai_addrlen;
+
+                if (!ws_sockaddr_u2ws( xuai->ai_addr, ai->ai_addr, &winlen ))
+                {
+                    ai->ai_addrlen = winlen;
+                    break;
+                }
+                len *= 2;
+                ai->ai_addr = HeapReAlloc( GetProcessHeap(), 0, ai->ai_addr, len );
+                if (!ai->ai_addr)
+                    goto outofmem;
+                ai->ai_addrlen = len;
+            } while (1);
+
+            if (addrinfo_in_list( *res, ai ))
+            {
+                HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
+                HeapFree( GetProcessHeap(), 0, ai->ai_addr );
+                HeapFree( GetProcessHeap(), 0, ai );
+            }
+            else
+            {
+                *xai = ai;
+                xai = &ai->ai_next;
+            }
+            xuai = xuai->ai_next;
+        }
+        freeaddrinfo( unixaires );
+
+        if (TRACE_ON(winsock))
+        {
+            struct WS_addrinfo *ai = *res;
+            while (ai)
+            {
+                TRACE( "=> %p, flags %#x, family %d, type %d, protocol %d, len %ld, name %s, addr %s\n",
+                       ai, ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol, ai->ai_addrlen,
+                       ai->ai_canonname, debugstr_sockaddr(ai->ai_addr) );
+                ai = ai->ai_next;
+            }
+        }
+    }
+    else
+        result = convert_eai_u2w( result );
+
+    SetLastError( result );
+    return result;
+
+outofmem:
+    if (*res) WS_freeaddrinfo( *res );
+    if (unixaires) freeaddrinfo( unixaires );
+    return WSA_NOT_ENOUGH_MEMORY;
+#else
+    FIXME( "getaddrinfo() failed, not found during build time.\n" );
+    return EAI_FAIL;
+#endif
+}
+
+
+static ADDRINFOEXW *addrinfo_AtoW( const struct WS_addrinfo *ai )
+{
+    ADDRINFOEXW *ret;
+
+    if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(ADDRINFOEXW) ))) 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_blob      = NULL;
+    ret->ai_bloblen   = 0;
+    ret->ai_provider  = 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 * sizeof(WCHAR) )))
+        {
+            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, ai->ai_addrlen )))
+        {
+            HeapFree( GetProcessHeap(), 0, ret->ai_canonname );
+            HeapFree( GetProcessHeap(), 0, ret );
+            return NULL;
+        }
+        memcpy( ret->ai_addr, ai->ai_addr, ai->ai_addrlen );
+    }
+    return ret;
+}
+
+static ADDRINFOEXW *addrinfo_list_AtoW( const struct WS_addrinfo *info )
+{
+    ADDRINFOEXW *ret, *infoW;
+
+    if (!(ret = infoW = addrinfo_AtoW( info ))) return NULL;
+    while (info->ai_next)
+    {
+        if (!(infoW->ai_next = addrinfo_AtoW( info->ai_next )))
+        {
+            FreeAddrInfoExW( ret );
+            return NULL;
+        }
+        infoW = infoW->ai_next;
+        info = info->ai_next;
+    }
+    return ret;
+}
+
+static 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;
+}
+
+struct getaddrinfo_args
+{
+    OVERLAPPED *overlapped;
+    LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine;
+    ADDRINFOEXW **result;
+    char *nodename;
+    char *servname;
+};
+
+static void WINAPI getaddrinfo_callback(TP_CALLBACK_INSTANCE *instance, void *context)
+{
+    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;
+
+    ret = WS_getaddrinfo( args->nodename, args->servname, NULL, &res );
+    if (res)
+    {
+        *args->result = addrinfo_list_AtoW(res);
+        overlapped->u.Pointer = args->result;
+        WS_freeaddrinfo(res);
+    }
+
+    HeapFree( GetProcessHeap(), 0, args->nodename );
+    HeapFree( GetProcessHeap(), 0, args->servname );
+    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,
+                            LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine )
+{
+    int ret = EAI_MEMORY, len, i;
+    char *nodenameA = NULL, *servnameA = NULL;
+    struct WS_addrinfo *resA;
+    WCHAR *local_nodenameW = (WCHAR *)nodename;
+
+    *res = NULL;
+    if (nodename)
+    {
+        /* Is this an IDN? Most likely if any char is above the Ascii table, this
+         * is the simplest validation possible, further validation will be done by
+         * the native getaddrinfo() */
+        for (i = 0; nodename[i]; i++)
+        {
+            if (nodename[i] > 'z')
+                break;
+        }
+        if (nodename[i])
+        {
+            if (hints && (hints->ai_flags & WS_AI_DISABLE_IDN_ENCODING))
+            {
+                /* Name requires conversion but it was disabled */
+                ret = WSAHOST_NOT_FOUND;
+                SetLastError( ret );
+                goto end;
+            }
+
+            len = IdnToAscii( 0, nodename, -1, NULL, 0 );
+            if (!len)
+            {
+                ERR("Failed to convert %s to punycode\n", debugstr_w(nodename));
+                ret = EAI_FAIL;
+                goto end;
+            }
+            if (!(local_nodenameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) goto end;
+            IdnToAscii( 0, nodename, -1, local_nodenameW, len );
+        }
+    }
+    if (local_nodenameW)
+    {
+        len = WideCharToMultiByte( CP_ACP, 0, local_nodenameW, -1, NULL, 0, NULL, NULL );
+        if (!(nodenameA = HeapAlloc( GetProcessHeap(), 0, len ))) goto end;
+        WideCharToMultiByte( CP_ACP, 0, local_nodenameW, -1, nodenameA, len, NULL, NULL );
+    }
+    if (servname)
+    {
+        len = WideCharToMultiByte( CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL );
+        if (!(servnameA = HeapAlloc( GetProcessHeap(), 0, len ))) goto end;
+        WideCharToMultiByte( CP_ACP, 0, servname, -1, servnameA, len, NULL, NULL );
+    }
+
+    if (overlapped)
+    {
+        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;
+
+        overlapped->Internal = WSAEINPROGRESS;
+        if (!TrySubmitThreadpoolCallback( getaddrinfo_callback, args, NULL ))
+        {
+            HeapFree( GetProcessHeap(), 0, args );
+            ret = GetLastError();
+            goto end;
+        }
+
+        if (local_nodenameW != nodename)
+            HeapFree( GetProcessHeap(), 0, local_nodenameW );
+        SetLastError( ERROR_IO_PENDING );
+        return ERROR_IO_PENDING;
+    }
+
+    ret = WS_getaddrinfo( nodenameA, servnameA, hints, &resA );
+    if (!ret)
+    {
+        *res = addrinfo_list_AtoW( resA );
+        WS_freeaddrinfo( resA );
+    }
+
+end:
+    if (local_nodenameW != nodename)
+        HeapFree( GetProcessHeap(), 0, local_nodenameW );
+    HeapFree( GetProcessHeap(), 0, nodenameA );
+    HeapFree( GetProcessHeap(), 0, servnameA );
+    return ret;
+}
+
+
+/***********************************************************************
+ *      GetAddrInfoExW   (ws2_32.@)
+ */
+int WINAPI GetAddrInfoExW( const WCHAR *name, const WCHAR *servname, DWORD namespace,
+                           GUID *namespace_id, const ADDRINFOEXW *hints, ADDRINFOEXW **result,
+                           struct WS_timeval *timeout, OVERLAPPED *overlapped,
+                           LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine, HANDLE *handle )
+{
+    int ret;
+
+    TRACE( "name %s, servname %s, namespace %u, namespace_id %s)\n",
+           debugstr_w(name), debugstr_w(servname), namespace, debugstr_guid(namespace_id) );
+
+    if (namespace != NS_DNS)
+        FIXME( "Unsupported namespace %u\n", namespace );
+    if (namespace_id)
+        FIXME( "Unsupported namespace_id %s\n", debugstr_guid(namespace_id) );
+    if (hints)
+        FIXME( "Unsupported hints\n" );
+    if (timeout)
+        FIXME( "Unsupported timeout\n" );
+    if (handle)
+        FIXME( "Unsupported cancel handle\n" );
+
+    ret = WS_getaddrinfoW( name, servname, NULL, result, overlapped, completion_routine );
+    if (ret) return ret;
+    if (handle) *handle = (HANDLE)0xdeadbeef;
+    return 0;
+}
+
+
+/***********************************************************************
+ *      GetAddrInfoExOverlappedResult   (ws2_32.@)
+ */
+int WINAPI GetAddrInfoExOverlappedResult( OVERLAPPED *overlapped )
+{
+    TRACE( "(%p)\n", overlapped );
+    return overlapped->Internal;
+}
+
+
+/***********************************************************************
+ *      GetAddrInfoExCancel   (ws2_32.@)
+ */
+int WINAPI GetAddrInfoExCancel( HANDLE *handle )
+{
+    FIXME( "(%p)\n", handle );
+    return WSA_INVALID_HANDLE;
+}
+
+
+/***********************************************************************
+ *      GetAddrInfoW   (ws2_32.@)
+ */
+int WINAPI GetAddrInfoW(const WCHAR *nodename, const WCHAR *servname, const ADDRINFOW *hints, ADDRINFOW **res)
+{
+    struct WS_addrinfo *hintsA = NULL;
+    ADDRINFOEXW *resex;
+    int ret = EAI_MEMORY;
+
+    TRACE( "nodename %s, servname %s, hints %p, result %p\n",
+           debugstr_w(nodename), debugstr_w(servname), hints, res );
+
+    *res = NULL;
+    if (hints) hintsA = addrinfo_WtoA( hints );
+    ret = WS_getaddrinfoW( nodename, servname, hintsA, &resex, NULL, NULL );
+    WS_freeaddrinfo( hintsA );
+    if (ret) return ret;
+
+    if (resex)
+    {
+        /* ADDRINFOEXW has a layout compatible with ADDRINFOW except for the
+         * ai_next field, so we may convert it in place */
+        *res = (ADDRINFOW *)resex;
+        do
+        {
+            ((ADDRINFOW *)resex)->ai_next = (ADDRINFOW *)resex->ai_next;
+            resex = resex->ai_next;
+        } while (resex);
+    }
+    return 0;
+}
+
+
+/***********************************************************************
+ *      freeaddrinfo   (ws2_32.@)
+ */
+void WINAPI WS_freeaddrinfo( struct WS_addrinfo *res )
+{
+    while (res)
+    {
+        struct WS_addrinfo *next;
+
+        HeapFree( GetProcessHeap(), 0, res->ai_canonname );
+        HeapFree( GetProcessHeap(), 0, res->ai_addr );
+        next = res->ai_next;
+        HeapFree( GetProcessHeap(), 0, res );
+        res = next;
+    }
+}
+
+
+/***********************************************************************
+ *      FreeAddrInfoW   (ws2_32.@)
+ */
+void WINAPI FreeAddrInfoW( ADDRINFOW *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;
+    }
+}
+
+
+/***********************************************************************
+ *      FreeAddrInfoEx   (ws2_32.@)
+ */
+void WINAPI FreeAddrInfoEx( ADDRINFOEXA *ai )
+{
+    TRACE( "(%p)\n", ai );
+
+    while (ai)
+    {
+        ADDRINFOEXA *next;
+        HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
+        HeapFree( GetProcessHeap(), 0, ai->ai_addr );
+        next = ai->ai_next;
+        HeapFree( GetProcessHeap(), 0, ai );
+        ai = next;
+    }
+}
+
+
+/***********************************************************************
+ *      FreeAddrInfoExW   (ws2_32.@)
+ */
+void WINAPI FreeAddrInfoExW( ADDRINFOEXW *ai )
+{
+    TRACE( "(%p)\n", ai );
+
+    while (ai)
+    {
+        ADDRINFOEXW *next;
+        HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
+        HeapFree( GetProcessHeap(), 0, ai->ai_addr );
+        next = ai->ai_next;
+        HeapFree( GetProcessHeap(), 0, ai );
+        ai = next;
+    }
+}
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index c2069198938..9e48fe256fd 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -29,138 +29,7 @@
 #include "config.h"
 #include "wine/port.h"
 
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <limits.h>
-#ifdef HAVE_SYS_IPC_H
-# include <sys/ipc.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h>
-#endif
-#ifdef HAVE_SYS_SOCKIO_H
-# include <sys/sockio.h>
-#endif
-
-#if defined(__EMX__)
-# include <sys/so_ioctl.h>
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-
-#ifdef HAVE_SYS_MSG_H
-# include <sys/msg.h>
-#endif
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-#ifdef HAVE_SYS_UIO_H
-# include <sys/uio.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_NETINET_TCP_H
-# include <netinet/tcp.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
-#include <ctype.h>
-#include <fcntl.h>
-#include <errno.h>
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#include <stdlib.h>
-#ifdef HAVE_ARPA_NAMESER_H
-# include <arpa/nameser.h>
-#endif
-#ifdef HAVE_RESOLV_H
-# include <resolv.h>
-#endif
-#ifdef HAVE_NET_IF_H
-# include <net/if.h>
-#endif
-#ifdef HAVE_LINUX_FILTER_H
-# include <linux/filter.h>
-#endif
-
-#ifdef HAVE_NETIPX_IPX_H
-# include <netipx/ipx.h>
-#elif defined(HAVE_LINUX_IPX_H)
-# ifdef HAVE_ASM_TYPES_H
-#  include <asm/types.h>
-# endif
-# ifdef HAVE_LINUX_TYPES_H
-#  include <linux/types.h>
-# endif
-# include <linux/ipx.h>
-#endif
-#if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS)
-# define HAS_IPX
-#endif
-
-#ifdef HAVE_LINUX_IRDA_H
-# ifdef HAVE_LINUX_TYPES_H
-#  include <linux/types.h>
-# endif
-# include <linux/irda.h>
-# define HAS_IRDA
-#endif
-
-#ifdef HAVE_POLL_H
-#include <poll.h>
-#endif
-#ifdef HAVE_SYS_POLL_H
-# include <sys/poll.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
-#include "windef.h"
-#include "winbase.h"
-#include "wingdi.h"
-#include "winuser.h"
-#include "winerror.h"
-#include "winnls.h"
-#include "winsock2.h"
-#include "mswsock.h"
-#include "ws2tcpip.h"
-#include "ws2spi.h"
-#include "wsipx.h"
-#include "wsnwlink.h"
-#include "wshisotp.h"
-#include "mstcpip.h"
-#include "af_irda.h"
-#include "winnt.h"
-#define USE_WC_PREFIX   /* For CMSG_DATA */
-#include "iphlpapi.h"
-#include "ip2string.h"
-#include "wine/afd.h"
-#include "wine/server.h"
-#include "wine/debug.h"
-#include "wine/exception.h"
-#include "wine/unicode.h"
-#include "wine/heap.h"
+#include "ws2_32_private.h"
 
 #if defined(linux) && !defined(IP_UNICAST_IF)
 #define IP_UNICAST_IF 50
@@ -300,8 +169,6 @@ static const WSAPROTOCOL_INFOW supported_protocols[] =
     },
 };
 
-#define IS_IPX_PROTO(X) ((X) >= WS_NSPROTO_IPX && (X) <= WS_NSPROTO_IPX + 255)
-
 #if defined(IP_UNICAST_IF) && defined(SO_ATTACH_FILTER)
 # define LINUX_BOUND_IF
 struct interface_filter {
@@ -381,7 +248,7 @@ union generic_unix_sockaddr
     char data[128];  /* should be big enough for all families */
 };
 
-static inline const char *debugstr_sockaddr( const struct WS_sockaddr *a )
+const char *debugstr_sockaddr( const struct WS_sockaddr *a )
 {
     if (!a) return "(nil)";
     switch (a->sa_family)
@@ -896,34 +763,6 @@ static const int ws_socktype_map[][2] =
     {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
 };
 
-static const int ws_proto_map[][2] =
-{
-    MAP_OPTION( IPPROTO_IP ),
-    MAP_OPTION( IPPROTO_TCP ),
-    MAP_OPTION( IPPROTO_UDP ),
-    MAP_OPTION( IPPROTO_IPV6 ),
-    MAP_OPTION( IPPROTO_ICMP ),
-    MAP_OPTION( IPPROTO_IGMP ),
-    MAP_OPTION( IPPROTO_RAW ),
-    {WS_IPPROTO_IPV4, IPPROTO_IPIP},
-    {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
-};
-
-static const int ws_aiflag_map[][2] =
-{
-    MAP_OPTION( AI_PASSIVE ),
-    MAP_OPTION( AI_CANONNAME ),
-    MAP_OPTION( AI_NUMERICHOST ),
-#ifdef AI_NUMERICSERV
-    MAP_OPTION( AI_NUMERICSERV ),
-#endif
-#ifdef  AI_V4MAPPED
-    MAP_OPTION( AI_V4MAPPED ),
-#endif
-    MAP_OPTION( AI_ALL ),
-    MAP_OPTION( AI_ADDRCONFIG ),
-};
-
 static const int ws_niflag_map[][2] =
 {
     MAP_OPTION( NI_NOFQDN ),
@@ -933,30 +772,6 @@ static const int ws_niflag_map[][2] =
     MAP_OPTION( NI_DGRAM ),
 };
 
-static const int ws_eai_map[][2] =
-{
-    MAP_OPTION( EAI_AGAIN ),
-    MAP_OPTION( EAI_BADFLAGS ),
-    MAP_OPTION( EAI_FAIL ),
-    MAP_OPTION( EAI_FAMILY ),
-    MAP_OPTION( EAI_MEMORY ),
-/* Note: EAI_NODATA is deprecated, but still 
- * used by Windows and Linux... We map the newer
- * EAI_NONAME to EAI_NODATA for now until Windows
- * changes too.
- */
-#ifdef EAI_NODATA
-    MAP_OPTION( EAI_NODATA ),
-#endif
-#ifdef EAI_NONAME
-    { WS_EAI_NODATA, EAI_NONAME },
-#endif
-
-    MAP_OPTION( EAI_SERVICE ),
-    MAP_OPTION( EAI_SOCKTYPE ),
-    { 0, 0 }
-};
-
 static const int ws_poll_map[][2] =
 {
     MAP_OPTION( POLLERR ),
@@ -1103,7 +918,7 @@ static NTSTATUS sock_get_ntstatus( int err )
     }
 }
 
-static UINT sock_get_error( int err )
+UINT sock_get_error( int err )
 {
 	switch(err)
     {
@@ -1671,7 +1486,7 @@ static inline int do_block( int fd, int events, int timeout )
   return pfd.revents;
 }
 
-static int
+int
 convert_af_w2u(int windowsaf) {
     unsigned int i;
 
@@ -1682,7 +1497,7 @@ convert_af_w2u(int windowsaf) {
     return -1;
 }
 
-static int
+int
 convert_af_u2w(int unixaf) {
     unsigned int i;
 
@@ -1693,40 +1508,7 @@ convert_af_u2w(int unixaf) {
     return -1;
 }
 
-static int
-convert_proto_w2u(int windowsproto) {
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(ws_proto_map); i++)
-    	if (ws_proto_map[i][0] == windowsproto)
-	    return ws_proto_map[i][1];
-
-    /* check for extended IPX */
-    if (IS_IPX_PROTO(windowsproto))
-      return windowsproto;
-
-    FIXME("unhandled Windows socket protocol %d\n", windowsproto);
-    return -1;
-}
-
-static int
-convert_proto_u2w(int unixproto) {
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(ws_proto_map); i++)
-    	if (ws_proto_map[i][1] == unixproto)
-	    return ws_proto_map[i][0];
-
-    /* if value is inside IPX range just return it - the kernel simply
-     * echoes the value used in the socket() function */
-    if (IS_IPX_PROTO(unixproto))
-      return unixproto;
-
-    FIXME("unhandled UNIX socket protocol %d\n", unixproto);
-    return -1;
-}
-
-static int
+int
 convert_socktype_w2u(int windowssocktype) {
     unsigned int i;
 
@@ -1737,7 +1519,7 @@ convert_socktype_w2u(int windowssocktype) {
     return -1;
 }
 
-static int
+int
 convert_socktype_u2w(int unixsocktype) {
     unsigned int i;
 
@@ -2130,7 +1912,7 @@ static int is_fd_bound(int fd, union generic_unix_sockaddr *uaddr, socklen_t *ua
 }
 
 /* Returns 0 if successful, -1 if the buffer is too small */
-static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, struct WS_sockaddr* wsaddr, int* wsaddrlen)
+int ws_sockaddr_u2ws(const struct sockaddr *uaddr, struct WS_sockaddr *wsaddr, int *wsaddrlen)
 {
     int res;
 
@@ -6430,37 +6212,6 @@ struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
     return retval;
 }
 
-/***********************************************************************
- *		freeaddrinfo		(WS2_32.@)
- */
-void WINAPI WS_freeaddrinfo(struct WS_addrinfo *res)
-{
-    while (res) {
-        struct WS_addrinfo *next;
-
-        HeapFree(GetProcessHeap(),0,res->ai_canonname);
-        HeapFree(GetProcessHeap(),0,res->ai_addr);
-        next = res->ai_next;
-        HeapFree(GetProcessHeap(),0,res);
-        res = next;
-    }
-}
-
-/* helper functions for getaddrinfo()/getnameinfo() */
-static int convert_aiflag_w2u(int winflags) {
-    unsigned int i;
-    int unixflags = 0;
-
-    for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
-        if (ws_aiflag_map[i][0] & winflags) {
-            unixflags |= ws_aiflag_map[i][1];
-            winflags &= ~ws_aiflag_map[i][0];
-        }
-    if (winflags)
-        FIXME("Unhandled windows AI_xxx flags 0x%x\n", winflags);
-    return unixflags;
-}
-
 static int convert_niflag_w2u(int winflags) {
     unsigned int i;
     int unixflags = 0;
@@ -6475,631 +6226,6 @@ static int convert_niflag_w2u(int winflags) {
     return unixflags;
 }
 
-static int convert_aiflag_u2w(int unixflags) {
-    unsigned int i;
-    int winflags = 0;
-
-    for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
-        if (ws_aiflag_map[i][1] & unixflags) {
-            winflags |= ws_aiflag_map[i][0];
-            unixflags &= ~ws_aiflag_map[i][1];
-        }
-    if (unixflags)
-        WARN("Unhandled UNIX AI_xxx flags 0x%x\n", unixflags);
-    return winflags;
-}
-
-static int convert_eai_u2w(int unixret) {
-    int i;
-
-    if (!unixret) return 0;
-
-    for (i=0;ws_eai_map[i][0];i++)
-        if (ws_eai_map[i][1] == unixret)
-            return ws_eai_map[i][0];
-
-    if (unixret == EAI_SYSTEM)
-        /* There are broken versions of glibc which return EAI_SYSTEM
-         * and set errno to 0 instead of returning EAI_NONAME.
-         */
-        return errno ? sock_get_error( errno ) : WS_EAI_NONAME;
-
-    FIXME("Unhandled unix EAI_xxx ret %d\n", unixret);
-    return unixret;
-}
-
-static char *get_fqdn(void)
-{
-    char *ret;
-    DWORD size = 0;
-
-    GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, NULL, &size );
-    if (GetLastError() != ERROR_MORE_DATA) return NULL;
-    if (!(ret = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
-    if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, ret, &size ))
-    {
-        HeapFree( GetProcessHeap(), 0, ret );
-        return NULL;
-    }
-    return ret;
-}
-
-static BOOL addrinfo_in_list( const struct WS_addrinfo *list, const struct WS_addrinfo *ai )
-{
-    const struct WS_addrinfo *cursor = list;
-    while (cursor)
-    {
-        if (ai->ai_flags == cursor->ai_flags && ai->ai_family == cursor->ai_family &&
-            ai->ai_socktype == cursor->ai_socktype && ai->ai_protocol == cursor->ai_protocol &&
-            ai->ai_addrlen == cursor->ai_addrlen && !memcmp(ai->ai_addr, cursor->ai_addr, ai->ai_addrlen) &&
-            ((ai->ai_canonname && cursor->ai_canonname && !strcmp(ai->ai_canonname, cursor->ai_canonname))
-            || (!ai->ai_canonname && !cursor->ai_canonname))) return TRUE;
-        cursor = cursor->ai_next;
-    }
-    return FALSE;
-}
-
-/***********************************************************************
- *		getaddrinfo		(WS2_32.@)
- */
-int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addrinfo *hints, struct WS_addrinfo **res)
-{
-#ifdef HAVE_GETADDRINFO
-    struct addrinfo *unixaires = NULL;
-    int   result;
-    struct addrinfo unixhints, *punixhints = NULL;
-    char *nodeV6 = NULL, *fqdn = NULL;
-    const char *node;
-
-    *res = NULL;
-    if (!nodename && !servname)
-    {
-        SetLastError(WSAHOST_NOT_FOUND);
-        return WSAHOST_NOT_FOUND;
-    }
-
-    if (!nodename)
-        node = NULL;
-    else if (!nodename[0])
-    {
-        if (!(fqdn = get_fqdn())) return WSA_NOT_ENOUGH_MEMORY;
-        node = fqdn;
-    }
-    else
-    {
-        node = nodename;
-
-        /* Check for [ipv6] or [ipv6]:portnumber, which are supported by Windows */
-        if (!hints || hints->ai_family == WS_AF_UNSPEC || hints->ai_family == WS_AF_INET6)
-        {
-            char *close_bracket;
-
-            if (node[0] == '[' && (close_bracket = strchr(node + 1, ']')))
-            {
-                nodeV6 = HeapAlloc(GetProcessHeap(), 0, close_bracket - node);
-                if (!nodeV6) return WSA_NOT_ENOUGH_MEMORY;
-                lstrcpynA(nodeV6, node + 1, close_bracket - node);
-                node = nodeV6;
-            }
-        }
-    }
-
-    /* servname tweak required by OSX and BSD kernels */
-    if (servname && !servname[0]) servname = "0";
-
-    if (hints) {
-        punixhints = &unixhints;
-
-        memset(&unixhints, 0, sizeof(unixhints));
-        punixhints->ai_flags = convert_aiflag_w2u(hints->ai_flags);
-
-        /* zero is a wildcard, no need to convert */
-        if (hints->ai_family)
-            punixhints->ai_family = convert_af_w2u(hints->ai_family);
-        if (hints->ai_socktype)
-            punixhints->ai_socktype = convert_socktype_w2u(hints->ai_socktype);
-        if (hints->ai_protocol)
-            punixhints->ai_protocol = max(convert_proto_w2u(hints->ai_protocol), 0);
-
-        if (punixhints->ai_socktype < 0)
-        {
-            SetLastError(WSAESOCKTNOSUPPORT);
-            HeapFree(GetProcessHeap(), 0, fqdn);
-            HeapFree(GetProcessHeap(), 0, nodeV6);
-            return SOCKET_ERROR;
-        }
-
-        /* windows allows invalid combinations of socket type and protocol, unix does not.
-         * fix the parameters here to make getaddrinfo call always work */
-        if (punixhints->ai_protocol == IPPROTO_TCP &&
-            punixhints->ai_socktype != SOCK_STREAM && punixhints->ai_socktype != SOCK_SEQPACKET)
-            punixhints->ai_socktype = 0;
-
-        else if (punixhints->ai_protocol == IPPROTO_UDP && punixhints->ai_socktype != SOCK_DGRAM)
-            punixhints->ai_socktype = 0;
-
-        else if (IS_IPX_PROTO(punixhints->ai_protocol) && punixhints->ai_socktype != SOCK_DGRAM)
-            punixhints->ai_socktype = 0;
-
-        else if (punixhints->ai_protocol == IPPROTO_IPV6)
-            punixhints->ai_protocol = 0;
-    }
-
-    /* getaddrinfo(3) is thread safe, no need to wrap in CS */
-    result = getaddrinfo(node, servname, punixhints, &unixaires);
-
-    if (result && (!hints || !(hints->ai_flags & WS_AI_NUMERICHOST)) && node)
-    {
-        if (!fqdn && !(fqdn = get_fqdn()))
-        {
-            HeapFree(GetProcessHeap(), 0, nodeV6);
-            return WSA_NOT_ENOUGH_MEMORY;
-        }
-        if (!strcmp(fqdn, node) || (!strncmp(fqdn, node, strlen(node)) && fqdn[strlen(node)] == '.'))
-        {
-            /* If it didn't work it means the host name IP is not in /etc/hosts, try again
-             * by sending a NULL host and avoid sending a NULL servname too because that
-             * is invalid */
-            ERR_(winediag)("Failed to resolve your host name IP\n");
-            result = getaddrinfo(NULL, servname ? servname : "0", punixhints, &unixaires);
-            if (!result && punixhints && (punixhints->ai_flags & AI_CANONNAME) && unixaires && !unixaires->ai_canonname)
-            {
-                freeaddrinfo(unixaires);
-                result = EAI_NONAME;
-            }
-        }
-    }
-    TRACE("%s, %s %p -> %p %d\n", debugstr_a(nodename), debugstr_a(servname), hints, res, result);
-    HeapFree(GetProcessHeap(), 0, fqdn);
-    HeapFree(GetProcessHeap(), 0, nodeV6);
-
-    if (!result) {
-        struct addrinfo *xuai = unixaires;
-        struct WS_addrinfo **xai = res;
-
-        *xai = NULL;
-        while (xuai) {
-            struct WS_addrinfo *ai = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo));
-            SIZE_T len;
-
-            if (!ai)
-                goto outofmem;
-
-            ai->ai_flags    = convert_aiflag_u2w(xuai->ai_flags);
-            ai->ai_family   = convert_af_u2w(xuai->ai_family);
-            /* copy whatever was sent in the hints */
-            if(hints) {
-                ai->ai_socktype = hints->ai_socktype;
-                ai->ai_protocol = hints->ai_protocol;
-            } else {
-                ai->ai_socktype = convert_socktype_u2w(xuai->ai_socktype);
-                ai->ai_protocol = convert_proto_u2w(xuai->ai_protocol);
-            }
-            if (xuai->ai_canonname) {
-                TRACE("canon name - %s\n",debugstr_a(xuai->ai_canonname));
-                ai->ai_canonname = HeapAlloc(GetProcessHeap(),0,strlen(xuai->ai_canonname)+1);
-                if (!ai->ai_canonname)
-                    goto outofmem;
-                strcpy(ai->ai_canonname,xuai->ai_canonname);
-            }
-            len = xuai->ai_addrlen;
-            ai->ai_addr = HeapAlloc(GetProcessHeap(),0,len);
-            if (!ai->ai_addr)
-                goto outofmem;
-            ai->ai_addrlen = len;
-            do {
-                int winlen = ai->ai_addrlen;
-
-                if (!ws_sockaddr_u2ws(xuai->ai_addr, ai->ai_addr, &winlen)) {
-                    ai->ai_addrlen = winlen;
-                    break;
-                }
-                len = 2*len;
-                ai->ai_addr = HeapReAlloc(GetProcessHeap(),0,ai->ai_addr,len);
-                if (!ai->ai_addr)
-                    goto outofmem;
-                ai->ai_addrlen = len;
-            } while (1);
-
-            if (addrinfo_in_list(*res, ai))
-            {
-                HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
-                HeapFree(GetProcessHeap(), 0, ai->ai_addr);
-                HeapFree(GetProcessHeap(), 0, ai);
-            }
-            else
-            {
-                *xai = ai;
-                xai = &ai->ai_next;
-            }
-            xuai = xuai->ai_next;
-        }
-        freeaddrinfo(unixaires);
-
-        if (TRACE_ON(winsock))
-        {
-            struct WS_addrinfo *ai = *res;
-            while (ai)
-            {
-                TRACE("=> %p, flags %#x, family %d, type %d, protocol %d, len %ld, name %s, addr %s\n",
-                      ai, ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol, ai->ai_addrlen,
-                      ai->ai_canonname, debugstr_sockaddr(ai->ai_addr));
-                ai = ai->ai_next;
-            }
-        }
-    } else
-        result = convert_eai_u2w(result);
-
-    SetLastError(result);
-    return result;
-
-outofmem:
-    if (*res) WS_freeaddrinfo(*res);
-    if (unixaires) freeaddrinfo(unixaires);
-    return WSA_NOT_ENOUGH_MEMORY;
-#else
-    FIXME("getaddrinfo() failed, not found during buildtime.\n");
-    return EAI_FAIL;
-#endif
-}
-
-static ADDRINFOEXW *addrinfo_AtoW(const struct WS_addrinfo *ai)
-{
-    ADDRINFOEXW *ret;
-
-    if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ADDRINFOEXW)))) 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_blob      = NULL;
-    ret->ai_bloblen   = 0;
-    ret->ai_provider  = 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*sizeof(WCHAR))))
-        {
-            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, ai->ai_addrlen)))
-        {
-            HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
-            HeapFree(GetProcessHeap(), 0, ret);
-            return NULL;
-        }
-        memcpy(ret->ai_addr, ai->ai_addr, ai->ai_addrlen);
-    }
-    return ret;
-}
-
-static ADDRINFOEXW *addrinfo_list_AtoW(const struct WS_addrinfo *info)
-{
-    ADDRINFOEXW *ret, *infoW;
-
-    if (!(ret = infoW = addrinfo_AtoW(info))) return NULL;
-    while (info->ai_next)
-    {
-        if (!(infoW->ai_next = addrinfo_AtoW(info->ai_next)))
-        {
-            FreeAddrInfoExW(ret);
-            return NULL;
-        }
-        infoW = infoW->ai_next;
-        info = info->ai_next;
-    }
-    return ret;
-}
-
-static 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;
-}
-
-struct getaddrinfo_args
-{
-    OVERLAPPED *overlapped;
-    LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine;
-    ADDRINFOEXW **result;
-    char *nodename;
-    char *servname;
-};
-
-static void WINAPI getaddrinfo_callback(TP_CALLBACK_INSTANCE *instance, void *context)
-{
-    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;
-
-    ret = WS_getaddrinfo(args->nodename, args->servname, NULL, &res);
-    if (res)
-    {
-        *args->result = addrinfo_list_AtoW(res);
-        overlapped->u.Pointer = args->result;
-        WS_freeaddrinfo(res);
-    }
-
-    HeapFree(GetProcessHeap(), 0, args->nodename);
-    HeapFree(GetProcessHeap(), 0, args->servname);
-    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, LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine)
-{
-    int ret = EAI_MEMORY, len, i;
-    char *nodenameA = NULL, *servnameA = NULL;
-    struct WS_addrinfo *resA;
-    WCHAR *local_nodenameW = (WCHAR *)nodename;
-
-    *res = NULL;
-    if (nodename)
-    {
-        /* Is this an IDN? Most likely if any char is above the Ascii table, this
-         * is the simplest validation possible, further validation will be done by
-         * the native getaddrinfo() */
-        for (i = 0; nodename[i]; i++)
-        {
-            if (nodename[i] > 'z')
-                break;
-        }
-        if (nodename[i])
-        {
-            if (hints && (hints->ai_flags & WS_AI_DISABLE_IDN_ENCODING))
-            {
-                /* Name requires conversion but it was disabled */
-                ret = WSAHOST_NOT_FOUND;
-                WSASetLastError(ret);
-                goto end;
-            }
-
-            len = IdnToAscii(0, nodename, -1, NULL, 0);
-            if (!len)
-            {
-                ERR("Failed to convert %s to punycode\n", debugstr_w(nodename));
-                ret = EAI_FAIL;
-                goto end;
-            }
-            if (!(local_nodenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) goto end;
-            IdnToAscii(0, nodename, -1, local_nodenameW, len);
-        }
-    }
-    if (local_nodenameW)
-    {
-        len = WideCharToMultiByte(CP_ACP, 0, local_nodenameW, -1, NULL, 0, NULL, NULL);
-        if (!(nodenameA = HeapAlloc(GetProcessHeap(), 0, len))) goto end;
-        WideCharToMultiByte(CP_ACP, 0, local_nodenameW, -1, nodenameA, len, NULL, NULL);
-    }
-    if (servname)
-    {
-        len = WideCharToMultiByte(CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL);
-        if (!(servnameA = HeapAlloc(GetProcessHeap(), 0, len))) goto end;
-        WideCharToMultiByte(CP_ACP, 0, servname, -1, servnameA, len, NULL, NULL);
-    }
-
-    if (overlapped)
-    {
-        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;
-
-        overlapped->Internal = WSAEINPROGRESS;
-        if (!TrySubmitThreadpoolCallback(getaddrinfo_callback, args, NULL))
-        {
-            HeapFree(GetProcessHeap(), 0, args);
-            ret = GetLastError();
-            goto end;
-        }
-
-        if (local_nodenameW != nodename)
-            HeapFree(GetProcessHeap(), 0, local_nodenameW);
-        WSASetLastError(ERROR_IO_PENDING);
-        return ERROR_IO_PENDING;
-    }
-
-    ret = WS_getaddrinfo(nodenameA, servnameA, hints, &resA);
-    if (!ret)
-    {
-        *res = addrinfo_list_AtoW(resA);
-        WS_freeaddrinfo(resA);
-    }
-
-end:
-    if (local_nodenameW != nodename)
-        HeapFree(GetProcessHeap(), 0, local_nodenameW);
-    HeapFree(GetProcessHeap(), 0, nodenameA);
-    HeapFree(GetProcessHeap(), 0, servnameA);
-    return ret;
-}
-
-/***********************************************************************
- *		GetAddrInfoExW		(WS2_32.@)
- */
-int WINAPI GetAddrInfoExW(const WCHAR *name, const WCHAR *servname, DWORD namespace, GUID *namespace_id,
-        const ADDRINFOEXW *hints, ADDRINFOEXW **result, struct WS_timeval *timeout, OVERLAPPED *overlapped,
-        LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine, HANDLE *handle)
-{
-    int ret;
-
-    TRACE("(%s %s %x %s %p %p %p %p %p %p)\n", debugstr_w(name), debugstr_w(servname), namespace,
-          debugstr_guid(namespace_id), hints, result, timeout, overlapped, completion_routine, handle);
-
-    if (namespace != NS_DNS)
-        FIXME("Unsupported namespace %u\n", namespace);
-    if (namespace_id)
-        FIXME("Unsupported naemspace_id %s\n", debugstr_guid(namespace_id));
-    if (hints)
-        FIXME("Unsupported hints\n");
-    if (timeout)
-        FIXME("Unsupported timeout\n");
-    if (handle)
-        FIXME("Unsupported cancel handle\n");
-
-    ret = WS_getaddrinfoW(name, servname, NULL, result, overlapped, completion_routine);
-    if (ret) return ret;
-    if (handle) *handle = (HANDLE)0xdeadbeef;
-    return 0;
-}
-
-/***********************************************************************
- *		GetAddrInfoExOverlappedResult  (WS2_32.@)
- */
-int WINAPI GetAddrInfoExOverlappedResult(OVERLAPPED *overlapped)
-{
-    TRACE("(%p)\n", overlapped);
-    return overlapped->Internal;
-}
-
-/***********************************************************************
- *		GetAddrInfoExCancel     (WS2_32.@)
- */
-int WINAPI GetAddrInfoExCancel(HANDLE *handle)
-{
-    FIXME("(%p)\n", handle);
-    return WSA_INVALID_HANDLE;
-}
-
-/***********************************************************************
- *		GetAddrInfoW		(WS2_32.@)
- */
-int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hints, PADDRINFOW *res)
-{
-    struct WS_addrinfo *hintsA = NULL;
-    ADDRINFOEXW *resex;
-    int ret = EAI_MEMORY;
-
-    TRACE("nodename %s, servname %s, hints %p, result %p\n",
-          debugstr_w(nodename), debugstr_w(servname), hints, res);
-
-    *res = NULL;
-    if (hints) hintsA = addrinfo_WtoA(hints);
-    ret = WS_getaddrinfoW(nodename, servname, hintsA, &resex, NULL, NULL);
-    WS_freeaddrinfo(hintsA);
-    if (ret) return ret;
-
-    if (resex)
-    {
-        /* ADDRINFOEXW has layout compatible with ADDRINFOW except for ai_next field,
-         * so we may convert it in place */
-        *res = (ADDRINFOW*)resex;
-        do {
-            ((ADDRINFOW*)resex)->ai_next = (ADDRINFOW*)resex->ai_next;
-            resex = resex->ai_next;
-        } while (resex);
-    }
-    return 0;
-}
-
-/***********************************************************************
- *      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;
-    }
-}
-
-/***********************************************************************
- *      FreeAddrInfoEx      (WS2_32.@)
- */
-void WINAPI FreeAddrInfoEx(ADDRINFOEXA *ai)
-{
-    TRACE("(%p)\n", ai);
-
-    while (ai)
-    {
-        ADDRINFOEXA *next;
-        HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
-        HeapFree(GetProcessHeap(), 0, ai->ai_addr);
-        next = ai->ai_next;
-        HeapFree(GetProcessHeap(), 0, ai);
-        ai = next;
-    }
-}
-
-/***********************************************************************
- *      FreeAddrInfoExW      (WS2_32.@)
- */
-void WINAPI FreeAddrInfoExW(ADDRINFOEXW *ai)
-{
-    TRACE("(%p)\n", ai);
-
-    while (ai)
-    {
-        ADDRINFOEXW *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,
                           DWORD hostlen, PCHAR serv, DWORD servlen, INT flags)
 {
diff --git a/dlls/ws2_32/ws2_32_private.h b/dlls/ws2_32/ws2_32_private.h
new file mode 100644
index 00000000000..8af23b11ded
--- /dev/null
+++ b/dlls/ws2_32/ws2_32_private.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2021 Zebediah Figura for CodeWeavers
+ *
+ * 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
+ */
+
+#ifndef __WINE_WS2_32_PRIVATE_H
+#define __WINE_WS2_32_PRIVATE_H
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <limits.h>
+#ifdef HAVE_SYS_IPC_H
+# include <sys/ipc.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+#ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+#endif
+
+#if defined(__EMX__)
+# include <sys/so_ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_MSG_H
+# include <sys/msg.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+# include <sys/uio.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+# include <netinet/tcp.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdlib.h>
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+# include <resolv.h>
+#endif
+#ifdef HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#ifdef HAVE_LINUX_FILTER_H
+# include <linux/filter.h>
+#endif
+
+#ifdef HAVE_NETIPX_IPX_H
+# include <netipx/ipx.h>
+#elif defined(HAVE_LINUX_IPX_H)
+# ifdef HAVE_ASM_TYPES_H
+#  include <asm/types.h>
+# endif
+# ifdef HAVE_LINUX_TYPES_H
+#  include <linux/types.h>
+# endif
+# include <linux/ipx.h>
+#endif
+#if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS)
+# define HAS_IPX
+#endif
+
+#ifdef HAVE_LINUX_IRDA_H
+# ifdef HAVE_LINUX_TYPES_H
+#  include <linux/types.h>
+# endif
+# include <linux/irda.h>
+# define HAS_IRDA
+#endif
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "winnls.h"
+#include "winsock2.h"
+#include "mswsock.h"
+#include "ws2tcpip.h"
+#include "ws2spi.h"
+#include "wsipx.h"
+#include "wsnwlink.h"
+#include "wshisotp.h"
+#include "mstcpip.h"
+#include "af_irda.h"
+#include "winnt.h"
+#define USE_WC_PREFIX   /* For CMSG_DATA */
+#include "iphlpapi.h"
+#include "ip2string.h"
+#include "wine/afd.h"
+#include "wine/server.h"
+#include "wine/debug.h"
+#include "wine/exception.h"
+#include "wine/unicode.h"
+#include "wine/heap.h"
+
+int convert_af_u2w( int family ) DECLSPEC_HIDDEN;
+int convert_af_w2u( int family ) DECLSPEC_HIDDEN;
+int convert_eai_u2w( int ret ) DECLSPEC_HIDDEN;
+int convert_socktype_u2w( int type ) DECLSPEC_HIDDEN;
+int convert_socktype_w2u( int type ) DECLSPEC_HIDDEN;
+int ws_sockaddr_u2ws( const struct sockaddr *unix_addr, struct WS_sockaddr *win_addr,
+                      int *win_addr_len ) DECLSPEC_HIDDEN;
+
+const char *debugstr_sockaddr( const struct WS_sockaddr *addr ) DECLSPEC_HIDDEN;
+
+UINT sock_get_error( int err ) DECLSPEC_HIDDEN;
+
+#endif
-- 
2.30.2




More information about the wine-devel mailing list