ws2_32/tests: Add some tests for opening the Afd device.
[wine.git] / dlls / ws2_32 / socket.c
blob3632397ef3d444cd475ee253dd253233ffaa0b8d
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 "ws2_32_private.h"
34 #if defined(linux) && !defined(IP_UNICAST_IF)
35 #define IP_UNICAST_IF 50
36 #endif
38 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
39 # define sipx_network sipx_addr.x_net
40 # define sipx_node sipx_addr.x_host.c_host
41 #endif /* __FreeBSD__ */
43 #if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE)
44 /* TCP_KEEPALIVE is the Mac OS name for TCP_KEEPIDLE */
45 #define TCP_KEEPIDLE TCP_KEEPALIVE
46 #endif
48 #define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2)
50 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
51 WINE_DECLARE_DEBUG_CHANNEL(winediag);
53 static const WSAPROTOCOL_INFOW supported_protocols[] =
56 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_EXPEDITED_DATA | XP1_GRACEFUL_CLOSE
57 | XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY,
58 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
59 .ProviderId = {0xe70f1aa0, 0xab8b, 0x11cf, {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
60 .dwCatalogEntryId = 1001,
61 .ProtocolChain.ChainLen = 1,
62 .iVersion = 2,
63 .iAddressFamily = WS_AF_INET,
64 .iMaxSockAddr = sizeof(struct WS_sockaddr_in),
65 .iMinSockAddr = sizeof(struct WS_sockaddr_in),
66 .iSocketType = WS_SOCK_STREAM,
67 .iProtocol = WS_IPPROTO_TCP,
68 .szProtocol = {'T','C','P','/','I','P',0},
71 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST
72 | XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | XP1_CONNECTIONLESS,
73 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
74 .ProviderId = {0xe70f1aa0, 0xab8b, 0x11cf, {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
75 .dwCatalogEntryId = 1002,
76 .ProtocolChain.ChainLen = 1,
77 .iVersion = 2,
78 .iAddressFamily = WS_AF_INET,
79 .iMaxSockAddr = sizeof(struct WS_sockaddr_in),
80 .iMinSockAddr = sizeof(struct WS_sockaddr_in),
81 .iSocketType = WS_SOCK_DGRAM,
82 .iProtocol = WS_IPPROTO_UDP,
83 .dwMessageSize = 0xffbb,
84 .szProtocol = {'U','D','P','/','I','P',0},
87 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_EXPEDITED_DATA | XP1_GRACEFUL_CLOSE
88 | XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY,
89 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
90 .ProviderId = {0xf9eab0c0, 0x26d4, 0x11d0, {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},
91 .dwCatalogEntryId = 1004,
92 .ProtocolChain.ChainLen = 1,
93 .iVersion = 2,
94 .iAddressFamily = WS_AF_INET6,
95 .iMaxSockAddr = sizeof(struct WS_sockaddr_in6),
96 .iMinSockAddr = sizeof(struct WS_sockaddr_in6),
97 .iSocketType = WS_SOCK_STREAM,
98 .iProtocol = WS_IPPROTO_TCP,
99 .szProtocol = {'T','C','P','/','I','P','v','6',0},
102 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST
103 | XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | XP1_CONNECTIONLESS,
104 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
105 .ProviderId = {0xf9eab0c0, 0x26d4, 0x11d0, {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},
106 .dwCatalogEntryId = 1005,
107 .ProtocolChain.ChainLen = 1,
108 .iVersion = 2,
109 .iAddressFamily = WS_AF_INET6,
110 .iMaxSockAddr = sizeof(struct WS_sockaddr_in6),
111 .iMinSockAddr = sizeof(struct WS_sockaddr_in6),
112 .iSocketType = WS_SOCK_DGRAM,
113 .iProtocol = WS_IPPROTO_UDP,
114 .dwMessageSize = 0xffbb,
115 .szProtocol = {'U','D','P','/','I','P','v','6',0},
118 .dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_SUPPORT_BROADCAST
119 | XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | XP1_CONNECTIONLESS,
120 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
121 .ProviderId = {0x11058240, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
122 .dwCatalogEntryId = 1030,
123 .ProtocolChain.ChainLen = 1,
124 .iVersion = 2,
125 .iAddressFamily = WS_AF_IPX,
126 .iMaxSockAddr = sizeof(struct WS_sockaddr),
127 .iMinSockAddr = sizeof(struct WS_sockaddr_ipx),
128 .iSocketType = WS_SOCK_DGRAM,
129 .iProtocol = WS_NSPROTO_IPX,
130 .iProtocolMaxOffset = 255,
131 .dwMessageSize = 0x240,
132 .szProtocol = {'I','P','X',0},
135 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED
136 | XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY,
137 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
138 .ProviderId = {0x11058241, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
139 .dwCatalogEntryId = 1031,
140 .ProtocolChain.ChainLen = 1,
141 .iVersion = 2,
142 .iAddressFamily = WS_AF_IPX,
143 .iMaxSockAddr = sizeof(struct WS_sockaddr),
144 .iMinSockAddr = sizeof(struct WS_sockaddr_ipx),
145 .iSocketType = WS_SOCK_SEQPACKET,
146 .iProtocol = WS_NSPROTO_SPX,
147 .dwMessageSize = UINT_MAX,
148 .szProtocol = {'S','P','X',0},
151 .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE | XP1_PSEUDO_STREAM
152 | XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY,
153 .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
154 .ProviderId = {0x11058241, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
155 .dwCatalogEntryId = 1033,
156 .ProtocolChain.ChainLen = 1,
157 .iVersion = 2,
158 .iAddressFamily = WS_AF_IPX,
159 .iMaxSockAddr = sizeof(struct WS_sockaddr),
160 .iMinSockAddr = sizeof(struct WS_sockaddr_ipx),
161 .iSocketType = WS_SOCK_SEQPACKET,
162 .iProtocol = WS_NSPROTO_SPXII,
163 .dwMessageSize = UINT_MAX,
164 .szProtocol = {'S','P','X',' ','I','I',0},
168 #if defined(IP_UNICAST_IF) && defined(SO_ATTACH_FILTER)
169 # define LINUX_BOUND_IF
170 struct interface_filter {
171 struct sock_filter iface_memaddr;
172 struct sock_filter iface_rule;
173 struct sock_filter ip_memaddr;
174 struct sock_filter ip_rule;
175 struct sock_filter return_keep;
176 struct sock_filter return_dump;
178 # define FILTER_JUMP_DUMP(here) (u_char)(offsetof(struct interface_filter, return_dump) \
179 -offsetof(struct interface_filter, here)-sizeof(struct sock_filter)) \
180 /sizeof(struct sock_filter)
181 # define FILTER_JUMP_KEEP(here) (u_char)(offsetof(struct interface_filter, return_keep) \
182 -offsetof(struct interface_filter, here)-sizeof(struct sock_filter)) \
183 /sizeof(struct sock_filter)
184 # define FILTER_JUMP_NEXT() (u_char)(0)
185 # define SKF_NET_DESTIP 16 /* offset in the network header to the destination IP */
186 static struct interface_filter generic_interface_filter = {
187 /* This filter rule allows incoming packets on the specified interface, which works for all
188 * remotely generated packets and for locally generated broadcast packets. */
189 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, SKF_AD_OFF+SKF_AD_IFINDEX),
190 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xdeadbeef, FILTER_JUMP_KEEP(iface_rule), FILTER_JUMP_NEXT()),
191 /* This rule allows locally generated packets targeted at the specific IP address of the chosen
192 * adapter (local packets not destined for the broadcast address do not have IFINDEX set) */
193 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, SKF_NET_OFF+SKF_NET_DESTIP),
194 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xdeadbeef, FILTER_JUMP_KEEP(ip_rule), FILTER_JUMP_DUMP(ip_rule)),
195 BPF_STMT(BPF_RET+BPF_K, (u_int)-1), /* keep packet */
196 BPF_STMT(BPF_RET+BPF_K, 0) /* dump packet */
198 #endif /* LINUX_BOUND_IF */
200 extern ssize_t CDECL __wine_locked_recvmsg( int fd, struct msghdr *hdr, int flags );
203 * The actual definition of WSASendTo, wrapped in a different function name
204 * so that internal calls from ws2_32 itself will not trigger programs like
205 * Garena, which hooks WSASendTo/WSARecvFrom calls.
207 static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
208 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
209 const struct WS_sockaddr *to, int tolen,
210 LPWSAOVERLAPPED lpOverlapped,
211 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine );
214 * Internal fundamental receive function, essentially WSARecvFrom with an
215 * additional parameter to support message control headers.
217 static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
218 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags,
219 struct WS_sockaddr *lpFrom,
220 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
221 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
222 LPWSABUF lpControlBuffer );
224 DECLARE_CRITICAL_SECTION(cs_if_addr_cache);
225 DECLARE_CRITICAL_SECTION(cs_socket_list);
227 static in_addr_t *if_addr_cache;
228 static unsigned int if_addr_cache_size;
230 static SOCKET *socket_list;
231 static unsigned int socket_list_size;
233 const char *debugstr_sockaddr( const struct WS_sockaddr *a )
235 if (!a) return "(nil)";
236 switch (a->sa_family)
238 case WS_AF_INET:
240 char buf[16];
241 const char *p;
242 struct WS_sockaddr_in *sin = (struct WS_sockaddr_in *)a;
244 p = WS_inet_ntop( WS_AF_INET, &sin->sin_addr, buf, sizeof(buf) );
245 if (!p)
246 p = "(unknown IPv4 address)";
248 return wine_dbg_sprintf("{ family AF_INET, address %s, port %d }",
249 p, ntohs(sin->sin_port));
251 case WS_AF_INET6:
253 char buf[46];
254 const char *p;
255 struct WS_sockaddr_in6 *sin = (struct WS_sockaddr_in6 *)a;
257 p = WS_inet_ntop( WS_AF_INET6, &sin->sin6_addr, buf, sizeof(buf) );
258 if (!p)
259 p = "(unknown IPv6 address)";
260 return wine_dbg_sprintf("{ family AF_INET6, address %s, port %d }",
261 p, ntohs(sin->sin6_port));
263 case WS_AF_IPX:
265 int i;
266 char netnum[16], nodenum[16];
267 struct WS_sockaddr_ipx *sin = (struct WS_sockaddr_ipx *)a;
269 for (i = 0;i < 4; i++) sprintf(netnum + i * 2, "%02X", (unsigned char) sin->sa_netnum[i]);
270 for (i = 0;i < 6; i++) sprintf(nodenum + i * 2, "%02X", (unsigned char) sin->sa_nodenum[i]);
272 return wine_dbg_sprintf("{ family AF_IPX, address %s.%s, ipx socket %d }",
273 netnum, nodenum, sin->sa_socket);
275 case WS_AF_IRDA:
277 DWORD addr;
279 memcpy( &addr, ((const SOCKADDR_IRDA *)a)->irdaDeviceID, sizeof(addr) );
280 addr = ntohl( addr );
281 return wine_dbg_sprintf("{ family AF_IRDA, addr %08x, name %s }",
282 addr,
283 ((const SOCKADDR_IRDA *)a)->irdaServiceName);
285 default:
286 return wine_dbg_sprintf("{ family %d }", a->sa_family);
290 static inline const char *debugstr_sockopt(int level, int optname)
292 const char *stropt = NULL, *strlevel = NULL;
294 #define DEBUG_SOCKLEVEL(x) case (x): strlevel = #x
295 #define DEBUG_SOCKOPT(x) case (x): stropt = #x; break
297 switch(level)
299 DEBUG_SOCKLEVEL(WS_SOL_SOCKET);
300 switch(optname)
302 DEBUG_SOCKOPT(WS_SO_ACCEPTCONN);
303 DEBUG_SOCKOPT(WS_SO_BROADCAST);
304 DEBUG_SOCKOPT(WS_SO_BSP_STATE);
305 DEBUG_SOCKOPT(WS_SO_CONDITIONAL_ACCEPT);
306 DEBUG_SOCKOPT(WS_SO_CONNECT_TIME);
307 DEBUG_SOCKOPT(WS_SO_DEBUG);
308 DEBUG_SOCKOPT(WS_SO_DONTLINGER);
309 DEBUG_SOCKOPT(WS_SO_DONTROUTE);
310 DEBUG_SOCKOPT(WS_SO_ERROR);
311 DEBUG_SOCKOPT(WS_SO_EXCLUSIVEADDRUSE);
312 DEBUG_SOCKOPT(WS_SO_GROUP_ID);
313 DEBUG_SOCKOPT(WS_SO_GROUP_PRIORITY);
314 DEBUG_SOCKOPT(WS_SO_KEEPALIVE);
315 DEBUG_SOCKOPT(WS_SO_LINGER);
316 DEBUG_SOCKOPT(WS_SO_MAX_MSG_SIZE);
317 DEBUG_SOCKOPT(WS_SO_OOBINLINE);
318 DEBUG_SOCKOPT(WS_SO_OPENTYPE);
319 DEBUG_SOCKOPT(WS_SO_PROTOCOL_INFOA);
320 DEBUG_SOCKOPT(WS_SO_PROTOCOL_INFOW);
321 DEBUG_SOCKOPT(WS_SO_RCVBUF);
322 DEBUG_SOCKOPT(WS_SO_RCVTIMEO);
323 DEBUG_SOCKOPT(WS_SO_REUSEADDR);
324 DEBUG_SOCKOPT(WS_SO_SNDBUF);
325 DEBUG_SOCKOPT(WS_SO_SNDTIMEO);
326 DEBUG_SOCKOPT(WS_SO_TYPE);
327 DEBUG_SOCKOPT(WS_SO_UPDATE_CONNECT_CONTEXT);
329 break;
331 DEBUG_SOCKLEVEL(WS_NSPROTO_IPX);
332 switch(optname)
334 DEBUG_SOCKOPT(WS_IPX_PTYPE);
335 DEBUG_SOCKOPT(WS_IPX_FILTERPTYPE);
336 DEBUG_SOCKOPT(WS_IPX_DSTYPE);
337 DEBUG_SOCKOPT(WS_IPX_RECVHDR);
338 DEBUG_SOCKOPT(WS_IPX_MAXSIZE);
339 DEBUG_SOCKOPT(WS_IPX_ADDRESS);
340 DEBUG_SOCKOPT(WS_IPX_MAX_ADAPTER_NUM);
342 break;
344 DEBUG_SOCKLEVEL(WS_SOL_IRLMP);
345 switch(optname)
347 DEBUG_SOCKOPT(WS_IRLMP_ENUMDEVICES);
349 break;
351 DEBUG_SOCKLEVEL(WS_IPPROTO_TCP);
352 switch(optname)
354 DEBUG_SOCKOPT(WS_TCP_BSDURGENT);
355 DEBUG_SOCKOPT(WS_TCP_EXPEDITED_1122);
356 DEBUG_SOCKOPT(WS_TCP_NODELAY);
358 break;
360 DEBUG_SOCKLEVEL(WS_IPPROTO_IP);
361 switch(optname)
363 DEBUG_SOCKOPT(WS_IP_ADD_MEMBERSHIP);
364 DEBUG_SOCKOPT(WS_IP_DONTFRAGMENT);
365 DEBUG_SOCKOPT(WS_IP_DROP_MEMBERSHIP);
366 DEBUG_SOCKOPT(WS_IP_HDRINCL);
367 DEBUG_SOCKOPT(WS_IP_MULTICAST_IF);
368 DEBUG_SOCKOPT(WS_IP_MULTICAST_LOOP);
369 DEBUG_SOCKOPT(WS_IP_MULTICAST_TTL);
370 DEBUG_SOCKOPT(WS_IP_OPTIONS);
371 DEBUG_SOCKOPT(WS_IP_PKTINFO);
372 DEBUG_SOCKOPT(WS_IP_RECEIVE_BROADCAST);
373 DEBUG_SOCKOPT(WS_IP_TOS);
374 DEBUG_SOCKOPT(WS_IP_TTL);
375 DEBUG_SOCKOPT(WS_IP_UNICAST_IF);
377 break;
379 DEBUG_SOCKLEVEL(WS_IPPROTO_IPV6);
380 switch(optname)
382 DEBUG_SOCKOPT(WS_IPV6_ADD_MEMBERSHIP);
383 DEBUG_SOCKOPT(WS_IPV6_DROP_MEMBERSHIP);
384 DEBUG_SOCKOPT(WS_IPV6_MULTICAST_IF);
385 DEBUG_SOCKOPT(WS_IPV6_MULTICAST_HOPS);
386 DEBUG_SOCKOPT(WS_IPV6_MULTICAST_LOOP);
387 DEBUG_SOCKOPT(WS_IPV6_UNICAST_HOPS);
388 DEBUG_SOCKOPT(WS_IPV6_V6ONLY);
389 DEBUG_SOCKOPT(WS_IPV6_UNICAST_IF);
390 DEBUG_SOCKOPT(WS_IPV6_DONTFRAG);
392 break;
394 #undef DEBUG_SOCKLEVEL
395 #undef DEBUG_SOCKOPT
397 if (!strlevel)
398 strlevel = wine_dbg_sprintf("WS_0x%x", level);
399 if (!stropt)
400 stropt = wine_dbg_sprintf("WS_0x%x", optname);
402 return wine_dbg_sprintf("level %s, name %s", strlevel + 3, stropt + 3);
405 static inline const char *debugstr_optval(const char *optval, int optlenval)
407 if (optval && !IS_INTRESOURCE(optval) && optlenval >= 1 && optlenval <= sizeof(DWORD))
409 DWORD value = 0;
410 memcpy(&value, optval, optlenval);
411 return wine_dbg_sprintf("%p (%u)", optval, value);
413 return wine_dbg_sprintf("%p", optval);
416 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
417 #define SOCKET2HANDLE(s) ((HANDLE)(s))
418 #define HANDLE2SOCKET(h) ((SOCKET)(h))
420 static BOOL socket_list_add(SOCKET socket)
422 unsigned int i, new_size;
423 SOCKET *new_array;
425 EnterCriticalSection(&cs_socket_list);
426 for (i = 0; i < socket_list_size; ++i)
428 if (!socket_list[i])
430 socket_list[i] = socket;
431 LeaveCriticalSection(&cs_socket_list);
432 return TRUE;
435 new_size = max(socket_list_size * 2, 8);
436 if (!(new_array = heap_realloc(socket_list, new_size * sizeof(*socket_list))))
438 LeaveCriticalSection(&cs_socket_list);
439 return FALSE;
441 socket_list = new_array;
442 memset(socket_list + socket_list_size, 0, (new_size - socket_list_size) * sizeof(*socket_list));
443 socket_list[socket_list_size] = socket;
444 socket_list_size = new_size;
445 LeaveCriticalSection(&cs_socket_list);
446 return TRUE;
449 static void socket_list_remove(SOCKET socket)
451 unsigned int i;
453 EnterCriticalSection(&cs_socket_list);
454 for (i = 0; i < socket_list_size; ++i)
456 if (socket_list[i] == socket)
458 socket_list[i] = 0;
459 break;
462 LeaveCriticalSection(&cs_socket_list);
465 /****************************************************************
466 * Async IO declarations
467 ****************************************************************/
469 typedef NTSTATUS async_callback_t( void *user, IO_STATUS_BLOCK *io, NTSTATUS status );
471 struct ws2_async_io
473 async_callback_t *callback; /* must be the first field */
474 struct ws2_async_io *next;
477 struct ws2_async_shutdown
479 struct ws2_async_io io;
480 HANDLE hSocket;
481 IO_STATUS_BLOCK iosb;
482 int type;
485 struct ws2_async
487 struct ws2_async_io io;
488 HANDLE hSocket;
489 LPWSAOVERLAPPED user_overlapped;
490 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
491 IO_STATUS_BLOCK local_iosb;
492 struct WS_sockaddr *addr;
493 union
495 int val; /* for send operations */
496 int *ptr; /* for recv operations */
497 } addrlen;
498 DWORD flags;
499 DWORD *lpFlags;
500 WSABUF *control;
501 unsigned int n_iovecs;
502 unsigned int first_iovec;
503 struct iovec iovec[1];
506 struct ws2_accept_async
508 struct ws2_async_io io;
509 HANDLE listen_socket;
510 HANDLE accept_socket;
511 LPOVERLAPPED user_overlapped;
512 ULONG_PTR cvalue;
513 PVOID buf; /* buffer to write data to */
514 int data_len;
515 int local_len;
516 int remote_len;
517 struct ws2_async *read;
520 struct ws2_transmitfile_async
522 struct ws2_async_io io;
523 char *buffer;
524 HANDLE file;
525 DWORD file_read;
526 DWORD file_bytes;
527 DWORD bytes_per_send;
528 TRANSMIT_FILE_BUFFERS buffers;
529 DWORD flags;
530 LARGE_INTEGER offset;
531 struct ws2_async write;
534 static struct ws2_async_io *async_io_freelist;
536 static void release_async_io( struct ws2_async_io *io )
538 for (;;)
540 struct ws2_async_io *next = async_io_freelist;
541 io->next = next;
542 if (InterlockedCompareExchangePointer( (void **)&async_io_freelist, io, next ) == next) return;
546 static struct ws2_async_io *alloc_async_io( DWORD size, async_callback_t callback )
548 /* first free remaining previous fileinfos */
550 struct ws2_async_io *io = InterlockedExchangePointer( (void **)&async_io_freelist, NULL );
552 while (io)
554 struct ws2_async_io *next = io->next;
555 HeapFree( GetProcessHeap(), 0, io );
556 io = next;
559 io = HeapAlloc( GetProcessHeap(), 0, size );
560 if (io) io->callback = callback;
561 return io;
564 static NTSTATUS register_async( int type, HANDLE handle, struct ws2_async_io *async, HANDLE event,
565 PIO_APC_ROUTINE apc, void *apc_context, IO_STATUS_BLOCK *io )
567 NTSTATUS status;
569 SERVER_START_REQ( register_async )
571 req->type = type;
572 req->async.handle = wine_server_obj_handle( handle );
573 req->async.user = wine_server_client_ptr( async );
574 req->async.iosb = wine_server_client_ptr( io );
575 req->async.event = wine_server_obj_handle( event );
576 req->async.apc = wine_server_client_ptr( apc );
577 req->async.apc_context = wine_server_client_ptr( apc_context );
578 status = wine_server_call( req );
580 SERVER_END_REQ;
582 return status;
585 /****************************************************************/
587 /* ----------------------------------- internal data */
589 /* ws_... struct conversion flags */
591 typedef struct /* WSAAsyncSelect() control struct */
593 HANDLE service, event, sock;
594 HWND hWnd;
595 UINT uMsg;
596 LONG lEvent;
597 } ws_select_info;
599 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
600 #define WS_MAX_UDP_DATAGRAM 1024
601 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
603 int num_startup;
604 static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
606 /* function prototypes */
607 static int ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size);
609 int WSAIOCTL_GetInterfaceCount(void);
610 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
612 static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus, ULONG Information, BOOL force );
614 #define MAP_OPTION(opt) { WS_##opt, opt }
616 static const int ws_flags_map[][2] =
618 MAP_OPTION( MSG_OOB ),
619 MAP_OPTION( MSG_PEEK ),
620 MAP_OPTION( MSG_DONTROUTE ),
621 MAP_OPTION( MSG_WAITALL ),
622 { WS_MSG_PARTIAL, 0 },
625 static const int ws_sock_map[][2] =
627 MAP_OPTION( SO_DEBUG ),
628 MAP_OPTION( SO_ACCEPTCONN ),
629 MAP_OPTION( SO_REUSEADDR ),
630 MAP_OPTION( SO_KEEPALIVE ),
631 MAP_OPTION( SO_DONTROUTE ),
632 MAP_OPTION( SO_BROADCAST ),
633 MAP_OPTION( SO_LINGER ),
634 MAP_OPTION( SO_OOBINLINE ),
635 MAP_OPTION( SO_SNDBUF ),
636 MAP_OPTION( SO_RCVBUF ),
637 MAP_OPTION( SO_ERROR ),
638 MAP_OPTION( SO_TYPE ),
639 #ifdef SO_RCVTIMEO
640 MAP_OPTION( SO_RCVTIMEO ),
641 #endif
642 #ifdef SO_SNDTIMEO
643 MAP_OPTION( SO_SNDTIMEO ),
644 #endif
647 static const int ws_tcp_map[][2] =
649 #ifdef TCP_NODELAY
650 MAP_OPTION( TCP_NODELAY ),
651 #endif
654 static const int ws_ip_map[][2] =
656 MAP_OPTION( IP_MULTICAST_IF ),
657 MAP_OPTION( IP_MULTICAST_TTL ),
658 MAP_OPTION( IP_MULTICAST_LOOP ),
659 MAP_OPTION( IP_ADD_MEMBERSHIP ),
660 MAP_OPTION( IP_DROP_MEMBERSHIP ),
661 MAP_OPTION( IP_ADD_SOURCE_MEMBERSHIP ),
662 MAP_OPTION( IP_DROP_SOURCE_MEMBERSHIP ),
663 MAP_OPTION( IP_BLOCK_SOURCE ),
664 MAP_OPTION( IP_UNBLOCK_SOURCE ),
665 MAP_OPTION( IP_OPTIONS ),
666 #ifdef IP_HDRINCL
667 MAP_OPTION( IP_HDRINCL ),
668 #endif
669 MAP_OPTION( IP_TOS ),
670 MAP_OPTION( IP_TTL ),
671 #if defined(IP_PKTINFO)
672 MAP_OPTION( IP_PKTINFO ),
673 #elif defined(IP_RECVDSTADDR)
674 { WS_IP_PKTINFO, IP_RECVDSTADDR },
675 #endif
676 #ifdef IP_UNICAST_IF
677 MAP_OPTION( IP_UNICAST_IF ),
678 #endif
681 static const int ws_ipv6_map[][2] =
683 #ifdef IPV6_ADD_MEMBERSHIP
684 MAP_OPTION( IPV6_ADD_MEMBERSHIP ),
685 #endif
686 #ifdef IPV6_DROP_MEMBERSHIP
687 MAP_OPTION( IPV6_DROP_MEMBERSHIP ),
688 #endif
689 MAP_OPTION( IPV6_MULTICAST_IF ),
690 MAP_OPTION( IPV6_MULTICAST_HOPS ),
691 MAP_OPTION( IPV6_MULTICAST_LOOP ),
692 MAP_OPTION( IPV6_UNICAST_HOPS ),
693 MAP_OPTION( IPV6_V6ONLY ),
694 #ifdef IPV6_UNICAST_IF
695 MAP_OPTION( IPV6_UNICAST_IF ),
696 #endif
699 static const int ws_socktype_map[][2] =
701 MAP_OPTION( SOCK_DGRAM ),
702 MAP_OPTION( SOCK_STREAM ),
703 MAP_OPTION( SOCK_RAW ),
704 {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
707 static const int ws_poll_map[][2] =
709 MAP_OPTION( POLLERR ),
710 MAP_OPTION( POLLHUP ),
711 MAP_OPTION( POLLNVAL ),
712 MAP_OPTION( POLLWRNORM ),
713 MAP_OPTION( POLLWRBAND ),
714 MAP_OPTION( POLLRDNORM ),
715 { WS_POLLRDBAND, POLLPRI }
718 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
719 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
720 static inline WSACMSGHDR *fill_control_message(int level, int type, WSACMSGHDR *current, ULONG *maxsize, void *data, int len)
722 ULONG msgsize = sizeof(WSACMSGHDR) + WSA_CMSG_ALIGN(len);
723 char *ptr = (char *) current + sizeof(WSACMSGHDR);
725 /* Make sure there is at least enough room for this entry */
726 if (msgsize > *maxsize)
727 return NULL;
728 *maxsize -= msgsize;
729 /* Fill in the entry */
730 current->cmsg_len = sizeof(WSACMSGHDR) + len;
731 current->cmsg_level = level;
732 current->cmsg_type = type;
733 memcpy(ptr, data, len);
734 /* Return the pointer to where next entry should go */
735 return (WSACMSGHDR *) (ptr + WSA_CMSG_ALIGN(len));
737 #endif /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
739 static inline int convert_control_headers(struct msghdr *hdr, WSABUF *control)
741 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
742 WSACMSGHDR *cmsg_win = (WSACMSGHDR *) control->buf, *ptr;
743 ULONG ctlsize = control->len;
744 struct cmsghdr *cmsg_unix;
746 ptr = cmsg_win;
747 /* Loop over all the headers, converting as appropriate */
748 for (cmsg_unix = CMSG_FIRSTHDR(hdr); cmsg_unix != NULL; cmsg_unix = CMSG_NXTHDR(hdr, cmsg_unix))
750 switch(cmsg_unix->cmsg_level)
752 case IPPROTO_IP:
753 switch(cmsg_unix->cmsg_type)
755 #if defined(IP_PKTINFO)
756 case IP_PKTINFO:
758 /* Convert the Unix IP_PKTINFO structure to the Windows version */
759 struct in_pktinfo *data_unix = (struct in_pktinfo *) CMSG_DATA(cmsg_unix);
760 struct WS_in_pktinfo data_win;
762 memcpy(&data_win.ipi_addr,&data_unix->ipi_addr.s_addr,4); /* 4 bytes = 32 address bits */
763 data_win.ipi_ifindex = data_unix->ipi_ifindex;
764 ptr = fill_control_message(WS_IPPROTO_IP, WS_IP_PKTINFO, ptr, &ctlsize,
765 (void*)&data_win, sizeof(data_win));
766 if (!ptr) goto error;
767 } break;
768 #elif defined(IP_RECVDSTADDR)
769 case IP_RECVDSTADDR:
771 struct in_addr *addr_unix = (struct in_addr *) CMSG_DATA(cmsg_unix);
772 struct WS_in_pktinfo data_win;
774 memcpy(&data_win.ipi_addr, &addr_unix->s_addr, 4); /* 4 bytes = 32 address bits */
775 data_win.ipi_ifindex = 0; /* FIXME */
776 ptr = fill_control_message(WS_IPPROTO_IP, WS_IP_PKTINFO, ptr, &ctlsize,
777 (void*)&data_win, sizeof(data_win));
778 if (!ptr) goto error;
779 } break;
780 #endif /* IP_PKTINFO */
781 default:
782 FIXME("Unhandled IPPROTO_IP message header type %d\n", cmsg_unix->cmsg_type);
783 break;
785 break;
786 default:
787 FIXME("Unhandled message header level %d\n", cmsg_unix->cmsg_level);
788 break;
792 /* Set the length of the returned control headers */
793 control->len = (char*)ptr - (char*)cmsg_win;
794 return 1;
795 error:
796 control->len = 0;
797 return 0;
798 #else /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
799 control->len = 0;
800 return 1;
801 #endif /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
803 #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
805 /* ----------------------------------- error handling */
807 static NTSTATUS sock_get_ntstatus( int err )
809 switch ( err )
811 case EBADF: return STATUS_INVALID_HANDLE;
812 case EBUSY: return STATUS_DEVICE_BUSY;
813 case EPERM:
814 case EACCES: return STATUS_ACCESS_DENIED;
815 case EFAULT: return STATUS_ACCESS_VIOLATION;
816 case EINVAL: return STATUS_INVALID_PARAMETER;
817 case ENFILE:
818 case EMFILE: return STATUS_TOO_MANY_OPENED_FILES;
819 case EINPROGRESS:
820 case EWOULDBLOCK: return STATUS_DEVICE_NOT_READY;
821 case EALREADY: return STATUS_NETWORK_BUSY;
822 case ENOTSOCK: return STATUS_OBJECT_TYPE_MISMATCH;
823 case EDESTADDRREQ: return STATUS_INVALID_PARAMETER;
824 case EMSGSIZE: return STATUS_BUFFER_OVERFLOW;
825 case EPROTONOSUPPORT:
826 case ESOCKTNOSUPPORT:
827 case EPFNOSUPPORT:
828 case EAFNOSUPPORT:
829 case EPROTOTYPE: return STATUS_NOT_SUPPORTED;
830 case ENOPROTOOPT: return STATUS_INVALID_PARAMETER;
831 case EOPNOTSUPP: return STATUS_NOT_SUPPORTED;
832 case EADDRINUSE: return STATUS_SHARING_VIOLATION;
833 case EADDRNOTAVAIL: return STATUS_INVALID_PARAMETER;
834 case ECONNREFUSED: return STATUS_CONNECTION_REFUSED;
835 case ESHUTDOWN: return STATUS_PIPE_DISCONNECTED;
836 case ENOTCONN: return STATUS_INVALID_CONNECTION;
837 case ETIMEDOUT: return STATUS_IO_TIMEOUT;
838 case ENETUNREACH: return STATUS_NETWORK_UNREACHABLE;
839 case ENETDOWN: return STATUS_NETWORK_BUSY;
840 case EPIPE:
841 case ECONNRESET: return STATUS_CONNECTION_RESET;
842 case ECONNABORTED: return STATUS_CONNECTION_ABORTED;
844 case 0: return STATUS_SUCCESS;
845 default:
846 WARN("Unknown errno %d!\n", err);
847 return STATUS_UNSUCCESSFUL;
851 UINT sock_get_error( int err )
853 switch(err)
855 case EINTR: return WSAEINTR;
856 case EPERM:
857 case EACCES: return WSAEACCES;
858 case EFAULT: return WSAEFAULT;
859 case EINVAL: return WSAEINVAL;
860 case EMFILE: return WSAEMFILE;
861 case EINPROGRESS:
862 case EWOULDBLOCK: return WSAEWOULDBLOCK;
863 case EALREADY: return WSAEALREADY;
864 case EBADF:
865 case ENOTSOCK: return WSAENOTSOCK;
866 case EDESTADDRREQ: return WSAEDESTADDRREQ;
867 case EMSGSIZE: return WSAEMSGSIZE;
868 case EPROTOTYPE: return WSAEPROTOTYPE;
869 case ENOPROTOOPT: return WSAENOPROTOOPT;
870 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
871 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
872 case EOPNOTSUPP: return WSAEOPNOTSUPP;
873 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
874 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
875 case EADDRINUSE: return WSAEADDRINUSE;
876 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
877 case ENETDOWN: return WSAENETDOWN;
878 case ENETUNREACH: return WSAENETUNREACH;
879 case ENETRESET: return WSAENETRESET;
880 case ECONNABORTED: return WSAECONNABORTED;
881 case EPIPE:
882 case ECONNRESET: return WSAECONNRESET;
883 case ENOBUFS: return WSAENOBUFS;
884 case EISCONN: return WSAEISCONN;
885 case ENOTCONN: return WSAENOTCONN;
886 case ESHUTDOWN: return WSAESHUTDOWN;
887 case ETOOMANYREFS: return WSAETOOMANYREFS;
888 case ETIMEDOUT: return WSAETIMEDOUT;
889 case ECONNREFUSED: return WSAECONNREFUSED;
890 case ELOOP: return WSAELOOP;
891 case ENAMETOOLONG: return WSAENAMETOOLONG;
892 case EHOSTDOWN: return WSAEHOSTDOWN;
893 case EHOSTUNREACH: return WSAEHOSTUNREACH;
894 case ENOTEMPTY: return WSAENOTEMPTY;
895 #ifdef EPROCLIM
896 case EPROCLIM: return WSAEPROCLIM;
897 #endif
898 #ifdef EUSERS
899 case EUSERS: return WSAEUSERS;
900 #endif
901 #ifdef EDQUOT
902 case EDQUOT: return WSAEDQUOT;
903 #endif
904 #ifdef ESTALE
905 case ESTALE: return WSAESTALE;
906 #endif
907 #ifdef EREMOTE
908 case EREMOTE: return WSAEREMOTE;
909 #endif
911 /* just in case we ever get here and there are no problems */
912 case 0: return 0;
913 default:
914 WARN("Unknown errno %d!\n", err);
915 return WSAEOPNOTSUPP;
919 static UINT wsaErrno(void)
921 int loc_errno = errno;
922 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
924 return sock_get_error( loc_errno );
927 /* most ws2 overlapped functions return an ntstatus-based error code */
928 static NTSTATUS wsaErrStatus(void)
930 int loc_errno = errno;
931 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
933 return sock_get_ntstatus(loc_errno);
936 static NTSTATUS sock_error_to_ntstatus( DWORD err )
938 switch (err)
940 case 0: return STATUS_SUCCESS;
941 case WSAEBADF: return STATUS_INVALID_HANDLE;
942 case WSAEACCES: return STATUS_ACCESS_DENIED;
943 case WSAEFAULT: return STATUS_ACCESS_VIOLATION;
944 case WSAEINVAL: return STATUS_INVALID_PARAMETER;
945 case WSAEMFILE: return STATUS_TOO_MANY_OPENED_FILES;
946 case WSAEINPROGRESS:
947 case WSAEWOULDBLOCK: return STATUS_DEVICE_NOT_READY;
948 case WSAEALREADY: return STATUS_NETWORK_BUSY;
949 case WSAENOTSOCK: return STATUS_OBJECT_TYPE_MISMATCH;
950 case WSAEDESTADDRREQ: return STATUS_INVALID_PARAMETER;
951 case WSAEMSGSIZE: return STATUS_BUFFER_OVERFLOW;
952 case WSAEPROTONOSUPPORT:
953 case WSAESOCKTNOSUPPORT:
954 case WSAEPFNOSUPPORT:
955 case WSAEAFNOSUPPORT:
956 case WSAEPROTOTYPE: return STATUS_NOT_SUPPORTED;
957 case WSAENOPROTOOPT: return STATUS_INVALID_PARAMETER;
958 case WSAEOPNOTSUPP: return STATUS_NOT_SUPPORTED;
959 case WSAEADDRINUSE: return STATUS_SHARING_VIOLATION;
960 case WSAEADDRNOTAVAIL: return STATUS_INVALID_PARAMETER;
961 case WSAECONNREFUSED: return STATUS_CONNECTION_REFUSED;
962 case WSAESHUTDOWN: return STATUS_PIPE_DISCONNECTED;
963 case WSAENOTCONN: return STATUS_INVALID_CONNECTION;
964 case WSAETIMEDOUT: return STATUS_IO_TIMEOUT;
965 case WSAENETUNREACH: return STATUS_NETWORK_UNREACHABLE;
966 case WSAENETDOWN: return STATUS_NETWORK_BUSY;
967 case WSAECONNRESET: return STATUS_CONNECTION_RESET;
968 case WSAECONNABORTED: return STATUS_CONNECTION_ABORTED;
969 default:
970 FIXME("unmapped error %u\n", err);
971 return STATUS_UNSUCCESSFUL;
975 static DWORD NtStatusToWSAError( NTSTATUS status )
977 static const struct
979 NTSTATUS status;
980 DWORD error;
982 errors[] =
984 {STATUS_PENDING, ERROR_IO_PENDING},
986 {STATUS_BUFFER_OVERFLOW, WSAEMSGSIZE},
988 {STATUS_NOT_IMPLEMENTED, WSAEOPNOTSUPP},
989 {STATUS_ACCESS_VIOLATION, WSAEFAULT},
990 {STATUS_PAGEFILE_QUOTA, WSAENOBUFS},
991 {STATUS_INVALID_HANDLE, WSAENOTSOCK},
992 {STATUS_NO_SUCH_DEVICE, WSAENETDOWN},
993 {STATUS_NO_SUCH_FILE, WSAENETDOWN},
994 {STATUS_NO_MEMORY, WSAENOBUFS},
995 {STATUS_CONFLICTING_ADDRESSES, WSAENOBUFS},
996 {STATUS_ACCESS_DENIED, WSAEACCES},
997 {STATUS_BUFFER_TOO_SMALL, WSAEFAULT},
998 {STATUS_OBJECT_TYPE_MISMATCH, WSAENOTSOCK},
999 {STATUS_OBJECT_NAME_NOT_FOUND, WSAENETDOWN},
1000 {STATUS_OBJECT_PATH_NOT_FOUND, WSAENETDOWN},
1001 {STATUS_SHARING_VIOLATION, WSAEADDRINUSE},
1002 {STATUS_QUOTA_EXCEEDED, WSAENOBUFS},
1003 {STATUS_TOO_MANY_PAGING_FILES, WSAENOBUFS},
1004 {STATUS_INSUFFICIENT_RESOURCES, WSAENOBUFS},
1005 {STATUS_WORKING_SET_QUOTA, WSAENOBUFS},
1006 {STATUS_DEVICE_NOT_READY, WSAEWOULDBLOCK},
1007 {STATUS_PIPE_DISCONNECTED, WSAESHUTDOWN},
1008 {STATUS_IO_TIMEOUT, WSAETIMEDOUT},
1009 {STATUS_NOT_SUPPORTED, WSAEOPNOTSUPP},
1010 {STATUS_REMOTE_NOT_LISTENING, WSAECONNREFUSED},
1011 {STATUS_BAD_NETWORK_PATH, WSAENETUNREACH},
1012 {STATUS_NETWORK_BUSY, WSAENETDOWN},
1013 {STATUS_INVALID_NETWORK_RESPONSE, WSAENETDOWN},
1014 {STATUS_UNEXPECTED_NETWORK_ERROR, WSAENETDOWN},
1015 {STATUS_REQUEST_NOT_ACCEPTED, WSAEWOULDBLOCK},
1016 {STATUS_CANCELLED, ERROR_OPERATION_ABORTED},
1017 {STATUS_COMMITMENT_LIMIT, WSAENOBUFS},
1018 {STATUS_LOCAL_DISCONNECT, WSAECONNABORTED},
1019 {STATUS_REMOTE_DISCONNECT, WSAECONNRESET},
1020 {STATUS_REMOTE_RESOURCES, WSAENOBUFS},
1021 {STATUS_LINK_FAILED, WSAECONNRESET},
1022 {STATUS_LINK_TIMEOUT, WSAETIMEDOUT},
1023 {STATUS_INVALID_CONNECTION, WSAENOTCONN},
1024 {STATUS_INVALID_ADDRESS, WSAEADDRNOTAVAIL},
1025 {STATUS_INVALID_BUFFER_SIZE, WSAEMSGSIZE},
1026 {STATUS_INVALID_ADDRESS_COMPONENT, WSAEADDRNOTAVAIL},
1027 {STATUS_TOO_MANY_ADDRESSES, WSAENOBUFS},
1028 {STATUS_ADDRESS_ALREADY_EXISTS, WSAEADDRINUSE},
1029 {STATUS_CONNECTION_DISCONNECTED, WSAECONNRESET},
1030 {STATUS_CONNECTION_RESET, WSAECONNRESET},
1031 {STATUS_TRANSACTION_ABORTED, WSAECONNABORTED},
1032 {STATUS_CONNECTION_REFUSED, WSAECONNREFUSED},
1033 {STATUS_GRACEFUL_DISCONNECT, WSAEDISCON},
1034 {STATUS_CONNECTION_ACTIVE, WSAEISCONN},
1035 {STATUS_NETWORK_UNREACHABLE, WSAENETUNREACH},
1036 {STATUS_HOST_UNREACHABLE, WSAEHOSTUNREACH},
1037 {STATUS_PROTOCOL_UNREACHABLE, WSAENETUNREACH},
1038 {STATUS_PORT_UNREACHABLE, WSAECONNRESET},
1039 {STATUS_REQUEST_ABORTED, WSAEINTR},
1040 {STATUS_CONNECTION_ABORTED, WSAECONNABORTED},
1041 {STATUS_DATATYPE_MISALIGNMENT_ERROR,WSAEFAULT},
1042 {STATUS_HOST_DOWN, WSAEHOSTDOWN},
1043 {0x80070000 | ERROR_IO_INCOMPLETE, ERROR_IO_INCOMPLETE},
1044 {0xc0010000 | ERROR_IO_INCOMPLETE, ERROR_IO_INCOMPLETE},
1045 {0xc0070000 | ERROR_IO_INCOMPLETE, ERROR_IO_INCOMPLETE},
1048 unsigned int i;
1050 for (i = 0; i < ARRAY_SIZE(errors); ++i)
1052 if (errors[i].status == status)
1053 return errors[i].error;
1056 return NT_SUCCESS(status) ? RtlNtStatusToDosErrorNoTeb(status) : WSAEINVAL;
1059 /* set last error code from NT status without mapping WSA errors */
1060 static inline unsigned int set_error( unsigned int err )
1062 if (err)
1064 err = NtStatusToWSAError( err );
1065 SetLastError( err );
1067 return err;
1070 static inline int get_sock_fd( SOCKET s, DWORD access, unsigned int *options )
1072 int fd;
1073 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, options ) ))
1074 return -1;
1075 return fd;
1078 static inline void release_sock_fd( SOCKET s, int fd )
1080 close( fd );
1083 static void _enable_event( HANDLE s, unsigned int event,
1084 unsigned int sstate, unsigned int cstate )
1086 SERVER_START_REQ( enable_socket_event )
1088 req->handle = wine_server_obj_handle( s );
1089 req->mask = event;
1090 req->sstate = sstate;
1091 req->cstate = cstate;
1092 wine_server_call( req );
1094 SERVER_END_REQ;
1097 static DWORD sock_is_blocking(SOCKET s, BOOL *ret)
1099 DWORD err;
1100 SERVER_START_REQ( get_socket_event )
1102 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
1103 req->service = FALSE;
1104 req->c_event = 0;
1105 err = NtStatusToWSAError( wine_server_call( req ));
1106 *ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
1108 SERVER_END_REQ;
1109 return err;
1112 static unsigned int _get_sock_mask(SOCKET s)
1114 unsigned int ret;
1115 SERVER_START_REQ( get_socket_event )
1117 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
1118 req->service = FALSE;
1119 req->c_event = 0;
1120 wine_server_call( req );
1121 ret = reply->mask;
1123 SERVER_END_REQ;
1124 return ret;
1127 static void _sync_sock_state(SOCKET s)
1129 BOOL dummy;
1130 /* do a dummy wineserver request in order to let
1131 the wineserver run through its select loop once */
1132 sock_is_blocking(s, &dummy);
1135 static void _get_sock_errors(SOCKET s, int *events)
1137 SERVER_START_REQ( get_socket_event )
1139 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
1140 req->service = FALSE;
1141 req->c_event = 0;
1142 wine_server_set_reply( req, events, sizeof(int) * FD_MAX_EVENTS );
1143 wine_server_call( req );
1145 SERVER_END_REQ;
1148 static int _get_fd_type(int fd)
1150 int sock_type = -1;
1151 socklen_t optlen = sizeof(sock_type);
1152 getsockopt(fd, SOL_SOCKET, SO_TYPE, (char*) &sock_type, &optlen);
1153 return sock_type;
1156 static BOOL set_dont_fragment(SOCKET s, int level, BOOL value)
1158 int fd, optname;
1160 if (level == IPPROTO_IP)
1162 #ifdef IP_DONTFRAG
1163 optname = IP_DONTFRAG;
1164 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) && defined(IP_PMTUDISC_DONT)
1165 optname = IP_MTU_DISCOVER;
1166 value = value ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
1167 #else
1168 static int once;
1169 if (!once++)
1170 FIXME("IP_DONTFRAGMENT for IPv4 not supported in this platform\n");
1171 return TRUE; /* fake success */
1172 #endif
1174 else
1176 #ifdef IPV6_DONTFRAG
1177 optname = IPV6_DONTFRAG;
1178 #elif defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) && defined(IPV6_PMTUDISC_DONT)
1179 optname = IPV6_MTU_DISCOVER;
1180 value = value ? IPV6_PMTUDISC_DO : IPV6_PMTUDISC_DONT;
1181 #else
1182 static int once;
1183 if (!once++)
1184 FIXME("IP_DONTFRAGMENT for IPv6 not supported in this platform\n");
1185 return TRUE; /* fake success */
1186 #endif
1189 fd = get_sock_fd(s, 0, NULL);
1190 if (fd == -1) return FALSE;
1192 if (!setsockopt(fd, level, optname, &value, sizeof(value)))
1193 value = TRUE;
1194 else
1196 WSASetLastError(wsaErrno());
1197 value = FALSE;
1200 release_sock_fd(s, fd);
1201 return value;
1204 static BOOL get_dont_fragment(SOCKET s, int level, BOOL *out)
1206 int fd, optname, value, not_expected;
1207 socklen_t optlen = sizeof(value);
1209 if (level == IPPROTO_IP)
1211 #ifdef IP_DONTFRAG
1212 optname = IP_DONTFRAG;
1213 not_expected = 0;
1214 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
1215 optname = IP_MTU_DISCOVER;
1216 not_expected = IP_PMTUDISC_DONT;
1217 #else
1218 static int once;
1219 if (!once++)
1220 FIXME("IP_DONTFRAGMENT for IPv4 not supported in this platform\n");
1221 return TRUE; /* fake success */
1222 #endif
1224 else
1226 #ifdef IPV6_DONTFRAG
1227 optname = IPV6_DONTFRAG;
1228 not_expected = 0;
1229 #elif defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
1230 optname = IPV6_MTU_DISCOVER;
1231 not_expected = IPV6_PMTUDISC_DONT;
1232 #else
1233 static int once;
1234 if (!once++)
1235 FIXME("IP_DONTFRAGMENT for IPv6 not supported in this platform\n");
1236 return TRUE; /* fake success */
1237 #endif
1240 fd = get_sock_fd(s, 0, NULL);
1241 if (fd == -1) return FALSE;
1243 if (!getsockopt(fd, level, optname, &value, &optlen))
1245 *out = value != not_expected;
1246 value = TRUE;
1248 else
1250 WSASetLastError(wsaErrno());
1251 value = FALSE;
1254 release_sock_fd(s, fd);
1255 return value;
1258 struct per_thread_data *get_per_thread_data(void)
1260 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
1261 /* lazy initialization */
1262 if (!ptb)
1264 ptb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptb) );
1265 NtCurrentTeb()->WinSockData = ptb;
1267 return ptb;
1270 static void free_per_thread_data(void)
1272 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
1274 if (!ptb) return;
1276 CloseHandle( ptb->sync_event );
1278 /* delete scratch buffers */
1279 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
1280 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
1281 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
1282 HeapFree( GetProcessHeap(), 0, ptb->fd_cache );
1284 HeapFree( GetProcessHeap(), 0, ptb );
1285 NtCurrentTeb()->WinSockData = NULL;
1288 static HANDLE get_sync_event(void)
1290 struct per_thread_data *data;
1292 if (!(data = get_per_thread_data())) return NULL;
1293 if (!data->sync_event)
1294 data->sync_event = CreateEventW( NULL, TRUE, FALSE, NULL );
1295 return data->sync_event;
1298 /***********************************************************************
1299 * DllMain (WS2_32.init)
1301 BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved )
1303 if (reason == DLL_THREAD_DETACH)
1304 free_per_thread_data();
1305 return TRUE;
1308 /***********************************************************************
1309 * convert_flags()
1311 * Converts send/recv flags from Windows format.
1312 * Return the converted flag bits, unsupported flags remain unchanged.
1314 static int convert_flags(int flags)
1316 int i, out;
1317 if (!flags) return 0;
1319 for (out = i = 0; flags && i < ARRAY_SIZE(ws_flags_map); i++)
1321 if (ws_flags_map[i][0] & flags)
1323 out |= ws_flags_map[i][1];
1324 flags &= ~ws_flags_map[i][0];
1327 if (flags)
1329 FIXME("Unknown send/recv flags 0x%x, using anyway...\n", flags);
1330 out |= flags;
1332 return out;
1335 /***********************************************************************
1336 * convert_sockopt()
1338 * Converts socket flags from Windows format.
1339 * Return 1 if converted, 0 if not (error).
1341 static int convert_sockopt(INT *level, INT *optname)
1343 unsigned int i;
1344 switch (*level)
1346 case WS_SOL_SOCKET:
1347 *level = SOL_SOCKET;
1348 for(i = 0; i < ARRAY_SIZE(ws_sock_map); i++) {
1349 if( ws_sock_map[i][0] == *optname )
1351 *optname = ws_sock_map[i][1];
1352 return 1;
1355 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
1356 break;
1357 case WS_IPPROTO_TCP:
1358 *level = IPPROTO_TCP;
1359 for(i = 0; i < ARRAY_SIZE(ws_tcp_map); i++) {
1360 if ( ws_tcp_map[i][0] == *optname )
1362 *optname = ws_tcp_map[i][1];
1363 return 1;
1366 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
1367 break;
1368 case WS_IPPROTO_IP:
1369 *level = IPPROTO_IP;
1370 for(i = 0; i < ARRAY_SIZE(ws_ip_map); i++) {
1371 if (ws_ip_map[i][0] == *optname )
1373 *optname = ws_ip_map[i][1];
1374 return 1;
1377 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
1378 break;
1379 case WS_IPPROTO_IPV6:
1380 *level = IPPROTO_IPV6;
1381 for(i = 0; i < ARRAY_SIZE(ws_ipv6_map); i++) {
1382 if (ws_ipv6_map[i][0] == *optname )
1384 *optname = ws_ipv6_map[i][1];
1385 return 1;
1388 FIXME("Unknown IPPROTO_IPV6 optname 0x%x\n", *optname);
1389 break;
1390 default: FIXME("Unimplemented or unknown socket level\n");
1392 return 0;
1395 /* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
1396 * from an fd and return the value converted to milli seconds
1397 * or 0 if there is an infinite time out */
1398 static inline INT64 get_rcvsnd_timeo( int fd, BOOL is_recv)
1400 struct timeval tv;
1401 socklen_t len = sizeof(tv);
1402 int optname, res;
1404 if (is_recv)
1405 #ifdef SO_RCVTIMEO
1406 optname = SO_RCVTIMEO;
1407 #else
1408 return 0;
1409 #endif
1410 else
1411 #ifdef SO_SNDTIMEO
1412 optname = SO_SNDTIMEO;
1413 #else
1414 return 0;
1415 #endif
1417 res = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
1418 if (res < 0)
1419 return 0;
1420 return (UINT64)tv.tv_sec * 1000 + tv.tv_usec / 1000;
1423 /* utility: given an fd, will block until one of the events occurs */
1424 static inline int do_block( int fd, int events, int timeout )
1426 struct pollfd pfd;
1427 int ret;
1429 pfd.fd = fd;
1430 pfd.events = events;
1432 while ((ret = poll(&pfd, 1, timeout)) < 0)
1434 if (errno != EINTR)
1435 return -1;
1437 if( ret == 0 )
1438 return 0;
1439 return pfd.revents;
1443 convert_socktype_w2u(int windowssocktype) {
1444 unsigned int i;
1446 for (i = 0; i < ARRAY_SIZE(ws_socktype_map); i++)
1447 if (ws_socktype_map[i][0] == windowssocktype)
1448 return ws_socktype_map[i][1];
1449 FIXME("unhandled Windows socket type %d\n", windowssocktype);
1450 return -1;
1454 convert_socktype_u2w(int unixsocktype) {
1455 unsigned int i;
1457 for (i = 0; i < ARRAY_SIZE(ws_socktype_map); i++)
1458 if (ws_socktype_map[i][1] == unixsocktype)
1459 return ws_socktype_map[i][0];
1460 FIXME("unhandled UNIX socket type %d\n", unixsocktype);
1461 return -1;
1464 static int convert_poll_w2u(int events)
1466 int i, ret;
1467 for (i = ret = 0; events && i < ARRAY_SIZE(ws_poll_map); i++)
1469 if (ws_poll_map[i][0] & events)
1471 ret |= ws_poll_map[i][1];
1472 events &= ~ws_poll_map[i][0];
1476 if (events)
1477 FIXME("Unsupported WSAPoll() flags 0x%x\n", events);
1478 return ret;
1481 static int convert_poll_u2w(int events)
1483 int i, ret;
1484 for (i = ret = 0; events && i < ARRAY_SIZE(ws_poll_map); i++)
1486 if (ws_poll_map[i][1] & events)
1488 ret |= ws_poll_map[i][0];
1489 events &= ~ws_poll_map[i][1];
1493 if (events)
1494 FIXME("Unsupported poll() flags 0x%x\n", events);
1495 return ret;
1498 static int set_ipx_packettype(int sock, int ptype)
1500 #ifdef HAS_IPX
1501 int fd = get_sock_fd( sock, 0, NULL ), ret = 0;
1502 TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", ptype, fd);
1504 if (fd == -1) return SOCKET_ERROR;
1506 /* We try to set the ipx type on ipx socket level. */
1507 #ifdef SOL_IPX
1508 if(setsockopt(fd, SOL_IPX, IPX_TYPE, &ptype, sizeof(ptype)) == -1)
1510 ERR("IPX: could not set ipx option type; expect weird behaviour\n");
1511 ret = SOCKET_ERROR;
1513 #else
1515 struct ipx val;
1516 /* Should we retrieve val using a getsockopt call and then
1517 * set the modified one? */
1518 val.ipx_pt = ptype;
1519 setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
1521 #endif
1522 release_sock_fd( sock, fd );
1523 return ret;
1524 #else
1525 WARN("IPX support is not enabled, can't set packet type\n");
1526 return SOCKET_ERROR;
1527 #endif
1530 /* ----------------------------------- API -----
1532 * Init / cleanup / error checking.
1535 /***********************************************************************
1536 * WSAStartup (WS2_32.115)
1538 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
1540 TRACE("verReq=%x\n", wVersionRequested);
1542 if (LOBYTE(wVersionRequested) < 1)
1543 return WSAVERNOTSUPPORTED;
1545 if (!lpWSAData) return WSAEINVAL;
1547 num_startup++;
1549 /* that's the whole of the negotiation for now */
1550 lpWSAData->wVersion = wVersionRequested;
1551 /* return winsock information */
1552 lpWSAData->wHighVersion = 0x0202;
1553 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
1554 strcpy(lpWSAData->szSystemStatus, "Running" );
1555 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
1556 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
1557 /* don't do anything with lpWSAData->lpVendorInfo */
1558 /* (some apps don't allocate the space for this field) */
1560 TRACE("succeeded starts: %d\n", num_startup);
1561 return 0;
1565 /***********************************************************************
1566 * WSACleanup (WS2_32.116)
1568 INT WINAPI WSACleanup(void)
1570 TRACE("decreasing startup count from %d\n", num_startup);
1571 if (num_startup)
1573 if (!--num_startup)
1575 unsigned int i;
1577 for (i = 0; i < socket_list_size; ++i)
1578 CloseHandle(SOCKET2HANDLE(socket_list[i]));
1579 memset(socket_list, 0, socket_list_size * sizeof(*socket_list));
1581 return 0;
1583 SetLastError(WSANOTINITIALISED);
1584 return SOCKET_ERROR;
1588 /***********************************************************************
1589 * WSAGetLastError (WS2_32.111)
1591 INT WINAPI WSAGetLastError(void)
1593 return GetLastError();
1596 /***********************************************************************
1597 * WSASetLastError (WS2_32.112)
1599 void WINAPI WSASetLastError(INT iError) {
1600 SetLastError(iError);
1603 static inline BOOL supported_pf(int pf)
1605 switch (pf)
1607 case WS_AF_INET:
1608 case WS_AF_INET6:
1609 return TRUE;
1610 #ifdef HAS_IPX
1611 case WS_AF_IPX:
1612 return TRUE;
1613 #endif
1614 #ifdef HAS_IRDA
1615 case WS_AF_IRDA:
1616 return TRUE;
1617 #endif
1618 default:
1619 return FALSE;
1623 /**********************************************************************/
1625 /* Returns the length of the converted address if successful, 0 if it was too
1626 * small to start with or unknown family or invalid address buffer.
1628 unsigned int ws_sockaddr_ws2u( const struct WS_sockaddr *wsaddr, int wsaddrlen,
1629 union generic_unix_sockaddr *uaddr )
1631 unsigned int uaddrlen = 0;
1633 if (!wsaddr)
1634 return 0;
1636 switch (wsaddr->sa_family)
1638 #ifdef HAS_IPX
1639 case WS_AF_IPX:
1641 const struct WS_sockaddr_ipx* wsipx=(const struct WS_sockaddr_ipx*)wsaddr;
1642 struct sockaddr_ipx* uipx = (struct sockaddr_ipx *)uaddr;
1644 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
1645 return 0;
1647 uaddrlen = sizeof(struct sockaddr_ipx);
1648 memset( uaddr, 0, uaddrlen );
1649 uipx->sipx_family=AF_IPX;
1650 uipx->sipx_port=wsipx->sa_socket;
1651 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
1652 * in one go
1654 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
1655 #ifdef IPX_FRAME_NONE
1656 uipx->sipx_type=IPX_FRAME_NONE;
1657 #endif
1658 break;
1660 #endif
1661 case WS_AF_INET6: {
1662 struct sockaddr_in6* uin6 = (struct sockaddr_in6 *)uaddr;
1663 const struct WS_sockaddr_in6* win6 = (const struct WS_sockaddr_in6*)wsaddr;
1665 /* Note: Windows has 2 versions of the sockaddr_in6 struct, one with
1666 * scope_id, one without.
1668 if (wsaddrlen >= sizeof(struct WS_sockaddr_in6_old)) {
1669 uaddrlen = sizeof(struct sockaddr_in6);
1670 memset( uaddr, 0, uaddrlen );
1671 uin6->sin6_family = AF_INET6;
1672 uin6->sin6_port = win6->sin6_port;
1673 uin6->sin6_flowinfo = win6->sin6_flowinfo;
1674 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
1675 if (wsaddrlen >= sizeof(struct WS_sockaddr_in6)) uin6->sin6_scope_id = win6->sin6_scope_id;
1676 #endif
1677 memcpy(&uin6->sin6_addr,&win6->sin6_addr,16); /* 16 bytes = 128 address bits */
1678 break;
1680 FIXME("bad size %d for WS_sockaddr_in6\n",wsaddrlen);
1681 return 0;
1683 case WS_AF_INET: {
1684 struct sockaddr_in* uin = (struct sockaddr_in *)uaddr;
1685 const struct WS_sockaddr_in* win = (const struct WS_sockaddr_in*)wsaddr;
1687 if (wsaddrlen<sizeof(struct WS_sockaddr_in))
1688 return 0;
1689 uaddrlen = sizeof(struct sockaddr_in);
1690 memset( uaddr, 0, uaddrlen );
1691 uin->sin_family = AF_INET;
1692 uin->sin_port = win->sin_port;
1693 memcpy(&uin->sin_addr,&win->sin_addr,4); /* 4 bytes = 32 address bits */
1694 break;
1696 #ifdef HAS_IRDA
1697 case WS_AF_IRDA: {
1698 struct sockaddr_irda *uin = (struct sockaddr_irda *)uaddr;
1699 const SOCKADDR_IRDA *win = (const SOCKADDR_IRDA *)wsaddr;
1701 if (wsaddrlen < sizeof(SOCKADDR_IRDA))
1702 return 0;
1703 uaddrlen = sizeof(struct sockaddr_irda);
1704 memset( uaddr, 0, uaddrlen );
1705 uin->sir_family = AF_IRDA;
1706 if (!strncmp( win->irdaServiceName, "LSAP-SEL", strlen( "LSAP-SEL" ) ))
1708 unsigned int lsap_sel = 0;
1710 sscanf( win->irdaServiceName, "LSAP-SEL%u", &lsap_sel );
1711 uin->sir_lsap_sel = lsap_sel;
1713 else
1715 uin->sir_lsap_sel = LSAP_ANY;
1716 memcpy( uin->sir_name, win->irdaServiceName, 25 );
1718 memcpy( &uin->sir_addr, win->irdaDeviceID, sizeof(uin->sir_addr) );
1719 break;
1721 #endif
1722 case WS_AF_UNSPEC: {
1723 /* Try to determine the needed space by the passed windows sockaddr space */
1724 switch (wsaddrlen) {
1725 default: /* likely an ipv4 address */
1726 case sizeof(struct WS_sockaddr_in):
1727 uaddrlen = sizeof(struct sockaddr_in);
1728 break;
1729 #ifdef HAS_IPX
1730 case sizeof(struct WS_sockaddr_ipx):
1731 uaddrlen = sizeof(struct sockaddr_ipx);
1732 break;
1733 #endif
1734 #ifdef HAS_IRDA
1735 case sizeof(SOCKADDR_IRDA):
1736 uaddrlen = sizeof(struct sockaddr_irda);
1737 break;
1738 #endif
1739 case sizeof(struct WS_sockaddr_in6):
1740 case sizeof(struct WS_sockaddr_in6_old):
1741 uaddrlen = sizeof(struct sockaddr_in6);
1742 break;
1744 memset( uaddr, 0, uaddrlen );
1745 break;
1747 default:
1748 FIXME("Unknown address family %d, return NULL.\n", wsaddr->sa_family);
1749 return 0;
1751 return uaddrlen;
1754 static BOOL is_sockaddr_bound(const struct sockaddr *uaddr, int uaddrlen)
1756 switch (uaddr->sa_family)
1758 #ifdef HAS_IPX
1759 case AF_IPX:
1761 static const struct sockaddr_ipx emptyAddr;
1762 struct sockaddr_ipx *ipx = (struct sockaddr_ipx*) uaddr;
1763 return ipx->sipx_port
1764 || memcmp(&ipx->sipx_network, &emptyAddr.sipx_network, sizeof(emptyAddr.sipx_network))
1765 || memcmp(&ipx->sipx_node, &emptyAddr.sipx_node, sizeof(emptyAddr.sipx_node));
1767 #endif
1768 case AF_INET6:
1770 static const struct sockaddr_in6 emptyAddr;
1771 const struct sockaddr_in6 *in6 = (const struct sockaddr_in6*) uaddr;
1772 return in6->sin6_port || memcmp(&in6->sin6_addr, &emptyAddr.sin6_addr, sizeof(struct in6_addr));
1774 case AF_INET:
1776 static const struct sockaddr_in emptyAddr;
1777 const struct sockaddr_in *in = (const struct sockaddr_in*) uaddr;
1778 return in->sin_port || memcmp(&in->sin_addr, &emptyAddr.sin_addr, sizeof(struct in_addr));
1780 case AF_UNSPEC:
1781 return FALSE;
1782 default:
1783 FIXME("unknown address family %d\n", uaddr->sa_family);
1784 return TRUE;
1788 /* Returns -1 if getsockname fails, 0 if not bound, 1 otherwise */
1789 static int is_fd_bound(int fd, union generic_unix_sockaddr *uaddr, socklen_t *uaddrlen)
1791 union generic_unix_sockaddr inaddr;
1792 socklen_t inlen;
1793 int res;
1795 if (!uaddr) uaddr = &inaddr;
1796 if (!uaddrlen) uaddrlen = &inlen;
1798 *uaddrlen = sizeof(inaddr);
1799 res = getsockname(fd, &uaddr->addr, uaddrlen);
1800 if (!res) res = is_sockaddr_bound(&uaddr->addr, *uaddrlen);
1801 return res;
1804 /* Returns 0 if successful, -1 if the buffer is too small */
1805 int ws_sockaddr_u2ws(const struct sockaddr *uaddr, struct WS_sockaddr *wsaddr, int *wsaddrlen)
1807 int res;
1809 switch(uaddr->sa_family)
1811 #ifdef HAS_IPX
1812 case AF_IPX:
1814 const struct sockaddr_ipx* uipx=(const struct sockaddr_ipx*)uaddr;
1815 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
1817 res=-1;
1818 switch (*wsaddrlen) /* how much can we copy? */
1820 default:
1821 res=0; /* enough */
1822 *wsaddrlen = sizeof(*wsipx);
1823 wsipx->sa_socket=uipx->sipx_port;
1824 /* fall through */
1825 case 13:
1826 case 12:
1827 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
1828 /* fall through */
1829 case 11:
1830 case 10:
1831 case 9:
1832 case 8:
1833 case 7:
1834 case 6:
1835 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
1836 /* fall through */
1837 case 5:
1838 case 4:
1839 case 3:
1840 case 2:
1841 wsipx->sa_family=WS_AF_IPX;
1842 /* fall through */
1843 case 1:
1844 case 0:
1845 /* way too small */
1846 break;
1849 break;
1850 #endif
1851 #ifdef HAS_IRDA
1852 case AF_IRDA: {
1853 const struct sockaddr_irda *uin = (const struct sockaddr_irda *)uaddr;
1854 SOCKADDR_IRDA *win = (SOCKADDR_IRDA *)wsaddr;
1856 if (*wsaddrlen < sizeof(SOCKADDR_IRDA))
1857 return -1;
1858 win->irdaAddressFamily = WS_AF_IRDA;
1859 memcpy( win->irdaDeviceID, &uin->sir_addr, sizeof(win->irdaDeviceID) );
1860 if (uin->sir_lsap_sel != LSAP_ANY)
1861 sprintf( win->irdaServiceName, "LSAP-SEL%u", uin->sir_lsap_sel );
1862 else
1863 memcpy( win->irdaServiceName, uin->sir_name,
1864 sizeof(win->irdaServiceName) );
1865 return 0;
1867 #endif
1868 case AF_INET6: {
1869 const struct sockaddr_in6* uin6 = (const struct sockaddr_in6*)uaddr;
1870 struct WS_sockaddr_in6_old* win6old = (struct WS_sockaddr_in6_old*)wsaddr;
1872 if (*wsaddrlen < sizeof(struct WS_sockaddr_in6_old))
1873 return -1;
1874 win6old->sin6_family = WS_AF_INET6;
1875 win6old->sin6_port = uin6->sin6_port;
1876 win6old->sin6_flowinfo = uin6->sin6_flowinfo;
1877 memcpy(&win6old->sin6_addr,&uin6->sin6_addr,16); /* 16 bytes = 128 address bits */
1878 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
1879 if (*wsaddrlen >= sizeof(struct WS_sockaddr_in6)) {
1880 struct WS_sockaddr_in6* win6 = (struct WS_sockaddr_in6*)wsaddr;
1881 win6->sin6_scope_id = uin6->sin6_scope_id;
1882 *wsaddrlen = sizeof(struct WS_sockaddr_in6);
1884 else
1885 *wsaddrlen = sizeof(struct WS_sockaddr_in6_old);
1886 #else
1887 *wsaddrlen = sizeof(struct WS_sockaddr_in6_old);
1888 #endif
1889 return 0;
1891 case AF_INET: {
1892 const struct sockaddr_in* uin = (const struct sockaddr_in*)uaddr;
1893 struct WS_sockaddr_in* win = (struct WS_sockaddr_in*)wsaddr;
1895 if (*wsaddrlen < sizeof(struct WS_sockaddr_in))
1896 return -1;
1897 win->sin_family = WS_AF_INET;
1898 win->sin_port = uin->sin_port;
1899 memcpy(&win->sin_addr,&uin->sin_addr,4); /* 4 bytes = 32 address bits */
1900 memset(win->sin_zero, 0, 8); /* Make sure the null padding is null */
1901 *wsaddrlen = sizeof(struct WS_sockaddr_in);
1902 return 0;
1904 case AF_UNSPEC: {
1905 memset(wsaddr,0,*wsaddrlen);
1906 return 0;
1908 default:
1909 FIXME("Unknown address family %d\n", uaddr->sa_family);
1910 return -1;
1912 return res;
1915 static INT WS_DuplicateSocket(BOOL unicode, SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo)
1917 HANDLE hProcess;
1918 int size;
1919 WSAPROTOCOL_INFOW infow;
1921 TRACE("(unicode %d, socket %04lx, processid %x, buffer %p)\n",
1922 unicode, s, dwProcessId, lpProtocolInfo);
1924 if (!ws_protocol_info(s, unicode, &infow, &size))
1925 return SOCKET_ERROR;
1927 if (!(hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId)))
1929 SetLastError(WSAEINVAL);
1930 return SOCKET_ERROR;
1933 if (!lpProtocolInfo)
1935 CloseHandle(hProcess);
1936 SetLastError(WSAEFAULT);
1937 return SOCKET_ERROR;
1940 /* I don't know what the real Windoze does next, this is a hack */
1941 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
1942 * the target use the global duplicate, or we could copy a reference to us to the structure
1943 * and let the target duplicate it from us, but let's do it as simple as possible */
1944 memcpy(lpProtocolInfo, &infow, size);
1945 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
1946 hProcess, (LPHANDLE)&lpProtocolInfo->dwServiceFlags3,
1947 0, FALSE, DUPLICATE_SAME_ACCESS);
1948 CloseHandle(hProcess);
1949 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
1950 return 0;
1953 static BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size)
1955 NTSTATUS status;
1956 int address_family;
1957 int socket_type;
1958 int protocol;
1959 unsigned int i;
1961 *size = unicode ? sizeof(WSAPROTOCOL_INFOW) : sizeof(WSAPROTOCOL_INFOA);
1962 memset(buffer, 0, *size);
1964 SERVER_START_REQ( get_socket_info )
1966 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
1967 status = wine_server_call( req );
1968 if (!status)
1970 address_family = reply->family;
1971 socket_type = reply->type;
1972 protocol = reply->protocol;
1975 SERVER_END_REQ;
1977 if (status)
1979 unsigned int err = NtStatusToWSAError( status );
1980 SetLastError( err == WSAEBADF ? WSAENOTSOCK : err );
1981 return FALSE;
1984 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
1986 const WSAPROTOCOL_INFOW *info = &supported_protocols[i];
1987 if (address_family == info->iAddressFamily &&
1988 socket_type == info->iSocketType &&
1989 protocol >= info->iProtocol && protocol <= info->iProtocol + info->iProtocolMaxOffset)
1991 if (unicode)
1992 *buffer = *info;
1993 else
1995 WSAPROTOCOL_INFOA *bufferA = (WSAPROTOCOL_INFOA *)buffer;
1996 memcpy( bufferA, info, offsetof( WSAPROTOCOL_INFOW, szProtocol ) );
1997 WideCharToMultiByte( CP_ACP, 0, info->szProtocol, -1,
1998 bufferA->szProtocol, sizeof(bufferA->szProtocol), NULL, NULL );
2000 buffer->iProtocol = protocol;
2001 return TRUE;
2004 FIXME("Could not fill protocol information for family %d, type %d, protocol %d.\n",
2005 address_family, socket_type, protocol);
2006 return TRUE;
2009 /**************************************************************************
2010 * Functions for handling overlapped I/O
2011 **************************************************************************/
2013 /* user APC called upon async completion */
2014 static void WINAPI ws2_async_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
2016 struct ws2_async *wsa = arg;
2018 if (wsa->completion_func) wsa->completion_func( NtStatusToWSAError(iosb->u.Status),
2019 iosb->Information, wsa->user_overlapped,
2020 wsa->flags );
2021 release_async_io( &wsa->io );
2024 /***********************************************************************
2025 * WS2_recv (INTERNAL)
2027 * Workhorse for both synchronous and asynchronous recv() operations.
2029 static int WS2_recv( int fd, struct ws2_async *wsa, int flags )
2031 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
2032 char pktbuf[512];
2033 #endif
2034 struct msghdr hdr;
2035 union generic_unix_sockaddr unix_sockaddr;
2036 int n;
2038 hdr.msg_name = NULL;
2040 if (wsa->addr)
2042 hdr.msg_namelen = sizeof(unix_sockaddr);
2043 hdr.msg_name = &unix_sockaddr;
2045 else
2046 hdr.msg_namelen = 0;
2048 hdr.msg_iov = wsa->iovec + wsa->first_iovec;
2049 hdr.msg_iovlen = wsa->n_iovecs - wsa->first_iovec;
2050 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
2051 hdr.msg_accrights = NULL;
2052 hdr.msg_accrightslen = 0;
2053 #else
2054 hdr.msg_control = pktbuf;
2055 hdr.msg_controllen = sizeof(pktbuf);
2056 hdr.msg_flags = 0;
2057 #endif
2059 while ((n = __wine_locked_recvmsg( fd, &hdr, flags )) == -1)
2061 if (errno != EINTR)
2062 return -1;
2065 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
2066 if (wsa->control)
2068 ERR("Message control headers cannot be properly supported on this system.\n");
2069 wsa->control->len = 0;
2071 #else
2072 if (wsa->control && !convert_control_headers(&hdr, wsa->control))
2074 WARN("Application passed insufficient room for control headers.\n");
2075 *wsa->lpFlags |= WS_MSG_CTRUNC;
2076 errno = EMSGSIZE;
2077 return -1;
2079 #endif
2081 /* if this socket is connected and lpFrom is not NULL, Linux doesn't give us
2082 * msg_name and msg_namelen from recvmsg, but it does set msg_namelen to zero.
2084 * quoting linux 2.6 net/ipv4/tcp.c:
2085 * "According to UNIX98, msg_name/msg_namelen are ignored
2086 * on connected socket. I was just happy when found this 8) --ANK"
2088 * likewise MSDN says that lpFrom and lpFromlen are ignored for
2089 * connection-oriented sockets, so don't try to update lpFrom.
2091 if (wsa->addr && hdr.msg_namelen)
2092 ws_sockaddr_u2ws( &unix_sockaddr.addr, wsa->addr, wsa->addrlen.ptr );
2094 return n;
2097 /***********************************************************************
2098 * WS2_async_recv (INTERNAL)
2100 * Handler for overlapped recv() operations.
2102 static NTSTATUS WS2_async_recv( void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status )
2104 struct ws2_async *wsa = user;
2105 int result = 0, fd;
2107 switch (status)
2109 case STATUS_ALERTED:
2110 if ((status = wine_server_handle_to_fd( wsa->hSocket, FILE_READ_DATA, &fd, NULL ) ))
2111 break;
2113 result = WS2_recv( fd, wsa, convert_flags(wsa->flags) );
2114 close( fd );
2115 if (result >= 0)
2117 status = STATUS_SUCCESS;
2118 _enable_event( wsa->hSocket, (wsa->flags & WS_MSG_OOB) ? FD_OOB : FD_READ, 0, 0 );
2120 else
2122 if (errno == EAGAIN)
2124 status = STATUS_PENDING;
2125 _enable_event( wsa->hSocket, (wsa->flags & WS_MSG_OOB) ? FD_OOB : FD_READ, 0, 0 );
2127 else
2129 result = 0;
2130 status = wsaErrStatus();
2133 break;
2135 if (status != STATUS_PENDING)
2137 iosb->u.Status = status;
2138 iosb->Information = result;
2139 if (!wsa->completion_func)
2140 release_async_io( &wsa->io );
2142 return status;
2145 /***********************************************************************
2146 * WS2_send (INTERNAL)
2148 * Workhorse for both synchronous and asynchronous send() operations.
2150 static int WS2_send( int fd, struct ws2_async *wsa, int flags )
2152 struct msghdr hdr;
2153 union generic_unix_sockaddr unix_addr;
2154 int n, ret;
2156 hdr.msg_name = NULL;
2157 hdr.msg_namelen = 0;
2159 if (wsa->addr)
2161 hdr.msg_name = &unix_addr;
2162 hdr.msg_namelen = ws_sockaddr_ws2u( wsa->addr, wsa->addrlen.val, &unix_addr );
2163 if ( !hdr.msg_namelen )
2165 errno = EFAULT;
2166 return -1;
2169 #if defined(HAS_IPX) && defined(SOL_IPX)
2170 if(wsa->addr->sa_family == WS_AF_IPX)
2172 struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
2173 int val=0;
2174 socklen_t len = sizeof(int);
2176 /* The packet type is stored at the ipx socket level; At least the linux kernel seems
2177 * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
2178 * the packet type and then we can retrieve it using getsockopt. After that we can set the
2179 * ipx type in the sockaddr_opx structure with the stored value.
2181 if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
2182 uipx->sipx_type = val;
2184 #endif
2187 hdr.msg_iov = wsa->iovec + wsa->first_iovec;
2188 hdr.msg_iovlen = wsa->n_iovecs - wsa->first_iovec;
2189 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
2190 hdr.msg_accrights = NULL;
2191 hdr.msg_accrightslen = 0;
2192 #else
2193 hdr.msg_control = NULL;
2194 hdr.msg_controllen = 0;
2195 hdr.msg_flags = 0;
2196 #endif
2198 while ((ret = sendmsg(fd, &hdr, flags)) == -1)
2200 if (errno == EISCONN)
2202 hdr.msg_name = 0;
2203 hdr.msg_namelen = 0;
2204 continue;
2206 if (errno != EINTR)
2207 return -1;
2210 n = ret;
2211 while (wsa->first_iovec < wsa->n_iovecs && wsa->iovec[wsa->first_iovec].iov_len <= n)
2212 n -= wsa->iovec[wsa->first_iovec++].iov_len;
2213 if (wsa->first_iovec < wsa->n_iovecs)
2215 wsa->iovec[wsa->first_iovec].iov_base = (char*)wsa->iovec[wsa->first_iovec].iov_base + n;
2216 wsa->iovec[wsa->first_iovec].iov_len -= n;
2218 return ret;
2221 /***********************************************************************
2222 * WS2_async_send (INTERNAL)
2224 * Handler for overlapped send() operations.
2226 static NTSTATUS WS2_async_send( void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status )
2228 struct ws2_async *wsa = user;
2229 int result = 0, fd;
2231 switch (status)
2233 case STATUS_ALERTED:
2234 if ( wsa->n_iovecs <= wsa->first_iovec )
2236 /* Nothing to do */
2237 status = STATUS_SUCCESS;
2238 break;
2240 if ((status = wine_server_handle_to_fd( wsa->hSocket, FILE_WRITE_DATA, &fd, NULL ) ))
2241 break;
2243 /* check to see if the data is ready (non-blocking) */
2244 result = WS2_send( fd, wsa, convert_flags(wsa->flags) );
2245 close( fd );
2247 if (result >= 0)
2249 if (wsa->first_iovec < wsa->n_iovecs)
2250 status = STATUS_PENDING;
2251 else
2252 status = STATUS_SUCCESS;
2254 iosb->Information += result;
2256 else if (errno == EAGAIN)
2258 status = STATUS_PENDING;
2260 else
2262 status = wsaErrStatus();
2264 break;
2266 if (status != STATUS_PENDING)
2268 iosb->u.Status = status;
2269 if (!wsa->completion_func)
2270 release_async_io( &wsa->io );
2272 return status;
2276 /***********************************************************************
2277 * accept (WS2_32.1)
2279 SOCKET WINAPI WS_accept( SOCKET s, struct WS_sockaddr *addr, int *len )
2281 IO_STATUS_BLOCK io;
2282 NTSTATUS status;
2283 obj_handle_t accept_handle;
2284 HANDLE sync_event;
2285 SOCKET ret;
2287 TRACE("%#lx\n", s);
2289 if (!(sync_event = get_sync_event())) return INVALID_SOCKET;
2290 status = NtDeviceIoControlFile( (HANDLE)s, sync_event, NULL, NULL, &io, IOCTL_AFD_WINE_ACCEPT,
2291 NULL, 0, &accept_handle, sizeof(accept_handle) );
2292 if (status == STATUS_PENDING)
2294 if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED)
2295 return SOCKET_ERROR;
2296 status = io.u.Status;
2298 if (status)
2300 WARN("failed; status %#x\n", status);
2301 WSASetLastError( NtStatusToWSAError( status ) );
2302 return INVALID_SOCKET;
2305 ret = HANDLE2SOCKET(wine_server_ptr_handle( accept_handle ));
2306 if (!socket_list_add( ret ))
2308 CloseHandle( SOCKET2HANDLE(ret) );
2309 return INVALID_SOCKET;
2311 if (addr && len && WS_getpeername( ret, addr, len ))
2313 WS_closesocket( ret );
2314 return INVALID_SOCKET;
2317 TRACE("returning %#lx\n", ret);
2318 return ret;
2321 /***********************************************************************
2322 * AcceptEx
2324 static BOOL WINAPI WS2_AcceptEx( SOCKET listener, SOCKET acceptor, void *dest, DWORD recv_len,
2325 DWORD local_len, DWORD remote_len, DWORD *ret_len, OVERLAPPED *overlapped)
2327 struct afd_accept_into_params params =
2329 .accept_handle = acceptor,
2330 .recv_len = recv_len,
2331 .local_len = local_len,
2333 void *cvalue = NULL;
2334 NTSTATUS status;
2336 TRACE( "listener %#lx, acceptor %#lx, dest %p, recv_len %u, local_len %u, remote_len %u, ret_len %p, "
2337 "overlapped %p\n", listener, acceptor, dest, recv_len, local_len, remote_len, ret_len, overlapped );
2339 if (!overlapped)
2341 SetLastError(WSA_INVALID_PARAMETER);
2342 return FALSE;
2345 if (!((ULONG_PTR)overlapped->hEvent & 1)) cvalue = overlapped;
2346 overlapped->Internal = STATUS_PENDING;
2347 overlapped->InternalHigh = 0;
2349 if (!dest)
2351 SetLastError(WSAEINVAL);
2352 return FALSE;
2355 if (!remote_len)
2357 SetLastError(WSAEFAULT);
2358 return FALSE;
2361 status = NtDeviceIoControlFile( SOCKET2HANDLE(listener), overlapped->hEvent, NULL, cvalue,
2362 (IO_STATUS_BLOCK *)overlapped, IOCTL_AFD_WINE_ACCEPT_INTO, &params, sizeof(params),
2363 dest, recv_len + local_len + remote_len );
2365 if (ret_len) *ret_len = overlapped->InternalHigh;
2366 WSASetLastError( NtStatusToWSAError(status) );
2367 return !status;
2370 /***********************************************************************
2371 * WS2_ReadFile (INTERNAL)
2373 * Perform an APC-safe ReadFile operation
2375 static NTSTATUS WS2_ReadFile(HANDLE hFile, PIO_STATUS_BLOCK io_status, char* buffer, ULONG length,
2376 PLARGE_INTEGER offset)
2378 int result = -1, unix_handle;
2379 unsigned int options;
2380 NTSTATUS status;
2382 TRACE( "(%p,%p,0x%08x)\n", hFile, buffer,length );
2384 status = wine_server_handle_to_fd( hFile, FILE_READ_DATA, &unix_handle, &options );
2385 if (status) return status;
2387 while (result == -1)
2389 if (offset->QuadPart != FILE_USE_FILE_POINTER_POSITION)
2390 result = pread( unix_handle, buffer, length, offset->QuadPart );
2391 else
2392 result = read( unix_handle, buffer, length );
2393 if (errno != EINTR)
2394 break;
2397 if (!result)
2398 status = (length ? STATUS_END_OF_FILE : STATUS_SUCCESS);
2399 else if (result != -1)
2400 status = STATUS_SUCCESS;
2401 else if (errno != EAGAIN)
2402 status = wsaErrStatus();
2403 else
2404 status = STATUS_PENDING;
2406 close( unix_handle );
2407 TRACE("= 0x%08x (%d)\n", status, result);
2408 if (status == STATUS_SUCCESS || status == STATUS_END_OF_FILE)
2410 io_status->u.Status = status;
2411 io_status->Information = result;
2414 return status;
2417 /***********************************************************************
2418 * WS2_transmitfile_getbuffer (INTERNAL)
2420 * Pick the appropriate buffer for a TransmitFile send operation.
2422 static NTSTATUS WS2_transmitfile_getbuffer( int fd, struct ws2_transmitfile_async *wsa )
2424 /* send any incomplete writes from a previous iteration */
2425 if (wsa->write.first_iovec < wsa->write.n_iovecs)
2426 return STATUS_PENDING;
2428 /* process the header (if applicable) */
2429 if (wsa->buffers.Head)
2431 wsa->write.first_iovec = 0;
2432 wsa->write.n_iovecs = 1;
2433 wsa->write.iovec[0].iov_base = wsa->buffers.Head;
2434 wsa->write.iovec[0].iov_len = wsa->buffers.HeadLength;
2435 wsa->buffers.Head = NULL;
2436 return STATUS_PENDING;
2439 /* process the main file */
2440 if (wsa->file)
2442 DWORD bytes_per_send = wsa->bytes_per_send;
2443 IO_STATUS_BLOCK iosb;
2444 NTSTATUS status;
2446 iosb.Information = 0;
2447 /* when the size of the transfer is limited ensure that we don't go past that limit */
2448 if (wsa->file_bytes != 0)
2449 bytes_per_send = min(bytes_per_send, wsa->file_bytes - wsa->file_read);
2450 status = WS2_ReadFile( wsa->file, &iosb, wsa->buffer, bytes_per_send, &wsa->offset );
2451 if (wsa->offset.QuadPart != FILE_USE_FILE_POINTER_POSITION)
2452 wsa->offset.QuadPart += iosb.Information;
2453 if (status == STATUS_END_OF_FILE)
2454 wsa->file = NULL; /* continue on to the footer */
2455 else if (status != STATUS_SUCCESS)
2456 return status;
2457 else
2459 if (iosb.Information)
2461 wsa->write.first_iovec = 0;
2462 wsa->write.n_iovecs = 1;
2463 wsa->write.iovec[0].iov_base = wsa->buffer;
2464 wsa->write.iovec[0].iov_len = iosb.Information;
2465 wsa->file_read += iosb.Information;
2468 if (wsa->file_bytes != 0 && wsa->file_read >= wsa->file_bytes)
2469 wsa->file = NULL;
2471 return STATUS_PENDING;
2475 /* send the footer (if applicable) */
2476 if (wsa->buffers.Tail)
2478 wsa->write.first_iovec = 0;
2479 wsa->write.n_iovecs = 1;
2480 wsa->write.iovec[0].iov_base = wsa->buffers.Tail;
2481 wsa->write.iovec[0].iov_len = wsa->buffers.TailLength;
2482 wsa->buffers.Tail = NULL;
2483 return STATUS_PENDING;
2486 return STATUS_SUCCESS;
2489 /***********************************************************************
2490 * WS2_transmitfile_base (INTERNAL)
2492 * Shared implementation for both synchronous and asynchronous TransmitFile.
2494 static NTSTATUS WS2_transmitfile_base( int fd, struct ws2_transmitfile_async *wsa )
2496 NTSTATUS status;
2498 status = WS2_transmitfile_getbuffer( fd, wsa );
2499 if (status == STATUS_PENDING)
2501 IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)wsa->write.user_overlapped;
2502 int n;
2504 n = WS2_send( fd, &wsa->write, convert_flags(wsa->write.flags) );
2505 if (n >= 0)
2507 if (iosb) iosb->Information += n;
2509 else if (errno != EAGAIN)
2510 return wsaErrStatus();
2513 return status;
2516 /***********************************************************************
2517 * WS2_async_transmitfile (INTERNAL)
2519 * Asynchronous callback for overlapped TransmitFile operations.
2521 static NTSTATUS WS2_async_transmitfile( void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status )
2523 struct ws2_transmitfile_async *wsa = user;
2524 int fd;
2526 if (status == STATUS_ALERTED)
2528 if (!(status = wine_server_handle_to_fd( wsa->write.hSocket, FILE_WRITE_DATA, &fd, NULL )))
2530 status = WS2_transmitfile_base( fd, wsa );
2531 close( fd );
2533 if (status == STATUS_PENDING)
2534 return status;
2537 iosb->u.Status = status;
2538 release_async_io( &wsa->io );
2539 return status;
2542 /***********************************************************************
2543 * TransmitFile
2545 static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD bytes_per_send,
2546 LPOVERLAPPED overlapped, LPTRANSMIT_FILE_BUFFERS buffers,
2547 DWORD flags )
2549 union generic_unix_sockaddr uaddr;
2550 socklen_t uaddrlen = sizeof(uaddr);
2551 struct ws2_transmitfile_async *wsa;
2552 NTSTATUS status;
2553 int fd;
2555 TRACE("(%lx, %p, %d, %d, %p, %p, %d)\n", s, h, file_bytes, bytes_per_send, overlapped,
2556 buffers, flags );
2558 fd = get_sock_fd( s, FILE_WRITE_DATA, NULL );
2559 if (fd == -1) return FALSE;
2561 if (getpeername( fd, &uaddr.addr, &uaddrlen ) != 0)
2563 release_sock_fd( s, fd );
2564 WSASetLastError( WSAENOTCONN );
2565 return FALSE;
2567 if (flags)
2568 FIXME("Flags are not currently supported (0x%x).\n", flags);
2570 if (h && GetFileType( h ) != FILE_TYPE_DISK)
2572 FIXME("Non-disk file handles are not currently supported.\n");
2573 release_sock_fd( s, fd );
2574 WSASetLastError( WSAEOPNOTSUPP );
2575 return FALSE;
2578 /* set reasonable defaults when requested */
2579 if (!bytes_per_send)
2580 bytes_per_send = (1 << 16); /* Depends on OS version: PAGE_SIZE, 2*PAGE_SIZE, or 2^16 */
2582 if (!(wsa = (struct ws2_transmitfile_async *)alloc_async_io( sizeof(*wsa) + bytes_per_send,
2583 WS2_async_transmitfile )))
2585 release_sock_fd( s, fd );
2586 WSASetLastError( WSAEFAULT );
2587 return FALSE;
2589 if (buffers)
2590 wsa->buffers = *buffers;
2591 else
2592 memset(&wsa->buffers, 0x0, sizeof(wsa->buffers));
2593 wsa->buffer = (char *)(wsa + 1);
2594 wsa->file = h;
2595 wsa->file_read = 0;
2596 wsa->file_bytes = file_bytes;
2597 wsa->bytes_per_send = bytes_per_send;
2598 wsa->flags = flags;
2599 wsa->offset.QuadPart = FILE_USE_FILE_POINTER_POSITION;
2600 wsa->write.hSocket = SOCKET2HANDLE(s);
2601 wsa->write.addr = NULL;
2602 wsa->write.addrlen.val = 0;
2603 wsa->write.flags = 0;
2604 wsa->write.lpFlags = &wsa->flags;
2605 wsa->write.control = NULL;
2606 wsa->write.n_iovecs = 0;
2607 wsa->write.first_iovec = 0;
2608 wsa->write.user_overlapped = overlapped;
2609 if (overlapped)
2611 IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)overlapped;
2612 int status;
2614 wsa->offset.u.LowPart = overlapped->u.s.Offset;
2615 wsa->offset.u.HighPart = overlapped->u.s.OffsetHigh;
2616 iosb->u.Status = STATUS_PENDING;
2617 iosb->Information = 0;
2618 status = register_async( ASYNC_TYPE_WRITE, SOCKET2HANDLE(s), &wsa->io,
2619 overlapped->hEvent, NULL, NULL, iosb );
2620 if(status != STATUS_PENDING) HeapFree( GetProcessHeap(), 0, wsa );
2621 release_sock_fd( s, fd );
2622 WSASetLastError( NtStatusToWSAError(status) );
2623 return FALSE;
2628 status = WS2_transmitfile_base( fd, wsa );
2629 if (status == STATUS_PENDING)
2631 /* block here */
2632 do_block(fd, POLLOUT, -1);
2633 _sync_sock_state(s); /* let wineserver notice connection */
2636 while (status == STATUS_PENDING);
2637 release_sock_fd( s, fd );
2639 if (status != STATUS_SUCCESS)
2640 WSASetLastError( NtStatusToWSAError(status) );
2641 HeapFree( GetProcessHeap(), 0, wsa );
2642 return (status == STATUS_SUCCESS);
2645 /***********************************************************************
2646 * GetAcceptExSockaddrs
2648 static void WINAPI WS2_GetAcceptExSockaddrs(PVOID buffer, DWORD data_size, DWORD local_size, DWORD remote_size,
2649 struct WS_sockaddr **local_addr, LPINT local_addr_len,
2650 struct WS_sockaddr **remote_addr, LPINT remote_addr_len)
2652 char *cbuf = buffer;
2653 TRACE("(%p, %d, %d, %d, %p, %p, %p, %p)\n", buffer, data_size, local_size, remote_size, local_addr,
2654 local_addr_len, remote_addr, remote_addr_len );
2655 cbuf += data_size;
2657 *local_addr_len = *(int *) cbuf;
2658 *local_addr = (struct WS_sockaddr *)(cbuf + sizeof(int));
2660 cbuf += local_size;
2662 *remote_addr_len = *(int *) cbuf;
2663 *remote_addr = (struct WS_sockaddr *)(cbuf + sizeof(int));
2666 /***********************************************************************
2667 * WSASendMsg
2669 int WINAPI WSASendMsg( SOCKET s, LPWSAMSG msg, DWORD dwFlags, LPDWORD lpNumberOfBytesSent,
2670 LPWSAOVERLAPPED lpOverlapped,
2671 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
2673 if (!msg)
2675 SetLastError( WSAEFAULT );
2676 return SOCKET_ERROR;
2679 return WS2_sendto( s, msg->lpBuffers, msg->dwBufferCount, lpNumberOfBytesSent,
2680 dwFlags, msg->name, msg->namelen,
2681 lpOverlapped, lpCompletionRoutine );
2684 /***********************************************************************
2685 * WSARecvMsg
2687 * Perform a receive operation that is capable of returning message
2688 * control headers. It is important to note that the WSAMSG parameter
2689 * must remain valid throughout the operation, even when an overlapped
2690 * receive is performed.
2692 static int WINAPI WS2_WSARecvMsg( SOCKET s, LPWSAMSG msg, LPDWORD lpNumberOfBytesRecvd,
2693 LPWSAOVERLAPPED lpOverlapped,
2694 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2696 if (!msg)
2698 SetLastError( WSAEFAULT );
2699 return SOCKET_ERROR;
2702 return WS2_recv_base( s, msg->lpBuffers, msg->dwBufferCount, lpNumberOfBytesRecvd,
2703 &msg->dwFlags, msg->name, &msg->namelen,
2704 lpOverlapped, lpCompletionRoutine, &msg->Control );
2707 /***********************************************************************
2708 * interface_bind (INTERNAL)
2710 * Take bind() calls on any name corresponding to a local network adapter and restrict the given socket to
2711 * operating only on the specified interface. This restriction consists of two components:
2712 * 1) An outgoing packet restriction suggesting the egress interface for all packets.
2713 * 2) An incoming packet restriction dropping packets not meant for the interface.
2714 * If the function succeeds in placing these restrictions (returns TRUE) then the name for the bind() may
2715 * safely be changed to INADDR_ANY, permitting the transmission and receipt of broadcast packets on the
2716 * socket. This behavior is only relevant to UDP sockets and is needed for applications that expect to be able
2717 * to receive broadcast packets on a socket that is bound to a specific network interface.
2719 static BOOL interface_bind( SOCKET s, int fd, struct sockaddr *addr )
2721 struct sockaddr_in *in_sock = (struct sockaddr_in *) addr;
2722 in_addr_t bind_addr = in_sock->sin_addr.s_addr;
2723 PIP_ADAPTER_INFO adapters = NULL, adapter;
2724 BOOL ret = FALSE;
2725 DWORD adap_size;
2726 int enable = 1;
2728 if (bind_addr == htonl(INADDR_ANY) || bind_addr == htonl(INADDR_LOOPBACK))
2729 return FALSE; /* Not binding to a network adapter, special interface binding unnecessary. */
2730 if (_get_fd_type(fd) != SOCK_DGRAM)
2731 return FALSE; /* Special interface binding is only necessary for UDP datagrams. */
2732 if (GetAdaptersInfo(NULL, &adap_size) != ERROR_BUFFER_OVERFLOW)
2733 goto cleanup;
2734 adapters = HeapAlloc(GetProcessHeap(), 0, adap_size);
2735 if (adapters == NULL || GetAdaptersInfo(adapters, &adap_size) != NO_ERROR)
2736 goto cleanup;
2737 /* Search the IPv4 adapter list for the appropriate binding interface */
2738 for (adapter = adapters; adapter != NULL; adapter = adapter->Next)
2740 in_addr_t adapter_addr = (in_addr_t) inet_addr(adapter->IpAddressList.IpAddress.String);
2742 if (bind_addr == adapter_addr)
2744 #if defined(IP_BOUND_IF)
2745 /* IP_BOUND_IF sets both the incoming and outgoing restriction at once */
2746 if (setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &adapter->Index, sizeof(adapter->Index)) != 0)
2747 goto cleanup;
2748 ret = TRUE;
2749 #elif defined(LINUX_BOUND_IF)
2750 in_addr_t ifindex = (in_addr_t) htonl(adapter->Index);
2751 struct interface_filter specific_interface_filter;
2752 struct sock_fprog filter_prog;
2754 if (setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex)) != 0)
2755 goto cleanup; /* Failed to suggest egress interface */
2756 specific_interface_filter = generic_interface_filter;
2757 specific_interface_filter.iface_rule.k = adapter->Index;
2758 specific_interface_filter.ip_rule.k = htonl(adapter_addr);
2759 filter_prog.len = sizeof(generic_interface_filter)/sizeof(struct sock_filter);
2760 filter_prog.filter = (struct sock_filter *) &specific_interface_filter;
2761 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, sizeof(filter_prog)) != 0)
2762 goto cleanup; /* Failed to specify incoming packet filter */
2763 ret = TRUE;
2764 #else
2765 FIXME("Broadcast packets on interface-bound sockets are not currently supported on this platform, "
2766 "receiving broadcast packets will not work on socket %04lx.\n", s);
2767 #endif
2768 if (ret)
2770 EnterCriticalSection(&cs_if_addr_cache);
2771 if (if_addr_cache_size <= adapter->Index)
2773 unsigned int new_size;
2774 in_addr_t *new;
2776 new_size = max(if_addr_cache_size * 2, adapter->Index + 1);
2777 if (!(new = heap_realloc(if_addr_cache, sizeof(*if_addr_cache) * new_size)))
2779 ERR("No memory.\n");
2780 ret = FALSE;
2781 LeaveCriticalSection(&cs_if_addr_cache);
2782 break;
2784 memset(new + if_addr_cache_size, 0, sizeof(*if_addr_cache)
2785 * (new_size - if_addr_cache_size));
2786 if_addr_cache = new;
2787 if_addr_cache_size = new_size;
2789 if (if_addr_cache[adapter->Index] && if_addr_cache[adapter->Index] != adapter_addr)
2790 WARN("Adapter addr for iface index %u has changed.\n", adapter->Index);
2792 if_addr_cache[adapter->Index] = adapter_addr;
2793 LeaveCriticalSection(&cs_if_addr_cache);
2795 break;
2798 /* Will soon be switching to INADDR_ANY: permit address reuse */
2799 if (ret && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) == 0)
2800 TRACE("Socket %04lx bound to interface index %d\n", s, adapter->Index);
2801 else
2802 ret = FALSE;
2804 cleanup:
2805 if(!ret)
2806 ERR("Failed to bind to interface, receiving broadcast packets will not work on socket %04lx.\n", s);
2807 HeapFree(GetProcessHeap(), 0, adapters);
2808 return ret;
2811 /***********************************************************************
2812 * bind (WS2_32.2)
2814 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
2816 int fd = get_sock_fd( s, 0, NULL );
2817 int res = SOCKET_ERROR;
2819 TRACE("socket %04lx, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
2821 if (fd != -1)
2823 if (!name || (name->sa_family && !supported_pf(name->sa_family)))
2825 SetLastError(WSAEAFNOSUPPORT);
2827 else
2829 union generic_unix_sockaddr uaddr;
2830 unsigned int uaddrlen = ws_sockaddr_ws2u(name, namelen, &uaddr);
2831 if (!uaddrlen)
2833 SetLastError(WSAEFAULT);
2835 else
2837 if (name->sa_family == WS_AF_INET)
2839 struct sockaddr_in *in4 = (struct sockaddr_in*) &uaddr;
2840 if (memcmp(&in4->sin_addr, magic_loopback_addr, 4) == 0)
2842 /* Trying to bind to the default host interface, using
2843 * INADDR_ANY instead*/
2844 WARN("Trying to bind to magic IP address, using "
2845 "INADDR_ANY instead.\n");
2846 in4->sin_addr.s_addr = htonl(INADDR_ANY);
2848 else if (interface_bind(s, fd, &uaddr.addr))
2849 in4->sin_addr.s_addr = htonl(INADDR_ANY);
2851 if (bind(fd, &uaddr.addr, uaddrlen) < 0)
2853 int loc_errno = errno;
2854 WARN("\tfailure - errno = %i\n", errno);
2855 errno = loc_errno;
2856 switch (errno)
2858 case EADDRNOTAVAIL:
2859 SetLastError(WSAEINVAL);
2860 break;
2861 case EADDRINUSE:
2863 int optval = 0;
2864 socklen_t optlen = sizeof(optval);
2865 /* Windows >= 2003 will return different results depending on
2866 * SO_REUSEADDR, WSAEACCES may be returned representing that
2867 * the socket hijacking protection prevented the bind */
2868 if (!getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, &optlen) && optval)
2870 SetLastError(WSAEACCES);
2871 break;
2873 /* fall through */
2875 default:
2876 SetLastError(wsaErrno());
2877 break;
2880 else
2882 res=0; /* success */
2886 release_sock_fd( s, fd );
2888 return res;
2891 /***********************************************************************
2892 * closesocket (WS2_32.3)
2894 int WINAPI WS_closesocket(SOCKET s)
2896 int res = SOCKET_ERROR, fd;
2897 if (num_startup)
2899 fd = get_sock_fd(s, FILE_READ_DATA, NULL);
2900 if (fd >= 0)
2902 release_sock_fd(s, fd);
2903 socket_list_remove(s);
2904 if (CloseHandle(SOCKET2HANDLE(s)))
2905 res = 0;
2908 else
2909 SetLastError(WSANOTINITIALISED);
2910 TRACE("(socket %04lx) -> %d\n", s, res);
2911 return res;
2915 /***********************************************************************
2916 * connect (ws2_32.4)
2918 int WINAPI WS_connect( SOCKET s, const struct WS_sockaddr *addr, int len )
2920 union generic_unix_sockaddr uaddr;
2921 unsigned int uaddrlen = ws_sockaddr_ws2u( addr, len, &uaddr );
2922 struct afd_connect_params *params;
2923 IO_STATUS_BLOCK io;
2924 HANDLE sync_event;
2925 NTSTATUS status;
2927 TRACE( "socket %#lx, addr %s, len %d\n", s, debugstr_sockaddr(addr), len );
2929 if (!uaddrlen)
2931 SetLastError( WSAEFAULT );
2932 return -1;
2935 if (addr->sa_family == WS_AF_INET)
2937 struct sockaddr_in *in4 = (struct sockaddr_in *)&uaddr;
2938 if (!memcmp(&in4->sin_addr, magic_loopback_addr, sizeof(magic_loopback_addr)))
2940 TRACE("Replacing magic address 127.12.34.56 with INADDR_LOOPBACK.\n");
2941 in4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2945 if (!(sync_event = get_sync_event())) return -1;
2947 if (!(params = HeapAlloc( GetProcessHeap(), 0, sizeof(*params) + uaddrlen )))
2949 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
2950 return -1;
2952 params->addr_len = uaddrlen;
2953 params->synchronous = TRUE;
2954 memcpy(params + 1, &uaddr, uaddrlen);
2956 status = NtDeviceIoControlFile( (HANDLE)s, sync_event, NULL, NULL, &io, IOCTL_AFD_WINE_CONNECT,
2957 params, sizeof(*params) + uaddrlen, NULL, 0);
2958 HeapFree( GetProcessHeap(), 0, params );
2959 if (status == STATUS_PENDING)
2961 if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED) return -1;
2962 status = io.u.Status;
2964 if (status)
2966 SetLastError( NtStatusToWSAError( status ) );
2967 return -1;
2969 return 0;
2973 /***********************************************************************
2974 * WSAConnect (WS2_32.30)
2976 int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
2977 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
2978 LPQOS lpSQOS, LPQOS lpGQOS )
2980 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
2981 FIXME("unsupported parameters!\n");
2982 return WS_connect( s, name, namelen );
2986 static BOOL WINAPI WS2_ConnectEx( SOCKET s, const struct WS_sockaddr *name, int namelen,
2987 void *send_buffer, DWORD send_len, DWORD *ret_len, OVERLAPPED *overlapped )
2989 union generic_unix_sockaddr uaddr;
2990 unsigned int uaddrlen = ws_sockaddr_ws2u(name, namelen, &uaddr);
2991 struct afd_connect_params *params;
2992 void *cvalue = NULL;
2993 NTSTATUS status;
2994 int fd, ret;
2996 TRACE( "socket %#lx, ptr %p %s, length %d, send_buffer %p, send_len %u, overlapped %p\n",
2997 s, name, debugstr_sockaddr(name), namelen, send_buffer, send_len, overlapped );
2999 if ((fd = get_sock_fd( s, FILE_READ_DATA, NULL )) == -1)
3000 return FALSE;
3002 if ((ret = is_fd_bound( fd, NULL, NULL )) <= 0)
3004 SetLastError( ret ? wsaErrno() : WSAEINVAL );
3005 release_sock_fd( s, fd );
3006 return FALSE;
3008 release_sock_fd( s, fd );
3010 if (!overlapped)
3012 SetLastError( WSA_INVALID_PARAMETER );
3013 return FALSE;
3016 if (!((ULONG_PTR)overlapped->hEvent & 1)) cvalue = overlapped;
3017 overlapped->Internal = STATUS_PENDING;
3018 overlapped->InternalHigh = 0;
3020 if (!uaddrlen)
3022 SetLastError( WSAEFAULT );
3023 return SOCKET_ERROR;
3026 if (name->sa_family == WS_AF_INET)
3028 struct sockaddr_in *in4 = (struct sockaddr_in *)&uaddr;
3029 if (!memcmp( &in4->sin_addr, magic_loopback_addr, sizeof(magic_loopback_addr) ))
3031 TRACE("Replacing magic address 127.12.34.56 with INADDR_LOOPBACK.\n");
3032 in4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
3036 if (!(params = HeapAlloc( GetProcessHeap(), 0, sizeof(*params) + uaddrlen + send_len )))
3038 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
3039 return SOCKET_ERROR;
3041 params->addr_len = uaddrlen;
3042 params->synchronous = FALSE;
3043 memcpy( params + 1, &uaddr, uaddrlen );
3044 memcpy( (char *)(params + 1) + uaddrlen, send_buffer, send_len );
3046 status = NtDeviceIoControlFile( SOCKET2HANDLE(s), overlapped->hEvent, NULL, cvalue,
3047 (IO_STATUS_BLOCK *)overlapped, IOCTL_AFD_WINE_CONNECT,
3048 params, sizeof(*params) + uaddrlen + send_len, NULL, 0 );
3049 HeapFree( GetProcessHeap(), 0, params );
3050 if (ret_len) *ret_len = overlapped->InternalHigh;
3051 SetLastError( NtStatusToWSAError( status ) );
3052 return !status;
3056 static BOOL WINAPI WS2_DisconnectEx( SOCKET s, OVERLAPPED *overlapped, DWORD flags, DWORD reserved )
3058 IO_STATUS_BLOCK iosb, *piosb = &iosb;
3059 void *cvalue = NULL;
3060 int how = SD_SEND;
3061 HANDLE event = 0;
3062 NTSTATUS status;
3064 TRACE( "socket %#lx, overlapped %p, flags %#x, reserved %#x\n", s, overlapped, flags, reserved );
3066 if (flags & TF_REUSE_SOCKET)
3067 FIXME( "Reusing socket not supported yet\n" );
3069 if (overlapped)
3071 piosb = (IO_STATUS_BLOCK *)overlapped;
3072 if (!((ULONG_PTR)overlapped->hEvent & 1)) cvalue = overlapped;
3073 event = overlapped->hEvent;
3074 overlapped->Internal = STATUS_PENDING;
3075 overlapped->InternalHigh = 0;
3078 status = NtDeviceIoControlFile( (HANDLE)s, event, NULL, cvalue, piosb,
3079 IOCTL_AFD_WINE_SHUTDOWN, &how, sizeof(how), NULL, 0 );
3080 if (!status && overlapped) status = STATUS_PENDING;
3081 SetLastError( NtStatusToWSAError( status ) );
3082 return !status;
3085 /***********************************************************************
3086 * getpeername (WS2_32.5)
3088 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
3090 int fd;
3091 int res;
3093 TRACE("socket %04lx, ptr %p, len %08x\n", s, name, namelen ? *namelen : 0);
3095 fd = get_sock_fd( s, 0, NULL );
3096 res = SOCKET_ERROR;
3098 if (fd != -1)
3100 union generic_unix_sockaddr uaddr;
3101 socklen_t uaddrlen = sizeof(uaddr);
3103 if (getpeername(fd, &uaddr.addr, &uaddrlen) == 0)
3105 if (!name || !namelen)
3106 SetLastError(WSAEFAULT);
3107 else if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
3108 /* The buffer was too small */
3109 SetLastError(WSAEFAULT);
3110 else
3112 res = 0;
3113 TRACE("=> %s\n", debugstr_sockaddr(name));
3116 else
3117 SetLastError(wsaErrno());
3118 release_sock_fd( s, fd );
3120 return res;
3123 /* When binding to an UDP address with filter support the getsockname call on the socket
3124 * will always return 0.0.0.0 instead of the filtered interface address. This function
3125 * checks if the socket is interface-bound on UDP and return the correct address.
3126 * This is required because applications often do a bind() with port zero followed by a
3127 * getsockname() to retrieve the port and address acquired.
3129 static void interface_bind_check(int fd, struct sockaddr_in *addr)
3131 #if !defined(IP_BOUND_IF) && !defined(LINUX_BOUND_IF)
3132 return;
3133 #else
3134 unsigned int ifindex;
3135 int ret;
3136 socklen_t len;
3138 /* Check for IPv4, address 0.0.0.0 and UDP socket */
3139 if (addr->sin_family != AF_INET || addr->sin_addr.s_addr != 0)
3140 return;
3141 if (_get_fd_type(fd) != SOCK_DGRAM)
3142 return;
3144 len = sizeof(ifindex);
3145 #if defined(IP_BOUND_IF)
3146 ret = getsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &ifindex, &len);
3147 #elif defined(LINUX_BOUND_IF)
3148 ret = getsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, &len);
3149 if (!ret) ifindex = ntohl(ifindex);
3150 #endif
3151 if (!ret && ifindex)
3153 EnterCriticalSection(&cs_if_addr_cache);
3154 if (ifindex < if_addr_cache_size)
3155 addr->sin_addr.s_addr = if_addr_cache[ifindex];
3156 else
3157 ERR("No cache entry for ifindex %u.\n", ifindex);
3158 LeaveCriticalSection(&cs_if_addr_cache);
3160 #endif
3163 /***********************************************************************
3164 * getsockname (WS2_32.6)
3166 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
3168 int fd;
3169 int res;
3171 TRACE("socket %04lx, ptr %p, len %08x\n", s, name, namelen ? *namelen : 0);
3173 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
3174 if( (name == NULL) || (namelen == NULL) )
3176 SetLastError( WSAEFAULT );
3177 return SOCKET_ERROR;
3180 fd = get_sock_fd( s, 0, NULL );
3181 res = SOCKET_ERROR;
3183 if (fd != -1)
3185 union generic_unix_sockaddr uaddr;
3186 socklen_t uaddrlen;
3187 int bound = is_fd_bound(fd, &uaddr, &uaddrlen);
3189 if (bound <= 0)
3191 SetLastError(bound == -1 ? wsaErrno() : WSAEINVAL);
3193 else if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
3195 /* The buffer was too small */
3196 SetLastError(WSAEFAULT);
3198 else
3200 interface_bind_check(fd, (struct sockaddr_in*) &uaddr);
3201 if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
3203 /* The buffer was too small */
3204 SetLastError(WSAEFAULT);
3206 else
3208 res = 0;
3209 TRACE("=> %s\n", debugstr_sockaddr(name));
3212 release_sock_fd( s, fd );
3214 return res;
3217 /***********************************************************************
3218 * getsockopt (WS2_32.7)
3220 INT WINAPI WS_getsockopt(SOCKET s, INT level,
3221 INT optname, char *optval, INT *optlen)
3223 int fd;
3224 INT ret = 0;
3226 TRACE("(socket %04lx, %s, optval %s, optlen %p (%d))\n", s,
3227 debugstr_sockopt(level, optname), debugstr_optval(optval, 0),
3228 optlen, optlen ? *optlen : 0);
3230 switch(level)
3232 case WS_SOL_SOCKET:
3234 switch(optname)
3236 /* Handle common cases. The special cases are below, sorted
3237 * alphabetically */
3238 case WS_SO_BROADCAST:
3239 case WS_SO_DEBUG:
3240 case WS_SO_KEEPALIVE:
3241 case WS_SO_OOBINLINE:
3242 case WS_SO_RCVBUF:
3243 case WS_SO_REUSEADDR:
3244 case WS_SO_SNDBUF:
3245 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3246 return SOCKET_ERROR;
3247 convert_sockopt(&level, &optname);
3248 if (getsockopt(fd, level, optname, optval, (socklen_t *)optlen) != 0 )
3250 SetLastError(wsaErrno());
3251 ret = SOCKET_ERROR;
3253 release_sock_fd( s, fd );
3254 return ret;
3255 case WS_SO_ACCEPTCONN:
3256 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3257 return SOCKET_ERROR;
3258 if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, optval, (socklen_t *)optlen) != 0 )
3260 SetLastError(wsaErrno());
3261 ret = SOCKET_ERROR;
3263 else
3265 /* BSD returns != 0 while Windows return exact == 1 */
3266 if (*(int *)optval) *(int *)optval = 1;
3268 release_sock_fd( s, fd );
3269 return ret;
3270 case WS_SO_BSP_STATE:
3272 int req_size, addr_size;
3273 WSAPROTOCOL_INFOW infow;
3274 CSADDR_INFO *csinfo;
3276 ret = ws_protocol_info(s, TRUE, &infow, &addr_size);
3277 if (ret)
3279 if (infow.iAddressFamily == WS_AF_INET)
3280 addr_size = sizeof(struct sockaddr_in);
3281 else if (infow.iAddressFamily == WS_AF_INET6)
3282 addr_size = sizeof(struct sockaddr_in6);
3283 else
3285 FIXME("Family %d is unsupported for SO_BSP_STATE\n", infow.iAddressFamily);
3286 SetLastError(WSAEAFNOSUPPORT);
3287 return SOCKET_ERROR;
3290 req_size = sizeof(CSADDR_INFO) + addr_size * 2;
3291 if (*optlen < req_size)
3293 ret = 0;
3294 SetLastError(WSAEFAULT);
3296 else
3298 union generic_unix_sockaddr uaddr;
3299 socklen_t uaddrlen;
3301 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3302 return SOCKET_ERROR;
3304 csinfo = (CSADDR_INFO*) optval;
3306 /* Check if the sock is bound */
3307 if (is_fd_bound(fd, &uaddr, &uaddrlen) == 1)
3309 csinfo->LocalAddr.lpSockaddr =
3310 (LPSOCKADDR) (optval + sizeof(CSADDR_INFO));
3311 ws_sockaddr_u2ws(&uaddr.addr, csinfo->LocalAddr.lpSockaddr, &addr_size);
3312 csinfo->LocalAddr.iSockaddrLength = addr_size;
3314 else
3316 csinfo->LocalAddr.lpSockaddr = NULL;
3317 csinfo->LocalAddr.iSockaddrLength = 0;
3320 /* Check if the sock is connected */
3321 if (!getpeername(fd, &uaddr.addr, &uaddrlen) &&
3322 is_sockaddr_bound(&uaddr.addr, uaddrlen))
3324 csinfo->RemoteAddr.lpSockaddr =
3325 (LPSOCKADDR) (optval + sizeof(CSADDR_INFO) + addr_size);
3326 ws_sockaddr_u2ws(&uaddr.addr, csinfo->RemoteAddr.lpSockaddr, &addr_size);
3327 csinfo->RemoteAddr.iSockaddrLength = addr_size;
3329 else
3331 csinfo->RemoteAddr.lpSockaddr = NULL;
3332 csinfo->RemoteAddr.iSockaddrLength = 0;
3335 csinfo->iSocketType = infow.iSocketType;
3336 csinfo->iProtocol = infow.iProtocol;
3337 release_sock_fd( s, fd );
3340 return ret ? 0 : SOCKET_ERROR;
3342 case WS_SO_DONTLINGER:
3344 struct linger lingval;
3345 socklen_t len = sizeof(struct linger);
3347 if (!optlen || *optlen < sizeof(BOOL)|| !optval)
3349 SetLastError(WSAEFAULT);
3350 return SOCKET_ERROR;
3352 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3353 return SOCKET_ERROR;
3355 if (getsockopt(fd, SOL_SOCKET, SO_LINGER, &lingval, &len) != 0 )
3357 SetLastError(wsaErrno());
3358 ret = SOCKET_ERROR;
3360 else
3362 *(BOOL *)optval = !lingval.l_onoff;
3363 *optlen = sizeof(BOOL);
3366 release_sock_fd( s, fd );
3367 return ret;
3370 case WS_SO_CONNECT_TIME:
3372 static int pretendtime = 0;
3373 struct WS_sockaddr addr;
3374 int len = sizeof(addr);
3376 if (!optlen || *optlen < sizeof(DWORD) || !optval)
3378 SetLastError(WSAEFAULT);
3379 return SOCKET_ERROR;
3381 if (WS_getpeername(s, &addr, &len) == SOCKET_ERROR)
3382 *(DWORD *)optval = ~0u;
3383 else
3385 if (!pretendtime) FIXME("WS_SO_CONNECT_TIME - faking results\n");
3386 *(DWORD *)optval = pretendtime++;
3388 *optlen = sizeof(DWORD);
3389 return ret;
3391 /* As mentioned in setsockopt, Windows ignores this, so we
3392 * always return true here */
3393 case WS_SO_DONTROUTE:
3394 if (!optlen || *optlen < sizeof(BOOL) || !optval)
3396 SetLastError(WSAEFAULT);
3397 return SOCKET_ERROR;
3399 *(BOOL *)optval = TRUE;
3400 *optlen = sizeof(BOOL);
3401 return 0;
3403 case WS_SO_ERROR:
3405 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3406 return SOCKET_ERROR;
3407 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, optval, (socklen_t *)optlen) != 0 )
3409 SetLastError(wsaErrno());
3410 ret = SOCKET_ERROR;
3412 release_sock_fd( s, fd );
3414 /* The wineserver may have swallowed the error before us */
3415 if (!ret && *(int*) optval == 0)
3417 int i, events[FD_MAX_EVENTS];
3418 _get_sock_errors(s, events);
3419 for (i = 0; i < FD_MAX_EVENTS; i++)
3421 if(events[i])
3423 TRACE("returning SO_ERROR %d from wine server\n", events[i]);
3424 *(int*) optval = events[i];
3425 break;
3429 return ret;
3432 case WS_SO_LINGER:
3434 struct linger lingval;
3435 socklen_t len = sizeof(struct linger);
3437 /* struct linger and LINGER have different sizes */
3438 if (!optlen || *optlen < sizeof(LINGER) || !optval)
3440 SetLastError(WSAEFAULT);
3441 return SOCKET_ERROR;
3443 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3444 return SOCKET_ERROR;
3446 if (_get_fd_type(fd) == SOCK_DGRAM)
3448 SetLastError(WSAENOPROTOOPT);
3449 ret = SOCKET_ERROR;
3451 else if (getsockopt(fd, SOL_SOCKET, SO_LINGER, &lingval, &len) != 0)
3453 SetLastError(wsaErrno());
3454 ret = SOCKET_ERROR;
3456 else
3458 ((LINGER *)optval)->l_onoff = lingval.l_onoff;
3459 ((LINGER *)optval)->l_linger = lingval.l_linger;
3460 *optlen = sizeof(struct linger);
3463 release_sock_fd( s, fd );
3464 return ret;
3467 case WS_SO_MAX_MSG_SIZE:
3468 if (!optlen || *optlen < sizeof(int) || !optval)
3470 SetLastError(WSAEFAULT);
3471 return SOCKET_ERROR;
3473 TRACE("getting global SO_MAX_MSG_SIZE = 65507\n");
3474 *(int *)optval = 65507;
3475 *optlen = sizeof(int);
3476 return 0;
3478 /* SO_OPENTYPE does not require a valid socket handle. */
3479 case WS_SO_OPENTYPE:
3480 if (!optlen || *optlen < sizeof(int) || !optval)
3482 SetLastError(WSAEFAULT);
3483 return SOCKET_ERROR;
3485 *(int *)optval = get_per_thread_data()->opentype;
3486 *optlen = sizeof(int);
3487 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
3488 return 0;
3489 case WS_SO_PROTOCOL_INFOA:
3490 case WS_SO_PROTOCOL_INFOW:
3492 int size;
3493 WSAPROTOCOL_INFOW infow;
3495 ret = ws_protocol_info(s, optname == WS_SO_PROTOCOL_INFOW, &infow, &size);
3496 if (ret)
3498 if (!optlen || !optval || *optlen < size)
3500 if(optlen) *optlen = size;
3501 ret = 0;
3502 SetLastError(WSAEFAULT);
3504 else
3505 memcpy(optval, &infow, size);
3507 return ret ? 0 : SOCKET_ERROR;
3509 case WS_SO_RCVTIMEO:
3510 case WS_SO_SNDTIMEO:
3512 INT64 timeout;
3514 if (!optlen || *optlen < sizeof(int)|| !optval)
3516 SetLastError(WSAEFAULT);
3517 return SOCKET_ERROR;
3519 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3520 return SOCKET_ERROR;
3522 timeout = get_rcvsnd_timeo(fd, optname == WS_SO_RCVTIMEO);
3523 *(int *)optval = timeout <= UINT_MAX ? timeout : UINT_MAX;
3525 release_sock_fd( s, fd );
3526 return ret;
3528 case WS_SO_TYPE:
3530 int sock_type;
3531 if (!optlen || *optlen < sizeof(int) || !optval)
3533 SetLastError(WSAEFAULT);
3534 return SOCKET_ERROR;
3536 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3537 return SOCKET_ERROR;
3539 sock_type = _get_fd_type(fd);
3540 if (sock_type == -1)
3542 SetLastError(wsaErrno());
3543 ret = SOCKET_ERROR;
3545 else
3546 (*(int *)optval) = convert_socktype_u2w(sock_type);
3548 release_sock_fd( s, fd );
3549 return ret;
3551 default:
3552 TRACE("Unknown SOL_SOCKET optname: 0x%08x\n", optname);
3553 SetLastError(WSAENOPROTOOPT);
3554 return SOCKET_ERROR;
3555 } /* end switch(optname) */
3556 }/* end case WS_SOL_SOCKET */
3557 #ifdef HAS_IPX
3558 case WS_NSPROTO_IPX:
3560 struct WS_sockaddr_ipx addr;
3561 IPX_ADDRESS_DATA *data;
3562 int namelen;
3563 switch(optname)
3565 case WS_IPX_PTYPE:
3566 if ((fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR;
3567 #ifdef SOL_IPX
3568 if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, (socklen_t *)optlen) == -1)
3570 ret = SOCKET_ERROR;
3572 #else
3574 struct ipx val;
3575 socklen_t len=sizeof(struct ipx);
3576 if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
3577 ret = SOCKET_ERROR;
3578 else
3579 *optval = (int)val.ipx_pt;
3581 #endif
3582 TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
3583 release_sock_fd( s, fd );
3584 return ret;
3586 case WS_IPX_ADDRESS:
3588 * On a Win2000 system with one network card there are usually
3589 * three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
3590 * Using this call you can then retrieve info about this all.
3591 * In case of Linux it is a bit different. Usually you have
3592 * only "one" device active and further it is not possible to
3593 * query things like the linkspeed.
3595 FIXME("IPX_ADDRESS\n");
3596 namelen = sizeof(struct WS_sockaddr_ipx);
3597 memset(&addr, 0, sizeof(struct WS_sockaddr_ipx));
3598 WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
3600 data = (IPX_ADDRESS_DATA*)optval;
3601 memcpy(data->nodenum,addr.sa_nodenum,sizeof(data->nodenum));
3602 memcpy(data->netnum,addr.sa_netnum,sizeof(data->netnum));
3603 data->adapternum = 0;
3604 data->wan = FALSE; /* We are not on a wan for now .. */
3605 data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
3606 data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
3607 data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit;
3608 * note 1MB = 1000kB in this case */
3609 return 0;
3611 case WS_IPX_MAX_ADAPTER_NUM:
3612 FIXME("IPX_MAX_ADAPTER_NUM\n");
3613 *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
3614 return 0;
3616 default:
3617 FIXME("IPX optname:%x\n", optname);
3618 return SOCKET_ERROR;
3619 }/* end switch(optname) */
3620 } /* end case WS_NSPROTO_IPX */
3621 #endif
3623 #ifdef HAS_IRDA
3624 #define MAX_IRDA_DEVICES 10
3626 case WS_SOL_IRLMP:
3627 switch(optname)
3629 case WS_IRLMP_ENUMDEVICES:
3631 char buf[sizeof(struct irda_device_list) +
3632 (MAX_IRDA_DEVICES - 1) * sizeof(struct irda_device_info)];
3633 int res;
3634 socklen_t len = sizeof(buf);
3636 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3637 return SOCKET_ERROR;
3638 res = getsockopt( fd, SOL_IRLMP, IRLMP_ENUMDEVICES, buf, &len );
3639 release_sock_fd( s, fd );
3640 if (res < 0)
3642 SetLastError(wsaErrno());
3643 return SOCKET_ERROR;
3645 else
3647 struct irda_device_list *src = (struct irda_device_list *)buf;
3648 DEVICELIST *dst = (DEVICELIST *)optval;
3649 INT needed = sizeof(DEVICELIST);
3650 unsigned int i;
3652 if (src->len > 0)
3653 needed += (src->len - 1) * sizeof(IRDA_DEVICE_INFO);
3654 if (*optlen < needed)
3656 SetLastError(WSAEFAULT);
3657 return SOCKET_ERROR;
3659 *optlen = needed;
3660 TRACE("IRLMP_ENUMDEVICES: %d devices found:\n", src->len);
3661 dst->numDevice = src->len;
3662 for (i = 0; i < src->len; i++)
3664 TRACE("saddr = %08x, daddr = %08x, info = %s, hints = %02x%02x\n",
3665 src->dev[i].saddr, src->dev[i].daddr,
3666 src->dev[i].info, src->dev[i].hints[0],
3667 src->dev[i].hints[1]);
3668 memcpy( dst->Device[i].irdaDeviceID,
3669 &src->dev[i].daddr,
3670 sizeof(dst->Device[i].irdaDeviceID) ) ;
3671 memcpy( dst->Device[i].irdaDeviceName,
3672 src->dev[i].info,
3673 sizeof(dst->Device[i].irdaDeviceName) ) ;
3674 memcpy( &dst->Device[i].irdaDeviceHints1,
3675 &src->dev[i].hints[0],
3676 sizeof(dst->Device[i].irdaDeviceHints1) ) ;
3677 memcpy( &dst->Device[i].irdaDeviceHints2,
3678 &src->dev[i].hints[1],
3679 sizeof(dst->Device[i].irdaDeviceHints2) ) ;
3680 dst->Device[i].irdaCharSet = src->dev[i].charset;
3682 return 0;
3685 default:
3686 FIXME("IrDA optname:0x%x\n", optname);
3687 return SOCKET_ERROR;
3689 break; /* case WS_SOL_IRLMP */
3690 #undef MAX_IRDA_DEVICES
3691 #endif
3693 /* Levels WS_IPPROTO_TCP and WS_IPPROTO_IP convert directly */
3694 case WS_IPPROTO_TCP:
3695 switch(optname)
3697 case WS_TCP_NODELAY:
3698 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3699 return SOCKET_ERROR;
3700 convert_sockopt(&level, &optname);
3701 if (getsockopt(fd, level, optname, optval, (socklen_t *)optlen) != 0 )
3703 SetLastError(wsaErrno());
3704 ret = SOCKET_ERROR;
3706 release_sock_fd( s, fd );
3707 return ret;
3709 FIXME("Unknown IPPROTO_TCP optname 0x%08x\n", optname);
3710 return SOCKET_ERROR;
3712 case WS_IPPROTO_IP:
3713 switch(optname)
3715 case WS_IP_ADD_MEMBERSHIP:
3716 case WS_IP_DROP_MEMBERSHIP:
3717 #ifdef IP_HDRINCL
3718 case WS_IP_HDRINCL:
3719 #endif
3720 case WS_IP_MULTICAST_IF:
3721 case WS_IP_MULTICAST_LOOP:
3722 case WS_IP_MULTICAST_TTL:
3723 case WS_IP_OPTIONS:
3724 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
3725 case WS_IP_PKTINFO:
3726 #endif
3727 case WS_IP_TOS:
3728 case WS_IP_TTL:
3729 #ifdef IP_UNICAST_IF
3730 case WS_IP_UNICAST_IF:
3731 #endif
3732 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3733 return SOCKET_ERROR;
3734 convert_sockopt(&level, &optname);
3735 if (getsockopt(fd, level, optname, optval, (socklen_t *)optlen) != 0 )
3737 SetLastError(wsaErrno());
3738 ret = SOCKET_ERROR;
3740 release_sock_fd( s, fd );
3741 return ret;
3742 case WS_IP_DONTFRAGMENT:
3743 return get_dont_fragment(s, IPPROTO_IP, (BOOL *)optval) ? 0 : SOCKET_ERROR;
3745 FIXME("Unknown IPPROTO_IP optname 0x%08x\n", optname);
3746 return SOCKET_ERROR;
3748 case WS_IPPROTO_IPV6:
3749 switch(optname)
3751 #ifdef IPV6_ADD_MEMBERSHIP
3752 case WS_IPV6_ADD_MEMBERSHIP:
3753 #endif
3754 #ifdef IPV6_DROP_MEMBERSHIP
3755 case WS_IPV6_DROP_MEMBERSHIP:
3756 #endif
3757 case WS_IPV6_MULTICAST_IF:
3758 case WS_IPV6_MULTICAST_HOPS:
3759 case WS_IPV6_MULTICAST_LOOP:
3760 case WS_IPV6_UNICAST_HOPS:
3761 case WS_IPV6_V6ONLY:
3762 #ifdef IPV6_UNICAST_IF
3763 case WS_IPV6_UNICAST_IF:
3764 #endif
3765 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
3766 return SOCKET_ERROR;
3767 convert_sockopt(&level, &optname);
3768 if (getsockopt(fd, level, optname, optval, (socklen_t *)optlen) != 0 )
3770 SetLastError(wsaErrno());
3771 ret = SOCKET_ERROR;
3773 release_sock_fd( s, fd );
3774 return ret;
3775 case WS_IPV6_DONTFRAG:
3776 return get_dont_fragment(s, IPPROTO_IPV6, (BOOL *)optval) ? 0 : SOCKET_ERROR;
3778 FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname);
3779 return SOCKET_ERROR;
3781 default:
3782 WARN("Unknown level: 0x%08x\n", level);
3783 SetLastError(WSAEINVAL);
3784 return SOCKET_ERROR;
3785 } /* end switch(level) */
3789 static const char *debugstr_wsaioctl(DWORD code)
3791 const char *name = NULL, *buf_type, *family;
3793 #define IOCTL_NAME(x) case x: name = #x; break
3794 switch (code)
3796 IOCTL_NAME(WS_FIONBIO);
3797 IOCTL_NAME(WS_FIONREAD);
3798 IOCTL_NAME(WS_SIOCATMARK);
3799 /* IOCTL_NAME(WS_SIO_ACQUIRE_PORT_RESERVATION); */
3800 IOCTL_NAME(WS_SIO_ADDRESS_LIST_CHANGE);
3801 IOCTL_NAME(WS_SIO_ADDRESS_LIST_QUERY);
3802 IOCTL_NAME(WS_SIO_ASSOCIATE_HANDLE);
3803 /* IOCTL_NAME(WS_SIO_ASSOCIATE_PORT_RESERVATION);
3804 IOCTL_NAME(WS_SIO_BASE_HANDLE);
3805 IOCTL_NAME(WS_SIO_BSP_HANDLE);
3806 IOCTL_NAME(WS_SIO_BSP_HANDLE_SELECT);
3807 IOCTL_NAME(WS_SIO_BSP_HANDLE_POLL);
3808 IOCTL_NAME(WS_SIO_CHK_QOS); */
3809 IOCTL_NAME(WS_SIO_ENABLE_CIRCULAR_QUEUEING);
3810 IOCTL_NAME(WS_SIO_FIND_ROUTE);
3811 IOCTL_NAME(WS_SIO_FLUSH);
3812 IOCTL_NAME(WS_SIO_GET_BROADCAST_ADDRESS);
3813 IOCTL_NAME(WS_SIO_GET_EXTENSION_FUNCTION_POINTER);
3814 IOCTL_NAME(WS_SIO_GET_GROUP_QOS);
3815 IOCTL_NAME(WS_SIO_GET_INTERFACE_LIST);
3816 /* IOCTL_NAME(WS_SIO_GET_INTERFACE_LIST_EX); */
3817 IOCTL_NAME(WS_SIO_GET_QOS);
3818 IOCTL_NAME(WS_SIO_IDEAL_SEND_BACKLOG_CHANGE);
3819 IOCTL_NAME(WS_SIO_IDEAL_SEND_BACKLOG_QUERY);
3820 IOCTL_NAME(WS_SIO_KEEPALIVE_VALS);
3821 IOCTL_NAME(WS_SIO_MULTIPOINT_LOOPBACK);
3822 IOCTL_NAME(WS_SIO_MULTICAST_SCOPE);
3823 /* IOCTL_NAME(WS_SIO_QUERY_RSS_SCALABILITY_INFO);
3824 IOCTL_NAME(WS_SIO_QUERY_WFP_ALE_ENDPOINT_HANDLE); */
3825 IOCTL_NAME(WS_SIO_RCVALL);
3826 IOCTL_NAME(WS_SIO_RCVALL_IGMPMCAST);
3827 IOCTL_NAME(WS_SIO_RCVALL_MCAST);
3828 /* IOCTL_NAME(WS_SIO_RELEASE_PORT_RESERVATION); */
3829 IOCTL_NAME(WS_SIO_ROUTING_INTERFACE_CHANGE);
3830 IOCTL_NAME(WS_SIO_ROUTING_INTERFACE_QUERY);
3831 IOCTL_NAME(WS_SIO_SET_COMPATIBILITY_MODE);
3832 IOCTL_NAME(WS_SIO_SET_GROUP_QOS);
3833 IOCTL_NAME(WS_SIO_SET_QOS);
3834 IOCTL_NAME(WS_SIO_TRANSLATE_HANDLE);
3835 IOCTL_NAME(WS_SIO_UDP_CONNRESET);
3837 #undef IOCTL_NAME
3839 if (name)
3840 return name + 3;
3842 /* If this is not a known code split its bits */
3843 switch(code & 0x18000000)
3845 case WS_IOC_WS2:
3846 family = "IOC_WS2";
3847 break;
3848 case WS_IOC_PROTOCOL:
3849 family = "IOC_PROTOCOL";
3850 break;
3851 case WS_IOC_VENDOR:
3852 family = "IOC_VENDOR";
3853 break;
3854 default: /* WS_IOC_UNIX */
3856 BYTE size = (code >> 16) & WS_IOCPARM_MASK;
3857 char x = (code & 0xff00) >> 8;
3858 BYTE y = code & 0xff;
3859 char args[14];
3861 switch (code & (WS_IOC_VOID|WS_IOC_INOUT))
3863 case WS_IOC_VOID:
3864 buf_type = "_IO";
3865 sprintf(args, "%d, %d", x, y);
3866 break;
3867 case WS_IOC_IN:
3868 buf_type = "_IOW";
3869 sprintf(args, "'%c', %d, %d", x, y, size);
3870 break;
3871 case WS_IOC_OUT:
3872 buf_type = "_IOR";
3873 sprintf(args, "'%c', %d, %d", x, y, size);
3874 break;
3875 default:
3876 buf_type = "?";
3877 sprintf(args, "'%c', %d, %d", x, y, size);
3878 break;
3880 return wine_dbg_sprintf("%s(%s)", buf_type, args);
3884 /* We are different from WS_IOC_UNIX. */
3885 switch (code & (WS_IOC_VOID|WS_IOC_INOUT))
3887 case WS_IOC_VOID:
3888 buf_type = "_WSAIO";
3889 break;
3890 case WS_IOC_INOUT:
3891 buf_type = "_WSAIORW";
3892 break;
3893 case WS_IOC_IN:
3894 buf_type = "_WSAIOW";
3895 break;
3896 case WS_IOC_OUT:
3897 buf_type = "_WSAIOR";
3898 break;
3899 default:
3900 buf_type = "?";
3901 break;
3904 return wine_dbg_sprintf("%s(%s, %d)", buf_type, family,
3905 (USHORT)(code & 0xffff));
3908 /* do an ioctl call through the server */
3909 static DWORD server_ioctl_sock( SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size,
3910 LPVOID out_buff, DWORD out_size, LPDWORD ret_size,
3911 LPWSAOVERLAPPED overlapped,
3912 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
3914 HANDLE event = overlapped ? overlapped->hEvent : 0;
3915 HANDLE handle = SOCKET2HANDLE( s );
3916 struct ws2_async *wsa = NULL;
3917 IO_STATUS_BLOCK *io = (PIO_STATUS_BLOCK)overlapped, iosb;
3918 void *cvalue = NULL;
3919 NTSTATUS status;
3921 if (completion)
3923 if (!(wsa = (struct ws2_async *)alloc_async_io( sizeof(*wsa), NULL )))
3924 return WSA_NOT_ENOUGH_MEMORY;
3925 wsa->hSocket = handle;
3926 wsa->user_overlapped = overlapped;
3927 wsa->completion_func = completion;
3928 if (!io) io = &wsa->local_iosb;
3929 cvalue = wsa;
3931 else if (!io)
3932 io = &iosb;
3933 else if (!((ULONG_PTR)overlapped->hEvent & 1))
3934 cvalue = overlapped;
3936 status = NtDeviceIoControlFile( handle, event, wsa ? ws2_async_apc : NULL, cvalue, io, code,
3937 in_buff, in_size, out_buff, out_size );
3938 if (status == STATUS_NOT_SUPPORTED)
3940 FIXME("Unsupported ioctl %x (device=%x access=%x func=%x method=%x)\n",
3941 code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
3943 else if (status == STATUS_SUCCESS)
3944 *ret_size = io->Information; /* "Information" is the size written to the output buffer */
3946 if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, wsa );
3948 return NtStatusToWSAError( status );
3951 static DWORD get_interface_list(SOCKET s, void *out_buff, DWORD out_size, DWORD *ret_size, DWORD *total_bytes)
3953 DWORD size, interface_count = 0, ret;
3954 INTERFACE_INFO *info = out_buff;
3955 PMIB_IPADDRTABLE table = NULL;
3956 struct if_nameindex *if_ni;
3957 DWORD status = 0;
3958 int fd;
3960 if (!out_buff || !ret_size)
3961 return WSAEFAULT;
3963 if ((fd = get_sock_fd(s, 0, NULL)) == -1)
3964 return SOCKET_ERROR;
3966 if ((ret = GetIpAddrTable(NULL, &size, TRUE)) != ERROR_INSUFFICIENT_BUFFER)
3968 if (ret != ERROR_NO_DATA)
3970 ERR("Unable to get ip address table.\n");
3971 status = WSAEINVAL;
3973 goto done;
3975 if (!(table = heap_alloc(size)))
3977 ERR("No memory.\n");
3978 status = WSAEINVAL;
3979 goto done;
3981 if (GetIpAddrTable(table, &size, TRUE) != NO_ERROR)
3983 ERR("Unable to get interface table.\n");
3984 status = WSAEINVAL;
3985 goto done;
3987 if (table->dwNumEntries * sizeof(INTERFACE_INFO) > out_size)
3989 WARN("Buffer too small, dwNumEntries %u, out_size = %u.\n", table->dwNumEntries, out_size);
3990 *ret_size = 0;
3991 status = WSAEFAULT;
3992 goto done;
3995 if (!(if_ni = if_nameindex()))
3997 ERR("Unable to get interface name index.\n");
3998 status = WSAEINVAL;
3999 goto done;
4002 for (; interface_count < table->dwNumEntries; ++interface_count, ++info)
4004 unsigned int addr, mask;
4005 struct ifreq if_info;
4006 unsigned int i;
4008 memset(info, 0, sizeof(*info));
4010 for (i = 0; if_ni[i].if_index || if_ni[i].if_name; ++i)
4011 if (if_ni[i].if_index == table->table[interface_count].dwIndex)
4012 break;
4014 if (!if_ni[i].if_name)
4016 ERR("Error obtaining interface name for ifindex %u.\n", table->table[interface_count].dwIndex);
4017 status = WSAEINVAL;
4018 break;
4021 lstrcpynA(if_info.ifr_name, if_ni[i].if_name, IFNAMSIZ);
4022 if (ioctl(fd, SIOCGIFFLAGS, &if_info) < 0)
4024 ERR("Error obtaining status flags for socket.\n");
4025 status = WSAEINVAL;
4026 break;
4029 if (if_info.ifr_flags & IFF_BROADCAST)
4030 info->iiFlags |= WS_IFF_BROADCAST;
4031 #ifdef IFF_POINTOPOINT
4032 if (if_info.ifr_flags & IFF_POINTOPOINT)
4033 info->iiFlags |= WS_IFF_POINTTOPOINT;
4034 #endif
4035 if (if_info.ifr_flags & IFF_LOOPBACK)
4036 info->iiFlags |= WS_IFF_LOOPBACK;
4037 if (if_info.ifr_flags & IFF_UP)
4038 info->iiFlags |= WS_IFF_UP;
4039 if (if_info.ifr_flags & IFF_MULTICAST)
4040 info->iiFlags |= WS_IFF_MULTICAST;
4042 addr = table->table[interface_count].dwAddr;
4043 mask = table->table[interface_count].dwMask;
4045 info->iiAddress.AddressIn.sin_family = WS_AF_INET;
4046 info->iiAddress.AddressIn.sin_port = 0;
4047 info->iiAddress.AddressIn.sin_addr.WS_s_addr = addr;
4049 info->iiNetmask.AddressIn.sin_family = WS_AF_INET;
4050 info->iiNetmask.AddressIn.sin_port = 0;
4051 info->iiNetmask.AddressIn.sin_addr.WS_s_addr = mask;
4053 if (if_info.ifr_flags & IFF_BROADCAST)
4055 info->iiBroadcastAddress.AddressIn.sin_family = WS_AF_INET;
4056 info->iiBroadcastAddress.AddressIn.sin_port = 0;
4057 info->iiBroadcastAddress.AddressIn.sin_addr.WS_s_addr = addr | ~mask;
4060 if_freenameindex(if_ni);
4061 done:
4062 heap_free(table);
4063 *total_bytes = sizeof(INTERFACE_INFO) * interface_count;
4064 release_sock_fd(s, fd);
4065 return status;
4068 /**********************************************************************
4069 * WSAIoctl (WS2_32.50)
4072 INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID out_buff,
4073 DWORD out_size, LPDWORD ret_size, LPWSAOVERLAPPED overlapped,
4074 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4076 int fd;
4077 DWORD status = 0, total = 0;
4079 TRACE("%04lx, %s, %p, %d, %p, %d, %p, %p, %p\n",
4080 s, debugstr_wsaioctl(code), in_buff, in_size, out_buff, out_size, ret_size, overlapped, completion);
4082 switch (code)
4084 case WS_FIONBIO:
4085 if (in_size != sizeof(WS_u_long) || IS_INTRESOURCE(in_buff))
4087 SetLastError(WSAEFAULT);
4088 return SOCKET_ERROR;
4090 TRACE("-> FIONBIO (%x)\n", *(WS_u_long*)in_buff);
4091 if (_get_sock_mask(s))
4093 /* AsyncSelect()'ed sockets are always nonblocking */
4094 if (!*(WS_u_long *)in_buff) status = WSAEINVAL;
4095 break;
4097 if (*(WS_u_long *)in_buff)
4098 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
4099 else
4100 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
4101 break;
4103 case WS_FIONREAD:
4105 #if defined(linux)
4106 int listening = 0;
4107 socklen_t len = sizeof(listening);
4108 #endif
4109 if (out_size != sizeof(WS_u_long) || IS_INTRESOURCE(out_buff))
4111 SetLastError(WSAEFAULT);
4112 return SOCKET_ERROR;
4114 if ((fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR;
4116 #if defined(linux)
4117 /* On Linux, FIONREAD on listening socket always fails (see tcp(7)).
4118 However, it succeeds on native. */
4119 if (!getsockopt( fd, SOL_SOCKET, SO_ACCEPTCONN, &listening, &len ) && listening)
4120 (*(WS_u_long *) out_buff) = 0;
4121 else
4122 #endif
4123 if (ioctl(fd, FIONREAD, out_buff ) == -1)
4124 status = wsaErrno();
4125 release_sock_fd( s, fd );
4126 break;
4129 case WS_SIOCATMARK:
4131 unsigned int oob = 0, atmark = 0;
4132 socklen_t oobsize = sizeof(int);
4133 if (out_size != sizeof(WS_u_long) || IS_INTRESOURCE(out_buff))
4135 SetLastError(WSAEFAULT);
4136 return SOCKET_ERROR;
4138 if ((fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR;
4139 /* SO_OOBINLINE sockets must always return TRUE to SIOCATMARK */
4140 if ((getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &oob, &oobsize ) == -1)
4141 || (!oob && ioctl(fd, SIOCATMARK, &atmark ) == -1))
4142 status = wsaErrno();
4143 else
4145 /* The SIOCATMARK value read from ioctl() is reversed
4146 * because BSD returns TRUE if it's in the OOB mark
4147 * while Windows returns TRUE if there are NO OOB bytes.
4149 (*(WS_u_long *) out_buff) = oob || !atmark;
4152 release_sock_fd( s, fd );
4153 break;
4156 case WS_FIOASYNC:
4157 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
4158 SetLastError(WSAEINVAL);
4159 return SOCKET_ERROR;
4161 case WS_SIO_GET_INTERFACE_LIST:
4163 TRACE("-> SIO_GET_INTERFACE_LIST request\n");
4165 status = get_interface_list(s, out_buff, out_size, ret_size, &total);
4166 break;
4169 case WS_SIO_ADDRESS_LIST_QUERY:
4171 DWORD size;
4173 TRACE("-> SIO_ADDRESS_LIST_QUERY request\n");
4175 if (!ret_size)
4177 SetLastError(WSAEFAULT);
4178 return SOCKET_ERROR;
4181 if (out_size && out_size < FIELD_OFFSET(SOCKET_ADDRESS_LIST, Address[0]))
4183 *ret_size = 0;
4184 SetLastError(WSAEINVAL);
4185 return SOCKET_ERROR;
4188 if (GetAdaptersInfo(NULL, &size) == ERROR_BUFFER_OVERFLOW)
4190 IP_ADAPTER_INFO *p, *table = HeapAlloc(GetProcessHeap(), 0, size);
4191 SOCKET_ADDRESS_LIST *sa_list;
4192 SOCKADDR_IN *sockaddr;
4193 SOCKET_ADDRESS *sa;
4194 unsigned int i;
4195 DWORD num;
4197 if (!table || GetAdaptersInfo(table, &size))
4199 HeapFree(GetProcessHeap(), 0, table);
4200 status = WSAEINVAL;
4201 break;
4204 for (p = table, num = 0; p; p = p->Next)
4205 if (p->IpAddressList.IpAddress.String[0]) num++;
4207 total = FIELD_OFFSET(SOCKET_ADDRESS_LIST, Address[num]) + num * sizeof(*sockaddr);
4208 if (total > out_size || !out_buff)
4210 *ret_size = total;
4211 HeapFree(GetProcessHeap(), 0, table);
4212 status = WSAEFAULT;
4213 break;
4216 sa_list = out_buff;
4217 sa = sa_list->Address;
4218 sockaddr = (SOCKADDR_IN *)&sa[num];
4219 sa_list->iAddressCount = num;
4221 for (p = table, i = 0; p; p = p->Next)
4223 if (!p->IpAddressList.IpAddress.String[0]) continue;
4225 sa[i].lpSockaddr = (SOCKADDR *)&sockaddr[i];
4226 sa[i].iSockaddrLength = sizeof(SOCKADDR);
4228 sockaddr[i].sin_family = WS_AF_INET;
4229 sockaddr[i].sin_port = 0;
4230 sockaddr[i].sin_addr.WS_s_addr = inet_addr(p->IpAddressList.IpAddress.String);
4231 i++;
4234 HeapFree(GetProcessHeap(), 0, table);
4236 else
4238 WARN("unable to get IP address list\n");
4239 status = WSAEINVAL;
4241 break;
4244 case WS_SIO_FLUSH:
4245 FIXME("SIO_FLUSH: stub.\n");
4246 break;
4248 case WS_SIO_GET_EXTENSION_FUNCTION_POINTER:
4250 #define EXTENSION_FUNCTION(x, y) { x, y, #y },
4251 static const struct
4253 GUID guid;
4254 void *func_ptr;
4255 const char *name;
4256 } guid_funcs[] = {
4257 EXTENSION_FUNCTION(WSAID_CONNECTEX, WS2_ConnectEx)
4258 EXTENSION_FUNCTION(WSAID_DISCONNECTEX, WS2_DisconnectEx)
4259 EXTENSION_FUNCTION(WSAID_ACCEPTEX, WS2_AcceptEx)
4260 EXTENSION_FUNCTION(WSAID_GETACCEPTEXSOCKADDRS, WS2_GetAcceptExSockaddrs)
4261 EXTENSION_FUNCTION(WSAID_TRANSMITFILE, WS2_TransmitFile)
4262 /* EXTENSION_FUNCTION(WSAID_TRANSMITPACKETS, WS2_TransmitPackets) */
4263 EXTENSION_FUNCTION(WSAID_WSARECVMSG, WS2_WSARecvMsg)
4264 EXTENSION_FUNCTION(WSAID_WSASENDMSG, WSASendMsg)
4266 #undef EXTENSION_FUNCTION
4267 BOOL found = FALSE;
4268 unsigned int i;
4270 for (i = 0; i < ARRAY_SIZE(guid_funcs); i++)
4272 if (IsEqualGUID(&guid_funcs[i].guid, in_buff))
4274 found = TRUE;
4275 break;
4279 if (found)
4281 TRACE("-> got %s\n", guid_funcs[i].name);
4282 *(void **)out_buff = guid_funcs[i].func_ptr;
4283 total = sizeof(void *);
4284 break;
4287 FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER %s: stub\n", debugstr_guid(in_buff));
4288 status = WSAEOPNOTSUPP;
4289 break;
4291 case WS_SIO_KEEPALIVE_VALS:
4293 struct tcp_keepalive *k;
4294 int keepalive, keepidle, keepintvl;
4296 if (!in_buff || in_size < sizeof(struct tcp_keepalive))
4298 SetLastError(WSAEFAULT);
4299 return SOCKET_ERROR;
4302 k = in_buff;
4303 keepalive = k->onoff ? 1 : 0;
4304 keepidle = max( 1, (k->keepalivetime + 500) / 1000 );
4305 keepintvl = max( 1, (k->keepaliveinterval + 500) / 1000 );
4307 TRACE("onoff: %d, keepalivetime: %d, keepaliveinterval: %d\n", keepalive, keepidle, keepintvl);
4309 fd = get_sock_fd(s, 0, NULL);
4310 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(int)) == -1)
4311 status = WSAEINVAL;
4312 #if defined(TCP_KEEPIDLE) || defined(TCP_KEEPINTVL)
4313 /* these values need to be set only if SO_KEEPALIVE is enabled */
4314 else if(keepalive)
4316 #ifndef TCP_KEEPIDLE
4317 FIXME("ignoring keepalive timeout\n");
4318 #else
4319 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, sizeof(int)) == -1)
4320 status = WSAEINVAL;
4321 else
4322 #endif
4323 #ifdef TCP_KEEPINTVL
4324 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof(int)) == -1)
4325 status = WSAEINVAL;
4326 #else
4327 FIXME("ignoring keepalive interval\n");
4328 #endif
4330 #else
4331 else
4332 FIXME("ignoring keepalive interval and timeout\n");
4333 #endif
4334 release_sock_fd(s, fd);
4335 break;
4337 case WS_SIO_ROUTING_INTERFACE_QUERY:
4339 struct WS_sockaddr *daddr = (struct WS_sockaddr *)in_buff;
4340 struct WS_sockaddr_in *daddr_in = (struct WS_sockaddr_in *)daddr;
4341 struct WS_sockaddr_in *saddr_in = out_buff;
4342 MIB_IPFORWARDROW row;
4343 PMIB_IPADDRTABLE ipAddrTable = NULL;
4344 DWORD size, i, found_index;
4346 TRACE("-> WS_SIO_ROUTING_INTERFACE_QUERY request\n");
4348 if (!in_buff || in_size < sizeof(struct WS_sockaddr) ||
4349 !out_buff || out_size < sizeof(struct WS_sockaddr_in) || !ret_size)
4351 SetLastError(WSAEFAULT);
4352 return SOCKET_ERROR;
4354 if (daddr->sa_family != WS_AF_INET)
4356 FIXME("unsupported address family %d\n", daddr->sa_family);
4357 status = WSAEAFNOSUPPORT;
4358 break;
4360 if (GetBestRoute(daddr_in->sin_addr.S_un.S_addr, 0, &row) != NOERROR ||
4361 GetIpAddrTable(NULL, &size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
4363 status = WSAEFAULT;
4364 break;
4366 ipAddrTable = HeapAlloc(GetProcessHeap(), 0, size);
4367 if (GetIpAddrTable(ipAddrTable, &size, FALSE))
4369 HeapFree(GetProcessHeap(), 0, ipAddrTable);
4370 status = WSAEFAULT;
4371 break;
4373 for (i = 0, found_index = ipAddrTable->dwNumEntries;
4374 i < ipAddrTable->dwNumEntries; i++)
4376 if (ipAddrTable->table[i].dwIndex == row.dwForwardIfIndex)
4377 found_index = i;
4379 if (found_index == ipAddrTable->dwNumEntries)
4381 ERR("no matching IP address for interface %d\n",
4382 row.dwForwardIfIndex);
4383 HeapFree(GetProcessHeap(), 0, ipAddrTable);
4384 status = WSAEFAULT;
4385 break;
4387 saddr_in->sin_family = WS_AF_INET;
4388 saddr_in->sin_addr.S_un.S_addr = ipAddrTable->table[found_index].dwAddr;
4389 saddr_in->sin_port = 0;
4390 total = sizeof(struct WS_sockaddr_in);
4391 HeapFree(GetProcessHeap(), 0, ipAddrTable);
4392 break;
4394 case WS_SIO_SET_COMPATIBILITY_MODE:
4395 TRACE("WS_SIO_SET_COMPATIBILITY_MODE ignored\n");
4396 status = WSAEOPNOTSUPP;
4397 break;
4398 case WS_SIO_UDP_CONNRESET:
4399 FIXME("WS_SIO_UDP_CONNRESET stub\n");
4400 break;
4401 case 0x667e: /* Netscape tries hard to use bogus ioctl 0x667e */
4402 SetLastError(WSAEOPNOTSUPP);
4403 return SOCKET_ERROR;
4404 case WS_SIO_ADDRESS_LIST_CHANGE:
4405 code = IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE;
4406 status = WSAEOPNOTSUPP;
4407 break;
4408 default:
4409 status = WSAEOPNOTSUPP;
4410 break;
4413 if (status == WSAEOPNOTSUPP)
4415 status = server_ioctl_sock(s, code, in_buff, in_size, out_buff, out_size, &total,
4416 overlapped, completion);
4417 if (status != WSAEOPNOTSUPP)
4419 if (status == 0 || status == WSA_IO_PENDING || status == WSAEWOULDBLOCK)
4420 TRACE("-> %s request\n", debugstr_wsaioctl(code));
4421 else
4422 ERR("-> %s request failed with status 0x%x\n", debugstr_wsaioctl(code), status);
4424 /* overlapped and completion operations will be handled by the server */
4425 completion = NULL;
4426 overlapped = NULL;
4428 else
4429 FIXME("unsupported WS_IOCTL cmd (%s)\n", debugstr_wsaioctl(code));
4432 if (completion)
4434 FIXME( "completion routine %p not supported\n", completion );
4436 else if (overlapped)
4438 ULONG_PTR cvalue = (overlapped && ((ULONG_PTR)overlapped->hEvent & 1) == 0) ? (ULONG_PTR)overlapped : 0;
4439 overlapped->Internal = sock_error_to_ntstatus( status );
4440 overlapped->InternalHigh = total;
4441 if (cvalue) WS_AddCompletion( HANDLE2SOCKET(s), cvalue, overlapped->Internal, total, FALSE );
4442 if (overlapped->hEvent) NtSetEvent( overlapped->hEvent, NULL );
4445 if (!status)
4447 if (ret_size) *ret_size = total;
4448 return 0;
4450 SetLastError( status );
4451 return SOCKET_ERROR;
4455 /***********************************************************************
4456 * ioctlsocket (WS2_32.10)
4458 int WINAPI WS_ioctlsocket(SOCKET s, LONG cmd, WS_u_long *argp)
4460 DWORD ret_size;
4461 return WSAIoctl( s, cmd, argp, sizeof(WS_u_long), argp, sizeof(WS_u_long), &ret_size, NULL, NULL );
4465 /***********************************************************************
4466 * listen (ws2_32.13)
4468 int WINAPI WS_listen( SOCKET s, int backlog )
4470 struct afd_listen_params params = {.backlog = backlog};
4471 IO_STATUS_BLOCK io;
4472 NTSTATUS status;
4473 int fd, bound;
4475 TRACE( "socket %#lx, backlog %d\n", s, backlog );
4477 if ((fd = get_sock_fd( s, FILE_READ_DATA, NULL )) == -1)
4478 return -1;
4479 bound = is_fd_bound( fd, NULL, NULL );
4480 release_sock_fd( s, fd );
4481 if (bound <= 0)
4483 SetLastError( bound ? wsaErrno() : WSAEINVAL );
4484 return -1;
4487 status = NtDeviceIoControlFile( SOCKET2HANDLE(s), NULL, NULL, NULL, &io,
4488 IOCTL_AFD_LISTEN, &params, sizeof(params), NULL, 0 );
4489 SetLastError( NtStatusToWSAError( status ) );
4490 return status ? -1 : 0;
4494 /***********************************************************************
4495 * recv (WS2_32.16)
4497 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
4499 DWORD n, dwFlags = flags;
4500 WSABUF wsabuf;
4502 wsabuf.len = len;
4503 wsabuf.buf = buf;
4505 if ( WS2_recv_base(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
4506 return SOCKET_ERROR;
4507 else
4508 return n;
4511 /***********************************************************************
4512 * recvfrom (WS2_32.17)
4514 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
4515 struct WS_sockaddr *from, int *fromlen)
4517 DWORD n, dwFlags = flags;
4518 WSABUF wsabuf;
4520 wsabuf.len = len;
4521 wsabuf.buf = buf;
4523 if ( WS2_recv_base(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL, NULL) == SOCKET_ERROR )
4524 return SOCKET_ERROR;
4525 else
4526 return n;
4529 /* allocate a poll array for the corresponding fd sets */
4530 static struct pollfd *fd_sets_to_poll( const WS_fd_set *readfds, const WS_fd_set *writefds,
4531 const WS_fd_set *exceptfds, int *count_ptr )
4533 unsigned int i, j = 0, count = 0;
4534 struct pollfd *fds;
4535 struct per_thread_data *ptb = get_per_thread_data();
4537 if (readfds) count += readfds->fd_count;
4538 if (writefds) count += writefds->fd_count;
4539 if (exceptfds) count += exceptfds->fd_count;
4540 *count_ptr = count;
4541 if (!count)
4543 SetLastError(WSAEINVAL);
4544 return NULL;
4547 /* check if the cache can hold all descriptors, if not do the resizing */
4548 if (ptb->fd_count < count)
4550 if (!(fds = HeapAlloc(GetProcessHeap(), 0, count * sizeof(fds[0]))))
4552 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
4553 return NULL;
4555 HeapFree(GetProcessHeap(), 0, ptb->fd_cache);
4556 ptb->fd_cache = fds;
4557 ptb->fd_count = count;
4559 else
4560 fds = ptb->fd_cache;
4562 if (readfds)
4563 for (i = 0; i < readfds->fd_count; i++, j++)
4565 fds[j].fd = get_sock_fd( readfds->fd_array[i], FILE_READ_DATA, NULL );
4566 if (fds[j].fd == -1) goto failed;
4567 fds[j].revents = 0;
4568 if (is_fd_bound(fds[j].fd, NULL, NULL) == 1)
4570 fds[j].events = POLLIN;
4572 else
4574 release_sock_fd( readfds->fd_array[i], fds[j].fd );
4575 fds[j].fd = -1;
4576 fds[j].events = 0;
4579 if (writefds)
4580 for (i = 0; i < writefds->fd_count; i++, j++)
4582 fds[j].fd = get_sock_fd( writefds->fd_array[i], FILE_WRITE_DATA, NULL );
4583 if (fds[j].fd == -1) goto failed;
4584 fds[j].revents = 0;
4585 if (is_fd_bound(fds[j].fd, NULL, NULL) == 1 ||
4586 _get_fd_type(fds[j].fd) == SOCK_DGRAM)
4588 fds[j].events = POLLOUT;
4590 else
4592 release_sock_fd( writefds->fd_array[i], fds[j].fd );
4593 fds[j].fd = -1;
4594 fds[j].events = 0;
4597 if (exceptfds)
4598 for (i = 0; i < exceptfds->fd_count; i++, j++)
4600 fds[j].fd = get_sock_fd( exceptfds->fd_array[i], 0, NULL );
4601 if (fds[j].fd == -1) goto failed;
4602 fds[j].revents = 0;
4603 if (is_fd_bound(fds[j].fd, NULL, NULL) == 1)
4605 int oob_inlined = 0;
4606 socklen_t olen = sizeof(oob_inlined);
4608 fds[j].events = POLLHUP;
4610 /* Check if we need to test for urgent data or not */
4611 getsockopt(fds[j].fd, SOL_SOCKET, SO_OOBINLINE, (char*) &oob_inlined, &olen);
4612 if (!oob_inlined)
4613 fds[j].events |= POLLPRI;
4615 else
4617 release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
4618 fds[j].fd = -1;
4619 fds[j].events = 0;
4622 return fds;
4624 failed:
4625 count = j;
4626 j = 0;
4627 if (readfds)
4628 for (i = 0; i < readfds->fd_count && j < count; i++, j++)
4629 if (fds[j].fd != -1) release_sock_fd( readfds->fd_array[i], fds[j].fd );
4630 if (writefds)
4631 for (i = 0; i < writefds->fd_count && j < count; i++, j++)
4632 if (fds[j].fd != -1) release_sock_fd( writefds->fd_array[i], fds[j].fd );
4633 if (exceptfds)
4634 for (i = 0; i < exceptfds->fd_count && j < count; i++, j++)
4635 if (fds[j].fd != -1) release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
4636 return NULL;
4639 /* release the file descriptor obtained in fd_sets_to_poll */
4640 /* must be called with the original fd_set arrays, before calling get_poll_results */
4641 static void release_poll_fds( const WS_fd_set *readfds, const WS_fd_set *writefds,
4642 const WS_fd_set *exceptfds, struct pollfd *fds )
4644 unsigned int i, j = 0;
4646 if (readfds)
4648 for (i = 0; i < readfds->fd_count; i++, j++)
4649 if (fds[j].fd != -1) release_sock_fd( readfds->fd_array[i], fds[j].fd );
4651 if (writefds)
4653 for (i = 0; i < writefds->fd_count; i++, j++)
4654 if (fds[j].fd != -1) release_sock_fd( writefds->fd_array[i], fds[j].fd );
4656 if (exceptfds)
4658 for (i = 0; i < exceptfds->fd_count; i++, j++)
4660 if (fds[j].fd == -1) continue;
4661 release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
4662 if (fds[j].revents & POLLHUP)
4664 int fd = get_sock_fd( exceptfds->fd_array[i], 0, NULL );
4665 if (fd != -1)
4666 release_sock_fd( exceptfds->fd_array[i], fd );
4667 else
4668 fds[j].revents = 0;
4674 static int do_poll(struct pollfd *pollfds, int count, int timeout)
4676 struct timeval tv1, tv2;
4677 int ret, torig = timeout;
4679 if (timeout > 0) gettimeofday( &tv1, 0 );
4681 while ((ret = poll( pollfds, count, timeout )) < 0)
4683 if (errno != EINTR) break;
4684 if (timeout < 0) continue;
4685 if (timeout == 0) return 0;
4687 gettimeofday( &tv2, 0 );
4689 tv2.tv_sec -= tv1.tv_sec;
4690 tv2.tv_usec -= tv1.tv_usec;
4691 if (tv2.tv_usec < 0)
4693 tv2.tv_usec += 1000000;
4694 tv2.tv_sec -= 1;
4697 timeout = torig - (tv2.tv_sec * 1000) - (tv2.tv_usec + 999) / 1000;
4698 if (timeout <= 0) return 0;
4700 return ret;
4703 /* map the poll results back into the Windows fd sets */
4704 static int get_poll_results( WS_fd_set *readfds, WS_fd_set *writefds, WS_fd_set *exceptfds,
4705 const struct pollfd *fds )
4707 const struct pollfd *poll_writefds = fds + (readfds ? readfds->fd_count : 0);
4708 const struct pollfd *poll_exceptfds = poll_writefds + (writefds ? writefds->fd_count : 0);
4709 unsigned int i, k, total = 0;
4711 if (readfds)
4713 for (i = k = 0; i < readfds->fd_count; i++)
4715 if (fds[i].revents ||
4716 (readfds == writefds && (poll_writefds[i].revents & POLLOUT) && !(poll_writefds[i].revents & POLLHUP)) ||
4717 (readfds == exceptfds && poll_exceptfds[i].revents))
4718 readfds->fd_array[k++] = readfds->fd_array[i];
4720 readfds->fd_count = k;
4721 total += k;
4723 if (writefds && writefds != readfds)
4725 for (i = k = 0; i < writefds->fd_count; i++)
4727 if (((poll_writefds[i].revents & POLLOUT) && !(poll_writefds[i].revents & POLLHUP)) ||
4728 (writefds == exceptfds && poll_exceptfds[i].revents))
4729 writefds->fd_array[k++] = writefds->fd_array[i];
4731 writefds->fd_count = k;
4732 total += k;
4734 if (exceptfds && exceptfds != readfds && exceptfds != writefds)
4736 for (i = k = 0; i < exceptfds->fd_count; i++)
4737 if (poll_exceptfds[i].revents) exceptfds->fd_array[k++] = exceptfds->fd_array[i];
4738 exceptfds->fd_count = k;
4739 total += k;
4741 return total;
4744 /***********************************************************************
4745 * select (WS2_32.18)
4747 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
4748 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
4749 const struct WS_timeval* ws_timeout)
4751 struct pollfd *pollfds;
4752 int count, ret, timeout = -1;
4754 TRACE("read %p, write %p, excp %p timeout %p\n",
4755 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
4757 if (!(pollfds = fd_sets_to_poll( ws_readfds, ws_writefds, ws_exceptfds, &count )))
4758 return SOCKET_ERROR;
4760 if (ws_timeout)
4761 timeout = (ws_timeout->tv_sec * 1000) + (ws_timeout->tv_usec + 999) / 1000;
4763 ret = do_poll(pollfds, count, timeout);
4764 release_poll_fds( ws_readfds, ws_writefds, ws_exceptfds, pollfds );
4766 if (ret == -1) SetLastError(wsaErrno());
4767 else ret = get_poll_results( ws_readfds, ws_writefds, ws_exceptfds, pollfds );
4768 return ret;
4771 /***********************************************************************
4772 * WSAPoll
4774 int WINAPI WSAPoll(WSAPOLLFD *wfds, ULONG count, int timeout)
4776 int i, ret;
4777 struct pollfd *ufds;
4779 if (!count)
4781 SetLastError(WSAEINVAL);
4782 return SOCKET_ERROR;
4784 if (!wfds)
4786 SetLastError(WSAEFAULT);
4787 return SOCKET_ERROR;
4790 if (!(ufds = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ufds[0]))))
4792 SetLastError(WSAENOBUFS);
4793 return SOCKET_ERROR;
4796 for (i = 0; i < count; i++)
4798 ufds[i].fd = get_sock_fd(wfds[i].fd, 0, NULL);
4799 ufds[i].events = convert_poll_w2u(wfds[i].events);
4800 ufds[i].revents = 0;
4803 ret = do_poll(ufds, count, timeout);
4805 for (i = 0; i < count; i++)
4807 if (ufds[i].fd != -1)
4809 release_sock_fd(wfds[i].fd, ufds[i].fd);
4810 if (ufds[i].revents & POLLHUP)
4812 /* Check if the socket still exists */
4813 int fd = get_sock_fd(wfds[i].fd, 0, NULL);
4814 if (fd != -1)
4816 wfds[i].revents = WS_POLLHUP;
4817 release_sock_fd(wfds[i].fd, fd);
4819 else
4820 wfds[i].revents = WS_POLLNVAL;
4822 else
4823 wfds[i].revents = convert_poll_u2w(ufds[i].revents);
4825 else
4826 wfds[i].revents = WS_POLLNVAL;
4829 HeapFree(GetProcessHeap(), 0, ufds);
4830 return ret;
4833 /* helper to send completion messages for client-only i/o operation case */
4834 static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus,
4835 ULONG Information, BOOL async )
4837 SERVER_START_REQ( add_fd_completion )
4839 req->handle = wine_server_obj_handle( SOCKET2HANDLE(sock) );
4840 req->cvalue = CompletionValue;
4841 req->status = CompletionStatus;
4842 req->information = Information;
4843 req->async = async;
4844 wine_server_call( req );
4846 SERVER_END_REQ;
4850 /***********************************************************************
4851 * send (WS2_32.19)
4853 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
4855 DWORD n;
4856 WSABUF wsabuf;
4858 wsabuf.len = len;
4859 wsabuf.buf = (char*) buf;
4861 if ( WS2_sendto( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
4862 return SOCKET_ERROR;
4863 else
4864 return n;
4867 /***********************************************************************
4868 * WSASend (WS2_32.72)
4870 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
4871 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
4872 LPWSAOVERLAPPED lpOverlapped,
4873 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
4875 return WS2_sendto( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
4876 NULL, 0, lpOverlapped, lpCompletionRoutine );
4879 /***********************************************************************
4880 * WSASendDisconnect (WS2_32.73)
4882 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
4884 return WS_shutdown( s, SD_SEND );
4888 static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
4889 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
4890 const struct WS_sockaddr *to, int tolen,
4891 LPWSAOVERLAPPED lpOverlapped,
4892 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
4894 unsigned int i, options;
4895 int n, fd, err, overlapped, flags;
4896 struct ws2_async *wsa = NULL, localwsa;
4897 int totalLength = 0;
4898 DWORD bytes_sent;
4899 BOOL is_blocking;
4901 TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, to %p, tolen %d, ovl %p, func %p\n",
4902 s, lpBuffers, dwBufferCount, dwFlags,
4903 to, tolen, lpOverlapped, lpCompletionRoutine);
4905 fd = get_sock_fd( s, FILE_WRITE_DATA, &options );
4906 TRACE( "fd=%d, options=%x\n", fd, options );
4908 if ( fd == -1 ) return SOCKET_ERROR;
4910 if (!lpOverlapped && !lpNumberOfBytesSent)
4912 err = WSAEFAULT;
4913 goto error;
4916 overlapped = (lpOverlapped || lpCompletionRoutine) &&
4917 !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
4918 if (overlapped || dwBufferCount > 1)
4920 if (!(wsa = (struct ws2_async *)alloc_async_io( offsetof(struct ws2_async, iovec[dwBufferCount]),
4921 WS2_async_send )))
4923 err = WSAEFAULT;
4924 goto error;
4927 else
4928 wsa = &localwsa;
4930 wsa->hSocket = SOCKET2HANDLE(s);
4931 wsa->addr = (struct WS_sockaddr *)to;
4932 wsa->addrlen.val = tolen;
4933 wsa->flags = dwFlags;
4934 wsa->lpFlags = &wsa->flags;
4935 wsa->control = NULL;
4936 wsa->n_iovecs = dwBufferCount;
4937 wsa->first_iovec = 0;
4938 for ( i = 0; i < dwBufferCount; i++ )
4940 wsa->iovec[i].iov_base = lpBuffers[i].buf;
4941 wsa->iovec[i].iov_len = lpBuffers[i].len;
4942 totalLength += lpBuffers[i].len;
4945 flags = convert_flags(dwFlags);
4946 n = WS2_send( fd, wsa, flags );
4947 if (n == -1 && errno != EAGAIN)
4949 err = wsaErrno();
4950 goto error;
4953 if (overlapped)
4955 IO_STATUS_BLOCK *iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
4956 ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
4958 wsa->user_overlapped = lpOverlapped;
4959 wsa->completion_func = lpCompletionRoutine;
4960 release_sock_fd( s, fd );
4962 if (n == -1 || n < totalLength)
4964 iosb->u.Status = STATUS_PENDING;
4965 iosb->Information = n == -1 ? 0 : n;
4967 if (wsa->completion_func)
4968 err = register_async( ASYNC_TYPE_WRITE, wsa->hSocket, &wsa->io, NULL,
4969 ws2_async_apc, wsa, iosb );
4970 else
4971 err = register_async( ASYNC_TYPE_WRITE, wsa->hSocket, &wsa->io, lpOverlapped->hEvent,
4972 NULL, (void *)cvalue, iosb );
4974 /* Enable the event only after starting the async. The server will deliver it as soon as
4975 the async is done. */
4976 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
4978 if (err != STATUS_PENDING) HeapFree( GetProcessHeap(), 0, wsa );
4979 SetLastError(NtStatusToWSAError( err ));
4980 return SOCKET_ERROR;
4983 iosb->u.Status = STATUS_SUCCESS;
4984 iosb->Information = n;
4985 if (lpNumberOfBytesSent) *lpNumberOfBytesSent = n;
4986 if (!wsa->completion_func)
4988 if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n, FALSE );
4989 if (lpOverlapped->hEvent) SetEvent( lpOverlapped->hEvent );
4990 HeapFree( GetProcessHeap(), 0, wsa );
4992 else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc,
4993 (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 );
4994 SetLastError(ERROR_SUCCESS);
4995 return 0;
4998 if ((err = sock_is_blocking( s, &is_blocking ))) goto error;
5000 if ( is_blocking )
5002 /* On a blocking non-overlapped stream socket,
5003 * sending blocks until the entire buffer is sent. */
5004 DWORD timeout_start = GetTickCount();
5006 bytes_sent = n == -1 ? 0 : n;
5008 while (wsa->first_iovec < wsa->n_iovecs)
5010 struct pollfd pfd;
5011 int poll_timeout = -1;
5012 INT64 timeout = get_rcvsnd_timeo(fd, FALSE);
5014 if (timeout)
5016 timeout -= GetTickCount() - timeout_start;
5017 if (timeout < 0) poll_timeout = 0;
5018 else poll_timeout = timeout <= INT_MAX ? timeout : INT_MAX;
5021 pfd.fd = fd;
5022 pfd.events = POLLOUT;
5024 if (!poll_timeout || !poll( &pfd, 1, poll_timeout ))
5026 err = WSAETIMEDOUT;
5027 goto error; /* msdn says a timeout in send is fatal */
5030 n = WS2_send( fd, wsa, flags );
5031 if (n == -1 && errno != EAGAIN)
5033 err = wsaErrno();
5034 goto error;
5037 if (n >= 0)
5038 bytes_sent += n;
5041 else /* non-blocking */
5043 if (n < totalLength)
5044 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
5045 if (n == -1)
5047 err = WSAEWOULDBLOCK;
5048 goto error;
5050 bytes_sent = n;
5053 TRACE(" -> %i bytes\n", bytes_sent);
5055 if (lpNumberOfBytesSent) *lpNumberOfBytesSent = bytes_sent;
5056 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
5057 release_sock_fd( s, fd );
5058 SetLastError(ERROR_SUCCESS);
5059 return 0;
5061 error:
5062 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
5063 release_sock_fd( s, fd );
5064 WARN(" -> ERROR %d\n", err);
5065 SetLastError(err);
5066 return SOCKET_ERROR;
5069 /***********************************************************************
5070 * WSASendTo (WS2_32.74)
5072 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
5073 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
5074 const struct WS_sockaddr *to, int tolen,
5075 LPWSAOVERLAPPED lpOverlapped,
5076 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
5078 return WS2_sendto( s, lpBuffers, dwBufferCount,
5079 lpNumberOfBytesSent, dwFlags,
5080 to, tolen,
5081 lpOverlapped, lpCompletionRoutine );
5084 /***********************************************************************
5085 * sendto (WS2_32.20)
5087 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
5088 const struct WS_sockaddr *to, int tolen)
5090 DWORD n;
5091 WSABUF wsabuf;
5093 wsabuf.len = len;
5094 wsabuf.buf = (char*) buf;
5096 if ( WS2_sendto(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
5097 return SOCKET_ERROR;
5098 else
5099 return n;
5102 /***********************************************************************
5103 * setsockopt (WS2_32.21)
5105 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
5106 const char *optval, int optlen)
5108 int fd;
5109 int woptval;
5110 struct linger linger;
5111 struct timeval tval;
5112 struct ip_mreq_source mreq_source;
5114 TRACE("(socket %04lx, %s, optval %s, optlen %d)\n", s,
5115 debugstr_sockopt(level, optname), debugstr_optval(optval, optlen),
5116 optlen);
5118 /* some broken apps pass the value directly instead of a pointer to it */
5119 if(optlen && IS_INTRESOURCE(optval))
5121 SetLastError(WSAEFAULT);
5122 return SOCKET_ERROR;
5125 switch(level)
5127 case WS_SOL_SOCKET:
5128 switch(optname)
5130 /* Some options need some conversion before they can be sent to
5131 * setsockopt. The conversions are done here, then they will fall through
5132 * to the general case. Special options that are not passed to
5133 * setsockopt follow below that.*/
5135 case WS_SO_DONTLINGER:
5136 if (!optval)
5138 SetLastError(WSAEFAULT);
5139 return SOCKET_ERROR;
5141 linger.l_onoff = *(const int*)optval == 0;
5142 linger.l_linger = 0;
5143 level = SOL_SOCKET;
5144 optname = SO_LINGER;
5145 optval = (char*)&linger;
5146 optlen = sizeof(struct linger);
5147 break;
5149 case WS_SO_LINGER:
5150 if (!optval)
5152 SetLastError(WSAEFAULT);
5153 return SOCKET_ERROR;
5155 linger.l_onoff = ((LINGER*)optval)->l_onoff;
5156 linger.l_linger = ((LINGER*)optval)->l_linger;
5157 level = SOL_SOCKET;
5158 optname = SO_LINGER;
5159 optval = (char*)&linger;
5160 optlen = sizeof(struct linger);
5161 break;
5163 case WS_SO_SNDBUF:
5164 if (!*(const int *)optval)
5166 FIXME("SO_SNDBUF ignoring request to disable send buffering\n");
5167 #ifdef __APPLE__
5168 return 0;
5169 #endif
5171 convert_sockopt(&level, &optname);
5172 break;
5174 case WS_SO_RCVBUF:
5175 if (*(const int*)optval < 2048)
5177 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(const int*)optval );
5178 return 0;
5180 /* Fall through */
5182 /* The options listed here don't need any special handling. Thanks to
5183 * the conversion happening above, options from there will fall through
5184 * to this, too.*/
5185 case WS_SO_ACCEPTCONN:
5186 case WS_SO_BROADCAST:
5187 case WS_SO_ERROR:
5188 case WS_SO_KEEPALIVE:
5189 case WS_SO_OOBINLINE:
5190 /* BSD socket SO_REUSEADDR is not 100% compatible to winsock semantics.
5191 * however, using it the BSD way fixes bug 8513 and seems to be what
5192 * most programmers assume, anyway */
5193 case WS_SO_REUSEADDR:
5194 case WS_SO_TYPE:
5195 convert_sockopt(&level, &optname);
5196 break;
5198 /* SO_DEBUG is a privileged operation, ignore it. */
5199 case WS_SO_DEBUG:
5200 TRACE("Ignoring SO_DEBUG\n");
5201 return 0;
5203 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
5204 * socket. According to MSDN, this option is silently ignored.*/
5205 case WS_SO_DONTROUTE:
5206 TRACE("Ignoring SO_DONTROUTE\n");
5207 return 0;
5209 /* Stops two sockets from being bound to the same port. Always happens
5210 * on unix systems, so just drop it. */
5211 case WS_SO_EXCLUSIVEADDRUSE:
5212 TRACE("Ignoring SO_EXCLUSIVEADDRUSE, is always set.\n");
5213 return 0;
5215 /* After a ConnectEx call succeeds, the socket can't be used with half of the
5216 * normal winsock functions on windows. We don't have that problem. */
5217 case WS_SO_UPDATE_CONNECT_CONTEXT:
5218 TRACE("Ignoring SO_UPDATE_CONNECT_CONTEXT, since our sockets are normal\n");
5219 return 0;
5221 /* After a AcceptEx call succeeds, the socket can't be used with half of the
5222 * normal winsock functions on windows. We don't have that problem. */
5223 case WS_SO_UPDATE_ACCEPT_CONTEXT:
5224 TRACE("Ignoring SO_UPDATE_ACCEPT_CONTEXT, since our sockets are normal\n");
5225 return 0;
5227 /* SO_OPENTYPE does not require a valid socket handle. */
5228 case WS_SO_OPENTYPE:
5229 if (!optlen || optlen < sizeof(int) || !optval)
5231 SetLastError(WSAEFAULT);
5232 return SOCKET_ERROR;
5234 get_per_thread_data()->opentype = *(const int *)optval;
5235 TRACE("setting global SO_OPENTYPE = 0x%x\n", *((const int*)optval) );
5236 return 0;
5238 #ifdef SO_RCVTIMEO
5239 case WS_SO_RCVTIMEO:
5240 #endif
5241 #ifdef SO_SNDTIMEO
5242 case WS_SO_SNDTIMEO:
5243 #endif
5244 #if defined(SO_RCVTIMEO) || defined(SO_SNDTIMEO)
5245 if (optval && optlen == sizeof(UINT32)) {
5246 /* WinSock passes milliseconds instead of struct timeval */
5247 tval.tv_usec = (*(const UINT32*)optval % 1000) * 1000;
5248 tval.tv_sec = *(const UINT32*)optval / 1000;
5249 /* min of 500 milliseconds */
5250 if (tval.tv_sec == 0 && tval.tv_usec && tval.tv_usec < 500000)
5251 tval.tv_usec = 500000;
5252 optlen = sizeof(struct timeval);
5253 optval = (char*)&tval;
5254 } else if (optlen == sizeof(struct timeval)) {
5255 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
5256 } else {
5257 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
5258 return 0;
5260 convert_sockopt(&level, &optname);
5261 break;
5262 #endif
5264 case WS_SO_RANDOMIZE_PORT:
5265 FIXME("Ignoring WS_SO_RANDOMIZE_PORT\n");
5266 return 0;
5268 case WS_SO_PORT_SCALABILITY:
5269 FIXME("Ignoring WS_SO_PORT_SCALABILITY\n");
5270 return 0;
5272 case WS_SO_REUSE_UNICASTPORT:
5273 FIXME("Ignoring WS_SO_REUSE_UNICASTPORT\n");
5274 return 0;
5276 case WS_SO_REUSE_MULTICASTPORT:
5277 FIXME("Ignoring WS_SO_REUSE_MULTICASTPORT\n");
5278 return 0;
5280 default:
5281 TRACE("Unknown SOL_SOCKET optname: 0x%08x\n", optname);
5282 SetLastError(WSAENOPROTOOPT);
5283 return SOCKET_ERROR;
5285 break; /* case WS_SOL_SOCKET */
5287 #ifdef HAS_IPX
5288 case WS_NSPROTO_IPX:
5289 switch(optname)
5291 case WS_IPX_PTYPE:
5292 return set_ipx_packettype(s, *(int*)optval);
5294 case WS_IPX_FILTERPTYPE:
5295 /* Sets the receive filter packet type, at the moment we don't support it */
5296 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
5297 /* Returning 0 is better for now than returning a SOCKET_ERROR */
5298 return 0;
5300 default:
5301 FIXME("opt_name:%x\n", optname);
5302 return SOCKET_ERROR;
5304 break; /* case WS_NSPROTO_IPX */
5305 #endif
5307 /* Levels WS_IPPROTO_TCP and WS_IPPROTO_IP convert directly */
5308 case WS_IPPROTO_TCP:
5309 switch(optname)
5311 case WS_TCP_NODELAY:
5312 convert_sockopt(&level, &optname);
5313 break;
5314 default:
5315 FIXME("Unknown IPPROTO_TCP optname 0x%08x\n", optname);
5316 return SOCKET_ERROR;
5318 break;
5320 case WS_IPPROTO_IP:
5321 switch(optname)
5323 case WS_IP_ADD_SOURCE_MEMBERSHIP:
5324 case WS_IP_DROP_SOURCE_MEMBERSHIP:
5325 case WS_IP_BLOCK_SOURCE:
5326 case WS_IP_UNBLOCK_SOURCE:
5328 WS_IP_MREQ_SOURCE* val = (void*)optval;
5329 mreq_source.imr_interface.s_addr = val->imr_interface.S_un.S_addr;
5330 mreq_source.imr_multiaddr.s_addr = val->imr_multiaddr.S_un.S_addr;
5331 mreq_source.imr_sourceaddr.s_addr = val->imr_sourceaddr.S_un.S_addr;
5333 optval = (char*)&mreq_source;
5334 optlen = sizeof(mreq_source);
5336 convert_sockopt(&level, &optname);
5337 break;
5339 case WS_IP_ADD_MEMBERSHIP:
5340 case WS_IP_DROP_MEMBERSHIP:
5341 #ifdef IP_HDRINCL
5342 case WS_IP_HDRINCL:
5343 #endif
5344 case WS_IP_MULTICAST_IF:
5345 case WS_IP_MULTICAST_LOOP:
5346 case WS_IP_MULTICAST_TTL:
5347 case WS_IP_OPTIONS:
5348 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
5349 case WS_IP_PKTINFO:
5350 #endif
5351 case WS_IP_TOS:
5352 case WS_IP_TTL:
5353 #ifdef IP_UNICAST_IF
5354 case WS_IP_UNICAST_IF:
5355 #endif
5356 convert_sockopt(&level, &optname);
5357 break;
5358 case WS_IP_DONTFRAGMENT:
5359 return set_dont_fragment(s, IPPROTO_IP, *(BOOL *)optval) ? 0 : SOCKET_ERROR;
5360 default:
5361 FIXME("Unknown IPPROTO_IP optname 0x%08x\n", optname);
5362 return SOCKET_ERROR;
5364 break;
5366 case WS_IPPROTO_IPV6:
5367 switch(optname)
5369 #ifdef IPV6_ADD_MEMBERSHIP
5370 case WS_IPV6_ADD_MEMBERSHIP:
5371 #endif
5372 #ifdef IPV6_DROP_MEMBERSHIP
5373 case WS_IPV6_DROP_MEMBERSHIP:
5374 #endif
5375 case WS_IPV6_MULTICAST_IF:
5376 case WS_IPV6_MULTICAST_HOPS:
5377 case WS_IPV6_MULTICAST_LOOP:
5378 case WS_IPV6_UNICAST_HOPS:
5379 #ifdef IPV6_UNICAST_IF
5380 case WS_IPV6_UNICAST_IF:
5381 #endif
5382 convert_sockopt(&level, &optname);
5383 break;
5384 case WS_IPV6_DONTFRAG:
5385 return set_dont_fragment(s, IPPROTO_IPV6, *(BOOL *)optval) ? 0 : SOCKET_ERROR;
5386 case WS_IPV6_PROTECTION_LEVEL:
5387 FIXME("IPV6_PROTECTION_LEVEL is ignored!\n");
5388 return 0;
5389 case WS_IPV6_V6ONLY:
5391 union generic_unix_sockaddr uaddr;
5392 socklen_t uaddrlen;
5393 int bound;
5395 fd = get_sock_fd( s, 0, NULL );
5396 if (fd == -1) return SOCKET_ERROR;
5398 bound = is_fd_bound(fd, &uaddr, &uaddrlen);
5399 release_sock_fd( s, fd );
5400 if (bound == 0 && uaddr.addr.sa_family == AF_INET)
5402 /* Changing IPV6_V6ONLY succeeds on AF_INET (IPv4) socket
5403 * on Windows (with IPv6 support) if the socket is unbound.
5404 * It is essentially a noop, though Windows does store the value
5406 WARN("Silently ignoring IPPROTO_IPV6+IPV6_V6ONLY on AF_INET socket\n");
5407 return 0;
5409 level = IPPROTO_IPV6;
5410 optname = IPV6_V6ONLY;
5411 break;
5413 default:
5414 FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname);
5415 return SOCKET_ERROR;
5417 break;
5419 default:
5420 WARN("Unknown level: 0x%08x\n", level);
5421 SetLastError(WSAEINVAL);
5422 return SOCKET_ERROR;
5423 } /* end switch(level) */
5425 /* avoid endianness issues if argument is a 16-bit int */
5426 if (optval && optlen < sizeof(int))
5428 woptval= *((const INT16 *) optval);
5429 optval= (char*) &woptval;
5430 woptval&= (1 << optlen * 8) - 1;
5431 optlen=sizeof(int);
5433 fd = get_sock_fd( s, 0, NULL );
5434 if (fd == -1) return SOCKET_ERROR;
5436 if (setsockopt(fd, level, optname, optval, optlen) == 0)
5438 #ifdef __APPLE__
5439 if (level == SOL_SOCKET && optname == SO_REUSEADDR &&
5440 setsockopt(fd, level, SO_REUSEPORT, optval, optlen) != 0)
5442 SetLastError(wsaErrno());
5443 release_sock_fd( s, fd );
5444 return SOCKET_ERROR;
5446 #endif
5447 release_sock_fd( s, fd );
5448 return 0;
5450 TRACE("Setting socket error, %d\n", wsaErrno());
5451 SetLastError(wsaErrno());
5452 release_sock_fd( s, fd );
5454 return SOCKET_ERROR;
5458 /***********************************************************************
5459 * shutdown (ws2_32.22)
5461 int WINAPI WS_shutdown( SOCKET s, int how )
5463 IO_STATUS_BLOCK io;
5464 NTSTATUS status;
5466 TRACE( "socket %#lx, how %u\n", s, how );
5468 status = NtDeviceIoControlFile( (HANDLE)s, NULL, NULL, NULL, &io,
5469 IOCTL_AFD_WINE_SHUTDOWN, &how, sizeof(how), NULL, 0 );
5470 SetLastError( NtStatusToWSAError( status ) );
5471 return status ? -1 : 0;
5475 /***********************************************************************
5476 * socket (WS2_32.23)
5478 SOCKET WINAPI WS_socket(int af, int type, int protocol)
5480 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
5482 return WSASocketW( af, type, protocol, NULL, 0,
5483 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
5487 /***********************************************************************
5488 * WSAEnumNetworkEvents (WS2_32.36)
5490 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
5492 int ret;
5493 int i;
5494 int errors[FD_MAX_EVENTS];
5496 TRACE("%04lx, hEvent %p, lpEvent %p\n", s, hEvent, lpEvent );
5498 SERVER_START_REQ( get_socket_event )
5500 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
5501 req->service = TRUE;
5502 req->c_event = wine_server_obj_handle( hEvent );
5503 wine_server_set_reply( req, errors, sizeof(errors) );
5504 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
5506 SERVER_END_REQ;
5507 if (!ret)
5509 for (i = 0; i < FD_MAX_EVENTS; i++)
5511 if (lpEvent->lNetworkEvents & (1 << i))
5512 lpEvent->iErrorCode[i] = errors[i];
5514 return 0;
5516 SetLastError(WSAEINVAL);
5517 return SOCKET_ERROR;
5520 /***********************************************************************
5521 * WSAEventSelect (WS2_32.39)
5523 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
5525 int ret;
5527 TRACE("%04lx, hEvent %p, event %08x\n", s, hEvent, lEvent);
5529 SERVER_START_REQ( set_socket_event )
5531 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
5532 req->mask = lEvent;
5533 req->event = wine_server_obj_handle( hEvent );
5534 req->window = 0;
5535 req->msg = 0;
5536 ret = wine_server_call( req );
5538 SERVER_END_REQ;
5539 if (!ret) return 0;
5540 SetLastError(WSAEINVAL);
5541 return SOCKET_ERROR;
5544 /**********************************************************************
5545 * WSAGetOverlappedResult (WS2_32.40)
5547 BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
5548 LPDWORD lpcbTransfer, BOOL fWait,
5549 LPDWORD lpdwFlags )
5551 NTSTATUS status;
5553 TRACE( "socket %04lx ovl %p trans %p, wait %d flags %p\n",
5554 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
5556 if ( lpOverlapped == NULL )
5558 ERR( "Invalid pointer\n" );
5559 SetLastError(WSA_INVALID_PARAMETER);
5560 return FALSE;
5563 status = lpOverlapped->Internal;
5564 if (status == STATUS_PENDING)
5566 if (!fWait)
5568 SetLastError( WSA_IO_INCOMPLETE );
5569 return FALSE;
5572 if (WaitForSingleObject( lpOverlapped->hEvent ? lpOverlapped->hEvent : SOCKET2HANDLE(s),
5573 INFINITE ) == WAIT_FAILED)
5574 return FALSE;
5575 status = lpOverlapped->Internal;
5578 if ( lpcbTransfer )
5579 *lpcbTransfer = lpOverlapped->InternalHigh;
5581 if ( lpdwFlags )
5582 *lpdwFlags = lpOverlapped->u.s.Offset;
5584 SetLastError( NtStatusToWSAError(status) );
5585 return NT_SUCCESS( status );
5589 /***********************************************************************
5590 * WSAAsyncSelect (WS2_32.101)
5592 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
5594 int ret;
5596 TRACE("%04lx, hWnd %p, uMsg %08x, event %08x\n", s, hWnd, uMsg, lEvent);
5598 SERVER_START_REQ( set_socket_event )
5600 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
5601 req->mask = lEvent;
5602 req->event = 0;
5603 req->window = wine_server_user_handle( hWnd );
5604 req->msg = uMsg;
5605 ret = wine_server_call( req );
5607 SERVER_END_REQ;
5608 if (!ret) return 0;
5609 SetLastError(WSAEINVAL);
5610 return SOCKET_ERROR;
5613 /***********************************************************************
5614 * WSACreateEvent (WS2_32.31)
5617 WSAEVENT WINAPI WSACreateEvent(void)
5619 /* Create a manual-reset event, with initial state: unsignaled */
5620 TRACE("\n");
5622 return CreateEventW(NULL, TRUE, FALSE, NULL);
5625 /***********************************************************************
5626 * WSACloseEvent (WS2_32.29)
5629 BOOL WINAPI WSACloseEvent(WSAEVENT event)
5631 TRACE ("event=%p\n", event);
5633 return CloseHandle(event);
5636 /***********************************************************************
5637 * WSASocketA (WS2_32.78)
5640 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
5641 LPWSAPROTOCOL_INFOA lpProtocolInfo,
5642 GROUP g, DWORD dwFlags)
5644 INT len;
5645 WSAPROTOCOL_INFOW info;
5647 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%x\n",
5648 af, type, protocol, lpProtocolInfo, g, dwFlags);
5650 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
5652 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
5653 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
5654 info.szProtocol, WSAPROTOCOL_LEN + 1);
5656 if (!len)
5658 SetLastError(WSAEINVAL);
5659 return SOCKET_ERROR;
5662 return WSASocketW(af, type, protocol, &info, g, dwFlags);
5665 /***********************************************************************
5666 * WSASocketW (WS2_32.79)
5669 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
5670 LPWSAPROTOCOL_INFOW lpProtocolInfo,
5671 GROUP g, DWORD flags)
5673 static const WCHAR afdW[] = {'\\','D','e','v','i','c','e','\\','A','f','d',0};
5674 struct afd_create_params create_params;
5675 OBJECT_ATTRIBUTES attr;
5676 UNICODE_STRING string;
5677 IO_STATUS_BLOCK io;
5678 NTSTATUS status;
5679 HANDLE handle;
5680 SOCKET ret;
5681 DWORD err;
5684 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
5685 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
5688 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%x\n",
5689 af, type, protocol, lpProtocolInfo, g, flags );
5691 if (!num_startup)
5693 err = WSANOTINITIALISED;
5694 goto done;
5697 /* hack for WSADuplicateSocket */
5698 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00)
5700 ret = lpProtocolInfo->dwServiceFlags3;
5701 TRACE("\tgot duplicate %04lx\n", ret);
5702 if (!socket_list_add(ret))
5704 CloseHandle(SOCKET2HANDLE(ret));
5705 return INVALID_SOCKET;
5707 return ret;
5710 if (lpProtocolInfo)
5712 if (af == FROM_PROTOCOL_INFO || !af)
5713 af = lpProtocolInfo->iAddressFamily;
5714 if (type == FROM_PROTOCOL_INFO || !type)
5715 type = lpProtocolInfo->iSocketType;
5716 if (protocol == FROM_PROTOCOL_INFO || !protocol)
5717 protocol = lpProtocolInfo->iProtocol;
5720 if (!af && !protocol)
5722 WSASetLastError(WSAEINVAL);
5723 return INVALID_SOCKET;
5726 if (!af && lpProtocolInfo)
5728 WSASetLastError(WSAEAFNOSUPPORT);
5729 return INVALID_SOCKET;
5732 if (!af || !type || !protocol)
5734 unsigned int i;
5736 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
5738 const WSAPROTOCOL_INFOW *info = &supported_protocols[i];
5740 if (af && af != info->iAddressFamily) continue;
5741 if (type && type != info->iSocketType) continue;
5742 if (protocol && (protocol < info->iProtocol ||
5743 protocol > info->iProtocol + info->iProtocolMaxOffset)) continue;
5744 if (!protocol && !(info->dwProviderFlags & PFL_MATCHES_PROTOCOL_ZERO)) continue;
5746 if (!af) af = supported_protocols[i].iAddressFamily;
5747 if (!type) type = supported_protocols[i].iSocketType;
5748 if (!protocol) protocol = supported_protocols[i].iProtocol;
5749 break;
5753 RtlInitUnicodeString(&string, afdW);
5754 InitializeObjectAttributes(&attr, &string, (flags & WSA_FLAG_NO_HANDLE_INHERIT) ? 0 : OBJ_INHERIT, NULL, NULL);
5755 if ((status = NtOpenFile(&handle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &attr,
5756 &io, 0, (flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT)))
5758 WARN("Failed to create socket, status %#x.\n", status);
5759 WSASetLastError(NtStatusToWSAError(status));
5760 return INVALID_SOCKET;
5763 create_params.family = af;
5764 create_params.type = type;
5765 create_params.protocol = protocol;
5766 create_params.flags = flags & ~(WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED);
5767 if ((status = NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io,
5768 IOCTL_AFD_WINE_CREATE, &create_params, sizeof(create_params), NULL, 0)))
5770 WARN("Failed to initialize socket, status %#x.\n", status);
5771 err = RtlNtStatusToDosError( status );
5772 if (err == WSAEACCES) /* raw socket denied */
5774 if (type == SOCK_RAW)
5775 ERR_(winediag)("Failed to create a socket of type SOCK_RAW, this requires special permissions.\n");
5776 else
5777 ERR_(winediag)("Failed to create socket, this requires special permissions.\n");
5779 WSASetLastError(err);
5780 NtClose(handle);
5781 return INVALID_SOCKET;
5784 ret = HANDLE2SOCKET(handle);
5785 TRACE("\tcreated %04lx\n", ret );
5787 if (!socket_list_add(ret))
5789 CloseHandle(handle);
5790 return INVALID_SOCKET;
5792 return ret;
5794 done:
5795 WARN("\t\tfailed, error %d!\n", err);
5796 SetLastError(err);
5797 return INVALID_SOCKET;
5800 /***********************************************************************
5801 * WSAJoinLeaf (WS2_32.58)
5804 SOCKET WINAPI WSAJoinLeaf(
5805 SOCKET s,
5806 const struct WS_sockaddr *addr,
5807 int addrlen,
5808 LPWSABUF lpCallerData,
5809 LPWSABUF lpCalleeData,
5810 LPQOS lpSQOS,
5811 LPQOS lpGQOS,
5812 DWORD dwFlags)
5814 FIXME("stub.\n");
5815 return INVALID_SOCKET;
5818 /***********************************************************************
5819 * __WSAFDIsSet (WS2_32.151)
5821 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
5823 int i = set->fd_count, ret = 0;
5825 while (i--)
5826 if (set->fd_array[i] == s)
5828 ret = 1;
5829 break;
5832 TRACE("(socket %04lx, fd_set %p, count %i) <- %d\n", s, set, set->fd_count, ret);
5833 return ret;
5836 /***********************************************************************
5837 * WSAIsBlocking (WS2_32.114)
5839 BOOL WINAPI WSAIsBlocking(void)
5841 /* By default WinSock should set all its sockets to non-blocking mode
5842 * and poll in PeekMessage loop when processing "blocking" ones. This
5843 * function is supposed to tell if the program is in this loop. Our
5844 * blocking calls are truly blocking so we always return FALSE.
5846 * Note: It is allowed to call this function without prior WSAStartup().
5849 TRACE("\n");
5850 return FALSE;
5853 /***********************************************************************
5854 * WSACancelBlockingCall (WS2_32.113)
5856 INT WINAPI WSACancelBlockingCall(void)
5858 TRACE("\n");
5859 return 0;
5862 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
5864 FIXME("How was this called?\n");
5865 return x();
5869 /***********************************************************************
5870 * WSASetBlockingHook (WS2_32.109)
5872 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
5874 FARPROC prev = blocking_hook;
5875 blocking_hook = lpBlockFunc;
5876 TRACE("hook %p\n", lpBlockFunc);
5877 return prev;
5881 /***********************************************************************
5882 * WSAUnhookBlockingHook (WS2_32.110)
5884 INT WINAPI WSAUnhookBlockingHook(void)
5886 blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
5887 return 0;
5891 /***********************************************************************
5892 * WSARecv (WS2_32.67)
5894 int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
5895 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
5896 LPWSAOVERLAPPED lpOverlapped,
5897 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
5899 return WS2_recv_base(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
5900 NULL, NULL, lpOverlapped, lpCompletionRoutine, NULL);
5903 static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
5904 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags,
5905 struct WS_sockaddr *lpFrom,
5906 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
5907 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
5908 LPWSABUF lpControlBuffer )
5910 unsigned int i, options;
5911 int n, fd, err, overlapped, flags;
5912 struct ws2_async *wsa = NULL, localwsa;
5913 BOOL is_blocking;
5914 DWORD timeout_start = GetTickCount();
5915 ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
5917 TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, from %p, fromlen %d, ovl %p, func %p\n",
5918 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
5919 (lpFromlen ? *lpFromlen : -1),
5920 lpOverlapped, lpCompletionRoutine);
5922 fd = get_sock_fd( s, FILE_READ_DATA, &options );
5923 TRACE( "fd=%d, options=%x\n", fd, options );
5925 if (fd == -1) return SOCKET_ERROR;
5927 if (*lpFlags & WS_MSG_OOB)
5929 /* It's invalid to receive OOB data from an OOBINLINED socket
5930 * as OOB data is turned into normal data. */
5931 socklen_t len = sizeof(n);
5932 if (!getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char*) &n, &len) && n)
5934 err = WSAEINVAL;
5935 goto error;
5939 overlapped = (lpOverlapped || lpCompletionRoutine) &&
5940 !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
5941 if (overlapped || dwBufferCount > 1)
5943 if (!(wsa = (struct ws2_async *)alloc_async_io( offsetof(struct ws2_async, iovec[dwBufferCount]),
5944 WS2_async_recv )))
5946 err = WSAEFAULT;
5947 goto error;
5950 else
5951 wsa = &localwsa;
5953 wsa->hSocket = SOCKET2HANDLE(s);
5954 wsa->flags = *lpFlags;
5955 wsa->lpFlags = lpFlags;
5956 wsa->addr = lpFrom;
5957 wsa->addrlen.ptr = lpFromlen;
5958 wsa->control = lpControlBuffer;
5959 wsa->n_iovecs = dwBufferCount;
5960 wsa->first_iovec = 0;
5961 for (i = 0; i < dwBufferCount; i++)
5963 /* check buffer first to trigger write watches */
5964 if (IsBadWritePtr( lpBuffers[i].buf, lpBuffers[i].len ))
5966 err = WSAEFAULT;
5967 goto error;
5969 wsa->iovec[i].iov_base = lpBuffers[i].buf;
5970 wsa->iovec[i].iov_len = lpBuffers[i].len;
5973 flags = convert_flags(wsa->flags);
5974 for (;;)
5976 n = WS2_recv( fd, wsa, flags );
5977 if (n == -1)
5979 /* Unix-like systems return EINVAL when attempting to read OOB data from
5980 * an empty socket buffer, convert that to a Windows expected return. */
5981 if ((flags & MSG_OOB) && errno == EINVAL)
5982 errno = EWOULDBLOCK;
5984 if (errno != EAGAIN)
5986 err = wsaErrno();
5987 goto error;
5990 else if (lpNumberOfBytesRecvd) *lpNumberOfBytesRecvd = n;
5992 if (overlapped)
5994 IO_STATUS_BLOCK *iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
5996 wsa->user_overlapped = lpOverlapped;
5997 wsa->completion_func = lpCompletionRoutine;
5998 release_sock_fd( s, fd );
6000 if (n == -1)
6002 iosb->u.Status = STATUS_PENDING;
6003 iosb->Information = 0;
6005 if (wsa->completion_func)
6006 err = register_async( ASYNC_TYPE_READ, wsa->hSocket, &wsa->io, NULL,
6007 ws2_async_apc, wsa, iosb );
6008 else
6009 err = register_async( ASYNC_TYPE_READ, wsa->hSocket, &wsa->io, lpOverlapped->hEvent,
6010 NULL, (void *)cvalue, iosb );
6012 if (err != STATUS_PENDING) HeapFree( GetProcessHeap(), 0, wsa );
6013 SetLastError(NtStatusToWSAError( err ));
6014 return SOCKET_ERROR;
6017 iosb->u.Status = STATUS_SUCCESS;
6018 iosb->Information = n;
6019 if (!wsa->completion_func)
6021 if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n, FALSE );
6022 if (lpOverlapped->hEvent) SetEvent( lpOverlapped->hEvent );
6023 HeapFree( GetProcessHeap(), 0, wsa );
6025 else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc,
6026 (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 );
6027 _enable_event(SOCKET2HANDLE(s), (wsa->flags & WS_MSG_OOB) ? FD_OOB : FD_READ, 0, 0);
6028 return 0;
6031 if (n != -1) break;
6033 if ((err = sock_is_blocking( s, &is_blocking ))) goto error;
6035 if ( is_blocking )
6037 struct pollfd pfd;
6038 int poll_timeout = -1;
6039 INT64 timeout = get_rcvsnd_timeo(fd, TRUE);
6041 if (timeout)
6043 timeout -= GetTickCount() - timeout_start;
6044 if (timeout < 0) poll_timeout = 0;
6045 else poll_timeout = timeout <= INT_MAX ? timeout : INT_MAX;
6048 pfd.fd = fd;
6049 pfd.events = POLLIN;
6050 if (*lpFlags & WS_MSG_OOB) pfd.events |= POLLPRI;
6052 if (!poll_timeout || !poll( &pfd, 1, poll_timeout ))
6054 err = WSAETIMEDOUT;
6055 /* a timeout is not fatal */
6056 _enable_event(SOCKET2HANDLE(s), (wsa->flags & WS_MSG_OOB) ? FD_OOB : FD_READ, 0, 0);
6057 goto error;
6060 else
6062 _enable_event(SOCKET2HANDLE(s), (wsa->flags & WS_MSG_OOB) ? FD_OOB : FD_READ, 0, 0);
6063 err = WSAEWOULDBLOCK;
6064 goto error;
6068 TRACE(" -> %i bytes\n", n);
6069 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
6070 release_sock_fd( s, fd );
6071 _enable_event(SOCKET2HANDLE(s), (wsa->flags & WS_MSG_OOB) ? FD_OOB : FD_READ, 0, 0);
6072 SetLastError(ERROR_SUCCESS);
6074 return 0;
6076 error:
6077 if (wsa != &localwsa) HeapFree( GetProcessHeap(), 0, wsa );
6078 release_sock_fd( s, fd );
6079 WARN(" -> ERROR %d\n", err);
6080 SetLastError( err );
6081 return SOCKET_ERROR;
6084 /***********************************************************************
6085 * WSARecvFrom (WS2_32.69)
6087 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
6088 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
6089 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
6090 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
6093 return WS2_recv_base( s, lpBuffers, dwBufferCount,
6094 lpNumberOfBytesRecvd, lpFlags,
6095 lpFrom, lpFromlen,
6096 lpOverlapped, lpCompletionRoutine, NULL );
6100 /***********************************************************************
6101 * WSAAccept (WS2_32.26)
6103 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
6104 LPCONDITIONPROC lpfnCondition, DWORD_PTR dwCallbackData)
6107 int ret = 0, size;
6108 WSABUF CallerId, CallerData, CalleeId, CalleeData;
6109 /* QOS SQOS, GQOS; */
6110 GROUP g;
6111 SOCKET cs;
6112 SOCKADDR src_addr, dst_addr;
6114 TRACE("socket %04lx, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
6115 s, addr, addrlen, lpfnCondition, dwCallbackData);
6117 cs = WS_accept(s, addr, addrlen);
6118 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
6119 if (!lpfnCondition) return cs;
6121 if (addr && addrlen)
6123 CallerId.buf = (char *)addr;
6124 CallerId.len = *addrlen;
6126 else
6128 size = sizeof(src_addr);
6129 WS_getpeername(cs, &src_addr, &size);
6130 CallerId.buf = (char *)&src_addr;
6131 CallerId.len = size;
6133 CallerData.buf = NULL;
6134 CallerData.len = 0;
6136 size = sizeof(dst_addr);
6137 WS_getsockname(cs, &dst_addr, &size);
6139 CalleeId.buf = (char *)&dst_addr;
6140 CalleeId.len = sizeof(dst_addr);
6142 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
6143 &CalleeId, &CalleeData, &g, dwCallbackData);
6145 switch (ret)
6147 case CF_ACCEPT:
6148 return cs;
6149 case CF_DEFER:
6150 SERVER_START_REQ( set_socket_deferred )
6152 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
6153 req->deferred = wine_server_obj_handle( SOCKET2HANDLE(cs) );
6154 if ( !wine_server_call_err ( req ) )
6156 SetLastError( WSATRY_AGAIN );
6157 WS_closesocket( cs );
6160 SERVER_END_REQ;
6161 return SOCKET_ERROR;
6162 case CF_REJECT:
6163 WS_closesocket(cs);
6164 SetLastError(WSAECONNREFUSED);
6165 return SOCKET_ERROR;
6166 default:
6167 FIXME("Unknown return type from Condition function\n");
6168 SetLastError(WSAENOTSOCK);
6169 return SOCKET_ERROR;
6173 /***********************************************************************
6174 * WSADuplicateSocketA (WS2_32.32)
6176 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
6178 return WS_DuplicateSocket(FALSE, s, dwProcessId, (LPWSAPROTOCOL_INFOW) lpProtocolInfo);
6181 /***********************************************************************
6182 * WSADuplicateSocketW (WS2_32.33)
6184 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
6186 return WS_DuplicateSocket(TRUE, s, dwProcessId, lpProtocolInfo);
6190 /***********************************************************************
6191 * WSAGetQOSByName (WS2_32.41)
6193 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
6195 FIXME( "(0x%04lx %p %p) Stub!\n", s, lpQOSName, lpQOS );
6196 return FALSE;
6200 /***********************************************************************
6201 * WSARecvDisconnect (WS2_32.68)
6203 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
6205 TRACE( "(%04lx %p)\n", s, disconnectdata );
6207 return WS_shutdown( s, SD_RECEIVE );
6211 static BOOL protocol_matches_filter( const int *filter, int protocol )
6213 if (!filter) return TRUE;
6214 while (*filter)
6216 if (protocol == *filter++) return TRUE;
6218 return FALSE;
6221 /*****************************************************************************
6222 * WSAEnumProtocolsA [WS2_32.@]
6224 * see function WSAEnumProtocolsW
6226 int WINAPI WSAEnumProtocolsA( int *filter, WSAPROTOCOL_INFOA *protocols, DWORD *size )
6228 DWORD i, count = 0;
6230 TRACE("filter %p, protocols %p, size %p\n", filter, protocols, size);
6232 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
6234 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
6235 ++count;
6238 if (!protocols || *size < count * sizeof(WSAPROTOCOL_INFOA))
6240 *size = count * sizeof(WSAPROTOCOL_INFOA);
6241 WSASetLastError( WSAENOBUFS );
6242 return SOCKET_ERROR;
6245 count = 0;
6246 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
6248 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
6250 memcpy( &protocols[count], &supported_protocols[i], offsetof( WSAPROTOCOL_INFOW, szProtocol ) );
6251 WideCharToMultiByte( CP_ACP, 0, supported_protocols[i].szProtocol, -1,
6252 protocols[count].szProtocol, sizeof(protocols[count].szProtocol), NULL, NULL );
6253 ++count;
6256 return count;
6259 /*****************************************************************************
6260 * WSAEnumProtocolsW [WS2_32.@]
6262 * Retrieves information about specified set of active network protocols.
6264 * PARAMS
6265 * protocols [I] Pointer to null-terminated array of protocol id's. NULL
6266 * retrieves information on all available protocols.
6267 * buffer [I] Pointer to a buffer to be filled with WSAPROTOCOL_INFO
6268 * structures.
6269 * len [I/O] Pointer to a variable specifying buffer size. On output
6270 * the variable holds the number of bytes needed when the
6271 * specified size is too small.
6273 * RETURNS
6274 * Success: number of WSAPROTOCOL_INFO structures in buffer.
6275 * Failure: SOCKET_ERROR
6277 * NOTES
6278 * NT4SP5 does not return SPX if protocols == NULL
6280 * BUGS
6281 * - NT4SP5 returns in addition these list of NETBIOS protocols
6282 * (address family 17), each entry two times one for socket type 2 and 5
6284 * iProtocol szProtocol
6285 * 0x80000000 \Device\NwlnkNb
6286 * 0xfffffffa \Device\NetBT_CBENT7
6287 * 0xfffffffb \Device\Nbf_CBENT7
6288 * 0xfffffffc \Device\NetBT_NdisWan5
6289 * 0xfffffffd \Device\NetBT_El9202
6290 * 0xfffffffe \Device\Nbf_El9202
6291 * 0xffffffff \Device\Nbf_NdisWan4
6293 * - there is no check that the operating system supports the returned
6294 * protocols
6296 int WINAPI WSAEnumProtocolsW( int *filter, WSAPROTOCOL_INFOW *protocols, DWORD *size )
6298 DWORD i, count = 0;
6300 TRACE("filter %p, protocols %p, size %p\n", filter, protocols, size);
6302 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
6304 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
6305 ++count;
6308 if (!protocols || *size < count * sizeof(WSAPROTOCOL_INFOW))
6310 *size = count * sizeof(WSAPROTOCOL_INFOW);
6311 WSASetLastError( WSAENOBUFS );
6312 return SOCKET_ERROR;
6315 count = 0;
6316 for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
6318 if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
6319 protocols[count++] = supported_protocols[i];
6321 return count;