[PATCH 2/5] ws2_32: Move host lookup functions to protocol.c.

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


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/ws2_32/protocol.c       | 492 +++++++++++++++++++++++++++++++++
 dlls/ws2_32/socket.c         | 516 +----------------------------------
 dlls/ws2_32/ws2_32_private.h |  29 +-
 3 files changed, 521 insertions(+), 516 deletions(-)

diff --git a/dlls/ws2_32/protocol.c b/dlls/ws2_32/protocol.c
index 7bf994b501f..5bbcdee3e0c 100644
--- a/dlls/ws2_32/protocol.c
+++ b/dlls/ws2_32/protocol.c
@@ -29,6 +29,8 @@
 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
 WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
+DECLARE_CRITICAL_SECTION(csWSgetXXXbyYYY);
+
 #define MAP_OPTION(opt) { WS_##opt, opt }
 
 static const int ws_aiflag_map[][2] =
@@ -66,6 +68,20 @@ static const int ws_eai_map[][2] =
     { 0, 0 }
 };
 
+static const int ws_af_map[][2] =
+{
+    MAP_OPTION( AF_UNSPEC ),
+    MAP_OPTION( AF_INET ),
+    MAP_OPTION( AF_INET6 ),
+#ifdef HAS_IPX
+    MAP_OPTION( AF_IPX ),
+#endif
+#ifdef AF_IRDA
+    MAP_OPTION( AF_IRDA ),
+#endif
+    {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
+};
+
 static const int ws_proto_map[][2] =
 {
     MAP_OPTION( IPPROTO_IP ),
@@ -81,6 +97,32 @@ static const int ws_proto_map[][2] =
 
 #define IS_IPX_PROTO(X) ((X) >= WS_NSPROTO_IPX && (X) <= WS_NSPROTO_IPX + 255)
 
+static int convert_af_w2u( int family )
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
+    {
+        if (ws_af_map[i][0] == family)
+            return ws_af_map[i][1];
+    }
+    FIXME( "unhandled Windows address family %d\n", family );
+    return -1;
+}
+
+static int convert_af_u2w( int family )
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
+    {
+        if (ws_af_map[i][1] == family)
+            return ws_af_map[i][0];
+    }
+    FIXME( "unhandled UNIX address family %d\n", family );
+    return -1;
+}
+
 static int convert_proto_w2u( int protocol )
 {
     unsigned int i;
@@ -810,3 +852,453 @@ void WINAPI FreeAddrInfoExW( ADDRINFOEXW *ai )
         ai = next;
     }
 }
