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