Use wine_server_release_fd() instead of close() everywhere we use
[wine] / dlls / winsock / socket.c
1 /*
2  * based on Windows Sockets 1.1 specs
3  * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4  *
5  * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
6  *
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.
11  *
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.
16  *
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
20  *
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).
24  */
25
26 #include "config.h"
27 #include "wine/port.h"
28
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
45
46 #if defined(__EMX__)
47 # include <sys/so_ioctl.h>
48 #endif
49
50 #ifdef HAVE_SYS_PARAM_H
51 # include <sys/param.h>
52 #endif
53
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
106
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
113
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 "ws2tcpip.h"
123 #include "wsipx.h"
124 #include "winnt.h"
125 #include "iphlpapi.h"
126 #include "thread.h"
127 #include "wine/server.h"
128 #include "wine/debug.h"
129
130 #ifdef __FreeBSD__
131 # define sipx_network    sipx_addr.x_net
132 # define sipx_node       sipx_addr.x_host.c_host
133 #endif  /* __FreeBSD__ */
134
135 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
136
137 /* critical section to protect some non-rentrant net function */
138 extern CRITICAL_SECTION csWSgetXXXbyYYY;
139
140 inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
141 {
142     if (!a) return "(nil)";
143     return wine_dbg_sprintf("{ family %d, address %s, port %d }",
144                             ((struct sockaddr_in *)a)->sin_family,
145                             inet_ntoa(((struct sockaddr_in *)a)->sin_addr),
146                             ntohs(((struct sockaddr_in *)a)->sin_port));
147 }
148
149 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
150 #define SOCKET2HANDLE(s) ((HANDLE)(s))
151 #define HANDLE2SOCKET(h) ((SOCKET)(h))
152
153 /****************************************************************
154  * Async IO declarations
155  ****************************************************************/
156 #include "async.h"
157
158 static DWORD ws2_async_get_count  (const struct async_private *ovp);
159 static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
160 static void ws2_async_cleanup ( struct async_private *ovp );
161
162 static struct async_ops ws2_async_ops =
163 {
164     ws2_async_get_count,
165     ws2_async_call_completion,
166     ws2_async_cleanup
167 };
168
169 static struct async_ops ws2_nocomp_async_ops =
170 {
171     ws2_async_get_count,
172     NULL,                     /* call_completion */
173     ws2_async_cleanup
174 };
175
176 typedef struct ws2_async
177 {
178     async_private                       async;
179     LPWSAOVERLAPPED                     user_overlapped;
180     LPWSAOVERLAPPED_COMPLETION_ROUTINE  completion_func;
181     struct iovec                        *iovec;
182     int                                 n_iovecs;
183     struct WS_sockaddr                  *addr;
184     union {
185         int val;     /* for send operations */
186         int *ptr;    /* for recv operations */
187     }                                   addrlen;
188     DWORD                               flags;
189 } ws2_async;
190
191 /****************************************************************/
192
193 /* ----------------------------------- internal data */
194
195 /* ws_... struct conversion flags */
196
197 typedef struct          /* WSAAsyncSelect() control struct */
198 {
199   HANDLE      service, event, sock;
200   HWND        hWnd;
201   UINT        uMsg;
202   LONG        lEvent;
203 } ws_select_info;
204
205 #define WS_MAX_SOCKETS_PER_PROCESS      128     /* reasonable guess */
206 #define WS_MAX_UDP_DATAGRAM             1024
207 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
208
209 static struct WS_hostent *he_buffer;          /* typecast for Win32 ws_hostent */
210 static struct WS_servent *se_buffer;          /* typecast for Win32 ws_servent */
211 static struct WS_protoent *pe_buffer;          /* typecast for Win32 ws_protoent */
212 static INT num_startup;          /* reference counter */
213 static FARPROC blocking_hook = WSA_DefaultBlockingHook;
214
215 /* function prototypes */
216 static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
217 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
218 static struct WS_servent *WS_dup_se(const struct servent* p_se);
219
220 int WSAIOCTL_GetInterfaceCount(void);
221 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
222
223 UINT wsaErrno(void);
224 UINT wsaHerrno(int errnr);
225
226 #define MAP_OPTION(opt) { WS_##opt, opt }
227
228 static const int ws_sock_map[][2] =
229 {
230     MAP_OPTION( SO_DEBUG ),
231     MAP_OPTION( SO_REUSEADDR ),
232     MAP_OPTION( SO_KEEPALIVE ),
233     MAP_OPTION( SO_DONTROUTE ),
234     MAP_OPTION( SO_BROADCAST ),
235     MAP_OPTION( SO_LINGER ),
236     MAP_OPTION( SO_OOBINLINE ),
237     MAP_OPTION( SO_SNDBUF ),
238     MAP_OPTION( SO_RCVBUF ),
239     MAP_OPTION( SO_ERROR ),
240     MAP_OPTION( SO_TYPE ),
241 #ifdef SO_RCVTIMEO
242     MAP_OPTION( SO_RCVTIMEO ),
243 #endif
244 #ifdef SO_SNDTIMEO
245     MAP_OPTION( SO_SNDTIMEO ),
246 #endif
247     { 0, 0 }
248 };
249
250 static const int ws_tcp_map[][2] =
251 {
252 #ifdef TCP_NODELAY
253     MAP_OPTION( TCP_NODELAY ),
254 #endif
255     { 0, 0 }
256 };
257
258 static const int ws_ip_map[][2] =
259 {
260     MAP_OPTION( IP_MULTICAST_IF ),
261     MAP_OPTION( IP_MULTICAST_TTL ),
262     MAP_OPTION( IP_MULTICAST_LOOP ),
263     MAP_OPTION( IP_ADD_MEMBERSHIP ),
264     MAP_OPTION( IP_DROP_MEMBERSHIP ),
265     MAP_OPTION( IP_OPTIONS ),
266 #ifdef IP_HDRINCL
267     MAP_OPTION( IP_HDRINCL ),
268 #endif
269     MAP_OPTION( IP_TOS ),
270     MAP_OPTION( IP_TTL ),
271     { 0, 0 }
272 };
273
274 static DWORD opentype_tls_index = TLS_OUT_OF_INDEXES;  /* TLS index for SO_OPENTYPE flag */
275
276 inline static DWORD NtStatusToWSAError ( const DWORD status )
277 {
278     /* We only need to cover the status codes set by server async request handling */
279     DWORD wserr;
280     switch ( status )
281     {
282     case STATUS_SUCCESS:              wserr = 0;                     break;
283     case STATUS_PENDING:              wserr = WSA_IO_PENDING;        break;
284     case STATUS_INVALID_HANDLE:       wserr = WSAENOTSOCK;           break;  /* WSAEBADF ? */
285     case STATUS_INVALID_PARAMETER:    wserr = WSAEINVAL;             break;
286     case STATUS_PIPE_DISCONNECTED:    wserr = WSAESHUTDOWN;          break;
287     case STATUS_CANCELLED:            wserr = WSA_OPERATION_ABORTED; break;
288     case STATUS_TIMEOUT:              wserr = WSAETIMEDOUT;          break;
289     case STATUS_NO_MEMORY:            wserr = WSAEFAULT;             break;
290     default:
291         if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
292             /* It is not a NT status code but a winsock error */
293             wserr = status;
294         else
295         {
296             wserr = RtlNtStatusToDosError( status );
297             FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
298         }
299     }
300     return wserr;
301 }
302
303 /* set last error code from NT status without mapping WSA errors */
304 inline static unsigned int set_error( unsigned int err )
305 {
306     if (err)
307     {
308         err = NtStatusToWSAError ( err );
309         SetLastError( err );
310     }
311     return err;
312 }
313
314 inline static int get_sock_fd( SOCKET s, DWORD access, int *flags )
315 {
316     int fd;
317     if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, NULL, flags ) ))
318         return -1;
319     return fd;
320 }
321
322 inline static void release_sock_fd( SOCKET s, int fd )
323 {
324     wine_server_release_fd( SOCKET2HANDLE(s), fd );
325 }
326
327 static void _enable_event( HANDLE s, unsigned int event,
328                            unsigned int sstate, unsigned int cstate )
329 {
330     SERVER_START_REQ( enable_socket_event )
331     {
332         req->handle = s;
333         req->mask   = event;
334         req->sstate = sstate;
335         req->cstate = cstate;
336         wine_server_call( req );
337     }
338     SERVER_END_REQ;
339 }
340
341 static int _is_blocking(SOCKET s)
342 {
343     int ret;
344     SERVER_START_REQ( get_socket_event )
345     {
346         req->handle  = SOCKET2HANDLE(s);
347         req->service = FALSE;
348         req->c_event = 0;
349         wine_server_call( req );
350         ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
351     }
352     SERVER_END_REQ;
353     return ret;
354 }
355
356 static unsigned int _get_sock_mask(SOCKET s)
357 {
358     unsigned int ret;
359     SERVER_START_REQ( get_socket_event )
360     {
361         req->handle  = SOCKET2HANDLE(s);
362         req->service = FALSE;
363         req->c_event = 0;
364         wine_server_call( req );
365         ret = reply->mask;
366     }
367     SERVER_END_REQ;
368     return ret;
369 }
370
371 static void _sync_sock_state(SOCKET s)
372 {
373     /* do a dummy wineserver request in order to let
374        the wineserver run through its select loop once */
375     (void)_is_blocking(s);
376 }
377
378 static int _get_sock_error(SOCKET s, unsigned int bit)
379 {
380     int events[FD_MAX_EVENTS];
381
382     SERVER_START_REQ( get_socket_event )
383     {
384         req->handle  = SOCKET2HANDLE(s);
385         req->service = FALSE;
386         req->c_event = 0;
387         wine_server_set_reply( req, events, sizeof(events) );
388         wine_server_call( req );
389     }
390     SERVER_END_REQ;
391     return events[bit];
392 }
393
394 static void WINSOCK_DeleteIData(void)
395 {
396     /* delete scratch buffers */
397
398     if (he_buffer) HeapFree( GetProcessHeap(), 0, he_buffer );
399     if (se_buffer) HeapFree( GetProcessHeap(), 0, se_buffer );
400     if (pe_buffer) HeapFree( GetProcessHeap(), 0, pe_buffer );
401     he_buffer = NULL;
402     se_buffer = NULL;
403     pe_buffer = NULL;
404     num_startup = 0;
405 }
406
407 /***********************************************************************
408  *              DllMain (WS2_32.init)
409  */
410 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
411 {
412     TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
413     switch (fdwReason) {
414     case DLL_PROCESS_ATTACH:
415         DisableThreadLibraryCalls(hInstDLL);
416         opentype_tls_index = TlsAlloc();
417         break;
418     case DLL_PROCESS_DETACH:
419         TlsFree( opentype_tls_index );
420         WINSOCK_DeleteIData();
421         break;
422     }
423     return TRUE;
424 }
425
426 /***********************************************************************
427  *          convert_sockopt()
428  *
429  * Converts socket flags from Windows format.
430  * Return 1 if converted, 0 if not (error).
431  */
432 static int convert_sockopt(INT *level, INT *optname)
433 {
434   int i;
435   switch (*level)
436   {
437      case WS_SOL_SOCKET:
438         *level = SOL_SOCKET;
439         for(i=0; ws_sock_map[i][0]; i++)
440         {
441             if( ws_sock_map[i][0] == *optname )
442             {
443                 *optname = ws_sock_map[i][1];
444                 return 1;
445             }
446         }
447         FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
448         break;
449      case WS_IPPROTO_TCP:
450         *level = IPPROTO_TCP;
451         for(i=0; ws_tcp_map[i][0]; i++)
452         {
453             if ( ws_tcp_map[i][0] == *optname )
454             {
455                 *optname = ws_tcp_map[i][1];
456                 return 1;
457             }
458         }
459         FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
460         break;
461      case WS_IPPROTO_IP:
462         *level = IPPROTO_IP;
463         for(i=0; ws_ip_map[i][0]; i++)
464         {
465             if (ws_ip_map[i][0] == *optname )
466             {
467                 *optname = ws_ip_map[i][1];
468                 return 1;
469             }
470         }
471         FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
472         break;
473      default: FIXME("Unimplemented or unknown socket level\n");
474   }
475   return 0;
476 }
477
478 static inline BOOL is_timeout_option( int optname )
479 {
480 #ifdef SO_RCVTIMEO
481     if (optname == SO_RCVTIMEO) return TRUE;
482 #endif
483 #ifdef SO_SNDTIMEO
484     if (optname == SO_SNDTIMEO) return TRUE;
485 #endif
486     return FALSE;
487 }
488
489 /* ----------------------------------- Per-thread info (or per-process?) */
490
491 static char *strdup_lower(const char *str)
492 {
493     int i;
494     char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
495
496     if (ret)
497     {
498         for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
499         ret[i] = 0;
500     }
501     else SetLastError(WSAENOBUFS);
502     return ret;
503 }
504
505 static fd_set* fd_set_import( fd_set* fds, const WS_fd_set* wsfds, int access, int* highfd, int lfd[] )
506 {
507     /* translate Winsock fd set into local fd set */
508     if( wsfds )
509     {
510         int i;
511
512         FD_ZERO(fds);
513         for( i = 0; i < wsfds->fd_count; i++ )
514         {
515             int s = wsfds->fd_array[i];
516             int fd = get_sock_fd( s, access, NULL );
517             if (fd != -1)
518             {
519                 lfd[ i ] = fd;
520                 if( fd > *highfd ) *highfd = fd;
521                 FD_SET(fd, fds);
522             }
523             else lfd[ i ] = -1;
524         }
525         return fds;
526     }
527     return NULL;
528 }
529
530 inline static int sock_error_p(int s)
531 {
532     unsigned int optval, optlen;
533
534     optlen = sizeof(optval);
535     getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
536     if (optval) WARN("\t[%i] error: %d\n", s, optval);
537     return optval != 0;
538 }
539
540 static int fd_set_export( const fd_set* fds, fd_set* exceptfds, WS_fd_set* wsfds, int lfd[] )
541 {
542     int num_err = 0;
543
544     /* translate local fd set into Winsock fd set, adding
545      * errors to exceptfds (only if app requested it) */
546
547     if( wsfds )
548     {
549         int i, j, count = wsfds->fd_count;
550
551         for( i = 0, j = 0; i < count; i++ )
552         {
553             int fd = lfd[i];
554             SOCKET s = wsfds->fd_array[i];
555             if (fd == -1) continue;
556             if( FD_ISSET(fd, fds) )
557             {
558                 if ( exceptfds && sock_error_p(fd) )
559                 {
560                     FD_SET(fd, exceptfds);
561                     num_err++;
562                 }
563                 else wsfds->fd_array[j++] = s;
564             }
565             release_sock_fd( s, fd );
566         }
567         wsfds->fd_count = j;
568     }
569     return num_err;
570 }
571
572 static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
573 {
574     if ( wsfds )
575     {
576         int i;
577
578         for( i = 0; i < wsfds->fd_count; i++ )
579             if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
580         wsfds->fd_count = 0;
581     }
582 }
583
584 /* utility: given an fd, will block until one of the events occurs */
585 static inline int do_block( int fd, int events )
586 {
587   struct pollfd pfd;
588
589   pfd.fd = fd;
590   pfd.events = events;
591   poll(&pfd, 1, -1);
592   return pfd.revents;
593 }
594
595
596 /* ----------------------------------- API -----
597  *
598  * Init / cleanup / error checking.
599  */
600
601 /***********************************************************************
602  *      WSAStartup              (WS2_32.115)
603  */
604 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
605 {
606     TRACE("verReq=%x\n", wVersionRequested);
607
608     if (LOBYTE(wVersionRequested) < 1)
609         return WSAVERNOTSUPPORTED;
610
611     if (!lpWSAData) return WSAEINVAL;
612
613     num_startup++;
614
615     /* that's the whole of the negotiation for now */
616     lpWSAData->wVersion = wVersionRequested;
617     /* return winsock information */
618     lpWSAData->wHighVersion = 0x0202;
619     strcpy(lpWSAData->szDescription, "WinSock 2.0" );
620     strcpy(lpWSAData->szSystemStatus, "Running" );
621     lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
622     lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
623     /* don't do anything with lpWSAData->lpVendorInfo */
624     /* (some apps don't allocate the space for this field) */
625
626     TRACE("succeeded\n");
627     return 0;
628 }
629
630
631 /***********************************************************************
632  *      WSACleanup                      (WS2_32.116)
633  */
634 INT WINAPI WSACleanup(void)
635 {
636     if (num_startup)
637     {
638         if (--num_startup > 0) return 0;
639         WINSOCK_DeleteIData();
640         return 0;
641     }
642     SetLastError(WSANOTINITIALISED);
643     return SOCKET_ERROR;
644 }
645
646
647 /***********************************************************************
648  *      WSAGetLastError         (WINSOCK.111)
649  *      WSAGetLastError         (WS2_32.111)
650  */
651 INT WINAPI WSAGetLastError(void)
652 {
653         return GetLastError();
654 }
655
656 /***********************************************************************
657  *      WSASetLastError         (WS2_32.112)
658  */
659 void WINAPI WSASetLastError(INT iError) {
660     SetLastError(iError);
661 }
662
663 static struct WS_hostent *check_buffer_he(int size)
664 {
665     static int he_len;
666     if (he_buffer)
667     {
668         if (he_len >= size ) return he_buffer;
669         HeapFree( GetProcessHeap(), 0, he_buffer );
670     }
671     he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
672     if (!he_buffer) SetLastError(WSAENOBUFS);
673     return he_buffer;
674 }
675
676 static struct WS_servent *check_buffer_se(int size)
677 {
678     static int se_len;
679     if (se_buffer)
680     {
681         if (se_len >= size ) return se_buffer;
682         HeapFree( GetProcessHeap(), 0, se_buffer );
683     }
684     se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
685     if (!se_buffer) SetLastError(WSAENOBUFS);
686     return se_buffer;
687 }
688
689 static struct WS_protoent *check_buffer_pe(int size)
690 {
691     static int pe_len;
692     if (pe_buffer)
693     {
694         if (pe_len >= size ) return pe_buffer;
695         HeapFree( GetProcessHeap(), 0, pe_buffer );
696     }
697     pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
698     if (!pe_buffer) SetLastError(WSAENOBUFS);
699     return pe_buffer;
700 }
701
702 /* ----------------------------------- i/o APIs */
703
704 #ifdef HAVE_IPX
705 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
706 #else
707 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
708 #endif
709
710
711 /**********************************************************************/
712
713 /* Returns the converted address if successful, NULL if it was too small to
714  * start with. Note that the returned pointer may be the original pointer
715  * if no conversion is necessary.
716  */
717 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
718 {
719     switch (wsaddr->sa_family)
720     {
721 #ifdef HAVE_IPX
722     case WS_AF_IPX:
723         {
724             struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
725             struct sockaddr_ipx* uipx;
726
727             if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
728                 return NULL;
729
730             *uaddrlen=sizeof(struct sockaddr_ipx);
731             uipx=malloc(*uaddrlen);
732             uipx->sipx_family=AF_IPX;
733             uipx->sipx_port=wsipx->sa_socket;
734             /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
735              * in one go
736              */
737             memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
738 #ifdef IPX_FRAME_NONE
739             uipx->sipx_type=IPX_FRAME_NONE;
740 #endif
741             memset(&uipx->sipx_zero,0,sizeof(uipx->sipx_zero));
742             return (const struct sockaddr*)uipx;
743         }
744 #endif
745
746     default:
747         if (wsaddrlen<sizeof(struct WS_sockaddr))
748             return NULL;
749
750         /* No conversion needed, just return the original address */
751         *uaddrlen=wsaddrlen;
752         return (const struct sockaddr*)wsaddr;
753     }
754     return NULL;
755 }
756
757 /* Allocates a Unix sockaddr structure to receive the data */
758 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
759 {
760     if (wsaddr==NULL)
761     {
762       ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
763
764       /* This is not strictly the right thing to do. Hope it works however */
765       *uaddrlen=0;
766
767       return NULL;
768     }
769
770     if (*wsaddrlen==0)
771         *uaddrlen=0;
772     else
773         *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
774
775     return malloc(*uaddrlen);
776 }
777
778 /* Returns 0 if successful, -1 if the buffer is too small */
779 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
780 {
781     int res;
782
783     switch(uaddr->sa_family)
784     {
785 #ifdef HAVE_IPX
786     case AF_IPX:
787         {
788             struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
789             struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
790
791             res=-1;
792             switch (*wsaddrlen) /* how much can we copy? */
793             {
794             default:
795                 res=0; /* enough */
796                 *wsaddrlen=uaddrlen;
797                 wsipx->sa_socket=uipx->sipx_port;
798                 /* fall through */
799             case 13:
800             case 12:
801                 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
802                 /* fall through */
803             case 11:
804             case 10:
805             case 9:
806             case 8:
807             case 7:
808             case 6:
809                 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
810                 /* fall through */
811             case 5:
812             case 4:
813             case 3:
814             case 2:
815                 wsipx->sa_family=WS_AF_IPX;
816                 /* fall through */
817             case 1:
818             case 0:
819                 /* way too small */
820                 break;
821             }
822         }
823         break;
824 #endif
825
826     default:
827         /* No conversion needed */
828         memcpy(wsaddr,uaddr,*wsaddrlen);
829         if (*wsaddrlen<uaddrlen) {
830             res=-1;
831         } else {
832             *wsaddrlen=uaddrlen;
833             res=0;
834         }
835     }
836     return res;
837 }
838
839 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
840  * ws_sockaddr_alloc
841  */
842 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
843 {
844     if (uaddr!=NULL && uaddr!=(const struct sockaddr*)wsaddr)
845         free((void*)uaddr);
846 }
847
848 /**************************************************************************
849  * Functions for handling overlapped I/O
850  **************************************************************************/
851
852 static DWORD ws2_async_get_count (const struct async_private *ovp)
853 {
854     return ovp->iosb->Information;
855 }
856
857 static void ws2_async_cleanup ( struct async_private *ap )
858 {
859     struct ws2_async *as = (struct ws2_async*) ap;
860
861     TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->async.iosb );
862     if ( !as->user_overlapped )
863     {
864 #if 0
865         /* FIXME: I don't think this is really used */
866         if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
867             WSACloseEvent ( as->overlapped->hEvent  );
868 #endif
869         HeapFree ( GetProcessHeap(), 0, as->async.iosb );
870     }
871
872     if ( as->iovec )
873         HeapFree ( GetProcessHeap(), 0, as->iovec );
874
875     HeapFree ( GetProcessHeap(), 0, as );
876 }
877
878 static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
879 {
880     ws2_async* as = (ws2_async*) data;
881
882     TRACE ("data: %p\n", as);
883
884     as->completion_func ( NtStatusToWSAError (as->async.iosb->u.Status),
885                           as->async.iosb->Information,
886                           as->user_overlapped,
887                           as->flags );
888     ws2_async_cleanup ( &as->async );
889 }
890
891 /***********************************************************************
892  *              WS2_make_async          (INTERNAL)
893  */
894
895 static void WS2_async_recv (async_private *as);
896 static void WS2_async_send (async_private *as);
897
898 inline static struct ws2_async*
899 WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
900                 LPDWORD lpFlags, struct WS_sockaddr *addr,
901                 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
902                 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
903 {
904     struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
905
906     TRACE ( "wsa %p\n", wsa );
907
908     if (!wsa)
909         return NULL;
910
911     wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
912     wsa->async.handle = (HANDLE) s;
913     wsa->async.fd = fd;
914     wsa->async.type = type;
915     switch (type)
916     {
917     case ASYNC_TYPE_READ:
918         wsa->flags = *lpFlags;
919         wsa->async.func = WS2_async_recv;
920         wsa->addrlen.ptr = addrlen;
921         break;
922     case ASYNC_TYPE_WRITE:
923         wsa->flags = 0;
924         wsa->async.func = WS2_async_send;
925         wsa->addrlen.val = *addrlen;
926         break;
927     default:
928         ERR ("Invalid async type: %d\n", type);
929     }
930     wsa->user_overlapped = lpOverlapped;
931     wsa->completion_func = lpCompletionRoutine;
932     wsa->iovec = iovec;
933     wsa->n_iovecs = dwBufferCount;
934     wsa->addr = addr;
935
936     if ( lpOverlapped )
937     {
938         wsa->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
939         wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
940     }
941     else
942     {
943         wsa->async.iosb = HeapAlloc ( GetProcessHeap(), 0,
944                                       sizeof (IO_STATUS_BLOCK) );
945         if ( !wsa->async.iosb )
946             goto error;
947         wsa->async.event = INVALID_HANDLE_VALUE;
948     }
949
950     wsa->async.iosb->Information = 0;
951     TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, iosb %p, uov %p, cfunc %p\n",
952             wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
953             wsa->async.iosb, wsa->user_overlapped, wsa->completion_func );
954
955     return wsa;
956
957 error:
958     TRACE ("Error\n");
959     HeapFree ( GetProcessHeap(), 0, wsa );
960     return NULL;
961 }
962
963 /***********************************************************************
964  *              WS2_recv                (INTERNAL)
965  *
966  * Work horse for both synchronous and asynchronous recv() operations.
967  */
968 static int WS2_recv ( int fd, struct iovec* iov, int count,
969                       struct WS_sockaddr *lpFrom, LPINT lpFromlen,
970                       LPDWORD lpFlags )
971 {
972     struct msghdr hdr;
973     int n;
974     TRACE ( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
975             fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
976
977     hdr.msg_name = NULL;
978
979     if ( lpFrom )
980     {
981         hdr.msg_namelen = *lpFromlen;
982         hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
983         if ( !hdr.msg_name )
984         {
985             WSASetLastError ( WSAEFAULT );
986             n = -1;
987             goto out;
988         }
989     }
990     else
991         hdr.msg_namelen = 0;
992
993     hdr.msg_iov = iov;
994     hdr.msg_iovlen = count;
995 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
996     hdr.msg_accrights = NULL;
997     hdr.msg_accrightslen = 0;
998 #else
999     hdr.msg_control = NULL;
1000     hdr.msg_controllen = 0;
1001     hdr.msg_flags = 0;
1002 #endif
1003
1004     if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
1005     {
1006         TRACE ( "recvmsg error %d\n", errno);
1007         goto out;
1008     }
1009
1010     if ( lpFrom &&
1011          ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
1012                             lpFrom, lpFromlen ) != 0 )
1013     {
1014         /* The from buffer was too small, but we read the data
1015          * anyway. Is that really bad?
1016          */
1017         WSASetLastError ( WSAEFAULT );
1018         WARN ( "Address buffer too small\n" );
1019     }
1020
1021 out:
1022
1023     ws_sockaddr_free ( hdr.msg_name, lpFrom );
1024     TRACE ("-> %d\n", n);
1025     return n;
1026 }
1027
1028 /***********************************************************************
1029  *              WS2_async_recv          (INTERNAL)
1030  *
1031  * Handler for overlapped recv() operations.
1032  */
1033 static void WS2_async_recv ( async_private *as )
1034 {
1035     ws2_async* wsa = (ws2_async*) as;
1036     int result, err;
1037
1038     TRACE ( "async %p\n", wsa );
1039
1040     if ( wsa->async.iosb->u.Status != STATUS_PENDING )
1041     {
1042         TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
1043         return;
1044     }
1045
1046     result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1047                         wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1048
1049     if (result >= 0)
1050     {
1051         wsa->async.iosb->u.Status = STATUS_SUCCESS;
1052         wsa->async.iosb->Information = result;
1053         TRACE ( "received %d bytes\n", result );
1054         _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1055         return;
1056     }
1057
1058     err = wsaErrno ();
1059     if ( err == WSAEINTR || err == WSAEWOULDBLOCK )  /* errno: EINTR / EAGAIN */
1060     {
1061         wsa->async.iosb->u.Status = STATUS_PENDING;
1062         _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1063         TRACE ( "still pending\n" );
1064     }
1065     else
1066     {
1067         wsa->async.iosb->u.Status = err;
1068         TRACE ( "Error: %x\n", err );
1069     }
1070 }
1071
1072 /***********************************************************************
1073  *              WS2_send                (INTERNAL)
1074  *
1075  * Work horse for both synchronous and asynchronous send() operations.
1076  */
1077 static int WS2_send ( int fd, struct iovec* iov, int count,
1078                       const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1079 {
1080     struct msghdr hdr;
1081     int n = -1;
1082     TRACE ( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
1083             fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
1084
1085     hdr.msg_name = NULL;
1086
1087     if ( to )
1088     {
1089         hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
1090         if ( !hdr.msg_name )
1091         {
1092             WSASetLastError ( WSAEFAULT );
1093             goto out;
1094         }
1095     }
1096     else
1097         hdr.msg_namelen = 0;
1098
1099     hdr.msg_iov = iov;
1100     hdr.msg_iovlen = count;
1101 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1102     hdr.msg_accrights = NULL;
1103     hdr.msg_accrightslen = 0;
1104 #else
1105     hdr.msg_control = NULL;
1106     hdr.msg_controllen = 0;
1107     hdr.msg_flags = 0;
1108 #endif
1109
1110     n = sendmsg (fd, &hdr, dwFlags);
1111
1112 out:
1113     ws_sockaddr_free ( hdr.msg_name, to );
1114     return n;
1115 }
1116
1117 /***********************************************************************
1118  *              WS2_async_send          (INTERNAL)
1119  *
1120  * Handler for overlapped send() operations.
1121  */
1122 static void WS2_async_send ( async_private *as )
1123 {
1124     ws2_async* wsa = (ws2_async*) as;
1125     int result, err;
1126
1127     TRACE ( "async %p\n", wsa );
1128
1129     if ( wsa->async.iosb->u.Status != STATUS_PENDING )
1130     {
1131         TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
1132         return;
1133     }
1134
1135     result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1136                         wsa->addr, wsa->addrlen.val, wsa->flags );
1137
1138     if (result >= 0)
1139     {
1140         wsa->async.iosb->u.Status = STATUS_SUCCESS;
1141         wsa->async.iosb->Information = result;
1142         TRACE ( "sent %d bytes\n", result );
1143         _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1144         return;
1145     }
1146
1147     err = wsaErrno ();
1148     if ( err == WSAEINTR )
1149     {
1150         wsa->async.iosb->u.Status = STATUS_PENDING;
1151         _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1152         TRACE ( "still pending\n" );
1153     }
1154     else
1155     {
1156         /* We set the status to a winsock error code and check for that
1157            later in NtStatusToWSAError () */
1158         wsa->async.iosb->u.Status = err;
1159         TRACE ( "Error: %x\n", err );
1160     }
1161 }
1162
1163 /***********************************************************************
1164  *              WS2_async_shutdown      (INTERNAL)
1165  *
1166  * Handler for shutdown() operations on overlapped sockets.
1167  */
1168 static void WS2_async_shutdown ( async_private *as )
1169 {
1170     ws2_async* wsa = (ws2_async*) as;
1171     int err = 1;
1172
1173     TRACE ( "async %p %d\n", wsa, wsa->async.type );
1174     switch ( wsa->async.type )
1175     {
1176     case ASYNC_TYPE_READ:
1177         err = shutdown ( wsa->async.fd, 0 );
1178         break;
1179     case ASYNC_TYPE_WRITE:
1180         err = shutdown ( wsa->async.fd, 1 );
1181         break;
1182     default:
1183         ERR ("invalid type: %d\n", wsa->async.type );
1184     }
1185
1186     if ( err )
1187         wsa->async.iosb->u.Status = wsaErrno ();
1188     else
1189         wsa->async.iosb->u.Status = STATUS_SUCCESS;
1190 }
1191
1192 /***********************************************************************
1193  *  WS2_register_async_shutdown         (INTERNAL)
1194  *
1195  * Helper function for WS_shutdown() on overlapped sockets.
1196  */
1197 static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
1198 {
1199     struct ws2_async *wsa;
1200     int ret, err = WSAEFAULT;
1201     DWORD dwflags = 0;
1202     int len = 0;
1203     LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
1204
1205     TRACE ("s %d fd %d type %d\n", s, fd, type);
1206     if (!ovl)
1207         goto out;
1208
1209     ovl->hEvent = WSACreateEvent ();
1210     if ( ovl->hEvent == WSA_INVALID_EVENT  )
1211         goto out_free;
1212
1213     wsa = WS2_make_async ( s, fd, type, NULL, 0,
1214                            &dwflags, NULL, &len, ovl, NULL );
1215     if ( !wsa )
1216         goto out_close;
1217
1218     /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1219     wsa->user_overlapped = NULL;
1220     wsa->async.func = WS2_async_shutdown;
1221     if ( (ret = register_new_async ( &wsa->async )) )
1222     {
1223         err = NtStatusToWSAError ( ret );
1224         goto out;
1225     }
1226     /* Try immediate completion */
1227     while ( WaitForSingleObjectEx ( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1228     return 0;
1229
1230 out_close:
1231     WSACloseEvent ( ovl->hEvent );
1232 out_free:
1233     HeapFree ( GetProcessHeap(), 0, ovl );
1234 out:
1235     return err;
1236 }
1237
1238 /***********************************************************************
1239  *              accept          (WS2_32.1)
1240  */
1241 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1242                                  int *addrlen32)
1243 {
1244     SOCKET as;
1245
1246     TRACE("socket %04x\n", s );
1247     if (_is_blocking(s))
1248     {
1249         int fd = get_sock_fd( s, GENERIC_READ, NULL );
1250         if (fd == -1) return INVALID_SOCKET;
1251         /* block here */
1252         do_block(fd, POLLIN);
1253         _sync_sock_state(s); /* let wineserver notice connection */
1254         release_sock_fd( s, fd );
1255         /* retrieve any error codes from it */
1256         SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1257         /* FIXME: care about the error? */
1258     }
1259     SERVER_START_REQ( accept_socket )
1260     {
1261         req->lhandle = SOCKET2HANDLE(s);
1262         req->access  = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1263         req->inherit = TRUE;
1264         set_error( wine_server_call( req ) );
1265         as = HANDLE2SOCKET( reply->handle );
1266     }
1267     SERVER_END_REQ;
1268     if (as)
1269     {
1270         if (addr) WS_getpeername(as, addr, addrlen32);
1271         return as;
1272     }
1273     return INVALID_SOCKET;
1274 }
1275
1276 /***********************************************************************
1277  *              bind                    (WS2_32.2)
1278  */
1279 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1280 {
1281     int fd = get_sock_fd( s, 0, NULL );
1282     int res = SOCKET_ERROR;
1283
1284     TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1285
1286     if (fd != -1)
1287     {
1288         if (!name || !SUPPORTED_PF(name->sa_family))
1289         {
1290             SetLastError(WSAEAFNOSUPPORT);
1291         }
1292         else
1293         {
1294             const struct sockaddr* uaddr;
1295             int uaddrlen;
1296
1297             uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1298             if (uaddr == NULL)
1299             {
1300                 SetLastError(WSAEFAULT);
1301             }
1302             else
1303             {
1304                 int on = 1;
1305                 /* The game GrandPrixLegends binds more than one time, but does
1306                  * not do a SO_REUSEADDR - Stevens says this is ok */
1307                 TRACE( "Setting WS_SO_REUSEADDR on socket before we bind it\n");
1308                 WS_setsockopt( s, WS_SOL_SOCKET, WS_SO_REUSEADDR, (char*)&on, sizeof(on) );
1309
1310                 if (bind(fd, uaddr, uaddrlen) < 0)
1311                 {
1312                     int loc_errno = errno;
1313                     WARN("\tfailure - errno = %i\n", errno);
1314                     errno = loc_errno;
1315                     switch (errno)
1316                     {
1317                     case EBADF:
1318                         SetLastError(WSAENOTSOCK);
1319                         break;
1320                     case EADDRNOTAVAIL:
1321                         SetLastError(WSAEINVAL);
1322                         break;
1323                     default:
1324                         SetLastError(wsaErrno());
1325                         break;
1326                     }
1327                 }
1328                 else
1329                 {
1330                     res=0; /* success */
1331                 }
1332                 ws_sockaddr_free(uaddr,name);
1333             }
1334         }
1335         release_sock_fd( s, fd );
1336     }
1337     return res;
1338 }
1339
1340 /***********************************************************************
1341  *              closesocket             (WS2_32.3)
1342  */
1343 int WINAPI WS_closesocket(SOCKET s)
1344 {
1345     TRACE("socket %08x\n", s);
1346     if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1347     return SOCKET_ERROR;
1348 }
1349
1350 /***********************************************************************
1351  *              connect         (WS2_32.4)
1352  */
1353 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1354 {
1355     int fd = get_sock_fd( s, GENERIC_READ, NULL );
1356
1357     TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1358
1359     if (fd != -1)
1360     {
1361         const struct sockaddr* uaddr;
1362         int uaddrlen;
1363
1364         uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1365         if (uaddr == NULL)
1366         {
1367             SetLastError(WSAEFAULT);
1368         }
1369         else
1370         {
1371             int rc;
1372
1373             rc=connect(fd, uaddr, uaddrlen);
1374             ws_sockaddr_free(uaddr,name);
1375             if (rc == 0)
1376                 goto connect_success;
1377         }
1378
1379         if (errno == EINPROGRESS)
1380         {
1381             /* tell wineserver that a connection is in progress */
1382             _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1383                           FD_CONNECT|FD_READ|FD_WRITE,
1384                           FD_WINE_CONNECTED|FD_WINE_LISTENING);
1385             if (_is_blocking(s))
1386             {
1387                 int result;
1388                 /* block here */
1389                 do_block(fd, POLLIN | POLLOUT );
1390                 _sync_sock_state(s); /* let wineserver notice connection */
1391                 /* retrieve any error codes from it */
1392                 result = _get_sock_error(s, FD_CONNECT_BIT);
1393                 if (result)
1394                     SetLastError(result);
1395                 else
1396                 {
1397                     goto connect_success;
1398                 }
1399             }
1400             else
1401             {
1402                 SetLastError(WSAEWOULDBLOCK);
1403             }
1404         }
1405         else
1406         {
1407             SetLastError(wsaErrno());
1408         }
1409         release_sock_fd( s, fd );
1410     }
1411     return SOCKET_ERROR;
1412
1413 connect_success:
1414     release_sock_fd( s, fd );
1415     _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1416                   FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1417                   FD_CONNECT|FD_WINE_LISTENING);
1418     return 0;
1419 }
1420
1421 /***********************************************************************
1422  *              WSAConnect             (WS2_32.30)
1423  */
1424 int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
1425                         LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1426                         LPQOS lpSQOS, LPQOS lpGQOS )
1427 {
1428     if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1429         FIXME ("unsupported parameters!\n");
1430     return WS_connect ( s, name, namelen );
1431 }
1432
1433
1434 /***********************************************************************
1435  *              getpeername             (WS2_32.5)
1436  */
1437 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1438 {
1439     int fd;
1440     int res;
1441
1442     TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1443
1444     /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1445     if( (name == NULL) || (namelen == NULL) )
1446     {
1447         SetLastError( WSAEFAULT );
1448         return SOCKET_ERROR;
1449     }
1450
1451     fd = get_sock_fd( s, 0, NULL );
1452     res = SOCKET_ERROR;
1453
1454     if (fd != -1)
1455     {
1456         struct sockaddr* uaddr;
1457         int uaddrlen;
1458
1459         uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1460         if (getpeername(fd, uaddr, &uaddrlen) != 0)
1461         {
1462             SetLastError(wsaErrno());
1463         }
1464         else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1465         {
1466             /* The buffer was too small */
1467             SetLastError(WSAEFAULT);
1468         }
1469         else
1470         {
1471             res=0;
1472         }
1473         ws_sockaddr_free(uaddr,name);
1474         release_sock_fd( s, fd );
1475     }
1476     return res;
1477 }
1478
1479 /***********************************************************************
1480  *              getsockname             (WS2_32.6)
1481  */
1482 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1483 {
1484     int fd;
1485     int res;
1486
1487     TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1488
1489     /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1490     if( (name == NULL) || (namelen == NULL) )
1491     {
1492         SetLastError( WSAEFAULT );
1493         return SOCKET_ERROR;
1494     }
1495
1496     fd = get_sock_fd( s, 0, NULL );
1497     res = SOCKET_ERROR;
1498
1499     if (fd != -1)
1500     {
1501         struct sockaddr* uaddr;
1502         int uaddrlen;
1503
1504         uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1505         if (getsockname(fd, uaddr, &uaddrlen) != 0)
1506         {
1507             SetLastError(wsaErrno());
1508         }
1509         else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1510         {
1511             /* The buffer was too small */
1512             SetLastError(WSAEFAULT);
1513         }
1514         else
1515         {
1516             res=0;
1517         }
1518         release_sock_fd( s, fd );
1519     }
1520     return res;
1521 }
1522
1523 /***********************************************************************
1524  *              getsockopt              (WS2_32.7)
1525  */
1526 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1527                                   INT optname, char *optval, INT *optlen)
1528 {
1529     int fd;
1530
1531     TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1532           (int) optname, (int) optval, (int) *optlen);
1533     /* SO_OPENTYPE does not require a valid socket handle. */
1534     if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1535     {
1536         if (!optlen || *optlen < sizeof(int) || !optval)
1537         {
1538             SetLastError(WSAEFAULT);
1539             return SOCKET_ERROR;
1540         }
1541         *(int *)optval = (int)TlsGetValue( opentype_tls_index );
1542         *optlen = sizeof(int);
1543         TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1544         return 0;
1545     }
1546
1547     fd = get_sock_fd( s, 0, NULL );
1548     if (fd != -1)
1549     {
1550         if (!convert_sockopt(&level, &optname)) {
1551             SetLastError(WSAENOPROTOOPT);       /* Unknown option */
1552         } else {
1553             if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1554             {
1555                 release_sock_fd( s, fd );
1556                 return 0;
1557             }
1558             SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1559         }
1560         release_sock_fd( s, fd );
1561     }
1562     return SOCKET_ERROR;
1563 }
1564
1565
1566 /***********************************************************************
1567  *              htonl                   (WINSOCK.8)
1568  *              htonl                   (WS2_32.8)
1569  */
1570 u_long WINAPI WS_htonl(u_long hostlong)
1571 {
1572     return htonl(hostlong);
1573 }
1574
1575
1576 /***********************************************************************
1577  *              htons                   (WINSOCK.9)
1578  *              htons                   (WS2_32.9)
1579  */
1580 u_short WINAPI WS_htons(u_short hostshort)
1581 {
1582     return htons(hostshort);
1583 }
1584
1585
1586 /***********************************************************************
1587  *              inet_addr               (WINSOCK.10)
1588  *              inet_addr               (WS2_32.11)
1589  */
1590 u_long WINAPI WS_inet_addr(const char *cp)
1591 {
1592     return inet_addr(cp);
1593 }
1594
1595
1596 /***********************************************************************
1597  *              ntohl                   (WINSOCK.14)
1598  *              ntohl                   (WS2_32.14)
1599  */
1600 u_long WINAPI WS_ntohl(u_long netlong)
1601 {
1602     return ntohl(netlong);
1603 }
1604
1605
1606 /***********************************************************************
1607  *              ntohs                   (WINSOCK.15)
1608  *              ntohs                   (WS2_32.15)
1609  */
1610 u_short WINAPI WS_ntohs(u_short netshort)
1611 {
1612     return ntohs(netshort);
1613 }
1614
1615
1616 /***********************************************************************
1617  *              inet_ntoa               (WS2_32.12)
1618  */
1619 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1620 {
1621   /* use "buffer for dummies" here because some applications have
1622    * propensity to decode addresses in ws_hostent structure without
1623    * saving them first...
1624    */
1625     static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1626
1627     char* s = inet_ntoa(*((struct in_addr*)&in));
1628     if( s )
1629     {
1630         strcpy(dbuffer, s);
1631         return dbuffer;
1632     }
1633     SetLastError(wsaErrno());
1634     return NULL;
1635 }
1636
1637 /**********************************************************************
1638  *              WSAIoctl                (WS2_32.50)
1639  *
1640  *
1641  *   FIXME:  Only SIO_GET_INTERFACE_LIST option implemented.
1642  */
1643 INT WINAPI WSAIoctl (SOCKET s,
1644                      DWORD   dwIoControlCode,
1645                      LPVOID  lpvInBuffer,
1646                      DWORD   cbInBuffer,
1647                      LPVOID  lpbOutBuffer,
1648                      DWORD   cbOutBuffer,
1649                      LPDWORD lpcbBytesReturned,
1650                      LPWSAOVERLAPPED lpOverlapped,
1651                      LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1652 {
1653    int fd = get_sock_fd( s, 0, NULL );
1654
1655    if (fd == -1) return SOCKET_ERROR;
1656
1657    switch( dwIoControlCode )
1658    {
1659    case SIO_GET_INTERFACE_LIST:
1660        {
1661            INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1662            DWORD size, numInt, apiReturn;
1663
1664            TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1665
1666            if (!lpbOutBuffer)
1667            {
1668                release_sock_fd( s, fd );
1669                WSASetLastError(WSAEFAULT);
1670                return SOCKET_ERROR;
1671            }
1672            if (!lpcbBytesReturned)
1673            {
1674                release_sock_fd( s, fd );
1675                WSASetLastError(WSAEFAULT);
1676                return SOCKET_ERROR;
1677            }
1678
1679            apiReturn = GetAdaptersInfo(NULL, &size);
1680            if (apiReturn == ERROR_NO_DATA)
1681            {
1682                numInt = 0;
1683            }
1684            else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1685            {
1686                PIP_ADAPTER_INFO table = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(),0,size);
1687
1688                if (table)
1689                {
1690                   if (GetAdaptersInfo(table, &size) == NO_ERROR)
1691                   {
1692                      PIP_ADAPTER_INFO ptr;
1693
1694                      if (size > cbOutBuffer)
1695                      {
1696                         HeapFree(GetProcessHeap(),0,table);
1697                         release_sock_fd( s, fd );
1698                         WSASetLastError(WSAEFAULT);
1699                         return (SOCKET_ERROR);
1700                      }
1701                      for (ptr = table, numInt = 0; ptr;
1702                       ptr = ptr->Next, intArray++, numInt++)
1703                      {
1704                         unsigned int addr, mask, bcast;
1705                         struct ifreq ifInfo;
1706
1707                         /* Socket Status Flags */
1708                         strncpy(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
1709                         ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
1710                         if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1711                         {
1712                            ERR ("Error obtaining status flags for socket!\n");
1713                            HeapFree(GetProcessHeap(),0,table);
1714                            release_sock_fd( s, fd );
1715                            WSASetLastError(WSAEINVAL);
1716                            return (SOCKET_ERROR);
1717                         }
1718                         else
1719                         {
1720                            /* set flags; the values of IFF_* are not the same
1721                               under Linux and Windows, therefore must generate
1722                               new flags */
1723                            intArray->iiFlags = 0;
1724                            if (ifInfo.ifr_flags & IFF_BROADCAST)
1725                               intArray->iiFlags |= WS_IFF_BROADCAST;
1726 #ifdef IFF_POINTOPOINT
1727                            if (ifInfo.ifr_flags & IFF_POINTOPOINT)
1728                               intArray->iiFlags |= WS_IFF_POINTTOPOINT;
1729 #endif
1730                            if (ifInfo.ifr_flags & IFF_LOOPBACK)
1731                               intArray->iiFlags |= WS_IFF_LOOPBACK;
1732                            if (ifInfo.ifr_flags & IFF_UP)
1733                               intArray->iiFlags |= WS_IFF_UP;
1734                         }
1735
1736                         addr = inet_addr(ptr->IpAddressList.IpAddress.String);
1737                         mask = inet_addr(ptr->IpAddressList.IpMask.String);
1738                         bcast = addr | (addr & !mask);
1739                         intArray->iiAddress.AddressIn.sin_family = AF_INET;
1740                         intArray->iiAddress.AddressIn.sin_port = 0;
1741                         intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
1742                          addr;
1743                         intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1744                         intArray->iiNetmask.AddressIn.sin_port = 0;
1745                         intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
1746                          mask;
1747                         intArray->iiBroadcastAddress.AddressIn.sin_family =
1748                          AF_INET;
1749                         intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
1750                         intArray->iiBroadcastAddress.AddressIn.sin_addr.
1751                          WS_s_addr = bcast;
1752                      }
1753                   }
1754                   else
1755                   {
1756                      ERR ("Unable to get interface table!\n");
1757                      release_sock_fd( s, fd );
1758                      HeapFree(GetProcessHeap(),0,table);
1759                      WSASetLastError(WSAEINVAL);
1760                      return (SOCKET_ERROR);
1761                   }
1762                   HeapFree(GetProcessHeap(),0,table);
1763                }
1764                else
1765                {
1766                   release_sock_fd( s, fd );
1767                   WSASetLastError(WSAEINVAL);
1768                   return (SOCKET_ERROR);
1769                }
1770            }
1771            else
1772            {
1773                ERR ("Unable to get interface table!\n");
1774                release_sock_fd( s, fd );
1775                WSASetLastError(WSAEINVAL);
1776                return (SOCKET_ERROR);
1777            }
1778            /* Calculate the size of the array being returned */
1779            *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1780            break;
1781        }
1782
1783    default:
1784        WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1785        release_sock_fd( s, fd );
1786        WSASetLastError(WSAEOPNOTSUPP);
1787        return (SOCKET_ERROR);
1788    }
1789
1790    /* Function executed with no errors */
1791    release_sock_fd( s, fd );
1792    return (0);
1793 }
1794
1795
1796 /***********************************************************************
1797  *              ioctlsocket             (WS2_32.10)
1798  */
1799 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
1800 {
1801     int fd;
1802     long newcmd  = cmd;
1803
1804     TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
1805
1806     switch( cmd )
1807     {
1808     case WS_FIONREAD:
1809         newcmd=FIONREAD;
1810         break;
1811
1812     case WS_FIONBIO:
1813         newcmd=FIONBIO;
1814         if( _get_sock_mask(s) )
1815         {
1816             /* AsyncSelect()'ed sockets are always nonblocking */
1817             if (*argp) return 0;
1818             SetLastError(WSAEINVAL);
1819             return SOCKET_ERROR;
1820         }
1821         if (*argp)
1822             _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
1823         else
1824             _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
1825         return 0;
1826
1827     case WS_SIOCATMARK:
1828         newcmd=SIOCATMARK;
1829         break;
1830
1831     case WS__IOW('f',125,u_long):
1832         WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1833         SetLastError(WSAEINVAL);
1834         return SOCKET_ERROR;
1835
1836     case SIOCGIFBRDADDR:
1837     case SIOCGIFNETMASK:
1838     case SIOCGIFADDR:
1839         /* These don't need any special handling.  They are used by
1840            WsControl, and are here to suppress an unecessary warning. */
1841         break;
1842
1843     default:
1844         /* Netscape tries hard to use bogus ioctl 0x667e */
1845         WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1846         break;
1847     }
1848
1849     fd = get_sock_fd( s, 0, NULL );
1850     if (fd != -1)
1851     {
1852         if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1853         {
1854             release_sock_fd( s, fd );
1855             return 0;
1856         }
1857         SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1858         release_sock_fd( s, fd );
1859     }
1860     return SOCKET_ERROR;
1861 }
1862
1863 /***********************************************************************
1864  *              listen          (WS2_32.13)
1865  */
1866 int WINAPI WS_listen(SOCKET s, int backlog)
1867 {
1868     int fd = get_sock_fd( s, GENERIC_READ, NULL );
1869
1870     TRACE("socket %04x, backlog %d\n", s, backlog);
1871     if (fd != -1)
1872     {
1873         if (listen(fd, backlog) == 0)
1874         {
1875             release_sock_fd( s, fd );
1876             _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
1877                           FD_WINE_LISTENING,
1878                           FD_CONNECT|FD_WINE_CONNECTED);
1879             return 0;
1880         }
1881         SetLastError(wsaErrno());
1882         release_sock_fd( s, fd );
1883     }
1884     return SOCKET_ERROR;
1885 }
1886
1887 /***********************************************************************
1888  *              recv                    (WS2_32.16)
1889  */
1890 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
1891 {
1892     DWORD n, dwFlags = flags;
1893     WSABUF wsabuf;
1894
1895     wsabuf.len = len;
1896     wsabuf.buf = buf;
1897
1898     if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
1899         return SOCKET_ERROR;
1900     else
1901         return n;
1902 }
1903
1904 /***********************************************************************
1905  *              recvfrom                (WS2_32.17)
1906  */
1907 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
1908                                 struct WS_sockaddr *from, int *fromlen)
1909 {
1910     DWORD n, dwFlags = flags;
1911     WSABUF wsabuf;
1912
1913     wsabuf.len = len;
1914     wsabuf.buf = buf;
1915
1916     if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
1917         return SOCKET_ERROR;
1918     else
1919         return n;
1920 }
1921
1922 /***********************************************************************
1923  *              select                  (WS2_32.18)
1924  */
1925 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
1926                      WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
1927                      const struct WS_timeval* ws_timeout)
1928 {
1929     int         highfd = 0;
1930     fd_set      readfds, writefds, exceptfds;
1931     fd_set     *p_read, *p_write, *p_except;
1932     int         readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1933     struct timeval timeout, *timeoutaddr = NULL;
1934
1935     TRACE("read %p, write %p, excp %p timeout %p\n",
1936           ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
1937
1938     p_read = fd_set_import(&readfds, ws_readfds, GENERIC_READ, &highfd, readfd);
1939     p_write = fd_set_import(&writefds, ws_writefds, GENERIC_WRITE, &highfd, writefd);
1940     p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
1941     if (ws_timeout)
1942     {
1943         timeoutaddr = &timeout;
1944         timeout.tv_sec=ws_timeout->tv_sec;
1945         timeout.tv_usec=ws_timeout->tv_usec;
1946     }
1947
1948     if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
1949     {
1950         fd_set_export(&readfds, p_except, ws_readfds, readfd);
1951         fd_set_export(&writefds, p_except, ws_writefds, writefd);
1952
1953         if (p_except && ws_exceptfds)
1954         {
1955             int i, j;
1956
1957             for (i = j = 0; i < ws_exceptfds->fd_count; i++)
1958             {
1959                 int fd = exceptfd[i];
1960                 SOCKET s = ws_exceptfds->fd_array[i];
1961                 if (fd == -1) continue;
1962                 if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
1963                 release_sock_fd( s, fd );
1964             }
1965             ws_exceptfds->fd_count = j;
1966         }
1967         return highfd;
1968     }
1969     fd_set_unimport(ws_readfds, readfd);
1970     fd_set_unimport(ws_writefds, writefd);
1971     fd_set_unimport(ws_exceptfds, exceptfd);
1972
1973     if( highfd == 0 ) return 0;
1974     SetLastError(wsaErrno());
1975     return SOCKET_ERROR;
1976 }
1977
1978
1979 /***********************************************************************
1980  *              send                    (WS2_32.19)
1981  */
1982 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
1983 {
1984     DWORD n;
1985     WSABUF wsabuf;
1986
1987     wsabuf.len = len;
1988     wsabuf.buf = (char*) buf;
1989
1990     if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
1991         return SOCKET_ERROR;
1992     else
1993         return n;
1994 }
1995
1996 /***********************************************************************
1997  *              WSASend                 (WS2_32.72)
1998  */
1999 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2000                     LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2001                     LPWSAOVERLAPPED lpOverlapped,
2002                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2003 {
2004     return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2005                        NULL, 0, lpOverlapped, lpCompletionRoutine );
2006 }
2007
2008 /***********************************************************************
2009  *              WSASendDisconnect       (WS2_32.73)
2010  */
2011 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2012 {
2013     return WS_shutdown ( s, SD_SEND );
2014 }
2015
2016
2017 /***********************************************************************
2018  *              WSASendTo               (WS2_32.74)
2019  */
2020 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2021                       LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2022                       const struct WS_sockaddr *to, int tolen,
2023                       LPWSAOVERLAPPED lpOverlapped,
2024                       LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2025 {
2026     int i, n, fd, err = WSAENOTSOCK, flags, ret;
2027     struct iovec* iovec;
2028     struct ws2_async *wsa;
2029
2030     TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2031            s, lpBuffers, dwBufferCount, dwFlags,
2032            to, tolen, lpOverlapped, lpCompletionRoutine);
2033
2034     fd = get_sock_fd( s, GENERIC_WRITE, &flags );
2035     TRACE ( "fd=%d, flags=%x\n", fd, flags );
2036
2037     if ( fd == -1 ) return SOCKET_ERROR;
2038
2039     if (flags & FD_FLAG_SEND_SHUTDOWN)
2040     {
2041         WSASetLastError ( WSAESHUTDOWN );
2042         goto err_close;
2043     }
2044
2045     if ( !lpNumberOfBytesSent )
2046     {
2047         err = WSAEFAULT;
2048         goto err_close;
2049     }
2050
2051     iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
2052
2053     if ( !iovec )
2054     {
2055         err = WSAEFAULT;
2056         goto err_close;
2057     }
2058
2059     for ( i = 0; i < dwBufferCount; i++ )
2060     {
2061         iovec[i].iov_base = lpBuffers[i].buf;
2062         iovec[i].iov_len  = lpBuffers[i].len;
2063     }
2064
2065     if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2066     {
2067         wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
2068                                &dwFlags, (struct WS_sockaddr*) to, &tolen,
2069                                lpOverlapped, lpCompletionRoutine );
2070         if ( !wsa )
2071         {
2072             err = WSAEFAULT;
2073             goto err_free;
2074         }
2075
2076         if ( ( ret = register_new_async ( &wsa->async )) )
2077         {
2078             err = NtStatusToWSAError ( ret );
2079
2080             if ( !lpOverlapped )
2081                 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
2082             HeapFree ( GetProcessHeap(), 0, wsa );
2083             goto err_free;
2084         }
2085
2086         /* Try immediate completion */
2087         if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
2088         {
2089             if  ( WSAGetOverlappedResult ( s, lpOverlapped,
2090                                            lpNumberOfBytesSent, FALSE, &dwFlags) )
2091                 return 0;
2092
2093             if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
2094                 goto error;
2095         }
2096
2097         WSASetLastError ( WSA_IO_PENDING );
2098         return SOCKET_ERROR;
2099     }
2100
2101     if (_is_blocking(s))
2102     {
2103         /* FIXME: exceptfds? */
2104         do_block(fd, POLLOUT);
2105     }
2106
2107     n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2108     if ( n == -1 )
2109     {
2110         err = wsaErrno();
2111         if ( err == WSAEWOULDBLOCK )
2112             _enable_event (SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2113         goto err_free;
2114     }
2115
2116     TRACE(" -> %i bytes\n", n);
2117     *lpNumberOfBytesSent = n;
2118
2119     HeapFree ( GetProcessHeap(), 0, iovec );
2120     release_sock_fd( s, fd );
2121     return 0;
2122
2123 err_free:
2124     HeapFree ( GetProcessHeap(), 0, iovec );
2125
2126 err_close:
2127     release_sock_fd( s, fd );
2128
2129 error:
2130     WARN (" -> ERROR %d\n", err);
2131     WSASetLastError (err);
2132     return SOCKET_ERROR;
2133 }
2134
2135 /***********************************************************************
2136  *              sendto          (WS2_32.20)
2137  */
2138 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2139                               const struct WS_sockaddr *to, int tolen)
2140 {
2141     DWORD n;
2142     WSABUF wsabuf;
2143
2144     wsabuf.len = len;
2145     wsabuf.buf = (char*) buf;
2146
2147     if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2148         return SOCKET_ERROR;
2149     else
2150         return n;
2151 }
2152
2153 /***********************************************************************
2154  *              setsockopt              (WS2_32.21)
2155  */
2156 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2157                                   const char *optval, int optlen)
2158 {
2159     int fd;
2160     int woptval;
2161     struct linger linger;
2162     struct timeval tval;
2163
2164     TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
2165           s, level, optname, optval, optlen);
2166
2167     /* SO_OPENTYPE does not require a valid socket handle. */
2168     if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2169     {
2170         if (optlen < sizeof(int) || !optval)
2171         {
2172             SetLastError(WSAEFAULT);
2173             return SOCKET_ERROR;
2174         }
2175         TlsSetValue( opentype_tls_index, (LPVOID)*(int *)optval );
2176         TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2177         return 0;
2178     }
2179
2180     /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2181      * socket. This will either not happen under windows or it is ignored in
2182      * windows (but it works in linux and therefor prevents the game to find
2183      * games outsite the current network) */
2184     if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE ) 
2185     {
2186         FIXME("Does windows ignore SO_DONTROUTE?\n");
2187         return 0;
2188     }
2189
2190     /* Is a privileged and useless operation, so we don't. */
2191     if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
2192     {
2193         FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2194         return 0;
2195     }
2196
2197     if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2198         /* This is unique to WinSock and takes special conversion */
2199         linger.l_onoff  = *((int*)optval) ? 0: 1;
2200         linger.l_linger = 0;
2201         optname=SO_LINGER;
2202         optval = (char*)&linger;
2203         optlen = sizeof(struct linger);
2204         level = SOL_SOCKET;
2205     }
2206     else
2207     {
2208         if (!convert_sockopt(&level, &optname)) {
2209             ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2210             SetLastError(WSAENOPROTOOPT);
2211             return SOCKET_ERROR;
2212         }
2213         if (optname == SO_LINGER && optval) {
2214             /* yes, uses unsigned short in both win16/win32 */
2215             linger.l_onoff  = ((UINT16*)optval)[0];
2216             linger.l_linger = ((UINT16*)optval)[1];
2217             /* FIXME: what is documented behavior if SO_LINGER optval
2218                is null?? */
2219             optval = (char*)&linger;
2220             optlen = sizeof(struct linger);
2221         }
2222         else if (optval && optlen < sizeof(int))
2223         {
2224             woptval= *((INT16 *) optval);
2225             optval= (char*) &woptval;
2226             optlen=sizeof(int);
2227         }
2228         if (level == SOL_SOCKET && is_timeout_option(optname))
2229         {
2230             if (optlen == sizeof(UINT32)) {
2231                 /* WinSock passes miliseconds instead of struct timeval */
2232                 tval.tv_usec = *(PUINT32)optval % 1000;
2233                 tval.tv_sec = *(PUINT32)optval / 1000;
2234                 /* min of 500 milisec */
2235                 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2236                 optlen = sizeof(struct timeval);
2237                 optval = (char*)&tval;
2238             } else if (optlen == sizeof(struct timeval)) {
2239                 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2240             } else {
2241                 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2242                 return 0;
2243             }
2244         }
2245         if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
2246         {
2247             WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2248             return 0;
2249         }
2250     }
2251
2252
2253     fd = get_sock_fd( s, 0, NULL );
2254     if (fd == -1) return SOCKET_ERROR;
2255
2256     if (setsockopt(fd, level, optname, optval, optlen) == 0)
2257     {
2258         release_sock_fd( s, fd );
2259         return 0;
2260     }
2261     TRACE("Setting socket error, %d\n", wsaErrno());
2262     SetLastError(wsaErrno());
2263     release_sock_fd( s, fd );
2264     return SOCKET_ERROR;
2265 }
2266
2267 /***********************************************************************
2268  *              shutdown                (WS2_32.22)
2269  */
2270 int WINAPI WS_shutdown(SOCKET s, int how)
2271 {
2272     int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2273     unsigned int clear_flags = 0;
2274
2275     fd = get_sock_fd( s, 0, &flags );
2276     TRACE("socket %04x, how %i %x\n", s, how, flags );
2277
2278     if (fd == -1)
2279         return SOCKET_ERROR;
2280
2281     switch( how )
2282     {
2283     case 0: /* drop receives */
2284         clear_flags |= FD_READ;
2285         break;
2286     case 1: /* drop sends */
2287         clear_flags |= FD_WRITE;
2288         break;
2289     case 2: /* drop all */
2290         clear_flags |= FD_READ|FD_WRITE;
2291     default:
2292         clear_flags |= FD_WINE_LISTENING;
2293     }
2294
2295     if ( flags & FD_FLAG_OVERLAPPED ) {
2296
2297         switch ( how )
2298         {
2299         case SD_RECEIVE:
2300             fd0 = fd;
2301             break;
2302         case SD_SEND:
2303             fd1 = fd;
2304             break;
2305         case SD_BOTH:
2306         default:
2307             fd0 = fd;
2308             fd1 = get_sock_fd ( s, 0, NULL );
2309             break;
2310         }
2311
2312         if ( fd0 != -1 )
2313         {
2314             err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
2315             if ( err )
2316             {
2317                 release_sock_fd( s, fd0 );
2318                 goto error;
2319             }
2320         }
2321         if ( fd1 != -1 )
2322         {
2323             err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
2324             if ( err )
2325             {
2326                 release_sock_fd( s, fd1 );
2327                 goto error;
2328             }
2329         }
2330     }
2331     else /* non-overlapped mode */
2332     {
2333         if ( shutdown( fd, how ) )
2334         {
2335             err = wsaErrno ();
2336             release_sock_fd( s, fd );
2337             goto error;
2338         }
2339         release_sock_fd( s, fd );
2340     }
2341
2342     _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2343     if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2344     return 0;
2345
2346 error:
2347     _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2348     WSASetLastError ( err );
2349     return SOCKET_ERROR;
2350 }
2351
2352 /***********************************************************************
2353  *              socket          (WS2_32.23)
2354  */
2355 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2356 {
2357     TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2358
2359     return WSASocketA ( af, type, protocol, NULL, 0,
2360                         (TlsGetValue(opentype_tls_index) ? 0 : WSA_FLAG_OVERLAPPED) );
2361 }
2362
2363
2364 /***********************************************************************
2365  *              gethostbyaddr           (WS2_32.51)
2366  */
2367 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
2368 {
2369     struct WS_hostent *retval = NULL;
2370     struct hostent* host;
2371
2372 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2373     char *extrabuf;
2374     int ebufsize=1024;
2375     struct hostent hostentry;
2376     int locerr=ENOBUFS;
2377     host = NULL;
2378     extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2379     while(extrabuf) {
2380         int res = gethostbyaddr_r(addr, len, type,
2381                                   &hostentry, extrabuf, ebufsize, &host, &locerr);
2382         if( res != ERANGE) break;
2383         ebufsize *=2;
2384         extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2385     }
2386     if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2387 #else
2388     EnterCriticalSection( &csWSgetXXXbyYYY );
2389     host = gethostbyaddr(addr, len, type);
2390     if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2391 #endif
2392     if( host != NULL ) retval = WS_dup_he(host);
2393 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2394     HeapFree(GetProcessHeap(),0,extrabuf);
2395 #else
2396     LeaveCriticalSection( &csWSgetXXXbyYYY );
2397 #endif
2398     TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
2399     return retval;
2400 }
2401
2402 /***********************************************************************
2403  *              gethostbyname           (WS2_32.52)
2404  */
2405 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2406 {
2407     struct WS_hostent *retval = NULL;
2408     struct hostent*     host;
2409 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2410     char *extrabuf;
2411     int ebufsize=1024;
2412     struct hostent hostentry;
2413     int locerr = ENOBUFS;
2414 #endif
2415     char buf[100];
2416     if( !name) {
2417         name = buf;
2418         if( gethostname( buf, 100) == -1) {
2419             SetLastError( WSAENOBUFS); /* appropriate ? */
2420             return retval;
2421         }
2422     }
2423 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2424     host = NULL;
2425     extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2426     while(extrabuf) {
2427         int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2428         if( res != ERANGE) break;
2429         ebufsize *=2;
2430         extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2431     }
2432     if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2433 #else
2434     EnterCriticalSection( &csWSgetXXXbyYYY );
2435     host = gethostbyname(name);
2436     if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2437 #endif
2438     if (host) retval = WS_dup_he(host);
2439 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2440     HeapFree(GetProcessHeap(),0,extrabuf);
2441 #else
2442     LeaveCriticalSection( &csWSgetXXXbyYYY );
2443 #endif
2444     TRACE( "%s ret %p\n", debugstr_a(name), retval );
2445     return retval;
2446 }
2447
2448
2449 /***********************************************************************
2450  *              getprotobyname          (WS2_32.53)
2451  */
2452 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2453 {
2454     struct WS_protoent* retval = NULL;
2455 #ifdef HAVE_GETPROTOBYNAME
2456     struct protoent*     proto;
2457     EnterCriticalSection( &csWSgetXXXbyYYY );
2458     if( (proto = getprotobyname(name)) != NULL )
2459     {
2460         retval = WS_dup_pe(proto);
2461     }
2462     else {
2463         MESSAGE("protocol %s not found; You might want to add "
2464                 "this to /etc/protocols\n", debugstr_a(name) );
2465         SetLastError(WSANO_DATA);
2466     }
2467     LeaveCriticalSection( &csWSgetXXXbyYYY );
2468 #endif
2469     TRACE( "%s ret %p\n", debugstr_a(name), retval );
2470     return retval;
2471 }
2472
2473
2474 /***********************************************************************
2475  *              getprotobynumber        (WS2_32.54)
2476  */
2477 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
2478 {
2479     struct WS_protoent* retval = NULL;
2480 #ifdef HAVE_GETPROTOBYNUMBER
2481     struct protoent*     proto;
2482     EnterCriticalSection( &csWSgetXXXbyYYY );
2483     if( (proto = getprotobynumber(number)) != NULL )
2484     {
2485         retval = WS_dup_pe(proto);
2486     }
2487     else {
2488         MESSAGE("protocol number %d not found; You might want to add "
2489                 "this to /etc/protocols\n", number );
2490         SetLastError(WSANO_DATA);
2491     }
2492     LeaveCriticalSection( &csWSgetXXXbyYYY );
2493 #endif
2494     TRACE("%i ret %p\n", number, retval);
2495     return retval;
2496 }
2497
2498
2499 /***********************************************************************
2500  *              getservbyname           (WS2_32.55)
2501  */
2502 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
2503 {
2504     struct WS_servent* retval = NULL;
2505     struct servent*     serv;
2506     char *name_str;
2507     char *proto_str = NULL;
2508
2509     if (!(name_str = strdup_lower(name))) return NULL;
2510
2511     if (proto && *proto)
2512     {
2513         if (!(proto_str = strdup_lower(proto)))
2514         {
2515             HeapFree( GetProcessHeap(), 0, name_str );
2516             return NULL;
2517         }
2518     }
2519
2520     EnterCriticalSection( &csWSgetXXXbyYYY );
2521     serv = getservbyname(name_str, proto_str);
2522     if( serv != NULL )
2523     {
2524         retval = WS_dup_se(serv);
2525     }
2526     else SetLastError(WSANO_DATA);
2527     LeaveCriticalSection( &csWSgetXXXbyYYY );
2528     if (proto_str) HeapFree( GetProcessHeap(), 0, proto_str );
2529     HeapFree( GetProcessHeap(), 0, name_str );
2530     TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
2531     return retval;
2532 }
2533
2534
2535 /***********************************************************************
2536  *              getservbyport           (WS2_32.56)
2537  */
2538 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
2539 {
2540     struct WS_servent* retval = NULL;
2541 #ifdef HAVE_GETSERVBYPORT
2542     struct servent*     serv;
2543     char *proto_str = NULL;
2544
2545     if (proto && *proto)
2546     {
2547         if (!(proto_str = strdup_lower(proto))) return NULL;
2548     }
2549     EnterCriticalSection( &csWSgetXXXbyYYY );
2550     if( (serv = getservbyport(port, proto_str)) != NULL ) {
2551         retval = WS_dup_se(serv);
2552     }
2553     else SetLastError(WSANO_DATA);
2554     LeaveCriticalSection( &csWSgetXXXbyYYY );
2555     if (proto_str) HeapFree( GetProcessHeap(), 0, proto_str );
2556 #endif
2557     TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
2558     return retval;
2559 }
2560
2561
2562 /***********************************************************************
2563  *              gethostname           (WS2_32.57)
2564  */
2565 int WINAPI WS_gethostname(char *name, int namelen)
2566 {
2567     TRACE("name %p, len %d\n", name, namelen);
2568
2569     if (gethostname(name, namelen) == 0)
2570     {
2571         TRACE("<- '%s'\n", name);
2572         return 0;
2573     }
2574     SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2575     TRACE("<- ERROR !\n");
2576     return SOCKET_ERROR;
2577 }
2578
2579
2580 /* ------------------------------------- Windows sockets extensions -- *
2581  *                                                                     *
2582  * ------------------------------------------------------------------- */
2583
2584 /***********************************************************************
2585  *              WSAEnumNetworkEvents (WS2_32.36)
2586  */
2587 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2588 {
2589     int ret;
2590
2591     TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2592
2593     SERVER_START_REQ( get_socket_event )
2594     {
2595         req->handle  = SOCKET2HANDLE(s);
2596         req->service = TRUE;
2597         req->c_event = hEvent;
2598         wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
2599         if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
2600     }
2601     SERVER_END_REQ;
2602     if (!ret) return 0;
2603     SetLastError(WSAEINVAL);
2604     return SOCKET_ERROR;
2605 }
2606
2607 /***********************************************************************
2608  *              WSAEventSelect (WS2_32.39)
2609  */
2610 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2611 {
2612     int ret;
2613
2614     TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
2615
2616     SERVER_START_REQ( set_socket_event )
2617     {
2618         req->handle = SOCKET2HANDLE(s);
2619         req->mask   = lEvent;
2620         req->event  = hEvent;
2621         req->window = 0;
2622         req->msg    = 0;
2623         ret = wine_server_call( req );
2624     }
2625     SERVER_END_REQ;
2626     if (!ret) return 0;
2627     SetLastError(WSAEINVAL);
2628     return SOCKET_ERROR;
2629 }
2630
2631 /**********************************************************************
2632  *      WSAGetOverlappedResult (WS2_32.40)
2633  */
2634 BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
2635                                      LPDWORD lpcbTransfer, BOOL fWait,
2636                                      LPDWORD lpdwFlags )
2637 {
2638     DWORD r;
2639
2640     TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
2641             s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
2642
2643     if ( !(lpOverlapped && lpOverlapped->hEvent) )
2644     {
2645         ERR ( "Invalid pointer\n" );
2646         WSASetLastError (WSA_INVALID_PARAMETER);
2647         return FALSE;
2648     }
2649
2650     if ( fWait )
2651     {
2652         while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC );
2653     }
2654     else if ( lpOverlapped->Internal == STATUS_PENDING )
2655     {
2656         /* Wait in order to give APCs a chance to run. */
2657         /* This is cheating, so we must set the event again in case of success -
2658            it may be a non-manual reset event. */
2659         while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
2660         if ( r == WAIT_OBJECT_0 )
2661             NtSetEvent ( lpOverlapped->hEvent, NULL );
2662     }
2663
2664     if ( lpcbTransfer )
2665         *lpcbTransfer = lpOverlapped->InternalHigh;
2666
2667     if ( lpdwFlags )
2668         *lpdwFlags = lpOverlapped->Offset;
2669
2670     switch ( lpOverlapped->Internal )
2671     {
2672     case STATUS_SUCCESS:
2673         return TRUE;
2674     case STATUS_PENDING:
2675         WSASetLastError ( WSA_IO_INCOMPLETE );
2676         if (fWait) ERR ("PENDING status after waiting!\n");
2677         return FALSE;
2678     default:
2679         WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
2680         return FALSE;
2681     }
2682 }
2683
2684
2685 /***********************************************************************
2686  *      WSAAsyncSelect                  (WS2_32.101)
2687  */
2688 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2689 {
2690     int ret;
2691
2692     TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
2693
2694     SERVER_START_REQ( set_socket_event )
2695     {
2696         req->handle = SOCKET2HANDLE(s);
2697         req->mask   = lEvent;
2698         req->event  = 0;
2699         req->window = hWnd;
2700         req->msg    = uMsg;
2701         ret = wine_server_call( req );
2702     }
2703     SERVER_END_REQ;
2704     if (!ret) return 0;
2705     SetLastError(WSAEINVAL);
2706     return SOCKET_ERROR;
2707 }
2708
2709 /***********************************************************************
2710  *      WSACreateEvent          (WS2_32.31)
2711  *
2712  */
2713 WSAEVENT WINAPI WSACreateEvent(void)
2714 {
2715     /* Create a manual-reset event, with initial state: unsignealed */
2716     TRACE("\n");
2717
2718     return CreateEventA(NULL, TRUE, FALSE, NULL);
2719 }
2720
2721 /***********************************************************************
2722  *      WSACloseEvent          (WS2_32.29)
2723  *
2724  */
2725 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2726 {
2727     TRACE ("event=%p\n", event);
2728
2729     return CloseHandle(event);
2730 }
2731
2732 /***********************************************************************
2733  *      WSASocketA          (WS2_32.78)
2734  *
2735  */
2736 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2737                          LPWSAPROTOCOL_INFOA lpProtocolInfo,
2738                          GROUP g, DWORD dwFlags)
2739 {
2740     SOCKET ret;
2741
2742    /*
2743       FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2744       g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
2745    */
2746
2747    TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2748          af, type, protocol, lpProtocolInfo, g, dwFlags );
2749
2750     /* hack for WSADuplicateSocket */
2751     if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
2752       ret = lpProtocolInfo->dwCatalogEntryId;
2753       TRACE("\tgot duplicate %04x\n", ret);
2754       return ret;
2755     }
2756
2757     /* check the socket family */
2758     switch(af)
2759     {
2760 #ifdef HAVE_IPX
2761         case WS_AF_IPX: af = AF_IPX;
2762 #endif
2763         case AF_INET:
2764         case AF_UNSPEC:
2765             break;
2766         default:
2767             SetLastError(WSAEAFNOSUPPORT);
2768             return INVALID_SOCKET;
2769     }
2770
2771     /* check the socket type */
2772     switch(type)
2773     {
2774         case WS_SOCK_STREAM:
2775             type=SOCK_STREAM;
2776             break;
2777         case WS_SOCK_DGRAM:
2778             type=SOCK_DGRAM;
2779             break;
2780         case WS_SOCK_RAW:
2781             type=SOCK_RAW;
2782             break;
2783         default:
2784             SetLastError(WSAESOCKTNOSUPPORT);
2785             return INVALID_SOCKET;
2786     }
2787
2788     /* check the protocol type */
2789     if ( protocol < 0 )  /* don't support negative values */
2790     {
2791         SetLastError(WSAEPROTONOSUPPORT);
2792         return INVALID_SOCKET;
2793     }
2794
2795     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
2796         switch(protocol)
2797         {
2798           case IPPROTO_TCP:
2799              if (type == SOCK_STREAM) { af = AF_INET; break; }
2800           case IPPROTO_UDP:
2801              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
2802           default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2803         }
2804
2805     SERVER_START_REQ( create_socket )
2806     {
2807         req->family   = af;
2808         req->type     = type;
2809         req->protocol = protocol;
2810         req->access   = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2811         req->flags    = dwFlags;
2812         req->inherit  = TRUE;
2813         set_error( wine_server_call( req ) );
2814         ret = HANDLE2SOCKET( reply->handle );
2815     }
2816     SERVER_END_REQ;
2817     if (ret)
2818     {
2819         TRACE("\tcreated %04x\n", ret );
2820         return ret;
2821     }
2822
2823     if (GetLastError() == WSAEACCES) /* raw socket denied */
2824     {
2825         if (type == SOCK_RAW)
2826             MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2827         else
2828             MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2829         SetLastError(WSAESOCKTNOSUPPORT);
2830     }
2831
2832     WARN("\t\tfailed!\n");
2833     return INVALID_SOCKET;
2834 }
2835
2836
2837 /***********************************************************************
2838  *      __WSAFDIsSet                    (WS2_32.151)
2839  */
2840 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
2841 {
2842   int i = set->fd_count;
2843
2844   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2845
2846   while (i--)
2847       if (set->fd_array[i] == s) return 1;
2848   return 0;
2849 }
2850
2851 /***********************************************************************
2852  *      WSAIsBlocking                   (WINSOCK.114)
2853  *      WSAIsBlocking                   (WS2_32.114)
2854  */
2855 BOOL WINAPI WSAIsBlocking(void)
2856 {
2857   /* By default WinSock should set all its sockets to non-blocking mode
2858    * and poll in PeekMessage loop when processing "blocking" ones. This
2859    * function is supposed to tell if the program is in this loop. Our
2860    * blocking calls are truly blocking so we always return FALSE.
2861    *
2862    * Note: It is allowed to call this function without prior WSAStartup().
2863    */
2864
2865   TRACE("\n");
2866   return FALSE;
2867 }
2868
2869 /***********************************************************************
2870  *      WSACancelBlockingCall           (WINSOCK.113)
2871  *      WSACancelBlockingCall           (WS2_32.113)
2872  */
2873 INT WINAPI WSACancelBlockingCall(void)
2874 {
2875     TRACE("\n");
2876     return 0;
2877 }
2878
2879 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
2880 {
2881     FIXME("How was this called?\n");
2882     return x();
2883 }
2884
2885
2886 /***********************************************************************
2887  *      WSASetBlockingHook (WS2_32.109)
2888  */
2889 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2890 {
2891   FARPROC prev = blocking_hook;
2892   blocking_hook = lpBlockFunc;
2893   TRACE("hook %p\n", lpBlockFunc);
2894   return prev;
2895 }
2896
2897
2898 /***********************************************************************
2899  *      WSAUnhookBlockingHook (WS2_32.110)
2900  */
2901 INT WINAPI WSAUnhookBlockingHook(void)
2902 {
2903     blocking_hook = WSA_DefaultBlockingHook;
2904     return 0;
2905 }
2906
2907
2908 /* ----------------------------------- end of API stuff */
2909
2910 /* ----------------------------------- helper functions -
2911  *
2912  * TODO: Merge WS_dup_..() stuff into one function that
2913  * would operate with a generic structure containing internal
2914  * pointers (via a template of some kind).
2915  */
2916
2917 static int list_size(char** l, int item_size)
2918 {
2919   int i,j = 0;
2920   if(l)
2921   { for(i=0;l[i];i++)
2922         j += (item_size) ? item_size : strlen(l[i]) + 1;
2923     j += (i + 1) * sizeof(char*); }
2924   return j;
2925 }
2926
2927 static int list_dup(char** l_src, char** l_to, int item_size)
2928 {
2929    char *p;
2930    int i;
2931
2932    for (i = 0; l_src[i]; i++) ;
2933    p = (char *)(l_to + i + 1);
2934    for (i = 0; l_src[i]; i++)
2935    {
2936        int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2937        memcpy(p, l_src[i], count);
2938        l_to[i] = p;
2939        p += count;
2940    }
2941    l_to[i] = NULL;
2942    return (p - (char *)l_to);
2943 }
2944
2945 /* ----- hostent */
2946
2947 /* duplicate hostent entry
2948  * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
2949  * Dito for protoent and servent.
2950  */
2951 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
2952 {
2953     char *p;
2954     struct WS_hostent *p_to;
2955
2956     int size = (sizeof(*p_he) +
2957                 strlen(p_he->h_name) + 1 +
2958                 list_size(p_he->h_aliases, 0) +
2959                 list_size(p_he->h_addr_list, p_he->h_length));
2960
2961     if (!(p_to = check_buffer_he(size))) return NULL;
2962     p_to->h_addrtype = p_he->h_addrtype;
2963     p_to->h_length = p_he->h_length;
2964
2965     p = (char *)(p_to + 1);
2966     p_to->h_name = p;
2967     strcpy(p, p_he->h_name);
2968     p += strlen(p) + 1;
2969
2970     p_to->h_aliases = (char **)p;
2971     p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
2972
2973     p_to->h_addr_list = (char **)p;
2974     list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
2975     return p_to;
2976 }
2977
2978 /* ----- protoent */
2979
2980 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
2981 {
2982     char *p;
2983     struct WS_protoent *p_to;
2984
2985     int size = (sizeof(*p_pe) +
2986                 strlen(p_pe->p_name) + 1 +
2987                 list_size(p_pe->p_aliases, 0));
2988
2989     if (!(p_to = check_buffer_pe(size))) return NULL;
2990     p_to->p_proto = p_pe->p_proto;
2991
2992     p = (char *)(p_to + 1);
2993     p_to->p_name = p;
2994     strcpy(p, p_pe->p_name);
2995     p += strlen(p) + 1;
2996
2997     p_to->p_aliases = (char **)p;
2998     list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
2999     return p_to;
3000 }
3001
3002 /* ----- servent */
3003
3004 static struct WS_servent *WS_dup_se(const struct servent* p_se)
3005 {
3006     char *p;
3007     struct WS_servent *p_to;
3008
3009     int size = (sizeof(*p_se) +
3010                 strlen(p_se->s_proto) + 1 +
3011                 strlen(p_se->s_name) + 1 +
3012                 list_size(p_se->s_aliases, 0));
3013
3014     if (!(p_to = check_buffer_se(size))) return NULL;
3015     p_to->s_port = p_se->s_port;
3016
3017     p = (char *)(p_to + 1);
3018     p_to->s_name = p;
3019     strcpy(p, p_se->s_name);
3020     p += strlen(p) + 1;
3021
3022     p_to->s_proto = p;
3023     strcpy(p, p_se->s_proto);
3024     p += strlen(p) + 1;
3025
3026     p_to->s_aliases = (char **)p;
3027     list_dup(p_se->s_aliases, p_to->s_aliases, 0);
3028     return p_to;
3029 }
3030
3031 /* ----------------------------------- error handling */
3032
3033 UINT wsaErrno(void)
3034 {
3035     int loc_errno = errno;
3036     WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3037
3038     switch(loc_errno)
3039     {
3040         case EINTR:             return WSAEINTR;
3041         case EBADF:             return WSAEBADF;
3042         case EPERM:
3043         case EACCES:            return WSAEACCES;
3044         case EFAULT:            return WSAEFAULT;
3045         case EINVAL:            return WSAEINVAL;
3046         case EMFILE:            return WSAEMFILE;
3047         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
3048         case EINPROGRESS:       return WSAEINPROGRESS;
3049         case EALREADY:          return WSAEALREADY;
3050         case ENOTSOCK:          return WSAENOTSOCK;
3051         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
3052         case EMSGSIZE:          return WSAEMSGSIZE;
3053         case EPROTOTYPE:        return WSAEPROTOTYPE;
3054         case ENOPROTOOPT:       return WSAENOPROTOOPT;
3055         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
3056         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
3057         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
3058         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
3059         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
3060         case EADDRINUSE:        return WSAEADDRINUSE;
3061         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
3062         case ENETDOWN:          return WSAENETDOWN;
3063         case ENETUNREACH:       return WSAENETUNREACH;
3064         case ENETRESET:         return WSAENETRESET;
3065         case ECONNABORTED:      return WSAECONNABORTED;
3066         case EPIPE:
3067         case ECONNRESET:        return WSAECONNRESET;
3068         case ENOBUFS:           return WSAENOBUFS;
3069         case EISCONN:           return WSAEISCONN;
3070         case ENOTCONN:          return WSAENOTCONN;
3071         case ESHUTDOWN:         return WSAESHUTDOWN;
3072         case ETOOMANYREFS:      return WSAETOOMANYREFS;
3073         case ETIMEDOUT:         return WSAETIMEDOUT;
3074         case ECONNREFUSED:      return WSAECONNREFUSED;
3075         case ELOOP:             return WSAELOOP;
3076         case ENAMETOOLONG:      return WSAENAMETOOLONG;
3077         case EHOSTDOWN:         return WSAEHOSTDOWN;
3078         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
3079         case ENOTEMPTY:         return WSAENOTEMPTY;
3080 #ifdef EPROCLIM
3081         case EPROCLIM:          return WSAEPROCLIM;
3082 #endif
3083 #ifdef EUSERS
3084         case EUSERS:            return WSAEUSERS;
3085 #endif
3086 #ifdef EDQUOT
3087         case EDQUOT:            return WSAEDQUOT;
3088 #endif
3089 #ifdef ESTALE
3090         case ESTALE:            return WSAESTALE;
3091 #endif
3092 #ifdef EREMOTE
3093         case EREMOTE:           return WSAEREMOTE;
3094 #endif
3095
3096        /* just in case we ever get here and there are no problems */
3097         case 0:                 return 0;
3098         default:
3099                 WARN("Unknown errno %d!\n", loc_errno);
3100                 return WSAEOPNOTSUPP;
3101     }
3102 }
3103
3104 UINT wsaHerrno(int loc_errno)
3105 {
3106
3107     WARN("h_errno %d.\n", loc_errno);
3108
3109     switch(loc_errno)
3110     {
3111         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
3112         case TRY_AGAIN:         return WSATRY_AGAIN;
3113         case NO_RECOVERY:       return WSANO_RECOVERY;
3114         case NO_DATA:           return WSANO_DATA;
3115         case ENOBUFS:           return WSAENOBUFS;
3116
3117         case 0:                 return 0;
3118         default:
3119                 WARN("Unknown h_errno %d!\n", loc_errno);
3120                 return WSAEOPNOTSUPP;
3121     }
3122 }
3123
3124
3125 /***********************************************************************
3126  *              WSARecv                 (WS2_32.67)
3127  */
3128 int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3129                     LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3130                     LPWSAOVERLAPPED lpOverlapped,
3131                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3132 {
3133     return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3134                         NULL, NULL, lpOverlapped, lpCompletionRoutine);
3135 }
3136
3137 /***********************************************************************
3138  *              WSARecvFrom             (WS2_32.69)
3139  */
3140 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3141                         LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3142                         LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3143                         LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3144
3145 {
3146     int i, n, fd, err = WSAENOTSOCK, flags, ret;
3147     struct iovec* iovec;
3148     struct ws2_async *wsa;
3149
3150     TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3151           s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3152           (lpFromlen ? *lpFromlen : -1L),
3153           lpOverlapped, lpCompletionRoutine);
3154
3155     fd = get_sock_fd( s, GENERIC_READ, &flags );
3156     TRACE ( "fd=%d, flags=%x\n", fd, flags );
3157
3158     if (fd == -1) return SOCKET_ERROR;
3159
3160     if (flags & FD_FLAG_RECV_SHUTDOWN)
3161     {
3162         WSASetLastError ( WSAESHUTDOWN );
3163         goto err_close;
3164     }
3165
3166     iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3167     if ( !iovec )
3168     {
3169         err = WSAEFAULT;
3170         goto err_close;
3171     }
3172
3173     for (i = 0; i < dwBufferCount; i++)
3174     {
3175         iovec[i].iov_base = lpBuffers[i].buf;
3176         iovec[i].iov_len  = lpBuffers[i].len;
3177     }
3178
3179     if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3180     {
3181         wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
3182                                lpFlags, lpFrom, lpFromlen,
3183                                lpOverlapped, lpCompletionRoutine );
3184
3185         if ( !wsa )
3186         {
3187             err = WSAEFAULT;
3188             goto err_free;
3189         }
3190
3191         if ( ( ret = register_new_async ( &wsa->async )) )
3192         {
3193             err = NtStatusToWSAError ( ret );
3194
3195             if ( !lpOverlapped )
3196                 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
3197             HeapFree ( GetProcessHeap(), 0, wsa );
3198             goto err_free;
3199         }
3200
3201         /* Try immediate completion */
3202         if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
3203         {
3204             if  ( WSAGetOverlappedResult ( s, lpOverlapped,
3205                                            lpNumberOfBytesRecvd, FALSE, lpFlags) )
3206                 return 0;
3207
3208             if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
3209                 goto error;
3210         }
3211
3212         WSASetLastError ( WSA_IO_PENDING );
3213         return SOCKET_ERROR;
3214     }
3215
3216     if ( _is_blocking(s) )
3217     {
3218         /* block here */
3219         /* FIXME: OOB and exceptfds? */
3220         do_block(fd, POLLIN);
3221     }
3222
3223     n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3224     if ( n == -1 )
3225     {
3226         err = wsaErrno();
3227         goto err_free;
3228     }
3229
3230     TRACE(" -> %i bytes\n", n);
3231     *lpNumberOfBytesRecvd = n;
3232
3233     HeapFree (GetProcessHeap(), 0, iovec);
3234     release_sock_fd( s, fd );
3235     _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3236
3237     return 0;
3238
3239 err_free:
3240     HeapFree (GetProcessHeap(), 0, iovec);
3241
3242 err_close:
3243     release_sock_fd( s, fd );
3244
3245 error:
3246     WARN(" -> ERROR %d\n", err);
3247     WSASetLastError ( err );
3248     return SOCKET_ERROR;
3249 }
3250
3251 /***********************************************************************
3252  *              WSCInstallProvider             (WS2_32.88)
3253  */
3254 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3255                                LPCWSTR lpszProviderDllPath,
3256                                const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3257                                DWORD dwNumberOfEntries,
3258                                LPINT lpErrno )
3259 {
3260     FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3261           debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3262           dwNumberOfEntries, lpErrno);
3263     *lpErrno = 0;
3264     return 0;
3265 }
3266
3267
3268 /***********************************************************************
3269  *              WSCDeinstallProvider             (WS2_32.83)
3270  */
3271 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3272 {
3273     FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3274     *lpErrno = 0;
3275     return 0;
3276 }
3277
3278
3279 /***********************************************************************
3280  *              WSAAccept                        (WS2_32.26)
3281  */
3282 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
3283                LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
3284 {
3285
3286        int ret = 0, size = 0;
3287        WSABUF CallerId, CallerData, CalleeId, CalleeData;
3288        /*        QOS SQOS, GQOS; */
3289        GROUP g;
3290        SOCKET cs;
3291        SOCKADDR src_addr, dst_addr;
3292
3293        TRACE("Socket  %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
3294                s, addr, addrlen, lpfnCondition, dwCallbackData);
3295
3296
3297        size = sizeof(src_addr);
3298        cs = WS_accept(s, &src_addr, &size);
3299
3300        if (cs == SOCKET_ERROR) return SOCKET_ERROR;
3301
3302        CallerId.buf = (char *)&src_addr;
3303        CallerId.len = sizeof(src_addr);
3304
3305        CallerData.buf = NULL;
3306        CallerData.len = (ULONG)NULL;
3307
3308        WS_getsockname(cs, &dst_addr, &size);
3309
3310        CalleeId.buf = (char *)&dst_addr;
3311        CalleeId.len = sizeof(dst_addr);
3312
3313
3314        ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
3315                        &CalleeId, &CalleeData, &g, dwCallbackData);
3316
3317        switch (ret)
3318        {
3319                case CF_ACCEPT:
3320                        if (addr && addrlen)
3321                                addr = memcpy(addr, &src_addr, (*addrlen > size) ?  size : *addrlen );
3322                        return cs;
3323                case CF_DEFER:
3324                        SERVER_START_REQ ( set_socket_deferred )
3325                        {
3326                            req->handle = SOCKET2HANDLE (s);
3327                            req->deferred = SOCKET2HANDLE (cs);
3328                            if ( !wine_server_call_err ( req ) )
3329                            {
3330                                SetLastError ( WSATRY_AGAIN );
3331                                WS_closesocket ( cs );
3332                            }
3333                        }
3334                        SERVER_END_REQ;
3335                        return SOCKET_ERROR;
3336                case CF_REJECT:
3337                        WS_closesocket(cs);
3338                        SetLastError(WSAECONNREFUSED);
3339                        return SOCKET_ERROR;
3340                default:
3341                        FIXME("Unknown return type from Condition function\n");
3342                        SetLastError(WSAENOTSOCK);
3343                        return SOCKET_ERROR;
3344                }
3345 }
3346
3347 /***********************************************************************
3348  *              WSAEnumProtocolsA                        (WS2_32.37)
3349  */
3350 int WINAPI WSAEnumProtocolsA(LPINT lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength)
3351 {
3352     FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
3353     return 0;
3354 }
3355
3356 /***********************************************************************
3357  *              WSAEnumProtocolsW                        (WS2_32.38)
3358  */
3359 int WINAPI WSAEnumProtocolsW(LPINT lpiProtocols, LPWSAPROTOCOL_INFOW lpProtocolBuffer, LPDWORD lpdwBufferLength)
3360 {
3361     FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
3362     return 0;
3363 }
3364
3365 /***********************************************************************
3366  *              WSADuplicateSocketA                      (WS2_32.32)
3367  */
3368 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
3369 {
3370    HANDLE hProcess;
3371
3372    TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3373    memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3374    /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
3375    /* I don't know what the real Windoze does next, this is a hack */
3376    /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
3377     * the target use the global duplicate, or we could copy a reference to us to the structure
3378     * and let the target duplicate it from us, but let's do it as simple as possible */
3379    hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3380    DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3381                    hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3382                    0, FALSE, DUPLICATE_SAME_ACCESS);
3383    CloseHandle(hProcess);
3384    lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3385    return 0;
3386 }
3387
3388 /***********************************************************************
3389  *              WSAInstallServiceClassA                  (WS2_32.48)
3390  */
3391 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
3392 {
3393     FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
3394     WSASetLastError(WSAEACCES);
3395     return SOCKET_ERROR;
3396 }
3397
3398 /***********************************************************************
3399  *              WSAInstallServiceClassW                  (WS2_32.49)
3400  */
3401 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
3402 {
3403     FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
3404     WSASetLastError(WSAEACCES);
3405     return SOCKET_ERROR;
3406 }
3407
3408 /***********************************************************************
3409  *              WSARemoveServiceClass                    (WS2_32.70)
3410  */
3411 int WINAPI WSARemoveServiceClass(LPGUID info)
3412 {
3413     FIXME("Request to remove service %p\n",info);
3414     WSASetLastError(WSATYPE_NOT_FOUND);
3415     return SOCKET_ERROR;
3416 }