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