widl: Always check the runtimeclass interfaces presence.
[wine/zf.git] / dlls / ws2_32 / socket.c
blob28b14e71c9c3715af4fca10003d155f284c0b2d0
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 struct if_nameindex *if_ni;
4498 DWORD status = 0;
4499 int fd;
4501 if (!out_buff || !ret_size)
4502 return WSAEFAULT;
4504 if ((fd = get_sock_fd(s, 0, NULL)) == -1)
4505 return SOCKET_ERROR;
4507 if ((ret = GetIpAddrTable(NULL, &size, TRUE)) != ERROR_INSUFFICIENT_BUFFER)
4509 if (ret != ERROR_NO_DATA)
4511 ERR("Unable to get ip address table.\n");
4512 status = WSAEINVAL;
4514 goto done;
4516 if (!(table = heap_alloc(size)))
4518 ERR("No memory.\n");
4519 status = WSAEINVAL;
4520 goto done;
4522 if (GetIpAddrTable(table, &size, TRUE) != NO_ERROR)
4524 ERR("Unable to get interface table.\n");
4525 status = WSAEINVAL;
4526 goto done;
4528 if (table->dwNumEntries * sizeof(INTERFACE_INFO) > out_size)
4530 WARN("Buffer too small, dwNumEntries %u, out_size = %u.\n", table->dwNumEntries, out_size);
4531 *ret_size = 0;
4532 status = WSAEFAULT;
4533 goto done;
4536 if (!(if_ni = if_nameindex()))
4538 ERR("Unable to get interface name index.\n");
4539 status = WSAEINVAL;
4540 goto done;
4543 for (; interface_count < table->dwNumEntries; ++interface_count, ++info)
4545 unsigned int addr, mask;
4546 struct ifreq if_info;
4547 unsigned int i;
4549 memset(info, 0, sizeof(*info));
4551 for (i = 0; if_ni[i].if_index || if_ni[i].if_name; ++i)
4552 if (if_ni[i].if_index == table->table[interface_count].dwIndex)
4553 break;
4555 if (!if_ni[i].if_name)
4557 ERR("Error obtaining interface name for ifindex %u.\n", table->table[interface_count].dwIndex);
4558 status = WSAEINVAL;
4559 break;
4562 lstrcpynA(if_info.ifr_name, if_ni[i].if_name, IFNAMSIZ);
4563 if (ioctl(fd, SIOCGIFFLAGS, &if_info) < 0)
4565 ERR("Error obtaining status flags for socket.\n");
4566 status = WSAEINVAL;
4567 break;
4570 if (if_info.ifr_flags & IFF_BROADCAST)
4571 info->iiFlags |= WS_IFF_BROADCAST;
4572 #ifdef IFF_POINTOPOINT
4573 if (if_info.ifr_flags & IFF_POINTOPOINT)
4574 info->iiFlags |= WS_IFF_POINTTOPOINT;
4575 #endif
4576 if (if_info.ifr_flags & IFF_LOOPBACK)
4577 info->iiFlags |= WS_IFF_LOOPBACK;
4578 if (if_info.ifr_flags & IFF_UP)
4579 info->iiFlags |= WS_IFF_UP;
4580 if (if_info.ifr_flags & IFF_MULTICAST)
4581 info->iiFlags |= WS_IFF_MULTICAST;
4583 addr = table->table[interface_count].dwAddr;
4584 mask = table->table[interface_count].dwMask;
4586 info->iiAddress.AddressIn.sin_family = WS_AF_INET;
4587 info->iiAddress.AddressIn.sin_port = 0;
4588 info->iiAddress.AddressIn.sin_addr.WS_s_addr = addr;
4590 info->iiNetmask.AddressIn.sin_family = WS_AF_INET;
4591 info->iiNetmask.AddressIn.sin_port = 0;
4592 info->iiNetmask.AddressIn.sin_addr.WS_s_addr = mask;
4594 if (if_info.ifr_flags & IFF_BROADCAST)
4596 info->iiBroadcastAddress.AddressIn.sin_family = WS_AF_INET;
4597 info->iiBroadcastAddress.AddressIn.sin_port = 0;
4598 info->iiBroadcastAddress.AddressIn.sin_addr.WS_s_addr = addr | ~mask;
4601 if_freenameindex(if_ni);
4602 done:
4603 heap_free(table);
4604 *total_bytes = sizeof(INTERFACE_INFO) * interface_count;
4605 release_sock_fd(s, fd);
4606 return status;
4609 /**********************************************************************
4610 * WSAIoctl (WS2_32.50)
4613 INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID out_buff,
4614 DWORD out_size, LPDWORD ret_size, LPWSAOVERLAPPED overlapped,
4615 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4617 int fd;
4618 DWORD status = 0, total = 0;
4620 TRACE("%04lx, %s, %p, %d, %p, %d, %p, %p, %p\n",
4621 s, debugstr_wsaioctl(code), in_buff, in_size, out_buff, out_size, ret_size, overlapped, completion);
4623 switch (code)
4625 case WS_FIONBIO:
4626 if (in_size != sizeof(WS_u_long) || IS_INTRESOURCE(in_buff))
4628 SetLastError(WSAEFAULT);
4629 return SOCKET_ERROR;
4631 TRACE("-> FIONBIO (%x)\n", *(WS_u_long*)in_buff);
4632 if (_get_sock_mask(s))
4634 /* AsyncSelect()'ed sockets are always nonblocking */
4635 if (!*(WS_u_long *)in_buff) status = WSAEINVAL;
4636 break;
4638 if (*(WS_u_long *)in_buff)
4639 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
4640 else
4641 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
4642 break;
4644 case WS_FIONREAD:
4646 #if defined(linux)
4647 int listening = 0;
4648 socklen_t len = sizeof(listening);
4649 #endif
4650 if (out_size != sizeof(WS_u_long) || IS_INTRESOURCE(out_buff))
4652 SetLastError(WSAEFAULT);
4653 return SOCKET_ERROR;
4655 if ((fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR;
4657 #if defined(linux)
4658 /* On Linux, FIONREAD on listening socket always fails (see tcp(7)).
4659 However, it succeeds on native. */
4660 if (!getsockopt( fd, SOL_SOCKET, SO_ACCEPTCONN, &listening, &len ) && listening)
4661 (*(WS_u_long *) out_buff) = 0;
4662 else
4663 #endif
4664 if (ioctl(fd, FIONREAD, out_buff ) == -1)
4665 status = wsaErrno();
4666 release_sock_fd( s, fd );
4667 break;
4670 case WS_SIOCATMARK:
4672 unsigned int oob = 0, atmark = 0;
4673 socklen_t oobsize = sizeof(int);
4674 if (out_size != sizeof(WS_u_long) || IS_INTRESOURCE(out_buff))
4676 SetLastError(WSAEFAULT);
4677 return SOCKET_ERROR;
4679 if ((fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR;
4680 /* SO_OOBINLINE sockets must always return TRUE to SIOCATMARK */
4681 if ((getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &oob, &oobsize ) == -1)
4682 || (!oob && ioctl(fd, SIOCATMARK, &atmark ) == -1))
4683 status = wsaErrno();
4684 else
4686 /* The SIOCATMARK value read from ioctl() is reversed
4687 * because BSD returns TRUE if it's in the OOB mark
4688 * while Windows returns TRUE if there are NO OOB bytes.
4690 (*(WS_u_long *) out_buff) = oob || !atmark;
4693 release_sock_fd( s, fd );
4694 break;
4697 case WS_FIOASYNC:
4698 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
4699 SetLastError(WSAEINVAL);
4700 return SOCKET_ERROR;
4702 case WS_SIO_GET_INTERFACE_LIST:
4704 TRACE("-> SIO_GET_INTERFACE_LIST request\n");
4706 status = get_interface_list(s, out_buff, out_size, ret_size, &total);
4707 break;
4710 case WS_SIO_ADDRESS_LIST_QUERY:
4712 DWORD size;
4714 TRACE("-> SIO_ADDRESS_LIST_QUERY request\n");
4716 if (!ret_size)
4718 SetLastError(WSAEFAULT);
4719 return SOCKET_ERROR;
4722 if (out_size && out_size < FIELD_OFFSET(SOCKET_ADDRESS_LIST, Address[0]))
4724 *ret_size = 0;
4725 SetLastError(WSAEINVAL);
4726 return SOCKET_ERROR;
4729 if (GetAdaptersInfo(NULL, &size) == ERROR_BUFFER_OVERFLOW)
4731 IP_ADAPTER_INFO *p, *table = HeapAlloc(GetProcessHeap(), 0, size);
4732 SOCKET_ADDRESS_LIST *sa_list;
4733 SOCKADDR_IN *sockaddr;
4734 SOCKET_ADDRESS *sa;
4735 unsigned int i;
4736 DWORD num;
4738 if (!table || GetAdaptersInfo(table, &size))
4740 HeapFree(GetProcessHeap(), 0, table);
4741 status = WSAEINVAL;
4742 break;
4745 for (p = table, num = 0; p; p = p->Next)
4746 if (p->IpAddressList.IpAddress.String[0]) num++;
4748 total = FIELD_OFFSET(SOCKET_ADDRESS_LIST, Address[num]) + num * sizeof(*sockaddr);
4749 if (total > out_size || !out_buff)
4751 *ret_size = total;
4752 HeapFree(GetProcessHeap(), 0, table);
4753 status = WSAEFAULT;
4754 break;
4757 sa_list = out_buff;
4758 sa = sa_list->Address;
4759 sockaddr = (SOCKADDR_IN *)&sa[num];
4760 sa_list->iAddressCount = num;
4762 for (p = table, i = 0; p; p = p->Next)
4764 if (!p->IpAddressList.IpAddress.String[0]) continue;
4766 sa[i].lpSockaddr = (SOCKADDR *)&sockaddr[i];
4767 sa[i].iSockaddrLength = sizeof(SOCKADDR);
4769 sockaddr[i].sin_family = WS_AF_INET;
4770 sockaddr[i].sin_port = 0;
4771 sockaddr[i].sin_addr.WS_s_addr = inet_addr(p->IpAddressList.IpAddress.String);
4772 i++;
4775 HeapFree(GetProcessHeap(), 0, table);
4777 else
4779 WARN("unable to get IP address list\n");
4780 status = WSAEINVAL;
4782 break;
4785 case WS_SIO_FLUSH:
4786 FIXME("SIO_FLUSH: stub.\n");
4787 break;
4789 case WS_SIO_GET_EXTENSION_FUNCTION_POINTER:
4791 #define EXTENSION_FUNCTION(x, y) { x, y, #y },
4792 static const struct
4794 GUID guid;
4795 void *func_ptr;
4796 const char *name;
4797 } guid_funcs[] = {
4798 EXTENSION_FUNCTION(WSAID_CONNECTEX, WS2_ConnectEx)
4799 EXTENSION_FUNCTION(WSAID_DISCONNECTEX, WS2_DisconnectEx)
4800 EXTENSION_FUNCTION(WSAID_ACCEPTEX, WS2_AcceptEx)
4801 EXTENSION_FUNCTION(WSAID_GETACCEPTEXSOCKADDRS, WS2_GetAcceptExSockaddrs)
4802 EXTENSION_FUNCTION(WSAID_TRANSMITFILE, WS2_TransmitFile)
4803 /* EXTENSION_FUNCTION(WSAID_TRANSMITPACKETS, WS2_TransmitPackets) */
4804 EXTENSION_FUNCTION(WSAID_WSARECVMSG, WS2_WSARecvMsg)
4805 EXTENSION_FUNCTION(WSAID_WSASENDMSG, WSASendMsg)
4807 #undef EXTENSION_FUNCTION
4808 BOOL found = FALSE;
4809 unsigned int i;
4811 for (i = 0; i < ARRAY_SIZE(guid_funcs); i++)
4813 if (IsEqualGUID(&guid_funcs[i].guid, in_buff))
4815 found = TRUE;
4816 break;
4820 if (found)
4822 TRACE("-> got %s\n", guid_funcs[i].name);
4823 *(void **)out_buff = guid_funcs[i].func_ptr;
4824 total = sizeof(void *);
4825 break;
4828 FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER %s: stub\n", debugstr_guid(in_buff));
4829 status = WSAEOPNOTSUPP;
4830 break;
4832 case WS_SIO_KEEPALIVE_VALS:
4834 struct tcp_keepalive *k;
4835 int keepalive, keepidle, keepintvl;
4837 if (!in_buff || in_size < sizeof(struct tcp_keepalive))
4839 SetLastError(WSAEFAULT);
4840 return SOCKET_ERROR;
4843 k = in_buff;
4844 keepalive = k->onoff ? 1 : 0;
4845 keepidle = max( 1, (k->keepalivetime + 500) / 1000 );
4846 keepintvl = max( 1, (k->keepaliveinterval + 500) / 1000 );
4848 TRACE("onoff: %d, keepalivetime: %d, keepaliveinterval: %d\n", keepalive, keepidle, keepintvl);
4850 fd = get_sock_fd(s, 0, NULL);
4851 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(int)) == -1)
4852 status = WSAEINVAL;
4853 #if defined(TCP_KEEPIDLE) || defined(TCP_KEEPINTVL)
4854 /* these values need to be set only if SO_KEEPALIVE is enabled */
4855 else if(keepalive)
4857 #ifndef TCP_KEEPIDLE
4858 FIXME("ignoring keepalive timeout\n");
4859 #else
4860 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, sizeof(int)) == -1)
4861 status = WSAEINVAL;
4862 else
4863 #endif
4864 #ifdef TCP_KEEPINTVL
4865 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof(int)) == -1)
4866 status = WSAEINVAL;
4867 #else
4868 FIXME("ignoring keepalive interval\n");
4869 #endif
4871 #else
4872 else
4873 FIXME("ignoring keepalive interval and timeout\n");
4874 #endif
4875 release_sock_fd(s, fd);
4876 break;
4878 case WS_SIO_ROUTING_INTERFACE_QUERY:
4880 struct WS_sockaddr *daddr = (struct WS_sockaddr *)in_buff;
4881 struct WS_sockaddr_in *daddr_in = (struct WS_sockaddr_in *)daddr;
4882 struct WS_sockaddr_in *saddr_in = out_buff;
4883 MIB_IPFORWARDROW row;
4884 PMIB_IPADDRTABLE ipAddrTable = NULL;
4885 DWORD size, i, found_index;
4887 TRACE("-> WS_SIO_ROUTING_INTERFACE_QUERY request\n");
4889 if (!in_buff || in_size < sizeof(struct WS_sockaddr) ||
4890 !out_buff || out_size < sizeof(struct WS_sockaddr_in) || !ret_size)
4892 SetLastError(WSAEFAULT);
4893 return SOCKET_ERROR;
4895 if (daddr->sa_family != WS_AF_INET)
4897 FIXME("unsupported address family %d\n", daddr->sa_family);
4898 status = WSAEAFNOSUPPORT;
4899 break;
4901 if (GetBestRoute(daddr_in->sin_addr.S_un.S_addr, 0, &row) != NOERROR ||
4902 GetIpAddrTable(NULL, &size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
4904 status = WSAEFAULT;
4905 break;
4907 ipAddrTable = HeapAlloc(GetProcessHeap(), 0, size);
4908 if (GetIpAddrTable(ipAddrTable, &size, FALSE))
4910 HeapFree(GetProcessHeap(), 0, ipAddrTable);
4911 status = WSAEFAULT;
4912 break;
4914 for (i = 0, found_index = ipAddrTable->dwNumEntries;
4915 i < ipAddrTable->dwNumEntries; i++)
4917 if (ipAddrTable->table[i].dwIndex == row.dwForwardIfIndex)
4918 found_index = i;
4920 if (found_index == ipAddrTable->dwNumEntries)
4922 ERR("no matching IP address for interface %d\n",
4923 row.dwForwardIfIndex);
4924 HeapFree(GetProcessHeap(), 0, ipAddrTable);
4925 status = WSAEFAULT;
4926 break;
4928 saddr_in->sin_family = WS_AF_INET;
4929 saddr_in->sin_addr.S_un.S_addr = ipAddrTable->table[found_index].dwAddr;
4930 saddr_in->sin_port = 0;
4931 total = sizeof(struct WS_sockaddr_in);
4932 HeapFree(GetProcessHeap(), 0, ipAddrTable);
4933 break;
4935 case WS_SIO_SET_COMPATIBILITY_MODE:
4936 TRACE("WS_SIO_SET_COMPATIBILITY_MODE ignored\n");
4937 status = WSAEOPNOTSUPP;
4938 break;
4939 case WS_SIO_UDP_CONNRESET:
4940 FIXME("WS_SIO_UDP_CONNRESET stub\n");
4941 break;
4942 case 0x667e: /* Netscape tries hard to use bogus ioctl 0x667e */
4943 SetLastError(WSAEOPNOTSUPP);
4944 return SOCKET_ERROR;
4945 case WS_SIO_ADDRESS_LIST_CHANGE:
4946 code = IOCTL_AFD_ADDRESS_LIST_CHANGE;
4947 status = WSAEOPNOTSUPP;
4948 break;
4949 default:
4950 status = WSAEOPNOTSUPP;
4951 break;
4954 if (status == WSAEOPNOTSUPP)
4956 status = server_ioctl_sock(s, code, in_buff, in_size, out_buff, out_size, &total,
4957 overlapped, completion);
4958 if (status != WSAEOPNOTSUPP)
4960 if (status == 0 || status == WSA_IO_PENDING || status == WSAEWOULDBLOCK)
4961 TRACE("-> %s request\n", debugstr_wsaioctl(code));
4962 else
4963 ERR("-> %s request failed with status 0x%x\n", debugstr_wsaioctl(code), status);
4965 /* overlapped and completion operations will be handled by the server */
4966 completion = NULL;
4967 overlapped = NULL;
4969 else
4970 FIXME("unsupported WS_IOCTL cmd (%s)\n", debugstr_wsaioctl(code));
4973 if (completion)
4975 FIXME( "completion routine %p not supported\n", completion );
4977 else if (overlapped)
4979 ULONG_PTR cvalue = (overlapped && ((ULONG_PTR)overlapped->hEvent & 1) == 0) ? (ULONG_PTR)overlapped : 0;
4980 overlapped->Internal = sock_error_to_ntstatus( status );
4981 overlapped->InternalHigh = total;
4982 if (cvalue) WS_AddCompletion( HANDLE2SOCKET(s), cvalue, overlapped->Internal, total, FALSE );
4983 if (overlapped->hEvent) NtSetEvent( overlapped->hEvent, NULL );
4986 if (!status)
4988 if (ret_size) *ret_size = total;
4989 return 0;
4991 SetLastError( status );
4992 return SOCKET_ERROR;
4996 /***********************************************************************
4997 * ioctlsocket (WS2_32.10)
4999 int WINAPI WS_ioctlsocket(SOCKET s, LONG cmd, WS_u_long *argp)
5001 DWORD ret_size;
5002 return WSAIoctl( s, cmd, argp, sizeof(WS_u_long), argp, sizeof(WS_u_long), &ret_size, NULL, NULL );
5005 /***********************************************************************
5006 * listen (WS2_32.13)
5008 int WINAPI WS_listen(SOCKET s, int backlog)
5010 int fd = get_sock_fd( s, FILE_READ_DATA, NULL ), ret = SOCKET_ERROR;
5012 TRACE("socket %04lx, backlog %d\n", s, backlog);
5013 if (fd != -1)
5015 int bound = is_fd_bound(fd, NULL, NULL);
5017 if (bound <= 0)
5019 SetLastError(bound == -1 ? wsaErrno() : WSAEINVAL);
5021 else if (listen(fd, backlog) == 0)
5023 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
5024 FD_WINE_LISTENING,
5025 FD_CONNECT|FD_WINE_CONNECTED);
5026 ret = 0;
5028 else
5029 SetLastError(wsaErrno());
5030 release_sock_fd( s, fd );
5033 return ret;
5036 /***********************************************************************
5037 * recv (WS2_32.16)
5039 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
5041 DWORD n, dwFlags = flags;
5042 WSABUF wsabuf;
5044 wsabuf.len = len;
5045 wsabuf.buf = buf;
5047 if ( WS2_recv_base(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
5048 return SOCKET_ERROR;
5049 else
5050 return n;
5053 /***********************************************************************
5054 * recvfrom (WS2_32.17)
5056 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
5057 struct WS_sockaddr *from, int *fromlen)
5059 DWORD n, dwFlags = flags;
5060 WSABUF wsabuf;
5062 wsabuf.len = len;
5063 wsabuf.buf = buf;
5065 if ( WS2_recv_base(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL, NULL) == SOCKET_ERROR )
5066 return SOCKET_ERROR;
5067 else
5068 return n;
5071 /* allocate a poll array for the corresponding fd sets */
5072 static struct pollfd *fd_sets_to_poll( const WS_fd_set *readfds, const WS_fd_set *writefds,
5073 const WS_fd_set *exceptfds, int *count_ptr )
5075 unsigned int i, j = 0, count = 0;
5076 struct pollfd *fds;
5077 struct per_thread_data *ptb = get_per_thread_data();
5079 if (readfds) count += readfds->fd_count;
5080 if (writefds) count += writefds->fd_count;
5081 if (exceptfds) count += exceptfds->fd_count;
5082 *count_ptr = count;
5083 if (!count)
5085 SetLastError(WSAEINVAL);
5086 return NULL;
5089 /* check if the cache can hold all descriptors, if not do the resizing */
5090 if (ptb->fd_count < count)
5092 if (!(fds = HeapAlloc(GetProcessHeap(), 0, count * sizeof(fds[0]))))
5094 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
5095 return NULL;
5097 HeapFree(GetProcessHeap(), 0, ptb->fd_cache);
5098 ptb->fd_cache = fds;
5099 ptb->fd_count = count;
5101 else
5102 fds = ptb->fd_cache;
5104 if (readfds)
5105 for (i = 0; i < readfds->fd_count; i++, j++)
5107 fds[j].fd = get_sock_fd( readfds->fd_array[i], FILE_READ_DATA, NULL );
5108 if (fds[j].fd == -1) goto failed;
5109 fds[j].revents = 0;
5110 if (is_fd_bound(fds[j].fd, NULL, NULL) == 1)
5112 fds[j].events = POLLIN;
5114 else
5116 release_sock_fd( readfds->fd_array[i], fds[j].fd );
5117 fds[j].fd = -1;
5118 fds[j].events = 0;
5121 if (writefds)
5122 for (i = 0; i < writefds->fd_count; i++, j++)
5124 fds[j].fd = get_sock_fd( writefds->fd_array[i], FILE_WRITE_DATA, NULL );
5125 if (fds[j].fd == -1) goto failed;
5126 fds[j].revents = 0;
5127 if (is_fd_bound(fds[j].fd, NULL, NULL) == 1 ||
5128 _get_fd_type(fds[j].fd) == SOCK_DGRAM)
5130 fds[j].events = POLLOUT;
5132 else
5134 release_sock_fd( writefds->fd_array[i], fds[j].fd );
5135 fds[j].fd = -1;
5136 fds[j].events = 0;
5139 if (exceptfds)
5140 for (i = 0; i < exceptfds->fd_count; i++, j++)
5142 fds[j].fd = get_sock_fd( exceptfds->fd_array[i], 0, NULL );
5143 if (fds[j].fd == -1) goto failed;
5144 fds[j].revents = 0;
5145 if (is_fd_bound(fds[j].fd, NULL, NULL) == 1)
5147 int oob_inlined = 0;
5148 socklen_t olen = sizeof(oob_inlined);
5150 fds[j].events = POLLHUP;
5152 /* Check if we need to test for urgent data or not */
5153 getsockopt(fds[j].fd, SOL_SOCKET, SO_OOBINLINE, (char*) &oob_inlined, &olen);
5154 if (!oob_inlined)
5155 fds[j].events |= POLLPRI;
5157 else
5159 release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
5160 fds[j].fd = -1;
5161 fds[j].events = 0;
5164 return fds;
5166 failed:
5167 count = j;
5168 j = 0;
5169 if (readfds)
5170 for (i = 0; i < readfds->fd_count && j < count; i++, j++)
5171 if (fds[j].fd != -1) release_sock_fd( readfds->fd_array[i], fds[j].fd );
5172 if (writefds)
5173 for (i = 0; i < writefds->fd_count && j < count; i++, j++)
5174 if (fds[j].fd != -1) release_sock_fd( writefds->fd_array[i], fds[j].fd );
5175 if (exceptfds)
5176 for (i = 0; i < exceptfds->fd_count && j < count; i++, j++)
5177 if (fds[j].fd != -1) release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
5178 return NULL;
5181 /* release the file descriptor obtained in fd_sets_to_poll */
5182 /* must be called with the original fd_set arrays, before calling get_poll_results */
5183 static void release_poll_fds( const WS_fd_set *readfds, const WS_fd_set *writefds,
5184 const WS_fd_set *exceptfds, struct pollfd *fds )
5186 unsigned int i, j = 0;
5188 if (readfds)
5190 for (i = 0; i < readfds->fd_count; i++, j++)
5191 if (fds[j].fd != -1) release_sock_fd( readfds->fd_array[i], fds[j].fd );
5193 if (writefds)
5195 for (i = 0; i < writefds->fd_count; i++, j++)
5196 if (fds[j].fd != -1) release_sock_fd( writefds->fd_array[i], fds[j].fd );
5198 if (exceptfds)
5200 for (i = 0; i < exceptfds->fd_count; i++, j++)
5202 if (fds[j].fd == -1) continue;
5203 release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
5204 if (fds[j].revents & POLLHUP)
5206 int fd = get_sock_fd( exceptfds->fd_array[i], 0, NULL );
5207 if (fd != -1)
5208 release_sock_fd( exceptfds->fd_array[i], fd );
5209 else
5210 fds[j].revents = 0;
5216 static int do_poll(struct pollfd *pollfds, int count, int timeout)
5218 struct timeval tv1, tv2;
5219 int ret, torig = timeout;
5221 if (timeout > 0) gettimeofday( &tv1, 0 );
5223 while ((ret = poll( pollfds, count, timeout )) < 0)
5225 if (errno != EINTR) break;
5226 if (timeout < 0) continue;
5227 if (timeout == 0) return 0;
5229 gettimeofday( &tv2, 0 );
5231 tv2.tv_sec -= tv1.tv_sec;
5232 tv2.tv_usec -= tv1.tv_usec;
5233 if (tv2.tv_usec < 0)
5235 tv2.tv_usec += 1000000;
5236 tv2.tv_sec -= 1;
5239 timeout = torig - (tv2.tv_sec * 1000) - (tv2.tv_usec + 999) / 1000;
5240 if (timeout <= 0) return 0;
5242 return ret;
5245 /* map the poll results back into the Windows fd sets */
5246 static int get_poll_results( WS_fd_set *readfds, WS_fd_set *writefds, WS_fd_set *exceptfds,
5247 const struct pollfd *fds )
5249 const struct pollfd *poll_writefds = fds + (readfds ? readfds->fd_count : 0);
5250 const struct pollfd *poll_exceptfds = poll_writefds + (writefds ? writefds->fd_count : 0);
5251 unsigned int i, k, total = 0;
5253 if (readfds)
5255 for (i = k = 0; i < readfds->fd_count; i++)
5257 if (fds[i].revents ||
5258 (readfds == writefds && (poll_writefds[i].revents & POLLOUT) && !(poll_writefds[i].revents & POLLHUP)) ||
5259 (readfds == exceptfds && poll_exceptfds[i].revents))
5260 readfds->fd_array[k++] = readfds->fd_array[i];
5262 readfds->fd_count = k;
5263 total += k;
5265 if (writefds && writefds != readfds)
5267 for (i = k = 0; i < writefds->fd_count; i++)
5269 if (((poll_writefds[i].revents & POLLOUT) && !(poll_writefds[i].revents & POLLHUP)) ||
5270 (writefds == exceptfds && poll_exceptfds[i].revents))
5271 writefds->fd_array[k++] = writefds->fd_array[i];
5273 writefds->fd_count = k;
5274 total += k;
5276 if (exceptfds && exceptfds != readfds && exceptfds != writefds)
5278 for (i = k = 0; i < exceptfds->fd_count; i++)
5279 if (poll_exceptfds[i].revents) exceptfds->fd_array[k++] = exceptfds->fd_array[i];
5280 exceptfds->fd_count = k;
5281 total += k;
5283 return total;
5286 /***********************************************************************
5287 * select (WS2_32.18)
5289 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
5290 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
5291 const struct WS_timeval* ws_timeout)
5293 struct pollfd *pollfds;
5294 int count, ret, timeout = -1;
5296 TRACE("read %p, write %p, excp %p timeout %p\n",
5297 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
5299 if (!(pollfds = fd_sets_to_poll( ws_readfds, ws_writefds, ws_exceptfds, &count )))
5300 return SOCKET_ERROR;
5302 if (ws_timeout)
5303 timeout = (ws_timeout->tv_sec * 1000) + (ws_timeout->tv_usec + 999) / 1000;
5305 ret = do_poll(pollfds, count, timeout);
5306 release_poll_fds( ws_readfds, ws_writefds, ws_exceptfds, pollfds );
5308 if (ret == -1) SetLastError(wsaErrno());
5309 else ret = get_poll_results( ws_readfds, ws_writefds, ws_exceptfds, pollfds );
5310 return ret;
5313 /***********************************************************************
5314 * WSAPoll
5316 int WINAPI WSAPoll(WSAPOLLFD *wfds, ULONG count, int timeout)
5318 int i, ret;
5319 struct pollfd *ufds;
5321 if (!count)
5323 SetLastError(WSAEINVAL);
5324 return SOCKET_ERROR;
5326 if (!wfds)
5328 SetLastError(WSAEFAULT);
5329 return SOCKET_ERROR;
5332 if (!(ufds = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ufds[0]))))
5334 SetLastError(WSAENOBUFS);
5335 return SOCKET_ERROR;
5338 for (i = 0; i < count; i++)
5340 ufds[i].fd = get_sock_fd(wfds[i].fd, 0, NULL);
5341 ufds[i].events = convert_poll_w2u(wfds[i].events);
5342 ufds[i].revents = 0;
5345 ret = do_poll(ufds, count, timeout);
5347 for (i = 0; i < count; i++)
5349 if (ufds[i].fd != -1)
5351 release_sock_fd(wfds[i].fd, ufds[i].fd);
5352 if (ufds[i].revents & POLLHUP)
5354 /* Check if the socket still exists */
5355 int fd = get_sock_fd(wfds[i].fd, 0, NULL);
5356 if (fd != -1)
5358 wfds[i].revents = WS_POLLHUP;
5359 release_sock_fd(wfds[i].fd, fd);
5361 else
5362 wfds[i].revents = WS_POLLNVAL;
5364 else
5365 wfds[i].revents = convert_poll_u2w(ufds[i].revents);
5367 else
5368 wfds[i].revents = WS_POLLNVAL;
5371 HeapFree(GetProcessHeap(), 0, ufds);
5372 return ret;
5375 /* helper to send completion messages for client-only i/o operation case */
5376 static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus,
5377 ULONG Information, BOOL async )
5379 SERVER_START_REQ( add_fd_completion )
5381 req->handle = wine_server_obj_handle( SOCKET2HANDLE(sock) );
5382 req->cvalue = CompletionValue;
5383 req->status = CompletionStatus;
5384 req->information = Information;
5385 req->async = async;
5386 wine_server_call( req );
5388 SERVER_END_REQ;
5392 /***********************************************************************
5393 * send (WS2_32.19)
5395 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
5397 DWORD n;
5398 WSABUF wsabuf;
5400 wsabuf.len = len;
5401 wsabuf.buf = (char*) buf;
5403 if ( WS2_sendto( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
5404 return SOCKET_ERROR;
5405 else
5406 return n;
5409 /***********************************************************************
5410 * WSASend (WS2_32.72)
5412 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
5413 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
5414 LPWSAOVERLAPPED lpOverlapped,
5415 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
5417 return WS2_sendto( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
5418 NULL, 0, lpOverlapped, lpCompletionRoutine );
5421 /***********************************************************************
5422 * WSASendDisconnect (WS2_32.73)
5424 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
5426 return WS_shutdown( s, SD_SEND );
5430 static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
5431 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
5432 const struct WS_sockaddr *to, int tolen,
5433 LPWSAOVERLAPPED lpOverlapped,
5434 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
5436 unsigned int i, options;
5437 int n, fd, err, overlapped, flags;
5438 struct ws2_async *wsa = NULL, localwsa;
5439 int totalLength = 0;
5440 DWORD bytes_sent;
5441 BOOL is_blocking;
5443 TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, to %p, tolen %d, ovl %p, func %p\n",
5444 s, lpBuffers, dwBufferCount, dwFlags,
5445 to, tolen, lpOverlapped, lpCompletionRoutine);
5447 fd = get_sock_fd( s, FILE_WRITE_DATA, &options );
5448 TRACE( "fd=%d, options=%x\n", fd, options );
5450 if ( fd == -1 ) return SOCKET_ERROR;
5452 if (!lpOverlapped && !lpNumberOfBytesSent)
5454 err = WSAEFAULT;
5455 goto error;
5458 overlapped = (lpOverlapped || lpCompletionRoutine) &&
5459 !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
5460 if (overlapped || dwBufferCount > 1)
5462 if (!(wsa = (struct ws2_async *)alloc_async_io( offsetof(struct ws2_async, iovec[dwBufferCount]),
5463 WS2_async_send )))
5465 err = WSAEFAULT;
5466 goto error;
5469 else
5470 wsa = &localwsa;
5472 wsa->hSocket = SOCKET2HANDLE(s);
5473 wsa->addr = (struct WS_sockaddr *)to;
5474 wsa->addrlen.val = tolen;
5475 wsa->flags = dwFlags;
5476 wsa->lpFlags = &wsa->flags;
5477 wsa->control = NULL;
5478 wsa->n_iovecs = dwBufferCount;
5479 wsa->first_iovec = 0;
5480 for ( i = 0; i < dwBufferCount; i++ )
5482 wsa->iovec[i].iov_base = lpBuffers[i].buf;
5483 wsa->iovec[i].iov_len = lpBuffers[i].len;
5484 totalLength += lpBuffers[i].len;
5487 flags = convert_flags(dwFlags);
5488 n = WS2_send( fd, wsa, flags );
5489 if (n == -1 && errno != EAGAIN)
5491 err = wsaErrno();
5492 goto error;
5495 if (overlapped)
5497 IO_STATUS_BLOCK *iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
5498 ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
5500 wsa->user_overlapped = lpOverlapped;
5501 wsa->completion_func = lpCompletionRoutine;
5502 release_sock_fd( s, fd );
5504 if (n == -1 || n < totalLength)
5506 iosb->u.Status = STATUS_PENDING;
5507 iosb->Information = n == -1 ? 0 : n;
5509 if (wsa->completion_func)
5510 err = register_async( ASYNC_TYPE_WRITE, wsa->hSocket, &wsa->io, NULL,
5511 ws2_async_apc, wsa, iosb );
5512 else
5513 err = register_async( ASYNC_TYPE_WRITE, wsa->hSocket, &wsa->io, lpOverlapped->hEvent,
5514 NULL, (void *)cvalue, iosb );
5516 /* Enable the event only after starting the async. The server will deliver it as soon as
5517 the async is done. */
5518 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
5520 if (err != STATUS_PENDING) HeapFree( GetProcessHeap(), 0, wsa );
5521 SetLastError(NtStatusToWSAError( err ));
5522 return SOCKET_ERROR;
5525 iosb->u.Status = STATUS_SUCCESS;
5526 iosb->Information = n;
5527 if (lpNumberOfBytesSent) *lpNumberOfBytesSent = n;
5528 if (!wsa->completion_func)
5530 if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n, FALSE );
5531 if (lpOverlapped->hEvent) SetEvent( lpOverlapped->hEvent );
5532 HeapFree( GetProcessHeap(), 0, wsa );
5534 else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc,
5535 (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 );
5536 SetLastError(ERROR_SUCCESS);
5537 return 0;
5540 if ((err = sock_is_blocking( s, &is_blocking ))) goto error;
5542 if ( is_blocking )
5544 /* On a blocking non-overlapped stream socket,
5545 * sending blocks until the entire buffer is sent. */
5546 DWORD timeout_start = GetTickCount();
5548 bytes_sent = n == -1 ? 0 : n;
5550 while (wsa->first_iovec < wsa->n_iovecs)
5552 struct pollfd pfd;
5553 int poll_timeout = -1;
5554 INT64 timeout = get_rcvsnd_timeo(fd, FALSE);
5556 if (timeout)
5558 timeout -= GetTickCount() - timeout_start;
5559 if (timeout < 0) poll_timeout = 0;
5560 else poll_timeout = timeout <= INT_MAX ? timeout : INT_MAX;
5563 pfd.fd = fd;
5564 pfd.events = POLLOUT;
5566 if (!poll_timeout || !poll( &pfd, 1, poll_timeout ))
5568 err = WSAETIMEDOUT;
5569 goto error; /* msdn says a timeout in send is fatal */
5572 n = WS2_send( fd, wsa, flags );
5573 if (n == -1 && errno != EAGAIN)
5575 err = wsaErrno();
5576 goto error;
5579 if (n >= 0)
5580 bytes_sent += n;
5583 else /* non-blocking */
5585 if (n < totalLength)
5586 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
5587 if (n == -1)
5589 err = WSAEWOULDBLOCK;
5590 goto error;
5592 bytes_sent = n;
5595 TRACE(" -> %i bytes\n", bytes_sent);
5597 if (lpNumberOfBytesSent) *lpNumberOfBytesSent = bytes_sent;
5598 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
5599 release_sock_fd( s, fd );
5600 SetLastError(ERROR_SUCCESS);
5601 return 0;
5603 error:
5604 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
5605 release_sock_fd( s, fd );
5606 WARN(" -> ERROR %d\n", err);
5607 SetLastError(err);
5608 return SOCKET_ERROR;
5611 /***********************************************************************
5612 * WSASendTo (WS2_32.74)
5614 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
5615 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
5616 const struct WS_sockaddr *to, int tolen,
5617 LPWSAOVERLAPPED lpOverlapped,
5618 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
5620 return WS2_sendto( s, lpBuffers, dwBufferCount,
5621 lpNumberOfBytesSent, dwFlags,
5622 to, tolen,
5623 lpOverlapped, lpCompletionRoutine );
5626 /***********************************************************************
5627 * sendto (WS2_32.20)
5629 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
5630 const struct WS_sockaddr *to, int tolen)
5632 DWORD n;
5633 WSABUF wsabuf;
5635 wsabuf.len = len;
5636 wsabuf.buf = (char*) buf;
5638 if ( WS2_sendto(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
5639 return SOCKET_ERROR;
5640 else
5641 return n;
5644 /***********************************************************************
5645 * setsockopt (WS2_32.21)
5647 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
5648 const char *optval, int optlen)
5650 int fd;
5651 int woptval;
5652 struct linger linger;
5653 struct timeval tval;
5654 struct ip_mreq_source mreq_source;
5656 TRACE("(socket %04lx, %s, optval %s, optlen %d)\n", s,
5657 debugstr_sockopt(level, optname), debugstr_optval(optval, optlen),
5658 optlen);
5660 /* some broken apps pass the value directly instead of a pointer to it */
5661 if(optlen && IS_INTRESOURCE(optval))
5663 SetLastError(WSAEFAULT);
5664 return SOCKET_ERROR;
5667 switch(level)
5669 case WS_SOL_SOCKET:
5670 switch(optname)
5672 /* Some options need some conversion before they can be sent to
5673 * setsockopt. The conversions are done here, then they will fall through
5674 * to the general case. Special options that are not passed to
5675 * setsockopt follow below that.*/
5677 case WS_SO_DONTLINGER:
5678 if (!optval)
5680 SetLastError(WSAEFAULT);
5681 return SOCKET_ERROR;
5683 linger.l_onoff = *(const int*)optval == 0;
5684 linger.l_linger = 0;
5685 level = SOL_SOCKET;
5686 optname = SO_LINGER;
5687 optval = (char*)&linger;
5688 optlen = sizeof(struct linger);
5689 break;
5691 case WS_SO_LINGER:
5692 if (!optval)
5694 SetLastError(WSAEFAULT);
5695 return SOCKET_ERROR;
5697 linger.l_onoff = ((LINGER*)optval)->l_onoff;
5698 linger.l_linger = ((LINGER*)optval)->l_linger;
5699 level = SOL_SOCKET;
5700 optname = SO_LINGER;
5701 optval = (char*)&linger;
5702 optlen = sizeof(struct linger);
5703 break;
5705 case WS_SO_SNDBUF:
5706 if (!*(const int *)optval)
5708 FIXME("SO_SNDBUF ignoring request to disable send buffering\n");
5709 #ifdef __APPLE__
5710 return 0;
5711 #endif
5713 convert_sockopt(&level, &optname);
5714 break;
5716 case WS_SO_RCVBUF:
5717 if (*(const int*)optval < 2048)
5719 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(const int*)optval );
5720 return 0;
5722 /* Fall through */
5724 /* The options listed here don't need any special handling. Thanks to
5725 * the conversion happening above, options from there will fall through
5726 * to this, too.*/
5727 case WS_SO_ACCEPTCONN:
5728 case WS_SO_BROADCAST:
5729 case WS_SO_ERROR:
5730 case WS_SO_KEEPALIVE:
5731 case WS_SO_OOBINLINE:
5732 /* BSD socket SO_REUSEADDR is not 100% compatible to winsock semantics.
5733 * however, using it the BSD way fixes bug 8513 and seems to be what
5734 * most programmers assume, anyway */
5735 case WS_SO_REUSEADDR:
5736 case WS_SO_TYPE:
5737 convert_sockopt(&level, &optname);
5738 break;
5740 /* SO_DEBUG is a privileged operation, ignore it. */
5741 case WS_SO_DEBUG:
5742 TRACE("Ignoring SO_DEBUG\n");
5743 return 0;
5745 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
5746 * socket. According to MSDN, this option is silently ignored.*/
5747 case WS_SO_DONTROUTE:
5748 TRACE("Ignoring SO_DONTROUTE\n");
5749 return 0;
5751 /* Stops two sockets from being bound to the same port. Always happens
5752 * on unix systems, so just drop it. */
5753 case WS_SO_EXCLUSIVEADDRUSE:
5754 TRACE("Ignoring SO_EXCLUSIVEADDRUSE, is always set.\n");
5755 return 0;
5757 /* After a ConnectEx call succeeds, the socket can't be used with half of the
5758 * normal winsock functions on windows. We don't have that problem. */
5759 case WS_SO_UPDATE_CONNECT_CONTEXT:
5760 TRACE("Ignoring SO_UPDATE_CONNECT_CONTEXT, since our sockets are normal\n");
5761 return 0;
5763 /* After a AcceptEx call succeeds, the socket can't be used with half of the
5764 * normal winsock functions on windows. We don't have that problem. */
5765 case WS_SO_UPDATE_ACCEPT_CONTEXT:
5766 TRACE("Ignoring SO_UPDATE_ACCEPT_CONTEXT, since our sockets are normal\n");
5767 return 0;
5769 /* SO_OPENTYPE does not require a valid socket handle. */
5770 case WS_SO_OPENTYPE:
5771 if (!optlen || optlen < sizeof(int) || !optval)
5773 SetLastError(WSAEFAULT);
5774 return SOCKET_ERROR;
5776 get_per_thread_data()->opentype = *(const int *)optval;
5777 TRACE("setting global SO_OPENTYPE = 0x%x\n", *((const int*)optval) );
5778 return 0;
5780 #ifdef SO_RCVTIMEO
5781 case WS_SO_RCVTIMEO:
5782 #endif
5783 #ifdef SO_SNDTIMEO
5784 case WS_SO_SNDTIMEO:
5785 #endif
5786 #if defined(SO_RCVTIMEO) || defined(SO_SNDTIMEO)
5787 if (optval && optlen == sizeof(UINT32)) {
5788 /* WinSock passes milliseconds instead of struct timeval */
5789 tval.tv_usec = (*(const UINT32*)optval % 1000) * 1000;
5790 tval.tv_sec = *(const UINT32*)optval / 1000;
5791 /* min of 500 milliseconds */
5792 if (tval.tv_sec == 0 && tval.tv_usec && tval.tv_usec < 500000)
5793 tval.tv_usec = 500000;
5794 optlen = sizeof(struct timeval);
5795 optval = (char*)&tval;
5796 } else if (optlen == sizeof(struct timeval)) {
5797 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
5798 } else {
5799 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
5800 return 0;
5802 convert_sockopt(&level, &optname);
5803 break;
5804 #endif
5806 case WS_SO_RANDOMIZE_PORT:
5807 FIXME("Ignoring WS_SO_RANDOMIZE_PORT\n");
5808 return 0;
5810 case WS_SO_PORT_SCALABILITY:
5811 FIXME("Ignoring WS_SO_PORT_SCALABILITY\n");
5812 return 0;
5814 case WS_SO_REUSE_UNICASTPORT:
5815 FIXME("Ignoring WS_SO_REUSE_UNICASTPORT\n");
5816 return 0;
5818 case WS_SO_REUSE_MULTICASTPORT:
5819 FIXME("Ignoring WS_SO_REUSE_MULTICASTPORT\n");
5820 return 0;
5822 default:
5823 TRACE("Unknown SOL_SOCKET optname: 0x%08x\n", optname);
5824 SetLastError(WSAENOPROTOOPT);
5825 return SOCKET_ERROR;
5827 break; /* case WS_SOL_SOCKET */
5829 #ifdef HAS_IPX
5830 case WS_NSPROTO_IPX:
5831 switch(optname)
5833 case WS_IPX_PTYPE:
5834 return set_ipx_packettype(s, *(int*)optval);
5836 case WS_IPX_FILTERPTYPE:
5837 /* Sets the receive filter packet type, at the moment we don't support it */
5838 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
5839 /* Returning 0 is better for now than returning a SOCKET_ERROR */
5840 return 0;
5842 default:
5843 FIXME("opt_name:%x\n", optname);
5844 return SOCKET_ERROR;
5846 break; /* case WS_NSPROTO_IPX */
5847 #endif
5849 /* Levels WS_IPPROTO_TCP and WS_IPPROTO_IP convert directly */
5850 case WS_IPPROTO_TCP:
5851 switch(optname)
5853 case WS_TCP_NODELAY:
5854 convert_sockopt(&level, &optname);
5855 break;
5856 default:
5857 FIXME("Unknown IPPROTO_TCP optname 0x%08x\n", optname);
5858 return SOCKET_ERROR;
5860 break;
5862 case WS_IPPROTO_IP:
5863 switch(optname)
5865 case WS_IP_ADD_SOURCE_MEMBERSHIP:
5866 case WS_IP_DROP_SOURCE_MEMBERSHIP:
5867 case WS_IP_BLOCK_SOURCE:
5868 case WS_IP_UNBLOCK_SOURCE:
5870 WS_IP_MREQ_SOURCE* val = (void*)optval;
5871 mreq_source.imr_interface.s_addr = val->imr_interface.S_un.S_addr;
5872 mreq_source.imr_multiaddr.s_addr = val->imr_multiaddr.S_un.S_addr;
5873 mreq_source.imr_sourceaddr.s_addr = val->imr_sourceaddr.S_un.S_addr;
5875 optval = (char*)&mreq_source;
5876 optlen = sizeof(mreq_source);
5878 convert_sockopt(&level, &optname);
5879 break;
5881 case WS_IP_ADD_MEMBERSHIP:
5882 case WS_IP_DROP_MEMBERSHIP:
5883 #ifdef IP_HDRINCL
5884 case WS_IP_HDRINCL:
5885 #endif
5886 case WS_IP_MULTICAST_IF:
5887 case WS_IP_MULTICAST_LOOP:
5888 case WS_IP_MULTICAST_TTL:
5889 case WS_IP_OPTIONS:
5890 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
5891 case WS_IP_PKTINFO:
5892 #endif
5893 case WS_IP_TOS:
5894 case WS_IP_TTL:
5895 #ifdef IP_UNICAST_IF
5896 case WS_IP_UNICAST_IF:
5897 #endif
5898 convert_sockopt(&level, &optname);
5899 break;
5900 case WS_IP_DONTFRAGMENT:
5901 return set_dont_fragment(s, IPPROTO_IP, *(BOOL *)optval) ? 0 : SOCKET_ERROR;
5902 default:
5903 FIXME("Unknown IPPROTO_IP optname 0x%08x\n", optname);
5904 return SOCKET_ERROR;
5906 break;
5908 case WS_IPPROTO_IPV6:
5909 switch(optname)
5911 #ifdef IPV6_ADD_MEMBERSHIP
5912 case WS_IPV6_ADD_MEMBERSHIP:
5913 #endif
5914 #ifdef IPV6_DROP_MEMBERSHIP
5915 case WS_IPV6_DROP_MEMBERSHIP:
5916 #endif
5917 case WS_IPV6_MULTICAST_IF:
5918 case WS_IPV6_MULTICAST_HOPS:
5919 case WS_IPV6_MULTICAST_LOOP:
5920 case WS_IPV6_UNICAST_HOPS:
5921 #ifdef IPV6_UNICAST_IF
5922 case WS_IPV6_UNICAST_IF:
5923 #endif
5924 convert_sockopt(&level, &optname);
5925 break;
5926 case WS_IPV6_DONTFRAG:
5927 return set_dont_fragment(s, IPPROTO_IPV6, *(BOOL *)optval) ? 0 : SOCKET_ERROR;
5928 case WS_IPV6_PROTECTION_LEVEL:
5929 FIXME("IPV6_PROTECTION_LEVEL is ignored!\n");
5930 return 0;
5931 case WS_IPV6_V6ONLY:
5933 union generic_unix_sockaddr uaddr;
5934 socklen_t uaddrlen;
5935 int bound;
5937 fd = get_sock_fd( s, 0, NULL );
5938 if (fd == -1) return SOCKET_ERROR;
5940 bound = is_fd_bound(fd, &uaddr, &uaddrlen);
5941 release_sock_fd( s, fd );
5942 if (bound == 0 && uaddr.addr.sa_family == AF_INET)
5944 /* Changing IPV6_V6ONLY succeeds on AF_INET (IPv4) socket
5945 * on Windows (with IPv6 support) if the socket is unbound.
5946 * It is essentially a noop, though Windows does store the value
5948 WARN("Silently ignoring IPPROTO_IPV6+IPV6_V6ONLY on AF_INET socket\n");
5949 return 0;
5951 level = IPPROTO_IPV6;
5952 optname = IPV6_V6ONLY;
5953 break;
5955 default:
5956 FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname);
5957 return SOCKET_ERROR;
5959 break;
5961 default:
5962 WARN("Unknown level: 0x%08x\n", level);
5963 SetLastError(WSAEINVAL);
5964 return SOCKET_ERROR;
5965 } /* end switch(level) */
5967 /* avoid endianness issues if argument is a 16-bit int */
5968 if (optval && optlen < sizeof(int))
5970 woptval= *((const INT16 *) optval);
5971 optval= (char*) &woptval;
5972 woptval&= (1 << optlen * 8) - 1;
5973 optlen=sizeof(int);
5975 fd = get_sock_fd( s, 0, NULL );
5976 if (fd == -1) return SOCKET_ERROR;
5978 if (setsockopt(fd, level, optname, optval, optlen) == 0)
5980 #ifdef __APPLE__
5981 if (level == SOL_SOCKET && optname == SO_REUSEADDR &&
5982 setsockopt(fd, level, SO_REUSEPORT, optval, optlen) != 0)
5984 SetLastError(wsaErrno());
5985 release_sock_fd( s, fd );
5986 return SOCKET_ERROR;
5988 #endif
5989 release_sock_fd( s, fd );
5990 return 0;
5992 TRACE("Setting socket error, %d\n", wsaErrno());
5993 SetLastError(wsaErrno());
5994 release_sock_fd( s, fd );
5996 return SOCKET_ERROR;
5999 /***********************************************************************
6000 * shutdown (WS2_32.22)
6002 int WINAPI WS_shutdown(SOCKET s, int how)
6004 int fd, err = WSAENOTSOCK;
6005 unsigned int options = 0, clear_flags = 0;
6007 fd = get_sock_fd( s, 0, &options );
6008 TRACE("socket %04lx, how 0x%x, options 0x%x\n", s, how, options );
6010 if (fd == -1)
6011 return SOCKET_ERROR;
6013 switch( how )
6015 case SD_RECEIVE: /* drop receives */
6016 clear_flags |= FD_READ;
6017 break;
6018 case SD_SEND: /* drop sends */
6019 clear_flags |= FD_WRITE;
6020 break;
6021 case SD_BOTH: /* drop all */
6022 clear_flags |= FD_READ|FD_WRITE;
6023 /*fall through */
6024 default:
6025 clear_flags |= FD_WINE_LISTENING;
6028 if (!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
6030 switch ( how )
6032 case SD_RECEIVE:
6033 err = WS2_register_async_shutdown( s, ASYNC_TYPE_READ );
6034 break;
6035 case SD_SEND:
6036 err = WS2_register_async_shutdown( s, ASYNC_TYPE_WRITE );
6037 break;
6038 case SD_BOTH:
6039 default:
6040 err = WS2_register_async_shutdown( s, ASYNC_TYPE_READ );
6041 if (!err) err = WS2_register_async_shutdown( s, ASYNC_TYPE_WRITE );
6042 break;
6044 if (err) goto error;
6046 else /* non-overlapped mode */
6048 if ( shutdown( fd, how ) )
6050 err = wsaErrno();
6051 goto error;
6055 release_sock_fd( s, fd );
6056 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
6057 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
6058 return 0;
6060 error:
6061 release_sock_fd( s, fd );
6062 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
6063 SetLastError( err );
6064 return SOCKET_ERROR;
6067 /***********************************************************************
6068 * socket (WS2_32.23)
6070 SOCKET WINAPI WS_socket(int af, int type, int protocol)
6072 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
6074 return WSASocketW( af, type, protocol, NULL, 0,
6075 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
6079 /***********************************************************************
6080 * gethostbyaddr (WS2_32.51)
6082 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
6084 struct WS_hostent *retval = NULL;
6085 struct hostent* host;
6086 int unixtype = convert_af_w2u(type);
6087 const char *paddr = addr;
6088 unsigned long loopback;
6089 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
6090 char *extrabuf;
6091 int ebufsize = 1024;
6092 struct hostent hostentry;
6093 int locerr = ENOBUFS;
6094 #endif
6096 /* convert back the magic loopback address if necessary */
6097 if (unixtype == AF_INET && len == 4 && !memcmp(addr, magic_loopback_addr, 4))
6099 loopback = htonl(INADDR_LOOPBACK);
6100 paddr = (char*) &loopback;
6103 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
6104 host = NULL;
6105 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
6106 while(extrabuf) {
6107 int res = gethostbyaddr_r(paddr, len, unixtype,
6108 &hostentry, extrabuf, ebufsize, &host, &locerr);
6109 if (res != ERANGE) break;
6110 ebufsize *=2;
6111 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
6113 if (host) retval = WS_dup_he(host);
6114 else SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
6115 HeapFree(GetProcessHeap(),0,extrabuf);
6116 #else
6117 EnterCriticalSection( &csWSgetXXXbyYYY );
6118 host = gethostbyaddr(paddr, len, unixtype);
6119 if (host) retval = WS_dup_he(host);
6120 else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
6121 LeaveCriticalSection( &csWSgetXXXbyYYY );
6122 #endif
6123 TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
6124 return retval;
6127 /***********************************************************************
6128 * WS_compare_routes_by_metric_asc (INTERNAL)
6130 * Comparison function for qsort(), for sorting two routes (struct route)
6131 * by metric in ascending order.
6133 static int WS_compare_routes_by_metric_asc(const void *left, const void *right)
6135 const struct route *a = left, *b = right;
6136 if (a->default_route && b->default_route)
6137 return a->default_route - b->default_route;
6138 if (a->default_route && !b->default_route)
6139 return -1;
6140 if (b->default_route && !a->default_route)
6141 return 1;
6142 return a->metric - b->metric;
6145 /***********************************************************************
6146 * WS_get_local_ips (INTERNAL)
6148 * Returns the list of local IP addresses by going through the network
6149 * adapters and using the local routing table to sort the addresses
6150 * from highest routing priority to lowest routing priority. This
6151 * functionality is inferred from the description for obtaining local
6152 * IP addresses given in the Knowledge Base Article Q160215.
6154 * Please note that the returned hostent is only freed when the thread
6155 * closes and is replaced if another hostent is requested.
6157 static struct WS_hostent* WS_get_local_ips( char *hostname )
6159 int numroutes = 0, i, j, default_routes = 0;
6160 DWORD n;
6161 PIP_ADAPTER_INFO adapters = NULL, k;
6162 struct WS_hostent *hostlist = NULL;
6163 PMIB_IPFORWARDTABLE routes = NULL;
6164 struct route *route_addrs = NULL;
6165 DWORD adap_size, route_size;
6167 /* Obtain the size of the adapter list and routing table, also allocate memory */
6168 if (GetAdaptersInfo(NULL, &adap_size) != ERROR_BUFFER_OVERFLOW)
6169 return NULL;
6170 if (GetIpForwardTable(NULL, &route_size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
6171 return NULL;
6172 adapters = HeapAlloc(GetProcessHeap(), 0, adap_size);
6173 routes = HeapAlloc(GetProcessHeap(), 0, route_size);
6174 if (adapters == NULL || routes == NULL)
6175 goto cleanup;
6176 /* Obtain the adapter list and the full routing table */
6177 if (GetAdaptersInfo(adapters, &adap_size) != NO_ERROR)
6178 goto cleanup;
6179 if (GetIpForwardTable(routes, &route_size, FALSE) != NO_ERROR)
6180 goto cleanup;
6181 /* Store the interface associated with each route */
6182 for (n = 0; n < routes->dwNumEntries; n++)
6184 IF_INDEX ifindex;
6185 DWORD ifmetric, ifdefault = 0;
6186 BOOL exists = FALSE;
6188 /* Check if this is a default route (there may be more than one) */
6189 if (!routes->table[n].dwForwardDest)
6190 ifdefault = ++default_routes;
6191 else if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
6192 continue;
6193 ifindex = routes->table[n].dwForwardIfIndex;
6194 ifmetric = routes->table[n].dwForwardMetric1;
6195 /* Only store the lowest valued metric for an interface */
6196 for (j = 0; j < numroutes; j++)
6198 if (route_addrs[j].interface == ifindex)
6200 if (route_addrs[j].metric > ifmetric)
6201 route_addrs[j].metric = ifmetric;
6202 exists = TRUE;
6205 if (exists)
6206 continue;
6207 route_addrs = heap_realloc(route_addrs, (numroutes+1)*sizeof(struct route));
6208 if (route_addrs == NULL)
6209 goto cleanup; /* Memory allocation error, fail gracefully */
6210 route_addrs[numroutes].interface = ifindex;
6211 route_addrs[numroutes].metric = ifmetric;
6212 route_addrs[numroutes].default_route = ifdefault;
6213 /* If no IP is found in the next step (for whatever reason)
6214 * then fall back to the magic loopback address.
6216 memcpy(&(route_addrs[numroutes].addr.s_addr), magic_loopback_addr, 4);
6217 numroutes++;
6219 if (numroutes == 0)
6220 goto cleanup; /* No routes, fall back to the Magic IP */
6221 /* Find the IP address associated with each found interface */
6222 for (i = 0; i < numroutes; i++)
6224 for (k = adapters; k != NULL; k = k->Next)
6226 char *ip = k->IpAddressList.IpAddress.String;
6228 if (route_addrs[i].interface == k->Index)
6229 route_addrs[i].addr.s_addr = (in_addr_t) inet_addr(ip);
6232 /* Allocate a hostent and enough memory for all the IPs,
6233 * including the NULL at the end of the list.
6235 hostlist = WS_create_he(hostname, 1, 0, numroutes+1, sizeof(struct in_addr));
6236 if (hostlist == NULL)
6237 goto cleanup; /* Failed to allocate a hostent for the list of IPs */
6238 hostlist->h_addr_list[numroutes] = NULL; /* NULL-terminate the address list */
6239 hostlist->h_aliases[0] = NULL; /* NULL-terminate the alias list */
6240 hostlist->h_addrtype = AF_INET;
6241 hostlist->h_length = sizeof(struct in_addr); /* = 4 */
6242 /* Reorder the entries before placing them in the host list. Windows expects
6243 * the IP list in order from highest priority to lowest (the critical thing
6244 * is that most applications expect the first IP to be the default route).
6246 if (numroutes > 1)
6247 qsort(route_addrs, numroutes, sizeof(struct route), WS_compare_routes_by_metric_asc);
6249 for (i = 0; i < numroutes; i++)
6250 (*(struct in_addr *) hostlist->h_addr_list[i]) = route_addrs[i].addr;
6252 /* Cleanup all allocated memory except the address list,
6253 * the address list is used by the calling app.
6255 cleanup:
6256 HeapFree(GetProcessHeap(), 0, route_addrs);
6257 HeapFree(GetProcessHeap(), 0, adapters);
6258 HeapFree(GetProcessHeap(), 0, routes);
6259 return hostlist;
6262 /***********************************************************************
6263 * gethostbyname (WS2_32.52)
6265 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
6267 struct WS_hostent *retval = NULL;
6268 struct hostent* host;
6269 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
6270 char *extrabuf;
6271 int ebufsize=1024;
6272 struct hostent hostentry;
6273 int locerr = ENOBUFS;
6274 #endif
6275 char hostname[100];
6276 if(!num_startup) {
6277 SetLastError(WSANOTINITIALISED);
6278 return NULL;
6280 if( gethostname( hostname, 100) == -1) {
6281 SetLastError(WSAENOBUFS); /* appropriate ? */
6282 return retval;
6284 if( !name || !name[0]) {
6285 name = hostname;
6287 /* If the hostname of the local machine is requested then return the
6288 * complete list of local IP addresses */
6289 if(strcmp(name, hostname) == 0)
6290 retval = WS_get_local_ips(hostname);
6291 /* If any other hostname was requested (or the routing table lookup failed)
6292 * then return the IP found by the host OS */
6293 if(retval == NULL)
6295 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
6296 host = NULL;
6297 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
6298 while(extrabuf) {
6299 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
6300 if( res != ERANGE) break;
6301 ebufsize *=2;
6302 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
6304 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
6305 #else
6306 EnterCriticalSection( &csWSgetXXXbyYYY );
6307 host = gethostbyname(name);
6308 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
6309 #endif
6310 if (host) retval = WS_dup_he(host);
6311 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
6312 HeapFree(GetProcessHeap(),0,extrabuf);
6313 #else
6314 LeaveCriticalSection( &csWSgetXXXbyYYY );
6315 #endif
6317 if (retval && retval->h_addr_list[0][0] == 127 &&
6318 strcmp(name, "localhost") != 0)
6320 /* hostname != "localhost" but has loopback address. replace by our
6321 * special address.*/
6322 memcpy(retval->h_addr_list[0], magic_loopback_addr, 4);
6324 TRACE( "%s ret %p\n", debugstr_a(name), retval );
6325 return retval;
6329 static const struct { int prot; const char *names[3]; } protocols[] =
6331 { 0, { "ip", "IP" }},
6332 { 1, { "icmp", "ICMP" }},
6333 { 3, { "ggp", "GGP" }},
6334 { 6, { "tcp", "TCP" }},
6335 { 8, { "egp", "EGP" }},
6336 { 12, { "pup", "PUP" }},
6337 { 17, { "udp", "UDP" }},
6338 { 20, { "hmp", "HMP" }},
6339 { 22, { "xns-idp", "XNS-IDP" }},
6340 { 27, { "rdp", "RDP" }},
6341 { 41, { "ipv6", "IPv6" }},
6342 { 43, { "ipv6-route", "IPv6-Route" }},
6343 { 44, { "ipv6-frag", "IPv6-Frag" }},
6344 { 50, { "esp", "ESP" }},
6345 { 51, { "ah", "AH" }},
6346 { 58, { "ipv6-icmp", "IPv6-ICMP" }},
6347 { 59, { "ipv6-nonxt", "IPv6-NoNxt" }},
6348 { 60, { "ipv6-opts", "IPv6-Opts" }},
6349 { 66, { "rvd", "RVD" }},
6352 /***********************************************************************
6353 * getprotobyname (WS2_32.53)
6355 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
6357 struct WS_protoent* retval = NULL;
6358 unsigned int i;
6360 for (i = 0; i < ARRAY_SIZE(protocols); i++)
6362 if (_strnicmp( protocols[i].names[0], name, -1 )) continue;
6363 retval = WS_create_pe( protocols[i].names[0], (char **)protocols[i].names + 1,
6364 protocols[i].prot );
6365 break;
6367 if (!retval)
6369 WARN( "protocol %s not found\n", debugstr_a(name) );
6370 SetLastError(WSANO_DATA);
6372 TRACE( "%s ret %p\n", debugstr_a(name), retval );
6373 return retval;
6377 /***********************************************************************
6378 * getprotobynumber (WS2_32.54)
6380 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
6382 struct WS_protoent* retval = NULL;
6383 unsigned int i;
6385 for (i = 0; i < ARRAY_SIZE(protocols); i++)
6387 if (protocols[i].prot != number) continue;
6388 retval = WS_create_pe( protocols[i].names[0], (char **)protocols[i].names + 1,
6389 protocols[i].prot );
6390 break;
6392 if (!retval)
6394 WARN( "protocol %d not found\n", number );
6395 SetLastError(WSANO_DATA);
6397 TRACE("%i ret %p\n", number, retval);
6398 return retval;
6402 /***********************************************************************
6403 * getservbyname (WS2_32.55)
6405 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
6407 struct WS_servent* retval = NULL;
6408 struct servent* serv;
6409 char *name_str;
6410 char *proto_str = NULL;
6412 if (!(name_str = strdup_lower(name))) return NULL;
6414 if (proto && *proto)
6416 if (!(proto_str = strdup_lower(proto)))
6418 HeapFree( GetProcessHeap(), 0, name_str );
6419 return NULL;
6423 EnterCriticalSection( &csWSgetXXXbyYYY );
6424 serv = getservbyname(name_str, proto_str);
6425 if( serv != NULL )
6427 retval = WS_dup_se(serv);
6429 else SetLastError(WSANO_DATA);
6430 LeaveCriticalSection( &csWSgetXXXbyYYY );
6431 HeapFree( GetProcessHeap(), 0, proto_str );
6432 HeapFree( GetProcessHeap(), 0, name_str );
6433 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
6434 return retval;
6437 /***********************************************************************
6438 * freeaddrinfo (WS2_32.@)
6440 void WINAPI WS_freeaddrinfo(struct WS_addrinfo *res)
6442 while (res) {
6443 struct WS_addrinfo *next;
6445 HeapFree(GetProcessHeap(),0,res->ai_canonname);
6446 HeapFree(GetProcessHeap(),0,res->ai_addr);
6447 next = res->ai_next;
6448 HeapFree(GetProcessHeap(),0,res);
6449 res = next;
6453 /* helper functions for getaddrinfo()/getnameinfo() */
6454 static int convert_aiflag_w2u(int winflags) {
6455 unsigned int i;
6456 int unixflags = 0;
6458 for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
6459 if (ws_aiflag_map[i][0] & winflags) {
6460 unixflags |= ws_aiflag_map[i][1];
6461 winflags &= ~ws_aiflag_map[i][0];
6463 if (winflags)
6464 FIXME("Unhandled windows AI_xxx flags 0x%x\n", winflags);
6465 return unixflags;
6468 static int convert_niflag_w2u(int winflags) {
6469 unsigned int i;
6470 int unixflags = 0;
6472 for (i = 0; i < ARRAY_SIZE(ws_niflag_map); i++)
6473 if (ws_niflag_map[i][0] & winflags) {
6474 unixflags |= ws_niflag_map[i][1];
6475 winflags &= ~ws_niflag_map[i][0];
6477 if (winflags)
6478 FIXME("Unhandled windows NI_xxx flags 0x%x\n", winflags);
6479 return unixflags;
6482 static int convert_aiflag_u2w(int unixflags) {
6483 unsigned int i;
6484 int winflags = 0;
6486 for (i = 0; i < ARRAY_SIZE(ws_aiflag_map); i++)
6487 if (ws_aiflag_map[i][1] & unixflags) {
6488 winflags |= ws_aiflag_map[i][0];
6489 unixflags &= ~ws_aiflag_map[i][1];
6491 if (unixflags)
6492 WARN("Unhandled UNIX AI_xxx flags 0x%x\n", unixflags);
6493 return winflags;
6496 static int convert_eai_u2w(int unixret) {
6497 int i;
6499 if (!unixret) return 0;
6501 for (i=0;ws_eai_map[i][0];i++)
6502 if (ws_eai_map[i][1] == unixret)
6503 return ws_eai_map[i][0];
6505 if (unixret == EAI_SYSTEM)
6506 /* There are broken versions of glibc which return EAI_SYSTEM
6507 * and set errno to 0 instead of returning EAI_NONAME.
6509 return errno ? sock_get_error( errno ) : WS_EAI_NONAME;
6511 FIXME("Unhandled unix EAI_xxx ret %d\n", unixret);
6512 return unixret;
6515 static char *get_fqdn(void)
6517 char *ret;
6518 DWORD size = 0;
6520 GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, NULL, &size );
6521 if (GetLastError() != ERROR_MORE_DATA) return NULL;
6522 if (!(ret = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
6523 if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, ret, &size ))
6525 HeapFree( GetProcessHeap(), 0, ret );
6526 return NULL;
6528 return ret;
6531 static BOOL addrinfo_in_list( const struct WS_addrinfo *list, const struct WS_addrinfo *ai )
6533 const struct WS_addrinfo *cursor = list;
6534 while (cursor)
6536 if (ai->ai_flags == cursor->ai_flags && ai->ai_family == cursor->ai_family &&
6537 ai->ai_socktype == cursor->ai_socktype && ai->ai_protocol == cursor->ai_protocol &&
6538 ai->ai_addrlen == cursor->ai_addrlen && !memcmp(ai->ai_addr, cursor->ai_addr, ai->ai_addrlen) &&
6539 ((ai->ai_canonname && cursor->ai_canonname && !strcmp(ai->ai_canonname, cursor->ai_canonname))
6540 || (!ai->ai_canonname && !cursor->ai_canonname))) return TRUE;
6541 cursor = cursor->ai_next;
6543 return FALSE;
6546 /***********************************************************************
6547 * getaddrinfo (WS2_32.@)
6549 int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addrinfo *hints, struct WS_addrinfo **res)
6551 #ifdef HAVE_GETADDRINFO
6552 struct addrinfo *unixaires = NULL;
6553 int result;
6554 struct addrinfo unixhints, *punixhints = NULL;
6555 char *nodeV6 = NULL, *fqdn = NULL;
6556 const char *node;
6558 *res = NULL;
6559 if (!nodename && !servname)
6561 SetLastError(WSAHOST_NOT_FOUND);
6562 return WSAHOST_NOT_FOUND;
6565 if (!nodename)
6566 node = NULL;
6567 else if (!nodename[0])
6569 if (!(fqdn = get_fqdn())) return WSA_NOT_ENOUGH_MEMORY;
6570 node = fqdn;
6572 else
6574 node = nodename;
6576 /* Check for [ipv6] or [ipv6]:portnumber, which are supported by Windows */
6577 if (!hints || hints->ai_family == WS_AF_UNSPEC || hints->ai_family == WS_AF_INET6)
6579 char *close_bracket;
6581 if (node[0] == '[' && (close_bracket = strchr(node + 1, ']')))
6583 nodeV6 = HeapAlloc(GetProcessHeap(), 0, close_bracket - node);
6584 if (!nodeV6) return WSA_NOT_ENOUGH_MEMORY;
6585 lstrcpynA(nodeV6, node + 1, close_bracket - node);
6586 node = nodeV6;
6591 /* servname tweak required by OSX and BSD kernels */
6592 if (servname && !servname[0]) servname = "0";
6594 if (hints) {
6595 punixhints = &unixhints;
6597 memset(&unixhints, 0, sizeof(unixhints));
6598 punixhints->ai_flags = convert_aiflag_w2u(hints->ai_flags);
6600 /* zero is a wildcard, no need to convert */
6601 if (hints->ai_family)
6602 punixhints->ai_family = convert_af_w2u(hints->ai_family);
6603 if (hints->ai_socktype)
6604 punixhints->ai_socktype = convert_socktype_w2u(hints->ai_socktype);
6605 if (hints->ai_protocol)
6606 punixhints->ai_protocol = max(convert_proto_w2u(hints->ai_protocol), 0);
6608 if (punixhints->ai_socktype < 0)
6610 SetLastError(WSAESOCKTNOSUPPORT);
6611 HeapFree(GetProcessHeap(), 0, fqdn);
6612 HeapFree(GetProcessHeap(), 0, nodeV6);
6613 return SOCKET_ERROR;
6616 /* windows allows invalid combinations of socket type and protocol, unix does not.
6617 * fix the parameters here to make getaddrinfo call always work */
6618 if (punixhints->ai_protocol == IPPROTO_TCP &&
6619 punixhints->ai_socktype != SOCK_STREAM && punixhints->ai_socktype != SOCK_SEQPACKET)
6620 punixhints->ai_socktype = 0;
6622 else if (punixhints->ai_protocol == IPPROTO_UDP && punixhints->ai_socktype != SOCK_DGRAM)
6623 punixhints->ai_socktype = 0;
6625 else if (IS_IPX_PROTO(punixhints->ai_protocol) && punixhints->ai_socktype != SOCK_DGRAM)
6626 punixhints->ai_socktype = 0;
6628 else if (punixhints->ai_protocol == IPPROTO_IPV6)
6629 punixhints->ai_protocol = 0;
6632 /* getaddrinfo(3) is thread safe, no need to wrap in CS */
6633 result = getaddrinfo(node, servname, punixhints, &unixaires);
6635 if (result && (!hints || !(hints->ai_flags & WS_AI_NUMERICHOST)) && node)
6637 if (!fqdn && !(fqdn = get_fqdn()))
6639 HeapFree(GetProcessHeap(), 0, nodeV6);
6640 return WSA_NOT_ENOUGH_MEMORY;
6642 if (!strcmp(fqdn, node) || (!strncmp(fqdn, node, strlen(node)) && fqdn[strlen(node)] == '.'))
6644 /* If it didn't work it means the host name IP is not in /etc/hosts, try again
6645 * by sending a NULL host and avoid sending a NULL servname too because that
6646 * is invalid */
6647 ERR_(winediag)("Failed to resolve your host name IP\n");
6648 result = getaddrinfo(NULL, servname ? servname : "0", punixhints, &unixaires);
6649 if (!result && punixhints && (punixhints->ai_flags & AI_CANONNAME) && unixaires && !unixaires->ai_canonname)
6651 freeaddrinfo(unixaires);
6652 result = EAI_NONAME;
6656 TRACE("%s, %s %p -> %p %d\n", debugstr_a(nodename), debugstr_a(servname), hints, res, result);
6657 HeapFree(GetProcessHeap(), 0, fqdn);
6658 HeapFree(GetProcessHeap(), 0, nodeV6);
6660 if (!result) {
6661 struct addrinfo *xuai = unixaires;
6662 struct WS_addrinfo **xai = res;
6664 *xai = NULL;
6665 while (xuai) {
6666 struct WS_addrinfo *ai = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo));
6667 SIZE_T len;
6669 if (!ai)
6670 goto outofmem;
6672 ai->ai_flags = convert_aiflag_u2w(xuai->ai_flags);
6673 ai->ai_family = convert_af_u2w(xuai->ai_family);
6674 /* copy whatever was sent in the hints */
6675 if(hints) {
6676 ai->ai_socktype = hints->ai_socktype;
6677 ai->ai_protocol = hints->ai_protocol;
6678 } else {
6679 ai->ai_socktype = convert_socktype_u2w(xuai->ai_socktype);
6680 ai->ai_protocol = convert_proto_u2w(xuai->ai_protocol);
6682 if (xuai->ai_canonname) {
6683 TRACE("canon name - %s\n",debugstr_a(xuai->ai_canonname));
6684 ai->ai_canonname = HeapAlloc(GetProcessHeap(),0,strlen(xuai->ai_canonname)+1);
6685 if (!ai->ai_canonname)
6686 goto outofmem;
6687 strcpy(ai->ai_canonname,xuai->ai_canonname);
6689 len = xuai->ai_addrlen;
6690 ai->ai_addr = HeapAlloc(GetProcessHeap(),0,len);
6691 if (!ai->ai_addr)
6692 goto outofmem;
6693 ai->ai_addrlen = len;
6694 do {
6695 int winlen = ai->ai_addrlen;
6697 if (!ws_sockaddr_u2ws(xuai->ai_addr, ai->ai_addr, &winlen)) {
6698 ai->ai_addrlen = winlen;
6699 break;
6701 len = 2*len;
6702 ai->ai_addr = HeapReAlloc(GetProcessHeap(),0,ai->ai_addr,len);
6703 if (!ai->ai_addr)
6704 goto outofmem;
6705 ai->ai_addrlen = len;
6706 } while (1);
6708 if (addrinfo_in_list(*res, ai))
6710 HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
6711 HeapFree(GetProcessHeap(), 0, ai->ai_addr);
6712 HeapFree(GetProcessHeap(), 0, ai);
6714 else
6716 *xai = ai;
6717 xai = &ai->ai_next;
6719 xuai = xuai->ai_next;
6721 freeaddrinfo(unixaires);
6723 if (TRACE_ON(winsock))
6725 struct WS_addrinfo *ai = *res;
6726 while (ai)
6728 TRACE("=> %p, flags %#x, family %d, type %d, protocol %d, len %ld, name %s, addr %s\n",
6729 ai, ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol, ai->ai_addrlen,
6730 ai->ai_canonname, debugstr_sockaddr(ai->ai_addr));
6731 ai = ai->ai_next;
6734 } else
6735 result = convert_eai_u2w(result);
6737 SetLastError(result);
6738 return result;
6740 outofmem:
6741 if (*res) WS_freeaddrinfo(*res);
6742 if (unixaires) freeaddrinfo(unixaires);
6743 return WSA_NOT_ENOUGH_MEMORY;
6744 #else
6745 FIXME("getaddrinfo() failed, not found during buildtime.\n");
6746 return EAI_FAIL;
6747 #endif
6750 static ADDRINFOEXW *addrinfo_AtoW(const struct WS_addrinfo *ai)
6752 ADDRINFOEXW *ret;
6754 if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ADDRINFOEXW)))) return NULL;
6755 ret->ai_flags = ai->ai_flags;
6756 ret->ai_family = ai->ai_family;
6757 ret->ai_socktype = ai->ai_socktype;
6758 ret->ai_protocol = ai->ai_protocol;
6759 ret->ai_addrlen = ai->ai_addrlen;
6760 ret->ai_canonname = NULL;
6761 ret->ai_addr = NULL;
6762 ret->ai_blob = NULL;
6763 ret->ai_bloblen = 0;
6764 ret->ai_provider = NULL;
6765 ret->ai_next = NULL;
6766 if (ai->ai_canonname)
6768 int len = MultiByteToWideChar(CP_ACP, 0, ai->ai_canonname, -1, NULL, 0);
6769 if (!(ret->ai_canonname = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR))))
6771 HeapFree(GetProcessHeap(), 0, ret);
6772 return NULL;
6774 MultiByteToWideChar(CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len);
6776 if (ai->ai_addr)
6778 if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, ai->ai_addrlen)))
6780 HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
6781 HeapFree(GetProcessHeap(), 0, ret);
6782 return NULL;
6784 memcpy(ret->ai_addr, ai->ai_addr, ai->ai_addrlen);
6786 return ret;
6789 static ADDRINFOEXW *addrinfo_list_AtoW(const struct WS_addrinfo *info)
6791 ADDRINFOEXW *ret, *infoW;
6793 if (!(ret = infoW = addrinfo_AtoW(info))) return NULL;
6794 while (info->ai_next)
6796 if (!(infoW->ai_next = addrinfo_AtoW(info->ai_next)))
6798 FreeAddrInfoExW(ret);
6799 return NULL;
6801 infoW = infoW->ai_next;
6802 info = info->ai_next;
6804 return ret;
6807 static struct WS_addrinfo *addrinfo_WtoA(const struct WS_addrinfoW *ai)
6809 struct WS_addrinfo *ret;
6811 if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_addrinfo)))) return NULL;
6812 ret->ai_flags = ai->ai_flags;
6813 ret->ai_family = ai->ai_family;
6814 ret->ai_socktype = ai->ai_socktype;
6815 ret->ai_protocol = ai->ai_protocol;
6816 ret->ai_addrlen = ai->ai_addrlen;
6817 ret->ai_canonname = NULL;
6818 ret->ai_addr = NULL;
6819 ret->ai_next = NULL;
6820 if (ai->ai_canonname)
6822 int len = WideCharToMultiByte(CP_ACP, 0, ai->ai_canonname, -1, NULL, 0, NULL, NULL);
6823 if (!(ret->ai_canonname = HeapAlloc(GetProcessHeap(), 0, len)))
6825 HeapFree(GetProcessHeap(), 0, ret);
6826 return NULL;
6828 WideCharToMultiByte(CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len, NULL, NULL);
6830 if (ai->ai_addr)
6832 if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_sockaddr))))
6834 HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
6835 HeapFree(GetProcessHeap(), 0, ret);
6836 return NULL;
6838 memcpy(ret->ai_addr, ai->ai_addr, sizeof(struct WS_sockaddr));
6840 return ret;
6843 struct getaddrinfo_args
6845 OVERLAPPED *overlapped;
6846 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine;
6847 ADDRINFOEXW **result;
6848 char *nodename;
6849 char *servname;
6852 static void WINAPI getaddrinfo_callback(TP_CALLBACK_INSTANCE *instance, void *context)
6854 struct getaddrinfo_args *args = context;
6855 OVERLAPPED *overlapped = args->overlapped;
6856 HANDLE event = overlapped->hEvent;
6857 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine = args->completion_routine;
6858 struct WS_addrinfo *res;
6859 int ret;
6861 ret = WS_getaddrinfo(args->nodename, args->servname, NULL, &res);
6862 if (res)
6864 *args->result = addrinfo_list_AtoW(res);
6865 overlapped->u.Pointer = args->result;
6866 WS_freeaddrinfo(res);
6869 HeapFree(GetProcessHeap(), 0, args->nodename);
6870 HeapFree(GetProcessHeap(), 0, args->servname);
6871 HeapFree(GetProcessHeap(), 0, args);
6873 overlapped->Internal = ret;
6874 if (completion_routine) completion_routine(ret, 0, overlapped);
6875 if (event) SetEvent(event);
6878 static int WS_getaddrinfoW(const WCHAR *nodename, const WCHAR *servname, const struct WS_addrinfo *hints, ADDRINFOEXW **res,
6879 OVERLAPPED *overlapped, LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine)
6881 int ret = EAI_MEMORY, len, i;
6882 char *nodenameA = NULL, *servnameA = NULL;
6883 struct WS_addrinfo *resA;
6884 WCHAR *local_nodenameW = (WCHAR *)nodename;
6886 *res = NULL;
6887 if (nodename)
6889 /* Is this an IDN? Most likely if any char is above the Ascii table, this
6890 * is the simplest validation possible, further validation will be done by
6891 * the native getaddrinfo() */
6892 for (i = 0; nodename[i]; i++)
6894 if (nodename[i] > 'z')
6895 break;
6897 if (nodename[i])
6899 if (hints && (hints->ai_flags & WS_AI_DISABLE_IDN_ENCODING))
6901 /* Name requires conversion but it was disabled */
6902 ret = WSAHOST_NOT_FOUND;
6903 WSASetLastError(ret);
6904 goto end;
6907 len = IdnToAscii(0, nodename, -1, NULL, 0);
6908 if (!len)
6910 ERR("Failed to convert %s to punycode\n", debugstr_w(nodename));
6911 ret = EAI_FAIL;
6912 goto end;
6914 if (!(local_nodenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) goto end;
6915 IdnToAscii(0, nodename, -1, local_nodenameW, len);
6918 if (local_nodenameW)
6920 len = WideCharToMultiByte(CP_ACP, 0, local_nodenameW, -1, NULL, 0, NULL, NULL);
6921 if (!(nodenameA = HeapAlloc(GetProcessHeap(), 0, len))) goto end;
6922 WideCharToMultiByte(CP_ACP, 0, local_nodenameW, -1, nodenameA, len, NULL, NULL);
6924 if (servname)
6926 len = WideCharToMultiByte(CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL);
6927 if (!(servnameA = HeapAlloc(GetProcessHeap(), 0, len))) goto end;
6928 WideCharToMultiByte(CP_ACP, 0, servname, -1, servnameA, len, NULL, NULL);
6931 if (overlapped)
6933 struct getaddrinfo_args *args;
6935 if (overlapped->hEvent && completion_routine)
6937 ret = WSAEINVAL;
6938 goto end;
6941 if (!(args = HeapAlloc(GetProcessHeap(), 0, sizeof(*args)))) goto end;
6942 args->overlapped = overlapped;
6943 args->completion_routine = completion_routine;
6944 args->result = res;
6945 args->nodename = nodenameA;
6946 args->servname = servnameA;
6948 overlapped->Internal = WSAEINPROGRESS;
6949 if (!TrySubmitThreadpoolCallback(getaddrinfo_callback, args, NULL))
6951 HeapFree(GetProcessHeap(), 0, args);
6952 ret = GetLastError();
6953 goto end;
6956 if (local_nodenameW != nodename)
6957 HeapFree(GetProcessHeap(), 0, local_nodenameW);
6958 WSASetLastError(ERROR_IO_PENDING);
6959 return ERROR_IO_PENDING;
6962 ret = WS_getaddrinfo(nodenameA, servnameA, hints, &resA);
6963 if (!ret)
6965 *res = addrinfo_list_AtoW(resA);
6966 WS_freeaddrinfo(resA);
6969 end:
6970 if (local_nodenameW != nodename)
6971 HeapFree(GetProcessHeap(), 0, local_nodenameW);
6972 HeapFree(GetProcessHeap(), 0, nodenameA);
6973 HeapFree(GetProcessHeap(), 0, servnameA);
6974 return ret;
6977 /***********************************************************************
6978 * GetAddrInfoExW (WS2_32.@)
6980 int WINAPI GetAddrInfoExW(const WCHAR *name, const WCHAR *servname, DWORD namespace, GUID *namespace_id,
6981 const ADDRINFOEXW *hints, ADDRINFOEXW **result, struct WS_timeval *timeout, OVERLAPPED *overlapped,
6982 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine, HANDLE *handle)
6984 int ret;
6986 TRACE("(%s %s %x %s %p %p %p %p %p %p)\n", debugstr_w(name), debugstr_w(servname), namespace,
6987 debugstr_guid(namespace_id), hints, result, timeout, overlapped, completion_routine, handle);
6989 if (namespace != NS_DNS)
6990 FIXME("Unsupported namespace %u\n", namespace);
6991 if (namespace_id)
6992 FIXME("Unsupported naemspace_id %s\n", debugstr_guid(namespace_id));
6993 if (hints)
6994 FIXME("Unsupported hints\n");
6995 if (timeout)
6996 FIXME("Unsupported timeout\n");
6997 if (handle)
6998 FIXME("Unsupported cancel handle\n");
7000 ret = WS_getaddrinfoW(name, servname, NULL, result, overlapped, completion_routine);
7001 if (ret) return ret;
7002 if (handle) *handle = (HANDLE)0xdeadbeef;
7003 return 0;
7006 /***********************************************************************
7007 * GetAddrInfoExOverlappedResult (WS2_32.@)
7009 int WINAPI GetAddrInfoExOverlappedResult(OVERLAPPED *overlapped)
7011 TRACE("(%p)\n", overlapped);
7012 return overlapped->Internal;
7015 /***********************************************************************
7016 * GetAddrInfoExCancel (WS2_32.@)
7018 int WINAPI GetAddrInfoExCancel(HANDLE *handle)
7020 FIXME("(%p)\n", handle);
7021 return WSA_INVALID_HANDLE;
7024 /***********************************************************************
7025 * GetAddrInfoW (WS2_32.@)
7027 int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hints, PADDRINFOW *res)
7029 struct WS_addrinfo *hintsA = NULL;
7030 ADDRINFOEXW *resex;
7031 int ret = EAI_MEMORY;
7033 TRACE("nodename %s, servname %s, hints %p, result %p\n",
7034 debugstr_w(nodename), debugstr_w(servname), hints, res);
7036 *res = NULL;
7037 if (hints) hintsA = addrinfo_WtoA(hints);
7038 ret = WS_getaddrinfoW(nodename, servname, hintsA, &resex, NULL, NULL);
7039 WS_freeaddrinfo(hintsA);
7040 if (ret) return ret;
7042 if (resex)
7044 /* ADDRINFOEXW has layout compatible with ADDRINFOW except for ai_next field,
7045 * so we may convert it in place */
7046 *res = (ADDRINFOW*)resex;
7047 do {
7048 ((ADDRINFOW*)resex)->ai_next = (ADDRINFOW*)resex->ai_next;
7049 resex = resex->ai_next;
7050 } while (resex);
7052 return 0;
7055 /***********************************************************************
7056 * FreeAddrInfoW (WS2_32.@)
7058 void WINAPI FreeAddrInfoW(PADDRINFOW ai)
7060 while (ai)
7062 ADDRINFOW *next;
7063 HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
7064 HeapFree(GetProcessHeap(), 0, ai->ai_addr);
7065 next = ai->ai_next;
7066 HeapFree(GetProcessHeap(), 0, ai);
7067 ai = next;
7071 /***********************************************************************
7072 * FreeAddrInfoEx (WS2_32.@)
7074 void WINAPI FreeAddrInfoEx(ADDRINFOEXA *ai)
7076 TRACE("(%p)\n", ai);
7078 while (ai)
7080 ADDRINFOEXA *next;
7081 HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
7082 HeapFree(GetProcessHeap(), 0, ai->ai_addr);
7083 next = ai->ai_next;
7084 HeapFree(GetProcessHeap(), 0, ai);
7085 ai = next;
7089 /***********************************************************************
7090 * FreeAddrInfoExW (WS2_32.@)
7092 void WINAPI FreeAddrInfoExW(ADDRINFOEXW *ai)
7094 TRACE("(%p)\n", ai);
7096 while (ai)
7098 ADDRINFOEXW *next;
7099 HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
7100 HeapFree(GetProcessHeap(), 0, ai->ai_addr);
7101 next = ai->ai_next;
7102 HeapFree(GetProcessHeap(), 0, ai);
7103 ai = next;
7107 int WINAPI WS_getnameinfo(const SOCKADDR *sa, WS_socklen_t salen, PCHAR host,
7108 DWORD hostlen, PCHAR serv, DWORD servlen, INT flags)
7110 #ifdef HAVE_GETNAMEINFO
7111 int ret;
7112 union generic_unix_sockaddr sa_u;
7113 unsigned int size;
7115 TRACE("%s %d %p %d %p %d %d\n", debugstr_sockaddr(sa), salen, host, hostlen,
7116 serv, servlen, flags);
7118 size = ws_sockaddr_ws2u(sa, salen, &sa_u);
7119 if (!size)
7121 SetLastError(WSAEFAULT);
7122 return WSA_NOT_ENOUGH_MEMORY;
7124 ret = getnameinfo(&sa_u.addr, size, host, hostlen, serv, servlen, convert_niflag_w2u(flags));
7125 return convert_eai_u2w(ret);
7126 #else
7127 FIXME("getnameinfo() failed, not found during buildtime.\n");
7128 return EAI_FAIL;
7129 #endif
7132 int WINAPI GetNameInfoW(const SOCKADDR *sa, WS_socklen_t salen, PWCHAR host,
7133 DWORD hostlen, PWCHAR serv, DWORD servlen, INT flags)
7135 int ret;
7136 char *hostA = NULL, *servA = NULL;
7138 if (host && (!(hostA = HeapAlloc(GetProcessHeap(), 0, hostlen)))) return EAI_MEMORY;
7139 if (serv && (!(servA = HeapAlloc(GetProcessHeap(), 0, servlen))))
7141 HeapFree(GetProcessHeap(), 0, hostA);
7142 return EAI_MEMORY;
7145 ret = WS_getnameinfo(sa, salen, hostA, hostlen, servA, servlen, flags);
7146 if (!ret)
7148 if (host) MultiByteToWideChar(CP_ACP, 0, hostA, -1, host, hostlen);
7149 if (serv) MultiByteToWideChar(CP_ACP, 0, servA, -1, serv, servlen);
7152 HeapFree(GetProcessHeap(), 0, hostA);
7153 HeapFree(GetProcessHeap(), 0, servA);
7154 return ret;
7157 /***********************************************************************
7158 * getservbyport (WS2_32.56)
7160 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
7162 struct WS_servent* retval = NULL;
7163 #ifdef HAVE_GETSERVBYPORT
7164 struct servent* serv;
7165 char *proto_str = NULL;
7167 if (proto && *proto)
7169 if (!(proto_str = strdup_lower(proto))) return NULL;
7171 EnterCriticalSection( &csWSgetXXXbyYYY );
7172 if( (serv = getservbyport(port, proto_str)) != NULL ) {
7173 retval = WS_dup_se(serv);
7175 else SetLastError(WSANO_DATA);
7176 LeaveCriticalSection( &csWSgetXXXbyYYY );
7177 HeapFree( GetProcessHeap(), 0, proto_str );
7178 #endif
7179 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
7180 return retval;
7184 /***********************************************************************
7185 * gethostname (WS2_32.57)
7187 int WINAPI WS_gethostname(char *name, int namelen)
7189 char buf[256];
7190 int len;
7192 TRACE("name %p, len %d\n", name, namelen);
7194 if (!name)
7196 SetLastError(WSAEFAULT);
7197 return SOCKET_ERROR;
7200 if (gethostname(buf, sizeof(buf)) != 0)
7202 SetLastError(wsaErrno());
7203 return SOCKET_ERROR;
7206 TRACE("<- '%s'\n", buf);
7207 len = strlen(buf);
7208 if (len > 15)
7209 WARN("Windows supports NetBIOS name length up to 15 bytes!\n");
7210 if (namelen <= len)
7212 SetLastError(WSAEFAULT);
7213 WARN("<- not enough space for hostname, required %d, got %d!\n", len + 1, namelen);
7214 return SOCKET_ERROR;
7216 strcpy(name, buf);
7217 return 0;
7221 /* ------------------------------------- Windows sockets extensions -- *
7223 * ------------------------------------------------------------------- */
7225 /***********************************************************************
7226 * WSAEnumNetworkEvents (WS2_32.36)
7228 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
7230 int ret;
7231 int i;
7232 int errors[FD_MAX_EVENTS];
7234 TRACE("%04lx, hEvent %p, lpEvent %p\n", s, hEvent, lpEvent );
7236 SERVER_START_REQ( get_socket_event )
7238 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
7239 req->service = TRUE;
7240 req->c_event = wine_server_obj_handle( hEvent );
7241 wine_server_set_reply( req, errors, sizeof(errors) );
7242 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
7244 SERVER_END_REQ;
7245 if (!ret)
7247 for (i = 0; i < FD_MAX_EVENTS; i++)
7249 if (lpEvent->lNetworkEvents & (1 << i))
7250 lpEvent->iErrorCode[i] = errors[i];
7252 return 0;
7254 SetLastError(WSAEINVAL);
7255 return SOCKET_ERROR;
7258 /***********************************************************************
7259 * WSAEventSelect (WS2_32.39)
7261 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
7263 int ret;
7265 TRACE("%04lx, hEvent %p, event %08x\n", s, hEvent, lEvent);
7267 SERVER_START_REQ( set_socket_event )
7269 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
7270 req->mask = lEvent;
7271 req->event = wine_server_obj_handle( hEvent );
7272 req->window = 0;
7273 req->msg = 0;
7274 ret = wine_server_call( req );
7276 SERVER_END_REQ;
7277 if (!ret) return 0;
7278 SetLastError(WSAEINVAL);
7279 return SOCKET_ERROR;
7282 /**********************************************************************
7283 * WSAGetOverlappedResult (WS2_32.40)
7285 BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
7286 LPDWORD lpcbTransfer, BOOL fWait,
7287 LPDWORD lpdwFlags )
7289 NTSTATUS status;
7291 TRACE( "socket %04lx ovl %p trans %p, wait %d flags %p\n",
7292 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
7294 if ( lpOverlapped == NULL )
7296 ERR( "Invalid pointer\n" );
7297 SetLastError(WSA_INVALID_PARAMETER);
7298 return FALSE;
7301 status = lpOverlapped->Internal;
7302 if (status == STATUS_PENDING)
7304 if (!fWait)
7306 SetLastError( WSA_IO_INCOMPLETE );
7307 return FALSE;
7310 if (WaitForSingleObject( lpOverlapped->hEvent ? lpOverlapped->hEvent : SOCKET2HANDLE(s),
7311 INFINITE ) == WAIT_FAILED)
7312 return FALSE;
7313 status = lpOverlapped->Internal;
7316 if ( lpcbTransfer )
7317 *lpcbTransfer = lpOverlapped->InternalHigh;
7319 if ( lpdwFlags )
7320 *lpdwFlags = lpOverlapped->u.s.Offset;
7322 if (status) SetLastError( RtlNtStatusToDosError(status) );
7323 return !status;
7327 /***********************************************************************
7328 * WSAAsyncSelect (WS2_32.101)
7330 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
7332 int ret;
7334 TRACE("%04lx, hWnd %p, uMsg %08x, event %08x\n", s, hWnd, uMsg, lEvent);
7336 SERVER_START_REQ( set_socket_event )
7338 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
7339 req->mask = lEvent;
7340 req->event = 0;
7341 req->window = wine_server_user_handle( hWnd );
7342 req->msg = uMsg;
7343 ret = wine_server_call( req );
7345 SERVER_END_REQ;
7346 if (!ret) return 0;
7347 SetLastError(WSAEINVAL);
7348 return SOCKET_ERROR;
7351 /***********************************************************************
7352 * WSACreateEvent (WS2_32.31)
7355 WSAEVENT WINAPI WSACreateEvent(void)
7357 /* Create a manual-reset event, with initial state: unsignaled */
7358 TRACE("\n");
7360 return CreateEventW(NULL, TRUE, FALSE, NULL);
7363 /***********************************************************************
7364 * WSACloseEvent (WS2_32.29)
7367 BOOL WINAPI WSACloseEvent(WSAEVENT event)
7369 TRACE ("event=%p\n", event);
7371 return CloseHandle(event);
7374 /***********************************************************************
7375 * WSASocketA (WS2_32.78)
7378 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
7379 LPWSAPROTOCOL_INFOA lpProtocolInfo,
7380 GROUP g, DWORD dwFlags)
7382 INT len;
7383 WSAPROTOCOL_INFOW info;
7385 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%x\n",
7386 af, type, protocol, lpProtocolInfo, g, dwFlags);
7388 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
7390 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
7391 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
7392 info.szProtocol, WSAPROTOCOL_LEN + 1);
7394 if (!len)
7396 SetLastError(WSAEINVAL);
7397 return SOCKET_ERROR;
7400 return WSASocketW(af, type, protocol, &info, g, dwFlags);
7403 /***********************************************************************
7404 * WSASocketW (WS2_32.79)
7407 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
7408 LPWSAPROTOCOL_INFOW lpProtocolInfo,
7409 GROUP g, DWORD flags)
7411 static const WCHAR afdW[] = {'\\','D','e','v','i','c','e','\\','A','f','d',0};
7412 struct afd_create_params create_params;
7413 OBJECT_ATTRIBUTES attr;
7414 UNICODE_STRING string;
7415 IO_STATUS_BLOCK io;
7416 NTSTATUS status;
7417 HANDLE handle;
7418 SOCKET ret;
7419 DWORD err;
7422 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
7423 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
7426 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%x\n",
7427 af, type, protocol, lpProtocolInfo, g, flags );
7429 if (!num_startup)
7431 err = WSANOTINITIALISED;
7432 goto done;
7435 /* hack for WSADuplicateSocket */
7436 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00)
7438 ret = lpProtocolInfo->dwServiceFlags3;
7439 TRACE("\tgot duplicate %04lx\n", ret);
7440 if (!socket_list_add(ret))
7442 CloseHandle(SOCKET2HANDLE(ret));
7443 return INVALID_SOCKET;
7445 return ret;
7448 if (lpProtocolInfo)
7450 if (af == FROM_PROTOCOL_INFO || !af)
7451 af = lpProtocolInfo->iAddressFamily;
7452 if (type == FROM_PROTOCOL_INFO || !type)
7453 type = lpProtocolInfo->iSocketType;
7454 if (protocol == FROM_PROTOCOL_INFO || !protocol)
7455 protocol = lpProtocolInfo->iProtocol;
7458 if (!af && !protocol)
7460 WSASetLastError(WSAEINVAL);
7461 return INVALID_SOCKET;
7464 if (!af && lpProtocolInfo)
7466 WSASetLastError(WSAEAFNOSUPPORT);
7467 return INVALID_SOCKET;
7470 if (!af || !type || !protocol)
7472 unsigned int i;
7474 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
7476 const WSAPROTOCOL_INFOW *info = &supported_protocols[i];
7478 if (af && af != info->iAddressFamily) continue;
7479 if (type && type != info->iSocketType) continue;
7480 if (protocol && (protocol < info->iProtocol ||
7481 protocol > info->iProtocol + info->iProtocolMaxOffset)) continue;
7482 if (!protocol && !(info->dwProviderFlags & PFL_MATCHES_PROTOCOL_ZERO)) continue;
7484 if (!af) af = supported_protocols[i].iAddressFamily;
7485 if (!type) type = supported_protocols[i].iSocketType;
7486 if (!protocol) protocol = supported_protocols[i].iProtocol;
7487 break;
7491 RtlInitUnicodeString(&string, afdW);
7492 InitializeObjectAttributes(&attr, &string, (flags & WSA_FLAG_NO_HANDLE_INHERIT) ? 0 : OBJ_INHERIT, NULL, NULL);
7493 if ((status = NtOpenFile(&handle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &attr,
7494 &io, 0, (flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT)))
7496 WARN("Failed to create socket, status %#x.\n", status);
7497 WSASetLastError(NtStatusToWSAError(status));
7498 return INVALID_SOCKET;
7501 create_params.family = af;
7502 create_params.type = type;
7503 create_params.protocol = protocol;
7504 create_params.flags = flags & ~(WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED);
7505 if ((status = NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io,
7506 IOCTL_AFD_CREATE, &create_params, sizeof(create_params), NULL, 0)))
7508 WARN("Failed to initialize socket, status %#x.\n", status);
7509 err = NtStatusToWSAError(status);
7510 if (err == WSAEACCES) /* raw socket denied */
7512 if (type == SOCK_RAW)
7513 ERR_(winediag)("Failed to create a socket of type SOCK_RAW, this requires special permissions.\n");
7514 else
7515 ERR_(winediag)("Failed to create socket, this requires special permissions.\n");
7517 WSASetLastError(err);
7518 NtClose(handle);
7519 return INVALID_SOCKET;
7522 ret = HANDLE2SOCKET(handle);
7523 TRACE("\tcreated %04lx\n", ret );
7525 if (!socket_list_add(ret))
7527 CloseHandle(handle);
7528 return INVALID_SOCKET;
7530 return ret;
7532 done:
7533 WARN("\t\tfailed, error %d!\n", err);
7534 SetLastError(err);
7535 return INVALID_SOCKET;
7538 /***********************************************************************
7539 * WSAJoinLeaf (WS2_32.58)
7542 SOCKET WINAPI WSAJoinLeaf(
7543 SOCKET s,
7544 const struct WS_sockaddr *addr,
7545 int addrlen,
7546 LPWSABUF lpCallerData,
7547 LPWSABUF lpCalleeData,
7548 LPQOS lpSQOS,
7549 LPQOS lpGQOS,
7550 DWORD dwFlags)
7552 FIXME("stub.\n");
7553 return INVALID_SOCKET;
7556 /***********************************************************************
7557 * __WSAFDIsSet (WS2_32.151)
7559 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
7561 int i = set->fd_count, ret = 0;
7563 while (i--)
7564 if (set->fd_array[i] == s)
7566 ret = 1;
7567 break;
7570 TRACE("(socket %04lx, fd_set %p, count %i) <- %d\n", s, set, set->fd_count, ret);
7571 return ret;
7574 /***********************************************************************
7575 * WSAIsBlocking (WS2_32.114)
7577 BOOL WINAPI WSAIsBlocking(void)
7579 /* By default WinSock should set all its sockets to non-blocking mode
7580 * and poll in PeekMessage loop when processing "blocking" ones. This
7581 * function is supposed to tell if the program is in this loop. Our
7582 * blocking calls are truly blocking so we always return FALSE.
7584 * Note: It is allowed to call this function without prior WSAStartup().
7587 TRACE("\n");
7588 return FALSE;
7591 /***********************************************************************
7592 * WSACancelBlockingCall (WS2_32.113)
7594 INT WINAPI WSACancelBlockingCall(void)
7596 TRACE("\n");
7597 return 0;
7600 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
7602 FIXME("How was this called?\n");
7603 return x();
7607 /***********************************************************************
7608 * WSASetBlockingHook (WS2_32.109)
7610 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
7612 FARPROC prev = blocking_hook;
7613 blocking_hook = lpBlockFunc;
7614 TRACE("hook %p\n", lpBlockFunc);
7615 return prev;
7619 /***********************************************************************
7620 * WSAUnhookBlockingHook (WS2_32.110)
7622 INT WINAPI WSAUnhookBlockingHook(void)
7624 blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
7625 return 0;
7629 /* ----------------------------------- end of API stuff */
7631 /* ----------------------------------- helper functions -
7633 * TODO: Merge WS_dup_..() stuff into one function that
7634 * would operate with a generic structure containing internal
7635 * pointers (via a template of some kind).
7638 static int list_size(char** l, int item_size)
7640 int i,j = 0;
7641 if(l)
7642 { for(i=0;l[i];i++)
7643 j += (item_size) ? item_size : strlen(l[i]) + 1;
7644 j += (i + 1) * sizeof(char*); }
7645 return j;
7648 static int list_dup(char** l_src, char** l_to, int item_size)
7650 char *p;
7651 int i;
7653 for (i = 0; l_src[i]; i++) ;
7654 p = (char *)(l_to + i + 1);
7655 for (i = 0; l_src[i]; i++)
7657 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
7658 memcpy(p, l_src[i], count);
7659 l_to[i] = p;
7660 p += count;
7662 l_to[i] = NULL;
7663 return p - (char *)l_to;
7666 /* ----- hostent */
7668 /* create a hostent entry
7670 * Creates the entry with enough memory for the name, aliases
7671 * addresses, and the address pointers. Also copies the name
7672 * and sets up all the pointers.
7674 * NOTE: The alias and address lists must be allocated with room
7675 * for the NULL item terminating the list. This is true even if
7676 * the list has no items ("aliases" and "addresses" must be
7677 * at least "1", a truly empty list is invalid).
7679 static struct WS_hostent *WS_create_he(char *name, int aliases, int aliases_size, int addresses, int address_length)
7681 struct WS_hostent *p_to;
7682 char *p;
7683 int size = (sizeof(struct WS_hostent) +
7684 strlen(name) + 1 +
7685 sizeof(char *) * aliases +
7686 aliases_size +
7687 sizeof(char *) * addresses +
7688 address_length * (addresses - 1)), i;
7690 if (!(p_to = check_buffer_he(size))) return NULL;
7691 memset(p_to, 0, size);
7693 /* Use the memory in the same way winsock does.
7694 * First set the pointer for aliases, second set the pointers for addresses.
7695 * Third fill the addresses indexes, fourth jump aliases names size.
7696 * Fifth fill the hostname.
7697 * NOTE: This method is valid for OS versions >= XP.
7699 p = (char *)(p_to + 1);
7700 p_to->h_aliases = (char **)p;
7701 p += sizeof(char *)*aliases;
7703 p_to->h_addr_list = (char **)p;
7704 p += sizeof(char *)*addresses;
7706 for (i = 0, addresses--; i < addresses; i++, p += address_length)
7707 p_to->h_addr_list[i] = p;
7709 /* NOTE: h_aliases must be filled in manually because we don't know each string
7710 * size, leave these pointers NULL (already set to NULL by memset earlier).
7712 p += aliases_size;
7714 p_to->h_name = p;
7715 strcpy(p, name);
7717 return p_to;
7720 /* duplicate hostent entry
7721 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
7722 * Ditto for protoent and servent.
7724 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
7726 int i, addresses = 0, alias_size = 0;
7727 struct WS_hostent *p_to;
7728 char *p;
7730 for( i = 0; p_he->h_aliases[i]; i++) alias_size += strlen(p_he->h_aliases[i]) + 1;
7731 while (p_he->h_addr_list[addresses]) addresses++;
7733 p_to = WS_create_he(p_he->h_name, i + 1, alias_size, addresses + 1, p_he->h_length);
7735 if (!p_to) return NULL;
7736 p_to->h_addrtype = convert_af_u2w(p_he->h_addrtype);
7737 p_to->h_length = p_he->h_length;
7739 for(i = 0, p = p_to->h_addr_list[0]; p_he->h_addr_list[i]; i++, p += p_to->h_length)
7740 memcpy(p, p_he->h_addr_list[i], p_to->h_length);
7742 /* Fill the aliases after the IP data */
7743 for(i = 0; p_he->h_aliases[i]; i++)
7745 p_to->h_aliases[i] = p;
7746 strcpy(p, p_he->h_aliases[i]);
7747 p += strlen(p) + 1;
7750 return p_to;
7753 /* ----- protoent */
7755 static struct WS_protoent *WS_create_pe( const char *name, char **aliases, int prot )
7757 struct WS_protoent *ret;
7758 unsigned int size = sizeof(*ret) + strlen(name) + sizeof(char *) + list_size(aliases, 0);
7760 if (!(ret = check_buffer_pe( size ))) return NULL;
7761 ret->p_proto = prot;
7762 ret->p_name = (char *)(ret + 1);
7763 strcpy( ret->p_name, name );
7764 ret->p_aliases = (char **)ret->p_name + strlen(name) / sizeof(char *) + 1;
7765 list_dup( aliases, ret->p_aliases, 0 );
7766 return ret;
7769 /* ----- servent */
7771 static struct WS_servent *WS_dup_se(const struct servent* p_se)
7773 char *p;
7774 struct WS_servent *p_to;
7776 int size = (sizeof(*p_se) +
7777 strlen(p_se->s_proto) + 1 +
7778 strlen(p_se->s_name) + 1 +
7779 list_size(p_se->s_aliases, 0));
7781 if (!(p_to = check_buffer_se(size))) return NULL;
7782 p_to->s_port = p_se->s_port;
7784 p = (char *)(p_to + 1);
7785 p_to->s_name = p;
7786 strcpy(p, p_se->s_name);
7787 p += strlen(p) + 1;
7789 p_to->s_proto = p;
7790 strcpy(p, p_se->s_proto);
7791 p += strlen(p) + 1;
7793 p_to->s_aliases = (char **)p;
7794 list_dup(p_se->s_aliases, p_to->s_aliases, 0);
7795 return p_to;
7799 /***********************************************************************
7800 * WSARecv (WS2_32.67)
7802 int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
7803 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
7804 LPWSAOVERLAPPED lpOverlapped,
7805 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
7807 return WS2_recv_base(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
7808 NULL, NULL, lpOverlapped, lpCompletionRoutine, NULL);
7811 static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
7812 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags,
7813 struct WS_sockaddr *lpFrom,
7814 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
7815 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
7816 LPWSABUF lpControlBuffer )
7818 unsigned int i, options;
7819 int n, fd, err, overlapped, flags;
7820 struct ws2_async *wsa = NULL, localwsa;
7821 BOOL is_blocking;
7822 DWORD timeout_start = GetTickCount();
7823 ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
7825 TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, from %p, fromlen %d, ovl %p, func %p\n",
7826 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
7827 (lpFromlen ? *lpFromlen : -1),
7828 lpOverlapped, lpCompletionRoutine);
7830 fd = get_sock_fd( s, FILE_READ_DATA, &options );
7831 TRACE( "fd=%d, options=%x\n", fd, options );
7833 if (fd == -1) return SOCKET_ERROR;
7835 if (*lpFlags & WS_MSG_OOB)
7837 /* It's invalid to receive OOB data from an OOBINLINED socket
7838 * as OOB data is turned into normal data. */
7839 socklen_t len = sizeof(n);
7840 if (!getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char*) &n, &len) && n)
7842 err = WSAEINVAL;
7843 goto error;
7847 overlapped = (lpOverlapped || lpCompletionRoutine) &&
7848 !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
7849 if (overlapped || dwBufferCount > 1)
7851 if (!(wsa = (struct ws2_async *)alloc_async_io( offsetof(struct ws2_async, iovec[dwBufferCount]),
7852 WS2_async_recv )))
7854 err = WSAEFAULT;
7855 goto error;
7858 else
7859 wsa = &localwsa;
7861 wsa->hSocket = SOCKET2HANDLE(s);
7862 wsa->flags = *lpFlags;
7863 wsa->lpFlags = lpFlags;
7864 wsa->addr = lpFrom;
7865 wsa->addrlen.ptr = lpFromlen;
7866 wsa->control = lpControlBuffer;
7867 wsa->n_iovecs = dwBufferCount;
7868 wsa->first_iovec = 0;
7869 for (i = 0; i < dwBufferCount; i++)
7871 /* check buffer first to trigger write watches */
7872 if (IsBadWritePtr( lpBuffers[i].buf, lpBuffers[i].len ))
7874 err = WSAEFAULT;
7875 goto error;
7877 wsa->iovec[i].iov_base = lpBuffers[i].buf;
7878 wsa->iovec[i].iov_len = lpBuffers[i].len;
7881 flags = convert_flags(wsa->flags);
7882 for (;;)
7884 n = WS2_recv( fd, wsa, flags );
7885 if (n == -1)
7887 /* Unix-like systems return EINVAL when attempting to read OOB data from
7888 * an empty socket buffer, convert that to a Windows expected return. */
7889 if ((flags & MSG_OOB) && errno == EINVAL)
7890 errno = EWOULDBLOCK;
7892 if (errno != EAGAIN)
7894 err = wsaErrno();
7895 goto error;
7898 else if (lpNumberOfBytesRecvd) *lpNumberOfBytesRecvd = n;
7900 if (overlapped)
7902 IO_STATUS_BLOCK *iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
7904 wsa->user_overlapped = lpOverlapped;
7905 wsa->completion_func = lpCompletionRoutine;
7906 release_sock_fd( s, fd );
7908 if (n == -1)
7910 iosb->u.Status = STATUS_PENDING;
7911 iosb->Information = 0;
7913 if (wsa->completion_func)
7914 err = register_async( ASYNC_TYPE_READ, wsa->hSocket, &wsa->io, NULL,
7915 ws2_async_apc, wsa, iosb );
7916 else
7917 err = register_async( ASYNC_TYPE_READ, wsa->hSocket, &wsa->io, lpOverlapped->hEvent,
7918 NULL, (void *)cvalue, iosb );
7920 if (err != STATUS_PENDING) HeapFree( GetProcessHeap(), 0, wsa );
7921 SetLastError(NtStatusToWSAError( err ));
7922 return SOCKET_ERROR;
7925 iosb->u.Status = STATUS_SUCCESS;
7926 iosb->Information = n;
7927 if (!wsa->completion_func)
7929 if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n, FALSE );
7930 if (lpOverlapped->hEvent) SetEvent( lpOverlapped->hEvent );
7931 HeapFree( GetProcessHeap(), 0, wsa );
7933 else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc,
7934 (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 );
7935 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
7936 return 0;
7939 if (n != -1) break;
7941 if ((err = sock_is_blocking( s, &is_blocking ))) goto error;
7943 if ( is_blocking )
7945 struct pollfd pfd;
7946 int poll_timeout = -1;
7947 INT64 timeout = get_rcvsnd_timeo(fd, TRUE);
7949 if (timeout)
7951 timeout -= GetTickCount() - timeout_start;
7952 if (timeout < 0) poll_timeout = 0;
7953 else poll_timeout = timeout <= INT_MAX ? timeout : INT_MAX;
7956 pfd.fd = fd;
7957 pfd.events = POLLIN;
7958 if (*lpFlags & WS_MSG_OOB) pfd.events |= POLLPRI;
7960 if (!poll_timeout || !poll( &pfd, 1, poll_timeout ))
7962 err = WSAETIMEDOUT;
7963 /* a timeout is not fatal */
7964 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
7965 goto error;
7968 else
7970 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
7971 err = WSAEWOULDBLOCK;
7972 goto error;
7976 TRACE(" -> %i bytes\n", n);
7977 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
7978 release_sock_fd( s, fd );
7979 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
7980 SetLastError(ERROR_SUCCESS);
7982 return 0;
7984 error:
7985 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
7986 release_sock_fd( s, fd );
7987 WARN(" -> ERROR %d\n", err);
7988 SetLastError( err );
7989 return SOCKET_ERROR;
7992 /***********************************************************************
7993 * WSARecvFrom (WS2_32.69)
7995 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
7996 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
7997 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
7998 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
8001 return WS2_recv_base( s, lpBuffers, dwBufferCount,
8002 lpNumberOfBytesRecvd, lpFlags,
8003 lpFrom, lpFromlen,
8004 lpOverlapped, lpCompletionRoutine, NULL );
8007 /***********************************************************************
8008 * WSCInstallProvider (WS2_32.88)
8010 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
8011 LPCWSTR lpszProviderDllPath,
8012 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
8013 DWORD dwNumberOfEntries,
8014 LPINT lpErrno )
8016 FIXME("(%s, %s, %p, %d, %p): stub !\n", debugstr_guid(lpProviderId),
8017 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
8018 dwNumberOfEntries, lpErrno);
8019 *lpErrno = 0;
8020 return 0;
8024 /***********************************************************************
8025 * WSCDeinstallProvider (WS2_32.83)
8027 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
8029 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
8030 *lpErrno = 0;
8031 return 0;
8035 /***********************************************************************
8036 * WSAAccept (WS2_32.26)
8038 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
8039 LPCONDITIONPROC lpfnCondition, DWORD_PTR dwCallbackData)
8042 int ret = 0, size;
8043 WSABUF CallerId, CallerData, CalleeId, CalleeData;
8044 /* QOS SQOS, GQOS; */
8045 GROUP g;
8046 SOCKET cs;
8047 SOCKADDR src_addr, dst_addr;
8049 TRACE("socket %04lx, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
8050 s, addr, addrlen, lpfnCondition, dwCallbackData);
8052 cs = WS_accept(s, addr, addrlen);
8053 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
8054 if (!lpfnCondition) return cs;
8056 if (addr && addrlen)
8058 CallerId.buf = (char *)addr;
8059 CallerId.len = *addrlen;
8061 else
8063 size = sizeof(src_addr);
8064 WS_getpeername(cs, &src_addr, &size);
8065 CallerId.buf = (char *)&src_addr;
8066 CallerId.len = size;
8068 CallerData.buf = NULL;
8069 CallerData.len = 0;
8071 size = sizeof(dst_addr);
8072 WS_getsockname(cs, &dst_addr, &size);
8074 CalleeId.buf = (char *)&dst_addr;
8075 CalleeId.len = sizeof(dst_addr);
8077 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
8078 &CalleeId, &CalleeData, &g, dwCallbackData);
8080 switch (ret)
8082 case CF_ACCEPT:
8083 return cs;
8084 case CF_DEFER:
8085 SERVER_START_REQ( set_socket_deferred )
8087 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
8088 req->deferred = wine_server_obj_handle( SOCKET2HANDLE(cs) );
8089 if ( !wine_server_call_err ( req ) )
8091 SetLastError( WSATRY_AGAIN );
8092 WS_closesocket( cs );
8095 SERVER_END_REQ;
8096 return SOCKET_ERROR;
8097 case CF_REJECT:
8098 WS_closesocket(cs);
8099 SetLastError(WSAECONNREFUSED);
8100 return SOCKET_ERROR;
8101 default:
8102 FIXME("Unknown return type from Condition function\n");
8103 SetLastError(WSAENOTSOCK);
8104 return SOCKET_ERROR;
8108 /***********************************************************************
8109 * WSADuplicateSocketA (WS2_32.32)
8111 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
8113 return WS_DuplicateSocket(FALSE, s, dwProcessId, (LPWSAPROTOCOL_INFOW) lpProtocolInfo);
8116 /***********************************************************************
8117 * WSADuplicateSocketW (WS2_32.33)
8119 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
8121 return WS_DuplicateSocket(TRUE, s, dwProcessId, lpProtocolInfo);
8124 /***********************************************************************
8125 * WSAInstallServiceClassA (WS2_32.48)
8127 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
8129 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
8130 SetLastError(WSAEACCES);
8131 return SOCKET_ERROR;
8134 /***********************************************************************
8135 * WSAInstallServiceClassW (WS2_32.49)
8137 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
8139 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
8140 SetLastError(WSAEACCES);
8141 return SOCKET_ERROR;
8144 /***********************************************************************
8145 * WSARemoveServiceClass (WS2_32.70)
8147 int WINAPI WSARemoveServiceClass(LPGUID info)
8149 FIXME("Request to remove service %s\n", debugstr_guid(info));
8150 SetLastError(WSATYPE_NOT_FOUND);
8151 return SOCKET_ERROR;
8154 /***********************************************************************
8155 * inet_ntop (WS2_32.@)
8157 PCSTR WINAPI WS_inet_ntop( INT family, PVOID addr, PSTR buffer, SIZE_T len )
8159 NTSTATUS status;
8160 ULONG size = min( len, (ULONG)-1 );
8162 TRACE("family %d, addr (%p), buffer (%p), len %ld\n", family, addr, buffer, len);
8163 if (!buffer)
8165 SetLastError( STATUS_INVALID_PARAMETER );
8166 return NULL;
8169 switch (family)
8171 case WS_AF_INET:
8173 status = RtlIpv4AddressToStringExA( (IN_ADDR *)addr, 0, buffer, &size );
8174 break;
8176 case WS_AF_INET6:
8178 status = RtlIpv6AddressToStringExA( (IN6_ADDR *)addr, 0, 0, buffer, &size );
8179 break;
8181 default:
8182 SetLastError( WSAEAFNOSUPPORT );
8183 return NULL;
8186 if (status == STATUS_SUCCESS) return buffer;
8187 SetLastError( STATUS_INVALID_PARAMETER );
8188 return NULL;
8191 /***********************************************************************
8192 * inet_pton (WS2_32.@)
8194 INT WINAPI WS_inet_pton(INT family, const char *addr, void *buffer)
8196 NTSTATUS status;
8197 const char *terminator;
8199 TRACE("family %d, addr %s, buffer (%p)\n", family, debugstr_a(addr), buffer);
8201 if (!addr || !buffer)
8203 SetLastError(WSAEFAULT);
8204 return SOCKET_ERROR;
8207 switch (family)
8209 case WS_AF_INET:
8210 status = RtlIpv4StringToAddressA(addr, TRUE, &terminator, buffer);
8211 break;
8212 case WS_AF_INET6:
8213 status = RtlIpv6StringToAddressA(addr, &terminator, buffer);
8214 break;
8215 default:
8216 SetLastError(WSAEAFNOSUPPORT);
8217 return SOCKET_ERROR;
8220 return (status == STATUS_SUCCESS && *terminator == 0);
8223 /***********************************************************************
8224 * InetPtonW (WS2_32.@)
8226 INT WINAPI InetPtonW(INT family, PCWSTR addr, PVOID buffer)
8228 char *addrA;
8229 int len;
8230 INT ret;
8232 TRACE("family %d, addr %s, buffer (%p)\n", family, debugstr_w(addr), buffer);
8234 if (!addr)
8236 SetLastError(WSAEFAULT);
8237 return SOCKET_ERROR;
8240 len = WideCharToMultiByte(CP_ACP, 0, addr, -1, NULL, 0, NULL, NULL);
8241 if (!(addrA = HeapAlloc(GetProcessHeap(), 0, len)))
8243 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8244 return SOCKET_ERROR;
8246 WideCharToMultiByte(CP_ACP, 0, addr, -1, addrA, len, NULL, NULL);
8248 ret = WS_inet_pton(family, addrA, buffer);
8249 if (!ret) SetLastError(WSAEINVAL);
8251 HeapFree(GetProcessHeap(), 0, addrA);
8252 return ret;
8255 /***********************************************************************
8256 * InetNtopW (WS2_32.@)
8258 PCWSTR WINAPI InetNtopW(INT family, PVOID addr, PWSTR buffer, SIZE_T len)
8260 char bufferA[WS_INET6_ADDRSTRLEN];
8261 PWSTR ret = NULL;
8263 TRACE("family %d, addr (%p), buffer (%p), len %ld\n", family, addr, buffer, len);
8265 if (WS_inet_ntop(family, addr, bufferA, sizeof(bufferA)))
8267 if (MultiByteToWideChar(CP_ACP, 0, bufferA, -1, buffer, len))
8268 ret = buffer;
8269 else
8270 SetLastError(ERROR_INVALID_PARAMETER);
8272 return ret;
8275 /***********************************************************************
8276 * WSAStringToAddressA (WS2_32.80)
8278 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
8279 INT AddressFamily,
8280 LPWSAPROTOCOL_INFOA lpProtocolInfo,
8281 LPSOCKADDR lpAddress,
8282 LPINT lpAddressLength)
8284 INT res=0;
8285 NTSTATUS status;
8287 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_a(AddressString), AddressFamily,
8288 lpProtocolInfo, lpAddress, lpAddressLength );
8290 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
8292 if (!AddressString)
8294 SetLastError(WSAEINVAL);
8295 return SOCKET_ERROR;
8298 if (lpProtocolInfo)
8299 FIXME("ProtocolInfo not implemented.\n");
8301 switch(AddressFamily)
8303 case WS_AF_INET:
8305 SOCKADDR_IN *addr4 = (SOCKADDR_IN *)lpAddress;
8307 /* If lpAddressLength is too small, tell caller the size we need */
8308 if (*lpAddressLength < sizeof(SOCKADDR_IN))
8310 *lpAddressLength = sizeof(SOCKADDR_IN);
8311 res = WSAEFAULT;
8312 break;
8314 memset(lpAddress, 0, sizeof(SOCKADDR_IN));
8316 status = RtlIpv4StringToAddressExA(AddressString, FALSE, &addr4->sin_addr, &addr4->sin_port);
8317 if (status != STATUS_SUCCESS)
8319 res = WSAEINVAL;
8320 break;
8322 addr4->sin_family = WS_AF_INET;
8323 *lpAddressLength = sizeof(SOCKADDR_IN);
8324 break;
8326 case WS_AF_INET6:
8328 SOCKADDR_IN6 *addr6 = (SOCKADDR_IN6 *)lpAddress;
8330 /* If lpAddressLength is too small, tell caller the size we need */
8331 if (*lpAddressLength < sizeof(SOCKADDR_IN6))
8333 *lpAddressLength = sizeof(SOCKADDR_IN6);
8334 res = WSAEFAULT;
8335 break;
8337 memset(lpAddress, 0, sizeof(SOCKADDR_IN6));
8339 status = RtlIpv6StringToAddressExA(AddressString, &addr6->sin6_addr, &addr6->sin6_scope_id, &addr6->sin6_port);
8340 if (status != STATUS_SUCCESS)
8342 res = WSAEINVAL;
8343 break;
8345 addr6->sin6_family = WS_AF_INET6;
8346 *lpAddressLength = sizeof(SOCKADDR_IN6);
8347 break;
8349 default:
8350 /* According to MSDN, only AF_INET and AF_INET6 are supported. */
8351 TRACE("Unsupported address family specified: %d.\n", AddressFamily);
8352 res = WSAEINVAL;
8355 if (!res) return 0;
8356 SetLastError(res);
8357 return SOCKET_ERROR;
8360 /***********************************************************************
8361 * WSAStringToAddressW (WS2_32.81)
8363 * FIXME: Does anybody know if this function allows using Hebrew/Arabic/Chinese... digits?
8364 * If this should be the case, it would be required to map these digits
8365 * to Unicode digits (0-9) using FoldString first.
8367 INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
8368 INT AddressFamily,
8369 LPWSAPROTOCOL_INFOW lpProtocolInfo,
8370 LPSOCKADDR lpAddress,
8371 LPINT lpAddressLength)
8373 INT sBuffer,res=0;
8374 LPSTR workBuffer=NULL;
8375 WSAPROTOCOL_INFOA infoA;
8376 LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
8378 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
8379 lpAddress, lpAddressLength );
8381 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
8383 /* if ProtocolInfo is available - convert to ANSI variant */
8384 if (lpProtocolInfo)
8386 lpProtoInfoA = &infoA;
8387 memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
8389 if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
8390 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
8392 SetLastError(WSAEINVAL);
8393 return SOCKET_ERROR;
8397 if (AddressString)
8399 /* Translate AddressString to ANSI code page - assumes that only
8400 standard digits 0-9 are used with this API call */
8401 sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
8402 workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
8404 if (workBuffer)
8406 WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
8407 res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
8408 lpAddress,lpAddressLength);
8409 HeapFree( GetProcessHeap(), 0, workBuffer );
8410 return res;
8412 else
8413 res = WSA_NOT_ENOUGH_MEMORY;
8415 else
8416 res = WSAEINVAL;
8418 SetLastError(res);
8419 return SOCKET_ERROR;
8422 /***********************************************************************
8423 * WSAAddressToStringA (WS2_32.27)
8425 * See WSAAddressToStringW
8427 INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
8428 LPWSAPROTOCOL_INFOA info, LPSTR string,
8429 LPDWORD lenstr )
8431 DWORD size;
8432 CHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
8433 CHAR *p;
8435 TRACE( "(%p, %d, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
8437 if (!sockaddr) return SOCKET_ERROR;
8438 if (!string || !lenstr) return SOCKET_ERROR;
8440 switch(sockaddr->sa_family)
8442 case WS_AF_INET:
8444 unsigned int long_ip = ntohl(((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr);
8445 if (len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
8446 sprintf( buffer, "%u.%u.%u.%u:%u",
8447 (long_ip >> 24) & 0xff,
8448 (long_ip >> 16) & 0xff,
8449 (long_ip >> 8) & 0xff,
8450 long_ip & 0xff,
8451 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
8453 p = strchr( buffer, ':' );
8454 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
8455 break;
8457 case WS_AF_INET6:
8459 struct WS_sockaddr_in6 *sockaddr6 = (LPSOCKADDR_IN6) sockaddr;
8460 size_t slen;
8462 buffer[0] = 0;
8463 if (len < sizeof(SOCKADDR_IN6)) return SOCKET_ERROR;
8464 if ((sockaddr6->sin6_port))
8465 strcpy(buffer, "[");
8466 slen = strlen(buffer);
8467 if (!WS_inet_ntop(WS_AF_INET6, &sockaddr6->sin6_addr, &buffer[slen], sizeof(buffer) - slen))
8469 SetLastError(WSAEINVAL);
8470 return SOCKET_ERROR;
8472 if ((sockaddr6->sin6_scope_id))
8473 sprintf(buffer+strlen(buffer), "%%%u", sockaddr6->sin6_scope_id);
8474 if ((sockaddr6->sin6_port))
8475 sprintf(buffer+strlen(buffer), "]:%u", ntohs(sockaddr6->sin6_port));
8476 break;
8479 default:
8480 SetLastError(WSAEINVAL);
8481 return SOCKET_ERROR;
8484 size = strlen( buffer ) + 1;
8486 if (*lenstr < size)
8488 *lenstr = size;
8489 SetLastError(WSAEFAULT);
8490 return SOCKET_ERROR;
8493 TRACE("=> %s,%u bytes\n", debugstr_a(buffer), size);
8494 *lenstr = size;
8495 strcpy( string, buffer );
8496 return 0;
8499 /***********************************************************************
8500 * WSAAddressToStringW (WS2_32.28)
8502 * Convert a sockaddr address into a readable address string.
8504 * PARAMS
8505 * sockaddr [I] Pointer to a sockaddr structure.
8506 * len [I] Size of the sockaddr structure.
8507 * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional).
8508 * string [I/O] Pointer to a buffer to receive the address string.
8509 * lenstr [I/O] Size of the receive buffer in WCHARs.
8511 * RETURNS
8512 * Success: 0
8513 * Failure: SOCKET_ERROR
8515 * NOTES
8516 * The 'info' parameter is ignored.
8518 INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
8519 LPWSAPROTOCOL_INFOW info, LPWSTR string,
8520 LPDWORD lenstr )
8522 INT ret;
8523 char buf[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
8525 TRACE( "(%p, %d, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
8527 if ((ret = WSAAddressToStringA(sockaddr, len, NULL, buf, lenstr))) return ret;
8529 MultiByteToWideChar(CP_ACP, 0, buf, *lenstr, string, *lenstr);
8530 TRACE("=> %s,%u chars\n", debugstr_w(string), *lenstr);
8531 return 0;
8534 /***********************************************************************
8535 * WSAEnumNameSpaceProvidersA (WS2_32.34)
8537 INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
8539 FIXME( "(%p %p) Stub!\n", len, buffer );
8540 return 0;
8543 /***********************************************************************
8544 * WSAEnumNameSpaceProvidersW (WS2_32.35)
8546 INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
8548 FIXME( "(%p %p) Stub!\n", len, buffer );
8549 return 0;
8552 /***********************************************************************
8553 * WSAGetQOSByName (WS2_32.41)
8555 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
8557 FIXME( "(0x%04lx %p %p) Stub!\n", s, lpQOSName, lpQOS );
8558 return FALSE;
8561 /***********************************************************************
8562 * WSAGetServiceClassInfoA (WS2_32.42)
8564 INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
8565 LPWSASERVICECLASSINFOA info )
8567 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
8568 len, info );
8569 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8570 return SOCKET_ERROR;
8573 /***********************************************************************
8574 * WSAGetServiceClassInfoW (WS2_32.43)
8576 INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
8577 LPWSASERVICECLASSINFOW info )
8579 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
8580 len, info );
8581 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8582 return SOCKET_ERROR;
8585 /***********************************************************************
8586 * WSAGetServiceClassNameByClassIdA (WS2_32.44)
8588 INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
8590 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
8591 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8592 return SOCKET_ERROR;
8595 /***********************************************************************
8596 * WSAGetServiceClassNameByClassIdW (WS2_32.45)
8598 INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
8600 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
8601 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8602 return SOCKET_ERROR;
8605 /***********************************************************************
8606 * WSALookupServiceBeginA (WS2_32.59)
8608 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
8609 DWORD dwControlFlags,
8610 LPHANDLE lphLookup)
8612 FIXME("(%p 0x%08x %p) Stub!\n", lpqsRestrictions, dwControlFlags,
8613 lphLookup);
8614 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8615 return SOCKET_ERROR;
8618 /***********************************************************************
8619 * WSALookupServiceBeginW (WS2_32.60)
8621 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
8622 DWORD dwControlFlags,
8623 LPHANDLE lphLookup)
8625 FIXME("(%p 0x%08x %p) Stub!\n", lpqsRestrictions, dwControlFlags,
8626 lphLookup);
8627 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8628 return SOCKET_ERROR;
8631 /***********************************************************************
8632 * WSALookupServiceEnd (WS2_32.61)
8634 INT WINAPI WSALookupServiceEnd( HANDLE lookup )
8636 FIXME("(%p) Stub!\n", lookup );
8637 return 0;
8640 /***********************************************************************
8641 * WSALookupServiceNextA (WS2_32.62)
8643 INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
8645 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup, flags, len, results );
8646 SetLastError(WSA_E_NO_MORE);
8647 return SOCKET_ERROR;
8650 /***********************************************************************
8651 * WSALookupServiceNextW (WS2_32.63)
8653 INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
8655 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup, flags, len, results );
8656 SetLastError(WSA_E_NO_MORE);
8657 return SOCKET_ERROR;
8660 /***********************************************************************
8661 * WSANtohl (WS2_32.64)
8663 INT WINAPI WSANtohl( SOCKET s, WS_u_long netlong, WS_u_long* lphostlong )
8665 TRACE( "(%04lx 0x%08x %p)\n", s, netlong, lphostlong );
8667 if (!lphostlong) return WSAEFAULT;
8669 *lphostlong = ntohl( netlong );
8670 return 0;
8673 /***********************************************************************
8674 * WSANtohs (WS2_32.65)
8676 INT WINAPI WSANtohs( SOCKET s, WS_u_short netshort, WS_u_short* lphostshort )
8678 TRACE( "(%04lx 0x%08x %p)\n", s, netshort, lphostshort );
8680 if (!lphostshort) return WSAEFAULT;
8682 *lphostshort = ntohs( netshort );
8683 return 0;
8686 /***********************************************************************
8687 * WSAProviderConfigChange (WS2_32.66)
8689 INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
8690 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
8692 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
8693 return SOCKET_ERROR;
8696 /***********************************************************************
8697 * WSARecvDisconnect (WS2_32.68)
8699 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
8701 TRACE( "(%04lx %p)\n", s, disconnectdata );
8703 return WS_shutdown( s, SD_RECEIVE );
8706 /***********************************************************************
8707 * WSASetServiceA (WS2_32.76)
8709 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
8711 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query, operation, flags );
8712 return 0;
8715 /***********************************************************************
8716 * WSASetServiceW (WS2_32.77)
8718 INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
8720 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query, operation, flags );
8721 return 0;
8724 /***********************************************************************
8725 * WSCEnableNSProvider (WS2_32.84)
8727 INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
8729 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
8730 return 0;
8733 /***********************************************************************
8734 * WSCGetProviderInfo
8736 INT WINAPI WSCGetProviderInfo( LPGUID provider, WSC_PROVIDER_INFO_TYPE info_type,
8737 PBYTE info, size_t* len, DWORD flags, LPINT errcode )
8739 FIXME( "(%s 0x%08x %p %p 0x%08x %p) Stub!\n",
8740 debugstr_guid(provider), info_type, info, len, flags, errcode );
8742 if (!errcode)
8743 return SOCKET_ERROR;
8745 if (!provider) {
8746 *errcode = WSAEFAULT;
8747 return SOCKET_ERROR;
8750 *errcode = WSANO_RECOVERY;
8751 return SOCKET_ERROR;
8754 /***********************************************************************
8755 * WSCGetProviderPath (WS2_32.86)
8757 INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errcode )
8759 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errcode );
8761 if (!provider || !len)
8763 if (errcode)
8764 *errcode = WSAEFAULT;
8765 return SOCKET_ERROR;
8768 if (*len <= 0)
8770 if (errcode)
8771 *errcode = WSAEINVAL;
8772 return SOCKET_ERROR;
8775 return 0;
8778 /***********************************************************************
8779 * WSCInstallNameSpace (WS2_32.87)
8781 INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
8782 DWORD version, LPGUID provider )
8784 FIXME( "(%s %s 0x%08x 0x%08x %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
8785 namespace, version, debugstr_guid(provider) );
8786 return 0;
8789 /***********************************************************************
8790 * WSCUnInstallNameSpace (WS2_32.89)
8792 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
8794 FIXME("(%s) Stub!\n", debugstr_guid(lpProviderId));
8795 return NO_ERROR;
8798 /***********************************************************************
8799 * WSCWriteProviderOrder (WS2_32.91)
8801 INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
8803 FIXME("(%p 0x%08x) Stub!\n", entry, number);
8804 return 0;
8807 /***********************************************************************
8808 * WSCSetApplicationCategory (WS2_32.@)
8810 INT WINAPI WSCSetApplicationCategory( LPCWSTR path, DWORD len, LPCWSTR extra, DWORD extralen,
8811 DWORD lspcat, DWORD *prev_lspcat, LPINT err )
8813 FIXME("(%s %d %s %d %d %p) Stub!\n", debugstr_w(path), len, debugstr_w(extra),
8814 extralen, lspcat, prev_lspcat);
8815 return 0;
8818 /***********************************************************************
8819 * WSANSPIoctl (WS2_32.91)
8821 INT WINAPI WSANSPIoctl( HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer,
8822 DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
8823 LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion )
8825 FIXME("(%p, 0x%08x, %p, 0x%08x, %p, 0x%08x, %p, %p) Stub!\n", hLookup, dwControlCode,
8826 lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpCompletion);
8827 SetLastError(WSA_NOT_ENOUGH_MEMORY);
8828 return SOCKET_ERROR;
8831 static BOOL protocol_matches_filter( const int *filter, int protocol )
8833 if (!filter) return TRUE;
8834 while (*filter)
8836 if (protocol == *filter++) return TRUE;
8838 return FALSE;
8841 /*****************************************************************************
8842 * WSAEnumProtocolsA [WS2_32.@]
8844 * see function WSAEnumProtocolsW
8846 int WINAPI WSAEnumProtocolsA( int *filter, WSAPROTOCOL_INFOA *protocols, DWORD *size )
8848 DWORD i, count = 0;
8850 TRACE("filter %p, protocols %p, size %p\n", filter, protocols, size);
8852 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
8854 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
8855 ++count;
8858 if (!protocols || *size < count * sizeof(WSAPROTOCOL_INFOA))
8860 *size = count * sizeof(WSAPROTOCOL_INFOA);
8861 WSASetLastError( WSAENOBUFS );
8862 return SOCKET_ERROR;
8865 count = 0;
8866 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
8868 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
8870 memcpy( &protocols[count], &supported_protocols[i], offsetof( WSAPROTOCOL_INFOW, szProtocol ) );
8871 WideCharToMultiByte( CP_ACP, 0, supported_protocols[i].szProtocol, -1,
8872 protocols[count].szProtocol, sizeof(protocols[count].szProtocol), NULL, NULL );
8873 ++count;
8876 return count;
8879 /*****************************************************************************
8880 * WSAEnumProtocolsW [WS2_32.@]
8882 * Retrieves information about specified set of active network protocols.
8884 * PARAMS
8885 * protocols [I] Pointer to null-terminated array of protocol id's. NULL
8886 * retrieves information on all available protocols.
8887 * buffer [I] Pointer to a buffer to be filled with WSAPROTOCOL_INFO
8888 * structures.
8889 * len [I/O] Pointer to a variable specifying buffer size. On output
8890 * the variable holds the number of bytes needed when the
8891 * specified size is too small.
8893 * RETURNS
8894 * Success: number of WSAPROTOCOL_INFO structures in buffer.
8895 * Failure: SOCKET_ERROR
8897 * NOTES
8898 * NT4SP5 does not return SPX if protocols == NULL
8900 * BUGS
8901 * - NT4SP5 returns in addition these list of NETBIOS protocols
8902 * (address family 17), each entry two times one for socket type 2 and 5
8904 * iProtocol szProtocol
8905 * 0x80000000 \Device\NwlnkNb
8906 * 0xfffffffa \Device\NetBT_CBENT7
8907 * 0xfffffffb \Device\Nbf_CBENT7
8908 * 0xfffffffc \Device\NetBT_NdisWan5
8909 * 0xfffffffd \Device\NetBT_El9202
8910 * 0xfffffffe \Device\Nbf_El9202
8911 * 0xffffffff \Device\Nbf_NdisWan4
8913 * - there is no check that the operating system supports the returned
8914 * protocols
8916 int WINAPI WSAEnumProtocolsW( int *filter, WSAPROTOCOL_INFOW *protocols, DWORD *size )
8918 DWORD i, count = 0;
8920 TRACE("filter %p, protocols %p, size %p\n", filter, protocols, size);
8922 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
8924 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
8925 ++count;
8928 if (!protocols || *size < count * sizeof(WSAPROTOCOL_INFOW))
8930 *size = count * sizeof(WSAPROTOCOL_INFOW);
8931 WSASetLastError( WSAENOBUFS );
8932 return SOCKET_ERROR;
8935 count = 0;
8936 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
8938 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
8939 protocols[count++] = supported_protocols[i];
8941 return count;
8944 /*****************************************************************************
8945 * WSCEnumProtocols [WS2_32.@]
8947 * PARAMS
8948 * protocols [I] Null-terminated array of iProtocol values.
8949 * buffer [O] Buffer of WSAPROTOCOL_INFOW structures.
8950 * len [I/O] Size of buffer on input/output.
8951 * errno [O] Error code.
8953 * RETURNS
8954 * Success: number of protocols to be reported on.
8955 * Failure: SOCKET_ERROR. error is in errno.
8957 * BUGS
8958 * Doesn't supply info on layered protocols.
8961 INT WINAPI WSCEnumProtocols( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len, LPINT err )
8963 INT ret = WSAEnumProtocolsW( protocols, buffer, len );
8965 if (ret == SOCKET_ERROR) *err = WSAENOBUFS;
8967 return ret;