+
+
+static UINT host_errno_from_unix( int err )
+{
+    WARN( "%d\n", err );
+
+    switch (err)
+    {
+        case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
+        case TRY_AGAIN:         return WSATRY_AGAIN;
+        case NO_RECOVERY:       return WSANO_RECOVERY;
+        case NO_DATA:           return WSANO_DATA;
+        case ENOBUFS:           return WSAENOBUFS;
+        case 0:                 return 0;
+        default:
+            WARN( "Unknown h_errno %d!\n", err );
+            return WSAEOPNOTSUPP;
+    }
+}
+
+static struct WS_hostent *get_hostent_buffer( unsigned int size )
+{
+    struct per_thread_data *data = get_per_thread_data();
+    if (data->he_buffer)
+    {
+        if (data->he_len >= size) return data->he_buffer;
+        HeapFree( GetProcessHeap(), 0, data->he_buffer );
+    }
+    data->he_buffer = HeapAlloc( GetProcessHeap(), 0, (data->he_len = size) );
+    if (!data->he_buffer) SetLastError(WSAENOBUFS);
+    return data->he_buffer;
+}
+
+/* create a hostent entry
+ *
+ * Creates the entry with enough memory for the name, aliases
+ * addresses, and the address pointers.  Also copies the name
+ * and sets up all the pointers.
+ *
+ * NOTE: The alias and address lists must be allocated with room
+ * for the NULL item terminating the list.  This is true even if
+ * the list has no items ("aliases" and "addresses" must be
+ * at least "1", a truly empty list is invalid).
+ */
+static struct WS_hostent *create_hostent( char *name, int alias_count, int aliases_size,
+                                          int address_count, int address_length )
+{
+    struct WS_hostent *p_to;
+    char *p;
+    unsigned int size = sizeof(struct WS_hostent), i;
+
+    size += strlen(name) + 1;
+    size += alias_count * sizeof(char *);
+    size += aliases_size;
+    size += address_count * sizeof(char *);
+    size += (address_count - 1) * address_length;
+
+    if (!(p_to = get_hostent_buffer( size ))) return NULL;
+    memset( p_to, 0, size );
+
+    /* Use the memory in the same way winsock does.
+     * First set the pointer for aliases, second set the pointers for addresses.
+     * Third fill the addresses indexes, fourth jump aliases names size.
+     * Fifth fill the hostname.
+     * NOTE: This method is valid for OS versions >= XP.
+     */
+    p = (char *)(p_to + 1);
+    p_to->h_aliases = (char **)p;
+    p += alias_count * sizeof(char *);
+
+    p_to->h_addr_list = (char **)p;
+    p += address_count * sizeof(char *);
+
+    for (i = 0, address_count--; i < address_count; i++, p += address_length)
+        p_to->h_addr_list[i] = p;
+
+    /* h_aliases must be filled in manually because we don't know each string
+     * size. Leave these pointers NULL (already set to NULL by memset earlier).
+     */
+    p += aliases_size;
+
+    p_to->h_name = p;
+    strcpy( p, name );
+
+    return p_to;
+}
+
+static struct WS_hostent *hostent_from_unix( const struct hostent *p_he )
+{
+    int i, addresses = 0, alias_size = 0;
+    struct WS_hostent *p_to;
+    char *p;
+
+    for (i = 0; p_he->h_aliases[i]; i++)
+        alias_size += strlen( p_he->h_aliases[i] ) + 1;
+    while (p_he->h_addr_list[addresses])
+        addresses++;
+
+    p_to = create_hostent( p_he->h_name, i + 1, alias_size, addresses + 1, p_he->h_length );
+
+    if (!p_to) return NULL;
+    p_to->h_addrtype = convert_af_u2w( p_he->h_addrtype );
+    p_to->h_length = p_he->h_length;
+
+    for (i = 0, p = p_to->h_addr_list[0]; p_he->h_addr_list[i]; i++, p += p_to->h_length)
+        memcpy( p, p_he->h_addr_list[i], p_to->h_length );
+
+    /* Fill the aliases after the IP data */
+    for (i = 0; p_he->h_aliases[i]; i++)
+    {
+        p_to->h_aliases[i] = p;
+        strcpy( p, p_he->h_aliases[i] );
+        p += strlen(p) + 1;
+    }
+
+    return p_to;
+}
+
+
+/***********************************************************************
+ *      gethostbyaddr   (ws2_32.51)
+ */
+struct WS_hostent * WINAPI WS_gethostbyaddr( const char *addr, int len, int type )
+{
+    struct WS_hostent *retval = NULL;
+    struct hostent *host;
+    int unixtype = convert_af_w2u(type);
+    const char *paddr = addr;
+    unsigned long loopback;
+#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
+    char *extrabuf;
+    int ebufsize = 1024;
+    struct hostent hostentry;
+    int locerr = ENOBUFS;
+#endif
+
+    /* convert back the magic loopback address if necessary */
+    if (unixtype == AF_INET && len == 4 && !memcmp( addr, magic_loopback_addr, 4 ))
+    {
+        loopback = htonl( INADDR_LOOPBACK );
+        paddr = (char *)&loopback;
+    }
+
+#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
+    host = NULL;
+    extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize );
+    while (extrabuf)
+    {
+        int res = gethostbyaddr_r( paddr, len, unixtype, &hostentry, extrabuf, ebufsize, &host, &locerr );
+        if (res != ERANGE) break;
+        ebufsize *= 2;
+        extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize );
+    }
+    if (host)
+        retval = hostent_from_unix( host );
+    else
+        SetLastError( (locerr < 0) ? sock_get_error( errno ) : host_errno_from_unix( locerr ) );
+    HeapFree( GetProcessHeap(), 0, extrabuf );
+#else
+    EnterCriticalSection( &csWSgetXXXbyYYY );
+    host = gethostbyaddr( paddr, len, unixtype );
+    if (host)
+        retval = hostent_from_unix( host );
+    else
+        SetLastError( (h_errno < 0) ? sock_get_error( errno ) : host_errno_from_unix( h_errno ) );
+    LeaveCriticalSection( &csWSgetXXXbyYYY );
+#endif
+
+    TRACE( "ptr %p, len %d, type %d ret %p\n", addr, len, type, retval );
+    return retval;
+}
+
+
+struct route
+{
+    struct in_addr addr;
+    IF_INDEX interface;
+    DWORD metric, default_route;
+};
+
+static int compare_routes_by_metric_asc( const void *left, const void *right )
+{
+    const struct route *a = left, *b = right;
+    if (a->default_route && b->default_route)
+        return a->default_route - b->default_route;
+    if (a->default_route && !b->default_route)
+        return -1;
+    if (b->default_route && !a->default_route)
+        return 1;
+    return a->metric - b->metric;
+}
+
+/* Returns the list of local IP addresses by going through the network
+ * adapters and using the local routing table to sort the addresses
+ * from highest routing priority to lowest routing priority. This
+ * functionality is inferred from the description for obtaining local
+ * IP addresses given in the Knowledge Base Article Q160215.
+ *
+ * Please note that the returned hostent is only freed when the thread
+ * closes and is replaced if another hostent is requested.
+ */
+static struct WS_hostent *get_local_ips( char *hostname )
+{
+    int numroutes = 0, i, j, default_routes = 0;
+    IP_ADAPTER_INFO *adapters = NULL, *k;
+    struct WS_hostent *hostlist = NULL;
+    MIB_IPFORWARDTABLE *routes = NULL;
+    struct route *route_addrs = NULL;
+    DWORD adap_size, route_size, n;
+
+    /* Obtain the size of the adapter list and routing table, also allocate memory */
+    if (GetAdaptersInfo( NULL, &adap_size ) != ERROR_BUFFER_OVERFLOW)
+        return NULL;
+    if (GetIpForwardTable( NULL, &route_size, FALSE ) != ERROR_INSUFFICIENT_BUFFER)
+        return NULL;
+
+    adapters = HeapAlloc( GetProcessHeap(), 0, adap_size );
+    routes = HeapAlloc( GetProcessHeap(), 0, route_size );
+    if (!adapters || !routes)
+        goto cleanup;
+
+    /* Obtain the adapter list and the full routing table */
+    if (GetAdaptersInfo( adapters, &adap_size ) != NO_ERROR)
+        goto cleanup;
+    if (GetIpForwardTable( routes, &route_size, FALSE ) != NO_ERROR)
+        goto cleanup;
+
+    /* Store the interface associated with each route */
+    for (n = 0; n < routes->dwNumEntries; n++)
+    {
+        IF_INDEX ifindex;
+        DWORD ifmetric, ifdefault = 0;
+        BOOL exists = FALSE;
+
+        /* Check if this is a default route (there may be more than one) */
+        if (!routes->table[n].dwForwardDest)
+            ifdefault = ++default_routes;
+        else if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
+            continue;
+        ifindex = routes->table[n].dwForwardIfIndex;
+        ifmetric = routes->table[n].dwForwardMetric1;
+        /* Only store the lowest valued metric for an interface */
+        for (j = 0; j < numroutes; j++)
+        {
+            if (route_addrs[j].interface == ifindex)
+            {
+                if (route_addrs[j].metric > ifmetric)
+                    route_addrs[j].metric = ifmetric;
+                exists = TRUE;
+            }
+        }
+        if (exists)
+            continue;
+        route_addrs = heap_realloc( route_addrs, (numroutes + 1) * sizeof(struct route) );
+        if (!route_addrs)
+            goto cleanup;
+        route_addrs[numroutes].interface = ifindex;
+        route_addrs[numroutes].metric = ifmetric;
+        route_addrs[numroutes].default_route = ifdefault;
+        /* If no IP is found in the next step (for whatever reason)
+         * then fall back to the magic loopback address.
+         */
+        memcpy( &route_addrs[numroutes].addr.s_addr, magic_loopback_addr, 4 );
+        numroutes++;
+    }
+    if (numroutes == 0)
+       goto cleanup; /* No routes, fall back to the Magic IP */
+
+    /* Find the IP address associated with each found interface */
+    for (i = 0; i < numroutes; i++)
+    {
+        for (k = adapters; k != NULL; k = k->Next)
+        {
+            char *ip = k->IpAddressList.IpAddress.String;
+
+            if (route_addrs[i].interface == k->Index)
+                route_addrs[i].addr.s_addr = inet_addr(ip);
+        }
+    }
+
+    /* Allocate a hostent and enough memory for all the IPs,
+     * including the NULL at the end of the list.
+     */
+    hostlist = create_hostent( hostname, 1, 0, numroutes+1, sizeof(struct in_addr) );
+    if (hostlist == NULL)
+        goto cleanup;
+    hostlist->h_addr_list[numroutes] = NULL;
+    hostlist->h_aliases[0] = NULL;
+    hostlist->h_addrtype = AF_INET;
+    hostlist->h_length = sizeof(struct in_addr);
+
+    /* Reorder the entries before placing them in the host list. Windows expects
+     * the IP list in order from highest priority to lowest (the critical thing
+     * is that most applications expect the first IP to be the default route).
+     */
+    if (numroutes > 1)
+        qsort( route_addrs, numroutes, sizeof(struct route), compare_routes_by_metric_asc );
+
+    for (i = 0; i < numroutes; i++)
+        *(struct in_addr *)hostlist->h_addr_list[i] = route_addrs[i].addr;
+
+cleanup:
+    HeapFree( GetProcessHeap(), 0, route_addrs );
+    HeapFree( GetProcessHeap(), 0, adapters );
+    HeapFree( GetProcessHeap(), 0, routes );
+    return hostlist;
+}
+
+
+/***********************************************************************
+ *      gethostbyname   (ws2_32.52)
+ */
+struct WS_hostent * WINAPI WS_gethostbyname( const char *name )
+{
+    struct WS_hostent *retval = NULL;
+    struct hostent *host;
+#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
+    char *extrabuf;
+    int ebufsize = 1024;
+    struct hostent hostentry;
+    int locerr = ENOBUFS;
+#endif
+    char hostname[100];
+
+    if (!num_startup)
+    {
+        SetLastError( WSANOTINITIALISED );
+        return NULL;
+    }
+
+    if (gethostname( hostname, 100 ) == -1)
+    {
+        SetLastError( WSAENOBUFS );
+        return retval;
+    }
+
+    if (!name || !name[0])
+        name = hostname;
+
+    /* If the hostname of the local machine is requested then return the
+     * complete list of local IP addresses */
+    if (!strcmp( name, hostname ))
+        retval = get_local_ips( hostname );
+
+    /* If any other hostname was requested (or the routing table lookup failed)
+     * then return the IP found by the host OS */
+    if (!retval)
+    {
+#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
+        host = NULL;
+        extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize );
+        while (extrabuf)
+        {
+            int res = gethostbyname_r( name, &hostentry, extrabuf, ebufsize, &host, &locerr );
+            if (res != ERANGE) break;
+            ebufsize *= 2;
+            extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize );
+        }
+        if (!host) SetLastError( (locerr < 0) ? sock_get_error( errno ) : host_errno_from_unix( locerr ) );
+#else
+        EnterCriticalSection( &csWSgetXXXbyYYY );
+        host = gethostbyname( name );
+        if (!host) SetLastError( (h_errno < 0) ? sock_get_error( errno ) : host_errno_from_unix( h_errno ) );
+#endif
+        if (host) retval = hostent_from_unix( host );
+#ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
+        HeapFree( GetProcessHeap(), 0, extrabuf );
+#else
+        LeaveCriticalSection( &csWSgetXXXbyYYY );
+#endif
+    }
+
+    if (retval && retval->h_addr_list[0][0] == 127 && strcmp( name, "localhost" ))
+    {
+        /* hostname != "localhost" but has loopback address. replace by our
+         * special address.*/
+        memcpy( retval->h_addr_list[0], magic_loopback_addr, 4 );
+    }
+
+    TRACE( "%s ret %p\n", debugstr_a(name), retval );
+    return retval;
+}
+
+
+/***********************************************************************
+ *      gethostname   (ws2_32.57)
+ */
+int WINAPI WS_gethostname( char *name, int namelen )
+{
+    char buf[256];
+    int len;
+
+    TRACE( "name %p, len %d\n", name, namelen );
+
+    if (!name)
+    {
+        SetLastError( WSAEFAULT );
+        return -1;
+    }
+
+    if (gethostname( buf, sizeof(buf) ) != 0)
+    {
+        SetLastError( sock_get_error( errno ) );
+        return -1;
+    }
+
+    TRACE( "<- %s\n", debugstr_a(buf) );
+    len = strlen( buf );
+    if (len > 15)
+        WARN( "Windows supports NetBIOS name length up to 15 bytes!\n" );
+    if (namelen <= len)
+    {
+        SetLastError( WSAEFAULT );
+        return -1;
+    }
+    strcpy( name, buf );
+    return 0;
+}
+
+
+/***********************************************************************
+ *      GetHostNameW   (ws2_32.@)
+ */
+int WINAPI GetHostNameW( WCHAR *name, int namelen )
+{
+    char buf[256];
+
+    TRACE( "name %p, len %d\n", name, namelen );
+
+    if (!name)
+    {
+        SetLastError( WSAEFAULT );
+        return -1;
+    }
+
+    if (gethostname( buf, sizeof(buf) ))
+    {
+        SetLastError( sock_get_error( errno ) );
+        return -1;
+    }
+
+    if (MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 ) > namelen)
+    {
+        SetLastError( WSAEFAULT );
+        return -1;
+    }
+    MultiByteToWideChar( CP_ACP, 0, buf, -1, name, namelen );
+    return 0;
+}
+
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 9e48fe256fd..7313741e4b1 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -225,13 +225,6 @@ static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
                           LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
                           LPWSABUF lpControlBuffer );
 
