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