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