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