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