-#define DECLARE_CRITICAL_SECTION(cs) \
-    static CRITICAL_SECTION cs; \
-    static CRITICAL_SECTION_DEBUG cs##_debug = \
-    { 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \
-      0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
-    static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 }
-
 DECLARE_CRITICAL_SECTION(csWSgetXXXbyYYY);
 DECLARE_CRITICAL_SECTION(cs_if_addr_cache);
 DECLARE_CRITICAL_SECTION(cs_socket_list);
@@ -618,35 +611,10 @@ typedef struct          /* WSAAsyncSelect() control struct */
 #define WS_MAX_UDP_DATAGRAM             1024
 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
 
-/* hostent's, servent's and protent's are stored in one buffer per thread,
- * as documented on MSDN for the functions that return any of the buffers */
-struct per_thread_data
-{
-    int opentype;
-    struct WS_hostent *he_buffer;
-    struct WS_servent *se_buffer;
-    struct WS_protoent *pe_buffer;
-    struct pollfd *fd_cache;
-    unsigned int fd_count;
-    int he_len;
-    int se_len;
-    int pe_len;
-    char ntoa_buffer[16]; /* 4*3 digits + 3 '.' + 1 '\0' */
-};
-
-/* internal: routing description information */
-struct route {
-    struct in_addr addr;
-    IF_INDEX interface;
-    DWORD metric, default_route;
-};
-
-static INT num_startup;          /* reference counter */
+int num_startup;
 static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
 
 /* function prototypes */
