Signed-off-by: Zebediah Figura z.figura12@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
Signed-off-by: Zebediah Figura z.figura12@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
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/protocol.c | 87 ++++++++++++++++++++++++++++++++++++ dlls/ws2_32/socket.c | 83 +--------------------------------- dlls/ws2_32/ws2_32_private.h | 8 ++++ 3 files changed, 97 insertions(+), 81 deletions(-)
diff --git a/dlls/ws2_32/protocol.c b/dlls/ws2_32/protocol.c index 5bbcdee3e0c..ecd564788d7 100644 --- a/dlls/ws2_32/protocol.c +++ b/dlls/ws2_32/protocol.c @@ -854,6 +854,93 @@ void WINAPI FreeAddrInfoExW( ADDRINFOEXW *ai ) }
+static const int ws_niflag_map[][2] = +{ + MAP_OPTION( NI_NOFQDN ), + MAP_OPTION( NI_NUMERICHOST ), + MAP_OPTION( NI_NAMEREQD ), + MAP_OPTION( NI_NUMERICSERV ), + MAP_OPTION( NI_DGRAM ), +}; + +static int convert_niflag_w2u( int winflags ) +{ + unsigned int i; + int unixflags = 0; + + for (i = 0; i < ARRAY_SIZE(ws_niflag_map); i++) + { + if (ws_niflag_map[i][0] & winflags) + { + unixflags |= ws_niflag_map[i][1]; + winflags &= ~ws_niflag_map[i][0]; + } + } + if (winflags) + FIXME("Unhandled windows NI_xxx flags 0x%x\n", winflags); + return unixflags; +} + + +/*********************************************************************** + * getnameinfo (ws2_32.@) + */ +int WINAPI WS_getnameinfo( const SOCKADDR *addr, WS_socklen_t addr_len, char *host, + DWORD host_len, char *serv, DWORD serv_len, int flags ) +{ +#ifdef HAVE_GETNAMEINFO + int ret; + union generic_unix_sockaddr uaddr; + unsigned int uaddr_len; + + TRACE( "addr %s, addr_len %d, host %p, host_len %u, serv %p, serv_len %d, flags %#x\n", + debugstr_sockaddr(addr), addr_len, host, host_len, serv, serv_len, flags ); + + uaddr_len = ws_sockaddr_ws2u( addr, addr_len, &uaddr ); + if (!uaddr_len) + { + SetLastError( WSAEFAULT ); + return WSA_NOT_ENOUGH_MEMORY; + } + ret = getnameinfo( &uaddr.addr, uaddr_len, host, host_len, serv, serv_len, convert_niflag_w2u(flags) ); + return convert_eai_u2w( ret ); +#else + FIXME( "getnameinfo() failed, not found during buildtime.\n" ); + return EAI_FAIL; +#endif +} + + +/*********************************************************************** + * GetNameInfoW (ws2_32.@) + */ +int WINAPI GetNameInfoW( const SOCKADDR *addr, WS_socklen_t addr_len, WCHAR *host, + DWORD host_len, WCHAR *serv, DWORD serv_len, int flags ) +{ + int ret; + char *hostA = NULL, *servA = NULL; + + if (host && (!(hostA = HeapAlloc( GetProcessHeap(), 0, host_len )))) + return EAI_MEMORY; + if (serv && (!(servA = HeapAlloc( GetProcessHeap(), 0, serv_len )))) + { + HeapFree( GetProcessHeap(), 0, hostA ); + return EAI_MEMORY; + } + + ret = WS_getnameinfo( addr, addr_len, hostA, host_len, servA, serv_len, flags ); + if (!ret) + { + if (host) MultiByteToWideChar( CP_ACP, 0, hostA, -1, host, host_len ); + if (serv) MultiByteToWideChar( CP_ACP, 0, servA, -1, serv, serv_len ); + } + + HeapFree( GetProcessHeap(), 0, hostA ); + HeapFree( GetProcessHeap(), 0, servA ); + return ret; +} + + static UINT host_errno_from_unix( int err ) { WARN( "%d\n", err ); diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 7313741e4b1..5ced4720558 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -235,12 +235,6 @@ static unsigned int if_addr_cache_size; static SOCKET *socket_list; static unsigned int socket_list_size;
-union generic_unix_sockaddr -{ - struct sockaddr addr; - char data[128]; /* should be big enough for all families */ -}; - const char *debugstr_sockaddr( const struct WS_sockaddr *a ) { if (!a) return "(nil)"; @@ -717,15 +711,6 @@ static const int ws_socktype_map[][2] = {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO}, };
-static const int ws_niflag_map[][2] = -{ - MAP_OPTION( NI_NOFQDN ), - MAP_OPTION( NI_NUMERICHOST ), - MAP_OPTION( NI_NAMEREQD ), - MAP_OPTION( NI_NUMERICSERV ), - MAP_OPTION( NI_DGRAM ), -}; - static const int ws_poll_map[][2] = { MAP_OPTION( POLLERR ), @@ -1633,8 +1618,8 @@ static inline BOOL supported_pf(int pf) /* Returns the length of the converted address if successful, 0 if it was too * small to start with or unknown family or invalid address buffer. */ -static unsigned int ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, - union generic_unix_sockaddr *uaddr) +unsigned int ws_sockaddr_ws2u( const struct WS_sockaddr *wsaddr, int wsaddrlen, + union generic_unix_sockaddr *uaddr ) { unsigned int uaddrlen = 0;
@@ -5860,70 +5845,6 @@ struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto) return retval; }
-static int convert_niflag_w2u(int winflags) { - unsigned int i; - int unixflags = 0; - - for (i = 0; i < ARRAY_SIZE(ws_niflag_map); i++) - if (ws_niflag_map[i][0] & winflags) { - unixflags |= ws_niflag_map[i][1]; - winflags &= ~ws_niflag_map[i][0]; - } - if (winflags) - FIXME("Unhandled windows NI_xxx flags 0x%x\n", winflags); - return unixflags; -} - -int WINAPI WS_getnameinfo(const SOCKADDR *sa, WS_socklen_t salen, PCHAR host, - DWORD hostlen, PCHAR serv, DWORD servlen, INT flags) -{ -#ifdef HAVE_GETNAMEINFO - int ret; - union generic_unix_sockaddr sa_u; - unsigned int size; - - TRACE("%s %d %p %d %p %d %d\n", debugstr_sockaddr(sa), salen, host, hostlen, - serv, servlen, flags); - - size = ws_sockaddr_ws2u(sa, salen, &sa_u); - if (!size) - { - SetLastError(WSAEFAULT); - return WSA_NOT_ENOUGH_MEMORY; - } - ret = getnameinfo(&sa_u.addr, size, host, hostlen, serv, servlen, convert_niflag_w2u(flags)); - return convert_eai_u2w(ret); -#else - FIXME("getnameinfo() failed, not found during buildtime.\n"); - return EAI_FAIL; -#endif -} - -int WINAPI GetNameInfoW(const SOCKADDR *sa, WS_socklen_t salen, PWCHAR host, - DWORD hostlen, PWCHAR serv, DWORD servlen, INT flags) -{ - int ret; - char *hostA = NULL, *servA = NULL; - - if (host && (!(hostA = HeapAlloc(GetProcessHeap(), 0, hostlen)))) return EAI_MEMORY; - if (serv && (!(servA = HeapAlloc(GetProcessHeap(), 0, servlen)))) - { - HeapFree(GetProcessHeap(), 0, hostA); - return EAI_MEMORY; - } - - ret = WS_getnameinfo(sa, salen, hostA, hostlen, servA, servlen, flags); - if (!ret) - { - if (host) MultiByteToWideChar(CP_ACP, 0, hostA, -1, host, hostlen); - if (serv) MultiByteToWideChar(CP_ACP, 0, servA, -1, serv, servlen); - } - - HeapFree(GetProcessHeap(), 0, hostA); - HeapFree(GetProcessHeap(), 0, servA); - return ret; -} - /*********************************************************************** * getservbyport (WS2_32.56) */ diff --git a/dlls/ws2_32/ws2_32_private.h b/dlls/ws2_32/ws2_32_private.h index 121ce25ad1d..e86a3569510 100644 --- a/dlls/ws2_32/ws2_32_private.h +++ b/dlls/ws2_32/ws2_32_private.h @@ -161,11 +161,19 @@
static const char magic_loopback_addr[] = {127, 12, 34, 56};
+union generic_unix_sockaddr +{ + struct sockaddr addr; + char data[128]; /* should be big enough for all families */ +}; + 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; +unsigned int ws_sockaddr_ws2u( const struct WS_sockaddr *win_addr, int win_addr_len, + union generic_unix_sockaddr *unix_addr ) DECLSPEC_HIDDEN;
const char *debugstr_sockaddr( const struct WS_sockaddr *addr ) DECLSPEC_HIDDEN;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/protocol.c | 143 +++++++++++++++++++++++++++++++++++++++++ dlls/ws2_32/socket.c | 103 ----------------------------- 2 files changed, 143 insertions(+), 103 deletions(-)
diff --git a/dlls/ws2_32/protocol.c b/dlls/ws2_32/protocol.c index ecd564788d7..ad840aaeb6f 100644 --- a/dlls/ws2_32/protocol.c +++ b/dlls/ws2_32/protocol.c @@ -1389,3 +1389,146 @@ int WINAPI GetHostNameW( WCHAR *name, int namelen ) return 0; }
+ +static int list_size( char **list, int item_size ) +{ + int i, size = 0; + if (list) + { + for (i = 0; list[i]; i++) + size += (item_size ? item_size : strlen(list[i]) + 1); + size += (i + 1) * sizeof(char *); + } + return size; +} + +static int list_dup( char **src, char **dst, int item_size ) +{ + char *p; + int i; + + for (i = 0; src[i]; i++) + ; + p = (char *)(dst + i + 1); + + for (i = 0; src[i]; i++) + { + int count = item_size ? item_size : strlen(src[i]) + 1; + memcpy( p, src[i], count ); + dst[i] = p; + p += count; + } + dst[i] = NULL; + return p - (char *)dst; +} + +static const struct +{ + int prot; + const char *names[3]; +} +protocols[] = +{ + { 0, {"ip", "IP"}}, + { 1, {"icmp", "ICMP"}}, + { 3, {"ggp", "GGP"}}, + { 6, {"tcp", "TCP"}}, + { 8, {"egp", "EGP"}}, + {12, {"pup", "PUP"}}, + {17, {"udp", "UDP"}}, + {20, {"hmp", "HMP"}}, + {22, {"xns-idp", "XNS-IDP"}}, + {27, {"rdp", "RDP"}}, + {41, {"ipv6", "IPv6"}}, + {43, {"ipv6-route", "IPv6-Route"}}, + {44, {"ipv6-frag", "IPv6-Frag"}}, + {50, {"esp", "ESP"}}, + {51, {"ah", "AH"}}, + {58, {"ipv6-icmp", "IPv6-ICMP"}}, + {59, {"ipv6-nonxt", "IPv6-NoNxt"}}, + {60, {"ipv6-opts", "IPv6-Opts"}}, + {66, {"rvd", "RVD"}}, +}; + +static struct WS_protoent *get_protoent_buffer( unsigned int size ) +{ + struct per_thread_data *data = get_per_thread_data(); + + if (data->pe_buffer) + { + if (data->pe_len >= size) return data->pe_buffer; + HeapFree( GetProcessHeap(), 0, data->pe_buffer ); + } + data->pe_len = size; + data->pe_buffer = HeapAlloc( GetProcessHeap(), 0, size ); + if (!data->pe_buffer) SetLastError( WSAENOBUFS ); + return data->pe_buffer; +} + +static struct WS_protoent *create_protoent( const char *name, char **aliases, int prot ) +{ + struct WS_protoent *ret; + unsigned int size = sizeof(*ret) + strlen( name ) + sizeof(char *) + list_size( aliases, 0 ); + + if (!(ret = get_protoent_buffer( size ))) return NULL; + ret->p_proto = prot; + ret->p_name = (char *)(ret + 1); + strcpy( ret->p_name, name ); + ret->p_aliases = (char **)ret->p_name + strlen( name ) / sizeof(char *) + 1; + list_dup( aliases, ret->p_aliases, 0 ); + return ret; +} + + +/*********************************************************************** + * getprotobyname (ws2_32.53) + */ +struct WS_protoent * WINAPI WS_getprotobyname( const char *name ) +{ + struct WS_protoent *retval = NULL; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(protocols); i++) + { + if (!_strnicmp( protocols[i].names[0], name, -1 )) + { + retval = create_protoent( protocols[i].names[0], (char **)protocols[i].names + 1, + protocols[i].prot ); + break; + } + } + if (!retval) + { + WARN( "protocol %s not found\n", debugstr_a(name) ); + SetLastError( WSANO_DATA ); + } + TRACE( "%s ret %p\n", debugstr_a(name), retval ); + return retval; +} + + +/*********************************************************************** + * getprotobynumber (ws2_32.54) + */ +struct WS_protoent * WINAPI WS_getprotobynumber( int number ) +{ + struct WS_protoent *retval = NULL; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(protocols); i++) + { + if (protocols[i].prot == number) + { + retval = create_protoent( protocols[i].names[0], (char **)protocols[i].names + 1, + protocols[i].prot ); + break; + } + } + if (!retval) + { + WARN( "protocol %d not found\n", number ); + SetLastError( WSANO_DATA ); + } + TRACE( "%d ret %p\n", number, retval ); + return retval; +} diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 5ced4720558..c3c73568c83 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -609,7 +609,6 @@ int num_startup; static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
/* function prototypes */ -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);
@@ -1578,21 +1577,6 @@ static struct WS_servent *check_buffer_se(int size) return ptb->se_buffer; }
-static struct WS_protoent *check_buffer_pe(int size) -{ - struct per_thread_data * ptb = get_per_thread_data(); - if (ptb->pe_buffer) - { - if (ptb->pe_len >= size ) return ptb->pe_buffer; - HeapFree( GetProcessHeap(), 0, ptb->pe_buffer ); - } - ptb->pe_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->pe_len = size) ); - if (!ptb->pe_buffer) SetLastError(WSAENOBUFS); - return ptb->pe_buffer; -} - -/* ----------------------------------- i/o APIs */ - static inline BOOL supported_pf(int pf) { switch (pf) @@ -5737,79 +5721,6 @@ SOCKET WINAPI WS_socket(int af, int type, int protocol) }
-static const struct { int prot; const char *names[3]; } protocols[] = -{ - { 0, { "ip", "IP" }}, - { 1, { "icmp", "ICMP" }}, - { 3, { "ggp", "GGP" }}, - { 6, { "tcp", "TCP" }}, - { 8, { "egp", "EGP" }}, - { 12, { "pup", "PUP" }}, - { 17, { "udp", "UDP" }}, - { 20, { "hmp", "HMP" }}, - { 22, { "xns-idp", "XNS-IDP" }}, - { 27, { "rdp", "RDP" }}, - { 41, { "ipv6", "IPv6" }}, - { 43, { "ipv6-route", "IPv6-Route" }}, - { 44, { "ipv6-frag", "IPv6-Frag" }}, - { 50, { "esp", "ESP" }}, - { 51, { "ah", "AH" }}, - { 58, { "ipv6-icmp", "IPv6-ICMP" }}, - { 59, { "ipv6-nonxt", "IPv6-NoNxt" }}, - { 60, { "ipv6-opts", "IPv6-Opts" }}, - { 66, { "rvd", "RVD" }}, -}; - -/*********************************************************************** - * getprotobyname (WS2_32.53) - */ -struct WS_protoent* WINAPI WS_getprotobyname(const char* name) -{ - struct WS_protoent* retval = NULL; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(protocols); i++) - { - if (_strnicmp( protocols[i].names[0], name, -1 )) continue; - retval = WS_create_pe( protocols[i].names[0], (char **)protocols[i].names + 1, - protocols[i].prot ); - break; - } - if (!retval) - { - WARN( "protocol %s not found\n", debugstr_a(name) ); - SetLastError(WSANO_DATA); - } - TRACE( "%s ret %p\n", debugstr_a(name), retval ); - return retval; -} - - -/*********************************************************************** - * getprotobynumber (WS2_32.54) - */ -struct WS_protoent* WINAPI WS_getprotobynumber(int number) -{ - struct WS_protoent* retval = NULL; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(protocols); i++) - { - if (protocols[i].prot != number) continue; - retval = WS_create_pe( protocols[i].names[0], (char **)protocols[i].names + 1, - protocols[i].prot ); - break; - } - if (!retval) - { - WARN( "protocol %d not found\n", number ); - SetLastError(WSANO_DATA); - } - TRACE("%i ret %p\n", number, retval); - return retval; -} - - /*********************************************************************** * getservbyname (WS2_32.55) */ @@ -6313,20 +6224,6 @@ static int list_dup(char** l_src, char** l_to, int item_size) return p - (char *)l_to; }
-static struct WS_protoent *WS_create_pe( const char *name, char **aliases, int prot ) -{ - struct WS_protoent *ret; - unsigned int size = sizeof(*ret) + strlen(name) + sizeof(char *) + list_size(aliases, 0); - - if (!(ret = check_buffer_pe( size ))) return NULL; - ret->p_proto = prot; - ret->p_name = (char *)(ret + 1); - strcpy( ret->p_name, name ); - ret->p_aliases = (char **)ret->p_name + strlen(name) / sizeof(char *) + 1; - list_dup( aliases, ret->p_aliases, 0 ); - return ret; -} - /* ----- servent */
static struct WS_servent *WS_dup_se(const struct servent* p_se)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=89687
Your paranoid android.
=== debiant2 (32 bit Chinese:China report) ===
ws2_32: sock.c:4168: Test succeeded inside todo block: expected timeout sock.c:4269: Test succeeded inside todo block: expected timeout sock.c:4274: Test succeeded inside todo block: expected timeout
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/protocol.c | 121 +++++++++++++++++++++++++++++++ dlls/ws2_32/socket.c | 160 ----------------------------------------- 2 files changed, 121 insertions(+), 160 deletions(-)
diff --git a/dlls/ws2_32/protocol.c b/dlls/ws2_32/protocol.c index ad840aaeb6f..2cb6ef4be1c 100644 --- a/dlls/ws2_32/protocol.c +++ b/dlls/ws2_32/protocol.c @@ -1532,3 +1532,124 @@ struct WS_protoent * WINAPI WS_getprotobynumber( int number ) TRACE( "%d ret %p\n", number, retval ); return retval; } + + +static char *strdup_lower( const char *str ) +{ + char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 ); + int i; + + if (ret) + { + for (i = 0; str[i]; i++) ret[i] = tolower( str[i] ); + ret[i] = 0; + } + else SetLastError( WSAENOBUFS ); + return ret; +} + +static struct WS_servent *get_servent_buffer( int size ) +{ + struct per_thread_data *data = get_per_thread_data(); + if (data->se_buffer) + { + if (data->se_len >= size) return data->se_buffer; + HeapFree( GetProcessHeap(), 0, data->se_buffer ); + } + data->se_len = size; + data->se_buffer = HeapAlloc( GetProcessHeap(), 0, size ); + if (!data->se_buffer) SetLastError( WSAENOBUFS ); + return data->se_buffer; +} + +static struct WS_servent *servent_from_unix( const struct servent *p_se ) +{ + char *p; + struct WS_servent *p_to; + + int size = (sizeof(*p_se) + + strlen(p_se->s_proto) + 1 + + strlen(p_se->s_name) + 1 + + list_size(p_se->s_aliases, 0)); + + if (!(p_to = get_servent_buffer( size ))) return NULL; + p_to->s_port = p_se->s_port; + + p = (char *)(p_to + 1); + p_to->s_name = p; + strcpy( p, p_se->s_name ); + p += strlen(p) + 1; + + p_to->s_proto = p; + strcpy( p, p_se->s_proto ); + p += strlen(p) + 1; + + p_to->s_aliases = (char **)p; + list_dup( p_se->s_aliases, p_to->s_aliases, 0 ); + return p_to; +} + + +/*********************************************************************** + * getservbyname (ws2_32.55) + */ +struct WS_servent * WINAPI WS_getservbyname( const char *name, const char *proto ) +{ + struct WS_servent *retval = NULL; + struct servent *serv; + char *name_str; + char *proto_str = NULL; + + if (!(name_str = strdup_lower( name ))) return NULL; + + if (proto && *proto) + { + if (!(proto_str = strdup_lower( proto ))) + { + HeapFree( GetProcessHeap(), 0, name_str ); + return NULL; + } + } + + EnterCriticalSection( &csWSgetXXXbyYYY ); + serv = getservbyname( name_str, proto_str ); + if (serv) + retval = servent_from_unix( serv ); + else + SetLastError( WSANO_DATA ); + LeaveCriticalSection( &csWSgetXXXbyYYY ); + + HeapFree( GetProcessHeap(), 0, proto_str ); + HeapFree( GetProcessHeap(), 0, name_str ); + TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval ); + return retval; +} + + +/*********************************************************************** + * getservbyport (ws2_32.56) + */ +struct WS_servent * WINAPI WS_getservbyport( int port, const char *proto ) +{ + struct WS_servent *retval = NULL; +#ifdef HAVE_GETSERVBYPORT + struct servent *serv; + char *proto_str = NULL; + + if (proto && *proto) + { + if (!(proto_str = strdup_lower( proto ))) return NULL; + } + + EnterCriticalSection( &csWSgetXXXbyYYY ); + if ((serv = getservbyport( port, proto_str ))) + retval = servent_from_unix( serv ); + else + SetLastError( WSANO_DATA ); + LeaveCriticalSection( &csWSgetXXXbyYYY ); + + HeapFree( GetProcessHeap(), 0, proto_str ); +#endif + TRACE( "%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval ); + return retval; +} diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index c3c73568c83..2776e2f0014 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -225,7 +225,6 @@ static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSABUF lpControlBuffer );
-DECLARE_CRITICAL_SECTION(csWSgetXXXbyYYY); DECLARE_CRITICAL_SECTION(cs_if_addr_cache); DECLARE_CRITICAL_SECTION(cs_socket_list);
@@ -609,7 +608,6 @@ int num_startup; static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
/* function prototypes */ -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);
int WSAIOCTL_GetInterfaceCount(void); @@ -1340,22 +1338,6 @@ static int convert_sockopt(INT *level, INT *optname) return 0; }
-/* ----------------------------------- Per-thread info (or per-process?) */ - -static char *strdup_lower(const char *str) -{ - int i; - char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 ); - - if (ret) - { - for (i = 0; str[i]; i++) ret[i] = tolower(str[i]); - ret[i] = 0; - } - else SetLastError(WSAENOBUFS); - return ret; -} - /* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option * from an fd and return the value converted to milli seconds * or 0 if there is an infinite time out */ @@ -1564,19 +1546,6 @@ void WINAPI WSASetLastError(INT iError) { SetLastError(iError); }
-static struct WS_servent *check_buffer_se(int size) -{ - struct per_thread_data * ptb = get_per_thread_data(); - if (ptb->se_buffer) - { - if (ptb->se_len >= size ) return ptb->se_buffer; - HeapFree( GetProcessHeap(), 0, ptb->se_buffer ); - } - ptb->se_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->se_len = size) ); - if (!ptb->se_buffer) SetLastError(WSAENOBUFS); - return ptb->se_buffer; -} - static inline BOOL supported_pf(int pf) { switch (pf) @@ -5721,68 +5690,6 @@ SOCKET WINAPI WS_socket(int af, int type, int protocol) }
-/*********************************************************************** - * getservbyname (WS2_32.55) - */ -struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto) -{ - struct WS_servent* retval = NULL; - struct servent* serv; - char *name_str; - char *proto_str = NULL; - - if (!(name_str = strdup_lower(name))) return NULL; - - if (proto && *proto) - { - if (!(proto_str = strdup_lower(proto))) - { - HeapFree( GetProcessHeap(), 0, name_str ); - return NULL; - } - } - - EnterCriticalSection( &csWSgetXXXbyYYY ); - serv = getservbyname(name_str, proto_str); - if( serv != NULL ) - { - retval = WS_dup_se(serv); - } - else SetLastError(WSANO_DATA); - LeaveCriticalSection( &csWSgetXXXbyYYY ); - HeapFree( GetProcessHeap(), 0, proto_str ); - HeapFree( GetProcessHeap(), 0, name_str ); - TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval ); - return retval; -} - -/*********************************************************************** - * getservbyport (WS2_32.56) - */ -struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto) -{ - struct WS_servent* retval = NULL; -#ifdef HAVE_GETSERVBYPORT - struct servent* serv; - char *proto_str = NULL; - - if (proto && *proto) - { - if (!(proto_str = strdup_lower(proto))) return NULL; - } - EnterCriticalSection( &csWSgetXXXbyYYY ); - if( (serv = getservbyport(port, proto_str)) != NULL ) { - retval = WS_dup_se(serv); - } - else SetLastError(WSANO_DATA); - LeaveCriticalSection( &csWSgetXXXbyYYY ); - HeapFree( GetProcessHeap(), 0, proto_str ); -#endif - TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval); - return retval; -} - - /*********************************************************************** * WSAEnumNetworkEvents (WS2_32.36) */ @@ -6187,73 +6094,6 @@ INT WINAPI WSAUnhookBlockingHook(void) }
-/* ----------------------------------- end of API stuff */ - -/* ----------------------------------- helper functions - - * - * TODO: Merge WS_dup_..() stuff into one function that - * would operate with a generic structure containing internal - * pointers (via a template of some kind). - */ - -static int list_size(char** l, int item_size) -{ - int i,j = 0; - if(l) - { for(i=0;l[i];i++) - j += (item_size) ? item_size : strlen(l[i]) + 1; - j += (i + 1) * sizeof(char*); } - return j; -} - -static int list_dup(char** l_src, char** l_to, int item_size) -{ - char *p; - int i; - - for (i = 0; l_src[i]; i++) ; - p = (char *)(l_to + i + 1); - for (i = 0; l_src[i]; i++) - { - int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1; - memcpy(p, l_src[i], count); - l_to[i] = p; - p += count; - } - l_to[i] = NULL; - return p - (char *)l_to; -} - -/* ----- servent */ - -static struct WS_servent *WS_dup_se(const struct servent* p_se) -{ - char *p; - struct WS_servent *p_to; - - int size = (sizeof(*p_se) + - strlen(p_se->s_proto) + 1 + - strlen(p_se->s_name) + 1 + - list_size(p_se->s_aliases, 0)); - - if (!(p_to = check_buffer_se(size))) return NULL; - p_to->s_port = p_se->s_port; - - p = (char *)(p_to + 1); - p_to->s_name = p; - strcpy(p, p_se->s_name); - p += strlen(p) + 1; - - p_to->s_proto = p; - strcpy(p, p_se->s_proto); - p += strlen(p) + 1; - - p_to->s_aliases = (char **)p; - list_dup(p_se->s_aliases, p_to->s_aliases, 0); - return p_to; -} - - /*********************************************************************** * WSARecv (WS2_32.67) */
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=89684
Your paranoid android.
=== debiant2 (32 bit report) ===
ws2_32: sock.c:2676: Test succeeded inside todo block: Test[1]: expected 0, got 0