Add a test case for scroll APIs, fix a few bugs spotted by it.
[wine.git] / dlls / winsock / socket.c
blobcfbf49fff1c708ae4e85d4390d8286097a16898f
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.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * NOTE: If you make any changes to fix a particular app, make sure
22 * they don't break something else like Netscape or telnet and ftp
23 * clients and servers (www.winsite.com got a lot of those).
26 #include "config.h"
27 #include "wine/port.h"
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #ifdef HAVE_SYS_IPC_H
34 # include <sys/ipc.h>
35 #endif
36 #ifdef HAVE_SYS_IOCTL_H
37 # include <sys/ioctl.h>
38 #endif
39 #ifdef HAVE_SYS_FILIO_H
40 # include <sys/filio.h>
41 #endif
42 #ifdef HAVE_SYS_SOCKIO_H
43 # include <sys/sockio.h>
44 #endif
46 #if defined(__EMX__)
47 # include <sys/so_ioctl.h>
48 #endif
50 #ifdef HAVE_SYS_PARAM_H
51 # include <sys/param.h>
52 #endif
54 #ifdef HAVE_SYS_MSG_H
55 # include <sys/msg.h>
56 #endif
57 #ifdef HAVE_SYS_WAIT_H
58 # include <sys/wait.h>
59 #endif
60 #ifdef HAVE_SYS_UIO_H
61 # include <sys/uio.h>
62 #endif
63 #ifdef HAVE_SYS_SOCKET_H
64 #include <sys/socket.h>
65 #endif
66 #ifdef HAVE_NETINET_IN_H
67 # include <netinet/in.h>
68 #endif
69 #ifdef HAVE_NETINET_TCP_H
70 # include <netinet/tcp.h>
71 #endif
72 #ifdef HAVE_ARPA_INET_H
73 # include <arpa/inet.h>
74 #endif
75 #include <ctype.h>
76 #include <fcntl.h>
77 #include <errno.h>
78 #ifdef HAVE_SYS_ERRNO_H
79 #include <sys/errno.h>
80 #endif
81 #ifdef HAVE_NETDB_H
82 #include <netdb.h>
83 #endif
84 #ifdef HAVE_UNISTD_H
85 # include <unistd.h>
86 #endif
87 #include <stdlib.h>
88 #ifdef HAVE_ARPA_NAMESER_H
89 # include <arpa/nameser.h>
90 #endif
91 #ifdef HAVE_RESOLV_H
92 # include <resolv.h>
93 #endif
94 #ifdef HAVE_NET_IF_H
95 # include <net/if.h>
96 #endif
97 #ifdef HAVE_IPX_GNU
98 # include <netipx/ipx.h>
99 # define HAVE_IPX
100 #endif
101 #ifdef HAVE_IPX_LINUX
102 # include <asm/types.h>
103 # include <linux/ipx.h>
104 # define HAVE_IPX
105 #endif
107 #ifdef HAVE_SYS_POLL_H
108 # include <sys/poll.h>
109 #endif
110 #ifdef HAVE_SYS_TIME_H
111 # include <sys/time.h>
112 #endif
114 #define NONAMELESSUNION
115 #define NONAMELESSSTRUCT
116 #include "windef.h"
117 #include "winbase.h"
118 #include "wingdi.h"
119 #include "winuser.h"
120 #include "winerror.h"
121 #include "winsock2.h"
122 #include "mswsock.h"
123 #include "ws2tcpip.h"
124 #include "wsipx.h"
125 #include "winnt.h"
126 #include "iphlpapi.h"
127 #include "thread.h"
128 #include "wine/server.h"
129 #include "wine/debug.h"
131 #ifdef __FreeBSD__
132 # define sipx_network sipx_addr.x_net
133 # define sipx_node sipx_addr.x_host.c_host
134 #endif /* __FreeBSD__ */
136 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
138 /* critical section to protect some non-rentrant net function */
139 extern CRITICAL_SECTION csWSgetXXXbyYYY;
141 inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
143 if (!a) return "(nil)";
144 return wine_dbg_sprintf("{ family %d, address %s, port %d }",
145 ((struct sockaddr_in *)a)->sin_family,
146 inet_ntoa(((struct sockaddr_in *)a)->sin_addr),
147 ntohs(((struct sockaddr_in *)a)->sin_port));
150 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
151 #define SOCKET2HANDLE(s) ((HANDLE)(s))
152 #define HANDLE2SOCKET(h) ((SOCKET)(h))
154 /****************************************************************
155 * Async IO declarations
156 ****************************************************************/
157 #include "async.h"
159 static DWORD ws2_async_get_count (const struct async_private *ovp);
160 static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
161 static void ws2_async_cleanup ( struct async_private *ovp );
163 static struct async_ops ws2_async_ops =
165 ws2_async_get_count,
166 ws2_async_call_completion,
167 ws2_async_cleanup
170 static struct async_ops ws2_nocomp_async_ops =
172 ws2_async_get_count,
173 NULL, /* call_completion */
174 ws2_async_cleanup
177 typedef struct ws2_async
179 async_private async;
180 LPWSAOVERLAPPED user_overlapped;
181 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
182 struct iovec *iovec;
183 int n_iovecs;
184 struct WS_sockaddr *addr;
185 union {
186 int val; /* for send operations */
187 int *ptr; /* for recv operations */
188 } addrlen;
189 DWORD flags;
190 } ws2_async;
192 /****************************************************************/
194 /* ----------------------------------- internal data */
196 /* ws_... struct conversion flags */
198 typedef struct /* WSAAsyncSelect() control struct */
200 HANDLE service, event, sock;
201 HWND hWnd;
202 UINT uMsg;
203 LONG lEvent;
204 } ws_select_info;
206 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
207 #define WS_MAX_UDP_DATAGRAM 1024
208 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
210 static struct WS_hostent *he_buffer; /* typecast for Win32 ws_hostent */
211 static struct WS_servent *se_buffer; /* typecast for Win32 ws_servent */
212 static struct WS_protoent *pe_buffer; /* typecast for Win32 ws_protoent */
213 static INT num_startup; /* reference counter */
214 static FARPROC blocking_hook = WSA_DefaultBlockingHook;
216 /* function prototypes */
217 static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
218 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
219 static struct WS_servent *WS_dup_se(const struct servent* p_se);
221 int WSAIOCTL_GetInterfaceCount(void);
222 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
224 UINT wsaErrno(void);
225 UINT wsaHerrno(int errnr);
227 #define MAP_OPTION(opt) { WS_##opt, opt }
229 static const int ws_sock_map[][2] =
231 MAP_OPTION( SO_DEBUG ),
232 MAP_OPTION( SO_REUSEADDR ),
233 MAP_OPTION( SO_KEEPALIVE ),
234 MAP_OPTION( SO_DONTROUTE ),
235 MAP_OPTION( SO_BROADCAST ),
236 MAP_OPTION( SO_LINGER ),
237 MAP_OPTION( SO_OOBINLINE ),
238 MAP_OPTION( SO_SNDBUF ),
239 MAP_OPTION( SO_RCVBUF ),
240 MAP_OPTION( SO_ERROR ),
241 MAP_OPTION( SO_TYPE ),
242 #ifdef SO_RCVTIMEO
243 MAP_OPTION( SO_RCVTIMEO ),
244 #endif
245 #ifdef SO_SNDTIMEO
246 MAP_OPTION( SO_SNDTIMEO ),
247 #endif
248 { 0, 0 }
251 static const int ws_tcp_map[][2] =
253 #ifdef TCP_NODELAY
254 MAP_OPTION( TCP_NODELAY ),
255 #endif
256 { 0, 0 }
259 static const int ws_ip_map[][2] =
261 MAP_OPTION( IP_MULTICAST_IF ),
262 MAP_OPTION( IP_MULTICAST_TTL ),
263 MAP_OPTION( IP_MULTICAST_LOOP ),
264 MAP_OPTION( IP_ADD_MEMBERSHIP ),
265 MAP_OPTION( IP_DROP_MEMBERSHIP ),
266 MAP_OPTION( IP_OPTIONS ),
267 #ifdef IP_HDRINCL
268 MAP_OPTION( IP_HDRINCL ),
269 #endif
270 MAP_OPTION( IP_TOS ),
271 MAP_OPTION( IP_TTL ),
272 { 0, 0 }
275 static DWORD opentype_tls_index = TLS_OUT_OF_INDEXES; /* TLS index for SO_OPENTYPE flag */
277 inline static DWORD NtStatusToWSAError ( const DWORD status )
279 /* We only need to cover the status codes set by server async request handling */
280 DWORD wserr;
281 switch ( status )
283 case STATUS_SUCCESS: wserr = 0; break;
284 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
285 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
286 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
287 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
288 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
289 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
290 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
291 default:
292 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
293 /* It is not a NT status code but a winsock error */
294 wserr = status;
295 else
297 wserr = RtlNtStatusToDosError( status );
298 FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
301 return wserr;
304 /* set last error code from NT status without mapping WSA errors */
305 inline static unsigned int set_error( unsigned int err )
307 if (err)
309 err = NtStatusToWSAError ( err );
310 SetLastError( err );
312 return err;
315 inline static int get_sock_fd( SOCKET s, DWORD access, int *flags )
317 int fd;
318 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, NULL, flags ) ))
319 return -1;
320 return fd;
323 inline static void release_sock_fd( SOCKET s, int fd )
325 wine_server_release_fd( SOCKET2HANDLE(s), fd );
328 static void _enable_event( HANDLE s, unsigned int event,
329 unsigned int sstate, unsigned int cstate )
331 SERVER_START_REQ( enable_socket_event )
333 req->handle = s;
334 req->mask = event;
335 req->sstate = sstate;
336 req->cstate = cstate;
337 wine_server_call( req );
339 SERVER_END_REQ;
342 static int _is_blocking(SOCKET s)
344 int ret;
345 SERVER_START_REQ( get_socket_event )
347 req->handle = SOCKET2HANDLE(s);
348 req->service = FALSE;
349 req->c_event = 0;
350 wine_server_call( req );
351 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
353 SERVER_END_REQ;
354 return ret;
357 static unsigned int _get_sock_mask(SOCKET s)
359 unsigned int ret;
360 SERVER_START_REQ( get_socket_event )
362 req->handle = SOCKET2HANDLE(s);
363 req->service = FALSE;
364 req->c_event = 0;
365 wine_server_call( req );
366 ret = reply->mask;
368 SERVER_END_REQ;
369 return ret;
372 static void _sync_sock_state(SOCKET s)
374 /* do a dummy wineserver request in order to let
375 the wineserver run through its select loop once */
376 (void)_is_blocking(s);
379 static int _get_sock_error(SOCKET s, unsigned int bit)
381 int events[FD_MAX_EVENTS];
383 SERVER_START_REQ( get_socket_event )
385 req->handle = SOCKET2HANDLE(s);
386 req->service = FALSE;
387 req->c_event = 0;
388 wine_server_set_reply( req, events, sizeof(events) );
389 wine_server_call( req );
391 SERVER_END_REQ;
392 return events[bit];
395 static void WINSOCK_DeleteIData(void)
397 /* delete scratch buffers */
399 if (he_buffer) HeapFree( GetProcessHeap(), 0, he_buffer );
400 if (se_buffer) HeapFree( GetProcessHeap(), 0, se_buffer );
401 if (pe_buffer) HeapFree( GetProcessHeap(), 0, pe_buffer );
402 he_buffer = NULL;
403 se_buffer = NULL;
404 pe_buffer = NULL;
405 num_startup = 0;
408 /***********************************************************************
409 * DllMain (WS2_32.init)
411 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
413 TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
414 switch (fdwReason) {
415 case DLL_PROCESS_ATTACH:
416 DisableThreadLibraryCalls(hInstDLL);
417 opentype_tls_index = TlsAlloc();
418 break;
419 case DLL_PROCESS_DETACH:
420 TlsFree( opentype_tls_index );
421 WINSOCK_DeleteIData();
422 break;
424 return TRUE;
427 /***********************************************************************
428 * convert_sockopt()
430 * Converts socket flags from Windows format.
431 * Return 1 if converted, 0 if not (error).
433 static int convert_sockopt(INT *level, INT *optname)
435 int i;
436 switch (*level)
438 case WS_SOL_SOCKET:
439 *level = SOL_SOCKET;
440 for(i=0; ws_sock_map[i][0]; i++)
442 if( ws_sock_map[i][0] == *optname )
444 *optname = ws_sock_map[i][1];
445 return 1;
448 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
449 break;
450 case WS_IPPROTO_TCP:
451 *level = IPPROTO_TCP;
452 for(i=0; ws_tcp_map[i][0]; i++)
454 if ( ws_tcp_map[i][0] == *optname )
456 *optname = ws_tcp_map[i][1];
457 return 1;
460 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
461 break;
462 case WS_IPPROTO_IP:
463 *level = IPPROTO_IP;
464 for(i=0; ws_ip_map[i][0]; i++)
466 if (ws_ip_map[i][0] == *optname )
468 *optname = ws_ip_map[i][1];
469 return 1;
472 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
473 break;
474 default: FIXME("Unimplemented or unknown socket level\n");
476 return 0;
479 static inline BOOL is_timeout_option( int optname )
481 #ifdef SO_RCVTIMEO
482 if (optname == SO_RCVTIMEO) return TRUE;
483 #endif
484 #ifdef SO_SNDTIMEO
485 if (optname == SO_SNDTIMEO) return TRUE;
486 #endif
487 return FALSE;
490 /* ----------------------------------- Per-thread info (or per-process?) */
492 static char *strdup_lower(const char *str)
494 int i;
495 char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
497 if (ret)
499 for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
500 ret[i] = 0;
502 else SetLastError(WSAENOBUFS);
503 return ret;
506 static fd_set* fd_set_import( fd_set* fds, const WS_fd_set* wsfds, int access, int* highfd, int lfd[] )
508 /* translate Winsock fd set into local fd set */
509 if( wsfds )
511 int i;
513 FD_ZERO(fds);
514 for( i = 0; i < wsfds->fd_count; i++ )
516 int s = wsfds->fd_array[i];
517 int fd = get_sock_fd( s, access, NULL );
518 if (fd != -1)
520 lfd[ i ] = fd;
521 if( fd > *highfd ) *highfd = fd;
522 FD_SET(fd, fds);
524 else lfd[ i ] = -1;
526 return fds;
528 return NULL;
531 inline static int sock_error_p(int s)
533 unsigned int optval, optlen;
535 optlen = sizeof(optval);
536 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
537 if (optval) WARN("\t[%i] error: %d\n", s, optval);
538 return optval != 0;
541 static int fd_set_export( const fd_set* fds, fd_set* exceptfds, WS_fd_set* wsfds, int lfd[] )
543 int num_err = 0;
545 /* translate local fd set into Winsock fd set, adding
546 * errors to exceptfds (only if app requested it) */
548 if( wsfds )
550 int i, j, count = wsfds->fd_count;
552 for( i = 0, j = 0; i < count; i++ )
554 int fd = lfd[i];
555 SOCKET s = wsfds->fd_array[i];
556 if (fd == -1) continue;
557 if( FD_ISSET(fd, fds) )
559 if ( exceptfds && sock_error_p(fd) )
561 FD_SET(fd, exceptfds);
562 num_err++;
564 else wsfds->fd_array[j++] = s;
566 release_sock_fd( s, fd );
568 wsfds->fd_count = j;
570 return num_err;
573 static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
575 if ( wsfds )
577 int i;
579 for( i = 0; i < wsfds->fd_count; i++ )
580 if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
581 wsfds->fd_count = 0;
585 /* utility: given an fd, will block until one of the events occurs */
586 static inline int do_block( int fd, int events )
588 struct pollfd pfd;
590 pfd.fd = fd;
591 pfd.events = events;
592 poll(&pfd, 1, -1);
593 return pfd.revents;
597 /* ----------------------------------- API -----
599 * Init / cleanup / error checking.
602 /***********************************************************************
603 * WSAStartup (WS2_32.115)
605 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
607 TRACE("verReq=%x\n", wVersionRequested);
609 if (LOBYTE(wVersionRequested) < 1)
610 return WSAVERNOTSUPPORTED;
612 if (!lpWSAData) return WSAEINVAL;
614 num_startup++;
616 /* that's the whole of the negotiation for now */
617 lpWSAData->wVersion = wVersionRequested;
618 /* return winsock information */
619 lpWSAData->wHighVersion = 0x0202;
620 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
621 strcpy(lpWSAData->szSystemStatus, "Running" );
622 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
623 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
624 /* don't do anything with lpWSAData->lpVendorInfo */
625 /* (some apps don't allocate the space for this field) */
627 TRACE("succeeded\n");
628 return 0;
632 /***********************************************************************
633 * WSACleanup (WS2_32.116)
635 INT WINAPI WSACleanup(void)
637 if (num_startup)
639 if (--num_startup > 0) return 0;
640 WINSOCK_DeleteIData();
641 return 0;
643 SetLastError(WSANOTINITIALISED);
644 return SOCKET_ERROR;
648 /***********************************************************************
649 * WSAGetLastError (WINSOCK.111)
650 * WSAGetLastError (WS2_32.111)
652 INT WINAPI WSAGetLastError(void)
654 return GetLastError();
657 /***********************************************************************
658 * WSASetLastError (WS2_32.112)
660 void WINAPI WSASetLastError(INT iError) {
661 SetLastError(iError);
664 static struct WS_hostent *check_buffer_he(int size)
666 static int he_len;
667 if (he_buffer)
669 if (he_len >= size ) return he_buffer;
670 HeapFree( GetProcessHeap(), 0, he_buffer );
672 he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
673 if (!he_buffer) SetLastError(WSAENOBUFS);
674 return he_buffer;
677 static struct WS_servent *check_buffer_se(int size)
679 static int se_len;
680 if (se_buffer)
682 if (se_len >= size ) return se_buffer;
683 HeapFree( GetProcessHeap(), 0, se_buffer );
685 se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
686 if (!se_buffer) SetLastError(WSAENOBUFS);
687 return se_buffer;
690 static struct WS_protoent *check_buffer_pe(int size)
692 static int pe_len;
693 if (pe_buffer)
695 if (pe_len >= size ) return pe_buffer;
696 HeapFree( GetProcessHeap(), 0, pe_buffer );
698 pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
699 if (!pe_buffer) SetLastError(WSAENOBUFS);
700 return pe_buffer;
703 /* ----------------------------------- i/o APIs */
705 #ifdef HAVE_IPX
706 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
707 #else
708 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
709 #endif
712 /**********************************************************************/
714 /* Returns the converted address if successful, NULL if it was too small to
715 * start with. Note that the returned pointer may be the original pointer
716 * if no conversion is necessary.
718 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
720 switch (wsaddr->sa_family)
722 #ifdef HAVE_IPX
723 case WS_AF_IPX:
725 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
726 struct sockaddr_ipx* uipx;
728 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
729 return NULL;
731 *uaddrlen=sizeof(struct sockaddr_ipx);
732 uipx=malloc(*uaddrlen);
733 memset(uipx,0,sizeof(*uipx));
734 uipx->sipx_family=AF_IPX;
735 uipx->sipx_port=wsipx->sa_socket;
736 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
737 * in one go
739 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
740 #ifdef IPX_FRAME_NONE
741 uipx->sipx_type=IPX_FRAME_NONE;
742 #endif
743 return (const struct sockaddr*)uipx;
745 #endif
747 default:
748 if (wsaddrlen<sizeof(struct WS_sockaddr))
749 return NULL;
751 /* No conversion needed, just return the original address */
752 *uaddrlen=wsaddrlen;
753 return (const struct sockaddr*)wsaddr;
755 return NULL;
758 /* Allocates a Unix sockaddr structure to receive the data */
759 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
761 if (wsaddr==NULL)
763 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
765 /* This is not strictly the right thing to do. Hope it works however */
766 *uaddrlen=0;
768 return NULL;
771 if (*wsaddrlen==0)
772 *uaddrlen=0;
773 else
774 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
776 return malloc(*uaddrlen);
779 /* Returns 0 if successful, -1 if the buffer is too small */
780 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
782 int res;
784 switch(uaddr->sa_family)
786 #ifdef HAVE_IPX
787 case AF_IPX:
789 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
790 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
792 res=-1;
793 switch (*wsaddrlen) /* how much can we copy? */
795 default:
796 res=0; /* enough */
797 *wsaddrlen=uaddrlen;
798 wsipx->sa_socket=uipx->sipx_port;
799 /* fall through */
800 case 13:
801 case 12:
802 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
803 /* fall through */
804 case 11:
805 case 10:
806 case 9:
807 case 8:
808 case 7:
809 case 6:
810 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
811 /* fall through */
812 case 5:
813 case 4:
814 case 3:
815 case 2:
816 wsipx->sa_family=WS_AF_IPX;
817 /* fall through */
818 case 1:
819 case 0:
820 /* way too small */
821 break;
824 break;
825 #endif
827 default:
828 /* No conversion needed */
829 memcpy(wsaddr,uaddr,*wsaddrlen);
830 if (*wsaddrlen<uaddrlen) {
831 res=-1;
832 } else {
833 *wsaddrlen=uaddrlen;
834 res=0;
837 return res;
840 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
841 * ws_sockaddr_alloc
843 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
845 if (uaddr!=NULL && uaddr!=(const struct sockaddr*)wsaddr)
846 free((void*)uaddr);
849 /**************************************************************************
850 * Functions for handling overlapped I/O
851 **************************************************************************/
853 static DWORD ws2_async_get_count (const struct async_private *ovp)
855 return ovp->iosb->Information;
858 static void ws2_async_cleanup ( struct async_private *ap )
860 struct ws2_async *as = (struct ws2_async*) ap;
862 TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->async.iosb );
863 if ( !as->user_overlapped )
865 #if 0
866 /* FIXME: I don't think this is really used */
867 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
868 WSACloseEvent ( as->overlapped->hEvent );
869 #endif
870 HeapFree ( GetProcessHeap(), 0, as->async.iosb );
873 if ( as->iovec )
874 HeapFree ( GetProcessHeap(), 0, as->iovec );
876 HeapFree ( GetProcessHeap(), 0, as );
879 static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
881 ws2_async* as = (ws2_async*) data;
883 TRACE ("data: %p\n", as);
885 as->completion_func ( NtStatusToWSAError (as->async.iosb->u.Status),
886 as->async.iosb->Information,
887 as->user_overlapped,
888 as->flags );
889 ws2_async_cleanup ( &as->async );
892 /***********************************************************************
893 * WS2_make_async (INTERNAL)
896 static void WS2_async_recv (async_private *as);
897 static void WS2_async_send (async_private *as);
899 inline static struct ws2_async*
900 WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
901 LPDWORD lpFlags, struct WS_sockaddr *addr,
902 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
903 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
905 struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
907 TRACE ( "wsa %p\n", wsa );
909 if (!wsa)
910 return NULL;
912 wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
913 wsa->async.handle = (HANDLE) s;
914 wsa->async.fd = fd;
915 wsa->async.type = type;
916 switch (type)
918 case ASYNC_TYPE_READ:
919 wsa->flags = *lpFlags;
920 wsa->async.func = WS2_async_recv;
921 wsa->addrlen.ptr = addrlen;
922 break;
923 case ASYNC_TYPE_WRITE:
924 wsa->flags = 0;
925 wsa->async.func = WS2_async_send;
926 wsa->addrlen.val = *addrlen;
927 break;
928 default:
929 ERR ("Invalid async type: %d\n", type);
931 wsa->user_overlapped = lpOverlapped;
932 wsa->completion_func = lpCompletionRoutine;
933 wsa->iovec = iovec;
934 wsa->n_iovecs = dwBufferCount;
935 wsa->addr = addr;
937 if ( lpOverlapped )
939 wsa->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
940 wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
942 else
944 wsa->async.iosb = HeapAlloc ( GetProcessHeap(), 0,
945 sizeof (IO_STATUS_BLOCK) );
946 if ( !wsa->async.iosb )
947 goto error;
948 wsa->async.event = INVALID_HANDLE_VALUE;
951 wsa->async.iosb->Information = 0;
952 TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, iosb %p, uov %p, cfunc %p\n",
953 wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
954 wsa->async.iosb, wsa->user_overlapped, wsa->completion_func );
956 return wsa;
958 error:
959 TRACE ("Error\n");
960 HeapFree ( GetProcessHeap(), 0, wsa );
961 return NULL;
964 /***********************************************************************
965 * WS2_recv (INTERNAL)
967 * Work horse for both synchronous and asynchronous recv() operations.
969 static int WS2_recv ( int fd, struct iovec* iov, int count,
970 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
971 LPDWORD lpFlags )
973 struct msghdr hdr;
974 int n;
975 TRACE ( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
976 fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
978 hdr.msg_name = NULL;
980 if ( lpFrom )
982 hdr.msg_namelen = *lpFromlen;
983 hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
984 if ( !hdr.msg_name )
986 WSASetLastError ( WSAEFAULT );
987 n = -1;
988 goto out;
991 else
992 hdr.msg_namelen = 0;
994 hdr.msg_iov = iov;
995 hdr.msg_iovlen = count;
996 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
997 hdr.msg_accrights = NULL;
998 hdr.msg_accrightslen = 0;
999 #else
1000 hdr.msg_control = NULL;
1001 hdr.msg_controllen = 0;
1002 hdr.msg_flags = 0;
1003 #endif
1005 if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
1007 TRACE ( "recvmsg error %d\n", errno);
1008 goto out;
1011 if ( lpFrom &&
1012 ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
1013 lpFrom, lpFromlen ) != 0 )
1015 /* The from buffer was too small, but we read the data
1016 * anyway. Is that really bad?
1018 WSASetLastError ( WSAEFAULT );
1019 WARN ( "Address buffer too small\n" );
1022 out:
1024 ws_sockaddr_free ( hdr.msg_name, lpFrom );
1025 TRACE ("-> %d\n", n);
1026 return n;
1029 /***********************************************************************
1030 * WS2_async_recv (INTERNAL)
1032 * Handler for overlapped recv() operations.
1034 static void WS2_async_recv ( async_private *as )
1036 ws2_async* wsa = (ws2_async*) as;
1037 int result, err;
1039 TRACE ( "async %p\n", wsa );
1041 if ( wsa->async.iosb->u.Status != STATUS_PENDING )
1043 TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
1044 return;
1047 result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1048 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1050 if (result >= 0)
1052 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1053 wsa->async.iosb->Information = result;
1054 TRACE ( "received %d bytes\n", result );
1055 _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1056 return;
1059 err = wsaErrno ();
1060 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1062 wsa->async.iosb->u.Status = STATUS_PENDING;
1063 _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1064 TRACE ( "still pending\n" );
1066 else
1068 wsa->async.iosb->u.Status = err;
1069 TRACE ( "Error: %x\n", err );
1073 /***********************************************************************
1074 * WS2_send (INTERNAL)
1076 * Work horse for both synchronous and asynchronous send() operations.
1078 static int WS2_send ( int fd, struct iovec* iov, int count,
1079 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1081 struct msghdr hdr;
1082 int n = -1;
1083 TRACE ( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
1084 fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
1086 hdr.msg_name = NULL;
1088 if ( to )
1090 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
1091 if ( !hdr.msg_name )
1093 WSASetLastError ( WSAEFAULT );
1094 goto out;
1097 else
1098 hdr.msg_namelen = 0;
1100 hdr.msg_iov = iov;
1101 hdr.msg_iovlen = count;
1102 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1103 hdr.msg_accrights = NULL;
1104 hdr.msg_accrightslen = 0;
1105 #else
1106 hdr.msg_control = NULL;
1107 hdr.msg_controllen = 0;
1108 hdr.msg_flags = 0;
1109 #endif
1111 n = sendmsg (fd, &hdr, dwFlags);
1113 out:
1114 ws_sockaddr_free ( hdr.msg_name, to );
1115 return n;
1118 /***********************************************************************
1119 * WS2_async_send (INTERNAL)
1121 * Handler for overlapped send() operations.
1123 static void WS2_async_send ( async_private *as )
1125 ws2_async* wsa = (ws2_async*) as;
1126 int result, err;
1128 TRACE ( "async %p\n", wsa );
1130 if ( wsa->async.iosb->u.Status != STATUS_PENDING )
1132 TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
1133 return;
1136 result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1137 wsa->addr, wsa->addrlen.val, wsa->flags );
1139 if (result >= 0)
1141 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1142 wsa->async.iosb->Information = result;
1143 TRACE ( "sent %d bytes\n", result );
1144 _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1145 return;
1148 err = wsaErrno ();
1149 if ( err == WSAEINTR )
1151 wsa->async.iosb->u.Status = STATUS_PENDING;
1152 _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1153 TRACE ( "still pending\n" );
1155 else
1157 /* We set the status to a winsock error code and check for that
1158 later in NtStatusToWSAError () */
1159 wsa->async.iosb->u.Status = err;
1160 TRACE ( "Error: %x\n", err );
1164 /***********************************************************************
1165 * WS2_async_shutdown (INTERNAL)
1167 * Handler for shutdown() operations on overlapped sockets.
1169 static void WS2_async_shutdown ( async_private *as )
1171 ws2_async* wsa = (ws2_async*) as;
1172 int err = 1;
1174 TRACE ( "async %p %d\n", wsa, wsa->async.type );
1175 switch ( wsa->async.type )
1177 case ASYNC_TYPE_READ:
1178 err = shutdown ( wsa->async.fd, 0 );
1179 break;
1180 case ASYNC_TYPE_WRITE:
1181 err = shutdown ( wsa->async.fd, 1 );
1182 break;
1183 default:
1184 ERR ("invalid type: %d\n", wsa->async.type );
1187 if ( err )
1188 wsa->async.iosb->u.Status = wsaErrno ();
1189 else
1190 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1193 /***********************************************************************
1194 * WS2_register_async_shutdown (INTERNAL)
1196 * Helper function for WS_shutdown() on overlapped sockets.
1198 static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
1200 struct ws2_async *wsa;
1201 int ret, err = WSAEFAULT;
1202 DWORD dwflags = 0;
1203 int len = 0;
1204 LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
1206 TRACE ("s %d fd %d type %d\n", s, fd, type);
1207 if (!ovl)
1208 goto out;
1210 ovl->hEvent = WSACreateEvent ();
1211 if ( ovl->hEvent == WSA_INVALID_EVENT )
1212 goto out_free;
1214 wsa = WS2_make_async ( s, fd, type, NULL, 0,
1215 &dwflags, NULL, &len, ovl, NULL );
1216 if ( !wsa )
1217 goto out_close;
1219 /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1220 wsa->user_overlapped = NULL;
1221 wsa->async.func = WS2_async_shutdown;
1222 if ( (ret = register_new_async ( &wsa->async )) )
1224 err = NtStatusToWSAError ( ret );
1225 goto out;
1227 /* Try immediate completion */
1228 while ( WaitForSingleObjectEx ( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1229 return 0;
1231 out_close:
1232 WSACloseEvent ( ovl->hEvent );
1233 out_free:
1234 HeapFree ( GetProcessHeap(), 0, ovl );
1235 out:
1236 return err;
1239 /***********************************************************************
1240 * accept (WS2_32.1)
1242 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1243 int *addrlen32)
1245 SOCKET as;
1247 TRACE("socket %04x\n", s );
1248 if (_is_blocking(s))
1250 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1251 if (fd == -1) return INVALID_SOCKET;
1252 /* block here */
1253 do_block(fd, POLLIN);
1254 _sync_sock_state(s); /* let wineserver notice connection */
1255 release_sock_fd( s, fd );
1256 /* retrieve any error codes from it */
1257 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1258 /* FIXME: care about the error? */
1260 SERVER_START_REQ( accept_socket )
1262 req->lhandle = SOCKET2HANDLE(s);
1263 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1264 req->inherit = TRUE;
1265 set_error( wine_server_call( req ) );
1266 as = HANDLE2SOCKET( reply->handle );
1268 SERVER_END_REQ;
1269 if (as)
1271 if (addr) WS_getpeername(as, addr, addrlen32);
1272 return as;
1274 return INVALID_SOCKET;
1277 /***********************************************************************
1278 * bind (WS2_32.2)
1280 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1282 int fd = get_sock_fd( s, 0, NULL );
1283 int res = SOCKET_ERROR;
1285 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1287 if (fd != -1)
1289 if (!name || !SUPPORTED_PF(name->sa_family))
1291 SetLastError(WSAEAFNOSUPPORT);
1293 else
1295 const struct sockaddr* uaddr;
1296 int uaddrlen;
1298 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1299 if (uaddr == NULL)
1301 SetLastError(WSAEFAULT);
1303 else
1305 if (bind(fd, uaddr, uaddrlen) < 0)
1307 int loc_errno = errno;
1308 WARN("\tfailure - errno = %i\n", errno);
1309 errno = loc_errno;
1310 switch (errno)
1312 case EBADF:
1313 SetLastError(WSAENOTSOCK);
1314 break;
1315 case EADDRNOTAVAIL:
1316 SetLastError(WSAEINVAL);
1317 break;
1318 default:
1319 SetLastError(wsaErrno());
1320 break;
1323 else
1325 res=0; /* success */
1327 ws_sockaddr_free(uaddr,name);
1330 release_sock_fd( s, fd );
1332 return res;
1335 /***********************************************************************
1336 * closesocket (WS2_32.3)
1338 int WINAPI WS_closesocket(SOCKET s)
1340 TRACE("socket %08x\n", s);
1341 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1342 return SOCKET_ERROR;
1345 /***********************************************************************
1346 * connect (WS2_32.4)
1348 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1350 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1352 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1354 if (fd != -1)
1356 const struct sockaddr* uaddr;
1357 int uaddrlen;
1359 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1360 if (uaddr == NULL)
1362 SetLastError(WSAEFAULT);
1364 else
1366 int rc;
1368 rc=connect(fd, uaddr, uaddrlen);
1369 ws_sockaddr_free(uaddr,name);
1370 if (rc == 0)
1371 goto connect_success;
1374 if (errno == EINPROGRESS)
1376 /* tell wineserver that a connection is in progress */
1377 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1378 FD_CONNECT|FD_READ|FD_WRITE,
1379 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1380 if (_is_blocking(s))
1382 int result;
1383 /* block here */
1384 do_block(fd, POLLIN | POLLOUT );
1385 _sync_sock_state(s); /* let wineserver notice connection */
1386 /* retrieve any error codes from it */
1387 result = _get_sock_error(s, FD_CONNECT_BIT);
1388 if (result)
1389 SetLastError(result);
1390 else
1392 goto connect_success;
1395 else
1397 SetLastError(WSAEWOULDBLOCK);
1400 else
1402 SetLastError(wsaErrno());
1404 release_sock_fd( s, fd );
1406 return SOCKET_ERROR;
1408 connect_success:
1409 release_sock_fd( s, fd );
1410 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1411 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1412 FD_CONNECT|FD_WINE_LISTENING);
1413 return 0;
1416 /***********************************************************************
1417 * WSAConnect (WS2_32.30)
1419 int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
1420 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1421 LPQOS lpSQOS, LPQOS lpGQOS )
1423 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1424 FIXME ("unsupported parameters!\n");
1425 return WS_connect ( s, name, namelen );
1429 /***********************************************************************
1430 * getpeername (WS2_32.5)
1432 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1434 int fd;
1435 int res;
1437 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1439 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1440 if( (name == NULL) || (namelen == NULL) )
1442 SetLastError( WSAEFAULT );
1443 return SOCKET_ERROR;
1446 fd = get_sock_fd( s, 0, NULL );
1447 res = SOCKET_ERROR;
1449 if (fd != -1)
1451 struct sockaddr* uaddr;
1452 int uaddrlen;
1454 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1455 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1457 SetLastError(wsaErrno());
1459 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1461 /* The buffer was too small */
1462 SetLastError(WSAEFAULT);
1464 else
1466 res=0;
1468 ws_sockaddr_free(uaddr,name);
1469 release_sock_fd( s, fd );
1471 return res;
1474 /***********************************************************************
1475 * getsockname (WS2_32.6)
1477 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1479 int fd;
1480 int res;
1482 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1484 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1485 if( (name == NULL) || (namelen == NULL) )
1487 SetLastError( WSAEFAULT );
1488 return SOCKET_ERROR;
1491 fd = get_sock_fd( s, 0, NULL );
1492 res = SOCKET_ERROR;
1494 if (fd != -1)
1496 struct sockaddr* uaddr;
1497 int uaddrlen;
1499 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1500 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1502 SetLastError(wsaErrno());
1504 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1506 /* The buffer was too small */
1507 SetLastError(WSAEFAULT);
1509 else
1511 res=0;
1513 release_sock_fd( s, fd );
1515 return res;
1518 /***********************************************************************
1519 * getsockopt (WS2_32.7)
1521 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1522 INT optname, char *optval, INT *optlen)
1524 int fd;
1526 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1527 (int) optname, (int) optval, (int) *optlen);
1528 /* SO_OPENTYPE does not require a valid socket handle. */
1529 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1531 if (!optlen || *optlen < sizeof(int) || !optval)
1533 SetLastError(WSAEFAULT);
1534 return SOCKET_ERROR;
1536 *(int *)optval = (int)TlsGetValue( opentype_tls_index );
1537 *optlen = sizeof(int);
1538 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1539 return 0;
1542 fd = get_sock_fd( s, 0, NULL );
1543 if (fd != -1)
1545 if (!convert_sockopt(&level, &optname)) {
1546 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1547 } else {
1548 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1550 release_sock_fd( s, fd );
1551 return 0;
1553 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1555 release_sock_fd( s, fd );
1557 return SOCKET_ERROR;
1561 /***********************************************************************
1562 * htonl (WINSOCK.8)
1563 * htonl (WS2_32.8)
1565 u_long WINAPI WS_htonl(u_long hostlong)
1567 return htonl(hostlong);
1571 /***********************************************************************
1572 * htons (WINSOCK.9)
1573 * htons (WS2_32.9)
1575 u_short WINAPI WS_htons(u_short hostshort)
1577 return htons(hostshort);
1580 /***********************************************************************
1581 * WSAHtonl (WS2_32.46)
1583 int WINAPI WSAHtonl(SOCKET s, u_long hostlong, u_long *lpnetlong)
1585 FIXME("stub.\n");
1586 return INVALID_SOCKET;
1589 /***********************************************************************
1590 * WSAHtons (WS2_32.47)
1592 int WINAPI WSAHtons(SOCKET s, u_short hostshort, u_short *lpnetshort)
1594 FIXME("stub.\n");
1595 return INVALID_SOCKET;
1599 /***********************************************************************
1600 * inet_addr (WINSOCK.10)
1601 * inet_addr (WS2_32.11)
1603 u_long WINAPI WS_inet_addr(const char *cp)
1605 return inet_addr(cp);
1609 /***********************************************************************
1610 * ntohl (WINSOCK.14)
1611 * ntohl (WS2_32.14)
1613 u_long WINAPI WS_ntohl(u_long netlong)
1615 return ntohl(netlong);
1619 /***********************************************************************
1620 * ntohs (WINSOCK.15)
1621 * ntohs (WS2_32.15)
1623 u_short WINAPI WS_ntohs(u_short netshort)
1625 return ntohs(netshort);
1629 /***********************************************************************
1630 * inet_ntoa (WS2_32.12)
1632 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1634 /* use "buffer for dummies" here because some applications have
1635 * propensity to decode addresses in ws_hostent structure without
1636 * saving them first...
1638 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1640 char* s = inet_ntoa(*((struct in_addr*)&in));
1641 if( s )
1643 strcpy(dbuffer, s);
1644 return dbuffer;
1646 SetLastError(wsaErrno());
1647 return NULL;
1650 /**********************************************************************
1651 * WSAIoctl (WS2_32.50)
1654 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1656 INT WINAPI WSAIoctl (SOCKET s,
1657 DWORD dwIoControlCode,
1658 LPVOID lpvInBuffer,
1659 DWORD cbInBuffer,
1660 LPVOID lpbOutBuffer,
1661 DWORD cbOutBuffer,
1662 LPDWORD lpcbBytesReturned,
1663 LPWSAOVERLAPPED lpOverlapped,
1664 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1666 int fd = get_sock_fd( s, 0, NULL );
1668 if (fd == -1) return SOCKET_ERROR;
1670 switch( dwIoControlCode )
1672 case SIO_GET_INTERFACE_LIST:
1674 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1675 DWORD size, numInt, apiReturn;
1677 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1679 if (!lpbOutBuffer)
1681 release_sock_fd( s, fd );
1682 WSASetLastError(WSAEFAULT);
1683 return SOCKET_ERROR;
1685 if (!lpcbBytesReturned)
1687 release_sock_fd( s, fd );
1688 WSASetLastError(WSAEFAULT);
1689 return SOCKET_ERROR;
1692 apiReturn = GetAdaptersInfo(NULL, &size);
1693 if (apiReturn == ERROR_NO_DATA)
1695 numInt = 0;
1697 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1699 PIP_ADAPTER_INFO table = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(),0,size);
1701 if (table)
1703 if (GetAdaptersInfo(table, &size) == NO_ERROR)
1705 PIP_ADAPTER_INFO ptr;
1707 if (size > cbOutBuffer)
1709 HeapFree(GetProcessHeap(),0,table);
1710 release_sock_fd( s, fd );
1711 WSASetLastError(WSAEFAULT);
1712 return (SOCKET_ERROR);
1714 for (ptr = table, numInt = 0; ptr;
1715 ptr = ptr->Next, intArray++, numInt++)
1717 unsigned int addr, mask, bcast;
1718 struct ifreq ifInfo;
1720 /* Socket Status Flags */
1721 strncpy(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
1722 ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
1723 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1725 ERR ("Error obtaining status flags for socket!\n");
1726 HeapFree(GetProcessHeap(),0,table);
1727 release_sock_fd( s, fd );
1728 WSASetLastError(WSAEINVAL);
1729 return (SOCKET_ERROR);
1731 else
1733 /* set flags; the values of IFF_* are not the same
1734 under Linux and Windows, therefore must generate
1735 new flags */
1736 intArray->iiFlags = 0;
1737 if (ifInfo.ifr_flags & IFF_BROADCAST)
1738 intArray->iiFlags |= WS_IFF_BROADCAST;
1739 #ifdef IFF_POINTOPOINT
1740 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
1741 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
1742 #endif
1743 if (ifInfo.ifr_flags & IFF_LOOPBACK)
1744 intArray->iiFlags |= WS_IFF_LOOPBACK;
1745 if (ifInfo.ifr_flags & IFF_UP)
1746 intArray->iiFlags |= WS_IFF_UP;
1749 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
1750 mask = inet_addr(ptr->IpAddressList.IpMask.String);
1751 bcast = addr | (addr & !mask);
1752 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1753 intArray->iiAddress.AddressIn.sin_port = 0;
1754 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
1755 addr;
1756 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1757 intArray->iiNetmask.AddressIn.sin_port = 0;
1758 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
1759 mask;
1760 intArray->iiBroadcastAddress.AddressIn.sin_family =
1761 AF_INET;
1762 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
1763 intArray->iiBroadcastAddress.AddressIn.sin_addr.
1764 WS_s_addr = bcast;
1767 else
1769 ERR ("Unable to get interface table!\n");
1770 release_sock_fd( s, fd );
1771 HeapFree(GetProcessHeap(),0,table);
1772 WSASetLastError(WSAEINVAL);
1773 return (SOCKET_ERROR);
1775 HeapFree(GetProcessHeap(),0,table);
1777 else
1779 release_sock_fd( s, fd );
1780 WSASetLastError(WSAEINVAL);
1781 return (SOCKET_ERROR);
1784 else
1786 ERR ("Unable to get interface table!\n");
1787 release_sock_fd( s, fd );
1788 WSASetLastError(WSAEINVAL);
1789 return (SOCKET_ERROR);
1791 /* Calculate the size of the array being returned */
1792 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1793 break;
1796 default:
1797 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1798 release_sock_fd( s, fd );
1799 WSASetLastError(WSAEOPNOTSUPP);
1800 return (SOCKET_ERROR);
1803 /* Function executed with no errors */
1804 release_sock_fd( s, fd );
1805 return (0);
1809 /***********************************************************************
1810 * ioctlsocket (WS2_32.10)
1812 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
1814 int fd;
1815 long newcmd = cmd;
1817 TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
1819 switch( cmd )
1821 case WS_FIONREAD:
1822 newcmd=FIONREAD;
1823 break;
1825 case WS_FIONBIO:
1826 if( _get_sock_mask(s) )
1828 /* AsyncSelect()'ed sockets are always nonblocking */
1829 if (*argp) return 0;
1830 SetLastError(WSAEINVAL);
1831 return SOCKET_ERROR;
1833 fd = get_sock_fd( s, 0, NULL );
1834 if (fd != -1)
1836 int ret;
1837 if (*argp)
1839 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
1840 ret = fcntl( fd, F_SETFL, O_NONBLOCK );
1842 else
1844 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
1845 ret = fcntl( fd, F_SETFL, 0 );
1847 release_sock_fd( s, fd );
1848 if (!ret) return 0;
1849 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1851 return SOCKET_ERROR;
1853 case WS_SIOCATMARK:
1854 newcmd=SIOCATMARK;
1855 break;
1857 case WS__IOW('f',125,u_long):
1858 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1859 SetLastError(WSAEINVAL);
1860 return SOCKET_ERROR;
1862 case SIOCGIFBRDADDR:
1863 case SIOCGIFNETMASK:
1864 case SIOCGIFADDR:
1865 /* These don't need any special handling. They are used by
1866 WsControl, and are here to suppress an unecessary warning. */
1867 break;
1869 default:
1870 /* Netscape tries hard to use bogus ioctl 0x667e */
1871 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1872 break;
1875 fd = get_sock_fd( s, 0, NULL );
1876 if (fd != -1)
1878 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1880 release_sock_fd( s, fd );
1881 return 0;
1883 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1884 release_sock_fd( s, fd );
1886 return SOCKET_ERROR;
1889 /***********************************************************************
1890 * listen (WS2_32.13)
1892 int WINAPI WS_listen(SOCKET s, int backlog)
1894 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1896 TRACE("socket %04x, backlog %d\n", s, backlog);
1897 if (fd != -1)
1899 if (listen(fd, backlog) == 0)
1901 release_sock_fd( s, fd );
1902 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
1903 FD_WINE_LISTENING,
1904 FD_CONNECT|FD_WINE_CONNECTED);
1905 return 0;
1907 SetLastError(wsaErrno());
1908 release_sock_fd( s, fd );
1910 return SOCKET_ERROR;
1913 /***********************************************************************
1914 * recv (WS2_32.16)
1916 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
1918 DWORD n, dwFlags = flags;
1919 WSABUF wsabuf;
1921 wsabuf.len = len;
1922 wsabuf.buf = buf;
1924 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
1925 return SOCKET_ERROR;
1926 else
1927 return n;
1930 /***********************************************************************
1931 * recvfrom (WS2_32.17)
1933 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
1934 struct WS_sockaddr *from, int *fromlen)
1936 DWORD n, dwFlags = flags;
1937 WSABUF wsabuf;
1939 wsabuf.len = len;
1940 wsabuf.buf = buf;
1942 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
1943 return SOCKET_ERROR;
1944 else
1945 return n;
1948 /***********************************************************************
1949 * select (WS2_32.18)
1951 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
1952 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
1953 const struct WS_timeval* ws_timeout)
1955 int highfd = 0;
1956 fd_set readfds, writefds, exceptfds;
1957 fd_set *p_read, *p_write, *p_except;
1958 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1959 struct timeval timeout, *timeoutaddr = NULL;
1961 TRACE("read %p, write %p, excp %p timeout %p\n",
1962 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
1964 p_read = fd_set_import(&readfds, ws_readfds, GENERIC_READ, &highfd, readfd);
1965 p_write = fd_set_import(&writefds, ws_writefds, GENERIC_WRITE, &highfd, writefd);
1966 p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
1967 if (ws_timeout)
1969 timeoutaddr = &timeout;
1970 timeout.tv_sec=ws_timeout->tv_sec;
1971 timeout.tv_usec=ws_timeout->tv_usec;
1974 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
1976 fd_set_export(&readfds, p_except, ws_readfds, readfd);
1977 fd_set_export(&writefds, p_except, ws_writefds, writefd);
1979 if (p_except && ws_exceptfds)
1981 int i, j;
1983 for (i = j = 0; i < ws_exceptfds->fd_count; i++)
1985 int fd = exceptfd[i];
1986 SOCKET s = ws_exceptfds->fd_array[i];
1987 if (fd == -1) continue;
1988 if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
1989 release_sock_fd( s, fd );
1991 ws_exceptfds->fd_count = j;
1993 return highfd;
1995 fd_set_unimport(ws_readfds, readfd);
1996 fd_set_unimport(ws_writefds, writefd);
1997 fd_set_unimport(ws_exceptfds, exceptfd);
1999 if( highfd == 0 ) return 0;
2000 SetLastError(wsaErrno());
2001 return SOCKET_ERROR;
2005 /***********************************************************************
2006 * send (WS2_32.19)
2008 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2010 DWORD n;
2011 WSABUF wsabuf;
2013 wsabuf.len = len;
2014 wsabuf.buf = (char*) buf;
2016 if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2017 return SOCKET_ERROR;
2018 else
2019 return n;
2022 /***********************************************************************
2023 * WSASend (WS2_32.72)
2025 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2026 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2027 LPWSAOVERLAPPED lpOverlapped,
2028 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2030 return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2031 NULL, 0, lpOverlapped, lpCompletionRoutine );
2034 /***********************************************************************
2035 * WSASendDisconnect (WS2_32.73)
2037 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2039 return WS_shutdown ( s, SD_SEND );
2043 /***********************************************************************
2044 * WSASendTo (WS2_32.74)
2046 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2047 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2048 const struct WS_sockaddr *to, int tolen,
2049 LPWSAOVERLAPPED lpOverlapped,
2050 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2052 int i, n, fd, err = WSAENOTSOCK, flags, ret;
2053 struct iovec* iovec;
2054 struct ws2_async *wsa;
2056 TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2057 s, lpBuffers, dwBufferCount, dwFlags,
2058 to, tolen, lpOverlapped, lpCompletionRoutine);
2060 fd = get_sock_fd( s, GENERIC_WRITE, &flags );
2061 TRACE ( "fd=%d, flags=%x\n", fd, flags );
2063 if ( fd == -1 ) return SOCKET_ERROR;
2065 if (flags & FD_FLAG_SEND_SHUTDOWN)
2067 WSASetLastError ( WSAESHUTDOWN );
2068 goto err_close;
2071 if ( !lpNumberOfBytesSent )
2073 err = WSAEFAULT;
2074 goto err_close;
2077 iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
2079 if ( !iovec )
2081 err = WSAEFAULT;
2082 goto err_close;
2085 for ( i = 0; i < dwBufferCount; i++ )
2087 iovec[i].iov_base = lpBuffers[i].buf;
2088 iovec[i].iov_len = lpBuffers[i].len;
2091 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2093 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
2094 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2095 lpOverlapped, lpCompletionRoutine );
2096 if ( !wsa )
2098 err = WSAEFAULT;
2099 goto err_free;
2102 if ( ( ret = register_new_async ( &wsa->async )) )
2104 err = NtStatusToWSAError ( ret );
2106 if ( !lpOverlapped )
2107 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
2108 HeapFree ( GetProcessHeap(), 0, wsa );
2109 goto err_free;
2112 /* Try immediate completion */
2113 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
2115 if ( WSAGetOverlappedResult ( s, lpOverlapped,
2116 lpNumberOfBytesSent, FALSE, &dwFlags) )
2117 return 0;
2119 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
2120 goto error;
2123 WSASetLastError ( WSA_IO_PENDING );
2124 return SOCKET_ERROR;
2127 if (_is_blocking(s))
2129 /* FIXME: exceptfds? */
2130 do_block(fd, POLLOUT);
2133 n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2134 if ( n == -1 )
2136 err = wsaErrno();
2137 if ( err == WSAEWOULDBLOCK )
2138 _enable_event (SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2139 goto err_free;
2142 TRACE(" -> %i bytes\n", n);
2143 *lpNumberOfBytesSent = n;
2145 HeapFree ( GetProcessHeap(), 0, iovec );
2146 release_sock_fd( s, fd );
2147 return 0;
2149 err_free:
2150 HeapFree ( GetProcessHeap(), 0, iovec );
2152 err_close:
2153 release_sock_fd( s, fd );
2155 error:
2156 WARN (" -> ERROR %d\n", err);
2157 WSASetLastError (err);
2158 return SOCKET_ERROR;
2161 /***********************************************************************
2162 * sendto (WS2_32.20)
2164 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2165 const struct WS_sockaddr *to, int tolen)
2167 DWORD n;
2168 WSABUF wsabuf;
2170 wsabuf.len = len;
2171 wsabuf.buf = (char*) buf;
2173 if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2174 return SOCKET_ERROR;
2175 else
2176 return n;
2179 /***********************************************************************
2180 * setsockopt (WS2_32.21)
2182 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2183 const char *optval, int optlen)
2185 int fd;
2186 int woptval;
2187 struct linger linger;
2188 struct timeval tval;
2190 TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
2191 s, level, optname, optval, optlen);
2193 /* SO_OPENTYPE does not require a valid socket handle. */
2194 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2196 if (optlen < sizeof(int) || !optval)
2198 SetLastError(WSAEFAULT);
2199 return SOCKET_ERROR;
2201 TlsSetValue( opentype_tls_index, (LPVOID)*(int *)optval );
2202 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2203 return 0;
2206 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2207 * socket. This will either not happen under windows or it is ignored in
2208 * windows (but it works in linux and therefor prevents the game to find
2209 * games outsite the current network) */
2210 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2212 FIXME("Does windows ignore SO_DONTROUTE?\n");
2213 return 0;
2216 /* Is a privileged and useless operation, so we don't. */
2217 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
2219 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2220 return 0;
2223 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2224 /* This is unique to WinSock and takes special conversion */
2225 linger.l_onoff = *((int*)optval) ? 0: 1;
2226 linger.l_linger = 0;
2227 optname=SO_LINGER;
2228 optval = (char*)&linger;
2229 optlen = sizeof(struct linger);
2230 level = SOL_SOCKET;
2232 else
2234 if (!convert_sockopt(&level, &optname)) {
2235 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2236 SetLastError(WSAENOPROTOOPT);
2237 return SOCKET_ERROR;
2239 if (optname == SO_LINGER && optval) {
2240 /* yes, uses unsigned short in both win16/win32 */
2241 linger.l_onoff = ((UINT16*)optval)[0];
2242 linger.l_linger = ((UINT16*)optval)[1];
2243 /* FIXME: what is documented behavior if SO_LINGER optval
2244 is null?? */
2245 optval = (char*)&linger;
2246 optlen = sizeof(struct linger);
2248 else if (optval && optlen < sizeof(int))
2250 woptval= *((INT16 *) optval);
2251 optval= (char*) &woptval;
2252 optlen=sizeof(int);
2254 if (level == SOL_SOCKET && is_timeout_option(optname))
2256 if (optlen == sizeof(UINT32)) {
2257 /* WinSock passes miliseconds instead of struct timeval */
2258 tval.tv_usec = *(PUINT32)optval % 1000;
2259 tval.tv_sec = *(PUINT32)optval / 1000;
2260 /* min of 500 milisec */
2261 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2262 optlen = sizeof(struct timeval);
2263 optval = (char*)&tval;
2264 } else if (optlen == sizeof(struct timeval)) {
2265 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2266 } else {
2267 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2268 return 0;
2271 if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
2273 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2274 return 0;
2279 fd = get_sock_fd( s, 0, NULL );
2280 if (fd == -1) return SOCKET_ERROR;
2282 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2284 release_sock_fd( s, fd );
2285 return 0;
2287 TRACE("Setting socket error, %d\n", wsaErrno());
2288 SetLastError(wsaErrno());
2289 release_sock_fd( s, fd );
2290 return SOCKET_ERROR;
2293 /***********************************************************************
2294 * shutdown (WS2_32.22)
2296 int WINAPI WS_shutdown(SOCKET s, int how)
2298 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2299 unsigned int clear_flags = 0;
2301 fd = get_sock_fd( s, 0, &flags );
2302 TRACE("socket %04x, how %i %x\n", s, how, flags );
2304 if (fd == -1)
2305 return SOCKET_ERROR;
2307 switch( how )
2309 case 0: /* drop receives */
2310 clear_flags |= FD_READ;
2311 break;
2312 case 1: /* drop sends */
2313 clear_flags |= FD_WRITE;
2314 break;
2315 case 2: /* drop all */
2316 clear_flags |= FD_READ|FD_WRITE;
2317 default:
2318 clear_flags |= FD_WINE_LISTENING;
2321 if ( flags & FD_FLAG_OVERLAPPED ) {
2323 switch ( how )
2325 case SD_RECEIVE:
2326 fd0 = fd;
2327 break;
2328 case SD_SEND:
2329 fd1 = fd;
2330 break;
2331 case SD_BOTH:
2332 default:
2333 fd0 = fd;
2334 fd1 = get_sock_fd ( s, 0, NULL );
2335 break;
2338 if ( fd0 != -1 )
2340 err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
2341 if ( err )
2343 release_sock_fd( s, fd0 );
2344 goto error;
2347 if ( fd1 != -1 )
2349 err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
2350 if ( err )
2352 release_sock_fd( s, fd1 );
2353 goto error;
2357 else /* non-overlapped mode */
2359 if ( shutdown( fd, how ) )
2361 err = wsaErrno ();
2362 release_sock_fd( s, fd );
2363 goto error;
2365 release_sock_fd( s, fd );
2368 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2369 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2370 return 0;
2372 error:
2373 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2374 WSASetLastError ( err );
2375 return SOCKET_ERROR;
2378 /***********************************************************************
2379 * socket (WS2_32.23)
2381 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2383 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2385 return WSASocketA ( af, type, protocol, NULL, 0,
2386 (TlsGetValue(opentype_tls_index) ? 0 : WSA_FLAG_OVERLAPPED) );
2390 /***********************************************************************
2391 * gethostbyaddr (WS2_32.51)
2393 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
2395 struct WS_hostent *retval = NULL;
2396 struct hostent* host;
2398 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2399 char *extrabuf;
2400 int ebufsize=1024;
2401 struct hostent hostentry;
2402 int locerr=ENOBUFS;
2403 host = NULL;
2404 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2405 while(extrabuf) {
2406 int res = gethostbyaddr_r(addr, len, type,
2407 &hostentry, extrabuf, ebufsize, &host, &locerr);
2408 if( res != ERANGE) break;
2409 ebufsize *=2;
2410 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2412 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2413 #else
2414 EnterCriticalSection( &csWSgetXXXbyYYY );
2415 host = gethostbyaddr(addr, len, type);
2416 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2417 #endif
2418 if( host != NULL ) retval = WS_dup_he(host);
2419 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2420 HeapFree(GetProcessHeap(),0,extrabuf);
2421 #else
2422 LeaveCriticalSection( &csWSgetXXXbyYYY );
2423 #endif
2424 TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
2425 return retval;
2428 /***********************************************************************
2429 * gethostbyname (WS2_32.52)
2431 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2433 struct WS_hostent *retval = NULL;
2434 struct hostent* host;
2435 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2436 char *extrabuf;
2437 int ebufsize=1024;
2438 struct hostent hostentry;
2439 int locerr = ENOBUFS;
2440 #endif
2441 char buf[100];
2442 if( !name) {
2443 name = buf;
2444 if( gethostname( buf, 100) == -1) {
2445 SetLastError( WSAENOBUFS); /* appropriate ? */
2446 return retval;
2449 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2450 host = NULL;
2451 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2452 while(extrabuf) {
2453 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2454 if( res != ERANGE) break;
2455 ebufsize *=2;
2456 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2458 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2459 #else
2460 EnterCriticalSection( &csWSgetXXXbyYYY );
2461 host = gethostbyname(name);
2462 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2463 #endif
2464 if (host) retval = WS_dup_he(host);
2465 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2466 HeapFree(GetProcessHeap(),0,extrabuf);
2467 #else
2468 LeaveCriticalSection( &csWSgetXXXbyYYY );
2469 #endif
2470 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2471 return retval;
2475 /***********************************************************************
2476 * getprotobyname (WS2_32.53)
2478 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2480 struct WS_protoent* retval = NULL;
2481 #ifdef HAVE_GETPROTOBYNAME
2482 struct protoent* proto;
2483 EnterCriticalSection( &csWSgetXXXbyYYY );
2484 if( (proto = getprotobyname(name)) != NULL )
2486 retval = WS_dup_pe(proto);
2488 else {
2489 MESSAGE("protocol %s not found; You might want to add "
2490 "this to /etc/protocols\n", debugstr_a(name) );
2491 SetLastError(WSANO_DATA);
2493 LeaveCriticalSection( &csWSgetXXXbyYYY );
2494 #endif
2495 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2496 return retval;
2500 /***********************************************************************
2501 * getprotobynumber (WS2_32.54)
2503 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
2505 struct WS_protoent* retval = NULL;
2506 #ifdef HAVE_GETPROTOBYNUMBER
2507 struct protoent* proto;
2508 EnterCriticalSection( &csWSgetXXXbyYYY );
2509 if( (proto = getprotobynumber(number)) != NULL )
2511 retval = WS_dup_pe(proto);
2513 else {
2514 MESSAGE("protocol number %d not found; You might want to add "
2515 "this to /etc/protocols\n", number );
2516 SetLastError(WSANO_DATA);
2518 LeaveCriticalSection( &csWSgetXXXbyYYY );
2519 #endif
2520 TRACE("%i ret %p\n", number, retval);
2521 return retval;
2525 /***********************************************************************
2526 * getservbyname (WS2_32.55)
2528 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
2530 struct WS_servent* retval = NULL;
2531 struct servent* serv;
2532 char *name_str;
2533 char *proto_str = NULL;
2535 if (!(name_str = strdup_lower(name))) return NULL;
2537 if (proto && *proto)
2539 if (!(proto_str = strdup_lower(proto)))
2541 HeapFree( GetProcessHeap(), 0, name_str );
2542 return NULL;
2546 EnterCriticalSection( &csWSgetXXXbyYYY );
2547 serv = getservbyname(name_str, proto_str);
2548 if( serv != NULL )
2550 retval = WS_dup_se(serv);
2552 else SetLastError(WSANO_DATA);
2553 LeaveCriticalSection( &csWSgetXXXbyYYY );
2554 if (proto_str) HeapFree( GetProcessHeap(), 0, proto_str );
2555 HeapFree( GetProcessHeap(), 0, name_str );
2556 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
2557 return retval;
2561 /***********************************************************************
2562 * getservbyport (WS2_32.56)
2564 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
2566 struct WS_servent* retval = NULL;
2567 #ifdef HAVE_GETSERVBYPORT
2568 struct servent* serv;
2569 char *proto_str = NULL;
2571 if (proto && *proto)
2573 if (!(proto_str = strdup_lower(proto))) return NULL;
2575 EnterCriticalSection( &csWSgetXXXbyYYY );
2576 if( (serv = getservbyport(port, proto_str)) != NULL ) {
2577 retval = WS_dup_se(serv);
2579 else SetLastError(WSANO_DATA);
2580 LeaveCriticalSection( &csWSgetXXXbyYYY );
2581 if (proto_str) HeapFree( GetProcessHeap(), 0, proto_str );
2582 #endif
2583 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
2584 return retval;
2588 /***********************************************************************
2589 * gethostname (WS2_32.57)
2591 int WINAPI WS_gethostname(char *name, int namelen)
2593 TRACE("name %p, len %d\n", name, namelen);
2595 if (gethostname(name, namelen) == 0)
2597 TRACE("<- '%s'\n", name);
2598 return 0;
2600 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2601 TRACE("<- ERROR !\n");
2602 return SOCKET_ERROR;
2606 /* ------------------------------------- Windows sockets extensions -- *
2608 * ------------------------------------------------------------------- */
2610 /***********************************************************************
2611 * WSAEnumNetworkEvents (WS2_32.36)
2613 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2615 int ret;
2617 TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2619 SERVER_START_REQ( get_socket_event )
2621 req->handle = SOCKET2HANDLE(s);
2622 req->service = TRUE;
2623 req->c_event = hEvent;
2624 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
2625 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
2627 SERVER_END_REQ;
2628 if (!ret) return 0;
2629 SetLastError(WSAEINVAL);
2630 return SOCKET_ERROR;
2633 /***********************************************************************
2634 * WSAEventSelect (WS2_32.39)
2636 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2638 int ret;
2640 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
2642 SERVER_START_REQ( set_socket_event )
2644 req->handle = SOCKET2HANDLE(s);
2645 req->mask = lEvent;
2646 req->event = hEvent;
2647 req->window = 0;
2648 req->msg = 0;
2649 ret = wine_server_call( req );
2651 SERVER_END_REQ;
2652 if (!ret) return 0;
2653 SetLastError(WSAEINVAL);
2654 return SOCKET_ERROR;
2657 /**********************************************************************
2658 * WSAGetOverlappedResult (WS2_32.40)
2660 BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
2661 LPDWORD lpcbTransfer, BOOL fWait,
2662 LPDWORD lpdwFlags )
2664 DWORD r;
2666 TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
2667 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
2669 if ( !(lpOverlapped && lpOverlapped->hEvent) )
2671 ERR ( "Invalid pointer\n" );
2672 WSASetLastError (WSA_INVALID_PARAMETER);
2673 return FALSE;
2676 if ( fWait )
2678 while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC );
2680 else if ( lpOverlapped->Internal == STATUS_PENDING )
2682 /* Wait in order to give APCs a chance to run. */
2683 /* This is cheating, so we must set the event again in case of success -
2684 it may be a non-manual reset event. */
2685 while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
2686 if ( r == WAIT_OBJECT_0 )
2687 NtSetEvent ( lpOverlapped->hEvent, NULL );
2690 if ( lpcbTransfer )
2691 *lpcbTransfer = lpOverlapped->InternalHigh;
2693 if ( lpdwFlags )
2694 *lpdwFlags = lpOverlapped->Offset;
2696 switch ( lpOverlapped->Internal )
2698 case STATUS_SUCCESS:
2699 return TRUE;
2700 case STATUS_PENDING:
2701 WSASetLastError ( WSA_IO_INCOMPLETE );
2702 if (fWait) ERR ("PENDING status after waiting!\n");
2703 return FALSE;
2704 default:
2705 WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
2706 return FALSE;
2711 /***********************************************************************
2712 * WSAAsyncSelect (WS2_32.101)
2714 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2716 int ret;
2718 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
2720 SERVER_START_REQ( set_socket_event )
2722 req->handle = SOCKET2HANDLE(s);
2723 req->mask = lEvent;
2724 req->event = 0;
2725 req->window = hWnd;
2726 req->msg = uMsg;
2727 ret = wine_server_call( req );
2729 SERVER_END_REQ;
2730 if (!ret) return 0;
2731 SetLastError(WSAEINVAL);
2732 return SOCKET_ERROR;
2735 /***********************************************************************
2736 * WSACreateEvent (WS2_32.31)
2739 WSAEVENT WINAPI WSACreateEvent(void)
2741 /* Create a manual-reset event, with initial state: unsignealed */
2742 TRACE("\n");
2744 return CreateEventA(NULL, TRUE, FALSE, NULL);
2747 /***********************************************************************
2748 * WSACloseEvent (WS2_32.29)
2751 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2753 TRACE ("event=%p\n", event);
2755 return CloseHandle(event);
2758 /***********************************************************************
2759 * WSASocketA (WS2_32.78)
2762 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2763 LPWSAPROTOCOL_INFOA lpProtocolInfo,
2764 GROUP g, DWORD dwFlags)
2766 SOCKET ret;
2769 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2770 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
2773 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2774 af, type, protocol, lpProtocolInfo, g, dwFlags );
2776 /* hack for WSADuplicateSocket */
2777 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
2778 ret = lpProtocolInfo->dwCatalogEntryId;
2779 TRACE("\tgot duplicate %04x\n", ret);
2780 return ret;
2783 /* check the socket family */
2784 switch(af)
2786 #ifdef HAVE_IPX
2787 case WS_AF_IPX: af = AF_IPX;
2788 #endif
2789 case AF_INET:
2790 case AF_UNSPEC:
2791 break;
2792 default:
2793 SetLastError(WSAEAFNOSUPPORT);
2794 return INVALID_SOCKET;
2797 /* check the socket type */
2798 switch(type)
2800 case WS_SOCK_STREAM:
2801 type=SOCK_STREAM;
2802 break;
2803 case WS_SOCK_DGRAM:
2804 type=SOCK_DGRAM;
2805 break;
2806 case WS_SOCK_RAW:
2807 type=SOCK_RAW;
2808 break;
2809 default:
2810 SetLastError(WSAESOCKTNOSUPPORT);
2811 return INVALID_SOCKET;
2814 /* check the protocol type */
2815 if ( protocol < 0 ) /* don't support negative values */
2817 SetLastError(WSAEPROTONOSUPPORT);
2818 return INVALID_SOCKET;
2821 if ( af == AF_UNSPEC) /* did they not specify the address family? */
2822 switch(protocol)
2824 case IPPROTO_TCP:
2825 if (type == SOCK_STREAM) { af = AF_INET; break; }
2826 case IPPROTO_UDP:
2827 if (type == SOCK_DGRAM) { af = AF_INET; break; }
2828 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2831 SERVER_START_REQ( create_socket )
2833 req->family = af;
2834 req->type = type;
2835 req->protocol = protocol;
2836 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2837 req->flags = dwFlags;
2838 req->inherit = TRUE;
2839 set_error( wine_server_call( req ) );
2840 ret = HANDLE2SOCKET( reply->handle );
2842 SERVER_END_REQ;
2843 if (ret)
2845 TRACE("\tcreated %04x\n", ret );
2846 return ret;
2849 if (GetLastError() == WSAEACCES) /* raw socket denied */
2851 if (type == SOCK_RAW)
2852 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2853 else
2854 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2855 SetLastError(WSAESOCKTNOSUPPORT);
2858 WARN("\t\tfailed!\n");
2859 return INVALID_SOCKET;
2862 /***********************************************************************
2863 * WSAJoinLeaf (WS2_32.58)
2866 SOCKET WINAPI WSAJoinLeaf(
2867 SOCKET s,
2868 const struct WS_sockaddr *addr,
2869 int addrlen,
2870 LPWSABUF lpCallerData,
2871 LPWSABUF lpCalleeData,
2872 LPQOS lpSQOS,
2873 LPQOS lpGQOS,
2874 DWORD dwFlags)
2876 FIXME("stub.\n");
2877 return INVALID_SOCKET;
2880 /***********************************************************************
2881 * __WSAFDIsSet (WS2_32.151)
2883 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
2885 int i = set->fd_count;
2887 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2889 while (i--)
2890 if (set->fd_array[i] == s) return 1;
2891 return 0;
2894 /***********************************************************************
2895 * WSAIsBlocking (WINSOCK.114)
2896 * WSAIsBlocking (WS2_32.114)
2898 BOOL WINAPI WSAIsBlocking(void)
2900 /* By default WinSock should set all its sockets to non-blocking mode
2901 * and poll in PeekMessage loop when processing "blocking" ones. This
2902 * function is supposed to tell if the program is in this loop. Our
2903 * blocking calls are truly blocking so we always return FALSE.
2905 * Note: It is allowed to call this function without prior WSAStartup().
2908 TRACE("\n");
2909 return FALSE;
2912 /***********************************************************************
2913 * WSACancelBlockingCall (WINSOCK.113)
2914 * WSACancelBlockingCall (WS2_32.113)
2916 INT WINAPI WSACancelBlockingCall(void)
2918 TRACE("\n");
2919 return 0;
2922 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
2924 FIXME("How was this called?\n");
2925 return x();
2929 /***********************************************************************
2930 * WSASetBlockingHook (WS2_32.109)
2932 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2934 FARPROC prev = blocking_hook;
2935 blocking_hook = lpBlockFunc;
2936 TRACE("hook %p\n", lpBlockFunc);
2937 return prev;
2941 /***********************************************************************
2942 * WSAUnhookBlockingHook (WS2_32.110)
2944 INT WINAPI WSAUnhookBlockingHook(void)
2946 blocking_hook = WSA_DefaultBlockingHook;
2947 return 0;
2951 /* ----------------------------------- end of API stuff */
2953 /* ----------------------------------- helper functions -
2955 * TODO: Merge WS_dup_..() stuff into one function that
2956 * would operate with a generic structure containing internal
2957 * pointers (via a template of some kind).
2960 static int list_size(char** l, int item_size)
2962 int i,j = 0;
2963 if(l)
2964 { for(i=0;l[i];i++)
2965 j += (item_size) ? item_size : strlen(l[i]) + 1;
2966 j += (i + 1) * sizeof(char*); }
2967 return j;
2970 static int list_dup(char** l_src, char** l_to, int item_size)
2972 char *p;
2973 int i;
2975 for (i = 0; l_src[i]; i++) ;
2976 p = (char *)(l_to + i + 1);
2977 for (i = 0; l_src[i]; i++)
2979 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2980 memcpy(p, l_src[i], count);
2981 l_to[i] = p;
2982 p += count;
2984 l_to[i] = NULL;
2985 return (p - (char *)l_to);
2988 /* ----- hostent */
2990 /* duplicate hostent entry
2991 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
2992 * Dito for protoent and servent.
2994 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
2996 char *p;
2997 struct WS_hostent *p_to;
2999 int size = (sizeof(*p_he) +
3000 strlen(p_he->h_name) + 1 +
3001 list_size(p_he->h_aliases, 0) +
3002 list_size(p_he->h_addr_list, p_he->h_length));
3004 if (!(p_to = check_buffer_he(size))) return NULL;
3005 p_to->h_addrtype = p_he->h_addrtype;
3006 p_to->h_length = p_he->h_length;
3008 p = (char *)(p_to + 1);
3009 p_to->h_name = p;
3010 strcpy(p, p_he->h_name);
3011 p += strlen(p) + 1;
3013 p_to->h_aliases = (char **)p;
3014 p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
3016 p_to->h_addr_list = (char **)p;
3017 list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
3018 return p_to;
3021 /* ----- protoent */
3023 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
3025 char *p;
3026 struct WS_protoent *p_to;
3028 int size = (sizeof(*p_pe) +
3029 strlen(p_pe->p_name) + 1 +
3030 list_size(p_pe->p_aliases, 0));
3032 if (!(p_to = check_buffer_pe(size))) return NULL;
3033 p_to->p_proto = p_pe->p_proto;
3035 p = (char *)(p_to + 1);
3036 p_to->p_name = p;
3037 strcpy(p, p_pe->p_name);
3038 p += strlen(p) + 1;
3040 p_to->p_aliases = (char **)p;
3041 list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
3042 return p_to;
3045 /* ----- servent */
3047 static struct WS_servent *WS_dup_se(const struct servent* p_se)
3049 char *p;
3050 struct WS_servent *p_to;
3052 int size = (sizeof(*p_se) +
3053 strlen(p_se->s_proto) + 1 +
3054 strlen(p_se->s_name) + 1 +
3055 list_size(p_se->s_aliases, 0));
3057 if (!(p_to = check_buffer_se(size))) return NULL;
3058 p_to->s_port = p_se->s_port;
3060 p = (char *)(p_to + 1);
3061 p_to->s_name = p;
3062 strcpy(p, p_se->s_name);
3063 p += strlen(p) + 1;
3065 p_to->s_proto = p;
3066 strcpy(p, p_se->s_proto);
3067 p += strlen(p) + 1;
3069 p_to->s_aliases = (char **)p;
3070 list_dup(p_se->s_aliases, p_to->s_aliases, 0);
3071 return p_to;
3074 /* ----------------------------------- error handling */
3076 UINT wsaErrno(void)
3078 int loc_errno = errno;
3079 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3081 switch(loc_errno)
3083 case EINTR: return WSAEINTR;
3084 case EBADF: return WSAEBADF;
3085 case EPERM:
3086 case EACCES: return WSAEACCES;
3087 case EFAULT: return WSAEFAULT;
3088 case EINVAL: return WSAEINVAL;
3089 case EMFILE: return WSAEMFILE;
3090 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3091 case EINPROGRESS: return WSAEINPROGRESS;
3092 case EALREADY: return WSAEALREADY;
3093 case ENOTSOCK: return WSAENOTSOCK;
3094 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3095 case EMSGSIZE: return WSAEMSGSIZE;
3096 case EPROTOTYPE: return WSAEPROTOTYPE;
3097 case ENOPROTOOPT: return WSAENOPROTOOPT;
3098 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3099 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3100 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3101 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3102 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3103 case EADDRINUSE: return WSAEADDRINUSE;
3104 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3105 case ENETDOWN: return WSAENETDOWN;
3106 case ENETUNREACH: return WSAENETUNREACH;
3107 case ENETRESET: return WSAENETRESET;
3108 case ECONNABORTED: return WSAECONNABORTED;
3109 case EPIPE:
3110 case ECONNRESET: return WSAECONNRESET;
3111 case ENOBUFS: return WSAENOBUFS;
3112 case EISCONN: return WSAEISCONN;
3113 case ENOTCONN: return WSAENOTCONN;
3114 case ESHUTDOWN: return WSAESHUTDOWN;
3115 case ETOOMANYREFS: return WSAETOOMANYREFS;
3116 case ETIMEDOUT: return WSAETIMEDOUT;
3117 case ECONNREFUSED: return WSAECONNREFUSED;
3118 case ELOOP: return WSAELOOP;
3119 case ENAMETOOLONG: return WSAENAMETOOLONG;
3120 case EHOSTDOWN: return WSAEHOSTDOWN;
3121 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3122 case ENOTEMPTY: return WSAENOTEMPTY;
3123 #ifdef EPROCLIM
3124 case EPROCLIM: return WSAEPROCLIM;
3125 #endif
3126 #ifdef EUSERS
3127 case EUSERS: return WSAEUSERS;
3128 #endif
3129 #ifdef EDQUOT
3130 case EDQUOT: return WSAEDQUOT;
3131 #endif
3132 #ifdef ESTALE
3133 case ESTALE: return WSAESTALE;
3134 #endif
3135 #ifdef EREMOTE
3136 case EREMOTE: return WSAEREMOTE;
3137 #endif
3139 /* just in case we ever get here and there are no problems */
3140 case 0: return 0;
3141 default:
3142 WARN("Unknown errno %d!\n", loc_errno);
3143 return WSAEOPNOTSUPP;
3147 UINT wsaHerrno(int loc_errno)
3150 WARN("h_errno %d.\n", loc_errno);
3152 switch(loc_errno)
3154 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3155 case TRY_AGAIN: return WSATRY_AGAIN;
3156 case NO_RECOVERY: return WSANO_RECOVERY;
3157 case NO_DATA: return WSANO_DATA;
3158 case ENOBUFS: return WSAENOBUFS;
3160 case 0: return 0;
3161 default:
3162 WARN("Unknown h_errno %d!\n", loc_errno);
3163 return WSAEOPNOTSUPP;
3168 /***********************************************************************
3169 * WSARecv (WS2_32.67)
3171 int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3172 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3173 LPWSAOVERLAPPED lpOverlapped,
3174 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3176 return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3177 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3180 /***********************************************************************
3181 * WSARecvFrom (WS2_32.69)
3183 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3184 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3185 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3186 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3189 int i, n, fd, err = WSAENOTSOCK, flags, ret;
3190 struct iovec* iovec;
3191 struct ws2_async *wsa;
3193 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3194 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3195 (lpFromlen ? *lpFromlen : -1L),
3196 lpOverlapped, lpCompletionRoutine);
3198 fd = get_sock_fd( s, GENERIC_READ, &flags );
3199 TRACE ( "fd=%d, flags=%x\n", fd, flags );
3201 if (fd == -1) return SOCKET_ERROR;
3203 if (flags & FD_FLAG_RECV_SHUTDOWN)
3205 WSASetLastError ( WSAESHUTDOWN );
3206 goto err_close;
3209 iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3210 if ( !iovec )
3212 err = WSAEFAULT;
3213 goto err_close;
3216 for (i = 0; i < dwBufferCount; i++)
3218 iovec[i].iov_base = lpBuffers[i].buf;
3219 iovec[i].iov_len = lpBuffers[i].len;
3222 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3224 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
3225 lpFlags, lpFrom, lpFromlen,
3226 lpOverlapped, lpCompletionRoutine );
3228 if ( !wsa )
3230 err = WSAEFAULT;
3231 goto err_free;
3234 if ( ( ret = register_new_async ( &wsa->async )) )
3236 err = NtStatusToWSAError ( ret );
3238 if ( !lpOverlapped )
3239 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
3240 HeapFree ( GetProcessHeap(), 0, wsa );
3241 goto err_free;
3244 /* Try immediate completion */
3245 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
3247 if ( WSAGetOverlappedResult ( s, lpOverlapped,
3248 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3249 return 0;
3251 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
3252 goto error;
3255 WSASetLastError ( WSA_IO_PENDING );
3256 return SOCKET_ERROR;
3259 if ( _is_blocking(s) )
3261 /* block here */
3262 /* FIXME: OOB and exceptfds? */
3263 do_block(fd, POLLIN);
3266 n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3267 if ( n == -1 )
3269 err = wsaErrno();
3270 goto err_free;
3273 TRACE(" -> %i bytes\n", n);
3274 *lpNumberOfBytesRecvd = n;
3276 HeapFree (GetProcessHeap(), 0, iovec);
3277 release_sock_fd( s, fd );
3278 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3280 return 0;
3282 err_free:
3283 HeapFree (GetProcessHeap(), 0, iovec);
3285 err_close:
3286 release_sock_fd( s, fd );
3288 error:
3289 WARN(" -> ERROR %d\n", err);
3290 WSASetLastError ( err );
3291 return SOCKET_ERROR;
3294 /***********************************************************************
3295 * WSCInstallProvider (WS2_32.88)
3297 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3298 LPCWSTR lpszProviderDllPath,
3299 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3300 DWORD dwNumberOfEntries,
3301 LPINT lpErrno )
3303 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3304 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3305 dwNumberOfEntries, lpErrno);
3306 *lpErrno = 0;
3307 return 0;
3311 /***********************************************************************
3312 * WSCDeinstallProvider (WS2_32.83)
3314 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3316 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3317 *lpErrno = 0;
3318 return 0;
3322 /***********************************************************************
3323 * WSAAccept (WS2_32.26)
3325 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
3326 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
3329 int ret = 0, size = 0;
3330 WSABUF CallerId, CallerData, CalleeId, CalleeData;
3331 /* QOS SQOS, GQOS; */
3332 GROUP g;
3333 SOCKET cs;
3334 SOCKADDR src_addr, dst_addr;
3336 TRACE("Socket %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
3337 s, addr, addrlen, lpfnCondition, dwCallbackData);
3340 size = sizeof(src_addr);
3341 cs = WS_accept(s, &src_addr, &size);
3343 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
3345 CallerId.buf = (char *)&src_addr;
3346 CallerId.len = sizeof(src_addr);
3348 CallerData.buf = NULL;
3349 CallerData.len = (ULONG)NULL;
3351 WS_getsockname(cs, &dst_addr, &size);
3353 CalleeId.buf = (char *)&dst_addr;
3354 CalleeId.len = sizeof(dst_addr);
3357 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
3358 &CalleeId, &CalleeData, &g, dwCallbackData);
3360 switch (ret)
3362 case CF_ACCEPT:
3363 if (addr && addrlen)
3364 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
3365 return cs;
3366 case CF_DEFER:
3367 SERVER_START_REQ ( set_socket_deferred )
3369 req->handle = SOCKET2HANDLE (s);
3370 req->deferred = SOCKET2HANDLE (cs);
3371 if ( !wine_server_call_err ( req ) )
3373 SetLastError ( WSATRY_AGAIN );
3374 WS_closesocket ( cs );
3377 SERVER_END_REQ;
3378 return SOCKET_ERROR;
3379 case CF_REJECT:
3380 WS_closesocket(cs);
3381 SetLastError(WSAECONNREFUSED);
3382 return SOCKET_ERROR;
3383 default:
3384 FIXME("Unknown return type from Condition function\n");
3385 SetLastError(WSAENOTSOCK);
3386 return SOCKET_ERROR;
3390 /***********************************************************************
3391 * WSAEnumProtocolsA (WS2_32.37)
3393 int WINAPI WSAEnumProtocolsA(LPINT lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength)
3395 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
3396 return 0;
3399 /***********************************************************************
3400 * WSAEnumProtocolsW (WS2_32.38)
3402 int WINAPI WSAEnumProtocolsW(LPINT lpiProtocols, LPWSAPROTOCOL_INFOW lpProtocolBuffer, LPDWORD lpdwBufferLength)
3404 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
3405 return 0;
3408 /***********************************************************************
3409 * WSADuplicateSocketA (WS2_32.32)
3411 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
3413 HANDLE hProcess;
3415 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3416 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3417 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
3418 /* I don't know what the real Windoze does next, this is a hack */
3419 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
3420 * the target use the global duplicate, or we could copy a reference to us to the structure
3421 * and let the target duplicate it from us, but let's do it as simple as possible */
3422 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3423 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3424 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3425 0, FALSE, DUPLICATE_SAME_ACCESS);
3426 CloseHandle(hProcess);
3427 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3428 return 0;
3431 /***********************************************************************
3432 * WSAInstallServiceClassA (WS2_32.48)
3434 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
3436 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
3437 WSASetLastError(WSAEACCES);
3438 return SOCKET_ERROR;
3441 /***********************************************************************
3442 * WSAInstallServiceClassW (WS2_32.49)
3444 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
3446 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
3447 WSASetLastError(WSAEACCES);
3448 return SOCKET_ERROR;
3451 /***********************************************************************
3452 * WSARemoveServiceClass (WS2_32.70)
3454 int WINAPI WSARemoveServiceClass(LPGUID info)
3456 FIXME("Request to remove service %p\n",info);
3457 WSASetLastError(WSATYPE_NOT_FOUND);
3458 return SOCKET_ERROR;
3461 /***********************************************************************
3462 * WSAStringToAddressA (WS2_32.80)
3464 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
3465 INT AddressFamily,
3466 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3467 LPSOCKADDR lpAddress,
3468 LPINT lpAddressLength)
3470 FIXME("(%s, %x, %p, %p, %p) Stub!\n", AddressString, AddressFamily, lpProtocolInfo, lpAddress, lpAddressLength);
3471 return 0;
3474 /***********************************************************************
3475 * WSALookupServiceBeginA (WS2_32.59)
3477 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
3478 DWORD dwControlFlags,
3479 LPHANDLE lphLookup)
3481 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
3482 lphLookup);
3483 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
3484 return SOCKET_ERROR;
3487 /***********************************************************************
3488 * WSALookupServiceBeginW (WS2_32.60)
3490 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
3491 DWORD dwControlFlags,
3492 LPHANDLE lphLookup)
3494 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
3495 lphLookup);
3496 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
3497 return SOCKET_ERROR;
3500 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
3502 FIXME("(%p) Stub!\n", lpProviderId);
3504 return NO_ERROR;