[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