Fix some parameter types.
[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                 if (bind(fd, uaddr, uaddrlen) < 0)
1483                 {
1484                     int loc_errno = errno;
1485                     WARN("\tfailure - errno = %i\n", errno);
1486                     errno = loc_errno;
1487                     switch (errno)
1488                     {
1489                     case EBADF:
1490                         SetLastError(WSAENOTSOCK);
1491                         break;
1492                     case EADDRNOTAVAIL:
1493                         SetLastError(WSAEINVAL);
1494                         break;
1495                     default:
1496                         SetLastError(wsaErrno());
1497                         break;
1498                     }
1499                 }
1500                 else
1501                 {
1502                     res=0; /* success */
1503                 }
1504                 ws_sockaddr_free(uaddr,name);
1505             }
1506         }
1507         close(fd);
1508     }
1509     else
1510     {
1511         SetLastError(WSAENOTSOCK);
1512     }
1513     return res;
1514 }
1515
1516 /***********************************************************************
1517  *              bind                    (WINSOCK.2)
1518  */
1519 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1520 {
1521   return (INT16)WS_bind( s, name, namelen );
1522 }
1523
1524 /***********************************************************************
1525  *              closesocket             (WS2_32.3)
1526  */
1527 int WINAPI WS_closesocket(SOCKET s)
1528 {
1529     TRACE("socket %08x\n", s);
1530     if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1531     return SOCKET_ERROR;
1532 }
1533
1534 /***********************************************************************
1535  *              closesocket           (WINSOCK.3)
1536  */
1537 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
1538 {
1539     return (INT16)WS_closesocket(s);
1540 }
1541
1542 /***********************************************************************
1543  *              connect         (WS2_32.4)
1544  */
1545 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1546 {
1547     int fd = _get_sock_fd(s);
1548
1549     TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1550 #if DEBUG_SOCKADDR
1551     dump_sockaddr(name);
1552 #endif
1553
1554     if (fd != -1)
1555     {
1556         const struct sockaddr* uaddr;
1557         int uaddrlen;
1558
1559         uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1560         if (uaddr == NULL)
1561         {
1562             SetLastError(WSAEFAULT);
1563         }
1564         else
1565         {
1566             int rc;
1567
1568             rc=connect(fd, uaddr, uaddrlen);
1569             ws_sockaddr_free(uaddr,name);
1570             if (rc == 0)
1571                 goto connect_success;
1572         }
1573
1574         if (errno == EINPROGRESS)
1575         {
1576             /* tell wineserver that a connection is in progress */
1577             _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1578                           FD_CONNECT|FD_READ|FD_WRITE,
1579                           FD_WINE_CONNECTED|FD_WINE_LISTENING);
1580             if (_is_blocking(s))
1581             {
1582                 int result;
1583                 /* block here */
1584                 do_block(fd, 7);
1585                 _sync_sock_state(s); /* let wineserver notice connection */
1586                 /* retrieve any error codes from it */
1587                 result = _get_sock_error(s, FD_CONNECT_BIT);
1588                 if (result)
1589                     SetLastError(result);
1590                 else
1591                 {
1592                     goto connect_success;
1593                 }
1594             }
1595             else
1596             {
1597                 SetLastError(WSAEWOULDBLOCK);
1598             }
1599         }
1600         else
1601         {
1602             SetLastError(wsaErrno());
1603         }
1604         close(fd);
1605     }
1606     else
1607     {
1608         SetLastError(WSAENOTSOCK);
1609     }
1610     return SOCKET_ERROR;
1611
1612 connect_success:
1613     close(fd);
1614     _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1615                   FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1616                   FD_CONNECT|FD_WINE_LISTENING);
1617     return 0;
1618 }
1619
1620 /***********************************************************************
1621  *              connect               (WINSOCK.4)
1622  */
1623 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1624 {
1625   return (INT16)WS_connect( s, name, namelen );
1626 }
1627
1628 /***********************************************************************
1629  *              WSAConnect             (WS2_32.30)
1630  */
1631 int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
1632                         LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1633                         LPQOS lpSQOS, LPQOS lpGQOS )
1634 {
1635     if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1636         FIXME ("unsupported parameters!\n");
1637     return WS_connect ( s, name, namelen );
1638 }
1639
1640
1641 /***********************************************************************
1642  *              getpeername             (WS2_32.5)
1643  */
1644 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1645 {
1646     int fd;
1647     int res;
1648
1649     TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1650
1651     /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1652     if( (name == NULL) || (namelen == NULL) )
1653     {
1654         SetLastError( WSAEFAULT );
1655         return SOCKET_ERROR;
1656     }
1657
1658     fd = _get_sock_fd(s);
1659     res = SOCKET_ERROR;
1660
1661     if (fd != -1)
1662     {
1663         struct sockaddr* uaddr;
1664         int uaddrlen;
1665
1666         uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1667         if (getpeername(fd, uaddr, &uaddrlen) != 0)
1668         {
1669             SetLastError(wsaErrno());
1670         }
1671         else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1672         {
1673             /* The buffer was too small */
1674             SetLastError(WSAEFAULT);
1675         }
1676         else
1677         {
1678             res=0;
1679         }
1680         ws_sockaddr_free(uaddr,name);
1681         close(fd);
1682     }
1683     else
1684     {
1685         SetLastError(WSAENOTSOCK);
1686     }
1687     return res;
1688 }
1689
1690 /***********************************************************************
1691  *              getpeername             (WINSOCK.5)
1692  */
1693 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct WS_sockaddr *name,
1694                                    INT16 *namelen16)
1695 {
1696     INT namelen32 = *namelen16;
1697     INT retVal = WS_getpeername( s, name, &namelen32 );
1698
1699 #if DEBUG_SOCKADDR
1700     dump_sockaddr(name);
1701 #endif
1702
1703    *namelen16 = namelen32;
1704     return (INT16)retVal;
1705 }
1706
1707 /***********************************************************************
1708  *              getsockname             (WS2_32.6)
1709  */
1710 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1711 {
1712     int fd;
1713     int res;
1714
1715     TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1716
1717     /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1718     if( (name == NULL) || (namelen == NULL) )
1719     {
1720         SetLastError( WSAEFAULT );
1721         return SOCKET_ERROR;
1722     }
1723
1724     fd = _get_sock_fd(s);
1725     res = SOCKET_ERROR;
1726
1727     if (fd != -1)
1728     {
1729         struct sockaddr* uaddr;
1730         int uaddrlen;
1731
1732         uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1733         if (getsockname(fd, uaddr, &uaddrlen) != 0)
1734         {
1735             SetLastError(wsaErrno());
1736         }
1737         else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1738         {
1739             /* The buffer was too small */
1740             SetLastError(WSAEFAULT);
1741         }
1742         else
1743         {
1744             res=0;
1745         }
1746         close(fd);
1747     }
1748     else
1749     {
1750         SetLastError(WSAENOTSOCK);
1751     }
1752     return res;
1753 }
1754
1755 /***********************************************************************
1756  *              getsockname             (WINSOCK.6)
1757  */
1758 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct WS_sockaddr *name,
1759                                    INT16 *namelen16)
1760 {
1761     INT retVal;
1762
1763     if( namelen16 )
1764     {
1765         INT namelen32 = *namelen16;
1766         retVal = WS_getsockname( s, name, &namelen32 );
1767        *namelen16 = namelen32;
1768
1769 #if DEBUG_SOCKADDR
1770     dump_sockaddr(name);
1771 #endif
1772
1773     }
1774     else retVal = SOCKET_ERROR;
1775     return (INT16)retVal;
1776 }
1777
1778
1779 /***********************************************************************
1780  *              getsockopt              (WS2_32.7)
1781  */
1782 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1783                                   INT optname, char *optval, INT *optlen)
1784 {
1785     int fd;
1786
1787     TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1788           (int) optname, (int) optval, (int) *optlen);
1789     /* SO_OPENTYPE does not require a valid socket handle. */
1790     if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1791     {
1792         if (!optlen || *optlen < sizeof(int) || !optval)
1793         {
1794             SetLastError(WSAEFAULT);
1795             return SOCKET_ERROR;
1796         }
1797         *(int *)optval = (int)TlsGetValue( opentype_tls_index );
1798         *optlen = sizeof(int);
1799         TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1800         return 0;
1801     }
1802
1803     fd = _get_sock_fd(s);
1804     if (fd != -1)
1805     {
1806         if (!convert_sockopt(&level, &optname)) {
1807             SetLastError(WSAENOPROTOOPT);       /* Unknown option */
1808         } else {
1809             if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1810             {
1811                 close(fd);
1812                 return 0;
1813             }
1814             SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1815         }
1816         close(fd);
1817     }
1818     return SOCKET_ERROR;
1819 }
1820
1821
1822 /***********************************************************************
1823  *              getsockopt              (WINSOCK.7)
1824  */
1825 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1826                                   INT16 optname, char *optval, INT16 *optlen)
1827 {
1828     INT optlen32;
1829     INT *p = &optlen32;
1830     INT retVal;
1831     if( optlen ) optlen32 = *optlen; else p = NULL;
1832     retVal = WS_getsockopt( s, (UINT16)level, optname, optval, p );
1833     if( optlen ) *optlen = optlen32;
1834     return (INT16)retVal;
1835 }
1836
1837
1838 /***********************************************************************
1839  *              htonl                   (WINSOCK.8)
1840  *              htonl                   (WS2_32.8)
1841  */
1842 u_long WINAPI WS_htonl(u_long hostlong)
1843 {
1844     return htonl(hostlong);
1845 }
1846
1847
1848 /***********************************************************************
1849  *              htons                   (WINSOCK.9)
1850  *              htons                   (WS2_32.9)
1851  */
1852 u_short WINAPI WS_htons(u_short hostshort)
1853 {
1854     return htons(hostshort);
1855 }
1856
1857
1858 /***********************************************************************
1859  *              inet_addr               (WINSOCK.10)
1860  *              inet_addr               (WS2_32.11)
1861  */
1862 u_long WINAPI WS_inet_addr(const char *cp)
1863 {
1864     return inet_addr(cp);
1865 }
1866
1867
1868 /***********************************************************************
1869  *              ntohl                   (WINSOCK.14)
1870  *              ntohl                   (WS2_32.14)
1871  */
1872 u_long WINAPI WS_ntohl(u_long netlong)
1873 {
1874     return ntohl(netlong);
1875 }
1876
1877
1878 /***********************************************************************
1879  *              ntohs                   (WINSOCK.15)
1880  *              ntohs                   (WS2_32.15)
1881  */
1882 u_short WINAPI WS_ntohs(u_short netshort)
1883 {
1884     return ntohs(netshort);
1885 }
1886
1887
1888 /***********************************************************************
1889  *              inet_ntoa               (WS2_32.12)
1890  */
1891 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1892 {
1893   /* use "buffer for dummies" here because some applications have
1894    * propensity to decode addresses in ws_hostent structure without
1895    * saving them first...
1896    */
1897     static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1898
1899     char* s = inet_ntoa(*((struct in_addr*)&in));
1900     if( s )
1901     {
1902         strcpy(dbuffer, s);
1903         return dbuffer;
1904     }
1905     SetLastError(wsaErrno());
1906     return NULL;
1907 }
1908
1909 /***********************************************************************
1910  *              inet_ntoa               (WINSOCK.11)
1911  */
1912 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1913 {
1914     char* retVal;
1915     if (!(retVal = WS_inet_ntoa(*((struct WS_in_addr*)&in)))) return 0;
1916     if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
1917     return dbuffer_seg;
1918 }
1919
1920
1921 /**********************************************************************
1922  *              WSAIoctl                (WS2_32.50)
1923  *
1924  *
1925  *   FIXME:  Only SIO_GET_INTERFACE_LIST option implemented.
1926  */
1927 INT WINAPI WSAIoctl (SOCKET s,
1928                      DWORD   dwIoControlCode,
1929                      LPVOID  lpvInBuffer,
1930                      DWORD   cbInBuffer,
1931                      LPVOID  lpbOutBuffer,
1932                      DWORD   cbOutBuffer,
1933                      LPDWORD lpcbBytesReturned,
1934                      LPWSAOVERLAPPED lpOverlapped,
1935                      LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1936 {
1937    int fd = _get_sock_fd(s);
1938
1939    if (fd != -1)
1940    {
1941       switch( dwIoControlCode )
1942       {
1943          case SIO_GET_INTERFACE_LIST:
1944          {
1945             INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1946             int i, numInt;
1947             struct ifreq ifInfo;
1948             char ifName[512];
1949
1950
1951             TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1952
1953             numInt = WSAIOCTL_GetInterfaceCount();
1954             if (numInt < 0)
1955             {
1956                ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1957                close(fd);
1958                WSASetLastError(WSAEINVAL);
1959                return (SOCKET_ERROR);
1960             }
1961
1962             for (i=0; i<numInt; i++)
1963             {
1964                if (!WSAIOCTL_GetInterfaceName(i, ifName))
1965                {
1966                   ERR ("Error parsing /proc filesystem!\n");
1967                   close(fd);
1968                   WSASetLastError(WSAEINVAL);
1969                   return (SOCKET_ERROR);
1970                }
1971
1972                ifInfo.ifr_addr.sa_family = AF_INET;
1973
1974                /* IP Address */
1975                strcpy (ifInfo.ifr_name, ifName);
1976                if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1977                {
1978                   ERR ("Error obtaining IP address\n");
1979                   close(fd);
1980                   WSASetLastError(WSAEINVAL);
1981                   return (SOCKET_ERROR);
1982                }
1983                else
1984                {
1985                   struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_addr;
1986
1987                   intArray->iiAddress.AddressIn.sin_family = AF_INET;
1988                   intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1989                   intArray->iiAddress.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
1990                }
1991
1992                /* Broadcast Address */
1993                strcpy (ifInfo.ifr_name, ifName);
1994                if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1995                {
1996                   ERR ("Error obtaining Broadcast IP address\n");
1997                   close(fd);
1998                   WSASetLastError(WSAEINVAL);
1999                   return (SOCKET_ERROR);
2000                }
2001                else
2002                {
2003                   struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_broadaddr;
2004
2005                   intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
2006                   intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
2007                   intArray->iiBroadcastAddress.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
2008                }
2009
2010                /* Subnet Mask */
2011                strcpy (ifInfo.ifr_name, ifName);
2012                if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
2013                {
2014                   ERR ("Error obtaining Subnet IP address\n");
2015                   close(fd);
2016                   WSASetLastError(WSAEINVAL);
2017                   return (SOCKET_ERROR);
2018                }
2019                else
2020                {
2021                   /* Trying to avoid some compile problems across platforms.
2022                      (Linux, FreeBSD, Solaris...) */
2023                   #ifndef ifr_netmask
2024                     #ifndef ifr_addr
2025                        intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2026                        intArray->iiNetmask.AddressIn.sin_port = 0;
2027                        intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = 0;
2028                        ERR ("Unable to determine Netmask on your platform!\n");
2029                     #else
2030                        struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_addr;
2031
2032                        intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2033                        intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
2034                        intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
2035                     #endif
2036                   #else
2037                      struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_netmask;
2038
2039                      intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2040                      intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
2041                      intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
2042                   #endif
2043                }
2044
2045                /* Socket Status Flags */
2046                strcpy(ifInfo.ifr_name, ifName);
2047                if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2048                {
2049                   ERR ("Error obtaining status flags for socket!\n");
2050                   close(fd);
2051                   WSASetLastError(WSAEINVAL);
2052                   return (SOCKET_ERROR);
2053                }
2054                else
2055                {
2056                   /* FIXME - Is this the right flag to use? */
2057                   intArray->iiFlags = ifInfo.ifr_flags;
2058                }
2059                intArray++; /* Prepare for another interface */
2060             }
2061
2062             /* Calculate the size of the array being returned */
2063             *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2064             break;
2065          }
2066
2067          default:
2068          {
2069             WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2070             close(fd);
2071             WSASetLastError(WSAEOPNOTSUPP);
2072             return (SOCKET_ERROR);
2073          }
2074       }
2075
2076       /* Function executed with no errors */
2077       close(fd);
2078       return (0);
2079    }
2080    else
2081    {
2082       WSASetLastError(WSAENOTSOCK);
2083       return (SOCKET_ERROR);
2084    }
2085 }
2086
2087
2088 /*
2089   Helper function for WSAIoctl - Get count of the number of interfaces
2090   by parsing /proc filesystem.
2091 */
2092 int WSAIOCTL_GetInterfaceCount(void)
2093 {
2094    FILE *procfs;
2095    char buf[512];  /* Size doesn't matter, something big */
2096    int  intcnt=0;
2097
2098
2099    /* Open /proc filesystem file for network devices */
2100    procfs = fopen(PROCFS_NETDEV_FILE, "r");
2101    if (!procfs)
2102    {
2103       /* If we can't open the file, return an error */
2104       return (-1);
2105    }
2106
2107    /* Omit first two lines, they are only headers */
2108    fgets(buf, sizeof buf, procfs);
2109    fgets(buf, sizeof buf, procfs);
2110
2111    while (fgets(buf, sizeof buf, procfs))
2112    {
2113       /* Each line in the file represents a network interface */
2114       intcnt++;
2115    }
2116
2117    fclose(procfs);
2118    return(intcnt);
2119 }
2120
2121
2122 /*
2123    Helper function for WSAIoctl - Get name of device from interface number
2124    by parsing /proc filesystem.
2125 */
2126 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
2127 {
2128    FILE *procfs;
2129    char buf[512]; /* Size doesn't matter, something big */
2130    int  i;
2131
2132    /* Open /proc filesystem file for network devices */
2133    procfs = fopen(PROCFS_NETDEV_FILE, "r");
2134    if (!procfs)
2135    {
2136       /* If we can't open the file, return an error */
2137       return (-1);
2138    }
2139
2140    /* Omit first two lines, they are only headers */
2141    fgets(buf, sizeof(buf), procfs);
2142    fgets(buf, sizeof(buf), procfs);
2143
2144    for (i=0; i<intNumber; i++)
2145    {
2146       /* Skip the lines that don't interest us. */
2147       fgets(buf, sizeof(buf), procfs);
2148    }
2149    fgets(buf, sizeof(buf), procfs); /* This is the line we want */
2150
2151
2152    /* Parse out the line, grabbing only the name of the device
2153       to the intName variable
2154
2155       The Line comes in like this: (we only care about the device name)
2156       lo:   21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
2157    */
2158    i=0;
2159    while (isspace(buf[i])) /* Skip initial space(s) */
2160    {
2161       i++;
2162    }
2163
2164    while (buf[i])
2165    {
2166       if (isspace(buf[i]))
2167       {
2168          break;
2169       }
2170
2171       if (buf[i] == ':')  /* FIXME: Not sure if this block (alias detection) works properly */
2172       {
2173          /* This interface could be an alias... */
2174          int hold = i;
2175          char *dotname = intName;
2176          *intName++ = buf[i++];
2177
2178          while (isdigit(buf[i]))
2179          {
2180             *intName++ = buf[i++];
2181          }
2182
2183          if (buf[i] != ':')
2184          {
2185             /* ... It wasn't, so back up */
2186             i = hold;
2187             intName = dotname;
2188          }
2189
2190          if (buf[i] == '\0')
2191          {
2192             fclose(procfs);
2193             return(FALSE);
2194          }
2195
2196          i++;
2197          break;
2198       }
2199
2200       *intName++ = buf[i++];
2201    }
2202    *intName++ = '\0';
2203
2204    fclose(procfs);
2205    return(TRUE);
2206  }
2207
2208
2209 /***********************************************************************
2210  *              ioctlsocket             (WS2_32.10)
2211  */
2212 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2213 {
2214   int fd = _get_sock_fd(s);
2215
2216   TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
2217   if (fd != -1)
2218   {
2219     long        newcmd  = cmd;
2220
2221     switch( cmd )
2222     {
2223         case WS_FIONREAD:
2224                 newcmd=FIONREAD;
2225                 break;
2226
2227         case WS_FIONBIO:
2228                 newcmd=FIONBIO;
2229                 if( _get_sock_mask(s) )
2230                 {
2231                     /* AsyncSelect()'ed sockets are always nonblocking */
2232                     if (*argp) {
2233                         close(fd);
2234                         return 0;
2235                     }
2236                     SetLastError(WSAEINVAL);
2237                     close(fd);
2238                     return SOCKET_ERROR;
2239                 }
2240                 close(fd);
2241                 if (*argp)
2242                     _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2243                 else
2244                     _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2245                 return 0;
2246
2247         case WS_SIOCATMARK:
2248                 newcmd=SIOCATMARK;
2249                 break;
2250
2251         case WS__IOW('f',125,u_long):
2252                 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2253                 SetLastError(WSAEINVAL);
2254                 return SOCKET_ERROR;
2255
2256         case SIOCGIFBRDADDR:
2257         case SIOCGIFNETMASK:
2258         case SIOCGIFADDR:
2259                 /* These don't need any special handling.  They are used by
2260                    WsControl, and are here to suppress an unecessary warning. */
2261                 break;
2262
2263
2264         default:
2265                 /* Netscape tries hard to use bogus ioctl 0x667e */
2266                 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2267     }
2268     if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2269     {
2270         close(fd);
2271         return 0;
2272     }
2273     SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2274     close(fd);
2275   }
2276   return SOCKET_ERROR;
2277 }
2278
2279 /***********************************************************************
2280  *              ioctlsocket           (WINSOCK.12)
2281  */
2282 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
2283 {
2284     return (INT16)WS_ioctlsocket( s, cmd, argp );
2285 }
2286
2287
2288 /***********************************************************************
2289  *              listen          (WS2_32.13)
2290  */
2291 int WINAPI WS_listen(SOCKET s, int backlog)
2292 {
2293     int fd = _get_sock_fd(s);
2294
2295     TRACE("socket %04x, backlog %d\n", s, backlog);
2296     if (fd != -1)
2297     {
2298         if (listen(fd, backlog) == 0)
2299         {
2300             close(fd);
2301             _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2302                           FD_WINE_LISTENING,
2303                           FD_CONNECT|FD_WINE_CONNECTED);
2304             return 0;
2305         }
2306         SetLastError(wsaErrno());
2307     }
2308     else SetLastError(WSAENOTSOCK);
2309     return SOCKET_ERROR;
2310 }
2311
2312 /***********************************************************************
2313  *              listen          (WINSOCK.13)
2314  */
2315 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
2316 {
2317     return (INT16)WS_listen( s, backlog );
2318 }
2319
2320
2321 /***********************************************************************
2322  *              recv                    (WS2_32.16)
2323  */
2324 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2325 {
2326     DWORD n, dwFlags = flags;
2327     WSABUF wsabuf;
2328
2329     wsabuf.len = len;
2330     wsabuf.buf = buf;
2331
2332     if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2333         return SOCKET_ERROR;
2334     else
2335         return n;
2336 }
2337
2338 /***********************************************************************
2339  *              recv                    (WINSOCK.16)
2340  */
2341 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2342 {
2343     return (INT16)WS_recv( s, buf, len, flags );
2344 }
2345
2346
2347 /***********************************************************************
2348  *              recvfrom                (WS2_32.17)
2349  */
2350 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2351                                 struct WS_sockaddr *from, int *fromlen)
2352 {
2353     DWORD n, dwFlags = flags;
2354     WSABUF wsabuf;
2355
2356     wsabuf.len = len;
2357     wsabuf.buf = buf;
2358
2359     if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2360         return SOCKET_ERROR;
2361     else
2362         return n;
2363 }
2364
2365 /***********************************************************************
2366  *              recvfrom                (WINSOCK.17)
2367  */
2368 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2369                                 struct WS_sockaddr *from, INT16 *fromlen16)
2370 {
2371     INT fromlen32;
2372     INT *p = &fromlen32;
2373     INT retVal;
2374
2375     if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
2376     retVal = WS_recvfrom( s, buf, len, flags, from, p );
2377     if( fromlen16 ) *fromlen16 = fromlen32;
2378     return (INT16)retVal;
2379 }
2380
2381 /***********************************************************************
2382  *              __ws_select
2383  */
2384 static int __ws_select(BOOL b32,
2385                        void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
2386                        const struct WS_timeval *ws_timeout)
2387 {
2388     int         highfd = 0;
2389     fd_set      readfds, writefds, exceptfds;
2390     fd_set     *p_read, *p_write, *p_except;
2391     int         readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2392     struct timeval timeout, *timeoutaddr = NULL;
2393
2394     TRACE("read %p, write %p, excp %p timeout %p\n",
2395           ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2396
2397     p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
2398     p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
2399     p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
2400     if (ws_timeout)
2401     {
2402         timeoutaddr = &timeout;
2403         timeout.tv_sec=ws_timeout->tv_sec;
2404         timeout.tv_usec=ws_timeout->tv_usec;
2405     }
2406
2407     if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2408     {
2409         fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
2410         fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
2411
2412         if (p_except && ws_exceptfds)
2413         {
2414 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
2415 #define wsfds32 ((WS_fd_set*)ws_exceptfds)
2416             int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
2417
2418             for (i = j = 0; i < count; i++)
2419             {
2420                 int fd = exceptfd[i];
2421                 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
2422                 {
2423                     if( b32 )
2424                         wsfds32->fd_array[j++] = wsfds32->fd_array[i];
2425                     else
2426                         wsfds16->fd_array[j++] = wsfds16->fd_array[i];
2427                 }
2428                 if( fd >= 0 ) close(fd);
2429                 exceptfd[i] = -1;
2430             }
2431             if( b32 )
2432                 wsfds32->fd_count = j;
2433             else
2434                 wsfds16->fd_count = j;
2435 #undef wsfds32
2436 #undef wsfds16
2437         }
2438         return highfd;
2439     }
2440     fd_set_unimport(ws_readfds, readfd, b32);
2441     fd_set_unimport(ws_writefds, writefd, b32);
2442     fd_set_unimport(ws_exceptfds, exceptfd, b32);
2443     if( ws_readfds ) ((WS_fd_set*)ws_readfds)->fd_count = 0;
2444     if( ws_writefds ) ((WS_fd_set*)ws_writefds)->fd_count = 0;
2445     if( ws_exceptfds ) ((WS_fd_set*)ws_exceptfds)->fd_count = 0;
2446
2447     if( highfd == 0 ) return 0;
2448     SetLastError(wsaErrno());
2449     return SOCKET_ERROR;
2450 }
2451
2452 /***********************************************************************
2453  *              select                  (WINSOCK.18)
2454  */
2455 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
2456                               ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
2457                               struct WS_timeval* timeout)
2458 {
2459     return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2460 }
2461
2462 /***********************************************************************
2463  *              select                  (WS2_32.18)
2464  */
2465 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2466                      WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2467                      const struct WS_timeval* timeout)
2468 {
2469     /* struct timeval is the same for both 32- and 16-bit code */
2470     return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2471 }
2472
2473
2474 /***********************************************************************
2475  *              send                    (WS2_32.19)
2476  */
2477 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2478 {
2479     DWORD n;
2480     WSABUF wsabuf;
2481
2482     wsabuf.len = len;
2483     wsabuf.buf = (char*) buf;
2484
2485     if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2486         return SOCKET_ERROR;
2487     else
2488         return n;
2489 }
2490
2491 /***********************************************************************
2492  *              WSASend                 (WS2_32.72)
2493  */
2494 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2495                     LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2496                     LPWSAOVERLAPPED lpOverlapped,
2497                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2498 {
2499     return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2500                        NULL, 0, lpOverlapped, lpCompletionRoutine );
2501 }
2502
2503 /***********************************************************************
2504  *              WSASendDisconnect       (WS2_32.73)
2505  */
2506 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2507 {
2508     return WS_shutdown ( s, SD_SEND );
2509 }
2510
2511
2512 /***********************************************************************
2513  *              WSASendTo               (WS2_32.74)
2514  */
2515 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2516                       LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2517                       const struct WS_sockaddr *to, int tolen,
2518                       LPWSAOVERLAPPED lpOverlapped,
2519                       LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2520 {
2521     int i, n, fd, err = WSAENOTSOCK, flags, ret;
2522     struct iovec* iovec;
2523     struct ws2_async *wsa;
2524     enum fd_type type;
2525
2526     TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2527            s, lpBuffers, dwBufferCount, dwFlags,
2528            to, tolen, lpOverlapped, lpCompletionRoutine);
2529
2530     fd = _get_sock_fd_type( s, GENERIC_WRITE, &type, &flags );
2531     TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
2532
2533     if ( fd == -1 )
2534     {
2535         err = WSAGetLastError ();
2536         goto error;
2537     }
2538
2539     iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
2540
2541     if ( !iovec )
2542     {
2543         err = WSAEFAULT;
2544         goto err_close;
2545     }
2546
2547     for ( i = 0; i < dwBufferCount; i++ )
2548     {
2549         iovec[i].iov_base = lpBuffers[i].buf;
2550         iovec[i].iov_len  = lpBuffers[i].len;
2551     }
2552
2553     if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2554     {
2555         wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
2556                                &dwFlags, (struct WS_sockaddr*) to, &tolen,
2557                                lpOverlapped, lpCompletionRoutine );
2558         if ( !wsa )
2559         {
2560             err = WSAEFAULT;
2561             goto err_free;
2562         }
2563
2564         if ( ( ret = register_new_async ( &wsa->async )) )
2565         {
2566             err = NtStatusToWSAError ( ret );
2567
2568             if ( !lpOverlapped )
2569                 HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
2570             HeapFree ( GetProcessHeap(), 0, wsa );
2571             goto err_free;
2572         }
2573
2574         /* Try immediate completion */
2575         if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
2576         {
2577             if  ( WSAGetOverlappedResult ( s, lpOverlapped,
2578                                            lpNumberOfBytesSent, FALSE, &dwFlags) )
2579                 return 0;
2580
2581             if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
2582                 goto error;
2583         }
2584
2585         WSASetLastError ( WSA_IO_PENDING );
2586         return SOCKET_ERROR;
2587     }
2588
2589     if (_is_blocking(s))
2590     {
2591         /* FIXME: exceptfds? */
2592         do_block(fd, 2);
2593     }
2594
2595     n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2596     if ( n == -1 )
2597     {
2598         err = wsaErrno();
2599         if ( err == WSAEWOULDBLOCK )
2600             _enable_event (SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2601         goto err_free;
2602     }
2603
2604     TRACE(" -> %i bytes\n", n);
2605     *lpNumberOfBytesSent = n;
2606
2607     HeapFree ( GetProcessHeap(), 0, iovec );
2608     close ( fd );
2609     return 0;
2610
2611 err_free:
2612     HeapFree ( GetProcessHeap(), 0, iovec );
2613
2614 err_close:
2615     close ( fd );
2616
2617 error:
2618     WARN (" -> ERROR %d\n", err);
2619     WSASetLastError (err);
2620     return SOCKET_ERROR;
2621 }
2622
2623 /***********************************************************************
2624  *              send                    (WINSOCK.19)
2625  */
2626 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2627 {
2628     return WS_send( s, buf, len, flags );
2629 }
2630
2631 /***********************************************************************
2632  *              sendto          (WS2_32.20)
2633  */
2634 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2635                               const struct WS_sockaddr *to, int tolen)
2636 {
2637     DWORD n;
2638     WSABUF wsabuf;
2639
2640     wsabuf.len = len;
2641     wsabuf.buf = (char*) buf;
2642
2643     if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2644         return SOCKET_ERROR;
2645     else
2646         return n;
2647 }
2648
2649 /***********************************************************************
2650  *              sendto          (WINSOCK.20)
2651  */
2652 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2653                               struct WS_sockaddr *to, INT16 tolen)
2654 {
2655     return (INT16)WS_sendto( s, buf, len, flags, to, tolen );
2656 }
2657
2658 /***********************************************************************
2659  *              setsockopt              (WS2_32.21)
2660  */
2661 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2662                                   const char *optval, int optlen)
2663 {
2664     int fd;
2665
2666     TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
2667           (int) optname, (int) optval, optlen);
2668     /* SO_OPENTYPE does not require a valid socket handle. */
2669     if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2670     {
2671         if (optlen < sizeof(int) || !optval)
2672         {
2673             SetLastError(WSAEFAULT);
2674             return SOCKET_ERROR;
2675         }
2676         TlsSetValue( opentype_tls_index, (LPVOID)*(int *)optval );
2677         TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2678         return 0;
2679     }
2680
2681     fd = _get_sock_fd(s);
2682     if (fd != -1)
2683     {
2684         struct  linger linger;
2685         int woptval;
2686         struct timeval tval;
2687
2688         /* Is a privileged and useless operation, so we don't. */
2689         if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2690             FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2691             return 0;
2692         }
2693
2694         if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2695             /* This is unique to WinSock and takes special conversion */
2696             linger.l_onoff      = *((int*)optval) ? 0: 1;
2697             linger.l_linger     = 0;
2698             optname=SO_LINGER;
2699             optval = (char*)&linger;
2700             optlen = sizeof(struct linger);
2701             level = SOL_SOCKET;
2702         }else{
2703             if (!convert_sockopt(&level, &optname)) {
2704                 SetLastError(WSAENOPROTOOPT);
2705                 close(fd);
2706                 return SOCKET_ERROR;
2707             }
2708             if (optname == SO_LINGER && optval) {
2709                 /* yes, uses unsigned short in both win16/win32 */
2710                 linger.l_onoff  = ((UINT16*)optval)[0];
2711                 linger.l_linger = ((UINT16*)optval)[1];
2712                 /* FIXME: what is documented behavior if SO_LINGER optval
2713                    is null?? */
2714                 optval = (char*)&linger;
2715                 optlen = sizeof(struct linger);
2716             } else if (optlen < sizeof(int)){
2717                 woptval= *((INT16 *) optval);
2718                 optval= (char*) &woptval;
2719                 optlen=sizeof(int);
2720             }
2721 #ifdef SO_RCVTIMEO
2722            if (level == SOL_SOCKET && optname == SO_RCVTIMEO) {
2723                if (optlen == sizeof(UINT32)) {
2724                    /* WinSock passes miliseconds instead of struct timeval */
2725                    tval.tv_usec = *(PUINT32)optval % 1000;
2726                    tval.tv_sec = *(PUINT32)optval / 1000;
2727                    /* min of 500 milisec */
2728                    if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2729                     optlen = sizeof(struct timeval);
2730                     optval = (char*)&tval;
2731                } else if (optlen == sizeof(struct timeval)) {
2732                    WARN("SO_RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2733                 } else {
2734                    WARN("SO_RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2735                     close(fd);
2736                     return 0;
2737                 }
2738             }
2739 #endif
2740 #ifdef SO_SNDTIMEO
2741            if (level == SOL_SOCKET && optname == SO_SNDTIMEO) {
2742                if (optlen == sizeof(UINT32)) {
2743                    /* WinSock passes miliseconds instead of struct timeval */
2744                    tval.tv_usec = *(PUINT32)optval % 1000;
2745                    tval.tv_sec = *(PUINT32)optval / 1000;
2746                    /* min of 500 milisec */
2747                    if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2748                    optlen = sizeof(struct timeval);
2749                    optval = (char*)&tval;
2750                } else if (optlen == sizeof(struct timeval)) {
2751                    WARN("SO_SNDTIMEO for %d bytes: assuming unixism\n", optlen);
2752                } else {
2753                    WARN("SO_SNDTIMEO for %d bytes is weird: ignored\n", optlen);
2754                    close(fd);
2755                    return 0;
2756                }
2757            }
2758 #endif
2759         }
2760         if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2761             WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2762             close( fd);
2763             return 0;
2764         }
2765
2766         if (setsockopt(fd, level, optname, optval, optlen) == 0)
2767         {
2768             close(fd);
2769             return 0;
2770         }
2771         SetLastError(wsaErrno());
2772         close(fd);
2773     }
2774     else SetLastError(WSAENOTSOCK);
2775     return SOCKET_ERROR;
2776 }
2777
2778 /***********************************************************************
2779  *              setsockopt              (WINSOCK.21)
2780  */
2781 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2782                                   char *optval, INT16 optlen)
2783 {
2784     if( !optval ) return SOCKET_ERROR;
2785     return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
2786 }
2787
2788
2789 /***********************************************************************
2790  *              shutdown                (WS2_32.22)
2791  */
2792 int WINAPI WS_shutdown(SOCKET s, int how)
2793 {
2794     int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2795     enum fd_type type;
2796     unsigned int clear_flags = 0;
2797
2798     fd = _get_sock_fd_type ( s, 0, &type, &flags );
2799     TRACE("socket %04x, how %i %d %d \n", s, how, type, flags );
2800
2801     if (fd == -1)
2802         return SOCKET_ERROR;
2803
2804     switch( how )
2805     {
2806     case 0: /* drop receives */
2807         clear_flags |= FD_READ;
2808         break;
2809     case 1: /* drop sends */
2810         clear_flags |= FD_WRITE;
2811         break;
2812     case 2: /* drop all */
2813         clear_flags |= FD_READ|FD_WRITE;
2814     default:
2815         clear_flags |= FD_WINE_CONNECTED|FD_WINE_LISTENING;
2816     }
2817
2818     if ( flags & FD_FLAG_OVERLAPPED ) {
2819
2820         switch ( how )
2821         {
2822         case SD_RECEIVE:
2823             fd0 = fd;
2824             break;
2825         case SD_SEND:
2826             fd1 = fd;
2827             break;
2828         case SD_BOTH:
2829         default:
2830             fd0 = fd;
2831             fd1 = _get_sock_fd ( s );
2832         }
2833
2834         if ( fd0 != -1 )
2835         {
2836             err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
2837             if ( err )
2838             {
2839                 close ( fd0 );
2840                 goto error;
2841             }
2842         }
2843         if ( fd1 != -1 )
2844         {
2845             err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
2846             if ( err )
2847             {
2848                 close ( fd1 );
2849                 goto error;
2850             }
2851         }
2852     }
2853     else /* non-overlapped mode */
2854     {
2855         if ( shutdown( fd, how ) )
2856         {
2857             err = wsaErrno ();
2858             close ( fd );
2859             goto error;
2860         }
2861         close(fd);
2862     }
2863
2864     _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2865     if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2866     return 0;
2867
2868 error:
2869     _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2870     WSASetLastError ( err );
2871     return SOCKET_ERROR;
2872 }
2873
2874 /***********************************************************************
2875  *              shutdown                (WINSOCK.22)
2876  */
2877 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2878 {
2879     return (INT16)WS_shutdown( s, how );
2880 }
2881
2882
2883 /***********************************************************************
2884  *              socket          (WS2_32.23)
2885  */
2886 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2887 {
2888     TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2889
2890     return WSASocketA ( af, type, protocol, NULL, 0,
2891                         (TlsGetValue(opentype_tls_index) ? 0 : WSA_FLAG_OVERLAPPED) );
2892 }
2893
2894 /***********************************************************************
2895  *              socket          (WINSOCK.23)
2896  */
2897 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2898 {
2899     return (SOCKET16)WS_socket( af, type, protocol );
2900 }
2901
2902
2903 /* ----------------------------------- DNS services
2904  *
2905  * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2906  * Also, we have to use wsock32 stubs to convert structures and
2907  * error codes from Unix to WSA, hence there is no direct mapping in
2908  * the relay32/wsock32.spec.
2909  */
2910
2911
2912 /***********************************************************************
2913  *              __ws_gethostbyaddr
2914  */
2915 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2916 {
2917     WIN_hostent *retval = NULL;
2918
2919     struct hostent* host;
2920 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2921     char *extrabuf;
2922     int ebufsize=1024;
2923     struct hostent hostentry;
2924     int locerr=ENOBUFS;
2925     host = NULL;
2926     extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2927     while(extrabuf) {
2928         int res = gethostbyaddr_r(addr, len, type,
2929                                   &hostentry, extrabuf, ebufsize, &host, &locerr);
2930         if( res != ERANGE) break;
2931         ebufsize *=2;
2932         extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2933     }
2934     if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2935 #else
2936     EnterCriticalSection( &csWSgetXXXbyYYY );
2937     host = gethostbyaddr(addr, len, type);
2938     if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2939 #endif
2940     if( host != NULL )
2941     {
2942         if( WS_dup_he(host, dup_flag) )
2943             retval = he_buffer;
2944         else
2945             SetLastError(WSAENOBUFS);
2946     }
2947 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2948     HeapFree(GetProcessHeap(),0,extrabuf);
2949 #else
2950     LeaveCriticalSection( &csWSgetXXXbyYYY );
2951 #endif
2952     return retval;
2953 }
2954
2955 /***********************************************************************
2956  *              gethostbyaddr           (WINSOCK.51)
2957  */
2958 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2959 {
2960     TRACE("ptr %p, len %d, type %d\n", addr, len, type);
2961     if (!__ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR )) return 0;
2962     return he_buffer_seg;
2963 }
2964
2965 /***********************************************************************
2966  *              gethostbyaddr           (WS2_32.51)
2967  */
2968 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len,
2969                                                 int type)
2970 {
2971     TRACE("ptr %08x, len %d, type %d\n",
2972                              (unsigned) addr, len, type);
2973     return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2974 }
2975
2976 /***********************************************************************
2977  *              __ws_gethostbyname
2978  */
2979 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2980 {
2981     WIN_hostent *retval = NULL;
2982     struct hostent*     host;
2983 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2984     char *extrabuf;
2985     int ebufsize=1024;
2986     struct hostent hostentry;
2987     int locerr = ENOBUFS;
2988     host = NULL;
2989     extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2990     while(extrabuf) {
2991         int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2992         if( res != ERANGE) break;
2993         ebufsize *=2;
2994         extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2995     }
2996     if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2997 #else
2998     EnterCriticalSection( &csWSgetXXXbyYYY );
2999     host = gethostbyname(name);
3000     if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
3001 #endif
3002     if( host  != NULL )
3003     {
3004         if( WS_dup_he(host, dup_flag) )
3005             retval = he_buffer;
3006         else SetLastError(WSAENOBUFS);
3007     }
3008 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
3009     HeapFree(GetProcessHeap(),0,extrabuf);
3010 #else
3011     LeaveCriticalSection( &csWSgetXXXbyYYY );
3012 #endif
3013     return retval;
3014 }
3015
3016 /***********************************************************************
3017  *              gethostbyname           (WINSOCK.52)
3018  */
3019 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
3020 {
3021     TRACE( "%s\n", debugstr_a(name) );
3022     if (!__ws_gethostbyname( name, WS_DUP_SEGPTR )) return 0;
3023     return he_buffer_seg;
3024 }
3025
3026 /***********************************************************************
3027  *              gethostbyname           (WS2_32.52)
3028  */
3029 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
3030 {
3031     TRACE( "%s\n", debugstr_a(name) );
3032     return __ws_gethostbyname( name, WS_DUP_LINEAR );
3033 }
3034
3035
3036 /***********************************************************************
3037  *              __ws_getprotobyname
3038  */
3039 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
3040 {
3041     WIN_protoent* retval = NULL;
3042 #ifdef HAVE_GETPROTOBYNAME
3043     struct protoent*     proto;
3044     EnterCriticalSection( &csWSgetXXXbyYYY );
3045     if( (proto = getprotobyname(name)) != NULL )
3046     {
3047         if( WS_dup_pe(proto, dup_flag) )
3048             retval = pe_buffer;
3049         else SetLastError(WSAENOBUFS);
3050     }
3051     else {
3052         MESSAGE("protocol %s not found; You might want to add "
3053                 "this to /etc/protocols\n", debugstr_a(name) );
3054         SetLastError(WSANO_DATA);
3055     }
3056     LeaveCriticalSection( &csWSgetXXXbyYYY );
3057 #endif
3058     return retval;
3059 }
3060
3061 /***********************************************************************
3062  *              getprotobyname          (WINSOCK.53)
3063  */
3064 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
3065 {
3066     TRACE( "%s\n", debugstr_a(name) );
3067     if (!__ws_getprotobyname(name, WS_DUP_SEGPTR)) return 0;
3068     return pe_buffer_seg;
3069 }
3070
3071 /***********************************************************************
3072  *              getprotobyname          (WS2_32.53)
3073  */
3074 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
3075 {
3076     TRACE( "%s\n", debugstr_a(name) );
3077     return __ws_getprotobyname(name, WS_DUP_LINEAR);
3078 }
3079
3080
3081 /***********************************************************************
3082  *              __ws_getprotobynumber
3083  */
3084 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
3085 {
3086     WIN_protoent* retval = NULL;
3087 #ifdef HAVE_GETPROTOBYNUMBER
3088     struct protoent*     proto;
3089     EnterCriticalSection( &csWSgetXXXbyYYY );
3090     if( (proto = getprotobynumber(number)) != NULL )
3091     {
3092         if( WS_dup_pe(proto, dup_flag) )
3093             retval = pe_buffer;
3094         else SetLastError(WSAENOBUFS);
3095     }
3096     else {
3097         MESSAGE("protocol number %d not found; You might want to add "
3098                 "this to /etc/protocols\n", number );
3099         SetLastError(WSANO_DATA);
3100     }
3101     LeaveCriticalSection( &csWSgetXXXbyYYY );
3102 #endif
3103     return retval;
3104 }
3105
3106 /***********************************************************************
3107  *              getprotobynumber        (WINSOCK.54)
3108  */
3109 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
3110 {
3111     TRACE("%i\n", number);
3112     if (!__ws_getprotobynumber(number, WS_DUP_SEGPTR)) return 0;
3113     return pe_buffer_seg;
3114 }
3115
3116 /***********************************************************************
3117  *              getprotobynumber        (WS2_32.54)
3118  */
3119 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
3120 {
3121     TRACE("%i\n", number);
3122     return __ws_getprotobynumber(number, WS_DUP_LINEAR);
3123 }
3124
3125
3126 /***********************************************************************
3127  *              __ws_getservbyname
3128  */
3129 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
3130 {
3131     WIN_servent* retval = NULL;
3132     struct servent*     serv;
3133     int i = wsi_strtolo( name, proto );
3134
3135     if( i ) {
3136         EnterCriticalSection( &csWSgetXXXbyYYY );
3137         serv = getservbyname(local_buffer,
3138                              proto ? (local_buffer + i) : NULL);
3139         if( serv != NULL )
3140         {
3141             if( WS_dup_se(serv, dup_flag) )
3142                 retval = se_buffer;
3143             else SetLastError(WSAENOBUFS);
3144         }
3145         else {
3146             MESSAGE("service %s protocol %s not found; You might want to add "
3147                     "this to /etc/services\n", debugstr_a(local_buffer),
3148                     proto ? debugstr_a(local_buffer+i):"*");
3149             SetLastError(WSANO_DATA);
3150         }
3151         LeaveCriticalSection( &csWSgetXXXbyYYY );
3152     }
3153     else SetLastError(WSAENOBUFS);
3154     return retval;
3155 }
3156
3157 /***********************************************************************
3158  *              getservbyname           (WINSOCK.55)
3159  */
3160 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
3161 {
3162     TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3163     if (!__ws_getservbyname(name, proto, WS_DUP_SEGPTR)) return 0;
3164     return se_buffer_seg;
3165 }
3166
3167 /***********************************************************************
3168  *              getservbyname           (WS2_32.55)
3169  */
3170 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
3171 {
3172     TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3173     return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
3174 }
3175
3176
3177 /***********************************************************************
3178  *              __ws_getservbyport
3179  */
3180 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
3181 {
3182     WIN_servent* retval = NULL;
3183 #ifdef HAVE_GETSERVBYPORT
3184     struct servent*     serv;
3185     if (!proto || wsi_strtolo( proto, NULL )) {
3186         EnterCriticalSection( &csWSgetXXXbyYYY );
3187         if( (serv = getservbyport(port, (proto) ? local_buffer : NULL)) != NULL ) {
3188             if( WS_dup_se(serv, dup_flag) )
3189                 retval = se_buffer;
3190             else SetLastError(WSAENOBUFS);
3191         }
3192         else {
3193             MESSAGE("service on port %lu protocol %s not found; You might want to add "
3194                     "this to /etc/services\n", (unsigned long)ntohl(port),
3195                     proto ? debugstr_a(local_buffer) : "*");
3196             SetLastError(WSANO_DATA);
3197         }
3198         LeaveCriticalSection( &csWSgetXXXbyYYY );
3199     }
3200     else SetLastError(WSAENOBUFS);
3201 #endif
3202     return retval;
3203 }
3204
3205 /***********************************************************************
3206  *              getservbyport           (WINSOCK.56)
3207  */
3208 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
3209 {
3210     TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3211     if (!__ws_getservbyport(port, proto, WS_DUP_SEGPTR)) return 0;
3212     return se_buffer_seg;
3213 }
3214
3215 /***********************************************************************
3216  *              getservbyport           (WS2_32.56)
3217  */
3218 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
3219 {
3220     TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3221     return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
3222 }
3223
3224
3225 /***********************************************************************
3226  *              gethostname           (WS2_32.57)
3227  */
3228 int WINAPI WS_gethostname(char *name, int namelen)
3229 {
3230     TRACE("name %p, len %d\n", name, namelen);
3231
3232     if (gethostname(name, namelen) == 0)
3233     {
3234         TRACE("<- '%s'\n", name);
3235         return 0;
3236     }
3237     SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
3238     TRACE("<- ERROR !\n");
3239     return SOCKET_ERROR;
3240 }
3241
3242 /***********************************************************************
3243  *              gethostname           (WINSOCK.57)
3244  */
3245 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
3246 {
3247     return (INT16)WS_gethostname(name, namelen);
3248 }
3249
3250
3251 /* ------------------------------------- Windows sockets extensions -- *
3252  *                                                                     *
3253  * ------------------------------------------------------------------- */
3254
3255 /***********************************************************************
3256  *              WSAEnumNetworkEvents (WS2_32.36)
3257  */
3258 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
3259 {
3260     int ret;
3261
3262     TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
3263
3264     SERVER_START_REQ( get_socket_event )
3265     {
3266         req->handle  = SOCKET2HANDLE(s);
3267         req->service = TRUE;
3268         req->c_event = hEvent;
3269         wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
3270         if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
3271     }
3272     SERVER_END_REQ;
3273     if (!ret) return 0;
3274     SetLastError(WSAEINVAL);
3275     return SOCKET_ERROR;
3276 }
3277
3278 /***********************************************************************
3279  *              WSAEventSelect (WS2_32.39)
3280  */
3281 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
3282 {
3283     int ret;
3284
3285     TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
3286
3287     SERVER_START_REQ( set_socket_event )
3288     {
3289         req->handle = SOCKET2HANDLE(s);
3290         req->mask   = lEvent;
3291         req->event  = hEvent;
3292         req->window = 0;
3293         req->msg    = 0;
3294         ret = wine_server_call( req );
3295     }
3296     SERVER_END_REQ;
3297     if (!ret) return 0;
3298     SetLastError(WSAEINVAL);
3299     return SOCKET_ERROR;
3300 }
3301
3302 /**********************************************************************
3303  *      WSAGetOverlappedResult (WS2_32.40)
3304  */
3305 BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
3306                                      LPDWORD lpcbTransfer, BOOL fWait,
3307                                      LPDWORD lpdwFlags )
3308 {
3309     DWORD r;
3310
3311     TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
3312             s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
3313
3314     if ( !(lpOverlapped && lpOverlapped->hEvent) )
3315     {
3316         ERR ( "Invalid pointer\n" );
3317         WSASetLastError (WSA_INVALID_PARAMETER);
3318         return FALSE;
3319     }
3320
3321     if ( fWait )
3322     {
3323         while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC );
3324     }
3325     else if ( lpOverlapped->Internal == STATUS_PENDING )
3326     {
3327         /* Wait in order to give APCs a chance to run. */
3328         /* This is cheating, so we must set the event again in case of success -
3329            it may be a non-manual reset event. */
3330         while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
3331         if ( r == WAIT_OBJECT_0 )
3332             NtSetEvent ( lpOverlapped->hEvent, NULL );
3333     }
3334
3335     if ( lpcbTransfer )
3336         *lpcbTransfer = lpOverlapped->InternalHigh;
3337
3338     if ( lpdwFlags )
3339         *lpdwFlags = lpOverlapped->Offset;
3340
3341     switch ( lpOverlapped->Internal )
3342     {
3343     case STATUS_SUCCESS:
3344         return TRUE;
3345     case STATUS_PENDING:
3346         WSASetLastError ( WSA_IO_INCOMPLETE );
3347         if (fWait) ERR ("PENDING status after waiting!\n");
3348         return FALSE;
3349     default:
3350         WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
3351         return FALSE;
3352     }
3353 }
3354
3355
3356 /***********************************************************************
3357  *      WSAAsyncSelect                  (WS2_32.101)
3358  */
3359 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
3360 {
3361     int ret;
3362
3363     TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3364
3365     SERVER_START_REQ( set_socket_event )
3366     {
3367         req->handle = SOCKET2HANDLE(s);
3368         req->mask   = lEvent;
3369         req->event  = 0;
3370         req->window = hWnd;
3371         req->msg    = uMsg;
3372         ret = wine_server_call( req );
3373     }
3374     SERVER_END_REQ;
3375     if (!ret) return 0;
3376     SetLastError(WSAEINVAL);
3377     return SOCKET_ERROR;
3378 }
3379
3380 /***********************************************************************
3381  *      WSAAsyncSelect          (WINSOCK.101)
3382  */
3383 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
3384 {
3385     return (INT16)WSAAsyncSelect( s, HWND_32(hWnd), wMsg, lEvent );
3386 }
3387
3388 /***********************************************************************
3389  *              WSARecvEx                       (WINSOCK.1107)
3390  *
3391  * See description for WSARecvEx()
3392  */
3393 INT16     WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
3394 {
3395   FIXME("(WSARecvEx16) partial packet return value not set \n");
3396
3397   return WINSOCK_recv16(s, buf, len, *flags);
3398 }
3399
3400
3401 /***********************************************************************
3402  *      WSACreateEvent          (WS2_32.31)
3403  *
3404  */
3405 WSAEVENT WINAPI WSACreateEvent(void)
3406 {
3407     /* Create a manual-reset event, with initial state: unsignealed */
3408     TRACE("\n");
3409
3410     return CreateEventA(NULL, TRUE, FALSE, NULL);
3411 }
3412
3413 /***********************************************************************
3414  *      WSACloseEvent          (WS2_32.29)
3415  *
3416  */
3417 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3418 {
3419     TRACE ("event=%p\n", event);
3420
3421     return CloseHandle(event);
3422 }
3423
3424 /***********************************************************************
3425  *      WSASocketA          (WS2_32.78)
3426  *
3427  */
3428 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3429                          LPWSAPROTOCOL_INFOA lpProtocolInfo,
3430                          GROUP g, DWORD dwFlags)
3431 {
3432     SOCKET ret;
3433
3434    /*
3435       FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
3436       g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3437    */
3438
3439    TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3440          af, type, protocol, lpProtocolInfo, g, dwFlags );
3441
3442     /* hack for WSADuplicateSocket */
3443     if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3444       ret = lpProtocolInfo->dwCatalogEntryId;
3445       TRACE("\tgot duplicate %04x\n", ret);
3446       return ret;
3447     }
3448
3449     /* check the socket family */
3450     switch(af)
3451     {
3452 #ifdef HAVE_IPX
3453         case WS_AF_IPX: af = AF_IPX;
3454 #endif
3455         case AF_INET:
3456         case AF_UNSPEC:
3457             break;
3458         default:
3459             SetLastError(WSAEAFNOSUPPORT);
3460             return INVALID_SOCKET;
3461     }
3462
3463     /* check the socket type */
3464     switch(type)
3465     {
3466         case WS_SOCK_STREAM:
3467             type=SOCK_STREAM;
3468             break;
3469         case WS_SOCK_DGRAM:
3470             type=SOCK_DGRAM;
3471             break;
3472         case WS_SOCK_RAW:
3473             type=SOCK_RAW;
3474             break;
3475         default:
3476             SetLastError(WSAESOCKTNOSUPPORT);
3477             return INVALID_SOCKET;
3478     }
3479
3480     /* check the protocol type */
3481     if ( protocol < 0 )  /* don't support negative values */
3482     {
3483         SetLastError(WSAEPROTONOSUPPORT);
3484         return INVALID_SOCKET;
3485     }
3486
3487     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
3488         switch(protocol)
3489         {
3490           case IPPROTO_TCP:
3491              if (type == SOCK_STREAM) { af = AF_INET; break; }
3492           case IPPROTO_UDP:
3493              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
3494           default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3495         }
3496
3497     SERVER_START_REQ( create_socket )
3498     {
3499         req->family   = af;
3500         req->type     = type;
3501         req->protocol = protocol;
3502         req->access   = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3503         req->flags    = dwFlags;
3504         req->inherit  = TRUE;
3505         set_error( wine_server_call( req ) );
3506         ret = HANDLE2SOCKET( reply->handle );
3507     }
3508     SERVER_END_REQ;
3509     if (ret)
3510     {
3511         TRACE("\tcreated %04x\n", ret );
3512         return ret;
3513     }
3514
3515     if (GetLastError() == WSAEACCES) /* raw socket denied */
3516     {
3517         if (type == SOCK_RAW)
3518             MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3519         else
3520             MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3521         SetLastError(WSAESOCKTNOSUPPORT);
3522     }
3523
3524     WARN("\t\tfailed!\n");
3525     return INVALID_SOCKET;
3526 }
3527
3528
3529 /***********************************************************************
3530  *      __WSAFDIsSet                    (WINSOCK.151)
3531  */
3532 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
3533 {
3534   int i = set->fd_count;
3535
3536   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3537
3538   while (i--)
3539       if (set->fd_array[i] == s) return 1;
3540   return 0;
3541 }
3542
3543 /***********************************************************************
3544  *      __WSAFDIsSet                    (WS2_32.151)
3545  */
3546 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3547 {
3548   int i = set->fd_count;
3549
3550   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3551
3552   while (i--)
3553       if (set->fd_array[i] == s) return 1;
3554   return 0;
3555 }
3556
3557 /***********************************************************************
3558  *      WSAIsBlocking                   (WINSOCK.114)
3559  *      WSAIsBlocking                   (WS2_32.114)
3560  */
3561 BOOL WINAPI WSAIsBlocking(void)
3562 {
3563   /* By default WinSock should set all its sockets to non-blocking mode
3564    * and poll in PeekMessage loop when processing "blocking" ones. This
3565    * function is supposed to tell if the program is in this loop. Our
3566    * blocking calls are truly blocking so we always return FALSE.
3567    *
3568    * Note: It is allowed to call this function without prior WSAStartup().
3569    */
3570
3571   TRACE("\n");
3572   return FALSE;
3573 }
3574
3575 /***********************************************************************
3576  *      WSACancelBlockingCall           (WINSOCK.113)
3577  *      WSACancelBlockingCall           (WS2_32.113)
3578  */
3579 INT WINAPI WSACancelBlockingCall(void)
3580 {
3581     TRACE("\n");
3582     return 0;
3583 }
3584
3585
3586 /***********************************************************************
3587  *      WSASetBlockingHook              (WINSOCK.109)
3588  */
3589 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
3590 {
3591   FARPROC16 prev = (FARPROC16)blocking_hook;
3592   blocking_hook = (FARPROC)lpBlockFunc;
3593   TRACE("hook %p\n", lpBlockFunc);
3594   return prev;
3595 }
3596
3597
3598 /***********************************************************************
3599  *      WSASetBlockingHook (WS2_32.109)
3600  */
3601 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3602 {
3603   FARPROC prev = blocking_hook;
3604   blocking_hook = lpBlockFunc;
3605   TRACE("hook %p\n", lpBlockFunc);
3606   return prev;
3607 }
3608
3609
3610 /***********************************************************************
3611  *      WSAUnhookBlockingHook   (WINSOCK.110)
3612  */
3613 INT16 WINAPI WSAUnhookBlockingHook16(void)
3614 {
3615     blocking_hook = NULL;
3616     return 0;
3617 }
3618
3619
3620 /***********************************************************************
3621  *      WSAUnhookBlockingHook (WS2_32.110)
3622  */
3623 INT WINAPI WSAUnhookBlockingHook(void)
3624 {
3625     blocking_hook = NULL;
3626     return 0;
3627 }
3628
3629
3630 /* ----------------------------------- end of API stuff */
3631
3632 /* ----------------------------------- helper functions -
3633  *
3634  * TODO: Merge WS_dup_..() stuff into one function that
3635  * would operate with a generic structure containing internal
3636  * pointers (via a template of some kind).
3637  */
3638
3639 static int list_size(char** l, int item_size)
3640 {
3641   int i,j = 0;
3642   if(l)
3643   { for(i=0;l[i];i++)
3644         j += (item_size) ? item_size : strlen(l[i]) + 1;
3645     j += (i + 1) * sizeof(char*); }
3646   return j;
3647 }
3648
3649 static int list_dup(char** l_src, char* ref, char* base, int item_size)
3650 {
3651    /* base is either either equal to ref or 0 or SEGPTR */
3652
3653    char*                p = ref;
3654    char**               l_to = (char**)ref;
3655    int                  i,j,k;
3656
3657    for(j=0;l_src[j];j++) ;
3658    p += (j + 1) * sizeof(char*);
3659    for(i=0;i<j;i++)
3660    { l_to[i] = base + (p - ref);
3661      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3662      memcpy(p, l_src[i], k); p += k; }
3663    l_to[i] = NULL;
3664    return (p - ref);
3665 }
3666
3667 /* ----- hostent */
3668
3669 static int hostent_size(struct hostent* p_he)
3670 {
3671   int size = 0;
3672   if( p_he )
3673   { size  = sizeof(struct hostent);
3674     size += strlen(p_he->h_name) + 1;
3675     size += list_size(p_he->h_aliases, 0);
3676     size += list_size(p_he->h_addr_list, p_he->h_length ); }
3677   return size;
3678 }
3679
3680 /* duplicate hostent entry
3681  * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3682  * Dito for protoent and servent.
3683  */
3684 static int WS_dup_he(struct hostent* p_he, int flag)
3685 {
3686     /* Convert hostent structure into ws_hostent so that the data fits
3687      * into local_buffer. Internal pointers can be linear, SEGPTR, or
3688      * relative to local_buffer depending on "flag" value. Returns size
3689      * of the data copied.
3690      */
3691
3692     int size = hostent_size(p_he);
3693     if( size )
3694     {
3695         char *p_name,*p_aliases,*p_addr,*p_base,*p;
3696         char *p_to;
3697         struct ws_hostent16 *p_to16;
3698         struct WS_hostent *p_to32;
3699
3700         check_buffer_he(size);
3701         p_to = he_buffer;
3702         p_to16 = he_buffer;
3703         p_to32 = he_buffer;
3704
3705         p = p_to;
3706         p_base = (flag & WS_DUP_SEGPTR) ? (char*)he_buffer_seg : he_buffer;
3707         p += (flag & WS_DUP_SEGPTR) ?
3708             sizeof(struct ws_hostent16) : sizeof(struct WS_hostent);
3709         p_name = p;
3710         strcpy(p, p_he->h_name); p += strlen(p) + 1;
3711         p_aliases = p;
3712         p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3713         p_addr = p;
3714         list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3715
3716         if (flag & WS_DUP_SEGPTR) /* Win16 */
3717         {
3718             p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3719             p_to16->h_length = (INT16)p_he->h_length;
3720             p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3721             p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3722             p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3723             size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3724         }
3725         else /* Win32 */
3726         {
3727             p_to32->h_addrtype = p_he->h_addrtype;
3728             p_to32->h_length = p_he->h_length;
3729             p_to32->h_name = (p_base + (p_name - p_to));
3730             p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3731             p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3732             size += (sizeof(struct WS_hostent) - sizeof(struct hostent));
3733         }
3734     }
3735     return size;
3736 }
3737
3738 /* ----- protoent */
3739
3740 static int protoent_size(struct protoent* p_pe)
3741 {
3742   int size = 0;
3743   if( p_pe )
3744   { size  = sizeof(struct protoent);
3745     size += strlen(p_pe->p_name) + 1;
3746     size += list_size(p_pe->p_aliases, 0); }
3747   return size;
3748 }
3749
3750 static int WS_dup_pe(struct protoent* p_pe, int flag)
3751 {
3752     int size = protoent_size(p_pe);
3753     if( size )
3754     {
3755         char *p_to;
3756         struct ws_protoent16 *p_to16;
3757         struct WS_protoent *p_to32;
3758         char *p_name,*p_aliases,*p_base,*p;
3759
3760         check_buffer_pe(size);
3761         p_to = pe_buffer;
3762         p_to16 = pe_buffer;
3763         p_to32 = pe_buffer;
3764         p = p_to;
3765         p_base = (flag & WS_DUP_SEGPTR) ? (char*)pe_buffer_seg : pe_buffer;
3766         p += (flag & WS_DUP_SEGPTR) ?
3767             sizeof(struct ws_protoent16) : sizeof(struct WS_protoent);
3768         p_name = p;
3769         strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3770         p_aliases = p;
3771         list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3772
3773         if (flag & WS_DUP_SEGPTR) /* Win16 */
3774         {
3775             p_to16->p_proto = (INT16)p_pe->p_proto;
3776             p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3777             p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3778             size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3779         }
3780         else /* Win32 */
3781         {
3782             p_to32->p_proto = p_pe->p_proto;
3783             p_to32->p_name = (p_base) + (p_name - p_to);
3784             p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3785             size += (sizeof(struct WS_protoent) - sizeof(struct protoent));
3786         }
3787     }
3788     return size;
3789 }
3790
3791 /* ----- servent */
3792
3793 static int servent_size(struct servent* p_se)
3794 {
3795   int size = 0;
3796   if( p_se )
3797   { size += sizeof(struct servent);
3798     size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3799     size += list_size(p_se->s_aliases, 0); }
3800   return size;
3801 }
3802
3803 static int WS_dup_se(struct servent* p_se, int flag)
3804 {
3805     int size = servent_size(p_se);
3806     if( size )
3807     {
3808         char *p_name,*p_aliases,*p_proto,*p_base,*p;
3809         char *p_to;
3810         struct ws_servent16 *p_to16;
3811         struct WS_servent *p_to32;
3812
3813         check_buffer_se(size);
3814         p_to = se_buffer;
3815         p_to16 = se_buffer;
3816         p_to32 = se_buffer;
3817         p = p_to;
3818         p_base = (flag & WS_DUP_SEGPTR) ? (char*)se_buffer_seg : se_buffer;
3819         p += (flag & WS_DUP_SEGPTR) ?
3820             sizeof(struct ws_servent16) : sizeof(struct WS_servent);
3821         p_name = p;
3822         strcpy(p, p_se->s_name); p += strlen(p) + 1;
3823         p_proto = p;
3824         strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3825         p_aliases = p;
3826         list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3827
3828         if (flag & WS_DUP_SEGPTR) /* Win16 */
3829         {
3830             p_to16->s_port = (INT16)p_se->s_port;
3831             p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3832             p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3833             p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3834             size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3835         }
3836         else /* Win32 */
3837         {
3838             p_to32->s_port = p_se->s_port;
3839             p_to32->s_name = (p_base + (p_name - p_to));
3840             p_to32->s_proto = (p_base + (p_proto - p_to));
3841             p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3842             size += (sizeof(struct WS_servent) - sizeof(struct servent));
3843         }
3844     }
3845     return size;
3846 }
3847
3848 /* ----------------------------------- error handling */
3849
3850 UINT16 wsaErrno(void)
3851 {
3852     int loc_errno = errno;
3853     WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3854
3855     switch(loc_errno)
3856     {
3857         case EINTR:             return WSAEINTR;
3858         case EBADF:             return WSAEBADF;
3859         case EPERM:
3860         case EACCES:            return WSAEACCES;
3861         case EFAULT:            return WSAEFAULT;
3862         case EINVAL:            return WSAEINVAL;
3863         case EMFILE:            return WSAEMFILE;
3864         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
3865         case EINPROGRESS:       return WSAEINPROGRESS;
3866         case EALREADY:          return WSAEALREADY;
3867         case ENOTSOCK:          return WSAENOTSOCK;
3868         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
3869         case EMSGSIZE:          return WSAEMSGSIZE;
3870         case EPROTOTYPE:        return WSAEPROTOTYPE;
3871         case ENOPROTOOPT:       return WSAENOPROTOOPT;
3872         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
3873         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
3874         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
3875         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
3876         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
3877         case EADDRINUSE:        return WSAEADDRINUSE;
3878         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
3879         case ENETDOWN:          return WSAENETDOWN;
3880         case ENETUNREACH:       return WSAENETUNREACH;
3881         case ENETRESET:         return WSAENETRESET;
3882         case ECONNABORTED:      return WSAECONNABORTED;
3883         case EPIPE:
3884         case ECONNRESET:        return WSAECONNRESET;
3885         case ENOBUFS:           return WSAENOBUFS;
3886         case EISCONN:           return WSAEISCONN;
3887         case ENOTCONN:          return WSAENOTCONN;
3888         case ESHUTDOWN:         return WSAESHUTDOWN;
3889         case ETOOMANYREFS:      return WSAETOOMANYREFS;
3890         case ETIMEDOUT:         return WSAETIMEDOUT;
3891         case ECONNREFUSED:      return WSAECONNREFUSED;
3892         case ELOOP:             return WSAELOOP;
3893         case ENAMETOOLONG:      return WSAENAMETOOLONG;
3894         case EHOSTDOWN:         return WSAEHOSTDOWN;
3895         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
3896         case ENOTEMPTY:         return WSAENOTEMPTY;
3897 #ifdef EPROCLIM
3898         case EPROCLIM:          return WSAEPROCLIM;
3899 #endif
3900 #ifdef EUSERS
3901         case EUSERS:            return WSAEUSERS;
3902 #endif
3903 #ifdef EDQUOT
3904         case EDQUOT:            return WSAEDQUOT;
3905 #endif
3906 #ifdef ESTALE
3907         case ESTALE:            return WSAESTALE;
3908 #endif
3909 #ifdef EREMOTE
3910         case EREMOTE:           return WSAEREMOTE;
3911 #endif
3912
3913        /* just in case we ever get here and there are no problems */
3914         case 0:                 return 0;
3915         default:
3916                 WARN("Unknown errno %d!\n", loc_errno);
3917                 return WSAEOPNOTSUPP;
3918     }
3919 }
3920
3921 UINT16 wsaHerrno(int loc_errno)
3922 {
3923
3924     WARN("h_errno %d.\n", loc_errno);
3925
3926     switch(loc_errno)
3927     {
3928         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
3929         case TRY_AGAIN:         return WSATRY_AGAIN;
3930         case NO_RECOVERY:       return WSANO_RECOVERY;
3931         case NO_DATA:           return WSANO_DATA;
3932         case ENOBUFS:           return WSAENOBUFS;
3933
3934         case 0:                 return 0;
3935         default:
3936                 WARN("Unknown h_errno %d!\n", loc_errno);
3937                 return WSAEOPNOTSUPP;
3938     }
3939 }
3940
3941
3942 /***********************************************************************
3943  *              WSARecv                 (WS2_32.67)
3944  */
3945 int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3946                     LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3947                     LPWSAOVERLAPPED lpOverlapped,
3948                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3949 {
3950     return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3951                         NULL, NULL, lpOverlapped, lpCompletionRoutine);
3952 }
3953
3954 /***********************************************************************
3955  *              WSARecvFrom             (WS2_32.69)
3956  */
3957 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3958                         LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3959                         LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3960                         LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3961
3962 {
3963     int i, n, fd, err = WSAENOTSOCK, flags, ret;
3964     struct iovec* iovec;
3965     struct ws2_async *wsa;
3966     enum fd_type type;
3967
3968     TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3969           s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3970           (lpFromlen ? *lpFromlen : -1L),
3971           lpOverlapped, lpCompletionRoutine);
3972
3973     fd = _get_sock_fd_type( s, GENERIC_READ, &type, &flags );
3974     TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
3975
3976     if (fd == -1)
3977     {
3978         err = WSAGetLastError ();
3979         goto error;
3980     }
3981
3982     iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3983     if ( !iovec )
3984     {
3985         err = WSAEFAULT;
3986         goto err_close;
3987     }
3988
3989     for (i = 0; i < dwBufferCount; i++)
3990     {
3991         iovec[i].iov_base = lpBuffers[i].buf;
3992         iovec[i].iov_len  = lpBuffers[i].len;
3993     }
3994
3995     if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3996     {
3997         wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
3998                                lpFlags, lpFrom, lpFromlen,
3999                                lpOverlapped, lpCompletionRoutine );
4000
4001         if ( !wsa )
4002         {
4003             err = WSAEFAULT;
4004             goto err_free;
4005         }
4006
4007         if ( ( ret = register_new_async ( &wsa->async )) )
4008         {
4009             err = NtStatusToWSAError ( ret );
4010
4011             if ( !lpOverlapped )
4012                 HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
4013             HeapFree ( GetProcessHeap(), 0, wsa );
4014             goto err_free;
4015         }
4016
4017         /* Try immediate completion */
4018         if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
4019         {
4020             if  ( WSAGetOverlappedResult ( s, lpOverlapped,
4021                                            lpNumberOfBytesRecvd, FALSE, lpFlags) )
4022                 return 0;
4023
4024             if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
4025                 goto error;
4026         }
4027
4028         WSASetLastError ( WSA_IO_PENDING );
4029         return SOCKET_ERROR;
4030     }
4031
4032     if ( _is_blocking(s) )
4033     {
4034         /* block here */
4035         /* FIXME: OOB and exceptfds? */
4036         do_block(fd, 1);
4037     }
4038
4039     n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
4040     if ( n == -1 )
4041     {
4042         err = wsaErrno();
4043         goto err_free;
4044     }
4045
4046     TRACE(" -> %i bytes\n", n);
4047     *lpNumberOfBytesRecvd = n;
4048
4049     HeapFree (GetProcessHeap(), 0, iovec);
4050     close(fd);
4051     _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
4052
4053     return 0;
4054
4055 err_free:
4056     HeapFree (GetProcessHeap(), 0, iovec);
4057
4058 err_close:
4059     close (fd);
4060
4061 error:
4062     WARN(" -> ERROR %d\n", err);
4063     WSASetLastError ( err );
4064     return SOCKET_ERROR;
4065 }
4066
4067 /***********************************************************************
4068  *              WSCInstallProvider             (WS2_32.88)
4069  */
4070 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
4071                                LPCWSTR lpszProviderDllPath,
4072                                const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
4073                                DWORD dwNumberOfEntries,
4074                                LPINT lpErrno )
4075 {
4076     FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
4077           debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
4078           dwNumberOfEntries, lpErrno);
4079     *lpErrno = 0;
4080     return 0;
4081 }
4082
4083
4084 /***********************************************************************
4085  *              WSCDeinstallProvider             (WS2_32.83)
4086  */
4087 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
4088 {
4089     FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
4090     *lpErrno = 0;
4091     return 0;
4092 }
4093
4094
4095 /***********************************************************************
4096  *              WSAAccept                        (WS2_32.26)
4097  */
4098 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
4099                LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
4100 {
4101
4102        int ret = 0, size = 0;
4103        WSABUF CallerId, CallerData, CalleeId, CalleeData;
4104        /*        QOS SQOS, GQOS; */
4105        GROUP g;
4106        SOCKET cs;
4107        SOCKADDR src_addr, dst_addr;
4108
4109        TRACE("Socket  %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
4110                s, addr, addrlen, lpfnCondition, dwCallbackData);
4111
4112
4113        size = sizeof(src_addr);
4114        cs = WS_accept(s, &src_addr, &size);
4115
4116        if (cs == SOCKET_ERROR) return SOCKET_ERROR;
4117
4118        CallerId.buf = (char *)&src_addr;
4119        CallerId.len = sizeof(src_addr);
4120
4121        CallerData.buf = NULL;
4122        CallerData.len = (ULONG)NULL;
4123
4124        WS_getsockname(cs, &dst_addr, &size);
4125
4126        CalleeId.buf = (char *)&dst_addr;
4127        CalleeId.len = sizeof(dst_addr);
4128
4129
4130        ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
4131                        &CalleeId, &CalleeData, &g, dwCallbackData);
4132
4133        switch (ret)
4134        {
4135                case CF_ACCEPT:
4136                        if (addr && addrlen)
4137                                addr = memcpy(addr, &src_addr, (*addrlen > size) ?  size : *addrlen );
4138                        return cs;
4139                case CF_DEFER:
4140                        SERVER_START_REQ ( set_socket_deferred )
4141                        {
4142                            req->handle = SOCKET2HANDLE (s);
4143                            req->deferred = SOCKET2HANDLE (cs);
4144                            if ( !wine_server_call_err ( req ) )
4145                            {
4146                                SetLastError ( WSATRY_AGAIN );
4147                                WS_closesocket ( cs );
4148                            }
4149                        }
4150                        SERVER_END_REQ;
4151                        return SOCKET_ERROR;
4152                case CF_REJECT:
4153                        WS_closesocket(cs);
4154                        SetLastError(WSAECONNREFUSED);
4155                        return SOCKET_ERROR;
4156                default:
4157                        FIXME("Unknown return type from Condition function\n");
4158                        SetLastError(WSAENOTSOCK);
4159                        return SOCKET_ERROR;
4160                }
4161
4162        SetLastError(WSAENOTSOCK);
4163        return SOCKET_ERROR;
4164 }
4165
4166 /***********************************************************************
4167  *              WSAEnumProtocolsA                        (WS2_32.37)
4168  */
4169 int WINAPI WSAEnumProtocolsA(LPINT lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength)
4170 {
4171     FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4172     return 0;
4173 }
4174
4175 /***********************************************************************
4176  *              WSAEnumProtocolsW                        (WS2_32.38)
4177  */
4178 int WINAPI WSAEnumProtocolsW(LPINT lpiProtocols, LPWSAPROTOCOL_INFOW lpProtocolBuffer, LPDWORD lpdwBufferLength)
4179 {
4180     FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4181     return 0;
4182 }
4183
4184 /***********************************************************************
4185  *              WSADuplicateSocketA                      (WS2_32.32)
4186  */
4187 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
4188 {
4189    HANDLE hProcess;
4190
4191    TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4192    memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4193    /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
4194    /* I don't know what the real Windoze does next, this is a hack */
4195    /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
4196     * the target use the global duplicate, or we could copy a reference to us to the structure
4197     * and let the target duplicate it from us, but let's do it as simple as possible */
4198    hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4199    DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
4200                    hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4201                    0, FALSE, DUPLICATE_SAME_ACCESS);
4202    CloseHandle(hProcess);
4203    lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4204    return 0;
4205 }
4206
4207 /***********************************************************************
4208  *              WSAInstallServiceClassA                  (WS2_32.48)
4209  */
4210 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
4211 {
4212     FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
4213     return WSAEACCES;
4214 }
4215
4216 /***********************************************************************
4217  *              WSAInstallServiceClassW                  (WS2_32.49)
4218  */
4219 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
4220 {
4221     FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
4222     return WSAEACCES;
4223 }