-static struct WS_hostent *WS_create_he(char *name, int aliases, int aliases_size, int addresses, int address_length);
-static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
 static struct WS_protoent *WS_create_pe( const char *name, char **aliases, int prot );
 static struct WS_servent *WS_dup_se(const struct servent* p_se);
 static int ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size);
@@ -741,20 +709,6 @@ static const int ws_ipv6_map[][2] =
 #endif
 };
 
-static const int ws_af_map[][2] =
-{
-    MAP_OPTION( AF_UNSPEC ),
-    MAP_OPTION( AF_INET ),
-    MAP_OPTION( AF_INET6 ),
-#ifdef HAS_IPX
-    MAP_OPTION( AF_IPX ),
-#endif
-#ifdef AF_IRDA
-    MAP_OPTION( AF_IRDA ),
-#endif
-    {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
-};
-
 static const int ws_socktype_map[][2] =
 {
     MAP_OPTION( SOCK_DGRAM ),
@@ -783,8 +737,6 @@ static const int ws_poll_map[][2] =
     { WS_POLLRDBAND, POLLPRI }
 };
 
-static const char magic_loopback_addr[] = {127, 12, 34, 56};
-
 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
 static inline WSACMSGHDR *fill_control_message(int level, int type, WSACMSGHDR *current, ULONG *maxsize, void *data, int len)
@@ -1003,25 +955,6 @@ static NTSTATUS wsaErrStatus(void)
     return sock_get_ntstatus(loc_errno);
 }
 
