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