Release 0.9.14.
[wine/multimedia.git] / dlls / ws2_32 / socket.c
blob8887ae8dd966e4b5ced796bb543213f71499ec2d
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * NOTE: If you make any changes to fix a particular app, make sure
23 * they don't break something else like Netscape or telnet and ftp
24 * clients and servers (www.winsite.com got a lot of those).
27 #include "config.h"
28 #include "wine/port.h"
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #ifdef HAVE_SYS_IPC_H
35 # include <sys/ipc.h>
36 #endif
37 #ifdef HAVE_SYS_IOCTL_H
38 # include <sys/ioctl.h>
39 #endif
40 #ifdef HAVE_SYS_FILIO_H
41 # include <sys/filio.h>
42 #endif
43 #ifdef HAVE_SYS_SOCKIO_H
44 # include <sys/sockio.h>
45 #endif
47 #if defined(__EMX__)
48 # include <sys/so_ioctl.h>
49 #endif
51 #ifdef HAVE_SYS_PARAM_H
52 # include <sys/param.h>
53 #endif
55 #ifdef HAVE_SYS_MSG_H
56 # include <sys/msg.h>
57 #endif
58 #ifdef HAVE_SYS_WAIT_H
59 # include <sys/wait.h>
60 #endif
61 #ifdef HAVE_SYS_UIO_H
62 # include <sys/uio.h>
63 #endif
64 #ifdef HAVE_SYS_SOCKET_H
65 #include <sys/socket.h>
66 #endif
67 #ifdef HAVE_NETINET_IN_H
68 # include <netinet/in.h>
69 #endif
70 #ifdef HAVE_NETINET_TCP_H
71 # include <netinet/tcp.h>
72 #endif
73 #ifdef HAVE_ARPA_INET_H
74 # include <arpa/inet.h>
75 #endif
76 #include <ctype.h>
77 #include <fcntl.h>
78 #include <errno.h>
79 #ifdef HAVE_SYS_ERRNO_H
80 #include <sys/errno.h>
81 #endif
82 #ifdef HAVE_NETDB_H
83 #include <netdb.h>
84 #endif
85 #ifdef HAVE_UNISTD_H
86 # include <unistd.h>
87 #endif
88 #include <stdlib.h>
89 #ifdef HAVE_ARPA_NAMESER_H
90 # include <arpa/nameser.h>
91 #endif
92 #ifdef HAVE_RESOLV_H
93 # include <resolv.h>
94 #endif
95 #ifdef HAVE_NET_IF_H
96 # include <net/if.h>
97 #endif
99 #ifdef HAVE_NETIPX_IPX_H
100 # include <netipx/ipx.h>
101 # define HAVE_IPX
102 #elif defined(HAVE_LINUX_IPX_H)
103 # ifdef HAVE_ASM_TYPES_H
104 # include <asm/types.h>
105 # endif
106 # 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 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
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;
934 /* Note: Windows has 2 versions of the sockaddr_in6 struct, one with
935 * scope_id, one without. Check:
936 * http://msdn.microsoft.com/library/en-us/winsock/winsock/sockaddr_2.asp
938 if (wsaddrlen >= sizeof(struct WS_sockaddr_in6_old)) {
939 *uaddrlen=sizeof(struct sockaddr_in6);
940 uin6=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
941 uin6->sin6_family = AF_INET6;
942 uin6->sin6_port = win6->sin6_port;
943 uin6->sin6_flowinfo = win6->sin6_flowinfo;
944 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
945 if (wsaddrlen >= sizeof(struct WS_sockaddr_in6)) uin6->sin6_scope_id = win6->sin6_scope_id;
946 #endif
947 memcpy(&uin6->sin6_addr,&win6->sin6_addr,16); /* 16 bytes = 128 address bits */
948 return (struct sockaddr*)uin6;
950 FIXME("bad size %d for WS_sockaddr_in6\n",wsaddrlen);
951 return NULL;
953 case WS_AF_INET: {
954 struct sockaddr_in* uin;
955 const struct WS_sockaddr_in* win = (struct WS_sockaddr_in*)wsaddr;
957 if (wsaddrlen<sizeof(struct WS_sockaddr_in))
958 return NULL;
959 *uaddrlen=sizeof(struct sockaddr_in);
960 uin = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
961 uin->sin_family = AF_INET;
962 uin->sin_port = win->sin_port;
963 memcpy(&uin->sin_addr,&win->sin_addr,4); /* 4 bytes = 32 address bits */
964 return (struct sockaddr*)uin;
966 case WS_AF_UNSPEC: {
967 /* Try to determine the needed space by the passed windows sockaddr space */
968 switch (wsaddrlen) {
969 default: /* likely a ipv4 address */
970 case sizeof(struct WS_sockaddr_in):
971 *uaddrlen = sizeof(struct sockaddr_in);
972 break;
973 #ifdef HAVE_IPX
974 case sizeof(struct WS_sockaddr_ipx):
975 *uaddrlen = sizeof(struct sockaddr_ipx);
976 break;
977 #endif
978 case sizeof(struct WS_sockaddr_in6):
979 case sizeof(struct WS_sockaddr_in6_old):
980 *uaddrlen = sizeof(struct sockaddr_in6);
981 break;
983 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,*uaddrlen);
985 default:
986 FIXME("Unknown address family %d, return NULL.\n", wsaddr->sa_family);
987 return NULL;
991 /* Allocates a Unix sockaddr structure to receive the data */
992 static inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, unsigned int* uaddrlen)
994 if (wsaddr==NULL)
996 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
998 /* This is not strictly the right thing to do. Hope it works however */
999 *uaddrlen=0;
1001 return NULL;
1004 if (*wsaddrlen==0)
1005 *uaddrlen=0;
1006 else
1007 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
1009 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
1012 /* Returns 0 if successful, -1 if the buffer is too small */
1013 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
1015 int res;
1017 switch(uaddr->sa_family)
1019 #ifdef HAVE_IPX
1020 case AF_IPX:
1022 const struct sockaddr_ipx* uipx=(const struct sockaddr_ipx*)uaddr;
1023 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
1025 res=-1;
1026 switch (*wsaddrlen) /* how much can we copy? */
1028 default:
1029 res=0; /* enough */
1030 *wsaddrlen=uaddrlen;
1031 wsipx->sa_socket=uipx->sipx_port;
1032 /* fall through */
1033 case 13:
1034 case 12:
1035 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
1036 /* fall through */
1037 case 11:
1038 case 10:
1039 case 9:
1040 case 8:
1041 case 7:
1042 case 6:
1043 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
1044 /* fall through */
1045 case 5:
1046 case 4:
1047 case 3:
1048 case 2:
1049 wsipx->sa_family=WS_AF_IPX;
1050 /* fall through */
1051 case 1:
1052 case 0:
1053 /* way too small */
1054 break;
1057 break;
1058 #endif
1059 case AF_INET6: {
1060 const struct sockaddr_in6* uin6 = (struct sockaddr_in6*)uaddr;
1061 struct WS_sockaddr_in6_old* win6old = (struct WS_sockaddr_in6_old*)wsaddr;
1063 if (*wsaddrlen < sizeof(struct WS_sockaddr_in6_old))
1064 return -1;
1065 win6old->sin6_family = WS_AF_INET6;
1066 win6old->sin6_port = uin6->sin6_port;
1067 win6old->sin6_flowinfo = uin6->sin6_flowinfo;
1068 memcpy(&win6old->sin6_addr,&uin6->sin6_addr,16); /* 16 bytes = 128 address bits */
1069 *wsaddrlen = sizeof(struct WS_sockaddr_in6_old);
1070 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
1071 if (*wsaddrlen >= sizeof(struct WS_sockaddr_in6)) {
1072 struct WS_sockaddr_in6* win6 = (struct WS_sockaddr_in6*)wsaddr;
1073 win6->sin6_scope_id = uin6->sin6_scope_id;
1074 *wsaddrlen = sizeof(struct WS_sockaddr_in6);
1076 #endif
1077 return 0;
1079 case AF_INET: {
1080 struct sockaddr_in* uin = (struct sockaddr_in*)uaddr;
1081 struct WS_sockaddr_in* win = (struct WS_sockaddr_in*)wsaddr;
1083 if (*wsaddrlen < sizeof(struct WS_sockaddr_in))
1084 return -1;
1085 win->sin_family = WS_AF_INET;
1086 win->sin_port = uin->sin_port;
1087 memcpy(&win->sin_addr,&uin->sin_addr,4); /* 4 bytes = 32 address bits */
1088 *wsaddrlen = sizeof(struct WS_sockaddr_in);
1089 return 0;
1091 case AF_UNSPEC: {
1092 memset(wsaddr,0,*wsaddrlen);
1093 return 0;
1095 default:
1096 FIXME("Unknown address family %d\n", uaddr->sa_family);
1097 return -1;
1099 return res;
1102 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
1103 * ws_sockaddr_alloc
1105 static inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
1107 if (uaddr!=(const struct sockaddr*)wsaddr)
1108 HeapFree(GetProcessHeap(), 0, (void *)uaddr);
1111 /**************************************************************************
1112 * Functions for handling overlapped I/O
1113 **************************************************************************/
1115 static void CALLBACK ws2_async_terminate(ws2_async* as, IO_STATUS_BLOCK* iosb)
1117 TRACE( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, iosb );
1119 wine_server_release_fd( as->hSocket, as->fd );
1120 if ( as->event != INVALID_HANDLE_VALUE )
1121 NtSetEvent( as->event, NULL );
1123 if (as->completion_func)
1124 as->completion_func( NtStatusToWSAError (iosb->u.Status),
1125 iosb->Information, as->user_overlapped, as->flags );
1126 if ( !as->user_overlapped )
1128 #if 0
1129 /* FIXME: I don't think this is really used */
1130 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
1131 WSACloseEvent( as->overlapped->hEvent );
1132 #endif
1133 HeapFree( GetProcessHeap(), 0, iosb );
1136 HeapFree( GetProcessHeap(), 0, as->iovec );
1137 HeapFree( GetProcessHeap(), 0, as );
1140 /***********************************************************************
1141 * WS2_make_async (INTERNAL)
1144 static void WINAPI WS2_async_recv(void*, IO_STATUS_BLOCK*, ULONG);
1145 static void WINAPI WS2_async_send(void*, IO_STATUS_BLOCK*, ULONG);
1146 static void WINAPI WS2_async_shutdown( void*, IO_STATUS_BLOCK*, ULONG);
1148 inline static struct ws2_async*
1149 WS2_make_async(SOCKET s, int fd, enum ws2_mode mode, struct iovec *iovec, DWORD dwBufferCount,
1150 LPDWORD lpFlags, struct WS_sockaddr *addr,
1151 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
1152 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
1153 IO_STATUS_BLOCK **piosb)
1155 struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof( ws2_async ) );
1157 TRACE( "wsa %p\n", wsa );
1159 if (!wsa)
1160 return NULL;
1162 wsa->hSocket = (HANDLE) s;
1163 wsa->mode = mode;
1164 switch (mode)
1166 case ws2m_read:
1167 case ws2m_sd_read:
1168 wsa->flags = *lpFlags;
1169 wsa->addrlen.ptr = addrlen;
1170 break;
1171 case ws2m_write:
1172 case ws2m_sd_write:
1173 wsa->flags = 0;
1174 wsa->addrlen.val = *addrlen;
1175 break;
1176 default:
1177 ERR("Invalid async mode: %d\n", mode);
1179 wsa->user_overlapped = lpOverlapped;
1180 wsa->completion_func = lpCompletionRoutine;
1181 wsa->iovec = iovec;
1182 wsa->n_iovecs = dwBufferCount;
1183 wsa->addr = addr;
1184 wsa->fd = fd;
1185 wsa->event = INVALID_HANDLE_VALUE;
1187 if ( lpOverlapped )
1189 *piosb = (IO_STATUS_BLOCK*)lpOverlapped;
1190 if (!lpCompletionRoutine)
1192 wsa->event = lpOverlapped->hEvent;
1193 NtResetEvent(wsa->event, NULL);
1196 else if (!(*piosb = HeapAlloc( GetProcessHeap(), 0, sizeof(IO_STATUS_BLOCK))))
1197 goto error;
1199 (*piosb)->Information = 0;
1200 (*piosb)->u.Status = STATUS_PENDING;
1201 TRACE( "wsa %p, h %p, ev %p, fd %d, iosb %p, uov %p, cfunc %p\n",
1202 wsa, wsa->hSocket, wsa->event, wsa->fd,
1203 *piosb, wsa->user_overlapped, wsa->completion_func );
1205 return wsa;
1207 error:
1208 TRACE("Error\n");
1209 HeapFree( GetProcessHeap(), 0, wsa );
1210 return NULL;
1213 static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb)
1215 PIO_APC_ROUTINE apc;
1216 int type;
1217 NTSTATUS status;
1219 switch (wsa->mode)
1221 case ws2m_read: apc = WS2_async_recv; type = ASYNC_TYPE_READ; break;
1222 case ws2m_write: apc = WS2_async_send; type = ASYNC_TYPE_WRITE; break;
1223 case ws2m_sd_read: apc = WS2_async_shutdown; type = ASYNC_TYPE_READ; break;
1224 case ws2m_sd_write: apc = WS2_async_shutdown; type = ASYNC_TYPE_WRITE; break;
1225 default: FIXME("Unknown internal mode (%d)\n", wsa->mode); return STATUS_INVALID_PARAMETER;
1228 SERVER_START_REQ( register_async )
1230 req->handle = wsa->hSocket;
1231 req->io_apc = apc;
1232 req->io_sb = iosb;
1233 req->io_user = wsa;
1234 req->type = type;
1235 req->count = iosb->Information;
1236 status = wine_server_call( req );
1238 SERVER_END_REQ;
1240 if ( status ) iosb->u.Status = status;
1241 if ( iosb->u.Status != STATUS_PENDING )
1243 /* Note: we get here a non zero status when we couldn't queue the async
1244 * in the server. Therefore, we simply terminate the async.
1246 status = iosb->u.Status;
1247 ws2_async_terminate(wsa, iosb);
1248 return status;
1250 NtCurrentTeb()->num_async_io++;
1251 return STATUS_SUCCESS;
1254 /***********************************************************************
1255 * WS2_recv (INTERNAL)
1257 * Workhorse for both synchronous and asynchronous recv() operations.
1259 static int WS2_recv( int fd, struct iovec* iov, int count,
1260 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1261 LPDWORD lpFlags )
1263 struct msghdr hdr;
1264 int n;
1265 TRACE( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
1266 fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
1268 hdr.msg_name = NULL;
1270 if ( lpFrom )
1272 hdr.msg_namelen = *lpFromlen;
1273 hdr.msg_name = ws_sockaddr_alloc( lpFrom, lpFromlen, &hdr.msg_namelen );
1274 if ( !hdr.msg_name )
1276 WSASetLastError( WSAEFAULT );
1277 n = -1;
1278 goto out;
1281 else
1282 hdr.msg_namelen = 0;
1284 hdr.msg_iov = iov;
1285 hdr.msg_iovlen = count;
1286 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1287 hdr.msg_accrights = NULL;
1288 hdr.msg_accrightslen = 0;
1289 #else
1290 hdr.msg_control = NULL;
1291 hdr.msg_controllen = 0;
1292 hdr.msg_flags = 0;
1293 #endif
1295 if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 )
1297 TRACE( "recvmsg error %d\n", errno);
1298 goto out;
1301 if ( lpFrom &&
1302 ws_sockaddr_u2ws( hdr.msg_name, hdr.msg_namelen,
1303 lpFrom, lpFromlen ) != 0 )
1305 /* The from buffer was too small, but we read the data
1306 * anyway. Is that really bad?
1308 WSASetLastError( WSAEFAULT );
1309 WARN( "Address buffer too small\n" );
1312 out:
1314 ws_sockaddr_free( hdr.msg_name, lpFrom );
1315 TRACE("-> %d\n", n);
1316 return n;
1319 /***********************************************************************
1320 * WS2_async_recv (INTERNAL)
1322 * Handler for overlapped recv() operations.
1324 static void WINAPI WS2_async_recv( void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
1326 ws2_async* wsa = (ws2_async*) ovp;
1327 int result, err;
1329 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1331 switch (status)
1333 case STATUS_ALERTED:
1334 result = WS2_recv( wsa->fd, wsa->iovec, wsa->n_iovecs,
1335 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1336 if (result >= 0)
1338 iosb->u.Status = STATUS_SUCCESS;
1339 iosb->Information = result;
1340 TRACE( "received %d bytes\n", result );
1341 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1343 else
1345 err = wsaErrno();
1346 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1348 iosb->u.Status = STATUS_PENDING;
1349 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1350 TRACE( "still pending\n" );
1352 else
1354 iosb->u.Status = err; /* FIXME: is this correct ???? */
1355 TRACE( "Error: %x\n", err );
1358 if (iosb->u.Status == STATUS_PENDING)
1359 ws2_queue_async(wsa, iosb);
1360 else
1361 ws2_async_terminate(wsa, iosb);
1362 break;
1363 default:
1364 FIXME( "status: %ld\n", status );
1365 iosb->u.Status = status;
1366 ws2_async_terminate(wsa, iosb);
1367 return;
1371 /***********************************************************************
1372 * WS2_send (INTERNAL)
1374 * Workhorse for both synchronous and asynchronous send() operations.
1376 static int WS2_send( int fd, struct iovec* iov, int count,
1377 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1379 struct msghdr hdr;
1380 int n = -1;
1381 TRACE( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
1382 fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
1384 hdr.msg_name = NULL;
1386 if ( to )
1388 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u( to, tolen, &hdr.msg_namelen );
1389 if ( !hdr.msg_name )
1391 WSASetLastError( WSAEFAULT );
1392 goto out;
1395 #ifdef HAVE_IPX
1396 if(to->sa_family == WS_AF_IPX)
1398 #ifdef SOL_IPX
1399 struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
1400 int val=0;
1401 unsigned int len=sizeof(int);
1403 /* The packet type is stored at the ipx socket level; At least the linux kernel seems
1404 * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
1405 * the packet type and then we can retrieve it using getsockopt. After that we can set the
1406 * ipx type in the sockaddr_opx structure with the stored value.
1408 if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
1410 TRACE("ptype: %d (fd:%d)\n", val, fd);
1411 uipx->sipx_type = val;
1413 #endif
1415 #endif
1418 else
1419 hdr.msg_namelen = 0;
1421 hdr.msg_iov = iov;
1422 hdr.msg_iovlen = count;
1423 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1424 hdr.msg_accrights = NULL;
1425 hdr.msg_accrightslen = 0;
1426 #else
1427 hdr.msg_control = NULL;
1428 hdr.msg_controllen = 0;
1429 hdr.msg_flags = 0;
1430 #endif
1432 n = sendmsg(fd, &hdr, dwFlags);
1434 out:
1435 ws_sockaddr_free( hdr.msg_name, to );
1436 return n;
1439 /***********************************************************************
1440 * WS2_async_send (INTERNAL)
1442 * Handler for overlapped send() operations.
1444 static void WINAPI WS2_async_send(void* as, IO_STATUS_BLOCK* iosb, ULONG status)
1446 ws2_async* wsa = (ws2_async*) as;
1447 int result;
1449 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1451 switch (status)
1453 case STATUS_ALERTED:
1454 if (iosb->u.Status != STATUS_PENDING) FIXME("wrong %08lx\n", iosb->u.Status);
1455 /* check to see if the data is ready (non-blocking) */
1456 result = WS2_send( wsa->fd, wsa->iovec, wsa->n_iovecs,
1457 wsa->addr, wsa->addrlen.val, wsa->flags );
1459 if (result >= 0)
1461 iosb->u.Status = STATUS_SUCCESS;
1462 iosb->Information = result;
1463 TRACE( "sent %d bytes\n", result );
1464 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1466 else
1468 int err = wsaErrno();
1469 if ( err == WSAEINTR )
1471 iosb->u.Status = STATUS_PENDING;
1472 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1473 TRACE( "still pending\n" );
1475 else
1477 /* We set the status to a winsock error code and check for that
1478 later in NtStatusToWSAError () */
1479 iosb->u.Status = err;
1480 TRACE( "Error: %x\n", err );
1483 if (iosb->u.Status == STATUS_PENDING)
1484 ws2_queue_async(wsa, iosb);
1485 else
1486 ws2_async_terminate(wsa, iosb);
1487 break;
1488 default:
1489 FIXME( "status: %ld\n", status );
1490 iosb->u.Status = status;
1491 ws2_async_terminate(wsa, iosb);
1492 return;
1497 /***********************************************************************
1498 * WS2_async_shutdown (INTERNAL)
1500 * Handler for shutdown() operations on overlapped sockets.
1502 static void WINAPI WS2_async_shutdown( void* as, PIO_STATUS_BLOCK iosb, ULONG status )
1504 ws2_async* wsa = (ws2_async*) as;
1505 int err = 1;
1507 TRACE( "async %p %d\n", wsa, wsa->mode );
1508 switch (status)
1510 case STATUS_ALERTED:
1511 switch ( wsa->mode )
1513 case ws2m_sd_read: err = shutdown( wsa->fd, 0 ); break;
1514 case ws2m_sd_write: err = shutdown( wsa->fd, 1 ); break;
1515 default: ERR("invalid mode: %d\n", wsa->mode );
1517 iosb->u.Status = err ? wsaErrno() : STATUS_SUCCESS;
1518 if (iosb->u.Status == STATUS_PENDING)
1519 ws2_queue_async(wsa, iosb);
1520 else
1521 ws2_async_terminate(wsa, iosb);
1522 break;
1523 default:
1524 iosb->u.Status = status;
1525 ws2_async_terminate(wsa, iosb);
1526 break;
1531 /***********************************************************************
1532 * WS2_register_async_shutdown (INTERNAL)
1534 * Helper function for WS_shutdown() on overlapped sockets.
1536 static int WS2_register_async_shutdown( SOCKET s, int fd, enum ws2_mode mode )
1538 struct ws2_async *wsa;
1539 int ret, err = WSAEFAULT;
1540 DWORD dwflags = 0;
1541 int len = 0;
1542 LPWSAOVERLAPPED ovl = HeapAlloc(GetProcessHeap(), 0, sizeof( WSAOVERLAPPED ));
1543 IO_STATUS_BLOCK *iosb = NULL;
1545 TRACE("s %d fd %d mode %d\n", s, fd, mode);
1546 if (!ovl)
1547 goto out;
1549 ovl->hEvent = WSACreateEvent();
1550 if ( ovl->hEvent == WSA_INVALID_EVENT )
1551 goto out_free;
1553 wsa = WS2_make_async( s, fd, mode, NULL, 0,
1554 &dwflags, NULL, &len, ovl, NULL, &iosb );
1555 if ( !wsa )
1556 goto out_close;
1558 /* Hack: this will cause ws2_async_terminate() to free the overlapped structure */
1559 wsa->user_overlapped = NULL;
1560 if ( (ret = ws2_queue_async( wsa, iosb )) )
1562 err = NtStatusToWSAError( ret );
1563 goto out;
1565 /* Try immediate completion */
1566 while ( WaitForSingleObjectEx( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1567 return 0;
1569 out_close:
1570 WSACloseEvent( ovl->hEvent );
1571 out_free:
1572 HeapFree( GetProcessHeap(), 0, ovl );
1573 out:
1574 return err;
1577 /***********************************************************************
1578 * accept (WS2_32.1)
1580 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1581 int *addrlen32)
1583 SOCKET as;
1584 BOOL is_blocking;
1586 TRACE("socket %04x\n", s );
1587 is_blocking = _is_blocking(s);
1589 do {
1590 if (is_blocking)
1592 int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
1593 if (fd == -1) return INVALID_SOCKET;
1594 /* block here */
1595 do_block(fd, POLLIN, -1);
1596 _sync_sock_state(s); /* let wineserver notice connection */
1597 release_sock_fd( s, fd );
1598 /* retrieve any error codes from it */
1599 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1600 /* FIXME: care about the error? */
1602 SERVER_START_REQ( accept_socket )
1604 req->lhandle = SOCKET2HANDLE(s);
1605 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1606 req->attributes = OBJ_INHERIT;
1607 set_error( wine_server_call( req ) );
1608 as = HANDLE2SOCKET( reply->handle );
1610 SERVER_END_REQ;
1611 if (as)
1613 if (addr) WS_getpeername(as, addr, addrlen32);
1614 return as;
1616 } while (is_blocking);
1617 return INVALID_SOCKET;
1620 /***********************************************************************
1621 * bind (WS2_32.2)
1623 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1625 int fd = get_sock_fd( s, 0, NULL );
1626 int res = SOCKET_ERROR;
1628 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1630 if (fd != -1)
1632 if (!name || (name->sa_family && !SUPPORTED_PF(name->sa_family)))
1634 SetLastError(WSAEAFNOSUPPORT);
1636 else
1638 const struct sockaddr* uaddr;
1639 unsigned int uaddrlen;
1641 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1642 if (uaddr == NULL)
1644 SetLastError(WSAEFAULT);
1646 else
1648 if (bind(fd, uaddr, uaddrlen) < 0)
1650 int loc_errno = errno;
1651 WARN("\tfailure - errno = %i\n", errno);
1652 errno = loc_errno;
1653 switch (errno)
1655 case EBADF:
1656 SetLastError(WSAENOTSOCK);
1657 break;
1658 case EADDRNOTAVAIL:
1659 SetLastError(WSAEINVAL);
1660 break;
1661 default:
1662 SetLastError(wsaErrno());
1663 break;
1666 else
1668 res=0; /* success */
1670 ws_sockaddr_free(uaddr,name);
1673 release_sock_fd( s, fd );
1675 return res;
1678 /***********************************************************************
1679 * closesocket (WS2_32.3)
1681 int WINAPI WS_closesocket(SOCKET s)
1683 TRACE("socket %04x\n", s);
1684 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1685 return SOCKET_ERROR;
1688 /***********************************************************************
1689 * connect (WS2_32.4)
1691 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1693 int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
1695 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1697 if (fd != -1)
1699 const struct sockaddr* uaddr;
1700 unsigned int uaddrlen;
1702 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1703 if (uaddr == NULL)
1705 SetLastError(WSAEFAULT);
1707 else
1709 int rc;
1711 rc=connect(fd, uaddr, uaddrlen);
1712 ws_sockaddr_free(uaddr,name);
1713 if (rc == 0)
1714 goto connect_success;
1717 if (errno == EINPROGRESS)
1719 /* tell wineserver that a connection is in progress */
1720 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1721 FD_CONNECT|FD_READ|FD_WRITE,
1722 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1723 if (_is_blocking(s))
1725 int result;
1726 /* block here */
1727 do_block(fd, POLLIN | POLLOUT, -1);
1728 _sync_sock_state(s); /* let wineserver notice connection */
1729 /* retrieve any error codes from it */
1730 result = _get_sock_error(s, FD_CONNECT_BIT);
1731 if (result)
1732 SetLastError(result);
1733 else
1735 goto connect_success;
1738 else
1740 SetLastError(WSAEWOULDBLOCK);
1743 else
1745 SetLastError(wsaErrno());
1747 release_sock_fd( s, fd );
1749 return SOCKET_ERROR;
1751 connect_success:
1752 release_sock_fd( s, fd );
1753 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1754 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1755 FD_CONNECT|FD_WINE_LISTENING);
1756 return 0;
1759 /***********************************************************************
1760 * WSAConnect (WS2_32.30)
1762 int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
1763 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1764 LPQOS lpSQOS, LPQOS lpGQOS )
1766 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1767 FIXME("unsupported parameters!\n");
1768 return WS_connect( s, name, namelen );
1772 /***********************************************************************
1773 * getpeername (WS2_32.5)
1775 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1777 int fd;
1778 int res;
1780 TRACE("socket: %04x, ptr %p, len %08x\n", s, name, *namelen);
1782 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1783 if( (name == NULL) || (namelen == NULL) )
1785 SetLastError( WSAEFAULT );
1786 return SOCKET_ERROR;
1789 fd = get_sock_fd( s, 0, NULL );
1790 res = SOCKET_ERROR;
1792 if (fd != -1)
1794 struct sockaddr* uaddr;
1795 unsigned int uaddrlen;
1797 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1798 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1800 SetLastError(wsaErrno());
1802 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1804 /* The buffer was too small */
1805 SetLastError(WSAEFAULT);
1807 else
1809 res=0;
1811 ws_sockaddr_free(uaddr,name);
1812 release_sock_fd( s, fd );
1814 return res;
1817 /***********************************************************************
1818 * getsockname (WS2_32.6)
1820 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1822 int fd;
1823 int res;
1825 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1827 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1828 if( (name == NULL) || (namelen == NULL) )
1830 SetLastError( WSAEFAULT );
1831 return SOCKET_ERROR;
1834 fd = get_sock_fd( s, 0, NULL );
1835 res = SOCKET_ERROR;
1837 if (fd != -1)
1839 struct sockaddr* uaddr;
1840 unsigned int uaddrlen;
1842 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1843 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1845 SetLastError(wsaErrno());
1847 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1849 /* The buffer was too small */
1850 SetLastError(WSAEFAULT);
1852 else
1854 res=0;
1856 ws_sockaddr_free(uaddr,name);
1857 release_sock_fd( s, fd );
1859 return res;
1862 /***********************************************************************
1863 * getsockopt (WS2_32.7)
1865 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1866 INT optname, char *optval, INT *optlen)
1868 int fd;
1869 INT ret = 0;
1871 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %p, len %d\n",
1872 s, level, optname, optval, *optlen);
1873 /* SO_OPENTYPE does not require a valid socket handle. */
1874 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1876 if (!optlen || *optlen < sizeof(int) || !optval)
1878 SetLastError(WSAEFAULT);
1879 return SOCKET_ERROR;
1881 *(int *)optval = get_per_thread_data()->opentype;
1882 *optlen = sizeof(int);
1883 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1884 return 0;
1887 #ifdef HAVE_IPX
1888 if(level == NSPROTO_IPX)
1890 struct WS_sockaddr_ipx addr;
1891 IPX_ADDRESS_DATA *data;
1892 int namelen;
1893 switch(optname)
1895 case IPX_PTYPE:
1896 fd = get_sock_fd( s, 0, NULL );
1897 #ifdef SOL_IPX
1898 if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, (unsigned int*)optlen) == -1)
1900 return SOCKET_ERROR;
1902 #else
1904 struct ipx val;
1905 socklen_t len=sizeof(struct ipx);
1907 if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
1908 return SOCKET_ERROR;
1909 *optval = (int)val.ipx_pt;
1911 #endif
1912 TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
1913 release_sock_fd( s, fd );
1915 return 0;
1916 case IPX_ADDRESS:
1918 * On a Win2000 system with one network card there are usually three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
1919 * Using this call you can then retrieve info about this all. In case of Linux it is a bit different. Usually you have
1920 * only "one" device active and further it is not possible to query things like the linkspeed.
1922 FIXME("IPX_ADDRESS\n");
1923 namelen = sizeof(struct WS_sockaddr_ipx);
1924 memset(&addr, 0, sizeof(struct WS_sockaddr_ipx));
1925 WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
1927 data = (IPX_ADDRESS_DATA*)optval;
1928 memcpy(data->nodenum,&addr.sa_nodenum,sizeof(data->nodenum));
1929 memcpy(data->netnum,&addr.sa_netnum,sizeof(data->netnum));
1930 data->adapternum = 0;
1931 data->wan = FALSE; /* We are not on a wan for now .. */
1932 data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
1933 data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
1934 data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit; note 1MB = 1000kB in this case */
1935 return 0;
1936 case IPX_MAX_ADAPTER_NUM:
1937 FIXME("IPX_MAX_ADAPTER_NUM\n");
1938 *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
1940 return 0;
1941 default:
1942 FIXME("IPX optname:%x\n", optname);
1943 return SOCKET_ERROR;
1946 #endif
1948 if( (fd = get_sock_fd( s, 0, NULL )) == -1)
1949 return SOCKET_ERROR;
1951 if (!convert_sockopt(&level, &optname)) {
1952 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1953 ret = SOCKET_ERROR;
1954 } else {
1955 struct timeval tv;
1956 struct linger lingval;
1957 unsigned int len, *plen = (unsigned int*)optlen;
1958 char *pval = optval;
1959 if(level == SOL_SOCKET && is_timeout_option(optname)) {
1960 len = sizeof(tv);
1961 plen = &len;
1962 pval = (char *) &tv;
1963 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1964 len = sizeof(lingval);
1965 plen = &len;
1966 pval = (char *) &lingval;
1968 if (getsockopt(fd, (int) level, optname, pval, plen) != 0 ) {
1969 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1970 ret = SOCKET_ERROR;
1971 } else if(level == SOL_SOCKET && is_timeout_option(optname)) {
1972 if( *optlen >= sizeof(INT) ) {
1973 *optlen = sizeof(INT);
1974 *(INT*)optval = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1975 } else {
1976 SetLastError(WSAEFAULT);
1977 ret = SOCKET_ERROR;
1979 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1980 if( *optlen >= sizeof( LINGER) ) {
1981 (( LINGER *) optval)->l_onoff = lingval.l_onoff;
1982 (( LINGER *) optval)->l_linger = lingval.l_linger;
1983 } else {
1984 SetLastError(WSAEFAULT);
1985 ret = SOCKET_ERROR;
1989 release_sock_fd( s, fd );
1990 return ret;
1994 /***********************************************************************
1995 * htonl (WINSOCK.8)
1996 * htonl (WS2_32.8)
1998 u_long WINAPI WS_htonl(u_long hostlong)
2000 return htonl(hostlong);
2004 /***********************************************************************
2005 * htons (WINSOCK.9)
2006 * htons (WS2_32.9)
2008 u_short WINAPI WS_htons(u_short hostshort)
2010 return htons(hostshort);
2013 /***********************************************************************
2014 * WSAHtonl (WS2_32.46)
2015 * From MSDN decription of error codes, this function should also
2016 * check if WinSock has been initialized and the socket is a valid
2017 * socket. But why? This function only translates a host byte order
2018 * u_long into a network byte order u_long...
2020 int WINAPI WSAHtonl(SOCKET s, u_long hostlong, u_long *lpnetlong)
2022 if (lpnetlong)
2024 *lpnetlong = htonl(hostlong);
2025 return 0;
2027 WSASetLastError(WSAEFAULT);
2028 return SOCKET_ERROR;
2031 /***********************************************************************
2032 * WSAHtons (WS2_32.47)
2033 * From MSDN decription of error codes, this function should also
2034 * check if WinSock has been initialized and the socket is a valid
2035 * socket. But why? This function only translates a host byte order
2036 * u_short into a network byte order u_short...
2038 int WINAPI WSAHtons(SOCKET s, u_short hostshort, u_short *lpnetshort)
2041 if (lpnetshort)
2043 *lpnetshort = htons(hostshort);
2044 return 0;
2046 WSASetLastError(WSAEFAULT);
2047 return SOCKET_ERROR;
2051 /***********************************************************************
2052 * inet_addr (WINSOCK.10)
2053 * inet_addr (WS2_32.11)
2055 u_long WINAPI WS_inet_addr(const char *cp)
2057 return inet_addr(cp);
2061 /***********************************************************************
2062 * ntohl (WINSOCK.14)
2063 * ntohl (WS2_32.14)
2065 u_long WINAPI WS_ntohl(u_long netlong)
2067 return ntohl(netlong);
2071 /***********************************************************************
2072 * ntohs (WINSOCK.15)
2073 * ntohs (WS2_32.15)
2075 u_short WINAPI WS_ntohs(u_short netshort)
2077 return ntohs(netshort);
2081 /***********************************************************************
2082 * inet_ntoa (WS2_32.12)
2084 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
2086 /* use "buffer for dummies" here because some applications have a
2087 * propensity to decode addresses in ws_hostent structure without
2088 * saving them first...
2090 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
2092 char* s = inet_ntoa(*((struct in_addr*)&in));
2093 if( s )
2095 strcpy(dbuffer, s);
2096 return dbuffer;
2098 SetLastError(wsaErrno());
2099 return NULL;
2102 /**********************************************************************
2103 * WSAIoctl (WS2_32.50)
2106 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
2108 INT WINAPI WSAIoctl(SOCKET s,
2109 DWORD dwIoControlCode,
2110 LPVOID lpvInBuffer,
2111 DWORD cbInBuffer,
2112 LPVOID lpbOutBuffer,
2113 DWORD cbOutBuffer,
2114 LPDWORD lpcbBytesReturned,
2115 LPWSAOVERLAPPED lpOverlapped,
2116 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
2118 int fd = get_sock_fd( s, 0, NULL );
2120 if (fd == -1) return SOCKET_ERROR;
2122 TRACE("%d, 0x%08lx, %p, %ld, %p, %ld, %p, %p, %p\n",
2123 s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpbOutBuffer,
2124 cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
2126 switch( dwIoControlCode )
2128 case SIO_GET_INTERFACE_LIST:
2130 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
2131 DWORD size, numInt, apiReturn;
2133 TRACE("-> SIO_GET_INTERFACE_LIST request\n");
2135 if (!lpbOutBuffer)
2137 release_sock_fd( s, fd );
2138 WSASetLastError(WSAEFAULT);
2139 return SOCKET_ERROR;
2141 if (!lpcbBytesReturned)
2143 release_sock_fd( s, fd );
2144 WSASetLastError(WSAEFAULT);
2145 return SOCKET_ERROR;
2148 apiReturn = GetAdaptersInfo(NULL, &size);
2149 if (apiReturn == ERROR_NO_DATA)
2151 numInt = 0;
2153 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
2155 PIP_ADAPTER_INFO table = HeapAlloc(GetProcessHeap(),0,size);
2157 if (table)
2159 if (GetAdaptersInfo(table, &size) == NO_ERROR)
2161 PIP_ADAPTER_INFO ptr;
2163 if (size*sizeof(INTERFACE_INFO)/sizeof(IP_ADAPTER_INFO) > cbOutBuffer)
2165 WARN("Buffer too small = %lu, cbOutBuffer = %lu\n", size, cbOutBuffer);
2166 HeapFree(GetProcessHeap(),0,table);
2167 release_sock_fd( s, fd );
2168 WSASetLastError(WSAEFAULT);
2169 return SOCKET_ERROR;
2171 for (ptr = table, numInt = 0; ptr;
2172 ptr = ptr->Next, intArray++, numInt++)
2174 unsigned int addr, mask, bcast;
2175 struct ifreq ifInfo;
2177 /* Socket Status Flags */
2178 lstrcpynA(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
2179 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2181 ERR("Error obtaining status flags for socket!\n");
2182 HeapFree(GetProcessHeap(),0,table);
2183 release_sock_fd( s, fd );
2184 WSASetLastError(WSAEINVAL);
2185 return SOCKET_ERROR;
2187 else
2189 /* set flags; the values of IFF_* are not the same
2190 under Linux and Windows, therefore must generate
2191 new flags */
2192 intArray->iiFlags = 0;
2193 if (ifInfo.ifr_flags & IFF_BROADCAST)
2194 intArray->iiFlags |= WS_IFF_BROADCAST;
2195 #ifdef IFF_POINTOPOINT
2196 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
2197 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
2198 #endif
2199 if (ifInfo.ifr_flags & IFF_LOOPBACK)
2200 intArray->iiFlags |= WS_IFF_LOOPBACK;
2201 if (ifInfo.ifr_flags & IFF_UP)
2202 intArray->iiFlags |= WS_IFF_UP;
2203 if (ifInfo.ifr_flags & IFF_MULTICAST)
2204 intArray->iiFlags |= WS_IFF_MULTICAST;
2207 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
2208 mask = inet_addr(ptr->IpAddressList.IpMask.String);
2209 bcast = addr | (addr & !mask);
2210 intArray->iiAddress.AddressIn.sin_family = AF_INET;
2211 intArray->iiAddress.AddressIn.sin_port = 0;
2212 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2213 addr;
2214 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2215 intArray->iiNetmask.AddressIn.sin_port = 0;
2216 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2217 mask;
2218 intArray->iiBroadcastAddress.AddressIn.sin_family =
2219 AF_INET;
2220 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2221 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2222 WS_s_addr = bcast;
2225 else
2227 ERR("Unable to get interface table!\n");
2228 release_sock_fd( s, fd );
2229 HeapFree(GetProcessHeap(),0,table);
2230 WSASetLastError(WSAEINVAL);
2231 return SOCKET_ERROR;
2233 HeapFree(GetProcessHeap(),0,table);
2235 else
2237 release_sock_fd( s, fd );
2238 WSASetLastError(WSAEINVAL);
2239 return SOCKET_ERROR;
2242 else
2244 ERR("Unable to get interface table!\n");
2245 release_sock_fd( s, fd );
2246 WSASetLastError(WSAEINVAL);
2247 return SOCKET_ERROR;
2249 /* Calculate the size of the array being returned */
2250 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2251 break;
2254 case SIO_ADDRESS_LIST_CHANGE:
2255 FIXME("-> SIO_ADDRESS_LIST_CHANGE request: stub\n");
2256 /* FIXME: error and return code depend on whether socket was created
2257 * with WSA_FLAG_OVERLAPPED, but there is no easy way to get this */
2258 break;
2260 default:
2261 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2262 release_sock_fd( s, fd );
2263 WSASetLastError(WSAEOPNOTSUPP);
2264 return SOCKET_ERROR;
2267 /* Function executed with no errors */
2268 release_sock_fd( s, fd );
2269 return 0;
2273 /***********************************************************************
2274 * ioctlsocket (WS2_32.10)
2276 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2278 int fd;
2279 long newcmd = cmd;
2281 TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
2283 switch( cmd )
2285 case WS_FIONREAD:
2286 newcmd=FIONREAD;
2287 break;
2289 case WS_FIONBIO:
2290 if( _get_sock_mask(s) )
2292 /* AsyncSelect()'ed sockets are always nonblocking */
2293 if (*argp) return 0;
2294 SetLastError(WSAEINVAL);
2295 return SOCKET_ERROR;
2297 fd = get_sock_fd( s, 0, NULL );
2298 if (fd != -1)
2300 int ret;
2301 if (*argp)
2303 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2304 ret = fcntl( fd, F_SETFL, O_NONBLOCK );
2306 else
2308 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2309 ret = fcntl( fd, F_SETFL, 0 );
2311 release_sock_fd( s, fd );
2312 if (!ret) return 0;
2313 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2315 return SOCKET_ERROR;
2317 case WS_SIOCATMARK:
2318 newcmd=SIOCATMARK;
2319 break;
2321 case WS__IOW('f',125,u_long):
2322 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2323 SetLastError(WSAEINVAL);
2324 return SOCKET_ERROR;
2326 case SIOCGIFBRDADDR:
2327 case SIOCGIFNETMASK:
2328 case SIOCGIFADDR:
2329 /* These don't need any special handling. They are used by
2330 WsControl, and are here to suppress an unnecessary warning. */
2331 break;
2333 default:
2334 /* Netscape tries hard to use bogus ioctl 0x667e */
2335 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2336 break;
2339 fd = get_sock_fd( s, 0, NULL );
2340 if (fd != -1)
2342 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2344 release_sock_fd( s, fd );
2345 return 0;
2347 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2348 release_sock_fd( s, fd );
2350 return SOCKET_ERROR;
2353 /***********************************************************************
2354 * listen (WS2_32.13)
2356 int WINAPI WS_listen(SOCKET s, int backlog)
2358 int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
2360 TRACE("socket %04x, backlog %d\n", s, backlog);
2361 if (fd != -1)
2363 if (listen(fd, backlog) == 0)
2365 release_sock_fd( s, fd );
2366 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2367 FD_WINE_LISTENING,
2368 FD_CONNECT|FD_WINE_CONNECTED);
2369 return 0;
2371 SetLastError(wsaErrno());
2372 release_sock_fd( s, fd );
2374 return SOCKET_ERROR;
2377 /***********************************************************************
2378 * recv (WS2_32.16)
2380 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2382 DWORD n, dwFlags = flags;
2383 WSABUF wsabuf;
2385 wsabuf.len = len;
2386 wsabuf.buf = buf;
2388 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2389 return SOCKET_ERROR;
2390 else
2391 return n;
2394 /***********************************************************************
2395 * recvfrom (WS2_32.17)
2397 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2398 struct WS_sockaddr *from, int *fromlen)
2400 DWORD n, dwFlags = flags;
2401 WSABUF wsabuf;
2403 wsabuf.len = len;
2404 wsabuf.buf = buf;
2406 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2407 return SOCKET_ERROR;
2408 else
2409 return n;
2412 /***********************************************************************
2413 * select (WS2_32.18)
2415 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2416 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2417 const struct WS_timeval* ws_timeout)
2419 int highfd = 0;
2420 fd_set readfds, writefds, exceptfds;
2421 fd_set *p_read, *p_write, *p_except;
2422 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2423 struct timeval timeout, *timeoutaddr = NULL;
2425 TRACE("read %p, write %p, excp %p timeout %p\n",
2426 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2428 p_read = fd_set_import(&readfds, ws_readfds, FILE_READ_DATA, &highfd, readfd);
2429 p_write = fd_set_import(&writefds, ws_writefds, FILE_WRITE_DATA, &highfd, writefd);
2430 p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
2431 if (ws_timeout)
2433 timeoutaddr = &timeout;
2434 timeout.tv_sec=ws_timeout->tv_sec;
2435 timeout.tv_usec=ws_timeout->tv_usec;
2438 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2440 fd_set_export(&readfds, p_except, ws_readfds, readfd);
2441 fd_set_export(&writefds, p_except, ws_writefds, writefd);
2443 if (p_except && ws_exceptfds)
2445 unsigned int i, j;
2447 for (i = j = 0; i < ws_exceptfds->fd_count; i++)
2449 int fd = exceptfd[i];
2450 SOCKET s = ws_exceptfds->fd_array[i];
2451 if (fd == -1) continue;
2452 if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
2453 release_sock_fd( s, fd );
2455 ws_exceptfds->fd_count = j;
2457 return highfd;
2459 fd_set_unimport(ws_readfds, readfd);
2460 fd_set_unimport(ws_writefds, writefd);
2461 fd_set_unimport(ws_exceptfds, exceptfd);
2463 if( highfd == 0 ) return 0;
2464 SetLastError(wsaErrno());
2465 return SOCKET_ERROR;
2469 /***********************************************************************
2470 * send (WS2_32.19)
2472 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2474 DWORD n;
2475 WSABUF wsabuf;
2477 wsabuf.len = len;
2478 wsabuf.buf = (char*) buf;
2480 if ( WSASendTo( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2481 return SOCKET_ERROR;
2482 else
2483 return n;
2486 /***********************************************************************
2487 * WSASend (WS2_32.72)
2489 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2490 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2491 LPWSAOVERLAPPED lpOverlapped,
2492 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2494 return WSASendTo( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2495 NULL, 0, lpOverlapped, lpCompletionRoutine );
2498 /***********************************************************************
2499 * WSASendDisconnect (WS2_32.73)
2501 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2503 return WS_shutdown( s, SD_SEND );
2507 /***********************************************************************
2508 * WSASendTo (WS2_32.74)
2510 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2511 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2512 const struct WS_sockaddr *to, int tolen,
2513 LPWSAOVERLAPPED lpOverlapped,
2514 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2516 unsigned int i;
2517 int n, fd, err = WSAENOTSOCK, flags, ret;
2518 struct iovec* iovec;
2519 struct ws2_async *wsa;
2520 IO_STATUS_BLOCK* iosb;
2522 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2523 s, lpBuffers, dwBufferCount, dwFlags,
2524 to, tolen, lpOverlapped, lpCompletionRoutine);
2526 fd = get_sock_fd( s, FILE_WRITE_DATA, &flags );
2527 TRACE( "fd=%d, flags=%x\n", fd, flags );
2529 if ( fd == -1 ) return SOCKET_ERROR;
2531 if (flags & FD_FLAG_SEND_SHUTDOWN)
2533 WSASetLastError( WSAESHUTDOWN );
2534 goto err_close;
2537 if ( !lpNumberOfBytesSent )
2539 err = WSAEFAULT;
2540 goto err_close;
2543 iovec = HeapAlloc(GetProcessHeap(), 0, dwBufferCount * sizeof(struct iovec) );
2545 if ( !iovec )
2547 err = WSAEFAULT;
2548 goto err_close;
2551 for ( i = 0; i < dwBufferCount; i++ )
2553 iovec[i].iov_base = lpBuffers[i].buf;
2554 iovec[i].iov_len = lpBuffers[i].len;
2557 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2559 wsa = WS2_make_async( s, fd, ws2m_write, iovec, dwBufferCount,
2560 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2561 lpOverlapped, lpCompletionRoutine, &iosb );
2562 if ( !wsa )
2564 err = WSAEFAULT;
2565 goto err_free;
2568 if ( ( ret = ws2_queue_async( wsa, iosb ) ) )
2570 err = NtStatusToWSAError( ret );
2572 if ( !lpOverlapped )
2573 HeapFree( GetProcessHeap(), 0, iosb );
2574 HeapFree( GetProcessHeap(), 0, wsa );
2575 goto err_free;
2578 /* Try immediate completion */
2579 if ( lpOverlapped )
2581 if ( WSAGetOverlappedResult( s, lpOverlapped,
2582 lpNumberOfBytesSent, FALSE, &dwFlags) )
2583 return 0;
2585 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
2586 goto error;
2589 WSASetLastError( WSA_IO_PENDING );
2590 return SOCKET_ERROR;
2593 if (_is_blocking(s))
2595 /* FIXME: exceptfds? */
2596 int timeout = GET_SNDTIMEO(fd);
2597 if( !do_block(fd, POLLOUT, timeout)) {
2598 err = WSAETIMEDOUT;
2599 goto err_free; /* msdn says a timeout in send is fatal */
2603 n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2604 if ( n == -1 )
2606 err = wsaErrno();
2607 if ( err == WSAEWOULDBLOCK )
2608 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2609 goto err_free;
2612 TRACE(" -> %i bytes\n", n);
2613 *lpNumberOfBytesSent = n;
2615 HeapFree( GetProcessHeap(), 0, iovec );
2616 release_sock_fd( s, fd );
2617 return 0;
2619 err_free:
2620 HeapFree( GetProcessHeap(), 0, iovec );
2622 err_close:
2623 release_sock_fd( s, fd );
2625 error:
2626 WARN(" -> ERROR %d\n", err);
2627 WSASetLastError(err);
2628 return SOCKET_ERROR;
2631 /***********************************************************************
2632 * sendto (WS2_32.20)
2634 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2635 const struct WS_sockaddr *to, int tolen)
2637 DWORD n;
2638 WSABUF wsabuf;
2640 wsabuf.len = len;
2641 wsabuf.buf = (char*) buf;
2643 if ( WSASendTo(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2644 return SOCKET_ERROR;
2645 else
2646 return n;
2649 /***********************************************************************
2650 * setsockopt (WS2_32.21)
2652 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2653 const char *optval, int optlen)
2655 int fd;
2656 int woptval;
2657 struct linger linger;
2658 struct timeval tval;
2660 TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
2661 s, level, optname, optval, optlen);
2663 /* SO_OPENTYPE does not require a valid socket handle. */
2664 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2666 if (optlen < sizeof(int) || !optval)
2668 SetLastError(WSAEFAULT);
2669 return SOCKET_ERROR;
2671 get_per_thread_data()->opentype = *(int *)optval;
2672 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2673 return 0;
2676 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2677 * socket. This will either not happen under windows or it is ignored in
2678 * windows (but it works in linux and therefore prevents the game from
2679 * finding games outside the current network) */
2680 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2682 FIXME("Does windows ignore SO_DONTROUTE?\n");
2683 return 0;
2686 #ifdef HAVE_IPX
2687 if(level == NSPROTO_IPX)
2689 switch(optname)
2691 case IPX_PTYPE:
2692 fd = get_sock_fd( s, 0, NULL );
2693 TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", *(int*)optval, fd);
2695 /* We try to set the ipx type on ipx socket level. */
2696 #ifdef SOL_IPX
2697 if(setsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
2699 ERR("IPX: could not set ipx option type; expect weird behaviour\n");
2700 return SOCKET_ERROR;
2702 #else
2704 struct ipx val;
2705 /* Should we retrieve val using a getsockopt call and then
2706 * set the modified one? */
2707 val.ipx_pt = *optval;
2708 setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
2710 #endif
2711 release_sock_fd( s, fd );
2712 return 0;
2713 case IPX_FILTERPTYPE:
2714 /* Sets the receive filter packet type, at the moment we don't support it */
2715 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
2717 /* Returning 0 is better for now than returning a SOCKET_ERROR */
2718 return 0;
2719 default:
2720 FIXME("opt_name:%x\n", optname);
2721 return SOCKET_ERROR;
2723 return 0;
2725 #endif
2727 /* Is a privileged and useless operation, so we don't. */
2728 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
2730 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2731 return 0;
2734 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2735 /* This is unique to WinSock and takes special conversion */
2736 linger.l_onoff = *((int*)optval) ? 0: 1;
2737 linger.l_linger = 0;
2738 optname=SO_LINGER;
2739 optval = (char*)&linger;
2740 optlen = sizeof(struct linger);
2741 level = SOL_SOCKET;
2743 else
2745 if (!convert_sockopt(&level, &optname)) {
2746 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2747 SetLastError(WSAENOPROTOOPT);
2748 return SOCKET_ERROR;
2750 if (optname == SO_LINGER && optval) {
2751 linger.l_onoff = ((LINGER*)optval)->l_onoff;
2752 linger.l_linger = ((LINGER*)optval)->l_linger;
2753 /* FIXME: what is documented behavior if SO_LINGER optval
2754 is null?? */
2755 optval = (char*)&linger;
2756 optlen = sizeof(struct linger);
2758 else if (optval && optlen < sizeof(int))
2760 woptval= *((INT16 *) optval);
2761 optval= (char*) &woptval;
2762 optlen=sizeof(int);
2764 if (level == SOL_SOCKET && is_timeout_option(optname))
2766 if (optlen == sizeof(UINT32)) {
2767 /* WinSock passes miliseconds instead of struct timeval */
2768 tval.tv_usec = (*(PUINT32)optval % 1000) * 1000;
2769 tval.tv_sec = *(PUINT32)optval / 1000;
2770 /* min of 500 milisec */
2771 if (tval.tv_sec == 0 && tval.tv_usec < 500000)
2772 tval.tv_usec = 500000;
2773 optlen = sizeof(struct timeval);
2774 optval = (char*)&tval;
2775 } else if (optlen == sizeof(struct timeval)) {
2776 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2777 } else {
2778 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2779 return 0;
2782 if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
2784 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2785 return 0;
2790 fd = get_sock_fd( s, 0, NULL );
2791 if (fd == -1) return SOCKET_ERROR;
2793 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2795 release_sock_fd( s, fd );
2796 return 0;
2798 TRACE("Setting socket error, %d\n", wsaErrno());
2799 SetLastError(wsaErrno());
2800 release_sock_fd( s, fd );
2801 return SOCKET_ERROR;
2804 /***********************************************************************
2805 * shutdown (WS2_32.22)
2807 int WINAPI WS_shutdown(SOCKET s, int how)
2809 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2810 unsigned int clear_flags = 0;
2812 fd = get_sock_fd( s, 0, &flags );
2813 TRACE("socket %04x, how %i %x\n", s, how, flags );
2815 if (fd == -1)
2816 return SOCKET_ERROR;
2818 switch( how )
2820 case 0: /* drop receives */
2821 clear_flags |= FD_READ;
2822 break;
2823 case 1: /* drop sends */
2824 clear_flags |= FD_WRITE;
2825 break;
2826 case 2: /* drop all */
2827 clear_flags |= FD_READ|FD_WRITE;
2828 default:
2829 clear_flags |= FD_WINE_LISTENING;
2832 if ( flags & FD_FLAG_OVERLAPPED ) {
2834 switch ( how )
2836 case SD_RECEIVE:
2837 fd0 = fd;
2838 break;
2839 case SD_SEND:
2840 fd1 = fd;
2841 break;
2842 case SD_BOTH:
2843 default:
2844 fd0 = fd;
2845 fd1 = get_sock_fd( s, 0, NULL );
2846 break;
2849 if ( fd0 != -1 )
2851 err = WS2_register_async_shutdown( s, fd0, ws2m_sd_read );
2852 if ( err )
2854 release_sock_fd( s, fd0 );
2855 goto error;
2858 if ( fd1 != -1 )
2860 err = WS2_register_async_shutdown( s, fd1, ws2m_sd_write );
2861 if ( err )
2863 release_sock_fd( s, fd1 );
2864 goto error;
2868 else /* non-overlapped mode */
2870 if ( shutdown( fd, how ) )
2872 err = wsaErrno();
2873 release_sock_fd( s, fd );
2874 goto error;
2876 release_sock_fd( s, fd );
2879 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2880 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2881 return 0;
2883 error:
2884 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2885 WSASetLastError( err );
2886 return SOCKET_ERROR;
2889 /***********************************************************************
2890 * socket (WS2_32.23)
2892 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2894 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2896 return WSASocketA( af, type, protocol, NULL, 0,
2897 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
2901 /***********************************************************************
2902 * gethostbyaddr (WS2_32.51)
2904 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
2906 struct WS_hostent *retval = NULL;
2907 struct hostent* host;
2909 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2910 char *extrabuf;
2911 int ebufsize=1024;
2912 struct hostent hostentry;
2913 int locerr=ENOBUFS;
2914 host = NULL;
2915 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2916 while(extrabuf) {
2917 int res = gethostbyaddr_r(addr, len, type,
2918 &hostentry, extrabuf, ebufsize, &host, &locerr);
2919 if( res != ERANGE) break;
2920 ebufsize *=2;
2921 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2923 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2924 #else
2925 EnterCriticalSection( &csWSgetXXXbyYYY );
2926 host = gethostbyaddr(addr, len, type);
2927 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2928 #endif
2929 if( host != NULL ) retval = WS_dup_he(host);
2930 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2931 HeapFree(GetProcessHeap(),0,extrabuf);
2932 #else
2933 LeaveCriticalSection( &csWSgetXXXbyYYY );
2934 #endif
2935 TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
2936 return retval;
2939 /***********************************************************************
2940 * gethostbyname (WS2_32.52)
2942 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2944 struct WS_hostent *retval = NULL;
2945 struct hostent* host;
2946 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2947 char *extrabuf;
2948 int ebufsize=1024;
2949 struct hostent hostentry;
2950 int locerr = ENOBUFS;
2951 #endif
2952 char buf[100];
2953 if( !name) {
2954 name = buf;
2955 if( gethostname( buf, 100) == -1) {
2956 SetLastError( WSAENOBUFS); /* appropriate ? */
2957 return retval;
2960 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2961 host = NULL;
2962 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2963 while(extrabuf) {
2964 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2965 if( res != ERANGE) break;
2966 ebufsize *=2;
2967 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2969 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2970 #else
2971 EnterCriticalSection( &csWSgetXXXbyYYY );
2972 host = gethostbyname(name);
2973 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2974 #endif
2975 if (host) retval = WS_dup_he(host);
2976 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2977 HeapFree(GetProcessHeap(),0,extrabuf);
2978 #else
2979 LeaveCriticalSection( &csWSgetXXXbyYYY );
2980 #endif
2981 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2982 return retval;
2986 /***********************************************************************
2987 * getprotobyname (WS2_32.53)
2989 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2991 struct WS_protoent* retval = NULL;
2992 #ifdef HAVE_GETPROTOBYNAME
2993 struct protoent* proto;
2994 EnterCriticalSection( &csWSgetXXXbyYYY );
2995 if( (proto = getprotobyname(name)) != NULL )
2997 retval = WS_dup_pe(proto);
2999 else {
3000 MESSAGE("protocol %s not found; You might want to add "
3001 "this to /etc/protocols\n", debugstr_a(name) );
3002 SetLastError(WSANO_DATA);
3004 LeaveCriticalSection( &csWSgetXXXbyYYY );
3005 #endif
3006 TRACE( "%s ret %p\n", debugstr_a(name), retval );
3007 return retval;
3011 /***********************************************************************
3012 * getprotobynumber (WS2_32.54)
3014 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
3016 struct WS_protoent* retval = NULL;
3017 #ifdef HAVE_GETPROTOBYNUMBER
3018 struct protoent* proto;
3019 EnterCriticalSection( &csWSgetXXXbyYYY );
3020 if( (proto = getprotobynumber(number)) != NULL )
3022 retval = WS_dup_pe(proto);
3024 else {
3025 MESSAGE("protocol number %d not found; You might want to add "
3026 "this to /etc/protocols\n", number );
3027 SetLastError(WSANO_DATA);
3029 LeaveCriticalSection( &csWSgetXXXbyYYY );
3030 #endif
3031 TRACE("%i ret %p\n", number, retval);
3032 return retval;
3036 /***********************************************************************
3037 * getservbyname (WS2_32.55)
3039 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
3041 struct WS_servent* retval = NULL;
3042 struct servent* serv;
3043 char *name_str;
3044 char *proto_str = NULL;
3046 if (!(name_str = strdup_lower(name))) return NULL;
3048 if (proto && *proto)
3050 if (!(proto_str = strdup_lower(proto)))
3052 HeapFree( GetProcessHeap(), 0, name_str );
3053 return NULL;
3057 EnterCriticalSection( &csWSgetXXXbyYYY );
3058 serv = getservbyname(name_str, proto_str);
3059 if( serv != NULL )
3061 retval = WS_dup_se(serv);
3063 else SetLastError(WSANO_DATA);
3064 LeaveCriticalSection( &csWSgetXXXbyYYY );
3065 HeapFree( GetProcessHeap(), 0, proto_str );
3066 HeapFree( GetProcessHeap(), 0, name_str );
3067 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
3068 return retval;
3071 /***********************************************************************
3072 * freeaddrinfo (WS2_32.@)
3074 void WINAPI WS_freeaddrinfo(struct WS_addrinfo *res)
3076 while (res) {
3077 struct WS_addrinfo *next;
3079 HeapFree(GetProcessHeap(),0,res->ai_canonname);
3080 HeapFree(GetProcessHeap(),0,res->ai_addr);
3081 next = res->ai_next;
3082 HeapFree(GetProcessHeap(),0,res);
3083 res = next;
3087 /* helper functions for getaddrinfo() */
3088 static int convert_aiflag_w2u(int winflags) {
3089 int i, unixflags = 0;
3091 for (i=0;i<sizeof(ws_aiflag_map)/sizeof(ws_aiflag_map[0]);i++)
3092 if (ws_aiflag_map[i][0] & winflags) {
3093 unixflags |= ws_aiflag_map[i][1];
3094 winflags &= ~ws_aiflag_map[i][0];
3096 if (winflags)
3097 FIXME("Unhandled windows AI_xxx flags %x\n", winflags);
3098 return unixflags;
3101 static int convert_aiflag_u2w(int unixflags) {
3102 int i, winflags = 0;
3104 for (i=0;i<sizeof(ws_aiflag_map)/sizeof(ws_aiflag_map[0]);i++)
3105 if (ws_aiflag_map[i][1] & unixflags) {
3106 winflags |= ws_aiflag_map[i][0];
3107 unixflags &= ~ws_aiflag_map[i][1];
3109 if (unixflags) /* will warn usually */
3110 WARN("Unhandled UNIX AI_xxx flags %x\n", unixflags);
3111 return winflags;
3114 static int convert_eai_u2w(int unixret) {
3115 int i;
3117 for (i=0;ws_eai_map[i][0];i++)
3118 if (ws_eai_map[i][1] == unixret)
3119 return ws_eai_map[i][0];
3120 return unixret;
3123 /***********************************************************************
3124 * getaddrinfo (WS2_32.@)
3126 int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addrinfo *hints, struct WS_addrinfo **res)
3128 #if HAVE_GETADDRINFO
3129 struct addrinfo *unixaires = NULL;
3130 int result;
3131 struct addrinfo unixhints, *punixhints = NULL;
3132 CHAR *node = NULL, *serv = NULL;
3134 if (nodename)
3135 if (!(node = strdup_lower(nodename))) return WSA_NOT_ENOUGH_MEMORY;
3137 if (servname) {
3138 if (!(serv = strdup_lower(servname))) {
3139 HeapFree(GetProcessHeap(), 0, node);
3140 return WSA_NOT_ENOUGH_MEMORY;
3144 if (hints) {
3145 punixhints = &unixhints;
3147 memset(&unixhints, 0, sizeof(unixhints));
3148 punixhints->ai_flags = convert_aiflag_w2u(hints->ai_flags);
3149 if (hints->ai_family == 0) /* wildcard, specific to getaddrinfo() */
3150 punixhints->ai_family = 0;
3151 else
3152 punixhints->ai_family = convert_af_w2u(hints->ai_family);
3153 if (hints->ai_socktype == 0) /* wildcard, specific to getaddrinfo() */
3154 punixhints->ai_socktype = 0;
3155 else
3156 punixhints->ai_socktype = convert_socktype_w2u(hints->ai_socktype);
3157 if (hints->ai_protocol == 0) /* wildcard, specific to getaddrinfo() */
3158 punixhints->ai_protocol = 0;
3159 else
3160 punixhints->ai_protocol = convert_proto_w2u(hints->ai_protocol);
3163 /* getaddrinfo(3) is thread safe, no need to wrap in CS */
3164 result = getaddrinfo(nodename, servname, punixhints, &unixaires);
3166 TRACE("%s, %s %p -> %p %d\n", nodename, servname, hints, res, result);
3168 HeapFree(GetProcessHeap(), 0, node);
3169 HeapFree(GetProcessHeap(), 0, serv);
3171 if (!result) {
3172 struct addrinfo *xuai = unixaires;
3173 struct WS_addrinfo **xai = res;
3175 *xai = NULL;
3176 while (xuai) {
3177 struct WS_addrinfo *ai = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo));
3178 int len;
3180 if (!ai)
3181 goto outofmem;
3183 *xai = ai;xai = &ai->ai_next;
3184 ai->ai_flags = convert_aiflag_u2w(xuai->ai_flags);
3185 ai->ai_family = convert_af_u2w(xuai->ai_family);
3186 ai->ai_socktype = convert_socktype_u2w(xuai->ai_socktype);
3187 ai->ai_protocol = convert_proto_u2w(xuai->ai_protocol);
3188 if (xuai->ai_canonname) {
3189 TRACE("canon name - %s\n",debugstr_a(xuai->ai_canonname));
3190 ai->ai_canonname = HeapAlloc(GetProcessHeap(),0,strlen(xuai->ai_canonname)+1);
3191 if (!ai->ai_canonname)
3192 goto outofmem;
3193 strcpy(ai->ai_canonname,xuai->ai_canonname);
3195 len = xuai->ai_addrlen;
3196 ai->ai_addr = HeapAlloc(GetProcessHeap(),0,len);
3197 if (!ai->ai_addr)
3198 goto outofmem;
3199 ai->ai_addrlen = len;
3200 do {
3201 int winlen = ai->ai_addrlen;
3203 if (!ws_sockaddr_u2ws(xuai->ai_addr, xuai->ai_addrlen, ai->ai_addr, &winlen)) {
3204 ai->ai_addrlen = winlen;
3205 break;
3207 len = 2*len;
3208 ai->ai_addr = HeapReAlloc(GetProcessHeap(),0,ai->ai_addr,len);
3209 if (!ai->ai_addr)
3210 goto outofmem;
3211 ai->ai_addrlen = len;
3212 } while (1);
3213 xuai = xuai->ai_next;
3215 freeaddrinfo(unixaires);
3216 } else {
3217 result = convert_eai_u2w(result);
3219 return result;
3221 outofmem:
3222 if (*res) WS_freeaddrinfo(*res);
3223 if (unixaires) freeaddrinfo(unixaires);
3224 *res = NULL;
3225 return WSA_NOT_ENOUGH_MEMORY;
3226 #else
3227 FIXME("getaddrinfo() failed, not found during buildtime.\n");
3228 return EAI_FAIL;
3229 #endif
3232 /***********************************************************************
3233 * GetAddrInfoW (WS2_32.@)
3235 int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hints, PADDRINFOW *res)
3237 FIXME("empty stub!\n");
3238 return EAI_FAIL;
3241 int WINAPI WS_getnameinfo(const SOCKADDR *sa, socklen_t salen, PCHAR host,
3242 DWORD hostlen, PCHAR serv, DWORD servlen, INT flags)
3244 #if HAVE_GETNAMEINFO
3245 int ret;
3246 const struct sockaddr* sa_u;
3247 unsigned int size;
3249 TRACE("%s %d %p %ld %p %ld %d\n", debugstr_sockaddr(sa), salen, host, hostlen,
3250 serv, servlen, flags);
3252 sa_u = ws_sockaddr_ws2u(sa, salen, &size);
3253 if (!sa_u)
3255 WSASetLastError(WSAEFAULT);
3256 return WSA_NOT_ENOUGH_MEMORY;
3258 ret = getnameinfo(sa_u, size, host, hostlen, serv, servlen, convert_aiflag_w2u(flags));
3260 ws_sockaddr_free(sa_u, sa);
3261 return convert_eai_u2w(ret);
3262 #else
3263 FIXME("getnameinfo() failed, not found during buildtime.\n");
3264 return EAI_FAIL;
3265 #endif
3268 /***********************************************************************
3269 * getservbyport (WS2_32.56)
3271 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
3273 struct WS_servent* retval = NULL;
3274 #ifdef HAVE_GETSERVBYPORT
3275 struct servent* serv;
3276 char *proto_str = NULL;
3278 if (proto && *proto)
3280 if (!(proto_str = strdup_lower(proto))) return NULL;
3282 EnterCriticalSection( &csWSgetXXXbyYYY );
3283 if( (serv = getservbyport(port, proto_str)) != NULL ) {
3284 retval = WS_dup_se(serv);
3286 else SetLastError(WSANO_DATA);
3287 LeaveCriticalSection( &csWSgetXXXbyYYY );
3288 HeapFree( GetProcessHeap(), 0, proto_str );
3289 #endif
3290 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
3291 return retval;
3295 /***********************************************************************
3296 * gethostname (WS2_32.57)
3298 int WINAPI WS_gethostname(char *name, int namelen)
3300 TRACE("name %p, len %d\n", name, namelen);
3302 if (gethostname(name, namelen) == 0)
3304 TRACE("<- '%s'\n", name);
3305 return 0;
3307 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
3308 TRACE("<- ERROR !\n");
3309 return SOCKET_ERROR;
3313 /* ------------------------------------- Windows sockets extensions -- *
3315 * ------------------------------------------------------------------- */
3317 /***********************************************************************
3318 * WSAEnumNetworkEvents (WS2_32.36)
3320 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
3322 int ret;
3324 TRACE("%08x, hEvent %p, lpEvent %p\n", s, hEvent, lpEvent );
3326 SERVER_START_REQ( get_socket_event )
3328 req->handle = SOCKET2HANDLE(s);
3329 req->service = TRUE;
3330 req->c_event = hEvent;
3331 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
3332 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
3334 SERVER_END_REQ;
3335 if (!ret) return 0;
3336 SetLastError(WSAEINVAL);
3337 return SOCKET_ERROR;
3340 /***********************************************************************
3341 * WSAEventSelect (WS2_32.39)
3343 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, long lEvent)
3345 int ret;
3347 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
3349 SERVER_START_REQ( set_socket_event )
3351 req->handle = SOCKET2HANDLE(s);
3352 req->mask = lEvent;
3353 req->event = hEvent;
3354 req->window = 0;
3355 req->msg = 0;
3356 ret = wine_server_call( req );
3358 SERVER_END_REQ;
3359 if (!ret) return 0;
3360 SetLastError(WSAEINVAL);
3361 return SOCKET_ERROR;
3364 /**********************************************************************
3365 * WSAGetOverlappedResult (WS2_32.40)
3367 BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
3368 LPDWORD lpcbTransfer, BOOL fWait,
3369 LPDWORD lpdwFlags )
3371 DWORD r;
3373 TRACE( "socket %04x ovl %p trans %p, wait %d flags %p\n",
3374 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
3376 if ( lpOverlapped == NULL )
3378 ERR( "Invalid pointer\n" );
3379 WSASetLastError(WSA_INVALID_PARAMETER);
3380 return FALSE;
3383 if ( fWait )
3385 if (lpOverlapped->hEvent)
3386 while ( WaitForSingleObjectEx(lpOverlapped->hEvent,
3387 INFINITE, TRUE) == STATUS_USER_APC );
3388 else /* busy loop */
3389 while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
3390 Sleep( 10 );
3393 else if ( lpOverlapped->Internal == STATUS_PENDING )
3395 /* Wait in order to give APCs a chance to run. */
3396 /* This is cheating, so we must set the event again in case of success -
3397 it may be a non-manual reset event. */
3398 while ( (r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
3399 if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent )
3400 NtSetEvent( lpOverlapped->hEvent, NULL );
3403 if ( lpcbTransfer )
3404 *lpcbTransfer = lpOverlapped->InternalHigh;
3406 if ( lpdwFlags )
3407 *lpdwFlags = lpOverlapped->u.s.Offset;
3409 switch ( lpOverlapped->Internal )
3411 case STATUS_SUCCESS:
3412 return TRUE;
3413 case STATUS_PENDING:
3414 WSASetLastError( WSA_IO_INCOMPLETE );
3415 if (fWait) ERR("PENDING status after waiting!\n");
3416 return FALSE;
3417 default:
3418 WSASetLastError( NtStatusToWSAError( lpOverlapped->Internal ));
3419 return FALSE;
3424 /***********************************************************************
3425 * WSAAsyncSelect (WS2_32.101)
3427 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, long lEvent)
3429 int ret;
3431 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3433 SERVER_START_REQ( set_socket_event )
3435 req->handle = SOCKET2HANDLE(s);
3436 req->mask = lEvent;
3437 req->event = 0;
3438 req->window = hWnd;
3439 req->msg = uMsg;
3440 ret = wine_server_call( req );
3442 SERVER_END_REQ;
3443 if (!ret) return 0;
3444 SetLastError(WSAEINVAL);
3445 return SOCKET_ERROR;
3448 /***********************************************************************
3449 * WSACreateEvent (WS2_32.31)
3452 WSAEVENT WINAPI WSACreateEvent(void)
3454 /* Create a manual-reset event, with initial state: unsignaled */
3455 TRACE("\n");
3457 return CreateEventW(NULL, TRUE, FALSE, NULL);
3460 /***********************************************************************
3461 * WSACloseEvent (WS2_32.29)
3464 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3466 TRACE ("event=%p\n", event);
3468 return CloseHandle(event);
3471 /***********************************************************************
3472 * WSASocketA (WS2_32.78)
3475 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3476 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3477 GROUP g, DWORD dwFlags)
3479 INT len;
3480 WSAPROTOCOL_INFOW info;
3482 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3483 af, type, protocol, lpProtocolInfo, g, dwFlags);
3485 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
3487 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
3488 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3489 info.szProtocol, WSAPROTOCOL_LEN + 1);
3491 if (!len)
3493 WSASetLastError( WSAEINVAL);
3494 return SOCKET_ERROR;
3497 return WSASocketW(af, type, protocol, &info, g, dwFlags);
3500 /***********************************************************************
3501 * WSASocketW (WS2_32.79)
3504 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
3505 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3506 GROUP g, DWORD dwFlags)
3508 SOCKET ret;
3511 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
3512 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3515 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3516 af, type, protocol, lpProtocolInfo, g, dwFlags );
3518 /* hack for WSADuplicateSocket */
3519 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3520 ret = lpProtocolInfo->dwCatalogEntryId;
3521 TRACE("\tgot duplicate %04x\n", ret);
3522 return ret;
3525 /* check and convert the socket family */
3526 af = convert_af_w2u(af);
3527 if (af == -1)
3529 FIXME("Unsupported socket family %d!\n", af);
3530 SetLastError(WSAEAFNOSUPPORT);
3531 return INVALID_SOCKET;
3534 /* check the socket type */
3535 type = convert_socktype_w2u(type);
3536 if (type == -1)
3538 SetLastError(WSAESOCKTNOSUPPORT);
3539 return INVALID_SOCKET;
3542 /* check the protocol type */
3543 if ( protocol < 0 ) /* don't support negative values */
3545 SetLastError(WSAEPROTONOSUPPORT);
3546 return INVALID_SOCKET;
3549 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3550 switch(protocol)
3552 case IPPROTO_TCP:
3553 if (type == SOCK_STREAM) { af = AF_INET; break; }
3554 case IPPROTO_UDP:
3555 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3556 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3559 SERVER_START_REQ( create_socket )
3561 req->family = af;
3562 req->type = type;
3563 req->protocol = protocol;
3564 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3565 req->attributes = OBJ_INHERIT;
3566 req->flags = dwFlags;
3567 set_error( wine_server_call( req ) );
3568 ret = HANDLE2SOCKET( reply->handle );
3570 SERVER_END_REQ;
3571 if (ret)
3573 TRACE("\tcreated %04x\n", ret );
3574 return ret;
3577 if (GetLastError() == WSAEACCES) /* raw socket denied */
3579 if (type == SOCK_RAW)
3580 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3581 else
3582 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3583 SetLastError(WSAESOCKTNOSUPPORT);
3586 WARN("\t\tfailed!\n");
3587 return INVALID_SOCKET;
3590 /***********************************************************************
3591 * WSAJoinLeaf (WS2_32.58)
3594 SOCKET WINAPI WSAJoinLeaf(
3595 SOCKET s,
3596 const struct WS_sockaddr *addr,
3597 int addrlen,
3598 LPWSABUF lpCallerData,
3599 LPWSABUF lpCalleeData,
3600 LPQOS lpSQOS,
3601 LPQOS lpGQOS,
3602 DWORD dwFlags)
3604 FIXME("stub.\n");
3605 return INVALID_SOCKET;
3608 /***********************************************************************
3609 * __WSAFDIsSet (WS2_32.151)
3611 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3613 int i = set->fd_count;
3615 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3617 while (i--)
3618 if (set->fd_array[i] == s) return 1;
3619 return 0;
3622 /***********************************************************************
3623 * WSAIsBlocking (WINSOCK.114)
3624 * WSAIsBlocking (WS2_32.114)
3626 BOOL WINAPI WSAIsBlocking(void)
3628 /* By default WinSock should set all its sockets to non-blocking mode
3629 * and poll in PeekMessage loop when processing "blocking" ones. This
3630 * function is supposed to tell if the program is in this loop. Our
3631 * blocking calls are truly blocking so we always return FALSE.
3633 * Note: It is allowed to call this function without prior WSAStartup().
3636 TRACE("\n");
3637 return FALSE;
3640 /***********************************************************************
3641 * WSACancelBlockingCall (WINSOCK.113)
3642 * WSACancelBlockingCall (WS2_32.113)
3644 INT WINAPI WSACancelBlockingCall(void)
3646 TRACE("\n");
3647 return 0;
3650 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
3652 FIXME("How was this called?\n");
3653 return x();
3657 /***********************************************************************
3658 * WSASetBlockingHook (WS2_32.109)
3660 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3662 FARPROC prev = blocking_hook;
3663 blocking_hook = lpBlockFunc;
3664 TRACE("hook %p\n", lpBlockFunc);
3665 return prev;
3669 /***********************************************************************
3670 * WSAUnhookBlockingHook (WS2_32.110)
3672 INT WINAPI WSAUnhookBlockingHook(void)
3674 blocking_hook = WSA_DefaultBlockingHook;
3675 return 0;
3679 /* ----------------------------------- end of API stuff */
3681 /* ----------------------------------- helper functions -
3683 * TODO: Merge WS_dup_..() stuff into one function that
3684 * would operate with a generic structure containing internal
3685 * pointers (via a template of some kind).
3688 static int list_size(char** l, int item_size)
3690 int i,j = 0;
3691 if(l)
3692 { for(i=0;l[i];i++)
3693 j += (item_size) ? item_size : strlen(l[i]) + 1;
3694 j += (i + 1) * sizeof(char*); }
3695 return j;
3698 static int list_dup(char** l_src, char** l_to, int item_size)
3700 char *p;
3701 int i;
3703 for (i = 0; l_src[i]; i++) ;
3704 p = (char *)(l_to + i + 1);
3705 for (i = 0; l_src[i]; i++)
3707 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3708 memcpy(p, l_src[i], count);
3709 l_to[i] = p;
3710 p += count;
3712 l_to[i] = NULL;
3713 return p - (char *)l_to;
3716 /* ----- hostent */
3718 /* duplicate hostent entry
3719 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3720 * Dito for protoent and servent.
3722 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
3724 char *p;
3725 struct WS_hostent *p_to;
3727 int size = (sizeof(*p_he) +
3728 strlen(p_he->h_name) + 1 +
3729 list_size(p_he->h_aliases, 0) +
3730 list_size(p_he->h_addr_list, p_he->h_length));
3732 if (!(p_to = check_buffer_he(size))) return NULL;
3733 p_to->h_addrtype = p_he->h_addrtype;
3734 p_to->h_length = p_he->h_length;
3736 p = (char *)(p_to + 1);
3737 p_to->h_name = p;
3738 strcpy(p, p_he->h_name);
3739 p += strlen(p) + 1;
3741 p_to->h_aliases = (char **)p;
3742 p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
3744 p_to->h_addr_list = (char **)p;
3745 list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
3746 return p_to;
3749 /* ----- protoent */
3751 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
3753 char *p;
3754 struct WS_protoent *p_to;
3756 int size = (sizeof(*p_pe) +
3757 strlen(p_pe->p_name) + 1 +
3758 list_size(p_pe->p_aliases, 0));
3760 if (!(p_to = check_buffer_pe(size))) return NULL;
3761 p_to->p_proto = p_pe->p_proto;
3763 p = (char *)(p_to + 1);
3764 p_to->p_name = p;
3765 strcpy(p, p_pe->p_name);
3766 p += strlen(p) + 1;
3768 p_to->p_aliases = (char **)p;
3769 list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
3770 return p_to;
3773 /* ----- servent */
3775 static struct WS_servent *WS_dup_se(const struct servent* p_se)
3777 char *p;
3778 struct WS_servent *p_to;
3780 int size = (sizeof(*p_se) +
3781 strlen(p_se->s_proto) + 1 +
3782 strlen(p_se->s_name) + 1 +
3783 list_size(p_se->s_aliases, 0));
3785 if (!(p_to = check_buffer_se(size))) return NULL;
3786 p_to->s_port = p_se->s_port;
3788 p = (char *)(p_to + 1);
3789 p_to->s_name = p;
3790 strcpy(p, p_se->s_name);
3791 p += strlen(p) + 1;
3793 p_to->s_proto = p;
3794 strcpy(p, p_se->s_proto);
3795 p += strlen(p) + 1;
3797 p_to->s_aliases = (char **)p;
3798 list_dup(p_se->s_aliases, p_to->s_aliases, 0);
3799 return p_to;
3802 /* ----------------------------------- error handling */
3804 UINT wsaErrno(void)
3806 int loc_errno = errno;
3807 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3809 switch(loc_errno)
3811 case EINTR: return WSAEINTR;
3812 case EBADF: return WSAEBADF;
3813 case EPERM:
3814 case EACCES: return WSAEACCES;
3815 case EFAULT: return WSAEFAULT;
3816 case EINVAL: return WSAEINVAL;
3817 case EMFILE: return WSAEMFILE;
3818 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3819 case EINPROGRESS: return WSAEINPROGRESS;
3820 case EALREADY: return WSAEALREADY;
3821 case ENOTSOCK: return WSAENOTSOCK;
3822 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3823 case EMSGSIZE: return WSAEMSGSIZE;
3824 case EPROTOTYPE: return WSAEPROTOTYPE;
3825 case ENOPROTOOPT: return WSAENOPROTOOPT;
3826 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3827 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3828 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3829 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3830 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3831 case EADDRINUSE: return WSAEADDRINUSE;
3832 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3833 case ENETDOWN: return WSAENETDOWN;
3834 case ENETUNREACH: return WSAENETUNREACH;
3835 case ENETRESET: return WSAENETRESET;
3836 case ECONNABORTED: return WSAECONNABORTED;
3837 case EPIPE:
3838 case ECONNRESET: return WSAECONNRESET;
3839 case ENOBUFS: return WSAENOBUFS;
3840 case EISCONN: return WSAEISCONN;
3841 case ENOTCONN: return WSAENOTCONN;
3842 case ESHUTDOWN: return WSAESHUTDOWN;
3843 case ETOOMANYREFS: return WSAETOOMANYREFS;
3844 case ETIMEDOUT: return WSAETIMEDOUT;
3845 case ECONNREFUSED: return WSAECONNREFUSED;
3846 case ELOOP: return WSAELOOP;
3847 case ENAMETOOLONG: return WSAENAMETOOLONG;
3848 case EHOSTDOWN: return WSAEHOSTDOWN;
3849 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3850 case ENOTEMPTY: return WSAENOTEMPTY;
3851 #ifdef EPROCLIM
3852 case EPROCLIM: return WSAEPROCLIM;
3853 #endif
3854 #ifdef EUSERS
3855 case EUSERS: return WSAEUSERS;
3856 #endif
3857 #ifdef EDQUOT
3858 case EDQUOT: return WSAEDQUOT;
3859 #endif
3860 #ifdef ESTALE
3861 case ESTALE: return WSAESTALE;
3862 #endif
3863 #ifdef EREMOTE
3864 case EREMOTE: return WSAEREMOTE;
3865 #endif
3867 /* just in case we ever get here and there are no problems */
3868 case 0: return 0;
3869 default:
3870 WARN("Unknown errno %d!\n", loc_errno);
3871 return WSAEOPNOTSUPP;
3875 UINT wsaHerrno(int loc_errno)
3878 WARN("h_errno %d.\n", loc_errno);
3880 switch(loc_errno)
3882 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3883 case TRY_AGAIN: return WSATRY_AGAIN;
3884 case NO_RECOVERY: return WSANO_RECOVERY;
3885 case NO_DATA: return WSANO_DATA;
3886 case ENOBUFS: return WSAENOBUFS;
3888 case 0: return 0;
3889 default:
3890 WARN("Unknown h_errno %d!\n", loc_errno);
3891 return WSAEOPNOTSUPP;
3896 /***********************************************************************
3897 * WSARecv (WS2_32.67)
3899 int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3900 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3901 LPWSAOVERLAPPED lpOverlapped,
3902 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3904 return WSARecvFrom(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3905 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3908 /***********************************************************************
3909 * WSARecvFrom (WS2_32.69)
3911 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3912 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3913 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3914 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3917 unsigned int i;
3918 int n, fd, err = WSAENOTSOCK, flags, ret;
3919 struct iovec* iovec;
3920 struct ws2_async *wsa;
3921 IO_STATUS_BLOCK* iosb;
3923 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3924 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3925 (lpFromlen ? *lpFromlen : -1L),
3926 lpOverlapped, lpCompletionRoutine);
3928 fd = get_sock_fd( s, FILE_READ_DATA, &flags );
3929 TRACE( "fd=%d, flags=%x\n", fd, flags );
3931 if (fd == -1) return SOCKET_ERROR;
3933 if (flags & FD_FLAG_RECV_SHUTDOWN)
3935 WSASetLastError( WSAESHUTDOWN );
3936 goto err_close;
3939 iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3940 if ( !iovec )
3942 err = WSAEFAULT;
3943 goto err_close;
3946 for (i = 0; i < dwBufferCount; i++)
3948 iovec[i].iov_base = lpBuffers[i].buf;
3949 iovec[i].iov_len = lpBuffers[i].len;
3952 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3954 wsa = WS2_make_async( s, fd, ws2m_read, iovec, dwBufferCount,
3955 lpFlags, lpFrom, lpFromlen,
3956 lpOverlapped, lpCompletionRoutine, &iosb );
3958 if ( !wsa )
3960 err = WSAEFAULT;
3961 goto err_free;
3964 if ( ( ret = ws2_queue_async( wsa, iosb )) )
3966 err = NtStatusToWSAError( ret );
3968 if ( !lpOverlapped )
3969 HeapFree( GetProcessHeap(), 0, iosb );
3970 HeapFree( GetProcessHeap(), 0, wsa );
3971 goto err_free;
3974 /* Try immediate completion */
3975 if ( lpOverlapped )
3977 if ( WSAGetOverlappedResult( s, lpOverlapped,
3978 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3979 return 0;
3981 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
3982 goto error;
3985 WSASetLastError( WSA_IO_PENDING );
3986 return SOCKET_ERROR;
3989 if ( _is_blocking(s) )
3991 /* block here */
3992 /* FIXME: OOB and exceptfds? */
3993 int timeout = GET_RCVTIMEO(fd);
3994 if( !do_block(fd, POLLIN, timeout)) {
3995 err = WSAETIMEDOUT;
3996 /* a timeout is not fatal */
3997 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3998 goto err_free;
4002 n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
4003 if ( n == -1 )
4005 err = wsaErrno();
4006 goto err_free;
4009 TRACE(" -> %i bytes\n", n);
4010 *lpNumberOfBytesRecvd = n;
4012 HeapFree(GetProcessHeap(), 0, iovec);
4013 release_sock_fd( s, fd );
4014 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
4016 return 0;
4018 err_free:
4019 HeapFree(GetProcessHeap(), 0, iovec);
4021 err_close:
4022 release_sock_fd( s, fd );
4024 error:
4025 WARN(" -> ERROR %d\n", err);
4026 WSASetLastError( err );
4027 return SOCKET_ERROR;
4030 /***********************************************************************
4031 * WSCInstallProvider (WS2_32.88)
4033 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
4034 LPCWSTR lpszProviderDllPath,
4035 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
4036 DWORD dwNumberOfEntries,
4037 LPINT lpErrno )
4039 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
4040 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
4041 dwNumberOfEntries, lpErrno);
4042 *lpErrno = 0;
4043 return 0;
4047 /***********************************************************************
4048 * WSCDeinstallProvider (WS2_32.83)
4050 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
4052 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
4053 *lpErrno = 0;
4054 return 0;
4058 /***********************************************************************
4059 * WSAAccept (WS2_32.26)
4061 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
4062 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
4065 int ret = 0, size = 0;
4066 WSABUF CallerId, CallerData, CalleeId, CalleeData;
4067 /* QOS SQOS, GQOS; */
4068 GROUP g;
4069 SOCKET cs;
4070 SOCKADDR src_addr, dst_addr;
4072 TRACE("Socket %04x, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
4073 s, addr, addrlen, lpfnCondition, dwCallbackData);
4076 size = sizeof(src_addr);
4077 cs = WS_accept(s, &src_addr, &size);
4079 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
4081 CallerId.buf = (char *)&src_addr;
4082 CallerId.len = sizeof(src_addr);
4084 CallerData.buf = NULL;
4085 CallerData.len = (ULONG)NULL;
4087 WS_getsockname(cs, &dst_addr, &size);
4089 CalleeId.buf = (char *)&dst_addr;
4090 CalleeId.len = sizeof(dst_addr);
4093 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
4094 &CalleeId, &CalleeData, &g, dwCallbackData);
4096 switch (ret)
4098 case CF_ACCEPT:
4099 if (addr && addrlen)
4100 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
4101 return cs;
4102 case CF_DEFER:
4103 SERVER_START_REQ( set_socket_deferred )
4105 req->handle = SOCKET2HANDLE(s);
4106 req->deferred = SOCKET2HANDLE(cs);
4107 if ( !wine_server_call_err ( req ) )
4109 SetLastError( WSATRY_AGAIN );
4110 WS_closesocket( cs );
4113 SERVER_END_REQ;
4114 return SOCKET_ERROR;
4115 case CF_REJECT:
4116 WS_closesocket(cs);
4117 SetLastError(WSAECONNREFUSED);
4118 return SOCKET_ERROR;
4119 default:
4120 FIXME("Unknown return type from Condition function\n");
4121 SetLastError(WSAENOTSOCK);
4122 return SOCKET_ERROR;
4126 /***********************************************************************
4127 * WSADuplicateSocketA (WS2_32.32)
4129 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
4131 HANDLE hProcess;
4133 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4134 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4135 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
4136 /* I don't know what the real Windoze does next, this is a hack */
4137 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
4138 * the target use the global duplicate, or we could copy a reference to us to the structure
4139 * and let the target duplicate it from us, but let's do it as simple as possible */
4140 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4141 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
4142 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4143 0, FALSE, DUPLICATE_SAME_ACCESS);
4144 CloseHandle(hProcess);
4145 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4146 return 0;
4149 /***********************************************************************
4150 * WSADuplicateSocketW (WS2_32.33)
4152 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
4154 HANDLE hProcess;
4156 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4158 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4159 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4160 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
4161 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4162 0, FALSE, DUPLICATE_SAME_ACCESS);
4163 CloseHandle(hProcess);
4164 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4165 return 0;
4168 /***********************************************************************
4169 * WSAInstallServiceClassA (WS2_32.48)
4171 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
4173 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
4174 WSASetLastError(WSAEACCES);
4175 return SOCKET_ERROR;
4178 /***********************************************************************
4179 * WSAInstallServiceClassW (WS2_32.49)
4181 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
4183 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
4184 WSASetLastError(WSAEACCES);
4185 return SOCKET_ERROR;
4188 /***********************************************************************
4189 * WSARemoveServiceClass (WS2_32.70)
4191 int WINAPI WSARemoveServiceClass(LPGUID info)
4193 FIXME("Request to remove service %p\n",info);
4194 WSASetLastError(WSATYPE_NOT_FOUND);
4195 return SOCKET_ERROR;
4198 /***********************************************************************
4199 * WSAStringToAddressA (WS2_32.80)
4201 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
4202 INT AddressFamily,
4203 LPWSAPROTOCOL_INFOA lpProtocolInfo,
4204 LPSOCKADDR lpAddress,
4205 LPINT lpAddressLength)
4207 INT res=0;
4208 struct in_addr inetaddr;
4209 LPSTR workBuffer=NULL,ptrPort;
4211 TRACE( "(%s, %x, %p, %p, %p)\n", AddressString, AddressFamily, lpProtocolInfo,
4212 lpAddress, lpAddressLength );
4214 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
4216 if (AddressString)
4218 workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 );
4219 if (workBuffer)
4221 strcpy(workBuffer,AddressString);
4222 switch (AddressFamily)
4224 case AF_INET:
4225 /* caller wants to know the size of the socket buffer */
4226 if (*lpAddressLength < sizeof(SOCKADDR_IN))
4228 *lpAddressLength = sizeof(SOCKADDR_IN);
4229 res = WSAEFAULT;
4231 else
4233 /* caller wants to translate an AdressString into a SOCKADDR */
4234 if (lpAddress)
4236 memset(lpAddress,0,sizeof(SOCKADDR_IN));
4237 ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET;
4238 ptrPort = strchr(workBuffer,':');
4239 if (ptrPort)
4241 ((LPSOCKADDR_IN)lpAddress)->sin_port = (u_short)atoi(ptrPort+1);
4242 *ptrPort = '\0';
4244 else
4245 ((LPSOCKADDR_IN)lpAddress)->sin_port = 0;
4246 if (inet_aton(workBuffer, &inetaddr) > 0)
4248 ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr;
4249 res = 0;
4251 else
4252 res = WSAEINVAL;
4255 if (lpProtocolInfo)
4256 FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n",
4257 AddressString, AddressFamily,
4258 lpProtocolInfo, lpAddress, lpAddressLength);
4260 break;
4261 default:
4262 FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n",
4263 AddressString, AddressFamily,
4264 lpProtocolInfo, lpAddress, lpAddressLength);
4266 HeapFree( GetProcessHeap(), 0, workBuffer );
4268 else
4269 res = WSA_NOT_ENOUGH_MEMORY;
4271 else
4272 res = WSAEINVAL;
4274 if (!res) return 0;
4275 WSASetLastError(res);
4276 return SOCKET_ERROR;
4279 /***********************************************************************
4280 * WSAStringToAddressW (WS2_32.81)
4282 * Does anybody know if this functions allows to use hebrew/arabic/chinese... digits?
4283 * If this should be the case, it would be required to map these digits
4284 * to Unicode digits (0-9) using FoldString first.
4286 INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
4287 INT AddressFamily,
4288 LPWSAPROTOCOL_INFOW lpProtocolInfo,
4289 LPSOCKADDR lpAddress,
4290 LPINT lpAddressLength)
4292 INT sBuffer,res=0;
4293 LPSTR workBuffer=NULL;
4294 WSAPROTOCOL_INFOA infoA;
4295 LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
4297 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
4298 lpAddress, lpAddressLength );
4300 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
4302 /* if ProtocolInfo is available - convert to ANSI variant */
4303 if (lpProtocolInfo)
4305 lpProtoInfoA = &infoA;
4306 memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
4308 if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
4309 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
4311 WSASetLastError( WSAEINVAL);
4312 return SOCKET_ERROR;
4316 if (AddressString)
4318 /* Translate AddressString to ANSI code page - assumes that only
4319 standard digits 0-9 are used with this API call */
4320 sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
4321 workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
4323 if (workBuffer)
4325 WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
4326 res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
4327 lpAddress,lpAddressLength);
4328 HeapFree( GetProcessHeap(), 0, workBuffer );
4329 return res;
4331 else
4332 res = WSA_NOT_ENOUGH_MEMORY;
4334 else
4335 res = WSAEINVAL;
4337 WSASetLastError(res);
4338 return SOCKET_ERROR;
4341 /***********************************************************************
4342 * WSAAddressToStringA (WS2_32.27)
4344 * See WSAAddressToStringW
4346 INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
4347 LPWSAPROTOCOL_INFOA info, LPSTR string,
4348 LPDWORD lenstr )
4350 INT size;
4351 CHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
4352 CHAR *p;
4354 TRACE( "(%p, %ld, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
4356 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
4357 if (!string || !lenstr) return SOCKET_ERROR;
4359 /* sin_family is garanteed to be the first u_short */
4360 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
4362 sprintf( buffer, "%u.%u.%u.%u:%u",
4363 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
4364 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
4365 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
4366 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
4367 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
4369 p = strchr( buffer, ':' );
4370 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
4372 size = strlen( buffer );
4374 if (*lenstr < size)
4376 *lenstr = size;
4377 WSASetLastError(WSAEFAULT);
4378 return SOCKET_ERROR;
4381 strcpy( string, buffer );
4382 return 0;
4385 /***********************************************************************
4386 * WSAAddressToStringW (WS2_32.28)
4388 * Convert a sockaddr address into a readable address string.
4390 * PARAMS
4391 * sockaddr [I] Pointer to a sockaddr structure.
4392 * len [I] Size of the sockaddr structure.
4393 * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional).
4394 * string [I/O] Pointer to a buffer to receive the address string.
4395 * lenstr [I/O] Size of the receive buffer in WCHARs.
4397 * RETURNS
4398 * Success: 0
4399 * Failure: SOCKET_ERROR
4401 * NOTES
4402 * The 'info' parameter is ignored.
4404 * BUGS
4405 * Only supports AF_INET addresses.
4407 INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
4408 LPWSAPROTOCOL_INFOW info, LPWSTR string,
4409 LPDWORD lenstr )
4411 INT size;
4412 WCHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
4413 static const WCHAR format[] = { '%','u','.','%','u','.','%','u','.','%','u',':','%','u',0 };
4414 WCHAR *p;
4416 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
4418 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
4419 if (!string || !lenstr) return SOCKET_ERROR;
4421 /* sin_family is garanteed to be the first u_short */
4422 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
4424 sprintfW( buffer, format,
4425 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
4426 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
4427 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
4428 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
4429 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
4431 p = strchrW( buffer, ':' );
4432 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
4434 size = lstrlenW( buffer );
4436 if (*lenstr < size)
4438 *lenstr = size;
4439 return SOCKET_ERROR;
4442 lstrcpyW( string, buffer );
4443 return 0;
4446 /***********************************************************************
4447 * WSAEnumNameSpaceProvidersA (WS2_32.34)
4449 INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
4451 FIXME( "(%p %p) Stub!\n", len, buffer );
4452 return 0;
4455 /***********************************************************************
4456 * WSAEnumNameSpaceProvidersW (WS2_32.35)
4458 INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
4460 FIXME( "(%p %p) Stub!\n", len, buffer );
4461 return 0;
4464 /***********************************************************************
4465 * WSAGetQOSByName (WS2_32.41)
4467 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
4469 FIXME( "(0x%04x %p %p) Stub!\n", s, lpQOSName, lpQOS );
4470 return FALSE;
4473 /***********************************************************************
4474 * WSAGetServiceClassInfoA (WS2_32.42)
4476 INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
4477 LPWSASERVICECLASSINFOA info )
4479 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4480 len, info );
4481 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4482 return SOCKET_ERROR;
4485 /***********************************************************************
4486 * WSAGetServiceClassInfoW (WS2_32.43)
4488 INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
4489 LPWSASERVICECLASSINFOW info )
4491 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4492 len, info );
4493 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4494 return SOCKET_ERROR;
4497 /***********************************************************************
4498 * WSAGetServiceClassNameByClassIdA (WS2_32.44)
4500 INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
4502 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4503 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4504 return SOCKET_ERROR;
4507 /***********************************************************************
4508 * WSAGetServiceClassNameByClassIdW (WS2_32.45)
4510 INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
4512 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4513 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4514 return SOCKET_ERROR;
4517 /***********************************************************************
4518 * WSALookupServiceBeginA (WS2_32.59)
4520 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
4521 DWORD dwControlFlags,
4522 LPHANDLE lphLookup)
4524 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4525 lphLookup);
4526 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4527 return SOCKET_ERROR;
4530 /***********************************************************************
4531 * WSALookupServiceBeginW (WS2_32.60)
4533 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
4534 DWORD dwControlFlags,
4535 LPHANDLE lphLookup)
4537 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4538 lphLookup);
4539 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4540 return SOCKET_ERROR;
4543 /***********************************************************************
4544 * WSALookupServiceBeginW (WS2_32.61)
4546 INT WINAPI WSALookupServiceEnd( HANDLE lookup )
4548 FIXME("(%p) Stub!\n", lookup );
4549 return 0;
4552 /***********************************************************************
4553 * WSALookupServiceNextA (WS2_32.62)
4555 INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
4557 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4558 return 0;
4561 /***********************************************************************
4562 * WSALookupServiceNextW (WS2_32.63)
4564 INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
4566 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4567 return 0;
4570 /***********************************************************************
4571 * WSANtohl (WS2_32.64)
4573 INT WINAPI WSANtohl( SOCKET s, u_long netlong, u_long* lphostlong )
4575 TRACE( "(0x%04x 0x%08lx %p)\n", s, netlong, lphostlong );
4577 if (!lphostlong) return WSAEFAULT;
4579 *lphostlong = ntohl( netlong );
4580 return 0;
4583 /***********************************************************************
4584 * WSANtohs (WS2_32.65)
4586 INT WINAPI WSANtohs( SOCKET s, u_short netshort, u_short* lphostshort )
4588 TRACE( "(0x%04x 0x%08x %p)\n", s, netshort, lphostshort );
4590 if (!lphostshort) return WSAEFAULT;
4592 *lphostshort = ntohs( netshort );
4593 return 0;
4596 /***********************************************************************
4597 * WSAProviderConfigChange (WS2_32.66)
4599 INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
4600 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4602 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
4603 return SOCKET_ERROR;
4606 /***********************************************************************
4607 * WSARecvDisconnect (WS2_32.68)
4609 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
4611 TRACE( "(0x%04x %p)\n", s, disconnectdata );
4613 return WS_shutdown( s, 0 );
4616 /***********************************************************************
4617 * WSASetServiceA (WS2_32.76)
4619 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
4621 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4622 return 0;
4625 /***********************************************************************
4626 * WSASetServiceW (WS2_32.77)
4628 INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
4630 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4631 return 0;
4634 /***********************************************************************
4635 * WSCEnableNSProvider (WS2_32.84)
4637 INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
4639 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
4640 return 0;
4643 /***********************************************************************
4644 * WSCGetProviderPath (WS2_32.86)
4646 INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errcode )
4648 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errcode );
4650 if (!errcode || !provider || !len) return WSAEFAULT;
4652 *errcode = WSAEINVAL;
4653 return SOCKET_ERROR;
4656 /***********************************************************************
4657 * WSCInstallNameSpace (WS2_32.87)
4659 INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
4660 DWORD version, LPGUID provider )
4662 FIXME( "(%s %s 0x%08lx 0x%08lx %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
4663 namespace, version, debugstr_guid(provider) );
4664 return 0;
4667 /***********************************************************************
4668 * WSCUnInstallNameSpace (WS2_32.89)
4670 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
4672 FIXME("(%p) Stub!\n", lpProviderId);
4673 return NO_ERROR;
4676 /***********************************************************************
4677 * WSCWriteProviderOrder (WS2_32.91)
4679 INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
4681 FIXME("(%p 0x%08lx) Stub!\n", entry, number);
4682 return 0;