ws2_32: Reimplement SIO_GET_INTERFACE_LIST on top of GetIpAddrTable().
[wine.git] / dlls / ws2_32 / socket.c
blob6a5697608c5c777d259022316d793b51aa5d2574
1 /*
2 * based on Windows Sockets 1.1 specs
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
5 * Copyright (C) 2001 Stefan Leichter
6 * Copyright (C) 2004 Hans Leidekker
7 * Copyright (C) 2005 Marcus Meissner
8 * Copyright (C) 2006-2008 Kai Blin
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * NOTE: If you make any changes to fix a particular app, make sure
25 * they don't break something else like Netscape or telnet and ftp
26 * clients and servers (www.winsite.com got a lot of those).
29 #include "config.h"
30 #include "wine/port.h"
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <sys/types.h>
36 #include <limits.h>
37 #ifdef HAVE_SYS_IPC_H
38 # include <sys/ipc.h>
39 #endif
40 #ifdef HAVE_SYS_IOCTL_H
41 # include <sys/ioctl.h>
42 #endif
43 #ifdef HAVE_SYS_FILIO_H
44 # include <sys/filio.h>
45 #endif
46 #ifdef HAVE_SYS_SOCKIO_H
47 # include <sys/sockio.h>
48 #endif
50 #if defined(__EMX__)
51 # include <sys/so_ioctl.h>
52 #endif
54 #ifdef HAVE_SYS_PARAM_H
55 # include <sys/param.h>
56 #endif
58 #ifdef HAVE_SYS_MSG_H
59 # include <sys/msg.h>
60 #endif
61 #ifdef HAVE_SYS_WAIT_H
62 # include <sys/wait.h>
63 #endif
64 #ifdef HAVE_SYS_UIO_H
65 # include <sys/uio.h>
66 #endif
67 #ifdef HAVE_SYS_SOCKET_H
68 #include <sys/socket.h>
69 #endif
70 #ifdef HAVE_NETINET_IN_H
71 # include <netinet/in.h>
72 #endif
73 #ifdef HAVE_NETINET_TCP_H
74 # include <netinet/tcp.h>
75 #endif
76 #ifdef HAVE_ARPA_INET_H
77 # include <arpa/inet.h>
78 #endif
79 #include <ctype.h>
80 #include <fcntl.h>
81 #include <errno.h>
82 #ifdef HAVE_NETDB_H
83 #include <netdb.h>
84 #endif
85 #ifdef HAVE_UNISTD_H
86 # include <unistd.h>
87 #endif
88 #include <stdlib.h>
89 #ifdef HAVE_ARPA_NAMESER_H
90 # include <arpa/nameser.h>
91 #endif
92 #ifdef HAVE_RESOLV_H
93 # include <resolv.h>
94 #endif
95 #ifdef HAVE_NET_IF_H
96 # include <net/if.h>
97 #endif
98 #ifdef HAVE_LINUX_FILTER_H
99 # include <linux/filter.h>
100 #endif
102 #ifdef HAVE_NETIPX_IPX_H
103 # include <netipx/ipx.h>
104 #elif defined(HAVE_LINUX_IPX_H)
105 # ifdef HAVE_ASM_TYPES_H
106 # include <asm/types.h>
107 # endif
108 # ifdef HAVE_LINUX_TYPES_H
109 # include <linux/types.h>
110 # endif
111 # include <linux/ipx.h>
112 #endif
113 #if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS)
114 # define HAS_IPX
115 #endif
117 #ifdef HAVE_LINUX_IRDA_H
118 # ifdef HAVE_LINUX_TYPES_H
119 # include <linux/types.h>
120 # endif
121 # include <linux/irda.h>
122 # define HAS_IRDA
123 #endif
125 #ifdef HAVE_POLL_H
126 #include <poll.h>
127 #endif
128 #ifdef HAVE_SYS_POLL_H
129 # include <sys/poll.h>
130 #endif
131 #ifdef HAVE_SYS_TIME_H
132 # include <sys/time.h>
133 #endif
135 #define NONAMELESSUNION
136 #define NONAMELESSSTRUCT
137 #include "ntstatus.h"
138 #define WIN32_NO_STATUS
139 #include "windef.h"
140 #include "winbase.h"
141 #include "wingdi.h"
142 #include "winuser.h"
143 #include "winerror.h"
144 #include "winnls.h"
145 #include "winsock2.h"
146 #include "mswsock.h"
147 #include "ws2tcpip.h"
148 #include "ws2spi.h"
149 #include "wsipx.h"
150 #include "wsnwlink.h"
151 #include "wshisotp.h"
152 #include "mstcpip.h"
153 #include "af_irda.h"
154 #include "winnt.h"
155 #define USE_WC_PREFIX /* For CMSG_DATA */
156 #include "iphlpapi.h"
157 #include "ip2string.h"
158 #include "wine/afd.h"
159 #include "wine/server.h"
160 #include "wine/debug.h"
161 #include "wine/exception.h"
162 #include "wine/unicode.h"
163 #include "wine/heap.h"
165 #if defined(linux) && !defined(IP_UNICAST_IF)
166 #define IP_UNICAST_IF 50
167 #endif
169 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
170 # define sipx_network sipx_addr.x_net
171 # define sipx_node sipx_addr.x_host.c_host
172 #endif /* __FreeBSD__ */
174 #ifndef INADDR_NONE
175 #define INADDR_NONE ~0UL
176 #endif
178 #if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE)
179 /* TCP_KEEPALIVE is the Mac OS name for TCP_KEEPIDLE */
180 #define TCP_KEEPIDLE TCP_KEEPALIVE
181 #endif
183 #define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2)
185 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
186 WINE_DECLARE_DEBUG_CHANNEL(winediag);
188 static const WSAPROTOCOL_INFOW supported_protocols[] =
191 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_EXPEDITED_DATA | XP1_GRACEFUL_CLOSE
192 | XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY,
193 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
194 .ProviderId = {0xe70f1aa0, 0xab8b, 0x11cf, {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
195 .dwCatalogEntryId = 1001,
196 .ProtocolChain.ChainLen = 1,
197 .iVersion = 2,
198 .iAddressFamily = WS_AF_INET,
199 .iMaxSockAddr = sizeof(struct WS_sockaddr_in),
200 .iMinSockAddr = sizeof(struct WS_sockaddr_in),
201 .iSocketType = WS_SOCK_STREAM,
202 .iProtocol = WS_IPPROTO_TCP,
203 .szProtocol = {'T','C','P','/','I','P',0},
206 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST
207 | XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | XP1_CONNECTIONLESS,
208 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
209 .ProviderId = {0xe70f1aa0, 0xab8b, 0x11cf, {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
210 .dwCatalogEntryId = 1002,
211 .ProtocolChain.ChainLen = 1,
212 .iVersion = 2,
213 .iAddressFamily = WS_AF_INET,
214 .iMaxSockAddr = sizeof(struct WS_sockaddr_in),
215 .iMinSockAddr = sizeof(struct WS_sockaddr_in),
216 .iSocketType = WS_SOCK_DGRAM,
217 .iProtocol = WS_IPPROTO_UDP,
218 .dwMessageSize = 0xffbb,
219 .szProtocol = {'U','D','P','/','I','P',0},
222 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_EXPEDITED_DATA | XP1_GRACEFUL_CLOSE
223 | XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY,
224 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
225 .ProviderId = {0xf9eab0c0, 0x26d4, 0x11d0, {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},
226 .dwCatalogEntryId = 1004,
227 .ProtocolChain.ChainLen = 1,
228 .iVersion = 2,
229 .iAddressFamily = WS_AF_INET6,
230 .iMaxSockAddr = sizeof(struct WS_sockaddr_in6),
231 .iMinSockAddr = sizeof(struct WS_sockaddr_in6),
232 .iSocketType = WS_SOCK_STREAM,
233 .iProtocol = WS_IPPROTO_TCP,
234 .szProtocol = {'T','C','P','/','I','P','v','6',0},
237 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST
238 | XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | XP1_CONNECTIONLESS,
239 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
240 .ProviderId = {0xf9eab0c0, 0x26d4, 0x11d0, {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},
241 .dwCatalogEntryId = 1005,
242 .ProtocolChain.ChainLen = 1,
243 .iVersion = 2,
244 .iAddressFamily = WS_AF_INET6,
245 .iMaxSockAddr = sizeof(struct WS_sockaddr_in6),
246 .iMinSockAddr = sizeof(struct WS_sockaddr_in6),
247 .iSocketType = WS_SOCK_DGRAM,
248 .iProtocol = WS_IPPROTO_UDP,
249 .dwMessageSize = 0xffbb,
250 .szProtocol = {'U','D','P','/','I','P','v','6',0},
253 .dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_SUPPORT_BROADCAST
254 | XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | XP1_CONNECTIONLESS,
255 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
256 .ProviderId = {0x11058240, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
257 .dwCatalogEntryId = 1030,
258 .ProtocolChain.ChainLen = 1,
259 .iVersion = 2,
260 .iAddressFamily = WS_AF_IPX,
261 .iMaxSockAddr = sizeof(struct WS_sockaddr),
262 .iMinSockAddr = sizeof(struct WS_sockaddr_ipx),
263 .iSocketType = WS_SOCK_DGRAM,
264 .iProtocol = WS_NSPROTO_IPX,
265 .iProtocolMaxOffset = 255,
266 .dwMessageSize = 0x240,
267 .szProtocol = {'I','P','X',0},
270 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED
271 | XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY,
272 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
273 .ProviderId = {0x11058241, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
274 .dwCatalogEntryId = 1031,
275 .ProtocolChain.ChainLen = 1,
276 .iVersion = 2,
277 .iAddressFamily = WS_AF_IPX,
278 .iMaxSockAddr = sizeof(struct WS_sockaddr),
279 .iMinSockAddr = sizeof(struct WS_sockaddr_ipx),
280 .iSocketType = WS_SOCK_SEQPACKET,
281 .iProtocol = WS_NSPROTO_SPX,
282 .dwMessageSize = UINT_MAX,
283 .szProtocol = {'S','P','X',0},
286 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE | XP1_PSEUDO_STREAM
287 | XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY,
288 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
289 .ProviderId = {0x11058241, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
290 .dwCatalogEntryId = 1033,
291 .ProtocolChain.ChainLen = 1,
292 .iVersion = 2,
293 .iAddressFamily = WS_AF_IPX,
294 .iMaxSockAddr = sizeof(struct WS_sockaddr),
295 .iMinSockAddr = sizeof(struct WS_sockaddr_ipx),
296 .iSocketType = WS_SOCK_SEQPACKET,
297 .iProtocol = WS_NSPROTO_SPXII,
298 .dwMessageSize = UINT_MAX,
299 .szProtocol = {'S','P','X',' ','I','I',0},
303 #define IS_IPX_PROTO(X) ((X) >= WS_NSPROTO_IPX && (X) <= WS_NSPROTO_IPX + 255)
305 #if defined(IP_UNICAST_IF) && defined(SO_ATTACH_FILTER)
306 # define LINUX_BOUND_IF
307 struct interface_filter {
308 struct sock_filter iface_memaddr;
309 struct sock_filter iface_rule;
310 struct sock_filter ip_memaddr;
311 struct sock_filter ip_rule;
312 struct sock_filter return_keep;
313 struct sock_filter return_dump;
315 # define FILTER_JUMP_DUMP(here) (u_char)(offsetof(struct interface_filter, return_dump) \
316 -offsetof(struct interface_filter, here)-sizeof(struct sock_filter)) \
317 /sizeof(struct sock_filter)
318 # define FILTER_JUMP_KEEP(here) (u_char)(offsetof(struct interface_filter, return_keep) \
319 -offsetof(struct interface_filter, here)-sizeof(struct sock_filter)) \
320 /sizeof(struct sock_filter)
321 # define FILTER_JUMP_NEXT() (u_char)(0)
322 # define SKF_NET_DESTIP 16 /* offset in the network header to the destination IP */
323 static struct interface_filter generic_interface_filter = {
324 /* This filter rule allows incoming packets on the specified interface, which works for all
325 * remotely generated packets and for locally generated broadcast packets. */
326 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, SKF_AD_OFF+SKF_AD_IFINDEX),
327 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xdeadbeef, FILTER_JUMP_KEEP(iface_rule), FILTER_JUMP_NEXT()),
328 /* This rule allows locally generated packets targeted at the specific IP address of the chosen
329 * adapter (local packets not destined for the broadcast address do not have IFINDEX set) */
330 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, SKF_NET_OFF+SKF_NET_DESTIP),
331 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xdeadbeef, FILTER_JUMP_KEEP(ip_rule), FILTER_JUMP_DUMP(ip_rule)),
332 BPF_STMT(BPF_RET+BPF_K, (u_int)-1), /* keep packet */
333 BPF_STMT(BPF_RET+BPF_K, 0) /* dump packet */
335 #endif /* LINUX_BOUND_IF */
337 extern ssize_t CDECL __wine_locked_recvmsg( int fd, struct msghdr *hdr, int flags );
340 * The actual definition of WSASendTo, wrapped in a different function name
341 * so that internal calls from ws2_32 itself will not trigger programs like
342 * Garena, which hooks WSASendTo/WSARecvFrom calls.
344 static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
345 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
346 const struct WS_sockaddr *to, int tolen,
347 LPWSAOVERLAPPED lpOverlapped,
348 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine );
351 * Internal fundamental receive function, essentially WSARecvFrom with an
352 * additional parameter to support message control headers.
354 static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
355 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags,
356 struct WS_sockaddr *lpFrom,
357 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
358 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
359 LPWSABUF lpControlBuffer );
361 #define DECLARE_CRITICAL_SECTION(cs) \
362 static CRITICAL_SECTION cs; \
363 static CRITICAL_SECTION_DEBUG cs##_debug = \
364 { 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \
365 0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
366 static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 }
368 DECLARE_CRITICAL_SECTION(csWSgetXXXbyYYY);
369 DECLARE_CRITICAL_SECTION(cs_if_addr_cache);
370 DECLARE_CRITICAL_SECTION(cs_socket_list);
372 static in_addr_t *if_addr_cache;
373 static unsigned int if_addr_cache_size;
375 static SOCKET *socket_list;
376 static unsigned int socket_list_size;
378 union generic_unix_sockaddr
380 struct sockaddr addr;
381 char data[128]; /* should be big enough for all families */
384 static inline const char *debugstr_sockaddr( const struct WS_sockaddr *a )
386 if (!a) return "(nil)";
387 switch (a->sa_family)
389 case WS_AF_INET:
391 char buf[16];
392 const char *p;
393 struct WS_sockaddr_in *sin = (struct WS_sockaddr_in *)a;
395 p = WS_inet_ntop( WS_AF_INET, &sin->sin_addr, buf, sizeof(buf) );
396 if (!p)
397 p = "(unknown IPv4 address)";
399 return wine_dbg_sprintf("{ family AF_INET, address %s, port %d }",
400 p, ntohs(sin->sin_port));
402 case WS_AF_INET6:
404 char buf[46];
405 const char *p;
406 struct WS_sockaddr_in6 *sin = (struct WS_sockaddr_in6 *)a;
408 p = WS_inet_ntop( WS_AF_INET6, &sin->sin6_addr, buf, sizeof(buf) );
409 if (!p)
410 p = "(unknown IPv6 address)";
411 return wine_dbg_sprintf("{ family AF_INET6, address %s, port %d }",
412 p, ntohs(sin->sin6_port));
414 case WS_AF_IPX:
416 int i;
417 char netnum[16], nodenum[16];
418 struct WS_sockaddr_ipx *sin = (struct WS_sockaddr_ipx *)a;
420 for (i = 0;i < 4; i++) sprintf(netnum + i * 2, "%02X", (unsigned char) sin->sa_netnum[i]);
421 for (i = 0;i < 6; i++) sprintf(nodenum + i * 2, "%02X", (unsigned char) sin->sa_nodenum[i]);
423 return wine_dbg_sprintf("{ family AF_IPX, address %s.%s, ipx socket %d }",
424 netnum, nodenum, sin->sa_socket);
426 case WS_AF_IRDA:
428 DWORD addr;
430 memcpy( &addr, ((const SOCKADDR_IRDA *)a)->irdaDeviceID, sizeof(addr) );
431 addr = ntohl( addr );
432 return wine_dbg_sprintf("{ family AF_IRDA, addr %08x, name %s }",
433 addr,
434 ((const SOCKADDR_IRDA *)a)->irdaServiceName);
436 default:
437 return wine_dbg_sprintf("{ family %d }", a->sa_family);
441 static inline const char *debugstr_sockopt(int level, int optname)
443 const char *stropt = NULL, *strlevel = NULL;
445 #define DEBUG_SOCKLEVEL(x) case (x): strlevel = #x
446 #define DEBUG_SOCKOPT(x) case (x): stropt = #x; break
448 switch(level)
450 DEBUG_SOCKLEVEL(WS_SOL_SOCKET);
451 switch(optname)
453 DEBUG_SOCKOPT(WS_SO_ACCEPTCONN);
454 DEBUG_SOCKOPT(WS_SO_BROADCAST);
455 DEBUG_SOCKOPT(WS_SO_BSP_STATE);
456 DEBUG_SOCKOPT(WS_SO_CONDITIONAL_ACCEPT);
457 DEBUG_SOCKOPT(WS_SO_CONNECT_TIME);
458 DEBUG_SOCKOPT(WS_SO_DEBUG);
459 DEBUG_SOCKOPT(WS_SO_DONTLINGER);
460 DEBUG_SOCKOPT(WS_SO_DONTROUTE);
461 DEBUG_SOCKOPT(WS_SO_ERROR);
462 DEBUG_SOCKOPT(WS_SO_EXCLUSIVEADDRUSE);
463 DEBUG_SOCKOPT(WS_SO_GROUP_ID);
464 DEBUG_SOCKOPT(WS_SO_GROUP_PRIORITY);
465 DEBUG_SOCKOPT(WS_SO_KEEPALIVE);
466 DEBUG_SOCKOPT(WS_SO_LINGER);
467 DEBUG_SOCKOPT(WS_SO_MAX_MSG_SIZE);
468 DEBUG_SOCKOPT(WS_SO_OOBINLINE);
469 DEBUG_SOCKOPT(WS_SO_OPENTYPE);
470 DEBUG_SOCKOPT(WS_SO_PROTOCOL_INFOA);
471 DEBUG_SOCKOPT(WS_SO_PROTOCOL_INFOW);
472 DEBUG_SOCKOPT(WS_SO_RCVBUF);
473 DEBUG_SOCKOPT(WS_SO_RCVTIMEO);
474 DEBUG_SOCKOPT(WS_SO_REUSEADDR);
475 DEBUG_SOCKOPT(WS_SO_SNDBUF);
476 DEBUG_SOCKOPT(WS_SO_SNDTIMEO);
477 DEBUG_SOCKOPT(WS_SO_TYPE);
478 DEBUG_SOCKOPT(WS_SO_UPDATE_CONNECT_CONTEXT);
480 break;
482 DEBUG_SOCKLEVEL(WS_NSPROTO_IPX);
483 switch(optname)
485 DEBUG_SOCKOPT(WS_IPX_PTYPE);
486 DEBUG_SOCKOPT(WS_IPX_FILTERPTYPE);
487 DEBUG_SOCKOPT(WS_IPX_DSTYPE);
488 DEBUG_SOCKOPT(WS_IPX_RECVHDR);
489 DEBUG_SOCKOPT(WS_IPX_MAXSIZE);
490 DEBUG_SOCKOPT(WS_IPX_ADDRESS);
491 DEBUG_SOCKOPT(WS_IPX_MAX_ADAPTER_NUM);
493 break;
495 DEBUG_SOCKLEVEL(WS_SOL_IRLMP);
496 switch(optname)
498 DEBUG_SOCKOPT(WS_IRLMP_ENUMDEVICES);
500 break;
502 DEBUG_SOCKLEVEL(WS_IPPROTO_TCP);
503 switch(optname)
505 DEBUG_SOCKOPT(WS_TCP_BSDURGENT);
506 DEBUG_SOCKOPT(WS_TCP_EXPEDITED_1122);
507 DEBUG_SOCKOPT(WS_TCP_NODELAY);
509 break;
511 DEBUG_SOCKLEVEL(WS_IPPROTO_IP);
512 switch(optname)
514 DEBUG_SOCKOPT(WS_IP_ADD_MEMBERSHIP);
515 DEBUG_SOCKOPT(WS_IP_DONTFRAGMENT);
516 DEBUG_SOCKOPT(WS_IP_DROP_MEMBERSHIP);
517 DEBUG_SOCKOPT(WS_IP_HDRINCL);
518 DEBUG_SOCKOPT(WS_IP_MULTICAST_IF);
519 DEBUG_SOCKOPT(WS_IP_MULTICAST_LOOP);
520 DEBUG_SOCKOPT(WS_IP_MULTICAST_TTL);
521 DEBUG_SOCKOPT(WS_IP_OPTIONS);
522 DEBUG_SOCKOPT(WS_IP_PKTINFO);
523 DEBUG_SOCKOPT(WS_IP_RECEIVE_BROADCAST);
524 DEBUG_SOCKOPT(WS_IP_TOS);
525 DEBUG_SOCKOPT(WS_IP_TTL);
526 DEBUG_SOCKOPT(WS_IP_UNICAST_IF);
528 break;
530 DEBUG_SOCKLEVEL(WS_IPPROTO_IPV6);
531 switch(optname)
533 DEBUG_SOCKOPT(WS_IPV6_ADD_MEMBERSHIP);
534 DEBUG_SOCKOPT(WS_IPV6_DROP_MEMBERSHIP);
535 DEBUG_SOCKOPT(WS_IPV6_MULTICAST_IF);
536 DEBUG_SOCKOPT(WS_IPV6_MULTICAST_HOPS);
537 DEBUG_SOCKOPT(WS_IPV6_MULTICAST_LOOP);
538 DEBUG_SOCKOPT(WS_IPV6_UNICAST_HOPS);
539 DEBUG_SOCKOPT(WS_IPV6_V6ONLY);
540 DEBUG_SOCKOPT(WS_IPV6_UNICAST_IF);
541 DEBUG_SOCKOPT(WS_IPV6_DONTFRAG);
543 break;
545 #undef DEBUG_SOCKLEVEL
546 #undef DEBUG_SOCKOPT
548 if (!strlevel)
549 strlevel = wine_dbg_sprintf("WS_0x%x", level);
550 if (!stropt)
551 stropt = wine_dbg_sprintf("WS_0x%x", optname);
553 return wine_dbg_sprintf("level %s, name %s", strlevel + 3, stropt + 3);
556 static inline const char *debugstr_optval(const char *optval, int optlenval)
558 if (optval && !IS_INTRESOURCE(optval) && optlenval >= 1 && optlenval <= sizeof(DWORD))
560 DWORD value = 0;
561 memcpy(&value, optval, optlenval);
562 return wine_dbg_sprintf("%p (%u)", optval, value);
564 return wine_dbg_sprintf("%p", optval);
567 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
568 #define SOCKET2HANDLE(s) ((HANDLE)(s))
569 #define HANDLE2SOCKET(h) ((SOCKET)(h))
571 static BOOL socket_list_add(SOCKET socket)
573 unsigned int i, new_size;
574 SOCKET *new_array;
576 EnterCriticalSection(&cs_socket_list);
577 for (i = 0; i < socket_list_size; ++i)
579 if (!socket_list[i])
581 socket_list[i] = socket;
582 LeaveCriticalSection(&cs_socket_list);
583 return TRUE;
586 new_size = max(socket_list_size * 2, 8);
587 if (!(new_array = heap_realloc(socket_list, new_size * sizeof(*socket_list))))
589 LeaveCriticalSection(&cs_socket_list);
590 return FALSE;
592 socket_list = new_array;
593 memset(socket_list + socket_list_size, 0, (new_size - socket_list_size) * sizeof(*socket_list));
594 socket_list[socket_list_size] = socket;
595 socket_list_size = new_size;
596 LeaveCriticalSection(&cs_socket_list);
597 return TRUE;
600 static void socket_list_remove(SOCKET socket)
602 unsigned int i;
604 EnterCriticalSection(&cs_socket_list);
605 for (i = 0; i < socket_list_size; ++i)
607 if (socket_list[i] == socket)
609 socket_list[i] = 0;
610 break;
613 LeaveCriticalSection(&cs_socket_list);
616 /****************************************************************
617 * Async IO declarations
618 ****************************************************************/
620 typedef NTSTATUS async_callback_t( void *user, IO_STATUS_BLOCK *io, NTSTATUS status );
622 struct ws2_async_io
624 async_callback_t *callback; /* must be the first field */
625 struct ws2_async_io *next;
628 struct ws2_async_shutdown
630 struct ws2_async_io io;
631 HANDLE hSocket;
632 IO_STATUS_BLOCK iosb;
633 int type;
636 struct ws2_async
638 struct ws2_async_io io;
639 HANDLE hSocket;
640 LPWSAOVERLAPPED user_overlapped;
641 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
642 IO_STATUS_BLOCK local_iosb;
643 struct WS_sockaddr *addr;
644 union
646 int val; /* for send operations */
647 int *ptr; /* for recv operations */
648 } addrlen;
649 DWORD flags;
650 DWORD *lpFlags;
651 WSABUF *control;
652 unsigned int n_iovecs;
653 unsigned int first_iovec;
654 struct iovec iovec[1];
657 struct ws2_accept_async
659 struct ws2_async_io io;
660 HANDLE listen_socket;
661 HANDLE accept_socket;
662 LPOVERLAPPED user_overlapped;
663 ULONG_PTR cvalue;
664 PVOID buf; /* buffer to write data to */
665 int data_len;
666 int local_len;
667 int remote_len;
668 struct ws2_async *read;
671 struct ws2_transmitfile_async
673 struct ws2_async_io io;
674 char *buffer;
675 HANDLE file;
676 DWORD file_read;
677 DWORD file_bytes;
678 DWORD bytes_per_send;
679 TRANSMIT_FILE_BUFFERS buffers;
680 DWORD flags;
681 LARGE_INTEGER offset;
682 struct ws2_async write;
685 static struct ws2_async_io *async_io_freelist;
687 static void release_async_io( struct ws2_async_io *io )
689 for (;;)
691 struct ws2_async_io *next = async_io_freelist;
692 io->next = next;
693 if (InterlockedCompareExchangePointer( (void **)&async_io_freelist, io, next ) == next) return;
697 static struct ws2_async_io *alloc_async_io( DWORD size, async_callback_t callback )
699 /* first free remaining previous fileinfos */
701 struct ws2_async_io *io = InterlockedExchangePointer( (void **)&async_io_freelist, NULL );
703 while (io)
705 struct ws2_async_io *next = io->next;
706 HeapFree( GetProcessHeap(), 0, io );
707 io = next;
710 io = HeapAlloc( GetProcessHeap(), 0, size );
711 if (io) io->callback = callback;
712 return io;
715 static NTSTATUS register_async( int type, HANDLE handle, struct ws2_async_io *async, HANDLE event,
716 PIO_APC_ROUTINE apc, void *apc_context, IO_STATUS_BLOCK *io )
718 NTSTATUS status;
720 SERVER_START_REQ( register_async )
722 req->type = type;
723 req->async.handle = wine_server_obj_handle( handle );
724 req->async.user = wine_server_client_ptr( async );
725 req->async.iosb = wine_server_client_ptr( io );
726 req->async.event = wine_server_obj_handle( event );
727 req->async.apc = wine_server_client_ptr( apc );
728 req->async.apc_context = wine_server_client_ptr( apc_context );
729 status = wine_server_call( req );
731 SERVER_END_REQ;
733 return status;
736 /****************************************************************/
738 /* ----------------------------------- internal data */
740 /* ws_... struct conversion flags */
742 typedef struct /* WSAAsyncSelect() control struct */
744 HANDLE service, event, sock;
745 HWND hWnd;
746 UINT uMsg;
747 LONG lEvent;
748 } ws_select_info;
750 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
751 #define WS_MAX_UDP_DATAGRAM 1024
752 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
754 /* hostent's, servent's and protent's are stored in one buffer per thread,
755 * as documented on MSDN for the functions that return any of the buffers */
756 struct per_thread_data
758 int opentype;
759 struct WS_hostent *he_buffer;
760 struct WS_servent *se_buffer;
761 struct WS_protoent *pe_buffer;
762 struct pollfd *fd_cache;
763 unsigned int fd_count;
764 int he_len;
765 int se_len;
766 int pe_len;
767 char ntoa_buffer[16]; /* 4*3 digits + 3 '.' + 1 '\0' */
770 /* internal: routing description information */
771 struct route {
772 struct in_addr addr;
773 IF_INDEX interface;
774 DWORD metric, default_route;
777 static INT num_startup; /* reference counter */
778 static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
780 /* function prototypes */
781 static struct WS_hostent *WS_create_he(char *name, int aliases, int aliases_size, int addresses, int address_length);
782 static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
783 static struct WS_protoent *WS_create_pe( const char *name, char **aliases, int prot );
784 static struct WS_servent *WS_dup_se(const struct servent* p_se);
785 static int ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size);
787 int WSAIOCTL_GetInterfaceCount(void);
788 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
790 static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus, ULONG Information, BOOL force );
792 #define MAP_OPTION(opt) { WS_##opt, opt }
794 static const int ws_flags_map[][2] =
796 MAP_OPTION( MSG_OOB ),
797 MAP_OPTION( MSG_PEEK ),
798 MAP_OPTION( MSG_DONTROUTE ),
799 MAP_OPTION( MSG_WAITALL ),
800 { WS_MSG_PARTIAL, 0 },
803 static const int ws_sock_map[][2] =
805 MAP_OPTION( SO_DEBUG ),
806 MAP_OPTION( SO_ACCEPTCONN ),
807 MAP_OPTION( SO_REUSEADDR ),
808 MAP_OPTION( SO_KEEPALIVE ),
809 MAP_OPTION( SO_DONTROUTE ),
810 MAP_OPTION( SO_BROADCAST ),
811 MAP_OPTION( SO_LINGER ),
812 MAP_OPTION( SO_OOBINLINE ),
813 MAP_OPTION( SO_SNDBUF ),
814 MAP_OPTION( SO_RCVBUF ),
815 MAP_OPTION( SO_ERROR ),
816 MAP_OPTION( SO_TYPE ),
817 #ifdef SO_RCVTIMEO
818 MAP_OPTION( SO_RCVTIMEO ),
819 #endif
820 #ifdef SO_SNDTIMEO
821 MAP_OPTION( SO_SNDTIMEO ),
822 #endif
825 static const int ws_tcp_map[][2] =
827 #ifdef TCP_NODELAY
828 MAP_OPTION( TCP_NODELAY ),
829 #endif
832 static const int ws_ip_map[][2] =
834 MAP_OPTION( IP_MULTICAST_IF ),
835 MAP_OPTION( IP_MULTICAST_TTL ),
836 MAP_OPTION( IP_MULTICAST_LOOP ),
837 MAP_OPTION( IP_ADD_MEMBERSHIP ),
838 MAP_OPTION( IP_DROP_MEMBERSHIP ),
839 MAP_OPTION( IP_ADD_SOURCE_MEMBERSHIP ),
840 MAP_OPTION( IP_DROP_SOURCE_MEMBERSHIP ),
841 MAP_OPTION( IP_BLOCK_SOURCE ),
842 MAP_OPTION( IP_UNBLOCK_SOURCE ),
843 MAP_OPTION( IP_OPTIONS ),
844 #ifdef IP_HDRINCL
845 MAP_OPTION( IP_HDRINCL ),
846 #endif
847 MAP_OPTION( IP_TOS ),
848 MAP_OPTION( IP_TTL ),
849 #if defined(IP_PKTINFO)
850 MAP_OPTION( IP_PKTINFO ),
851 #elif defined(IP_RECVDSTADDR)
852 { WS_IP_PKTINFO, IP_RECVDSTADDR },
853 #endif
854 #ifdef IP_UNICAST_IF
855 MAP_OPTION( IP_UNICAST_IF ),
856 #endif
859 static const int ws_ipv6_map[][2] =
861 #ifdef IPV6_ADD_MEMBERSHIP
862 MAP_OPTION( IPV6_ADD_MEMBERSHIP ),
863 #endif
864 #ifdef IPV6_DROP_MEMBERSHIP
865 MAP_OPTION( IPV6_DROP_MEMBERSHIP ),
866 #endif
867 MAP_OPTION( IPV6_MULTICAST_IF ),
868 MAP_OPTION( IPV6_MULTICAST_HOPS ),
869 MAP_OPTION( IPV6_MULTICAST_LOOP ),
870 MAP_OPTION( IPV6_UNICAST_HOPS ),
871 MAP_OPTION( IPV6_V6ONLY ),
872 #ifdef IPV6_UNICAST_IF
873 MAP_OPTION( IPV6_UNICAST_IF ),
874 #endif
877 static const int ws_af_map[][2] =
879 MAP_OPTION( AF_UNSPEC ),
880 MAP_OPTION( AF_INET ),
881 MAP_OPTION( AF_INET6 ),
882 #ifdef HAS_IPX
883 MAP_OPTION( AF_IPX ),
884 #endif
885 #ifdef AF_IRDA
886 MAP_OPTION( AF_IRDA ),
887 #endif
888 {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
891 static const int ws_socktype_map[][2] =
893 MAP_OPTION( SOCK_DGRAM ),
894 MAP_OPTION( SOCK_STREAM ),
895 MAP_OPTION( SOCK_RAW ),
896 {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
899 static const int ws_proto_map[][2] =
901 MAP_OPTION( IPPROTO_IP ),
902 MAP_OPTION( IPPROTO_TCP ),
903 MAP_OPTION( IPPROTO_UDP ),
904 MAP_OPTION( IPPROTO_IPV6 ),
905 MAP_OPTION( IPPROTO_ICMP ),
906 MAP_OPTION( IPPROTO_IGMP ),
907 MAP_OPTION( IPPROTO_RAW ),
908 MAP_OPTION( IPPROTO_IPIP ),
909 {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
912 static const int ws_aiflag_map[][2] =
914 MAP_OPTION( AI_PASSIVE ),
915 MAP_OPTION( AI_CANONNAME ),
916 MAP_OPTION( AI_NUMERICHOST ),
917 #ifdef AI_NUMERICSERV
918 MAP_OPTION( AI_NUMERICSERV ),
919 #endif
920 #ifdef AI_V4MAPPED
921 MAP_OPTION( AI_V4MAPPED ),
922 #endif
923 MAP_OPTION( AI_ALL ),
924 MAP_OPTION( AI_ADDRCONFIG ),
927 static const int ws_niflag_map[][2] =
929 MAP_OPTION( NI_NOFQDN ),
930 MAP_OPTION( NI_NUMERICHOST ),
931 MAP_OPTION( NI_NAMEREQD ),
932 MAP_OPTION( NI_NUMERICSERV ),
933 MAP_OPTION( NI_DGRAM ),
936 static const int ws_eai_map[][2] =
938 MAP_OPTION( EAI_AGAIN ),
939 MAP_OPTION( EAI_BADFLAGS ),
940 MAP_OPTION( EAI_FAIL ),
941 MAP_OPTION( EAI_FAMILY ),
942 MAP_OPTION( EAI_MEMORY ),
943 /* Note: EAI_NODATA is deprecated, but still
944 * used by Windows and Linux... We map the newer
945 * EAI_NONAME to EAI_NODATA for now until Windows
946 * changes too.
948 #ifdef EAI_NODATA
949 MAP_OPTION( EAI_NODATA ),
950 #endif
951 #ifdef EAI_NONAME
952 { WS_EAI_NODATA, EAI_NONAME },
953 #endif
955 MAP_OPTION( EAI_SERVICE ),
956 MAP_OPTION( EAI_SOCKTYPE ),
957 { 0, 0 }
960 static const int ws_poll_map[][2] =
962 MAP_OPTION( POLLERR ),
963 MAP_OPTION( POLLHUP ),
964 MAP_OPTION( POLLNVAL ),
965 MAP_OPTION( POLLWRNORM ),
966 MAP_OPTION( POLLWRBAND ),
967 MAP_OPTION( POLLRDNORM ),
968 { WS_POLLRDBAND, POLLPRI }
971 static const char magic_loopback_addr[] = {127, 12, 34, 56};
973 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
974 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
975 static inline WSACMSGHDR *fill_control_message(int level, int type, WSACMSGHDR *current, ULONG *maxsize, void *data, int len)
977 ULONG msgsize = sizeof(WSACMSGHDR) + WSA_CMSG_ALIGN(len);
978 char *ptr = (char *) current + sizeof(WSACMSGHDR);
980 /* Make sure there is at least enough room for this entry */
981 if (msgsize > *maxsize)
982 return NULL;
983 *maxsize -= msgsize;
984 /* Fill in the entry */
985 current->cmsg_len = sizeof(WSACMSGHDR) + len;
986 current->cmsg_level = level;
987 current->cmsg_type = type;
988 memcpy(ptr, data, len);
989 /* Return the pointer to where next entry should go */
990 return (WSACMSGHDR *) (ptr + WSA_CMSG_ALIGN(len));
992 #endif /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
994 static inline int convert_control_headers(struct msghdr *hdr, WSABUF *control)
996 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
997 WSACMSGHDR *cmsg_win = (WSACMSGHDR *) control->buf, *ptr;
998 ULONG ctlsize = control->len;
999 struct cmsghdr *cmsg_unix;
1001 ptr = cmsg_win;
1002 /* Loop over all the headers, converting as appropriate */
1003 for (cmsg_unix = CMSG_FIRSTHDR(hdr); cmsg_unix != NULL; cmsg_unix = CMSG_NXTHDR(hdr, cmsg_unix))
1005 switch(cmsg_unix->cmsg_level)
1007 case IPPROTO_IP:
1008 switch(cmsg_unix->cmsg_type)
1010 #if defined(IP_PKTINFO)
1011 case IP_PKTINFO:
1013 /* Convert the Unix IP_PKTINFO structure to the Windows version */
1014 struct in_pktinfo *data_unix = (struct in_pktinfo *) CMSG_DATA(cmsg_unix);
1015 struct WS_in_pktinfo data_win;
1017 memcpy(&data_win.ipi_addr,&data_unix->ipi_addr.s_addr,4); /* 4 bytes = 32 address bits */
1018 data_win.ipi_ifindex = data_unix->ipi_ifindex;
1019 ptr = fill_control_message(WS_IPPROTO_IP, WS_IP_PKTINFO, ptr, &ctlsize,
1020 (void*)&data_win, sizeof(data_win));
1021 if (!ptr) goto error;
1022 } break;
1023 #elif defined(IP_RECVDSTADDR)
1024 case IP_RECVDSTADDR:
1026 struct in_addr *addr_unix = (struct in_addr *) CMSG_DATA(cmsg_unix);
1027 struct WS_in_pktinfo data_win;
1029 memcpy(&data_win.ipi_addr, &addr_unix->s_addr, 4); /* 4 bytes = 32 address bits */
1030 data_win.ipi_ifindex = 0; /* FIXME */
1031 ptr = fill_control_message(WS_IPPROTO_IP, WS_IP_PKTINFO, ptr, &ctlsize,
1032 (void*)&data_win, sizeof(data_win));
1033 if (!ptr) goto error;
1034 } break;
1035 #endif /* IP_PKTINFO */
1036 default:
1037 FIXME("Unhandled IPPROTO_IP message header type %d\n", cmsg_unix->cmsg_type);
1038 break;
1040 break;
1041 default:
1042 FIXME("Unhandled message header level %d\n", cmsg_unix->cmsg_level);
1043 break;
1047 /* Set the length of the returned control headers */
1048 control->len = (char*)ptr - (char*)cmsg_win;
1049 return 1;
1050 error:
1051 control->len = 0;
1052 return 0;
1053 #else /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
1054 control->len = 0;
1055 return 1;
1056 #endif /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
1058 #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
1060 /* ----------------------------------- error handling */
1062 static NTSTATUS sock_get_ntstatus( int err )
1064 switch ( err )
1066 case EBADF: return STATUS_INVALID_HANDLE;
1067 case EBUSY: return STATUS_DEVICE_BUSY;
1068 case EPERM:
1069 case EACCES: return STATUS_ACCESS_DENIED;
1070 case EFAULT: return STATUS_NO_MEMORY;
1071 case EINVAL: return STATUS_INVALID_PARAMETER;
1072 case ENFILE:
1073 case EMFILE: return STATUS_TOO_MANY_OPENED_FILES;
1074 case EWOULDBLOCK: return STATUS_CANT_WAIT;
1075 case EINPROGRESS: return STATUS_PENDING;
1076 case EALREADY: return STATUS_NETWORK_BUSY;
1077 case ENOTSOCK: return STATUS_OBJECT_TYPE_MISMATCH;
1078 case EDESTADDRREQ: return STATUS_INVALID_PARAMETER;
1079 case EMSGSIZE: return STATUS_BUFFER_OVERFLOW;
1080 case EPROTONOSUPPORT:
1081 case ESOCKTNOSUPPORT:
1082 case EPFNOSUPPORT:
1083 case EAFNOSUPPORT:
1084 case EPROTOTYPE: return STATUS_NOT_SUPPORTED;
1085 case ENOPROTOOPT: return STATUS_INVALID_PARAMETER;
1086 case EOPNOTSUPP: return STATUS_NOT_SUPPORTED;
1087 case EADDRINUSE: return STATUS_ADDRESS_ALREADY_ASSOCIATED;
1088 case EADDRNOTAVAIL: return STATUS_INVALID_PARAMETER;
1089 case ECONNREFUSED: return STATUS_CONNECTION_REFUSED;
1090 case ESHUTDOWN: return STATUS_PIPE_DISCONNECTED;
1091 case ENOTCONN: return STATUS_CONNECTION_DISCONNECTED;
1092 case ETIMEDOUT: return STATUS_IO_TIMEOUT;
1093 case ENETUNREACH: return STATUS_NETWORK_UNREACHABLE;
1094 case ENETDOWN: return STATUS_NETWORK_BUSY;
1095 case EPIPE:
1096 case ECONNRESET: return STATUS_CONNECTION_RESET;
1097 case ECONNABORTED: return STATUS_CONNECTION_ABORTED;
1099 case 0: return STATUS_SUCCESS;
1100 default:
1101 WARN("Unknown errno %d!\n", err);
1102 return STATUS_UNSUCCESSFUL;
1106 static UINT sock_get_error( int err )
1108 switch(err)
1110 case EINTR: return WSAEINTR;
1111 case EPERM:
1112 case EACCES: return WSAEACCES;
1113 case EFAULT: return WSAEFAULT;
1114 case EINVAL: return WSAEINVAL;
1115 case EMFILE: return WSAEMFILE;
1116 case EWOULDBLOCK: return WSAEWOULDBLOCK;
1117 case EINPROGRESS: return WSAEINPROGRESS;
1118 case EALREADY: return WSAEALREADY;
1119 case EBADF:
1120 case ENOTSOCK: return WSAENOTSOCK;
1121 case EDESTADDRREQ: return WSAEDESTADDRREQ;
1122 case EMSGSIZE: return WSAEMSGSIZE;
1123 case EPROTOTYPE: return WSAEPROTOTYPE;
1124 case ENOPROTOOPT: return WSAENOPROTOOPT;
1125 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
1126 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
1127 case EOPNOTSUPP: return WSAEOPNOTSUPP;
1128 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
1129 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
1130 case EADDRINUSE: return WSAEADDRINUSE;
1131 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
1132 case ENETDOWN: return WSAENETDOWN;
1133 case ENETUNREACH: return WSAENETUNREACH;
1134 case ENETRESET: return WSAENETRESET;
1135 case ECONNABORTED: return WSAECONNABORTED;
1136 case EPIPE:
1137 case ECONNRESET: return WSAECONNRESET;
1138 case ENOBUFS: return WSAENOBUFS;
1139 case EISCONN: return WSAEISCONN;
1140 case ENOTCONN: return WSAENOTCONN;
1141 case ESHUTDOWN: return WSAESHUTDOWN;
1142 case ETOOMANYREFS: return WSAETOOMANYREFS;
1143 case ETIMEDOUT: return WSAETIMEDOUT;
1144 case ECONNREFUSED: return WSAECONNREFUSED;
1145 case ELOOP: return WSAELOOP;
1146 case ENAMETOOLONG: return WSAENAMETOOLONG;
1147 case EHOSTDOWN: return WSAEHOSTDOWN;
1148 case EHOSTUNREACH: return WSAEHOSTUNREACH;
1149 case ENOTEMPTY: return WSAENOTEMPTY;
1150 #ifdef EPROCLIM
1151 case EPROCLIM: return WSAEPROCLIM;
1152 #endif
1153 #ifdef EUSERS
1154 case EUSERS: return WSAEUSERS;
1155 #endif
1156 #ifdef EDQUOT
1157 case EDQUOT: return WSAEDQUOT;
1158 #endif
1159 #ifdef ESTALE
1160 case ESTALE: return WSAESTALE;
1161 #endif
1162 #ifdef EREMOTE
1163 case EREMOTE: return WSAEREMOTE;
1164 #endif
1166 /* just in case we ever get here and there are no problems */
1167 case 0: return 0;
1168 default:
1169 WARN("Unknown errno %d!\n", err);
1170 return WSAEOPNOTSUPP;
1174 static UINT wsaErrno(void)
1176 int loc_errno = errno;
1177 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
1179 return sock_get_error( loc_errno );
1182 /* most ws2 overlapped functions return an ntstatus-based error code */
1183 static NTSTATUS wsaErrStatus(void)
1185 int loc_errno = errno;
1186 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
1188 return sock_get_ntstatus(loc_errno);
1191 static UINT wsaHerrno(int loc_errno)
1193 WARN("h_errno %d.\n", loc_errno);
1195 switch(loc_errno)
1197 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
1198 case TRY_AGAIN: return WSATRY_AGAIN;
1199 case NO_RECOVERY: return WSANO_RECOVERY;
1200 case NO_DATA: return WSANO_DATA;
1201 case ENOBUFS: return WSAENOBUFS;
1203 case 0: return 0;
1204 default:
1205 WARN("Unknown h_errno %d!\n", loc_errno);
1206 return WSAEOPNOTSUPP;
1210 static NTSTATUS sock_error_to_ntstatus( DWORD err )
1212 switch (err)
1214 case 0: return STATUS_SUCCESS;
1215 case WSAEBADF: return STATUS_INVALID_HANDLE;
1216 case WSAEACCES: return STATUS_ACCESS_DENIED;
1217 case WSAEFAULT: return STATUS_NO_MEMORY;
1218 case WSAEINVAL: return STATUS_INVALID_PARAMETER;
1219 case WSAEMFILE: return STATUS_TOO_MANY_OPENED_FILES;
1220 case WSAEWOULDBLOCK: return STATUS_CANT_WAIT;
1221 case WSAEINPROGRESS: return STATUS_PENDING;
1222 case WSAEALREADY: return STATUS_NETWORK_BUSY;
1223 case WSAENOTSOCK: return STATUS_OBJECT_TYPE_MISMATCH;
1224 case WSAEDESTADDRREQ: return STATUS_INVALID_PARAMETER;
1225 case WSAEMSGSIZE: return STATUS_BUFFER_OVERFLOW;
1226 case WSAEPROTONOSUPPORT:
1227 case WSAESOCKTNOSUPPORT:
1228 case WSAEPFNOSUPPORT:
1229 case WSAEAFNOSUPPORT:
1230 case WSAEPROTOTYPE: return STATUS_NOT_SUPPORTED;
1231 case WSAENOPROTOOPT: return STATUS_INVALID_PARAMETER;
1232 case WSAEOPNOTSUPP: return STATUS_NOT_SUPPORTED;
1233 case WSAEADDRINUSE: return STATUS_ADDRESS_ALREADY_ASSOCIATED;
1234 case WSAEADDRNOTAVAIL: return STATUS_INVALID_PARAMETER;
1235 case WSAECONNREFUSED: return STATUS_CONNECTION_REFUSED;
1236 case WSAESHUTDOWN: return STATUS_PIPE_DISCONNECTED;
1237 case WSAENOTCONN: return STATUS_CONNECTION_DISCONNECTED;
1238 case WSAETIMEDOUT: return STATUS_IO_TIMEOUT;
1239 case WSAENETUNREACH: return STATUS_NETWORK_UNREACHABLE;
1240 case WSAENETDOWN: return STATUS_NETWORK_BUSY;
1241 case WSAECONNRESET: return STATUS_CONNECTION_RESET;
1242 case WSAECONNABORTED: return STATUS_CONNECTION_ABORTED;
1243 default:
1244 FIXME("unmapped error %u\n", err);
1245 return STATUS_UNSUCCESSFUL;
1249 static DWORD NtStatusToWSAError( DWORD status )
1251 switch ( status )
1253 case STATUS_SUCCESS: return 0;
1254 case STATUS_PENDING: return WSA_IO_PENDING;
1255 case STATUS_INVALID_HANDLE:
1256 case STATUS_OBJECT_TYPE_MISMATCH: return WSAENOTSOCK;
1257 case STATUS_INVALID_PARAMETER: return WSAEINVAL;
1258 case STATUS_PIPE_DISCONNECTED: return WSAESHUTDOWN;
1259 case STATUS_NETWORK_BUSY: return WSAEALREADY;
1260 case STATUS_NETWORK_UNREACHABLE: return WSAENETUNREACH;
1261 case STATUS_CONNECTION_REFUSED: return WSAECONNREFUSED;
1262 case STATUS_CONNECTION_DISCONNECTED: return WSAENOTCONN;
1263 case STATUS_CONNECTION_RESET: return WSAECONNRESET;
1264 case STATUS_CONNECTION_ABORTED: return WSAECONNABORTED;
1265 case STATUS_CANCELLED: return WSA_OPERATION_ABORTED;
1266 case STATUS_ADDRESS_ALREADY_ASSOCIATED: return WSAEADDRINUSE;
1267 case STATUS_IO_TIMEOUT:
1268 case STATUS_TIMEOUT: return WSAETIMEDOUT;
1269 case STATUS_NO_MEMORY: return WSAEFAULT;
1270 case STATUS_ACCESS_DENIED: return WSAEACCES;
1271 case STATUS_TOO_MANY_OPENED_FILES: return WSAEMFILE;
1272 case STATUS_CANT_WAIT: return WSAEWOULDBLOCK;
1273 case STATUS_BUFFER_OVERFLOW: return WSAEMSGSIZE;
1274 case STATUS_NOT_SUPPORTED: return WSAEOPNOTSUPP;
1275 case STATUS_HOST_UNREACHABLE: return WSAEHOSTUNREACH;
1276 default: return RtlNtStatusToDosError( status );
1280 /* set last error code from NT status without mapping WSA errors */
1281 static inline unsigned int set_error( unsigned int err )
1283 if (err)
1285 err = NtStatusToWSAError( err );
1286 SetLastError( err );
1288 return err;
1291 static inline int get_sock_fd( SOCKET s, DWORD access, unsigned int *options )
1293 int fd;
1294 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, options ) ))
1295 return -1;
1296 return fd;
1299 static inline void release_sock_fd( SOCKET s, int fd )
1301 wine_server_release_fd( SOCKET2HANDLE(s), fd );
1304 static void _enable_event( HANDLE s, unsigned int event,
1305 unsigned int sstate, unsigned int cstate )
1307 SERVER_START_REQ( enable_socket_event )
1309 req->handle = wine_server_obj_handle( s );
1310 req->mask = event;
1311 req->sstate = sstate;
1312 req->cstate = cstate;
1313 wine_server_call( req );
1315 SERVER_END_REQ;
1318 static DWORD sock_is_blocking(SOCKET s, BOOL *ret)
1320 DWORD err;
1321 SERVER_START_REQ( get_socket_event )
1323 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
1324 req->service = FALSE;
1325 req->c_event = 0;
1326 err = NtStatusToWSAError( wine_server_call( req ));
1327 *ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
1329 SERVER_END_REQ;
1330 return err;
1333 static unsigned int _get_sock_mask(SOCKET s)
1335 unsigned int ret;
1336 SERVER_START_REQ( get_socket_event )
1338 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
1339 req->service = FALSE;
1340 req->c_event = 0;
1341 wine_server_call( req );
1342 ret = reply->mask;
1344 SERVER_END_REQ;
1345 return ret;
1348 static void _sync_sock_state(SOCKET s)
1350 BOOL dummy;
1351 /* do a dummy wineserver request in order to let
1352 the wineserver run through its select loop once */
1353 sock_is_blocking(s, &dummy);
1356 static void _get_sock_errors(SOCKET s, int *events)
1358 SERVER_START_REQ( get_socket_event )
1360 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
1361 req->service = FALSE;
1362 req->c_event = 0;
1363 wine_server_set_reply( req, events, sizeof(int) * FD_MAX_EVENTS );
1364 wine_server_call( req );
1366 SERVER_END_REQ;
1369 static int get_sock_error(SOCKET s, unsigned int bit)
1371 int events[FD_MAX_EVENTS];
1372 _get_sock_errors(s, events);
1373 return events[bit];
1376 static int _get_fd_type(int fd)
1378 int sock_type = -1;
1379 socklen_t optlen = sizeof(sock_type);
1380 getsockopt(fd, SOL_SOCKET, SO_TYPE, (char*) &sock_type, &optlen);
1381 return sock_type;
1384 static BOOL set_dont_fragment(SOCKET s, int level, BOOL value)
1386 int fd, optname;
1388 if (level == IPPROTO_IP)
1390 #ifdef IP_DONTFRAG
1391 optname = IP_DONTFRAG;
1392 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) && defined(IP_PMTUDISC_DONT)
1393 optname = IP_MTU_DISCOVER;
1394 value = value ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
1395 #else
1396 static int once;
1397 if (!once++)
1398 FIXME("IP_DONTFRAGMENT for IPv4 not supported in this platform\n");
1399 return TRUE; /* fake success */
1400 #endif
1402 else
1404 #ifdef IPV6_DONTFRAG
1405 optname = IPV6_DONTFRAG;
1406 #elif defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) && defined(IPV6_PMTUDISC_DONT)
1407 optname = IPV6_MTU_DISCOVER;
1408 value = value ? IPV6_PMTUDISC_DO : IPV6_PMTUDISC_DONT;
1409 #else
1410 static int once;
1411 if (!once++)
1412 FIXME("IP_DONTFRAGMENT for IPv6 not supported in this platform\n");
1413 return TRUE; /* fake success */
1414 #endif
1417 fd = get_sock_fd(s, 0, NULL);
1418 if (fd == -1) return FALSE;
1420 if (!setsockopt(fd, level, optname, &value, sizeof(value)))
1421 value = TRUE;
1422 else
1424 WSASetLastError(wsaErrno());
1425 value = FALSE;
1428 release_sock_fd(s, fd);
1429 return value;
1432 static BOOL get_dont_fragment(SOCKET s, int level, BOOL *out)
1434 int fd, optname, value, not_expected;
1435 socklen_t optlen = sizeof(value);
1437 if (level == IPPROTO_IP)
1439 #ifdef IP_DONTFRAG
1440 optname = IP_DONTFRAG;
1441 not_expected = 0;
1442 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
1443 optname = IP_MTU_DISCOVER;
1444 not_expected = IP_PMTUDISC_DONT;
1445 #else
1446 static int once;
1447 if (!once++)
1448 FIXME("IP_DONTFRAGMENT for IPv4 not supported in this platform\n");
1449 return TRUE; /* fake success */
1450 #endif
1452 else
1454 #ifdef IPV6_DONTFRAG
1455 optname = IPV6_DONTFRAG;
1456 not_expected = 0;
1457 #elif defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
1458 optname = IPV6_MTU_DISCOVER;
1459 not_expected = IPV6_PMTUDISC_DONT;
1460 #else
1461 static int once;
1462 if (!once++)
1463 FIXME("IP_DONTFRAGMENT for IPv6 not supported in this platform\n");
1464 return TRUE; /* fake success */
1465 #endif
1468 fd = get_sock_fd(s, 0, NULL);
1469 if (fd == -1) return FALSE;
1471 if (!getsockopt(fd, level, optname, &value, &optlen))
1473 *out = value != not_expected;
1474 value = TRUE;
1476 else
1478 WSASetLastError(wsaErrno());
1479 value = FALSE;
1482 release_sock_fd(s, fd);
1483 return value;
1486 static struct per_thread_data *get_per_thread_data(void)
1488 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
1489 /* lazy initialization */
1490 if (!ptb)
1492 ptb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptb) );
1493 NtCurrentTeb()->WinSockData = ptb;
1495 return ptb;
1498 static void free_per_thread_data(void)
1500 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
1502 if (!ptb) return;
1504 /* delete scratch buffers */
1505 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
1506 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
1507 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
1508 HeapFree( GetProcessHeap(), 0, ptb->fd_cache );
1510 HeapFree( GetProcessHeap(), 0, ptb );
1511 NtCurrentTeb()->WinSockData = NULL;
1514 /***********************************************************************
1515 * DllMain (WS2_32.init)
1517 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
1519 TRACE("%p 0x%x %p\n", hInstDLL, fdwReason, fImpLoad);
1520 switch (fdwReason) {
1521 case DLL_PROCESS_ATTACH:
1522 break;
1523 case DLL_PROCESS_DETACH:
1524 if (fImpLoad) break;
1525 free_per_thread_data();
1526 DeleteCriticalSection(&csWSgetXXXbyYYY);
1527 break;
1528 case DLL_THREAD_DETACH:
1529 free_per_thread_data();
1530 break;
1532 return TRUE;
1535 /***********************************************************************
1536 * convert_flags()
1538 * Converts send/recv flags from Windows format.
1539 * Return the converted flag bits, unsupported flags remain unchanged.
1541 static int convert_flags(int flags)
1543 int i, out;
1544 if (!flags) return 0;
1546 for (out = i = 0; flags && i < ARRAY_SIZE(ws_flags_map); i++)
1548 if (ws_flags_map[i][0] & flags)
1550 out |= ws_flags_map[i][1];
1551 flags &= ~ws_flags_map[i][0];
1554 if (flags)
1556 FIXME("Unknown send/recv flags 0x%x, using anyway...\n", flags);
1557 out |= flags;
1559 return out;
1562 /***********************************************************************
1563 * convert_sockopt()
1565 * Converts socket flags from Windows format.
1566 * Return 1 if converted, 0 if not (error).
1568 static int convert_sockopt(INT *level, INT *optname)
1570 unsigned int i;
1571 switch (*level)
1573 case WS_SOL_SOCKET:
1574 *level = SOL_SOCKET;
1575 for(i = 0; i < ARRAY_SIZE(ws_sock_map); i++) {
1576 if( ws_sock_map[i][0] == *optname )
1578 *optname = ws_sock_map[i][1];
1579 return 1;
1582 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
1583 break;
1584 case WS_IPPROTO_TCP:
1585 *level = IPPROTO_TCP;
1586 for(i = 0; i < ARRAY_SIZE(ws_tcp_map); i++) {
1587 if ( ws_tcp_map[i][0] == *optname )
1589 *optname = ws_tcp_map[i][1];
1590 return 1;
1593 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
1594 break;
1595 case WS_IPPROTO_IP:
1596 *level = IPPROTO_IP;
1597 for(i = 0; i < ARRAY_SIZE(ws_ip_map); i++) {
1598 if (ws_ip_map[i][0] == *optname )
1600 *optname = ws_ip_map[i][1];
1601 return 1;
1604 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
1605 break;
1606 case WS_IPPROTO_IPV6:
1607 *level = IPPROTO_IPV6;
1608 for(i = 0; i < ARRAY_SIZE(ws_ipv6_map); i++) {
1609 if (ws_ipv6_map[i][0] == *optname )
1611 *optname = ws_ipv6_map[i][1];
1612 return 1;
1615 FIXME("Unknown IPPROTO_IPV6 optname 0x%x\n", *optname);
1616 break;
1617 default: FIXME("Unimplemented or unknown socket level\n");
1619 return 0;
1622 /* ----------------------------------- Per-thread info (or per-process?) */
1624 static char *strdup_lower(const char *str)
1626 int i;
1627 char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
1629 if (ret)
1631 for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
1632 ret[i] = 0;
1634 else SetLastError(WSAENOBUFS);
1635 return ret;
1638 /* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
1639 * from an fd and return the value converted to milli seconds
1640 * or 0 if there is an infinite time out */
1641 static inline INT64 get_rcvsnd_timeo( int fd, BOOL is_recv)
1643 struct timeval tv;
1644 socklen_t len = sizeof(tv);
1645 int optname, res;
1647 if (is_recv)
1648 #ifdef SO_RCVTIMEO
1649 optname = SO_RCVTIMEO;
1650 #else
1651 return 0;
1652 #endif
1653 else
1654 #ifdef SO_SNDTIMEO
1655 optname = SO_SNDTIMEO;
1656 #else
1657 return 0;
1658 #endif
1660 res = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
1661 if (res < 0)
1662 return 0;
1663 return (UINT64)tv.tv_sec * 1000 + tv.tv_usec / 1000;
1666 /* utility: given an fd, will block until one of the events occurs */
1667 static inline int do_block( int fd, int events, int timeout )
1669 struct pollfd pfd;
1670 int ret;
1672 pfd.fd = fd;
1673 pfd.events = events;
1675 while ((ret = poll(&pfd, 1, timeout)) < 0)
1677 if (errno != EINTR)
1678 return -1;
1680 if( ret == 0 )
1681 return 0;
1682 return pfd.revents;
1685 static int
1686 convert_af_w2u(int windowsaf) {
1687 unsigned int i;
1689 for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
1690 if (ws_af_map[i][0] == windowsaf)
1691 return ws_af_map[i][1];
1692 FIXME("unhandled Windows address family %d\n", windowsaf);
1693 return -1;
1696 static int
1697 convert_af_u2w(int unixaf) {
1698 unsigned int i;
1700 for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
1701 if (ws_af_map[i][1] == unixaf)
1702 return ws_af_map[i][0];
1703 FIXME("unhandled UNIX address family %d\n", unixaf);
1704 return -1;
1707 static int
1708 convert_proto_w2u(int windowsproto) {
1709 unsigned int i;
1711 for (i = 0; i < ARRAY_SIZE(ws_proto_map); i++)
1712 if (ws_proto_map[i][0] == windowsproto)
1713 return ws_proto_map[i][1];
1715 /* check for extended IPX */
1716 if (IS_IPX_PROTO(windowsproto))
1717 return windowsproto;
1719 FIXME("unhandled Windows socket protocol %d\n", windowsproto);
1720 return -1;
1723 static int
1724 convert_proto_u2w(int unixproto) {
1725 unsigned int i;
1727 for (i = 0; i < ARRAY_SIZE(ws_proto_map); i++)
1728 if (ws_proto_map[i][1] == unixproto)
1729 return ws_proto_map[i][0];
1731 /* if value is inside IPX range just return it - the kernel simply
1732 * echoes the value used in the socket() function */
1733 if (IS_IPX_PROTO(unixproto))
1734 return unixproto;
1736 FIXME("unhandled UNIX socket protocol %d\n", unixproto);
1737 return -1;
1740 static int
1741 convert_socktype_w2u(int windowssocktype) {
1742 unsigned int i;
1744 for (i = 0; i < ARRAY_SIZE(ws_socktype_map); i++)
1745 if (ws_socktype_map[i][0] == windowssocktype)
1746 return ws_socktype_map[i][1];
1747 FIXME("unhandled Windows socket type %d\n", windowssocktype);
1748 return -1;
1751 static int
1752 convert_socktype_u2w(int unixsocktype) {
1753 unsigned int i;
1755 for (i = 0; i < ARRAY_SIZE(ws_socktype_map); i++)
1756 if (ws_socktype_map[i][1] == unixsocktype)
1757 return ws_socktype_map[i][0];
1758 FIXME("unhandled UNIX socket type %d\n", unixsocktype);
1759 return -1;
1762 static int convert_poll_w2u(int events)
1764 int i, ret;
1765 for (i = ret = 0; events && i < ARRAY_SIZE(ws_poll_map); i++)
1767 if (ws_poll_map[i][0] & events)
1769 ret |= ws_poll_map[i][1];
1770 events &= ~ws_poll_map[i][0];
1774 if (events)
1775 FIXME("Unsupported WSAPoll() flags 0x%x\n", events);
1776 return ret;
1779 static int convert_poll_u2w(int events)
1781 int i, ret;
1782 for (i = ret = 0; events && i < ARRAY_SIZE(ws_poll_map); i++)
1784 if (ws_poll_map[i][1] & events)
1786 ret |= ws_poll_map[i][0];
1787 events &= ~ws_poll_map[i][1];
1791 if (events)
1792 FIXME("Unsupported poll() flags 0x%x\n", events);
1793 return ret;
1796 static int set_ipx_packettype(int sock, int ptype)
1798 #ifdef HAS_IPX
1799 int fd = get_sock_fd( sock, 0, NULL ), ret = 0;
1800 TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", ptype, fd);
1802 if (fd == -1) return SOCKET_ERROR;
1804 /* We try to set the ipx type on ipx socket level. */
1805 #ifdef SOL_IPX
1806 if(setsockopt(fd, SOL_IPX, IPX_TYPE, &ptype, sizeof(ptype)) == -1)
1808 ERR("IPX: could not set ipx option type; expect weird behaviour\n");
1809 ret = SOCKET_ERROR;
1811 #else
1813 struct ipx val;
1814 /* Should we retrieve val using a getsockopt call and then
1815 * set the modified one? */
1816 val.ipx_pt = ptype;
1817 setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
1819 #endif
1820 release_sock_fd( sock, fd );
1821 return ret;
1822 #else
1823 WARN("IPX support is not enabled, can't set packet type\n");
1824 return SOCKET_ERROR;
1825 #endif
1828 /* ----------------------------------- API -----
1830 * Init / cleanup / error checking.
1833 /***********************************************************************
1834 * WSAStartup (WS2_32.115)
1836 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
1838 TRACE("verReq=%x\n", wVersionRequested);
1840 if (LOBYTE(wVersionRequested) < 1)
1841 return WSAVERNOTSUPPORTED;
1843 if (!lpWSAData) return WSAEINVAL;
1845 num_startup++;
1847 /* that's the whole of the negotiation for now */
1848 lpWSAData->wVersion = wVersionRequested;
1849 /* return winsock information */
1850 lpWSAData->wHighVersion = 0x0202;
1851 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
1852 strcpy(lpWSAData->szSystemStatus, "Running" );
1853 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
1854 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
1855 /* don't do anything with lpWSAData->lpVendorInfo */
1856 /* (some apps don't allocate the space for this field) */
1858 TRACE("succeeded starts: %d\n", num_startup);
1859 return 0;
1863 /***********************************************************************
1864 * WSACleanup (WS2_32.116)
1866 INT WINAPI WSACleanup(void)
1868 TRACE("decreasing startup count from %d\n", num_startup);
1869 if (num_startup)
1871 if (!--num_startup)
1873 unsigned int i;
1875 for (i = 0; i < socket_list_size; ++i)
1876 CloseHandle(SOCKET2HANDLE(socket_list[i]));
1877 memset(socket_list, 0, socket_list_size * sizeof(*socket_list));
1879 return 0;
1881 SetLastError(WSANOTINITIALISED);
1882 return SOCKET_ERROR;
1886 /***********************************************************************
1887 * WSAGetLastError (WS2_32.111)
1889 INT WINAPI WSAGetLastError(void)
1891 return GetLastError();
1894 /***********************************************************************
1895 * WSASetLastError (WS2_32.112)
1897 void WINAPI WSASetLastError(INT iError) {
1898 SetLastError(iError);
1901 static struct WS_hostent *check_buffer_he(int size)
1903 struct per_thread_data * ptb = get_per_thread_data();
1904 if (ptb->he_buffer)
1906 if (ptb->he_len >= size ) return ptb->he_buffer;
1907 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
1909 ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
1910 if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
1911 return ptb->he_buffer;
1914 static struct WS_servent *check_buffer_se(int size)
1916 struct per_thread_data * ptb = get_per_thread_data();
1917 if (ptb->se_buffer)
1919 if (ptb->se_len >= size ) return ptb->se_buffer;
1920 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
1922 ptb->se_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->se_len = size) );
1923 if (!ptb->se_buffer) SetLastError(WSAENOBUFS);
1924 return ptb->se_buffer;
1927 static struct WS_protoent *check_buffer_pe(int size)
1929 struct per_thread_data * ptb = get_per_thread_data();
1930 if (ptb->pe_buffer)
1932 if (ptb->pe_len >= size ) return ptb->pe_buffer;
1933 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
1935 ptb->pe_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->pe_len = size) );
1936 if (!ptb->pe_buffer) SetLastError(WSAENOBUFS);
1937 return ptb->pe_buffer;
1940 /* ----------------------------------- i/o APIs */
1942 static inline BOOL supported_pf(int pf)
1944 switch (pf)
1946 case WS_AF_INET:
1947 case WS_AF_INET6:
1948 return TRUE;
1949 #ifdef HAS_IPX
1950 case WS_AF_IPX:
1951 return TRUE;
1952 #endif
1953 #ifdef HAS_IRDA
1954 case WS_AF_IRDA:
1955 return TRUE;
1956 #endif
1957 default:
1958 return FALSE;
1962 /**********************************************************************/
1964 /* Returns the length of the converted address if successful, 0 if it was too
1965 * small to start with or unknown family or invalid address buffer.
1967 static unsigned int ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen,
1968 union generic_unix_sockaddr *uaddr)
1970 unsigned int uaddrlen = 0;
1972 if (!wsaddr)
1973 return 0;
1975 switch (wsaddr->sa_family)
1977 #ifdef HAS_IPX
1978 case WS_AF_IPX:
1980 const struct WS_sockaddr_ipx* wsipx=(const struct WS_sockaddr_ipx*)wsaddr;
1981 struct sockaddr_ipx* uipx = (struct sockaddr_ipx *)uaddr;
1983 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
1984 return 0;
1986 uaddrlen = sizeof(struct sockaddr_ipx);
1987 memset( uaddr, 0, uaddrlen );
1988 uipx->sipx_family=AF_IPX;
1989 uipx->sipx_port=wsipx->sa_socket;
1990 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
1991 * in one go
1993 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
1994 #ifdef IPX_FRAME_NONE
1995 uipx->sipx_type=IPX_FRAME_NONE;
1996 #endif
1997 break;
1999 #endif
2000 case WS_AF_INET6: {
2001 struct sockaddr_in6* uin6 = (struct sockaddr_in6 *)uaddr;
2002 const struct WS_sockaddr_in6* win6 = (const struct WS_sockaddr_in6*)wsaddr;
2004 /* Note: Windows has 2 versions of the sockaddr_in6 struct, one with
2005 * scope_id, one without.
2007 if (wsaddrlen >= sizeof(struct WS_sockaddr_in6_old)) {
2008 uaddrlen = sizeof(struct sockaddr_in6);
2009 memset( uaddr, 0, uaddrlen );
2010 uin6->sin6_family = AF_INET6;
2011 uin6->sin6_port = win6->sin6_port;
2012 uin6->sin6_flowinfo = win6->sin6_flowinfo;
2013 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
2014 if (wsaddrlen >= sizeof(struct WS_sockaddr_in6)) uin6->sin6_scope_id = win6->sin6_scope_id;
2015 #endif
2016 memcpy(&uin6->sin6_addr,&win6->sin6_addr,16); /* 16 bytes = 128 address bits */
2017 break;
2019 FIXME("bad size %d for WS_sockaddr_in6\n",wsaddrlen);
2020 return 0;
2022 case WS_AF_INET: {
2023 struct sockaddr_in* uin = (struct sockaddr_in *)uaddr;
2024 const struct WS_sockaddr_in* win = (const struct WS_sockaddr_in*)wsaddr;
2026 if (wsaddrlen<sizeof(struct WS_sockaddr_in))
2027 return 0;
2028 uaddrlen = sizeof(struct sockaddr_in);
2029 memset( uaddr, 0, uaddrlen );
2030 uin->sin_family = AF_INET;
2031 uin->sin_port = win->sin_port;
2032 memcpy(&uin->sin_addr,&win->sin_addr,4); /* 4 bytes = 32 address bits */
2033 break;
2035 #ifdef HAS_IRDA
2036 case WS_AF_IRDA: {
2037 struct sockaddr_irda *uin = (struct sockaddr_irda *)uaddr;
2038 const SOCKADDR_IRDA *win = (const SOCKADDR_IRDA *)wsaddr;
2040 if (wsaddrlen < sizeof(SOCKADDR_IRDA))
2041 return 0;
2042 uaddrlen = sizeof(struct sockaddr_irda);
2043 memset( uaddr, 0, uaddrlen );
2044 uin->sir_family = AF_IRDA;
2045 if (!strncmp( win->irdaServiceName, "LSAP-SEL", strlen( "LSAP-SEL" ) ))
2047 unsigned int lsap_sel = 0;
2049 sscanf( win->irdaServiceName, "LSAP-SEL%u", &lsap_sel );
2050 uin->sir_lsap_sel = lsap_sel;
2052 else
2054 uin->sir_lsap_sel = LSAP_ANY;
2055 memcpy( uin->sir_name, win->irdaServiceName, 25 );
2057 memcpy( &uin->sir_addr, win->irdaDeviceID, sizeof(uin->sir_addr) );
2058 break;
2060 #endif
2061 case WS_AF_UNSPEC: {
2062 /* Try to determine the needed space by the passed windows sockaddr space */
2063 switch (wsaddrlen) {
2064 default: /* likely an ipv4 address */
2065 case sizeof(struct WS_sockaddr_in):
2066 uaddrlen = sizeof(struct sockaddr_in);
2067 break;
2068 #ifdef HAS_IPX
2069 case sizeof(struct WS_sockaddr_ipx):
2070 uaddrlen = sizeof(struct sockaddr_ipx);
2071 break;
2072 #endif
2073 #ifdef HAS_IRDA
2074 case sizeof(SOCKADDR_IRDA):
2075 uaddrlen = sizeof(struct sockaddr_irda);
2076 break;
2077 #endif
2078 case sizeof(struct WS_sockaddr_in6):
2079 case sizeof(struct WS_sockaddr_in6_old):
2080 uaddrlen = sizeof(struct sockaddr_in6);
2081 break;
2083 memset( uaddr, 0, uaddrlen );
2084 break;
2086 default:
2087 FIXME("Unknown address family %d, return NULL.\n", wsaddr->sa_family);
2088 return 0;
2090 return uaddrlen;
2093 static BOOL is_sockaddr_bound(const struct sockaddr *uaddr, int uaddrlen)
2095 switch (uaddr->sa_family)
2097 #ifdef HAS_IPX
2098 case AF_IPX:
2100 static const struct sockaddr_ipx emptyAddr;
2101 struct sockaddr_ipx *ipx = (struct sockaddr_ipx*) uaddr;
2102 return ipx->sipx_port
2103 || memcmp(&ipx->sipx_network, &emptyAddr.sipx_network, sizeof(emptyAddr.sipx_network))
2104 || memcmp(&ipx->sipx_node, &emptyAddr.sipx_node, sizeof(emptyAddr.sipx_node));
2106 #endif
2107 case AF_INET6:
2109 static const struct sockaddr_in6 emptyAddr;
2110 const struct sockaddr_in6 *in6 = (const struct sockaddr_in6*) uaddr;
2111 return in6->sin6_port || memcmp(&in6->sin6_addr, &emptyAddr.sin6_addr, sizeof(struct in6_addr));
2113 case AF_INET:
2115 static const struct sockaddr_in emptyAddr;
2116 const struct sockaddr_in *in = (const struct sockaddr_in*) uaddr;
2117 return in->sin_port || memcmp(&in->sin_addr, &emptyAddr.sin_addr, sizeof(struct in_addr));
2119 case AF_UNSPEC:
2120 return FALSE;
2121 default:
2122 FIXME("unknown address family %d\n", uaddr->sa_family);
2123 return TRUE;
2127 /* Returns -1 if getsockname fails, 0 if not bound, 1 otherwise */
2128 static int is_fd_bound(int fd, union generic_unix_sockaddr *uaddr, socklen_t *uaddrlen)
2130 union generic_unix_sockaddr inaddr;
2131 socklen_t inlen;
2132 int res;
2134 if (!uaddr) uaddr = &inaddr;
2135 if (!uaddrlen) uaddrlen = &inlen;
2137 *uaddrlen = sizeof(inaddr);
2138 res = getsockname(fd, &uaddr->addr, uaddrlen);
2139 if (!res) res = is_sockaddr_bound(&uaddr->addr, *uaddrlen);
2140 return res;
2143 /* Returns 0 if successful, -1 if the buffer is too small */
2144 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, struct WS_sockaddr* wsaddr, int* wsaddrlen)
2146 int res;
2148 switch(uaddr->sa_family)
2150 #ifdef HAS_IPX
2151 case AF_IPX:
2153 const struct sockaddr_ipx* uipx=(const struct sockaddr_ipx*)uaddr;
2154 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
2156 res=-1;
2157 switch (*wsaddrlen) /* how much can we copy? */
2159 default:
2160 res=0; /* enough */
2161 *wsaddrlen = sizeof(*wsipx);
2162 wsipx->sa_socket=uipx->sipx_port;
2163 /* fall through */
2164 case 13:
2165 case 12:
2166 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
2167 /* fall through */
2168 case 11:
2169 case 10:
2170 case 9:
2171 case 8:
2172 case 7:
2173 case 6:
2174 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
2175 /* fall through */
2176 case 5:
2177 case 4:
2178 case 3:
2179 case 2:
2180 wsipx->sa_family=WS_AF_IPX;
2181 /* fall through */
2182 case 1:
2183 case 0:
2184 /* way too small */
2185 break;
2188 break;
2189 #endif
2190 #ifdef HAS_IRDA
2191 case AF_IRDA: {
2192 const struct sockaddr_irda *uin = (const struct sockaddr_irda *)uaddr;
2193 SOCKADDR_IRDA *win = (SOCKADDR_IRDA *)wsaddr;
2195 if (*wsaddrlen < sizeof(SOCKADDR_IRDA))
2196 return -1;
2197 win->irdaAddressFamily = WS_AF_IRDA;
2198 memcpy( win->irdaDeviceID, &uin->sir_addr, sizeof(win->irdaDeviceID) );
2199 if (uin->sir_lsap_sel != LSAP_ANY)
2200 sprintf( win->irdaServiceName, "LSAP-SEL%u", uin->sir_lsap_sel );
2201 else
2202 memcpy( win->irdaServiceName, uin->sir_name,
2203 sizeof(win->irdaServiceName) );
2204 return 0;
2206 #endif
2207 case AF_INET6: {
2208 const struct sockaddr_in6* uin6 = (const struct sockaddr_in6*)uaddr;
2209 struct WS_sockaddr_in6_old* win6old = (struct WS_sockaddr_in6_old*)wsaddr;
2211 if (*wsaddrlen < sizeof(struct WS_sockaddr_in6_old))
2212 return -1;
2213 win6old->sin6_family = WS_AF_INET6;
2214 win6old->sin6_port = uin6->sin6_port;
2215 win6old->sin6_flowinfo = uin6->sin6_flowinfo;
2216 memcpy(&win6old->sin6_addr,&uin6->sin6_addr,16); /* 16 bytes = 128 address bits */
2217 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
2218 if (*wsaddrlen >= sizeof(struct WS_sockaddr_in6)) {
2219 struct WS_sockaddr_in6* win6 = (struct WS_sockaddr_in6*)wsaddr;
2220 win6->sin6_scope_id = uin6->sin6_scope_id;
2221 *wsaddrlen = sizeof(struct WS_sockaddr_in6);
2223 else
2224 *wsaddrlen = sizeof(struct WS_sockaddr_in6_old);
2225 #else
2226 *wsaddrlen = sizeof(struct WS_sockaddr_in6_old);
2227 #endif
2228 return 0;
2230 case AF_INET: {
2231 const struct sockaddr_in* uin = (const struct sockaddr_in*)uaddr;
2232 struct WS_sockaddr_in* win = (struct WS_sockaddr_in*)wsaddr;
2234 if (*wsaddrlen < sizeof(struct WS_sockaddr_in))
2235 return -1;
2236 win->sin_family = WS_AF_INET;
2237 win->sin_port = uin->sin_port;
2238 memcpy(&win->sin_addr,&uin->sin_addr,4); /* 4 bytes = 32 address bits */
2239 memset(win->sin_zero, 0, 8); /* Make sure the null padding is null */
2240 *wsaddrlen = sizeof(struct WS_sockaddr_in);
2241 return 0;
2243 case AF_UNSPEC: {
2244 memset(wsaddr,0,*wsaddrlen);
2245 return 0;
2247 default:
2248 FIXME("Unknown address family %d\n", uaddr->sa_family);
2249 return -1;
2251 return res;
2254 static INT WS_DuplicateSocket(BOOL unicode, SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo)
2256 HANDLE hProcess;
2257 int size;
2258 WSAPROTOCOL_INFOW infow;
2260 TRACE("(unicode %d, socket %04lx, processid %x, buffer %p)\n",
2261 unicode, s, dwProcessId, lpProtocolInfo);
2263 if (!ws_protocol_info(s, unicode, &infow, &size))
2264 return SOCKET_ERROR;
2266 if (!(hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId)))
2268 SetLastError(WSAEINVAL);
2269 return SOCKET_ERROR;
2272 if (!lpProtocolInfo)
2274 CloseHandle(hProcess);
2275 SetLastError(WSAEFAULT);
2276 return SOCKET_ERROR;
2279 /* I don't know what the real Windoze does next, this is a hack */
2280 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
2281 * the target use the global duplicate, or we could copy a reference to us to the structure
2282 * and let the target duplicate it from us, but let's do it as simple as possible */
2283 memcpy(lpProtocolInfo, &infow, size);
2284 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
2285 hProcess, (LPHANDLE)&lpProtocolInfo->dwServiceFlags3,
2286 0, FALSE, DUPLICATE_SAME_ACCESS);
2287 CloseHandle(hProcess);
2288 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
2289 return 0;
2292 static BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size)
2294 NTSTATUS status;
2295 int address_family;
2296 int socket_type;
2297 int protocol;
2298 unsigned int i;
2300 *size = unicode ? sizeof(WSAPROTOCOL_INFOW) : sizeof(WSAPROTOCOL_INFOA);
2301 memset(buffer, 0, *size);
2303 SERVER_START_REQ( get_socket_info )
2305 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
2306 status = wine_server_call( req );
2307 if (!status)
2309 address_family = reply->family;
2310 socket_type = reply->type;
2311 protocol = reply->protocol;
2314 SERVER_END_REQ;
2316 if (status)
2318 unsigned int err = NtStatusToWSAError( status );
2319 SetLastError( err == WSAEBADF ? WSAENOTSOCK : err );
2320 return FALSE;
2323 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
2325 const WSAPROTOCOL_INFOW *info = &supported_protocols[i];
2326 if (address_family == info->iAddressFamily &&
2327 socket_type == info->iSocketType &&
2328 protocol >= info->iProtocol && protocol <= info->iProtocol + info->iProtocolMaxOffset)
2330 if (unicode)
2331 *buffer = *info;
2332 else
2334 WSAPROTOCOL_INFOA *bufferA = (WSAPROTOCOL_INFOA *)buffer;
2335 memcpy( bufferA, info, offsetof( WSAPROTOCOL_INFOW, szProtocol ) );
2336 WideCharToMultiByte( CP_ACP, 0, info->szProtocol, -1,
2337 bufferA->szProtocol, sizeof(bufferA->szProtocol), NULL, NULL );
2339 buffer->iProtocol = protocol;
2340 return TRUE;
2343 FIXME("Could not fill protocol information for family %d, type %d, protocol %d.\n",
2344 address_family, socket_type, protocol);
2345 return TRUE;
2348 /**************************************************************************
2349 * Functions for handling overlapped I/O
2350 **************************************************************************/
2352 /* user APC called upon async completion */
2353 static void WINAPI ws2_async_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
2355 struct ws2_async *wsa = arg;
2357 if (wsa->completion_func) wsa->completion_func( NtStatusToWSAError(iosb->u.Status),
2358 iosb->Information, wsa->user_overlapped,
2359 wsa->flags );
2360 release_async_io( &wsa->io );
2363 /***********************************************************************
2364 * WS2_recv (INTERNAL)
2366 * Workhorse for both synchronous and asynchronous recv() operations.
2368 static int WS2_recv( int fd, struct ws2_async *wsa, int flags )
2370 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
2371 char pktbuf[512];
2372 #endif
2373 struct msghdr hdr;
2374 union generic_unix_sockaddr unix_sockaddr;
2375 int n;
2377 hdr.msg_name = NULL;
2379 if (wsa->addr)
2381 hdr.msg_namelen = sizeof(unix_sockaddr);
2382 hdr.msg_name = &unix_sockaddr;
2384 else
2385 hdr.msg_namelen = 0;
2387 hdr.msg_iov = wsa->iovec + wsa->first_iovec;
2388 hdr.msg_iovlen = wsa->n_iovecs - wsa->first_iovec;
2389 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
2390 hdr.msg_accrights = NULL;
2391 hdr.msg_accrightslen = 0;
2392 #else
2393 hdr.msg_control = pktbuf;
2394 hdr.msg_controllen = sizeof(pktbuf);
2395 hdr.msg_flags = 0;
2396 #endif
2398 while ((n = __wine_locked_recvmsg( fd, &hdr, flags )) == -1)
2400 if (errno != EINTR)
2401 return -1;
2404 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
2405 if (wsa->control)
2407 ERR("Message control headers cannot be properly supported on this system.\n");
2408 wsa->control->len = 0;
2410 #else
2411 if (wsa->control && !convert_control_headers(&hdr, wsa->control))
2413 WARN("Application passed insufficient room for control headers.\n");
2414 *wsa->lpFlags |= WS_MSG_CTRUNC;
2415 errno = EMSGSIZE;
2416 return -1;
2418 #endif
2420 /* if this socket is connected and lpFrom is not NULL, Linux doesn't give us
2421 * msg_name and msg_namelen from recvmsg, but it does set msg_namelen to zero.
2423 * quoting linux 2.6 net/ipv4/tcp.c:
2424 * "According to UNIX98, msg_name/msg_namelen are ignored
2425 * on connected socket. I was just happy when found this 8) --ANK"
2427 * likewise MSDN says that lpFrom and lpFromlen are ignored for
2428 * connection-oriented sockets, so don't try to update lpFrom.
2430 if (wsa->addr && hdr.msg_namelen)
2431 ws_sockaddr_u2ws( &unix_sockaddr.addr, wsa->addr, wsa->addrlen.ptr );
2433 return n;
2436 /***********************************************************************
2437 * WS2_async_recv (INTERNAL)
2439 * Handler for overlapped recv() operations.
2441 static NTSTATUS WS2_async_recv( void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status )
2443 struct ws2_async *wsa = user;
2444 int result = 0, fd;
2446 switch (status)
2448 case STATUS_ALERTED:
2449 if ((status = wine_server_handle_to_fd( wsa->hSocket, FILE_READ_DATA, &fd, NULL ) ))
2450 break;
2452 result = WS2_recv( fd, wsa, convert_flags(wsa->flags) );
2453 wine_server_release_fd( wsa->hSocket, fd );
2454 if (result >= 0)
2456 status = STATUS_SUCCESS;
2457 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
2459 else
2461 if (errno == EAGAIN)
2463 status = STATUS_PENDING;
2464 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
2466 else
2468 result = 0;
2469 status = wsaErrStatus();
2472 break;
2474 if (status != STATUS_PENDING)
2476 iosb->u.Status = status;
2477 iosb->Information = result;
2478 if (!wsa->completion_func)
2479 release_async_io( &wsa->io );
2481 return status;
2484 /***********************************************************************
2485 * WS2_send (INTERNAL)
2487 * Workhorse for both synchronous and asynchronous send() operations.
2489 static int WS2_send( int fd, struct ws2_async *wsa, int flags )
2491 struct msghdr hdr;
2492 union generic_unix_sockaddr unix_addr;
2493 int n, ret;
2495 hdr.msg_name = NULL;
2496 hdr.msg_namelen = 0;
2498 if (wsa->addr)
2500 hdr.msg_name = &unix_addr;
2501 hdr.msg_namelen = ws_sockaddr_ws2u( wsa->addr, wsa->addrlen.val, &unix_addr );
2502 if ( !hdr.msg_namelen )
2504 errno = EFAULT;
2505 return -1;
2508 #if defined(HAS_IPX) && defined(SOL_IPX)
2509 if(wsa->addr->sa_family == WS_AF_IPX)
2511 struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
2512 int val=0;
2513 socklen_t len = sizeof(int);
2515 /* The packet type is stored at the ipx socket level; At least the linux kernel seems
2516 * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
2517 * the packet type and then we can retrieve it using getsockopt. After that we can set the
2518 * ipx type in the sockaddr_opx structure with the stored value.
2520 if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
2521 uipx->sipx_type = val;
2523 #endif
2526 hdr.msg_iov = wsa->iovec + wsa->first_iovec;
2527 hdr.msg_iovlen = wsa->n_iovecs - wsa->first_iovec;
2528 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
2529 hdr.msg_accrights = NULL;
2530 hdr.msg_accrightslen = 0;
2531 #else
2532 hdr.msg_control = NULL;
2533 hdr.msg_controllen = 0;
2534 hdr.msg_flags = 0;
2535 #endif
2537 while ((ret = sendmsg(fd, &hdr, flags)) == -1)
2539 if (errno == EISCONN)
2541 hdr.msg_name = 0;
2542 hdr.msg_namelen = 0;
2543 continue;
2545 if (errno != EINTR)
2546 return -1;
2549 n = ret;
2550 while (wsa->first_iovec < wsa->n_iovecs && wsa->iovec[wsa->first_iovec].iov_len <= n)
2551 n -= wsa->iovec[wsa->first_iovec++].iov_len;
2552 if (wsa->first_iovec < wsa->n_iovecs)
2554 wsa->iovec[wsa->first_iovec].iov_base = (char*)wsa->iovec[wsa->first_iovec].iov_base + n;
2555 wsa->iovec[wsa->first_iovec].iov_len -= n;
2557 return ret;
2560 /***********************************************************************
2561 * WS2_async_send (INTERNAL)
2563 * Handler for overlapped send() operations.
2565 static NTSTATUS WS2_async_send( void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status )
2567 struct ws2_async *wsa = user;
2568 int result = 0, fd;
2570 switch (status)
2572 case STATUS_ALERTED:
2573 if ( wsa->n_iovecs <= wsa->first_iovec )
2575 /* Nothing to do */
2576 status = STATUS_SUCCESS;
2577 break;
2579 if ((status = wine_server_handle_to_fd( wsa->hSocket, FILE_WRITE_DATA, &fd, NULL ) ))
2580 break;
2582 /* check to see if the data is ready (non-blocking) */
2583 result = WS2_send( fd, wsa, convert_flags(wsa->flags) );
2584 wine_server_release_fd( wsa->hSocket, fd );
2586 if (result >= 0)
2588 if (wsa->first_iovec < wsa->n_iovecs)
2589 status = STATUS_PENDING;
2590 else
2591 status = STATUS_SUCCESS;
2593 iosb->Information += result;
2595 else if (errno == EAGAIN)
2597 status = STATUS_PENDING;
2599 else
2601 status = wsaErrStatus();
2603 break;
2605 if (status != STATUS_PENDING)
2607 iosb->u.Status = status;
2608 if (!wsa->completion_func)
2609 release_async_io( &wsa->io );
2611 return status;
2614 /***********************************************************************
2615 * WS2_async_shutdown (INTERNAL)
2617 * Handler for shutdown() operations on overlapped sockets.
2619 static NTSTATUS WS2_async_shutdown( void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status )
2621 struct ws2_async_shutdown *wsa = user;
2622 int fd, err = 1;
2624 switch (status)
2626 case STATUS_ALERTED:
2627 if ((status = wine_server_handle_to_fd( wsa->hSocket, 0, &fd, NULL ) ))
2628 break;
2630 switch ( wsa->type )
2632 case ASYNC_TYPE_READ: err = shutdown( fd, 0 ); break;
2633 case ASYNC_TYPE_WRITE: err = shutdown( fd, 1 ); break;
2635 status = err ? wsaErrStatus() : STATUS_SUCCESS;
2636 wine_server_release_fd( wsa->hSocket, fd );
2637 break;
2639 iosb->u.Status = status;
2640 iosb->Information = 0;
2641 release_async_io( &wsa->io );
2642 return status;
2645 /***********************************************************************
2646 * WS2_register_async_shutdown (INTERNAL)
2648 * Helper function for WS_shutdown() on overlapped sockets.
2650 static int WS2_register_async_shutdown( SOCKET s, int type )
2652 struct ws2_async_shutdown *wsa;
2653 NTSTATUS status;
2655 TRACE("socket %04lx type %d\n", s, type);
2657 wsa = (struct ws2_async_shutdown *)alloc_async_io( sizeof(*wsa), WS2_async_shutdown );
2658 if ( !wsa )
2659 return WSAEFAULT;
2661 wsa->hSocket = SOCKET2HANDLE(s);
2662 wsa->type = type;
2664 status = register_async( type, wsa->hSocket, &wsa->io, 0, NULL, NULL, &wsa->iosb );
2665 if (status != STATUS_PENDING)
2667 HeapFree( GetProcessHeap(), 0, wsa );
2668 return NtStatusToWSAError( status );
2670 return 0;
2673 /***********************************************************************
2674 * accept (WS2_32.1)
2676 SOCKET WINAPI WS_accept( SOCKET s, struct WS_sockaddr *addr, int *len )
2678 IO_STATUS_BLOCK io;
2679 NTSTATUS status;
2680 obj_handle_t accept_handle;
2681 HANDLE sync_event;
2682 SOCKET ret;
2684 TRACE("%#lx\n", s);
2686 if (!(sync_event = CreateEventW( NULL, TRUE, FALSE, NULL ))) return INVALID_SOCKET;
2687 status = NtDeviceIoControlFile( SOCKET2HANDLE(s), (HANDLE)((ULONG_PTR)sync_event | 0), NULL, NULL, &io,
2688 IOCTL_AFD_ACCEPT, NULL, 0, &accept_handle, sizeof(accept_handle) );
2689 if (status == STATUS_PENDING)
2691 if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED)
2693 CloseHandle( sync_event );
2694 return SOCKET_ERROR;
2696 status = io.u.Status;
2698 CloseHandle( sync_event );
2699 if (status)
2701 WARN("failed; status %#x\n", status);
2702 WSASetLastError( NtStatusToWSAError( status ) );
2703 return INVALID_SOCKET;
2706 ret = HANDLE2SOCKET(wine_server_ptr_handle( accept_handle ));
2707 if (!socket_list_add( ret ))
2709 CloseHandle( SOCKET2HANDLE(ret) );
2710 return INVALID_SOCKET;
2712 if (addr && len && WS_getpeername( ret, addr, len ))
2714 WS_closesocket( ret );
2715 return INVALID_SOCKET;
2718 TRACE("returning %#lx\n", ret);
2719 return ret;
2722 /***********************************************************************
2723 * AcceptEx
2725 static BOOL WINAPI WS2_AcceptEx( SOCKET listener, SOCKET acceptor, void *dest, DWORD recv_len,
2726 DWORD local_len, DWORD remote_len, DWORD *ret_len, OVERLAPPED *overlapped)
2728 struct afd_accept_into_params params =
2730 .accept_handle = acceptor,
2731 .recv_len = recv_len,
2732 .local_len = local_len,
2734 void *cvalue = NULL;
2735 NTSTATUS status;
2737 TRACE( "listener %#lx, acceptor %#lx, dest %p, recv_len %u, local_len %u, remote_len %u, ret_len %p, "
2738 "overlapped %p\n", listener, acceptor, dest, recv_len, local_len, remote_len, ret_len, overlapped );
2740 if (!overlapped)
2742 SetLastError(WSA_INVALID_PARAMETER);
2743 return FALSE;
2746 if (!((ULONG_PTR)overlapped->hEvent & 1)) cvalue = overlapped;
2747 overlapped->Internal = STATUS_PENDING;
2748 overlapped->InternalHigh = 0;
2750 if (!dest)
2752 SetLastError(WSAEINVAL);
2753 return FALSE;
2756 if (!remote_len)
2758 SetLastError(WSAEFAULT);
2759 return FALSE;
2762 status = NtDeviceIoControlFile( SOCKET2HANDLE(listener), overlapped->hEvent, NULL, cvalue,
2763 (IO_STATUS_BLOCK *)overlapped, IOCTL_AFD_ACCEPT_INTO, &params, sizeof(params),
2764 dest, recv_len + local_len + remote_len );
2766 if (ret_len) *ret_len = overlapped->InternalHigh;
2767 WSASetLastError( NtStatusToWSAError(status) );
2768 return !status;
2771 /***********************************************************************
2772 * WS2_ReadFile (INTERNAL)
2774 * Perform an APC-safe ReadFile operation
2776 static NTSTATUS WS2_ReadFile(HANDLE hFile, PIO_STATUS_BLOCK io_status, char* buffer, ULONG length,
2777 PLARGE_INTEGER offset)
2779 int result = -1, unix_handle;
2780 unsigned int options;
2781 NTSTATUS status;
2783 TRACE( "(%p,%p,0x%08x)\n", hFile, buffer,length );
2785 status = wine_server_handle_to_fd( hFile, FILE_READ_DATA, &unix_handle, &options );
2786 if (status) return status;
2788 while (result == -1)
2790 if (offset->QuadPart != FILE_USE_FILE_POINTER_POSITION)
2791 result = pread( unix_handle, buffer, length, offset->QuadPart );
2792 else
2793 result = read( unix_handle, buffer, length );
2794 if (errno != EINTR)
2795 break;
2798 if (!result)
2799 status = (length ? STATUS_END_OF_FILE : STATUS_SUCCESS);
2800 else if (result != -1)
2801 status = STATUS_SUCCESS;
2802 else if (errno != EAGAIN)
2803 status = wsaErrStatus();
2804 else
2805 status = STATUS_PENDING;
2807 wine_server_release_fd( hFile, unix_handle );
2808 TRACE("= 0x%08x (%d)\n", status, result);
2809 if (status == STATUS_SUCCESS || status == STATUS_END_OF_FILE)
2811 io_status->u.Status = status;
2812 io_status->Information = result;
2815 return status;
2818 /***********************************************************************
2819 * WS2_transmitfile_getbuffer (INTERNAL)
2821 * Pick the appropriate buffer for a TransmitFile send operation.
2823 static NTSTATUS WS2_transmitfile_getbuffer( int fd, struct ws2_transmitfile_async *wsa )
2825 /* send any incomplete writes from a previous iteration */
2826 if (wsa->write.first_iovec < wsa->write.n_iovecs)
2827 return STATUS_PENDING;
2829 /* process the header (if applicable) */
2830 if (wsa->buffers.Head)
2832 wsa->write.first_iovec = 0;
2833 wsa->write.n_iovecs = 1;
2834 wsa->write.iovec[0].iov_base = wsa->buffers.Head;
2835 wsa->write.iovec[0].iov_len = wsa->buffers.HeadLength;
2836 wsa->buffers.Head = NULL;
2837 return STATUS_PENDING;
2840 /* process the main file */
2841 if (wsa->file)
2843 DWORD bytes_per_send = wsa->bytes_per_send;
2844 IO_STATUS_BLOCK iosb;
2845 NTSTATUS status;
2847 iosb.Information = 0;
2848 /* when the size of the transfer is limited ensure that we don't go past that limit */
2849 if (wsa->file_bytes != 0)
2850 bytes_per_send = min(bytes_per_send, wsa->file_bytes - wsa->file_read);
2851 status = WS2_ReadFile( wsa->file, &iosb, wsa->buffer, bytes_per_send, &wsa->offset );
2852 if (wsa->offset.QuadPart != FILE_USE_FILE_POINTER_POSITION)
2853 wsa->offset.QuadPart += iosb.Information;
2854 if (status == STATUS_END_OF_FILE)
2855 wsa->file = NULL; /* continue on to the footer */
2856 else if (status != STATUS_SUCCESS)
2857 return status;
2858 else
2860 if (iosb.Information)
2862 wsa->write.first_iovec = 0;
2863 wsa->write.n_iovecs = 1;
2864 wsa->write.iovec[0].iov_base = wsa->buffer;
2865 wsa->write.iovec[0].iov_len = iosb.Information;
2866 wsa->file_read += iosb.Information;
2869 if (wsa->file_bytes != 0 && wsa->file_read >= wsa->file_bytes)
2870 wsa->file = NULL;
2872 return STATUS_PENDING;
2876 /* send the footer (if applicable) */
2877 if (wsa->buffers.Tail)
2879 wsa->write.first_iovec = 0;
2880 wsa->write.n_iovecs = 1;
2881 wsa->write.iovec[0].iov_base = wsa->buffers.Tail;
2882 wsa->write.iovec[0].iov_len = wsa->buffers.TailLength;
2883 wsa->buffers.Tail = NULL;
2884 return STATUS_PENDING;
2887 return STATUS_SUCCESS;
2890 /***********************************************************************
2891 * WS2_transmitfile_base (INTERNAL)
2893 * Shared implementation for both synchronous and asynchronous TransmitFile.
2895 static NTSTATUS WS2_transmitfile_base( int fd, struct ws2_transmitfile_async *wsa )
2897 NTSTATUS status;
2899 status = WS2_transmitfile_getbuffer( fd, wsa );
2900 if (status == STATUS_PENDING)
2902 IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)wsa->write.user_overlapped;
2903 int n;
2905 n = WS2_send( fd, &wsa->write, convert_flags(wsa->write.flags) );
2906 if (n >= 0)
2908 if (iosb) iosb->Information += n;
2910 else if (errno != EAGAIN)
2911 return wsaErrStatus();
2914 return status;
2917 /***********************************************************************
2918 * WS2_async_transmitfile (INTERNAL)
2920 * Asynchronous callback for overlapped TransmitFile operations.
2922 static NTSTATUS WS2_async_transmitfile( void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status )
2924 struct ws2_transmitfile_async *wsa = user;
2925 int fd;
2927 if (status == STATUS_ALERTED)
2929 if (!(status = wine_server_handle_to_fd( wsa->write.hSocket, FILE_WRITE_DATA, &fd, NULL )))
2931 status = WS2_transmitfile_base( fd, wsa );
2932 wine_server_release_fd( wsa->write.hSocket, fd );
2934 if (status == STATUS_PENDING)
2935 return status;
2938 iosb->u.Status = status;
2939 release_async_io( &wsa->io );
2940 return status;
2943 /***********************************************************************
2944 * TransmitFile
2946 static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD bytes_per_send,
2947 LPOVERLAPPED overlapped, LPTRANSMIT_FILE_BUFFERS buffers,
2948 DWORD flags )
2950 union generic_unix_sockaddr uaddr;
2951 socklen_t uaddrlen = sizeof(uaddr);
2952 struct ws2_transmitfile_async *wsa;
2953 NTSTATUS status;
2954 int fd;
2956 TRACE("(%lx, %p, %d, %d, %p, %p, %d)\n", s, h, file_bytes, bytes_per_send, overlapped,
2957 buffers, flags );
2959 fd = get_sock_fd( s, FILE_WRITE_DATA, NULL );
2960 if (fd == -1) return FALSE;
2962 if (getpeername( fd, &uaddr.addr, &uaddrlen ) != 0)
2964 release_sock_fd( s, fd );
2965 WSASetLastError( WSAENOTCONN );
2966 return FALSE;
2968 if (flags)
2969 FIXME("Flags are not currently supported (0x%x).\n", flags);
2971 if (h && GetFileType( h ) != FILE_TYPE_DISK)
2973 FIXME("Non-disk file handles are not currently supported.\n");
2974 release_sock_fd( s, fd );
2975 WSASetLastError( WSAEOPNOTSUPP );
2976 return FALSE;
2979 /* set reasonable defaults when requested */
2980 if (!bytes_per_send)
2981 bytes_per_send = (1 << 16); /* Depends on OS version: PAGE_SIZE, 2*PAGE_SIZE, or 2^16 */
2983 if (!(wsa = (struct ws2_transmitfile_async *)alloc_async_io( sizeof(*wsa) + bytes_per_send,
2984 WS2_async_transmitfile )))
2986 release_sock_fd( s, fd );
2987 WSASetLastError( WSAEFAULT );
2988 return FALSE;
2990 if (buffers)
2991 wsa->buffers = *buffers;
2992 else
2993 memset(&wsa->buffers, 0x0, sizeof(wsa->buffers));
2994 wsa->buffer = (char *)(wsa + 1);
2995 wsa->file = h;
2996 wsa->file_read = 0;
2997 wsa->file_bytes = file_bytes;
2998 wsa->bytes_per_send = bytes_per_send;
2999 wsa->flags = flags;
3000 wsa->offset.QuadPart = FILE_USE_FILE_POINTER_POSITION;
3001 wsa->write.hSocket = SOCKET2HANDLE(s);
3002 wsa->write.addr = NULL;
3003 wsa->write.addrlen.val = 0;
3004 wsa->write.flags = 0;
3005 wsa->write.lpFlags = &wsa->flags;
3006 wsa->write.control = NULL;
3007 wsa->write.n_iovecs = 0;
3008 wsa->write.first_iovec = 0;
3009 wsa->write.user_overlapped = overlapped;
3010 if (overlapped)
3012 IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)overlapped;
3013 int status;
3015 wsa->offset.u.LowPart = overlapped->u.s.Offset;
3016 wsa->offset.u.HighPart = overlapped->u.s.OffsetHigh;
3017 iosb->u.Status = STATUS_PENDING;
3018 iosb->Information = 0;
3019 status = register_async( ASYNC_TYPE_WRITE, SOCKET2HANDLE(s), &wsa->io,
3020 overlapped->hEvent, NULL, NULL, iosb );
3021 if(status != STATUS_PENDING) HeapFree( GetProcessHeap(), 0, wsa );
3022 release_sock_fd( s, fd );
3023 WSASetLastError( NtStatusToWSAError(status) );
3024 return FALSE;
3029 status = WS2_transmitfile_base( fd, wsa );
3030 if (status == STATUS_PENDING)
3032 /* block here */
3033 do_block(fd, POLLOUT, -1);
3034 _sync_sock_state(s); /* let wineserver notice connection */
3037 while (status == STATUS_PENDING);
3038 release_sock_fd( s, fd );
3040 if (status != STATUS_SUCCESS)
3041 WSASetLastError( NtStatusToWSAError(status) );
3042 HeapFree( GetProcessHeap(), 0, wsa );
3043 return (status == STATUS_SUCCESS);
3046 /***********************************************************************
3047 * GetAcceptExSockaddrs
3049 static void WINAPI WS2_GetAcceptExSockaddrs(PVOID buffer, DWORD data_size, DWORD local_size, DWORD remote_size,
3050 struct WS_sockaddr **local_addr, LPINT local_addr_len,
3051 struct WS_sockaddr **remote_addr, LPINT remote_addr_len)
3053 char *cbuf = buffer;
3054 TRACE("(%p, %d, %d, %d, %p, %p, %p, %p)\n", buffer, data_size, local_size, remote_size, local_addr,
3055 local_addr_len, remote_addr, remote_addr_len );
3056 cbuf += data_size;
3058 *local_addr_len = *(int *) cbuf;
3059 *local_addr = (struct WS_sockaddr *)(cbuf + sizeof(int));
3061 cbuf += local_size;
3063 *remote_addr_len = *(int *) cbuf;
3064 *remote_addr = (struct WS_sockaddr *)(cbuf + sizeof(int));
3067 /***********************************************************************
3068 * WSASendMsg
3070 int WINAPI WSASendMsg( SOCKET s, LPWSAMSG msg, DWORD dwFlags, LPDWORD lpNumberOfBytesSent,
3071 LPWSAOVERLAPPED lpOverlapped,
3072 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3074 if (!msg)
3076 SetLastError( WSAEFAULT );
3077 return SOCKET_ERROR;
3080 return WS2_sendto( s, msg->lpBuffers, msg->dwBufferCount, lpNumberOfBytesSent,
3081 dwFlags, msg->name, msg->namelen,
3082 lpOverlapped, lpCompletionRoutine );
3085 /***********************************************************************
3086 * WSARecvMsg
3088 * Perform a receive operation that is capable of returning message
3089 * control headers. It is important to note that the WSAMSG parameter
3090 * must remain valid throughout the operation, even when an overlapped
3091 * receive is performed.
3093 static int WINAPI WS2_WSARecvMsg( SOCKET s, LPWSAMSG msg, LPDWORD lpNumberOfBytesRecvd,
3094 LPWSAOVERLAPPED lpOverlapped,
3095 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3097 if (!msg)
3099 SetLastError( WSAEFAULT );
3100 return SOCKET_ERROR;
3103 return WS2_recv_base( s, msg->lpBuffers, msg->dwBufferCount, lpNumberOfBytesRecvd,
3104 &msg->dwFlags, msg->name, &msg->namelen,
3105 lpOverlapped, lpCompletionRoutine, &msg->Control );
3108 /***********************************************************************
3109 * interface_bind (INTERNAL)
3111 * Take bind() calls on any name corresponding to a local network adapter and restrict the given socket to
3112 * operating only on the specified interface. This restriction consists of two components:
3113 * 1) An outgoing packet restriction suggesting the egress interface for all packets.
3114 * 2) An incoming packet restriction dropping packets not meant for the interface.
3115 * If the function succeeds in placing these restrictions (returns TRUE) then the name for the bind() may
3116 * safely be changed to INADDR_ANY, permitting the transmission and receipt of broadcast packets on the
3117 * socket. This behavior is only relevant to UDP sockets and is needed for applications that expect to be able
3118 * to receive broadcast packets on a socket that is bound to a specific network interface.
3120 static BOOL interface_bind( SOCKET s, int fd, struct sockaddr *addr )
3122 struct sockaddr_in *in_sock = (struct sockaddr_in *) addr;
3123 in_addr_t bind_addr = in_sock->sin_addr.s_addr;
3124 PIP_ADAPTER_INFO adapters = NULL, adapter;
3125 BOOL ret = FALSE;
3126 DWORD adap_size;
3127 int enable = 1;
3129 if (bind_addr == htonl(INADDR_ANY) || bind_addr == htonl(INADDR_LOOPBACK))
3130 return FALSE; /* Not binding to a network adapter, special interface binding unnecessary. */
3131 if (_get_fd_type(fd) != SOCK_DGRAM)
3132 return FALSE; /* Special interface binding is only necessary for UDP datagrams. */
3133 if (GetAdaptersInfo(NULL, &adap_size) != ERROR_BUFFER_OVERFLOW)
3134 goto cleanup;
3135 adapters = HeapAlloc(GetProcessHeap(), 0, adap_size);
3136 if (adapters == NULL || GetAdaptersInfo(adapters, &adap_size) != NO_ERROR)
3137 goto cleanup;
3138 /* Search the IPv4 adapter list for the appropriate binding interface */
3139 for (adapter = adapters; adapter != NULL; adapter = adapter->Next)
3141 in_addr_t adapter_addr = (in_addr_t) inet_addr(adapter->IpAddressList.IpAddress.String);
3143 if (bind_addr == adapter_addr)
3145 #if defined(IP_BOUND_IF)
3146 /* IP_BOUND_IF sets both the incoming and outgoing restriction at once */
3147 if (setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &adapter->Index, sizeof(adapter->Index)) != 0)
3148 goto cleanup;
3149 ret = TRUE;
3150 #elif defined(LINUX_BOUND_IF)
3151 in_addr_t ifindex = (in_addr_t) htonl(adapter->Index);
3152 struct interface_filter specific_interface_filter;
3153 struct sock_fprog filter_prog;
3155 if (setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex)) != 0)
3156 goto cleanup; /* Failed to suggest egress interface */
3157 specific_interface_filter = generic_interface_filter;
3158 specific_interface_filter.iface_rule.k = adapter->Index;
3159 specific_interface_filter.ip_rule.k = htonl(adapter_addr);
3160 filter_prog.len = sizeof(generic_interface_filter)/sizeof(struct sock_filter);
3161 filter_prog.filter = (struct sock_filter *) &specific_interface_filter;
3162 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, sizeof(filter_prog)) != 0)
3163 goto cleanup; /* Failed to specify incoming packet filter */
3164 ret = TRUE;
3165 #else
3166 FIXME("Broadcast packets on interface-bound sockets are not currently supported on this platform, "
3167 "receiving broadcast packets will not work on socket %04lx.\n", s);
3168 #endif
3169 if (ret)
3171 EnterCriticalSection(&cs_if_addr_cache);
3172 if (if_addr_cache_size <= adapter->Index)
3174 unsigned int new_size;
3175 in_addr_t *new;
3177 new_size = max(if_addr_cache_size * 2, adapter->Index + 1);
3178 if (!(new = heap_realloc(if_addr_cache, sizeof(*if_addr_cache) * new_size)))
3180 ERR("No memory.\n");
3181 ret = FALSE;
3182 LeaveCriticalSection(&cs_if_addr_cache);
3183 break;
3185 memset(new + if_addr_cache_size, 0, sizeof(*if_addr_cache)
3186 * (new_size - if_addr_cache_size));
3187 if_addr_cache = new;
3188 if_addr_cache_size = new_size;
3190 if (if_addr_cache[adapter->Index] && if_addr_cache[adapter->Index] != adapter_addr)
3191 WARN("Adapter addr for iface index %u has changed.\n", adapter->Index);
3193 if_addr_cache[adapter->Index] = adapter_addr;
3194 LeaveCriticalSection(&cs_if_addr_cache);
3196 break;
3199 /* Will soon be switching to INADDR_ANY: permit address reuse */
3200 if (ret && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) == 0)
3201 TRACE("Socket %04lx bound to interface index %d\n", s, adapter->Index);
3202 else
3203 ret = FALSE;
3205 cleanup:
3206 if(!ret)
3207 ERR("Failed to bind to interface, receiving broadcast packets will not work on socket %04lx.\n", s);
3208 HeapFree(GetProcessHeap(), 0, adapters);
3209 return ret;
3212 /***********************************************************************
3213 * bind (WS2_32.2)
3215 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
3217 int fd = get_sock_fd( s, 0, NULL );
3218 int res = SOCKET_ERROR;
3220 TRACE("socket %04lx, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
3222 if (fd != -1)
3224 if (!name || (name->sa_family && !supported_pf(name->sa_family)))
3226 SetLastError(WSAEAFNOSUPPORT);
3228 else
3230 union generic_unix_sockaddr uaddr;
3231 unsigned int uaddrlen = ws_sockaddr_ws2u(name, namelen, &uaddr);
3232 if (!uaddrlen)
3234 SetLastError(WSAEFAULT);
3236 else
3238 if (name->sa_family == WS_AF_INET)
3240 struct sockaddr_in *in4 = (struct sockaddr_in*) &uaddr;
3241 if (memcmp(&in4->sin_addr, magic_loopback_addr, 4) == 0)
3243 /* Trying to bind to the default host interface, using
3244 * INADDR_ANY instead*/
3245 WARN("Trying to bind to magic IP address, using "
3246 "INADDR_ANY instead.\n");
3247 in4->sin_addr.s_addr = htonl(INADDR_ANY);
3249 else if (interface_bind(s, fd, &uaddr.addr))
3250 in4->sin_addr.s_addr = htonl(INADDR_ANY);
3252 if (bind(fd, &uaddr.addr, uaddrlen) < 0)
3254 int loc_errno = errno;
3255 WARN("\tfailure - errno = %i\n", errno);
3256 errno = loc_errno;
3257 switch (errno)
3259 case EADDRNOTAVAIL:
3260 SetLastError(WSAEINVAL);
3261 break;
3262 case EADDRINUSE:
3264 int optval = 0;
3265 socklen_t optlen = sizeof(optval);
3266 /* Windows >= 2003 will return different results depending on
3267 * SO_REUSEADDR, WSAEACCES may be returned representing that
3268 * the socket hijacking protection prevented the bind */
3269 if (!getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, &optlen) && optval)
3271 SetLastError(WSAEACCES);
3272 break;
3274 /* fall through */
3276 default:
3277 SetLastError(wsaErrno());
3278 break;
3281 else
3283 res=0; /* success */
3287 release_sock_fd( s, fd );
3289 return res;
3292 /***********************************************************************
3293 * closesocket (WS2_32.3)
3295 int WINAPI WS_closesocket(SOCKET s)
3297 int res = SOCKET_ERROR, fd;
3298 if (num_startup)
3300 fd = get_sock_fd(s, FILE_READ_DATA, NULL);
3301 if (fd >= 0)
3303 release_sock_fd(s, fd);
3304 socket_list_remove(s);
3305 if (CloseHandle(SOCKET2HANDLE(s)))
3306 res = 0;
3309 else
3310 SetLastError(WSANOTINITIALISED);
3311 TRACE("(socket %04lx) -> %d\n", s, res);
3312 return res;
3315 static int do_connect(int fd, const struct WS_sockaddr* name, int namelen)
3317 union generic_unix_sockaddr uaddr;
3318 unsigned int uaddrlen = ws_sockaddr_ws2u(name, namelen, &uaddr);
3320 if (!uaddrlen)
3321 return WSAEFAULT;
3323 if (name->sa_family == WS_AF_INET)
3325 struct sockaddr_in *in4 = (struct sockaddr_in*) &uaddr;
3326 if (memcmp(&in4->sin_addr, magic_loopback_addr, 4) == 0)
3328 /* Trying to connect to magic replace-loopback address,
3329 * assuming we really want to connect to localhost */
3330 TRACE("Trying to connect to magic IP address, using "
3331 "INADDR_LOOPBACK instead.\n");
3332 in4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
3336 if (connect(fd, &uaddr.addr, uaddrlen) == 0)
3337 return 0;
3339 return wsaErrno();
3342 /***********************************************************************
3343 * connect (WS2_32.4)
3345 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
3347 int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
3349 TRACE("socket %04lx, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
3351 if (fd != -1)
3353 BOOL is_blocking;
3354 int ret = do_connect(fd, name, namelen);
3355 if (ret == 0)
3356 goto connect_success;
3358 if (ret == WSAEINPROGRESS)
3360 /* tell wineserver that a connection is in progress */
3361 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
3362 FD_CONNECT,
3363 FD_WINE_CONNECTED|FD_WINE_LISTENING);
3364 ret = sock_is_blocking( s, &is_blocking );
3365 if (!ret)
3367 if (is_blocking)
3369 do_block(fd, POLLIN | POLLOUT, -1);
3370 _sync_sock_state(s); /* let wineserver notice connection */
3371 /* retrieve any error codes from it */
3372 if (!(ret = get_sock_error(s, FD_CONNECT_BIT))) goto connect_success;
3374 else ret = WSAEWOULDBLOCK;
3377 release_sock_fd( s, fd );
3378 SetLastError(ret);
3380 return SOCKET_ERROR;
3382 connect_success:
3383 release_sock_fd( s, fd );
3384 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
3385 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
3386 FD_CONNECT|FD_WINE_LISTENING);
3387 TRACE("\tconnected %04lx\n", s);
3388 return 0;
3391 /***********************************************************************
3392 * WSAConnect (WS2_32.30)
3394 int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
3395 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
3396 LPQOS lpSQOS, LPQOS lpGQOS )
3398 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
3399 FIXME("unsupported parameters!\n");
3400 return WS_connect( s, name, namelen );
3403 /***********************************************************************
3404 * ConnectEx
3406 static BOOL WINAPI WS2_ConnectEx(SOCKET s, const struct WS_sockaddr* name, int namelen,
3407 PVOID sendBuf, DWORD sendBufLen, LPDWORD sent, LPOVERLAPPED ov)
3409 int fd, ret, status;
3411 if (!ov)
3413 SetLastError( ERROR_INVALID_PARAMETER );
3414 return FALSE;
3417 fd = get_sock_fd( s, FILE_READ_DATA, NULL );
3418 if (fd == -1) return FALSE;
3420 TRACE("socket %04lx, ptr %p %s, length %d, sendptr %p, len %d, ov %p\n",
3421 s, name, debugstr_sockaddr(name), namelen, sendBuf, sendBufLen, ov);
3423 ret = is_fd_bound(fd, NULL, NULL);
3424 if (ret <= 0)
3426 SetLastError(ret == -1 ? wsaErrno() : WSAEINVAL);
3427 release_sock_fd( s, fd );
3428 return FALSE;
3431 ret = do_connect(fd, name, namelen);
3432 if (ret == 0)
3434 WSABUF wsabuf;
3436 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
3437 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
3438 FD_CONNECT|FD_WINE_LISTENING);
3440 wsabuf.len = sendBufLen;
3441 wsabuf.buf = (char*) sendBuf;
3443 /* WSASend takes care of completion if need be */
3444 if (WSASend(s, &wsabuf, sendBuf ? 1 : 0, sent, 0, ov, NULL) != SOCKET_ERROR)
3445 goto connection_success;
3447 else if (ret == WSAEINPROGRESS)
3449 struct ws2_async *wsa;
3450 ULONG_PTR cvalue = (((ULONG_PTR)ov->hEvent & 1) == 0) ? (ULONG_PTR)ov : 0;
3452 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
3453 FD_CONNECT,
3454 FD_WINE_CONNECTED|FD_WINE_LISTENING);
3456 /* Indirectly call WSASend */
3457 if (!(wsa = (struct ws2_async *)alloc_async_io( offsetof( struct ws2_async, iovec[1] ), WS2_async_send )))
3459 SetLastError(WSAEFAULT);
3461 else
3463 IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)ov;
3464 iosb->u.Status = STATUS_PENDING;
3465 iosb->Information = 0;
3467 wsa->hSocket = SOCKET2HANDLE(s);
3468 wsa->addr = NULL;
3469 wsa->addrlen.val = 0;
3470 wsa->flags = 0;
3471 wsa->lpFlags = &wsa->flags;
3472 wsa->control = NULL;
3473 wsa->n_iovecs = sendBuf ? 1 : 0;
3474 wsa->first_iovec = 0;
3475 wsa->completion_func = NULL;
3476 wsa->iovec[0].iov_base = sendBuf;
3477 wsa->iovec[0].iov_len = sendBufLen;
3479 status = register_async( ASYNC_TYPE_WRITE, wsa->hSocket, &wsa->io, ov->hEvent,
3480 NULL, (void *)cvalue, iosb );
3481 if (status != STATUS_PENDING) HeapFree(GetProcessHeap(), 0, wsa);
3483 /* If the connect already failed */
3484 if (status == STATUS_PIPE_DISCONNECTED)
3486 ov->Internal = sock_error_to_ntstatus( get_sock_error( s, FD_CONNECT_BIT ));
3487 ov->InternalHigh = 0;
3488 if (cvalue) WS_AddCompletion( s, cvalue, ov->Internal, ov->InternalHigh, TRUE );
3489 if (ov->hEvent) NtSetEvent( ov->hEvent, NULL );
3490 status = STATUS_PENDING;
3492 SetLastError( NtStatusToWSAError(status) );
3495 else
3497 SetLastError(ret);
3500 release_sock_fd( s, fd );
3501 return FALSE;
3503 connection_success:
3504 release_sock_fd( s, fd );
3505 return TRUE;
3508 /***********************************************************************
3509 * DisconnectEx
3511 static BOOL WINAPI WS2_DisconnectEx( SOCKET s, LPOVERLAPPED ov, DWORD flags, DWORD reserved )
3513 TRACE( "socket %04lx, ov %p, flags 0x%x, reserved 0x%x\n", s, ov, flags, reserved );
3515 if (flags & TF_REUSE_SOCKET)
3516 FIXME( "Reusing socket not supported yet\n" );
3518 if (ov)
3520 ov->Internal = STATUS_PENDING;
3521 ov->InternalHigh = 0;
3524 return !WS_shutdown( s, SD_BOTH );
3527 /***********************************************************************
3528 * getpeername (WS2_32.5)
3530 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
3532 int fd;
3533 int res;
3535 TRACE("socket %04lx, ptr %p, len %08x\n", s, name, namelen ? *namelen : 0);
3537 fd = get_sock_fd( s, 0, NULL );
3538 res = SOCKET_ERROR;
3540 if (fd != -1)
3542 union generic_unix_sockaddr uaddr;
3543 socklen_t uaddrlen = sizeof(uaddr);
3545 if (getpeername(fd, &uaddr.addr, &uaddrlen) == 0)
3547 if (!name || !namelen)
3548 SetLastError(WSAEFAULT);
3549 else if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
3550 /* The buffer was too small */
3551 SetLastError(WSAEFAULT);
3552 else
3554 res = 0;
3555 TRACE("=> %s\n", debugstr_sockaddr(name));
3558 else
3559 SetLastError(wsaErrno());
3560 release_sock_fd( s, fd );
3562 return res;
3565 /* When binding to an UDP address with filter support the getsockname call on the socket
3566 * will always return 0.0.0.0 instead of the filtered interface address. This function
3567 * checks if the socket is interface-bound on UDP and return the correct address.
3568 * This is required because applications often do a bind() with port zero followed by a
3569 * getsockname() to retrieve the port and address acquired.
3571 static void interface_bind_check(int fd, struct sockaddr_in *addr)
3573 #if !defined(IP_BOUND_IF) && !defined(LINUX_BOUND_IF)
3574 return;
3575 #else
3576 unsigned int ifindex;
3577 int ret;
3578 socklen_t len;
3580 /* Check for IPv4, address 0.0.0.0 and UDP socket */
3581 if (addr->sin_family != AF_INET || addr->sin_addr.s_addr != 0)
3582 return;
3583 if (_get_fd_type(fd) != SOCK_DGRAM)
3584 return;
3586 len = sizeof(ifindex);
3587 #if defined(IP_BOUND_IF)
3588 ret = getsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &ifindex, &len);
3589 #elif defined(LINUX_BOUND_IF)
3590 ret = getsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, &len);
3591 if (!ret) ifindex = ntohl(ifindex);
3592 #endif
3593 if (!ret && ifindex)
3595 EnterCriticalSection(&cs_if_addr_cache);
3596 if (ifindex < if_addr_cache_size)
3597 addr->sin_addr.s_addr = if_addr_cache[ifindex];
3598 else
3599 ERR("No cache entry for ifindex %u.\n", ifindex);
3600 LeaveCriticalSection(&cs_if_addr_cache);
3602 #endif
3605 /***********************************************************************
3606 * getsockname (WS2_32.6)
3608 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
3610 int fd;
3611 int res;
3613 TRACE("socket %04lx, ptr %p, len %08x\n", s, name, namelen ? *namelen : 0);
3615 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
3616 if( (name == NULL) || (namelen == NULL) )
3618 SetLastError( WSAEFAULT );
3619 return SOCKET_ERROR;
3622 fd = get_sock_fd( s, 0, NULL );
3623 res = SOCKET_ERROR;
3625 if (fd != -1)
3627 union generic_unix_sockaddr uaddr;
3628 socklen_t uaddrlen;
3629 int bound = is_fd_bound(fd, &uaddr, &uaddrlen);
3631 if (bound <= 0)
3633 SetLastError(bound == -1 ? wsaErrno() : WSAEINVAL);
3635 else if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
3637 /* The buffer was too small */
3638 SetLastError(WSAEFAULT);
3640 else
3642 interface_bind_check(fd, (struct sockaddr_in*) &uaddr);
3643 if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
3645 /* The buffer was too small */
3646 SetLastError(WSAEFAULT);
3648 else
3650 res = 0;
3651 TRACE("=> %s\n", debugstr_sockaddr(name));
3654 release_sock_fd( s, fd );
3656 return res;
3659 /***********************************************************************
3660 * getsockopt (WS2_32.7)
3662 INT WINAPI WS_getsockopt(SOCKET s, INT level,
3663 INT optname, char *optval, INT *optlen)
3665 int fd;
3666 INT ret = 0;
3668 TRACE("(socket %04lx, %s, optval %s, optlen %p (%d))\n", s,
3669 debugstr_sockopt(level, optname), debugstr_optval(optval, 0),
3670 optlen, optlen ? *optlen : 0);
3672 switch(level)
3674 case WS_SOL_SOCKET:
3676 switch(optname)
3678 /* Handle common cases. The special cases are below, sorted
3679 * alphabetically */
3680 case WS_SO_BROADCAST:
3681 case WS_SO_DEBUG:
3682 case WS_SO_KEEPALIVE:
3683 case WS_SO_OOBINLINE:
3684 case WS_SO_RCVBUF:
3685 case WS_SO_REUSEADDR:
3686 case WS_SO_SNDBUF:
3687 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3688 return SOCKET_ERROR;
3689 convert_sockopt(&level, &optname);
3690 if (getsockopt(fd, level, optname, optval, (socklen_t *)optlen) != 0 )
3692 SetLastError(wsaErrno());
3693 ret = SOCKET_ERROR;
3695 release_sock_fd( s, fd );
3696 return ret;
3697 case WS_SO_ACCEPTCONN:
3698 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3699 return SOCKET_ERROR;
3700 if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, optval, (socklen_t *)optlen) != 0 )
3702 SetLastError(wsaErrno());
3703 ret = SOCKET_ERROR;
3705 else
3707 /* BSD returns != 0 while Windows return exact == 1 */
3708 if (*(int *)optval) *(int *)optval = 1;
3710 release_sock_fd( s, fd );
3711 return ret;
3712 case WS_SO_BSP_STATE:
3714 int req_size, addr_size;
3715 WSAPROTOCOL_INFOW infow;
3716 CSADDR_INFO *csinfo;
3718 ret = ws_protocol_info(s, TRUE, &infow, &addr_size);
3719 if (ret)
3721 if (infow.iAddressFamily == WS_AF_INET)
3722 addr_size = sizeof(struct sockaddr_in);
3723 else if (infow.iAddressFamily == WS_AF_INET6)
3724 addr_size = sizeof(struct sockaddr_in6);
3725 else
3727 FIXME("Family %d is unsupported for SO_BSP_STATE\n", infow.iAddressFamily);
3728 SetLastError(WSAEAFNOSUPPORT);
3729 return SOCKET_ERROR;
3732 req_size = sizeof(CSADDR_INFO) + addr_size * 2;
3733 if (*optlen < req_size)
3735 ret = 0;
3736 SetLastError(WSAEFAULT);
3738 else
3740 union generic_unix_sockaddr uaddr;
3741 socklen_t uaddrlen;
3743 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3744 return SOCKET_ERROR;
3746 csinfo = (CSADDR_INFO*) optval;
3748 /* Check if the sock is bound */
3749 if (is_fd_bound(fd, &uaddr, &uaddrlen) == 1)
3751 csinfo->LocalAddr.lpSockaddr =
3752 (LPSOCKADDR) (optval + sizeof(CSADDR_INFO));
3753 ws_sockaddr_u2ws(&uaddr.addr, csinfo->LocalAddr.lpSockaddr, &addr_size);
3754 csinfo->LocalAddr.iSockaddrLength = addr_size;
3756 else
3758 csinfo->LocalAddr.lpSockaddr = NULL;
3759 csinfo->LocalAddr.iSockaddrLength = 0;
3762 /* Check if the sock is connected */
3763 if (!getpeername(fd, &uaddr.addr, &uaddrlen) &&
3764 is_sockaddr_bound(&uaddr.addr, uaddrlen))
3766 csinfo->RemoteAddr.lpSockaddr =
3767 (LPSOCKADDR) (optval + sizeof(CSADDR_INFO) + addr_size);
3768 ws_sockaddr_u2ws(&uaddr.addr, csinfo->RemoteAddr.lpSockaddr, &addr_size);
3769 csinfo->RemoteAddr.iSockaddrLength = addr_size;
3771 else
3773 csinfo->RemoteAddr.lpSockaddr = NULL;
3774 csinfo->RemoteAddr.iSockaddrLength = 0;
3777 csinfo->iSocketType = infow.iSocketType;
3778 csinfo->iProtocol = infow.iProtocol;
3779 release_sock_fd( s, fd );
3782 return ret ? 0 : SOCKET_ERROR;
3784 case WS_SO_DONTLINGER:
3786 struct linger lingval;
3787 socklen_t len = sizeof(struct linger);
3789 if (!optlen || *optlen < sizeof(BOOL)|| !optval)
3791 SetLastError(WSAEFAULT);
3792 return SOCKET_ERROR;
3794 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3795 return SOCKET_ERROR;
3797 if (getsockopt(fd, SOL_SOCKET, SO_LINGER, &lingval, &len) != 0 )
3799 SetLastError(wsaErrno());
3800 ret = SOCKET_ERROR;
3802 else
3804 *(BOOL *)optval = !lingval.l_onoff;
3805 *optlen = sizeof(BOOL);
3808 release_sock_fd( s, fd );
3809 return ret;
3812 case WS_SO_CONNECT_TIME:
3814 static int pretendtime = 0;
3815 struct WS_sockaddr addr;
3816 int len = sizeof(addr);
3818 if (!optlen || *optlen < sizeof(DWORD) || !optval)
3820 SetLastError(WSAEFAULT);
3821 return SOCKET_ERROR;
3823 if (WS_getpeername(s, &addr, &len) == SOCKET_ERROR)
3824 *(DWORD *)optval = ~0u;
3825 else
3827 if (!pretendtime) FIXME("WS_SO_CONNECT_TIME - faking results\n");
3828 *(DWORD *)optval = pretendtime++;
3830 *optlen = sizeof(DWORD);
3831 return ret;
3833 /* As mentioned in setsockopt, Windows ignores this, so we
3834 * always return true here */
3835 case WS_SO_DONTROUTE:
3836 if (!optlen || *optlen < sizeof(BOOL) || !optval)
3838 SetLastError(WSAEFAULT);
3839 return SOCKET_ERROR;
3841 *(BOOL *)optval = TRUE;
3842 *optlen = sizeof(BOOL);
3843 return 0;
3845 case WS_SO_ERROR:
3847 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3848 return SOCKET_ERROR;
3849 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, optval, (socklen_t *)optlen) != 0 )
3851 SetLastError(wsaErrno());
3852 ret = SOCKET_ERROR;
3854 release_sock_fd( s, fd );
3856 /* The wineserver may have swallowed the error before us */
3857 if (!ret && *(int*) optval == 0)
3859 int i, events[FD_MAX_EVENTS];
3860 _get_sock_errors(s, events);
3861 for (i = 0; i < FD_MAX_EVENTS; i++)
3863 if(events[i])
3865 TRACE("returning SO_ERROR %d from wine server\n", events[i]);
3866 *(int*) optval = events[i];
3867 break;
3871 return ret;
3874 case WS_SO_LINGER:
3876 struct linger lingval;
3877 socklen_t len = sizeof(struct linger);
3879 /* struct linger and LINGER have different sizes */
3880 if (!optlen || *optlen < sizeof(LINGER) || !optval)
3882 SetLastError(WSAEFAULT);
3883 return SOCKET_ERROR;
3885 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3886 return SOCKET_ERROR;
3888 if (_get_fd_type(fd) == SOCK_DGRAM)
3890 SetLastError(WSAENOPROTOOPT);
3891 ret = SOCKET_ERROR;
3893 else if (getsockopt(fd, SOL_SOCKET, SO_LINGER, &lingval, &len) != 0)
3895 SetLastError(wsaErrno());
3896 ret = SOCKET_ERROR;
3898 else
3900 ((LINGER *)optval)->l_onoff = lingval.l_onoff;
3901 ((LINGER *)optval)->l_linger = lingval.l_linger;
3902 *optlen = sizeof(struct linger);
3905 release_sock_fd( s, fd );
3906 return ret;
3909 case WS_SO_MAX_MSG_SIZE:
3910 if (!optlen || *optlen < sizeof(int) || !optval)
3912 SetLastError(WSAEFAULT);
3913 return SOCKET_ERROR;
3915 TRACE("getting global SO_MAX_MSG_SIZE = 65507\n");
3916 *(int *)optval = 65507;
3917 *optlen = sizeof(int);
3918 return 0;
3920 /* SO_OPENTYPE does not require a valid socket handle. */
3921 case WS_SO_OPENTYPE:
3922 if (!optlen || *optlen < sizeof(int) || !optval)
3924 SetLastError(WSAEFAULT);
3925 return SOCKET_ERROR;
3927 *(int *)optval = get_per_thread_data()->opentype;
3928 *optlen = sizeof(int);
3929 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
3930 return 0;
3931 case WS_SO_PROTOCOL_INFOA:
3932 case WS_SO_PROTOCOL_INFOW:
3934 int size;
3935 WSAPROTOCOL_INFOW infow;
3937 ret = ws_protocol_info(s, optname == WS_SO_PROTOCOL_INFOW, &infow, &size);
3938 if (ret)
3940 if (!optlen || !optval || *optlen < size)
3942 if(optlen) *optlen = size;
3943 ret = 0;
3944 SetLastError(WSAEFAULT);
3946 else
3947 memcpy(optval, &infow, size);
3949 return ret ? 0 : SOCKET_ERROR;
3951 case WS_SO_RCVTIMEO:
3952 case WS_SO_SNDTIMEO:
3954 INT64 timeout;
3956 if (!optlen || *optlen < sizeof(int)|| !optval)
3958 SetLastError(WSAEFAULT);
3959 return SOCKET_ERROR;
3961 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3962 return SOCKET_ERROR;
3964 timeout = get_rcvsnd_timeo(fd, optname == WS_SO_RCVTIMEO);
3965 *(int *)optval = timeout <= UINT_MAX ? timeout : UINT_MAX;
3967 release_sock_fd( s, fd );
3968 return ret;
3970 case WS_SO_TYPE:
3972 int sock_type;
3973 if (!optlen || *optlen < sizeof(int) || !optval)
3975 SetLastError(WSAEFAULT);
3976 return SOCKET_ERROR;
3978 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3979 return SOCKET_ERROR;
3981 sock_type = _get_fd_type(fd);
3982 if (sock_type == -1)
3984 SetLastError(wsaErrno());
3985 ret = SOCKET_ERROR;
3987 else
3988 (*(int *)optval) = convert_socktype_u2w(sock_type);
3990 release_sock_fd( s, fd );
3991 return ret;
3993 default:
3994 TRACE("Unknown SOL_SOCKET optname: 0x%08x\n", optname);
3995 SetLastError(WSAENOPROTOOPT);
3996 return SOCKET_ERROR;
3997 } /* end switch(optname) */
3998 }/* end case WS_SOL_SOCKET */
3999 #ifdef HAS_IPX
4000 case WS_NSPROTO_IPX:
4002 struct WS_sockaddr_ipx addr;
4003 IPX_ADDRESS_DATA *data;
4004 int namelen;
4005 switch(optname)
4007 case WS_IPX_PTYPE:
4008 if ((fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR;
4009 #ifdef SOL_IPX
4010 if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, (socklen_t *)optlen) == -1)
4012 ret = SOCKET_ERROR;
4014 #else
4016 struct ipx val;
4017 socklen_t len=sizeof(struct ipx);
4018 if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
4019 ret = SOCKET_ERROR;
4020 else
4021 *optval = (int)val.ipx_pt;
4023 #endif
4024 TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
4025 release_sock_fd( s, fd );
4026 return ret;
4028 case WS_IPX_ADDRESS:
4030 * On a Win2000 system with one network card there are usually
4031 * three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
4032 * Using this call you can then retrieve info about this all.
4033 * In case of Linux it is a bit different. Usually you have
4034 * only "one" device active and further it is not possible to
4035 * query things like the linkspeed.
4037 FIXME("IPX_ADDRESS\n");
4038 namelen = sizeof(struct WS_sockaddr_ipx);
4039 memset(&addr, 0, sizeof(struct WS_sockaddr_ipx));
4040 WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
4042 data = (IPX_ADDRESS_DATA*)optval;
4043 memcpy(data->nodenum,addr.sa_nodenum,sizeof(data->nodenum));
4044 memcpy(data->netnum,addr.sa_netnum,sizeof(data->netnum));
4045 data->adapternum = 0;
4046 data->wan = FALSE; /* We are not on a wan for now .. */
4047 data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
4048 data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
4049 data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit;
4050 * note 1MB = 1000kB in this case */
4051 return 0;
4053 case WS_IPX_MAX_ADAPTER_NUM:
4054 FIXME("IPX_MAX_ADAPTER_NUM\n");
4055 *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
4056 return 0;
4058 default:
4059 FIXME("IPX optname:%x\n", optname);
4060 return SOCKET_ERROR;
4061 }/* end switch(optname) */
4062 } /* end case WS_NSPROTO_IPX */
4063 #endif
4065 #ifdef HAS_IRDA
4066 #define MAX_IRDA_DEVICES 10
4068 case WS_SOL_IRLMP:
4069 switch(optname)
4071 case WS_IRLMP_ENUMDEVICES:
4073 char buf[sizeof(struct irda_device_list) +
4074 (MAX_IRDA_DEVICES - 1) * sizeof(struct irda_device_info)];
4075 int res;
4076 socklen_t len = sizeof(buf);
4078 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
4079 return SOCKET_ERROR;
4080 res = getsockopt( fd, SOL_IRLMP, IRLMP_ENUMDEVICES, buf, &len );
4081 release_sock_fd( s, fd );
4082 if (res < 0)
4084 SetLastError(wsaErrno());
4085 return SOCKET_ERROR;
4087 else
4089 struct irda_device_list *src = (struct irda_device_list *)buf;
4090 DEVICELIST *dst = (DEVICELIST *)optval;
4091 INT needed = sizeof(DEVICELIST);
4092 unsigned int i;
4094 if (src->len > 0)
4095 needed += (src->len - 1) * sizeof(IRDA_DEVICE_INFO);
4096 if (*optlen < needed)
4098 SetLastError(WSAEFAULT);
4099 return SOCKET_ERROR;
4101 *optlen = needed;
4102 TRACE("IRLMP_ENUMDEVICES: %d devices found:\n", src->len);
4103 dst->numDevice = src->len;
4104 for (i = 0; i < src->len; i++)
4106 TRACE("saddr = %08x, daddr = %08x, info = %s, hints = %02x%02x\n",
4107 src->dev[i].saddr, src->dev[i].daddr,
4108 src->dev[i].info, src->dev[i].hints[0],
4109 src->dev[i].hints[1]);
4110 memcpy( dst->Device[i].irdaDeviceID,
4111 &src->dev[i].daddr,
4112 sizeof(dst->Device[i].irdaDeviceID) ) ;
4113 memcpy( dst->Device[i].irdaDeviceName,
4114 src->dev[i].info,
4115 sizeof(dst->Device[i].irdaDeviceName) ) ;
4116 memcpy( &dst->Device[i].irdaDeviceHints1,
4117 &src->dev[i].hints[0],
4118 sizeof(dst->Device[i].irdaDeviceHints1) ) ;
4119 memcpy( &dst->Device[i].irdaDeviceHints2,
4120 &src->dev[i].hints[1],
4121 sizeof(dst->Device[i].irdaDeviceHints2) ) ;
4122 dst->Device[i].irdaCharSet = src->dev[i].charset;
4124 return 0;
4127 default:
4128 FIXME("IrDA optname:0x%x\n", optname);
4129 return SOCKET_ERROR;
4131 break; /* case WS_SOL_IRLMP */
4132 #undef MAX_IRDA_DEVICES
4133 #endif
4135 /* Levels WS_IPPROTO_TCP and WS_IPPROTO_IP convert directly */
4136 case WS_IPPROTO_TCP:
4137 switch(optname)
4139 case WS_TCP_NODELAY:
4140 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
4141 return SOCKET_ERROR;
4142 convert_sockopt(&level, &optname);
4143 if (getsockopt(fd, level, optname, optval, (socklen_t *)optlen) != 0 )
4145 SetLastError(wsaErrno());
4146 ret = SOCKET_ERROR;
4148 release_sock_fd( s, fd );
4149 return ret;
4151 FIXME("Unknown IPPROTO_TCP optname 0x%08x\n", optname);
4152 return SOCKET_ERROR;
4154 case WS_IPPROTO_IP:
4155 switch(optname)
4157 case WS_IP_ADD_MEMBERSHIP:
4158 case WS_IP_DROP_MEMBERSHIP:
4159 #ifdef IP_HDRINCL
4160 case WS_IP_HDRINCL:
4161 #endif
4162 case WS_IP_MULTICAST_IF:
4163 case WS_IP_MULTICAST_LOOP:
4164 case WS_IP_MULTICAST_TTL:
4165 case WS_IP_OPTIONS:
4166 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
4167 case WS_IP_PKTINFO:
4168 #endif
4169 case WS_IP_TOS:
4170 case WS_IP_TTL:
4171 #ifdef IP_UNICAST_IF
4172 case WS_IP_UNICAST_IF:
4173 #endif
4174 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
4175 return SOCKET_ERROR;
4176 convert_sockopt(&level, &optname);
4177 if (getsockopt(fd, level, optname, optval, (socklen_t *)optlen) != 0 )
4179 SetLastError(wsaErrno());
4180 ret = SOCKET_ERROR;
4182 release_sock_fd( s, fd );
4183 return ret;
4184 case WS_IP_DONTFRAGMENT:
4185 return get_dont_fragment(s, IPPROTO_IP, (BOOL *)optval) ? 0 : SOCKET_ERROR;
4187 FIXME("Unknown IPPROTO_IP optname 0x%08x\n", optname);
4188 return SOCKET_ERROR;
4190 case WS_IPPROTO_IPV6:
4191 switch(optname)
4193 #ifdef IPV6_ADD_MEMBERSHIP
4194 case WS_IPV6_ADD_MEMBERSHIP:
4195 #endif
4196 #ifdef IPV6_DROP_MEMBERSHIP
4197 case WS_IPV6_DROP_MEMBERSHIP:
4198 #endif
4199 case WS_IPV6_MULTICAST_IF:
4200 case WS_IPV6_MULTICAST_HOPS:
4201 case WS_IPV6_MULTICAST_LOOP:
4202 case WS_IPV6_UNICAST_HOPS:
4203 case WS_IPV6_V6ONLY:
4204 #ifdef IPV6_UNICAST_IF
4205 case WS_IPV6_UNICAST_IF:
4206 #endif
4207 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
4208 return SOCKET_ERROR;
4209 convert_sockopt(&level, &optname);
4210 if (getsockopt(fd, level, optname, optval, (socklen_t *)optlen) != 0 )
4212 SetLastError(wsaErrno());
4213 ret = SOCKET_ERROR;
4215 release_sock_fd( s, fd );
4216 return ret;
4217 case WS_IPV6_DONTFRAG:
4218 return get_dont_fragment(s, IPPROTO_IPV6, (BOOL *)optval) ? 0 : SOCKET_ERROR;
4220 FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname);
4221 return SOCKET_ERROR;
4223 default:
4224 WARN("Unknown level: 0x%08x\n", level);
4225 SetLastError(WSAEINVAL);
4226 return SOCKET_ERROR;
4227 } /* end switch(level) */
4230 /***********************************************************************
4231 * htonl (WS2_32.8)
4233 WS_u_long WINAPI WS_htonl(WS_u_long hostlong)
4235 return htonl(hostlong);
4239 /***********************************************************************
4240 * htons (WS2_32.9)
4242 WS_u_short WINAPI WS_htons(WS_u_short hostshort)
4244 return htons(hostshort);
4247 /***********************************************************************
4248 * WSAHtonl (WS2_32.46)
4249 * From MSDN description of error codes, this function should also
4250 * check if WinSock has been initialized and the socket is a valid
4251 * socket. But why? This function only translates a host byte order
4252 * u_long into a network byte order u_long...
4254 int WINAPI WSAHtonl(SOCKET s, WS_u_long hostlong, WS_u_long *lpnetlong)
4256 if (lpnetlong)
4258 *lpnetlong = htonl(hostlong);
4259 return 0;
4261 SetLastError(WSAEFAULT);
4262 return SOCKET_ERROR;
4265 /***********************************************************************
4266 * WSAHtons (WS2_32.47)
4267 * From MSDN description of error codes, this function should also
4268 * check if WinSock has been initialized and the socket is a valid
4269 * socket. But why? This function only translates a host byte order
4270 * u_short into a network byte order u_short...
4272 int WINAPI WSAHtons(SOCKET s, WS_u_short hostshort, WS_u_short *lpnetshort)
4275 if (lpnetshort)
4277 *lpnetshort = htons(hostshort);
4278 return 0;
4280 SetLastError(WSAEFAULT);
4281 return SOCKET_ERROR;
4285 /***********************************************************************
4286 * inet_addr (WS2_32.11)
4288 WS_u_long WINAPI WS_inet_addr(const char *cp)
4290 if (!cp) return INADDR_NONE;
4291 return inet_addr(cp);
4295 /***********************************************************************
4296 * ntohl (WS2_32.14)
4298 WS_u_long WINAPI WS_ntohl(WS_u_long netlong)
4300 return ntohl(netlong);
4304 /***********************************************************************
4305 * ntohs (WS2_32.15)
4307 WS_u_short WINAPI WS_ntohs(WS_u_short netshort)
4309 return ntohs(netshort);
4313 /***********************************************************************
4314 * inet_ntoa (WS2_32.12)
4316 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
4318 unsigned int long_ip = ntohl(in.WS_s_addr);
4319 struct per_thread_data *data = get_per_thread_data();
4321 sprintf( data->ntoa_buffer, "%u.%u.%u.%u",
4322 (long_ip >> 24) & 0xff,
4323 (long_ip >> 16) & 0xff,
4324 (long_ip >> 8) & 0xff,
4325 long_ip & 0xff);
4327 return data->ntoa_buffer;
4330 static const char *debugstr_wsaioctl(DWORD code)
4332 const char *name = NULL, *buf_type, *family;
4334 #define IOCTL_NAME(x) case x: name = #x; break
4335 switch (code)
4337 IOCTL_NAME(WS_FIONBIO);
4338 IOCTL_NAME(WS_FIONREAD);
4339 IOCTL_NAME(WS_SIOCATMARK);
4340 /* IOCTL_NAME(WS_SIO_ACQUIRE_PORT_RESERVATION); */
4341 IOCTL_NAME(WS_SIO_ADDRESS_LIST_CHANGE);
4342 IOCTL_NAME(WS_SIO_ADDRESS_LIST_QUERY);
4343 IOCTL_NAME(WS_SIO_ASSOCIATE_HANDLE);
4344 /* IOCTL_NAME(WS_SIO_ASSOCIATE_PORT_RESERVATION);
4345 IOCTL_NAME(WS_SIO_BASE_HANDLE);
4346 IOCTL_NAME(WS_SIO_BSP_HANDLE);
4347 IOCTL_NAME(WS_SIO_BSP_HANDLE_SELECT);
4348 IOCTL_NAME(WS_SIO_BSP_HANDLE_POLL);
4349 IOCTL_NAME(WS_SIO_CHK_QOS); */
4350 IOCTL_NAME(WS_SIO_ENABLE_CIRCULAR_QUEUEING);
4351 IOCTL_NAME(WS_SIO_FIND_ROUTE);
4352 IOCTL_NAME(WS_SIO_FLUSH);
4353 IOCTL_NAME(WS_SIO_GET_BROADCAST_ADDRESS);
4354 IOCTL_NAME(WS_SIO_GET_EXTENSION_FUNCTION_POINTER);
4355 IOCTL_NAME(WS_SIO_GET_GROUP_QOS);
4356 IOCTL_NAME(WS_SIO_GET_INTERFACE_LIST);
4357 /* IOCTL_NAME(WS_SIO_GET_INTERFACE_LIST_EX); */
4358 IOCTL_NAME(WS_SIO_GET_QOS);
4359 IOCTL_NAME(WS_SIO_IDEAL_SEND_BACKLOG_CHANGE);
4360 IOCTL_NAME(WS_SIO_IDEAL_SEND_BACKLOG_QUERY);
4361 IOCTL_NAME(WS_SIO_KEEPALIVE_VALS);
4362 IOCTL_NAME(WS_SIO_MULTIPOINT_LOOPBACK);
4363 IOCTL_NAME(WS_SIO_MULTICAST_SCOPE);
4364 /* IOCTL_NAME(WS_SIO_QUERY_RSS_SCALABILITY_INFO);
4365 IOCTL_NAME(WS_SIO_QUERY_WFP_ALE_ENDPOINT_HANDLE); */
4366 IOCTL_NAME(WS_SIO_RCVALL);
4367 IOCTL_NAME(WS_SIO_RCVALL_IGMPMCAST);
4368 IOCTL_NAME(WS_SIO_RCVALL_MCAST);
4369 /* IOCTL_NAME(WS_SIO_RELEASE_PORT_RESERVATION); */
4370 IOCTL_NAME(WS_SIO_ROUTING_INTERFACE_CHANGE);
4371 IOCTL_NAME(WS_SIO_ROUTING_INTERFACE_QUERY);
4372 IOCTL_NAME(WS_SIO_SET_COMPATIBILITY_MODE);
4373 IOCTL_NAME(WS_SIO_SET_GROUP_QOS);
4374 IOCTL_NAME(WS_SIO_SET_QOS);
4375 IOCTL_NAME(WS_SIO_TRANSLATE_HANDLE);
4376 IOCTL_NAME(WS_SIO_UDP_CONNRESET);
4378 #undef IOCTL_NAME
4380 if (name)
4381 return name + 3;
4383 /* If this is not a known code split its bits */
4384 switch(code & 0x18000000)
4386 case WS_IOC_WS2:
4387 family = "IOC_WS2";
4388 break;
4389 case WS_IOC_PROTOCOL:
4390 family = "IOC_PROTOCOL";
4391 break;
4392 case WS_IOC_VENDOR:
4393 family = "IOC_VENDOR";
4394 break;
4395 default: /* WS_IOC_UNIX */
4397 BYTE size = (code >> 16) & WS_IOCPARM_MASK;
4398 char x = (code & 0xff00) >> 8;
4399 BYTE y = code & 0xff;
4400 char args[14];
4402 switch (code & (WS_IOC_VOID|WS_IOC_INOUT))
4404 case WS_IOC_VOID:
4405 buf_type = "_IO";
4406 sprintf(args, "%d, %d", x, y);
4407 break;
4408 case WS_IOC_IN:
4409 buf_type = "_IOW";
4410 sprintf(args, "'%c', %d, %d", x, y, size);
4411 break;
4412 case WS_IOC_OUT:
4413 buf_type = "_IOR";
4414 sprintf(args, "'%c', %d, %d", x, y, size);
4415 break;
4416 default:
4417 buf_type = "?";
4418 sprintf(args, "'%c', %d, %d", x, y, size);
4419 break;
4421 return wine_dbg_sprintf("%s(%s)", buf_type, args);
4425 /* We are different from WS_IOC_UNIX. */
4426 switch (code & (WS_IOC_VOID|WS_IOC_INOUT))
4428 case WS_IOC_VOID:
4429 buf_type = "_WSAIO";
4430 break;
4431 case WS_IOC_INOUT:
4432 buf_type = "_WSAIORW";
4433 break;
4434 case WS_IOC_IN:
4435 buf_type = "_WSAIOW";
4436 break;
4437 case WS_IOC_OUT:
4438 buf_type = "_WSAIOR";
4439 break;
4440 default:
4441 buf_type = "?";
4442 break;
4445 return wine_dbg_sprintf("%s(%s, %d)", buf_type, family,
4446 (USHORT)(code & 0xffff));
4449 /* do an ioctl call through the server */
4450 static DWORD server_ioctl_sock( SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size,
4451 LPVOID out_buff, DWORD out_size, LPDWORD ret_size,
4452 LPWSAOVERLAPPED overlapped,
4453 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4455 HANDLE event = overlapped ? overlapped->hEvent : 0;
4456 HANDLE handle = SOCKET2HANDLE( s );
4457 struct ws2_async *wsa = NULL;
4458 IO_STATUS_BLOCK *io = (PIO_STATUS_BLOCK)overlapped, iosb;
4459 void *cvalue = NULL;
4460 NTSTATUS status;
4462 if (completion)
4464 if (!(wsa = (struct ws2_async *)alloc_async_io( sizeof(*wsa), NULL )))
4465 return WSA_NOT_ENOUGH_MEMORY;
4466 wsa->hSocket = handle;
4467 wsa->user_overlapped = overlapped;
4468 wsa->completion_func = completion;
4469 if (!io) io = &wsa->local_iosb;
4470 cvalue = wsa;
4472 else if (!io)
4473 io = &iosb;
4474 else if (!((ULONG_PTR)overlapped->hEvent & 1))
4475 cvalue = overlapped;
4477 status = NtDeviceIoControlFile( handle, event, wsa ? ws2_async_apc : NULL, cvalue, io, code,
4478 in_buff, in_size, out_buff, out_size );
4479 if (status == STATUS_NOT_SUPPORTED)
4481 FIXME("Unsupported ioctl %x (device=%x access=%x func=%x method=%x)\n",
4482 code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
4484 else if (status == STATUS_SUCCESS)
4485 *ret_size = io->Information; /* "Information" is the size written to the output buffer */
4487 if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, wsa );
4489 return NtStatusToWSAError( status );
4492 static DWORD get_interface_list(SOCKET s, void *out_buff, DWORD out_size, DWORD *ret_size, DWORD *total_bytes)
4494 DWORD size, interface_count = 0, ret;
4495 INTERFACE_INFO *info = out_buff;
4496 PMIB_IPADDRTABLE table = NULL;
4497 DWORD status = 0;
4498 int fd;
4500 if (!out_buff || !ret_size)
4501 return WSAEFAULT;
4503 if ((fd = get_sock_fd(s, 0, NULL)) == -1)
4504 return SOCKET_ERROR;
4506 if ((ret = GetIpAddrTable(NULL, &size, TRUE)) != ERROR_INSUFFICIENT_BUFFER)
4508 if (ret != ERROR_NO_DATA)
4510 ERR("Unable to get ip address table.\n");
4511 status = WSAEINVAL;
4513 goto done;
4515 if (!(table = heap_alloc(size)))
4517 ERR("No memory.\n");
4518 status = WSAEINVAL;
4519 goto done;
4521 if (GetIpAddrTable(table, &size, TRUE) != NO_ERROR)
4523 ERR("Unable to get interface table./\n");
4524 status = WSAEINVAL;
4525 goto done;
4527 if (table->dwNumEntries * sizeof(INTERFACE_INFO) > out_size)
4529 WARN("Buffer too small, dwNumEntries %u, out_size = %u.\n", table->dwNumEntries, out_size);
4530 *ret_size = 0;
4531 status = WSAEFAULT;
4532 goto done;
4535 for (; interface_count < table->dwNumEntries; ++interface_count, ++info)
4537 unsigned int addr, mask;
4538 struct ifreq if_info;
4540 memset(info, 0, sizeof(*info));
4542 if_info.ifr_ifindex = table->table[interface_count].dwIndex;
4543 if (ioctl(fd, SIOCGIFNAME, &if_info) < 0)
4545 ERR("Error obtaining interface name for ifindex %d.\n", if_info.ifr_ifindex);
4546 status = WSAEINVAL;
4547 break;
4550 if (ioctl(fd, SIOCGIFFLAGS, &if_info) < 0)
4552 ERR("Error obtaining status flags for socket!\n");
4553 status = WSAEINVAL;
4554 break;
4557 if (if_info.ifr_flags & IFF_BROADCAST)
4558 info->iiFlags |= WS_IFF_BROADCAST;
4559 #ifdef IFF_POINTOPOINT
4560 if (if_info.ifr_flags & IFF_POINTOPOINT)
4561 info->iiFlags |= WS_IFF_POINTTOPOINT;
4562 #endif
4563 if (if_info.ifr_flags & IFF_LOOPBACK)
4564 info->iiFlags |= WS_IFF_LOOPBACK;
4565 if (if_info.ifr_flags & IFF_UP)
4566 info->iiFlags |= WS_IFF_UP;
4567 if (if_info.ifr_flags & IFF_MULTICAST)
4568 info->iiFlags |= WS_IFF_MULTICAST;
4570 addr = table->table[interface_count].dwAddr;
4571 mask = table->table[interface_count].dwMask;
4573 info->iiAddress.AddressIn.sin_family = WS_AF_INET;
4574 info->iiAddress.AddressIn.sin_port = 0;
4575 info->iiAddress.AddressIn.sin_addr.WS_s_addr = addr;
4577 info->iiNetmask.AddressIn.sin_family = WS_AF_INET;
4578 info->iiNetmask.AddressIn.sin_port = 0;
4579 info->iiNetmask.AddressIn.sin_addr.WS_s_addr = mask;
4581 if (if_info.ifr_flags & IFF_BROADCAST)
4583 info->iiBroadcastAddress.AddressIn.sin_family = WS_AF_INET;
4584 info->iiBroadcastAddress.AddressIn.sin_port = 0;
4585 info->iiBroadcastAddress.AddressIn.sin_addr.WS_s_addr = addr | ~mask;
4589 done:
4590 heap_free(table);
4591 *total_bytes = sizeof(INTERFACE_INFO) * interface_count;
4592 release_sock_fd(s, fd);
4593 return status;
4596 /**********************************************************************
4597 * WSAIoctl (WS2_32.50)
4600 INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID out_buff,
4601 DWORD out_size, LPDWORD ret_size, LPWSAOVERLAPPED overlapped,
4602 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4604 int fd;
4605 DWORD status = 0, total = 0;
4607 TRACE("%04lx, %s, %p, %d, %p, %d, %p, %p, %p\n",
4608 s, debugstr_wsaioctl(code), in_buff, in_size, out_buff, out_size, ret_size, overlapped, completion);
4610 switch (code)
4612 case WS_FIONBIO:
4613 if (in_size != sizeof(WS_u_long) || IS_INTRESOURCE(in_buff))
4615 SetLastError(WSAEFAULT);
4616 return SOCKET_ERROR;
4618 TRACE("-> FIONBIO (%x)\n", *(WS_u_long*)in_buff);
4619 if (_get_sock_mask(s))
4621 /* AsyncSelect()'ed sockets are always nonblocking */
4622 if (!*(WS_u_long *)in_buff) status = WSAEINVAL;
4623 break;
4625 if (*(WS_u_long *)in_buff)
4626 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
4627 else
4628 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
4629 break;
4631 case WS_FIONREAD:
4633 #if defined(linux)
4634 int listening = 0;
4635 socklen_t len = sizeof(listening);
4636 #endif
4637 if (out_size != sizeof(WS_u_long) || IS_INTRESOURCE(out_buff))
4639 SetLastError(WSAEFAULT);
4640 return SOCKET_ERROR;
4642 if ((fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR;
4644 #if defined(linux)
4645 /* On Linux, FIONREAD on listening socket always fails (see tcp(7)).
4646 However, it succeeds on native. */
4647 if (!getsockopt( fd, SOL_SOCKET, SO_ACCEPTCONN, &listening, &len ) && listening)
4648 (*(WS_u_long *) out_buff) = 0;
4649 else
4650 #endif
4651 if (ioctl(fd, FIONREAD, out_buff ) == -1)
4652 status = wsaErrno();
4653 release_sock_fd( s, fd );
4654 break;
4657 case WS_SIOCATMARK:
4659 unsigned int oob = 0, atmark = 0;
4660 socklen_t oobsize = sizeof(int);
4661 if (out_size != sizeof(WS_u_long) || IS_INTRESOURCE(out_buff))
4663 SetLastError(WSAEFAULT);
4664 return SOCKET_ERROR;
4666 if ((fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR;
4667 /* SO_OOBINLINE sockets must always return TRUE to SIOCATMARK */
4668 if ((getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &oob, &oobsize ) == -1)
4669 || (!oob && ioctl(fd, SIOCATMARK, &atmark ) == -1))
4670 status = wsaErrno();
4671 else
4673 /* The SIOCATMARK value read from ioctl() is reversed
4674 * because BSD returns TRUE if it's in the OOB mark
4675 * while Windows returns TRUE if there are NO OOB bytes.
4677 (*(WS_u_long *) out_buff) = oob || !atmark;
4680 release_sock_fd( s, fd );
4681 break;
4684 case WS_FIOASYNC:
4685 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
4686 SetLastError(WSAEINVAL);
4687 return SOCKET_ERROR;
4689 case WS_SIO_GET_INTERFACE_LIST:
4691 TRACE("-> SIO_GET_INTERFACE_LIST request\n");
4693 status = get_interface_list(s, out_buff, out_size, ret_size, &total);
4694 break;
4697 case WS_SIO_ADDRESS_LIST_QUERY:
4699 DWORD size;
4701 TRACE("-> SIO_ADDRESS_LIST_QUERY request\n");
4703 if (!ret_size)
4705 SetLastError(WSAEFAULT);
4706 return SOCKET_ERROR;
4709 if (out_size && out_size < FIELD_OFFSET(SOCKET_ADDRESS_LIST, Address[0]))
4711 *ret_size = 0;
4712 SetLastError(WSAEINVAL);
4713 return SOCKET_ERROR;
4716 if (GetAdaptersInfo(NULL, &size) == ERROR_BUFFER_OVERFLOW)
4718 IP_ADAPTER_INFO *p, *table = HeapAlloc(GetProcessHeap(), 0, size);
4719 SOCKET_ADDRESS_LIST *sa_list;
4720 SOCKADDR_IN *sockaddr;
4721 SOCKET_ADDRESS *sa;
4722 unsigned int i;
4723 DWORD num;
4725 if (!table || GetAdaptersInfo(table, &size))
4727 HeapFree(GetProcessHeap(), 0, table);
4728 status = WSAEINVAL;
4729 break;
4732 for (p = table, num = 0; p; p = p->Next)
4733 if (p->IpAddressList.IpAddress.String[0]) num++;
4735 total = FIELD_OFFSET(SOCKET_ADDRESS_LIST, Address[num]) + num * sizeof(*sockaddr);
4736 if (total > out_size || !out_buff)
4738 *ret_size = total;
4739 HeapFree(GetProcessHeap(), 0, table);
4740 status = WSAEFAULT;
4741 break;
4744 sa_list = out_buff;
4745 sa = sa_list->Address;
4746 sockaddr = (SOCKADDR_IN *)&sa[num];
4747 sa_list->iAddressCount = num;
4749 for (p = table, i = 0; p; p = p->Next)
4751 if (!p->IpAddressList.IpAddress.String[0]) continue;
4753 sa[i].lpSockaddr = (SOCKADDR *)&sockaddr[i];
4754 sa[i].iSockaddrLength = sizeof(SOCKADDR);
4756 sockaddr[i].sin_family = WS_AF_INET;
4757 sockaddr[i].sin_port = 0;
4758 sockaddr[i].sin_addr.WS_s_addr = inet_addr(p->IpAddressList.IpAddress.String);
4759 i++;
4762 HeapFree(GetProcessHeap(), 0, table);
4764 else
4766 WARN("unable to get IP address list\n");
4767 status = WSAEINVAL;
4769 break;
4772 case WS_SIO_FLUSH:
4773 FIXME("SIO_FLUSH: stub.\n");
4774 break;
4776 case WS_SIO_GET_EXTENSION_FUNCTION_POINTER:
4778 #define EXTENSION_FUNCTION(x, y) { x, y, #y },
4779 static const struct
4781 GUID guid;
4782 void *func_ptr;
4783 const char *name;
4784 } guid_funcs[] = {
4785 EXTENSION_FUNCTION(WSAID_CONNECTEX, WS2_ConnectEx)
4786 EXTENSION_FUNCTION(WSAID_DISCONNECTEX, WS2_DisconnectEx)
4787 EXTENSION_FUNCTION(WSAID_ACCEPTEX, WS2_AcceptEx)
4788 EXTENSION_FUNCTION(WSAID_GETACCEPTEXSOCKADDRS, WS2_GetAcceptExSockaddrs)
4789 EXTENSION_FUNCTION(WSAID_TRANSMITFILE, WS2_TransmitFile)
4790 /* EXTENSION_FUNCTION(WSAID_TRANSMITPACKETS, WS2_TransmitPackets) */
4791 EXTENSION_FUNCTION(WSAID_WSARECVMSG, WS2_WSARecvMsg)
4792 EXTENSION_FUNCTION(WSAID_WSASENDMSG, WSASendMsg)
4794 #undef EXTENSION_FUNCTION
4795 BOOL found = FALSE;
4796 unsigned int i;
4798 for (i = 0; i < ARRAY_SIZE(guid_funcs); i++)
4800 if (IsEqualGUID(&guid_funcs[i].guid, in_buff))
4802 found = TRUE;
4803 break;
4807 if (found)
4809 TRACE("-> got %s\n", guid_funcs[i].name);
4810 *(void **)out_buff = guid_funcs[i].func_ptr;
4811 total = sizeof(void *);
4812 break;
4815 FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER %s: stub\n", debugstr_guid(in_buff));
4816 status = WSAEOPNOTSUPP;
4817 break;
4819 case WS_SIO_KEEPALIVE_VALS:
4821 struct tcp_keepalive *k;
4822 int keepalive, keepidle, keepintvl;
4824 if (!in_buff || in_size < sizeof(struct tcp_keepalive))
4826 SetLastError(WSAEFAULT);
4827 return SOCKET_ERROR;
4830 k = in_buff;
4831 keepalive = k->onoff ? 1 : 0;
4832 keepidle = max( 1, (k->keepalivetime + 500) / 1000 );
4833 keepintvl = max( 1, (k->keepaliveinterval + 500) / 1000 );
4835 TRACE("onoff: %d, keepalivetime: %d, keepaliveinterval: %d\n", keepalive, keepidle, keepintvl);
4837 fd = get_sock_fd(s, 0, NULL);
4838 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(int)) == -1)
4839 status = WSAEINVAL;
4840 #if defined(TCP_KEEPIDLE) || defined(TCP_KEEPINTVL)
4841 /* these values need to be set only if SO_KEEPALIVE is enabled */
4842 else if(keepalive)
4844 #ifndef TCP_KEEPIDLE
4845 FIXME("ignoring keepalive timeout\n");
4846 #else
4847 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, sizeof(int)) == -1)
4848 status = WSAEINVAL;
4849 else
4850 #endif
4851 #ifdef TCP_KEEPINTVL
4852 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof(int)) == -1)
4853 status = WSAEINVAL;
4854 #else
4855 FIXME("ignoring keepalive interval\n");
4856 #endif
4858 #else
4859 else
4860 FIXME("ignoring keepalive interval and timeout\n");
4861 #endif
4862 release_sock_fd(s, fd);
4863 break;
4865 case WS_SIO_ROUTING_INTERFACE_QUERY:
4867 struct WS_sockaddr *daddr = (struct WS_sockaddr *)in_buff;
4868 struct WS_sockaddr_in *daddr_in = (struct WS_sockaddr_in *)daddr;
4869 struct WS_sockaddr_in *saddr_in = out_buff;
4870 MIB_IPFORWARDROW row;
4871 PMIB_IPADDRTABLE ipAddrTable = NULL;
4872 DWORD size, i, found_index;
4874 TRACE("-> WS_SIO_ROUTING_INTERFACE_QUERY request\n");
4876 if (!in_buff || in_size < sizeof(struct WS_sockaddr) ||
4877 !out_buff || out_size < sizeof(struct WS_sockaddr_in) || !ret_size)
4879 SetLastError(WSAEFAULT);
4880 return SOCKET_ERROR;
4882 if (daddr->sa_family != WS_AF_INET)
4884 FIXME("unsupported address family %d\n", daddr->sa_family);
4885 status = WSAEAFNOSUPPORT;
4886 break;
4888 if (GetBestRoute(daddr_in->sin_addr.S_un.S_addr, 0, &row) != NOERROR ||
4889 GetIpAddrTable(NULL, &size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
4891 status = WSAEFAULT;
4892 break;
4894 ipAddrTable = HeapAlloc(GetProcessHeap(), 0, size);
4895 if (GetIpAddrTable(ipAddrTable, &size, FALSE))
4897 HeapFree(GetProcessHeap(), 0, ipAddrTable);
4898 status = WSAEFAULT;
4899 break;
4901 for (i = 0, found_index = ipAddrTable->dwNumEntries;
4902 i < ipAddrTable->dwNumEntries; i++)
4904 if (ipAddrTable->table[i].dwIndex == row.dwForwardIfIndex)
4905 found_index = i;
4907 if (found_index == ipAddrTable->dwNumEntries)
4909 ERR("no matching IP address for interface %d\n",
4910 row.dwForwardIfIndex);
4911 HeapFree(GetProcessHeap(), 0, ipAddrTable);
4912 status = WSAEFAULT;
4913 break;
4915 saddr_in->sin_family = WS_AF_INET;
4916 saddr_in->sin_addr.S_un.S_addr = ipAddrTable->table[found_index].dwAddr;
4917 saddr_in->sin_port = 0;
4918 total = sizeof(struct WS_sockaddr_in);
4919 HeapFree(GetProcessHeap(), 0, ipAddrTable);
4920 break;
4922 case WS_SIO_SET_COMPATIBILITY_MODE:
4923 TRACE("WS_SIO_SET_COMPATIBILITY_MODE ignored\n");
4924 status = WSAEOPNOTSUPP;
4925 break;
4926 case WS_SIO_UDP_CONNRESET:
4927 FIXME("WS_SIO_UDP_CONNRESET stub\n");
4928 break;
4929 case 0x667e: /* Netscape tries hard to use bogus ioctl 0x667e */
4930 SetLastError(WSAEOPNOTSUPP);
4931 return SOCKET_ERROR;
4932 case WS_SIO_ADDRESS_LIST_CHANGE:
4933 code = IOCTL_AFD_ADDRESS_LIST_CHANGE;
4934 status = WSAEOPNOTSUPP;
4935 break;
4936 default:
4937 status = WSAEOPNOTSUPP;
4938 break;
4941 if (status == WSAEOPNOTSUPP)
4943 status = server_ioctl_sock(s, code, in_buff, in_size, out_buff, out_size, &total,
4944 overlapped, completion);
4945 if (status != WSAEOPNOTSUPP)
4947 if (status == 0 || status == WSA_IO_PENDING)
4948 TRACE("-> %s request\n", debugstr_wsaioctl(code));
4949 else
4950 ERR("-> %s request failed with status 0x%x\n", debugstr_wsaioctl(code), status);
4952 /* overlapped and completion operations will be handled by the server */
4953 completion = NULL;
4954 overlapped = NULL;
4956 else
4957 FIXME("unsupported WS_IOCTL cmd (%s)\n", debugstr_wsaioctl(code));
4960 if (completion)
4962 FIXME( "completion routine %p not supported\n", completion );
4964 else if (overlapped)
4966 ULONG_PTR cvalue = (overlapped && ((ULONG_PTR)overlapped->hEvent & 1) == 0) ? (ULONG_PTR)overlapped : 0;
4967 overlapped->Internal = sock_error_to_ntstatus( status );
4968 overlapped->InternalHigh = total;
4969 if (cvalue) WS_AddCompletion( HANDLE2SOCKET(s), cvalue, overlapped->Internal, total, FALSE );
4970 if (overlapped->hEvent) NtSetEvent( overlapped->hEvent, NULL );
4973 if (!status)
4975 if (ret_size) *ret_size = total;
4976 return 0;
4978 SetLastError( status );
4979 return SOCKET_ERROR;
4983 /***********************************************************************
4984 * ioctlsocket (WS2_32.10)
4986 int WINAPI WS_ioctlsocket(SOCKET s, LONG cmd, WS_u_long *argp)
4988 DWORD ret_size;
4989 return WSAIoctl( s, cmd, argp, sizeof(WS_u_long), argp, sizeof(WS_u_long), &ret_size, NULL, NULL );
4992 /***********************************************************************
4993 * listen (WS2_32.13)
4995 int WINAPI WS_listen(SOCKET s, int backlog)
4997 int fd = get_sock_fd( s, FILE_READ_DATA, NULL ), ret = SOCKET_ERROR;
4999 TRACE("socket %04lx, backlog %d\n", s, backlog);
5000 if (fd != -1)
5002 int bound = is_fd_bound(fd, NULL, NULL);
5004 if (bound <= 0)
5006 SetLastError(bound == -1 ? wsaErrno() : WSAEINVAL);
5008 else if (listen(fd, backlog) == 0)
5010 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
5011 FD_WINE_LISTENING,
5012 FD_CONNECT|FD_WINE_CONNECTED);
5013 ret = 0;
5015 else
5016 SetLastError(wsaErrno());
5017 release_sock_fd( s, fd );
5020 return ret;
5023 /***********************************************************************
5024 * recv (WS2_32.16)
5026 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
5028 DWORD n, dwFlags = flags;
5029 WSABUF wsabuf;
5031 wsabuf.len = len;
5032 wsabuf.buf = buf;
5034 if ( WS2_recv_base(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
5035 return SOCKET_ERROR;
5036 else
5037 return n;
5040 /***********************************************************************
5041 * recvfrom (WS2_32.17)
5043 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
5044 struct WS_sockaddr *from, int *fromlen)
5046 DWORD n, dwFlags = flags;
5047 WSABUF wsabuf;
5049 wsabuf.len = len;
5050 wsabuf.buf = buf;
5052 if ( WS2_recv_base(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL, NULL) == SOCKET_ERROR )
5053 return SOCKET_ERROR;
5054 else
5055 return n;
5058 /* allocate a poll array for the corresponding fd sets */
5059 static struct pollfd *fd_sets_to_poll( const WS_fd_set *readfds, const WS_fd_set *writefds,
5060 const WS_fd_set *exceptfds, int *count_ptr )
5062 unsigned int i, j = 0, count = 0;
5063 struct pollfd *fds;
5064 struct per_thread_data *ptb = get_per_thread_data();
5066 if (readfds) count += readfds->fd_count;
5067 if (writefds) count += writefds->fd_count;
5068 if (exceptfds) count += exceptfds->fd_count;
5069 *count_ptr = count;
5070 if (!count)
5072 SetLastError(WSAEINVAL);
5073 return NULL;
5076 /* check if the cache can hold all descriptors, if not do the resizing */
5077 if (ptb->fd_count < count)
5079 if (!(fds = HeapAlloc(GetProcessHeap(), 0, count * sizeof(fds[0]))))
5081 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
5082 return NULL;
5084 HeapFree(GetProcessHeap(), 0, ptb->fd_cache);
5085 ptb->fd_cache = fds;
5086 ptb->fd_count = count;
5088 else
5089 fds = ptb->fd_cache;
5091 if (readfds)
5092 for (i = 0; i < readfds->fd_count; i++, j++)
5094 fds[j].fd = get_sock_fd( readfds->fd_array[i], FILE_READ_DATA, NULL );
5095 if (fds[j].fd == -1) goto failed;
5096 fds[j].revents = 0;
5097 if (is_fd_bound(fds[j].fd, NULL, NULL) == 1)
5099 fds[j].events = POLLIN;
5101 else
5103 release_sock_fd( readfds->fd_array[i], fds[j].fd );
5104 fds[j].fd = -1;
5105 fds[j].events = 0;
5108 if (writefds)
5109 for (i = 0; i < writefds->fd_count; i++, j++)
5111 fds[j].fd = get_sock_fd( writefds->fd_array[i], FILE_WRITE_DATA, NULL );
5112 if (fds[j].fd == -1) goto failed;
5113 fds[j].revents = 0;
5114 if (is_fd_bound(fds[j].fd, NULL, NULL) == 1 ||
5115 _get_fd_type(fds[j].fd) == SOCK_DGRAM)
5117 fds[j].events = POLLOUT;
5119 else
5121 release_sock_fd( writefds->fd_array[i], fds[j].fd );
5122 fds[j].fd = -1;
5123 fds[j].events = 0;
5126 if (exceptfds)
5127 for (i = 0; i < exceptfds->fd_count; i++, j++)
5129 fds[j].fd = get_sock_fd( exceptfds->fd_array[i], 0, NULL );
5130 if (fds[j].fd == -1) goto failed;
5131 fds[j].revents = 0;
5132 if (is_fd_bound(fds[j].fd, NULL, NULL) == 1)
5134 int oob_inlined = 0;
5135 socklen_t olen = sizeof(oob_inlined);
5137 fds[j].events = POLLHUP;
5139 /* Check if we need to test for urgent data or not */
5140 getsockopt(fds[j].fd, SOL_SOCKET, SO_OOBINLINE, (char*) &oob_inlined, &olen);
5141 if (!oob_inlined)
5142 fds[j].events |= POLLPRI;
5144 else
5146 release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
5147 fds[j].fd = -1;
5148 fds[j].events = 0;
5151 return fds;
5153 failed:
5154 count = j;
5155 j = 0;
5156 if (readfds)
5157 for (i = 0; i < readfds->fd_count && j < count; i++, j++)
5158 if (fds[j].fd != -1) release_sock_fd( readfds->fd_array[i], fds[j].fd );
5159 if (writefds)
5160 for (i = 0; i < writefds->fd_count && j < count; i++, j++)
5161 if (fds[j].fd != -1) release_sock_fd( writefds->fd_array[i], fds[j].fd );
5162 if (exceptfds)
5163 for (i = 0; i < exceptfds->fd_count && j < count; i++, j++)
5164 if (fds[j].fd != -1) release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
5165 return NULL;
5168 /* release the file descriptor obtained in fd_sets_to_poll */
5169 /* must be called with the original fd_set arrays, before calling get_poll_results */
5170 static void release_poll_fds( const WS_fd_set *readfds, const WS_fd_set *writefds,
5171 const WS_fd_set *exceptfds, struct pollfd *fds )
5173 unsigned int i, j = 0;
5175 if (readfds)
5177 for (i = 0; i < readfds->fd_count; i++, j++)
5178 if (fds[j].fd != -1) release_sock_fd( readfds->fd_array[i], fds[j].fd );
5180 if (writefds)
5182 for (i = 0; i < writefds->fd_count; i++, j++)
5183 if (fds[j].fd != -1) release_sock_fd( writefds->fd_array[i], fds[j].fd );
5185 if (exceptfds)
5187 for (i = 0; i < exceptfds->fd_count; i++, j++)
5189 if (fds[j].fd == -1) continue;
5190 release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
5191 if (fds[j].revents & POLLHUP)
5193 int fd = get_sock_fd( exceptfds->fd_array[i], 0, NULL );
5194 if (fd != -1)
5195 release_sock_fd( exceptfds->fd_array[i], fd );
5196 else
5197 fds[j].revents = 0;
5203 static int do_poll(struct pollfd *pollfds, int count, int timeout)
5205 struct timeval tv1, tv2;
5206 int ret, torig = timeout;
5208 if (timeout > 0) gettimeofday( &tv1, 0 );
5210 while ((ret = poll( pollfds, count, timeout )) < 0)
5212 if (errno != EINTR) break;
5213 if (timeout < 0) continue;
5214 if (timeout == 0) return 0;
5216 gettimeofday( &tv2, 0 );
5218 tv2.tv_sec -= tv1.tv_sec;
5219 tv2.tv_usec -= tv1.tv_usec;
5220 if (tv2.tv_usec < 0)
5222 tv2.tv_usec += 1000000;
5223 tv2.tv_sec -= 1;
5226 timeout = torig - (tv2.tv_sec * 1000) - (tv2.tv_usec + 999) / 1000;
5227 if (timeout <= 0) return 0;
5229 return ret;
5232 /* map the poll results back into the Windows fd sets */
5233 static int get_poll_results( WS_fd_set *readfds, WS_fd_set *writefds, WS_fd_set *exceptfds,
5234 const struct pollfd *fds )
5236 const struct pollfd *poll_writefds = fds + (readfds ? readfds->fd_count : 0);
5237 const struct pollfd *poll_exceptfds = poll_writefds + (writefds ? writefds->fd_count : 0);
5238 unsigned int i, k, total = 0;
5240 if (readfds)
5242 for (i = k = 0; i < readfds->fd_count; i++)
5244 if (fds[i].revents ||
5245 (readfds == writefds && (poll_writefds[i].revents & POLLOUT) && !(poll_writefds[i].revents & POLLHUP)) ||
5246 (readfds == exceptfds && poll_exceptfds[i].revents))
5247 readfds->fd_array[k++] = readfds->fd_array[i];
5249 readfds->fd_count = k;
5250 total += k;
5252 if (writefds && writefds != readfds)
5254 for (i = k = 0; i < writefds->fd_count; i++)
5256 if (((poll_writefds[i].revents & POLLOUT) && !(poll_writefds[i].revents & POLLHUP)) ||
5257 (writefds == exceptfds && poll_exceptfds[i].revents))
5258 writefds->fd_array[k++] = writefds->fd_array[i];
5260 writefds->fd_count = k;
5261 total += k;
5263 if (exceptfds && exceptfds != readfds && exceptfds != writefds)
5265 for (i = k = 0; i < exceptfds->fd_count; i++)
5266 if (poll_exceptfds[i].revents) exceptfds->fd_array[k++] = exceptfds->fd_array[i];
5267 exceptfds->fd_count = k;
5268 total += k;
5270 return total;
5273 /***********************************************************************
5274 * select (WS2_32.18)
5276 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
5277 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
5278 const struct WS_timeval* ws_timeout)
5280 struct pollfd *pollfds;
5281 int count, ret, timeout = -1;
5283 TRACE("read %p, write %p, excp %p timeout %p\n",
5284 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
5286 if (!(pollfds = fd_sets_to_poll( ws_readfds, ws_writefds, ws_exceptfds, &count )))
5287 return SOCKET_ERROR;
5289 if (ws_timeout)
5290 timeout = (ws_timeout->tv_sec * 1000) + (ws_timeout->tv_usec + 999) / 1000;
5292 ret = do_poll(pollfds, count, timeout);
5293 release_poll_fds( ws_readfds, ws_writefds, ws_exceptfds, pollfds );
5295 if (ret == -1) SetLastError(wsaErrno());
5296 else ret = get_poll_results( ws_readfds, ws_writefds, ws_exceptfds, pollfds );
5297 return ret;
5300 /***********************************************************************
5301 * WSAPoll
5303 int WINAPI WSAPoll(WSAPOLLFD *wfds, ULONG count, int timeout)
5305 int i, ret;
5306 struct pollfd *ufds;
5308 if (!count)
5310 SetLastError(WSAEINVAL);
5311 return SOCKET_ERROR;
5313 if (!wfds)
5315 SetLastError(WSAEFAULT);
5316 return SOCKET_ERROR;
5319 if (!(ufds = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ufds[0]))))
5321 SetLastError(WSAENOBUFS);
5322 return SOCKET_ERROR;
5325 for (i = 0; i < count; i++)
5327 ufds[i].fd = get_sock_fd(wfds[i].fd, 0, NULL);
5328 ufds[i].events = convert_poll_w2u(wfds[i].events);
5329 ufds[i].revents = 0;
5332 ret = do_poll(ufds, count, timeout);
5334 for (i = 0; i < count; i++)
5336 if (ufds[i].fd != -1)
5338 release_sock_fd(wfds[i].fd, ufds[i].fd);
5339 if (ufds[i].revents & POLLHUP)
5341 /* Check if the socket still exists */
5342 int fd = get_sock_fd(wfds[i].fd, 0, NULL);
5343 if (fd != -1)
5345 wfds[i].revents = WS_POLLHUP;
5346 release_sock_fd(wfds[i].fd, fd);
5348 else
5349 wfds[i].revents = WS_POLLNVAL;
5351 else
5352 wfds[i].revents = convert_poll_u2w(ufds[i].revents);
5354 else
5355 wfds[i].revents = WS_POLLNVAL;
5358 HeapFree(GetProcessHeap(), 0, ufds);
5359 return ret;
5362 /* helper to send completion messages for client-only i/o operation case */
5363 static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus,
5364 ULONG Information, BOOL async )
5366 SERVER_START_REQ( add_fd_completion )
5368 req->handle = wine_server_obj_handle( SOCKET2HANDLE(sock) );
5369 req->cvalue = CompletionValue;
5370 req->status = CompletionStatus;
5371 req->information = Information;
5372 req->async = async;
5373 wine_server_call( req );
5375 SERVER_END_REQ;
5379 /***********************************************************************
5380 * send (WS2_32.19)
5382 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
5384 DWORD n;
5385 WSABUF wsabuf;
5387 wsabuf.len = len;
5388 wsabuf.buf = (char*) buf;
5390 if ( WS2_sendto( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
5391 return SOCKET_ERROR;
5392 else
5393 return n;
5396 /***********************************************************************
5397 * WSASend (WS2_32.72)
5399 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
5400 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
5401 LPWSAOVERLAPPED lpOverlapped,
5402 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
5404 return WS2_sendto( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
5405 NULL, 0, lpOverlapped, lpCompletionRoutine );
5408 /***********************************************************************
5409 * WSASendDisconnect (WS2_32.73)
5411 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
5413 return WS_shutdown( s, SD_SEND );
5417 static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
5418 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
5419 const struct WS_sockaddr *to, int tolen,
5420 LPWSAOVERLAPPED lpOverlapped,
5421 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
5423 unsigned int i, options;
5424 int n, fd, err, overlapped, flags;
5425 struct ws2_async *wsa = NULL, localwsa;
5426 int totalLength = 0;
5427 DWORD bytes_sent;
5428 BOOL is_blocking;
5430 TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, to %p, tolen %d, ovl %p, func %p\n",
5431 s, lpBuffers, dwBufferCount, dwFlags,
5432 to, tolen, lpOverlapped, lpCompletionRoutine);
5434 fd = get_sock_fd( s, FILE_WRITE_DATA, &options );
5435 TRACE( "fd=%d, options=%x\n", fd, options );
5437 if ( fd == -1 ) return SOCKET_ERROR;
5439 if (!lpOverlapped && !lpNumberOfBytesSent)
5441 err = WSAEFAULT;
5442 goto error;
5445 overlapped = (lpOverlapped || lpCompletionRoutine) &&
5446 !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
5447 if (overlapped || dwBufferCount > 1)
5449 if (!(wsa = (struct ws2_async *)alloc_async_io( offsetof(struct ws2_async, iovec[dwBufferCount]),
5450 WS2_async_send )))
5452 err = WSAEFAULT;
5453 goto error;
5456 else
5457 wsa = &localwsa;
5459 wsa->hSocket = SOCKET2HANDLE(s);
5460 wsa->addr = (struct WS_sockaddr *)to;
5461 wsa->addrlen.val = tolen;
5462 wsa->flags = dwFlags;
5463 wsa->lpFlags = &wsa->flags;
5464 wsa->control = NULL;
5465 wsa->n_iovecs = dwBufferCount;
5466 wsa->first_iovec = 0;
5467 for ( i = 0; i < dwBufferCount; i++ )
5469 wsa->iovec[i].iov_base = lpBuffers[i].buf;
5470 wsa->iovec[i].iov_len = lpBuffers[i].len;
5471 totalLength += lpBuffers[i].len;
5474 flags = convert_flags(dwFlags);
5475 n = WS2_send( fd, wsa, flags );
5476 if (n == -1 && errno != EAGAIN)
5478 err = wsaErrno();
5479 goto error;
5482 if (overlapped)
5484 IO_STATUS_BLOCK *iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
5485 ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
5487 wsa->user_overlapped = lpOverlapped;
5488 wsa->completion_func = lpCompletionRoutine;
5489 release_sock_fd( s, fd );
5491 if (n == -1 || n < totalLength)
5493 iosb->u.Status = STATUS_PENDING;
5494 iosb->Information = n == -1 ? 0 : n;
5496 if (wsa->completion_func)
5497 err = register_async( ASYNC_TYPE_WRITE, wsa->hSocket, &wsa->io, NULL,
5498 ws2_async_apc, wsa, iosb );
5499 else
5500 err = register_async( ASYNC_TYPE_WRITE, wsa->hSocket, &wsa->io, lpOverlapped->hEvent,
5501 NULL, (void *)cvalue, iosb );
5503 /* Enable the event only after starting the async. The server will deliver it as soon as
5504 the async is done. */
5505 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
5507 if (err != STATUS_PENDING) HeapFree( GetProcessHeap(), 0, wsa );
5508 SetLastError(NtStatusToWSAError( err ));
5509 return SOCKET_ERROR;
5512 iosb->u.Status = STATUS_SUCCESS;
5513 iosb->Information = n;
5514 if (lpNumberOfBytesSent) *lpNumberOfBytesSent = n;
5515 if (!wsa->completion_func)
5517 if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n, FALSE );
5518 if (lpOverlapped->hEvent) SetEvent( lpOverlapped->hEvent );
5519 HeapFree( GetProcessHeap(), 0, wsa );
5521 else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc,
5522 (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 );
5523 SetLastError(ERROR_SUCCESS);
5524 return 0;
5527 if ((err = sock_is_blocking( s, &is_blocking ))) goto error;
5529 if ( is_blocking )
5531 /* On a blocking non-overlapped stream socket,
5532 * sending blocks until the entire buffer is sent. */
5533 DWORD timeout_start = GetTickCount();
5535 bytes_sent = n == -1 ? 0 : n;
5537 while (wsa->first_iovec < wsa->n_iovecs)
5539 struct pollfd pfd;
5540 int poll_timeout = -1;
5541 INT64 timeout = get_rcvsnd_timeo(fd, FALSE);
5543 if (timeout)
5545 timeout -= GetTickCount() - timeout_start;
5546 if (timeout < 0) poll_timeout = 0;
5547 else poll_timeout = timeout <= INT_MAX ? timeout : INT_MAX;
5550 pfd.fd = fd;
5551 pfd.events = POLLOUT;
5553 if (!poll_timeout || !poll( &pfd, 1, poll_timeout ))
5555 err = WSAETIMEDOUT;
5556 goto error; /* msdn says a timeout in send is fatal */
5559 n = WS2_send( fd, wsa, flags );
5560 if (n == -1 && errno != EAGAIN)
5562 err = wsaErrno();
5563 goto error;
5566 if (n >= 0)
5567 bytes_sent += n;
5570 else /* non-blocking */
5572 if (n < totalLength)
5573 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
5574 if (n == -1)
5576 err = WSAEWOULDBLOCK;
5577 goto error;
5579 bytes_sent = n;
5582 TRACE(" -> %i bytes\n", bytes_sent);
5584 if (lpNumberOfBytesSent) *lpNumberOfBytesSent = bytes_sent;
5585 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
5586 release_sock_fd( s, fd );
5587 SetLastError(ERROR_SUCCESS);
5588 return 0;
5590 error:
5591 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
5592 release_sock_fd( s, fd );
5593 WARN(" -> ERROR %d\n", err);
5594 SetLastError(err);
5595 return SOCKET_ERROR;
5598 /***********************************************************************
5599 * WSASendTo (WS2_32.74)
5601 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
5602 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
5603 const struct WS_sockaddr *to, int tolen,
5604 LPWSAOVERLAPPED lpOverlapped,
5605 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
5607 return WS2_sendto( s, lpBuffers, dwBufferCount,
5608 lpNumberOfBytesSent, dwFlags,
5609 to, tolen,
5610 lpOverlapped, lpCompletionRoutine );
5613 /***********************************************************************
5614 * sendto (WS2_32.20)
5616 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
5617 const struct WS_sockaddr *to, int tolen)
5619 DWORD n;
5620 WSABUF wsabuf;
5622 wsabuf.len = len;
5623 wsabuf.buf = (char*) buf;
5625 if ( WS2_sendto(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
5626 return SOCKET_ERROR;
5627 else
5628 return n;
5631 /***********************************************************************
5632 * setsockopt (WS2_32.21)
5634 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
5635 const char *optval, int optlen)
5637 int fd;
5638 int woptval;
5639 struct linger linger;
5640 struct timeval tval;
5641 struct ip_mreq_source mreq_source;
5643 TRACE("(socket %04lx, %s, optval %s, optlen %d)\n", s,
5644 debugstr_sockopt(level, optname), debugstr_optval(optval, optlen),
5645 optlen);
5647 /* some broken apps pass the value directly instead of a pointer to it */
5648 if(optlen && IS_INTRESOURCE(optval))
5650 SetLastError(WSAEFAULT);
5651 return SOCKET_ERROR;
5654 switch(level)
5656 case WS_SOL_SOCKET:
5657 switch(optname)
5659 /* Some options need some conversion before they can be sent to
5660 * setsockopt. The conversions are done here, then they will fall through
5661 * to the general case. Special options that are not passed to
5662 * setsockopt follow below that.*/
5664 case WS_SO_DONTLINGER:
5665 if (!optval)
5667 SetLastError(WSAEFAULT);
5668 return SOCKET_ERROR;
5670 linger.l_onoff = *(const int*)optval == 0;
5671 linger.l_linger = 0;
5672 level = SOL_SOCKET;
5673 optname = SO_LINGER;
5674 optval = (char*)&linger;
5675 optlen = sizeof(struct linger);
5676 break;
5678 case WS_SO_LINGER:
5679 if (!optval)
5681 SetLastError(WSAEFAULT);
5682 return SOCKET_ERROR;
5684 linger.l_onoff = ((LINGER*)optval)->l_onoff;
5685 linger.l_linger = ((LINGER*)optval)->l_linger;
5686 level = SOL_SOCKET;
5687 optname = SO_LINGER;
5688 optval = (char*)&linger;
5689 optlen = sizeof(struct linger);
5690 break;
5692 case WS_SO_SNDBUF:
5693 if (!*(const int *)optval)
5695 FIXME("SO_SNDBUF ignoring request to disable send buffering\n");
5696 #ifdef __APPLE__
5697 return 0;
5698 #endif
5700 convert_sockopt(&level, &optname);
5701 break;
5703 case WS_SO_RCVBUF:
5704 if (*(const int*)optval < 2048)
5706 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(const int*)optval );
5707 return 0;
5709 /* Fall through */
5711 /* The options listed here don't need any special handling. Thanks to
5712 * the conversion happening above, options from there will fall through
5713 * to this, too.*/
5714 case WS_SO_ACCEPTCONN:
5715 case WS_SO_BROADCAST:
5716 case WS_SO_ERROR:
5717 case WS_SO_KEEPALIVE:
5718 case WS_SO_OOBINLINE:
5719 /* BSD socket SO_REUSEADDR is not 100% compatible to winsock semantics.
5720 * however, using it the BSD way fixes bug 8513 and seems to be what
5721 * most programmers assume, anyway */
5722 case WS_SO_REUSEADDR:
5723 case WS_SO_TYPE:
5724 convert_sockopt(&level, &optname);
5725 break;
5727 /* SO_DEBUG is a privileged operation, ignore it. */
5728 case WS_SO_DEBUG:
5729 TRACE("Ignoring SO_DEBUG\n");
5730 return 0;
5732 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
5733 * socket. According to MSDN, this option is silently ignored.*/
5734 case WS_SO_DONTROUTE:
5735 TRACE("Ignoring SO_DONTROUTE\n");
5736 return 0;
5738 /* Stops two sockets from being bound to the same port. Always happens
5739 * on unix systems, so just drop it. */
5740 case WS_SO_EXCLUSIVEADDRUSE:
5741 TRACE("Ignoring SO_EXCLUSIVEADDRUSE, is always set.\n");
5742 return 0;
5744 /* After a ConnectEx call succeeds, the socket can't be used with half of the
5745 * normal winsock functions on windows. We don't have that problem. */
5746 case WS_SO_UPDATE_CONNECT_CONTEXT:
5747 TRACE("Ignoring SO_UPDATE_CONNECT_CONTEXT, since our sockets are normal\n");
5748 return 0;
5750 /* After a AcceptEx call succeeds, the socket can't be used with half of the
5751 * normal winsock functions on windows. We don't have that problem. */
5752 case WS_SO_UPDATE_ACCEPT_CONTEXT:
5753 TRACE("Ignoring SO_UPDATE_ACCEPT_CONTEXT, since our sockets are normal\n");
5754 return 0;
5756 /* SO_OPENTYPE does not require a valid socket handle. */
5757 case WS_SO_OPENTYPE:
5758 if (!optlen || optlen < sizeof(int) || !optval)
5760 SetLastError(WSAEFAULT);
5761 return SOCKET_ERROR;
5763 get_per_thread_data()->opentype = *(const int *)optval;
5764 TRACE("setting global SO_OPENTYPE = 0x%x\n", *((const int*)optval) );
5765 return 0;
5767 #ifdef SO_RCVTIMEO
5768 case WS_SO_RCVTIMEO:
5769 #endif
5770 #ifdef SO_SNDTIMEO
5771 case WS_SO_SNDTIMEO:
5772 #endif
5773 #if defined(SO_RCVTIMEO) || defined(SO_SNDTIMEO)
5774 if (optval && optlen == sizeof(UINT32)) {
5775 /* WinSock passes milliseconds instead of struct timeval */
5776 tval.tv_usec = (*(const UINT32*)optval % 1000) * 1000;
5777 tval.tv_sec = *(const UINT32*)optval / 1000;
5778 /* min of 500 milliseconds */
5779 if (tval.tv_sec == 0 && tval.tv_usec && tval.tv_usec < 500000)
5780 tval.tv_usec = 500000;
5781 optlen = sizeof(struct timeval);
5782 optval = (char*)&tval;
5783 } else if (optlen == sizeof(struct timeval)) {
5784 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
5785 } else {
5786 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
5787 return 0;
5789 convert_sockopt(&level, &optname);
5790 break;
5791 #endif
5793 case WS_SO_RANDOMIZE_PORT:
5794 FIXME("Ignoring WS_SO_RANDOMIZE_PORT\n");
5795 return 0;
5797 case WS_SO_PORT_SCALABILITY:
5798 FIXME("Ignoring WS_SO_PORT_SCALABILITY\n");
5799 return 0;
5801 case WS_SO_REUSE_UNICASTPORT:
5802 FIXME("Ignoring WS_SO_REUSE_UNICASTPORT\n");
5803 return 0;
5805 case WS_SO_REUSE_MULTICASTPORT:
5806 FIXME("Ignoring WS_SO_REUSE_MULTICASTPORT\n");
5807 return 0;
5809 default:
5810 TRACE("Unknown SOL_SOCKET optname: 0x%08x\n", optname);
5811 SetLastError(WSAENOPROTOOPT);
5812 return SOCKET_ERROR;
5814 break; /* case WS_SOL_SOCKET */
5816 #ifdef HAS_IPX
5817 case WS_NSPROTO_IPX:
5818 switch(optname)
5820 case WS_IPX_PTYPE:
5821 return set_ipx_packettype(s, *(int*)optval);
5823 case WS_IPX_FILTERPTYPE:
5824 /* Sets the receive filter packet type, at the moment we don't support it */
5825 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
5826 /* Returning 0 is better for now than returning a SOCKET_ERROR */
5827 return 0;
5829 default:
5830 FIXME("opt_name:%x\n", optname);
5831 return SOCKET_ERROR;
5833 break; /* case WS_NSPROTO_IPX */
5834 #endif
5836 /* Levels WS_IPPROTO_TCP and WS_IPPROTO_IP convert directly */
5837 case WS_IPPROTO_TCP:
5838 switch(optname)
5840 case WS_TCP_NODELAY:
5841 convert_sockopt(&level, &optname);
5842 break;
5843 default:
5844 FIXME("Unknown IPPROTO_TCP optname 0x%08x\n", optname);
5845 return SOCKET_ERROR;
5847 break;
5849 case WS_IPPROTO_IP:
5850 switch(optname)
5852 case WS_IP_ADD_SOURCE_MEMBERSHIP:
5853 case WS_IP_DROP_SOURCE_MEMBERSHIP:
5854 case WS_IP_BLOCK_SOURCE:
5855 case WS_IP_UNBLOCK_SOURCE:
5857 WS_IP_MREQ_SOURCE* val = (void*)optval;
5858 mreq_source.imr_interface.s_addr = val->imr_interface.S_un.S_addr;
5859 mreq_source.imr_multiaddr.s_addr = val->imr_multiaddr.S_un.S_addr;
5860 mreq_source.imr_sourceaddr.s_addr = val->imr_sourceaddr.S_un.S_addr;
5862 optval = (char*)&mreq_source;
5863 optlen = sizeof(mreq_source);
5865 convert_sockopt(&level, &optname);
5866 break;
5868 case WS_IP_ADD_MEMBERSHIP:
5869 case WS_IP_DROP_MEMBERSHIP:
5870 #ifdef IP_HDRINCL
5871 case WS_IP_HDRINCL:
5872 #endif
5873 case WS_IP_MULTICAST_IF:
5874 case WS_IP_MULTICAST_LOOP:
5875 case WS_IP_MULTICAST_TTL:
5876 case WS_IP_OPTIONS:
5877 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
5878 case WS_IP_PKTINFO:
5879 #endif
5880 case WS_IP_TOS:
5881 case WS_IP_TTL:
5882 #ifdef IP_UNICAST_IF
5883 case WS_IP_UNICAST_IF:
5884 #endif
5885 convert_sockopt(&level, &optname);
5886 break;
5887 case WS_IP_DONTFRAGMENT:
5888 return set_dont_fragment(s, IPPROTO_IP, *(BOOL *)optval) ? 0 : SOCKET_ERROR;
5889 default:
5890 FIXME("Unknown IPPROTO_IP optname 0x%08x\n", optname);
5891 return SOCKET_ERROR;
5893 break;
5895 case WS_IPPROTO_IPV6:
5896 switch(optname)
5898 #ifdef IPV6_ADD_MEMBERSHIP
5899 case WS_IPV6_ADD_MEMBERSHIP:
5900 #endif
5901 #ifdef IPV6_DROP_MEMBERSHIP
5902 case WS_IPV6_DROP_MEMBERSHIP:
5903 #endif
5904 case WS_IPV6_MULTICAST_IF:
5905 case WS_IPV6_MULTICAST_HOPS:
5906 case WS_IPV6_MULTICAST_LOOP:
5907 case WS_IPV6_UNICAST_HOPS:
5908 #ifdef IPV6_UNICAST_IF
5909 case WS_IPV6_UNICAST_IF:
5910 #endif
5911 convert_sockopt(&level, &optname);
5912 break;
5913 case WS_IPV6_DONTFRAG:
5914 return set_dont_fragment(s, IPPROTO_IPV6, *(BOOL *)optval) ? 0 : SOCKET_ERROR;
5915 case WS_IPV6_PROTECTION_LEVEL:
5916 FIXME("IPV6_PROTECTION_LEVEL is ignored!\n");
5917 return 0;
5918 case WS_IPV6_V6ONLY:
5920 union generic_unix_sockaddr uaddr;
5921 socklen_t uaddrlen;
5922 int bound;
5924 fd = get_sock_fd( s, 0, NULL );
5925 if (fd == -1) return SOCKET_ERROR;
5927 bound = is_fd_bound(fd, &uaddr, &uaddrlen);
5928 release_sock_fd( s, fd );
5929 if (bound == 0 && uaddr.addr.sa_family == AF_INET)
5931 /* Changing IPV6_V6ONLY succeeds on AF_INET (IPv4) socket
5932 * on Windows (with IPv6 support) if the socket is unbound.
5933 * It is essentially a noop, though Windows does store the value
5935 WARN("Silently ignoring IPPROTO_IPV6+IPV6_V6ONLY on AF_INET socket\n");
5936 return 0;
5938 level = IPPROTO_IPV6;
5939 optname = IPV6_V6ONLY;
5940 break;
5942 default:
5943 FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname);
5944 return SOCKET_ERROR;
5946 break;
5948 default:
5949 WARN("Unknown level: 0x%08x\n", level);
5950 SetLastError(WSAEINVAL);
5951 return SOCKET_ERROR;
5952 } /* end switch(level) */
5954 /* avoid endianness issues if argument is a 16-bit int */
5955 if (optval && optlen < sizeof(int))
5957 woptval= *((const INT16 *) optval);
5958 optval= (char*) &woptval;
5959 woptval&= (1 << optlen * 8) - 1;
5960 optlen=sizeof(int);
5962 fd = get_sock_fd( s, 0, NULL );
5963 if (fd == -1) return SOCKET_ERROR;
5965 if (setsockopt(fd, level, optname, optval, optlen) == 0)
5967 #ifdef __APPLE__
5968 if (level == SOL_SOCKET && optname == SO_REUSEADDR &&
5969 setsockopt(fd, level, SO_REUSEPORT, optval, optlen) != 0)
5971 SetLastError(wsaErrno());
5972 release_sock_fd( s, fd );
5973 return SOCKET_ERROR;
5975 #endif
5976 release_sock_fd( s, fd );
5977 return 0;
5979 TRACE("Setting socket error, %d\n", wsaErrno());
5980 SetLastError(wsaErrno());
5981 release_sock_fd( s, fd );
5983 return SOCKET_ERROR;
5986 /***********************************************************************
5987 * shutdown (WS2_32.22)
5989 int WINAPI WS_shutdown(SOCKET s, int how)
5991 int fd, err = WSAENOTSOCK;
5992 unsigned int options = 0, clear_flags = 0;
5994 fd = get_sock_fd( s, 0, &options );
5995 TRACE("socket %04lx, how 0x%x, options 0x%x\n", s, how, options );
5997 if (fd == -1)
5998 return SOCKET_ERROR;
6000 switch( how )
6002 case SD_RECEIVE: /* drop receives */
6003 clear_flags |= FD_READ;
6004 break;
6005 case SD_SEND: /* drop sends */
6006 clear_flags |= FD_WRITE;
6007 break;
6008 case SD_BOTH: /* drop all */
6009 clear_flags |= FD_READ|FD_WRITE;
6010 /*fall through */
6011 default:
6012 clear_flags |= FD_WINE_LISTENING;
6015 if (!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
6017 switch ( how )
6019 case SD_RECEIVE:
6020 err = WS2_register_async_shutdown( s, ASYNC_TYPE_READ );
6021 break;
6022 case SD_SEND:
6023 err = WS2_register_async_shutdown( s, ASYNC_TYPE_WRITE );
6024 break;
6025 case SD_BOTH:
6026 default:
6027 err = WS2_register_async_shutdown( s, ASYNC_TYPE_READ );
6028 if (!err) err = WS2_register_async_shutdown( s, ASYNC_TYPE_WRITE );
6029 break;
6031 if (err) goto error;
6033 else /* non-overlapped mode */
6035 if ( shutdown( fd, how ) )
6037 err = wsaErrno();
6038 goto error;
6042 release_sock_fd( s, fd );
6043 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
6044 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
6045 return 0;
6047 error:
6048 release_sock_fd( s, fd );
6049 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
6050 SetLastError( err );
6051 return SOCKET_ERROR;
6054 /***********************************************************************
6055 * socket (WS2_32.23)
6057 SOCKET WINAPI WS_socket(int af, int type, int protocol)
6059 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
6061 return WSASocketW( af, type, protocol, NULL, 0,
6062 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
6066 /***********************************************************************
6067 * gethostbyaddr (WS2_32.51)
6069 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
6071 struct WS_hostent *retval = NULL;
6072 struct hostent* host;
6073 int unixtype = convert_af_w2u(type);
6074 const char *paddr = addr;
6075 unsigned long loopback;
6076 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
6077 char *extrabuf;
6078 int ebufsize = 1024;
6079 struct hostent hostentry;
6080 int locerr = ENOBUFS;
6081 #endif
6083 /* convert back the magic loopback address if necessary */
6084 if (unixtype == AF_INET && len == 4 && !memcmp(addr, magic_loopback_addr, 4))
6086 loopback = htonl(INADDR_LOOPBACK);
6087 paddr = (char*) &loopback;
6090 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
6091 host = NULL;
6092 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
6093 while(extrabuf) {
6094 int res = gethostbyaddr_r(paddr, len, unixtype,
6095 &hostentry, extrabuf, ebufsize, &host, &locerr);
6096 if (res != ERANGE) break;
6097 ebufsize *=2;
6098 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
6100 if (host) retval = WS_dup_he(host);
6101 else SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
6102 HeapFree(GetProcessHeap(),0,extrabuf);
6103 #else
6104 EnterCriticalSection( &csWSgetXXXbyYYY );
6105 host = gethostbyaddr(paddr, len, unixtype);
6106 if (host) retval = WS_dup_he(host);
6107 else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
6108 LeaveCriticalSection( &csWSgetXXXbyYYY );
6109 #endif
6110 TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
6111 return retval;
6114 /***********************************************************************
6115 * WS_compare_routes_by_metric_asc (INTERNAL)
6117 * Comparison function for qsort(), for sorting two routes (struct route)
6118 * by metric in ascending order.
6120 static int WS_compare_routes_by_metric_asc(const void *left, const void *right)
6122 const struct route *a = left, *b = right;
6123 if (a->default_route && b->default_route)
6124 return a->default_route - b->default_route;
6125 if (a->default_route && !b->default_route)
6126 return -1;
6127 if (b->default_route && !a->default_route)
6128 return 1;
6129 return a->metric - b->metric;
6132 /***********************************************************************
6133 * WS_get_local_ips (INTERNAL)
6135 * Returns the list of local IP addresses by going through the network
6136 * adapters and using the local routing table to sort the addresses
6137 * from highest routing priority to lowest routing priority. This
6138 * functionality is inferred from the description for obtaining local
6139 * IP addresses given in the Knowledge Base Article Q160215.
6141 * Please note that the returned hostent is only freed when the thread
6142 * closes and is replaced if another hostent is requested.
6144 static struct WS_hostent* WS_get_local_ips( char *hostname )
6146 int numroutes = 0, i, j, default_routes = 0;
6147 DWORD n;
6148 PIP_ADAPTER_INFO adapters = NULL, k;
6149 struct WS_hostent *hostlist = NULL;
6150 PMIB_IPFORWARDTABLE routes = NULL;
6151 struct route *route_addrs = NULL;
6152 DWORD adap_size, route_size;
6154 /* Obtain the size of the adapter list and routing table, also allocate memory */
6155 if (GetAdaptersInfo(NULL, &adap_size) != ERROR_BUFFER_OVERFLOW)
6156 return NULL;
6157 if (GetIpForwardTable(NULL, &route_size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
6158 return NULL;
6159 adapters = HeapAlloc(GetProcessHeap(), 0, adap_size);
6160 routes = HeapAlloc(GetProcessHeap(), 0, route_size);
6161 if (adapters == NULL || routes == NULL)
6162 goto cleanup;
6163 /* Obtain the adapter list and the full routing table */
6164 if (GetAdaptersInfo(adapters, &adap_size) != NO_ERROR)
6165 goto cleanup;
6166 if (GetIpForwardTable(routes, &route_size, FALSE) != NO_ERROR)
6167 goto cleanup;
6168 /* Store the interface associated with each route */
6169 for (n = 0; n < routes->dwNumEntries; n++)
6171 IF_INDEX ifindex;
6172 DWORD ifmetric, ifdefault = 0;
6173 BOOL exists = FALSE;
6175 /* Check if this is a default route (there may be more than one) */
6176 if (!routes->table[n].dwForwardDest)
6177 ifdefault = ++default_routes;
6178 else if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
6179 continue;
6180 ifindex = routes->table[n].dwForwardIfIndex;
6181 ifmetric = routes->table[n].dwForwardMetric1;
6182 /* Only store the lowest valued metric for an interface */
6183 for (j = 0; j < numroutes; j++)
6185 if (route_addrs[j].interface == ifindex)
6187 if (route_addrs[j].metric > ifmetric)
6188 route_addrs[j].metric = ifmetric;
6189 exists = TRUE;
6192 if (exists)
6193 continue;
6194 route_addrs = heap_realloc(route_addrs, (numroutes+1)*sizeof(struct route));
6195 if (route_addrs == NULL)
6196 goto cleanup; /* Memory allocation error, fail gracefully */
6197 route_addrs[numroutes].interface = ifindex;
6198 route_addrs[numroutes].metric = ifmetric;
6199 route_addrs[numroutes].default_route = ifdefault;
6200 /* If no IP is found in the next step (for whatever reason)
6201 * then fall back to the magic loopback address.
6203 memcpy(&(route_addrs[numroutes].addr.s_addr), magic_loopback_addr, 4);
6204 numroutes++;
6206 if (numroutes == 0)
6207 goto cleanup; /* No routes, fall back to the Magic IP */
6208 /* Find the IP address associated with each found interface */
6209 for (i = 0; i < numroutes; i++)
6211 for (k = adapters; k != NULL; k = k->Next)
6213 char *ip = k->IpAddressList.IpAddress.String;
6215 if (route_addrs[i].interface == k->Index)
6216 route_addrs[i].addr.s_addr = (in_addr_t) inet_addr(ip);
6219 /* Allocate a hostent and enough memory for all the IPs,
6220 * including the NULL at the end of the list.
6222 hostlist = WS_create_he(hostname, 1, 0, numroutes+1, sizeof(struct in_addr));
6223 if (hostlist == NULL)
6224 goto cleanup; /* Failed to allocate a hostent for the list of IPs */
6225 hostlist->h_addr_list[numroutes] = NULL; /* NULL-terminate the address list */
6226 hostlist->h_aliases[0] = NULL; /* NULL-terminate the alias list */
6227 hostlist->h_addrtype = AF_INET;
6228 hostlist->h_length = sizeof(struct in_addr); /* = 4 */
6229 /* Reorder the entries before placing them in the host list. Windows expects
6230 * the IP list in order from highest priority to lowest (the critical thing
6231 * is that most applications expect the first IP to be the default route).
6233 if (numroutes > 1)
6234 qsort(route_addrs, numroutes, sizeof(struct route), WS_compare_routes_by_metric_asc);
6236 for (i = 0; i < numroutes; i++)
6237 (*(struct in_addr *) hostlist->h_addr_list[i]) = route_addrs[i].addr;
6239 /* Cleanup all allocated memory except the address list,
6240 * the address list is used by the calling app.
6242 cleanup:
6243 HeapFree(GetProcessHeap(), 0, route_addrs);
6244 HeapFree(GetProcessHeap(), 0, adapters);
6245 HeapFree(GetProcessHeap(), 0, routes);
6246 return hostlist;
6249 /***********************************************************************
6250 * gethostbyname (WS2_32.52)
6252 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
6254 struct WS_hostent *retval = NULL;
6255 struct hostent* host;
6256 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
6257 char *extrabuf;
6258 int ebufsize=1024;
6259 struct hostent hostentry;
6260 int locerr = ENOBUFS;
6261 #endif
6262 char hostname[100];
6263 if(!num_startup) {
6264 SetLastError(WSANOTINITIALISED);
6265 return NULL;
6267 if( gethostname( hostname, 100) == -1) {
6268 SetLastError(WSAENOBUFS); /* appropriate ? */
6269 return retval;
6271 if( !name || !name[0]) {
6272 name = hostname;
6274 /* If the hostname of the local machine is requested then return the
6275 * complete list of local IP addresses */
6276 if(strcmp(name, hostname) == 0)
6277 retval = WS_get_local_ips(hostname);
6278 /* If any other hostname was requested (or the routing table lookup failed)
6279 * then return the IP found by the host OS */
6280 if(retval == NULL)
6282 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
6283 host = NULL;
6284 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
6285 while(extrabuf) {
6286 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
6287 if( res != ERANGE) break;
6288 ebufsize *=2;
6289 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
6291 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
6292 #else
6293 EnterCriticalSection( &csWSgetXXXbyYYY );
6294 host = gethostbyname(name);
6295 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
6296 #endif
6297 if (host) retval = WS_dup_he(host);
6298 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
6299 HeapFree(GetProcessHeap(),0,extrabuf);
6300 #else
6301 LeaveCriticalSection( &csWSgetXXXbyYYY );
6302 #endif
6304 if (retval && retval->h_addr_list[0][0] == 127 &&
6305 strcmp(name, "localhost") != 0)
6307 /* hostname != "localhost" but has loopback address. replace by our
6308 * special address.*/
6309 memcpy(retval->h_addr_list[0], magic_loopback_addr, 4);
6311 TRACE( "%s ret %p\n", debugstr_a(name), retval );
6312 return retval;
6316 static const struct { int prot; const char *names[3]; } protocols[] =
6318 { 0, { "ip", "IP" }},
6319 { 1, { "icmp", "ICMP" }},
6320 { 3, { "ggp", "GGP" }},
6321 { 6, { "tcp", "TCP" }},
6322 { 8, { "egp", "EGP" }},
6323 { 12, { "pup", "PUP" }},
6324 { 17, { "udp", "UDP" }},
6325 { 20, { "hmp", "HMP" }},
6326 { 22, { "xns-idp", "XNS-IDP" }},
6327 { 27, { "rdp", "RDP" }},
6328 { 41, { "ipv6", "IPv6" }},
6329 { 43, { "ipv6-route", "IPv6-Route" }},
6330 { 44, { "ipv6-frag", "IPv6-Frag" }},
6331 { 50, { "esp", "ESP" }},
6332 { 51, { "ah", "AH" }},
6333 { 58, { "ipv6-icmp", "IPv6-ICMP" }},
6334 { 59, { "ipv6-nonxt", "IPv6-NoNxt" }},
6335 { 60, { "ipv6-opts", "IPv6-Opts" }},
6336 { 66, { "rvd", "RVD" }},
6339 /***********************************************************************
6340 * getprotobyname (WS2_32.53)
6342 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
6344 struct WS_protoent* retval = NULL;
6345 unsigned int i;
6347 for (i = 0; i < ARRAY_SIZE(protocols); i++)
6349 if (_strnicmp( protocols[i].names[0], name, -1 )) continue;
6350 retval = WS_create_pe( protocols[i].names[0], (char **)protocols[i].names + 1,
6351 protocols[i].prot );
6352 break;
6354 if (!retval)
6356 WARN( "protocol %s not found\n", debugstr_a(name) );
6357 SetLastError(WSANO_DATA);
6359 TRACE( "%s ret %p\n", debugstr_a(name), retval );
6360 return retval;
6364 /***********************************************************************
6365 * getprotobynumber (WS2_32.54)
6367 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
6369 struct WS_protoent* retval = NULL;
6370 unsigned int i;
6372 for (i = 0; i < ARRAY_SIZE(protocols); i++)
6374 if (protocols[i].prot != number) continue;
6375 retval = WS_create_pe( protocols[i].names[0], (char **)protocols[i].names + 1,
6376 protocols[i].prot );
6377 break;
6379 if (!retval)
6381 WARN( "protocol %d not found\n", number );
6382 SetLastError(WSANO_DATA);
6384 TRACE("%i ret %p\n", number, retval);
6385 return retval;
6389 /***********************************************************************
6390 * getservbyname (WS2_32.55)
6392 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
6394 struct WS_servent* retval = NULL;
6395 struct servent* serv;
6396 char *name_str;
6397 char *proto_str = NULL;
6399 if (!(name_str = strdup_lower(name))) return NULL;
6401 if (proto && *proto)
6403 if (!(proto_str = strdup_lower(proto)))
6405 HeapFree( GetProcessHeap(), 0, name_str );
6406 return NULL;
6410 EnterCriticalSection( &csWSgetXXXbyYYY );
6411 serv = getservbyname(name_str, proto_str);
6412 if( serv != NULL )
6414 retval = WS_dup_se(serv);
6416 else SetLastError(WSANO_DATA);
6417 LeaveCriticalSection( &csWSgetXXXbyYYY );
6418 HeapFree( GetProcessHeap(), 0, proto_str );
6419 HeapFree( GetProcessHeap(), 0, name_str );
6420 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
6421 return retval;
6424 /***********************************************************************
6425 * freeaddrinfo (WS2_32.@)
6427 void WINAPI WS_freeaddrinfo(struct WS_addrinfo *res)
6429 while (res) {
6430 struct WS_addrinfo *next;
6432 HeapFree(GetProcessHeap(),0,res->ai_canonname);
6433 HeapFree(GetProcessHeap(),0,res->ai_addr);
6434 next = res->ai_next;
6435 HeapFree(GetProcessHeap(),0,res);
6436 res = next;
6440 /* helper functions for getaddrinfo()/getnameinfo() */
6441 static int convert_aiflag_w2u(int winflags) {
6442 unsigned int i;
6443 int unixflags = 0;
6445 for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
6446 if (ws_aiflag_map[i][0] & winflags) {
6447 unixflags |= ws_aiflag_map[i][1];
6448 winflags &= ~ws_aiflag_map[i][0];
6450 if (winflags)
6451 FIXME("Unhandled windows AI_xxx flags 0x%x\n", winflags);
6452 return unixflags;
6455 static int convert_niflag_w2u(int winflags) {
6456 unsigned int i;
6457 int unixflags = 0;
6459 for (i = 0; i < ARRAY_SIZE(ws_niflag_map); i++)
6460 if (ws_niflag_map[i][0] & winflags) {
6461 unixflags |= ws_niflag_map[i][1];
6462 winflags &= ~ws_niflag_map[i][0];
6464 if (winflags)
6465 FIXME("Unhandled windows NI_xxx flags 0x%x\n", winflags);
6466 return unixflags;
6469 static int convert_aiflag_u2w(int unixflags) {
6470 unsigned int i;
6471 int winflags = 0;
6473 for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
6474 if (ws_aiflag_map[i][1] & unixflags) {
6475 winflags |= ws_aiflag_map[i][0];
6476 unixflags &= ~ws_aiflag_map[i][1];
6478 if (unixflags)
6479 WARN("Unhandled UNIX AI_xxx flags 0x%x\n", unixflags);
6480 return winflags;
6483 static int convert_eai_u2w(int unixret) {
6484 int i;
6486 if (!unixret) return 0;
6488 for (i=0;ws_eai_map[i][0];i++)
6489 if (ws_eai_map[i][1] == unixret)
6490 return ws_eai_map[i][0];
6492 if (unixret == EAI_SYSTEM)
6493 /* There are broken versions of glibc which return EAI_SYSTEM
6494 * and set errno to 0 instead of returning EAI_NONAME.
6496 return errno ? sock_get_error( errno ) : WS_EAI_NONAME;
6498 FIXME("Unhandled unix EAI_xxx ret %d\n", unixret);
6499 return unixret;
6502 static char *get_fqdn(void)
6504 char *ret;
6505 DWORD size = 0;
6507 GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, NULL, &size );
6508 if (GetLastError() != ERROR_MORE_DATA) return NULL;
6509 if (!(ret = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
6510 if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, ret, &size ))
6512 HeapFree( GetProcessHeap(), 0, ret );
6513 return NULL;
6515 return ret;
6518 /***********************************************************************
6519 * getaddrinfo (WS2_32.@)
6521 int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addrinfo *hints, struct WS_addrinfo **res)
6523 #ifdef HAVE_GETADDRINFO
6524 struct addrinfo *unixaires = NULL;
6525 int result;
6526 struct addrinfo unixhints, *punixhints = NULL;
6527 char *nodeV6 = NULL, *fqdn = NULL;
6528 const char *node;
6530 *res = NULL;
6531 if (!nodename && !servname)
6533 SetLastError(WSAHOST_NOT_FOUND);
6534 return WSAHOST_NOT_FOUND;
6537 if (!nodename)
6538 node = NULL;
6539 else if (!nodename[0])
6541 if (!(fqdn = get_fqdn())) return WSA_NOT_ENOUGH_MEMORY;
6542 node = fqdn;
6544 else
6546 node = nodename;
6548 /* Check for [ipv6] or [ipv6]:portnumber, which are supported by Windows */
6549 if (!hints || hints->ai_family == WS_AF_UNSPEC || hints->ai_family == WS_AF_INET6)
6551 char *close_bracket;
6553 if (node[0] == '[' && (close_bracket = strchr(node + 1, ']')))
6555 nodeV6 = HeapAlloc(GetProcessHeap(), 0, close_bracket - node);
6556 if (!nodeV6) return WSA_NOT_ENOUGH_MEMORY;
6557 lstrcpynA(nodeV6, node + 1, close_bracket - node);
6558 node = nodeV6;
6563 /* servname tweak required by OSX and BSD kernels */
6564 if (servname && !servname[0]) servname = "0";
6566 if (hints) {
6567 punixhints = &unixhints;
6569 memset(&unixhints, 0, sizeof(unixhints));
6570 punixhints->ai_flags = convert_aiflag_w2u(hints->ai_flags);
6572 /* zero is a wildcard, no need to convert */
6573 if (hints->ai_family)
6574 punixhints->ai_family = convert_af_w2u(hints->ai_family);
6575 if (hints->ai_socktype)
6576 punixhints->ai_socktype = convert_socktype_w2u(hints->ai_socktype);
6577 if (hints->ai_protocol)
6578 punixhints->ai_protocol = max(convert_proto_w2u(hints->ai_protocol), 0);
6580 if (punixhints->ai_socktype < 0)
6582 SetLastError(WSAESOCKTNOSUPPORT);
6583 HeapFree(GetProcessHeap(), 0, fqdn);
6584 HeapFree(GetProcessHeap(), 0, nodeV6);
6585 return SOCKET_ERROR;
6588 /* windows allows invalid combinations of socket type and protocol, unix does not.
6589 * fix the parameters here to make getaddrinfo call always work */
6590 if (punixhints->ai_protocol == IPPROTO_TCP &&
6591 punixhints->ai_socktype != SOCK_STREAM && punixhints->ai_socktype != SOCK_SEQPACKET)
6592 punixhints->ai_socktype = 0;
6594 else if (punixhints->ai_protocol == IPPROTO_UDP && punixhints->ai_socktype != SOCK_DGRAM)
6595 punixhints->ai_socktype = 0;
6597 else if (IS_IPX_PROTO(punixhints->ai_protocol) && punixhints->ai_socktype != SOCK_DGRAM)
6598 punixhints->ai_socktype = 0;
6600 else if (punixhints->ai_protocol == IPPROTO_IPV6)
6601 punixhints->ai_protocol = 0;
6604 /* getaddrinfo(3) is thread safe, no need to wrap in CS */
6605 result = getaddrinfo(node, servname, punixhints, &unixaires);
6607 if (result && (!hints || !(hints->ai_flags & WS_AI_NUMERICHOST)) && node)
6609 if (!fqdn && !(fqdn = get_fqdn()))
6611 HeapFree(GetProcessHeap(), 0, nodeV6);
6612 return WSA_NOT_ENOUGH_MEMORY;
6614 if (!strcmp(fqdn, node) || (!strncmp(fqdn, node, strlen(node)) && fqdn[strlen(node)] == '.'))
6616 /* If it didn't work it means the host name IP is not in /etc/hosts, try again
6617 * by sending a NULL host and avoid sending a NULL servname too because that
6618 * is invalid */
6619 ERR_(winediag)("Failed to resolve your host name IP\n");
6620 result = getaddrinfo(NULL, servname ? servname : "0", punixhints, &unixaires);
6621 if (!result && punixhints && (punixhints->ai_flags & AI_CANONNAME) && unixaires && !unixaires->ai_canonname)
6623 freeaddrinfo(unixaires);
6624 result = EAI_NONAME;
6628 TRACE("%s, %s %p -> %p %d\n", debugstr_a(nodename), debugstr_a(servname), hints, res, result);
6629 HeapFree(GetProcessHeap(), 0, fqdn);
6630 HeapFree(GetProcessHeap(), 0, nodeV6);
6632 if (!result) {
6633 struct addrinfo *xuai = unixaires;
6634 struct WS_addrinfo **xai = res;
6636 *xai = NULL;
6637 while (xuai) {
6638 struct WS_addrinfo *ai = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo));
6639 SIZE_T len;
6641 if (!ai)
6642 goto outofmem;
6644 *xai = ai;xai = &ai->ai_next;
6645 ai->ai_flags = convert_aiflag_u2w(xuai->ai_flags);
6646 ai->ai_family = convert_af_u2w(xuai->ai_family);
6647 /* copy whatever was sent in the hints */
6648 if(hints) {
6649 ai->ai_socktype = hints->ai_socktype;
6650 ai->ai_protocol = hints->ai_protocol;
6651 } else {
6652 ai->ai_socktype = convert_socktype_u2w(xuai->ai_socktype);
6653 ai->ai_protocol = convert_proto_u2w(xuai->ai_protocol);
6655 if (xuai->ai_canonname) {
6656 TRACE("canon name - %s\n",debugstr_a(xuai->ai_canonname));
6657 ai->ai_canonname = HeapAlloc(GetProcessHeap(),0,strlen(xuai->ai_canonname)+1);
6658 if (!ai->ai_canonname)
6659 goto outofmem;
6660 strcpy(ai->ai_canonname,xuai->ai_canonname);
6662 len = xuai->ai_addrlen;
6663 ai->ai_addr = HeapAlloc(GetProcessHeap(),0,len);
6664 if (!ai->ai_addr)
6665 goto outofmem;
6666 ai->ai_addrlen = len;
6667 do {
6668 int winlen = ai->ai_addrlen;
6670 if (!ws_sockaddr_u2ws(xuai->ai_addr, ai->ai_addr, &winlen)) {
6671 ai->ai_addrlen = winlen;
6672 break;
6674 len = 2*len;
6675 ai->ai_addr = HeapReAlloc(GetProcessHeap(),0,ai->ai_addr,len);
6676 if (!ai->ai_addr)
6677 goto outofmem;
6678 ai->ai_addrlen = len;
6679 } while (1);
6680 xuai = xuai->ai_next;
6682 freeaddrinfo(unixaires);
6684 if (TRACE_ON(winsock))
6686 struct WS_addrinfo *ai = *res;
6687 while (ai)
6689 TRACE("=> %p, flags %#x, family %d, type %d, protocol %d, len %ld, name %s, addr %s\n",
6690 ai, ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol, ai->ai_addrlen,
6691 ai->ai_canonname, debugstr_sockaddr(ai->ai_addr));
6692 ai = ai->ai_next;
6695 } else
6696 result = convert_eai_u2w(result);
6698 SetLastError(result);
6699 return result;
6701 outofmem:
6702 if (*res) WS_freeaddrinfo(*res);
6703 if (unixaires) freeaddrinfo(unixaires);
6704 return WSA_NOT_ENOUGH_MEMORY;
6705 #else
6706 FIXME("getaddrinfo() failed, not found during buildtime.\n");
6707 return EAI_FAIL;
6708 #endif
6711 static ADDRINFOEXW *addrinfo_AtoW(const struct WS_addrinfo *ai)
6713 ADDRINFOEXW *ret;
6715 if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ADDRINFOEXW)))) return NULL;
6716 ret->ai_flags = ai->ai_flags;
6717 ret->ai_family = ai->ai_family;
6718 ret->ai_socktype = ai->ai_socktype;
6719 ret->ai_protocol = ai->ai_protocol;
6720 ret->ai_addrlen = ai->ai_addrlen;
6721 ret->ai_canonname = NULL;
6722 ret->ai_addr = NULL;
6723 ret->ai_blob = NULL;
6724 ret->ai_bloblen = 0;
6725 ret->ai_provider = NULL;
6726 ret->ai_next = NULL;
6727 if (ai->ai_canonname)
6729 int len = MultiByteToWideChar(CP_ACP, 0, ai->ai_canonname, -1, NULL, 0);
6730 if (!(ret->ai_canonname = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR))))
6732 HeapFree(GetProcessHeap(), 0, ret);
6733 return NULL;
6735 MultiByteToWideChar(CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len);
6737 if (ai->ai_addr)
6739 if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, ai->ai_addrlen)))
6741 HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
6742 HeapFree(GetProcessHeap(), 0, ret);
6743 return NULL;
6745 memcpy(ret->ai_addr, ai->ai_addr, ai->ai_addrlen);
6747 return ret;
6750 static ADDRINFOEXW *addrinfo_list_AtoW(const struct WS_addrinfo *info)
6752 ADDRINFOEXW *ret, *infoW;
6754 if (!(ret = infoW = addrinfo_AtoW(info))) return NULL;
6755 while (info->ai_next)
6757 if (!(infoW->ai_next = addrinfo_AtoW(info->ai_next)))
6759 FreeAddrInfoExW(ret);
6760 return NULL;
6762 infoW = infoW->ai_next;
6763 info = info->ai_next;
6765 return ret;
6768 static struct WS_addrinfo *addrinfo_WtoA(const struct WS_addrinfoW *ai)
6770 struct WS_addrinfo *ret;
6772 if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_addrinfo)))) return NULL;
6773 ret->ai_flags = ai->ai_flags;
6774 ret->ai_family = ai->ai_family;
6775 ret->ai_socktype = ai->ai_socktype;
6776 ret->ai_protocol = ai->ai_protocol;
6777 ret->ai_addrlen = ai->ai_addrlen;
6778 ret->ai_canonname = NULL;
6779 ret->ai_addr = NULL;
6780 ret->ai_next = NULL;
6781 if (ai->ai_canonname)
6783 int len = WideCharToMultiByte(CP_ACP, 0, ai->ai_canonname, -1, NULL, 0, NULL, NULL);
6784 if (!(ret->ai_canonname = HeapAlloc(GetProcessHeap(), 0, len)))
6786 HeapFree(GetProcessHeap(), 0, ret);
6787 return NULL;
6789 WideCharToMultiByte(CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len, NULL, NULL);
6791 if (ai->ai_addr)
6793 if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_sockaddr))))
6795 HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
6796 HeapFree(GetProcessHeap(), 0, ret);
6797 return NULL;
6799 memcpy(ret->ai_addr, ai->ai_addr, sizeof(struct WS_sockaddr));
6801 return ret;
6804 struct getaddrinfo_args
6806 OVERLAPPED *overlapped;
6807 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine;
6808 ADDRINFOEXW **result;
6809 char *nodename;
6810 char *servname;
6813 static void WINAPI getaddrinfo_callback(TP_CALLBACK_INSTANCE *instance, void *context)
6815 struct getaddrinfo_args *args = context;
6816 OVERLAPPED *overlapped = args->overlapped;
6817 HANDLE event = overlapped->hEvent;
6818 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine = args->completion_routine;
6819 struct WS_addrinfo *res;
6820 int ret;
6822 ret = WS_getaddrinfo(args->nodename, args->servname, NULL, &res);
6823 if (res)
6825 *args->result = addrinfo_list_AtoW(res);
6826 overlapped->u.Pointer = args->result;
6827 WS_freeaddrinfo(res);
6830 HeapFree(GetProcessHeap(), 0, args->nodename);
6831 HeapFree(GetProcessHeap(), 0, args->servname);
6832 HeapFree(GetProcessHeap(), 0, args);
6834 overlapped->Internal = ret;
6835 if (completion_routine) completion_routine(ret, 0, overlapped);
6836 if (event) SetEvent(event);
6839 static int WS_getaddrinfoW(const WCHAR *nodename, const WCHAR *servname, const struct WS_addrinfo *hints, ADDRINFOEXW **res,
6840 OVERLAPPED *overlapped, LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine)
6842 int ret = EAI_MEMORY, len, i;
6843 char *nodenameA = NULL, *servnameA = NULL;
6844 struct WS_addrinfo *resA;
6845 WCHAR *local_nodenameW = (WCHAR *)nodename;
6847 *res = NULL;
6848 if (nodename)
6850 /* Is this an IDN? Most likely if any char is above the Ascii table, this
6851 * is the simplest validation possible, further validation will be done by
6852 * the native getaddrinfo() */
6853 for (i = 0; nodename[i]; i++)
6855 if (nodename[i] > 'z')
6856 break;
6858 if (nodename[i])
6860 if (hints && (hints->ai_flags & WS_AI_DISABLE_IDN_ENCODING))
6862 /* Name requires conversion but it was disabled */
6863 ret = WSAHOST_NOT_FOUND;
6864 WSASetLastError(ret);
6865 goto end;
6868 len = IdnToAscii(0, nodename, -1, NULL, 0);
6869 if (!len)
6871 ERR("Failed to convert %s to punycode\n", debugstr_w(nodename));
6872 ret = EAI_FAIL;
6873 goto end;
6875 if (!(local_nodenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) goto end;
6876 IdnToAscii(0, nodename, -1, local_nodenameW, len);
6879 if (local_nodenameW)
6881 len = WideCharToMultiByte(CP_ACP, 0, local_nodenameW, -1, NULL, 0, NULL, NULL);
6882 if (!(nodenameA = HeapAlloc(GetProcessHeap(), 0, len))) goto end;
6883 WideCharToMultiByte(CP_ACP, 0, local_nodenameW, -1, nodenameA, len, NULL, NULL);
6885 if (servname)
6887 len = WideCharToMultiByte(CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL);
6888 if (!(servnameA = HeapAlloc(GetProcessHeap(), 0, len))) goto end;
6889 WideCharToMultiByte(CP_ACP, 0, servname, -1, servnameA, len, NULL, NULL);
6892 if (overlapped)
6894 struct getaddrinfo_args *args;
6896 if (overlapped->hEvent && completion_routine)
6898 ret = WSAEINVAL;
6899 goto end;
6902 if (!(args = HeapAlloc(GetProcessHeap(), 0, sizeof(*args)))) goto end;
6903 args->overlapped = overlapped;
6904 args->completion_routine = completion_routine;
6905 args->result = res;
6906 args->nodename = nodenameA;
6907 args->servname = servnameA;
6909 overlapped->Internal = WSAEINPROGRESS;
6910 if (!TrySubmitThreadpoolCallback(getaddrinfo_callback, args, NULL))
6912 HeapFree(GetProcessHeap(), 0, args);
6913 ret = GetLastError();
6914 goto end;
6917 if (local_nodenameW != nodename)
6918 HeapFree(GetProcessHeap(), 0, local_nodenameW);
6919 WSASetLastError(ERROR_IO_PENDING);
6920 return ERROR_IO_PENDING;
6923 ret = WS_getaddrinfo(nodenameA, servnameA, hints, &resA);
6924 if (!ret)
6926 *res = addrinfo_list_AtoW(resA);
6927 WS_freeaddrinfo(resA);
6930 end:
6931 if (local_nodenameW != nodename)
6932 HeapFree(GetProcessHeap(), 0, local_nodenameW);
6933 HeapFree(GetProcessHeap(), 0, nodenameA);
6934 HeapFree(GetProcessHeap(), 0, servnameA);
6935 return ret;
6938 /***********************************************************************
6939 * GetAddrInfoExW (WS2_32.@)
6941 int WINAPI GetAddrInfoExW(const WCHAR *name, const WCHAR *servname, DWORD namespace, GUID *namespace_id,
6942 const ADDRINFOEXW *hints, ADDRINFOEXW **result, struct WS_timeval *timeout, OVERLAPPED *overlapped,
6943 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine, HANDLE *handle)
6945 int ret;
6947 TRACE("(%s %s %x %s %p %p %p %p %p %p)\n", debugstr_w(name), debugstr_w(servname), namespace,
6948 debugstr_guid(namespace_id), hints, result, timeout, overlapped, completion_routine, handle);
6950 if (namespace != NS_DNS)
6951 FIXME("Unsupported namespace %u\n", namespace);
6952 if (namespace_id)
6953 FIXME("Unsupported naemspace_id %s\n", debugstr_guid(namespace_id));
6954 if (hints)
6955 FIXME("Unsupported hints\n");
6956 if (timeout)
6957 FIXME("Unsupported timeout\n");
6958 if (handle)
6959 FIXME("Unsupported cancel handle\n");
6961 ret = WS_getaddrinfoW(name, servname, NULL, result, overlapped, completion_routine);
6962 if (ret) return ret;
6963 if (handle) *handle = (HANDLE)0xdeadbeef;
6964 return 0;
6967 /***********************************************************************
6968 * GetAddrInfoExOverlappedResult (WS2_32.@)
6970 int WINAPI GetAddrInfoExOverlappedResult(OVERLAPPED *overlapped)
6972 TRACE("(%p)\n", overlapped);
6973 return overlapped->Internal;
6976 /***********************************************************************
6977 * GetAddrInfoExCancel (WS2_32.@)
6979 int WINAPI GetAddrInfoExCancel(HANDLE *handle)
6981 FIXME("(%p)\n", handle);
6982 return WSA_INVALID_HANDLE;
6985 /***********************************************************************
6986 * GetAddrInfoW (WS2_32.@)
6988 int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hints, PADDRINFOW *res)
6990 struct WS_addrinfo *hintsA = NULL;
6991 ADDRINFOEXW *resex;
6992 int ret = EAI_MEMORY;
6994 TRACE("nodename %s, servname %s, hints %p, result %p\n",
6995 debugstr_w(nodename), debugstr_w(servname), hints, res);
6997 *res = NULL;
6998 if (hints) hintsA = addrinfo_WtoA(hints);
6999 ret = WS_getaddrinfoW(nodename, servname, hintsA, &resex, NULL, NULL);
7000 WS_freeaddrinfo(hintsA);
7001 if (ret) return ret;
7003 if (resex)
7005 /* ADDRINFOEXW has layout compatible with ADDRINFOW except for ai_next field,
7006 * so we may convert it in place */
7007 *res = (ADDRINFOW*)resex;
7008 do {
7009 ((ADDRINFOW*)resex)->ai_next = (ADDRINFOW*)resex->ai_next;
7010 resex = resex->ai_next;
7011 } while (resex);
7013 return 0;
7016 /***********************************************************************
7017 * FreeAddrInfoW (WS2_32.@)
7019 void WINAPI FreeAddrInfoW(PADDRINFOW ai)
7021 while (ai)
7023 ADDRINFOW *next;
7024 HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
7025 HeapFree(GetProcessHeap(), 0, ai->ai_addr);
7026 next = ai->ai_next;
7027 HeapFree(GetProcessHeap(), 0, ai);
7028 ai = next;
7032 /***********************************************************************
7033 * FreeAddrInfoEx (WS2_32.@)
7035 void WINAPI FreeAddrInfoEx(ADDRINFOEXA *ai)
7037 TRACE("(%p)\n", ai);
7039 while (ai)
7041 ADDRINFOEXA *next;
7042 HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
7043 HeapFree(GetProcessHeap(), 0, ai->ai_addr);
7044 next = ai->ai_next;
7045 HeapFree(GetProcessHeap(), 0, ai);
7046 ai = next;
7050 /***********************************************************************
7051 * FreeAddrInfoExW (WS2_32.@)
7053 void WINAPI FreeAddrInfoExW(ADDRINFOEXW *ai)
7055 TRACE("(%p)\n", ai);
7057 while (ai)
7059 ADDRINFOEXW *next;
7060 HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
7061 HeapFree(GetProcessHeap(), 0, ai->ai_addr);
7062 next = ai->ai_next;
7063 HeapFree(GetProcessHeap(), 0, ai);
7064 ai = next;
7068 int WINAPI WS_getnameinfo(const SOCKADDR *sa, WS_socklen_t salen, PCHAR host,
7069 DWORD hostlen, PCHAR serv, DWORD servlen, INT flags)
7071 #ifdef HAVE_GETNAMEINFO
7072 int ret;
7073 union generic_unix_sockaddr sa_u;
7074 unsigned int size;
7076 TRACE("%s %d %p %d %p %d %d\n", debugstr_sockaddr(sa), salen, host, hostlen,
7077 serv, servlen, flags);
7079 size = ws_sockaddr_ws2u(sa, salen, &sa_u);
7080 if (!size)
7082 SetLastError(WSAEFAULT);
7083 return WSA_NOT_ENOUGH_MEMORY;
7085 ret = getnameinfo(&sa_u.addr, size, host, hostlen, serv, servlen, convert_niflag_w2u(flags));
7086 return convert_eai_u2w(ret);
7087 #else
7088 FIXME("getnameinfo() failed, not found during buildtime.\n");
7089 return EAI_FAIL;
7090 #endif
7093 int WINAPI GetNameInfoW(const SOCKADDR *sa, WS_socklen_t salen, PWCHAR host,
7094 DWORD hostlen, PWCHAR serv, DWORD servlen, INT flags)
7096 int ret;
7097 char *hostA = NULL, *servA = NULL;
7099 if (host && (!(hostA = HeapAlloc(GetProcessHeap(), 0, hostlen)))) return EAI_MEMORY;
7100 if (serv && (!(servA = HeapAlloc(GetProcessHeap(), 0, servlen))))
7102 HeapFree(GetProcessHeap(), 0, hostA);
7103 return EAI_MEMORY;
7106 ret = WS_getnameinfo(sa, salen, hostA, hostlen, servA, servlen, flags);
7107 if (!ret)
7109 if (host) MultiByteToWideChar(CP_ACP, 0, hostA, -1, host, hostlen);
7110 if (serv) MultiByteToWideChar(CP_ACP, 0, servA, -1, serv, servlen);
7113 HeapFree(GetProcessHeap(), 0, hostA);
7114 HeapFree(GetProcessHeap(), 0, servA);
7115 return ret;
7118 /***********************************************************************
7119 * getservbyport (WS2_32.56)
7121 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
7123 struct WS_servent* retval = NULL;
7124 #ifdef HAVE_GETSERVBYPORT
7125 struct servent* serv;
7126 char *proto_str = NULL;
7128 if (proto && *proto)
7130 if (!(proto_str = strdup_lower(proto))) return NULL;
7132 EnterCriticalSection( &csWSgetXXXbyYYY );
7133 if( (serv = getservbyport(port, proto_str)) != NULL ) {
7134 retval = WS_dup_se(serv);
7136 else SetLastError(WSANO_DATA);
7137 LeaveCriticalSection( &csWSgetXXXbyYYY );
7138 HeapFree( GetProcessHeap(), 0, proto_str );
7139 #endif
7140 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
7141 return retval;
7145 /***********************************************************************
7146 * gethostname (WS2_32.57)
7148 int WINAPI WS_gethostname(char *name, int namelen)
7150 char buf[256];
7151 int len;
7153 TRACE("name %p, len %d\n", name, namelen);
7155 if (!name)
7157 SetLastError(WSAEFAULT);
7158 return SOCKET_ERROR;
7161 if (gethostname(buf, sizeof(buf)) != 0)
7163 SetLastError(wsaErrno());
7164 return SOCKET_ERROR;
7167 TRACE("<- '%s'\n", buf);
7168 len = strlen(buf);
7169 if (len > 15)
7170 WARN("Windows supports NetBIOS name length up to 15 bytes!\n");
7171 if (namelen <= len)
7173 SetLastError(WSAEFAULT);
7174 WARN("<- not enough space for hostname, required %d, got %d!\n", len + 1, namelen);
7175 return SOCKET_ERROR;
7177 strcpy(name, buf);
7178 return 0;
7182 /* ------------------------------------- Windows sockets extensions -- *
7184 * ------------------------------------------------------------------- */
7186 /***********************************************************************
7187 * WSAEnumNetworkEvents (WS2_32.36)
7189 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
7191 int ret;
7192 int i;
7193 int errors[FD_MAX_EVENTS];
7195 TRACE("%04lx, hEvent %p, lpEvent %p\n", s, hEvent, lpEvent );
7197 SERVER_START_REQ( get_socket_event )
7199 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
7200 req->service = TRUE;
7201 req->c_event = wine_server_obj_handle( hEvent );
7202 wine_server_set_reply( req, errors, sizeof(errors) );
7203 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
7205 SERVER_END_REQ;
7206 if (!ret)
7208 for (i = 0; i < FD_MAX_EVENTS; i++)
7210 if (lpEvent->lNetworkEvents & (1 << i))
7211 lpEvent->iErrorCode[i] = errors[i];
7213 return 0;
7215 SetLastError(WSAEINVAL);
7216 return SOCKET_ERROR;
7219 /***********************************************************************
7220 * WSAEventSelect (WS2_32.39)
7222 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
7224 int ret;
7226 TRACE("%04lx, hEvent %p, event %08x\n", s, hEvent, lEvent);
7228 SERVER_START_REQ( set_socket_event )
7230 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
7231 req->mask = lEvent;
7232 req->event = wine_server_obj_handle( hEvent );
7233 req->window = 0;
7234 req->msg = 0;
7235 ret = wine_server_call( req );
7237 SERVER_END_REQ;
7238 if (!ret) return 0;
7239 SetLastError(WSAEINVAL);
7240 return SOCKET_ERROR;
7243 /**********************************************************************
7244 * WSAGetOverlappedResult (WS2_32.40)
7246 BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
7247 LPDWORD lpcbTransfer, BOOL fWait,
7248 LPDWORD lpdwFlags )
7250 NTSTATUS status;
7252 TRACE( "socket %04lx ovl %p trans %p, wait %d flags %p\n",
7253 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
7255 if ( lpOverlapped == NULL )
7257 ERR( "Invalid pointer\n" );
7258 SetLastError(WSA_INVALID_PARAMETER);
7259 return FALSE;
7262 status = lpOverlapped->Internal;
7263 if (status == STATUS_PENDING)
7265 if (!fWait)
7267 SetLastError( WSA_IO_INCOMPLETE );
7268 return FALSE;
7271 if (WaitForSingleObject( lpOverlapped->hEvent ? lpOverlapped->hEvent : SOCKET2HANDLE(s),
7272 INFINITE ) == WAIT_FAILED)
7273 return FALSE;
7274 status = lpOverlapped->Internal;
7277 if ( lpcbTransfer )
7278 *lpcbTransfer = lpOverlapped->InternalHigh;
7280 if ( lpdwFlags )
7281 *lpdwFlags = lpOverlapped->u.s.Offset;
7283 if (status) SetLastError( RtlNtStatusToDosError(status) );
7284 return !status;
7288 /***********************************************************************
7289 * WSAAsyncSelect (WS2_32.101)
7291 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
7293 int ret;
7295 TRACE("%04lx, hWnd %p, uMsg %08x, event %08x\n", s, hWnd, uMsg, lEvent);
7297 SERVER_START_REQ( set_socket_event )
7299 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
7300 req->mask = lEvent;
7301 req->event = 0;
7302 req->window = wine_server_user_handle( hWnd );
7303 req->msg = uMsg;
7304 ret = wine_server_call( req );
7306 SERVER_END_REQ;
7307 if (!ret) return 0;
7308 SetLastError(WSAEINVAL);
7309 return SOCKET_ERROR;
7312 /***********************************************************************
7313 * WSACreateEvent (WS2_32.31)
7316 WSAEVENT WINAPI WSACreateEvent(void)
7318 /* Create a manual-reset event, with initial state: unsignaled */
7319 TRACE("\n");
7321 return CreateEventW(NULL, TRUE, FALSE, NULL);
7324 /***********************************************************************
7325 * WSACloseEvent (WS2_32.29)
7328 BOOL WINAPI WSACloseEvent(WSAEVENT event)
7330 TRACE ("event=%p\n", event);
7332 return CloseHandle(event);
7335 /***********************************************************************
7336 * WSASocketA (WS2_32.78)
7339 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
7340 LPWSAPROTOCOL_INFOA lpProtocolInfo,
7341 GROUP g, DWORD dwFlags)
7343 INT len;
7344 WSAPROTOCOL_INFOW info;
7346 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%x\n",
7347 af, type, protocol, lpProtocolInfo, g, dwFlags);
7349 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
7351 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
7352 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
7353 info.szProtocol, WSAPROTOCOL_LEN + 1);
7355 if (!len)
7357 SetLastError(WSAEINVAL);
7358 return SOCKET_ERROR;
7361 return WSASocketW(af, type, protocol, &info, g, dwFlags);
7364 /***********************************************************************
7365 * WSASocketW (WS2_32.79)
7368 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
7369 LPWSAPROTOCOL_INFOW lpProtocolInfo,
7370 GROUP g, DWORD flags)
7372 static const WCHAR afdW[] = {'\\','D','e','v','i','c','e','\\','A','f','d',0};
7373 struct afd_create_params create_params;
7374 OBJECT_ATTRIBUTES attr;
7375 UNICODE_STRING string;
7376 IO_STATUS_BLOCK io;
7377 NTSTATUS status;
7378 HANDLE handle;
7379 SOCKET ret;
7380 DWORD err;
7383 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
7384 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
7387 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%x\n",
7388 af, type, protocol, lpProtocolInfo, g, flags );
7390 if (!num_startup)
7392 err = WSANOTINITIALISED;
7393 goto done;
7396 /* hack for WSADuplicateSocket */
7397 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00)
7399 ret = lpProtocolInfo->dwServiceFlags3;
7400 TRACE("\tgot duplicate %04lx\n", ret);
7401 if (!socket_list_add(ret))
7403 CloseHandle(SOCKET2HANDLE(ret));
7404 return INVALID_SOCKET;
7406 return ret;
7409 if (lpProtocolInfo)
7411 if (af == FROM_PROTOCOL_INFO || !af)
7412 af = lpProtocolInfo->iAddressFamily;
7413 if (type == FROM_PROTOCOL_INFO || !type)
7414 type = lpProtocolInfo->iSocketType;
7415 if (protocol == FROM_PROTOCOL_INFO || !protocol)
7416 protocol = lpProtocolInfo->iProtocol;
7419 if (!af && !protocol)
7421 WSASetLastError(WSAEINVAL);
7422 return INVALID_SOCKET;
7425 if (!af && lpProtocolInfo)
7427 WSASetLastError(WSAEAFNOSUPPORT);
7428 return INVALID_SOCKET;
7431 if (!af || !type || !protocol)
7433 unsigned int i;
7435 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
7437 const WSAPROTOCOL_INFOW *info = &supported_protocols[i];
7439 if (af && af != info->iAddressFamily) continue;
7440 if (type && type != info->iSocketType) continue;
7441 if (protocol && (protocol < info->iProtocol ||
7442 protocol > info->iProtocol + info->iProtocolMaxOffset)) continue;
7443 if (!protocol && !(info->dwProviderFlags & PFL_MATCHES_PROTOCOL_ZERO)) continue;
7445 if (!af) af = supported_protocols[i].iAddressFamily;
7446 if (!type) type = supported_protocols[i].iSocketType;
7447 if (!protocol) protocol = supported_protocols[i].iProtocol;
7451 RtlInitUnicodeString(&string, afdW);
7452 InitializeObjectAttributes(&attr, &string, (flags & WSA_FLAG_NO_HANDLE_INHERIT) ? 0 : OBJ_INHERIT, NULL, NULL);
7453 if ((status = NtOpenFile(&handle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &attr,
7454 &io, 0, (flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT)))
7456 WARN("Failed to create socket, status %#x.\n", status);
7457 WSASetLastError(NtStatusToWSAError(status));
7458 return INVALID_SOCKET;
7461 create_params.family = af;
7462 create_params.type = type;
7463 create_params.protocol = protocol;
7464 create_params.flags = flags & ~(WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED);
7465 if ((status = NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io,
7466 IOCTL_AFD_CREATE, &create_params, sizeof(create_params), NULL, 0)))
7468 WARN("Failed to initialize socket, status %#x.\n", status);
7469 err = NtStatusToWSAError(status);
7470 if (err == WSAEACCES) /* raw socket denied */
7472 if (type == SOCK_RAW)
7473 ERR_(winediag)("Failed to create a socket of type SOCK_RAW, this requires special permissions.\n");
7474 else
7475 ERR_(winediag)("Failed to create socket, this requires special permissions.\n");
7477 WSASetLastError(err);
7478 NtClose(handle);
7479 return INVALID_SOCKET;
7482 ret = HANDLE2SOCKET(handle);
7483 TRACE("\tcreated %04lx\n", ret );
7485 if (!socket_list_add(ret))
7487 CloseHandle(handle);
7488 return INVALID_SOCKET;
7490 return ret;
7492 done:
7493 WARN("\t\tfailed, error %d!\n", err);
7494 SetLastError(err);
7495 return INVALID_SOCKET;
7498 /***********************************************************************
7499 * WSAJoinLeaf (WS2_32.58)
7502 SOCKET WINAPI WSAJoinLeaf(
7503 SOCKET s,
7504 const struct WS_sockaddr *addr,
7505 int addrlen,
7506 LPWSABUF lpCallerData,
7507 LPWSABUF lpCalleeData,
7508 LPQOS lpSQOS,
7509 LPQOS lpGQOS,
7510 DWORD dwFlags)
7512 FIXME("stub.\n");
7513 return INVALID_SOCKET;
7516 /***********************************************************************
7517 * __WSAFDIsSet (WS2_32.151)
7519 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
7521 int i = set->fd_count, ret = 0;
7523 while (i--)
7524 if (set->fd_array[i] == s)
7526 ret = 1;
7527 break;
7530 TRACE("(socket %04lx, fd_set %p, count %i) <- %d\n", s, set, set->fd_count, ret);
7531 return ret;
7534 /***********************************************************************
7535 * WSAIsBlocking (WS2_32.114)
7537 BOOL WINAPI WSAIsBlocking(void)
7539 /* By default WinSock should set all its sockets to non-blocking mode
7540 * and poll in PeekMessage loop when processing "blocking" ones. This
7541 * function is supposed to tell if the program is in this loop. Our
7542 * blocking calls are truly blocking so we always return FALSE.
7544 * Note: It is allowed to call this function without prior WSAStartup().
7547 TRACE("\n");
7548 return FALSE;
7551 /***********************************************************************
7552 * WSACancelBlockingCall (WS2_32.113)
7554 INT WINAPI WSACancelBlockingCall(void)
7556 TRACE("\n");
7557 return 0;
7560 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
7562 FIXME("How was this called?\n");
7563 return x();
7567 /***********************************************************************
7568 * WSASetBlockingHook (WS2_32.109)
7570 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
7572 FARPROC prev = blocking_hook;
7573 blocking_hook = lpBlockFunc;
7574 TRACE("hook %p\n", lpBlockFunc);
7575 return prev;
7579 /***********************************************************************
7580 * WSAUnhookBlockingHook (WS2_32.110)
7582 INT WINAPI WSAUnhookBlockingHook(void)
7584 blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
7585 return 0;
7589 /* ----------------------------------- end of API stuff */
7591 /* ----------------------------------- helper functions -
7593 * TODO: Merge WS_dup_..() stuff into one function that
7594 * would operate with a generic structure containing internal
7595 * pointers (via a template of some kind).
7598 static int list_size(char** l, int item_size)
7600 int i,j = 0;
7601 if(l)
7602 { for(i=0;l[i];i++)
7603 j += (item_size) ? item_size : strlen(l[i]) + 1;
7604 j += (i + 1) * sizeof(char*); }
7605 return j;
7608 static int list_dup(char** l_src, char** l_to, int item_size)
7610 char *p;
7611 int i;
7613 for (i = 0; l_src[i]; i++) ;
7614 p = (char *)(l_to + i + 1);
7615 for (i = 0; l_src[i]; i++)
7617 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
7618 memcpy(p, l_src[i], count);
7619 l_to[i] = p;
7620 p += count;
7622 l_to[i] = NULL;
7623 return p - (char *)l_to;
7626 /* ----- hostent */
7628 /* create a hostent entry
7630 * Creates the entry with enough memory for the name, aliases
7631 * addresses, and the address pointers. Also copies the name
7632 * and sets up all the pointers.
7634 * NOTE: The alias and address lists must be allocated with room
7635 * for the NULL item terminating the list. This is true even if
7636 * the list has no items ("aliases" and "addresses" must be
7637 * at least "1", a truly empty list is invalid).
7639 static struct WS_hostent *WS_create_he(char *name, int aliases, int aliases_size, int addresses, int address_length)
7641 struct WS_hostent *p_to;
7642 char *p;
7643 int size = (sizeof(struct WS_hostent) +
7644 strlen(name) + 1 +
7645 sizeof(char *) * aliases +
7646 aliases_size +
7647 sizeof(char *) * addresses +
7648 address_length * (addresses - 1)), i;
7650 if (!(p_to = check_buffer_he(size))) return NULL;
7651 memset(p_to, 0, size);
7653 /* Use the memory in the same way winsock does.
7654 * First set the pointer for aliases, second set the pointers for addresses.
7655 * Third fill the addresses indexes, fourth jump aliases names size.
7656 * Fifth fill the hostname.
7657 * NOTE: This method is valid for OS versions >= XP.
7659 p = (char *)(p_to + 1);
7660 p_to->h_aliases = (char **)p;
7661 p += sizeof(char *)*aliases;
7663 p_to->h_addr_list = (char **)p;
7664 p += sizeof(char *)*addresses;
7666 for (i = 0, addresses--; i < addresses; i++, p += address_length)
7667 p_to->h_addr_list[i] = p;
7669 /* NOTE: h_aliases must be filled in manually because we don't know each string
7670 * size, leave these pointers NULL (already set to NULL by memset earlier).
7672 p += aliases_size;
7674 p_to->h_name = p;
7675 strcpy(p, name);
7677 return p_to;
7680 /* duplicate hostent entry
7681 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
7682 * Ditto for protoent and servent.
7684 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
7686 int i, addresses = 0, alias_size = 0;
7687 struct WS_hostent *p_to;
7688 char *p;
7690 for( i = 0; p_he->h_aliases[i]; i++) alias_size += strlen(p_he->h_aliases[i]) + 1;
7691 while (p_he->h_addr_list[addresses]) addresses++;
7693 p_to = WS_create_he(p_he->h_name, i + 1, alias_size, addresses + 1, p_he->h_length);
7695 if (!p_to) return NULL;
7696 p_to->h_addrtype = convert_af_u2w(p_he->h_addrtype);
7697 p_to->h_length = p_he->h_length;
7699 for(i = 0, p = p_to->h_addr_list[0]; p_he->h_addr_list[i]; i++, p += p_to->h_length)
7700 memcpy(p, p_he->h_addr_list[i], p_to->h_length);
7702 /* Fill the aliases after the IP data */
7703 for(i = 0; p_he->h_aliases[i]; i++)
7705 p_to->h_aliases[i] = p;
7706 strcpy(p, p_he->h_aliases[i]);
7707 p += strlen(p) + 1;
7710 return p_to;
7713 /* ----- protoent */
7715 static struct WS_protoent *WS_create_pe( const char *name, char **aliases, int prot )
7717 struct WS_protoent *ret;
7718 unsigned int size = sizeof(*ret) + strlen(name) + sizeof(char *) + list_size(aliases, 0);
7720 if (!(ret = check_buffer_pe( size ))) return NULL;
7721 ret->p_proto = prot;
7722 ret->p_name = (char *)(ret + 1);
7723 strcpy( ret->p_name, name );
7724 ret->p_aliases = (char **)ret->p_name + strlen(name) / sizeof(char *) + 1;
7725 list_dup( aliases, ret->p_aliases, 0 );
7726 return ret;
7729 /* ----- servent */
7731 static struct WS_servent *WS_dup_se(const struct servent* p_se)
7733 char *p;
7734 struct WS_servent *p_to;
7736 int size = (sizeof(*p_se) +
7737 strlen(p_se->s_proto) + 1 +
7738 strlen(p_se->s_name) + 1 +
7739 list_size(p_se->s_aliases, 0));
7741 if (!(p_to = check_buffer_se(size))) return NULL;
7742 p_to->s_port = p_se->s_port;
7744 p = (char *)(p_to + 1);
7745 p_to->s_name = p;
7746 strcpy(p, p_se->s_name);
7747 p += strlen(p) + 1;
7749 p_to->s_proto = p;
7750 strcpy(p, p_se->s_proto);
7751 p += strlen(p) + 1;
7753 p_to->s_aliases = (char **)p;
7754 list_dup(p_se->s_aliases, p_to->s_aliases, 0);
7755 return p_to;
7759 /***********************************************************************
7760 * WSARecv (WS2_32.67)
7762 int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
7763 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
7764 LPWSAOVERLAPPED lpOverlapped,
7765 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
7767 return WS2_recv_base(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
7768 NULL, NULL, lpOverlapped, lpCompletionRoutine, NULL);
7771 static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
7772 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags,
7773 struct WS_sockaddr *lpFrom,
7774 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
7775 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
7776 LPWSABUF lpControlBuffer )
7778 unsigned int i, options;
7779 int n, fd, err, overlapped, flags;
7780 struct ws2_async *wsa = NULL, localwsa;
7781 BOOL is_blocking;
7782 DWORD timeout_start = GetTickCount();
7783 ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
7785 TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, from %p, fromlen %d, ovl %p, func %p\n",
7786 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
7787 (lpFromlen ? *lpFromlen : -1),
7788 lpOverlapped, lpCompletionRoutine);
7790 fd = get_sock_fd( s, FILE_READ_DATA, &options );
7791 TRACE( "fd=%d, options=%x\n", fd, options );
7793 if (fd == -1) return SOCKET_ERROR;
7795 if (*lpFlags & WS_MSG_OOB)
7797 /* It's invalid to receive OOB data from an OOBINLINED socket
7798 * as OOB data is turned into normal data. */
7799 socklen_t len = sizeof(n);
7800 if (!getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char*) &n, &len) && n)
7802 err = WSAEINVAL;
7803 goto error;
7807 overlapped = (lpOverlapped || lpCompletionRoutine) &&
7808 !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
7809 if (overlapped || dwBufferCount > 1)
7811 if (!(wsa = (struct ws2_async *)alloc_async_io( offsetof(struct ws2_async, iovec[dwBufferCount]),
7812 WS2_async_recv )))
7814 err = WSAEFAULT;
7815 goto error;
7818 else
7819 wsa = &localwsa;
7821 wsa->hSocket = SOCKET2HANDLE(s);
7822 wsa->flags = *lpFlags;
7823 wsa->lpFlags = lpFlags;
7824 wsa->addr = lpFrom;
7825 wsa->addrlen.ptr = lpFromlen;
7826 wsa->control = lpControlBuffer;
7827 wsa->n_iovecs = dwBufferCount;
7828 wsa->first_iovec = 0;
7829 for (i = 0; i < dwBufferCount; i++)
7831 /* check buffer first to trigger write watches */
7832 if (IsBadWritePtr( lpBuffers[i].buf, lpBuffers[i].len ))
7834 err = WSAEFAULT;
7835 goto error;
7837 wsa->iovec[i].iov_base = lpBuffers[i].buf;
7838 wsa->iovec[i].iov_len = lpBuffers[i].len;
7841 flags = convert_flags(wsa->flags);
7842 for (;;)
7844 n = WS2_recv( fd, wsa, flags );
7845 if (n == -1)
7847 /* Unix-like systems return EINVAL when attempting to read OOB data from
7848 * an empty socket buffer, convert that to a Windows expected return. */
7849 if ((flags & MSG_OOB) && errno == EINVAL)
7850 errno = EWOULDBLOCK;
7852 if (errno != EAGAIN)
7854 err = wsaErrno();
7855 goto error;
7858 else if (lpNumberOfBytesRecvd) *lpNumberOfBytesRecvd = n;
7860 if (overlapped)
7862 IO_STATUS_BLOCK *iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
7864 wsa->user_overlapped = lpOverlapped;
7865 wsa->completion_func = lpCompletionRoutine;
7866 release_sock_fd( s, fd );
7868 if (n == -1)
7870 iosb->u.Status = STATUS_PENDING;
7871 iosb->Information = 0;
7873 if (wsa->completion_func)
7874 err = register_async( ASYNC_TYPE_READ, wsa->hSocket, &wsa->io, NULL,
7875 ws2_async_apc, wsa, iosb );
7876 else
7877 err = register_async( ASYNC_TYPE_READ, wsa->hSocket, &wsa->io, lpOverlapped->hEvent,
7878 NULL, (void *)cvalue, iosb );
7880 if (err != STATUS_PENDING) HeapFree( GetProcessHeap(), 0, wsa );
7881 SetLastError(NtStatusToWSAError( err ));
7882 return SOCKET_ERROR;
7885 iosb->u.Status = STATUS_SUCCESS;
7886 iosb->Information = n;
7887 if (!wsa->completion_func)
7889 if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n, FALSE );
7890 if (lpOverlapped->hEvent) SetEvent( lpOverlapped->hEvent );
7891 HeapFree( GetProcessHeap(), 0, wsa );
7893 else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc,
7894 (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 );
7895 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
7896 return 0;
7899 if (n != -1) break;
7901 if ((err = sock_is_blocking( s, &is_blocking ))) goto error;
7903 if ( is_blocking )
7905 struct pollfd pfd;
7906 int poll_timeout = -1;
7907 INT64 timeout = get_rcvsnd_timeo(fd, TRUE);
7909 if (timeout)
7911 timeout -= GetTickCount() - timeout_start;
7912 if (timeout < 0) poll_timeout = 0;
7913 else poll_timeout = timeout <= INT_MAX ? timeout : INT_MAX;
7916 pfd.fd = fd;
7917 pfd.events = POLLIN;
7918 if (*lpFlags & WS_MSG_OOB) pfd.events |= POLLPRI;
7920 if (!poll_timeout || !poll( &pfd, 1, poll_timeout ))
7922 err = WSAETIMEDOUT;
7923 /* a timeout is not fatal */
7924 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
7925 goto error;
7928 else
7930 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
7931 err = WSAEWOULDBLOCK;
7932 goto error;
7936 TRACE(" -> %i bytes\n", n);
7937 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
7938 release_sock_fd( s, fd );
7939 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
7940 SetLastError(ERROR_SUCCESS);
7942 return 0;
7944 error:
7945 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
7946 release_sock_fd( s, fd );
7947 WARN(" -> ERROR %d\n", err);
7948 SetLastError( err );
7949 return SOCKET_ERROR;
7952 /***********************************************************************
7953 * WSARecvFrom (WS2_32.69)
7955 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
7956 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
7957 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
7958 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
7961 return WS2_recv_base( s, lpBuffers, dwBufferCount,
7962 lpNumberOfBytesRecvd, lpFlags,
7963 lpFrom, lpFromlen,
7964 lpOverlapped, lpCompletionRoutine, NULL );
7967 /***********************************************************************
7968 * WSCInstallProvider (WS2_32.88)
7970 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
7971 LPCWSTR lpszProviderDllPath,
7972 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
7973 DWORD dwNumberOfEntries,
7974 LPINT lpErrno )
7976 FIXME("(%s, %s, %p, %d, %p): stub !\n", debugstr_guid(lpProviderId),
7977 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
7978 dwNumberOfEntries, lpErrno);
7979 *lpErrno = 0;
7980 return 0;
7984 /***********************************************************************
7985 * WSCDeinstallProvider (WS2_32.83)
7987 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
7989 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
7990 *lpErrno = 0;
7991 return 0;
7995 /***********************************************************************
7996 * WSAAccept (WS2_32.26)
7998 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
7999 LPCONDITIONPROC lpfnCondition, DWORD_PTR dwCallbackData)
8002 int ret = 0, size;
8003 WSABUF CallerId, CallerData, CalleeId, CalleeData;
8004 /* QOS SQOS, GQOS; */
8005 GROUP g;
8006 SOCKET cs;
8007 SOCKADDR src_addr, dst_addr;
8009 TRACE("socket %04lx, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
8010 s, addr, addrlen, lpfnCondition, dwCallbackData);
8012 cs = WS_accept(s, addr, addrlen);
8013 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
8014 if (!lpfnCondition) return cs;
8016 if (addr && addrlen)
8018 CallerId.buf = (char *)addr;
8019 CallerId.len = *addrlen;
8021 else
8023 size = sizeof(src_addr);
8024 WS_getpeername(cs, &src_addr, &size);
8025 CallerId.buf = (char *)&src_addr;
8026 CallerId.len = size;
8028 CallerData.buf = NULL;
8029 CallerData.len = 0;
8031 size = sizeof(dst_addr);
8032 WS_getsockname(cs, &dst_addr, &size);
8034 CalleeId.buf = (char *)&dst_addr;
8035 CalleeId.len = sizeof(dst_addr);
8037 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
8038 &CalleeId, &CalleeData, &g, dwCallbackData);
8040 switch (ret)
8042 case CF_ACCEPT:
8043 return cs;
8044 case CF_DEFER:
8045 SERVER_START_REQ( set_socket_deferred )
8047 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
8048 req->deferred = wine_server_obj_handle( SOCKET2HANDLE(cs) );
8049 if ( !wine_server_call_err ( req ) )
8051 SetLastError( WSATRY_AGAIN );
8052 WS_closesocket( cs );
8055 SERVER_END_REQ;
8056 return SOCKET_ERROR;
8057 case CF_REJECT:
8058 WS_closesocket(cs);
8059 SetLastError(WSAECONNREFUSED);
8060 return SOCKET_ERROR;
8061 default:
8062 FIXME("Unknown return type from Condition function\n");
8063 SetLastError(WSAENOTSOCK);
8064 return SOCKET_ERROR;
8068 /***********************************************************************
8069 * WSADuplicateSocketA (WS2_32.32)
8071 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
8073 return WS_DuplicateSocket(FALSE, s, dwProcessId, (LPWSAPROTOCOL_INFOW) lpProtocolInfo);
8076 /***********************************************************************
8077 * WSADuplicateSocketW (WS2_32.33)
8079 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
8081 return WS_DuplicateSocket(TRUE, s, dwProcessId, lpProtocolInfo);
8084 /***********************************************************************
8085 * WSAInstallServiceClassA (WS2_32.48)
8087 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
8089 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
8090 SetLastError(WSAEACCES);
8091 return SOCKET_ERROR;
8094 /***********************************************************************
8095 * WSAInstallServiceClassW (WS2_32.49)
8097 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
8099 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
8100 SetLastError(WSAEACCES);
8101 return SOCKET_ERROR;
8104 /***********************************************************************
8105 * WSARemoveServiceClass (WS2_32.70)
8107 int WINAPI WSARemoveServiceClass(LPGUID info)
8109 FIXME("Request to remove service %s\n", debugstr_guid(info));
8110 SetLastError(WSATYPE_NOT_FOUND);
8111 return SOCKET_ERROR;
8114 /***********************************************************************
8115 * inet_ntop (WS2_32.@)
8117 PCSTR WINAPI WS_inet_ntop( INT family, PVOID addr, PSTR buffer, SIZE_T len )
8119 NTSTATUS status;
8120 ULONG size = min( len, (ULONG)-1 );
8122 TRACE("family %d, addr (%p), buffer (%p), len %ld\n", family, addr, buffer, len);
8123 if (!buffer)
8125 SetLastError( STATUS_INVALID_PARAMETER );
8126 return NULL;
8129 switch (family)
8131 case WS_AF_INET:
8133 status = RtlIpv4AddressToStringExA( (IN_ADDR *)addr, 0, buffer, &size );
8134 break;
8136 case WS_AF_INET6:
8138 status = RtlIpv6AddressToStringExA( (IN6_ADDR *)addr, 0, 0, buffer, &size );
8139 break;
8141 default:
8142 SetLastError( WSAEAFNOSUPPORT );
8143 return NULL;
8146 if (status == STATUS_SUCCESS) return buffer;
8147 SetLastError( STATUS_INVALID_PARAMETER );
8148 return NULL;
8151 /***********************************************************************
8152 * inet_pton (WS2_32.@)
8154 INT WINAPI WS_inet_pton(INT family, const char *addr, void *buffer)
8156 NTSTATUS status;
8157 const char *terminator;
8159 TRACE("family %d, addr %s, buffer (%p)\n", family, debugstr_a(addr), buffer);
8161 if (!addr || !buffer)
8163 SetLastError(WSAEFAULT);
8164 return SOCKET_ERROR;
8167 switch (family)
8169 case WS_AF_INET:
8170 status = RtlIpv4StringToAddressA(addr, TRUE, &terminator, buffer);
8171 break;
8172 case WS_AF_INET6:
8173 status = RtlIpv6StringToAddressA(addr, &terminator, buffer);
8174 break;
8175 default:
8176 SetLastError(WSAEAFNOSUPPORT);
8177 return SOCKET_ERROR;
8180 return (status == STATUS_SUCCESS && *terminator == 0);
8183 /***********************************************************************
8184 * InetPtonW (WS2_32.@)
8186 INT WINAPI InetPtonW(INT family, PCWSTR addr, PVOID buffer)
8188 char *addrA;
8189 int len;
8190 INT ret;
8192 TRACE("family %d, addr %s, buffer (%p)\n", family, debugstr_w(addr), buffer);
8194 if (!addr)
8196 SetLastError(WSAEFAULT);
8197 return SOCKET_ERROR;
8200 len = WideCharToMultiByte(CP_ACP, 0, addr, -1, NULL, 0, NULL, NULL);
8201 if (!(addrA = HeapAlloc(GetProcessHeap(), 0, len)))
8203 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8204 return SOCKET_ERROR;
8206 WideCharToMultiByte(CP_ACP, 0, addr, -1, addrA, len, NULL, NULL);
8208 ret = WS_inet_pton(family, addrA, buffer);
8209 if (!ret) SetLastError(WSAEINVAL);
8211 HeapFree(GetProcessHeap(), 0, addrA);
8212 return ret;
8215 /***********************************************************************
8216 * InetNtopW (WS2_32.@)
8218 PCWSTR WINAPI InetNtopW(INT family, PVOID addr, PWSTR buffer, SIZE_T len)
8220 char bufferA[WS_INET6_ADDRSTRLEN];
8221 PWSTR ret = NULL;
8223 TRACE("family %d, addr (%p), buffer (%p), len %ld\n", family, addr, buffer, len);
8225 if (WS_inet_ntop(family, addr, bufferA, sizeof(bufferA)))
8227 if (MultiByteToWideChar(CP_ACP, 0, bufferA, -1, buffer, len))
8228 ret = buffer;
8229 else
8230 SetLastError(ERROR_INVALID_PARAMETER);
8232 return ret;
8235 /***********************************************************************
8236 * WSAStringToAddressA (WS2_32.80)
8238 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
8239 INT AddressFamily,
8240 LPWSAPROTOCOL_INFOA lpProtocolInfo,
8241 LPSOCKADDR lpAddress,
8242 LPINT lpAddressLength)
8244 INT res=0;
8245 NTSTATUS status;
8247 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_a(AddressString), AddressFamily,
8248 lpProtocolInfo, lpAddress, lpAddressLength );
8250 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
8252 if (!AddressString)
8254 SetLastError(WSAEINVAL);
8255 return SOCKET_ERROR;
8258 if (lpProtocolInfo)
8259 FIXME("ProtocolInfo not implemented.\n");
8261 switch(AddressFamily)
8263 case WS_AF_INET:
8265 SOCKADDR_IN *addr4 = (SOCKADDR_IN *)lpAddress;
8267 /* If lpAddressLength is too small, tell caller the size we need */
8268 if (*lpAddressLength < sizeof(SOCKADDR_IN))
8270 *lpAddressLength = sizeof(SOCKADDR_IN);
8271 res = WSAEFAULT;
8272 break;
8274 memset(lpAddress, 0, sizeof(SOCKADDR_IN));
8276 status = RtlIpv4StringToAddressExA(AddressString, FALSE, &addr4->sin_addr, &addr4->sin_port);
8277 if (status != STATUS_SUCCESS)
8279 res = WSAEINVAL;
8280 break;
8282 addr4->sin_family = WS_AF_INET;
8283 *lpAddressLength = sizeof(SOCKADDR_IN);
8284 break;
8286 case WS_AF_INET6:
8288 SOCKADDR_IN6 *addr6 = (SOCKADDR_IN6 *)lpAddress;
8290 /* If lpAddressLength is too small, tell caller the size we need */
8291 if (*lpAddressLength < sizeof(SOCKADDR_IN6))
8293 *lpAddressLength = sizeof(SOCKADDR_IN6);
8294 res = WSAEFAULT;
8295 break;
8297 memset(lpAddress, 0, sizeof(SOCKADDR_IN6));
8299 status = RtlIpv6StringToAddressExA(AddressString, &addr6->sin6_addr, &addr6->sin6_scope_id, &addr6->sin6_port);
8300 if (status != STATUS_SUCCESS)
8302 res = WSAEINVAL;
8303 break;
8305 addr6->sin6_family = WS_AF_INET6;
8306 *lpAddressLength = sizeof(SOCKADDR_IN6);
8307 break;
8309 default:
8310 /* According to MSDN, only AF_INET and AF_INET6 are supported. */
8311 TRACE("Unsupported address family specified: %d.\n", AddressFamily);
8312 res = WSAEINVAL;
8315 if (!res) return 0;
8316 SetLastError(res);
8317 return SOCKET_ERROR;
8320 /***********************************************************************
8321 * WSAStringToAddressW (WS2_32.81)
8323 * FIXME: Does anybody know if this function allows using Hebrew/Arabic/Chinese... digits?
8324 * If this should be the case, it would be required to map these digits
8325 * to Unicode digits (0-9) using FoldString first.
8327 INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
8328 INT AddressFamily,
8329 LPWSAPROTOCOL_INFOW lpProtocolInfo,
8330 LPSOCKADDR lpAddress,
8331 LPINT lpAddressLength)
8333 INT sBuffer,res=0;
8334 LPSTR workBuffer=NULL;
8335 WSAPROTOCOL_INFOA infoA;
8336 LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
8338 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
8339 lpAddress, lpAddressLength );
8341 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
8343 /* if ProtocolInfo is available - convert to ANSI variant */
8344 if (lpProtocolInfo)
8346 lpProtoInfoA = &infoA;
8347 memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
8349 if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
8350 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
8352 SetLastError(WSAEINVAL);
8353 return SOCKET_ERROR;
8357 if (AddressString)
8359 /* Translate AddressString to ANSI code page - assumes that only
8360 standard digits 0-9 are used with this API call */
8361 sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
8362 workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
8364 if (workBuffer)
8366 WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
8367 res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
8368 lpAddress,lpAddressLength);
8369 HeapFree( GetProcessHeap(), 0, workBuffer );
8370 return res;
8372 else
8373 res = WSA_NOT_ENOUGH_MEMORY;
8375 else
8376 res = WSAEINVAL;
8378 SetLastError(res);
8379 return SOCKET_ERROR;
8382 /***********************************************************************
8383 * WSAAddressToStringA (WS2_32.27)
8385 * See WSAAddressToStringW
8387 INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
8388 LPWSAPROTOCOL_INFOA info, LPSTR string,
8389 LPDWORD lenstr )
8391 DWORD size;
8392 CHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
8393 CHAR *p;
8395 TRACE( "(%p, %d, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
8397 if (!sockaddr) return SOCKET_ERROR;
8398 if (!string || !lenstr) return SOCKET_ERROR;
8400 switch(sockaddr->sa_family)
8402 case WS_AF_INET:
8404 unsigned int long_ip = ntohl(((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr);
8405 if (len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
8406 sprintf( buffer, "%u.%u.%u.%u:%u",
8407 (long_ip >> 24) & 0xff,
8408 (long_ip >> 16) & 0xff,
8409 (long_ip >> 8) & 0xff,
8410 long_ip & 0xff,
8411 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
8413 p = strchr( buffer, ':' );
8414 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
8415 break;
8417 case WS_AF_INET6:
8419 struct WS_sockaddr_in6 *sockaddr6 = (LPSOCKADDR_IN6) sockaddr;
8420 size_t slen;
8422 buffer[0] = 0;
8423 if (len < sizeof(SOCKADDR_IN6)) return SOCKET_ERROR;
8424 if ((sockaddr6->sin6_port))
8425 strcpy(buffer, "[");
8426 slen = strlen(buffer);
8427 if (!WS_inet_ntop(WS_AF_INET6, &sockaddr6->sin6_addr, &buffer[slen], sizeof(buffer) - slen))
8429 SetLastError(WSAEINVAL);
8430 return SOCKET_ERROR;
8432 if ((sockaddr6->sin6_scope_id))
8433 sprintf(buffer+strlen(buffer), "%%%u", sockaddr6->sin6_scope_id);
8434 if ((sockaddr6->sin6_port))
8435 sprintf(buffer+strlen(buffer), "]:%u", ntohs(sockaddr6->sin6_port));
8436 break;
8439 default:
8440 SetLastError(WSAEINVAL);
8441 return SOCKET_ERROR;
8444 size = strlen( buffer ) + 1;
8446 if (*lenstr < size)
8448 *lenstr = size;
8449 SetLastError(WSAEFAULT);
8450 return SOCKET_ERROR;
8453 TRACE("=> %s,%u bytes\n", debugstr_a(buffer), size);
8454 *lenstr = size;
8455 strcpy( string, buffer );
8456 return 0;
8459 /***********************************************************************
8460 * WSAAddressToStringW (WS2_32.28)
8462 * Convert a sockaddr address into a readable address string.
8464 * PARAMS
8465 * sockaddr [I] Pointer to a sockaddr structure.
8466 * len [I] Size of the sockaddr structure.
8467 * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional).
8468 * string [I/O] Pointer to a buffer to receive the address string.
8469 * lenstr [I/O] Size of the receive buffer in WCHARs.
8471 * RETURNS
8472 * Success: 0
8473 * Failure: SOCKET_ERROR
8475 * NOTES
8476 * The 'info' parameter is ignored.
8478 INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
8479 LPWSAPROTOCOL_INFOW info, LPWSTR string,
8480 LPDWORD lenstr )
8482 INT ret;
8483 DWORD size;
8484 WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
8485 CHAR bufAddr[54];
8487 TRACE( "(%p, %d, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
8489 size = *lenstr;
8490 ret = WSAAddressToStringA(sockaddr, len, NULL, bufAddr, &size);
8492 if (ret) return ret;
8494 MultiByteToWideChar(CP_ACP, 0, bufAddr, size, buffer, ARRAY_SIZE(buffer));
8496 if (*lenstr < size)
8498 *lenstr = size;
8499 SetLastError(WSAEFAULT);
8500 return SOCKET_ERROR;
8503 TRACE("=> %s,%u bytes\n", debugstr_w(buffer), size);
8504 *lenstr = size;
8505 lstrcpyW( string, buffer );
8506 return 0;
8509 /***********************************************************************
8510 * WSAEnumNameSpaceProvidersA (WS2_32.34)
8512 INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
8514 FIXME( "(%p %p) Stub!\n", len, buffer );
8515 return 0;
8518 /***********************************************************************
8519 * WSAEnumNameSpaceProvidersW (WS2_32.35)
8521 INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
8523 FIXME( "(%p %p) Stub!\n", len, buffer );
8524 return 0;
8527 /***********************************************************************
8528 * WSAGetQOSByName (WS2_32.41)
8530 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
8532 FIXME( "(0x%04lx %p %p) Stub!\n", s, lpQOSName, lpQOS );
8533 return FALSE;
8536 /***********************************************************************
8537 * WSAGetServiceClassInfoA (WS2_32.42)
8539 INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
8540 LPWSASERVICECLASSINFOA info )
8542 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
8543 len, info );
8544 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8545 return SOCKET_ERROR;
8548 /***********************************************************************
8549 * WSAGetServiceClassInfoW (WS2_32.43)
8551 INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
8552 LPWSASERVICECLASSINFOW info )
8554 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
8555 len, info );
8556 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8557 return SOCKET_ERROR;
8560 /***********************************************************************
8561 * WSAGetServiceClassNameByClassIdA (WS2_32.44)
8563 INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
8565 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
8566 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8567 return SOCKET_ERROR;
8570 /***********************************************************************
8571 * WSAGetServiceClassNameByClassIdW (WS2_32.45)
8573 INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
8575 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
8576 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8577 return SOCKET_ERROR;
8580 /***********************************************************************
8581 * WSALookupServiceBeginA (WS2_32.59)
8583 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
8584 DWORD dwControlFlags,
8585 LPHANDLE lphLookup)
8587 FIXME("(%p 0x%08x %p) Stub!\n", lpqsRestrictions, dwControlFlags,
8588 lphLookup);
8589 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8590 return SOCKET_ERROR;
8593 /***********************************************************************
8594 * WSALookupServiceBeginW (WS2_32.60)
8596 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
8597 DWORD dwControlFlags,
8598 LPHANDLE lphLookup)
8600 FIXME("(%p 0x%08x %p) Stub!\n", lpqsRestrictions, dwControlFlags,
8601 lphLookup);
8602 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8603 return SOCKET_ERROR;
8606 /***********************************************************************
8607 * WSALookupServiceEnd (WS2_32.61)
8609 INT WINAPI WSALookupServiceEnd( HANDLE lookup )
8611 FIXME("(%p) Stub!\n", lookup );
8612 return 0;
8615 /***********************************************************************
8616 * WSALookupServiceNextA (WS2_32.62)
8618 INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
8620 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup, flags, len, results );
8621 SetLastError(WSA_E_NO_MORE);
8622 return SOCKET_ERROR;
8625 /***********************************************************************
8626 * WSALookupServiceNextW (WS2_32.63)
8628 INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
8630 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup, flags, len, results );
8631 SetLastError(WSA_E_NO_MORE);
8632 return SOCKET_ERROR;
8635 /***********************************************************************
8636 * WSANtohl (WS2_32.64)
8638 INT WINAPI WSANtohl( SOCKET s, WS_u_long netlong, WS_u_long* lphostlong )
8640 TRACE( "(%04lx 0x%08x %p)\n", s, netlong, lphostlong );
8642 if (!lphostlong) return WSAEFAULT;
8644 *lphostlong = ntohl( netlong );
8645 return 0;
8648 /***********************************************************************
8649 * WSANtohs (WS2_32.65)
8651 INT WINAPI WSANtohs( SOCKET s, WS_u_short netshort, WS_u_short* lphostshort )
8653 TRACE( "(%04lx 0x%08x %p)\n", s, netshort, lphostshort );
8655 if (!lphostshort) return WSAEFAULT;
8657 *lphostshort = ntohs( netshort );
8658 return 0;
8661 /***********************************************************************
8662 * WSAProviderConfigChange (WS2_32.66)
8664 INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
8665 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
8667 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
8668 return SOCKET_ERROR;
8671 /***********************************************************************
8672 * WSARecvDisconnect (WS2_32.68)
8674 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
8676 TRACE( "(%04lx %p)\n", s, disconnectdata );
8678 return WS_shutdown( s, SD_RECEIVE );
8681 /***********************************************************************
8682 * WSASetServiceA (WS2_32.76)
8684 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
8686 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query, operation, flags );
8687 return 0;
8690 /***********************************************************************
8691 * WSASetServiceW (WS2_32.77)
8693 INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
8695 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query, operation, flags );
8696 return 0;
8699 /***********************************************************************
8700 * WSCEnableNSProvider (WS2_32.84)
8702 INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
8704 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
8705 return 0;
8708 /***********************************************************************
8709 * WSCGetProviderInfo
8711 INT WINAPI WSCGetProviderInfo( LPGUID provider, WSC_PROVIDER_INFO_TYPE info_type,
8712 PBYTE info, size_t* len, DWORD flags, LPINT errcode )
8714 FIXME( "(%s 0x%08x %p %p 0x%08x %p) Stub!\n",
8715 debugstr_guid(provider), info_type, info, len, flags, errcode );
8717 if (!errcode)
8718 return SOCKET_ERROR;
8720 if (!provider) {
8721 *errcode = WSAEFAULT;
8722 return SOCKET_ERROR;
8725 *errcode = WSANO_RECOVERY;
8726 return SOCKET_ERROR;
8729 /***********************************************************************
8730 * WSCGetProviderPath (WS2_32.86)
8732 INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errcode )
8734 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errcode );
8736 if (!provider || !len)
8738 if (errcode)
8739 *errcode = WSAEFAULT;
8740 return SOCKET_ERROR;
8743 if (*len <= 0)
8745 if (errcode)
8746 *errcode = WSAEINVAL;
8747 return SOCKET_ERROR;
8750 return 0;
8753 /***********************************************************************
8754 * WSCInstallNameSpace (WS2_32.87)
8756 INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
8757 DWORD version, LPGUID provider )
8759 FIXME( "(%s %s 0x%08x 0x%08x %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
8760 namespace, version, debugstr_guid(provider) );
8761 return 0;
8764 /***********************************************************************
8765 * WSCUnInstallNameSpace (WS2_32.89)
8767 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
8769 FIXME("(%s) Stub!\n", debugstr_guid(lpProviderId));
8770 return NO_ERROR;
8773 /***********************************************************************
8774 * WSCWriteProviderOrder (WS2_32.91)
8776 INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
8778 FIXME("(%p 0x%08x) Stub!\n", entry, number);
8779 return 0;
8782 /***********************************************************************
8783 * WSCSetApplicationCategory (WS2_32.@)
8785 INT WINAPI WSCSetApplicationCategory( LPCWSTR path, DWORD len, LPCWSTR extra, DWORD extralen,
8786 DWORD lspcat, DWORD *prev_lspcat, LPINT err )
8788 FIXME("(%s %d %s %d %d %p) Stub!\n", debugstr_w(path), len, debugstr_w(extra),
8789 extralen, lspcat, prev_lspcat);
8790 return 0;
8793 /***********************************************************************
8794 * WSANSPIoctl (WS2_32.91)
8796 INT WINAPI WSANSPIoctl( HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer,
8797 DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
8798 LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion )
8800 FIXME("(%p, 0x%08x, %p, 0x%08x, %p, 0x%08x, %p, %p) Stub!\n", hLookup, dwControlCode,
8801 lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpCompletion);
8802 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8803 return SOCKET_ERROR;
8806 static BOOL protocol_matches_filter( const int *filter, int protocol )
8808 if (!filter) return TRUE;
8809 while (*filter)
8811 if (protocol == *filter++) return TRUE;
8813 return FALSE;
8816 /*****************************************************************************
8817 * WSAEnumProtocolsA [WS2_32.@]
8819 * see function WSAEnumProtocolsW
8821 int WINAPI WSAEnumProtocolsA( int *filter, WSAPROTOCOL_INFOA *protocols, DWORD *size )
8823 DWORD i, count = 0;
8825 TRACE("filter %p, protocols %p, size %p\n", filter, protocols, size);
8827 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
8829 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
8830 ++count;
8833 if (!protocols || *size < count * sizeof(WSAPROTOCOL_INFOA))
8835 *size = count * sizeof(WSAPROTOCOL_INFOA);
8836 WSASetLastError( WSAENOBUFS );
8837 return SOCKET_ERROR;
8840 count = 0;
8841 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
8843 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
8845 memcpy( &protocols[count], &supported_protocols[i], offsetof( WSAPROTOCOL_INFOW, szProtocol ) );
8846 WideCharToMultiByte( CP_ACP, 0, supported_protocols[i].szProtocol, -1,
8847 protocols[count].szProtocol, sizeof(protocols[count].szProtocol), NULL, NULL );
8848 ++count;
8851 return count;
8854 /*****************************************************************************
8855 * WSAEnumProtocolsW [WS2_32.@]
8857 * Retrieves information about specified set of active network protocols.
8859 * PARAMS
8860 * protocols [I] Pointer to null-terminated array of protocol id's. NULL
8861 * retrieves information on all available protocols.
8862 * buffer [I] Pointer to a buffer to be filled with WSAPROTOCOL_INFO
8863 * structures.
8864 * len [I/O] Pointer to a variable specifying buffer size. On output
8865 * the variable holds the number of bytes needed when the
8866 * specified size is too small.
8868 * RETURNS
8869 * Success: number of WSAPROTOCOL_INFO structures in buffer.
8870 * Failure: SOCKET_ERROR
8872 * NOTES
8873 * NT4SP5 does not return SPX if protocols == NULL
8875 * BUGS
8876 * - NT4SP5 returns in addition these list of NETBIOS protocols
8877 * (address family 17), each entry two times one for socket type 2 and 5
8879 * iProtocol szProtocol
8880 * 0x80000000 \Device\NwlnkNb
8881 * 0xfffffffa \Device\NetBT_CBENT7
8882 * 0xfffffffb \Device\Nbf_CBENT7
8883 * 0xfffffffc \Device\NetBT_NdisWan5
8884 * 0xfffffffd \Device\NetBT_El9202
8885 * 0xfffffffe \Device\Nbf_El9202
8886 * 0xffffffff \Device\Nbf_NdisWan4
8888 * - there is no check that the operating system supports the returned
8889 * protocols
8891 int WINAPI WSAEnumProtocolsW( int *filter, WSAPROTOCOL_INFOW *protocols, DWORD *size )
8893 DWORD i, count = 0;
8895 TRACE("filter %p, protocols %p, size %p\n", filter, protocols, size);
8897 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
8899 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
8900 ++count;
8903 if (!protocols || *size < count * sizeof(WSAPROTOCOL_INFOW))
8905 *size = count * sizeof(WSAPROTOCOL_INFOW);
8906 WSASetLastError( WSAENOBUFS );
8907 return SOCKET_ERROR;
8910 count = 0;
8911 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
8913 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
8914 protocols[count++] = supported_protocols[i];
8916 return count;
8919 /*****************************************************************************
8920 * WSCEnumProtocols [WS2_32.@]
8922 * PARAMS
8923 * protocols [I] Null-terminated array of iProtocol values.
8924 * buffer [O] Buffer of WSAPROTOCOL_INFOW structures.
8925 * len [I/O] Size of buffer on input/output.
8926 * errno [O] Error code.
8928 * RETURNS
8929 * Success: number of protocols to be reported on.
8930 * Failure: SOCKET_ERROR. error is in errno.
8932 * BUGS
8933 * Doesn't supply info on layered protocols.
8936 INT WINAPI WSCEnumProtocols( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len, LPINT err )
8938 INT ret = WSAEnumProtocolsW( protocols, buffer, len );
8940 if (ret == SOCKET_ERROR) *err = WSAENOBUFS;
8942 return ret;