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