Implemented getaddrinfo(), including full mapping of struct addrinfo
[wine/multimedia.git] / dlls / winsock / socket.c
blobf0fc266d49c243c1963378d967af7743313ee684
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 "windef.h"
123 #include "winbase.h"
124 #include "wingdi.h"
125 #include "winuser.h"
126 #include "winerror.h"
127 #include "winnls.h"
128 #include "winsock2.h"
129 #include "mswsock.h"
130 #include "ws2tcpip.h"
131 #include "ws2spi.h"
132 #include "wsipx.h"
133 #include "winnt.h"
134 #include "iphlpapi.h"
135 #include "thread.h"
136 #include "wine/server.h"
137 #include "wine/debug.h"
138 #include "ntstatus.h"
139 #include "wine/unicode.h"
141 #ifdef HAVE_IPX
142 # include "wsnwlink.h"
143 #endif
146 #ifdef __FreeBSD__
147 # define sipx_network sipx_addr.x_net
148 # define sipx_node sipx_addr.x_host.c_host
149 #endif /* __FreeBSD__ */
151 #ifndef INADDR_NONE
152 #define INADDR_NONE ~0UL
153 #endif
155 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
157 /* critical section to protect some non-rentrant net function */
158 extern CRITICAL_SECTION csWSgetXXXbyYYY;
160 inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
162 if (!a) return "(nil)";
163 return wine_dbg_sprintf("{ family %d, address %s, port %d }",
164 ((const struct sockaddr_in *)a)->sin_family,
165 inet_ntoa(((const struct sockaddr_in *)a)->sin_addr),
166 ntohs(((const struct sockaddr_in *)a)->sin_port));
169 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
170 #define SOCKET2HANDLE(s) ((HANDLE)(s))
171 #define HANDLE2SOCKET(h) ((SOCKET)(h))
173 /****************************************************************
174 * Async IO declarations
175 ****************************************************************/
177 typedef struct ws2_async
179 HANDLE hSocket;
180 enum ws2_mode {ws2m_read, ws2m_write, ws2m_sd_read, ws2m_sd_write} mode;
181 LPWSAOVERLAPPED user_overlapped;
182 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
183 struct iovec *iovec;
184 int n_iovecs;
185 struct WS_sockaddr *addr;
186 union
188 int val; /* for send operations */
189 int *ptr; /* for recv operations */
190 } addrlen;
191 DWORD flags;
192 int fd;
193 HANDLE event;
194 } ws2_async;
196 /****************************************************************/
198 /* ----------------------------------- internal data */
200 /* ws_... struct conversion flags */
202 typedef struct /* WSAAsyncSelect() control struct */
204 HANDLE service, event, sock;
205 HWND hWnd;
206 UINT uMsg;
207 LONG lEvent;
208 } ws_select_info;
210 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
211 #define WS_MAX_UDP_DATAGRAM 1024
212 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
214 /* hostent's, servent's and protent's are stored in one buffer per thread,
215 * as documented on MSDN for the functions that return any of the buffers */
216 struct per_thread_data
218 int opentype;
219 struct WS_hostent *he_buffer;
220 struct WS_servent *se_buffer;
221 struct WS_protoent *pe_buffer;
222 int he_len;
223 int se_len;
224 int pe_len;
227 static INT num_startup; /* reference counter */
228 static FARPROC blocking_hook = WSA_DefaultBlockingHook;
230 /* function prototypes */
231 static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
232 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
233 static struct WS_servent *WS_dup_se(const struct servent* p_se);
235 int WSAIOCTL_GetInterfaceCount(void);
236 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
238 UINT wsaErrno(void);
239 UINT wsaHerrno(int errnr);
241 #define MAP_OPTION(opt) { WS_##opt, opt }
243 static const int ws_sock_map[][2] =
245 MAP_OPTION( SO_DEBUG ),
246 MAP_OPTION( SO_REUSEADDR ),
247 MAP_OPTION( SO_KEEPALIVE ),
248 MAP_OPTION( SO_DONTROUTE ),
249 MAP_OPTION( SO_BROADCAST ),
250 MAP_OPTION( SO_LINGER ),
251 MAP_OPTION( SO_OOBINLINE ),
252 MAP_OPTION( SO_SNDBUF ),
253 MAP_OPTION( SO_RCVBUF ),
254 MAP_OPTION( SO_ERROR ),
255 MAP_OPTION( SO_TYPE ),
256 #ifdef SO_RCVTIMEO
257 MAP_OPTION( SO_RCVTIMEO ),
258 #endif
259 #ifdef SO_SNDTIMEO
260 MAP_OPTION( SO_SNDTIMEO ),
261 #endif
262 { 0, 0 }
265 static const int ws_tcp_map[][2] =
267 #ifdef TCP_NODELAY
268 MAP_OPTION( TCP_NODELAY ),
269 #endif
270 { 0, 0 }
273 static const int ws_ip_map[][2] =
275 MAP_OPTION( IP_MULTICAST_IF ),
276 MAP_OPTION( IP_MULTICAST_TTL ),
277 MAP_OPTION( IP_MULTICAST_LOOP ),
278 MAP_OPTION( IP_ADD_MEMBERSHIP ),
279 MAP_OPTION( IP_DROP_MEMBERSHIP ),
280 MAP_OPTION( IP_OPTIONS ),
281 #ifdef IP_HDRINCL
282 MAP_OPTION( IP_HDRINCL ),
283 #endif
284 MAP_OPTION( IP_TOS ),
285 MAP_OPTION( IP_TTL ),
286 { 0, 0 }
289 static const int ws_af_map[][2] =
291 MAP_OPTION( AF_INET ),
292 MAP_OPTION( AF_INET6 ),
293 #ifdef HAVE_IPX
294 MAP_OPTION( AF_IPX ),
295 #endif
296 { 0, 0 }
299 static const int ws_socktype_map[][2] =
301 MAP_OPTION( SOCK_DGRAM ),
302 MAP_OPTION( SOCK_STREAM ),
303 MAP_OPTION( SOCK_RAW ),
304 { 0, 0 }
307 static const int ws_proto_map[][2] =
309 MAP_OPTION( IPPROTO_TCP ),
310 MAP_OPTION( IPPROTO_UDP ),
311 MAP_OPTION( IPPROTO_ICMP ),
312 MAP_OPTION( IPPROTO_IGMP ),
313 MAP_OPTION( IPPROTO_RAW ),
314 { 0, 0 }
317 static const int ws_aiflag_map[][2] =
319 MAP_OPTION( AI_PASSIVE ),
320 MAP_OPTION( AI_CANONNAME ),
321 MAP_OPTION( AI_NUMERICHOST ),
322 /* Linux/UNIX knows a lot more. But Windows only
323 * has 3 as far as I could see. -Marcus
325 { 0, 0 }
328 static const int ws_eai_map[][2] =
330 MAP_OPTION( EAI_AGAIN ),
331 MAP_OPTION( EAI_BADFLAGS ),
332 MAP_OPTION( EAI_FAIL ),
333 MAP_OPTION( EAI_FAMILY ),
334 MAP_OPTION( EAI_MEMORY ),
335 MAP_OPTION( EAI_NODATA ),
336 MAP_OPTION( EAI_SERVICE ),
337 MAP_OPTION( EAI_SOCKTYPE ),
338 { 0, 0 }
341 inline static DWORD NtStatusToWSAError( const DWORD status )
343 /* We only need to cover the status codes set by server async request handling */
344 DWORD wserr;
345 switch ( status )
347 case STATUS_SUCCESS: wserr = 0; break;
348 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
349 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
350 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
351 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
352 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
353 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
354 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
355 default:
356 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
357 /* It is not a NT status code but a winsock error */
358 wserr = status;
359 else
361 wserr = RtlNtStatusToDosError( status );
362 FIXME( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
365 return wserr;
368 /* set last error code from NT status without mapping WSA errors */
369 inline static unsigned int set_error( unsigned int err )
371 if (err)
373 err = NtStatusToWSAError( err );
374 SetLastError( err );
376 return err;
379 inline static int get_sock_fd( SOCKET s, DWORD access, int *flags )
381 int fd;
382 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, flags ) ))
383 return -1;
384 return fd;
387 inline static void release_sock_fd( SOCKET s, int fd )
389 wine_server_release_fd( SOCKET2HANDLE(s), fd );
392 static void _enable_event( HANDLE s, unsigned int event,
393 unsigned int sstate, unsigned int cstate )
395 SERVER_START_REQ( enable_socket_event )
397 req->handle = s;
398 req->mask = event;
399 req->sstate = sstate;
400 req->cstate = cstate;
401 wine_server_call( req );
403 SERVER_END_REQ;
406 static int _is_blocking(SOCKET s)
408 int ret;
409 SERVER_START_REQ( get_socket_event )
411 req->handle = SOCKET2HANDLE(s);
412 req->service = FALSE;
413 req->c_event = 0;
414 wine_server_call( req );
415 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
417 SERVER_END_REQ;
418 return ret;
421 static unsigned int _get_sock_mask(SOCKET s)
423 unsigned int ret;
424 SERVER_START_REQ( get_socket_event )
426 req->handle = SOCKET2HANDLE(s);
427 req->service = FALSE;
428 req->c_event = 0;
429 wine_server_call( req );
430 ret = reply->mask;
432 SERVER_END_REQ;
433 return ret;
436 static void _sync_sock_state(SOCKET s)
438 /* do a dummy wineserver request in order to let
439 the wineserver run through its select loop once */
440 (void)_is_blocking(s);
443 static int _get_sock_error(SOCKET s, unsigned int bit)
445 int events[FD_MAX_EVENTS];
447 SERVER_START_REQ( get_socket_event )
449 req->handle = SOCKET2HANDLE(s);
450 req->service = FALSE;
451 req->c_event = 0;
452 wine_server_set_reply( req, events, sizeof(events) );
453 wine_server_call( req );
455 SERVER_END_REQ;
456 return events[bit];
459 static struct per_thread_data *get_per_thread_data(void)
461 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
462 /* lazy initialization */
463 if (!ptb)
465 ptb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptb) );
466 NtCurrentTeb()->WinSockData = ptb;
468 return ptb;
471 static void free_per_thread_data(void)
473 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
475 if (!ptb) return;
477 /* delete scratch buffers */
478 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
479 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
480 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
481 ptb->he_buffer = NULL;
482 ptb->se_buffer = NULL;
483 ptb->pe_buffer = NULL;
485 HeapFree( GetProcessHeap(), 0, ptb );
486 NtCurrentTeb()->WinSockData = NULL;
489 /***********************************************************************
490 * DllMain (WS2_32.init)
492 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
494 TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
495 switch (fdwReason) {
496 case DLL_PROCESS_ATTACH:
497 break;
498 case DLL_PROCESS_DETACH:
499 free_per_thread_data();
500 num_startup = 0;
501 break;
502 case DLL_THREAD_DETACH:
503 free_per_thread_data();
504 break;
506 return TRUE;
509 /***********************************************************************
510 * convert_sockopt()
512 * Converts socket flags from Windows format.
513 * Return 1 if converted, 0 if not (error).
515 static int convert_sockopt(INT *level, INT *optname)
517 int i;
518 switch (*level)
520 case WS_SOL_SOCKET:
521 *level = SOL_SOCKET;
522 for(i=0; ws_sock_map[i][0]; i++)
524 if( ws_sock_map[i][0] == *optname )
526 *optname = ws_sock_map[i][1];
527 return 1;
530 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
531 break;
532 case WS_IPPROTO_TCP:
533 *level = IPPROTO_TCP;
534 for(i=0; ws_tcp_map[i][0]; i++)
536 if ( ws_tcp_map[i][0] == *optname )
538 *optname = ws_tcp_map[i][1];
539 return 1;
542 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
543 break;
544 case WS_IPPROTO_IP:
545 *level = IPPROTO_IP;
546 for(i=0; ws_ip_map[i][0]; i++)
548 if (ws_ip_map[i][0] == *optname )
550 *optname = ws_ip_map[i][1];
551 return 1;
554 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
555 break;
556 default: FIXME("Unimplemented or unknown socket level\n");
558 return 0;
561 static inline BOOL is_timeout_option( int optname )
563 #ifdef SO_RCVTIMEO
564 if (optname == SO_RCVTIMEO) return TRUE;
565 #endif
566 #ifdef SO_SNDTIMEO
567 if (optname == SO_SNDTIMEO) return TRUE;
568 #endif
569 return FALSE;
572 /* ----------------------------------- Per-thread info (or per-process?) */
574 static char *strdup_lower(const char *str)
576 int i;
577 char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
579 if (ret)
581 for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
582 ret[i] = 0;
584 else SetLastError(WSAENOBUFS);
585 return ret;
588 static fd_set* fd_set_import( fd_set* fds, const WS_fd_set* wsfds, int access, int* highfd, int lfd[] )
590 /* translate Winsock fd set into local fd set */
591 if( wsfds )
593 unsigned int i;
595 FD_ZERO(fds);
596 for( i = 0; i < wsfds->fd_count; i++ )
598 int s = wsfds->fd_array[i];
599 int fd = get_sock_fd( s, access, NULL );
600 if (fd != -1)
602 lfd[ i ] = fd;
603 if( fd > *highfd ) *highfd = fd;
604 FD_SET(fd, fds);
606 else lfd[ i ] = -1;
608 return fds;
610 return NULL;
613 inline static int sock_error_p(int s)
615 unsigned int optval, optlen;
617 optlen = sizeof(optval);
618 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
619 if (optval) WARN("\t[%i] error: %d\n", s, optval);
620 return optval != 0;
623 static int fd_set_export( const fd_set* fds, fd_set* exceptfds, WS_fd_set* wsfds, int lfd[] )
625 int num_err = 0;
627 /* translate local fd set into Winsock fd set, adding
628 * errors to exceptfds (only if app requested it) */
630 if( wsfds )
632 int i, j, count = wsfds->fd_count;
634 for( i = 0, j = 0; i < count; i++ )
636 int fd = lfd[i];
637 SOCKET s = wsfds->fd_array[i];
638 if (fd == -1) continue;
639 if( FD_ISSET(fd, fds) )
641 if ( exceptfds && sock_error_p(fd) )
643 FD_SET(fd, exceptfds);
644 num_err++;
646 else wsfds->fd_array[j++] = s;
648 release_sock_fd( s, fd );
650 wsfds->fd_count = j;
652 return num_err;
655 static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
657 if ( wsfds )
659 unsigned int i;
661 for ( i = 0; i < wsfds->fd_count; i++ )
662 if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
663 wsfds->fd_count = 0;
667 /* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
668 * from an fd and return the value converted to milli seconds
669 * or -1 if there is an infinite time out */
670 static inline int get_rcvsnd_timeo( int fd, int optname)
672 struct timeval tv;
673 unsigned int len = sizeof(tv);
674 int ret = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
675 if( ret >= 0)
676 ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
677 if( ret <= 0 ) /* tv == {0,0} means infinite time out */
678 return -1;
679 return ret;
682 /* macro wrappers for portability */
683 #ifdef SO_RCVTIMEO
684 #define GET_RCVTIMEO(fd) get_rcvsnd_timeo( (fd), SO_RCVTIMEO)
685 #else
686 #define GET_RCVTIMEO(fd) (-1)
687 #endif
689 #ifdef SO_SNDTIMEO
690 #define GET_SNDTIMEO(fd) get_rcvsnd_timeo( (fd), SO_SNDTIMEO)
691 #else
692 #define GET_SNDTIMEO(fd) (-1)
693 #endif
695 /* utility: given an fd, will block until one of the events occurs */
696 static inline int do_block( int fd, int events, int timeout )
698 struct pollfd pfd;
699 int ret;
701 pfd.fd = fd;
702 pfd.events = events;
704 while ((ret = poll(&pfd, 1, timeout)) < 0)
706 if (errno != EINTR)
707 return -1;
709 if( ret == 0 )
710 return 0;
711 return pfd.revents;
714 static int
715 convert_af_w2u(int windowsaf) {
716 int i;
718 for (i=0;ws_af_map[i][0];i++)
719 if (ws_af_map[i][0] == windowsaf)
720 return ws_af_map[i][1];
721 FIXME("unhandled Windows address family %d\n", windowsaf);
722 return -1;
725 static int
726 convert_af_u2w(int unixaf) {
727 int i;
729 for (i=0;ws_af_map[i][0];i++)
730 if (ws_af_map[i][1] == unixaf)
731 return ws_af_map[i][0];
732 FIXME("unhandled UNIX address family %d\n", unixaf);
733 return -1;
736 static int
737 convert_proto_w2u(int windowsproto) {
738 int i;
740 for (i=0;ws_proto_map[i][0];i++)
741 if (ws_proto_map[i][0] == windowsproto)
742 return ws_proto_map[i][1];
743 FIXME("unhandled Windows socket protocol %d\n", windowsproto);
744 return -1;
747 static int
748 convert_proto_u2w(int unixproto) {
749 int i;
751 for (i=0;ws_proto_map[i][0];i++)
752 if (ws_proto_map[i][1] == unixproto)
753 return ws_proto_map[i][0];
754 if (unixproto == 0) /* 0 is ok too as wild card */
755 return 0;
756 FIXME("unhandled UNIX socket protocol %d\n", unixproto);
757 return -1;
760 static int
761 convert_socktype_w2u(int windowssocktype) {
762 int i;
764 for (i=0;ws_socktype_map[i][0];i++)
765 if (ws_socktype_map[i][0] == windowssocktype)
766 return ws_socktype_map[i][1];
767 FIXME("unhandled Windows socket type %d\n", windowssocktype);
768 return -1;
771 static int
772 convert_socktype_u2w(int unixsocktype) {
773 int i;
775 for (i=0;ws_socktype_map[i][0];i++)
776 if (ws_socktype_map[i][1] == unixsocktype)
777 return ws_socktype_map[i][0];
778 FIXME("unhandled UNIX socket type %d\n", unixsocktype);
779 return -1;
782 /* ----------------------------------- API -----
784 * Init / cleanup / error checking.
787 /***********************************************************************
788 * WSAStartup (WS2_32.115)
790 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
792 TRACE("verReq=%x\n", wVersionRequested);
794 if (LOBYTE(wVersionRequested) < 1)
795 return WSAVERNOTSUPPORTED;
797 if (!lpWSAData) return WSAEINVAL;
799 num_startup++;
801 /* that's the whole of the negotiation for now */
802 lpWSAData->wVersion = wVersionRequested;
803 /* return winsock information */
804 lpWSAData->wHighVersion = 0x0202;
805 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
806 strcpy(lpWSAData->szSystemStatus, "Running" );
807 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
808 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
809 /* don't do anything with lpWSAData->lpVendorInfo */
810 /* (some apps don't allocate the space for this field) */
812 TRACE("succeeded\n");
813 return 0;
817 /***********************************************************************
818 * WSACleanup (WS2_32.116)
820 INT WINAPI WSACleanup(void)
822 if (num_startup)
823 return 0;
824 SetLastError(WSANOTINITIALISED);
825 return SOCKET_ERROR;
829 /***********************************************************************
830 * WSAGetLastError (WINSOCK.111)
831 * WSAGetLastError (WS2_32.111)
833 INT WINAPI WSAGetLastError(void)
835 return GetLastError();
838 /***********************************************************************
839 * WSASetLastError (WS2_32.112)
841 void WINAPI WSASetLastError(INT iError) {
842 SetLastError(iError);
845 static struct WS_hostent *check_buffer_he(int size)
847 struct per_thread_data * ptb = get_per_thread_data();
848 if (ptb->he_buffer)
850 if (ptb->he_len >= size ) return ptb->he_buffer;
851 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
853 ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
854 if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
855 return ptb->he_buffer;
858 static struct WS_servent *check_buffer_se(int size)
860 struct per_thread_data * ptb = get_per_thread_data();
861 if (ptb->se_buffer)
863 if (ptb->se_len >= size ) return ptb->se_buffer;
864 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
866 ptb->se_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->se_len = size) );
867 if (!ptb->se_buffer) SetLastError(WSAENOBUFS);
868 return ptb->se_buffer;
871 static struct WS_protoent *check_buffer_pe(int size)
873 struct per_thread_data * ptb = get_per_thread_data();
874 if (ptb->pe_buffer)
876 if (ptb->pe_len >= size ) return ptb->pe_buffer;
877 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
879 ptb->pe_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->pe_len = size) );
880 if (!ptb->pe_buffer) SetLastError(WSAENOBUFS);
881 return ptb->pe_buffer;
884 /* ----------------------------------- i/o APIs */
886 #ifdef HAVE_IPX
887 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX || (pf) == WS_AF_INET6)
888 #else
889 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf) == WS_AF_INET6)
890 #endif
893 /**********************************************************************/
895 /* Returns the converted address if successful, NULL if it was too small to
896 * start with. Note that the returned pointer may be the original pointer
897 * if no conversion is necessary.
899 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, unsigned int *uaddrlen)
901 switch (wsaddr->sa_family)
903 #ifdef HAVE_IPX
904 case WS_AF_IPX:
906 const struct WS_sockaddr_ipx* wsipx=(const struct WS_sockaddr_ipx*)wsaddr;
907 struct sockaddr_ipx* uipx;
909 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
910 return NULL;
912 *uaddrlen=sizeof(struct sockaddr_ipx);
913 uipx=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
914 uipx->sipx_family=AF_IPX;
915 uipx->sipx_port=wsipx->sa_socket;
916 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
917 * in one go
919 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
920 #ifdef IPX_FRAME_NONE
921 uipx->sipx_type=IPX_FRAME_NONE;
922 #endif
923 return (const struct sockaddr*)uipx;
925 #endif
926 case WS_AF_INET6: {
927 struct sockaddr_in6* uin6;
928 const struct WS_sockaddr_in6* win6 = (struct WS_sockaddr_in6*)wsaddr;
929 const struct WS_sockaddr_in6_old* win6old = (struct WS_sockaddr_in6_old*)wsaddr;
931 /* Note: Windows has 2 versions of the sockaddr_in6 struct, one with
932 * scope_id, one without. Check:
933 * http://msdn.microsoft.com/library/en-us/winsock/winsock/sockaddr_2.asp
935 if (wsaddrlen==sizeof(struct WS_sockaddr_in6_old)) {
936 *uaddrlen=sizeof(struct sockaddr_in6);
937 uin6=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
938 uin6->sin6_family = AF_INET6;
939 uin6->sin6_port = win6old->sin6_port;
940 uin6->sin6_flowinfo = win6old->sin6_flowinfo;
941 memcpy(&uin6->sin6_addr,&win6old->sin6_addr,16); /* 16 bytes = 128 address bits */
942 return (const struct sockaddr*)uin6;
944 if (wsaddrlen>=sizeof(struct WS_sockaddr_in6)) {
945 *uaddrlen=sizeof(struct sockaddr_in6);
946 uin6=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
947 uin6->sin6_family = AF_INET6;
948 uin6->sin6_port = win6->sin6_port;
949 uin6->sin6_flowinfo = win6->sin6_flowinfo;
950 uin6->sin6_scope_id = win6->sin6_scope_id;
951 memcpy(&uin6->sin6_addr,&win6->sin6_addr,16); /* 16 bytes = 128 address bits */
952 return (const struct sockaddr*)uin6;
954 FIXME("bad size %d for WS_sockaddr_in6\n",wsaddrlen);
955 return NULL;
957 case WS_AF_INET: {
958 struct sockaddr_in* uin;
959 const struct WS_sockaddr_in* win = (struct WS_sockaddr_in*)wsaddr;
961 if (wsaddrlen<sizeof(struct WS_sockaddr_in))
962 return NULL;
963 *uaddrlen=sizeof(struct sockaddr_in);
964 uin = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
965 uin->sin_family = AF_INET;
966 uin->sin_port = win->sin_port;
967 memcpy(&uin->sin_addr,&win->sin_addr,4); /* 4 bytes = 32 address bits */
968 return (const struct sockaddr*)uin;
970 default:
971 FIXME("Unknown address family %d, return NULL.\n", wsaddr->sa_family);
972 return NULL;
976 /* Allocates a Unix sockaddr structure to receive the data */
977 static inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, unsigned int* uaddrlen)
979 if (wsaddr==NULL)
981 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
983 /* This is not strictly the right thing to do. Hope it works however */
984 *uaddrlen=0;
986 return NULL;
989 if (*wsaddrlen==0)
990 *uaddrlen=0;
991 else
992 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
994 return HeapAlloc(GetProcessHeap(), 0, *uaddrlen);
997 /* Returns 0 if successful, -1 if the buffer is too small */
998 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
1000 int res;
1002 switch(uaddr->sa_family)
1004 #ifdef HAVE_IPX
1005 case AF_IPX:
1007 const struct sockaddr_ipx* uipx=(const struct sockaddr_ipx*)uaddr;
1008 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
1010 res=-1;
1011 switch (*wsaddrlen) /* how much can we copy? */
1013 default:
1014 res=0; /* enough */
1015 *wsaddrlen=uaddrlen;
1016 wsipx->sa_socket=uipx->sipx_port;
1017 /* fall through */
1018 case 13:
1019 case 12:
1020 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
1021 /* fall through */
1022 case 11:
1023 case 10:
1024 case 9:
1025 case 8:
1026 case 7:
1027 case 6:
1028 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
1029 /* fall through */
1030 case 5:
1031 case 4:
1032 case 3:
1033 case 2:
1034 wsipx->sa_family=WS_AF_IPX;
1035 /* fall through */
1036 case 1:
1037 case 0:
1038 /* way too small */
1039 break;
1042 break;
1043 #endif
1044 case AF_INET6: {
1045 const struct sockaddr_in6* uin6 = (struct sockaddr_in6*)uaddr;
1046 struct WS_sockaddr_in6* win6 = (struct WS_sockaddr_in6*)wsaddr;
1047 struct WS_sockaddr_in6_old* win6old = (struct WS_sockaddr_in6_old*)wsaddr;
1049 if (*wsaddrlen < sizeof(struct WS_sockaddr_in6_old))
1050 return -1;
1051 if (*wsaddrlen == sizeof(struct WS_sockaddr_in6_old)) {
1052 win6old->sin6_family = WS_AF_INET6;
1053 win6old->sin6_port = uin6->sin6_port;
1054 win6old->sin6_flowinfo = uin6->sin6_flowinfo;
1055 memcpy(&win6old->sin6_addr,&uin6->sin6_addr,16); /* 16 bytes = 128 address bits */
1056 *wsaddrlen = sizeof(struct WS_sockaddr_in6_old);
1057 return 0;
1059 if (*wsaddrlen >= sizeof(struct WS_sockaddr_in6)) {
1060 win6->sin6_family = WS_AF_INET6;
1061 win6->sin6_port = uin6->sin6_port;
1062 win6->sin6_flowinfo = uin6->sin6_flowinfo;
1063 memcpy(&win6->sin6_addr,&uin6->sin6_addr,16); /* 16 bytes = 128 address bits */
1064 win6->sin6_scope_id = uin6->sin6_scope_id;
1065 *wsaddrlen = sizeof(struct WS_sockaddr_in6);
1066 return 0;
1068 return 0;
1070 case AF_INET: {
1071 struct sockaddr_in* uin = (struct sockaddr_in*)uaddr;
1072 struct WS_sockaddr_in* win = (struct WS_sockaddr_in*)wsaddr;
1074 if (*wsaddrlen < sizeof(struct WS_sockaddr_in))
1075 return -1;
1076 win->sin_family = WS_AF_INET;
1077 win->sin_port = uin->sin_port;
1078 memcpy(&win->sin_addr,&uin->sin_addr,4); /* 4 bytes = 32 address bits */
1079 *wsaddrlen = sizeof(struct WS_sockaddr_in6);
1080 return 0;
1082 default:
1083 FIXME("Unknown address family %d\n", uaddr->sa_family);
1084 return -1;
1086 return res;
1089 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
1090 * ws_sockaddr_alloc
1092 static inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
1094 if (uaddr!=(const struct sockaddr*)wsaddr)
1095 HeapFree(GetProcessHeap(), 0, (void *)uaddr);
1098 /**************************************************************************
1099 * Functions for handling overlapped I/O
1100 **************************************************************************/
1102 static void CALLBACK ws2_async_terminate(ws2_async* as, IO_STATUS_BLOCK* iosb)
1104 TRACE( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, iosb );
1106 wine_server_release_fd( as->hSocket, as->fd );
1107 if ( as->event != INVALID_HANDLE_VALUE )
1108 NtSetEvent( as->event, NULL );
1110 if (as->completion_func)
1111 as->completion_func( NtStatusToWSAError (iosb->u.Status),
1112 iosb->Information, as->user_overlapped, as->flags );
1113 if ( !as->user_overlapped )
1115 #if 0
1116 /* FIXME: I don't think this is really used */
1117 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
1118 WSACloseEvent( as->overlapped->hEvent );
1119 #endif
1120 HeapFree( GetProcessHeap(), 0, iosb );
1123 HeapFree( GetProcessHeap(), 0, as->iovec );
1124 HeapFree( GetProcessHeap(), 0, as );
1127 /***********************************************************************
1128 * WS2_make_async (INTERNAL)
1131 static void WINAPI WS2_async_recv(void*, IO_STATUS_BLOCK*, ULONG);
1132 static void WINAPI WS2_async_send(void*, IO_STATUS_BLOCK*, ULONG);
1133 static void WINAPI WS2_async_shutdown( void*, IO_STATUS_BLOCK*, ULONG);
1135 inline static struct ws2_async*
1136 WS2_make_async(SOCKET s, int fd, enum ws2_mode mode, struct iovec *iovec, DWORD dwBufferCount,
1137 LPDWORD lpFlags, struct WS_sockaddr *addr,
1138 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
1139 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
1140 IO_STATUS_BLOCK **piosb)
1142 struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof( ws2_async ) );
1144 TRACE( "wsa %p\n", wsa );
1146 if (!wsa)
1147 return NULL;
1149 wsa->hSocket = (HANDLE) s;
1150 wsa->mode = mode;
1151 switch (mode)
1153 case ws2m_read:
1154 case ws2m_sd_read:
1155 wsa->flags = *lpFlags;
1156 wsa->addrlen.ptr = addrlen;
1157 break;
1158 case ws2m_write:
1159 case ws2m_sd_write:
1160 wsa->flags = 0;
1161 wsa->addrlen.val = *addrlen;
1162 break;
1163 default:
1164 ERR("Invalid async mode: %d\n", mode);
1166 wsa->user_overlapped = lpOverlapped;
1167 wsa->completion_func = lpCompletionRoutine;
1168 wsa->iovec = iovec;
1169 wsa->n_iovecs = dwBufferCount;
1170 wsa->addr = addr;
1171 wsa->fd = fd;
1172 wsa->event = INVALID_HANDLE_VALUE;
1174 if ( lpOverlapped )
1176 *piosb = (IO_STATUS_BLOCK*)lpOverlapped;
1177 if (!lpCompletionRoutine)
1179 wsa->event = lpOverlapped->hEvent;
1180 NtResetEvent(wsa->event, NULL);
1183 else if (!(*piosb = HeapAlloc( GetProcessHeap(), 0, sizeof(IO_STATUS_BLOCK))))
1184 goto error;
1186 (*piosb)->Information = 0;
1187 (*piosb)->u.Status = STATUS_PENDING;
1188 TRACE( "wsa %p, h %p, ev %p, fd %d, iosb %p, uov %p, cfunc %p\n",
1189 wsa, wsa->hSocket, wsa->event, wsa->fd,
1190 *piosb, wsa->user_overlapped, wsa->completion_func );
1192 return wsa;
1194 error:
1195 TRACE("Error\n");
1196 HeapFree( GetProcessHeap(), 0, wsa );
1197 return NULL;
1200 static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb)
1202 PIO_APC_ROUTINE apc;
1203 int type;
1204 NTSTATUS status;
1206 switch (wsa->mode)
1208 case ws2m_read: apc = WS2_async_recv; type = ASYNC_TYPE_READ; break;
1209 case ws2m_write: apc = WS2_async_send; type = ASYNC_TYPE_WRITE; break;
1210 case ws2m_sd_read: apc = WS2_async_shutdown; type = ASYNC_TYPE_READ; break;
1211 case ws2m_sd_write: apc = WS2_async_shutdown; type = ASYNC_TYPE_WRITE; break;
1212 default: FIXME("Unknown internal mode (%d)\n", wsa->mode); return STATUS_INVALID_PARAMETER;
1215 SERVER_START_REQ( register_async )
1217 req->handle = wsa->hSocket;
1218 req->io_apc = apc;
1219 req->io_sb = iosb;
1220 req->io_user = wsa;
1221 req->type = type;
1222 req->count = iosb->Information;
1223 status = wine_server_call( req );
1225 SERVER_END_REQ;
1227 if ( status ) iosb->u.Status = status;
1228 if ( iosb->u.Status != STATUS_PENDING )
1230 /* Note: we get here a non zero status when we couldn't queue the async
1231 * in the server. Therefore, we simply terminate the async.
1233 status = iosb->u.Status;
1234 ws2_async_terminate(wsa, iosb);
1235 return status;
1237 NtCurrentTeb()->num_async_io++;
1238 return STATUS_SUCCESS;
1241 /***********************************************************************
1242 * WS2_recv (INTERNAL)
1244 * Workhorse for both synchronous and asynchronous recv() operations.
1246 static int WS2_recv( int fd, struct iovec* iov, int count,
1247 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1248 LPDWORD lpFlags )
1250 struct msghdr hdr;
1251 int n;
1252 TRACE( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
1253 fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
1255 hdr.msg_name = NULL;
1257 if ( lpFrom )
1259 hdr.msg_namelen = *lpFromlen;
1260 hdr.msg_name = ws_sockaddr_alloc( lpFrom, lpFromlen, &hdr.msg_namelen );
1261 if ( !hdr.msg_name )
1263 WSASetLastError( WSAEFAULT );
1264 n = -1;
1265 goto out;
1268 else
1269 hdr.msg_namelen = 0;
1271 hdr.msg_iov = iov;
1272 hdr.msg_iovlen = count;
1273 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1274 hdr.msg_accrights = NULL;
1275 hdr.msg_accrightslen = 0;
1276 #else
1277 hdr.msg_control = NULL;
1278 hdr.msg_controllen = 0;
1279 hdr.msg_flags = 0;
1280 #endif
1282 if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 )
1284 TRACE( "recvmsg error %d\n", errno);
1285 goto out;
1288 if ( lpFrom &&
1289 ws_sockaddr_u2ws( hdr.msg_name, hdr.msg_namelen,
1290 lpFrom, lpFromlen ) != 0 )
1292 /* The from buffer was too small, but we read the data
1293 * anyway. Is that really bad?
1295 WSASetLastError( WSAEFAULT );
1296 WARN( "Address buffer too small\n" );
1299 out:
1301 ws_sockaddr_free( hdr.msg_name, lpFrom );
1302 TRACE("-> %d\n", n);
1303 return n;
1306 /***********************************************************************
1307 * WS2_async_recv (INTERNAL)
1309 * Handler for overlapped recv() operations.
1311 static void WINAPI WS2_async_recv( void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
1313 ws2_async* wsa = (ws2_async*) ovp;
1314 int result, err;
1316 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1318 switch (status)
1320 case STATUS_ALERTED:
1321 result = WS2_recv( wsa->fd, wsa->iovec, wsa->n_iovecs,
1322 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1323 if (result >= 0)
1325 iosb->u.Status = STATUS_SUCCESS;
1326 iosb->Information = result;
1327 TRACE( "received %d bytes\n", result );
1328 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1330 else
1332 err = wsaErrno();
1333 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1335 iosb->u.Status = STATUS_PENDING;
1336 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1337 TRACE( "still pending\n" );
1339 else
1341 iosb->u.Status = err; /* FIXME: is this correct ???? */
1342 TRACE( "Error: %x\n", err );
1345 if (iosb->u.Status == STATUS_PENDING)
1346 ws2_queue_async(wsa, iosb);
1347 else
1348 ws2_async_terminate(wsa, iosb);
1349 break;
1350 default:
1351 FIXME( "status: %ld\n", status );
1352 iosb->u.Status = status;
1353 ws2_async_terminate(wsa, iosb);
1354 return;
1358 /***********************************************************************
1359 * WS2_send (INTERNAL)
1361 * Workhorse for both synchronous and asynchronous send() operations.
1363 static int WS2_send( int fd, struct iovec* iov, int count,
1364 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1366 struct msghdr hdr;
1367 int n = -1;
1368 TRACE( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
1369 fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
1371 hdr.msg_name = NULL;
1373 if ( to )
1375 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u( to, tolen, &hdr.msg_namelen );
1376 if ( !hdr.msg_name )
1378 WSASetLastError( WSAEFAULT );
1379 goto out;
1382 #ifdef HAVE_IPX
1383 if(to->sa_family == WS_AF_IPX)
1385 #ifdef SOL_IPX
1386 struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
1387 int val=0;
1388 unsigned int len=sizeof(int);
1390 /* The packet type is stored at the ipx socket level; At least the linux kernel seems
1391 * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
1392 * the packet type and then we can retrieve it using getsockopt. After that we can set the
1393 * ipx type in the sockaddr_opx structure with the stored value.
1395 if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
1397 TRACE("ptype: %d (fd:%d)\n", val, fd);
1398 uipx->sipx_type = val;
1400 #endif
1402 #endif
1405 else
1406 hdr.msg_namelen = 0;
1408 hdr.msg_iov = iov;
1409 hdr.msg_iovlen = count;
1410 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1411 hdr.msg_accrights = NULL;
1412 hdr.msg_accrightslen = 0;
1413 #else
1414 hdr.msg_control = NULL;
1415 hdr.msg_controllen = 0;
1416 hdr.msg_flags = 0;
1417 #endif
1419 n = sendmsg(fd, &hdr, dwFlags);
1421 out:
1422 ws_sockaddr_free( hdr.msg_name, to );
1423 return n;
1426 /***********************************************************************
1427 * WS2_async_send (INTERNAL)
1429 * Handler for overlapped send() operations.
1431 static void WINAPI WS2_async_send(void* as, IO_STATUS_BLOCK* iosb, ULONG status)
1433 ws2_async* wsa = (ws2_async*) as;
1434 int result;
1436 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1438 switch (status)
1440 case STATUS_ALERTED:
1441 if (iosb->u.Status != STATUS_PENDING) FIXME("wrong %08lx\n", iosb->u.Status);
1442 /* check to see if the data is ready (non-blocking) */
1443 result = WS2_send( wsa->fd, wsa->iovec, wsa->n_iovecs,
1444 wsa->addr, wsa->addrlen.val, wsa->flags );
1446 if (result >= 0)
1448 iosb->u.Status = STATUS_SUCCESS;
1449 iosb->Information = result;
1450 TRACE( "sent %d bytes\n", result );
1451 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1453 else
1455 int err = wsaErrno();
1456 if ( err == WSAEINTR )
1458 iosb->u.Status = STATUS_PENDING;
1459 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1460 TRACE( "still pending\n" );
1462 else
1464 /* We set the status to a winsock error code and check for that
1465 later in NtStatusToWSAError () */
1466 iosb->u.Status = err;
1467 TRACE( "Error: %x\n", err );
1470 if (iosb->u.Status == STATUS_PENDING)
1471 ws2_queue_async(wsa, iosb);
1472 else
1473 ws2_async_terminate(wsa, iosb);
1474 break;
1475 default:
1476 FIXME( "status: %ld\n", status );
1477 iosb->u.Status = status;
1478 ws2_async_terminate(wsa, iosb);
1479 return;
1484 /***********************************************************************
1485 * WS2_async_shutdown (INTERNAL)
1487 * Handler for shutdown() operations on overlapped sockets.
1489 static void WINAPI WS2_async_shutdown( void* as, PIO_STATUS_BLOCK iosb, ULONG status )
1491 ws2_async* wsa = (ws2_async*) as;
1492 int err = 1;
1494 TRACE( "async %p %d\n", wsa, wsa->mode );
1495 switch (status)
1497 case STATUS_ALERTED:
1498 switch ( wsa->mode )
1500 case ws2m_sd_read: err = shutdown( wsa->fd, 0 ); break;
1501 case ws2m_sd_write: err = shutdown( wsa->fd, 1 ); break;
1502 default: ERR("invalid mode: %d\n", wsa->mode );
1504 iosb->u.Status = err ? wsaErrno() : STATUS_SUCCESS;
1505 if (iosb->u.Status == STATUS_PENDING)
1506 ws2_queue_async(wsa, iosb);
1507 else
1508 ws2_async_terminate(wsa, iosb);
1509 break;
1510 default:
1511 iosb->u.Status = status;
1512 ws2_async_terminate(wsa, iosb);
1513 break;
1518 /***********************************************************************
1519 * WS2_register_async_shutdown (INTERNAL)
1521 * Helper function for WS_shutdown() on overlapped sockets.
1523 static int WS2_register_async_shutdown( SOCKET s, int fd, enum ws2_mode mode )
1525 struct ws2_async *wsa;
1526 int ret, err = WSAEFAULT;
1527 DWORD dwflags = 0;
1528 int len = 0;
1529 LPWSAOVERLAPPED ovl = HeapAlloc(GetProcessHeap(), 0, sizeof( WSAOVERLAPPED ));
1530 IO_STATUS_BLOCK *iosb = NULL;
1532 TRACE("s %d fd %d mode %d\n", s, fd, mode);
1533 if (!ovl)
1534 goto out;
1536 ovl->hEvent = WSACreateEvent();
1537 if ( ovl->hEvent == WSA_INVALID_EVENT )
1538 goto out_free;
1540 wsa = WS2_make_async( s, fd, mode, NULL, 0,
1541 &dwflags, NULL, &len, ovl, NULL, &iosb );
1542 if ( !wsa )
1543 goto out_close;
1545 /* Hack: this will cause ws2_async_terminate() to free the overlapped structure */
1546 wsa->user_overlapped = NULL;
1547 if ( (ret = ws2_queue_async( wsa, iosb )) )
1549 err = NtStatusToWSAError( ret );
1550 goto out;
1552 /* Try immediate completion */
1553 while ( WaitForSingleObjectEx( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1554 return 0;
1556 out_close:
1557 WSACloseEvent( ovl->hEvent );
1558 out_free:
1559 HeapFree( GetProcessHeap(), 0, ovl );
1560 out:
1561 return err;
1564 /***********************************************************************
1565 * accept (WS2_32.1)
1567 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1568 int *addrlen32)
1570 SOCKET as;
1571 BOOL is_blocking;
1573 TRACE("socket %04x\n", s );
1574 is_blocking = _is_blocking(s);
1576 do {
1577 if (is_blocking)
1579 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1580 if (fd == -1) return INVALID_SOCKET;
1581 /* block here */
1582 do_block(fd, POLLIN, -1);
1583 _sync_sock_state(s); /* let wineserver notice connection */
1584 release_sock_fd( s, fd );
1585 /* retrieve any error codes from it */
1586 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1587 /* FIXME: care about the error? */
1589 SERVER_START_REQ( accept_socket )
1591 req->lhandle = SOCKET2HANDLE(s);
1592 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1593 req->inherit = TRUE;
1594 set_error( wine_server_call( req ) );
1595 as = HANDLE2SOCKET( reply->handle );
1597 SERVER_END_REQ;
1598 if (as)
1600 if (addr) WS_getpeername(as, addr, addrlen32);
1601 return as;
1603 } while (is_blocking);
1604 return INVALID_SOCKET;
1607 /***********************************************************************
1608 * bind (WS2_32.2)
1610 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1612 int fd = get_sock_fd( s, 0, NULL );
1613 int res = SOCKET_ERROR;
1615 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1617 if (fd != -1)
1619 if (!name || (name->sa_family && !SUPPORTED_PF(name->sa_family)))
1621 SetLastError(WSAEAFNOSUPPORT);
1623 else
1625 const struct sockaddr* uaddr;
1626 unsigned int uaddrlen;
1628 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1629 if (uaddr == NULL)
1631 SetLastError(WSAEFAULT);
1633 else
1635 if (bind(fd, uaddr, uaddrlen) < 0)
1637 int loc_errno = errno;
1638 WARN("\tfailure - errno = %i\n", errno);
1639 errno = loc_errno;
1640 switch (errno)
1642 case EBADF:
1643 SetLastError(WSAENOTSOCK);
1644 break;
1645 case EADDRNOTAVAIL:
1646 SetLastError(WSAEINVAL);
1647 break;
1648 default:
1649 SetLastError(wsaErrno());
1650 break;
1653 else
1655 res=0; /* success */
1657 ws_sockaddr_free(uaddr,name);
1660 release_sock_fd( s, fd );
1662 return res;
1665 /***********************************************************************
1666 * closesocket (WS2_32.3)
1668 int WINAPI WS_closesocket(SOCKET s)
1670 TRACE("socket %04x\n", s);
1671 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1672 return SOCKET_ERROR;
1675 /***********************************************************************
1676 * connect (WS2_32.4)
1678 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1680 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1682 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1684 if (fd != -1)
1686 const struct sockaddr* uaddr;
1687 unsigned int uaddrlen;
1689 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1690 if (uaddr == NULL)
1692 SetLastError(WSAEFAULT);
1694 else
1696 int rc;
1698 rc=connect(fd, uaddr, uaddrlen);
1699 ws_sockaddr_free(uaddr,name);
1700 if (rc == 0)
1701 goto connect_success;
1704 if (errno == EINPROGRESS)
1706 /* tell wineserver that a connection is in progress */
1707 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1708 FD_CONNECT|FD_READ|FD_WRITE,
1709 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1710 if (_is_blocking(s))
1712 int result;
1713 /* block here */
1714 do_block(fd, POLLIN | POLLOUT, -1);
1715 _sync_sock_state(s); /* let wineserver notice connection */
1716 /* retrieve any error codes from it */
1717 result = _get_sock_error(s, FD_CONNECT_BIT);
1718 if (result)
1719 SetLastError(result);
1720 else
1722 goto connect_success;
1725 else
1727 SetLastError(WSAEWOULDBLOCK);
1730 else
1732 SetLastError(wsaErrno());
1734 release_sock_fd( s, fd );
1736 return SOCKET_ERROR;
1738 connect_success:
1739 release_sock_fd( s, fd );
1740 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1741 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1742 FD_CONNECT|FD_WINE_LISTENING);
1743 return 0;
1746 /***********************************************************************
1747 * WSAConnect (WS2_32.30)
1749 int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
1750 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1751 LPQOS lpSQOS, LPQOS lpGQOS )
1753 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1754 FIXME("unsupported parameters!\n");
1755 return WS_connect( s, name, namelen );
1759 /***********************************************************************
1760 * getpeername (WS2_32.5)
1762 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1764 int fd;
1765 int res;
1767 TRACE("socket: %04x, ptr %p, len %08x\n", s, name, *namelen);
1769 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1770 if( (name == NULL) || (namelen == NULL) )
1772 SetLastError( WSAEFAULT );
1773 return SOCKET_ERROR;
1776 fd = get_sock_fd( s, 0, NULL );
1777 res = SOCKET_ERROR;
1779 if (fd != -1)
1781 struct sockaddr* uaddr;
1782 unsigned int uaddrlen;
1784 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1785 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1787 SetLastError(wsaErrno());
1789 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1791 /* The buffer was too small */
1792 SetLastError(WSAEFAULT);
1794 else
1796 res=0;
1798 ws_sockaddr_free(uaddr,name);
1799 release_sock_fd( s, fd );
1801 return res;
1804 /***********************************************************************
1805 * getsockname (WS2_32.6)
1807 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1809 int fd;
1810 int res;
1812 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1814 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1815 if( (name == NULL) || (namelen == NULL) )
1817 SetLastError( WSAEFAULT );
1818 return SOCKET_ERROR;
1821 fd = get_sock_fd( s, 0, NULL );
1822 res = SOCKET_ERROR;
1824 if (fd != -1)
1826 struct sockaddr* uaddr;
1827 unsigned int uaddrlen;
1829 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1830 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1832 SetLastError(wsaErrno());
1834 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1836 /* The buffer was too small */
1837 SetLastError(WSAEFAULT);
1839 else
1841 res=0;
1843 ws_sockaddr_free(uaddr,name);
1844 release_sock_fd( s, fd );
1846 return res;
1849 /***********************************************************************
1850 * getsockopt (WS2_32.7)
1852 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1853 INT optname, char *optval, INT *optlen)
1855 int fd;
1856 INT ret = 0;
1858 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %p, len %d\n",
1859 s, level, optname, optval, *optlen);
1860 /* SO_OPENTYPE does not require a valid socket handle. */
1861 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1863 if (!optlen || *optlen < sizeof(int) || !optval)
1865 SetLastError(WSAEFAULT);
1866 return SOCKET_ERROR;
1868 *(int *)optval = get_per_thread_data()->opentype;
1869 *optlen = sizeof(int);
1870 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1871 return 0;
1874 #ifdef HAVE_IPX
1875 if(level == NSPROTO_IPX)
1877 struct WS_sockaddr_ipx addr;
1878 IPX_ADDRESS_DATA *data;
1879 int namelen;
1880 switch(optname)
1882 case IPX_PTYPE:
1883 fd = get_sock_fd( s, 0, NULL );
1884 #ifdef SOL_IPX
1885 if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, (unsigned int*)optlen) == -1)
1887 return SOCKET_ERROR;
1889 #else
1891 struct ipx val;
1892 socklen_t len=sizeof(struct ipx);
1894 if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
1895 return SOCKET_ERROR;
1896 *optval = (int)val.ipx_pt;
1898 #endif
1899 TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
1900 release_sock_fd( s, fd );
1902 return 0;
1903 case IPX_ADDRESS:
1905 * On a Win2000 system with one network card there are usually three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
1906 * Using this call you can then retrieve info about this all. In case of Linux it is a bit different. Usually you have
1907 * only "one" device active and further it is not possible to query things like the linkspeed.
1909 FIXME("IPX_ADDRESS\n");
1910 namelen = sizeof(struct WS_sockaddr_ipx);
1911 memset(&addr, 0, sizeof(struct WS_sockaddr_ipx));
1912 WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
1914 data = (IPX_ADDRESS_DATA*)optval;
1915 memcpy(data->nodenum,&addr.sa_nodenum,sizeof(data->nodenum));
1916 memcpy(data->netnum,&addr.sa_netnum,sizeof(data->netnum));
1917 data->adapternum = 0;
1918 data->wan = FALSE; /* We are not on a wan for now .. */
1919 data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
1920 data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
1921 data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit; note 1MB = 1000kB in this case */
1922 return 0;
1923 case IPX_MAX_ADAPTER_NUM:
1924 FIXME("IPX_MAX_ADAPTER_NUM\n");
1925 *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
1927 return 0;
1928 default:
1929 FIXME("IPX optname:%x\n", optname);
1930 return SOCKET_ERROR;
1933 #endif
1935 if( (fd = get_sock_fd( s, 0, NULL )) == -1)
1936 return SOCKET_ERROR;
1938 if (!convert_sockopt(&level, &optname)) {
1939 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1940 ret = SOCKET_ERROR;
1941 } else {
1942 struct timeval tv;
1943 struct linger lingval;
1944 unsigned int len, *plen = (unsigned int*)optlen;
1945 char *pval = optval;
1946 if(level == SOL_SOCKET && is_timeout_option(optname)) {
1947 len = sizeof(tv);
1948 plen = &len;
1949 pval = (char *) &tv;
1950 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1951 len = sizeof(lingval);
1952 plen = &len;
1953 pval = (char *) &lingval;
1955 if (getsockopt(fd, (int) level, optname, pval, plen) != 0 ) {
1956 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1957 ret = SOCKET_ERROR;
1958 } else if(level == SOL_SOCKET && is_timeout_option(optname)) {
1959 if( *optlen >= sizeof(INT) ) {
1960 *optlen = sizeof(INT);
1961 *(INT*)optval = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1962 } else {
1963 SetLastError(WSAEFAULT);
1964 ret = SOCKET_ERROR;
1966 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1967 if( *optlen >= sizeof( LINGER) ) {
1968 (( LINGER *) optval)->l_onoff = lingval.l_onoff;
1969 (( LINGER *) optval)->l_linger = lingval.l_linger;
1970 } else {
1971 SetLastError(WSAEFAULT);
1972 ret = SOCKET_ERROR;
1976 release_sock_fd( s, fd );
1977 return ret;
1981 /***********************************************************************
1982 * htonl (WINSOCK.8)
1983 * htonl (WS2_32.8)
1985 u_long WINAPI WS_htonl(u_long hostlong)
1987 return htonl(hostlong);
1991 /***********************************************************************
1992 * htons (WINSOCK.9)
1993 * htons (WS2_32.9)
1995 u_short WINAPI WS_htons(u_short hostshort)
1997 return htons(hostshort);
2000 /***********************************************************************
2001 * WSAHtonl (WS2_32.46)
2002 * From MSDN decription of error codes, this function should also
2003 * check if WinSock has been initialized and the socket is a valid
2004 * socket. But why? This function only translates a host byte order
2005 * u_long into a network byte order u_long...
2007 int WINAPI WSAHtonl(SOCKET s, u_long hostlong, u_long *lpnetlong)
2009 if (lpnetlong)
2011 *lpnetlong = htonl(hostlong);
2012 return 0;
2014 WSASetLastError(WSAEFAULT);
2015 return SOCKET_ERROR;
2018 /***********************************************************************
2019 * WSAHtons (WS2_32.47)
2020 * From MSDN decription of error codes, this function should also
2021 * check if WinSock has been initialized and the socket is a valid
2022 * socket. But why? This function only translates a host byte order
2023 * u_short into a network byte order u_short...
2025 int WINAPI WSAHtons(SOCKET s, u_short hostshort, u_short *lpnetshort)
2028 if (lpnetshort)
2030 *lpnetshort = htons(hostshort);
2031 return 0;
2033 WSASetLastError(WSAEFAULT);
2034 return SOCKET_ERROR;
2038 /***********************************************************************
2039 * inet_addr (WINSOCK.10)
2040 * inet_addr (WS2_32.11)
2042 u_long WINAPI WS_inet_addr(const char *cp)
2044 return inet_addr(cp);
2048 /***********************************************************************
2049 * ntohl (WINSOCK.14)
2050 * ntohl (WS2_32.14)
2052 u_long WINAPI WS_ntohl(u_long netlong)
2054 return ntohl(netlong);
2058 /***********************************************************************
2059 * ntohs (WINSOCK.15)
2060 * ntohs (WS2_32.15)
2062 u_short WINAPI WS_ntohs(u_short netshort)
2064 return ntohs(netshort);
2068 /***********************************************************************
2069 * inet_ntoa (WS2_32.12)
2071 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
2073 /* use "buffer for dummies" here because some applications have a
2074 * propensity to decode addresses in ws_hostent structure without
2075 * saving them first...
2077 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
2079 char* s = inet_ntoa(*((struct in_addr*)&in));
2080 if( s )
2082 strcpy(dbuffer, s);
2083 return dbuffer;
2085 SetLastError(wsaErrno());
2086 return NULL;
2089 /**********************************************************************
2090 * WSAIoctl (WS2_32.50)
2093 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
2095 INT WINAPI WSAIoctl(SOCKET s,
2096 DWORD dwIoControlCode,
2097 LPVOID lpvInBuffer,
2098 DWORD cbInBuffer,
2099 LPVOID lpbOutBuffer,
2100 DWORD cbOutBuffer,
2101 LPDWORD lpcbBytesReturned,
2102 LPWSAOVERLAPPED lpOverlapped,
2103 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
2105 int fd = get_sock_fd( s, 0, NULL );
2107 if (fd == -1) return SOCKET_ERROR;
2109 TRACE("%d, 0x%08lx, %p, %ld, %p, %ld, %p, %p, %p\n",
2110 s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpbOutBuffer,
2111 cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
2113 switch( dwIoControlCode )
2115 case SIO_GET_INTERFACE_LIST:
2117 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
2118 DWORD size, numInt, apiReturn;
2120 TRACE("-> SIO_GET_INTERFACE_LIST request\n");
2122 if (!lpbOutBuffer)
2124 release_sock_fd( s, fd );
2125 WSASetLastError(WSAEFAULT);
2126 return SOCKET_ERROR;
2128 if (!lpcbBytesReturned)
2130 release_sock_fd( s, fd );
2131 WSASetLastError(WSAEFAULT);
2132 return SOCKET_ERROR;
2135 apiReturn = GetAdaptersInfo(NULL, &size);
2136 if (apiReturn == ERROR_NO_DATA)
2138 numInt = 0;
2140 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
2142 PIP_ADAPTER_INFO table = HeapAlloc(GetProcessHeap(),0,size);
2144 if (table)
2146 if (GetAdaptersInfo(table, &size) == NO_ERROR)
2148 PIP_ADAPTER_INFO ptr;
2150 if (size*sizeof(INTERFACE_INFO)/sizeof(IP_ADAPTER_INFO) > cbOutBuffer)
2152 WARN("Buffer too small = %lu, cbOutBuffer = %lu\n", size, cbOutBuffer);
2153 HeapFree(GetProcessHeap(),0,table);
2154 release_sock_fd( s, fd );
2155 WSASetLastError(WSAEFAULT);
2156 return SOCKET_ERROR;
2158 for (ptr = table, numInt = 0; ptr;
2159 ptr = ptr->Next, intArray++, numInt++)
2161 unsigned int addr, mask, bcast;
2162 struct ifreq ifInfo;
2164 /* Socket Status Flags */
2165 lstrcpynA(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
2166 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2168 ERR("Error obtaining status flags for socket!\n");
2169 HeapFree(GetProcessHeap(),0,table);
2170 release_sock_fd( s, fd );
2171 WSASetLastError(WSAEINVAL);
2172 return SOCKET_ERROR;
2174 else
2176 /* set flags; the values of IFF_* are not the same
2177 under Linux and Windows, therefore must generate
2178 new flags */
2179 intArray->iiFlags = 0;
2180 if (ifInfo.ifr_flags & IFF_BROADCAST)
2181 intArray->iiFlags |= WS_IFF_BROADCAST;
2182 #ifdef IFF_POINTOPOINT
2183 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
2184 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
2185 #endif
2186 if (ifInfo.ifr_flags & IFF_LOOPBACK)
2187 intArray->iiFlags |= WS_IFF_LOOPBACK;
2188 if (ifInfo.ifr_flags & IFF_UP)
2189 intArray->iiFlags |= WS_IFF_UP;
2190 if (ifInfo.ifr_flags & IFF_MULTICAST)
2191 intArray->iiFlags |= WS_IFF_MULTICAST;
2194 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
2195 mask = inet_addr(ptr->IpAddressList.IpMask.String);
2196 bcast = addr | (addr & !mask);
2197 intArray->iiAddress.AddressIn.sin_family = AF_INET;
2198 intArray->iiAddress.AddressIn.sin_port = 0;
2199 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2200 addr;
2201 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2202 intArray->iiNetmask.AddressIn.sin_port = 0;
2203 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2204 mask;
2205 intArray->iiBroadcastAddress.AddressIn.sin_family =
2206 AF_INET;
2207 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2208 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2209 WS_s_addr = bcast;
2212 else
2214 ERR("Unable to get interface table!\n");
2215 release_sock_fd( s, fd );
2216 HeapFree(GetProcessHeap(),0,table);
2217 WSASetLastError(WSAEINVAL);
2218 return SOCKET_ERROR;
2220 HeapFree(GetProcessHeap(),0,table);
2222 else
2224 release_sock_fd( s, fd );
2225 WSASetLastError(WSAEINVAL);
2226 return SOCKET_ERROR;
2229 else
2231 ERR("Unable to get interface table!\n");
2232 release_sock_fd( s, fd );
2233 WSASetLastError(WSAEINVAL);
2234 return SOCKET_ERROR;
2236 /* Calculate the size of the array being returned */
2237 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2238 break;
2241 case SIO_ADDRESS_LIST_CHANGE:
2242 FIXME("-> SIO_ADDRESS_LIST_CHANGE request: stub\n");
2243 /* FIXME: error and return code depend on whether socket was created
2244 * with WSA_FLAG_OVERLAPPED, but there is no easy way to get this */
2245 break;
2247 default:
2248 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2249 release_sock_fd( s, fd );
2250 WSASetLastError(WSAEOPNOTSUPP);
2251 return SOCKET_ERROR;
2254 /* Function executed with no errors */
2255 release_sock_fd( s, fd );
2256 return 0;
2260 /***********************************************************************
2261 * ioctlsocket (WS2_32.10)
2263 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2265 int fd;
2266 long newcmd = cmd;
2268 TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
2270 switch( cmd )
2272 case WS_FIONREAD:
2273 newcmd=FIONREAD;
2274 break;
2276 case WS_FIONBIO:
2277 if( _get_sock_mask(s) )
2279 /* AsyncSelect()'ed sockets are always nonblocking */
2280 if (*argp) return 0;
2281 SetLastError(WSAEINVAL);
2282 return SOCKET_ERROR;
2284 fd = get_sock_fd( s, 0, NULL );
2285 if (fd != -1)
2287 int ret;
2288 if (*argp)
2290 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2291 ret = fcntl( fd, F_SETFL, O_NONBLOCK );
2293 else
2295 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2296 ret = fcntl( fd, F_SETFL, 0 );
2298 release_sock_fd( s, fd );
2299 if (!ret) return 0;
2300 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2302 return SOCKET_ERROR;
2304 case WS_SIOCATMARK:
2305 newcmd=SIOCATMARK;
2306 break;
2308 case WS__IOW('f',125,u_long):
2309 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2310 SetLastError(WSAEINVAL);
2311 return SOCKET_ERROR;
2313 case SIOCGIFBRDADDR:
2314 case SIOCGIFNETMASK:
2315 case SIOCGIFADDR:
2316 /* These don't need any special handling. They are used by
2317 WsControl, and are here to suppress an unnecessary warning. */
2318 break;
2320 default:
2321 /* Netscape tries hard to use bogus ioctl 0x667e */
2322 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2323 break;
2326 fd = get_sock_fd( s, 0, NULL );
2327 if (fd != -1)
2329 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2331 release_sock_fd( s, fd );
2332 return 0;
2334 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2335 release_sock_fd( s, fd );
2337 return SOCKET_ERROR;
2340 /***********************************************************************
2341 * listen (WS2_32.13)
2343 int WINAPI WS_listen(SOCKET s, int backlog)
2345 int fd = get_sock_fd( s, GENERIC_READ, NULL );
2347 TRACE("socket %04x, backlog %d\n", s, backlog);
2348 if (fd != -1)
2350 if (listen(fd, backlog) == 0)
2352 release_sock_fd( s, fd );
2353 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2354 FD_WINE_LISTENING,
2355 FD_CONNECT|FD_WINE_CONNECTED);
2356 return 0;
2358 SetLastError(wsaErrno());
2359 release_sock_fd( s, fd );
2361 return SOCKET_ERROR;
2364 /***********************************************************************
2365 * recv (WS2_32.16)
2367 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2369 DWORD n, dwFlags = flags;
2370 WSABUF wsabuf;
2372 wsabuf.len = len;
2373 wsabuf.buf = buf;
2375 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2376 return SOCKET_ERROR;
2377 else
2378 return n;
2381 /***********************************************************************
2382 * recvfrom (WS2_32.17)
2384 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2385 struct WS_sockaddr *from, int *fromlen)
2387 DWORD n, dwFlags = flags;
2388 WSABUF wsabuf;
2390 wsabuf.len = len;
2391 wsabuf.buf = buf;
2393 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2394 return SOCKET_ERROR;
2395 else
2396 return n;
2399 /***********************************************************************
2400 * select (WS2_32.18)
2402 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2403 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2404 const struct WS_timeval* ws_timeout)
2406 int highfd = 0;
2407 fd_set readfds, writefds, exceptfds;
2408 fd_set *p_read, *p_write, *p_except;
2409 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2410 struct timeval timeout, *timeoutaddr = NULL;
2412 TRACE("read %p, write %p, excp %p timeout %p\n",
2413 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2415 p_read = fd_set_import(&readfds, ws_readfds, GENERIC_READ, &highfd, readfd);
2416 p_write = fd_set_import(&writefds, ws_writefds, GENERIC_WRITE, &highfd, writefd);
2417 p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
2418 if (ws_timeout)
2420 timeoutaddr = &timeout;
2421 timeout.tv_sec=ws_timeout->tv_sec;
2422 timeout.tv_usec=ws_timeout->tv_usec;
2425 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2427 fd_set_export(&readfds, p_except, ws_readfds, readfd);
2428 fd_set_export(&writefds, p_except, ws_writefds, writefd);
2430 if (p_except && ws_exceptfds)
2432 unsigned int i, j;
2434 for (i = j = 0; i < ws_exceptfds->fd_count; i++)
2436 int fd = exceptfd[i];
2437 SOCKET s = ws_exceptfds->fd_array[i];
2438 if (fd == -1) continue;
2439 if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
2440 release_sock_fd( s, fd );
2442 ws_exceptfds->fd_count = j;
2444 return highfd;
2446 fd_set_unimport(ws_readfds, readfd);
2447 fd_set_unimport(ws_writefds, writefd);
2448 fd_set_unimport(ws_exceptfds, exceptfd);
2450 if( highfd == 0 ) return 0;
2451 SetLastError(wsaErrno());
2452 return SOCKET_ERROR;
2456 /***********************************************************************
2457 * send (WS2_32.19)
2459 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2461 DWORD n;
2462 WSABUF wsabuf;
2464 wsabuf.len = len;
2465 wsabuf.buf = (char*) buf;
2467 if ( WSASendTo( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2468 return SOCKET_ERROR;
2469 else
2470 return n;
2473 /***********************************************************************
2474 * WSASend (WS2_32.72)
2476 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2477 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2478 LPWSAOVERLAPPED lpOverlapped,
2479 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2481 return WSASendTo( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2482 NULL, 0, lpOverlapped, lpCompletionRoutine );
2485 /***********************************************************************
2486 * WSASendDisconnect (WS2_32.73)
2488 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2490 return WS_shutdown( s, SD_SEND );
2494 /***********************************************************************
2495 * WSASendTo (WS2_32.74)
2497 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2498 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2499 const struct WS_sockaddr *to, int tolen,
2500 LPWSAOVERLAPPED lpOverlapped,
2501 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2503 unsigned int i;
2504 int n, fd, err = WSAENOTSOCK, flags, ret;
2505 struct iovec* iovec;
2506 struct ws2_async *wsa;
2507 IO_STATUS_BLOCK* iosb;
2509 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2510 s, lpBuffers, dwBufferCount, dwFlags,
2511 to, tolen, lpOverlapped, lpCompletionRoutine);
2513 fd = get_sock_fd( s, GENERIC_WRITE, &flags );
2514 TRACE( "fd=%d, flags=%x\n", fd, flags );
2516 if ( fd == -1 ) return SOCKET_ERROR;
2518 if (flags & FD_FLAG_SEND_SHUTDOWN)
2520 WSASetLastError( WSAESHUTDOWN );
2521 goto err_close;
2524 if ( !lpNumberOfBytesSent )
2526 err = WSAEFAULT;
2527 goto err_close;
2530 iovec = HeapAlloc(GetProcessHeap(), 0, dwBufferCount * sizeof(struct iovec) );
2532 if ( !iovec )
2534 err = WSAEFAULT;
2535 goto err_close;
2538 for ( i = 0; i < dwBufferCount; i++ )
2540 iovec[i].iov_base = lpBuffers[i].buf;
2541 iovec[i].iov_len = lpBuffers[i].len;
2544 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2546 wsa = WS2_make_async( s, fd, ws2m_write, iovec, dwBufferCount,
2547 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2548 lpOverlapped, lpCompletionRoutine, &iosb );
2549 if ( !wsa )
2551 err = WSAEFAULT;
2552 goto err_free;
2555 if ( ( ret = ws2_queue_async( wsa, iosb ) ) )
2557 err = NtStatusToWSAError( ret );
2559 if ( !lpOverlapped )
2560 HeapFree( GetProcessHeap(), 0, iosb );
2561 HeapFree( GetProcessHeap(), 0, wsa );
2562 goto err_free;
2565 /* Try immediate completion */
2566 if ( lpOverlapped )
2568 if ( WSAGetOverlappedResult( s, lpOverlapped,
2569 lpNumberOfBytesSent, FALSE, &dwFlags) )
2570 return 0;
2572 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
2573 goto error;
2576 WSASetLastError( WSA_IO_PENDING );
2577 return SOCKET_ERROR;
2580 if (_is_blocking(s))
2582 /* FIXME: exceptfds? */
2583 int timeout = GET_SNDTIMEO(fd);
2584 if( !do_block(fd, POLLOUT, timeout)) {
2585 err = WSAETIMEDOUT;
2586 goto err_free; /* msdn says a timeout in send is fatal */
2590 n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2591 if ( n == -1 )
2593 err = wsaErrno();
2594 if ( err == WSAEWOULDBLOCK )
2595 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2596 goto err_free;
2599 TRACE(" -> %i bytes\n", n);
2600 *lpNumberOfBytesSent = n;
2602 HeapFree( GetProcessHeap(), 0, iovec );
2603 release_sock_fd( s, fd );
2604 return 0;
2606 err_free:
2607 HeapFree( GetProcessHeap(), 0, iovec );
2609 err_close:
2610 release_sock_fd( s, fd );
2612 error:
2613 WARN(" -> ERROR %d\n", err);
2614 WSASetLastError(err);
2615 return SOCKET_ERROR;
2618 /***********************************************************************
2619 * sendto (WS2_32.20)
2621 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2622 const struct WS_sockaddr *to, int tolen)
2624 DWORD n;
2625 WSABUF wsabuf;
2627 wsabuf.len = len;
2628 wsabuf.buf = (char*) buf;
2630 if ( WSASendTo(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2631 return SOCKET_ERROR;
2632 else
2633 return n;
2636 /***********************************************************************
2637 * setsockopt (WS2_32.21)
2639 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2640 const char *optval, int optlen)
2642 int fd;
2643 int woptval;
2644 struct linger linger;
2645 struct timeval tval;
2647 TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
2648 s, level, optname, optval, optlen);
2650 /* SO_OPENTYPE does not require a valid socket handle. */
2651 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2653 if (optlen < sizeof(int) || !optval)
2655 SetLastError(WSAEFAULT);
2656 return SOCKET_ERROR;
2658 get_per_thread_data()->opentype = *(int *)optval;
2659 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2660 return 0;
2663 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2664 * socket. This will either not happen under windows or it is ignored in
2665 * windows (but it works in linux and therefore prevents the game from
2666 * finding games outside the current network) */
2667 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2669 FIXME("Does windows ignore SO_DONTROUTE?\n");
2670 return 0;
2673 #ifdef HAVE_IPX
2674 if(level == NSPROTO_IPX)
2676 switch(optname)
2678 case IPX_PTYPE:
2679 fd = get_sock_fd( s, 0, NULL );
2680 TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", *(int*)optval, fd);
2682 /* We try to set the ipx type on ipx socket level. */
2683 #ifdef SOL_IPX
2684 if(setsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
2686 ERR("IPX: could not set ipx option type; expect weird behaviour\n");
2687 return SOCKET_ERROR;
2689 #else
2691 struct ipx val;
2692 /* Should we retrieve val using a getsockopt call and then
2693 * set the modified one? */
2694 val.ipx_pt = *optval;
2695 setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
2697 #endif
2698 release_sock_fd( s, fd );
2699 return 0;
2700 case IPX_FILTERPTYPE:
2701 /* Sets the receive filter packet type, at the moment we don't support it */
2702 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
2704 /* Returning 0 is better for now than returning a SOCKET_ERROR */
2705 return 0;
2706 default:
2707 FIXME("opt_name:%x\n", optname);
2708 return SOCKET_ERROR;
2710 return 0;
2712 #endif
2714 /* Is a privileged and useless operation, so we don't. */
2715 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
2717 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2718 return 0;
2721 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2722 /* This is unique to WinSock and takes special conversion */
2723 linger.l_onoff = *((int*)optval) ? 0: 1;
2724 linger.l_linger = 0;
2725 optname=SO_LINGER;
2726 optval = (char*)&linger;
2727 optlen = sizeof(struct linger);
2728 level = SOL_SOCKET;
2730 else
2732 if (!convert_sockopt(&level, &optname)) {
2733 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2734 SetLastError(WSAENOPROTOOPT);
2735 return SOCKET_ERROR;
2737 if (optname == SO_LINGER && optval) {
2738 linger.l_onoff = ((LINGER*)optval)->l_onoff;
2739 linger.l_linger = ((LINGER*)optval)->l_linger;
2740 /* FIXME: what is documented behavior if SO_LINGER optval
2741 is null?? */
2742 optval = (char*)&linger;
2743 optlen = sizeof(struct linger);
2745 else if (optval && optlen < sizeof(int))
2747 woptval= *((INT16 *) optval);
2748 optval= (char*) &woptval;
2749 optlen=sizeof(int);
2751 if (level == SOL_SOCKET && is_timeout_option(optname))
2753 if (optlen == sizeof(UINT32)) {
2754 /* WinSock passes miliseconds instead of struct timeval */
2755 tval.tv_usec = (*(PUINT32)optval % 1000) * 1000;
2756 tval.tv_sec = *(PUINT32)optval / 1000;
2757 /* min of 500 milisec */
2758 if (tval.tv_sec == 0 && tval.tv_usec < 500000)
2759 tval.tv_usec = 500000;
2760 optlen = sizeof(struct timeval);
2761 optval = (char*)&tval;
2762 } else if (optlen == sizeof(struct timeval)) {
2763 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2764 } else {
2765 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2766 return 0;
2769 if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
2771 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2772 return 0;
2777 fd = get_sock_fd( s, 0, NULL );
2778 if (fd == -1) return SOCKET_ERROR;
2780 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2782 release_sock_fd( s, fd );
2783 return 0;
2785 TRACE("Setting socket error, %d\n", wsaErrno());
2786 SetLastError(wsaErrno());
2787 release_sock_fd( s, fd );
2788 return SOCKET_ERROR;
2791 /***********************************************************************
2792 * shutdown (WS2_32.22)
2794 int WINAPI WS_shutdown(SOCKET s, int how)
2796 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2797 unsigned int clear_flags = 0;
2799 fd = get_sock_fd( s, 0, &flags );
2800 TRACE("socket %04x, how %i %x\n", s, how, flags );
2802 if (fd == -1)
2803 return SOCKET_ERROR;
2805 switch( how )
2807 case 0: /* drop receives */
2808 clear_flags |= FD_READ;
2809 break;
2810 case 1: /* drop sends */
2811 clear_flags |= FD_WRITE;
2812 break;
2813 case 2: /* drop all */
2814 clear_flags |= FD_READ|FD_WRITE;
2815 default:
2816 clear_flags |= FD_WINE_LISTENING;
2819 if ( flags & FD_FLAG_OVERLAPPED ) {
2821 switch ( how )
2823 case SD_RECEIVE:
2824 fd0 = fd;
2825 break;
2826 case SD_SEND:
2827 fd1 = fd;
2828 break;
2829 case SD_BOTH:
2830 default:
2831 fd0 = fd;
2832 fd1 = get_sock_fd( s, 0, NULL );
2833 break;
2836 if ( fd0 != -1 )
2838 err = WS2_register_async_shutdown( s, fd0, ws2m_sd_read );
2839 if ( err )
2841 release_sock_fd( s, fd0 );
2842 goto error;
2845 if ( fd1 != -1 )
2847 err = WS2_register_async_shutdown( s, fd1, ws2m_sd_write );
2848 if ( err )
2850 release_sock_fd( s, fd1 );
2851 goto error;
2855 else /* non-overlapped mode */
2857 if ( shutdown( fd, how ) )
2859 err = wsaErrno();
2860 release_sock_fd( s, fd );
2861 goto error;
2863 release_sock_fd( s, fd );
2866 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2867 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2868 return 0;
2870 error:
2871 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2872 WSASetLastError( err );
2873 return SOCKET_ERROR;
2876 /***********************************************************************
2877 * socket (WS2_32.23)
2879 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2881 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2883 return WSASocketA( af, type, protocol, NULL, 0,
2884 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
2888 /***********************************************************************
2889 * gethostbyaddr (WS2_32.51)
2891 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
2893 struct WS_hostent *retval = NULL;
2894 struct hostent* host;
2896 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2897 char *extrabuf;
2898 int ebufsize=1024;
2899 struct hostent hostentry;
2900 int locerr=ENOBUFS;
2901 host = NULL;
2902 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2903 while(extrabuf) {
2904 int res = gethostbyaddr_r(addr, len, type,
2905 &hostentry, extrabuf, ebufsize, &host, &locerr);
2906 if( res != ERANGE) break;
2907 ebufsize *=2;
2908 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2910 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2911 #else
2912 EnterCriticalSection( &csWSgetXXXbyYYY );
2913 host = gethostbyaddr(addr, len, type);
2914 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2915 #endif
2916 if( host != NULL ) retval = WS_dup_he(host);
2917 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2918 HeapFree(GetProcessHeap(),0,extrabuf);
2919 #else
2920 LeaveCriticalSection( &csWSgetXXXbyYYY );
2921 #endif
2922 TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
2923 return retval;
2926 /***********************************************************************
2927 * gethostbyname (WS2_32.52)
2929 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2931 struct WS_hostent *retval = NULL;
2932 struct hostent* host;
2933 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2934 char *extrabuf;
2935 int ebufsize=1024;
2936 struct hostent hostentry;
2937 int locerr = ENOBUFS;
2938 #endif
2939 char buf[100];
2940 if( !name) {
2941 name = buf;
2942 if( gethostname( buf, 100) == -1) {
2943 SetLastError( WSAENOBUFS); /* appropriate ? */
2944 return retval;
2947 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2948 host = NULL;
2949 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2950 while(extrabuf) {
2951 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2952 if( res != ERANGE) break;
2953 ebufsize *=2;
2954 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2956 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2957 #else
2958 EnterCriticalSection( &csWSgetXXXbyYYY );
2959 host = gethostbyname(name);
2960 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2961 #endif
2962 if (host) retval = WS_dup_he(host);
2963 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2964 HeapFree(GetProcessHeap(),0,extrabuf);
2965 #else
2966 LeaveCriticalSection( &csWSgetXXXbyYYY );
2967 #endif
2968 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2969 return retval;
2973 /***********************************************************************
2974 * getprotobyname (WS2_32.53)
2976 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2978 struct WS_protoent* retval = NULL;
2979 #ifdef HAVE_GETPROTOBYNAME
2980 struct protoent* proto;
2981 EnterCriticalSection( &csWSgetXXXbyYYY );
2982 if( (proto = getprotobyname(name)) != NULL )
2984 retval = WS_dup_pe(proto);
2986 else {
2987 MESSAGE("protocol %s not found; You might want to add "
2988 "this to /etc/protocols\n", debugstr_a(name) );
2989 SetLastError(WSANO_DATA);
2991 LeaveCriticalSection( &csWSgetXXXbyYYY );
2992 #endif
2993 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2994 return retval;
2998 /***********************************************************************
2999 * getprotobynumber (WS2_32.54)
3001 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
3003 struct WS_protoent* retval = NULL;
3004 #ifdef HAVE_GETPROTOBYNUMBER
3005 struct protoent* proto;
3006 EnterCriticalSection( &csWSgetXXXbyYYY );
3007 if( (proto = getprotobynumber(number)) != NULL )
3009 retval = WS_dup_pe(proto);
3011 else {
3012 MESSAGE("protocol number %d not found; You might want to add "
3013 "this to /etc/protocols\n", number );
3014 SetLastError(WSANO_DATA);
3016 LeaveCriticalSection( &csWSgetXXXbyYYY );
3017 #endif
3018 TRACE("%i ret %p\n", number, retval);
3019 return retval;
3023 /***********************************************************************
3024 * getservbyname (WS2_32.55)
3026 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
3028 struct WS_servent* retval = NULL;
3029 struct servent* serv;
3030 char *name_str;
3031 char *proto_str = NULL;
3033 if (!(name_str = strdup_lower(name))) return NULL;
3035 if (proto && *proto)
3037 if (!(proto_str = strdup_lower(proto)))
3039 HeapFree( GetProcessHeap(), 0, name_str );
3040 return NULL;
3044 EnterCriticalSection( &csWSgetXXXbyYYY );
3045 serv = getservbyname(name_str, proto_str);
3046 if( serv != NULL )
3048 retval = WS_dup_se(serv);
3050 else SetLastError(WSANO_DATA);
3051 LeaveCriticalSection( &csWSgetXXXbyYYY );
3052 HeapFree( GetProcessHeap(), 0, proto_str );
3053 HeapFree( GetProcessHeap(), 0, name_str );
3054 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
3055 return retval;
3058 /***********************************************************************
3059 * freeaddrinfo (WS2_32.@)
3061 void WINAPI WS_freeaddrinfo(struct WS_addrinfo *res)
3063 while (res) {
3064 struct WS_addrinfo *next;
3066 HeapFree(GetProcessHeap(),0,res->ai_canonname);
3067 HeapFree(GetProcessHeap(),0,res->ai_addr);
3068 next = res->ai_next;
3069 HeapFree(GetProcessHeap(),0,res);
3070 res = next;
3074 /* helper functions for getaddrinfo() */
3075 static int convert_aiflag_w2u(int winflags) {
3076 int i, unixflags = 0;
3078 for (i=0;ws_aiflag_map[i][0];i++) {
3079 if (ws_aiflag_map[i][0] & winflags) {
3080 unixflags |= ws_aiflag_map[i][1];
3081 winflags &= ~ws_aiflag_map[i][0];
3084 if (winflags)
3085 FIXME("Unhandled windows AI_xxx flags %x\n", winflags);
3086 return unixflags;
3089 static int convert_aiflag_u2w(int unixflags) {
3090 int i, winflags = 0;
3092 for (i=0;ws_aiflag_map[i][0];i++) {
3093 if (ws_aiflag_map[i][1] & unixflags) {
3094 winflags |= ws_aiflag_map[i][0];
3095 unixflags &= ~ws_aiflag_map[i][1];
3098 if (unixflags) /* will warn usually */
3099 WARN("Unhandled UNIX AI_xxx flags %x\n", unixflags);
3100 return winflags;
3103 static int convert_eai_u2w(int unixret) {
3104 int i;
3106 for (i=0;ws_eai_map[i][0];i++)
3107 if (ws_eai_map[i][0] == unixret)
3108 return ws_eai_map[i][1];
3109 return unixret;
3112 /***********************************************************************
3113 * getaddrinfo (WS2_32.@)
3115 int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const ADDRINFOA *hints, ADDRINFOA **res)
3117 #if HAVE_GETADDRINFO
3118 struct addrinfo *unixaires = NULL;
3119 int result;
3120 struct addrinfo unixhints, *punixhints = NULL;
3121 CHAR *node = NULL, *serv = NULL;
3123 if (nodename)
3124 if (!(node = strdup_lower(nodename))) return WSA_NOT_ENOUGH_MEMORY;
3126 if (servname) {
3127 if (!(serv = strdup_lower(servname))) {
3128 HeapFree(GetProcessHeap(), 0, node);
3129 return WSA_NOT_ENOUGH_MEMORY;
3133 if (hints) {
3134 punixhints = &unixhints;
3136 memset(&unixhints, 0, sizeof(unixhints));
3137 punixhints->ai_flags = convert_aiflag_w2u(hints->ai_flags);
3138 punixhints->ai_family = convert_af_w2u(hints->ai_family);
3139 punixhints->ai_socktype = convert_socktype_w2u(hints->ai_socktype);
3140 punixhints->ai_protocol = convert_proto_w2u(hints->ai_protocol);
3143 /* getaddrinfo(3) is thread safe, no need to wrap in CS */
3144 result = getaddrinfo(nodename, servname, punixhints, &unixaires);
3146 TRACE("%s, %s %p -> %p %d\n", nodename, servname, hints, res, result);
3148 HeapFree(GetProcessHeap(), 0, node);
3149 HeapFree(GetProcessHeap(), 0, serv);
3151 if (!result) {
3152 struct addrinfo *xuai = unixaires;
3153 struct WS_addrinfo **xai = res;
3155 *xai = NULL;
3156 while (xuai) {
3157 struct WS_addrinfo *ai = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo));
3158 int len;
3160 if (!ai)
3161 goto outofmem;
3163 *xai = ai;xai = &ai->ai_next;
3164 ai->ai_flags = convert_aiflag_u2w(xuai->ai_flags);
3165 ai->ai_family = convert_af_u2w(xuai->ai_family);
3166 ai->ai_socktype = convert_socktype_u2w(xuai->ai_socktype);
3167 ai->ai_protocol = convert_proto_u2w(xuai->ai_protocol);
3168 if (xuai->ai_canonname) {
3169 TRACE("canon name - %s\n",debugstr_a(xuai->ai_canonname));
3170 ai->ai_canonname = HeapAlloc(GetProcessHeap(),0,strlen(xuai->ai_canonname)+1);
3171 if (!ai->ai_canonname)
3172 goto outofmem;
3173 strcpy(ai->ai_canonname,xuai->ai_canonname);
3175 len = xuai->ai_addrlen;
3176 ai->ai_addr = HeapAlloc(GetProcessHeap(),0,len);
3177 if (!ai->ai_addr)
3178 goto outofmem;
3179 ai->ai_addrlen = len;
3180 do {
3181 int winlen = ai->ai_addrlen;
3183 if (!ws_sockaddr_u2ws(xuai->ai_addr, xuai->ai_addrlen, ai->ai_addr, &winlen)) {
3184 ai->ai_addrlen = winlen;
3185 break;
3187 len = 2*len;
3188 ai->ai_addr = HeapReAlloc(GetProcessHeap(),0,ai->ai_addr,len);
3189 if (!ai->ai_addr)
3190 goto outofmem;
3191 ai->ai_addrlen = len;
3192 } while (1);
3193 xuai = xuai->ai_next;
3195 freeaddrinfo(unixaires);
3196 } else {
3197 result = convert_eai_u2w(result);
3199 return result;
3201 outofmem:
3202 if (*res) WS_freeaddrinfo(*res);
3203 if (unixaires) freeaddrinfo(unixaires);
3204 *res = NULL;
3205 return WSA_NOT_ENOUGH_MEMORY;
3206 #else
3207 FIXME("getaddrinfo() failed, not found during buildtime.\n");
3208 return EAI_FAIL;
3209 #endif
3212 /***********************************************************************
3213 * GetAddrInfoW (WS2_32.@)
3215 int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hints, ADDRINFOW **res)
3217 FIXME("empty stub!\n");
3218 return EAI_FAIL;
3221 /***********************************************************************
3222 * getservbyport (WS2_32.56)
3224 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
3226 struct WS_servent* retval = NULL;
3227 #ifdef HAVE_GETSERVBYPORT
3228 struct servent* serv;
3229 char *proto_str = NULL;
3231 if (proto && *proto)
3233 if (!(proto_str = strdup_lower(proto))) return NULL;
3235 EnterCriticalSection( &csWSgetXXXbyYYY );
3236 if( (serv = getservbyport(port, proto_str)) != NULL ) {
3237 retval = WS_dup_se(serv);
3239 else SetLastError(WSANO_DATA);
3240 LeaveCriticalSection( &csWSgetXXXbyYYY );
3241 HeapFree( GetProcessHeap(), 0, proto_str );
3242 #endif
3243 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
3244 return retval;
3248 /***********************************************************************
3249 * gethostname (WS2_32.57)
3251 int WINAPI WS_gethostname(char *name, int namelen)
3253 TRACE("name %p, len %d\n", name, namelen);
3255 if (gethostname(name, namelen) == 0)
3257 TRACE("<- '%s'\n", name);
3258 return 0;
3260 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
3261 TRACE("<- ERROR !\n");
3262 return SOCKET_ERROR;
3266 /* ------------------------------------- Windows sockets extensions -- *
3268 * ------------------------------------------------------------------- */
3270 /***********************************************************************
3271 * WSAEnumNetworkEvents (WS2_32.36)
3273 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
3275 int ret;
3277 TRACE("%08x, hEvent %p, lpEvent %p\n", s, hEvent, lpEvent );
3279 SERVER_START_REQ( get_socket_event )
3281 req->handle = SOCKET2HANDLE(s);
3282 req->service = TRUE;
3283 req->c_event = hEvent;
3284 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
3285 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
3287 SERVER_END_REQ;
3288 if (!ret) return 0;
3289 SetLastError(WSAEINVAL);
3290 return SOCKET_ERROR;
3293 /***********************************************************************
3294 * WSAEventSelect (WS2_32.39)
3296 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, long lEvent)
3298 int ret;
3300 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
3302 SERVER_START_REQ( set_socket_event )
3304 req->handle = SOCKET2HANDLE(s);
3305 req->mask = lEvent;
3306 req->event = hEvent;
3307 req->window = 0;
3308 req->msg = 0;
3309 ret = wine_server_call( req );
3311 SERVER_END_REQ;
3312 if (!ret) return 0;
3313 SetLastError(WSAEINVAL);
3314 return SOCKET_ERROR;
3317 /**********************************************************************
3318 * WSAGetOverlappedResult (WS2_32.40)
3320 BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
3321 LPDWORD lpcbTransfer, BOOL fWait,
3322 LPDWORD lpdwFlags )
3324 DWORD r;
3326 TRACE( "socket %04x ovl %p trans %p, wait %d flags %p\n",
3327 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
3329 if ( lpOverlapped == NULL )
3331 ERR( "Invalid pointer\n" );
3332 WSASetLastError(WSA_INVALID_PARAMETER);
3333 return FALSE;
3336 if ( fWait )
3338 if (lpOverlapped->hEvent)
3339 while ( WaitForSingleObjectEx(lpOverlapped->hEvent,
3340 INFINITE, TRUE) == STATUS_USER_APC );
3341 else /* busy loop */
3342 while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
3343 Sleep( 10 );
3346 else if ( lpOverlapped->Internal == STATUS_PENDING )
3348 /* Wait in order to give APCs a chance to run. */
3349 /* This is cheating, so we must set the event again in case of success -
3350 it may be a non-manual reset event. */
3351 while ( (r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
3352 if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent )
3353 NtSetEvent( lpOverlapped->hEvent, NULL );
3356 if ( lpcbTransfer )
3357 *lpcbTransfer = lpOverlapped->InternalHigh;
3359 if ( lpdwFlags )
3360 *lpdwFlags = lpOverlapped->u.s.Offset;
3362 switch ( lpOverlapped->Internal )
3364 case STATUS_SUCCESS:
3365 return TRUE;
3366 case STATUS_PENDING:
3367 WSASetLastError( WSA_IO_INCOMPLETE );
3368 if (fWait) ERR("PENDING status after waiting!\n");
3369 return FALSE;
3370 default:
3371 WSASetLastError( NtStatusToWSAError( lpOverlapped->Internal ));
3372 return FALSE;
3377 /***********************************************************************
3378 * WSAAsyncSelect (WS2_32.101)
3380 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, long lEvent)
3382 int ret;
3384 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3386 SERVER_START_REQ( set_socket_event )
3388 req->handle = SOCKET2HANDLE(s);
3389 req->mask = lEvent;
3390 req->event = 0;
3391 req->window = hWnd;
3392 req->msg = uMsg;
3393 ret = wine_server_call( req );
3395 SERVER_END_REQ;
3396 if (!ret) return 0;
3397 SetLastError(WSAEINVAL);
3398 return SOCKET_ERROR;
3401 /***********************************************************************
3402 * WSACreateEvent (WS2_32.31)
3405 WSAEVENT WINAPI WSACreateEvent(void)
3407 /* Create a manual-reset event, with initial state: unsignaled */
3408 TRACE("\n");
3410 return CreateEventW(NULL, TRUE, FALSE, NULL);
3413 /***********************************************************************
3414 * WSACloseEvent (WS2_32.29)
3417 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3419 TRACE ("event=%p\n", event);
3421 return CloseHandle(event);
3424 /***********************************************************************
3425 * WSASocketA (WS2_32.78)
3428 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3429 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3430 GROUP g, DWORD dwFlags)
3432 INT len;
3433 WSAPROTOCOL_INFOW info;
3435 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3436 af, type, protocol, lpProtocolInfo, g, dwFlags);
3438 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
3440 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
3441 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3442 info.szProtocol, WSAPROTOCOL_LEN + 1);
3444 if (!len)
3446 WSASetLastError( WSAEINVAL);
3447 return SOCKET_ERROR;
3450 return WSASocketW(af, type, protocol, &info, g, dwFlags);
3453 /***********************************************************************
3454 * WSASocketW (WS2_32.79)
3457 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
3458 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3459 GROUP g, DWORD dwFlags)
3461 SOCKET ret;
3464 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
3465 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3468 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3469 af, type, protocol, lpProtocolInfo, g, dwFlags );
3471 /* hack for WSADuplicateSocket */
3472 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3473 ret = lpProtocolInfo->dwCatalogEntryId;
3474 TRACE("\tgot duplicate %04x\n", ret);
3475 return ret;
3478 /* check and convert the socket family */
3479 af = convert_af_w2u(af);
3480 if (af == -1)
3482 FIXME("Unsupported socket family %d!\n", af);
3483 SetLastError(WSAEAFNOSUPPORT);
3484 return INVALID_SOCKET;
3487 /* check the socket type */
3488 type = convert_socktype_w2u(type);
3489 if (type == -1)
3491 SetLastError(WSAESOCKTNOSUPPORT);
3492 return INVALID_SOCKET;
3495 /* check the protocol type */
3496 if ( protocol < 0 ) /* don't support negative values */
3498 SetLastError(WSAEPROTONOSUPPORT);
3499 return INVALID_SOCKET;
3502 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3503 switch(protocol)
3505 case IPPROTO_TCP:
3506 if (type == SOCK_STREAM) { af = AF_INET; break; }
3507 case IPPROTO_UDP:
3508 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3509 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3512 SERVER_START_REQ( create_socket )
3514 req->family = af;
3515 req->type = type;
3516 req->protocol = protocol;
3517 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3518 req->flags = dwFlags;
3519 req->inherit = TRUE;
3520 set_error( wine_server_call( req ) );
3521 ret = HANDLE2SOCKET( reply->handle );
3523 SERVER_END_REQ;
3524 if (ret)
3526 TRACE("\tcreated %04x\n", ret );
3527 return ret;
3530 if (GetLastError() == WSAEACCES) /* raw socket denied */
3532 if (type == SOCK_RAW)
3533 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3534 else
3535 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3536 SetLastError(WSAESOCKTNOSUPPORT);
3539 WARN("\t\tfailed!\n");
3540 return INVALID_SOCKET;
3543 /***********************************************************************
3544 * WSAJoinLeaf (WS2_32.58)
3547 SOCKET WINAPI WSAJoinLeaf(
3548 SOCKET s,
3549 const struct WS_sockaddr *addr,
3550 int addrlen,
3551 LPWSABUF lpCallerData,
3552 LPWSABUF lpCalleeData,
3553 LPQOS lpSQOS,
3554 LPQOS lpGQOS,
3555 DWORD dwFlags)
3557 FIXME("stub.\n");
3558 return INVALID_SOCKET;
3561 /***********************************************************************
3562 * __WSAFDIsSet (WS2_32.151)
3564 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3566 int i = set->fd_count;
3568 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3570 while (i--)
3571 if (set->fd_array[i] == s) return 1;
3572 return 0;
3575 /***********************************************************************
3576 * WSAIsBlocking (WINSOCK.114)
3577 * WSAIsBlocking (WS2_32.114)
3579 BOOL WINAPI WSAIsBlocking(void)
3581 /* By default WinSock should set all its sockets to non-blocking mode
3582 * and poll in PeekMessage loop when processing "blocking" ones. This
3583 * function is supposed to tell if the program is in this loop. Our
3584 * blocking calls are truly blocking so we always return FALSE.
3586 * Note: It is allowed to call this function without prior WSAStartup().
3589 TRACE("\n");
3590 return FALSE;
3593 /***********************************************************************
3594 * WSACancelBlockingCall (WINSOCK.113)
3595 * WSACancelBlockingCall (WS2_32.113)
3597 INT WINAPI WSACancelBlockingCall(void)
3599 TRACE("\n");
3600 return 0;
3603 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
3605 FIXME("How was this called?\n");
3606 return x();
3610 /***********************************************************************
3611 * WSASetBlockingHook (WS2_32.109)
3613 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3615 FARPROC prev = blocking_hook;
3616 blocking_hook = lpBlockFunc;
3617 TRACE("hook %p\n", lpBlockFunc);
3618 return prev;
3622 /***********************************************************************
3623 * WSAUnhookBlockingHook (WS2_32.110)
3625 INT WINAPI WSAUnhookBlockingHook(void)
3627 blocking_hook = WSA_DefaultBlockingHook;
3628 return 0;
3632 /* ----------------------------------- end of API stuff */
3634 /* ----------------------------------- helper functions -
3636 * TODO: Merge WS_dup_..() stuff into one function that
3637 * would operate with a generic structure containing internal
3638 * pointers (via a template of some kind).
3641 static int list_size(char** l, int item_size)
3643 int i,j = 0;
3644 if(l)
3645 { for(i=0;l[i];i++)
3646 j += (item_size) ? item_size : strlen(l[i]) + 1;
3647 j += (i + 1) * sizeof(char*); }
3648 return j;
3651 static int list_dup(char** l_src, char** l_to, int item_size)
3653 char *p;
3654 int i;
3656 for (i = 0; l_src[i]; i++) ;
3657 p = (char *)(l_to + i + 1);
3658 for (i = 0; l_src[i]; i++)
3660 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3661 memcpy(p, l_src[i], count);
3662 l_to[i] = p;
3663 p += count;
3665 l_to[i] = NULL;
3666 return p - (char *)l_to;
3669 /* ----- hostent */
3671 /* duplicate hostent entry
3672 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3673 * Dito for protoent and servent.
3675 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
3677 char *p;
3678 struct WS_hostent *p_to;
3680 int size = (sizeof(*p_he) +
3681 strlen(p_he->h_name) + 1 +
3682 list_size(p_he->h_aliases, 0) +
3683 list_size(p_he->h_addr_list, p_he->h_length));
3685 if (!(p_to = check_buffer_he(size))) return NULL;
3686 p_to->h_addrtype = p_he->h_addrtype;
3687 p_to->h_length = p_he->h_length;
3689 p = (char *)(p_to + 1);
3690 p_to->h_name = p;
3691 strcpy(p, p_he->h_name);
3692 p += strlen(p) + 1;
3694 p_to->h_aliases = (char **)p;
3695 p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
3697 p_to->h_addr_list = (char **)p;
3698 list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
3699 return p_to;
3702 /* ----- protoent */
3704 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
3706 char *p;
3707 struct WS_protoent *p_to;
3709 int size = (sizeof(*p_pe) +
3710 strlen(p_pe->p_name) + 1 +
3711 list_size(p_pe->p_aliases, 0));
3713 if (!(p_to = check_buffer_pe(size))) return NULL;
3714 p_to->p_proto = p_pe->p_proto;
3716 p = (char *)(p_to + 1);
3717 p_to->p_name = p;
3718 strcpy(p, p_pe->p_name);
3719 p += strlen(p) + 1;
3721 p_to->p_aliases = (char **)p;
3722 list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
3723 return p_to;
3726 /* ----- servent */
3728 static struct WS_servent *WS_dup_se(const struct servent* p_se)
3730 char *p;
3731 struct WS_servent *p_to;
3733 int size = (sizeof(*p_se) +
3734 strlen(p_se->s_proto) + 1 +
3735 strlen(p_se->s_name) + 1 +
3736 list_size(p_se->s_aliases, 0));
3738 if (!(p_to = check_buffer_se(size))) return NULL;
3739 p_to->s_port = p_se->s_port;
3741 p = (char *)(p_to + 1);
3742 p_to->s_name = p;
3743 strcpy(p, p_se->s_name);
3744 p += strlen(p) + 1;
3746 p_to->s_proto = p;
3747 strcpy(p, p_se->s_proto);
3748 p += strlen(p) + 1;
3750 p_to->s_aliases = (char **)p;
3751 list_dup(p_se->s_aliases, p_to->s_aliases, 0);
3752 return p_to;
3755 /* ----------------------------------- error handling */
3757 UINT wsaErrno(void)
3759 int loc_errno = errno;
3760 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3762 switch(loc_errno)
3764 case EINTR: return WSAEINTR;
3765 case EBADF: return WSAEBADF;
3766 case EPERM:
3767 case EACCES: return WSAEACCES;
3768 case EFAULT: return WSAEFAULT;
3769 case EINVAL: return WSAEINVAL;
3770 case EMFILE: return WSAEMFILE;
3771 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3772 case EINPROGRESS: return WSAEINPROGRESS;
3773 case EALREADY: return WSAEALREADY;
3774 case ENOTSOCK: return WSAENOTSOCK;
3775 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3776 case EMSGSIZE: return WSAEMSGSIZE;
3777 case EPROTOTYPE: return WSAEPROTOTYPE;
3778 case ENOPROTOOPT: return WSAENOPROTOOPT;
3779 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3780 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3781 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3782 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3783 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3784 case EADDRINUSE: return WSAEADDRINUSE;
3785 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3786 case ENETDOWN: return WSAENETDOWN;
3787 case ENETUNREACH: return WSAENETUNREACH;
3788 case ENETRESET: return WSAENETRESET;
3789 case ECONNABORTED: return WSAECONNABORTED;
3790 case EPIPE:
3791 case ECONNRESET: return WSAECONNRESET;
3792 case ENOBUFS: return WSAENOBUFS;
3793 case EISCONN: return WSAEISCONN;
3794 case ENOTCONN: return WSAENOTCONN;
3795 case ESHUTDOWN: return WSAESHUTDOWN;
3796 case ETOOMANYREFS: return WSAETOOMANYREFS;
3797 case ETIMEDOUT: return WSAETIMEDOUT;
3798 case ECONNREFUSED: return WSAECONNREFUSED;
3799 case ELOOP: return WSAELOOP;
3800 case ENAMETOOLONG: return WSAENAMETOOLONG;
3801 case EHOSTDOWN: return WSAEHOSTDOWN;
3802 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3803 case ENOTEMPTY: return WSAENOTEMPTY;
3804 #ifdef EPROCLIM
3805 case EPROCLIM: return WSAEPROCLIM;
3806 #endif
3807 #ifdef EUSERS
3808 case EUSERS: return WSAEUSERS;
3809 #endif
3810 #ifdef EDQUOT
3811 case EDQUOT: return WSAEDQUOT;
3812 #endif
3813 #ifdef ESTALE
3814 case ESTALE: return WSAESTALE;
3815 #endif
3816 #ifdef EREMOTE
3817 case EREMOTE: return WSAEREMOTE;
3818 #endif
3820 /* just in case we ever get here and there are no problems */
3821 case 0: return 0;
3822 default:
3823 WARN("Unknown errno %d!\n", loc_errno);
3824 return WSAEOPNOTSUPP;
3828 UINT wsaHerrno(int loc_errno)
3831 WARN("h_errno %d.\n", loc_errno);
3833 switch(loc_errno)
3835 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3836 case TRY_AGAIN: return WSATRY_AGAIN;
3837 case NO_RECOVERY: return WSANO_RECOVERY;
3838 case NO_DATA: return WSANO_DATA;
3839 case ENOBUFS: return WSAENOBUFS;
3841 case 0: return 0;
3842 default:
3843 WARN("Unknown h_errno %d!\n", loc_errno);
3844 return WSAEOPNOTSUPP;
3849 /***********************************************************************
3850 * WSARecv (WS2_32.67)
3852 int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3853 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3854 LPWSAOVERLAPPED lpOverlapped,
3855 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3857 return WSARecvFrom(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3858 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3861 /***********************************************************************
3862 * WSARecvFrom (WS2_32.69)
3864 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3865 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3866 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3867 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3870 unsigned int i;
3871 int n, fd, err = WSAENOTSOCK, flags, ret;
3872 struct iovec* iovec;
3873 struct ws2_async *wsa;
3874 IO_STATUS_BLOCK* iosb;
3876 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3877 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3878 (lpFromlen ? *lpFromlen : -1L),
3879 lpOverlapped, lpCompletionRoutine);
3881 fd = get_sock_fd( s, GENERIC_READ, &flags );
3882 TRACE( "fd=%d, flags=%x\n", fd, flags );
3884 if (fd == -1) return SOCKET_ERROR;
3886 if (flags & FD_FLAG_RECV_SHUTDOWN)
3888 WSASetLastError( WSAESHUTDOWN );
3889 goto err_close;
3892 iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3893 if ( !iovec )
3895 err = WSAEFAULT;
3896 goto err_close;
3899 for (i = 0; i < dwBufferCount; i++)
3901 iovec[i].iov_base = lpBuffers[i].buf;
3902 iovec[i].iov_len = lpBuffers[i].len;
3905 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3907 wsa = WS2_make_async( s, fd, ws2m_read, iovec, dwBufferCount,
3908 lpFlags, lpFrom, lpFromlen,
3909 lpOverlapped, lpCompletionRoutine, &iosb );
3911 if ( !wsa )
3913 err = WSAEFAULT;
3914 goto err_free;
3917 if ( ( ret = ws2_queue_async( wsa, iosb )) )
3919 err = NtStatusToWSAError( ret );
3921 if ( !lpOverlapped )
3922 HeapFree( GetProcessHeap(), 0, iosb );
3923 HeapFree( GetProcessHeap(), 0, wsa );
3924 goto err_free;
3927 /* Try immediate completion */
3928 if ( lpOverlapped )
3930 if ( WSAGetOverlappedResult( s, lpOverlapped,
3931 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3932 return 0;
3934 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
3935 goto error;
3938 WSASetLastError( WSA_IO_PENDING );
3939 return SOCKET_ERROR;
3942 if ( _is_blocking(s) )
3944 /* block here */
3945 /* FIXME: OOB and exceptfds? */
3946 int timeout = GET_RCVTIMEO(fd);
3947 if( !do_block(fd, POLLIN, timeout)) {
3948 err = WSAETIMEDOUT;
3949 /* a timeout is not fatal */
3950 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3951 goto err_free;
3955 n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3956 if ( n == -1 )
3958 err = wsaErrno();
3959 goto err_free;
3962 TRACE(" -> %i bytes\n", n);
3963 *lpNumberOfBytesRecvd = n;
3965 HeapFree(GetProcessHeap(), 0, iovec);
3966 release_sock_fd( s, fd );
3967 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3969 return 0;
3971 err_free:
3972 HeapFree(GetProcessHeap(), 0, iovec);
3974 err_close:
3975 release_sock_fd( s, fd );
3977 error:
3978 WARN(" -> ERROR %d\n", err);
3979 WSASetLastError( err );
3980 return SOCKET_ERROR;
3983 /***********************************************************************
3984 * WSCInstallProvider (WS2_32.88)
3986 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3987 LPCWSTR lpszProviderDllPath,
3988 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3989 DWORD dwNumberOfEntries,
3990 LPINT lpErrno )
3992 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3993 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3994 dwNumberOfEntries, lpErrno);
3995 *lpErrno = 0;
3996 return 0;
4000 /***********************************************************************
4001 * WSCDeinstallProvider (WS2_32.83)
4003 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
4005 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
4006 *lpErrno = 0;
4007 return 0;
4011 /***********************************************************************
4012 * WSAAccept (WS2_32.26)
4014 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
4015 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
4018 int ret = 0, size = 0;
4019 WSABUF CallerId, CallerData, CalleeId, CalleeData;
4020 /* QOS SQOS, GQOS; */
4021 GROUP g;
4022 SOCKET cs;
4023 SOCKADDR src_addr, dst_addr;
4025 TRACE("Socket %04x, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
4026 s, addr, addrlen, lpfnCondition, dwCallbackData);
4029 size = sizeof(src_addr);
4030 cs = WS_accept(s, &src_addr, &size);
4032 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
4034 CallerId.buf = (char *)&src_addr;
4035 CallerId.len = sizeof(src_addr);
4037 CallerData.buf = NULL;
4038 CallerData.len = (ULONG)NULL;
4040 WS_getsockname(cs, &dst_addr, &size);
4042 CalleeId.buf = (char *)&dst_addr;
4043 CalleeId.len = sizeof(dst_addr);
4046 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
4047 &CalleeId, &CalleeData, &g, dwCallbackData);
4049 switch (ret)
4051 case CF_ACCEPT:
4052 if (addr && addrlen)
4053 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
4054 return cs;
4055 case CF_DEFER:
4056 SERVER_START_REQ( set_socket_deferred )
4058 req->handle = SOCKET2HANDLE(s);
4059 req->deferred = SOCKET2HANDLE(cs);
4060 if ( !wine_server_call_err ( req ) )
4062 SetLastError( WSATRY_AGAIN );
4063 WS_closesocket( cs );
4066 SERVER_END_REQ;
4067 return SOCKET_ERROR;
4068 case CF_REJECT:
4069 WS_closesocket(cs);
4070 SetLastError(WSAECONNREFUSED);
4071 return SOCKET_ERROR;
4072 default:
4073 FIXME("Unknown return type from Condition function\n");
4074 SetLastError(WSAENOTSOCK);
4075 return SOCKET_ERROR;
4079 /***********************************************************************
4080 * WSADuplicateSocketA (WS2_32.32)
4082 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
4084 HANDLE hProcess;
4086 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4087 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4088 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
4089 /* I don't know what the real Windoze does next, this is a hack */
4090 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
4091 * the target use the global duplicate, or we could copy a reference to us to the structure
4092 * and let the target duplicate it from us, but let's do it as simple as possible */
4093 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4094 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
4095 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4096 0, FALSE, DUPLICATE_SAME_ACCESS);
4097 CloseHandle(hProcess);
4098 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4099 return 0;
4102 /***********************************************************************
4103 * WSADuplicateSocketW (WS2_32.33)
4105 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
4107 HANDLE hProcess;
4109 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4111 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4112 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4113 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
4114 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4115 0, FALSE, DUPLICATE_SAME_ACCESS);
4116 CloseHandle(hProcess);
4117 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4118 return 0;
4121 /***********************************************************************
4122 * WSAInstallServiceClassA (WS2_32.48)
4124 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
4126 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
4127 WSASetLastError(WSAEACCES);
4128 return SOCKET_ERROR;
4131 /***********************************************************************
4132 * WSAInstallServiceClassW (WS2_32.49)
4134 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
4136 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
4137 WSASetLastError(WSAEACCES);
4138 return SOCKET_ERROR;
4141 /***********************************************************************
4142 * WSARemoveServiceClass (WS2_32.70)
4144 int WINAPI WSARemoveServiceClass(LPGUID info)
4146 FIXME("Request to remove service %p\n",info);
4147 WSASetLastError(WSATYPE_NOT_FOUND);
4148 return SOCKET_ERROR;
4151 /***********************************************************************
4152 * WSAStringToAddressA (WS2_32.80)
4154 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
4155 INT AddressFamily,
4156 LPWSAPROTOCOL_INFOA lpProtocolInfo,
4157 LPSOCKADDR lpAddress,
4158 LPINT lpAddressLength)
4160 INT res=0;
4161 struct in_addr inetaddr;
4162 LPSTR workBuffer=NULL,ptrPort;
4164 TRACE( "(%s, %x, %p, %p, %p)\n", AddressString, AddressFamily, lpProtocolInfo,
4165 lpAddress, lpAddressLength );
4167 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
4169 if (AddressString)
4171 workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 );
4172 if (workBuffer)
4174 strcpy(workBuffer,AddressString);
4175 switch (AddressFamily)
4177 case AF_INET:
4178 /* caller wants to know the size of the socket buffer */
4179 if (*lpAddressLength < sizeof(SOCKADDR_IN))
4181 *lpAddressLength = sizeof(SOCKADDR_IN);
4182 res = WSAEFAULT;
4184 else
4186 /* caller wants to translate an AdressString into a SOCKADDR */
4187 if (lpAddress)
4189 memset(lpAddress,0,sizeof(SOCKADDR_IN));
4190 ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET;
4191 ptrPort = strchr(workBuffer,':');
4192 if (ptrPort)
4194 ((LPSOCKADDR_IN)lpAddress)->sin_port = (u_short)atoi(ptrPort+1);
4195 *ptrPort = '\0';
4197 else
4198 ((LPSOCKADDR_IN)lpAddress)->sin_port = 0;
4199 if (inet_aton(workBuffer, &inetaddr) > 0)
4201 ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr;
4202 res = 0;
4204 else
4205 res = WSAEINVAL;
4208 if (lpProtocolInfo)
4209 FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n",
4210 AddressString, AddressFamily,
4211 lpProtocolInfo, lpAddress, lpAddressLength);
4213 break;
4214 default:
4215 FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n",
4216 AddressString, AddressFamily,
4217 lpProtocolInfo, lpAddress, lpAddressLength);
4219 HeapFree( GetProcessHeap(), 0, workBuffer );
4221 else
4222 res = WSA_NOT_ENOUGH_MEMORY;
4224 else
4225 res = WSAEINVAL;
4227 if (!res) return 0;
4228 WSASetLastError(res);
4229 return SOCKET_ERROR;
4232 /***********************************************************************
4233 * WSAStringToAddressW (WS2_32.81)
4235 * Does anybody know if this functions allows to use hebrew/arabic/chinese... digits?
4236 * If this should be the case, it would be required to map these digits
4237 * to Unicode digits (0-9) using FoldString first.
4239 INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
4240 INT AddressFamily,
4241 LPWSAPROTOCOL_INFOW lpProtocolInfo,
4242 LPSOCKADDR lpAddress,
4243 LPINT lpAddressLength)
4245 INT sBuffer,res=0;
4246 LPSTR workBuffer=NULL;
4247 WSAPROTOCOL_INFOA infoA;
4248 LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
4250 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
4251 lpAddress, lpAddressLength );
4253 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
4255 /* if ProtocolInfo is available - convert to ANSI variant */
4256 if (lpProtocolInfo)
4258 lpProtoInfoA = &infoA;
4259 memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
4261 if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
4262 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
4264 WSASetLastError( WSAEINVAL);
4265 return SOCKET_ERROR;
4269 if (AddressString)
4271 /* Translate AddressString to ANSI code page - assumes that only
4272 standard digits 0-9 are used with this API call */
4273 sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
4274 workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
4276 if (workBuffer)
4278 WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
4279 res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
4280 lpAddress,lpAddressLength);
4281 HeapFree( GetProcessHeap(), 0, workBuffer );
4282 return res;
4284 else
4285 res = WSA_NOT_ENOUGH_MEMORY;
4287 else
4288 res = WSAEINVAL;
4290 WSASetLastError(res);
4291 return SOCKET_ERROR;
4294 /***********************************************************************
4295 * WSAAddressToStringA (WS2_32.27)
4297 * See WSAAddressToStringW
4299 INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
4300 LPWSAPROTOCOL_INFOA info, LPSTR string,
4301 LPDWORD lenstr )
4303 INT size;
4304 CHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
4305 CHAR *p;
4307 TRACE( "(%p, %ld, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
4309 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
4310 if (!string || !lenstr) return SOCKET_ERROR;
4312 /* sin_family is garanteed to be the first u_short */
4313 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
4315 sprintf( buffer, "%u.%u.%u.%u:%u",
4316 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
4317 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
4318 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
4319 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
4320 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
4322 p = strchr( buffer, ':' );
4323 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
4325 size = strlen( buffer );
4327 if (*lenstr < size)
4329 *lenstr = size;
4330 WSASetLastError(WSAEFAULT);
4331 return SOCKET_ERROR;
4334 strcpy( string, buffer );
4335 return 0;
4338 /***********************************************************************
4339 * WSAAddressToStringW (WS2_32.28)
4341 * Convert a sockaddr address into a readable address string.
4343 * PARAMS
4344 * sockaddr [I] Pointer to a sockaddr structure.
4345 * len [I] Size of the sockaddr structure.
4346 * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional).
4347 * string [I/O] Pointer to a buffer to receive the address string.
4348 * lenstr [I/O] Size of the receive buffer in WCHARs.
4350 * RETURNS
4351 * Success: 0
4352 * Failure: SOCKET_ERROR
4354 * NOTES
4355 * The 'info' parameter is ignored.
4357 * BUGS
4358 * Only supports AF_INET addresses.
4360 INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
4361 LPWSAPROTOCOL_INFOW info, LPWSTR string,
4362 LPDWORD lenstr )
4364 INT size;
4365 WCHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
4366 static const WCHAR format[] = { '%','u','.','%','u','.','%','u','.','%','u',':','%','u',0 };
4367 WCHAR *p;
4369 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
4371 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
4372 if (!string || !lenstr) return SOCKET_ERROR;
4374 /* sin_family is garanteed to be the first u_short */
4375 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
4377 sprintfW( buffer, format,
4378 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
4379 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
4380 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
4381 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
4382 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
4384 p = strchrW( buffer, ':' );
4385 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
4387 size = lstrlenW( buffer );
4389 if (*lenstr < size)
4391 *lenstr = size;
4392 return SOCKET_ERROR;
4395 lstrcpyW( string, buffer );
4396 return 0;
4399 /***********************************************************************
4400 * WSAEnumNameSpaceProvidersA (WS2_32.34)
4402 INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
4404 FIXME( "(%p %p) Stub!\n", len, buffer );
4405 return 0;
4408 /***********************************************************************
4409 * WSAEnumNameSpaceProvidersW (WS2_32.35)
4411 INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
4413 FIXME( "(%p %p) Stub!\n", len, buffer );
4414 return 0;
4417 /***********************************************************************
4418 * WSAGetQOSByName (WS2_32.41)
4420 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
4422 FIXME( "(0x%04x %p %p) Stub!\n", s, lpQOSName, lpQOS );
4423 return FALSE;
4426 /***********************************************************************
4427 * WSAGetServiceClassInfoA (WS2_32.42)
4429 INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
4430 LPWSASERVICECLASSINFOA info )
4432 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4433 len, info );
4434 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4435 return SOCKET_ERROR;
4438 /***********************************************************************
4439 * WSAGetServiceClassInfoW (WS2_32.43)
4441 INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
4442 LPWSASERVICECLASSINFOW info )
4444 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4445 len, info );
4446 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4447 return SOCKET_ERROR;
4450 /***********************************************************************
4451 * WSAGetServiceClassNameByClassIdA (WS2_32.44)
4453 INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
4455 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4456 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4457 return SOCKET_ERROR;
4460 /***********************************************************************
4461 * WSAGetServiceClassNameByClassIdW (WS2_32.45)
4463 INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
4465 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4466 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4467 return SOCKET_ERROR;
4470 /***********************************************************************
4471 * WSALookupServiceBeginA (WS2_32.59)
4473 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
4474 DWORD dwControlFlags,
4475 LPHANDLE lphLookup)
4477 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4478 lphLookup);
4479 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4480 return SOCKET_ERROR;
4483 /***********************************************************************
4484 * WSALookupServiceBeginW (WS2_32.60)
4486 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
4487 DWORD dwControlFlags,
4488 LPHANDLE lphLookup)
4490 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4491 lphLookup);
4492 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4493 return SOCKET_ERROR;
4496 /***********************************************************************
4497 * WSALookupServiceBeginW (WS2_32.61)
4499 INT WINAPI WSALookupServiceEnd( HANDLE lookup )
4501 FIXME("(%p) Stub!\n", lookup );
4502 return 0;
4505 /***********************************************************************
4506 * WSALookupServiceNextA (WS2_32.62)
4508 INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
4510 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4511 return 0;
4514 /***********************************************************************
4515 * WSALookupServiceNextW (WS2_32.63)
4517 INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
4519 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4520 return 0;
4523 /***********************************************************************
4524 * WSANtohl (WS2_32.64)
4526 INT WINAPI WSANtohl( SOCKET s, u_long netlong, u_long* lphostlong )
4528 TRACE( "(0x%04x 0x%08lx %p)\n", s, netlong, lphostlong );
4530 if (!lphostlong) return WSAEFAULT;
4532 *lphostlong = ntohl( netlong );
4533 return 0;
4536 /***********************************************************************
4537 * WSANtohs (WS2_32.65)
4539 INT WINAPI WSANtohs( SOCKET s, u_short netshort, u_short* lphostshort )
4541 TRACE( "(0x%04x 0x%08x %p)\n", s, netshort, lphostshort );
4543 if (!lphostshort) return WSAEFAULT;
4545 *lphostshort = ntohs( netshort );
4546 return 0;
4549 /***********************************************************************
4550 * WSAProviderConfigChange (WS2_32.66)
4552 INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
4553 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4555 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
4556 return SOCKET_ERROR;
4559 /***********************************************************************
4560 * WSARecvDisconnect (WS2_32.68)
4562 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
4564 TRACE( "(0x%04x %p)\n", s, disconnectdata );
4566 return WS_shutdown( s, 0 );
4569 /***********************************************************************
4570 * WSASetServiceA (WS2_32.76)
4572 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
4574 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4575 return 0;
4578 /***********************************************************************
4579 * WSASetServiceW (WS2_32.77)
4581 INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
4583 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4584 return 0;
4587 /***********************************************************************
4588 * WSCEnableNSProvider (WS2_32.84)
4590 INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
4592 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
4593 return 0;
4596 /***********************************************************************
4597 * WSCGetProviderPath (WS2_32.86)
4599 INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errcode )
4601 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errcode );
4603 if (!errcode || !provider || !len) return WSAEFAULT;
4605 *errcode = WSAEINVAL;
4606 return SOCKET_ERROR;
4609 /***********************************************************************
4610 * WSCInstallNameSpace (WS2_32.87)
4612 INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
4613 DWORD version, LPGUID provider )
4615 FIXME( "(%s %s 0x%08lx 0x%08lx %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
4616 namespace, version, debugstr_guid(provider) );
4617 return 0;
4620 /***********************************************************************
4621 * WSCUnInstallNameSpace (WS2_32.89)
4623 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
4625 FIXME("(%p) Stub!\n", lpProviderId);
4626 return NO_ERROR;
4629 /***********************************************************************
4630 * WSCWriteProviderOrder (WS2_32.91)
4632 INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
4634 FIXME("(%p 0x%08lx) Stub!\n", entry, number);
4635 return 0;