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