Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
May 2021
- 86 participants
- 2040 messages
[PATCH 3/3] windowscodecs: Implement DdsEncoder_Initialize.
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
dlls/windowscodecs/ddsformat.c | 31 +++++++++++++++++++++++++---
dlls/windowscodecs/tests/ddsformat.c | 4 ----
2 files changed, 28 insertions(+), 7 deletions(-)
May 1, 2021
[PATCH 2/3] windowscodecs: Add test data index to win_skip messages for DDS tests.
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
dlls/windowscodecs/tests/ddsformat.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
May 1, 2021
[PATCH 1/3] windowscodecs: Add tests for DDS encoder.
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
dlls/windowscodecs/tests/ddsformat.c | 89 ++++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
May 1, 2021
Re: [PATCH 4/5] ws2_32: Move protocol lookup functions to protocol.c.
by Marvin
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
May 1, 2021
Re: [PATCH 1/5] ws2_32: Move getaddrinfo() and related functions to a separate file.
by Marvin
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
May 1, 2021
[PATCH 5/5] ws2_32: Move service lookup functions to protocol.c.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)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)
*/
--
2.30.2
May 1, 2021
[PATCH 4/5] ws2_32: Move protocol lookup functions to protocol.c.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)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)
--
2.30.2
May 1, 2021
[PATCH 3/5] ws2_32: Move name info functions to protocol.c.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)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;
--
2.30.2
May 1, 2021
[PATCH 2/5] ws2_32: Move host lookup functions to protocol.c.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/ws2_32/protocol.c | 492 +++++++++++++++++++++++++++++++++
dlls/ws2_32/socket.c | 516 +----------------------------------
dlls/ws2_32/ws2_32_private.h | 29 +-
3 files changed, 521 insertions(+), 516 deletions(-)
diff --git a/dlls/ws2_32/protocol.c b/dlls/ws2_32/protocol.c
index 7bf994b501f..5bbcdee3e0c 100644
--- a/dlls/ws2_32/protocol.c
+++ b/dlls/ws2_32/protocol.c
@@ -29,6 +29,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(winsock);
WINE_DECLARE_DEBUG_CHANNEL(winediag);
+DECLARE_CRITICAL_SECTION(csWSgetXXXbyYYY);
+
#define MAP_OPTION(opt) { WS_##opt, opt }
static const int ws_aiflag_map[][2] =
@@ -66,6 +68,20 @@ static const int ws_eai_map[][2] =
{ 0, 0 }
};
+static const int ws_af_map[][2] =
+{
+ MAP_OPTION( AF_UNSPEC ),
+ MAP_OPTION( AF_INET ),
+ MAP_OPTION( AF_INET6 ),
+#ifdef HAS_IPX
+ MAP_OPTION( AF_IPX ),
+#endif
+#ifdef AF_IRDA
+ MAP_OPTION( AF_IRDA ),
+#endif
+ {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
+};
+
static const int ws_proto_map[][2] =
{
MAP_OPTION( IPPROTO_IP ),
@@ -81,6 +97,32 @@ static const int ws_proto_map[][2] =
#define IS_IPX_PROTO(X) ((X) >= WS_NSPROTO_IPX && (X) <= WS_NSPROTO_IPX + 255)
+static int convert_af_w2u( int family )
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
+ {
+ if (ws_af_map[i][0] == family)
+ return ws_af_map[i][1];
+ }
+ FIXME( "unhandled Windows address family %d\n", family );
+ return -1;
+}
+
+static int convert_af_u2w( int family )
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
+ {
+ if (ws_af_map[i][1] == family)
+ return ws_af_map[i][0];
+ }
+ FIXME( "unhandled UNIX address family %d\n", family );
+ return -1;
+}
+
static int convert_proto_w2u( int protocol )
{
unsigned int i;
@@ -810,3 +852,453 @@ void WINAPI FreeAddrInfoExW( ADDRINFOEXW *ai )
ai = next;
}
}
+
+
+static UINT host_errno_from_unix( int err )
+{
+ WARN( "%d\n", err );
+
+ switch (err)
+ {
+ case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
+ case TRY_AGAIN: return WSATRY_AGAIN;
+ case NO_RECOVERY: return WSANO_RECOVERY;
+ case NO_DATA: return WSANO_DATA;
+ case ENOBUFS: return WSAENOBUFS;
+ case 0: return 0;
+ default:
+ WARN( "Unknown h_errno %d!\n", err );
+ return WSAEOPNOTSUPP;
+ }
+}
+
+static struct WS_hostent *get_hostent_buffer( unsigned int size )
+{
+ struct per_thread_data *data = get_per_thread_data();
+ if (data->he_buffer)
+ {
+ if (data->he_len >= size) return data->he_buffer;
+ HeapFree( GetProcessHeap(), 0, data->he_buffer );
+ }
+ data->he_buffer = HeapAlloc( GetProcessHeap(), 0, (data->he_len = size) );
+ if (!data->he_buffer) SetLastError(WSAENOBUFS);
+ return data->he_buffer;
+}
+
+/* create a hostent entry
+ *
+ * Creates the entry with enough memory for the name, aliases
+ * addresses, and the address pointers. Also copies the name
+ * and sets up all the pointers.
+ *
+ * NOTE: The alias and address lists must be allocated with room
+ * for the NULL item terminating the list. This is true even if
+ * the list has no items ("aliases" and "addresses" must be
+ * at least "1", a truly empty list is invalid).
+ */
+static struct WS_hostent *create_hostent( char *name, int alias_count, int aliases_size,
+ int address_count, int address_length )
+{
+ struct WS_hostent *p_to;
+ char *p;
+ unsigned int size = sizeof(struct WS_hostent), i;
+
+ size += strlen(name) + 1;
+ size += alias_count * sizeof(char *);
+ size += aliases_size;
+ size += address_count * sizeof(char *);
+ size += (address_count - 1) * address_length;
+
+ if (!(p_to = get_hostent_buffer( size ))) return NULL;
+ memset( p_to, 0, size );
+
+ /* Use the memory in the same way winsock does.
+ * First set the pointer for aliases, second set the pointers for addresses.
+ * Third fill the addresses indexes, fourth jump aliases names size.
+ * Fifth fill the hostname.
+ * NOTE: This method is valid for OS versions >= XP.
+ */
+ p = (char *)(p_to + 1);
+ p_to->h_aliases = (char **)p;
+ p += alias_count * sizeof(char *);
+
+ p_to->h_addr_list = (char **)p;
+ p += address_count * sizeof(char *);
+
+ for (i = 0, address_count--; i < address_count; i++, p += address_length)
+ p_to->h_addr_list[i] = p;
+
+ /* h_aliases must be filled in manually because we don't know each string
+ * size. Leave these pointers NULL (already set to NULL by memset earlier).
+ */
+ p += aliases_size;
+
+ p_to->h_name = p;
+ strcpy( p, name );
+
+ return p_to;
+}
+
+static struct WS_hostent *hostent_from_unix( const struct hostent *p_he )
+{
+ int i, addresses = 0, alias_size = 0;
+ struct WS_hostent *p_to;
+ char *p;
+
+ for (i = 0; p_he->h_aliases[i]; i++)
+ alias_size += strlen( p_he->h_aliases[i] ) + 1;
+ while (p_he->h_addr_list[addresses])
+ addresses++;
+
+ p_to = create_hostent( p_he->h_name, i + 1, alias_size, addresses + 1, p_he->h_length );
+
+ if (!p_to) return NULL;
+ p_to->h_addrtype = convert_af_u2w( p_he->h_addrtype );
+ p_to->h_length = p_he->h_length;
+
+ for (i = 0, p = p_to->h_addr_list[0]; p_he->h_addr_list[i]; i++, p += p_to->h_length)
+ memcpy( p, p_he->h_addr_list[i], p_to->h_length );
+
+ /* Fill the aliases after the IP data */
+ for (i = 0; p_he->h_aliases[i]; i++)
+ {
+ p_to->h_aliases[i] = p;
+ strcpy( p, p_he->h_aliases[i] );
+ p += strlen(p) + 1;
+ }
+
+ return p_to;
+}
+
+
+/***********************************************************************
+ * gethostbyaddr (ws2_32.51)
+ */
+struct WS_hostent * WINAPI WS_gethostbyaddr( const char *addr, int len, int type )
+{
+ struct WS_hostent *retval = NULL;
+ struct hostent *host;
+ int unixtype = convert_af_w2u(type);
+ const char *paddr = addr;
+ unsigned long loopback;
+#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
+ char *extrabuf;
+ int ebufsize = 1024;
+ struct hostent hostentry;
+ int locerr = ENOBUFS;
+#endif
+
+ /* convert back the magic loopback address if necessary */
+ if (unixtype == AF_INET && len == 4 && !memcmp( addr, magic_loopback_addr, 4 ))
+ {
+ loopback = htonl( INADDR_LOOPBACK );
+ paddr = (char *)&loopback;
+ }
+
+#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
+ host = NULL;
+ extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize );
+ while (extrabuf)
+ {
+ int res = gethostbyaddr_r( paddr, len, unixtype, &hostentry, extrabuf, ebufsize, &host, &locerr );
+ if (res != ERANGE) break;
+ ebufsize *= 2;
+ extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize );
+ }
+ if (host)
+ retval = hostent_from_unix( host );
+ else
+ SetLastError( (locerr < 0) ? sock_get_error( errno ) : host_errno_from_unix( locerr ) );
+ HeapFree( GetProcessHeap(), 0, extrabuf );
+#else
+ EnterCriticalSection( &csWSgetXXXbyYYY );
+ host = gethostbyaddr( paddr, len, unixtype );
+ if (host)
+ retval = hostent_from_unix( host );
+ else
+ SetLastError( (h_errno < 0) ? sock_get_error( errno ) : host_errno_from_unix( h_errno ) );
+ LeaveCriticalSection( &csWSgetXXXbyYYY );
+#endif
+
+ TRACE( "ptr %p, len %d, type %d ret %p\n", addr, len, type, retval );
+ return retval;
+}
+
+
+struct route
+{
+ struct in_addr addr;
+ IF_INDEX interface;
+ DWORD metric, default_route;
+};
+
+static int compare_routes_by_metric_asc( const void *left, const void *right )
+{
+ const struct route *a = left, *b = right;
+ if (a->default_route && b->default_route)
+ return a->default_route - b->default_route;
+ if (a->default_route && !b->default_route)
+ return -1;
+ if (b->default_route && !a->default_route)
+ return 1;
+ return a->metric - b->metric;
+}
+
+/* Returns the list of local IP addresses by going through the network
+ * adapters and using the local routing table to sort the addresses
+ * from highest routing priority to lowest routing priority. This
+ * functionality is inferred from the description for obtaining local
+ * IP addresses given in the Knowledge Base Article Q160215.
+ *
+ * Please note that the returned hostent is only freed when the thread
+ * closes and is replaced if another hostent is requested.
+ */
+static struct WS_hostent *get_local_ips( char *hostname )
+{
+ int numroutes = 0, i, j, default_routes = 0;
+ IP_ADAPTER_INFO *adapters = NULL, *k;
+ struct WS_hostent *hostlist = NULL;
+ MIB_IPFORWARDTABLE *routes = NULL;
+ struct route *route_addrs = NULL;
+ DWORD adap_size, route_size, n;
+
+ /* Obtain the size of the adapter list and routing table, also allocate memory */
+ if (GetAdaptersInfo( NULL, &adap_size ) != ERROR_BUFFER_OVERFLOW)
+ return NULL;
+ if (GetIpForwardTable( NULL, &route_size, FALSE ) != ERROR_INSUFFICIENT_BUFFER)
+ return NULL;
+
+ adapters = HeapAlloc( GetProcessHeap(), 0, adap_size );
+ routes = HeapAlloc( GetProcessHeap(), 0, route_size );
+ if (!adapters || !routes)
+ goto cleanup;
+
+ /* Obtain the adapter list and the full routing table */
+ if (GetAdaptersInfo( adapters, &adap_size ) != NO_ERROR)
+ goto cleanup;
+ if (GetIpForwardTable( routes, &route_size, FALSE ) != NO_ERROR)
+ goto cleanup;
+
+ /* Store the interface associated with each route */
+ for (n = 0; n < routes->dwNumEntries; n++)
+ {
+ IF_INDEX ifindex;
+ DWORD ifmetric, ifdefault = 0;
+ BOOL exists = FALSE;
+
+ /* Check if this is a default route (there may be more than one) */
+ if (!routes->table[n].dwForwardDest)
+ ifdefault = ++default_routes;
+ else if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
+ continue;
+ ifindex = routes->table[n].dwForwardIfIndex;
+ ifmetric = routes->table[n].dwForwardMetric1;
+ /* Only store the lowest valued metric for an interface */
+ for (j = 0; j < numroutes; j++)
+ {
+ if (route_addrs[j].interface == ifindex)
+ {
+ if (route_addrs[j].metric > ifmetric)
+ route_addrs[j].metric = ifmetric;
+ exists = TRUE;
+ }
+ }
+ if (exists)
+ continue;
+ route_addrs = heap_realloc( route_addrs, (numroutes + 1) * sizeof(struct route) );
+ if (!route_addrs)
+ goto cleanup;
+ route_addrs[numroutes].interface = ifindex;
+ route_addrs[numroutes].metric = ifmetric;
+ route_addrs[numroutes].default_route = ifdefault;
+ /* If no IP is found in the next step (for whatever reason)
+ * then fall back to the magic loopback address.
+ */
+ memcpy( &route_addrs[numroutes].addr.s_addr, magic_loopback_addr, 4 );
+ numroutes++;
+ }
+ if (numroutes == 0)
+ goto cleanup; /* No routes, fall back to the Magic IP */
+
+ /* Find the IP address associated with each found interface */
+ for (i = 0; i < numroutes; i++)
+ {
+ for (k = adapters; k != NULL; k = k->Next)
+ {
+ char *ip = k->IpAddressList.IpAddress.String;
+
+ if (route_addrs[i].interface == k->Index)
+ route_addrs[i].addr.s_addr = inet_addr(ip);
+ }
+ }
+
+ /* Allocate a hostent and enough memory for all the IPs,
+ * including the NULL at the end of the list.
+ */
+ hostlist = create_hostent( hostname, 1, 0, numroutes+1, sizeof(struct in_addr) );
+ if (hostlist == NULL)
+ goto cleanup;
+ hostlist->h_addr_list[numroutes] = NULL;
+ hostlist->h_aliases[0] = NULL;
+ hostlist->h_addrtype = AF_INET;
+ hostlist->h_length = sizeof(struct in_addr);
+
+ /* Reorder the entries before placing them in the host list. Windows expects
+ * the IP list in order from highest priority to lowest (the critical thing
+ * is that most applications expect the first IP to be the default route).
+ */
+ if (numroutes > 1)
+ qsort( route_addrs, numroutes, sizeof(struct route), compare_routes_by_metric_asc );
+
+ for (i = 0; i < numroutes; i++)
+ *(struct in_addr *)hostlist->h_addr_list[i] = route_addrs[i].addr;
+
+cleanup:
+ HeapFree( GetProcessHeap(), 0, route_addrs );
+ HeapFree( GetProcessHeap(), 0, adapters );
+ HeapFree( GetProcessHeap(), 0, routes );
+ return hostlist;
+}
+
+
+/***********************************************************************
+ * gethostbyname (ws2_32.52)
+ */
+struct WS_hostent * WINAPI WS_gethostbyname( const char *name )
+{
+ struct WS_hostent *retval = NULL;
+ struct hostent *host;
+#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
+ char *extrabuf;
+ int ebufsize = 1024;
+ struct hostent hostentry;
+ int locerr = ENOBUFS;
+#endif
+ char hostname[100];
+
+ if (!num_startup)
+ {
+ SetLastError( WSANOTINITIALISED );
+ return NULL;
+ }
+
+ if (gethostname( hostname, 100 ) == -1)
+ {
+ SetLastError( WSAENOBUFS );
+ return retval;
+ }
+
+ if (!name || !name[0])
+ name = hostname;
+
+ /* If the hostname of the local machine is requested then return the
+ * complete list of local IP addresses */
+ if (!strcmp( name, hostname ))
+ retval = get_local_ips( hostname );
+
+ /* If any other hostname was requested (or the routing table lookup failed)
+ * then return the IP found by the host OS */
+ if (!retval)
+ {
+#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
+ host = NULL;
+ extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize );
+ while (extrabuf)
+ {
+ int res = gethostbyname_r( name, &hostentry, extrabuf, ebufsize, &host, &locerr );
+ if (res != ERANGE) break;
+ ebufsize *= 2;
+ extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize );
+ }
+ if (!host) SetLastError( (locerr < 0) ? sock_get_error( errno ) : host_errno_from_unix( locerr ) );
+#else
+ EnterCriticalSection( &csWSgetXXXbyYYY );
+ host = gethostbyname( name );
+ if (!host) SetLastError( (h_errno < 0) ? sock_get_error( errno ) : host_errno_from_unix( h_errno ) );
+#endif
+ if (host) retval = hostent_from_unix( host );
+#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
+ HeapFree( GetProcessHeap(), 0, extrabuf );
+#else
+ LeaveCriticalSection( &csWSgetXXXbyYYY );
+#endif
+ }
+
+ if (retval && retval->h_addr_list[0][0] == 127 && strcmp( name, "localhost" ))
+ {
+ /* hostname != "localhost" but has loopback address. replace by our
+ * special address.*/
+ memcpy( retval->h_addr_list[0], magic_loopback_addr, 4 );
+ }
+
+ TRACE( "%s ret %p\n", debugstr_a(name), retval );
+ return retval;
+}
+
+
+/***********************************************************************
+ * gethostname (ws2_32.57)
+ */
+int WINAPI WS_gethostname( char *name, int namelen )
+{
+ char buf[256];
+ int len;
+
+ TRACE( "name %p, len %d\n", name, namelen );
+
+ if (!name)
+ {
+ SetLastError( WSAEFAULT );
+ return -1;
+ }
+
+ if (gethostname( buf, sizeof(buf) ) != 0)
+ {
+ SetLastError( sock_get_error( errno ) );
+ return -1;
+ }
+
+ TRACE( "<- %s\n", debugstr_a(buf) );
+ len = strlen( buf );
+ if (len > 15)
+ WARN( "Windows supports NetBIOS name length up to 15 bytes!\n" );
+ if (namelen <= len)
+ {
+ SetLastError( WSAEFAULT );
+ return -1;
+ }
+ strcpy( name, buf );
+ return 0;
+}
+
+
+/***********************************************************************
+ * GetHostNameW (ws2_32.@)
+ */
+int WINAPI GetHostNameW( WCHAR *name, int namelen )
+{
+ char buf[256];
+
+ TRACE( "name %p, len %d\n", name, namelen );
+
+ if (!name)
+ {
+ SetLastError( WSAEFAULT );
+ return -1;
+ }
+
+ if (gethostname( buf, sizeof(buf) ))
+ {
+ SetLastError( sock_get_error( errno ) );
+ return -1;
+ }
+
+ if (MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 ) > namelen)
+ {
+ SetLastError( WSAEFAULT );
+ return -1;
+ }
+ MultiByteToWideChar( CP_ACP, 0, buf, -1, name, namelen );
+ return 0;
+}
+
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 9e48fe256fd..7313741e4b1 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -225,13 +225,6 @@ static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
LPWSABUF lpControlBuffer );
-#define DECLARE_CRITICAL_SECTION(cs) \
- static CRITICAL_SECTION cs; \
- static CRITICAL_SECTION_DEBUG cs##_debug = \
- { 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \
- 0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
- static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 }
-
DECLARE_CRITICAL_SECTION(csWSgetXXXbyYYY);
DECLARE_CRITICAL_SECTION(cs_if_addr_cache);
DECLARE_CRITICAL_SECTION(cs_socket_list);
@@ -618,35 +611,10 @@ typedef struct /* WSAAsyncSelect() control struct */
#define WS_MAX_UDP_DATAGRAM 1024
static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
-/* hostent's, servent's and protent's are stored in one buffer per thread,
- * as documented on MSDN for the functions that return any of the buffers */
-struct per_thread_data
-{
- int opentype;
- struct WS_hostent *he_buffer;
- struct WS_servent *se_buffer;
- struct WS_protoent *pe_buffer;
- struct pollfd *fd_cache;
- unsigned int fd_count;
- int he_len;
- int se_len;
- int pe_len;
- char ntoa_buffer[16]; /* 4*3 digits + 3 '.' + 1 '\0' */
-};
-
-/* internal: routing description information */
-struct route {
- struct in_addr addr;
- IF_INDEX interface;
- DWORD metric, default_route;
-};
-
-static INT num_startup; /* reference counter */
+int num_startup;
static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
/* function prototypes */
-static struct WS_hostent *WS_create_he(char *name, int aliases, int aliases_size, int addresses, int address_length);
-static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
static struct WS_protoent *WS_create_pe( const char *name, char **aliases, int prot );
static struct WS_servent *WS_dup_se(const struct servent* p_se);
static int ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size);
@@ -741,20 +709,6 @@ static const int ws_ipv6_map[][2] =
#endif
};
-static const int ws_af_map[][2] =
-{
- MAP_OPTION( AF_UNSPEC ),
- MAP_OPTION( AF_INET ),
- MAP_OPTION( AF_INET6 ),
-#ifdef HAS_IPX
- MAP_OPTION( AF_IPX ),
-#endif
-#ifdef AF_IRDA
- MAP_OPTION( AF_IRDA ),
-#endif
- {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
-};
-
static const int ws_socktype_map[][2] =
{
MAP_OPTION( SOCK_DGRAM ),
@@ -783,8 +737,6 @@ static const int ws_poll_map[][2] =
{ WS_POLLRDBAND, POLLPRI }
};
-static const char magic_loopback_addr[] = {127, 12, 34, 56};
-
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
#if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
static inline WSACMSGHDR *fill_control_message(int level, int type, WSACMSGHDR *current, ULONG *maxsize, void *data, int len)
@@ -1003,25 +955,6 @@ static NTSTATUS wsaErrStatus(void)
return sock_get_ntstatus(loc_errno);
}
-static UINT wsaHerrno(int loc_errno)
-{
- WARN("h_errno %d.\n", loc_errno);
-
- switch(loc_errno)
- {
- case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
- case TRY_AGAIN: return WSATRY_AGAIN;
- case NO_RECOVERY: return WSANO_RECOVERY;
- case NO_DATA: return WSANO_DATA;
- case ENOBUFS: return WSAENOBUFS;
-
- case 0: return 0;
- default:
- WARN("Unknown h_errno %d!\n", loc_errno);
- return WSAEOPNOTSUPP;
- }
-}
-
static NTSTATUS sock_error_to_ntstatus( DWORD err )
{
switch (err)
@@ -1298,7 +1231,7 @@ static BOOL get_dont_fragment(SOCKET s, int level, BOOL *out)
return value;
}
-static struct per_thread_data *get_per_thread_data(void)
+struct per_thread_data *get_per_thread_data(void)
{
struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
/* lazy initialization */
@@ -1486,28 +1419,6 @@ static inline int do_block( int fd, int events, int timeout )
return pfd.revents;
}
-int
-convert_af_w2u(int windowsaf) {
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
- if (ws_af_map[i][0] == windowsaf)
- return ws_af_map[i][1];
- FIXME("unhandled Windows address family %d\n", windowsaf);
- return -1;
-}
-
-int
-convert_af_u2w(int unixaf) {
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
- if (ws_af_map[i][1] == unixaf)
- return ws_af_map[i][0];
- FIXME("unhandled UNIX address family %d\n", unixaf);
- return -1;
-}
-
int
convert_socktype_w2u(int windowssocktype) {
unsigned int i;
@@ -1669,19 +1580,6 @@ void WINAPI WSASetLastError(INT iError) {
SetLastError(iError);
}
-static struct WS_hostent *check_buffer_he(int size)
-{
- struct per_thread_data * ptb = get_per_thread_data();
- if (ptb->he_buffer)
- {
- if (ptb->he_len >= size ) return ptb->he_buffer;
- HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
- }
- ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
- if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
- return ptb->he_buffer;
-}
-
static struct WS_servent *check_buffer_se(int size)
{
struct per_thread_data * ptb = get_per_thread_data();
@@ -5854,256 +5752,6 @@ SOCKET WINAPI WS_socket(int af, int type, int protocol)
}
-/***********************************************************************
- * gethostbyaddr (WS2_32.51)
- */
-struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
-{
- struct WS_hostent *retval = NULL;
- struct hostent* host;
- int unixtype = convert_af_w2u(type);
- const char *paddr = addr;
- unsigned long loopback;
-#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
- char *extrabuf;
- int ebufsize = 1024;
- struct hostent hostentry;
- int locerr = ENOBUFS;
-#endif
-
- /* convert back the magic loopback address if necessary */
- if (unixtype == AF_INET && len == 4 && !memcmp(addr, magic_loopback_addr, 4))
- {
- loopback = htonl(INADDR_LOOPBACK);
- paddr = (char*) &loopback;
- }
-
-#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
- host = NULL;
- extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
- while(extrabuf) {
- int res = gethostbyaddr_r(paddr, len, unixtype,
- &hostentry, extrabuf, ebufsize, &host, &locerr);
- if (res != ERANGE) break;
- ebufsize *=2;
- extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
- }
- if (host) retval = WS_dup_he(host);
- else SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
- HeapFree(GetProcessHeap(),0,extrabuf);
-#else
- EnterCriticalSection( &csWSgetXXXbyYYY );
- host = gethostbyaddr(paddr, len, unixtype);
- if (host) retval = WS_dup_he(host);
- else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
- LeaveCriticalSection( &csWSgetXXXbyYYY );
-#endif
- TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
- return retval;
-}
-
-/***********************************************************************
- * WS_compare_routes_by_metric_asc (INTERNAL)
- *
- * Comparison function for qsort(), for sorting two routes (struct route)
- * by metric in ascending order.
- */
-static int WS_compare_routes_by_metric_asc(const void *left, const void *right)
-{
- const struct route *a = left, *b = right;
- if (a->default_route && b->default_route)
- return a->default_route - b->default_route;
- if (a->default_route && !b->default_route)
- return -1;
- if (b->default_route && !a->default_route)
- return 1;
- return a->metric - b->metric;
-}
-
-/***********************************************************************
- * WS_get_local_ips (INTERNAL)
- *
- * Returns the list of local IP addresses by going through the network
- * adapters and using the local routing table to sort the addresses
- * from highest routing priority to lowest routing priority. This
- * functionality is inferred from the description for obtaining local
- * IP addresses given in the Knowledge Base Article Q160215.
- *
- * Please note that the returned hostent is only freed when the thread
- * closes and is replaced if another hostent is requested.
- */
-static struct WS_hostent* WS_get_local_ips( char *hostname )
-{
- int numroutes = 0, i, j, default_routes = 0;
- DWORD n;
- PIP_ADAPTER_INFO adapters = NULL, k;
- struct WS_hostent *hostlist = NULL;
- PMIB_IPFORWARDTABLE routes = NULL;
- struct route *route_addrs = NULL;
- DWORD adap_size, route_size;
-
- /* Obtain the size of the adapter list and routing table, also allocate memory */
- if (GetAdaptersInfo(NULL, &adap_size) != ERROR_BUFFER_OVERFLOW)
- return NULL;
- if (GetIpForwardTable(NULL, &route_size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
- return NULL;
- adapters = HeapAlloc(GetProcessHeap(), 0, adap_size);
- routes = HeapAlloc(GetProcessHeap(), 0, route_size);
- if (adapters == NULL || routes == NULL)
- goto cleanup;
- /* Obtain the adapter list and the full routing table */
- if (GetAdaptersInfo(adapters, &adap_size) != NO_ERROR)
- goto cleanup;
- if (GetIpForwardTable(routes, &route_size, FALSE) != NO_ERROR)
- goto cleanup;
- /* Store the interface associated with each route */
- for (n = 0; n < routes->dwNumEntries; n++)
- {
- IF_INDEX ifindex;
- DWORD ifmetric, ifdefault = 0;
- BOOL exists = FALSE;
-
- /* Check if this is a default route (there may be more than one) */
- if (!routes->table[n].dwForwardDest)
- ifdefault = ++default_routes;
- else if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
- continue;
- ifindex = routes->table[n].dwForwardIfIndex;
- ifmetric = routes->table[n].dwForwardMetric1;
- /* Only store the lowest valued metric for an interface */
- for (j = 0; j < numroutes; j++)
- {
- if (route_addrs[j].interface == ifindex)
- {
- if (route_addrs[j].metric > ifmetric)
- route_addrs[j].metric = ifmetric;
- exists = TRUE;
- }
- }
- if (exists)
- continue;
- route_addrs = heap_realloc(route_addrs, (numroutes+1)*sizeof(struct route));
- if (route_addrs == NULL)
- goto cleanup; /* Memory allocation error, fail gracefully */
- route_addrs[numroutes].interface = ifindex;
- route_addrs[numroutes].metric = ifmetric;
- route_addrs[numroutes].default_route = ifdefault;
- /* If no IP is found in the next step (for whatever reason)
- * then fall back to the magic loopback address.
- */
- memcpy(&(route_addrs[numroutes].addr.s_addr), magic_loopback_addr, 4);
- numroutes++;
- }
- if (numroutes == 0)
- goto cleanup; /* No routes, fall back to the Magic IP */
- /* Find the IP address associated with each found interface */
- for (i = 0; i < numroutes; i++)
- {
- for (k = adapters; k != NULL; k = k->Next)
- {
- char *ip = k->IpAddressList.IpAddress.String;
-
- if (route_addrs[i].interface == k->Index)
- route_addrs[i].addr.s_addr = (in_addr_t) inet_addr(ip);
- }
- }
- /* Allocate a hostent and enough memory for all the IPs,
- * including the NULL at the end of the list.
- */
- hostlist = WS_create_he(hostname, 1, 0, numroutes+1, sizeof(struct in_addr));
- if (hostlist == NULL)
- goto cleanup; /* Failed to allocate a hostent for the list of IPs */
- hostlist->h_addr_list[numroutes] = NULL; /* NULL-terminate the address list */
- hostlist->h_aliases[0] = NULL; /* NULL-terminate the alias list */
- hostlist->h_addrtype = AF_INET;
- hostlist->h_length = sizeof(struct in_addr); /* = 4 */
- /* Reorder the entries before placing them in the host list. Windows expects
- * the IP list in order from highest priority to lowest (the critical thing
- * is that most applications expect the first IP to be the default route).
- */
- if (numroutes > 1)
- qsort(route_addrs, numroutes, sizeof(struct route), WS_compare_routes_by_metric_asc);
-
- for (i = 0; i < numroutes; i++)
- (*(struct in_addr *) hostlist->h_addr_list[i]) = route_addrs[i].addr;
-
- /* Cleanup all allocated memory except the address list,
- * the address list is used by the calling app.
- */
-cleanup:
- HeapFree(GetProcessHeap(), 0, route_addrs);
- HeapFree(GetProcessHeap(), 0, adapters);
- HeapFree(GetProcessHeap(), 0, routes);
- return hostlist;
-}
-
-/***********************************************************************
- * gethostbyname (WS2_32.52)
- */
-struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
-{
- struct WS_hostent *retval = NULL;
- struct hostent* host;
-#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
- char *extrabuf;
- int ebufsize=1024;
- struct hostent hostentry;
- int locerr = ENOBUFS;
-#endif
- char hostname[100];
- if(!num_startup) {
- SetLastError(WSANOTINITIALISED);
- return NULL;
- }
- if( gethostname( hostname, 100) == -1) {
- SetLastError(WSAENOBUFS); /* appropriate ? */
- return retval;
- }
- if( !name || !name[0]) {
- name = hostname;
- }
- /* If the hostname of the local machine is requested then return the
- * complete list of local IP addresses */
- if(strcmp(name, hostname) == 0)
- retval = WS_get_local_ips(hostname);
- /* If any other hostname was requested (or the routing table lookup failed)
- * then return the IP found by the host OS */
- if(retval == NULL)
- {
-#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
- host = NULL;
- extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
- while(extrabuf) {
- int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
- if( res != ERANGE) break;
- ebufsize *=2;
- extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
- }
- if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
-#else
- EnterCriticalSection( &csWSgetXXXbyYYY );
- host = gethostbyname(name);
- if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
-#endif
- if (host) retval = WS_dup_he(host);
-#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
- HeapFree(GetProcessHeap(),0,extrabuf);
-#else
- LeaveCriticalSection( &csWSgetXXXbyYYY );
-#endif
- }
- if (retval && retval->h_addr_list[0][0] == 127 &&
- strcmp(name, "localhost") != 0)
- {
- /* hostname != "localhost" but has loopback address. replace by our
- * special address.*/
- memcpy(retval->h_addr_list[0], magic_loopback_addr, 4);
- }
- TRACE( "%s ret %p\n", debugstr_a(name), retval );
- return retval;
-}
-
-
static const struct { int prot; const char *names[3]; } protocols[] =
{
{ 0, { "ip", "IP" }},
@@ -6303,77 +5951,6 @@ struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
}
-/***********************************************************************
- * gethostname (WS2_32.57)
- */
-int WINAPI WS_gethostname(char *name, int namelen)
-{
- char buf[256];
- int len;
-
- TRACE("name %p, len %d\n", name, namelen);
-
- if (!name)
- {
- SetLastError(WSAEFAULT);
- return SOCKET_ERROR;
- }
-
- if (gethostname(buf, sizeof(buf)) != 0)
- {
- SetLastError(wsaErrno());
- return SOCKET_ERROR;
- }
-
- TRACE("<- '%s'\n", buf);
- len = strlen(buf);
- if (len > 15)
- WARN("Windows supports NetBIOS name length up to 15 bytes!\n");
- if (namelen <= len)
- {
- SetLastError(WSAEFAULT);
- WARN("<- not enough space for hostname, required %d, got %d!\n", len + 1, namelen);
- return SOCKET_ERROR;
- }
- strcpy(name, buf);
- return 0;
-}
-
-/***********************************************************************
- * GetHostNameW (WS2_32.@)
- */
-int WINAPI GetHostNameW(WCHAR *name, int namelen)
-{
- char buf[256];
- int len;
-
- TRACE("name %p, len %d\n", name, namelen);
-
- if (!name)
- {
- SetLastError(WSAEFAULT);
- return SOCKET_ERROR;
- }
-
- if (gethostname(buf, sizeof(buf)))
- {
- SetLastError(wsaErrno());
- return SOCKET_ERROR;
- }
-
- if ((len = MultiByteToWideChar(CP_ACP, 0, buf, -1, NULL, 0)) > namelen)
- {
- SetLastError(WSAEFAULT);
- return SOCKET_ERROR;
- }
- MultiByteToWideChar(CP_ACP, 0, buf, -1, name, namelen);
- return 0;
-}
-
-/* ------------------------------------- Windows sockets extensions -- *
- * *
- * ------------------------------------------------------------------- */
-
/***********************************************************************
* WSAEnumNetworkEvents (WS2_32.36)
*/
@@ -6815,95 +6392,6 @@ static int list_dup(char** l_src, char** l_to, int item_size)
return p - (char *)l_to;
}
-/* ----- hostent */
-
-/* create a hostent entry
- *
- * Creates the entry with enough memory for the name, aliases
- * addresses, and the address pointers. Also copies the name
- * and sets up all the pointers.
- *
- * NOTE: The alias and address lists must be allocated with room
- * for the NULL item terminating the list. This is true even if
- * the list has no items ("aliases" and "addresses" must be
- * at least "1", a truly empty list is invalid).
- */
-static struct WS_hostent *WS_create_he(char *name, int aliases, int aliases_size, int addresses, int address_length)
-{
- struct WS_hostent *p_to;
- char *p;
- int size = (sizeof(struct WS_hostent) +
- strlen(name) + 1 +
- sizeof(char *) * aliases +
- aliases_size +
- sizeof(char *) * addresses +
- address_length * (addresses - 1)), i;
-
- if (!(p_to = check_buffer_he(size))) return NULL;
- memset(p_to, 0, size);
-
- /* Use the memory in the same way winsock does.
- * First set the pointer for aliases, second set the pointers for addresses.
- * Third fill the addresses indexes, fourth jump aliases names size.
- * Fifth fill the hostname.
- * NOTE: This method is valid for OS versions >= XP.
- */
- p = (char *)(p_to + 1);
- p_to->h_aliases = (char **)p;
- p += sizeof(char *)*aliases;
-
- p_to->h_addr_list = (char **)p;
- p += sizeof(char *)*addresses;
-
- for (i = 0, addresses--; i < addresses; i++, p += address_length)
- p_to->h_addr_list[i] = p;
-
- /* NOTE: h_aliases must be filled in manually because we don't know each string
- * size, leave these pointers NULL (already set to NULL by memset earlier).
- */
- p += aliases_size;
-
- p_to->h_name = p;
- strcpy(p, name);
-
- return p_to;
-}
-
-/* duplicate hostent entry
- * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
- * Ditto for protoent and servent.
- */
-static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
-{
- int i, addresses = 0, alias_size = 0;
- struct WS_hostent *p_to;
- char *p;
-
- for( i = 0; p_he->h_aliases[i]; i++) alias_size += strlen(p_he->h_aliases[i]) + 1;
- while (p_he->h_addr_list[addresses]) addresses++;
-
- p_to = WS_create_he(p_he->h_name, i + 1, alias_size, addresses + 1, p_he->h_length);
-
- if (!p_to) return NULL;
- p_to->h_addrtype = convert_af_u2w(p_he->h_addrtype);
- p_to->h_length = p_he->h_length;
-
- for(i = 0, p = p_to->h_addr_list[0]; p_he->h_addr_list[i]; i++, p += p_to->h_length)
- memcpy(p, p_he->h_addr_list[i], p_to->h_length);
-
- /* Fill the aliases after the IP data */
- for(i = 0; p_he->h_aliases[i]; i++)
- {
- p_to->h_aliases[i] = p;
- strcpy(p, p_he->h_aliases[i]);
- p += strlen(p) + 1;
- }
-
- return p_to;
-}
-
-/* ----- protoent */
-
static struct WS_protoent *WS_create_pe( const char *name, char **aliases, int prot )
{
struct WS_protoent *ret;
diff --git a/dlls/ws2_32/ws2_32_private.h b/dlls/ws2_32/ws2_32_private.h
index 8af23b11ded..121ce25ad1d 100644
--- a/dlls/ws2_32/ws2_32_private.h
+++ b/dlls/ws2_32/ws2_32_private.h
@@ -152,8 +152,15 @@
#include "wine/unicode.h"
#include "wine/heap.h"
-int convert_af_u2w( int family ) DECLSPEC_HIDDEN;
-int convert_af_w2u( int family ) DECLSPEC_HIDDEN;
+#define DECLARE_CRITICAL_SECTION(cs) \
+ static CRITICAL_SECTION cs; \
+ static CRITICAL_SECTION_DEBUG cs##_debug = \
+ { 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \
+ 0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
+ static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 }
+
+static const char magic_loopback_addr[] = {127, 12, 34, 56};
+
int convert_eai_u2w( int ret ) DECLSPEC_HIDDEN;
int convert_socktype_u2w( int type ) DECLSPEC_HIDDEN;
int convert_socktype_w2u( int type ) DECLSPEC_HIDDEN;
@@ -164,4 +171,22 @@ const char *debugstr_sockaddr( const struct WS_sockaddr *addr ) DECLSPEC_HIDDEN;
UINT sock_get_error( int err ) DECLSPEC_HIDDEN;
+struct per_thread_data
+{
+ int opentype;
+ struct WS_hostent *he_buffer;
+ struct WS_servent *se_buffer;
+ struct WS_protoent *pe_buffer;
+ struct pollfd *fd_cache;
+ unsigned int fd_count;
+ int he_len;
+ int se_len;
+ int pe_len;
+ char ntoa_buffer[16]; /* 4*3 digits + 3 '.' + 1 '\0' */
+};
+
+extern int num_startup;
+
+struct per_thread_data *get_per_thread_data(void) DECLSPEC_HIDDEN;
+
#endif
--
2.30.2
May 1, 2021
[PATCH 1/5] ws2_32: Move getaddrinfo() and related functions to a separate file.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/ws2_32/Makefile.in | 1 +
dlls/ws2_32/protocol.c | 812 ++++++++++++++++++++++++++++++++
dlls/ws2_32/socket.c | 890 +----------------------------------
dlls/ws2_32/ws2_32_private.h | 167 +++++++
4 files changed, 988 insertions(+), 882 deletions(-)
create mode 100644 dlls/ws2_32/protocol.c
create mode 100644 dlls/ws2_32/ws2_32_private.h
diff --git a/dlls/ws2_32/Makefile.in b/dlls/ws2_32/Makefile.in
index 9d7dfafeb3c..6312b20739d 100644
--- a/dlls/ws2_32/Makefile.in
+++ b/dlls/ws2_32/Makefile.in
@@ -6,6 +6,7 @@ EXTRALIBS = $(POLL_LIBS)
C_SRCS = \
async.c \
+ protocol.c \
socket.c
RC_SRCS = version.rc
diff --git a/dlls/ws2_32/protocol.c b/dlls/ws2_32/protocol.c
new file mode 100644
index 00000000000..7bf994b501f
--- /dev/null
+++ b/dlls/ws2_32/protocol.c
@@ -0,0 +1,812 @@
+/*
+ * Protocol-level socket functions
+ *
+ * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
+ * Copyright (C) 2001 Stefan Leichter
+ * Copyright (C) 2004 Hans Leidekker
+ * Copyright (C) 2005 Marcus Meissner
+ * Copyright (C) 2006-2008 Kai Blin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include "ws2_32_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winsock);
+WINE_DECLARE_DEBUG_CHANNEL(winediag);
+
+#define MAP_OPTION(opt) { WS_##opt, opt }
+
+static const int ws_aiflag_map[][2] =
+{
+ MAP_OPTION( AI_PASSIVE ),
+ MAP_OPTION( AI_CANONNAME ),
+ MAP_OPTION( AI_NUMERICHOST ),
+#ifdef AI_NUMERICSERV
+ MAP_OPTION( AI_NUMERICSERV ),
+#endif
+#ifdef AI_V4MAPPED
+ MAP_OPTION( AI_V4MAPPED ),
+#endif
+ MAP_OPTION( AI_ALL ),
+ MAP_OPTION( AI_ADDRCONFIG ),
+};
+
+static const int ws_eai_map[][2] =
+{
+ MAP_OPTION( EAI_AGAIN ),
+ MAP_OPTION( EAI_BADFLAGS ),
+ MAP_OPTION( EAI_FAIL ),
+ MAP_OPTION( EAI_FAMILY ),
+ MAP_OPTION( EAI_MEMORY ),
+/* Note: EAI_NODATA is deprecated, but still used by Windows and Linux. We map
+ * the newer EAI_NONAME to EAI_NODATA for now until Windows changes too. */
+#ifdef EAI_NODATA
+ MAP_OPTION( EAI_NODATA ),
+#endif
+#ifdef EAI_NONAME
+ { WS_EAI_NODATA, EAI_NONAME },
+#endif
+ MAP_OPTION( EAI_SERVICE ),
+ MAP_OPTION( EAI_SOCKTYPE ),
+ { 0, 0 }
+};
+
+static const int ws_proto_map[][2] =
+{
+ MAP_OPTION( IPPROTO_IP ),
+ MAP_OPTION( IPPROTO_TCP ),
+ MAP_OPTION( IPPROTO_UDP ),
+ MAP_OPTION( IPPROTO_IPV6 ),
+ MAP_OPTION( IPPROTO_ICMP ),
+ MAP_OPTION( IPPROTO_IGMP ),
+ MAP_OPTION( IPPROTO_RAW ),
+ {WS_IPPROTO_IPV4, IPPROTO_IPIP},
+ {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
+};
+
+#define IS_IPX_PROTO(X) ((X) >= WS_NSPROTO_IPX && (X) <= WS_NSPROTO_IPX + 255)
+
+static int convert_proto_w2u( int protocol )
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(ws_proto_map); i++)
+ {
+ if (ws_proto_map[i][0] == protocol)
+ return ws_proto_map[i][1];
+ }
+
+ if (IS_IPX_PROTO(protocol))
+ return protocol;
+
+ FIXME( "unhandled Windows socket protocol %d\n", protocol );
+ return -1;
+}
+
+static int convert_proto_u2w( int protocol )
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(ws_proto_map); i++)
+ {
+ if (ws_proto_map[i][1] == protocol)
+ return ws_proto_map[i][0];
+ }
+
+ /* if value is inside IPX range just return it - the kernel simply
+ * echoes the value used in the socket() function */
+ if (IS_IPX_PROTO(protocol))
+ return protocol;
+
+ FIXME("unhandled UNIX socket protocol %d\n", protocol);
+ return -1;
+}
+
+static int convert_aiflag_w2u( int winflags )
+{
+ unsigned int i;
+ int unixflags = 0;
+
+ for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
+ {
+ if (ws_aiflag_map[i][0] & winflags)
+ {
+ unixflags |= ws_aiflag_map[i][1];
+ winflags &= ~ws_aiflag_map[i][0];
+ }
+ }
+ if (winflags)
+ FIXME( "Unhandled windows AI_xxx flags 0x%x\n", winflags );
+ return unixflags;
+}
+
+static int convert_aiflag_u2w( int unixflags )
+{
+ unsigned int i;
+ int winflags = 0;
+
+ for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
+ {
+ if (ws_aiflag_map[i][1] & unixflags)
+ {
+ winflags |= ws_aiflag_map[i][0];
+ unixflags &= ~ws_aiflag_map[i][1];
+ }
+ }
+ if (unixflags)
+ WARN( "Unhandled UNIX AI_xxx flags 0x%x\n", unixflags );
+ return winflags;
+}
+
+int convert_eai_u2w( int unixret )
+{
+ int i;
+
+ if (!unixret) return 0;
+
+ for (i = 0; ws_eai_map[i][0]; i++)
+ {
+ if (ws_eai_map[i][1] == unixret)
+ return ws_eai_map[i][0];
+ }
+
+ if (unixret == EAI_SYSTEM)
+ /* There are broken versions of glibc which return EAI_SYSTEM
+ * and set errno to 0 instead of returning EAI_NONAME. */
+ return errno ? sock_get_error( errno ) : WS_EAI_NONAME;
+
+ FIXME("Unhandled unix EAI_xxx ret %d\n", unixret);
+ return unixret;
+}
+
+static char *get_fqdn(void)
+{
+ char *ret;
+ DWORD size = 0;
+
+ GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, NULL, &size );
+ if (GetLastError() != ERROR_MORE_DATA) return NULL;
+ if (!(ret = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
+ if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, ret, &size ))
+ {
+ HeapFree( GetProcessHeap(), 0, ret );
+ return NULL;
+ }
+ return ret;
+}
+
+static BOOL addrinfo_in_list( const struct WS_addrinfo *list, const struct WS_addrinfo *ai )
+{
+ const struct WS_addrinfo *cursor = list;
+ while (cursor)
+ {
+ if (ai->ai_flags == cursor->ai_flags &&
+ ai->ai_family == cursor->ai_family &&
+ ai->ai_socktype == cursor->ai_socktype &&
+ ai->ai_protocol == cursor->ai_protocol &&
+ ai->ai_addrlen == cursor->ai_addrlen &&
+ !memcmp(ai->ai_addr, cursor->ai_addr, ai->ai_addrlen) &&
+ ((ai->ai_canonname && cursor->ai_canonname && !strcmp(ai->ai_canonname, cursor->ai_canonname))
+ || (!ai->ai_canonname && !cursor->ai_canonname)))
+ {
+ return TRUE;
+ }
+ cursor = cursor->ai_next;
+ }
+ return FALSE;
+}
+
+
+/***********************************************************************
+ * getaddrinfo (ws2_32.@)
+ */
+int WINAPI WS_getaddrinfo( const char *nodename, const char *servname,
+ const struct WS_addrinfo *hints, struct WS_addrinfo **res )
+{
+#ifdef HAVE_GETADDRINFO
+ struct addrinfo *unixaires = NULL;
+ int result;
+ struct addrinfo unixhints, *punixhints = NULL;
+ char *nodev6 = NULL, *fqdn = NULL;
+ const char *node;
+
+ *res = NULL;
+ if (!nodename && !servname)
+ {
+ SetLastError(WSAHOST_NOT_FOUND);
+ return WSAHOST_NOT_FOUND;
+ }
+
+ if (!nodename)
+ node = NULL;
+ else if (!nodename[0])
+ {
+ if (!(fqdn = get_fqdn())) return WSA_NOT_ENOUGH_MEMORY;
+ node = fqdn;
+ }
+ else
+ {
+ node = nodename;
+
+ /* Check for [ipv6] or [ipv6]:portnumber, which are supported by Windows */
+ if (!hints || hints->ai_family == WS_AF_UNSPEC || hints->ai_family == WS_AF_INET6)
+ {
+ char *close_bracket;
+
+ if (node[0] == '[' && (close_bracket = strchr(node + 1, ']')))
+ {
+ nodev6 = HeapAlloc( GetProcessHeap(), 0, close_bracket - node );
+ if (!nodev6) return WSA_NOT_ENOUGH_MEMORY;
+ lstrcpynA( nodev6, node + 1, close_bracket - node );
+ node = nodev6;
+ }
+ }
+ }
+
+ /* servname tweak required by OSX and BSD kernels */
+ if (servname && !servname[0]) servname = "0";
+
+ if (hints)
+ {
+ punixhints = &unixhints;
+
+ memset( &unixhints, 0, sizeof(unixhints) );
+ punixhints->ai_flags = convert_aiflag_w2u( hints->ai_flags );
+
+ /* zero is a wildcard, no need to convert */
+ if (hints->ai_family)
+ punixhints->ai_family = convert_af_w2u( hints->ai_family );
+ if (hints->ai_socktype)
+ punixhints->ai_socktype = convert_socktype_w2u( hints->ai_socktype );
+ if (hints->ai_protocol)
+ punixhints->ai_protocol = max( convert_proto_w2u( hints->ai_protocol ), 0 );
+
+ if (punixhints->ai_socktype < 0)
+ {
+ SetLastError( WSAESOCKTNOSUPPORT );
+ HeapFree( GetProcessHeap(), 0, fqdn );
+ HeapFree( GetProcessHeap(), 0, nodev6 );
+ return -1;
+ }
+
+ /* windows allows invalid combinations of socket type and protocol, unix does not.
+ * fix the parameters here to make getaddrinfo call always work */
+ if (punixhints->ai_protocol == IPPROTO_TCP
+ && punixhints->ai_socktype != SOCK_STREAM
+ && punixhints->ai_socktype != SOCK_SEQPACKET)
+ punixhints->ai_socktype = 0;
+ else if (punixhints->ai_protocol == IPPROTO_UDP && punixhints->ai_socktype != SOCK_DGRAM)
+ punixhints->ai_socktype = 0;
+ else if (IS_IPX_PROTO(punixhints->ai_protocol) && punixhints->ai_socktype != SOCK_DGRAM)
+ punixhints->ai_socktype = 0;
+ else if (punixhints->ai_protocol == IPPROTO_IPV6)
+ punixhints->ai_protocol = 0;
+ }
+
+ /* getaddrinfo(3) is thread safe, no need to wrap in CS */
+ result = getaddrinfo( node, servname, punixhints, &unixaires );
+
+ if (result && (!hints || !(hints->ai_flags & WS_AI_NUMERICHOST)) && node)
+ {
+ if (!fqdn && !(fqdn = get_fqdn()))
+ {
+ HeapFree( GetProcessHeap(), 0, nodev6 );
+ return WSA_NOT_ENOUGH_MEMORY;
+ }
+ if (!strcmp( fqdn, node ) || (!strncmp( fqdn, node, strlen( node ) ) && fqdn[strlen( node )] == '.'))
+ {
+ /* If it didn't work it means the host name IP is not in /etc/hosts, try again
+ * by sending a NULL host and avoid sending a NULL servname too because that
+ * is invalid */
+ ERR_(winediag)( "Failed to resolve your host name IP\n" );
+ result = getaddrinfo( NULL, servname ? servname : "0", punixhints, &unixaires );
+ if (!result && punixhints && (punixhints->ai_flags & AI_CANONNAME) && unixaires && !unixaires->ai_canonname)
+ {
+ freeaddrinfo( unixaires );
+ result = EAI_NONAME;
+ }
+ }
+ }
+ TRACE( "%s, %s %p -> %p %d\n", debugstr_a(nodename), debugstr_a(servname), hints, res, result );
+ HeapFree( GetProcessHeap(), 0, fqdn );
+ HeapFree( GetProcessHeap(), 0, nodev6 );
+
+ if (!result)
+ {
+ struct addrinfo *xuai = unixaires;
+ struct WS_addrinfo **xai = res;
+
+ *xai = NULL;
+ while (xuai)
+ {
+ struct WS_addrinfo *ai = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo) );
+ SIZE_T len;
+
+ if (!ai)
+ goto outofmem;
+
+ ai->ai_flags = convert_aiflag_u2w( xuai->ai_flags );
+ ai->ai_family = convert_af_u2w( xuai->ai_family );
+ /* copy whatever was sent in the hints */
+ if (hints)
+ {
+ ai->ai_socktype = hints->ai_socktype;
+ ai->ai_protocol = hints->ai_protocol;
+ }
+ else
+ {
+ ai->ai_socktype = convert_socktype_u2w( xuai->ai_socktype );
+ ai->ai_protocol = convert_proto_u2w( xuai->ai_protocol );
+ }
+ if (xuai->ai_canonname)
+ {
+ TRACE( "canon name - %s\n", debugstr_a(xuai->ai_canonname) );
+ ai->ai_canonname = HeapAlloc( GetProcessHeap(), 0, strlen( xuai->ai_canonname ) + 1 );
+ if (!ai->ai_canonname)
+ goto outofmem;
+ strcpy( ai->ai_canonname, xuai->ai_canonname );
+ }
+ len = xuai->ai_addrlen;
+ ai->ai_addr = HeapAlloc( GetProcessHeap(), 0, len );
+ if (!ai->ai_addr)
+ goto outofmem;
+ ai->ai_addrlen = len;
+ do
+ {
+ int winlen = ai->ai_addrlen;
+
+ if (!ws_sockaddr_u2ws( xuai->ai_addr, ai->ai_addr, &winlen ))
+ {
+ ai->ai_addrlen = winlen;
+ break;
+ }
+ len *= 2;
+ ai->ai_addr = HeapReAlloc( GetProcessHeap(), 0, ai->ai_addr, len );
+ if (!ai->ai_addr)
+ goto outofmem;
+ ai->ai_addrlen = len;
+ } while (1);
+
+ if (addrinfo_in_list( *res, ai ))
+ {
+ HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
+ HeapFree( GetProcessHeap(), 0, ai->ai_addr );
+ HeapFree( GetProcessHeap(), 0, ai );
+ }
+ else
+ {
+ *xai = ai;
+ xai = &ai->ai_next;
+ }
+ xuai = xuai->ai_next;
+ }
+ freeaddrinfo( unixaires );
+
+ if (TRACE_ON(winsock))
+ {
+ struct WS_addrinfo *ai = *res;
+ while (ai)
+ {
+ TRACE( "=> %p, flags %#x, family %d, type %d, protocol %d, len %ld, name %s, addr %s\n",
+ ai, ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol, ai->ai_addrlen,
+ ai->ai_canonname, debugstr_sockaddr(ai->ai_addr) );
+ ai = ai->ai_next;
+ }
+ }
+ }
+ else
+ result = convert_eai_u2w( result );
+
+ SetLastError( result );
+ return result;
+
+outofmem:
+ if (*res) WS_freeaddrinfo( *res );
+ if (unixaires) freeaddrinfo( unixaires );
+ return WSA_NOT_ENOUGH_MEMORY;
+#else
+ FIXME( "getaddrinfo() failed, not found during build time.\n" );
+ return EAI_FAIL;
+#endif
+}
+
+
+static ADDRINFOEXW *addrinfo_AtoW( const struct WS_addrinfo *ai )
+{
+ ADDRINFOEXW *ret;
+
+ if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(ADDRINFOEXW) ))) return NULL;
+ ret->ai_flags = ai->ai_flags;
+ ret->ai_family = ai->ai_family;
+ ret->ai_socktype = ai->ai_socktype;
+ ret->ai_protocol = ai->ai_protocol;
+ ret->ai_addrlen = ai->ai_addrlen;
+ ret->ai_canonname = NULL;
+ ret->ai_addr = NULL;
+ ret->ai_blob = NULL;
+ ret->ai_bloblen = 0;
+ ret->ai_provider = NULL;
+ ret->ai_next = NULL;
+ if (ai->ai_canonname)
+ {
+ int len = MultiByteToWideChar( CP_ACP, 0, ai->ai_canonname, -1, NULL, 0 );
+ if (!(ret->ai_canonname = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
+ {
+ HeapFree( GetProcessHeap(), 0, ret );
+ return NULL;
+ }
+ MultiByteToWideChar( CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len );
+ }
+ if (ai->ai_addr)
+ {
+ if (!(ret->ai_addr = HeapAlloc( GetProcessHeap(), 0, ai->ai_addrlen )))
+ {
+ HeapFree( GetProcessHeap(), 0, ret->ai_canonname );
+ HeapFree( GetProcessHeap(), 0, ret );
+ return NULL;
+ }
+ memcpy( ret->ai_addr, ai->ai_addr, ai->ai_addrlen );
+ }
+ return ret;
+}
+
+static ADDRINFOEXW *addrinfo_list_AtoW( const struct WS_addrinfo *info )
+{
+ ADDRINFOEXW *ret, *infoW;
+
+ if (!(ret = infoW = addrinfo_AtoW( info ))) return NULL;
+ while (info->ai_next)
+ {
+ if (!(infoW->ai_next = addrinfo_AtoW( info->ai_next )))
+ {
+ FreeAddrInfoExW( ret );
+ return NULL;
+ }
+ infoW = infoW->ai_next;
+ info = info->ai_next;
+ }
+ return ret;
+}
+
+static struct WS_addrinfo *addrinfo_WtoA( const struct WS_addrinfoW *ai )
+{
+ struct WS_addrinfo *ret;
+
+ if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(struct WS_addrinfo) ))) return NULL;
+ ret->ai_flags = ai->ai_flags;
+ ret->ai_family = ai->ai_family;
+ ret->ai_socktype = ai->ai_socktype;
+ ret->ai_protocol = ai->ai_protocol;
+ ret->ai_addrlen = ai->ai_addrlen;
+ ret->ai_canonname = NULL;
+ ret->ai_addr = NULL;
+ ret->ai_next = NULL;
+ if (ai->ai_canonname)
+ {
+ int len = WideCharToMultiByte( CP_ACP, 0, ai->ai_canonname, -1, NULL, 0, NULL, NULL );
+ if (!(ret->ai_canonname = HeapAlloc( GetProcessHeap(), 0, len )))
+ {
+ HeapFree( GetProcessHeap(), 0, ret );
+ return NULL;
+ }
+ WideCharToMultiByte( CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len, NULL, NULL );
+ }
+ if (ai->ai_addr)
+ {
+ if (!(ret->ai_addr = HeapAlloc( GetProcessHeap(), 0, sizeof(struct WS_sockaddr) )))
+ {
+ HeapFree( GetProcessHeap(), 0, ret->ai_canonname );
+ HeapFree( GetProcessHeap(), 0, ret );
+ return NULL;
+ }
+ memcpy( ret->ai_addr, ai->ai_addr, sizeof(struct WS_sockaddr) );
+ }
+ return ret;
+}
+
+struct getaddrinfo_args
+{
+ OVERLAPPED *overlapped;
+ LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine;
+ ADDRINFOEXW **result;
+ char *nodename;
+ char *servname;
+};
+
+static void WINAPI getaddrinfo_callback(TP_CALLBACK_INSTANCE *instance, void *context)
+{
+ struct getaddrinfo_args *args = context;
+ OVERLAPPED *overlapped = args->overlapped;
+ HANDLE event = overlapped->hEvent;
+ LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine = args->completion_routine;
+ struct WS_addrinfo *res;
+ int ret;
+
+ ret = WS_getaddrinfo( args->nodename, args->servname, NULL, &res );
+ if (res)
+ {
+ *args->result = addrinfo_list_AtoW(res);
+ overlapped->u.Pointer = args->result;
+ WS_freeaddrinfo(res);
+ }
+
+ HeapFree( GetProcessHeap(), 0, args->nodename );
+ HeapFree( GetProcessHeap(), 0, args->servname );
+ HeapFree( GetProcessHeap(), 0, args );
+
+ overlapped->Internal = ret;
+ if (completion_routine) completion_routine( ret, 0, overlapped );
+ if (event) SetEvent( event );
+}
+
+static int WS_getaddrinfoW( const WCHAR *nodename, const WCHAR *servname,
+ const struct WS_addrinfo *hints, ADDRINFOEXW **res, OVERLAPPED *overlapped,
+ LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine )
+{
+ int ret = EAI_MEMORY, len, i;
+ char *nodenameA = NULL, *servnameA = NULL;
+ struct WS_addrinfo *resA;
+ WCHAR *local_nodenameW = (WCHAR *)nodename;
+
+ *res = NULL;
+ if (nodename)
+ {
+ /* Is this an IDN? Most likely if any char is above the Ascii table, this
+ * is the simplest validation possible, further validation will be done by
+ * the native getaddrinfo() */
+ for (i = 0; nodename[i]; i++)
+ {
+ if (nodename[i] > 'z')
+ break;
+ }
+ if (nodename[i])
+ {
+ if (hints && (hints->ai_flags & WS_AI_DISABLE_IDN_ENCODING))
+ {
+ /* Name requires conversion but it was disabled */
+ ret = WSAHOST_NOT_FOUND;
+ SetLastError( ret );
+ goto end;
+ }
+
+ len = IdnToAscii( 0, nodename, -1, NULL, 0 );
+ if (!len)
+ {
+ ERR("Failed to convert %s to punycode\n", debugstr_w(nodename));
+ ret = EAI_FAIL;
+ goto end;
+ }
+ if (!(local_nodenameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) goto end;
+ IdnToAscii( 0, nodename, -1, local_nodenameW, len );
+ }
+ }
+ if (local_nodenameW)
+ {
+ len = WideCharToMultiByte( CP_ACP, 0, local_nodenameW, -1, NULL, 0, NULL, NULL );
+ if (!(nodenameA = HeapAlloc( GetProcessHeap(), 0, len ))) goto end;
+ WideCharToMultiByte( CP_ACP, 0, local_nodenameW, -1, nodenameA, len, NULL, NULL );
+ }
+ if (servname)
+ {
+ len = WideCharToMultiByte( CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL );
+ if (!(servnameA = HeapAlloc( GetProcessHeap(), 0, len ))) goto end;
+ WideCharToMultiByte( CP_ACP, 0, servname, -1, servnameA, len, NULL, NULL );
+ }
+
+ if (overlapped)
+ {
+ struct getaddrinfo_args *args;
+
+ if (overlapped->hEvent && completion_routine)
+ {
+ ret = WSAEINVAL;
+ goto end;
+ }
+
+ if (!(args = HeapAlloc( GetProcessHeap(), 0, sizeof(*args) ))) goto end;
+ args->overlapped = overlapped;
+ args->completion_routine = completion_routine;
+ args->result = res;
+ args->nodename = nodenameA;
+ args->servname = servnameA;
+
+ overlapped->Internal = WSAEINPROGRESS;
+ if (!TrySubmitThreadpoolCallback( getaddrinfo_callback, args, NULL ))
+ {
+ HeapFree( GetProcessHeap(), 0, args );
+ ret = GetLastError();
+ goto end;
+ }
+
+ if (local_nodenameW != nodename)
+ HeapFree( GetProcessHeap(), 0, local_nodenameW );
+ SetLastError( ERROR_IO_PENDING );
+ return ERROR_IO_PENDING;
+ }
+
+ ret = WS_getaddrinfo( nodenameA, servnameA, hints, &resA );
+ if (!ret)
+ {
+ *res = addrinfo_list_AtoW( resA );
+ WS_freeaddrinfo( resA );
+ }
+
+end:
+ if (local_nodenameW != nodename)
+ HeapFree( GetProcessHeap(), 0, local_nodenameW );
+ HeapFree( GetProcessHeap(), 0, nodenameA );
+ HeapFree( GetProcessHeap(), 0, servnameA );
+ return ret;
+}
+
+
+/***********************************************************************
+ * GetAddrInfoExW (ws2_32.@)
+ */
+int WINAPI GetAddrInfoExW( const WCHAR *name, const WCHAR *servname, DWORD namespace,
+ GUID *namespace_id, const ADDRINFOEXW *hints, ADDRINFOEXW **result,
+ struct WS_timeval *timeout, OVERLAPPED *overlapped,
+ LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine, HANDLE *handle )
+{
+ int ret;
+
+ TRACE( "name %s, servname %s, namespace %u, namespace_id %s)\n",
+ debugstr_w(name), debugstr_w(servname), namespace, debugstr_guid(namespace_id) );
+
+ if (namespace != NS_DNS)
+ FIXME( "Unsupported namespace %u\n", namespace );
+ if (namespace_id)
+ FIXME( "Unsupported namespace_id %s\n", debugstr_guid(namespace_id) );
+ if (hints)
+ FIXME( "Unsupported hints\n" );
+ if (timeout)
+ FIXME( "Unsupported timeout\n" );
+ if (handle)
+ FIXME( "Unsupported cancel handle\n" );
+
+ ret = WS_getaddrinfoW( name, servname, NULL, result, overlapped, completion_routine );
+ if (ret) return ret;
+ if (handle) *handle = (HANDLE)0xdeadbeef;
+ return 0;
+}
+
+
+/***********************************************************************
+ * GetAddrInfoExOverlappedResult (ws2_32.@)
+ */
+int WINAPI GetAddrInfoExOverlappedResult( OVERLAPPED *overlapped )
+{
+ TRACE( "(%p)\n", overlapped );
+ return overlapped->Internal;
+}
+
+
+/***********************************************************************
+ * GetAddrInfoExCancel (ws2_32.@)
+ */
+int WINAPI GetAddrInfoExCancel( HANDLE *handle )
+{
+ FIXME( "(%p)\n", handle );
+ return WSA_INVALID_HANDLE;
+}
+
+
+/***********************************************************************
+ * GetAddrInfoW (ws2_32.@)
+ */
+int WINAPI GetAddrInfoW(const WCHAR *nodename, const WCHAR *servname, const ADDRINFOW *hints, ADDRINFOW **res)
+{
+ struct WS_addrinfo *hintsA = NULL;
+ ADDRINFOEXW *resex;
+ int ret = EAI_MEMORY;
+
+ TRACE( "nodename %s, servname %s, hints %p, result %p\n",
+ debugstr_w(nodename), debugstr_w(servname), hints, res );
+
+ *res = NULL;
+ if (hints) hintsA = addrinfo_WtoA( hints );
+ ret = WS_getaddrinfoW( nodename, servname, hintsA, &resex, NULL, NULL );
+ WS_freeaddrinfo( hintsA );
+ if (ret) return ret;
+
+ if (resex)
+ {
+ /* ADDRINFOEXW has a layout compatible with ADDRINFOW except for the
+ * ai_next field, so we may convert it in place */
+ *res = (ADDRINFOW *)resex;
+ do
+ {
+ ((ADDRINFOW *)resex)->ai_next = (ADDRINFOW *)resex->ai_next;
+ resex = resex->ai_next;
+ } while (resex);
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * freeaddrinfo (ws2_32.@)
+ */
+void WINAPI WS_freeaddrinfo( struct WS_addrinfo *res )
+{
+ while (res)
+ {
+ struct WS_addrinfo *next;
+
+ HeapFree( GetProcessHeap(), 0, res->ai_canonname );
+ HeapFree( GetProcessHeap(), 0, res->ai_addr );
+ next = res->ai_next;
+ HeapFree( GetProcessHeap(), 0, res );
+ res = next;
+ }
+}
+
+
+/***********************************************************************
+ * FreeAddrInfoW (ws2_32.@)
+ */
+void WINAPI FreeAddrInfoW( ADDRINFOW *ai )
+{
+ while (ai)
+ {
+ ADDRINFOW *next;
+ HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
+ HeapFree( GetProcessHeap(), 0, ai->ai_addr );
+ next = ai->ai_next;
+ HeapFree( GetProcessHeap(), 0, ai );
+ ai = next;
+ }
+}
+
+
+/***********************************************************************
+ * FreeAddrInfoEx (ws2_32.@)
+ */
+void WINAPI FreeAddrInfoEx( ADDRINFOEXA *ai )
+{
+ TRACE( "(%p)\n", ai );
+
+ while (ai)
+ {
+ ADDRINFOEXA *next;
+ HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
+ HeapFree( GetProcessHeap(), 0, ai->ai_addr );
+ next = ai->ai_next;
+ HeapFree( GetProcessHeap(), 0, ai );
+ ai = next;
+ }
+}
+
+
+/***********************************************************************
+ * FreeAddrInfoExW (ws2_32.@)
+ */
+void WINAPI FreeAddrInfoExW( ADDRINFOEXW *ai )
+{
+ TRACE( "(%p)\n", ai );
+
+ while (ai)
+ {
+ ADDRINFOEXW *next;
+ HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
+ HeapFree( GetProcessHeap(), 0, ai->ai_addr );
+ next = ai->ai_next;
+ HeapFree( GetProcessHeap(), 0, ai );
+ ai = next;
+ }
+}
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index c2069198938..9e48fe256fd 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -29,138 +29,7 @@
#include "config.h"
#include "wine/port.h"
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <limits.h>
-#ifdef HAVE_SYS_IPC_H
-# include <sys/ipc.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h>
-#endif
-#ifdef HAVE_SYS_SOCKIO_H
-# include <sys/sockio.h>
-#endif
-
-#if defined(__EMX__)
-# include <sys/so_ioctl.h>
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-
-#ifdef HAVE_SYS_MSG_H
-# include <sys/msg.h>
-#endif
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-#ifdef HAVE_SYS_UIO_H
-# include <sys/uio.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_NETINET_TCP_H
-# include <netinet/tcp.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
-#include <ctype.h>
-#include <fcntl.h>
-#include <errno.h>
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#include <stdlib.h>
-#ifdef HAVE_ARPA_NAMESER_H
-# include <arpa/nameser.h>
-#endif
-#ifdef HAVE_RESOLV_H
-# include <resolv.h>
-#endif
-#ifdef HAVE_NET_IF_H
-# include <net/if.h>
-#endif
-#ifdef HAVE_LINUX_FILTER_H
-# include <linux/filter.h>
-#endif
-
-#ifdef HAVE_NETIPX_IPX_H
-# include <netipx/ipx.h>
-#elif defined(HAVE_LINUX_IPX_H)
-# ifdef HAVE_ASM_TYPES_H
-# include <asm/types.h>
-# endif
-# ifdef HAVE_LINUX_TYPES_H
-# include <linux/types.h>
-# endif
-# include <linux/ipx.h>
-#endif
-#if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS)
-# define HAS_IPX
-#endif
-
-#ifdef HAVE_LINUX_IRDA_H
-# ifdef HAVE_LINUX_TYPES_H
-# include <linux/types.h>
-# endif
-# include <linux/irda.h>
-# define HAS_IRDA
-#endif
-
-#ifdef HAVE_POLL_H
-#include <poll.h>
-#endif
-#ifdef HAVE_SYS_POLL_H
-# include <sys/poll.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
-#include "windef.h"
-#include "winbase.h"
-#include "wingdi.h"
-#include "winuser.h"
-#include "winerror.h"
-#include "winnls.h"
-#include "winsock2.h"
-#include "mswsock.h"
-#include "ws2tcpip.h"
-#include "ws2spi.h"
-#include "wsipx.h"
-#include "wsnwlink.h"
-#include "wshisotp.h"
-#include "mstcpip.h"
-#include "af_irda.h"
-#include "winnt.h"
-#define USE_WC_PREFIX /* For CMSG_DATA */
-#include "iphlpapi.h"
-#include "ip2string.h"
-#include "wine/afd.h"
-#include "wine/server.h"
-#include "wine/debug.h"
-#include "wine/exception.h"
-#include "wine/unicode.h"
-#include "wine/heap.h"
+#include "ws2_32_private.h"
#if defined(linux) && !defined(IP_UNICAST_IF)
#define IP_UNICAST_IF 50
@@ -300,8 +169,6 @@ static const WSAPROTOCOL_INFOW supported_protocols[] =
},
};
-#define IS_IPX_PROTO(X) ((X) >= WS_NSPROTO_IPX && (X) <= WS_NSPROTO_IPX + 255)
-
#if defined(IP_UNICAST_IF) && defined(SO_ATTACH_FILTER)
# define LINUX_BOUND_IF
struct interface_filter {
@@ -381,7 +248,7 @@ union generic_unix_sockaddr
char data[128]; /* should be big enough for all families */
};
-static inline const char *debugstr_sockaddr( const struct WS_sockaddr *a )
+const char *debugstr_sockaddr( const struct WS_sockaddr *a )
{
if (!a) return "(nil)";
switch (a->sa_family)
@@ -896,34 +763,6 @@ static const int ws_socktype_map[][2] =
{FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
};
-static const int ws_proto_map[][2] =
-{
- MAP_OPTION( IPPROTO_IP ),
- MAP_OPTION( IPPROTO_TCP ),
- MAP_OPTION( IPPROTO_UDP ),
- MAP_OPTION( IPPROTO_IPV6 ),
- MAP_OPTION( IPPROTO_ICMP ),
- MAP_OPTION( IPPROTO_IGMP ),
- MAP_OPTION( IPPROTO_RAW ),
- {WS_IPPROTO_IPV4, IPPROTO_IPIP},
- {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
-};
-
-static const int ws_aiflag_map[][2] =
-{
- MAP_OPTION( AI_PASSIVE ),
- MAP_OPTION( AI_CANONNAME ),
- MAP_OPTION( AI_NUMERICHOST ),
-#ifdef AI_NUMERICSERV
- MAP_OPTION( AI_NUMERICSERV ),
-#endif
-#ifdef AI_V4MAPPED
- MAP_OPTION( AI_V4MAPPED ),
-#endif
- MAP_OPTION( AI_ALL ),
- MAP_OPTION( AI_ADDRCONFIG ),
-};
-
static const int ws_niflag_map[][2] =
{
MAP_OPTION( NI_NOFQDN ),
@@ -933,30 +772,6 @@ static const int ws_niflag_map[][2] =
MAP_OPTION( NI_DGRAM ),
};
-static const int ws_eai_map[][2] =
-{
- MAP_OPTION( EAI_AGAIN ),
- MAP_OPTION( EAI_BADFLAGS ),
- MAP_OPTION( EAI_FAIL ),
- MAP_OPTION( EAI_FAMILY ),
- MAP_OPTION( EAI_MEMORY ),
-/* Note: EAI_NODATA is deprecated, but still
- * used by Windows and Linux... We map the newer
- * EAI_NONAME to EAI_NODATA for now until Windows
- * changes too.
- */
-#ifdef EAI_NODATA
- MAP_OPTION( EAI_NODATA ),
-#endif
-#ifdef EAI_NONAME
- { WS_EAI_NODATA, EAI_NONAME },
-#endif
-
- MAP_OPTION( EAI_SERVICE ),
- MAP_OPTION( EAI_SOCKTYPE ),
- { 0, 0 }
-};
-
static const int ws_poll_map[][2] =
{
MAP_OPTION( POLLERR ),
@@ -1103,7 +918,7 @@ static NTSTATUS sock_get_ntstatus( int err )
}
}
-static UINT sock_get_error( int err )
+UINT sock_get_error( int err )
{
switch(err)
{
@@ -1671,7 +1486,7 @@ static inline int do_block( int fd, int events, int timeout )
return pfd.revents;
}
-static int
+int
convert_af_w2u(int windowsaf) {
unsigned int i;
@@ -1682,7 +1497,7 @@ convert_af_w2u(int windowsaf) {
return -1;
}
-static int
+int
convert_af_u2w(int unixaf) {
unsigned int i;
@@ -1693,40 +1508,7 @@ convert_af_u2w(int unixaf) {
return -1;
}
-static int
-convert_proto_w2u(int windowsproto) {
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(ws_proto_map); i++)
- if (ws_proto_map[i][0] == windowsproto)
- return ws_proto_map[i][1];
-
- /* check for extended IPX */
- if (IS_IPX_PROTO(windowsproto))
- return windowsproto;
-
- FIXME("unhandled Windows socket protocol %d\n", windowsproto);
- return -1;
-}
-
-static int
-convert_proto_u2w(int unixproto) {
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(ws_proto_map); i++)
- if (ws_proto_map[i][1] == unixproto)
- return ws_proto_map[i][0];
-
- /* if value is inside IPX range just return it - the kernel simply
- * echoes the value used in the socket() function */
- if (IS_IPX_PROTO(unixproto))
- return unixproto;
-
- FIXME("unhandled UNIX socket protocol %d\n", unixproto);
- return -1;
-}
-
-static int
+int
convert_socktype_w2u(int windowssocktype) {
unsigned int i;
@@ -1737,7 +1519,7 @@ convert_socktype_w2u(int windowssocktype) {
return -1;
}
-static int
+int
convert_socktype_u2w(int unixsocktype) {
unsigned int i;
@@ -2130,7 +1912,7 @@ static int is_fd_bound(int fd, union generic_unix_sockaddr *uaddr, socklen_t *ua
}
/* Returns 0 if successful, -1 if the buffer is too small */
-static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, struct WS_sockaddr* wsaddr, int* wsaddrlen)
+int ws_sockaddr_u2ws(const struct sockaddr *uaddr, struct WS_sockaddr *wsaddr, int *wsaddrlen)
{
int res;
@@ -6430,37 +6212,6 @@ struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
return retval;
}
-/***********************************************************************
- * freeaddrinfo (WS2_32.@)
- */
-void WINAPI WS_freeaddrinfo(struct WS_addrinfo *res)
-{
- while (res) {
- struct WS_addrinfo *next;
-
- HeapFree(GetProcessHeap(),0,res->ai_canonname);
- HeapFree(GetProcessHeap(),0,res->ai_addr);
- next = res->ai_next;
- HeapFree(GetProcessHeap(),0,res);
- res = next;
- }
-}
-
-/* helper functions for getaddrinfo()/getnameinfo() */
-static int convert_aiflag_w2u(int winflags) {
- unsigned int i;
- int unixflags = 0;
-
- for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
- if (ws_aiflag_map[i][0] & winflags) {
- unixflags |= ws_aiflag_map[i][1];
- winflags &= ~ws_aiflag_map[i][0];
- }
- if (winflags)
- FIXME("Unhandled windows AI_xxx flags 0x%x\n", winflags);
- return unixflags;
-}
-
static int convert_niflag_w2u(int winflags) {
unsigned int i;
int unixflags = 0;
@@ -6475,631 +6226,6 @@ static int convert_niflag_w2u(int winflags) {
return unixflags;
}
-static int convert_aiflag_u2w(int unixflags) {
- unsigned int i;
- int winflags = 0;
-
- for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
- if (ws_aiflag_map[i][1] & unixflags) {
- winflags |= ws_aiflag_map[i][0];
- unixflags &= ~ws_aiflag_map[i][1];
- }
- if (unixflags)
- WARN("Unhandled UNIX AI_xxx flags 0x%x\n", unixflags);
- return winflags;
-}
-
-static int convert_eai_u2w(int unixret) {
- int i;
-
- if (!unixret) return 0;
-
- for (i=0;ws_eai_map[i][0];i++)
- if (ws_eai_map[i][1] == unixret)
- return ws_eai_map[i][0];
-
- if (unixret == EAI_SYSTEM)
- /* There are broken versions of glibc which return EAI_SYSTEM
- * and set errno to 0 instead of returning EAI_NONAME.
- */
- return errno ? sock_get_error( errno ) : WS_EAI_NONAME;
-
- FIXME("Unhandled unix EAI_xxx ret %d\n", unixret);
- return unixret;
-}
-
-static char *get_fqdn(void)
-{
- char *ret;
- DWORD size = 0;
-
- GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, NULL, &size );
- if (GetLastError() != ERROR_MORE_DATA) return NULL;
- if (!(ret = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
- if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, ret, &size ))
- {
- HeapFree( GetProcessHeap(), 0, ret );
- return NULL;
- }
- return ret;
-}
-
-static BOOL addrinfo_in_list( const struct WS_addrinfo *list, const struct WS_addrinfo *ai )
-{
- const struct WS_addrinfo *cursor = list;
- while (cursor)
- {
- if (ai->ai_flags == cursor->ai_flags && ai->ai_family == cursor->ai_family &&
- ai->ai_socktype == cursor->ai_socktype && ai->ai_protocol == cursor->ai_protocol &&
- ai->ai_addrlen == cursor->ai_addrlen && !memcmp(ai->ai_addr, cursor->ai_addr, ai->ai_addrlen) &&
- ((ai->ai_canonname && cursor->ai_canonname && !strcmp(ai->ai_canonname, cursor->ai_canonname))
- || (!ai->ai_canonname && !cursor->ai_canonname))) return TRUE;
- cursor = cursor->ai_next;
- }
- return FALSE;
-}
-
-/***********************************************************************
- * getaddrinfo (WS2_32.@)
- */
-int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addrinfo *hints, struct WS_addrinfo **res)
-{
-#ifdef HAVE_GETADDRINFO
- struct addrinfo *unixaires = NULL;
- int result;
- struct addrinfo unixhints, *punixhints = NULL;
- char *nodeV6 = NULL, *fqdn = NULL;
- const char *node;
-
- *res = NULL;
- if (!nodename && !servname)
- {
- SetLastError(WSAHOST_NOT_FOUND);
- return WSAHOST_NOT_FOUND;
- }
-
- if (!nodename)
- node = NULL;
- else if (!nodename[0])
- {
- if (!(fqdn = get_fqdn())) return WSA_NOT_ENOUGH_MEMORY;
- node = fqdn;
- }
- else
- {
- node = nodename;
-
- /* Check for [ipv6] or [ipv6]:portnumber, which are supported by Windows */
- if (!hints || hints->ai_family == WS_AF_UNSPEC || hints->ai_family == WS_AF_INET6)
- {
- char *close_bracket;
-
- if (node[0] == '[' && (close_bracket = strchr(node + 1, ']')))
- {
- nodeV6 = HeapAlloc(GetProcessHeap(), 0, close_bracket - node);
- if (!nodeV6) return WSA_NOT_ENOUGH_MEMORY;
- lstrcpynA(nodeV6, node + 1, close_bracket - node);
- node = nodeV6;
- }
- }
- }
-
- /* servname tweak required by OSX and BSD kernels */
- if (servname && !servname[0]) servname = "0";
-
- if (hints) {
- punixhints = &unixhints;
-
- memset(&unixhints, 0, sizeof(unixhints));
- punixhints->ai_flags = convert_aiflag_w2u(hints->ai_flags);
-
- /* zero is a wildcard, no need to convert */
- if (hints->ai_family)
- punixhints->ai_family = convert_af_w2u(hints->ai_family);
- if (hints->ai_socktype)
- punixhints->ai_socktype = convert_socktype_w2u(hints->ai_socktype);
- if (hints->ai_protocol)
- punixhints->ai_protocol = max(convert_proto_w2u(hints->ai_protocol), 0);
-
- if (punixhints->ai_socktype < 0)
- {
- SetLastError(WSAESOCKTNOSUPPORT);
- HeapFree(GetProcessHeap(), 0, fqdn);
- HeapFree(GetProcessHeap(), 0, nodeV6);
- return SOCKET_ERROR;
- }
-
- /* windows allows invalid combinations of socket type and protocol, unix does not.
- * fix the parameters here to make getaddrinfo call always work */
- if (punixhints->ai_protocol == IPPROTO_TCP &&
- punixhints->ai_socktype != SOCK_STREAM && punixhints->ai_socktype != SOCK_SEQPACKET)
- punixhints->ai_socktype = 0;
-
- else if (punixhints->ai_protocol == IPPROTO_UDP && punixhints->ai_socktype != SOCK_DGRAM)
- punixhints->ai_socktype = 0;
-
- else if (IS_IPX_PROTO(punixhints->ai_protocol) && punixhints->ai_socktype != SOCK_DGRAM)
- punixhints->ai_socktype = 0;
-
- else if (punixhints->ai_protocol == IPPROTO_IPV6)
- punixhints->ai_protocol = 0;
- }
-
- /* getaddrinfo(3) is thread safe, no need to wrap in CS */
- result = getaddrinfo(node, servname, punixhints, &unixaires);
-
- if (result && (!hints || !(hints->ai_flags & WS_AI_NUMERICHOST)) && node)
- {
- if (!fqdn && !(fqdn = get_fqdn()))
- {
- HeapFree(GetProcessHeap(), 0, nodeV6);
- return WSA_NOT_ENOUGH_MEMORY;
- }
- if (!strcmp(fqdn, node) || (!strncmp(fqdn, node, strlen(node)) && fqdn[strlen(node)] == '.'))
- {
- /* If it didn't work it means the host name IP is not in /etc/hosts, try again
- * by sending a NULL host and avoid sending a NULL servname too because that
- * is invalid */
- ERR_(winediag)("Failed to resolve your host name IP\n");
- result = getaddrinfo(NULL, servname ? servname : "0", punixhints, &unixaires);
- if (!result && punixhints && (punixhints->ai_flags & AI_CANONNAME) && unixaires && !unixaires->ai_canonname)
- {
- freeaddrinfo(unixaires);
- result = EAI_NONAME;
- }
- }
- }
- TRACE("%s, %s %p -> %p %d\n", debugstr_a(nodename), debugstr_a(servname), hints, res, result);
- HeapFree(GetProcessHeap(), 0, fqdn);
- HeapFree(GetProcessHeap(), 0, nodeV6);
-
- if (!result) {
- struct addrinfo *xuai = unixaires;
- struct WS_addrinfo **xai = res;
-
- *xai = NULL;
- while (xuai) {
- struct WS_addrinfo *ai = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo));
- SIZE_T len;
-
- if (!ai)
- goto outofmem;
-
- ai->ai_flags = convert_aiflag_u2w(xuai->ai_flags);
- ai->ai_family = convert_af_u2w(xuai->ai_family);
- /* copy whatever was sent in the hints */
- if(hints) {
- ai->ai_socktype = hints->ai_socktype;
- ai->ai_protocol = hints->ai_protocol;
- } else {
- ai->ai_socktype = convert_socktype_u2w(xuai->ai_socktype);
- ai->ai_protocol = convert_proto_u2w(xuai->ai_protocol);
- }
- if (xuai->ai_canonname) {
- TRACE("canon name - %s\n",debugstr_a(xuai->ai_canonname));
- ai->ai_canonname = HeapAlloc(GetProcessHeap(),0,strlen(xuai->ai_canonname)+1);
- if (!ai->ai_canonname)
- goto outofmem;
- strcpy(ai->ai_canonname,xuai->ai_canonname);
- }
- len = xuai->ai_addrlen;
- ai->ai_addr = HeapAlloc(GetProcessHeap(),0,len);
- if (!ai->ai_addr)
- goto outofmem;
- ai->ai_addrlen = len;
- do {
- int winlen = ai->ai_addrlen;
-
- if (!ws_sockaddr_u2ws(xuai->ai_addr, ai->ai_addr, &winlen)) {
- ai->ai_addrlen = winlen;
- break;
- }
- len = 2*len;
- ai->ai_addr = HeapReAlloc(GetProcessHeap(),0,ai->ai_addr,len);
- if (!ai->ai_addr)
- goto outofmem;
- ai->ai_addrlen = len;
- } while (1);
-
- if (addrinfo_in_list(*res, ai))
- {
- HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
- HeapFree(GetProcessHeap(), 0, ai->ai_addr);
- HeapFree(GetProcessHeap(), 0, ai);
- }
- else
- {
- *xai = ai;
- xai = &ai->ai_next;
- }
- xuai = xuai->ai_next;
- }
- freeaddrinfo(unixaires);
-
- if (TRACE_ON(winsock))
- {
- struct WS_addrinfo *ai = *res;
- while (ai)
- {
- TRACE("=> %p, flags %#x, family %d, type %d, protocol %d, len %ld, name %s, addr %s\n",
- ai, ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol, ai->ai_addrlen,
- ai->ai_canonname, debugstr_sockaddr(ai->ai_addr));
- ai = ai->ai_next;
- }
- }
- } else
- result = convert_eai_u2w(result);
-
- SetLastError(result);
- return result;
-
-outofmem:
- if (*res) WS_freeaddrinfo(*res);
- if (unixaires) freeaddrinfo(unixaires);
- return WSA_NOT_ENOUGH_MEMORY;
-#else
- FIXME("getaddrinfo() failed, not found during buildtime.\n");
- return EAI_FAIL;
-#endif
-}
-
-static ADDRINFOEXW *addrinfo_AtoW(const struct WS_addrinfo *ai)
-{
- ADDRINFOEXW *ret;
-
- if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ADDRINFOEXW)))) return NULL;
- ret->ai_flags = ai->ai_flags;
- ret->ai_family = ai->ai_family;
- ret->ai_socktype = ai->ai_socktype;
- ret->ai_protocol = ai->ai_protocol;
- ret->ai_addrlen = ai->ai_addrlen;
- ret->ai_canonname = NULL;
- ret->ai_addr = NULL;
- ret->ai_blob = NULL;
- ret->ai_bloblen = 0;
- ret->ai_provider = NULL;
- ret->ai_next = NULL;
- if (ai->ai_canonname)
- {
- int len = MultiByteToWideChar(CP_ACP, 0, ai->ai_canonname, -1, NULL, 0);
- if (!(ret->ai_canonname = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR))))
- {
- HeapFree(GetProcessHeap(), 0, ret);
- return NULL;
- }
- MultiByteToWideChar(CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len);
- }
- if (ai->ai_addr)
- {
- if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, ai->ai_addrlen)))
- {
- HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
- HeapFree(GetProcessHeap(), 0, ret);
- return NULL;
- }
- memcpy(ret->ai_addr, ai->ai_addr, ai->ai_addrlen);
- }
- return ret;
-}
-
-static ADDRINFOEXW *addrinfo_list_AtoW(const struct WS_addrinfo *info)
-{
- ADDRINFOEXW *ret, *infoW;
-
- if (!(ret = infoW = addrinfo_AtoW(info))) return NULL;
- while (info->ai_next)
- {
- if (!(infoW->ai_next = addrinfo_AtoW(info->ai_next)))
- {
- FreeAddrInfoExW(ret);
- return NULL;
- }
- infoW = infoW->ai_next;
- info = info->ai_next;
- }
- return ret;
-}
-
-static struct WS_addrinfo *addrinfo_WtoA(const struct WS_addrinfoW *ai)
-{
- struct WS_addrinfo *ret;
-
- if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_addrinfo)))) return NULL;
- ret->ai_flags = ai->ai_flags;
- ret->ai_family = ai->ai_family;
- ret->ai_socktype = ai->ai_socktype;
- ret->ai_protocol = ai->ai_protocol;
- ret->ai_addrlen = ai->ai_addrlen;
- ret->ai_canonname = NULL;
- ret->ai_addr = NULL;
- ret->ai_next = NULL;
- if (ai->ai_canonname)
- {
- int len = WideCharToMultiByte(CP_ACP, 0, ai->ai_canonname, -1, NULL, 0, NULL, NULL);
- if (!(ret->ai_canonname = HeapAlloc(GetProcessHeap(), 0, len)))
- {
- HeapFree(GetProcessHeap(), 0, ret);
- return NULL;
- }
- WideCharToMultiByte(CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len, NULL, NULL);
- }
- if (ai->ai_addr)
- {
- if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_sockaddr))))
- {
- HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
- HeapFree(GetProcessHeap(), 0, ret);
- return NULL;
- }
- memcpy(ret->ai_addr, ai->ai_addr, sizeof(struct WS_sockaddr));
- }
- return ret;
-}
-
-struct getaddrinfo_args
-{
- OVERLAPPED *overlapped;
- LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine;
- ADDRINFOEXW **result;
- char *nodename;
- char *servname;
-};
-
-static void WINAPI getaddrinfo_callback(TP_CALLBACK_INSTANCE *instance, void *context)
-{
- struct getaddrinfo_args *args = context;
- OVERLAPPED *overlapped = args->overlapped;
- HANDLE event = overlapped->hEvent;
- LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine = args->completion_routine;
- struct WS_addrinfo *res;
- int ret;
-
- ret = WS_getaddrinfo(args->nodename, args->servname, NULL, &res);
- if (res)
- {
- *args->result = addrinfo_list_AtoW(res);
- overlapped->u.Pointer = args->result;
- WS_freeaddrinfo(res);
- }
-
- HeapFree(GetProcessHeap(), 0, args->nodename);
- HeapFree(GetProcessHeap(), 0, args->servname);
- HeapFree(GetProcessHeap(), 0, args);
-
- overlapped->Internal = ret;
- if (completion_routine) completion_routine(ret, 0, overlapped);
- if (event) SetEvent(event);
-}
-
-static int WS_getaddrinfoW(const WCHAR *nodename, const WCHAR *servname, const struct WS_addrinfo *hints, ADDRINFOEXW **res,
- OVERLAPPED *overlapped, LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine)
-{
- int ret = EAI_MEMORY, len, i;
- char *nodenameA = NULL, *servnameA = NULL;
- struct WS_addrinfo *resA;
- WCHAR *local_nodenameW = (WCHAR *)nodename;
-
- *res = NULL;
- if (nodename)
- {
- /* Is this an IDN? Most likely if any char is above the Ascii table, this
- * is the simplest validation possible, further validation will be done by
- * the native getaddrinfo() */
- for (i = 0; nodename[i]; i++)
- {
- if (nodename[i] > 'z')
- break;
- }
- if (nodename[i])
- {
- if (hints && (hints->ai_flags & WS_AI_DISABLE_IDN_ENCODING))
- {
- /* Name requires conversion but it was disabled */
- ret = WSAHOST_NOT_FOUND;
- WSASetLastError(ret);
- goto end;
- }
-
- len = IdnToAscii(0, nodename, -1, NULL, 0);
- if (!len)
- {
- ERR("Failed to convert %s to punycode\n", debugstr_w(nodename));
- ret = EAI_FAIL;
- goto end;
- }
- if (!(local_nodenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) goto end;
- IdnToAscii(0, nodename, -1, local_nodenameW, len);
- }
- }
- if (local_nodenameW)
- {
- len = WideCharToMultiByte(CP_ACP, 0, local_nodenameW, -1, NULL, 0, NULL, NULL);
- if (!(nodenameA = HeapAlloc(GetProcessHeap(), 0, len))) goto end;
- WideCharToMultiByte(CP_ACP, 0, local_nodenameW, -1, nodenameA, len, NULL, NULL);
- }
- if (servname)
- {
- len = WideCharToMultiByte(CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL);
- if (!(servnameA = HeapAlloc(GetProcessHeap(), 0, len))) goto end;
- WideCharToMultiByte(CP_ACP, 0, servname, -1, servnameA, len, NULL, NULL);
- }
-
- if (overlapped)
- {
- struct getaddrinfo_args *args;
-
- if (overlapped->hEvent && completion_routine)
- {
- ret = WSAEINVAL;
- goto end;
- }
-
- if (!(args = HeapAlloc(GetProcessHeap(), 0, sizeof(*args)))) goto end;
- args->overlapped = overlapped;
- args->completion_routine = completion_routine;
- args->result = res;
- args->nodename = nodenameA;
- args->servname = servnameA;
-
- overlapped->Internal = WSAEINPROGRESS;
- if (!TrySubmitThreadpoolCallback(getaddrinfo_callback, args, NULL))
- {
- HeapFree(GetProcessHeap(), 0, args);
- ret = GetLastError();
- goto end;
- }
-
- if (local_nodenameW != nodename)
- HeapFree(GetProcessHeap(), 0, local_nodenameW);
- WSASetLastError(ERROR_IO_PENDING);
- return ERROR_IO_PENDING;
- }
-
- ret = WS_getaddrinfo(nodenameA, servnameA, hints, &resA);
- if (!ret)
- {
- *res = addrinfo_list_AtoW(resA);
- WS_freeaddrinfo(resA);
- }
-
-end:
- if (local_nodenameW != nodename)
- HeapFree(GetProcessHeap(), 0, local_nodenameW);
- HeapFree(GetProcessHeap(), 0, nodenameA);
- HeapFree(GetProcessHeap(), 0, servnameA);
- return ret;
-}
-
-/***********************************************************************
- * GetAddrInfoExW (WS2_32.@)
- */
-int WINAPI GetAddrInfoExW(const WCHAR *name, const WCHAR *servname, DWORD namespace, GUID *namespace_id,
- const ADDRINFOEXW *hints, ADDRINFOEXW **result, struct WS_timeval *timeout, OVERLAPPED *overlapped,
- LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine, HANDLE *handle)
-{
- int ret;
-
- TRACE("(%s %s %x %s %p %p %p %p %p %p)\n", debugstr_w(name), debugstr_w(servname), namespace,
- debugstr_guid(namespace_id), hints, result, timeout, overlapped, completion_routine, handle);
-
- if (namespace != NS_DNS)
- FIXME("Unsupported namespace %u\n", namespace);
- if (namespace_id)
- FIXME("Unsupported naemspace_id %s\n", debugstr_guid(namespace_id));
- if (hints)
- FIXME("Unsupported hints\n");
- if (timeout)
- FIXME("Unsupported timeout\n");
- if (handle)
- FIXME("Unsupported cancel handle\n");
-
- ret = WS_getaddrinfoW(name, servname, NULL, result, overlapped, completion_routine);
- if (ret) return ret;
- if (handle) *handle = (HANDLE)0xdeadbeef;
- return 0;
-}
-
-/***********************************************************************
- * GetAddrInfoExOverlappedResult (WS2_32.@)
- */
-int WINAPI GetAddrInfoExOverlappedResult(OVERLAPPED *overlapped)
-{
- TRACE("(%p)\n", overlapped);
- return overlapped->Internal;
-}
-
-/***********************************************************************
- * GetAddrInfoExCancel (WS2_32.@)
- */
-int WINAPI GetAddrInfoExCancel(HANDLE *handle)
-{
- FIXME("(%p)\n", handle);
- return WSA_INVALID_HANDLE;
-}
-
-/***********************************************************************
- * GetAddrInfoW (WS2_32.@)
- */
-int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hints, PADDRINFOW *res)
-{
- struct WS_addrinfo *hintsA = NULL;
- ADDRINFOEXW *resex;
- int ret = EAI_MEMORY;
-
- TRACE("nodename %s, servname %s, hints %p, result %p\n",
- debugstr_w(nodename), debugstr_w(servname), hints, res);
-
- *res = NULL;
- if (hints) hintsA = addrinfo_WtoA(hints);
- ret = WS_getaddrinfoW(nodename, servname, hintsA, &resex, NULL, NULL);
- WS_freeaddrinfo(hintsA);
- if (ret) return ret;
-
- if (resex)
- {
- /* ADDRINFOEXW has layout compatible with ADDRINFOW except for ai_next field,
- * so we may convert it in place */
- *res = (ADDRINFOW*)resex;
- do {
- ((ADDRINFOW*)resex)->ai_next = (ADDRINFOW*)resex->ai_next;
- resex = resex->ai_next;
- } while (resex);
- }
- return 0;
-}
-
-/***********************************************************************
- * FreeAddrInfoW (WS2_32.@)
- */
-void WINAPI FreeAddrInfoW(PADDRINFOW ai)
-{
- while (ai)
- {
- ADDRINFOW *next;
- HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
- HeapFree(GetProcessHeap(), 0, ai->ai_addr);
- next = ai->ai_next;
- HeapFree(GetProcessHeap(), 0, ai);
- ai = next;
- }
-}
-
-/***********************************************************************
- * FreeAddrInfoEx (WS2_32.@)
- */
-void WINAPI FreeAddrInfoEx(ADDRINFOEXA *ai)
-{
- TRACE("(%p)\n", ai);
-
- while (ai)
- {
- ADDRINFOEXA *next;
- HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
- HeapFree(GetProcessHeap(), 0, ai->ai_addr);
- next = ai->ai_next;
- HeapFree(GetProcessHeap(), 0, ai);
- ai = next;
- }
-}
-
-/***********************************************************************
- * FreeAddrInfoExW (WS2_32.@)
- */
-void WINAPI FreeAddrInfoExW(ADDRINFOEXW *ai)
-{
- TRACE("(%p)\n", ai);
-
- while (ai)
- {
- ADDRINFOEXW *next;
- HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
- HeapFree(GetProcessHeap(), 0, ai->ai_addr);
- next = ai->ai_next;
- HeapFree(GetProcessHeap(), 0, ai);
- ai = next;
- }
-}
-
int WINAPI WS_getnameinfo(const SOCKADDR *sa, WS_socklen_t salen, PCHAR host,
DWORD hostlen, PCHAR serv, DWORD servlen, INT flags)
{
diff --git a/dlls/ws2_32/ws2_32_private.h b/dlls/ws2_32/ws2_32_private.h
new file mode 100644
index 00000000000..8af23b11ded
--- /dev/null
+++ b/dlls/ws2_32/ws2_32_private.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2021 Zebediah Figura for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_WS2_32_PRIVATE_H
+#define __WINE_WS2_32_PRIVATE_H
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <limits.h>
+#ifdef HAVE_SYS_IPC_H
+# include <sys/ipc.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+#ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+#endif
+
+#if defined(__EMX__)
+# include <sys/so_ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_MSG_H
+# include <sys/msg.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+# include <sys/uio.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+# include <netinet/tcp.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdlib.h>
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+# include <resolv.h>
+#endif
+#ifdef HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#ifdef HAVE_LINUX_FILTER_H
+# include <linux/filter.h>
+#endif
+
+#ifdef HAVE_NETIPX_IPX_H
+# include <netipx/ipx.h>
+#elif defined(HAVE_LINUX_IPX_H)
+# ifdef HAVE_ASM_TYPES_H
+# include <asm/types.h>
+# endif
+# ifdef HAVE_LINUX_TYPES_H
+# include <linux/types.h>
+# endif
+# include <linux/ipx.h>
+#endif
+#if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS)
+# define HAS_IPX
+#endif
+
+#ifdef HAVE_LINUX_IRDA_H
+# ifdef HAVE_LINUX_TYPES_H
+# include <linux/types.h>
+# endif
+# include <linux/irda.h>
+# define HAS_IRDA
+#endif
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "winnls.h"
+#include "winsock2.h"
+#include "mswsock.h"
+#include "ws2tcpip.h"
+#include "ws2spi.h"
+#include "wsipx.h"
+#include "wsnwlink.h"
+#include "wshisotp.h"
+#include "mstcpip.h"
+#include "af_irda.h"
+#include "winnt.h"
+#define USE_WC_PREFIX /* For CMSG_DATA */
+#include "iphlpapi.h"
+#include "ip2string.h"
+#include "wine/afd.h"
+#include "wine/server.h"
+#include "wine/debug.h"
+#include "wine/exception.h"
+#include "wine/unicode.h"
+#include "wine/heap.h"
+
+int convert_af_u2w( int family ) DECLSPEC_HIDDEN;
+int convert_af_w2u( int family ) DECLSPEC_HIDDEN;
+int convert_eai_u2w( int ret ) DECLSPEC_HIDDEN;
+int convert_socktype_u2w( int type ) DECLSPEC_HIDDEN;
+int convert_socktype_w2u( int type ) DECLSPEC_HIDDEN;
+int ws_sockaddr_u2ws( const struct sockaddr *unix_addr, struct WS_sockaddr *win_addr,
+ int *win_addr_len ) DECLSPEC_HIDDEN;
+
+const char *debugstr_sockaddr( const struct WS_sockaddr *addr ) DECLSPEC_HIDDEN;
+
+UINT sock_get_error( int err ) DECLSPEC_HIDDEN;
+
+#endif
--
2.30.2
May 1, 2021