winsock: AF_UNSPEC mapping.
[wine/multimedia.git] / dlls / winsock / socket.c
blobe47b18260f365a12dd945a3e6b8e6daf38cc1bb3
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
5 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
6 * Copyright (C) 2005 Marcus Meissner
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 # include <linux/ipx.h>
107 # define HAVE_IPX
108 #endif
110 #ifdef HAVE_POLL_H
111 #include <poll.h>
112 #endif
113 #ifdef HAVE_SYS_POLL_H
114 # include <sys/poll.h>
115 #endif
116 #ifdef HAVE_SYS_TIME_H
117 # include <sys/time.h>
118 #endif
120 #define NONAMELESSUNION
121 #define NONAMELESSSTRUCT
122 #include "ntstatus.h"
123 #define WIN32_NO_STATUS
124 #include "windef.h"
125 #include "winbase.h"
126 #include "wingdi.h"
127 #include "winuser.h"
128 #include "winerror.h"
129 #include "winnls.h"
130 #include "winsock2.h"
131 #include "mswsock.h"
132 #include "ws2tcpip.h"
133 #include "ws2spi.h"
134 #include "wsipx.h"
135 #include "winnt.h"
136 #include "iphlpapi.h"
137 #include "thread.h"
138 #include "wine/server.h"
139 #include "wine/debug.h"
140 #include "wine/unicode.h"
142 #ifdef HAVE_IPX
143 # include "wsnwlink.h"
144 #endif
147 #ifdef __FreeBSD__
148 # define sipx_network sipx_addr.x_net
149 # define sipx_node sipx_addr.x_host.c_host
150 #endif /* __FreeBSD__ */
152 #ifndef INADDR_NONE
153 #define INADDR_NONE ~0UL
154 #endif
156 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
158 /* critical section to protect some non-rentrant net function */
159 extern CRITICAL_SECTION csWSgetXXXbyYYY;
161 inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
163 if (!a) return "(nil)";
164 return wine_dbg_sprintf("{ family %d, address %s, port %d }",
165 ((const struct sockaddr_in *)a)->sin_family,
166 inet_ntoa(((const struct sockaddr_in *)a)->sin_addr),
167 ntohs(((const struct sockaddr_in *)a)->sin_port));
170 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
171 #define SOCKET2HANDLE(s) ((HANDLE)(s))
172 #define HANDLE2SOCKET(h) ((SOCKET)(h))
174 /****************************************************************
175 * Async IO declarations
176 ****************************************************************/
178 typedef struct ws2_async
180 HANDLE hSocket;
181 enum ws2_mode {ws2m_read, ws2m_write, ws2m_sd_read, ws2m_sd_write} mode;
182 LPWSAOVERLAPPED user_overlapped;
183 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
184 struct iovec *iovec;
185 int n_iovecs;
186 struct WS_sockaddr *addr;
187 union
189 int val; /* for send operations */
190 int *ptr; /* for recv operations */
191 } addrlen;
192 DWORD flags;
193 int fd;
194 HANDLE event;
195 } ws2_async;
197 /****************************************************************/
199 /* ----------------------------------- internal data */
201 /* ws_... struct conversion flags */
203 typedef struct /* WSAAsyncSelect() control struct */
205 HANDLE service, event, sock;
206 HWND hWnd;
207 UINT uMsg;
208 LONG lEvent;
209 } ws_select_info;
211 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
212 #define WS_MAX_UDP_DATAGRAM 1024
213 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
215 /* hostent's, servent's and protent's are stored in one buffer per thread,
216 * as documented on MSDN for the functions that return any of the buffers */
217 struct per_thread_data
219 int opentype;
220 struct WS_hostent *he_buffer;
221 struct WS_servent *se_buffer;
222 struct WS_protoent *pe_buffer;
223 int he_len;
224 int se_len;
225 int pe_len;
228 static INT num_startup; /* reference counter */
229 static FARPROC blocking_hook = WSA_DefaultBlockingHook;
231 /* function prototypes */
232 static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
233 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
234 static struct WS_servent *WS_dup_se(const struct servent* p_se);
236 int WSAIOCTL_GetInterfaceCount(void);
237 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
239 UINT wsaErrno(void);
240 UINT wsaHerrno(int errnr);
242 #define MAP_OPTION(opt) { WS_##opt, opt }
244 static const int ws_sock_map[][2] =
246 MAP_OPTION( SO_DEBUG ),
247 MAP_OPTION( SO_REUSEADDR ),
248 MAP_OPTION( SO_KEEPALIVE ),
249 MAP_OPTION( SO_DONTROUTE ),
250 MAP_OPTION( SO_BROADCAST ),
251 MAP_OPTION( SO_LINGER ),
252 MAP_OPTION( SO_OOBINLINE ),
253 MAP_OPTION( SO_SNDBUF ),
254 MAP_OPTION( SO_RCVBUF ),
255 MAP_OPTION( SO_ERROR ),
256 MAP_OPTION( SO_TYPE ),
257 #ifdef SO_RCVTIMEO
258 MAP_OPTION( SO_RCVTIMEO ),
259 #endif
260 #ifdef SO_SNDTIMEO
261 MAP_OPTION( SO_SNDTIMEO ),
262 #endif
265 static const int ws_tcp_map[][2] =
267 #ifdef TCP_NODELAY
268 MAP_OPTION( TCP_NODELAY ),
269 #endif
272 static const int ws_ip_map[][2] =
274 MAP_OPTION( IP_MULTICAST_IF ),
275 MAP_OPTION( IP_MULTICAST_TTL ),
276 MAP_OPTION( IP_MULTICAST_LOOP ),
277 MAP_OPTION( IP_ADD_MEMBERSHIP ),
278 MAP_OPTION( IP_DROP_MEMBERSHIP ),
279 MAP_OPTION( IP_OPTIONS ),
280 #ifdef IP_HDRINCL
281 MAP_OPTION( IP_HDRINCL ),
282 #endif
283 MAP_OPTION( IP_TOS ),
284 MAP_OPTION( IP_TTL ),
287 static const int ws_af_map[][2] =
289 MAP_OPTION( AF_UNSPEC ),
290 MAP_OPTION( AF_INET ),
291 MAP_OPTION( AF_INET6 ),
292 #ifdef HAVE_IPX
293 MAP_OPTION( AF_IPX ),
294 #endif
297 static const int ws_socktype_map[][2] =
299 MAP_OPTION( SOCK_DGRAM ),
300 MAP_OPTION( SOCK_STREAM ),
301 MAP_OPTION( SOCK_RAW ),
304 static const int ws_proto_map[][2] =
306 MAP_OPTION( IPPROTO_IP ),
307 MAP_OPTION( IPPROTO_TCP ),
308 MAP_OPTION( IPPROTO_UDP ),
309 MAP_OPTION( IPPROTO_ICMP ),
310 MAP_OPTION( IPPROTO_IGMP ),
311 MAP_OPTION( IPPROTO_RAW ),
314 static const int ws_aiflag_map[][2] =
316 MAP_OPTION( AI_PASSIVE ),
317 MAP_OPTION( AI_CANONNAME ),
318 MAP_OPTION( AI_NUMERICHOST ),
319 /* Linux/UNIX knows a lot more. But Windows only
320 * has 3 as far as I could see. -Marcus
324 static const int ws_eai_map[][2] =
326 MAP_OPTION( EAI_AGAIN ),
327 MAP_OPTION( EAI_BADFLAGS ),
328 MAP_OPTION( EAI_FAIL ),
329 MAP_OPTION( EAI_FAMILY ),
330 MAP_OPTION( EAI_MEMORY ),
331 /* Note: EAI_NODATA is deprecated, but still
332 * used by Windows and Linux... We map the newer
333 * EAI_NONAME to EAI_NODATA for now until Windows
334 * changes too.
336 #ifdef EAI_NODATA
337 MAP_OPTION( EAI_NODATA ),
338 #endif
339 #ifdef EAI_NONAME
340 { WS_EAI_NODATA, EAI_NONAME },
341 #endif
343 MAP_OPTION( EAI_SERVICE ),
344 MAP_OPTION( EAI_SOCKTYPE ),
345 { 0, 0 }
348 inline static DWORD NtStatusToWSAError( const DWORD status )
350 /* We only need to cover the status codes set by server async request handling */
351 DWORD wserr;
352 switch ( status )
354 case STATUS_SUCCESS: wserr = 0; break;
355 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
356 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
357 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
358 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
359 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
360 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
361 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
362 default:
363 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
364 /* It is not a NT status code but a winsock error */
365 wserr = status;
366 else
368 wserr = RtlNtStatusToDosError( status );
369 FIXME( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
372 return wserr;
375 /* set last error code from NT status without mapping WSA errors */
376 inline static unsigned int set_error( unsigned int err )
378 if (err)
380 err = NtStatusToWSAError( err );
381 SetLastError( err );
383 return err;
386 inline static int get_sock_fd( SOCKET s, DWORD access, int *flags )
388 int fd;
389 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, flags ) ))
390 return -1;
391 return fd;
394 inline static void release_sock_fd( SOCKET s, int fd )
396 wine_server_release_fd( SOCKET2HANDLE(s), fd );
399 static void _enable_event( HANDLE s, unsigned int event,
400 unsigned int sstate, unsigned int cstate )
402 SERVER_START_REQ( enable_socket_event )
404 req->handle = s;
405 req->mask = event;
406 req->sstate = sstate;
407 req->cstate = cstate;
408 wine_server_call( req );
410 SERVER_END_REQ;
413 static int _is_blocking(SOCKET s)
415 int ret;
416 SERVER_START_REQ( get_socket_event )
418 req->handle = SOCKET2HANDLE(s);
419 req->service = FALSE;
420 req->c_event = 0;
421 wine_server_call( req );
422 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
424 SERVER_END_REQ;
425 return ret;
428 static unsigned int _get_sock_mask(SOCKET s)
430 unsigned int ret;
431 SERVER_START_REQ( get_socket_event )
433 req->handle = SOCKET2HANDLE(s);
434 req->service = FALSE;
435 req->c_event = 0;
436 wine_server_call( req );
437 ret = reply->mask;
439 SERVER_END_REQ;
440 return ret;
443 static void _sync_sock_state(SOCKET s)
445 /* do a dummy wineserver request in order to let
446 the wineserver run through its select loop once */
447 (void)_is_blocking(s);
450 static int _get_sock_error(SOCKET s, unsigned int bit)
452 int events[FD_MAX_EVENTS];
454 SERVER_START_REQ( get_socket_event )
456 req->handle = SOCKET2HANDLE(s);
457 req->service = FALSE;
458 req->c_event = 0;
459 wine_server_set_reply( req, events, sizeof(events) );
460 wine_server_call( req );
462 SERVER_END_REQ;
463 return events[bit];
466 static struct per_thread_data *get_per_thread_data(void)
468 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
469 /* lazy initialization */
470 if (!ptb)
472 ptb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptb) );
473 NtCurrentTeb()->WinSockData = ptb;
475 return ptb;
478 static void free_per_thread_data(void)
480 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
482 if (!ptb) return;
484 /* delete scratch buffers */
485 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
486 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
487 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
488 ptb->he_buffer = NULL;
489 ptb->se_buffer = NULL;
490 ptb->pe_buffer = NULL;
492 HeapFree( GetProcessHeap(), 0, ptb );
493 NtCurrentTeb()->WinSockData = NULL;
496 /***********************************************************************
497 * DllMain (WS2_32.init)
499 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
501 TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
502 switch (fdwReason) {
503 case DLL_PROCESS_ATTACH:
504 break;
505 case DLL_PROCESS_DETACH:
506 free_per_thread_data();
507 num_startup = 0;
508 break;
509 case DLL_THREAD_DETACH:
510 free_per_thread_data();
511 break;
513 return TRUE;
516 /***********************************************************************
517 * convert_sockopt()
519 * Converts socket flags from Windows format.
520 * Return 1 if converted, 0 if not (error).
522 static int convert_sockopt(INT *level, INT *optname)
524 int i;
525 switch (*level)
527 case WS_SOL_SOCKET:
528 *level = SOL_SOCKET;
529 for(i=0; i<sizeof(ws_sock_map)/sizeof(ws_sock_map[0]); i++) {
530 if( ws_sock_map[i][0] == *optname )
532 *optname = ws_sock_map[i][1];
533 return 1;
536 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
537 break;
538 case WS_IPPROTO_TCP:
539 *level = IPPROTO_TCP;
540 for(i=0; i<sizeof(ws_tcp_map)/sizeof(ws_tcp_map[0]); i++) {
541 if ( ws_tcp_map[i][0] == *optname )
543 *optname = ws_tcp_map[i][1];
544 return 1;
547 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
548 break;
549 case WS_IPPROTO_IP:
550 *level = IPPROTO_IP;
551 for(i=0; i<sizeof(ws_ip_map)/sizeof(ws_ip_map[0]); i++) {
552 if (ws_ip_map[i][0] == *optname )
554 *optname = ws_ip_map[i][1];
555 return 1;
558 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
559 break;
560 default: FIXME("Unimplemented or unknown socket level\n");
562 return 0;
565 static inline BOOL is_timeout_option( int optname )
567 #ifdef SO_RCVTIMEO
568 if (optname == SO_RCVTIMEO) return TRUE;
569 #endif
570 #ifdef SO_SNDTIMEO
571 if (optname == SO_SNDTIMEO) return TRUE;
572 #endif
573 return FALSE;
576 /* ----------------------------------- Per-thread info (or per-process?) */
578 static char *strdup_lower(const char *str)
580 int i;
581 char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
583 if (ret)
585 for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
586 ret[i] = 0;
588 else SetLastError(WSAENOBUFS);
589 return ret;
592 static fd_set* fd_set_import( fd_set* fds, const WS_fd_set* wsfds, int access, int* highfd, int lfd[] )
594 /* translate Winsock fd set into local fd set */
595 if( wsfds )
597 unsigned int i;
599 FD_ZERO(fds);
600 for( i = 0; i < wsfds->fd_count; i++ )
602 int s = wsfds->fd_array[i];
603 int fd = get_sock_fd( s, access, NULL );
604 if (fd != -1)
606 lfd[ i ] = fd;
607 if( fd > *highfd ) *highfd = fd;
608 FD_SET(fd, fds);
610 else lfd[ i ] = -1;
612 return fds;
614 return NULL;
617 inline static int sock_error_p(int s)
619 unsigned int optval, optlen;
621 optlen = sizeof(optval);
622 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
623 if (optval) WARN("\t[%i] error: %d\n", s, optval);
624 return optval != 0;
627 static int fd_set_export( const fd_set* fds, fd_set* exceptfds, WS_fd_set* wsfds, int lfd[] )
629 int num_err = 0;
631 /* translate local fd set into Winsock fd set, adding
632 * errors to exceptfds (only if app requested it) */
634 if( wsfds )
636 int i, j, count = wsfds->fd_count;
638 for( i = 0, j = 0; i < count; i++ )
640 int fd = lfd[i];
641 SOCKET s = wsfds->fd_array[i];
642 if (fd == -1) continue;
643 if( FD_ISSET(fd, fds) )
645 if ( exceptfds && sock_error_p(fd) )
647 FD_SET(fd, exceptfds);
648 num_err++;
650 else wsfds->fd_array[j++] = s;
652 release_sock_fd( s, fd );
654 wsfds->fd_count = j;
656 return num_err;
659 static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
661 if ( wsfds )
663 unsigned int i;
665 for ( i = 0; i < wsfds->fd_count; i++ )
666 if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
667 wsfds->fd_count = 0;
671 /* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
672 * from an fd and return the value converted to milli seconds
673 * or -1 if there is an infinite time out */
674 static inline int get_rcvsnd_timeo( int fd, int optname)
676 struct timeval tv;
677 unsigned int len = sizeof(tv);
678 int ret = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
679 if( ret >= 0)
680 ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
681 if( ret <= 0 ) /* tv == {0,0} means infinite time out */
682 return -1;
683 return ret;
686 /* macro wrappers for portability */
687 #ifdef SO_RCVTIMEO
688 #define GET_RCVTIMEO(fd) get_rcvsnd_timeo( (fd), SO_RCVTIMEO)
689 #else
690 #define GET_RCVTIMEO(fd) (-1)
691 #endif
693 #ifdef SO_SNDTIMEO
694 #define GET_SNDTIMEO(fd) get_rcvsnd_timeo( (fd), SO_SNDTIMEO)
695 #else
696 #define GET_SNDTIMEO(fd) (-1)
697 #endif
699 /* utility: given an fd, will block until one of the events occurs */
700 static inline int do_block( int fd, int events, int timeout )
702 struct pollfd pfd;
703 int ret;
705 pfd.fd = fd;
706 pfd.events = events;
708 while ((ret = poll(&pfd, 1, timeout)) < 0)
710 if (errno != EINTR)
711 return -1;
713 if( ret == 0 )
714 return 0;
715 return pfd.revents;
718 static int
719 convert_af_w2u(int windowsaf) {
720 int i;
722 for (i=0;i<sizeof(ws_af_map)/sizeof(ws_af_map[0]);i++)
723 if (ws_af_map[i][0] == windowsaf)
724 return ws_af_map[i][1];
725 FIXME("unhandled Windows address family %d\n", windowsaf);
726 return -1;
729 static int
730 convert_af_u2w(int unixaf) {
731 int i;
733 for (i=0;i<sizeof(ws_af_map)/sizeof(ws_af_map[0]);i++)
734 if (ws_af_map[i][1] == unixaf)
735 return ws_af_map[i][0];
736 FIXME("unhandled UNIX address family %d\n", unixaf);
737 return -1;
740 static int
741 convert_proto_w2u(int windowsproto) {
742 int i;
744 for (i=0;i<sizeof(ws_proto_map)/sizeof(ws_proto_map[0]);i++)
745 if (ws_proto_map[i][0] == windowsproto)
746 return ws_proto_map[i][1];
747 FIXME("unhandled Windows socket protocol %d\n", windowsproto);
748 return -1;
751 static int
752 convert_proto_u2w(int unixproto) {
753 int i;
755 for (i=0;i<sizeof(ws_proto_map)/sizeof(ws_proto_map[0]);i++)
756 if (ws_proto_map[i][1] == unixproto)
757 return ws_proto_map[i][0];
758 FIXME("unhandled UNIX socket protocol %d\n", unixproto);
759 return -1;
762 static int
763 convert_socktype_w2u(int windowssocktype) {
764 int i;
766 for (i=0;i<sizeof(ws_socktype_map)/sizeof(ws_socktype_map[0]);i++)
767 if (ws_socktype_map[i][0] == windowssocktype)
768 return ws_socktype_map[i][1];
769 FIXME("unhandled Windows socket type %d\n", windowssocktype);
770 return -1;
773 static int
774 convert_socktype_u2w(int unixsocktype) {
775 int i;
777 for (i=0;i<sizeof(ws_socktype_map)/sizeof(ws_socktype_map[0]);i++)
778 if (ws_socktype_map[i][1] == unixsocktype)
779 return ws_socktype_map[i][0];
780 FIXME("unhandled UNIX socket type %d\n", unixsocktype);
781 return -1;
784 /* ----------------------------------- API -----
786 * Init / cleanup / error checking.
789 /***********************************************************************
790 * WSAStartup (WS2_32.115)
792 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
794 TRACE("verReq=%x\n", wVersionRequested);
796 if (LOBYTE(wVersionRequested) < 1)
797 return WSAVERNOTSUPPORTED;
799 if (!lpWSAData) return WSAEINVAL;
801 num_startup++;
803 /* that's the whole of the negotiation for now */
804 lpWSAData->wVersion = wVersionRequested;
805 /* return winsock information */
806 lpWSAData->wHighVersion = 0x0202;
807 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
808 strcpy(lpWSAData->szSystemStatus, "Running" );
809 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
810 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
811 /* don't do anything with lpWSAData->lpVendorInfo */
812 /* (some apps don't allocate the space for this field) */
814 TRACE("succeeded\n");
815 return 0;
819 /***********************************************************************
820 * WSACleanup (WS2_32.116)
822 INT WINAPI WSACleanup(void)
824 if (num_startup) {
825 num_startup--;
826 return 0;
828 SetLastError(WSANOTINITIALISED);
829 return SOCKET_ERROR;
833 /***********************************************************************
834 * WSAGetLastError (WINSOCK.111)
835 * WSAGetLastError (WS2_32.111)
837 INT WINAPI WSAGetLastError(void)
839 return GetLastError();
842 /***********************************************************************
843 * WSASetLastError (WS2_32.112)
845 void WINAPI WSASetLastError(INT iError) {
846 SetLastError(iError);
849 static struct WS_hostent *check_buffer_he(int size)
851 struct per_thread_data * ptb = get_per_thread_data();
852 if (ptb->he_buffer)
854 if (ptb->he_len >= size ) return ptb->he_buffer;
855 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
857 ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
858 if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
859 return ptb->he_buffer;
862 static struct WS_servent *check_buffer_se(int size)
864 struct per_thread_data * ptb = get_per_thread_data();
865 if (ptb->se_buffer)
867 if (ptb->se_len >= size ) return ptb->se_buffer;
868 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
870 ptb->se_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->se_len = size) );
871 if (!ptb->se_buffer) SetLastError(WSAENOBUFS);
872 return ptb->se_buffer;
875 static struct WS_protoent *check_buffer_pe(int size)
877 struct per_thread_data * ptb = get_per_thread_data();
878 if (ptb->pe_buffer)
880 if (ptb->pe_len >= size ) return ptb->pe_buffer;
881 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
883 ptb->pe_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->pe_len = size) );
884 if (!ptb->pe_buffer) SetLastError(WSAENOBUFS);
885 return ptb->pe_buffer;
888 /* ----------------------------------- i/o APIs */
890 #ifdef HAVE_IPX
891 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX || (pf) == WS_AF_INET6)
892 #else
893 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf) == WS_AF_INET6)
894 #endif
897 /**********************************************************************/
899 /* Returns the converted address if successful, NULL if it was too small to
900 * start with. Note that the returned pointer may be the original pointer
901 * if no conversion is necessary.
903 static struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, unsigned int *uaddrlen)
905 switch (wsaddr->sa_family)
907 #ifdef HAVE_IPX
908 case WS_AF_IPX:
910 const struct WS_sockaddr_ipx* wsipx=(const struct WS_sockaddr_ipx*)wsaddr;
911 struct sockaddr_ipx* uipx;
913 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
914 return NULL;
916 *uaddrlen=sizeof(struct sockaddr_ipx);
917 uipx=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
918 uipx->sipx_family=AF_IPX;
919 uipx->sipx_port=wsipx->sa_socket;
920 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
921 * in one go
923 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
924 #ifdef IPX_FRAME_NONE
925 uipx->sipx_type=IPX_FRAME_NONE;
926 #endif
927 return (struct sockaddr*)uipx;
929 #endif
930 case WS_AF_INET6: {
931 struct sockaddr_in6* uin6;
932 const struct WS_sockaddr_in6* win6 = (struct WS_sockaddr_in6*)wsaddr;
933 const struct WS_sockaddr_in6_old* win6old = (struct WS_sockaddr_in6_old*)wsaddr;
935 /* Note: Windows has 2 versions of the sockaddr_in6 struct, one with
936 * scope_id, one without. Check:
937 * http://msdn.microsoft.com/library/en-us/winsock/winsock/sockaddr_2.asp
939 if (wsaddrlen==sizeof(struct WS_sockaddr_in6_old)) {
940 *uaddrlen=sizeof(struct sockaddr_in6);
941 uin6=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
942 uin6->sin6_family = AF_INET6;
943 uin6->sin6_port = win6old->sin6_port;
944 uin6->sin6_flowinfo = win6old->sin6_flowinfo;
945 memcpy(&uin6->sin6_addr,&win6old->sin6_addr,16); /* 16 bytes = 128 address bits */
946 return (struct sockaddr*)uin6;
948 if (wsaddrlen>=sizeof(struct WS_sockaddr_in6)) {
949 *uaddrlen=sizeof(struct sockaddr_in6);
950 uin6=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
951 uin6->sin6_family = AF_INET6;
952 uin6->sin6_port = win6->sin6_port;
953 uin6->sin6_flowinfo = win6->sin6_flowinfo;
954 uin6->sin6_scope_id = win6->sin6_scope_id;
955 memcpy(&uin6->sin6_addr,&win6->sin6_addr,16); /* 16 bytes = 128 address bits */
956 return (struct sockaddr*)uin6;
958 FIXME("bad size %d for WS_sockaddr_in6\n",wsaddrlen);
959 return NULL;
961 case WS_AF_INET: {
962 struct sockaddr_in* uin;
963 const struct WS_sockaddr_in* win = (struct WS_sockaddr_in*)wsaddr;
965 if (wsaddrlen<sizeof(struct WS_sockaddr_in))
966 return NULL;
967 *uaddrlen=sizeof(struct sockaddr_in);
968 uin = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
969 uin->sin_family = AF_INET;
970 uin->sin_port = win->sin_port;
971 memcpy(&uin->sin_addr,&win->sin_addr,4); /* 4 bytes = 32 address bits */
972 return (struct sockaddr*)uin;
974 case WS_AF_UNSPEC: {
975 /* Try to determine the needed space by the passed windows sockaddr space */
976 switch (wsaddrlen) {
977 default: /* likely a ipv4 address */
978 case sizeof(struct WS_sockaddr_in):
979 *uaddrlen = sizeof(struct sockaddr_in);
980 break;
981 #ifdef HAVE_IPX
982 case sizeof(struct WS_sockaddr_ipx):
983 *uaddrlen = sizeof(struct sockaddr_ipx);
984 break;
985 #endif
986 case sizeof(struct WS_sockaddr_in6):
987 case sizeof(struct WS_sockaddr_in6_old):
988 *uaddrlen = sizeof(struct sockaddr_in6);
989 break;
991 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,*uaddrlen);
993 default:
994 FIXME("Unknown address family %d, return NULL.\n", wsaddr->sa_family);
995 return NULL;
999 /* Allocates a Unix sockaddr structure to receive the data */
1000 static inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, unsigned int* uaddrlen)
1002 if (wsaddr==NULL)
1004 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
1006 /* This is not strictly the right thing to do. Hope it works however */
1007 *uaddrlen=0;
1009 return NULL;
1012 if (*wsaddrlen==0)
1013 *uaddrlen=0;
1014 else
1015 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
1017 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
1020 /* Returns 0 if successful, -1 if the buffer is too small */
1021 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
1023 int res;
1025 switch(uaddr->sa_family)
1027 #ifdef HAVE_IPX
1028 case AF_IPX:
1030 const struct sockaddr_ipx* uipx=(const struct sockaddr_ipx*)uaddr;
1031 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
1033 res=-1;
1034 switch (*wsaddrlen) /* how much can we copy? */
1036 default:
1037 res=0; /* enough */
1038 *wsaddrlen=uaddrlen;
1039 wsipx->sa_socket=uipx->sipx_port;
1040 /* fall through */
1041 case 13:
1042 case 12:
1043 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
1044 /* fall through */
1045 case 11:
1046 case 10:
1047 case 9:
1048 case 8:
1049 case 7:
1050 case 6:
1051 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
1052 /* fall through */
1053 case 5:
1054 case 4:
1055 case 3:
1056 case 2:
1057 wsipx->sa_family=WS_AF_IPX;
1058 /* fall through */
1059 case 1:
1060 case 0:
1061 /* way too small */
1062 break;
1065 break;
1066 #endif
1067 case AF_INET6: {
1068 const struct sockaddr_in6* uin6 = (struct sockaddr_in6*)uaddr;
1069 struct WS_sockaddr_in6* win6 = (struct WS_sockaddr_in6*)wsaddr;
1070 struct WS_sockaddr_in6_old* win6old = (struct WS_sockaddr_in6_old*)wsaddr;
1072 if (*wsaddrlen < sizeof(struct WS_sockaddr_in6_old))
1073 return -1;
1074 if (*wsaddrlen == sizeof(struct WS_sockaddr_in6_old)) {
1075 win6old->sin6_family = WS_AF_INET6;
1076 win6old->sin6_port = uin6->sin6_port;
1077 win6old->sin6_flowinfo = uin6->sin6_flowinfo;
1078 memcpy(&win6old->sin6_addr,&uin6->sin6_addr,16); /* 16 bytes = 128 address bits */
1079 *wsaddrlen = sizeof(struct WS_sockaddr_in6_old);
1080 return 0;
1082 if (*wsaddrlen >= sizeof(struct WS_sockaddr_in6)) {
1083 win6->sin6_family = WS_AF_INET6;
1084 win6->sin6_port = uin6->sin6_port;
1085 win6->sin6_flowinfo = uin6->sin6_flowinfo;
1086 memcpy(&win6->sin6_addr,&uin6->sin6_addr,16); /* 16 bytes = 128 address bits */
1087 win6->sin6_scope_id = uin6->sin6_scope_id;
1088 *wsaddrlen = sizeof(struct WS_sockaddr_in6);
1089 return 0;
1091 return 0;
1093 case AF_INET: {
1094 struct sockaddr_in* uin = (struct sockaddr_in*)uaddr;
1095 struct WS_sockaddr_in* win = (struct WS_sockaddr_in*)wsaddr;
1097 if (*wsaddrlen < sizeof(struct WS_sockaddr_in))
1098 return -1;
1099 win->sin_family = WS_AF_INET;
1100 win->sin_port = uin->sin_port;
1101 memcpy(&win->sin_addr,&uin->sin_addr,4); /* 4 bytes = 32 address bits */
1102 *wsaddrlen = sizeof(struct WS_sockaddr_in);
1103 return 0;
1105 case AF_UNSPEC: {
1106 memset(wsaddr,0,*wsaddrlen);
1107 return 0;
1109 default:
1110 FIXME("Unknown address family %d\n", uaddr->sa_family);
1111 return -1;
1113 return res;
1116 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
1117 * ws_sockaddr_alloc
1119 static inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
1121 if (uaddr!=(const struct sockaddr*)wsaddr)
1122 HeapFree(GetProcessHeap(), 0, (void *)uaddr);
1125 /**************************************************************************
1126 * Functions for handling overlapped I/O
1127 **************************************************************************/
1129 static void CALLBACK ws2_async_terminate(ws2_async* as, IO_STATUS_BLOCK* iosb)
1131 TRACE( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, iosb );
1133 wine_server_release_fd( as->hSocket, as->fd );
1134 if ( as->event != INVALID_HANDLE_VALUE )
1135 NtSetEvent( as->event, NULL );
1137 if (as->completion_func)
1138 as->completion_func( NtStatusToWSAError (iosb->u.Status),
1139 iosb->Information, as->user_overlapped, as->flags );
1140 if ( !as->user_overlapped )
1142 #if 0
1143 /* FIXME: I don't think this is really used */
1144 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
1145 WSACloseEvent( as->overlapped->hEvent );
1146 #endif
1147 HeapFree( GetProcessHeap(), 0, iosb );
1150 HeapFree( GetProcessHeap(), 0, as->iovec );
1151 HeapFree( GetProcessHeap(), 0, as );
1154 /***********************************************************************
1155 * WS2_make_async (INTERNAL)
1158 static void WINAPI WS2_async_recv(void*, IO_STATUS_BLOCK*, ULONG);
1159 static void WINAPI WS2_async_send(void*, IO_STATUS_BLOCK*, ULONG);
1160 static void WINAPI WS2_async_shutdown( void*, IO_STATUS_BLOCK*, ULONG);
1162 inline static struct ws2_async*
1163 WS2_make_async(SOCKET s, int fd, enum ws2_mode mode, struct iovec *iovec, DWORD dwBufferCount,
1164 LPDWORD lpFlags, struct WS_sockaddr *addr,
1165 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
1166 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
1167 IO_STATUS_BLOCK **piosb)
1169 struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof( ws2_async ) );
1171 TRACE( "wsa %p\n", wsa );
1173 if (!wsa)
1174 return NULL;
1176 wsa->hSocket = (HANDLE) s;
1177 wsa->mode = mode;
1178 switch (mode)
1180 case ws2m_read:
1181 case ws2m_sd_read:
1182 wsa->flags = *lpFlags;
1183 wsa->addrlen.ptr = addrlen;
1184 break;
1185 case ws2m_write:
1186 case ws2m_sd_write:
1187 wsa->flags = 0;
1188 wsa->addrlen.val = *addrlen;
1189 break;
1190 default:
1191 ERR("Invalid async mode: %d\n", mode);
1193 wsa->user_overlapped = lpOverlapped;
1194 wsa->completion_func = lpCompletionRoutine;
1195 wsa->iovec = iovec;
1196 wsa->n_iovecs = dwBufferCount;
1197 wsa->addr = addr;
1198 wsa->fd = fd;
1199 wsa->event = INVALID_HANDLE_VALUE;
1201 if ( lpOverlapped )
1203 *piosb = (IO_STATUS_BLOCK*)lpOverlapped;
1204 if (!lpCompletionRoutine)
1206 wsa->event = lpOverlapped->hEvent;
1207 NtResetEvent(wsa->event, NULL);
1210 else if (!(*piosb = HeapAlloc( GetProcessHeap(), 0, sizeof(IO_STATUS_BLOCK))))
1211 goto error;
1213 (*piosb)->Information = 0;
1214 (*piosb)->u.Status = STATUS_PENDING;
1215 TRACE( "wsa %p, h %p, ev %p, fd %d, iosb %p, uov %p, cfunc %p\n",
1216 wsa, wsa->hSocket, wsa->event, wsa->fd,
1217 *piosb, wsa->user_overlapped, wsa->completion_func );
1219 return wsa;
1221 error:
1222 TRACE("Error\n");
1223 HeapFree( GetProcessHeap(), 0, wsa );
1224 return NULL;
1227 static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb)
1229 PIO_APC_ROUTINE apc;
1230 int type;
1231 NTSTATUS status;
1233 switch (wsa->mode)
1235 case ws2m_read: apc = WS2_async_recv; type = ASYNC_TYPE_READ; break;
1236 case ws2m_write: apc = WS2_async_send; type = ASYNC_TYPE_WRITE; break;
1237 case ws2m_sd_read: apc = WS2_async_shutdown; type = ASYNC_TYPE_READ; break;
1238 case ws2m_sd_write: apc = WS2_async_shutdown; type = ASYNC_TYPE_WRITE; break;
1239 default: FIXME("Unknown internal mode (%d)\n", wsa->mode); return STATUS_INVALID_PARAMETER;
1242 SERVER_START_REQ( register_async )
1244 req->handle = wsa->hSocket;
1245 req->io_apc = apc;
1246 req->io_sb = iosb;
1247 req->io_user = wsa;
1248 req->type = type;
1249 req->count = iosb->Information;
1250 status = wine_server_call( req );
1252 SERVER_END_REQ;
1254 if ( status ) iosb->u.Status = status;
1255 if ( iosb->u.Status != STATUS_PENDING )
1257 /* Note: we get here a non zero status when we couldn't queue the async
1258 * in the server. Therefore, we simply terminate the async.
1260 status = iosb->u.Status;
1261 ws2_async_terminate(wsa, iosb);
1262 return status;
1264 NtCurrentTeb()->num_async_io++;
1265 return STATUS_SUCCESS;
1268 /***********************************************************************
1269 * WS2_recv (INTERNAL)
1271 * Workhorse for both synchronous and asynchronous recv() operations.
1273 static int WS2_recv( int fd, struct iovec* iov, int count,
1274 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1275 LPDWORD lpFlags )
1277 struct msghdr hdr;
1278 int n;
1279 TRACE( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
1280 fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
1282 hdr.msg_name = NULL;
1284 if ( lpFrom )
1286 hdr.msg_namelen = *lpFromlen;
1287 hdr.msg_name = ws_sockaddr_alloc( lpFrom, lpFromlen, &hdr.msg_namelen );
1288 if ( !hdr.msg_name )
1290 WSASetLastError( WSAEFAULT );
1291 n = -1;
1292 goto out;
1295 else
1296 hdr.msg_namelen = 0;
1298 hdr.msg_iov = iov;
1299 hdr.msg_iovlen = count;
1300 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1301 hdr.msg_accrights = NULL;
1302 hdr.msg_accrightslen = 0;
1303 #else
1304 hdr.msg_control = NULL;
1305 hdr.msg_controllen = 0;
1306 hdr.msg_flags = 0;
1307 #endif
1309 if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 )
1311 TRACE( "recvmsg error %d\n", errno);
1312 goto out;
1315 if ( lpFrom &&
1316 ws_sockaddr_u2ws( hdr.msg_name, hdr.msg_namelen,
1317 lpFrom, lpFromlen ) != 0 )
1319 /* The from buffer was too small, but we read the data
1320 * anyway. Is that really bad?
1322 WSASetLastError( WSAEFAULT );
1323 WARN( "Address buffer too small\n" );
1326 out:
1328 ws_sockaddr_free( hdr.msg_name, lpFrom );
1329 TRACE("-> %d\n", n);
1330 return n;
1333 /***********************************************************************
1334 * WS2_async_recv (INTERNAL)
1336 * Handler for overlapped recv() operations.
1338 static void WINAPI WS2_async_recv( void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
1340 ws2_async* wsa = (ws2_async*) ovp;
1341 int result, err;
1343 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1345 switch (status)
1347 case STATUS_ALERTED:
1348 result = WS2_recv( wsa->fd, wsa->iovec, wsa->n_iovecs,
1349 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1350 if (result >= 0)
1352 iosb->u.Status = STATUS_SUCCESS;
1353 iosb->Information = result;
1354 TRACE( "received %d bytes\n", result );
1355 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1357 else
1359 err = wsaErrno();
1360 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1362 iosb->u.Status = STATUS_PENDING;
1363 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1364 TRACE( "still pending\n" );
1366 else
1368 iosb->u.Status = err; /* FIXME: is this correct ???? */
1369 TRACE( "Error: %x\n", err );
1372 if (iosb->u.Status == STATUS_PENDING)
1373 ws2_queue_async(wsa, iosb);
1374 else
1375 ws2_async_terminate(wsa, iosb);
1376 break;
1377 default:
1378 FIXME( "status: %ld\n", status );
1379 iosb->u.Status = status;
1380 ws2_async_terminate(wsa, iosb);
1381 return;
1385 /***********************************************************************
1386 * WS2_send (INTERNAL)
1388 * Workhorse for both synchronous and asynchronous send() operations.
1390 static int WS2_send( int fd, struct iovec* iov, int count,
1391 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1393 struct msghdr hdr;
1394 int n = -1;
1395 TRACE( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
1396 fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
1398 hdr.msg_name = NULL;
1400 if ( to )
1402 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u( to, tolen, &hdr.msg_namelen );
1403 if ( !hdr.msg_name )
1405 WSASetLastError( WSAEFAULT );
1406 goto out;
1409 #ifdef HAVE_IPX
1410 if(to->sa_family == WS_AF_IPX)
1412 #ifdef SOL_IPX
1413 struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
1414 int val=0;
1415 unsigned int len=sizeof(int);
1417 /* The packet type is stored at the ipx socket level; At least the linux kernel seems
1418 * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
1419 * the packet type and then we can retrieve it using getsockopt. After that we can set the
1420 * ipx type in the sockaddr_opx structure with the stored value.
1422 if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
1424 TRACE("ptype: %d (fd:%d)\n", val, fd);
1425 uipx->sipx_type = val;
1427 #endif
1429 #endif
1432 else
1433 hdr.msg_namelen = 0;
1435 hdr.msg_iov = iov;
1436 hdr.msg_iovlen = count;
1437 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1438 hdr.msg_accrights = NULL;
1439 hdr.msg_accrightslen = 0;
1440 #else
1441 hdr.msg_control = NULL;
1442 hdr.msg_controllen = 0;
1443 hdr.msg_flags = 0;
1444 #endif
1446 n = sendmsg(fd, &hdr, dwFlags);
1448 out:
1449 ws_sockaddr_free( hdr.msg_name, to );
1450 return n;
1453 /***********************************************************************
1454 * WS2_async_send (INTERNAL)
1456 * Handler for overlapped send() operations.
1458 static void WINAPI WS2_async_send(void* as, IO_STATUS_BLOCK* iosb, ULONG status)
1460 ws2_async* wsa = (ws2_async*) as;
1461 int result;
1463 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1465 switch (status)
1467 case STATUS_ALERTED:
1468 if (iosb->u.Status != STATUS_PENDING) FIXME("wrong %08lx\n", iosb->u.Status);
1469 /* check to see if the data is ready (non-blocking) */
1470 result = WS2_send( wsa->fd, wsa->iovec, wsa->n_iovecs,
1471 wsa->addr, wsa->addrlen.val, wsa->flags );
1473 if (result >= 0)
1475 iosb->u.Status = STATUS_SUCCESS;
1476 iosb->Information = result;
1477 TRACE( "sent %d bytes\n", result );
1478 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1480 else
1482 int err = wsaErrno();
1483 if ( err == WSAEINTR )
1485 iosb->u.Status = STATUS_PENDING;
1486 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1487 TRACE( "still pending\n" );
1489 else
1491 /* We set the status to a winsock error code and check for that
1492 later in NtStatusToWSAError () */
1493 iosb->u.Status = err;
1494 TRACE( "Error: %x\n", err );
1497 if (iosb->u.Status == STATUS_PENDING)
1498 ws2_queue_async(wsa, iosb);
1499 else
1500 ws2_async_terminate(wsa, iosb);
1501 break;
1502 default:
1503 FIXME( "status: %ld\n", status );
1504 iosb->u.Status = status;
1505 ws2_async_terminate(wsa, iosb);
1506 return;
1511 /***********************************************************************
1512 * WS2_async_shutdown (INTERNAL)
1514 * Handler for shutdown() operations on overlapped sockets.
1516 static void WINAPI WS2_async_shutdown( void* as, PIO_STATUS_BLOCK iosb, ULONG status )
1518 ws2_async* wsa = (ws2_async*) as;
1519 int err = 1;
1521 TRACE( "async %p %d\n", wsa, wsa->mode );
1522 switch (status)
1524 case STATUS_ALERTED:
1525 switch ( wsa->mode )
1527 case ws2m_sd_read: err = shutdown( wsa->fd, 0 ); break;
1528 case ws2m_sd_write: err = shutdown( wsa->fd, 1 ); break;
1529 default: ERR("invalid mode: %d\n", wsa->mode );
1531 iosb->u.Status = err ? wsaErrno() : STATUS_SUCCESS;
1532 if (iosb->u.Status == STATUS_PENDING)
1533 ws2_queue_async(wsa, iosb);
1534 else
1535 ws2_async_terminate(wsa, iosb);
1536 break;
1537 default:
1538 iosb->u.Status = status;
1539 ws2_async_terminate(wsa, iosb);
1540 break;
1545 /***********************************************************************
1546 * WS2_register_async_shutdown (INTERNAL)
1548 * Helper function for WS_shutdown() on overlapped sockets.
1550 static int WS2_register_async_shutdown( SOCKET s, int fd, enum ws2_mode mode )
1552 struct ws2_async *wsa;
1553 int ret, err = WSAEFAULT;
1554 DWORD dwflags = 0;
1555 int len = 0;
1556 LPWSAOVERLAPPED ovl = HeapAlloc(GetProcessHeap(), 0, sizeof( WSAOVERLAPPED ));
1557 IO_STATUS_BLOCK *iosb = NULL;
1559 TRACE("s %d fd %d mode %d\n", s, fd, mode);
1560 if (!ovl)
1561 goto out;
1563 ovl->hEvent = WSACreateEvent();
1564 if ( ovl->hEvent == WSA_INVALID_EVENT )
1565 goto out_free;
1567 wsa = WS2_make_async( s, fd, mode, NULL, 0,
1568 &dwflags, NULL, &len, ovl, NULL, &iosb );
1569 if ( !wsa )
1570 goto out_close;
1572 /* Hack: this will cause ws2_async_terminate() to free the overlapped structure */
1573 wsa->user_overlapped = NULL;
1574 if ( (ret = ws2_queue_async( wsa, iosb )) )
1576 err = NtStatusToWSAError( ret );
1577 goto out;
1579 /* Try immediate completion */
1580 while ( WaitForSingleObjectEx( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1581 return 0;
1583 out_close:
1584 WSACloseEvent( ovl->hEvent );
1585 out_free:
1586 HeapFree( GetProcessHeap(), 0, ovl );
1587 out:
1588 return err;
1591 /***********************************************************************
1592 * accept (WS2_32.1)
1594 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1595 int *addrlen32)
1597 SOCKET as;
1598 BOOL is_blocking;
1600 TRACE("socket %04x\n", s );
1601 is_blocking = _is_blocking(s);
1603 do {
1604 if (is_blocking)
1606 int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
1607 if (fd == -1) return INVALID_SOCKET;
1608 /* block here */
1609 do_block(fd, POLLIN, -1);
1610 _sync_sock_state(s); /* let wineserver notice connection */
1611 release_sock_fd( s, fd );
1612 /* retrieve any error codes from it */
1613 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1614 /* FIXME: care about the error? */
1616 SERVER_START_REQ( accept_socket )
1618 req->lhandle = SOCKET2HANDLE(s);
1619 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1620 req->attributes = OBJ_INHERIT;
1621 set_error( wine_server_call( req ) );
1622 as = HANDLE2SOCKET( reply->handle );
1624 SERVER_END_REQ;
1625 if (as)
1627 if (addr) WS_getpeername(as, addr, addrlen32);
1628 return as;
1630 } while (is_blocking);
1631 return INVALID_SOCKET;
1634 /***********************************************************************
1635 * bind (WS2_32.2)
1637 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1639 int fd = get_sock_fd( s, 0, NULL );
1640 int res = SOCKET_ERROR;
1642 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1644 if (fd != -1)
1646 if (!name || (name->sa_family && !SUPPORTED_PF(name->sa_family)))
1648 SetLastError(WSAEAFNOSUPPORT);
1650 else
1652 const struct sockaddr* uaddr;
1653 unsigned int uaddrlen;
1655 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1656 if (uaddr == NULL)
1658 SetLastError(WSAEFAULT);
1660 else
1662 if (bind(fd, uaddr, uaddrlen) < 0)
1664 int loc_errno = errno;
1665 WARN("\tfailure - errno = %i\n", errno);
1666 errno = loc_errno;
1667 switch (errno)
1669 case EBADF:
1670 SetLastError(WSAENOTSOCK);
1671 break;
1672 case EADDRNOTAVAIL:
1673 SetLastError(WSAEINVAL);
1674 break;
1675 default:
1676 SetLastError(wsaErrno());
1677 break;
1680 else
1682 res=0; /* success */
1684 ws_sockaddr_free(uaddr,name);
1687 release_sock_fd( s, fd );
1689 return res;
1692 /***********************************************************************
1693 * closesocket (WS2_32.3)
1695 int WINAPI WS_closesocket(SOCKET s)
1697 TRACE("socket %04x\n", s);
1698 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1699 return SOCKET_ERROR;
1702 /***********************************************************************
1703 * connect (WS2_32.4)
1705 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1707 int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
1709 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1711 if (fd != -1)
1713 const struct sockaddr* uaddr;
1714 unsigned int uaddrlen;
1716 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1717 if (uaddr == NULL)
1719 SetLastError(WSAEFAULT);
1721 else
1723 int rc;
1725 rc=connect(fd, uaddr, uaddrlen);
1726 ws_sockaddr_free(uaddr,name);
1727 if (rc == 0)
1728 goto connect_success;
1731 if (errno == EINPROGRESS)
1733 /* tell wineserver that a connection is in progress */
1734 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1735 FD_CONNECT|FD_READ|FD_WRITE,
1736 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1737 if (_is_blocking(s))
1739 int result;
1740 /* block here */
1741 do_block(fd, POLLIN | POLLOUT, -1);
1742 _sync_sock_state(s); /* let wineserver notice connection */
1743 /* retrieve any error codes from it */
1744 result = _get_sock_error(s, FD_CONNECT_BIT);
1745 if (result)
1746 SetLastError(result);
1747 else
1749 goto connect_success;
1752 else
1754 SetLastError(WSAEWOULDBLOCK);
1757 else
1759 SetLastError(wsaErrno());
1761 release_sock_fd( s, fd );
1763 return SOCKET_ERROR;
1765 connect_success:
1766 release_sock_fd( s, fd );
1767 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1768 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1769 FD_CONNECT|FD_WINE_LISTENING);
1770 return 0;
1773 /***********************************************************************
1774 * WSAConnect (WS2_32.30)
1776 int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
1777 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1778 LPQOS lpSQOS, LPQOS lpGQOS )
1780 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1781 FIXME("unsupported parameters!\n");
1782 return WS_connect( s, name, namelen );
1786 /***********************************************************************
1787 * getpeername (WS2_32.5)
1789 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1791 int fd;
1792 int res;
1794 TRACE("socket: %04x, ptr %p, len %08x\n", s, name, *namelen);
1796 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1797 if( (name == NULL) || (namelen == NULL) )
1799 SetLastError( WSAEFAULT );
1800 return SOCKET_ERROR;
1803 fd = get_sock_fd( s, 0, NULL );
1804 res = SOCKET_ERROR;
1806 if (fd != -1)
1808 struct sockaddr* uaddr;
1809 unsigned int uaddrlen;
1811 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1812 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1814 SetLastError(wsaErrno());
1816 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1818 /* The buffer was too small */
1819 SetLastError(WSAEFAULT);
1821 else
1823 res=0;
1825 ws_sockaddr_free(uaddr,name);
1826 release_sock_fd( s, fd );
1828 return res;
1831 /***********************************************************************
1832 * getsockname (WS2_32.6)
1834 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1836 int fd;
1837 int res;
1839 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1841 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1842 if( (name == NULL) || (namelen == NULL) )
1844 SetLastError( WSAEFAULT );
1845 return SOCKET_ERROR;
1848 fd = get_sock_fd( s, 0, NULL );
1849 res = SOCKET_ERROR;
1851 if (fd != -1)
1853 struct sockaddr* uaddr;
1854 unsigned int uaddrlen;
1856 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1857 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1859 SetLastError(wsaErrno());
1861 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1863 /* The buffer was too small */
1864 SetLastError(WSAEFAULT);
1866 else
1868 res=0;
1870 ws_sockaddr_free(uaddr,name);
1871 release_sock_fd( s, fd );
1873 return res;
1876 /***********************************************************************
1877 * getsockopt (WS2_32.7)
1879 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1880 INT optname, char *optval, INT *optlen)
1882 int fd;
1883 INT ret = 0;
1885 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %p, len %d\n",
1886 s, level, optname, optval, *optlen);
1887 /* SO_OPENTYPE does not require a valid socket handle. */
1888 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1890 if (!optlen || *optlen < sizeof(int) || !optval)
1892 SetLastError(WSAEFAULT);
1893 return SOCKET_ERROR;
1895 *(int *)optval = get_per_thread_data()->opentype;
1896 *optlen = sizeof(int);
1897 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1898 return 0;
1901 #ifdef HAVE_IPX
1902 if(level == NSPROTO_IPX)
1904 struct WS_sockaddr_ipx addr;
1905 IPX_ADDRESS_DATA *data;
1906 int namelen;
1907 switch(optname)
1909 case IPX_PTYPE:
1910 fd = get_sock_fd( s, 0, NULL );
1911 #ifdef SOL_IPX
1912 if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, (unsigned int*)optlen) == -1)
1914 return SOCKET_ERROR;
1916 #else
1918 struct ipx val;
1919 socklen_t len=sizeof(struct ipx);
1921 if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
1922 return SOCKET_ERROR;
1923 *optval = (int)val.ipx_pt;
1925 #endif
1926 TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
1927 release_sock_fd( s, fd );
1929 return 0;
1930 case IPX_ADDRESS:
1932 * On a Win2000 system with one network card there are usually three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
1933 * Using this call you can then retrieve info about this all. In case of Linux it is a bit different. Usually you have
1934 * only "one" device active and further it is not possible to query things like the linkspeed.
1936 FIXME("IPX_ADDRESS\n");
1937 namelen = sizeof(struct WS_sockaddr_ipx);
1938 memset(&addr, 0, sizeof(struct WS_sockaddr_ipx));
1939 WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
1941 data = (IPX_ADDRESS_DATA*)optval;
1942 memcpy(data->nodenum,&addr.sa_nodenum,sizeof(data->nodenum));
1943 memcpy(data->netnum,&addr.sa_netnum,sizeof(data->netnum));
1944 data->adapternum = 0;
1945 data->wan = FALSE; /* We are not on a wan for now .. */
1946 data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
1947 data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
1948 data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit; note 1MB = 1000kB in this case */
1949 return 0;
1950 case IPX_MAX_ADAPTER_NUM:
1951 FIXME("IPX_MAX_ADAPTER_NUM\n");
1952 *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
1954 return 0;
1955 default:
1956 FIXME("IPX optname:%x\n", optname);
1957 return SOCKET_ERROR;
1960 #endif
1962 if( (fd = get_sock_fd( s, 0, NULL )) == -1)
1963 return SOCKET_ERROR;
1965 if (!convert_sockopt(&level, &optname)) {
1966 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1967 ret = SOCKET_ERROR;
1968 } else {
1969 struct timeval tv;
1970 struct linger lingval;
1971 unsigned int len, *plen = (unsigned int*)optlen;
1972 char *pval = optval;
1973 if(level == SOL_SOCKET && is_timeout_option(optname)) {
1974 len = sizeof(tv);
1975 plen = &len;
1976 pval = (char *) &tv;
1977 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1978 len = sizeof(lingval);
1979 plen = &len;
1980 pval = (char *) &lingval;
1982 if (getsockopt(fd, (int) level, optname, pval, plen) != 0 ) {
1983 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1984 ret = SOCKET_ERROR;
1985 } else if(level == SOL_SOCKET && is_timeout_option(optname)) {
1986 if( *optlen >= sizeof(INT) ) {
1987 *optlen = sizeof(INT);
1988 *(INT*)optval = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1989 } else {
1990 SetLastError(WSAEFAULT);
1991 ret = SOCKET_ERROR;
1993 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1994 if( *optlen >= sizeof( LINGER) ) {
1995 (( LINGER *) optval)->l_onoff = lingval.l_onoff;
1996 (( LINGER *) optval)->l_linger = lingval.l_linger;
1997 } else {
1998 SetLastError(WSAEFAULT);
1999 ret = SOCKET_ERROR;
2003 release_sock_fd( s, fd );
2004 return ret;
2008 /***********************************************************************
2009 * htonl (WINSOCK.8)
2010 * htonl (WS2_32.8)
2012 u_long WINAPI WS_htonl(u_long hostlong)
2014 return htonl(hostlong);
2018 /***********************************************************************
2019 * htons (WINSOCK.9)
2020 * htons (WS2_32.9)
2022 u_short WINAPI WS_htons(u_short hostshort)
2024 return htons(hostshort);
2027 /***********************************************************************
2028 * WSAHtonl (WS2_32.46)
2029 * From MSDN decription of error codes, this function should also
2030 * check if WinSock has been initialized and the socket is a valid
2031 * socket. But why? This function only translates a host byte order
2032 * u_long into a network byte order u_long...
2034 int WINAPI WSAHtonl(SOCKET s, u_long hostlong, u_long *lpnetlong)
2036 if (lpnetlong)
2038 *lpnetlong = htonl(hostlong);
2039 return 0;
2041 WSASetLastError(WSAEFAULT);
2042 return SOCKET_ERROR;
2045 /***********************************************************************
2046 * WSAHtons (WS2_32.47)
2047 * From MSDN decription of error codes, this function should also
2048 * check if WinSock has been initialized and the socket is a valid
2049 * socket. But why? This function only translates a host byte order
2050 * u_short into a network byte order u_short...
2052 int WINAPI WSAHtons(SOCKET s, u_short hostshort, u_short *lpnetshort)
2055 if (lpnetshort)
2057 *lpnetshort = htons(hostshort);
2058 return 0;
2060 WSASetLastError(WSAEFAULT);
2061 return SOCKET_ERROR;
2065 /***********************************************************************
2066 * inet_addr (WINSOCK.10)
2067 * inet_addr (WS2_32.11)
2069 u_long WINAPI WS_inet_addr(const char *cp)
2071 return inet_addr(cp);
2075 /***********************************************************************
2076 * ntohl (WINSOCK.14)
2077 * ntohl (WS2_32.14)
2079 u_long WINAPI WS_ntohl(u_long netlong)
2081 return ntohl(netlong);
2085 /***********************************************************************
2086 * ntohs (WINSOCK.15)
2087 * ntohs (WS2_32.15)
2089 u_short WINAPI WS_ntohs(u_short netshort)
2091 return ntohs(netshort);
2095 /***********************************************************************
2096 * inet_ntoa (WS2_32.12)
2098 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
2100 /* use "buffer for dummies" here because some applications have a
2101 * propensity to decode addresses in ws_hostent structure without
2102 * saving them first...
2104 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
2106 char* s = inet_ntoa(*((struct in_addr*)&in));
2107 if( s )
2109 strcpy(dbuffer, s);
2110 return dbuffer;
2112 SetLastError(wsaErrno());
2113 return NULL;
2116 /**********************************************************************
2117 * WSAIoctl (WS2_32.50)
2120 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
2122 INT WINAPI WSAIoctl(SOCKET s,
2123 DWORD dwIoControlCode,
2124 LPVOID lpvInBuffer,
2125 DWORD cbInBuffer,
2126 LPVOID lpbOutBuffer,
2127 DWORD cbOutBuffer,
2128 LPDWORD lpcbBytesReturned,
2129 LPWSAOVERLAPPED lpOverlapped,
2130 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
2132 int fd = get_sock_fd( s, 0, NULL );
2134 if (fd == -1) return SOCKET_ERROR;
2136 TRACE("%d, 0x%08lx, %p, %ld, %p, %ld, %p, %p, %p\n",
2137 s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpbOutBuffer,
2138 cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
2140 switch( dwIoControlCode )
2142 case SIO_GET_INTERFACE_LIST:
2144 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
2145 DWORD size, numInt, apiReturn;
2147 TRACE("-> SIO_GET_INTERFACE_LIST request\n");
2149 if (!lpbOutBuffer)
2151 release_sock_fd( s, fd );
2152 WSASetLastError(WSAEFAULT);
2153 return SOCKET_ERROR;
2155 if (!lpcbBytesReturned)
2157 release_sock_fd( s, fd );
2158 WSASetLastError(WSAEFAULT);
2159 return SOCKET_ERROR;
2162 apiReturn = GetAdaptersInfo(NULL, &size);
2163 if (apiReturn == ERROR_NO_DATA)
2165 numInt = 0;
2167 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
2169 PIP_ADAPTER_INFO table = HeapAlloc(GetProcessHeap(),0,size);
2171 if (table)
2173 if (GetAdaptersInfo(table, &size) == NO_ERROR)
2175 PIP_ADAPTER_INFO ptr;
2177 if (size*sizeof(INTERFACE_INFO)/sizeof(IP_ADAPTER_INFO) > cbOutBuffer)
2179 WARN("Buffer too small = %lu, cbOutBuffer = %lu\n", size, cbOutBuffer);
2180 HeapFree(GetProcessHeap(),0,table);
2181 release_sock_fd( s, fd );
2182 WSASetLastError(WSAEFAULT);
2183 return SOCKET_ERROR;
2185 for (ptr = table, numInt = 0; ptr;
2186 ptr = ptr->Next, intArray++, numInt++)
2188 unsigned int addr, mask, bcast;
2189 struct ifreq ifInfo;
2191 /* Socket Status Flags */
2192 lstrcpynA(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
2193 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2195 ERR("Error obtaining status flags for socket!\n");
2196 HeapFree(GetProcessHeap(),0,table);
2197 release_sock_fd( s, fd );
2198 WSASetLastError(WSAEINVAL);
2199 return SOCKET_ERROR;
2201 else
2203 /* set flags; the values of IFF_* are not the same
2204 under Linux and Windows, therefore must generate
2205 new flags */
2206 intArray->iiFlags = 0;
2207 if (ifInfo.ifr_flags & IFF_BROADCAST)
2208 intArray->iiFlags |= WS_IFF_BROADCAST;
2209 #ifdef IFF_POINTOPOINT
2210 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
2211 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
2212 #endif
2213 if (ifInfo.ifr_flags & IFF_LOOPBACK)
2214 intArray->iiFlags |= WS_IFF_LOOPBACK;
2215 if (ifInfo.ifr_flags & IFF_UP)
2216 intArray->iiFlags |= WS_IFF_UP;
2217 if (ifInfo.ifr_flags & IFF_MULTICAST)
2218 intArray->iiFlags |= WS_IFF_MULTICAST;
2221 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
2222 mask = inet_addr(ptr->IpAddressList.IpMask.String);
2223 bcast = addr | (addr & !mask);
2224 intArray->iiAddress.AddressIn.sin_family = AF_INET;
2225 intArray->iiAddress.AddressIn.sin_port = 0;
2226 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2227 addr;
2228 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2229 intArray->iiNetmask.AddressIn.sin_port = 0;
2230 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2231 mask;
2232 intArray->iiBroadcastAddress.AddressIn.sin_family =
2233 AF_INET;
2234 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2235 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2236 WS_s_addr = bcast;
2239 else
2241 ERR("Unable to get interface table!\n");
2242 release_sock_fd( s, fd );
2243 HeapFree(GetProcessHeap(),0,table);
2244 WSASetLastError(WSAEINVAL);
2245 return SOCKET_ERROR;
2247 HeapFree(GetProcessHeap(),0,table);
2249 else
2251 release_sock_fd( s, fd );
2252 WSASetLastError(WSAEINVAL);
2253 return SOCKET_ERROR;
2256 else
2258 ERR("Unable to get interface table!\n");
2259 release_sock_fd( s, fd );
2260 WSASetLastError(WSAEINVAL);
2261 return SOCKET_ERROR;
2263 /* Calculate the size of the array being returned */
2264 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2265 break;
2268 case SIO_ADDRESS_LIST_CHANGE:
2269 FIXME("-> SIO_ADDRESS_LIST_CHANGE request: stub\n");
2270 /* FIXME: error and return code depend on whether socket was created
2271 * with WSA_FLAG_OVERLAPPED, but there is no easy way to get this */
2272 break;
2274 default:
2275 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2276 release_sock_fd( s, fd );
2277 WSASetLastError(WSAEOPNOTSUPP);
2278 return SOCKET_ERROR;
2281 /* Function executed with no errors */
2282 release_sock_fd( s, fd );
2283 return 0;
2287 /***********************************************************************
2288 * ioctlsocket (WS2_32.10)
2290 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2292 int fd;
2293 long newcmd = cmd;
2295 TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
2297 switch( cmd )
2299 case WS_FIONREAD:
2300 newcmd=FIONREAD;
2301 break;
2303 case WS_FIONBIO:
2304 if( _get_sock_mask(s) )
2306 /* AsyncSelect()'ed sockets are always nonblocking */
2307 if (*argp) return 0;
2308 SetLastError(WSAEINVAL);
2309 return SOCKET_ERROR;
2311 fd = get_sock_fd( s, 0, NULL );
2312 if (fd != -1)
2314 int ret;
2315 if (*argp)
2317 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2318 ret = fcntl( fd, F_SETFL, O_NONBLOCK );
2320 else
2322 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2323 ret = fcntl( fd, F_SETFL, 0 );
2325 release_sock_fd( s, fd );
2326 if (!ret) return 0;
2327 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2329 return SOCKET_ERROR;
2331 case WS_SIOCATMARK:
2332 newcmd=SIOCATMARK;
2333 break;
2335 case WS__IOW('f',125,u_long):
2336 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2337 SetLastError(WSAEINVAL);
2338 return SOCKET_ERROR;
2340 case SIOCGIFBRDADDR:
2341 case SIOCGIFNETMASK:
2342 case SIOCGIFADDR:
2343 /* These don't need any special handling. They are used by
2344 WsControl, and are here to suppress an unnecessary warning. */
2345 break;
2347 default:
2348 /* Netscape tries hard to use bogus ioctl 0x667e */
2349 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2350 break;
2353 fd = get_sock_fd( s, 0, NULL );
2354 if (fd != -1)
2356 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2358 release_sock_fd( s, fd );
2359 return 0;
2361 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2362 release_sock_fd( s, fd );
2364 return SOCKET_ERROR;
2367 /***********************************************************************
2368 * listen (WS2_32.13)
2370 int WINAPI WS_listen(SOCKET s, int backlog)
2372 int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
2374 TRACE("socket %04x, backlog %d\n", s, backlog);
2375 if (fd != -1)
2377 if (listen(fd, backlog) == 0)
2379 release_sock_fd( s, fd );
2380 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2381 FD_WINE_LISTENING,
2382 FD_CONNECT|FD_WINE_CONNECTED);
2383 return 0;
2385 SetLastError(wsaErrno());
2386 release_sock_fd( s, fd );
2388 return SOCKET_ERROR;
2391 /***********************************************************************
2392 * recv (WS2_32.16)
2394 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2396 DWORD n, dwFlags = flags;
2397 WSABUF wsabuf;
2399 wsabuf.len = len;
2400 wsabuf.buf = buf;
2402 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2403 return SOCKET_ERROR;
2404 else
2405 return n;
2408 /***********************************************************************
2409 * recvfrom (WS2_32.17)
2411 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2412 struct WS_sockaddr *from, int *fromlen)
2414 DWORD n, dwFlags = flags;
2415 WSABUF wsabuf;
2417 wsabuf.len = len;
2418 wsabuf.buf = buf;
2420 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2421 return SOCKET_ERROR;
2422 else
2423 return n;
2426 /***********************************************************************
2427 * select (WS2_32.18)
2429 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2430 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2431 const struct WS_timeval* ws_timeout)
2433 int highfd = 0;
2434 fd_set readfds, writefds, exceptfds;
2435 fd_set *p_read, *p_write, *p_except;
2436 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2437 struct timeval timeout, *timeoutaddr = NULL;
2439 TRACE("read %p, write %p, excp %p timeout %p\n",
2440 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2442 p_read = fd_set_import(&readfds, ws_readfds, FILE_READ_DATA, &highfd, readfd);
2443 p_write = fd_set_import(&writefds, ws_writefds, FILE_WRITE_DATA, &highfd, writefd);
2444 p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
2445 if (ws_timeout)
2447 timeoutaddr = &timeout;
2448 timeout.tv_sec=ws_timeout->tv_sec;
2449 timeout.tv_usec=ws_timeout->tv_usec;
2452 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2454 fd_set_export(&readfds, p_except, ws_readfds, readfd);
2455 fd_set_export(&writefds, p_except, ws_writefds, writefd);
2457 if (p_except && ws_exceptfds)
2459 unsigned int i, j;
2461 for (i = j = 0; i < ws_exceptfds->fd_count; i++)
2463 int fd = exceptfd[i];
2464 SOCKET s = ws_exceptfds->fd_array[i];
2465 if (fd == -1) continue;
2466 if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
2467 release_sock_fd( s, fd );
2469 ws_exceptfds->fd_count = j;
2471 return highfd;
2473 fd_set_unimport(ws_readfds, readfd);
2474 fd_set_unimport(ws_writefds, writefd);
2475 fd_set_unimport(ws_exceptfds, exceptfd);
2477 if( highfd == 0 ) return 0;
2478 SetLastError(wsaErrno());
2479 return SOCKET_ERROR;
2483 /***********************************************************************
2484 * send (WS2_32.19)
2486 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2488 DWORD n;
2489 WSABUF wsabuf;
2491 wsabuf.len = len;
2492 wsabuf.buf = (char*) buf;
2494 if ( WSASendTo( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2495 return SOCKET_ERROR;
2496 else
2497 return n;
2500 /***********************************************************************
2501 * WSASend (WS2_32.72)
2503 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2504 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2505 LPWSAOVERLAPPED lpOverlapped,
2506 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2508 return WSASendTo( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2509 NULL, 0, lpOverlapped, lpCompletionRoutine );
2512 /***********************************************************************
2513 * WSASendDisconnect (WS2_32.73)
2515 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2517 return WS_shutdown( s, SD_SEND );
2521 /***********************************************************************
2522 * WSASendTo (WS2_32.74)
2524 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2525 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2526 const struct WS_sockaddr *to, int tolen,
2527 LPWSAOVERLAPPED lpOverlapped,
2528 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2530 unsigned int i;
2531 int n, fd, err = WSAENOTSOCK, flags, ret;
2532 struct iovec* iovec;
2533 struct ws2_async *wsa;
2534 IO_STATUS_BLOCK* iosb;
2536 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2537 s, lpBuffers, dwBufferCount, dwFlags,
2538 to, tolen, lpOverlapped, lpCompletionRoutine);
2540 fd = get_sock_fd( s, FILE_WRITE_DATA, &flags );
2541 TRACE( "fd=%d, flags=%x\n", fd, flags );
2543 if ( fd == -1 ) return SOCKET_ERROR;
2545 if (flags & FD_FLAG_SEND_SHUTDOWN)
2547 WSASetLastError( WSAESHUTDOWN );
2548 goto err_close;
2551 if ( !lpNumberOfBytesSent )
2553 err = WSAEFAULT;
2554 goto err_close;
2557 iovec = HeapAlloc(GetProcessHeap(), 0, dwBufferCount * sizeof(struct iovec) );
2559 if ( !iovec )
2561 err = WSAEFAULT;
2562 goto err_close;
2565 for ( i = 0; i < dwBufferCount; i++ )
2567 iovec[i].iov_base = lpBuffers[i].buf;
2568 iovec[i].iov_len = lpBuffers[i].len;
2571 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2573 wsa = WS2_make_async( s, fd, ws2m_write, iovec, dwBufferCount,
2574 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2575 lpOverlapped, lpCompletionRoutine, &iosb );
2576 if ( !wsa )
2578 err = WSAEFAULT;
2579 goto err_free;
2582 if ( ( ret = ws2_queue_async( wsa, iosb ) ) )
2584 err = NtStatusToWSAError( ret );
2586 if ( !lpOverlapped )
2587 HeapFree( GetProcessHeap(), 0, iosb );
2588 HeapFree( GetProcessHeap(), 0, wsa );
2589 goto err_free;
2592 /* Try immediate completion */
2593 if ( lpOverlapped )
2595 if ( WSAGetOverlappedResult( s, lpOverlapped,
2596 lpNumberOfBytesSent, FALSE, &dwFlags) )
2597 return 0;
2599 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
2600 goto error;
2603 WSASetLastError( WSA_IO_PENDING );
2604 return SOCKET_ERROR;
2607 if (_is_blocking(s))
2609 /* FIXME: exceptfds? */
2610 int timeout = GET_SNDTIMEO(fd);
2611 if( !do_block(fd, POLLOUT, timeout)) {
2612 err = WSAETIMEDOUT;
2613 goto err_free; /* msdn says a timeout in send is fatal */
2617 n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2618 if ( n == -1 )
2620 err = wsaErrno();
2621 if ( err == WSAEWOULDBLOCK )
2622 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2623 goto err_free;
2626 TRACE(" -> %i bytes\n", n);
2627 *lpNumberOfBytesSent = n;
2629 HeapFree( GetProcessHeap(), 0, iovec );
2630 release_sock_fd( s, fd );
2631 return 0;
2633 err_free:
2634 HeapFree( GetProcessHeap(), 0, iovec );
2636 err_close:
2637 release_sock_fd( s, fd );
2639 error:
2640 WARN(" -> ERROR %d\n", err);
2641 WSASetLastError(err);
2642 return SOCKET_ERROR;
2645 /***********************************************************************
2646 * sendto (WS2_32.20)
2648 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2649 const struct WS_sockaddr *to, int tolen)
2651 DWORD n;
2652 WSABUF wsabuf;
2654 wsabuf.len = len;
2655 wsabuf.buf = (char*) buf;
2657 if ( WSASendTo(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2658 return SOCKET_ERROR;
2659 else
2660 return n;
2663 /***********************************************************************
2664 * setsockopt (WS2_32.21)
2666 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2667 const char *optval, int optlen)
2669 int fd;
2670 int woptval;
2671 struct linger linger;
2672 struct timeval tval;
2674 TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
2675 s, level, optname, optval, optlen);
2677 /* SO_OPENTYPE does not require a valid socket handle. */
2678 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2680 if (optlen < sizeof(int) || !optval)
2682 SetLastError(WSAEFAULT);
2683 return SOCKET_ERROR;
2685 get_per_thread_data()->opentype = *(int *)optval;
2686 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2687 return 0;
2690 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2691 * socket. This will either not happen under windows or it is ignored in
2692 * windows (but it works in linux and therefore prevents the game from
2693 * finding games outside the current network) */
2694 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2696 FIXME("Does windows ignore SO_DONTROUTE?\n");
2697 return 0;
2700 #ifdef HAVE_IPX
2701 if(level == NSPROTO_IPX)
2703 switch(optname)
2705 case IPX_PTYPE:
2706 fd = get_sock_fd( s, 0, NULL );
2707 TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", *(int*)optval, fd);
2709 /* We try to set the ipx type on ipx socket level. */
2710 #ifdef SOL_IPX
2711 if(setsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
2713 ERR("IPX: could not set ipx option type; expect weird behaviour\n");
2714 return SOCKET_ERROR;
2716 #else
2718 struct ipx val;
2719 /* Should we retrieve val using a getsockopt call and then
2720 * set the modified one? */
2721 val.ipx_pt = *optval;
2722 setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
2724 #endif
2725 release_sock_fd( s, fd );
2726 return 0;
2727 case IPX_FILTERPTYPE:
2728 /* Sets the receive filter packet type, at the moment we don't support it */
2729 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
2731 /* Returning 0 is better for now than returning a SOCKET_ERROR */
2732 return 0;
2733 default:
2734 FIXME("opt_name:%x\n", optname);
2735 return SOCKET_ERROR;
2737 return 0;
2739 #endif
2741 /* Is a privileged and useless operation, so we don't. */
2742 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
2744 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2745 return 0;
2748 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2749 /* This is unique to WinSock and takes special conversion */
2750 linger.l_onoff = *((int*)optval) ? 0: 1;
2751 linger.l_linger = 0;
2752 optname=SO_LINGER;
2753 optval = (char*)&linger;
2754 optlen = sizeof(struct linger);
2755 level = SOL_SOCKET;
2757 else
2759 if (!convert_sockopt(&level, &optname)) {
2760 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2761 SetLastError(WSAENOPROTOOPT);
2762 return SOCKET_ERROR;
2764 if (optname == SO_LINGER && optval) {
2765 linger.l_onoff = ((LINGER*)optval)->l_onoff;
2766 linger.l_linger = ((LINGER*)optval)->l_linger;
2767 /* FIXME: what is documented behavior if SO_LINGER optval
2768 is null?? */
2769 optval = (char*)&linger;
2770 optlen = sizeof(struct linger);
2772 else if (optval && optlen < sizeof(int))
2774 woptval= *((INT16 *) optval);
2775 optval= (char*) &woptval;
2776 optlen=sizeof(int);
2778 if (level == SOL_SOCKET && is_timeout_option(optname))
2780 if (optlen == sizeof(UINT32)) {
2781 /* WinSock passes miliseconds instead of struct timeval */
2782 tval.tv_usec = (*(PUINT32)optval % 1000) * 1000;
2783 tval.tv_sec = *(PUINT32)optval / 1000;
2784 /* min of 500 milisec */
2785 if (tval.tv_sec == 0 && tval.tv_usec < 500000)
2786 tval.tv_usec = 500000;
2787 optlen = sizeof(struct timeval);
2788 optval = (char*)&tval;
2789 } else if (optlen == sizeof(struct timeval)) {
2790 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2791 } else {
2792 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2793 return 0;
2796 if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
2798 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2799 return 0;
2804 fd = get_sock_fd( s, 0, NULL );
2805 if (fd == -1) return SOCKET_ERROR;
2807 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2809 release_sock_fd( s, fd );
2810 return 0;
2812 TRACE("Setting socket error, %d\n", wsaErrno());
2813 SetLastError(wsaErrno());
2814 release_sock_fd( s, fd );
2815 return SOCKET_ERROR;
2818 /***********************************************************************
2819 * shutdown (WS2_32.22)
2821 int WINAPI WS_shutdown(SOCKET s, int how)
2823 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2824 unsigned int clear_flags = 0;
2826 fd = get_sock_fd( s, 0, &flags );
2827 TRACE("socket %04x, how %i %x\n", s, how, flags );
2829 if (fd == -1)
2830 return SOCKET_ERROR;
2832 switch( how )
2834 case 0: /* drop receives */
2835 clear_flags |= FD_READ;
2836 break;
2837 case 1: /* drop sends */
2838 clear_flags |= FD_WRITE;
2839 break;
2840 case 2: /* drop all */
2841 clear_flags |= FD_READ|FD_WRITE;
2842 default:
2843 clear_flags |= FD_WINE_LISTENING;
2846 if ( flags & FD_FLAG_OVERLAPPED ) {
2848 switch ( how )
2850 case SD_RECEIVE:
2851 fd0 = fd;
2852 break;
2853 case SD_SEND:
2854 fd1 = fd;
2855 break;
2856 case SD_BOTH:
2857 default:
2858 fd0 = fd;
2859 fd1 = get_sock_fd( s, 0, NULL );
2860 break;
2863 if ( fd0 != -1 )
2865 err = WS2_register_async_shutdown( s, fd0, ws2m_sd_read );
2866 if ( err )
2868 release_sock_fd( s, fd0 );
2869 goto error;
2872 if ( fd1 != -1 )
2874 err = WS2_register_async_shutdown( s, fd1, ws2m_sd_write );
2875 if ( err )
2877 release_sock_fd( s, fd1 );
2878 goto error;
2882 else /* non-overlapped mode */
2884 if ( shutdown( fd, how ) )
2886 err = wsaErrno();
2887 release_sock_fd( s, fd );
2888 goto error;
2890 release_sock_fd( s, fd );
2893 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2894 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2895 return 0;
2897 error:
2898 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2899 WSASetLastError( err );
2900 return SOCKET_ERROR;
2903 /***********************************************************************
2904 * socket (WS2_32.23)
2906 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2908 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2910 return WSASocketA( af, type, protocol, NULL, 0,
2911 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
2915 /***********************************************************************
2916 * gethostbyaddr (WS2_32.51)
2918 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
2920 struct WS_hostent *retval = NULL;
2921 struct hostent* host;
2923 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2924 char *extrabuf;
2925 int ebufsize=1024;
2926 struct hostent hostentry;
2927 int locerr=ENOBUFS;
2928 host = NULL;
2929 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2930 while(extrabuf) {
2931 int res = gethostbyaddr_r(addr, len, type,
2932 &hostentry, extrabuf, ebufsize, &host, &locerr);
2933 if( res != ERANGE) break;
2934 ebufsize *=2;
2935 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2937 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2938 #else
2939 EnterCriticalSection( &csWSgetXXXbyYYY );
2940 host = gethostbyaddr(addr, len, type);
2941 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2942 #endif
2943 if( host != NULL ) retval = WS_dup_he(host);
2944 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2945 HeapFree(GetProcessHeap(),0,extrabuf);
2946 #else
2947 LeaveCriticalSection( &csWSgetXXXbyYYY );
2948 #endif
2949 TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
2950 return retval;
2953 /***********************************************************************
2954 * gethostbyname (WS2_32.52)
2956 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2958 struct WS_hostent *retval = NULL;
2959 struct hostent* host;
2960 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2961 char *extrabuf;
2962 int ebufsize=1024;
2963 struct hostent hostentry;
2964 int locerr = ENOBUFS;
2965 #endif
2966 char buf[100];
2967 if( !name) {
2968 name = buf;
2969 if( gethostname( buf, 100) == -1) {
2970 SetLastError( WSAENOBUFS); /* appropriate ? */
2971 return retval;
2974 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2975 host = NULL;
2976 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2977 while(extrabuf) {
2978 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2979 if( res != ERANGE) break;
2980 ebufsize *=2;
2981 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2983 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2984 #else
2985 EnterCriticalSection( &csWSgetXXXbyYYY );
2986 host = gethostbyname(name);
2987 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2988 #endif
2989 if (host) retval = WS_dup_he(host);
2990 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2991 HeapFree(GetProcessHeap(),0,extrabuf);
2992 #else
2993 LeaveCriticalSection( &csWSgetXXXbyYYY );
2994 #endif
2995 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2996 return retval;
3000 /***********************************************************************
3001 * getprotobyname (WS2_32.53)
3003 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
3005 struct WS_protoent* retval = NULL;
3006 #ifdef HAVE_GETPROTOBYNAME
3007 struct protoent* proto;
3008 EnterCriticalSection( &csWSgetXXXbyYYY );
3009 if( (proto = getprotobyname(name)) != NULL )
3011 retval = WS_dup_pe(proto);
3013 else {
3014 MESSAGE("protocol %s not found; You might want to add "
3015 "this to /etc/protocols\n", debugstr_a(name) );
3016 SetLastError(WSANO_DATA);
3018 LeaveCriticalSection( &csWSgetXXXbyYYY );
3019 #endif
3020 TRACE( "%s ret %p\n", debugstr_a(name), retval );
3021 return retval;
3025 /***********************************************************************
3026 * getprotobynumber (WS2_32.54)
3028 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
3030 struct WS_protoent* retval = NULL;
3031 #ifdef HAVE_GETPROTOBYNUMBER
3032 struct protoent* proto;
3033 EnterCriticalSection( &csWSgetXXXbyYYY );
3034 if( (proto = getprotobynumber(number)) != NULL )
3036 retval = WS_dup_pe(proto);
3038 else {
3039 MESSAGE("protocol number %d not found; You might want to add "
3040 "this to /etc/protocols\n", number );
3041 SetLastError(WSANO_DATA);
3043 LeaveCriticalSection( &csWSgetXXXbyYYY );
3044 #endif
3045 TRACE("%i ret %p\n", number, retval);
3046 return retval;
3050 /***********************************************************************
3051 * getservbyname (WS2_32.55)
3053 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
3055 struct WS_servent* retval = NULL;
3056 struct servent* serv;
3057 char *name_str;
3058 char *proto_str = NULL;
3060 if (!(name_str = strdup_lower(name))) return NULL;
3062 if (proto && *proto)
3064 if (!(proto_str = strdup_lower(proto)))
3066 HeapFree( GetProcessHeap(), 0, name_str );
3067 return NULL;
3071 EnterCriticalSection( &csWSgetXXXbyYYY );
3072 serv = getservbyname(name_str, proto_str);
3073 if( serv != NULL )
3075 retval = WS_dup_se(serv);
3077 else SetLastError(WSANO_DATA);
3078 LeaveCriticalSection( &csWSgetXXXbyYYY );
3079 HeapFree( GetProcessHeap(), 0, proto_str );
3080 HeapFree( GetProcessHeap(), 0, name_str );
3081 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
3082 return retval;
3085 /***********************************************************************
3086 * freeaddrinfo (WS2_32.@)
3088 void WINAPI WS_freeaddrinfo(struct WS_addrinfo *res)
3090 while (res) {
3091 struct WS_addrinfo *next;
3093 HeapFree(GetProcessHeap(),0,res->ai_canonname);
3094 HeapFree(GetProcessHeap(),0,res->ai_addr);
3095 next = res->ai_next;
3096 HeapFree(GetProcessHeap(),0,res);
3097 res = next;
3101 /* helper functions for getaddrinfo() */
3102 static int convert_aiflag_w2u(int winflags) {
3103 int i, unixflags = 0;
3105 for (i=0;i<sizeof(ws_aiflag_map)/sizeof(ws_aiflag_map[0]);i++)
3106 if (ws_aiflag_map[i][0] & winflags) {
3107 unixflags |= ws_aiflag_map[i][1];
3108 winflags &= ~ws_aiflag_map[i][0];
3110 if (winflags)
3111 FIXME("Unhandled windows AI_xxx flags %x\n", winflags);
3112 return unixflags;
3115 static int convert_aiflag_u2w(int unixflags) {
3116 int i, winflags = 0;
3118 for (i=0;i<sizeof(ws_aiflag_map)/sizeof(ws_aiflag_map[0]);i++)
3119 if (ws_aiflag_map[i][1] & unixflags) {
3120 winflags |= ws_aiflag_map[i][0];
3121 unixflags &= ~ws_aiflag_map[i][1];
3123 if (unixflags) /* will warn usually */
3124 WARN("Unhandled UNIX AI_xxx flags %x\n", unixflags);
3125 return winflags;
3128 static int convert_eai_u2w(int unixret) {
3129 int i;
3131 for (i=0;ws_eai_map[i][0];i++)
3132 if (ws_eai_map[i][1] == unixret)
3133 return ws_eai_map[i][0];
3134 return unixret;
3137 /***********************************************************************
3138 * getaddrinfo (WS2_32.@)
3140 int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addrinfo *hints, struct WS_addrinfo **res)
3142 #if HAVE_GETADDRINFO
3143 struct addrinfo *unixaires = NULL;
3144 int result;
3145 struct addrinfo unixhints, *punixhints = NULL;
3146 CHAR *node = NULL, *serv = NULL;
3148 if (nodename)
3149 if (!(node = strdup_lower(nodename))) return WSA_NOT_ENOUGH_MEMORY;
3151 if (servname) {
3152 if (!(serv = strdup_lower(servname))) {
3153 HeapFree(GetProcessHeap(), 0, node);
3154 return WSA_NOT_ENOUGH_MEMORY;
3158 if (hints) {
3159 punixhints = &unixhints;
3161 memset(&unixhints, 0, sizeof(unixhints));
3162 punixhints->ai_flags = convert_aiflag_w2u(hints->ai_flags);
3163 punixhints->ai_family = convert_af_w2u(hints->ai_family);
3164 punixhints->ai_socktype = convert_socktype_w2u(hints->ai_socktype);
3165 punixhints->ai_protocol = convert_proto_w2u(hints->ai_protocol);
3168 /* getaddrinfo(3) is thread safe, no need to wrap in CS */
3169 result = getaddrinfo(nodename, servname, punixhints, &unixaires);
3171 TRACE("%s, %s %p -> %p %d\n", nodename, servname, hints, res, result);
3173 HeapFree(GetProcessHeap(), 0, node);
3174 HeapFree(GetProcessHeap(), 0, serv);
3176 if (!result) {
3177 struct addrinfo *xuai = unixaires;
3178 struct WS_addrinfo **xai = res;
3180 *xai = NULL;
3181 while (xuai) {
3182 struct WS_addrinfo *ai = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo));
3183 int len;
3185 if (!ai)
3186 goto outofmem;
3188 *xai = ai;xai = &ai->ai_next;
3189 ai->ai_flags = convert_aiflag_u2w(xuai->ai_flags);
3190 ai->ai_family = convert_af_u2w(xuai->ai_family);
3191 ai->ai_socktype = convert_socktype_u2w(xuai->ai_socktype);
3192 ai->ai_protocol = convert_proto_u2w(xuai->ai_protocol);
3193 if (xuai->ai_canonname) {
3194 TRACE("canon name - %s\n",debugstr_a(xuai->ai_canonname));
3195 ai->ai_canonname = HeapAlloc(GetProcessHeap(),0,strlen(xuai->ai_canonname)+1);
3196 if (!ai->ai_canonname)
3197 goto outofmem;
3198 strcpy(ai->ai_canonname,xuai->ai_canonname);
3200 len = xuai->ai_addrlen;
3201 ai->ai_addr = HeapAlloc(GetProcessHeap(),0,len);
3202 if (!ai->ai_addr)
3203 goto outofmem;
3204 ai->ai_addrlen = len;
3205 do {
3206 int winlen = ai->ai_addrlen;
3208 if (!ws_sockaddr_u2ws(xuai->ai_addr, xuai->ai_addrlen, ai->ai_addr, &winlen)) {
3209 ai->ai_addrlen = winlen;
3210 break;
3212 len = 2*len;
3213 ai->ai_addr = HeapReAlloc(GetProcessHeap(),0,ai->ai_addr,len);
3214 if (!ai->ai_addr)
3215 goto outofmem;
3216 ai->ai_addrlen = len;
3217 } while (1);
3218 xuai = xuai->ai_next;
3220 freeaddrinfo(unixaires);
3221 } else {
3222 result = convert_eai_u2w(result);
3224 return result;
3226 outofmem:
3227 if (*res) WS_freeaddrinfo(*res);
3228 if (unixaires) freeaddrinfo(unixaires);
3229 *res = NULL;
3230 return WSA_NOT_ENOUGH_MEMORY;
3231 #else
3232 FIXME("getaddrinfo() failed, not found during buildtime.\n");
3233 return EAI_FAIL;
3234 #endif
3237 /***********************************************************************
3238 * GetAddrInfoW (WS2_32.@)
3240 int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hints, PADDRINFOW *res)
3242 FIXME("empty stub!\n");
3243 return EAI_FAIL;
3246 /***********************************************************************
3247 * getservbyport (WS2_32.56)
3249 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
3251 struct WS_servent* retval = NULL;
3252 #ifdef HAVE_GETSERVBYPORT
3253 struct servent* serv;
3254 char *proto_str = NULL;
3256 if (proto && *proto)
3258 if (!(proto_str = strdup_lower(proto))) return NULL;
3260 EnterCriticalSection( &csWSgetXXXbyYYY );
3261 if( (serv = getservbyport(port, proto_str)) != NULL ) {
3262 retval = WS_dup_se(serv);
3264 else SetLastError(WSANO_DATA);
3265 LeaveCriticalSection( &csWSgetXXXbyYYY );
3266 HeapFree( GetProcessHeap(), 0, proto_str );
3267 #endif
3268 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
3269 return retval;
3273 /***********************************************************************
3274 * gethostname (WS2_32.57)
3276 int WINAPI WS_gethostname(char *name, int namelen)
3278 TRACE("name %p, len %d\n", name, namelen);
3280 if (gethostname(name, namelen) == 0)
3282 TRACE("<- '%s'\n", name);
3283 return 0;
3285 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
3286 TRACE("<- ERROR !\n");
3287 return SOCKET_ERROR;
3291 /* ------------------------------------- Windows sockets extensions -- *
3293 * ------------------------------------------------------------------- */
3295 /***********************************************************************
3296 * WSAEnumNetworkEvents (WS2_32.36)
3298 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
3300 int ret;
3302 TRACE("%08x, hEvent %p, lpEvent %p\n", s, hEvent, lpEvent );
3304 SERVER_START_REQ( get_socket_event )
3306 req->handle = SOCKET2HANDLE(s);
3307 req->service = TRUE;
3308 req->c_event = hEvent;
3309 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
3310 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
3312 SERVER_END_REQ;
3313 if (!ret) return 0;
3314 SetLastError(WSAEINVAL);
3315 return SOCKET_ERROR;
3318 /***********************************************************************
3319 * WSAEventSelect (WS2_32.39)
3321 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, long lEvent)
3323 int ret;
3325 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
3327 SERVER_START_REQ( set_socket_event )
3329 req->handle = SOCKET2HANDLE(s);
3330 req->mask = lEvent;
3331 req->event = hEvent;
3332 req->window = 0;
3333 req->msg = 0;
3334 ret = wine_server_call( req );
3336 SERVER_END_REQ;
3337 if (!ret) return 0;
3338 SetLastError(WSAEINVAL);
3339 return SOCKET_ERROR;
3342 /**********************************************************************
3343 * WSAGetOverlappedResult (WS2_32.40)
3345 BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
3346 LPDWORD lpcbTransfer, BOOL fWait,
3347 LPDWORD lpdwFlags )
3349 DWORD r;
3351 TRACE( "socket %04x ovl %p trans %p, wait %d flags %p\n",
3352 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
3354 if ( lpOverlapped == NULL )
3356 ERR( "Invalid pointer\n" );
3357 WSASetLastError(WSA_INVALID_PARAMETER);
3358 return FALSE;
3361 if ( fWait )
3363 if (lpOverlapped->hEvent)
3364 while ( WaitForSingleObjectEx(lpOverlapped->hEvent,
3365 INFINITE, TRUE) == STATUS_USER_APC );
3366 else /* busy loop */
3367 while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
3368 Sleep( 10 );
3371 else if ( lpOverlapped->Internal == STATUS_PENDING )
3373 /* Wait in order to give APCs a chance to run. */
3374 /* This is cheating, so we must set the event again in case of success -
3375 it may be a non-manual reset event. */
3376 while ( (r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
3377 if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent )
3378 NtSetEvent( lpOverlapped->hEvent, NULL );
3381 if ( lpcbTransfer )
3382 *lpcbTransfer = lpOverlapped->InternalHigh;
3384 if ( lpdwFlags )
3385 *lpdwFlags = lpOverlapped->u.s.Offset;
3387 switch ( lpOverlapped->Internal )
3389 case STATUS_SUCCESS:
3390 return TRUE;
3391 case STATUS_PENDING:
3392 WSASetLastError( WSA_IO_INCOMPLETE );
3393 if (fWait) ERR("PENDING status after waiting!\n");
3394 return FALSE;
3395 default:
3396 WSASetLastError( NtStatusToWSAError( lpOverlapped->Internal ));
3397 return FALSE;
3402 /***********************************************************************
3403 * WSAAsyncSelect (WS2_32.101)
3405 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, long lEvent)
3407 int ret;
3409 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3411 SERVER_START_REQ( set_socket_event )
3413 req->handle = SOCKET2HANDLE(s);
3414 req->mask = lEvent;
3415 req->event = 0;
3416 req->window = hWnd;
3417 req->msg = uMsg;
3418 ret = wine_server_call( req );
3420 SERVER_END_REQ;
3421 if (!ret) return 0;
3422 SetLastError(WSAEINVAL);
3423 return SOCKET_ERROR;
3426 /***********************************************************************
3427 * WSACreateEvent (WS2_32.31)
3430 WSAEVENT WINAPI WSACreateEvent(void)
3432 /* Create a manual-reset event, with initial state: unsignaled */
3433 TRACE("\n");
3435 return CreateEventW(NULL, TRUE, FALSE, NULL);
3438 /***********************************************************************
3439 * WSACloseEvent (WS2_32.29)
3442 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3444 TRACE ("event=%p\n", event);
3446 return CloseHandle(event);
3449 /***********************************************************************
3450 * WSASocketA (WS2_32.78)
3453 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3454 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3455 GROUP g, DWORD dwFlags)
3457 INT len;
3458 WSAPROTOCOL_INFOW info;
3460 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3461 af, type, protocol, lpProtocolInfo, g, dwFlags);
3463 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
3465 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
3466 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3467 info.szProtocol, WSAPROTOCOL_LEN + 1);
3469 if (!len)
3471 WSASetLastError( WSAEINVAL);
3472 return SOCKET_ERROR;
3475 return WSASocketW(af, type, protocol, &info, g, dwFlags);
3478 /***********************************************************************
3479 * WSASocketW (WS2_32.79)
3482 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
3483 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3484 GROUP g, DWORD dwFlags)
3486 SOCKET ret;
3489 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
3490 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3493 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3494 af, type, protocol, lpProtocolInfo, g, dwFlags );
3496 /* hack for WSADuplicateSocket */
3497 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3498 ret = lpProtocolInfo->dwCatalogEntryId;
3499 TRACE("\tgot duplicate %04x\n", ret);
3500 return ret;
3503 /* check and convert the socket family */
3504 af = convert_af_w2u(af);
3505 if (af == -1)
3507 FIXME("Unsupported socket family %d!\n", af);
3508 SetLastError(WSAEAFNOSUPPORT);
3509 return INVALID_SOCKET;
3512 /* check the socket type */
3513 type = convert_socktype_w2u(type);
3514 if (type == -1)
3516 SetLastError(WSAESOCKTNOSUPPORT);
3517 return INVALID_SOCKET;
3520 /* check the protocol type */
3521 if ( protocol < 0 ) /* don't support negative values */
3523 SetLastError(WSAEPROTONOSUPPORT);
3524 return INVALID_SOCKET;
3527 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3528 switch(protocol)
3530 case IPPROTO_TCP:
3531 if (type == SOCK_STREAM) { af = AF_INET; break; }
3532 case IPPROTO_UDP:
3533 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3534 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3537 SERVER_START_REQ( create_socket )
3539 req->family = af;
3540 req->type = type;
3541 req->protocol = protocol;
3542 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3543 req->attributes = OBJ_INHERIT;
3544 req->flags = dwFlags;
3545 set_error( wine_server_call( req ) );
3546 ret = HANDLE2SOCKET( reply->handle );
3548 SERVER_END_REQ;
3549 if (ret)
3551 TRACE("\tcreated %04x\n", ret );
3552 return ret;
3555 if (GetLastError() == WSAEACCES) /* raw socket denied */
3557 if (type == SOCK_RAW)
3558 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3559 else
3560 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3561 SetLastError(WSAESOCKTNOSUPPORT);
3564 WARN("\t\tfailed!\n");
3565 return INVALID_SOCKET;
3568 /***********************************************************************
3569 * WSAJoinLeaf (WS2_32.58)
3572 SOCKET WINAPI WSAJoinLeaf(
3573 SOCKET s,
3574 const struct WS_sockaddr *addr,
3575 int addrlen,
3576 LPWSABUF lpCallerData,
3577 LPWSABUF lpCalleeData,
3578 LPQOS lpSQOS,
3579 LPQOS lpGQOS,
3580 DWORD dwFlags)
3582 FIXME("stub.\n");
3583 return INVALID_SOCKET;
3586 /***********************************************************************
3587 * __WSAFDIsSet (WS2_32.151)
3589 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3591 int i = set->fd_count;
3593 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3595 while (i--)
3596 if (set->fd_array[i] == s) return 1;
3597 return 0;
3600 /***********************************************************************
3601 * WSAIsBlocking (WINSOCK.114)
3602 * WSAIsBlocking (WS2_32.114)
3604 BOOL WINAPI WSAIsBlocking(void)
3606 /* By default WinSock should set all its sockets to non-blocking mode
3607 * and poll in PeekMessage loop when processing "blocking" ones. This
3608 * function is supposed to tell if the program is in this loop. Our
3609 * blocking calls are truly blocking so we always return FALSE.
3611 * Note: It is allowed to call this function without prior WSAStartup().
3614 TRACE("\n");
3615 return FALSE;
3618 /***********************************************************************
3619 * WSACancelBlockingCall (WINSOCK.113)
3620 * WSACancelBlockingCall (WS2_32.113)
3622 INT WINAPI WSACancelBlockingCall(void)
3624 TRACE("\n");
3625 return 0;
3628 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
3630 FIXME("How was this called?\n");
3631 return x();
3635 /***********************************************************************
3636 * WSASetBlockingHook (WS2_32.109)
3638 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3640 FARPROC prev = blocking_hook;
3641 blocking_hook = lpBlockFunc;
3642 TRACE("hook %p\n", lpBlockFunc);
3643 return prev;
3647 /***********************************************************************
3648 * WSAUnhookBlockingHook (WS2_32.110)
3650 INT WINAPI WSAUnhookBlockingHook(void)
3652 blocking_hook = WSA_DefaultBlockingHook;
3653 return 0;
3657 /* ----------------------------------- end of API stuff */
3659 /* ----------------------------------- helper functions -
3661 * TODO: Merge WS_dup_..() stuff into one function that
3662 * would operate with a generic structure containing internal
3663 * pointers (via a template of some kind).
3666 static int list_size(char** l, int item_size)
3668 int i,j = 0;
3669 if(l)
3670 { for(i=0;l[i];i++)
3671 j += (item_size) ? item_size : strlen(l[i]) + 1;
3672 j += (i + 1) * sizeof(char*); }
3673 return j;
3676 static int list_dup(char** l_src, char** l_to, int item_size)
3678 char *p;
3679 int i;
3681 for (i = 0; l_src[i]; i++) ;
3682 p = (char *)(l_to + i + 1);
3683 for (i = 0; l_src[i]; i++)
3685 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3686 memcpy(p, l_src[i], count);
3687 l_to[i] = p;
3688 p += count;
3690 l_to[i] = NULL;
3691 return p - (char *)l_to;
3694 /* ----- hostent */
3696 /* duplicate hostent entry
3697 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3698 * Dito for protoent and servent.
3700 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
3702 char *p;
3703 struct WS_hostent *p_to;
3705 int size = (sizeof(*p_he) +
3706 strlen(p_he->h_name) + 1 +
3707 list_size(p_he->h_aliases, 0) +
3708 list_size(p_he->h_addr_list, p_he->h_length));
3710 if (!(p_to = check_buffer_he(size))) return NULL;
3711 p_to->h_addrtype = p_he->h_addrtype;
3712 p_to->h_length = p_he->h_length;
3714 p = (char *)(p_to + 1);
3715 p_to->h_name = p;
3716 strcpy(p, p_he->h_name);
3717 p += strlen(p) + 1;
3719 p_to->h_aliases = (char **)p;
3720 p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
3722 p_to->h_addr_list = (char **)p;
3723 list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
3724 return p_to;
3727 /* ----- protoent */
3729 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
3731 char *p;
3732 struct WS_protoent *p_to;
3734 int size = (sizeof(*p_pe) +
3735 strlen(p_pe->p_name) + 1 +
3736 list_size(p_pe->p_aliases, 0));
3738 if (!(p_to = check_buffer_pe(size))) return NULL;
3739 p_to->p_proto = p_pe->p_proto;
3741 p = (char *)(p_to + 1);
3742 p_to->p_name = p;
3743 strcpy(p, p_pe->p_name);
3744 p += strlen(p) + 1;
3746 p_to->p_aliases = (char **)p;
3747 list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
3748 return p_to;
3751 /* ----- servent */
3753 static struct WS_servent *WS_dup_se(const struct servent* p_se)
3755 char *p;
3756 struct WS_servent *p_to;
3758 int size = (sizeof(*p_se) +
3759 strlen(p_se->s_proto) + 1 +
3760 strlen(p_se->s_name) + 1 +
3761 list_size(p_se->s_aliases, 0));
3763 if (!(p_to = check_buffer_se(size))) return NULL;
3764 p_to->s_port = p_se->s_port;
3766 p = (char *)(p_to + 1);
3767 p_to->s_name = p;
3768 strcpy(p, p_se->s_name);
3769 p += strlen(p) + 1;
3771 p_to->s_proto = p;
3772 strcpy(p, p_se->s_proto);
3773 p += strlen(p) + 1;
3775 p_to->s_aliases = (char **)p;
3776 list_dup(p_se->s_aliases, p_to->s_aliases, 0);
3777 return p_to;
3780 /* ----------------------------------- error handling */
3782 UINT wsaErrno(void)
3784 int loc_errno = errno;
3785 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3787 switch(loc_errno)
3789 case EINTR: return WSAEINTR;
3790 case EBADF: return WSAEBADF;
3791 case EPERM:
3792 case EACCES: return WSAEACCES;
3793 case EFAULT: return WSAEFAULT;
3794 case EINVAL: return WSAEINVAL;
3795 case EMFILE: return WSAEMFILE;
3796 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3797 case EINPROGRESS: return WSAEINPROGRESS;
3798 case EALREADY: return WSAEALREADY;
3799 case ENOTSOCK: return WSAENOTSOCK;
3800 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3801 case EMSGSIZE: return WSAEMSGSIZE;
3802 case EPROTOTYPE: return WSAEPROTOTYPE;
3803 case ENOPROTOOPT: return WSAENOPROTOOPT;
3804 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3805 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3806 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3807 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3808 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3809 case EADDRINUSE: return WSAEADDRINUSE;
3810 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3811 case ENETDOWN: return WSAENETDOWN;
3812 case ENETUNREACH: return WSAENETUNREACH;
3813 case ENETRESET: return WSAENETRESET;
3814 case ECONNABORTED: return WSAECONNABORTED;
3815 case EPIPE:
3816 case ECONNRESET: return WSAECONNRESET;
3817 case ENOBUFS: return WSAENOBUFS;
3818 case EISCONN: return WSAEISCONN;
3819 case ENOTCONN: return WSAENOTCONN;
3820 case ESHUTDOWN: return WSAESHUTDOWN;
3821 case ETOOMANYREFS: return WSAETOOMANYREFS;
3822 case ETIMEDOUT: return WSAETIMEDOUT;
3823 case ECONNREFUSED: return WSAECONNREFUSED;
3824 case ELOOP: return WSAELOOP;
3825 case ENAMETOOLONG: return WSAENAMETOOLONG;
3826 case EHOSTDOWN: return WSAEHOSTDOWN;
3827 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3828 case ENOTEMPTY: return WSAENOTEMPTY;
3829 #ifdef EPROCLIM
3830 case EPROCLIM: return WSAEPROCLIM;
3831 #endif
3832 #ifdef EUSERS
3833 case EUSERS: return WSAEUSERS;
3834 #endif
3835 #ifdef EDQUOT
3836 case EDQUOT: return WSAEDQUOT;
3837 #endif
3838 #ifdef ESTALE
3839 case ESTALE: return WSAESTALE;
3840 #endif
3841 #ifdef EREMOTE
3842 case EREMOTE: return WSAEREMOTE;
3843 #endif
3845 /* just in case we ever get here and there are no problems */
3846 case 0: return 0;
3847 default:
3848 WARN("Unknown errno %d!\n", loc_errno);
3849 return WSAEOPNOTSUPP;
3853 UINT wsaHerrno(int loc_errno)
3856 WARN("h_errno %d.\n", loc_errno);
3858 switch(loc_errno)
3860 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3861 case TRY_AGAIN: return WSATRY_AGAIN;
3862 case NO_RECOVERY: return WSANO_RECOVERY;
3863 case NO_DATA: return WSANO_DATA;
3864 case ENOBUFS: return WSAENOBUFS;
3866 case 0: return 0;
3867 default:
3868 WARN("Unknown h_errno %d!\n", loc_errno);
3869 return WSAEOPNOTSUPP;
3874 /***********************************************************************
3875 * WSARecv (WS2_32.67)
3877 int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3878 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3879 LPWSAOVERLAPPED lpOverlapped,
3880 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3882 return WSARecvFrom(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3883 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3886 /***********************************************************************
3887 * WSARecvFrom (WS2_32.69)
3889 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3890 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3891 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3892 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3895 unsigned int i;
3896 int n, fd, err = WSAENOTSOCK, flags, ret;
3897 struct iovec* iovec;
3898 struct ws2_async *wsa;
3899 IO_STATUS_BLOCK* iosb;
3901 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3902 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3903 (lpFromlen ? *lpFromlen : -1L),
3904 lpOverlapped, lpCompletionRoutine);
3906 fd = get_sock_fd( s, FILE_READ_DATA, &flags );
3907 TRACE( "fd=%d, flags=%x\n", fd, flags );
3909 if (fd == -1) return SOCKET_ERROR;
3911 if (flags & FD_FLAG_RECV_SHUTDOWN)
3913 WSASetLastError( WSAESHUTDOWN );
3914 goto err_close;
3917 iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3918 if ( !iovec )
3920 err = WSAEFAULT;
3921 goto err_close;
3924 for (i = 0; i < dwBufferCount; i++)
3926 iovec[i].iov_base = lpBuffers[i].buf;
3927 iovec[i].iov_len = lpBuffers[i].len;
3930 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3932 wsa = WS2_make_async( s, fd, ws2m_read, iovec, dwBufferCount,
3933 lpFlags, lpFrom, lpFromlen,
3934 lpOverlapped, lpCompletionRoutine, &iosb );
3936 if ( !wsa )
3938 err = WSAEFAULT;
3939 goto err_free;
3942 if ( ( ret = ws2_queue_async( wsa, iosb )) )
3944 err = NtStatusToWSAError( ret );
3946 if ( !lpOverlapped )
3947 HeapFree( GetProcessHeap(), 0, iosb );
3948 HeapFree( GetProcessHeap(), 0, wsa );
3949 goto err_free;
3952 /* Try immediate completion */
3953 if ( lpOverlapped )
3955 if ( WSAGetOverlappedResult( s, lpOverlapped,
3956 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3957 return 0;
3959 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
3960 goto error;
3963 WSASetLastError( WSA_IO_PENDING );
3964 return SOCKET_ERROR;
3967 if ( _is_blocking(s) )
3969 /* block here */
3970 /* FIXME: OOB and exceptfds? */
3971 int timeout = GET_RCVTIMEO(fd);
3972 if( !do_block(fd, POLLIN, timeout)) {
3973 err = WSAETIMEDOUT;
3974 /* a timeout is not fatal */
3975 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3976 goto err_free;
3980 n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3981 if ( n == -1 )
3983 err = wsaErrno();
3984 goto err_free;
3987 TRACE(" -> %i bytes\n", n);
3988 *lpNumberOfBytesRecvd = n;
3990 HeapFree(GetProcessHeap(), 0, iovec);
3991 release_sock_fd( s, fd );
3992 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3994 return 0;
3996 err_free:
3997 HeapFree(GetProcessHeap(), 0, iovec);
3999 err_close:
4000 release_sock_fd( s, fd );
4002 error:
4003 WARN(" -> ERROR %d\n", err);
4004 WSASetLastError( err );
4005 return SOCKET_ERROR;
4008 /***********************************************************************
4009 * WSCInstallProvider (WS2_32.88)
4011 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
4012 LPCWSTR lpszProviderDllPath,
4013 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
4014 DWORD dwNumberOfEntries,
4015 LPINT lpErrno )
4017 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
4018 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
4019 dwNumberOfEntries, lpErrno);
4020 *lpErrno = 0;
4021 return 0;
4025 /***********************************************************************
4026 * WSCDeinstallProvider (WS2_32.83)
4028 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
4030 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
4031 *lpErrno = 0;
4032 return 0;
4036 /***********************************************************************
4037 * WSAAccept (WS2_32.26)
4039 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
4040 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
4043 int ret = 0, size = 0;
4044 WSABUF CallerId, CallerData, CalleeId, CalleeData;
4045 /* QOS SQOS, GQOS; */
4046 GROUP g;
4047 SOCKET cs;
4048 SOCKADDR src_addr, dst_addr;
4050 TRACE("Socket %04x, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
4051 s, addr, addrlen, lpfnCondition, dwCallbackData);
4054 size = sizeof(src_addr);
4055 cs = WS_accept(s, &src_addr, &size);
4057 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
4059 CallerId.buf = (char *)&src_addr;
4060 CallerId.len = sizeof(src_addr);
4062 CallerData.buf = NULL;
4063 CallerData.len = (ULONG)NULL;
4065 WS_getsockname(cs, &dst_addr, &size);
4067 CalleeId.buf = (char *)&dst_addr;
4068 CalleeId.len = sizeof(dst_addr);
4071 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
4072 &CalleeId, &CalleeData, &g, dwCallbackData);
4074 switch (ret)
4076 case CF_ACCEPT:
4077 if (addr && addrlen)
4078 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
4079 return cs;
4080 case CF_DEFER:
4081 SERVER_START_REQ( set_socket_deferred )
4083 req->handle = SOCKET2HANDLE(s);
4084 req->deferred = SOCKET2HANDLE(cs);
4085 if ( !wine_server_call_err ( req ) )
4087 SetLastError( WSATRY_AGAIN );
4088 WS_closesocket( cs );
4091 SERVER_END_REQ;
4092 return SOCKET_ERROR;
4093 case CF_REJECT:
4094 WS_closesocket(cs);
4095 SetLastError(WSAECONNREFUSED);
4096 return SOCKET_ERROR;
4097 default:
4098 FIXME("Unknown return type from Condition function\n");
4099 SetLastError(WSAENOTSOCK);
4100 return SOCKET_ERROR;
4104 /***********************************************************************
4105 * WSADuplicateSocketA (WS2_32.32)
4107 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
4109 HANDLE hProcess;
4111 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4112 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4113 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
4114 /* I don't know what the real Windoze does next, this is a hack */
4115 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
4116 * the target use the global duplicate, or we could copy a reference to us to the structure
4117 * and let the target duplicate it from us, but let's do it as simple as possible */
4118 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4119 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
4120 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4121 0, FALSE, DUPLICATE_SAME_ACCESS);
4122 CloseHandle(hProcess);
4123 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4124 return 0;
4127 /***********************************************************************
4128 * WSADuplicateSocketW (WS2_32.33)
4130 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
4132 HANDLE hProcess;
4134 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4136 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4137 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4138 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
4139 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4140 0, FALSE, DUPLICATE_SAME_ACCESS);
4141 CloseHandle(hProcess);
4142 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4143 return 0;
4146 /***********************************************************************
4147 * WSAInstallServiceClassA (WS2_32.48)
4149 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
4151 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
4152 WSASetLastError(WSAEACCES);
4153 return SOCKET_ERROR;
4156 /***********************************************************************
4157 * WSAInstallServiceClassW (WS2_32.49)
4159 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
4161 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
4162 WSASetLastError(WSAEACCES);
4163 return SOCKET_ERROR;
4166 /***********************************************************************
4167 * WSARemoveServiceClass (WS2_32.70)
4169 int WINAPI WSARemoveServiceClass(LPGUID info)
4171 FIXME("Request to remove service %p\n",info);
4172 WSASetLastError(WSATYPE_NOT_FOUND);
4173 return SOCKET_ERROR;
4176 /***********************************************************************
4177 * WSAStringToAddressA (WS2_32.80)
4179 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
4180 INT AddressFamily,
4181 LPWSAPROTOCOL_INFOA lpProtocolInfo,
4182 LPSOCKADDR lpAddress,
4183 LPINT lpAddressLength)
4185 INT res=0;
4186 struct in_addr inetaddr;
4187 LPSTR workBuffer=NULL,ptrPort;
4189 TRACE( "(%s, %x, %p, %p, %p)\n", AddressString, AddressFamily, lpProtocolInfo,
4190 lpAddress, lpAddressLength );
4192 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
4194 if (AddressString)
4196 workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 );
4197 if (workBuffer)
4199 strcpy(workBuffer,AddressString);
4200 switch (AddressFamily)
4202 case AF_INET:
4203 /* caller wants to know the size of the socket buffer */
4204 if (*lpAddressLength < sizeof(SOCKADDR_IN))
4206 *lpAddressLength = sizeof(SOCKADDR_IN);
4207 res = WSAEFAULT;
4209 else
4211 /* caller wants to translate an AdressString into a SOCKADDR */
4212 if (lpAddress)
4214 memset(lpAddress,0,sizeof(SOCKADDR_IN));
4215 ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET;
4216 ptrPort = strchr(workBuffer,':');
4217 if (ptrPort)
4219 ((LPSOCKADDR_IN)lpAddress)->sin_port = (u_short)atoi(ptrPort+1);
4220 *ptrPort = '\0';
4222 else
4223 ((LPSOCKADDR_IN)lpAddress)->sin_port = 0;
4224 if (inet_aton(workBuffer, &inetaddr) > 0)
4226 ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr;
4227 res = 0;
4229 else
4230 res = WSAEINVAL;
4233 if (lpProtocolInfo)
4234 FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n",
4235 AddressString, AddressFamily,
4236 lpProtocolInfo, lpAddress, lpAddressLength);
4238 break;
4239 default:
4240 FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n",
4241 AddressString, AddressFamily,
4242 lpProtocolInfo, lpAddress, lpAddressLength);
4244 HeapFree( GetProcessHeap(), 0, workBuffer );
4246 else
4247 res = WSA_NOT_ENOUGH_MEMORY;
4249 else
4250 res = WSAEINVAL;
4252 if (!res) return 0;
4253 WSASetLastError(res);
4254 return SOCKET_ERROR;
4257 /***********************************************************************
4258 * WSAStringToAddressW (WS2_32.81)
4260 * Does anybody know if this functions allows to use hebrew/arabic/chinese... digits?
4261 * If this should be the case, it would be required to map these digits
4262 * to Unicode digits (0-9) using FoldString first.
4264 INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
4265 INT AddressFamily,
4266 LPWSAPROTOCOL_INFOW lpProtocolInfo,
4267 LPSOCKADDR lpAddress,
4268 LPINT lpAddressLength)
4270 INT sBuffer,res=0;
4271 LPSTR workBuffer=NULL;
4272 WSAPROTOCOL_INFOA infoA;
4273 LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
4275 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
4276 lpAddress, lpAddressLength );
4278 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
4280 /* if ProtocolInfo is available - convert to ANSI variant */
4281 if (lpProtocolInfo)
4283 lpProtoInfoA = &infoA;
4284 memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
4286 if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
4287 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
4289 WSASetLastError( WSAEINVAL);
4290 return SOCKET_ERROR;
4294 if (AddressString)
4296 /* Translate AddressString to ANSI code page - assumes that only
4297 standard digits 0-9 are used with this API call */
4298 sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
4299 workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
4301 if (workBuffer)
4303 WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
4304 res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
4305 lpAddress,lpAddressLength);
4306 HeapFree( GetProcessHeap(), 0, workBuffer );
4307 return res;
4309 else
4310 res = WSA_NOT_ENOUGH_MEMORY;
4312 else
4313 res = WSAEINVAL;
4315 WSASetLastError(res);
4316 return SOCKET_ERROR;
4319 /***********************************************************************
4320 * WSAAddressToStringA (WS2_32.27)
4322 * See WSAAddressToStringW
4324 INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
4325 LPWSAPROTOCOL_INFOA info, LPSTR string,
4326 LPDWORD lenstr )
4328 INT size;
4329 CHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
4330 CHAR *p;
4332 TRACE( "(%p, %ld, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
4334 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
4335 if (!string || !lenstr) return SOCKET_ERROR;
4337 /* sin_family is garanteed to be the first u_short */
4338 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
4340 sprintf( buffer, "%u.%u.%u.%u:%u",
4341 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
4342 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
4343 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
4344 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
4345 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
4347 p = strchr( buffer, ':' );
4348 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
4350 size = strlen( buffer );
4352 if (*lenstr < size)
4354 *lenstr = size;
4355 WSASetLastError(WSAEFAULT);
4356 return SOCKET_ERROR;
4359 strcpy( string, buffer );
4360 return 0;
4363 /***********************************************************************
4364 * WSAAddressToStringW (WS2_32.28)
4366 * Convert a sockaddr address into a readable address string.
4368 * PARAMS
4369 * sockaddr [I] Pointer to a sockaddr structure.
4370 * len [I] Size of the sockaddr structure.
4371 * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional).
4372 * string [I/O] Pointer to a buffer to receive the address string.
4373 * lenstr [I/O] Size of the receive buffer in WCHARs.
4375 * RETURNS
4376 * Success: 0
4377 * Failure: SOCKET_ERROR
4379 * NOTES
4380 * The 'info' parameter is ignored.
4382 * BUGS
4383 * Only supports AF_INET addresses.
4385 INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
4386 LPWSAPROTOCOL_INFOW info, LPWSTR string,
4387 LPDWORD lenstr )
4389 INT size;
4390 WCHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
4391 static const WCHAR format[] = { '%','u','.','%','u','.','%','u','.','%','u',':','%','u',0 };
4392 WCHAR *p;
4394 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
4396 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
4397 if (!string || !lenstr) return SOCKET_ERROR;
4399 /* sin_family is garanteed to be the first u_short */
4400 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
4402 sprintfW( buffer, format,
4403 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
4404 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
4405 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
4406 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
4407 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
4409 p = strchrW( buffer, ':' );
4410 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
4412 size = lstrlenW( buffer );
4414 if (*lenstr < size)
4416 *lenstr = size;
4417 return SOCKET_ERROR;
4420 lstrcpyW( string, buffer );
4421 return 0;
4424 /***********************************************************************
4425 * WSAEnumNameSpaceProvidersA (WS2_32.34)
4427 INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
4429 FIXME( "(%p %p) Stub!\n", len, buffer );
4430 return 0;
4433 /***********************************************************************
4434 * WSAEnumNameSpaceProvidersW (WS2_32.35)
4436 INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
4438 FIXME( "(%p %p) Stub!\n", len, buffer );
4439 return 0;
4442 /***********************************************************************
4443 * WSAGetQOSByName (WS2_32.41)
4445 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
4447 FIXME( "(0x%04x %p %p) Stub!\n", s, lpQOSName, lpQOS );
4448 return FALSE;
4451 /***********************************************************************
4452 * WSAGetServiceClassInfoA (WS2_32.42)
4454 INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
4455 LPWSASERVICECLASSINFOA info )
4457 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4458 len, info );
4459 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4460 return SOCKET_ERROR;
4463 /***********************************************************************
4464 * WSAGetServiceClassInfoW (WS2_32.43)
4466 INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
4467 LPWSASERVICECLASSINFOW info )
4469 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4470 len, info );
4471 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4472 return SOCKET_ERROR;
4475 /***********************************************************************
4476 * WSAGetServiceClassNameByClassIdA (WS2_32.44)
4478 INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
4480 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4481 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4482 return SOCKET_ERROR;
4485 /***********************************************************************
4486 * WSAGetServiceClassNameByClassIdW (WS2_32.45)
4488 INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
4490 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4491 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4492 return SOCKET_ERROR;
4495 /***********************************************************************
4496 * WSALookupServiceBeginA (WS2_32.59)
4498 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
4499 DWORD dwControlFlags,
4500 LPHANDLE lphLookup)
4502 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4503 lphLookup);
4504 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4505 return SOCKET_ERROR;
4508 /***********************************************************************
4509 * WSALookupServiceBeginW (WS2_32.60)
4511 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
4512 DWORD dwControlFlags,
4513 LPHANDLE lphLookup)
4515 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4516 lphLookup);
4517 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4518 return SOCKET_ERROR;
4521 /***********************************************************************
4522 * WSALookupServiceBeginW (WS2_32.61)
4524 INT WINAPI WSALookupServiceEnd( HANDLE lookup )
4526 FIXME("(%p) Stub!\n", lookup );
4527 return 0;
4530 /***********************************************************************
4531 * WSALookupServiceNextA (WS2_32.62)
4533 INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
4535 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4536 return 0;
4539 /***********************************************************************
4540 * WSALookupServiceNextW (WS2_32.63)
4542 INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
4544 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4545 return 0;
4548 /***********************************************************************
4549 * WSANtohl (WS2_32.64)
4551 INT WINAPI WSANtohl( SOCKET s, u_long netlong, u_long* lphostlong )
4553 TRACE( "(0x%04x 0x%08lx %p)\n", s, netlong, lphostlong );
4555 if (!lphostlong) return WSAEFAULT;
4557 *lphostlong = ntohl( netlong );
4558 return 0;
4561 /***********************************************************************
4562 * WSANtohs (WS2_32.65)
4564 INT WINAPI WSANtohs( SOCKET s, u_short netshort, u_short* lphostshort )
4566 TRACE( "(0x%04x 0x%08x %p)\n", s, netshort, lphostshort );
4568 if (!lphostshort) return WSAEFAULT;
4570 *lphostshort = ntohs( netshort );
4571 return 0;
4574 /***********************************************************************
4575 * WSAProviderConfigChange (WS2_32.66)
4577 INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
4578 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4580 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
4581 return SOCKET_ERROR;
4584 /***********************************************************************
4585 * WSARecvDisconnect (WS2_32.68)
4587 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
4589 TRACE( "(0x%04x %p)\n", s, disconnectdata );
4591 return WS_shutdown( s, 0 );
4594 /***********************************************************************
4595 * WSASetServiceA (WS2_32.76)
4597 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
4599 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4600 return 0;
4603 /***********************************************************************
4604 * WSASetServiceW (WS2_32.77)
4606 INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
4608 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4609 return 0;
4612 /***********************************************************************
4613 * WSCEnableNSProvider (WS2_32.84)
4615 INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
4617 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
4618 return 0;
4621 /***********************************************************************
4622 * WSCGetProviderPath (WS2_32.86)
4624 INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errcode )
4626 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errcode );
4628 if (!errcode || !provider || !len) return WSAEFAULT;
4630 *errcode = WSAEINVAL;
4631 return SOCKET_ERROR;
4634 /***********************************************************************
4635 * WSCInstallNameSpace (WS2_32.87)
4637 INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
4638 DWORD version, LPGUID provider )
4640 FIXME( "(%s %s 0x%08lx 0x%08lx %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
4641 namespace, version, debugstr_guid(provider) );
4642 return 0;
4645 /***********************************************************************
4646 * WSCUnInstallNameSpace (WS2_32.89)
4648 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
4650 FIXME("(%p) Stub!\n", lpProviderId);
4651 return NO_ERROR;
4654 /***********************************************************************
4655 * WSCWriteProviderOrder (WS2_32.91)
4657 INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
4659 FIXME("(%p 0x%08lx) Stub!\n", entry, number);
4660 return 0;