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