configure: Changes from running autconf after previous patch.
[wine/hacks.git] / dlls / ws2_32 / socket.c
blobe3153a7143c2a8523f52c12cdc777fe08ea2b8d6
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) 2005 Marcus Meissner
6 * Copyright (C) 2006-2008 Kai Blin
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * NOTE: If you make any changes to fix a particular app, make sure
23 * they don't break something else like Netscape or telnet and ftp
24 * clients and servers (www.winsite.com got a lot of those).
27 #include "config.h"
28 #include "wine/port.h"
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #ifdef HAVE_SYS_IPC_H
35 # include <sys/ipc.h>
36 #endif
37 #ifdef HAVE_SYS_IOCTL_H
38 # include <sys/ioctl.h>
39 #endif
40 #ifdef HAVE_SYS_FILIO_H
41 # include <sys/filio.h>
42 #endif
43 #ifdef HAVE_SYS_SOCKIO_H
44 # include <sys/sockio.h>
45 #endif
47 #if defined(__EMX__)
48 # include <sys/so_ioctl.h>
49 #endif
51 #ifdef HAVE_SYS_PARAM_H
52 # include <sys/param.h>
53 #endif
55 #ifdef HAVE_SYS_MSG_H
56 # include <sys/msg.h>
57 #endif
58 #ifdef HAVE_SYS_WAIT_H
59 # include <sys/wait.h>
60 #endif
61 #ifdef HAVE_SYS_UIO_H
62 # include <sys/uio.h>
63 #endif
64 #ifdef HAVE_SYS_SOCKET_H
65 #include <sys/socket.h>
66 #endif
67 #ifdef HAVE_NETINET_IN_H
68 # include <netinet/in.h>
69 #endif
70 #ifdef HAVE_NETINET_TCP_H
71 # include <netinet/tcp.h>
72 #endif
73 #ifdef HAVE_ARPA_INET_H
74 # include <arpa/inet.h>
75 #endif
76 #include <ctype.h>
77 #include <fcntl.h>
78 #include <errno.h>
79 #ifdef HAVE_SYS_ERRNO_H
80 #include <sys/errno.h>
81 #endif
82 #ifdef HAVE_NETDB_H
83 #include <netdb.h>
84 #endif
85 #ifdef HAVE_UNISTD_H
86 # include <unistd.h>
87 #endif
88 #include <stdlib.h>
89 #ifdef HAVE_ARPA_NAMESER_H
90 # include <arpa/nameser.h>
91 #endif
92 #ifdef HAVE_RESOLV_H
93 # include <resolv.h>
94 #endif
95 #ifdef HAVE_NET_IF_H
96 # include <net/if.h>
97 #endif
99 #ifdef HAVE_NETIPX_IPX_H
100 # include <netipx/ipx.h>
101 # define HAVE_IPX
102 #elif defined(HAVE_LINUX_IPX_H)
103 # ifdef HAVE_ASM_TYPES_H
104 # include <asm/types.h>
105 # endif
106 # ifdef HAVE_LINUX_TYPES_H
107 # include <linux/types.h>
108 # endif
109 # include <linux/ipx.h>
110 # define HAVE_IPX
111 #endif
113 #ifdef HAVE_LINUX_IRDA_H
114 # ifdef HAVE_LINUX_TYPES_H
115 # include <linux/types.h>
116 # endif
117 # include <linux/irda.h>
118 # define HAVE_IRDA
119 #endif
121 #ifdef HAVE_POLL_H
122 #include <poll.h>
123 #endif
124 #ifdef HAVE_SYS_POLL_H
125 # include <sys/poll.h>
126 #endif
127 #ifdef HAVE_SYS_TIME_H
128 # include <sys/time.h>
129 #endif
131 #define NONAMELESSUNION
132 #define NONAMELESSSTRUCT
133 #include "ntstatus.h"
134 #define WIN32_NO_STATUS
135 #include "windef.h"
136 #include "winbase.h"
137 #include "wingdi.h"
138 #include "winuser.h"
139 #include "winerror.h"
140 #include "winnls.h"
141 #include "winsock2.h"
142 #include "mswsock.h"
143 #include "ws2tcpip.h"
144 #include "ws2spi.h"
145 #include "wsipx.h"
146 #include "mstcpip.h"
147 #include "af_irda.h"
148 #include "winnt.h"
149 #include "iphlpapi.h"
150 #include "wine/server.h"
151 #include "wine/debug.h"
152 #include "wine/exception.h"
153 #include "wine/unicode.h"
155 #ifdef HAVE_IPX
156 # include "wsnwlink.h"
157 #endif
160 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
161 # define sipx_network sipx_addr.x_net
162 # define sipx_node sipx_addr.x_host.c_host
163 #endif /* __FreeBSD__ */
165 #ifndef INADDR_NONE
166 #define INADDR_NONE ~0UL
167 #endif
169 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
170 WINE_DECLARE_DEBUG_CHANNEL(winediag);
172 /* critical section to protect some non-reentrant net function */
173 static CRITICAL_SECTION csWSgetXXXbyYYY;
174 static CRITICAL_SECTION_DEBUG critsect_debug =
176 0, 0, &csWSgetXXXbyYYY,
177 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
178 0, 0, { (DWORD_PTR)(__FILE__ ": csWSgetXXXbyYYY") }
180 static CRITICAL_SECTION csWSgetXXXbyYYY = { &critsect_debug, -1, 0, 0, 0, 0 };
182 union generic_unix_sockaddr
184 struct sockaddr addr;
185 char data[128]; /* should be big enough for all families */
188 static inline const char *debugstr_sockaddr( const struct WS_sockaddr *a )
190 if (!a) return "(nil)";
191 switch (a->sa_family)
193 case WS_AF_INET:
194 return wine_dbg_sprintf("{ family AF_INET, address %s, port %d }",
195 inet_ntoa(((const struct sockaddr_in *)a)->sin_addr),
196 ntohs(((const struct sockaddr_in *)a)->sin_port));
197 case WS_AF_INET6:
199 char buf[46];
200 const char *p;
201 struct WS_sockaddr_in6 *sin = (struct WS_sockaddr_in6 *)a;
203 p = WS_inet_ntop( WS_AF_INET6, &sin->sin6_addr, buf, sizeof(buf) );
204 if (!p)
205 p = "(unknown IPv6 address)";
206 return wine_dbg_sprintf("{ family AF_INET6, address %s, port %d }",
207 p, ntohs(sin->sin6_port));
209 case WS_AF_IRDA:
211 DWORD addr;
213 memcpy( &addr, ((const SOCKADDR_IRDA *)a)->irdaDeviceID, sizeof(addr) );
214 addr = ntohl( addr );
215 return wine_dbg_sprintf("{ family AF_IRDA, addr %08x, name %s }",
216 addr,
217 ((const SOCKADDR_IRDA *)a)->irdaServiceName);
219 default:
220 return wine_dbg_sprintf("{ family %d }", a->sa_family);
224 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
225 #define SOCKET2HANDLE(s) ((HANDLE)(s))
226 #define HANDLE2SOCKET(h) ((SOCKET)(h))
228 /****************************************************************
229 * Async IO declarations
230 ****************************************************************/
232 typedef struct ws2_async
234 HANDLE hSocket;
235 int type;
236 LPWSAOVERLAPPED user_overlapped;
237 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
238 IO_STATUS_BLOCK local_iosb;
239 struct WS_sockaddr *addr;
240 union
242 int val; /* for send operations */
243 int *ptr; /* for recv operations */
244 } addrlen;
245 DWORD flags;
246 unsigned int n_iovecs;
247 unsigned int first_iovec;
248 struct iovec iovec[1];
249 } ws2_async;
251 typedef struct ws2_accept_async
253 SOCKET s_listen;
254 SOCKET s_accept;
255 LPOVERLAPPED user_overlapped;
256 ULONG_PTR cvalue;
257 PVOID buf;
258 int data_len;
259 int local_len;
260 int remote_len;
261 ws2_async *read;
262 } ws2_accept_async;
264 /****************************************************************/
266 /* ----------------------------------- internal data */
268 /* ws_... struct conversion flags */
270 typedef struct /* WSAAsyncSelect() control struct */
272 HANDLE service, event, sock;
273 HWND hWnd;
274 UINT uMsg;
275 LONG lEvent;
276 } ws_select_info;
278 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
279 #define WS_MAX_UDP_DATAGRAM 1024
280 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
281 static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus,
282 ULONG Information );
284 /* hostent's, servent's and protent's are stored in one buffer per thread,
285 * as documented on MSDN for the functions that return any of the buffers */
286 struct per_thread_data
288 int opentype;
289 struct WS_hostent *he_buffer;
290 struct WS_servent *se_buffer;
291 struct WS_protoent *pe_buffer;
292 int he_len;
293 int se_len;
294 int pe_len;
297 /* internal: routing description information */
298 struct route {
299 struct in_addr addr;
300 DWORD interface;
301 DWORD metric;
304 static INT num_startup; /* reference counter */
305 static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
307 /* function prototypes */
308 static struct WS_hostent *WS_create_he(char *name, int aliases, int addresses, int fill_addresses);
309 static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
310 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
311 static struct WS_servent *WS_dup_se(const struct servent* p_se);
313 int WSAIOCTL_GetInterfaceCount(void);
314 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
316 #define MAP_OPTION(opt) { WS_##opt, opt }
318 static const int ws_sock_map[][2] =
320 MAP_OPTION( SO_DEBUG ),
321 MAP_OPTION( SO_ACCEPTCONN ),
322 MAP_OPTION( SO_REUSEADDR ),
323 MAP_OPTION( SO_KEEPALIVE ),
324 MAP_OPTION( SO_DONTROUTE ),
325 MAP_OPTION( SO_BROADCAST ),
326 MAP_OPTION( SO_LINGER ),
327 MAP_OPTION( SO_OOBINLINE ),
328 MAP_OPTION( SO_SNDBUF ),
329 MAP_OPTION( SO_RCVBUF ),
330 MAP_OPTION( SO_ERROR ),
331 MAP_OPTION( SO_TYPE ),
332 #ifdef SO_RCVTIMEO
333 MAP_OPTION( SO_RCVTIMEO ),
334 #endif
335 #ifdef SO_SNDTIMEO
336 MAP_OPTION( SO_SNDTIMEO ),
337 #endif
340 static const int ws_tcp_map[][2] =
342 #ifdef TCP_NODELAY
343 MAP_OPTION( TCP_NODELAY ),
344 #endif
347 static const int ws_ip_map[][2] =
349 MAP_OPTION( IP_MULTICAST_IF ),
350 MAP_OPTION( IP_MULTICAST_TTL ),
351 MAP_OPTION( IP_MULTICAST_LOOP ),
352 MAP_OPTION( IP_ADD_MEMBERSHIP ),
353 MAP_OPTION( IP_DROP_MEMBERSHIP ),
354 MAP_OPTION( IP_OPTIONS ),
355 #ifdef IP_HDRINCL
356 MAP_OPTION( IP_HDRINCL ),
357 #endif
358 MAP_OPTION( IP_TOS ),
359 MAP_OPTION( IP_TTL ),
362 static const int ws_ipv6_map[][2] =
364 #ifdef IPV6_ADD_MEMBERSHIP
365 MAP_OPTION( IPV6_ADD_MEMBERSHIP ),
366 #endif
367 #ifdef IPV6_DROP_MEMBERSHIP
368 MAP_OPTION( IPV6_DROP_MEMBERSHIP ),
369 #endif
370 MAP_OPTION( IPV6_MULTICAST_IF ),
371 MAP_OPTION( IPV6_MULTICAST_HOPS ),
372 MAP_OPTION( IPV6_MULTICAST_LOOP ),
373 MAP_OPTION( IPV6_UNICAST_HOPS ),
374 MAP_OPTION( IPV6_V6ONLY ),
377 static const int ws_af_map[][2] =
379 MAP_OPTION( AF_UNSPEC ),
380 MAP_OPTION( AF_INET ),
381 MAP_OPTION( AF_INET6 ),
382 #ifdef HAVE_IPX
383 MAP_OPTION( AF_IPX ),
384 #endif
385 #ifdef AF_IRDA
386 MAP_OPTION( AF_IRDA ),
387 #endif
388 {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
391 static const int ws_socktype_map[][2] =
393 MAP_OPTION( SOCK_DGRAM ),
394 MAP_OPTION( SOCK_STREAM ),
395 MAP_OPTION( SOCK_RAW ),
396 {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
399 static const int ws_proto_map[][2] =
401 MAP_OPTION( IPPROTO_IP ),
402 MAP_OPTION( IPPROTO_TCP ),
403 MAP_OPTION( IPPROTO_UDP ),
404 MAP_OPTION( IPPROTO_ICMP ),
405 MAP_OPTION( IPPROTO_IGMP ),
406 MAP_OPTION( IPPROTO_RAW ),
407 {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
410 static const int ws_aiflag_map[][2] =
412 MAP_OPTION( AI_PASSIVE ),
413 MAP_OPTION( AI_CANONNAME ),
414 MAP_OPTION( AI_NUMERICHOST ),
415 /* Linux/UNIX knows a lot more. But Windows only
416 * has 3 as far as I could see. -Marcus
420 static const int ws_niflag_map[][2] =
422 MAP_OPTION( NI_NOFQDN ),
423 MAP_OPTION( NI_NUMERICHOST ),
424 MAP_OPTION( NI_NAMEREQD ),
425 MAP_OPTION( NI_NUMERICSERV ),
426 MAP_OPTION( NI_DGRAM ),
429 static const int ws_eai_map[][2] =
431 MAP_OPTION( EAI_AGAIN ),
432 MAP_OPTION( EAI_BADFLAGS ),
433 MAP_OPTION( EAI_FAIL ),
434 MAP_OPTION( EAI_FAMILY ),
435 MAP_OPTION( EAI_MEMORY ),
436 /* Note: EAI_NODATA is deprecated, but still
437 * used by Windows and Linux... We map the newer
438 * EAI_NONAME to EAI_NODATA for now until Windows
439 * changes too.
441 #ifdef EAI_NODATA
442 MAP_OPTION( EAI_NODATA ),
443 #endif
444 #ifdef EAI_NONAME
445 { WS_EAI_NODATA, EAI_NONAME },
446 #endif
448 MAP_OPTION( EAI_SERVICE ),
449 MAP_OPTION( EAI_SOCKTYPE ),
450 { 0, 0 }
453 static const char magic_loopback_addr[] = {127, 12, 34, 56};
455 /* ----------------------------------- error handling */
457 static NTSTATUS sock_get_ntstatus( int err )
459 switch ( err )
461 case EBADF: return STATUS_INVALID_HANDLE;
462 case EBUSY: return STATUS_DEVICE_BUSY;
463 case EPERM:
464 case EACCES: return STATUS_ACCESS_DENIED;
465 case EFAULT: return STATUS_NO_MEMORY;
466 case EINVAL: return STATUS_INVALID_PARAMETER;
467 case ENFILE:
468 case EMFILE: return STATUS_TOO_MANY_OPENED_FILES;
469 case EWOULDBLOCK: return STATUS_CANT_WAIT;
470 case EINPROGRESS: return STATUS_PENDING;
471 case EALREADY: return STATUS_NETWORK_BUSY;
472 case ENOTSOCK: return STATUS_OBJECT_TYPE_MISMATCH;
473 case EDESTADDRREQ: return STATUS_INVALID_PARAMETER;
474 case EMSGSIZE: return STATUS_BUFFER_OVERFLOW;
475 case EPROTONOSUPPORT:
476 case ESOCKTNOSUPPORT:
477 case EPFNOSUPPORT:
478 case EAFNOSUPPORT:
479 case EPROTOTYPE: return STATUS_NOT_SUPPORTED;
480 case ENOPROTOOPT: return STATUS_INVALID_PARAMETER;
481 case EOPNOTSUPP: return STATUS_NOT_SUPPORTED;
482 case EADDRINUSE: return STATUS_ADDRESS_ALREADY_ASSOCIATED;
483 case EADDRNOTAVAIL: return STATUS_INVALID_PARAMETER;
484 case ECONNREFUSED: return STATUS_CONNECTION_REFUSED;
485 case ESHUTDOWN: return STATUS_PIPE_DISCONNECTED;
486 case ENOTCONN: return STATUS_CONNECTION_DISCONNECTED;
487 case ETIMEDOUT: return STATUS_IO_TIMEOUT;
488 case ENETUNREACH: return STATUS_NETWORK_UNREACHABLE;
489 case ENETDOWN: return STATUS_NETWORK_BUSY;
490 case EPIPE:
491 case ECONNRESET: return STATUS_CONNECTION_RESET;
492 case ECONNABORTED: return STATUS_CONNECTION_ABORTED;
494 case 0: return STATUS_SUCCESS;
495 default:
496 WARN("Unknown errno %d!\n", err);
497 return STATUS_UNSUCCESSFUL;
501 static UINT sock_get_error( int err )
503 switch(err)
505 case EINTR: return WSAEINTR;
506 case EBADF: return WSAEBADF;
507 case EPERM:
508 case EACCES: return WSAEACCES;
509 case EFAULT: return WSAEFAULT;
510 case EINVAL: return WSAEINVAL;
511 case EMFILE: return WSAEMFILE;
512 case EWOULDBLOCK: return WSAEWOULDBLOCK;
513 case EINPROGRESS: return WSAEINPROGRESS;
514 case EALREADY: return WSAEALREADY;
515 case ENOTSOCK: return WSAENOTSOCK;
516 case EDESTADDRREQ: return WSAEDESTADDRREQ;
517 case EMSGSIZE: return WSAEMSGSIZE;
518 case EPROTOTYPE: return WSAEPROTOTYPE;
519 case ENOPROTOOPT: return WSAENOPROTOOPT;
520 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
521 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
522 case EOPNOTSUPP: return WSAEOPNOTSUPP;
523 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
524 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
525 case EADDRINUSE: return WSAEADDRINUSE;
526 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
527 case ENETDOWN: return WSAENETDOWN;
528 case ENETUNREACH: return WSAENETUNREACH;
529 case ENETRESET: return WSAENETRESET;
530 case ECONNABORTED: return WSAECONNABORTED;
531 case EPIPE:
532 case ECONNRESET: return WSAECONNRESET;
533 case ENOBUFS: return WSAENOBUFS;
534 case EISCONN: return WSAEISCONN;
535 case ENOTCONN: return WSAENOTCONN;
536 case ESHUTDOWN: return WSAESHUTDOWN;
537 case ETOOMANYREFS: return WSAETOOMANYREFS;
538 case ETIMEDOUT: return WSAETIMEDOUT;
539 case ECONNREFUSED: return WSAECONNREFUSED;
540 case ELOOP: return WSAELOOP;
541 case ENAMETOOLONG: return WSAENAMETOOLONG;
542 case EHOSTDOWN: return WSAEHOSTDOWN;
543 case EHOSTUNREACH: return WSAEHOSTUNREACH;
544 case ENOTEMPTY: return WSAENOTEMPTY;
545 #ifdef EPROCLIM
546 case EPROCLIM: return WSAEPROCLIM;
547 #endif
548 #ifdef EUSERS
549 case EUSERS: return WSAEUSERS;
550 #endif
551 #ifdef EDQUOT
552 case EDQUOT: return WSAEDQUOT;
553 #endif
554 #ifdef ESTALE
555 case ESTALE: return WSAESTALE;
556 #endif
557 #ifdef EREMOTE
558 case EREMOTE: return WSAEREMOTE;
559 #endif
561 /* just in case we ever get here and there are no problems */
562 case 0: return 0;
563 default:
564 WARN("Unknown errno %d!\n", err);
565 return WSAEOPNOTSUPP;
569 static UINT wsaErrno(void)
571 int loc_errno = errno;
572 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
574 return sock_get_error( loc_errno );
577 /* most ws2 overlapped functions return an ntstatus-based error code */
578 static NTSTATUS wsaErrStatus(void)
580 int loc_errno = errno;
581 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
583 return sock_get_ntstatus(loc_errno);
586 static UINT wsaHerrno(int loc_errno)
588 WARN("h_errno %d.\n", loc_errno);
590 switch(loc_errno)
592 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
593 case TRY_AGAIN: return WSATRY_AGAIN;
594 case NO_RECOVERY: return WSANO_RECOVERY;
595 case NO_DATA: return WSANO_DATA;
596 case ENOBUFS: return WSAENOBUFS;
598 case 0: return 0;
599 default:
600 WARN("Unknown h_errno %d!\n", loc_errno);
601 return WSAEOPNOTSUPP;
605 static inline DWORD NtStatusToWSAError( const DWORD status )
607 /* We only need to cover the status codes set by server async request handling */
608 DWORD wserr;
609 switch ( status )
611 case STATUS_SUCCESS: wserr = 0; break;
612 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
613 case STATUS_OBJECT_TYPE_MISMATCH: wserr = WSAENOTSOCK; break;
614 case STATUS_INVALID_HANDLE: wserr = WSAEBADF; break;
615 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
616 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
617 case STATUS_NETWORK_BUSY: wserr = WSAEALREADY; break;
618 case STATUS_NETWORK_UNREACHABLE: wserr = WSAENETUNREACH; break;
619 case STATUS_CONNECTION_REFUSED: wserr = WSAECONNREFUSED; break;
620 case STATUS_CONNECTION_DISCONNECTED: wserr = WSAENOTCONN; break;
621 case STATUS_CONNECTION_RESET: wserr = WSAECONNRESET; break;
622 case STATUS_CONNECTION_ABORTED: wserr = WSAECONNABORTED; break;
623 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
624 case STATUS_ADDRESS_ALREADY_ASSOCIATED: wserr = WSAEADDRINUSE; break;
625 case STATUS_IO_TIMEOUT:
626 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
627 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
628 case STATUS_ACCESS_DENIED: wserr = WSAEACCES; break;
629 case STATUS_TOO_MANY_OPENED_FILES: wserr = WSAEMFILE; break;
630 case STATUS_CANT_WAIT: wserr = WSAEWOULDBLOCK; break;
631 case STATUS_BUFFER_OVERFLOW: wserr = WSAEMSGSIZE; break;
632 case STATUS_NOT_SUPPORTED: wserr = WSAEOPNOTSUPP; break;
633 case STATUS_HOST_UNREACHABLE: wserr = WSAEHOSTUNREACH; break;
635 default:
636 wserr = RtlNtStatusToDosError( status );
637 FIXME( "Status code %08x converted to DOS error code %x\n", status, wserr );
639 return wserr;
642 /* set last error code from NT status without mapping WSA errors */
643 static inline unsigned int set_error( unsigned int err )
645 if (err)
647 err = NtStatusToWSAError( err );
648 SetLastError( err );
650 return err;
653 static inline int get_sock_fd( SOCKET s, DWORD access, unsigned int *options )
655 int fd;
656 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, options ) ))
657 return -1;
658 return fd;
661 static inline void release_sock_fd( SOCKET s, int fd )
663 wine_server_release_fd( SOCKET2HANDLE(s), fd );
666 static void _enable_event( HANDLE s, unsigned int event,
667 unsigned int sstate, unsigned int cstate )
669 SERVER_START_REQ( enable_socket_event )
671 req->handle = wine_server_obj_handle( s );
672 req->mask = event;
673 req->sstate = sstate;
674 req->cstate = cstate;
675 wine_server_call( req );
677 SERVER_END_REQ;
680 static int _is_blocking(SOCKET s)
682 int ret;
683 SERVER_START_REQ( get_socket_event )
685 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
686 req->service = FALSE;
687 req->c_event = 0;
688 wine_server_call( req );
689 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
691 SERVER_END_REQ;
692 return ret;
695 static unsigned int _get_sock_mask(SOCKET s)
697 unsigned int ret;
698 SERVER_START_REQ( get_socket_event )
700 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
701 req->service = FALSE;
702 req->c_event = 0;
703 wine_server_call( req );
704 ret = reply->mask;
706 SERVER_END_REQ;
707 return ret;
710 static void _sync_sock_state(SOCKET s)
712 /* do a dummy wineserver request in order to let
713 the wineserver run through its select loop once */
714 (void)_is_blocking(s);
717 static int _get_sock_error(SOCKET s, unsigned int bit)
719 int events[FD_MAX_EVENTS];
721 SERVER_START_REQ( get_socket_event )
723 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
724 req->service = FALSE;
725 req->c_event = 0;
726 wine_server_set_reply( req, events, sizeof(events) );
727 wine_server_call( req );
729 SERVER_END_REQ;
730 return events[bit];
733 static struct per_thread_data *get_per_thread_data(void)
735 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
736 /* lazy initialization */
737 if (!ptb)
739 ptb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptb) );
740 NtCurrentTeb()->WinSockData = ptb;
742 return ptb;
745 static void free_per_thread_data(void)
747 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
749 if (!ptb) return;
751 /* delete scratch buffers */
752 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
753 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
754 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
755 ptb->he_buffer = NULL;
756 ptb->se_buffer = NULL;
757 ptb->pe_buffer = NULL;
759 HeapFree( GetProcessHeap(), 0, ptb );
760 NtCurrentTeb()->WinSockData = NULL;
763 /***********************************************************************
764 * DllMain (WS2_32.init)
766 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
768 TRACE("%p 0x%x %p\n", hInstDLL, fdwReason, fImpLoad);
769 switch (fdwReason) {
770 case DLL_PROCESS_ATTACH:
771 break;
772 case DLL_PROCESS_DETACH:
773 free_per_thread_data();
774 num_startup = 0;
775 break;
776 case DLL_THREAD_DETACH:
777 free_per_thread_data();
778 break;
780 return TRUE;
783 /***********************************************************************
784 * convert_sockopt()
786 * Converts socket flags from Windows format.
787 * Return 1 if converted, 0 if not (error).
789 static int convert_sockopt(INT *level, INT *optname)
791 unsigned int i;
792 switch (*level)
794 case WS_SOL_SOCKET:
795 *level = SOL_SOCKET;
796 for(i=0; i<sizeof(ws_sock_map)/sizeof(ws_sock_map[0]); i++) {
797 if( ws_sock_map[i][0] == *optname )
799 *optname = ws_sock_map[i][1];
800 return 1;
803 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
804 break;
805 case WS_IPPROTO_TCP:
806 *level = IPPROTO_TCP;
807 for(i=0; i<sizeof(ws_tcp_map)/sizeof(ws_tcp_map[0]); i++) {
808 if ( ws_tcp_map[i][0] == *optname )
810 *optname = ws_tcp_map[i][1];
811 return 1;
814 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
815 break;
816 case WS_IPPROTO_IP:
817 *level = IPPROTO_IP;
818 for(i=0; i<sizeof(ws_ip_map)/sizeof(ws_ip_map[0]); i++) {
819 if (ws_ip_map[i][0] == *optname )
821 *optname = ws_ip_map[i][1];
822 return 1;
825 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
826 break;
827 case WS_IPPROTO_IPV6:
828 *level = IPPROTO_IPV6;
829 for(i=0; i<sizeof(ws_ipv6_map)/sizeof(ws_ipv6_map[0]); i++) {
830 if (ws_ipv6_map[i][0] == *optname )
832 *optname = ws_ipv6_map[i][1];
833 return 1;
836 FIXME("Unknown IPPROTO_IPV6 optname 0x%x\n", *optname);
837 break;
838 default: FIXME("Unimplemented or unknown socket level\n");
840 return 0;
843 /* ----------------------------------- Per-thread info (or per-process?) */
845 static char *strdup_lower(const char *str)
847 int i;
848 char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
850 if (ret)
852 for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
853 ret[i] = 0;
855 else SetLastError(WSAENOBUFS);
856 return ret;
859 static inline int sock_error_p(int s)
861 unsigned int optval, optlen;
863 optlen = sizeof(optval);
864 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
865 if (optval) WARN("\t[%i] error: %d\n", s, optval);
866 return optval != 0;
869 /* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
870 * from an fd and return the value converted to milli seconds
871 * or -1 if there is an infinite time out */
872 static inline int get_rcvsnd_timeo( int fd, int optname)
874 struct timeval tv;
875 unsigned int len = sizeof(tv);
876 int ret = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
877 if( ret >= 0)
878 ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
879 if( ret <= 0 ) /* tv == {0,0} means infinite time out */
880 return -1;
881 return ret;
884 /* macro wrappers for portability */
885 #ifdef SO_RCVTIMEO
886 #define GET_RCVTIMEO(fd) get_rcvsnd_timeo( (fd), SO_RCVTIMEO)
887 #else
888 #define GET_RCVTIMEO(fd) (-1)
889 #endif
891 #ifdef SO_SNDTIMEO
892 #define GET_SNDTIMEO(fd) get_rcvsnd_timeo( (fd), SO_SNDTIMEO)
893 #else
894 #define GET_SNDTIMEO(fd) (-1)
895 #endif
897 /* utility: given an fd, will block until one of the events occurs */
898 static inline int do_block( int fd, int events, int timeout )
900 struct pollfd pfd;
901 int ret;
903 pfd.fd = fd;
904 pfd.events = events;
906 while ((ret = poll(&pfd, 1, timeout)) < 0)
908 if (errno != EINTR)
909 return -1;
911 if( ret == 0 )
912 return 0;
913 return pfd.revents;
916 static int
917 convert_af_w2u(int windowsaf) {
918 unsigned int i;
920 for (i=0;i<sizeof(ws_af_map)/sizeof(ws_af_map[0]);i++)
921 if (ws_af_map[i][0] == windowsaf)
922 return ws_af_map[i][1];
923 FIXME("unhandled Windows address family %d\n", windowsaf);
924 return -1;
927 static int
928 convert_af_u2w(int unixaf) {
929 unsigned int i;
931 for (i=0;i<sizeof(ws_af_map)/sizeof(ws_af_map[0]);i++)
932 if (ws_af_map[i][1] == unixaf)
933 return ws_af_map[i][0];
934 FIXME("unhandled UNIX address family %d\n", unixaf);
935 return -1;
938 static int
939 convert_proto_w2u(int windowsproto) {
940 unsigned int i;
942 for (i=0;i<sizeof(ws_proto_map)/sizeof(ws_proto_map[0]);i++)
943 if (ws_proto_map[i][0] == windowsproto)
944 return ws_proto_map[i][1];
945 FIXME("unhandled Windows socket protocol %d\n", windowsproto);
946 return -1;
949 static int
950 convert_proto_u2w(int unixproto) {
951 unsigned int i;
953 for (i=0;i<sizeof(ws_proto_map)/sizeof(ws_proto_map[0]);i++)
954 if (ws_proto_map[i][1] == unixproto)
955 return ws_proto_map[i][0];
956 FIXME("unhandled UNIX socket protocol %d\n", unixproto);
957 return -1;
960 static int
961 convert_socktype_w2u(int windowssocktype) {
962 unsigned int i;
964 for (i=0;i<sizeof(ws_socktype_map)/sizeof(ws_socktype_map[0]);i++)
965 if (ws_socktype_map[i][0] == windowssocktype)
966 return ws_socktype_map[i][1];
967 FIXME("unhandled Windows socket type %d\n", windowssocktype);
968 return -1;
971 static int
972 convert_socktype_u2w(int unixsocktype) {
973 unsigned int i;
975 for (i=0;i<sizeof(ws_socktype_map)/sizeof(ws_socktype_map[0]);i++)
976 if (ws_socktype_map[i][1] == unixsocktype)
977 return ws_socktype_map[i][0];
978 FIXME("unhandled UNIX socket type %d\n", unixsocktype);
979 return -1;
982 /* ----------------------------------- API -----
984 * Init / cleanup / error checking.
987 /***********************************************************************
988 * WSAStartup (WS2_32.115)
990 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
992 TRACE("verReq=%x\n", wVersionRequested);
994 if (LOBYTE(wVersionRequested) < 1)
995 return WSAVERNOTSUPPORTED;
997 if (!lpWSAData) return WSAEINVAL;
999 num_startup++;
1001 /* that's the whole of the negotiation for now */
1002 lpWSAData->wVersion = wVersionRequested;
1003 /* return winsock information */
1004 lpWSAData->wHighVersion = 0x0202;
1005 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
1006 strcpy(lpWSAData->szSystemStatus, "Running" );
1007 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
1008 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
1009 /* don't do anything with lpWSAData->lpVendorInfo */
1010 /* (some apps don't allocate the space for this field) */
1012 TRACE("succeeded\n");
1013 return 0;
1017 /***********************************************************************
1018 * WSACleanup (WS2_32.116)
1020 INT WINAPI WSACleanup(void)
1022 if (num_startup) {
1023 num_startup--;
1024 return 0;
1026 SetLastError(WSANOTINITIALISED);
1027 return SOCKET_ERROR;
1031 /***********************************************************************
1032 * WSAGetLastError (WS2_32.111)
1034 INT WINAPI WSAGetLastError(void)
1036 return GetLastError();
1039 /***********************************************************************
1040 * WSASetLastError (WS2_32.112)
1042 void WINAPI WSASetLastError(INT iError) {
1043 SetLastError(iError);
1046 static struct WS_hostent *check_buffer_he(int size)
1048 struct per_thread_data * ptb = get_per_thread_data();
1049 if (ptb->he_buffer)
1051 if (ptb->he_len >= size ) return ptb->he_buffer;
1052 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
1054 ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
1055 if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
1056 return ptb->he_buffer;
1059 static struct WS_servent *check_buffer_se(int size)
1061 struct per_thread_data * ptb = get_per_thread_data();
1062 if (ptb->se_buffer)
1064 if (ptb->se_len >= size ) return ptb->se_buffer;
1065 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
1067 ptb->se_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->se_len = size) );
1068 if (!ptb->se_buffer) SetLastError(WSAENOBUFS);
1069 return ptb->se_buffer;
1072 static struct WS_protoent *check_buffer_pe(int size)
1074 struct per_thread_data * ptb = get_per_thread_data();
1075 if (ptb->pe_buffer)
1077 if (ptb->pe_len >= size ) return ptb->pe_buffer;
1078 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
1080 ptb->pe_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->pe_len = size) );
1081 if (!ptb->pe_buffer) SetLastError(WSAENOBUFS);
1082 return ptb->pe_buffer;
1085 /* ----------------------------------- i/o APIs */
1087 static inline BOOL supported_pf(int pf)
1089 switch (pf)
1091 case WS_AF_INET:
1092 case WS_AF_INET6:
1093 return TRUE;
1094 #ifdef HAVE_IPX
1095 case WS_AF_IPX:
1096 return TRUE;
1097 #endif
1098 #ifdef HAVE_IRDA
1099 case WS_AF_IRDA:
1100 return TRUE;
1101 #endif
1102 default:
1103 return FALSE;
1108 /**********************************************************************/
1110 /* Returns the length of the converted address if successful, 0 if it was too small to
1111 * start with.
1113 static unsigned int ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen,
1114 union generic_unix_sockaddr *uaddr)
1116 unsigned int uaddrlen = 0;
1118 switch (wsaddr->sa_family)
1120 #ifdef HAVE_IPX
1121 case WS_AF_IPX:
1123 const struct WS_sockaddr_ipx* wsipx=(const struct WS_sockaddr_ipx*)wsaddr;
1124 struct sockaddr_ipx* uipx = (struct sockaddr_ipx *)uaddr;
1126 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
1127 return 0;
1129 uaddrlen = sizeof(struct sockaddr_ipx);
1130 memset( uaddr, 0, uaddrlen );
1131 uipx->sipx_family=AF_IPX;
1132 uipx->sipx_port=wsipx->sa_socket;
1133 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
1134 * in one go
1136 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
1137 #ifdef IPX_FRAME_NONE
1138 uipx->sipx_type=IPX_FRAME_NONE;
1139 #endif
1140 break;
1142 #endif
1143 case WS_AF_INET6: {
1144 struct sockaddr_in6* uin6 = (struct sockaddr_in6 *)uaddr;
1145 const struct WS_sockaddr_in6* win6 = (const struct WS_sockaddr_in6*)wsaddr;
1147 /* Note: Windows has 2 versions of the sockaddr_in6 struct, one with
1148 * scope_id, one without.
1150 if (wsaddrlen >= sizeof(struct WS_sockaddr_in6_old)) {
1151 uaddrlen = sizeof(struct sockaddr_in6);
1152 memset( uaddr, 0, uaddrlen );
1153 uin6->sin6_family = AF_INET6;
1154 uin6->sin6_port = win6->sin6_port;
1155 uin6->sin6_flowinfo = win6->sin6_flowinfo;
1156 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
1157 if (wsaddrlen >= sizeof(struct WS_sockaddr_in6)) uin6->sin6_scope_id = win6->sin6_scope_id;
1158 #endif
1159 memcpy(&uin6->sin6_addr,&win6->sin6_addr,16); /* 16 bytes = 128 address bits */
1160 break;
1162 FIXME("bad size %d for WS_sockaddr_in6\n",wsaddrlen);
1163 return 0;
1165 case WS_AF_INET: {
1166 struct sockaddr_in* uin = (struct sockaddr_in *)uaddr;
1167 const struct WS_sockaddr_in* win = (const struct WS_sockaddr_in*)wsaddr;
1169 if (wsaddrlen<sizeof(struct WS_sockaddr_in))
1170 return 0;
1171 uaddrlen = sizeof(struct sockaddr_in);
1172 memset( uaddr, 0, uaddrlen );
1173 uin->sin_family = AF_INET;
1174 uin->sin_port = win->sin_port;
1175 memcpy(&uin->sin_addr,&win->sin_addr,4); /* 4 bytes = 32 address bits */
1176 break;
1178 #ifdef HAVE_IRDA
1179 case WS_AF_IRDA: {
1180 struct sockaddr_irda *uin = (struct sockaddr_irda *)uaddr;
1181 const SOCKADDR_IRDA *win = (const SOCKADDR_IRDA *)wsaddr;
1183 if (wsaddrlen < sizeof(SOCKADDR_IRDA))
1184 return 0;
1185 uaddrlen = sizeof(struct sockaddr_irda);
1186 memset( uaddr, 0, uaddrlen );
1187 uin->sir_family = AF_IRDA;
1188 if (!strncmp( win->irdaServiceName, "LSAP-SEL", strlen( "LSAP-SEL" ) ))
1190 unsigned int lsap_sel;
1192 sscanf( win->irdaServiceName, "LSAP-SEL%u", &lsap_sel );
1193 uin->sir_lsap_sel = lsap_sel;
1195 else
1197 uin->sir_lsap_sel = LSAP_ANY;
1198 memcpy( uin->sir_name, win->irdaServiceName, 25 );
1200 memcpy( &uin->sir_addr, win->irdaDeviceID, sizeof(uin->sir_addr) );
1201 break;
1203 #endif
1204 case WS_AF_UNSPEC: {
1205 /* Try to determine the needed space by the passed windows sockaddr space */
1206 switch (wsaddrlen) {
1207 default: /* likely a ipv4 address */
1208 case sizeof(struct WS_sockaddr_in):
1209 uaddrlen = sizeof(struct sockaddr_in);
1210 break;
1211 #ifdef HAVE_IPX
1212 case sizeof(struct WS_sockaddr_ipx):
1213 uaddrlen = sizeof(struct sockaddr_ipx);
1214 break;
1215 #endif
1216 #ifdef HAVE_IRDA
1217 case sizeof(SOCKADDR_IRDA):
1218 uaddrlen = sizeof(struct sockaddr_irda);
1219 break;
1220 #endif
1221 case sizeof(struct WS_sockaddr_in6):
1222 case sizeof(struct WS_sockaddr_in6_old):
1223 uaddrlen = sizeof(struct sockaddr_in6);
1224 break;
1226 memset( uaddr, 0, uaddrlen );
1227 break;
1229 default:
1230 FIXME("Unknown address family %d, return NULL.\n", wsaddr->sa_family);
1231 return 0;
1233 return uaddrlen;
1236 static BOOL is_sockaddr_bound(const struct sockaddr *uaddr, int uaddrlen)
1238 switch (uaddr->sa_family)
1240 #ifdef HAVE_IPX
1241 case AF_IPX:
1242 FIXME("don't know how to tell if IPX socket is bound, assuming it is!\n");
1243 return TRUE;
1244 #endif
1245 case AF_INET6:
1247 static const struct sockaddr_in6 emptyAddr;
1248 const struct sockaddr_in6 *in6 = (const struct sockaddr_in6*) uaddr;
1249 return in6->sin6_port || memcmp(&in6->sin6_addr, &emptyAddr.sin6_addr, sizeof(struct in6_addr));
1251 case AF_INET:
1253 static const struct sockaddr_in emptyAddr;
1254 const struct sockaddr_in *in = (const struct sockaddr_in*) uaddr;
1255 return in->sin_port || memcmp(&in->sin_addr, &emptyAddr.sin_addr, sizeof(struct in_addr));
1257 case AF_UNSPEC:
1258 return FALSE;
1259 default:
1260 FIXME("unknown address family %d\n", uaddr->sa_family);
1261 return TRUE;
1265 /* Returns 0 if successful, -1 if the buffer is too small */
1266 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, struct WS_sockaddr* wsaddr, int* wsaddrlen)
1268 int res;
1270 switch(uaddr->sa_family)
1272 #ifdef HAVE_IPX
1273 case AF_IPX:
1275 const struct sockaddr_ipx* uipx=(const struct sockaddr_ipx*)uaddr;
1276 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
1278 res=-1;
1279 switch (*wsaddrlen) /* how much can we copy? */
1281 default:
1282 res=0; /* enough */
1283 *wsaddrlen = sizeof(*wsipx);
1284 wsipx->sa_socket=uipx->sipx_port;
1285 /* fall through */
1286 case 13:
1287 case 12:
1288 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
1289 /* fall through */
1290 case 11:
1291 case 10:
1292 case 9:
1293 case 8:
1294 case 7:
1295 case 6:
1296 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
1297 /* fall through */
1298 case 5:
1299 case 4:
1300 case 3:
1301 case 2:
1302 wsipx->sa_family=WS_AF_IPX;
1303 /* fall through */
1304 case 1:
1305 case 0:
1306 /* way too small */
1307 break;
1310 break;
1311 #endif
1312 #ifdef HAVE_IRDA
1313 case AF_IRDA: {
1314 const struct sockaddr_irda *uin = (const struct sockaddr_irda *)uaddr;
1315 SOCKADDR_IRDA *win = (SOCKADDR_IRDA *)wsaddr;
1317 if (*wsaddrlen < sizeof(SOCKADDR_IRDA))
1318 return -1;
1319 win->irdaAddressFamily = WS_AF_IRDA;
1320 memcpy( win->irdaDeviceID, &uin->sir_addr, sizeof(win->irdaDeviceID) );
1321 if (uin->sir_lsap_sel != LSAP_ANY)
1322 sprintf( win->irdaServiceName, "LSAP-SEL%u", uin->sir_lsap_sel );
1323 else
1324 memcpy( win->irdaServiceName, uin->sir_name,
1325 sizeof(win->irdaServiceName) );
1326 return 0;
1328 #endif
1329 case AF_INET6: {
1330 const struct sockaddr_in6* uin6 = (const struct sockaddr_in6*)uaddr;
1331 struct WS_sockaddr_in6_old* win6old = (struct WS_sockaddr_in6_old*)wsaddr;
1333 if (*wsaddrlen < sizeof(struct WS_sockaddr_in6_old))
1334 return -1;
1335 win6old->sin6_family = WS_AF_INET6;
1336 win6old->sin6_port = uin6->sin6_port;
1337 win6old->sin6_flowinfo = uin6->sin6_flowinfo;
1338 memcpy(&win6old->sin6_addr,&uin6->sin6_addr,16); /* 16 bytes = 128 address bits */
1339 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
1340 if (*wsaddrlen >= sizeof(struct WS_sockaddr_in6)) {
1341 struct WS_sockaddr_in6* win6 = (struct WS_sockaddr_in6*)wsaddr;
1342 win6->sin6_scope_id = uin6->sin6_scope_id;
1343 *wsaddrlen = sizeof(struct WS_sockaddr_in6);
1345 else
1346 *wsaddrlen = sizeof(struct WS_sockaddr_in6_old);
1347 #else
1348 *wsaddrlen = sizeof(struct WS_sockaddr_in6_old);
1349 #endif
1350 return 0;
1352 case AF_INET: {
1353 const struct sockaddr_in* uin = (const struct sockaddr_in*)uaddr;
1354 struct WS_sockaddr_in* win = (struct WS_sockaddr_in*)wsaddr;
1356 if (*wsaddrlen < sizeof(struct WS_sockaddr_in))
1357 return -1;
1358 win->sin_family = WS_AF_INET;
1359 win->sin_port = uin->sin_port;
1360 memcpy(&win->sin_addr,&uin->sin_addr,4); /* 4 bytes = 32 address bits */
1361 memset(win->sin_zero, 0, 8); /* Make sure the null padding is null */
1362 *wsaddrlen = sizeof(struct WS_sockaddr_in);
1363 return 0;
1365 case AF_UNSPEC: {
1366 memset(wsaddr,0,*wsaddrlen);
1367 return 0;
1369 default:
1370 FIXME("Unknown address family %d\n", uaddr->sa_family);
1371 return -1;
1373 return res;
1376 /**************************************************************************
1377 * Functions for handling overlapped I/O
1378 **************************************************************************/
1380 /* user APC called upon async completion */
1381 static void WINAPI ws2_async_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
1383 ws2_async *wsa = arg;
1385 if (wsa->completion_func) wsa->completion_func( NtStatusToWSAError(iosb->u.Status),
1386 iosb->Information, wsa->user_overlapped,
1387 wsa->flags );
1388 HeapFree( GetProcessHeap(), 0, wsa );
1391 /***********************************************************************
1392 * WS2_recv (INTERNAL)
1394 * Workhorse for both synchronous and asynchronous recv() operations.
1396 static int WS2_recv( int fd, struct ws2_async *wsa )
1398 struct msghdr hdr;
1399 union generic_unix_sockaddr unix_sockaddr;
1400 int n;
1402 hdr.msg_name = NULL;
1404 if (wsa->addr)
1406 hdr.msg_namelen = sizeof(unix_sockaddr);
1407 hdr.msg_name = &unix_sockaddr;
1409 else
1410 hdr.msg_namelen = 0;
1412 hdr.msg_iov = wsa->iovec + wsa->first_iovec;
1413 hdr.msg_iovlen = wsa->n_iovecs - wsa->first_iovec;
1414 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1415 hdr.msg_accrights = NULL;
1416 hdr.msg_accrightslen = 0;
1417 #else
1418 hdr.msg_control = NULL;
1419 hdr.msg_controllen = 0;
1420 hdr.msg_flags = 0;
1421 #endif
1423 if ( (n = recvmsg(fd, &hdr, wsa->flags)) == -1 )
1424 return -1;
1426 /* if this socket is connected and lpFrom is not NULL, Linux doesn't give us
1427 * msg_name and msg_namelen from recvmsg, but it does set msg_namelen to zero.
1429 * quoting linux 2.6 net/ipv4/tcp.c:
1430 * "According to UNIX98, msg_name/msg_namelen are ignored
1431 * on connected socket. I was just happy when found this 8) --ANK"
1433 * likewise MSDN says that lpFrom and lpFromlen are ignored for
1434 * connection-oriented sockets, so don't try to update lpFrom.
1436 if (wsa->addr && hdr.msg_namelen)
1437 ws_sockaddr_u2ws( &unix_sockaddr.addr, wsa->addr, wsa->addrlen.ptr );
1439 return n;
1442 /***********************************************************************
1443 * WS2_async_recv (INTERNAL)
1445 * Handler for overlapped recv() operations.
1447 static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS status, void **apc)
1449 ws2_async* wsa = user;
1450 int result = 0, fd;
1452 switch (status)
1454 case STATUS_ALERTED:
1455 if ((status = wine_server_handle_to_fd( wsa->hSocket, FILE_READ_DATA, &fd, NULL ) ))
1456 break;
1458 result = WS2_recv( fd, wsa );
1459 wine_server_release_fd( wsa->hSocket, fd );
1460 if (result >= 0)
1462 status = STATUS_SUCCESS;
1463 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1465 else
1467 if (errno == EINTR || errno == EAGAIN)
1469 status = STATUS_PENDING;
1470 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1472 else
1474 result = 0;
1475 status = wsaErrStatus();
1478 break;
1480 if (status != STATUS_PENDING)
1482 iosb->u.Status = status;
1483 iosb->Information = result;
1484 *apc = ws2_async_apc;
1486 return status;
1489 /***********************************************************************
1490 * WS2_send (INTERNAL)
1492 * Workhorse for both synchronous and asynchronous send() operations.
1494 static int WS2_send( int fd, struct ws2_async *wsa )
1496 struct msghdr hdr;
1497 union generic_unix_sockaddr unix_addr;
1499 hdr.msg_name = NULL;
1500 hdr.msg_namelen = 0;
1502 if (wsa->addr)
1504 hdr.msg_name = &unix_addr;
1505 hdr.msg_namelen = ws_sockaddr_ws2u( wsa->addr, wsa->addrlen.val, &unix_addr );
1506 if ( !hdr.msg_namelen )
1508 errno = EFAULT;
1509 return -1;
1512 #if defined(HAVE_IPX) && defined(SOL_IPX)
1513 if(wsa->addr->sa_family == WS_AF_IPX)
1515 struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
1516 int val=0;
1517 unsigned int len=sizeof(int);
1519 /* The packet type is stored at the ipx socket level; At least the linux kernel seems
1520 * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
1521 * the packet type and then we can retrieve it using getsockopt. After that we can set the
1522 * ipx type in the sockaddr_opx structure with the stored value.
1524 if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
1525 uipx->sipx_type = val;
1527 #endif
1530 hdr.msg_iov = wsa->iovec + wsa->first_iovec;
1531 hdr.msg_iovlen = wsa->n_iovecs - wsa->first_iovec;
1532 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1533 hdr.msg_accrights = NULL;
1534 hdr.msg_accrightslen = 0;
1535 #else
1536 hdr.msg_control = NULL;
1537 hdr.msg_controllen = 0;
1538 hdr.msg_flags = 0;
1539 #endif
1541 return sendmsg(fd, &hdr, wsa->flags);
1544 /***********************************************************************
1545 * WS2_async_send (INTERNAL)
1547 * Handler for overlapped send() operations.
1549 static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS status, void **apc)
1551 ws2_async* wsa = user;
1552 int result = 0, fd;
1554 switch (status)
1556 case STATUS_ALERTED:
1557 if ((status = wine_server_handle_to_fd( wsa->hSocket, FILE_WRITE_DATA, &fd, NULL ) ))
1558 break;
1560 /* check to see if the data is ready (non-blocking) */
1561 result = WS2_send( fd, wsa );
1562 wine_server_release_fd( wsa->hSocket, fd );
1564 if (result >= 0)
1566 int totalLength = 0;
1567 unsigned int i;
1568 status = STATUS_SUCCESS;
1569 for (i = 0; i < wsa->n_iovecs; i++)
1570 totalLength += wsa->iovec[i].iov_len;
1571 if (result < totalLength)
1572 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1574 else
1576 if (errno == EINTR || errno == EAGAIN)
1578 status = STATUS_PENDING;
1579 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1581 else
1583 status = wsaErrStatus();
1584 result = 0;
1587 break;
1589 if (status != STATUS_PENDING)
1591 iosb->u.Status = status;
1592 iosb->Information = result;
1593 *apc = ws2_async_apc;
1595 return status;
1598 /***********************************************************************
1599 * WS2_async_shutdown (INTERNAL)
1601 * Handler for shutdown() operations on overlapped sockets.
1603 static NTSTATUS WS2_async_shutdown( void* user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc )
1605 ws2_async* wsa = user;
1606 int fd, err = 1;
1608 switch (status)
1610 case STATUS_ALERTED:
1611 if ((status = wine_server_handle_to_fd( wsa->hSocket, 0, &fd, NULL ) ))
1612 break;
1614 switch ( wsa->type )
1616 case ASYNC_TYPE_READ: err = shutdown( fd, 0 ); break;
1617 case ASYNC_TYPE_WRITE: err = shutdown( fd, 1 ); break;
1619 status = err ? wsaErrStatus() : STATUS_SUCCESS;
1620 wine_server_release_fd( wsa->hSocket, fd );
1621 break;
1623 iosb->u.Status = status;
1624 iosb->Information = 0;
1625 *apc = ws2_async_apc;
1626 return status;
1629 /***********************************************************************
1630 * WS2_async_accept_recv (INTERNAL)
1632 * This function is used to finish the acceptex read request. It is
1633 * needed to place the completion on the correct socket (listener).
1635 static NTSTATUS WINAPI WS2_async_accept_recv( void *arg, IO_STATUS_BLOCK *iosb, NTSTATUS status )
1637 void *apc;
1638 struct ws2_accept_async *wsa = arg;
1640 if (!wsa->read)
1642 if (!(wsa->read = HeapAlloc( GetProcessHeap(), 0,
1643 FIELD_OFFSET(struct ws2_async, iovec[1]) )))
1645 iosb->u.Status = STATUS_NO_MEMORY;
1646 iosb->Information = 0;
1647 goto finish;
1650 wsa->read->hSocket = SOCKET2HANDLE(wsa->s_accept);
1651 wsa->read->addr = NULL;
1652 wsa->read->addrlen.ptr = NULL;
1653 wsa->read->flags = 0;
1654 wsa->read->n_iovecs = 1;
1655 wsa->read->first_iovec = 0;
1657 wsa->read->iovec[0].iov_base = wsa->buf;
1658 wsa->read->iovec[0].iov_len = wsa->data_len;
1661 status = WS2_async_recv( wsa->read, iosb, status, &apc);
1662 if (status == STATUS_PENDING)
1663 return status;
1665 finish:
1666 if (wsa->user_overlapped->hEvent) SetEvent(wsa->user_overlapped->hEvent);
1667 if (wsa->cvalue) WS_AddCompletion( wsa->s_listen, wsa->cvalue, iosb->u.Status, iosb->Information );
1669 HeapFree( GetProcessHeap(), 0, wsa->read );
1670 HeapFree( GetProcessHeap(), 0, wsa );
1671 return status;
1674 /***********************************************************************
1675 * WS2_async_accept (INTERNAL)
1677 * This is the function called to satisfy the AcceptEx callback
1679 static NTSTATUS WINAPI WS2_async_accept( void *arg, IO_STATUS_BLOCK *iosb, NTSTATUS status )
1681 struct ws2_accept_async *wsa = arg;
1682 char *addr = ((char *) wsa->buf) + wsa->data_len;
1683 int len;
1685 TRACE("listen: %lx, accept: %lx, status %x\n", wsa->s_listen, wsa->s_accept, status);
1687 if (status == STATUS_HANDLES_CLOSED)
1688 status = STATUS_CANCELLED;
1690 if (status != STATUS_ALERTED)
1691 goto error;
1693 /* WS2 Spec says size param is extra 16 bytes long...what do we put in it? */
1694 len = wsa->local_len - sizeof(int);
1695 WS_getsockname(wsa->s_accept, (struct WS_sockaddr *)(addr + sizeof(int)),&len);
1696 *(int *)addr = len;
1698 addr += wsa->local_len;
1700 len = wsa->remote_len - sizeof(int);
1701 WS_getpeername(wsa->s_accept, (struct WS_sockaddr *)(addr + sizeof(int)),&len);
1702 *(int *)addr = len;
1704 if (!wsa->data_len)
1706 iosb->u.Status = STATUS_SUCCESS;
1707 iosb->Information = 0;
1708 goto finish;
1711 SERVER_START_REQ( register_async )
1713 req->type = ASYNC_TYPE_READ;
1714 req->async.handle = wine_server_obj_handle( SOCKET2HANDLE(wsa->s_accept) );
1715 req->async.callback = wine_server_client_ptr( WS2_async_accept_recv );
1716 req->async.iosb = wine_server_client_ptr( iosb );
1717 req->async.arg = wine_server_client_ptr( wsa );
1718 status = wine_server_call( req );
1720 SERVER_END_REQ;
1722 if (status != STATUS_PENDING)
1724 ERR("Could not register async read, %x\n", status);
1725 goto error;
1728 iosb->u.Status = STATUS_PENDING;
1729 iosb->Information = 0;
1731 return STATUS_SUCCESS;
1733 error:
1734 iosb->u.Status = status;
1735 iosb->Information = 0;
1737 finish:
1738 if (wsa->user_overlapped->hEvent) SetEvent(wsa->user_overlapped->hEvent);
1739 if (wsa->cvalue) WS_AddCompletion( wsa->s_listen, wsa->cvalue, iosb->u.Status, iosb->Information );
1741 HeapFree( GetProcessHeap(), 0, wsa );
1743 return status;
1746 /***********************************************************************
1747 * WS2_register_async_shutdown (INTERNAL)
1749 * Helper function for WS_shutdown() on overlapped sockets.
1751 static int WS2_register_async_shutdown( SOCKET s, int type )
1753 struct ws2_async *wsa;
1754 NTSTATUS status;
1756 TRACE("s %ld type %d\n", s, type);
1758 wsa = HeapAlloc( GetProcessHeap(), 0, sizeof(*wsa) );
1759 if ( !wsa )
1760 return WSAEFAULT;
1762 wsa->hSocket = SOCKET2HANDLE(s);
1763 wsa->type = type;
1764 wsa->completion_func = NULL;
1766 SERVER_START_REQ( register_async )
1768 req->type = type;
1769 req->async.handle = wine_server_obj_handle( wsa->hSocket );
1770 req->async.callback = wine_server_client_ptr( WS2_async_shutdown );
1771 req->async.iosb = wine_server_client_ptr( &wsa->local_iosb );
1772 req->async.arg = wine_server_client_ptr( wsa );
1773 req->async.cvalue = 0;
1774 status = wine_server_call( req );
1776 SERVER_END_REQ;
1778 if (status != STATUS_PENDING)
1780 HeapFree( GetProcessHeap(), 0, wsa );
1781 return NtStatusToWSAError( status );
1783 return 0;
1786 /***********************************************************************
1787 * accept (WS2_32.1)
1789 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1790 int *addrlen32)
1792 NTSTATUS status;
1793 SOCKET as;
1794 BOOL is_blocking;
1796 TRACE("socket %04lx\n", s );
1797 is_blocking = _is_blocking(s);
1799 do {
1800 /* try accepting first (if there is a deferred connection) */
1801 SERVER_START_REQ( accept_socket )
1803 req->lhandle = wine_server_obj_handle( SOCKET2HANDLE(s) );
1804 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1805 req->attributes = OBJ_INHERIT;
1806 status = wine_server_call( req );
1807 as = HANDLE2SOCKET( wine_server_ptr_handle( reply->handle ));
1809 SERVER_END_REQ;
1810 if (!status)
1812 if (addr) WS_getpeername(as, addr, addrlen32);
1813 return as;
1815 if (is_blocking && status == STATUS_CANT_WAIT)
1817 int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
1818 /* block here */
1819 do_block(fd, POLLIN, -1);
1820 _sync_sock_state(s); /* let wineserver notice connection */
1821 release_sock_fd( s, fd );
1823 } while (is_blocking && status == STATUS_CANT_WAIT);
1825 set_error(status);
1826 return INVALID_SOCKET;
1829 /***********************************************************************
1830 * bind (WS2_32.2)
1832 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1834 int fd = get_sock_fd( s, 0, NULL );
1835 int res = SOCKET_ERROR;
1837 TRACE("socket %04lx, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1839 if (fd != -1)
1841 if (!name || (name->sa_family && !supported_pf(name->sa_family)))
1843 SetLastError(WSAEAFNOSUPPORT);
1845 else
1847 union generic_unix_sockaddr uaddr;
1848 unsigned int uaddrlen = ws_sockaddr_ws2u(name, namelen, &uaddr);
1849 if (!uaddrlen)
1851 SetLastError(WSAEFAULT);
1853 else
1855 #ifdef IPV6_V6ONLY
1856 const struct sockaddr_in6 *in6 = (const struct sockaddr_in6*) &uaddr;
1857 if (name->sa_family == WS_AF_INET6 &&
1858 !memcmp(&in6->sin6_addr, &in6addr_any, sizeof(struct in6_addr)))
1860 int enable = 1;
1861 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(enable)) == -1)
1863 release_sock_fd( s, fd );
1864 SetLastError(WSAEAFNOSUPPORT);
1865 return SOCKET_ERROR;
1868 #endif
1869 if (name->sa_family == WS_AF_INET)
1871 struct sockaddr_in *in4 = (struct sockaddr_in*) &uaddr;
1872 if (memcmp(&in4->sin_addr, magic_loopback_addr, 4) == 0)
1874 /* Trying to bind to the default host interface, using
1875 * INADDR_ANY instead*/
1876 WARN("Trying to bind to magic IP address, using "
1877 "INADDR_ANY instead.\n");
1878 in4->sin_addr.s_addr = htonl(WS_INADDR_ANY);
1881 if (bind(fd, &uaddr.addr, uaddrlen) < 0)
1883 int loc_errno = errno;
1884 WARN("\tfailure - errno = %i\n", errno);
1885 errno = loc_errno;
1886 switch (errno)
1888 case EBADF:
1889 SetLastError(WSAENOTSOCK);
1890 break;
1891 case EADDRNOTAVAIL:
1892 SetLastError(WSAEINVAL);
1893 break;
1894 default:
1895 SetLastError(wsaErrno());
1896 break;
1899 else
1901 res=0; /* success */
1905 release_sock_fd( s, fd );
1907 return res;
1910 /***********************************************************************
1911 * closesocket (WS2_32.3)
1913 int WINAPI WS_closesocket(SOCKET s)
1915 TRACE("socket %04lx\n", s);
1916 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1917 return SOCKET_ERROR;
1920 /***********************************************************************
1921 * connect (WS2_32.4)
1923 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1925 int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
1927 TRACE("socket %04lx, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1929 if (fd != -1)
1931 union generic_unix_sockaddr uaddr;
1932 unsigned int uaddrlen = ws_sockaddr_ws2u(name, namelen, &uaddr);
1934 if (!uaddrlen)
1936 SetLastError(WSAEFAULT);
1938 else
1940 if (name->sa_family == WS_AF_INET)
1942 struct sockaddr_in *in4 = (struct sockaddr_in*) &uaddr;
1943 if (memcmp(&in4->sin_addr, magic_loopback_addr, 4) == 0)
1945 /* Trying to connect to magic replace-loopback address,
1946 * assuming we really want to connect to localhost */
1947 TRACE("Trying to connect to magic IP address, using "
1948 "INADDR_LOOPBACK instead.\n");
1949 in4->sin_addr.s_addr = htonl(WS_INADDR_LOOPBACK);
1953 if (connect(fd, &uaddr.addr, uaddrlen) == 0)
1954 goto connect_success;
1957 if (errno == EINPROGRESS)
1959 /* tell wineserver that a connection is in progress */
1960 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1961 FD_CONNECT|FD_READ|FD_WRITE,
1962 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1963 if (_is_blocking(s))
1965 int result;
1966 /* block here */
1967 do_block(fd, POLLIN | POLLOUT, -1);
1968 _sync_sock_state(s); /* let wineserver notice connection */
1969 /* retrieve any error codes from it */
1970 result = _get_sock_error(s, FD_CONNECT_BIT);
1971 if (result)
1972 SetLastError(NtStatusToWSAError(result));
1973 else
1975 goto connect_success;
1978 else
1980 SetLastError(WSAEWOULDBLOCK);
1983 else
1985 SetLastError(wsaErrno());
1987 release_sock_fd( s, fd );
1989 return SOCKET_ERROR;
1991 connect_success:
1992 release_sock_fd( s, fd );
1993 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1994 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1995 FD_CONNECT|FD_WINE_LISTENING);
1996 return 0;
1999 /***********************************************************************
2000 * WSAConnect (WS2_32.30)
2002 int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
2003 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
2004 LPQOS lpSQOS, LPQOS lpGQOS )
2006 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
2007 FIXME("unsupported parameters!\n");
2008 return WS_connect( s, name, namelen );
2012 /***********************************************************************
2013 * getpeername (WS2_32.5)
2015 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
2017 int fd;
2018 int res;
2020 TRACE("socket: %04lx, ptr %p, len %08x\n", s, name, namelen?*namelen:0);
2022 fd = get_sock_fd( s, 0, NULL );
2023 res = SOCKET_ERROR;
2025 if (fd != -1)
2027 union generic_unix_sockaddr uaddr;
2028 unsigned int uaddrlen = sizeof(uaddr);
2030 if (getpeername(fd, &uaddr.addr, &uaddrlen) == 0)
2032 if (!name || !namelen)
2033 SetLastError(WSAEFAULT);
2034 else if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
2035 /* The buffer was too small */
2036 SetLastError(WSAEFAULT);
2037 else
2038 res = 0;
2040 else
2041 SetLastError(wsaErrno());
2042 release_sock_fd( s, fd );
2044 return res;
2047 /***********************************************************************
2048 * getsockname (WS2_32.6)
2050 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
2052 int fd;
2053 int res;
2055 TRACE("socket: %04lx, ptr %p, len %8x\n", s, name, *namelen);
2057 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
2058 if( (name == NULL) || (namelen == NULL) )
2060 SetLastError( WSAEFAULT );
2061 return SOCKET_ERROR;
2064 fd = get_sock_fd( s, 0, NULL );
2065 res = SOCKET_ERROR;
2067 if (fd != -1)
2069 union generic_unix_sockaddr uaddr;
2070 unsigned int uaddrlen = sizeof(uaddr);
2072 if (getsockname(fd, &uaddr.addr, &uaddrlen) != 0)
2074 SetLastError(wsaErrno());
2076 else if (!is_sockaddr_bound(&uaddr.addr, uaddrlen))
2078 SetLastError(WSAEINVAL);
2080 else if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
2082 /* The buffer was too small */
2083 SetLastError(WSAEFAULT);
2085 else
2087 res=0;
2089 release_sock_fd( s, fd );
2091 return res;
2094 /***********************************************************************
2095 * getsockopt (WS2_32.7)
2097 INT WINAPI WS_getsockopt(SOCKET s, INT level,
2098 INT optname, char *optval, INT *optlen)
2100 int fd;
2101 INT ret = 0;
2103 TRACE("socket: %04lx, level 0x%x, name 0x%x, ptr %p, len %d\n",
2104 s, level, optname, optval, *optlen);
2106 switch(level)
2108 case WS_SOL_SOCKET:
2110 switch(optname)
2112 /* Handle common cases. The special cases are below, sorted
2113 * alphabetically */
2114 case WS_SO_ACCEPTCONN:
2115 case WS_SO_BROADCAST:
2116 case WS_SO_DEBUG:
2117 case WS_SO_ERROR:
2118 case WS_SO_KEEPALIVE:
2119 case WS_SO_OOBINLINE:
2120 case WS_SO_RCVBUF:
2121 case WS_SO_REUSEADDR:
2122 case WS_SO_SNDBUF:
2123 case WS_SO_TYPE:
2124 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
2125 return SOCKET_ERROR;
2126 convert_sockopt(&level, &optname);
2127 if (getsockopt(fd, level, optname, optval, (unsigned int *)optlen) != 0 )
2129 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2130 ret = SOCKET_ERROR;
2132 release_sock_fd( s, fd );
2133 return ret;
2135 case WS_SO_DONTLINGER:
2137 struct linger lingval;
2138 unsigned int len = sizeof(struct linger);
2140 if (!optlen || *optlen < sizeof(BOOL)|| !optval)
2142 SetLastError(WSAEFAULT);
2143 return SOCKET_ERROR;
2145 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
2146 return SOCKET_ERROR;
2148 if (getsockopt(fd, SOL_SOCKET, SO_LINGER, &lingval, &len) != 0 )
2150 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2151 ret = SOCKET_ERROR;
2153 else
2155 *(BOOL *)optval = (lingval.l_onoff) ? FALSE : TRUE;
2156 *optlen = sizeof(BOOL);
2159 release_sock_fd( s, fd );
2160 return ret;
2163 /* As mentioned in setsockopt, Windows ignores this, so we
2164 * always return true here */
2165 case WS_SO_DONTROUTE:
2166 if (!optlen || *optlen < sizeof(BOOL) || !optval)
2168 SetLastError(WSAEFAULT);
2169 return SOCKET_ERROR;
2171 *(BOOL *)optval = TRUE;
2172 *optlen = sizeof(BOOL);
2173 return 0;
2175 case WS_SO_LINGER:
2177 struct linger lingval;
2178 unsigned int len = sizeof(struct linger);
2180 /* struct linger and LINGER have different sizes */
2181 if (!optlen || *optlen < sizeof(LINGER) || !optval)
2183 SetLastError(WSAEFAULT);
2184 return SOCKET_ERROR;
2186 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
2187 return SOCKET_ERROR;
2189 if (getsockopt(fd, SOL_SOCKET, SO_LINGER, &lingval, &len) != 0 )
2191 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2192 ret = SOCKET_ERROR;
2194 else
2196 ((LINGER *)optval)->l_onoff = lingval.l_onoff;
2197 ((LINGER *)optval)->l_linger = lingval.l_linger;
2198 *optlen = sizeof(struct linger);
2201 release_sock_fd( s, fd );
2202 return ret;
2205 case WS_SO_MAX_MSG_SIZE:
2206 if (!optlen || *optlen < sizeof(int) || !optval)
2208 SetLastError(WSAEFAULT);
2209 return SOCKET_ERROR;
2211 TRACE("getting global SO_MAX_MSG_SIZE = 65507\n");
2212 *(int *)optval = 65507;
2213 *optlen = sizeof(int);
2214 return 0;
2216 /* SO_OPENTYPE does not require a valid socket handle. */
2217 case WS_SO_OPENTYPE:
2218 if (!optlen || *optlen < sizeof(int) || !optval)
2220 SetLastError(WSAEFAULT);
2221 return SOCKET_ERROR;
2223 *(int *)optval = get_per_thread_data()->opentype;
2224 *optlen = sizeof(int);
2225 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
2226 return 0;
2228 #ifdef SO_RCVTIMEO
2229 case WS_SO_RCVTIMEO:
2230 #endif
2231 #ifdef SO_SNDTIMEO
2232 case WS_SO_SNDTIMEO:
2233 #endif
2234 #if defined(SO_RCVTIMEO) || defined(SO_SNDTIMEO)
2236 struct timeval tv;
2237 unsigned int len = sizeof(struct timeval);
2239 if (!optlen || *optlen < sizeof(int)|| !optval)
2241 SetLastError(WSAEFAULT);
2242 return SOCKET_ERROR;
2244 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
2245 return SOCKET_ERROR;
2247 convert_sockopt(&level, &optname);
2248 if (getsockopt(fd, level, optname, &tv, &len) != 0 )
2250 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2251 ret = SOCKET_ERROR;
2253 else
2255 *(int *)optval = tv.tv_sec * 1000 + tv.tv_usec / 1000;
2256 *optlen = sizeof(int);
2259 release_sock_fd( s, fd );
2260 return ret;
2262 #endif
2263 default:
2264 TRACE("Unknown SOL_SOCKET optname: 0x%08x\n", optname);
2265 SetLastError(WSAENOPROTOOPT);
2266 return SOCKET_ERROR;
2267 } /* end switch(optname) */
2268 }/* end case WS_SOL_SOCKET */
2269 #ifdef HAVE_IPX
2270 case NSPROTO_IPX:
2272 struct WS_sockaddr_ipx addr;
2273 IPX_ADDRESS_DATA *data;
2274 int namelen;
2275 switch(optname)
2277 case IPX_PTYPE:
2278 if ((fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR;
2279 #ifdef SOL_IPX
2280 if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, (unsigned int*)optlen) == -1)
2282 ret = SOCKET_ERROR;
2284 #else
2286 struct ipx val;
2287 socklen_t len=sizeof(struct ipx);
2288 if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
2289 ret = SOCKET_ERROR;
2290 else
2291 *optval = (int)val.ipx_pt;
2293 #endif
2294 TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
2295 release_sock_fd( s, fd );
2296 return ret;
2298 case IPX_ADDRESS:
2300 * On a Win2000 system with one network card there are usually
2301 * three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
2302 * Using this call you can then retrieve info about this all.
2303 * In case of Linux it is a bit different. Usually you have
2304 * only "one" device active and further it is not possible to
2305 * query things like the linkspeed.
2307 FIXME("IPX_ADDRESS\n");
2308 namelen = sizeof(struct WS_sockaddr_ipx);
2309 memset(&addr, 0, sizeof(struct WS_sockaddr_ipx));
2310 WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
2312 data = (IPX_ADDRESS_DATA*)optval;
2313 memcpy(data->nodenum,addr.sa_nodenum,sizeof(data->nodenum));
2314 memcpy(data->netnum,addr.sa_netnum,sizeof(data->netnum));
2315 data->adapternum = 0;
2316 data->wan = FALSE; /* We are not on a wan for now .. */
2317 data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
2318 data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
2319 data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit;
2320 * note 1MB = 1000kB in this case */
2321 return 0;
2323 case IPX_MAX_ADAPTER_NUM:
2324 FIXME("IPX_MAX_ADAPTER_NUM\n");
2325 *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
2326 return 0;
2328 default:
2329 FIXME("IPX optname:%x\n", optname);
2330 return SOCKET_ERROR;
2331 }/* end switch(optname) */
2332 } /* end case NSPROTO_IPX */
2333 #endif
2335 #ifdef HAVE_IRDA
2336 case WS_SOL_IRLMP:
2337 switch(optname)
2339 case WS_IRLMP_ENUMDEVICES:
2341 static const int MAX_IRDA_DEVICES = 10;
2342 char buf[sizeof(struct irda_device_list) +
2343 (MAX_IRDA_DEVICES - 1) * sizeof(struct irda_device_info)];
2344 int fd, res;
2345 socklen_t len = sizeof(buf);
2347 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
2348 return SOCKET_ERROR;
2349 res = getsockopt( fd, SOL_IRLMP, IRLMP_ENUMDEVICES, buf, &len );
2350 if (res < 0)
2352 SetLastError(wsaErrno());
2353 return SOCKET_ERROR;
2355 else
2357 struct irda_device_list *src = (struct irda_device_list *)buf;
2358 DEVICELIST *dst = (DEVICELIST *)optval;
2359 INT needed = sizeof(DEVICELIST), i;
2361 if (src->len > 0)
2362 needed += (src->len - 1) * sizeof(IRDA_DEVICE_INFO);
2363 if (*optlen < needed)
2365 SetLastError(WSAEFAULT);
2366 return SOCKET_ERROR;
2368 *optlen = needed;
2369 TRACE("IRLMP_ENUMDEVICES: %d devices found:\n", src->len);
2370 dst->numDevice = src->len;
2371 for (i = 0; i < src->len; i++)
2373 TRACE("saddr = %08x, daddr = %08x, info = %s, hints = %02x%02x\n",
2374 src->dev[i].saddr, src->dev[i].daddr,
2375 src->dev[i].info, src->dev[i].hints[0],
2376 src->dev[i].hints[1]);
2377 memcpy( dst->Device[i].irdaDeviceID,
2378 &src->dev[i].daddr,
2379 sizeof(dst->Device[i].irdaDeviceID) ) ;
2380 memcpy( dst->Device[i].irdaDeviceName,
2381 &src->dev[i].info,
2382 sizeof(dst->Device[i].irdaDeviceName) ) ;
2383 memcpy( &dst->Device[i].irdaDeviceHints1,
2384 &src->dev[i].hints[0],
2385 sizeof(dst->Device[i].irdaDeviceHints1) ) ;
2386 memcpy( &dst->Device[i].irdaDeviceHints2,
2387 &src->dev[i].hints[1],
2388 sizeof(dst->Device[i].irdaDeviceHints2) ) ;
2389 dst->Device[i].irdaCharSet = src->dev[i].charset;
2391 return 0;
2394 default:
2395 FIXME("IrDA optname:0x%x\n", optname);
2396 return SOCKET_ERROR;
2398 break; /* case WS_SOL_IRLMP */
2399 #endif
2401 /* Levels WS_IPPROTO_TCP and WS_IPPROTO_IP convert directly */
2402 case WS_IPPROTO_TCP:
2403 switch(optname)
2405 case WS_TCP_NODELAY:
2406 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
2407 return SOCKET_ERROR;
2408 convert_sockopt(&level, &optname);
2409 if (getsockopt(fd, level, optname, optval, (unsigned int *)optlen) != 0 )
2411 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2412 ret = SOCKET_ERROR;
2414 release_sock_fd( s, fd );
2415 return ret;
2417 FIXME("Unknown IPPROTO_TCP optname 0x%08x\n", optname);
2418 return SOCKET_ERROR;
2420 case WS_IPPROTO_IP:
2421 switch(optname)
2423 case WS_IP_ADD_MEMBERSHIP:
2424 case WS_IP_DROP_MEMBERSHIP:
2425 #ifdef IP_HDRINCL
2426 case WS_IP_HDRINCL:
2427 #endif
2428 case WS_IP_MULTICAST_IF:
2429 case WS_IP_MULTICAST_LOOP:
2430 case WS_IP_MULTICAST_TTL:
2431 case WS_IP_OPTIONS:
2432 case WS_IP_TOS:
2433 case WS_IP_TTL:
2434 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
2435 return SOCKET_ERROR;
2436 convert_sockopt(&level, &optname);
2437 if (getsockopt(fd, level, optname, optval, (unsigned int *)optlen) != 0 )
2439 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2440 ret = SOCKET_ERROR;
2442 release_sock_fd( s, fd );
2443 return ret;
2444 case WS_IP_DONTFRAGMENT:
2445 FIXME("WS_IP_DONTFRAGMENT is always false!\n");
2446 *(BOOL*)optval = FALSE;
2447 return 0;
2449 FIXME("Unknown IPPROTO_IP optname 0x%08x\n", optname);
2450 return SOCKET_ERROR;
2452 case WS_IPPROTO_IPV6:
2453 switch(optname)
2455 #ifdef IPV6_ADD_MEMBERSHIP
2456 case WS_IPV6_ADD_MEMBERSHIP:
2457 #endif
2458 #ifdef IPV6_DROP_MEMBERSHIP
2459 case WS_IPV6_DROP_MEMBERSHIP:
2460 #endif
2461 case WS_IPV6_MULTICAST_IF:
2462 case WS_IPV6_MULTICAST_HOPS:
2463 case WS_IPV6_MULTICAST_LOOP:
2464 case WS_IPV6_UNICAST_HOPS:
2465 case WS_IPV6_V6ONLY:
2466 if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
2467 return SOCKET_ERROR;
2468 convert_sockopt(&level, &optname);
2469 if (getsockopt(fd, level, optname, optval, (unsigned int *)optlen) != 0 )
2471 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2472 ret = SOCKET_ERROR;
2474 release_sock_fd( s, fd );
2475 return ret;
2476 case WS_IPV6_DONTFRAG:
2477 FIXME("WS_IPV6_DONTFRAG is always false!\n");
2478 *(BOOL*)optval = FALSE;
2479 return 0;
2481 FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname);
2482 return SOCKET_ERROR;
2484 default:
2485 WARN("Unknown level: 0x%08x\n", level);
2486 SetLastError(WSAEINVAL);
2487 return SOCKET_ERROR;
2488 } /* end switch(level) */
2491 /***********************************************************************
2492 * htonl (WS2_32.8)
2494 WS_u_long WINAPI WS_htonl(WS_u_long hostlong)
2496 return htonl(hostlong);
2500 /***********************************************************************
2501 * htons (WS2_32.9)
2503 WS_u_short WINAPI WS_htons(WS_u_short hostshort)
2505 return htons(hostshort);
2508 /***********************************************************************
2509 * WSAHtonl (WS2_32.46)
2510 * From MSDN description of error codes, this function should also
2511 * check if WinSock has been initialized and the socket is a valid
2512 * socket. But why? This function only translates a host byte order
2513 * u_long into a network byte order u_long...
2515 int WINAPI WSAHtonl(SOCKET s, WS_u_long hostlong, WS_u_long *lpnetlong)
2517 if (lpnetlong)
2519 *lpnetlong = htonl(hostlong);
2520 return 0;
2522 WSASetLastError(WSAEFAULT);
2523 return SOCKET_ERROR;
2526 /***********************************************************************
2527 * WSAHtons (WS2_32.47)
2528 * From MSDN description of error codes, this function should also
2529 * check if WinSock has been initialized and the socket is a valid
2530 * socket. But why? This function only translates a host byte order
2531 * u_short into a network byte order u_short...
2533 int WINAPI WSAHtons(SOCKET s, WS_u_short hostshort, WS_u_short *lpnetshort)
2536 if (lpnetshort)
2538 *lpnetshort = htons(hostshort);
2539 return 0;
2541 WSASetLastError(WSAEFAULT);
2542 return SOCKET_ERROR;
2546 /***********************************************************************
2547 * inet_addr (WS2_32.11)
2549 WS_u_long WINAPI WS_inet_addr(const char *cp)
2551 if (!cp) return INADDR_NONE;
2552 return inet_addr(cp);
2556 /***********************************************************************
2557 * ntohl (WS2_32.14)
2559 WS_u_long WINAPI WS_ntohl(WS_u_long netlong)
2561 return ntohl(netlong);
2565 /***********************************************************************
2566 * ntohs (WS2_32.15)
2568 WS_u_short WINAPI WS_ntohs(WS_u_short netshort)
2570 return ntohs(netshort);
2574 /***********************************************************************
2575 * inet_ntoa (WS2_32.12)
2577 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
2579 /* use "buffer for dummies" here because some applications have a
2580 * propensity to decode addresses in ws_hostent structure without
2581 * saving them first...
2583 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
2585 char* s = inet_ntoa(*((struct in_addr*)&in));
2586 if( s )
2588 strcpy(dbuffer, s);
2589 return dbuffer;
2591 SetLastError(wsaErrno());
2592 return NULL;
2595 /**********************************************************************
2596 * WSAIoctl (WS2_32.50)
2599 INT WINAPI WSAIoctl(SOCKET s,
2600 DWORD dwIoControlCode,
2601 LPVOID lpvInBuffer,
2602 DWORD cbInBuffer,
2603 LPVOID lpbOutBuffer,
2604 DWORD cbOutBuffer,
2605 LPDWORD lpcbBytesReturned,
2606 LPWSAOVERLAPPED lpOverlapped,
2607 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
2609 TRACE("%ld, 0x%08x, %p, %d, %p, %d, %p, %p, %p\n",
2610 s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpbOutBuffer,
2611 cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
2613 switch( dwIoControlCode )
2615 case WS_FIONBIO:
2616 if (cbInBuffer != sizeof(WS_u_long)) {
2617 WSASetLastError(WSAEFAULT);
2618 return SOCKET_ERROR;
2620 return WS_ioctlsocket( s, WS_FIONBIO, lpvInBuffer);
2622 case WS_FIONREAD:
2623 if (cbOutBuffer != sizeof(WS_u_long)) {
2624 WSASetLastError(WSAEFAULT);
2625 return SOCKET_ERROR;
2627 return WS_ioctlsocket( s, WS_FIONREAD, lpbOutBuffer);
2629 case WS_SIO_GET_INTERFACE_LIST:
2631 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
2632 DWORD size, numInt, apiReturn;
2633 int fd;
2635 TRACE("-> SIO_GET_INTERFACE_LIST request\n");
2637 if (!lpbOutBuffer)
2639 WSASetLastError(WSAEFAULT);
2640 return SOCKET_ERROR;
2642 if (!lpcbBytesReturned)
2644 WSASetLastError(WSAEFAULT);
2645 return SOCKET_ERROR;
2648 fd = get_sock_fd( s, 0, NULL );
2649 if (fd == -1) return SOCKET_ERROR;
2651 apiReturn = GetAdaptersInfo(NULL, &size);
2652 if (apiReturn == ERROR_NO_DATA)
2654 numInt = 0;
2656 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
2658 PIP_ADAPTER_INFO table = HeapAlloc(GetProcessHeap(),0,size);
2660 if (table)
2662 if (GetAdaptersInfo(table, &size) == NO_ERROR)
2664 PIP_ADAPTER_INFO ptr;
2666 if (size*sizeof(INTERFACE_INFO)/sizeof(IP_ADAPTER_INFO) > cbOutBuffer)
2668 WARN("Buffer too small = %u, cbOutBuffer = %u\n", size, cbOutBuffer);
2669 HeapFree(GetProcessHeap(),0,table);
2670 release_sock_fd( s, fd );
2671 WSASetLastError(WSAEFAULT);
2672 return SOCKET_ERROR;
2674 for (ptr = table, numInt = 0; ptr;
2675 ptr = ptr->Next, intArray++, numInt++)
2677 unsigned int addr, mask, bcast;
2678 struct ifreq ifInfo;
2680 /* Socket Status Flags */
2681 lstrcpynA(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
2682 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2684 ERR("Error obtaining status flags for socket!\n");
2685 HeapFree(GetProcessHeap(),0,table);
2686 release_sock_fd( s, fd );
2687 WSASetLastError(WSAEINVAL);
2688 return SOCKET_ERROR;
2690 else
2692 /* set flags; the values of IFF_* are not the same
2693 under Linux and Windows, therefore must generate
2694 new flags */
2695 intArray->iiFlags = 0;
2696 if (ifInfo.ifr_flags & IFF_BROADCAST)
2697 intArray->iiFlags |= WS_IFF_BROADCAST;
2698 #ifdef IFF_POINTOPOINT
2699 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
2700 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
2701 #endif
2702 if (ifInfo.ifr_flags & IFF_LOOPBACK)
2703 intArray->iiFlags |= WS_IFF_LOOPBACK;
2704 if (ifInfo.ifr_flags & IFF_UP)
2705 intArray->iiFlags |= WS_IFF_UP;
2706 if (ifInfo.ifr_flags & IFF_MULTICAST)
2707 intArray->iiFlags |= WS_IFF_MULTICAST;
2710 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
2711 mask = inet_addr(ptr->IpAddressList.IpMask.String);
2712 bcast = addr | ~mask;
2713 intArray->iiAddress.AddressIn.sin_family = AF_INET;
2714 intArray->iiAddress.AddressIn.sin_port = 0;
2715 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2716 addr;
2717 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2718 intArray->iiNetmask.AddressIn.sin_port = 0;
2719 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2720 mask;
2721 intArray->iiBroadcastAddress.AddressIn.sin_family =
2722 AF_INET;
2723 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2724 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2725 WS_s_addr = bcast;
2728 else
2730 ERR("Unable to get interface table!\n");
2731 release_sock_fd( s, fd );
2732 HeapFree(GetProcessHeap(),0,table);
2733 WSASetLastError(WSAEINVAL);
2734 return SOCKET_ERROR;
2736 HeapFree(GetProcessHeap(),0,table);
2738 else
2740 release_sock_fd( s, fd );
2741 WSASetLastError(WSAEINVAL);
2742 return SOCKET_ERROR;
2745 else
2747 ERR("Unable to get interface table!\n");
2748 release_sock_fd( s, fd );
2749 WSASetLastError(WSAEINVAL);
2750 return SOCKET_ERROR;
2752 /* Calculate the size of the array being returned */
2753 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2754 release_sock_fd( s, fd );
2755 break;
2758 case WS_SIO_ADDRESS_LIST_CHANGE:
2759 FIXME("-> SIO_ADDRESS_LIST_CHANGE request: stub\n");
2760 /* FIXME: error and return code depend on whether socket was created
2761 * with WSA_FLAG_OVERLAPPED, but there is no easy way to get this */
2762 break;
2764 case WS_SIO_ADDRESS_LIST_QUERY:
2766 DWORD size;
2768 TRACE("-> SIO_ADDRESS_LIST_QUERY request\n");
2770 if (!lpcbBytesReturned)
2772 WSASetLastError(WSAEFAULT);
2773 return SOCKET_ERROR;
2776 if (GetAdaptersInfo(NULL, &size) == ERROR_BUFFER_OVERFLOW)
2778 IP_ADAPTER_INFO *p, *table = HeapAlloc(GetProcessHeap(), 0, size);
2779 DWORD need, num;
2781 if (!table || GetAdaptersInfo(table, &size))
2783 HeapFree(GetProcessHeap(), 0, table);
2784 WSASetLastError(WSAEINVAL);
2785 return SOCKET_ERROR;
2788 for (p = table, num = 0; p; p = p->Next)
2789 if (p->IpAddressList.IpAddress.String[0]) num++;
2791 need = sizeof(SOCKET_ADDRESS_LIST) + sizeof(SOCKET_ADDRESS) * (num - 1);
2792 need += sizeof(SOCKADDR) * num;
2793 *lpcbBytesReturned = need;
2795 if (need > cbOutBuffer)
2797 HeapFree(GetProcessHeap(), 0, table);
2798 WSASetLastError(WSAEFAULT);
2799 return SOCKET_ERROR;
2802 if (lpbOutBuffer)
2804 unsigned int i;
2805 SOCKET_ADDRESS *sa;
2806 SOCKET_ADDRESS_LIST *sa_list = (SOCKET_ADDRESS_LIST *)lpbOutBuffer;
2807 SOCKADDR_IN *sockaddr;
2809 sa = sa_list->Address;
2810 sockaddr = (SOCKADDR_IN *)((char *)sa + num * sizeof(SOCKET_ADDRESS));
2811 sa_list->iAddressCount = num;
2813 for (p = table, i = 0; p; p = p->Next)
2815 if (!p->IpAddressList.IpAddress.String[0]) continue;
2817 sa[i].lpSockaddr = (SOCKADDR *)&sockaddr[i];
2818 sa[i].iSockaddrLength = sizeof(SOCKADDR);
2820 sockaddr[i].sin_family = AF_INET;
2821 sockaddr[i].sin_port = 0;
2822 sockaddr[i].sin_addr.WS_s_addr = inet_addr(p->IpAddressList.IpAddress.String);
2823 i++;
2827 HeapFree(GetProcessHeap(), 0, table);
2828 return 0;
2830 else
2832 WARN("unable to get IP address list\n");
2833 WSASetLastError(WSAEINVAL);
2834 return SOCKET_ERROR;
2837 case WS_SIO_FLUSH:
2838 FIXME("SIO_FLUSH: stub.\n");
2839 break;
2841 case WS_SIO_GET_EXTENSION_FUNCTION_POINTER:
2843 static const GUID connectex_guid = WSAID_CONNECTEX;
2844 static const GUID disconnectex_guid = WSAID_DISCONNECTEX;
2845 static const GUID acceptex_guid = WSAID_ACCEPTEX;
2846 static const GUID getaccepexsockaddrs_guid = WSAID_GETACCEPTEXSOCKADDRS;
2847 static const GUID transmitfile_guid = WSAID_TRANSMITFILE;
2848 static const GUID transmitpackets_guid = WSAID_TRANSMITPACKETS;
2849 static const GUID wsarecvmsg_guid = WSAID_WSARECVMSG;
2850 static const GUID wsasendmsg_guid = WSAID_WSASENDMSG;
2852 if ( IsEqualGUID(&connectex_guid, lpvInBuffer) )
2854 FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER: unimplemented ConnectEx\n");
2856 else if ( IsEqualGUID(&disconnectex_guid, lpvInBuffer) )
2858 FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER: unimplemented DisconnectEx\n");
2860 else if ( IsEqualGUID(&acceptex_guid, lpvInBuffer) )
2862 *(LPFN_ACCEPTEX *)lpbOutBuffer = AcceptEx;
2863 WSASetLastError(STATUS_SUCCESS);
2864 return STATUS_SUCCESS;
2866 else if ( IsEqualGUID(&getaccepexsockaddrs_guid, lpvInBuffer) )
2868 *(LPFN_GETACCEPTEXSOCKADDRS *)lpbOutBuffer = GetAcceptExSockaddrs;
2869 WSASetLastError(STATUS_SUCCESS);
2870 return STATUS_SUCCESS;
2872 else if ( IsEqualGUID(&transmitfile_guid, lpvInBuffer) )
2874 FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER: unimplemented TransmitFile\n");
2876 else if ( IsEqualGUID(&transmitpackets_guid, lpvInBuffer) )
2878 FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER: unimplemented TransmitPackets\n");
2880 else if ( IsEqualGUID(&wsarecvmsg_guid, lpvInBuffer) )
2882 FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER: unimplemented WSARecvMsg\n");
2884 else if ( IsEqualGUID(&wsasendmsg_guid, lpvInBuffer) )
2886 FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER: unimplemented WSASendMsg\n");
2888 else
2889 FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER %s: stub\n", debugstr_guid(lpvInBuffer));
2891 WSASetLastError(WSAEOPNOTSUPP);
2892 return SOCKET_ERROR;
2895 case WS_SIO_KEEPALIVE_VALS:
2897 int fd;
2898 struct tcp_keepalive *k = lpvInBuffer;
2899 int keepalive = k->onoff ? 1 : 0;
2900 int keepidle = k->keepalivetime / 1000;
2901 int keepintvl = k->keepaliveinterval / 1000;
2903 if (!lpvInBuffer)
2905 WSASetLastError(WSAEINVAL);
2906 return SOCKET_ERROR;
2909 TRACE("onoff: %d, keepalivetime: %d, keepaliveinterval: %d\n", keepalive, keepidle, keepintvl);
2911 fd = get_sock_fd(s, 0, NULL);
2912 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(int)) == -1)
2914 release_sock_fd(s, fd);
2915 WSASetLastError(WSAEINVAL);
2916 return SOCKET_ERROR;
2918 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
2919 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, sizeof(int)) == -1)
2921 release_sock_fd(s, fd);
2922 WSASetLastError(WSAEINVAL);
2923 return SOCKET_ERROR;
2925 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof(int)) == -1)
2927 release_sock_fd(s, fd);
2928 WSASetLastError(WSAEINVAL);
2929 return SOCKET_ERROR;
2931 #else
2932 FIXME("ignoring keepalive interval and timeout\n");
2933 #endif
2935 release_sock_fd(s, fd);
2936 break;
2938 case WS_SIO_UDP_CONNRESET:
2939 FIXME("WS_SIO_UDP_CONNRESET stub\n");
2940 break;
2941 default:
2942 FIXME("unsupported WS_IOCTL cmd (%08x)\n", dwIoControlCode);
2943 WSASetLastError(WSAEOPNOTSUPP);
2944 return SOCKET_ERROR;
2947 return 0;
2951 /***********************************************************************
2952 * ioctlsocket (WS2_32.10)
2954 int WINAPI WS_ioctlsocket(SOCKET s, LONG cmd, WS_u_long *argp)
2956 int fd;
2957 LONG newcmd = cmd;
2959 TRACE("socket %04lx, cmd %08x, ptr %p\n", s, cmd, argp);
2960 /* broken apps like defcon pass the argp value directly instead of a pointer to it */
2961 if(IS_INTRESOURCE(argp))
2963 SetLastError(WSAEFAULT);
2964 return SOCKET_ERROR;
2967 switch( cmd )
2969 case WS_FIONREAD:
2970 newcmd=FIONREAD;
2971 break;
2973 case WS_FIONBIO:
2974 if( _get_sock_mask(s) )
2976 /* AsyncSelect()'ed sockets are always nonblocking */
2977 if (*argp) return 0;
2978 SetLastError(WSAEINVAL);
2979 return SOCKET_ERROR;
2981 if (*argp)
2982 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2983 else
2984 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2985 return 0;
2987 case WS_SIOCATMARK:
2988 newcmd=SIOCATMARK;
2989 break;
2991 case WS_FIOASYNC:
2992 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2993 SetLastError(WSAEINVAL);
2994 return SOCKET_ERROR;
2996 case SIOCGIFBRDADDR:
2997 case SIOCGIFNETMASK:
2998 case SIOCGIFADDR:
2999 /* These don't need any special handling. They are used by
3000 WsControl, and are here to suppress an unnecessary warning. */
3001 break;
3003 default:
3004 /* Netscape tries hard to use bogus ioctl 0x667e */
3005 /* FIXME: 0x667e above is ('f' << 8) | 126, and is a low word of
3006 * FIONBIO (_IOW('f', 126, u_long)), how that should be handled?
3008 WARN("\tunknown WS_IOCTL cmd (%08x)\n", cmd);
3009 break;
3012 fd = get_sock_fd( s, 0, NULL );
3013 if (fd != -1)
3015 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
3017 release_sock_fd( s, fd );
3018 return 0;
3020 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
3021 release_sock_fd( s, fd );
3023 return SOCKET_ERROR;
3026 /***********************************************************************
3027 * listen (WS2_32.13)
3029 int WINAPI WS_listen(SOCKET s, int backlog)
3031 int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
3033 TRACE("socket %04lx, backlog %d\n", s, backlog);
3034 if (fd != -1)
3036 if (listen(fd, backlog) == 0)
3038 release_sock_fd( s, fd );
3039 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
3040 FD_WINE_LISTENING,
3041 FD_CONNECT|FD_WINE_CONNECTED);
3042 return 0;
3044 SetLastError(wsaErrno());
3045 release_sock_fd( s, fd );
3047 return SOCKET_ERROR;
3050 /***********************************************************************
3051 * recv (WS2_32.16)
3053 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
3055 DWORD n, dwFlags = flags;
3056 WSABUF wsabuf;
3058 wsabuf.len = len;
3059 wsabuf.buf = buf;
3061 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
3062 return SOCKET_ERROR;
3063 else
3064 return n;
3067 /***********************************************************************
3068 * recvfrom (WS2_32.17)
3070 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
3071 struct WS_sockaddr *from, int *fromlen)
3073 DWORD n, dwFlags = flags;
3074 WSABUF wsabuf;
3076 wsabuf.len = len;
3077 wsabuf.buf = buf;
3079 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
3080 return SOCKET_ERROR;
3081 else
3082 return n;
3085 /* allocate a poll array for the corresponding fd sets */
3086 static struct pollfd *fd_sets_to_poll( const WS_fd_set *readfds, const WS_fd_set *writefds,
3087 const WS_fd_set *exceptfds, int *count_ptr )
3089 unsigned int i, j = 0, count = 0;
3090 struct pollfd *fds;
3092 if (readfds) count += readfds->fd_count;
3093 if (writefds) count += writefds->fd_count;
3094 if (exceptfds) count += exceptfds->fd_count;
3095 *count_ptr = count;
3096 if (!count) return NULL;
3097 if (!(fds = HeapAlloc( GetProcessHeap(), 0, count * sizeof(fds[0])))) return NULL;
3098 if (readfds)
3099 for (i = 0; i < readfds->fd_count; i++, j++)
3101 fds[j].fd = get_sock_fd( readfds->fd_array[i], FILE_READ_DATA, NULL );
3102 fds[j].events = POLLIN;
3103 fds[j].revents = 0;
3105 if (writefds)
3106 for (i = 0; i < writefds->fd_count; i++, j++)
3108 fds[j].fd = get_sock_fd( writefds->fd_array[i], FILE_WRITE_DATA, NULL );
3109 fds[j].events = POLLOUT;
3110 fds[j].revents = 0;
3112 if (exceptfds)
3113 for (i = 0; i < exceptfds->fd_count; i++, j++)
3115 fds[j].fd = get_sock_fd( exceptfds->fd_array[i], 0, NULL );
3116 fds[j].events = POLLHUP;
3117 fds[j].revents = 0;
3119 return fds;
3122 /* release the file descriptor obtained in fd_sets_to_poll */
3123 /* must be called with the original fd_set arrays, before calling get_poll_results */
3124 static void release_poll_fds( const WS_fd_set *readfds, const WS_fd_set *writefds,
3125 const WS_fd_set *exceptfds, struct pollfd *fds )
3127 unsigned int i, j = 0;
3129 if (readfds)
3131 for (i = 0; i < readfds->fd_count; i++, j++)
3132 if (fds[j].fd != -1) release_sock_fd( readfds->fd_array[i], fds[j].fd );
3134 if (writefds)
3136 for (i = 0; i < writefds->fd_count; i++, j++)
3137 if (fds[j].fd != -1) release_sock_fd( writefds->fd_array[i], fds[j].fd );
3139 if (exceptfds)
3141 for (i = 0; i < exceptfds->fd_count; i++, j++)
3142 if (fds[j].fd != -1)
3144 /* make sure we have a real error before releasing the fd */
3145 if (!sock_error_p( fds[j].fd )) fds[j].revents = 0;
3146 release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
3151 /* map the poll results back into the Windows fd sets */
3152 static int get_poll_results( WS_fd_set *readfds, WS_fd_set *writefds, WS_fd_set *exceptfds,
3153 const struct pollfd *fds )
3155 unsigned int i, j = 0, k, total = 0;
3157 if (readfds)
3159 for (i = k = 0; i < readfds->fd_count; i++, j++)
3160 if (fds[j].revents) readfds->fd_array[k++] = readfds->fd_array[i];
3161 readfds->fd_count = k;
3162 total += k;
3164 if (writefds)
3166 for (i = k = 0; i < writefds->fd_count; i++, j++)
3167 if (fds[j].revents) writefds->fd_array[k++] = writefds->fd_array[i];
3168 writefds->fd_count = k;
3169 total += k;
3171 if (exceptfds)
3173 for (i = k = 0; i < exceptfds->fd_count; i++, j++)
3174 if (fds[j].revents) exceptfds->fd_array[k++] = exceptfds->fd_array[i];
3175 exceptfds->fd_count = k;
3176 total += k;
3178 return total;
3182 /***********************************************************************
3183 * select (WS2_32.18)
3185 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
3186 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
3187 const struct WS_timeval* ws_timeout)
3189 struct pollfd *pollfds;
3190 struct timeval tv1, tv2;
3191 int torig = 0;
3192 int count, ret, timeout = -1;
3194 TRACE("read %p, write %p, excp %p timeout %p\n",
3195 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
3197 if (!(pollfds = fd_sets_to_poll( ws_readfds, ws_writefds, ws_exceptfds, &count )) && count)
3199 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
3200 return SOCKET_ERROR;
3203 if (ws_timeout)
3205 torig = (ws_timeout->tv_sec * 1000) + (ws_timeout->tv_usec + 999) / 1000;
3206 timeout = torig;
3207 gettimeofday( &tv1, 0 );
3210 while ((ret = poll( pollfds, count, timeout )) < 0)
3212 if (errno == EINTR)
3214 if (!ws_timeout) continue;
3215 gettimeofday( &tv2, 0 );
3217 tv2.tv_sec -= tv1.tv_sec;
3218 tv2.tv_usec -= tv1.tv_usec;
3219 if (tv2.tv_usec < 0)
3221 tv2.tv_usec += 1000000;
3222 tv2.tv_sec -= 1;
3225 timeout = torig - (tv2.tv_sec * 1000) - (tv2.tv_usec + 999) / 1000;
3226 if (timeout <= 0) break;
3227 } else break;
3229 release_poll_fds( ws_readfds, ws_writefds, ws_exceptfds, pollfds );
3231 if (ret == -1) SetLastError(wsaErrno());
3232 else ret = get_poll_results( ws_readfds, ws_writefds, ws_exceptfds, pollfds );
3233 HeapFree( GetProcessHeap(), 0, pollfds );
3234 return ret;
3237 /* helper to send completion messages for client-only i/o operation case */
3238 static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus,
3239 ULONG Information )
3241 NTSTATUS status;
3243 SERVER_START_REQ( add_fd_completion )
3245 req->handle = wine_server_obj_handle( SOCKET2HANDLE(sock) );
3246 req->cvalue = CompletionValue;
3247 req->status = CompletionStatus;
3248 req->information = Information;
3249 status = wine_server_call( req );
3251 SERVER_END_REQ;
3255 /***********************************************************************
3256 * send (WS2_32.19)
3258 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
3260 DWORD n;
3261 WSABUF wsabuf;
3263 wsabuf.len = len;
3264 wsabuf.buf = (char*) buf;
3266 if ( WSASendTo( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
3267 return SOCKET_ERROR;
3268 else
3269 return n;
3272 /***********************************************************************
3273 * WSASend (WS2_32.72)
3275 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3276 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
3277 LPWSAOVERLAPPED lpOverlapped,
3278 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3280 return WSASendTo( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
3281 NULL, 0, lpOverlapped, lpCompletionRoutine );
3284 /***********************************************************************
3285 * WSASendDisconnect (WS2_32.73)
3287 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
3289 return WS_shutdown( s, SD_SEND );
3293 /***********************************************************************
3294 * WSASendTo (WS2_32.74)
3296 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3297 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
3298 const struct WS_sockaddr *to, int tolen,
3299 LPWSAOVERLAPPED lpOverlapped,
3300 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3302 unsigned int i, options;
3303 int n, fd, err;
3304 struct ws2_async *wsa;
3305 int totalLength = 0;
3306 ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
3308 TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, to %p, tolen %d, ovl %p, func %p\n",
3309 s, lpBuffers, dwBufferCount, dwFlags,
3310 to, tolen, lpOverlapped, lpCompletionRoutine);
3312 fd = get_sock_fd( s, FILE_WRITE_DATA, &options );
3313 TRACE( "fd=%d, options=%x\n", fd, options );
3315 if ( fd == -1 ) return SOCKET_ERROR;
3317 if (!(wsa = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(struct ws2_async, iovec[dwBufferCount]) )))
3319 err = WSAEFAULT;
3320 goto error;
3323 wsa->hSocket = SOCKET2HANDLE(s);
3324 wsa->addr = (struct WS_sockaddr *)to;
3325 wsa->addrlen.val = tolen;
3326 wsa->flags = dwFlags;
3327 wsa->n_iovecs = dwBufferCount;
3328 wsa->first_iovec = 0;
3329 for ( i = 0; i < dwBufferCount; i++ )
3331 wsa->iovec[i].iov_base = lpBuffers[i].buf;
3332 wsa->iovec[i].iov_len = lpBuffers[i].len;
3333 totalLength += lpBuffers[i].len;
3336 if (!lpNumberOfBytesSent)
3338 err = WSAEFAULT;
3339 goto error;
3342 for (;;)
3344 n = WS2_send( fd, wsa );
3345 if (n != -1 || errno != EINTR) break;
3347 if (n == -1 && errno != EAGAIN)
3349 int loc_errno = errno;
3350 err = wsaErrno();
3351 if (cvalue) WS_AddCompletion( s, cvalue, sock_get_ntstatus(loc_errno), 0 );
3352 goto error;
3355 if ((lpOverlapped || lpCompletionRoutine) &&
3356 !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
3358 IO_STATUS_BLOCK *iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
3360 wsa->user_overlapped = lpOverlapped;
3361 wsa->completion_func = lpCompletionRoutine;
3362 release_sock_fd( s, fd );
3364 if (n == -1)
3366 iosb->u.Status = STATUS_PENDING;
3367 iosb->Information = 0;
3369 SERVER_START_REQ( register_async )
3371 req->type = ASYNC_TYPE_WRITE;
3372 req->async.handle = wine_server_obj_handle( wsa->hSocket );
3373 req->async.callback = wine_server_client_ptr( WS2_async_send );
3374 req->async.iosb = wine_server_client_ptr( iosb );
3375 req->async.arg = wine_server_client_ptr( wsa );
3376 req->async.event = wine_server_obj_handle( lpCompletionRoutine ? 0 : lpOverlapped->hEvent );
3377 req->async.cvalue = cvalue;
3378 err = wine_server_call( req );
3380 SERVER_END_REQ;
3382 if (err != STATUS_PENDING) HeapFree( GetProcessHeap(), 0, wsa );
3383 WSASetLastError( NtStatusToWSAError( err ));
3384 return SOCKET_ERROR;
3387 iosb->u.Status = STATUS_SUCCESS;
3388 iosb->Information = n;
3389 *lpNumberOfBytesSent = n;
3390 if (!wsa->completion_func)
3392 if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n );
3393 if (lpOverlapped->hEvent) SetEvent( lpOverlapped->hEvent );
3394 HeapFree( GetProcessHeap(), 0, wsa );
3396 else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc,
3397 (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 );
3398 WSASetLastError(0);
3399 return 0;
3402 if ( _is_blocking(s) )
3404 /* On a blocking non-overlapped stream socket,
3405 * sending blocks until the entire buffer is sent. */
3406 DWORD timeout_start = GetTickCount();
3408 *lpNumberOfBytesSent = 0;
3410 while (wsa->first_iovec < dwBufferCount)
3412 struct pollfd pfd;
3413 int timeout = GET_SNDTIMEO(fd);
3415 if (n >= 0)
3417 *lpNumberOfBytesSent += n;
3418 while (wsa->first_iovec < dwBufferCount && wsa->iovec[wsa->first_iovec].iov_len <= n)
3419 n -= wsa->iovec[wsa->first_iovec++].iov_len;
3420 if (wsa->first_iovec >= dwBufferCount) break;
3421 wsa->iovec[wsa->first_iovec].iov_base = (char*)wsa->iovec[wsa->first_iovec].iov_base + n;
3422 wsa->iovec[wsa->first_iovec].iov_len -= n;
3425 if (timeout != -1)
3427 timeout -= GetTickCount() - timeout_start;
3428 if (timeout < 0) timeout = 0;
3431 pfd.fd = fd;
3432 pfd.events = POLLOUT;
3434 if (!timeout || !poll( &pfd, 1, timeout ))
3436 err = WSAETIMEDOUT;
3437 goto error; /* msdn says a timeout in send is fatal */
3440 n = WS2_send( fd, wsa );
3441 if (n == -1 && errno != EAGAIN && errno != EINTR)
3443 err = wsaErrno();
3444 goto error;
3448 else /* non-blocking */
3450 if (n < totalLength)
3451 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
3452 if (n == -1)
3454 err = WSAEWOULDBLOCK;
3455 goto error;
3457 *lpNumberOfBytesSent = n;
3460 TRACE(" -> %i bytes\n", *lpNumberOfBytesSent);
3462 HeapFree( GetProcessHeap(), 0, wsa );
3463 release_sock_fd( s, fd );
3464 WSASetLastError(0);
3465 return 0;
3467 error:
3468 HeapFree( GetProcessHeap(), 0, wsa );
3469 release_sock_fd( s, fd );
3470 WARN(" -> ERROR %d\n", err);
3471 WSASetLastError(err);
3472 return SOCKET_ERROR;
3475 /***********************************************************************
3476 * sendto (WS2_32.20)
3478 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
3479 const struct WS_sockaddr *to, int tolen)
3481 DWORD n;
3482 WSABUF wsabuf;
3484 wsabuf.len = len;
3485 wsabuf.buf = (char*) buf;
3487 if ( WSASendTo(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
3488 return SOCKET_ERROR;
3489 else
3490 return n;
3493 /***********************************************************************
3494 * setsockopt (WS2_32.21)
3496 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
3497 const char *optval, int optlen)
3499 int fd;
3500 int woptval;
3501 struct linger linger;
3502 struct timeval tval;
3504 TRACE("socket: %04lx, level 0x%x, name 0x%x, ptr %p, len %d\n",
3505 s, level, optname, optval, optlen);
3507 /* some broken apps pass the value directly instead of a pointer to it */
3508 if(IS_INTRESOURCE(optval))
3510 SetLastError(WSAEFAULT);
3511 return SOCKET_ERROR;
3514 switch(level)
3516 case WS_SOL_SOCKET:
3517 switch(optname)
3519 /* Some options need some conversion before they can be sent to
3520 * setsockopt. The conversions are done here, then they will fall though
3521 * to the general case. Special options that are not passed to
3522 * setsockopt follow below that.*/
3524 case WS_SO_DONTLINGER:
3525 linger.l_onoff = *((const int*)optval) ? 0: 1;
3526 linger.l_linger = 0;
3527 level = SOL_SOCKET;
3528 optname = SO_LINGER;
3529 optval = (char*)&linger;
3530 optlen = sizeof(struct linger);
3531 break;
3533 case WS_SO_LINGER:
3534 linger.l_onoff = ((LINGER*)optval)->l_onoff;
3535 linger.l_linger = ((LINGER*)optval)->l_linger;
3536 /* FIXME: what is documented behavior if SO_LINGER optval
3537 is null?? */
3538 level = SOL_SOCKET;
3539 optname = SO_LINGER;
3540 optval = (char*)&linger;
3541 optlen = sizeof(struct linger);
3542 break;
3544 case WS_SO_RCVBUF:
3545 if (*(const int*)optval < 2048)
3547 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(const int*)optval );
3548 return 0;
3550 /* Fall through */
3552 /* The options listed here don't need any special handling. Thanks to
3553 * the conversion happening above, options from there will fall through
3554 * to this, too.*/
3555 case WS_SO_ACCEPTCONN:
3556 case WS_SO_BROADCAST:
3557 case WS_SO_ERROR:
3558 case WS_SO_KEEPALIVE:
3559 case WS_SO_OOBINLINE:
3560 /* BSD socket SO_REUSEADDR is not 100% compatible to winsock semantics.
3561 * however, using it the BSD way fixes bug 8513 and seems to be what
3562 * most programmers assume, anyway */
3563 case WS_SO_REUSEADDR:
3564 case WS_SO_SNDBUF:
3565 case WS_SO_TYPE:
3566 convert_sockopt(&level, &optname);
3567 break;
3569 /* SO_DEBUG is a privileged operation, ignore it. */
3570 case WS_SO_DEBUG:
3571 TRACE("Ignoring SO_DEBUG\n");
3572 return 0;
3574 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
3575 * socket. According to MSDN, this option is silently ignored.*/
3576 case WS_SO_DONTROUTE:
3577 TRACE("Ignoring SO_DONTROUTE\n");
3578 return 0;
3580 /* Stops two sockets from being bound to the same port. Always happens
3581 * on unix systems, so just drop it. */
3582 case WS_SO_EXCLUSIVEADDRUSE:
3583 TRACE("Ignoring SO_EXCLUSIVEADDRUSE, is always set.\n");
3584 return 0;
3586 /* SO_OPENTYPE does not require a valid socket handle. */
3587 case WS_SO_OPENTYPE:
3588 if (!optlen || optlen < sizeof(int) || !optval)
3590 SetLastError(WSAEFAULT);
3591 return SOCKET_ERROR;
3593 get_per_thread_data()->opentype = *(const int *)optval;
3594 TRACE("setting global SO_OPENTYPE = 0x%x\n", *((const int*)optval) );
3595 return 0;
3597 #ifdef SO_RCVTIMEO
3598 case WS_SO_RCVTIMEO:
3599 #endif
3600 #ifdef SO_SNDTIMEO
3601 case WS_SO_SNDTIMEO:
3602 #endif
3603 #if defined(SO_RCVTIMEO) || defined(SO_SNDTIMEO)
3604 if (optval && optlen == sizeof(UINT32)) {
3605 /* WinSock passes milliseconds instead of struct timeval */
3606 tval.tv_usec = (*(const UINT32*)optval % 1000) * 1000;
3607 tval.tv_sec = *(const UINT32*)optval / 1000;
3608 /* min of 500 milliseconds */
3609 if (tval.tv_sec == 0 && tval.tv_usec && tval.tv_usec < 500000)
3610 tval.tv_usec = 500000;
3611 optlen = sizeof(struct timeval);
3612 optval = (char*)&tval;
3613 } else if (optlen == sizeof(struct timeval)) {
3614 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
3615 } else {
3616 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
3617 return 0;
3619 convert_sockopt(&level, &optname);
3620 break;
3621 #endif
3623 default:
3624 TRACE("Unknown SOL_SOCKET optname: 0x%08x\n", optname);
3625 SetLastError(WSAENOPROTOOPT);
3626 return SOCKET_ERROR;
3628 break; /* case WS_SOL_SOCKET */
3630 #ifdef HAVE_IPX
3631 case NSPROTO_IPX:
3632 switch(optname)
3634 case IPX_PTYPE:
3635 fd = get_sock_fd( s, 0, NULL );
3636 TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", *(const int*)optval, fd);
3638 /* We try to set the ipx type on ipx socket level. */
3639 #ifdef SOL_IPX
3640 if(setsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
3642 ERR("IPX: could not set ipx option type; expect weird behaviour\n");
3643 release_sock_fd( s, fd );
3644 return SOCKET_ERROR;
3646 #else
3648 struct ipx val;
3649 /* Should we retrieve val using a getsockopt call and then
3650 * set the modified one? */
3651 val.ipx_pt = *optval;
3652 setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
3654 #endif
3655 release_sock_fd( s, fd );
3656 return 0;
3658 case IPX_FILTERPTYPE:
3659 /* Sets the receive filter packet type, at the moment we don't support it */
3660 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
3661 /* Returning 0 is better for now than returning a SOCKET_ERROR */
3662 return 0;
3664 default:
3665 FIXME("opt_name:%x\n", optname);
3666 return SOCKET_ERROR;
3668 break; /* case NSPROTO_IPX */
3669 #endif
3671 /* Levels WS_IPPROTO_TCP and WS_IPPROTO_IP convert directly */
3672 case WS_IPPROTO_TCP:
3673 switch(optname)
3675 case WS_TCP_NODELAY:
3676 convert_sockopt(&level, &optname);
3677 break;
3678 default:
3679 FIXME("Unknown IPPROTO_TCP optname 0x%08x\n", optname);
3680 return SOCKET_ERROR;
3682 break;
3684 case WS_IPPROTO_IP:
3685 switch(optname)
3687 case WS_IP_ADD_MEMBERSHIP:
3688 case WS_IP_DROP_MEMBERSHIP:
3689 #ifdef IP_HDRINCL
3690 case WS_IP_HDRINCL:
3691 #endif
3692 case WS_IP_MULTICAST_IF:
3693 case WS_IP_MULTICAST_LOOP:
3694 case WS_IP_MULTICAST_TTL:
3695 case WS_IP_OPTIONS:
3696 case WS_IP_TOS:
3697 case WS_IP_TTL:
3698 convert_sockopt(&level, &optname);
3699 break;
3700 case WS_IP_DONTFRAGMENT:
3701 FIXME("IP_DONTFRAGMENT is silently ignored!\n");
3702 return 0;
3703 default:
3704 FIXME("Unknown IPPROTO_IP optname 0x%08x\n", optname);
3705 return SOCKET_ERROR;
3707 break;
3709 case WS_IPPROTO_IPV6:
3710 switch(optname)
3712 #ifdef IPV6_ADD_MEMBERSHIP
3713 case WS_IPV6_ADD_MEMBERSHIP:
3714 #endif
3715 #ifdef IPV6_DROP_MEMBERSHIP
3716 case WS_IPV6_DROP_MEMBERSHIP:
3717 #endif
3718 case WS_IPV6_MULTICAST_IF:
3719 case WS_IPV6_MULTICAST_HOPS:
3720 case WS_IPV6_MULTICAST_LOOP:
3721 case WS_IPV6_UNICAST_HOPS:
3722 case WS_IPV6_V6ONLY:
3723 convert_sockopt(&level, &optname);
3724 break;
3725 case WS_IPV6_DONTFRAG:
3726 FIXME("IPV6_DONTFRAG is silently ignored!\n");
3727 return 0;
3728 default:
3729 FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname);
3730 return SOCKET_ERROR;
3732 break;
3734 default:
3735 WARN("Unknown level: 0x%08x\n", level);
3736 SetLastError(WSAEINVAL);
3737 return SOCKET_ERROR;
3738 } /* end switch(level) */
3740 /* avoid endianness issues if argument is a 16-bit int */
3741 if (optval && optlen < sizeof(int))
3743 woptval= *((const INT16 *) optval);
3744 optval= (char*) &woptval;
3745 optlen=sizeof(int);
3747 fd = get_sock_fd( s, 0, NULL );
3748 if (fd == -1) return SOCKET_ERROR;
3750 if (setsockopt(fd, level, optname, optval, optlen) == 0)
3752 release_sock_fd( s, fd );
3753 return 0;
3755 TRACE("Setting socket error, %d\n", wsaErrno());
3756 SetLastError(wsaErrno());
3757 release_sock_fd( s, fd );
3759 return SOCKET_ERROR;
3762 /***********************************************************************
3763 * shutdown (WS2_32.22)
3765 int WINAPI WS_shutdown(SOCKET s, int how)
3767 int fd, err = WSAENOTSOCK;
3768 unsigned int options, clear_flags = 0;
3770 fd = get_sock_fd( s, 0, &options );
3771 TRACE("socket %04lx, how %i %x\n", s, how, options );
3773 if (fd == -1)
3774 return SOCKET_ERROR;
3776 switch( how )
3778 case 0: /* drop receives */
3779 clear_flags |= FD_READ;
3780 break;
3781 case 1: /* drop sends */
3782 clear_flags |= FD_WRITE;
3783 break;
3784 case 2: /* drop all */
3785 clear_flags |= FD_READ|FD_WRITE;
3786 default:
3787 clear_flags |= FD_WINE_LISTENING;
3790 if (!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
3792 switch ( how )
3794 case SD_RECEIVE:
3795 err = WS2_register_async_shutdown( s, ASYNC_TYPE_READ );
3796 break;
3797 case SD_SEND:
3798 err = WS2_register_async_shutdown( s, ASYNC_TYPE_WRITE );
3799 break;
3800 case SD_BOTH:
3801 default:
3802 err = WS2_register_async_shutdown( s, ASYNC_TYPE_READ );
3803 if (!err) err = WS2_register_async_shutdown( s, ASYNC_TYPE_WRITE );
3804 break;
3806 if (err) goto error;
3808 else /* non-overlapped mode */
3810 if ( shutdown( fd, how ) )
3812 err = wsaErrno();
3813 goto error;
3817 release_sock_fd( s, fd );
3818 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
3819 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
3820 return 0;
3822 error:
3823 release_sock_fd( s, fd );
3824 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
3825 WSASetLastError( err );
3826 return SOCKET_ERROR;
3829 /***********************************************************************
3830 * socket (WS2_32.23)
3832 SOCKET WINAPI WS_socket(int af, int type, int protocol)
3834 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
3836 return WSASocketA( af, type, protocol, NULL, 0,
3837 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
3841 /***********************************************************************
3842 * gethostbyaddr (WS2_32.51)
3844 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
3846 struct WS_hostent *retval = NULL;
3847 struct hostent* host;
3849 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
3850 char *extrabuf;
3851 int ebufsize=1024;
3852 struct hostent hostentry;
3853 int locerr=ENOBUFS;
3854 host = NULL;
3855 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
3856 while(extrabuf) {
3857 int res = gethostbyaddr_r(addr, len, type,
3858 &hostentry, extrabuf, ebufsize, &host, &locerr);
3859 if( res != ERANGE) break;
3860 ebufsize *=2;
3861 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
3863 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
3864 #else
3865 EnterCriticalSection( &csWSgetXXXbyYYY );
3866 host = gethostbyaddr(addr, len, type);
3867 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
3868 #endif
3869 if( host != NULL ) retval = WS_dup_he(host);
3870 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
3871 HeapFree(GetProcessHeap(),0,extrabuf);
3872 #else
3873 LeaveCriticalSection( &csWSgetXXXbyYYY );
3874 #endif
3875 TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
3876 return retval;
3879 /***********************************************************************
3880 * WS_get_local_ips (INTERNAL)
3882 * Returns the list of local IP addresses by going through the network
3883 * adapters and using the local routing table to sort the addresses
3884 * from highest routing priority to lowest routing priority. This
3885 * functionality is inferred from the description for obtaining local
3886 * IP addresses given in the Knowledge Base Article Q160215.
3888 * Please note that the returned hostent is only freed when the thread
3889 * closes and is replaced if another hostent is requested.
3891 static struct WS_hostent* WS_get_local_ips( char *hostname )
3893 int last_metric, numroutes = 0, i, j;
3894 PIP_ADAPTER_INFO adapters = NULL, k;
3895 struct WS_hostent *hostlist = NULL;
3896 PMIB_IPFORWARDTABLE routes = NULL;
3897 struct route *route_addrs = NULL;
3898 DWORD adap_size, route_size;
3900 /* Obtain the size of the adapter list and routing table, also allocate memory */
3901 if (GetAdaptersInfo(NULL, &adap_size) != ERROR_BUFFER_OVERFLOW)
3902 return NULL;
3903 if (GetIpForwardTable(NULL, &route_size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
3904 return NULL;
3905 adapters = HeapAlloc(GetProcessHeap(), 0, adap_size);
3906 routes = HeapAlloc(GetProcessHeap(), 0, route_size);
3907 route_addrs = HeapAlloc(GetProcessHeap(), 0, 0); /* HeapReAlloc doesn't work on NULL */
3908 if (adapters == NULL || routes == NULL || route_addrs == NULL)
3909 goto cleanup;
3910 /* Obtain the adapter list and the full routing table */
3911 if (GetAdaptersInfo(adapters, &adap_size) != NO_ERROR)
3912 goto cleanup;
3913 if (GetIpForwardTable(routes, &route_size, FALSE) != NO_ERROR)
3914 goto cleanup;
3915 /* Store the interface associated with each route */
3916 for (i = 0; i < routes->dwNumEntries; i++)
3918 DWORD ifindex, ifmetric, exists = FALSE;
3920 if (routes->table[i].dwForwardType != MIB_IPROUTE_TYPE_DIRECT)
3921 continue;
3922 ifindex = routes->table[i].dwForwardIfIndex;
3923 ifmetric = routes->table[i].dwForwardMetric1;
3924 /* Only store the lowest valued metric for an interface */
3925 for (j = 0; j < numroutes; j++)
3927 if (route_addrs[j].interface == ifindex)
3929 if (route_addrs[j].metric > ifmetric)
3930 route_addrs[j].metric = ifmetric;
3931 exists = TRUE;
3934 if (exists)
3935 continue;
3936 route_addrs = HeapReAlloc(GetProcessHeap(), 0, route_addrs, (numroutes+1)*sizeof(struct route));
3937 if (route_addrs == NULL)
3938 goto cleanup; /* Memory allocation error, fail gracefully */
3939 route_addrs[numroutes].interface = ifindex;
3940 route_addrs[numroutes].metric = ifmetric;
3941 /* If no IP is found in the next step (for whatever reason)
3942 * then fall back to the magic loopback address.
3944 memcpy(&(route_addrs[numroutes].addr.s_addr), magic_loopback_addr, 4);
3945 numroutes++;
3947 if (numroutes == 0)
3948 goto cleanup; /* No routes, fall back to the Magic IP */
3949 /* Find the IP address associated with each found interface */
3950 for (i = 0; i < numroutes; i++)
3952 for (k = adapters; k != NULL; k = k->Next)
3954 char *ip = k->IpAddressList.IpAddress.String;
3956 if (route_addrs[i].interface == k->Index)
3957 route_addrs[i].addr.s_addr = (in_addr_t) inet_addr(ip);
3960 /* Allocate a hostent and enough memory for all the IPs,
3961 * including the NULL at the end of the list.
3963 hostlist = WS_create_he(hostname, 1, numroutes+1, TRUE);
3964 if (hostlist == NULL)
3965 goto cleanup; /* Failed to allocate a hostent for the list of IPs */
3966 hostlist->h_addr_list[numroutes] = NULL; /* NULL-terminate the address list */
3967 hostlist->h_aliases[0] = NULL; /* NULL-terminate the alias list */
3968 hostlist->h_addrtype = AF_INET;
3969 hostlist->h_length = sizeof(struct in_addr); /* = 4 */
3970 /* Reorder the entries when placing them in the host list, Windows expects
3971 * the IP list in order from highest priority to lowest (the critical thing
3972 * is that most applications expect the first IP to be the default route).
3974 last_metric = -1;
3975 for (i = 0; i < numroutes; i++)
3977 struct in_addr addr;
3978 int metric = 0xFFFF;
3980 memcpy(&addr, magic_loopback_addr, 4);
3981 for (j = 0; j < numroutes; j++)
3983 int this_metric = route_addrs[j].metric;
3985 if (this_metric > last_metric && this_metric < metric)
3987 addr = route_addrs[j].addr;
3988 metric = this_metric;
3991 last_metric = metric;
3992 (*(struct in_addr *) hostlist->h_addr_list[i]) = addr;
3995 /* Cleanup all allocated memory except the address list,
3996 * the address list is used by the calling app.
3998 cleanup:
3999 HeapFree(GetProcessHeap(), 0, route_addrs);
4000 HeapFree(GetProcessHeap(), 0, adapters);
4001 HeapFree(GetProcessHeap(), 0, routes);
4002 return hostlist;
4005 /***********************************************************************
4006 * gethostbyname (WS2_32.52)
4008 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
4010 struct WS_hostent *retval = NULL;
4011 struct hostent* host;
4012 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
4013 char *extrabuf;
4014 int ebufsize=1024;
4015 struct hostent hostentry;
4016 int locerr = ENOBUFS;
4017 #endif
4018 char hostname[100];
4019 if( gethostname( hostname, 100) == -1) {
4020 SetLastError( WSAENOBUFS); /* appropriate ? */
4021 return retval;
4023 if( !name || !name[0]) {
4024 name = hostname;
4026 /* If the hostname of the local machine is requested then return the
4027 * complete list of local IP addresses */
4028 if(strcmp(name, hostname) == 0)
4029 retval = WS_get_local_ips(hostname);
4030 /* If any other hostname was requested (or the routing table lookup failed)
4031 * then return the IP found by the host OS */
4032 if(retval == NULL)
4034 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
4035 host = NULL;
4036 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
4037 while(extrabuf) {
4038 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
4039 if( res != ERANGE) break;
4040 ebufsize *=2;
4041 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
4043 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
4044 #else
4045 EnterCriticalSection( &csWSgetXXXbyYYY );
4046 host = gethostbyname(name);
4047 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
4048 #endif
4049 if (host) retval = WS_dup_he(host);
4050 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
4051 HeapFree(GetProcessHeap(),0,extrabuf);
4052 #else
4053 LeaveCriticalSection( &csWSgetXXXbyYYY );
4054 #endif
4056 if (retval && retval->h_addr_list[0][0] == 127 &&
4057 strcmp(name, "localhost") != 0)
4059 /* hostname != "localhost" but has loopback address. replace by our
4060 * special address.*/
4061 memcpy(retval->h_addr_list[0], magic_loopback_addr, 4);
4063 TRACE( "%s ret %p\n", debugstr_a(name), retval );
4064 return retval;
4068 /***********************************************************************
4069 * getprotobyname (WS2_32.53)
4071 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
4073 struct WS_protoent* retval = NULL;
4074 #ifdef HAVE_GETPROTOBYNAME
4075 struct protoent* proto;
4076 EnterCriticalSection( &csWSgetXXXbyYYY );
4077 if( (proto = getprotobyname(name)) != NULL )
4079 retval = WS_dup_pe(proto);
4081 else {
4082 MESSAGE("protocol %s not found; You might want to add "
4083 "this to /etc/protocols\n", debugstr_a(name) );
4084 SetLastError(WSANO_DATA);
4086 LeaveCriticalSection( &csWSgetXXXbyYYY );
4087 #endif
4088 TRACE( "%s ret %p\n", debugstr_a(name), retval );
4089 return retval;
4093 /***********************************************************************
4094 * getprotobynumber (WS2_32.54)
4096 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
4098 struct WS_protoent* retval = NULL;
4099 #ifdef HAVE_GETPROTOBYNUMBER
4100 struct protoent* proto;
4101 EnterCriticalSection( &csWSgetXXXbyYYY );
4102 if( (proto = getprotobynumber(number)) != NULL )
4104 retval = WS_dup_pe(proto);
4106 else {
4107 MESSAGE("protocol number %d not found; You might want to add "
4108 "this to /etc/protocols\n", number );
4109 SetLastError(WSANO_DATA);
4111 LeaveCriticalSection( &csWSgetXXXbyYYY );
4112 #endif
4113 TRACE("%i ret %p\n", number, retval);
4114 return retval;
4118 /***********************************************************************
4119 * getservbyname (WS2_32.55)
4121 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
4123 struct WS_servent* retval = NULL;
4124 struct servent* serv;
4125 char *name_str;
4126 char *proto_str = NULL;
4128 if (!(name_str = strdup_lower(name))) return NULL;
4130 if (proto && *proto)
4132 if (!(proto_str = strdup_lower(proto)))
4134 HeapFree( GetProcessHeap(), 0, name_str );
4135 return NULL;
4139 EnterCriticalSection( &csWSgetXXXbyYYY );
4140 serv = getservbyname(name_str, proto_str);
4141 if( serv != NULL )
4143 retval = WS_dup_se(serv);
4145 else SetLastError(WSANO_DATA);
4146 LeaveCriticalSection( &csWSgetXXXbyYYY );
4147 HeapFree( GetProcessHeap(), 0, proto_str );
4148 HeapFree( GetProcessHeap(), 0, name_str );
4149 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
4150 return retval;
4153 /***********************************************************************
4154 * freeaddrinfo (WS2_32.@)
4156 void WINAPI WS_freeaddrinfo(struct WS_addrinfo *res)
4158 while (res) {
4159 struct WS_addrinfo *next;
4161 HeapFree(GetProcessHeap(),0,res->ai_canonname);
4162 HeapFree(GetProcessHeap(),0,res->ai_addr);
4163 next = res->ai_next;
4164 HeapFree(GetProcessHeap(),0,res);
4165 res = next;
4169 /* helper functions for getaddrinfo()/getnameinfo() */
4170 static int convert_aiflag_w2u(int winflags) {
4171 unsigned int i;
4172 int unixflags = 0;
4174 for (i=0;i<sizeof(ws_aiflag_map)/sizeof(ws_aiflag_map[0]);i++)
4175 if (ws_aiflag_map[i][0] & winflags) {
4176 unixflags |= ws_aiflag_map[i][1];
4177 winflags &= ~ws_aiflag_map[i][0];
4179 if (winflags)
4180 FIXME("Unhandled windows AI_xxx flags %x\n", winflags);
4181 return unixflags;
4184 static int convert_niflag_w2u(int winflags) {
4185 unsigned int i;
4186 int unixflags = 0;
4188 for (i=0;i<sizeof(ws_niflag_map)/sizeof(ws_niflag_map[0]);i++)
4189 if (ws_niflag_map[i][0] & winflags) {
4190 unixflags |= ws_niflag_map[i][1];
4191 winflags &= ~ws_niflag_map[i][0];
4193 if (winflags)
4194 FIXME("Unhandled windows NI_xxx flags %x\n", winflags);
4195 return unixflags;
4198 static int convert_aiflag_u2w(int unixflags) {
4199 unsigned int i;
4200 int winflags = 0;
4202 for (i=0;i<sizeof(ws_aiflag_map)/sizeof(ws_aiflag_map[0]);i++)
4203 if (ws_aiflag_map[i][1] & unixflags) {
4204 winflags |= ws_aiflag_map[i][0];
4205 unixflags &= ~ws_aiflag_map[i][1];
4207 if (unixflags) /* will warn usually */
4208 WARN("Unhandled UNIX AI_xxx flags %x\n", unixflags);
4209 return winflags;
4212 static int convert_eai_u2w(int unixret) {
4213 int i;
4215 for (i=0;ws_eai_map[i][0];i++)
4216 if (ws_eai_map[i][1] == unixret)
4217 return ws_eai_map[i][0];
4218 return unixret;
4221 /***********************************************************************
4222 * getaddrinfo (WS2_32.@)
4224 int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addrinfo *hints, struct WS_addrinfo **res)
4226 #ifdef HAVE_GETADDRINFO
4227 struct addrinfo *unixaires = NULL;
4228 int result;
4229 struct addrinfo unixhints, *punixhints = NULL;
4230 CHAR *node = NULL, *serv = NULL;
4232 if (nodename)
4233 if (!(node = strdup_lower(nodename))) return WSA_NOT_ENOUGH_MEMORY;
4235 if (servname) {
4236 if (!(serv = strdup_lower(servname))) {
4237 HeapFree(GetProcessHeap(), 0, node);
4238 return WSA_NOT_ENOUGH_MEMORY;
4242 if (hints) {
4243 punixhints = &unixhints;
4245 memset(&unixhints, 0, sizeof(unixhints));
4246 punixhints->ai_flags = convert_aiflag_w2u(hints->ai_flags);
4247 if (hints->ai_family == 0) /* wildcard, specific to getaddrinfo() */
4248 punixhints->ai_family = 0;
4249 else
4250 punixhints->ai_family = convert_af_w2u(hints->ai_family);
4251 if (hints->ai_socktype == 0) /* wildcard, specific to getaddrinfo() */
4252 punixhints->ai_socktype = 0;
4253 else
4254 punixhints->ai_socktype = convert_socktype_w2u(hints->ai_socktype);
4255 if (hints->ai_protocol == 0) /* wildcard, specific to getaddrinfo() */
4256 punixhints->ai_protocol = 0;
4257 else
4258 punixhints->ai_protocol = convert_proto_w2u(hints->ai_protocol);
4261 /* getaddrinfo(3) is thread safe, no need to wrap in CS */
4262 result = getaddrinfo(nodename, servname, punixhints, &unixaires);
4264 TRACE("%s, %s %p -> %p %d\n", debugstr_a(nodename), debugstr_a(servname), hints, res, result);
4266 HeapFree(GetProcessHeap(), 0, node);
4267 HeapFree(GetProcessHeap(), 0, serv);
4269 if (!result) {
4270 struct addrinfo *xuai = unixaires;
4271 struct WS_addrinfo **xai = res;
4273 *xai = NULL;
4274 while (xuai) {
4275 struct WS_addrinfo *ai = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo));
4276 int len;
4278 if (!ai)
4279 goto outofmem;
4281 *xai = ai;xai = &ai->ai_next;
4282 ai->ai_flags = convert_aiflag_u2w(xuai->ai_flags);
4283 ai->ai_family = convert_af_u2w(xuai->ai_family);
4284 ai->ai_socktype = convert_socktype_u2w(xuai->ai_socktype);
4285 ai->ai_protocol = convert_proto_u2w(xuai->ai_protocol);
4286 if (xuai->ai_canonname) {
4287 TRACE("canon name - %s\n",debugstr_a(xuai->ai_canonname));
4288 ai->ai_canonname = HeapAlloc(GetProcessHeap(),0,strlen(xuai->ai_canonname)+1);
4289 if (!ai->ai_canonname)
4290 goto outofmem;
4291 strcpy(ai->ai_canonname,xuai->ai_canonname);
4293 len = xuai->ai_addrlen;
4294 ai->ai_addr = HeapAlloc(GetProcessHeap(),0,len);
4295 if (!ai->ai_addr)
4296 goto outofmem;
4297 ai->ai_addrlen = len;
4298 do {
4299 int winlen = ai->ai_addrlen;
4301 if (!ws_sockaddr_u2ws(xuai->ai_addr, ai->ai_addr, &winlen)) {
4302 ai->ai_addrlen = winlen;
4303 break;
4305 len = 2*len;
4306 ai->ai_addr = HeapReAlloc(GetProcessHeap(),0,ai->ai_addr,len);
4307 if (!ai->ai_addr)
4308 goto outofmem;
4309 ai->ai_addrlen = len;
4310 } while (1);
4311 xuai = xuai->ai_next;
4313 freeaddrinfo(unixaires);
4314 } else {
4315 result = convert_eai_u2w(result);
4316 *res = NULL;
4318 return result;
4320 outofmem:
4321 if (*res) WS_freeaddrinfo(*res);
4322 if (unixaires) freeaddrinfo(unixaires);
4323 *res = NULL;
4324 return WSA_NOT_ENOUGH_MEMORY;
4325 #else
4326 FIXME("getaddrinfo() failed, not found during buildtime.\n");
4327 return EAI_FAIL;
4328 #endif
4331 static struct WS_addrinfoW *addrinfo_AtoW(const struct WS_addrinfo *ai)
4333 struct WS_addrinfoW *ret;
4335 if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_addrinfoW)))) return NULL;
4336 ret->ai_flags = ai->ai_flags;
4337 ret->ai_family = ai->ai_family;
4338 ret->ai_socktype = ai->ai_socktype;
4339 ret->ai_protocol = ai->ai_protocol;
4340 ret->ai_addrlen = ai->ai_addrlen;
4341 ret->ai_canonname = NULL;
4342 ret->ai_addr = NULL;
4343 ret->ai_next = NULL;
4344 if (ai->ai_canonname)
4346 int len = MultiByteToWideChar(CP_ACP, 0, ai->ai_canonname, -1, NULL, 0);
4347 if (!(ret->ai_canonname = HeapAlloc(GetProcessHeap(), 0, len)))
4349 HeapFree(GetProcessHeap(), 0, ret);
4350 return NULL;
4352 MultiByteToWideChar(CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len);
4354 if (ai->ai_addr)
4356 if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_sockaddr))))
4358 HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
4359 HeapFree(GetProcessHeap(), 0, ret);
4360 return NULL;
4362 memcpy(ret->ai_addr, ai->ai_addr, sizeof(struct WS_sockaddr));
4364 return ret;
4367 static struct WS_addrinfoW *addrinfo_list_AtoW(const struct WS_addrinfo *info)
4369 struct WS_addrinfoW *ret, *infoW;
4371 if (!(ret = infoW = addrinfo_AtoW(info))) return NULL;
4372 while (info->ai_next)
4374 if (!(infoW->ai_next = addrinfo_AtoW(info->ai_next)))
4376 FreeAddrInfoW(ret);
4377 return NULL;
4379 infoW = infoW->ai_next;
4380 info = info->ai_next;
4382 return ret;
4385 static struct WS_addrinfo *addrinfo_WtoA(const struct WS_addrinfoW *ai)
4387 struct WS_addrinfo *ret;
4389 if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_addrinfo)))) return NULL;
4390 ret->ai_flags = ai->ai_flags;
4391 ret->ai_family = ai->ai_family;
4392 ret->ai_socktype = ai->ai_socktype;
4393 ret->ai_protocol = ai->ai_protocol;
4394 ret->ai_addrlen = ai->ai_addrlen;
4395 ret->ai_canonname = NULL;
4396 ret->ai_addr = NULL;
4397 ret->ai_next = NULL;
4398 if (ai->ai_canonname)
4400 int len = WideCharToMultiByte(CP_ACP, 0, ai->ai_canonname, -1, NULL, 0, NULL, NULL);
4401 if (!(ret->ai_canonname = HeapAlloc(GetProcessHeap(), 0, len)))
4403 HeapFree(GetProcessHeap(), 0, ret);
4404 return NULL;
4406 WideCharToMultiByte(CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len, NULL, NULL);
4408 if (ai->ai_addr)
4410 if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_sockaddr))))
4412 HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
4413 HeapFree(GetProcessHeap(), 0, ret);
4414 return NULL;
4416 memcpy(ret->ai_addr, ai->ai_addr, sizeof(struct WS_sockaddr));
4418 return ret;
4421 /***********************************************************************
4422 * GetAddrInfoW (WS2_32.@)
4424 int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hints, PADDRINFOW *res)
4426 int ret, len;
4427 char *nodenameA, *servnameA = NULL;
4428 struct WS_addrinfo *resA, *hintsA = NULL;
4430 if (!nodename) return WSAHOST_NOT_FOUND;
4432 len = WideCharToMultiByte(CP_ACP, 0, nodename, -1, NULL, 0, NULL, NULL);
4433 if (!(nodenameA = HeapAlloc(GetProcessHeap(), 0, len))) return EAI_MEMORY;
4434 WideCharToMultiByte(CP_ACP, 0, nodename, -1, nodenameA, len, NULL, NULL);
4436 if (servname)
4438 len = WideCharToMultiByte(CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL);
4439 if (!(servnameA = HeapAlloc(GetProcessHeap(), 0, len)))
4441 HeapFree(GetProcessHeap(), 0, nodenameA);
4442 return EAI_MEMORY;
4444 WideCharToMultiByte(CP_ACP, 0, servname, -1, servnameA, len, NULL, NULL);
4447 if (hints) hintsA = addrinfo_WtoA(hints);
4448 ret = WS_getaddrinfo(nodenameA, servnameA, hintsA, &resA);
4449 WS_freeaddrinfo(hintsA);
4451 if (!ret)
4453 *res = addrinfo_list_AtoW(resA);
4454 WS_freeaddrinfo(resA);
4457 HeapFree(GetProcessHeap(), 0, nodenameA);
4458 HeapFree(GetProcessHeap(), 0, servnameA);
4459 return ret;
4462 /***********************************************************************
4463 * FreeAddrInfoW (WS2_32.@)
4465 void WINAPI FreeAddrInfoW(PADDRINFOW ai)
4467 while (ai)
4469 ADDRINFOW *next;
4470 HeapFree(GetProcessHeap(), 0, ai->ai_canonname);
4471 HeapFree(GetProcessHeap(), 0, ai->ai_addr);
4472 next = ai->ai_next;
4473 HeapFree(GetProcessHeap(), 0, ai);
4474 ai = next;
4478 int WINAPI WS_getnameinfo(const SOCKADDR *sa, WS_socklen_t salen, PCHAR host,
4479 DWORD hostlen, PCHAR serv, DWORD servlen, INT flags)
4481 #ifdef HAVE_GETNAMEINFO
4482 int ret;
4483 union generic_unix_sockaddr sa_u;
4484 unsigned int size;
4486 TRACE("%s %d %p %d %p %d %d\n", debugstr_sockaddr(sa), salen, host, hostlen,
4487 serv, servlen, flags);
4489 size = ws_sockaddr_ws2u(sa, salen, &sa_u);
4490 if (!size)
4492 WSASetLastError(WSAEFAULT);
4493 return WSA_NOT_ENOUGH_MEMORY;
4495 ret = getnameinfo(&sa_u.addr, size, host, hostlen, serv, servlen, convert_niflag_w2u(flags));
4496 return convert_eai_u2w(ret);
4497 #else
4498 FIXME("getnameinfo() failed, not found during buildtime.\n");
4499 return EAI_FAIL;
4500 #endif
4503 /***********************************************************************
4504 * getservbyport (WS2_32.56)
4506 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
4508 struct WS_servent* retval = NULL;
4509 #ifdef HAVE_GETSERVBYPORT
4510 struct servent* serv;
4511 char *proto_str = NULL;
4513 if (proto && *proto)
4515 if (!(proto_str = strdup_lower(proto))) return NULL;
4517 EnterCriticalSection( &csWSgetXXXbyYYY );
4518 if( (serv = getservbyport(port, proto_str)) != NULL ) {
4519 retval = WS_dup_se(serv);
4521 else SetLastError(WSANO_DATA);
4522 LeaveCriticalSection( &csWSgetXXXbyYYY );
4523 HeapFree( GetProcessHeap(), 0, proto_str );
4524 #endif
4525 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
4526 return retval;
4530 /***********************************************************************
4531 * gethostname (WS2_32.57)
4533 int WINAPI WS_gethostname(char *name, int namelen)
4535 TRACE("name %p, len %d\n", name, namelen);
4537 if (gethostname(name, namelen) == 0)
4539 TRACE("<- '%s'\n", name);
4540 return 0;
4542 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
4543 TRACE("<- ERROR !\n");
4544 return SOCKET_ERROR;
4548 /* ------------------------------------- Windows sockets extensions -- *
4550 * ------------------------------------------------------------------- */
4552 /***********************************************************************
4553 * WSAEnumNetworkEvents (WS2_32.36)
4555 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
4557 int ret;
4558 int i;
4559 int errors[FD_MAX_EVENTS];
4561 TRACE("%08lx, hEvent %p, lpEvent %p\n", s, hEvent, lpEvent );
4563 SERVER_START_REQ( get_socket_event )
4565 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
4566 req->service = TRUE;
4567 req->c_event = wine_server_obj_handle( hEvent );
4568 wine_server_set_reply( req, errors, sizeof(errors) );
4569 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
4571 SERVER_END_REQ;
4572 if (!ret)
4574 for (i = 0; i < FD_MAX_EVENTS; i++)
4575 lpEvent->iErrorCode[i] = NtStatusToWSAError(errors[i]);
4576 return 0;
4578 SetLastError(WSAEINVAL);
4579 return SOCKET_ERROR;
4582 /***********************************************************************
4583 * WSAEventSelect (WS2_32.39)
4585 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
4587 int ret;
4589 TRACE("%08lx, hEvent %p, event %08x\n", s, hEvent, lEvent);
4591 SERVER_START_REQ( set_socket_event )
4593 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
4594 req->mask = lEvent;
4595 req->event = wine_server_obj_handle( hEvent );
4596 req->window = 0;
4597 req->msg = 0;
4598 ret = wine_server_call( req );
4600 SERVER_END_REQ;
4601 if (!ret) return 0;
4602 SetLastError(WSAEINVAL);
4603 return SOCKET_ERROR;
4606 /**********************************************************************
4607 * WSAGetOverlappedResult (WS2_32.40)
4609 BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
4610 LPDWORD lpcbTransfer, BOOL fWait,
4611 LPDWORD lpdwFlags )
4613 NTSTATUS status;
4615 TRACE( "socket %04lx ovl %p trans %p, wait %d flags %p\n",
4616 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
4618 if ( lpOverlapped == NULL )
4620 ERR( "Invalid pointer\n" );
4621 WSASetLastError(WSA_INVALID_PARAMETER);
4622 return FALSE;
4625 status = lpOverlapped->Internal;
4626 if (status == STATUS_PENDING)
4628 if (!fWait)
4630 SetLastError( WSA_IO_INCOMPLETE );
4631 return FALSE;
4634 if (WaitForSingleObject( lpOverlapped->hEvent ? lpOverlapped->hEvent : SOCKET2HANDLE(s),
4635 INFINITE ) == WAIT_FAILED)
4636 return FALSE;
4637 status = lpOverlapped->Internal;
4640 if ( lpcbTransfer )
4641 *lpcbTransfer = lpOverlapped->InternalHigh;
4643 if ( lpdwFlags )
4644 *lpdwFlags = lpOverlapped->u.s.Offset;
4646 if (status) SetLastError( RtlNtStatusToDosError(status) );
4647 return !status;
4651 /***********************************************************************
4652 * WSAAsyncSelect (WS2_32.101)
4654 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
4656 int ret;
4658 TRACE("%lx, hWnd %p, uMsg %08x, event %08x\n", s, hWnd, uMsg, lEvent);
4660 SERVER_START_REQ( set_socket_event )
4662 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
4663 req->mask = lEvent;
4664 req->event = 0;
4665 req->window = wine_server_user_handle( hWnd );
4666 req->msg = uMsg;
4667 ret = wine_server_call( req );
4669 SERVER_END_REQ;
4670 if (!ret) return 0;
4671 SetLastError(WSAEINVAL);
4672 return SOCKET_ERROR;
4675 /***********************************************************************
4676 * WSACreateEvent (WS2_32.31)
4679 WSAEVENT WINAPI WSACreateEvent(void)
4681 /* Create a manual-reset event, with initial state: unsignaled */
4682 TRACE("\n");
4684 return CreateEventW(NULL, TRUE, FALSE, NULL);
4687 /***********************************************************************
4688 * WSACloseEvent (WS2_32.29)
4691 BOOL WINAPI WSACloseEvent(WSAEVENT event)
4693 TRACE ("event=%p\n", event);
4695 return CloseHandle(event);
4698 /***********************************************************************
4699 * WSASocketA (WS2_32.78)
4702 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
4703 LPWSAPROTOCOL_INFOA lpProtocolInfo,
4704 GROUP g, DWORD dwFlags)
4706 INT len;
4707 WSAPROTOCOL_INFOW info;
4709 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%x\n",
4710 af, type, protocol, lpProtocolInfo, g, dwFlags);
4712 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
4714 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
4715 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
4716 info.szProtocol, WSAPROTOCOL_LEN + 1);
4718 if (!len)
4720 WSASetLastError( WSAEINVAL);
4721 return SOCKET_ERROR;
4724 return WSASocketW(af, type, protocol, &info, g, dwFlags);
4727 /***********************************************************************
4728 * WSASocketW (WS2_32.79)
4731 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
4732 LPWSAPROTOCOL_INFOW lpProtocolInfo,
4733 GROUP g, DWORD dwFlags)
4735 SOCKET ret;
4738 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
4739 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
4742 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%x\n",
4743 af, type, protocol, lpProtocolInfo, g, dwFlags );
4745 /* hack for WSADuplicateSocket */
4746 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
4747 ret = lpProtocolInfo->dwCatalogEntryId;
4748 TRACE("\tgot duplicate %04lx\n", ret);
4749 return ret;
4752 /* convert the socket family and type */
4753 af = convert_af_w2u(af);
4754 type = convert_socktype_w2u(type);
4756 if (lpProtocolInfo)
4758 if (af == FROM_PROTOCOL_INFO)
4759 af = lpProtocolInfo->iAddressFamily;
4760 if (type == FROM_PROTOCOL_INFO)
4761 type = lpProtocolInfo->iSocketType;
4762 if (protocol == FROM_PROTOCOL_INFO)
4763 protocol = lpProtocolInfo->iProtocol;
4766 if ( af == AF_UNSPEC) /* did they not specify the address family? */
4767 switch(protocol)
4769 case IPPROTO_TCP:
4770 if (type == SOCK_STREAM) { af = AF_INET; break; }
4771 case IPPROTO_UDP:
4772 if (type == SOCK_DGRAM) { af = AF_INET; break; }
4773 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
4776 SERVER_START_REQ( create_socket )
4778 req->family = af;
4779 req->type = type;
4780 req->protocol = protocol;
4781 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
4782 req->attributes = OBJ_INHERIT;
4783 req->flags = dwFlags;
4784 set_error( wine_server_call( req ) );
4785 ret = HANDLE2SOCKET( wine_server_ptr_handle( reply->handle ));
4787 SERVER_END_REQ;
4788 if (ret)
4790 TRACE("\tcreated %04lx\n", ret );
4791 return ret;
4794 if (GetLastError() == WSAEACCES) /* raw socket denied */
4796 if (type == SOCK_RAW)
4797 ERR_(winediag)("Failed to create a socket of type SOCK_RAW, this requires special permissions.\n");
4798 else
4799 ERR_(winediag)("Failed to create socket, this requires special permissions.\n");
4800 SetLastError(WSAESOCKTNOSUPPORT);
4803 WARN("\t\tfailed!\n");
4804 return INVALID_SOCKET;
4807 /***********************************************************************
4808 * WSAJoinLeaf (WS2_32.58)
4811 SOCKET WINAPI WSAJoinLeaf(
4812 SOCKET s,
4813 const struct WS_sockaddr *addr,
4814 int addrlen,
4815 LPWSABUF lpCallerData,
4816 LPWSABUF lpCalleeData,
4817 LPQOS lpSQOS,
4818 LPQOS lpGQOS,
4819 DWORD dwFlags)
4821 FIXME("stub.\n");
4822 return INVALID_SOCKET;
4825 /***********************************************************************
4826 * __WSAFDIsSet (WS2_32.151)
4828 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
4830 int i = set->fd_count;
4832 TRACE("(%ld,%p(%i))\n", s, set, i);
4834 while (i--)
4835 if (set->fd_array[i] == s) return 1;
4836 return 0;
4839 /***********************************************************************
4840 * WSAIsBlocking (WS2_32.114)
4842 BOOL WINAPI WSAIsBlocking(void)
4844 /* By default WinSock should set all its sockets to non-blocking mode
4845 * and poll in PeekMessage loop when processing "blocking" ones. This
4846 * function is supposed to tell if the program is in this loop. Our
4847 * blocking calls are truly blocking so we always return FALSE.
4849 * Note: It is allowed to call this function without prior WSAStartup().
4852 TRACE("\n");
4853 return FALSE;
4856 /***********************************************************************
4857 * WSACancelBlockingCall (WS2_32.113)
4859 INT WINAPI WSACancelBlockingCall(void)
4861 TRACE("\n");
4862 return 0;
4865 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
4867 FIXME("How was this called?\n");
4868 return x();
4872 /***********************************************************************
4873 * WSASetBlockingHook (WS2_32.109)
4875 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
4877 FARPROC prev = blocking_hook;
4878 blocking_hook = lpBlockFunc;
4879 TRACE("hook %p\n", lpBlockFunc);
4880 return prev;
4884 /***********************************************************************
4885 * WSAUnhookBlockingHook (WS2_32.110)
4887 INT WINAPI WSAUnhookBlockingHook(void)
4889 blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
4890 return 0;
4894 /* ----------------------------------- end of API stuff */
4896 /* ----------------------------------- helper functions -
4898 * TODO: Merge WS_dup_..() stuff into one function that
4899 * would operate with a generic structure containing internal
4900 * pointers (via a template of some kind).
4903 static int list_size(char** l, int item_size)
4905 int i,j = 0;
4906 if(l)
4907 { for(i=0;l[i];i++)
4908 j += (item_size) ? item_size : strlen(l[i]) + 1;
4909 j += (i + 1) * sizeof(char*); }
4910 return j;
4913 static int list_dup(char** l_src, char** l_to, int item_size)
4915 char *p;
4916 int i;
4918 for (i = 0; l_src[i]; i++) ;
4919 p = (char *)(l_to + i + 1);
4920 for (i = 0; l_src[i]; i++)
4922 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
4923 memcpy(p, l_src[i], count);
4924 l_to[i] = p;
4925 p += count;
4927 l_to[i] = NULL;
4928 return p - (char *)l_to;
4931 /* ----- hostent */
4933 /* create a hostent entry
4935 * Creates the entry with enough memory for the name, aliases
4936 * addresses, and the address pointers. Also copies the name
4937 * and sets up all the pointers. If "fill_addresses" is set then
4938 * sufficient memory for the addresses is also allocated and the
4939 * address pointers are set to this memory.
4941 * NOTE: The alias and address lists must be allocated with room
4942 * for the NULL item terminating the list. This is true even if
4943 * the list has no items ("aliases" and "addresses" must be
4944 * at least "1", a truly empty list is invalid).
4946 static struct WS_hostent *WS_create_he(char *name, int aliases, int addresses, int fill_addresses)
4948 struct WS_hostent *p_to;
4949 char *p;
4951 int size = (sizeof(struct WS_hostent) +
4952 strlen(name) + 1 +
4953 sizeof(char *)*aliases +
4954 sizeof(char *)*addresses);
4956 /* Allocate enough memory for the addresses */
4957 if (fill_addresses)
4958 size += sizeof(struct in_addr)*addresses;
4960 if (!(p_to = check_buffer_he(size))) return NULL;
4961 memset(p_to, 0, size);
4963 p = (char *)(p_to + 1);
4964 p_to->h_name = p;
4965 strcpy(p, name);
4966 p += strlen(p) + 1;
4968 p_to->h_aliases = (char **)p;
4969 p += sizeof(char *)*aliases;
4970 p_to->h_addr_list = (char **)p;
4971 p += sizeof(char *)*addresses;
4972 if (fill_addresses)
4974 int i;
4976 /* NOTE: h_aliases must be filled in manually, leave these
4977 * pointers NULL (already set to NULL by memset earlier).
4980 /* Fill in the list of address pointers */
4981 for (i = 0; i < addresses; i++)
4982 p_to->h_addr_list[i] = (p += sizeof(struct in_addr));
4983 p += sizeof(struct in_addr);
4985 return p_to;
4988 /* duplicate hostent entry
4989 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
4990 * Ditto for protoent and servent.
4992 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
4994 int addresses = list_size(p_he->h_addr_list, p_he->h_length);
4995 int aliases = list_size(p_he->h_aliases, 0);
4996 struct WS_hostent *p_to;
4998 p_to = WS_create_he(p_he->h_name, aliases, addresses, FALSE);
5000 if (!p_to) return NULL;
5001 p_to->h_addrtype = p_he->h_addrtype;
5002 p_to->h_length = p_he->h_length;
5004 list_dup(p_he->h_aliases, p_to->h_aliases, 0);
5005 list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
5006 return p_to;
5009 /* ----- protoent */
5011 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
5013 char *p;
5014 struct WS_protoent *p_to;
5016 int size = (sizeof(*p_pe) +
5017 strlen(p_pe->p_name) + 1 +
5018 list_size(p_pe->p_aliases, 0));
5020 if (!(p_to = check_buffer_pe(size))) return NULL;
5021 p_to->p_proto = p_pe->p_proto;
5023 p = (char *)(p_to + 1);
5024 p_to->p_name = p;
5025 strcpy(p, p_pe->p_name);
5026 p += strlen(p) + 1;
5028 p_to->p_aliases = (char **)p;
5029 list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
5030 return p_to;
5033 /* ----- servent */
5035 static struct WS_servent *WS_dup_se(const struct servent* p_se)
5037 char *p;
5038 struct WS_servent *p_to;
5040 int size = (sizeof(*p_se) +
5041 strlen(p_se->s_proto) + 1 +
5042 strlen(p_se->s_name) + 1 +
5043 list_size(p_se->s_aliases, 0));
5045 if (!(p_to = check_buffer_se(size))) return NULL;
5046 p_to->s_port = p_se->s_port;
5048 p = (char *)(p_to + 1);
5049 p_to->s_name = p;
5050 strcpy(p, p_se->s_name);
5051 p += strlen(p) + 1;
5053 p_to->s_proto = p;
5054 strcpy(p, p_se->s_proto);
5055 p += strlen(p) + 1;
5057 p_to->s_aliases = (char **)p;
5058 list_dup(p_se->s_aliases, p_to->s_aliases, 0);
5059 return p_to;
5063 /***********************************************************************
5064 * WSARecv (WS2_32.67)
5066 int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
5067 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
5068 LPWSAOVERLAPPED lpOverlapped,
5069 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
5071 return WSARecvFrom(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
5072 NULL, NULL, lpOverlapped, lpCompletionRoutine);
5075 /***********************************************************************
5076 * WSARecvFrom (WS2_32.69)
5078 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
5079 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
5080 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
5081 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
5084 unsigned int i, options;
5085 int n, fd, err;
5086 struct ws2_async *wsa;
5087 DWORD timeout_start = GetTickCount();
5088 ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
5090 TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, from %p, fromlen %d, ovl %p, func %p\n",
5091 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
5092 (lpFromlen ? *lpFromlen : -1),
5093 lpOverlapped, lpCompletionRoutine);
5095 fd = get_sock_fd( s, FILE_READ_DATA, &options );
5096 TRACE( "fd=%d, options=%x\n", fd, options );
5098 if (fd == -1) return SOCKET_ERROR;
5100 if (!(wsa = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(struct ws2_async, iovec[dwBufferCount]) )))
5102 err = WSAEFAULT;
5103 goto error;
5106 wsa->hSocket = SOCKET2HANDLE(s);
5107 wsa->flags = *lpFlags;
5108 wsa->addr = lpFrom;
5109 wsa->addrlen.ptr = lpFromlen;
5110 wsa->n_iovecs = dwBufferCount;
5111 wsa->first_iovec = 0;
5112 for (i = 0; i < dwBufferCount; i++)
5114 /* check buffer first to trigger write watches */
5115 if (IsBadWritePtr( lpBuffers[i].buf, lpBuffers[i].len ))
5117 err = WSAEFAULT;
5118 goto error;
5120 wsa->iovec[i].iov_base = lpBuffers[i].buf;
5121 wsa->iovec[i].iov_len = lpBuffers[i].len;
5124 for (;;)
5126 n = WS2_recv( fd, wsa );
5127 if (n == -1)
5129 if (errno == EINTR) continue;
5130 if (errno != EAGAIN)
5132 int loc_errno = errno;
5133 err = wsaErrno();
5134 if (cvalue) WS_AddCompletion( s, cvalue, sock_get_ntstatus(loc_errno), 0 );
5135 goto error;
5138 else
5139 *lpNumberOfBytesRecvd = n;
5141 if ((lpOverlapped || lpCompletionRoutine) &&
5142 !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
5144 IO_STATUS_BLOCK *iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
5146 wsa->user_overlapped = lpOverlapped;
5147 wsa->completion_func = lpCompletionRoutine;
5148 release_sock_fd( s, fd );
5150 if (n == -1)
5152 iosb->u.Status = STATUS_PENDING;
5153 iosb->Information = 0;
5155 SERVER_START_REQ( register_async )
5157 req->type = ASYNC_TYPE_READ;
5158 req->async.handle = wine_server_obj_handle( wsa->hSocket );
5159 req->async.callback = wine_server_client_ptr( WS2_async_recv );
5160 req->async.iosb = wine_server_client_ptr( iosb );
5161 req->async.arg = wine_server_client_ptr( wsa );
5162 req->async.event = wine_server_obj_handle( lpCompletionRoutine ? 0 : lpOverlapped->hEvent );
5163 req->async.cvalue = cvalue;
5164 err = wine_server_call( req );
5166 SERVER_END_REQ;
5168 if (err != STATUS_PENDING) HeapFree( GetProcessHeap(), 0, wsa );
5169 WSASetLastError( NtStatusToWSAError( err ));
5170 return SOCKET_ERROR;
5173 iosb->u.Status = STATUS_SUCCESS;
5174 iosb->Information = n;
5175 if (!wsa->completion_func)
5177 if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n );
5178 if (lpOverlapped->hEvent) SetEvent( lpOverlapped->hEvent );
5179 HeapFree( GetProcessHeap(), 0, wsa );
5181 else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc,
5182 (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 );
5183 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
5184 return 0;
5187 if (n != -1) break;
5189 if ( _is_blocking(s) )
5191 struct pollfd pfd;
5192 int timeout = GET_RCVTIMEO(fd);
5193 if (timeout != -1)
5195 timeout -= GetTickCount() - timeout_start;
5196 if (timeout < 0) timeout = 0;
5199 pfd.fd = fd;
5200 pfd.events = POLLIN;
5201 if (*lpFlags & WS_MSG_OOB) pfd.events |= POLLPRI;
5203 if (!timeout || !poll( &pfd, 1, timeout ))
5205 err = WSAETIMEDOUT;
5206 /* a timeout is not fatal */
5207 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
5208 goto error;
5211 else
5213 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
5214 err = WSAEWOULDBLOCK;
5215 goto error;
5219 TRACE(" -> %i bytes\n", n);
5220 HeapFree( GetProcessHeap(), 0, wsa );
5221 release_sock_fd( s, fd );
5222 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
5224 return 0;
5226 error:
5227 HeapFree( GetProcessHeap(), 0, wsa );
5228 release_sock_fd( s, fd );
5229 WARN(" -> ERROR %d\n", err);
5230 WSASetLastError( err );
5231 return SOCKET_ERROR;
5234 /***********************************************************************
5235 * WSCInstallProvider (WS2_32.88)
5237 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
5238 LPCWSTR lpszProviderDllPath,
5239 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
5240 DWORD dwNumberOfEntries,
5241 LPINT lpErrno )
5243 FIXME("(%s, %s, %p, %d, %p): stub !\n", debugstr_guid(lpProviderId),
5244 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
5245 dwNumberOfEntries, lpErrno);
5246 *lpErrno = 0;
5247 return 0;
5251 /***********************************************************************
5252 * WSCDeinstallProvider (WS2_32.83)
5254 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
5256 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
5257 *lpErrno = 0;
5258 return 0;
5262 /***********************************************************************
5263 * WSAAccept (WS2_32.26)
5265 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
5266 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
5269 int ret = 0, size = 0;
5270 WSABUF CallerId, CallerData, CalleeId, CalleeData;
5271 /* QOS SQOS, GQOS; */
5272 GROUP g;
5273 SOCKET cs;
5274 SOCKADDR src_addr, dst_addr;
5276 TRACE("Socket %04lx, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %d\n",
5277 s, addr, addrlen, lpfnCondition, dwCallbackData);
5280 size = sizeof(src_addr);
5281 cs = WS_accept(s, &src_addr, &size);
5283 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
5285 if (!lpfnCondition) return cs;
5287 CallerId.buf = (char *)&src_addr;
5288 CallerId.len = sizeof(src_addr);
5290 CallerData.buf = NULL;
5291 CallerData.len = 0;
5293 WS_getsockname(cs, &dst_addr, &size);
5295 CalleeId.buf = (char *)&dst_addr;
5296 CalleeId.len = sizeof(dst_addr);
5299 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
5300 &CalleeId, &CalleeData, &g, dwCallbackData);
5302 switch (ret)
5304 case CF_ACCEPT:
5305 if (addr && addrlen)
5306 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
5307 return cs;
5308 case CF_DEFER:
5309 SERVER_START_REQ( set_socket_deferred )
5311 req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
5312 req->deferred = wine_server_obj_handle( SOCKET2HANDLE(cs) );
5313 if ( !wine_server_call_err ( req ) )
5315 SetLastError( WSATRY_AGAIN );
5316 WS_closesocket( cs );
5319 SERVER_END_REQ;
5320 return SOCKET_ERROR;
5321 case CF_REJECT:
5322 WS_closesocket(cs);
5323 SetLastError(WSAECONNREFUSED);
5324 return SOCKET_ERROR;
5325 default:
5326 FIXME("Unknown return type from Condition function\n");
5327 SetLastError(WSAENOTSOCK);
5328 return SOCKET_ERROR;
5332 /***********************************************************************
5333 * AcceptEx (ws2_32.@)
5335 * Accept a new connection, retrieving the connected addresses and initial data.
5337 * listener [I] Listening socket
5338 * acceptor [I] Socket to accept on
5339 * dest [O] Destination for inital data
5340 * dest_len [I] Size of dest in bytes
5341 * local_addr_len [I] Number of bytes reserved in dest for local addrress
5342 * rem_addr_len [I] Number of bytes reserved in dest for remote addrress
5343 * received [O] Destination for number of bytes of initial data
5344 * overlapped [I] For asynchronous execution
5346 * RETURNS
5347 * Success: TRUE (Does this ever happen on windows?)
5348 * Failure: FALSE. Use WSAGetLastError() for details of the error.
5350 BOOL WINAPI AcceptEx( SOCKET listener, SOCKET acceptor, PVOID dest, DWORD dest_len, DWORD local_addr_len,
5351 DWORD rem_addr_len, LPDWORD received, LPOVERLAPPED overlapped )
5353 DWORD status;
5354 struct ws2_accept_async *wsa;
5355 ULONG_PTR cvalue = (overlapped && ((ULONG_PTR)overlapped->hEvent & 1) == 0) ? (ULONG_PTR)overlapped : 0;
5357 TRACE("(%lx, %lx, %p, %d, %d, %d, %p, %p)\n", listener, acceptor, dest, dest_len, local_addr_len,
5358 rem_addr_len, received, overlapped);
5360 if (!dest)
5362 set_error(STATUS_INVALID_PARAMETER);
5363 return FALSE;
5366 if (!overlapped)
5368 WSASetLastError(WSA_INVALID_PARAMETER);
5369 return FALSE;
5372 wsa = HeapAlloc( GetProcessHeap(), 0, sizeof(*wsa) );
5373 if(!wsa)
5375 set_error(ERROR_NOT_ENOUGH_MEMORY);
5376 return FALSE;
5379 wsa->s_listen = listener;
5380 wsa->s_accept = acceptor;
5381 wsa->user_overlapped = overlapped;
5382 wsa->cvalue = cvalue;
5383 wsa->buf = dest;
5384 wsa->data_len = dest_len;
5385 wsa->local_len = local_addr_len;
5386 wsa->remote_len = rem_addr_len;
5387 wsa->read = NULL;
5389 SERVER_START_REQ( register_accept_async )
5391 req->data.handle = wine_server_obj_handle( SOCKET2HANDLE(wsa->s_listen) );
5392 req->ahandle = wine_server_obj_handle( SOCKET2HANDLE(wsa->s_accept) );
5393 req->data.callback = wine_server_client_ptr( WS2_async_accept );
5394 req->data.iosb = wine_server_client_ptr( wsa->user_overlapped );
5395 req->data.arg = wine_server_client_ptr( wsa );
5396 req->data.cvalue = 0;
5397 status = wine_server_call( req );
5399 SERVER_END_REQ;
5401 if(status != STATUS_PENDING)
5403 FIXME("Failed to query async: %x\n", status);
5404 HeapFree( GetProcessHeap(), 0, wsa );
5405 set_error(status);
5406 return FALSE;
5409 set_error( STATUS_PENDING );
5410 return FALSE;
5413 /***********************************************************************
5414 * GetAcceptExSockaddrs (ws2_32.@)
5416 * Get infomation about an accepted socket.
5418 * buf [O] Destination for the first block of data from AcceptEx()
5419 * data_size [I] length of data in bytes
5420 * local_size [I] Bytes reserved for local addrinfo
5421 * remote_size [I] Bytes reserved for remote addrinfo
5422 * local_addr [O] Destination for local sockaddr
5423 * local_addr_len [I] Size of local_addr
5424 * remote_addr [O] Destination for remote sockaddr
5425 * remote_addr_len [I] Size of rem_addr
5427 * RETURNS
5428 * Nothing.
5430 void WINAPI GetAcceptExSockaddrs( PVOID buf, DWORD data_size, DWORD local_size, DWORD remote_size,
5431 struct sockaddr **local_addr, LPINT local_addr_len,
5432 struct sockaddr **remote_addr, LPINT remote_addr_len )
5434 char *cbuf = buf;
5435 TRACE("(%p, %d, %d, %d, %p, %p, %p, %p)\n", buf, data_size, local_size, remote_size, local_addr,
5436 local_addr_len, remote_addr, remote_addr_len );
5437 cbuf += data_size;
5439 *local_addr_len = *(int *) cbuf;
5440 *local_addr = (struct sockaddr *)(cbuf + sizeof(int));
5442 cbuf += local_size;
5444 *remote_addr_len = *(int *) cbuf;
5445 *remote_addr = (struct sockaddr *)(cbuf + sizeof(int));
5448 /***********************************************************************
5449 * WSADuplicateSocketA (WS2_32.32)
5451 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
5453 HANDLE hProcess;
5455 TRACE("(%ld,%x,%p)\n", s, dwProcessId, lpProtocolInfo);
5456 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
5457 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
5458 /* I don't know what the real Windoze does next, this is a hack */
5459 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
5460 * the target use the global duplicate, or we could copy a reference to us to the structure
5461 * and let the target duplicate it from us, but let's do it as simple as possible */
5462 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
5463 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
5464 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
5465 0, FALSE, DUPLICATE_SAME_ACCESS);
5466 CloseHandle(hProcess);
5467 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
5468 return 0;
5471 /***********************************************************************
5472 * WSADuplicateSocketW (WS2_32.33)
5474 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
5476 HANDLE hProcess;
5478 TRACE("(%ld,%x,%p)\n", s, dwProcessId, lpProtocolInfo);
5480 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
5481 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
5482 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
5483 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
5484 0, FALSE, DUPLICATE_SAME_ACCESS);
5485 CloseHandle(hProcess);
5486 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
5487 return 0;
5490 /***********************************************************************
5491 * WSAInstallServiceClassA (WS2_32.48)
5493 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
5495 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
5496 WSASetLastError(WSAEACCES);
5497 return SOCKET_ERROR;
5500 /***********************************************************************
5501 * WSAInstallServiceClassW (WS2_32.49)
5503 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
5505 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
5506 WSASetLastError(WSAEACCES);
5507 return SOCKET_ERROR;
5510 /***********************************************************************
5511 * WSARemoveServiceClass (WS2_32.70)
5513 int WINAPI WSARemoveServiceClass(LPGUID info)
5515 FIXME("Request to remove service %p\n",info);
5516 WSASetLastError(WSATYPE_NOT_FOUND);
5517 return SOCKET_ERROR;
5520 /***********************************************************************
5521 * inet_ntop (WS2_32.@)
5523 PCSTR WINAPI WS_inet_ntop( INT family, PVOID addr, PSTR buffer, SIZE_T len )
5525 #ifdef HAVE_INET_NTOP
5526 struct WS_in6_addr *in6;
5527 struct WS_in_addr *in;
5528 PCSTR pdst;
5530 TRACE("family %d, addr (%p), buffer (%p), len %ld\n", family, addr, buffer, len);
5531 if (!buffer)
5533 WSASetLastError( STATUS_INVALID_PARAMETER );
5534 return NULL;
5537 switch (family)
5539 case WS_AF_INET:
5541 in = addr;
5542 pdst = inet_ntop( AF_INET, &in->WS_s_addr, buffer, len );
5543 break;
5545 case WS_AF_INET6:
5547 in6 = addr;
5548 pdst = inet_ntop( AF_INET6, in6->WS_s6_addr, buffer, len );
5549 break;
5551 default:
5552 WSASetLastError( WSAEAFNOSUPPORT );
5553 return NULL;
5556 if (!pdst) WSASetLastError( STATUS_INVALID_PARAMETER );
5557 return pdst;
5558 #else
5559 FIXME( "not supported on this platform\n" );
5560 WSASetLastError( WSAEAFNOSUPPORT );
5561 return NULL;
5562 #endif
5565 /***********************************************************************
5566 * WSAStringToAddressA (WS2_32.80)
5568 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
5569 INT AddressFamily,
5570 LPWSAPROTOCOL_INFOA lpProtocolInfo,
5571 LPSOCKADDR lpAddress,
5572 LPINT lpAddressLength)
5574 INT res=0;
5575 LPSTR workBuffer=NULL,ptrPort;
5577 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_a(AddressString), AddressFamily,
5578 lpProtocolInfo, lpAddress, lpAddressLength );
5580 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
5582 if (!AddressString)
5584 WSASetLastError(WSAEINVAL);
5585 return SOCKET_ERROR;
5588 if (lpProtocolInfo)
5589 FIXME("ProtocolInfo not implemented.\n");
5591 workBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5592 strlen(AddressString) + 1);
5593 if (!workBuffer)
5595 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
5596 return SOCKET_ERROR;
5599 strcpy(workBuffer, AddressString);
5601 switch(AddressFamily)
5603 case WS_AF_INET:
5605 struct in_addr inetaddr;
5607 /* If lpAddressLength is too small, tell caller the size we need */
5608 if (*lpAddressLength < sizeof(SOCKADDR_IN))
5610 *lpAddressLength = sizeof(SOCKADDR_IN);
5611 res = WSAEFAULT;
5612 break;
5614 memset(lpAddress, 0, sizeof(SOCKADDR_IN));
5616 ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET;
5618 ptrPort = strchr(workBuffer, ':');
5619 if(ptrPort)
5621 ((LPSOCKADDR_IN)lpAddress)->sin_port = htons(atoi(ptrPort+1));
5622 *ptrPort = '\0';
5624 else
5626 ((LPSOCKADDR_IN)lpAddress)->sin_port = 0;
5629 if(inet_aton(workBuffer, &inetaddr) > 0)
5631 ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr;
5632 res = 0;
5634 else
5635 res = WSAEINVAL;
5637 break;
5640 case WS_AF_INET6:
5642 struct in6_addr inetaddr;
5643 /* If lpAddressLength is too small, tell caller the size we need */
5644 if (*lpAddressLength < sizeof(SOCKADDR_IN6))
5646 *lpAddressLength = sizeof(SOCKADDR_IN6);
5647 res = WSAEFAULT;
5648 break;
5650 #ifdef HAVE_INET_PTON
5651 memset(lpAddress, 0, sizeof(SOCKADDR_IN6));
5653 ((LPSOCKADDR_IN6)lpAddress)->sin6_family = WS_AF_INET6;
5655 /* This one is a bit tricky. An IPv6 address contains colons, so the
5656 * check from IPv4 doesn't work like that. However, IPv6 addresses that
5657 * contain a port are written with braces like [fd12:3456:7890::1]:12345
5658 * so what we will do is to look for ']', check if the next char is a
5659 * colon, and if it is, parse the port as in IPv4. */
5661 ptrPort = strchr(workBuffer, ']');
5662 if(ptrPort && *(++ptrPort) == ':')
5664 ((LPSOCKADDR_IN6)lpAddress)->sin6_port = htons(atoi(ptrPort+1));
5665 *ptrPort = '\0';
5667 else
5669 ((LPSOCKADDR_IN6)lpAddress)->sin6_port = 0;
5672 if(inet_pton(AF_INET6, workBuffer, &inetaddr) > 0)
5674 memcpy(&((LPSOCKADDR_IN6)lpAddress)->sin6_addr, &inetaddr,
5675 sizeof(struct in6_addr));
5676 res = 0;
5678 else
5679 #endif /* HAVE_INET_PTON */
5680 res = WSAEINVAL;
5682 break;
5684 default:
5685 /* According to MSDN, only AF_INET and AF_INET6 are supported. */
5686 TRACE("Unsupported address family specified: %d.\n", AddressFamily);
5687 res = WSAEINVAL;
5690 HeapFree(GetProcessHeap(), 0, workBuffer);
5692 if (!res) return 0;
5693 WSASetLastError(res);
5694 return SOCKET_ERROR;
5697 /***********************************************************************
5698 * WSAStringToAddressW (WS2_32.81)
5700 * Does anybody know if this functions allows to use hebrew/arabic/chinese... digits?
5701 * If this should be the case, it would be required to map these digits
5702 * to Unicode digits (0-9) using FoldString first.
5704 INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
5705 INT AddressFamily,
5706 LPWSAPROTOCOL_INFOW lpProtocolInfo,
5707 LPSOCKADDR lpAddress,
5708 LPINT lpAddressLength)
5710 INT sBuffer,res=0;
5711 LPSTR workBuffer=NULL;
5712 WSAPROTOCOL_INFOA infoA;
5713 LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
5715 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
5716 lpAddress, lpAddressLength );
5718 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
5720 /* if ProtocolInfo is available - convert to ANSI variant */
5721 if (lpProtocolInfo)
5723 lpProtoInfoA = &infoA;
5724 memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
5726 if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
5727 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
5729 WSASetLastError( WSAEINVAL);
5730 return SOCKET_ERROR;
5734 if (AddressString)
5736 /* Translate AddressString to ANSI code page - assumes that only
5737 standard digits 0-9 are used with this API call */
5738 sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
5739 workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
5741 if (workBuffer)
5743 WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
5744 res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
5745 lpAddress,lpAddressLength);
5746 HeapFree( GetProcessHeap(), 0, workBuffer );
5747 return res;
5749 else
5750 res = WSA_NOT_ENOUGH_MEMORY;
5752 else
5753 res = WSAEINVAL;
5755 WSASetLastError(res);
5756 return SOCKET_ERROR;
5759 /***********************************************************************
5760 * WSAAddressToStringA (WS2_32.27)
5762 * See WSAAddressToStringW
5764 INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
5765 LPWSAPROTOCOL_INFOA info, LPSTR string,
5766 LPDWORD lenstr )
5768 DWORD size;
5769 CHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
5770 CHAR *p;
5772 TRACE( "(%p, %d, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
5774 if (!sockaddr) return SOCKET_ERROR;
5775 if (!string || !lenstr) return SOCKET_ERROR;
5777 switch(sockaddr->sa_family)
5779 case WS_AF_INET:
5780 if (len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
5781 sprintf( buffer, "%u.%u.%u.%u:%u",
5782 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
5783 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
5784 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
5785 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
5786 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
5788 p = strchr( buffer, ':' );
5789 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
5790 break;
5792 case WS_AF_INET6:
5794 struct WS_sockaddr_in6 *sockaddr6 = (LPSOCKADDR_IN6) sockaddr;
5796 buffer[0] = 0;
5797 if (len < sizeof(SOCKADDR_IN6)) return SOCKET_ERROR;
5798 if ((sockaddr6->sin6_port))
5799 strcpy(buffer, "[");
5800 if (!WS_inet_ntop(WS_AF_INET6, &sockaddr6->sin6_addr, buffer+strlen(buffer), sizeof(buffer)))
5802 WSASetLastError(WSAEINVAL);
5803 return SOCKET_ERROR;
5805 if ((sockaddr6->sin6_scope_id))
5806 sprintf(buffer+strlen(buffer), "%%%u", sockaddr6->sin6_scope_id);
5807 if ((sockaddr6->sin6_port))
5808 sprintf(buffer+strlen(buffer), "]:%u", ntohs(sockaddr6->sin6_port));
5809 break;
5812 default:
5813 WSASetLastError(WSAEINVAL);
5814 return SOCKET_ERROR;
5817 size = strlen( buffer ) + 1;
5819 if (*lenstr < size)
5821 *lenstr = size;
5822 WSASetLastError(WSAEFAULT);
5823 return SOCKET_ERROR;
5826 *lenstr = size;
5827 strcpy( string, buffer );
5828 return 0;
5831 /***********************************************************************
5832 * WSAAddressToStringW (WS2_32.28)
5834 * Convert a sockaddr address into a readable address string.
5836 * PARAMS
5837 * sockaddr [I] Pointer to a sockaddr structure.
5838 * len [I] Size of the sockaddr structure.
5839 * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional).
5840 * string [I/O] Pointer to a buffer to receive the address string.
5841 * lenstr [I/O] Size of the receive buffer in WCHARs.
5843 * RETURNS
5844 * Success: 0
5845 * Failure: SOCKET_ERROR
5847 * NOTES
5848 * The 'info' parameter is ignored.
5850 INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
5851 LPWSAPROTOCOL_INFOW info, LPWSTR string,
5852 LPDWORD lenstr )
5854 INT ret;
5855 DWORD size;
5856 WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
5857 CHAR bufAddr[54];
5859 TRACE( "(%p, %d, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
5861 size = *lenstr;
5862 ret = WSAAddressToStringA(sockaddr, len, NULL, bufAddr, &size);
5864 if (ret) return ret;
5866 MultiByteToWideChar( CP_ACP, 0, bufAddr, size, buffer, sizeof( buffer )/sizeof(WCHAR));
5868 if (*lenstr < size)
5870 *lenstr = size;
5871 WSASetLastError(WSAEFAULT);
5872 return SOCKET_ERROR;
5875 *lenstr = size;
5876 lstrcpyW( string, buffer );
5877 return 0;
5880 /***********************************************************************
5881 * WSAEnumNameSpaceProvidersA (WS2_32.34)
5883 INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
5885 FIXME( "(%p %p) Stub!\n", len, buffer );
5886 return 0;
5889 /***********************************************************************
5890 * WSAEnumNameSpaceProvidersW (WS2_32.35)
5892 INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
5894 FIXME( "(%p %p) Stub!\n", len, buffer );
5895 return 0;
5898 /***********************************************************************
5899 * WSAGetQOSByName (WS2_32.41)
5901 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
5903 FIXME( "(0x%04lx %p %p) Stub!\n", s, lpQOSName, lpQOS );
5904 return FALSE;
5907 /***********************************************************************
5908 * WSAGetServiceClassInfoA (WS2_32.42)
5910 INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
5911 LPWSASERVICECLASSINFOA info )
5913 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
5914 len, info );
5915 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
5916 return SOCKET_ERROR;
5919 /***********************************************************************
5920 * WSAGetServiceClassInfoW (WS2_32.43)
5922 INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
5923 LPWSASERVICECLASSINFOW info )
5925 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
5926 len, info );
5927 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
5928 return SOCKET_ERROR;
5931 /***********************************************************************
5932 * WSAGetServiceClassNameByClassIdA (WS2_32.44)
5934 INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
5936 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
5937 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
5938 return SOCKET_ERROR;
5941 /***********************************************************************
5942 * WSAGetServiceClassNameByClassIdW (WS2_32.45)
5944 INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
5946 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
5947 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
5948 return SOCKET_ERROR;
5951 /***********************************************************************
5952 * WSALookupServiceBeginA (WS2_32.59)
5954 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
5955 DWORD dwControlFlags,
5956 LPHANDLE lphLookup)
5958 FIXME("(%p 0x%08x %p) Stub!\n", lpqsRestrictions, dwControlFlags,
5959 lphLookup);
5960 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
5961 return SOCKET_ERROR;
5964 /***********************************************************************
5965 * WSALookupServiceBeginW (WS2_32.60)
5967 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
5968 DWORD dwControlFlags,
5969 LPHANDLE lphLookup)
5971 FIXME("(%p 0x%08x %p) Stub!\n", lpqsRestrictions, dwControlFlags,
5972 lphLookup);
5973 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
5974 return SOCKET_ERROR;
5977 /***********************************************************************
5978 * WSALookupServiceBeginW (WS2_32.61)
5980 INT WINAPI WSALookupServiceEnd( HANDLE lookup )
5982 FIXME("(%p) Stub!\n", lookup );
5983 return 0;
5986 /***********************************************************************
5987 * WSALookupServiceNextA (WS2_32.62)
5989 INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
5991 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup, flags, len, results );
5992 return 0;
5995 /***********************************************************************
5996 * WSALookupServiceNextW (WS2_32.63)
5998 INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
6000 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup, flags, len, results );
6001 return 0;
6004 /***********************************************************************
6005 * WSANtohl (WS2_32.64)
6007 INT WINAPI WSANtohl( SOCKET s, WS_u_long netlong, WS_u_long* lphostlong )
6009 TRACE( "(0x%04lx 0x%08x %p)\n", s, netlong, lphostlong );
6011 if (!lphostlong) return WSAEFAULT;
6013 *lphostlong = ntohl( netlong );
6014 return 0;
6017 /***********************************************************************
6018 * WSANtohs (WS2_32.65)
6020 INT WINAPI WSANtohs( SOCKET s, WS_u_short netshort, WS_u_short* lphostshort )
6022 TRACE( "(0x%04lx 0x%08x %p)\n", s, netshort, lphostshort );
6024 if (!lphostshort) return WSAEFAULT;
6026 *lphostshort = ntohs( netshort );
6027 return 0;
6030 /***********************************************************************
6031 * WSAProviderConfigChange (WS2_32.66)
6033 INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
6034 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
6036 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
6037 return SOCKET_ERROR;
6040 /***********************************************************************
6041 * WSARecvDisconnect (WS2_32.68)
6043 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
6045 TRACE( "(0x%04lx %p)\n", s, disconnectdata );
6047 return WS_shutdown( s, 0 );
6050 /***********************************************************************
6051 * WSASetServiceA (WS2_32.76)
6053 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
6055 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query, operation, flags );
6056 return 0;
6059 /***********************************************************************
6060 * WSASetServiceW (WS2_32.77)
6062 INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
6064 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query, operation, flags );
6065 return 0;
6068 /***********************************************************************
6069 * WSCEnableNSProvider (WS2_32.84)
6071 INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
6073 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
6074 return 0;
6077 /***********************************************************************
6078 * WSCGetProviderPath (WS2_32.86)
6080 INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errcode )
6082 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errcode );
6084 if (!errcode || !provider || !len) return WSAEFAULT;
6086 *errcode = WSAEINVAL;
6087 return SOCKET_ERROR;
6090 /***********************************************************************
6091 * WSCInstallNameSpace (WS2_32.87)
6093 INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
6094 DWORD version, LPGUID provider )
6096 FIXME( "(%s %s 0x%08x 0x%08x %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
6097 namespace, version, debugstr_guid(provider) );
6098 return 0;
6101 /***********************************************************************
6102 * WSCUnInstallNameSpace (WS2_32.89)
6104 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
6106 FIXME("(%p) Stub!\n", lpProviderId);
6107 return NO_ERROR;
6110 /***********************************************************************
6111 * WSCWriteProviderOrder (WS2_32.91)
6113 INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
6115 FIXME("(%p 0x%08x) Stub!\n", entry, number);
6116 return 0;