-static UINT wsaHerrno(int loc_errno)
-{
-    WARN("h_errno %d.\n", loc_errno);
-
-    switch(loc_errno)
-    {
-	case HOST_NOT_FOUND:	return WSAHOST_NOT_FOUND;
-	case TRY_AGAIN:		return WSATRY_AGAIN;
-	case NO_RECOVERY:	return WSANO_RECOVERY;
-	case NO_DATA:		return WSANO_DATA;
-	case ENOBUFS:		return WSAENOBUFS;
-
-	case 0:			return 0;
-	default:
-		WARN("Unknown h_errno %d!\n", loc_errno);
-		return WSAEOPNOTSUPP;
-    }
-}
-
 static NTSTATUS sock_error_to_ntstatus( DWORD err )
 {
     switch (err)
@@ -1298,7 +1231,7 @@ static BOOL get_dont_fragment(SOCKET s, int level, BOOL *out)
     return value;
 }
 
-static struct per_thread_data *get_per_thread_data(void)
+struct per_thread_data *get_per_thread_data(void)
 {
     struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
     /* lazy initialization */
@@ -1486,28 +1419,6 @@ static inline int do_block( int fd, int events, int timeout )
   return pfd.revents;
 }
 
-int
-convert_af_w2u(int windowsaf) {
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
-    	if (ws_af_map[i][0] == windowsaf)
-	    return ws_af_map[i][1];
-    FIXME("unhandled Windows address family %d\n", windowsaf);
-    return -1;
-}
-
-int
-convert_af_u2w(int unixaf) {
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
-    	if (ws_af_map[i][1] == unixaf)
-	    return ws_af_map[i][0];
-    FIXME("unhandled UNIX address family %d\n", unixaf);
-    return -1;
-}
-
 int
 convert_socktype_w2u(int windowssocktype) {
     unsigned int i;
@@ -1669,19 +1580,6 @@ void WINAPI WSASetLastError(INT iError) {
     SetLastError(iError);
 }
 
-static struct WS_hostent *check_buffer_he(int size)
-{
-    struct per_thread_data * ptb = get_per_thread_data();
-    if (ptb->he_buffer)
-    {
-        if (ptb->he_len >= size ) return ptb->he_buffer;
-        HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
-    }
-    ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
-    if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
-    return ptb->he_buffer;
-}
-
 static struct WS_servent *check_buffer_se(int size)
 {
     struct per_thread_data * ptb = get_per_thread_data();
@@ -5854,256 +5752,6 @@ SOCKET WINAPI WS_socket(int af, int type, int protocol)
 }
 
 
-/***********************************************************************
- *		gethostbyaddr		(WS2_32.51)
- */
-struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
-{
-    struct WS_hostent *retval = NULL;
-    struct hostent* host;
-    int unixtype = convert_af_w2u(type);
-    const char *paddr = addr;
-    unsigned long loopback;
-#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
-    char *extrabuf;
-    int ebufsize = 1024;
-    struct hostent hostentry;
-    int locerr = ENOBUFS;
-#endif
-
-    /* convert back the magic loopback address if necessary */
-    if (unixtype == AF_INET && len == 4 && !memcmp(addr, magic_loopback_addr, 4))
-    {
-        loopback = htonl(INADDR_LOOPBACK);
-        paddr = (char*) &loopback;
-    }
-
-#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
-    host = NULL;
-    extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
-    while(extrabuf) {
-        int res = gethostbyaddr_r(paddr, len, unixtype,
-                                  &hostentry, extrabuf, ebufsize, &host, &locerr);
-        if (res != ERANGE) break;
-        ebufsize *=2;
-        extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
-    }
-    if (host) retval = WS_dup_he(host);
-    else SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
-    HeapFree(GetProcessHeap(),0,extrabuf);
-#else
-    EnterCriticalSection( &csWSgetXXXbyYYY );
-    host = gethostbyaddr(paddr, len, unixtype);
-    if (host) retval = WS_dup_he(host);
-    else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
-    LeaveCriticalSection( &csWSgetXXXbyYYY );
-#endif
-    TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
-    return retval;
-}
-
-/***********************************************************************
- *		WS_compare_routes_by_metric_asc (INTERNAL)
- *
- * Comparison function for qsort(), for sorting two routes (struct route)
- * by metric in ascending order.
- */
-static int WS_compare_routes_by_metric_asc(const void *left, const void *right)
-{
-    const struct route *a = left, *b = right;
-    if (a->default_route && b->default_route)
-        return a->default_route - b->default_route;
-    if (a->default_route && !b->default_route)
-        return -1;
-    if (b->default_route && !a->default_route)
-        return 1;
-    return a->metric - b->metric;
-}
-
-/***********************************************************************
- *		WS_get_local_ips		(INTERNAL)
- *
- * Returns the list of local IP addresses by going through the network
- * adapters and using the local routing table to sort the addresses
- * from highest routing priority to lowest routing priority. This
- * functionality is inferred from the description for obtaining local
- * IP addresses given in the Knowledge Base Article Q160215.
- *
- * Please note that the returned hostent is only freed when the thread
- * closes and is replaced if another hostent is requested.
- */
-static struct WS_hostent* WS_get_local_ips( char *hostname )
-{
-    int numroutes = 0, i, j, default_routes = 0;
-    DWORD n;
-    PIP_ADAPTER_INFO adapters = NULL, k;
-    struct WS_hostent *hostlist = NULL;
-    PMIB_IPFORWARDTABLE routes = NULL;
-    struct route *route_addrs = NULL;
-    DWORD adap_size, route_size;
-
-    /* Obtain the size of the adapter list and routing table, also allocate memory */
-    if (GetAdaptersInfo(NULL, &adap_size) != ERROR_BUFFER_OVERFLOW)
-        return NULL;
-    if (GetIpForwardTable(NULL, &route_size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
-        return NULL;
-    adapters = HeapAlloc(GetProcessHeap(), 0, adap_size);
-    routes = HeapAlloc(GetProcessHeap(), 0, route_size);
-    if (adapters == NULL || routes == NULL)
-        goto cleanup;
-    /* Obtain the adapter list and the full routing table */
-    if (GetAdaptersInfo(adapters, &adap_size) != NO_ERROR)
-        goto cleanup;
-    if (GetIpForwardTable(routes, &route_size, FALSE) != NO_ERROR)
-        goto cleanup;
-    /* Store the interface associated with each route */
-    for (n = 0; n < routes->dwNumEntries; n++)
-    {
-        IF_INDEX ifindex;
-        DWORD ifmetric, ifdefault = 0;
-        BOOL exists = FALSE;
-
-        /* Check if this is a default route (there may be more than one) */
-        if (!routes->table[n].dwForwardDest)
-            ifdefault = ++default_routes;
-        else if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
-            continue;
-        ifindex = routes->table[n].dwForwardIfIndex;
-        ifmetric = routes->table[n].dwForwardMetric1;
-        /* Only store the lowest valued metric for an interface */
-        for (j = 0; j < numroutes; j++)
-        {
-            if (route_addrs[j].interface == ifindex)
-            {
-                if (route_addrs[j].metric > ifmetric)
-                    route_addrs[j].metric = ifmetric;
-                exists = TRUE;
-            }
-        }
-        if (exists)
-            continue;
-        route_addrs = heap_realloc(route_addrs, (numroutes+1)*sizeof(struct route));
-        if (route_addrs == NULL)
-            goto cleanup; /* Memory allocation error, fail gracefully */
-        route_addrs[numroutes].interface = ifindex;
-        route_addrs[numroutes].metric = ifmetric;
-        route_addrs[numroutes].default_route = ifdefault;
-        /* If no IP is found in the next step (for whatever reason)
-         * then fall back to the magic loopback address.
-         */
-        memcpy(&(route_addrs[numroutes].addr.s_addr), magic_loopback_addr, 4);
-        numroutes++;
-    }
-    if (numroutes == 0)
-       goto cleanup; /* No routes, fall back to the Magic IP */
-    /* Find the IP address associated with each found interface */
-    for (i = 0; i < numroutes; i++)
-    {
-        for (k = adapters; k != NULL; k = k->Next)
-        {
-            char *ip = k->IpAddressList.IpAddress.String;
-
-            if (route_addrs[i].interface == k->Index)
-                route_addrs[i].addr.s_addr = (in_addr_t) inet_addr(ip);
-        }
-    }
-    /* Allocate a hostent and enough memory for all the IPs,
-     * including the NULL at the end of the list.
-     */
-    hostlist = WS_create_he(hostname, 1, 0, numroutes+1, sizeof(struct in_addr));
-    if (hostlist == NULL)
-        goto cleanup; /* Failed to allocate a hostent for the list of IPs */
-    hostlist->h_addr_list[numroutes] = NULL; /* NULL-terminate the address list */
-    hostlist->h_aliases[0] = NULL; /* NULL-terminate the alias list */
-    hostlist->h_addrtype = AF_INET;
-    hostlist->h_length = sizeof(struct in_addr); /* = 4 */
-    /* Reorder the entries before placing them in the host list. Windows expects
-     * the IP list in order from highest priority to lowest (the critical thing
-     * is that most applications expect the first IP to be the default route).
-     */
-    if (numroutes > 1)
-        qsort(route_addrs, numroutes, sizeof(struct route), WS_compare_routes_by_metric_asc);
-
-    for (i = 0; i < numroutes; i++)
-        (*(struct in_addr *) hostlist->h_addr_list[i]) = route_addrs[i].addr;
-
-    /* Cleanup all allocated memory except the address list,
-     * the address list is used by the calling app.
-     */
-cleanup:
-    HeapFree(GetProcessHeap(), 0, route_addrs);
-    HeapFree(GetProcessHeap(), 0, adapters);
-    HeapFree(GetProcessHeap(), 0, routes);
-    return hostlist;
-}
-
-/***********************************************************************
- *		gethostbyname		(WS2_32.52)
- */
-struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
-{
-    struct WS_hostent *retval = NULL;
-    struct hostent*     host;
-#ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
-    char *extrabuf;
-    int ebufsize=1024;
-    struct hostent hostentry;
-    int locerr = ENOBUFS;
-#endif
-    char hostname[100];
-    if(!num_startup) {
-        SetLastError(WSANOTINITIALISED);
-        return NULL;
-    }
-    if( gethostname( hostname, 100) == -1) {
-        SetLastError(WSAENOBUFS); /* appropriate ? */
-        return retval;
-    }
-    if( !name || !name[0]) {
-        name = hostname;
-    }
-    /* If the hostname of the local machine is requested then return the
-     * complete list of local IP addresses */
-    if(strcmp(name, hostname) == 0)
-        retval = WS_get_local_ips(hostname);
-    /* If any other hostname was requested (or the routing table lookup failed)
-     * then return the IP found by the host OS */
-    if(retval == NULL)
-    {
-#ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
-        host = NULL;
-        extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
-        while(extrabuf) {
-            int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
-            if( res != ERANGE) break;
-            ebufsize *=2;
-            extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
-        }
-        if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
-#else
-        EnterCriticalSection( &csWSgetXXXbyYYY );
-        host = gethostbyname(name);
-        if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
-#endif
-        if (host) retval = WS_dup_he(host);
-#ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
-        HeapFree(GetProcessHeap(),0,extrabuf);
-#else
-        LeaveCriticalSection( &csWSgetXXXbyYYY );
-#endif
-    }
-    if (retval && retval->h_addr_list[0][0] == 127 &&
-        strcmp(name, "localhost") != 0)
-    {
-        /* hostname != "localhost" but has loopback address. replace by our
-         * special address.*/
-        memcpy(retval->h_addr_list[0], magic_loopback_addr, 4);
-    }
-    TRACE( "%s ret %p\n", debugstr_a(name), retval );
-    return retval;
-}
-
-
 static const struct { int prot; const char *names[3]; } protocols[] =
 {
     {   0, { "ip", "IP" }},
@@ -6303,77 +5951,6 @@ struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
 }
 
 
-/***********************************************************************
- *              gethostname           (WS2_32.57)
- */
-int WINAPI WS_gethostname(char *name, int namelen)
-{
-    char buf[256];
-    int len;
-
-    TRACE("name %p, len %d\n", name, namelen);
-
-    if (!name)
-    {
-        SetLastError(WSAEFAULT);
-        return SOCKET_ERROR;
-    }
-
-    if (gethostname(buf, sizeof(buf)) != 0)
-    {
-        SetLastError(wsaErrno());
-        return SOCKET_ERROR;
-    }
-
-    TRACE("<- '%s'\n", buf);
-    len = strlen(buf);
-    if (len > 15)
-        WARN("Windows supports NetBIOS name length up to 15 bytes!\n");
-    if (namelen <= len)
-    {
-        SetLastError(WSAEFAULT);
-        WARN("<- not enough space for hostname, required %d, got %d!\n", len + 1, namelen);
-        return SOCKET_ERROR;
-    }
-    strcpy(name, buf);
-    return 0;
-}
-
-/***********************************************************************
- *              GetHostNameW           (WS2_32.@)
- */
-int WINAPI GetHostNameW(WCHAR *name, int namelen)
-{
-    char buf[256];
-    int len;
-
-    TRACE("name %p, len %d\n", name, namelen);
-
-    if (!name)
-    {
-        SetLastError(WSAEFAULT);
-        return SOCKET_ERROR;
-    }
-
-    if (gethostname(buf, sizeof(buf)))
-    {
-        SetLastError(wsaErrno());
-        return SOCKET_ERROR;
-    }
-
-    if ((len = MultiByteToWideChar(CP_ACP, 0, buf, -1, NULL, 0)) > namelen)
-    {
-        SetLastError(WSAEFAULT);
-        return SOCKET_ERROR;
-    }
-    MultiByteToWideChar(CP_ACP, 0, buf, -1, name, namelen);
-    return 0;
-}
-
-/* ------------------------------------- Windows sockets extensions -- *
- *								       *
- * ------------------------------------------------------------------- */
-
 /***********************************************************************
  *		WSAEnumNetworkEvents (WS2_32.36)
  */
@@ -6815,95 +6392,6 @@ static int list_dup(char** l_src, char** l_to, int item_size)
    return p - (char *)l_to;
 }
 
-/* ----- hostent */
-
-/* create a hostent entry
- *
- * Creates the entry with enough memory for the name, aliases
- * addresses, and the address pointers.  Also copies the name
- * and sets up all the pointers.
- *
- * NOTE: The alias and address lists must be allocated with room
- * for the NULL item terminating the list.  This is true even if
- * the list has no items ("aliases" and "addresses" must be
- * at least "1", a truly empty list is invalid).
- */
-static struct WS_hostent *WS_create_he(char *name, int aliases, int aliases_size, int addresses, int address_length)
-{
-    struct WS_hostent *p_to;
-    char *p;
-    int size = (sizeof(struct WS_hostent) +
-                strlen(name) + 1 +
-                sizeof(char *) * aliases +
-                aliases_size +
-                sizeof(char *) * addresses +
-                address_length * (addresses - 1)), i;
-
-    if (!(p_to = check_buffer_he(size))) return NULL;
-    memset(p_to, 0, size);
-
-    /* Use the memory in the same way winsock does.
-     * First set the pointer for aliases, second set the pointers for addresses.
-     * Third fill the addresses indexes, fourth jump aliases names size.
-     * Fifth fill the hostname.
-     * NOTE: This method is valid for OS versions >= XP.
-     */
-    p = (char *)(p_to + 1);
-    p_to->h_aliases = (char **)p;
-    p += sizeof(char *)*aliases;
-
-    p_to->h_addr_list = (char **)p;
-    p += sizeof(char *)*addresses;
-
-    for (i = 0, addresses--; i < addresses; i++, p += address_length)
-        p_to->h_addr_list[i] = p;
-
-    /* NOTE: h_aliases must be filled in manually because we don't know each string
-     * size, leave these pointers NULL (already set to NULL by memset earlier).
-     */
-    p += aliases_size;
-
-    p_to->h_name = p;
-    strcpy(p, name);
-
-    return p_to;
-}
-
-/* duplicate hostent entry
- * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
- * Ditto for protoent and servent.
- */
-static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
-{
-    int i, addresses = 0, alias_size = 0;
-    struct WS_hostent *p_to;
-    char *p;
-
-    for( i = 0; p_he->h_aliases[i]; i++) alias_size += strlen(p_he->h_aliases[i]) + 1;
-    while (p_he->h_addr_list[addresses]) addresses++;
-
-    p_to = WS_create_he(p_he->h_name, i + 1, alias_size, addresses + 1, p_he->h_length);
-
-    if (!p_to) return NULL;
-    p_to->h_addrtype = convert_af_u2w(p_he->h_addrtype);
-    p_to->h_length = p_he->h_length;
-
-    for(i = 0, p = p_to->h_addr_list[0]; p_he->h_addr_list[i]; i++, p += p_to->h_length)
-        memcpy(p, p_he->h_addr_list[i], p_to->h_length);
-
-    /* Fill the aliases after the IP data */
-    for(i = 0; p_he->h_aliases[i]; i++)
-    {
-        p_to->h_aliases[i] = p;
-        strcpy(p, p_he->h_aliases[i]);
-        p += strlen(p) + 1;
-    }
-
-    return p_to;
-}
-
-/* ----- protoent */
-
 static struct WS_protoent *WS_create_pe( const char *name, char **aliases, int prot )
 {
     struct WS_protoent *ret;
diff --git a/dlls/ws2_32/ws2_32_private.h b/dlls/ws2_32/ws2_32_private.h
index 8af23b11ded..121ce25ad1d 100644
--- a/dlls/ws2_32/ws2_32_private.h
+++ b/dlls/ws2_32/ws2_32_private.h
@@ -152,8 +152,15 @@
 #include "wine/unicode.h"
 #include "wine/heap.h"
 
-int convert_af_u2w( int family ) DECLSPEC_HIDDEN;
-int convert_af_w2u( int family ) DECLSPEC_HIDDEN;
+#define DECLARE_CRITICAL_SECTION(cs) \
+    static CRITICAL_SECTION cs; \
+    static CRITICAL_SECTION_DEBUG cs##_debug = \
+    { 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \
+      0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
+    static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 }
+
+static const char magic_loopback_addr[] = {127, 12, 34, 56};
+
 int convert_eai_u2w( int ret ) DECLSPEC_HIDDEN;
 int convert_socktype_u2w( int type ) DECLSPEC_HIDDEN;
 int convert_socktype_w2u( int type ) DECLSPEC_HIDDEN;
@@ -164,4 +171,22 @@ const char *debugstr_sockaddr( const struct WS_sockaddr *addr ) DECLSPEC_HIDDEN;
 
 UINT sock_get_error( int err ) DECLSPEC_HIDDEN;
 
+struct per_thread_data
+{
+    int opentype;
+    struct WS_hostent *he_buffer;
+    struct WS_servent *se_buffer;
+    struct WS_protoent *pe_buffer;
+    struct pollfd *fd_cache;
+    unsigned int fd_count;
+    int he_len;
+    int se_len;
+    int pe_len;
+    char ntoa_buffer[16]; /* 4*3 digits + 3 '.' + 1 '\0' */
+};
+
+extern int num_startup;
+
+struct per_thread_data *get_per_thread_data(void) DECLSPEC_HIDDEN;
+
 #endif
-- 
2.30.2




More information about the wine-devel mailing list