A socket becomes readable after connect in Linux 2.4 (even for
[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 /**********************************************************************/
788
789 SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr,
790                                  INT *addrlen32)
791 {
792     LPWSINFO                 pwsi = WINSOCK_GetIData();
793 #ifdef HAVE_IPX
794     struct ws_sockaddr_ipx*  addr2 = (struct ws_sockaddr_ipx *)addr;
795 #endif
796
797     TRACE("(%08x): socket %04x\n", 
798                                   (unsigned)pwsi, (UINT16)s ); 
799     if( _check_ws(pwsi, s) )
800     {
801         SOCKET as;
802         if (_is_blocking(s))
803         {
804             /* block here */
805             int fd = _get_sock_fd(s);
806             do_block(fd, 5);
807             close(fd);
808             _sync_sock_state(s); /* let wineserver notice connection */
809             /* retrieve any error codes from it */
810             SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
811             /* FIXME: care about the error? */
812         }
813         SERVER_START_REQ
814         {
815             struct accept_socket_request *req = server_alloc_req( sizeof(*req), 0 );
816
817             req->lhandle = s;
818             req->access  = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
819             req->inherit = TRUE;
820             sock_server_call( REQ_ACCEPT_SOCKET );
821             as = req->handle;
822         }
823         SERVER_END_REQ;
824         if( ((int)as) >= 0 )
825         {
826             unsigned omask = _get_sock_mask( s );
827             int fd = _get_sock_fd( as );
828             if( getpeername(fd, addr, addrlen32) != -1 )
829             {
830 #ifdef HAVE_IPX
831                 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
832                     addr = (struct sockaddr *)
833                                 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
834                     memcpy(addr, addr2,
835                                 addrlen32 ? *addrlen32 : sizeof(*addr2));
836                     addr2->sipx_family = WS_AF_IPX;
837                     addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
838                     addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
839                     memcpy(addr2->sipx_node,
840                         ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
841                     free(addr);
842                 }
843 #endif
844             } else SetLastError(wsaErrno());
845             close(fd);
846             if (omask & WS_FD_SERVEVENT)
847                 WSOCK32_async_accept(pwsi, s, as);
848             return as;
849         }
850     }
851     return INVALID_SOCKET;
852 }
853
854 /***********************************************************************
855  *              accept()                (WINSOCK.1)
856  */
857 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
858                                  INT16* addrlen16 )
859 {
860     INT addrlen32 = addrlen16 ? *addrlen16 : 0;
861     SOCKET retSocket = WSOCK32_accept( s, addr, &addrlen32 );
862     if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
863     return (SOCKET16)retSocket;
864 }
865
866 /***********************************************************************
867  *              bind()                  (WSOCK32.2)
868  */
869 INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen)
870 {
871     LPWSINFO                 pwsi = WINSOCK_GetIData();
872 #ifdef HAVE_IPX
873     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
874 #endif
875
876     TRACE("(%08x): socket %04x, ptr %8x, length %d\n", 
877                            (unsigned)pwsi, s, (int) name, namelen);
878 #if DEBUG_SOCKADDR
879     dump_sockaddr(name);
880 #endif
881
882     if ( _check_ws(pwsi, s) )
883     {
884       int fd = _get_sock_fd(s);
885       /* FIXME: what family does this really map to on the Unix side? */
886       if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
887         ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
888 #ifdef HAVE_IPX
889       else if (name &&
890                 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
891       {
892         name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
893         memset(name, '\0', sizeof(struct sockaddr_ipx));
894         ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
895         ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
896         ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
897         memcpy(((struct sockaddr_ipx *)name)->sipx_node,
898                 name2->sipx_node, IPX_NODE_LEN);
899         namelen = sizeof(struct sockaddr_ipx);
900       }
901 #endif
902       if ( namelen >= sizeof(*name) ) 
903       {
904         if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
905 #ifdef HAVE_IPX
906              || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
907 #endif
908            ))
909         {
910           if ( bind(fd, name, namelen) < 0 ) 
911           {
912              int        loc_errno = errno;
913              WARN("\tfailure - errno = %i\n", errno);
914              errno = loc_errno;
915              switch(errno)
916              {
917                 case EBADF: SetLastError(WSAENOTSOCK); break;
918                 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
919                 default: SetLastError(wsaErrno());break;
920              }
921           }
922           else {
923 #ifdef HAVE_IPX
924             if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
925                 free(name);
926 #endif
927             close(fd);
928             return 0; /* success */
929           }
930         } else SetLastError(WSAEAFNOSUPPORT);
931       } else SetLastError(WSAEFAULT);
932 #ifdef HAVE_IPX
933       if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
934         free(name);
935 #endif
936       close(fd);
937     }
938     return SOCKET_ERROR;
939 }
940
941 /***********************************************************************
942  *              bind()                  (WINSOCK.2)
943  */
944 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
945 {
946   return (INT16)WSOCK32_bind( s, name, namelen );
947 }
948
949 /***********************************************************************
950  *              closesocket()           (WSOCK32.3)
951  */
952 INT WINAPI WSOCK32_closesocket(SOCKET s)
953 {
954     LPWSINFO      pwsi = WINSOCK_GetIData();
955
956     TRACE("(%08x): socket %08x\n", (unsigned)pwsi, s);
957
958     if( _check_ws(pwsi, s) )
959     { 
960         if( CloseHandle(s) )
961             return 0;
962     }
963     return SOCKET_ERROR;
964 }
965
966 /***********************************************************************
967  *              closesocket()           (WINSOCK.3)
968  */
969 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
970 {
971     return (INT16)WSOCK32_closesocket(s);
972 }
973
974 /***********************************************************************
975  *              connect()               (WSOCK32.4)
976  */
977 INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen)
978 {
979   LPWSINFO                 pwsi = WINSOCK_GetIData();
980 #ifdef HAVE_IPX
981   struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
982 #endif
983
984   TRACE("(%08x): socket %04x, ptr %8x, length %d\n", 
985                            (unsigned)pwsi, s, (int) name, namelen);
986 #if DEBUG_SOCKADDR
987   dump_sockaddr(name);
988 #endif
989
990   if( _check_ws(pwsi, s) )
991   {
992     int fd = _get_sock_fd(s);
993     if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
994         ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
995 #ifdef HAVE_IPX
996     else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
997     {
998         name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
999         memset(name, '\0', sizeof(struct sockaddr_ipx));
1000         ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
1001         ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
1002         ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
1003         memcpy(((struct sockaddr_ipx *)name)->sipx_node,
1004                 name2->sipx_node, IPX_NODE_LEN);
1005         namelen = sizeof(struct sockaddr_ipx);
1006     }
1007 #endif
1008     if (connect(fd, name, namelen) == 0) {
1009         close(fd);
1010         goto connect_success;
1011     }
1012     if (errno == EINPROGRESS)
1013     {
1014         /* tell wineserver that a connection is in progress */
1015         _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1016                       WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
1017                       WS_FD_CONNECTED|WS_FD_LISTENING);
1018         if (_is_blocking(s))
1019         {
1020             int result;
1021             /* block here */
1022             do_block(fd, 7);
1023             _sync_sock_state(s); /* let wineserver notice connection */
1024             /* retrieve any error codes from it */
1025             result = _get_sock_error(s, FD_CONNECT_BIT);
1026             if (result)
1027                 SetLastError(result);
1028             else {
1029                 close(fd);
1030                 goto connect_success;
1031             }
1032         }
1033         else SetLastError(WSAEWOULDBLOCK);
1034         close(fd);
1035     }
1036     else
1037     {
1038         SetLastError(wsaErrno());
1039         close(fd);
1040     }
1041   }
1042 #ifdef HAVE_IPX
1043   if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1044     free(name);
1045 #endif
1046   return SOCKET_ERROR;
1047 connect_success:
1048 #ifdef HAVE_IPX
1049     if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1050         free(name);
1051 #endif
1052     _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1053                   WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
1054                   WS_FD_CONNECT|WS_FD_LISTENING);
1055     return 0; 
1056 }
1057
1058 /***********************************************************************
1059  *              connect()               (WINSOCK.4)
1060  */
1061 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1062 {
1063   return (INT16)WSOCK32_connect( s, name, namelen );
1064 }
1065
1066 /***********************************************************************
1067  *              getpeername()           (WSOCK32.5)
1068  */
1069 INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name,
1070                                    INT *namelen)
1071 {
1072     LPWSINFO                 pwsi = WINSOCK_GetIData();
1073 #ifdef HAVE_IPX
1074     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
1075 #endif
1076
1077     TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
1078                            (unsigned)pwsi, s, (int) name, *namelen);
1079     if( _check_ws(pwsi, s) )
1080     {
1081         int fd = _get_sock_fd(s);
1082         if (getpeername(fd, name, namelen) == 0) {
1083 #ifdef HAVE_IPX
1084             if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1085                 name = (struct sockaddr *)
1086                                 malloc(namelen ? *namelen : sizeof(*name2));
1087                 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1088                 name2->sipx_family = WS_AF_IPX;
1089                 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1090                 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1091                 memcpy(name2->sipx_node,
1092                         ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1093                 free(name);
1094             }
1095 #endif
1096             close(fd);
1097             return 0; 
1098         }
1099         SetLastError(wsaErrno());
1100         close(fd);
1101     }
1102     return SOCKET_ERROR;
1103 }
1104
1105 /***********************************************************************
1106  *              getpeername()           (WINSOCK.5)
1107  */
1108 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1109                                    INT16 *namelen16)
1110 {
1111     INT namelen32 = *namelen16;
1112     INT retVal = WSOCK32_getpeername( s, name, &namelen32 );
1113
1114 #if DEBUG_SOCKADDR
1115     dump_sockaddr(name);
1116 #endif
1117
1118    *namelen16 = namelen32;
1119     return (INT16)retVal;
1120 }
1121
1122 /***********************************************************************
1123  *              getsockname()           (WSOCK32.6)
1124  */
1125 INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name,
1126                                    INT *namelen)
1127 {
1128     LPWSINFO                 pwsi = WINSOCK_GetIData();
1129 #ifdef HAVE_IPX
1130     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
1131 #endif
1132
1133     TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
1134                           (unsigned)pwsi, s, (int) name, (int) *namelen);
1135     if( _check_ws(pwsi, s) )
1136     {
1137         int fd = _get_sock_fd(s);
1138         if (getsockname(fd, name, namelen) == 0) {
1139 #ifdef HAVE_IPX
1140             if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1141                 name = (struct sockaddr *)
1142                                 malloc(namelen ? *namelen : sizeof(*name2));
1143                 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1144                 name2->sipx_family = WS_AF_IPX;
1145                 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1146                 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1147                 memcpy(name2->sipx_node,
1148                         ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1149                 free(name);
1150             }
1151 #endif
1152             close(fd);
1153             return 0; 
1154         }
1155         SetLastError(wsaErrno());
1156         close(fd);
1157     }
1158     return SOCKET_ERROR;
1159 }
1160
1161 /***********************************************************************
1162  *              getsockname()           (WINSOCK.6)
1163  */
1164 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1165                                    INT16 *namelen16)
1166 {
1167     INT retVal;
1168
1169     if( namelen16 )
1170     {
1171         INT namelen32 = *namelen16;
1172         retVal = WSOCK32_getsockname( s, name, &namelen32 );
1173        *namelen16 = namelen32;
1174
1175 #if DEBUG_SOCKADDR
1176     dump_sockaddr(name);
1177 #endif
1178
1179     }
1180     else retVal = SOCKET_ERROR;
1181     return (INT16)retVal;
1182 }
1183
1184
1185 /***********************************************************************
1186  *              getsockopt()            (WSOCK32.7)
1187  */
1188 INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level, 
1189                                   INT optname, char *optval, INT *optlen)
1190 {
1191     LPWSINFO      pwsi = WINSOCK_GetIData();
1192
1193     TRACE("(%08x): socket: %04x, opt 0x%x, ptr %8x, len %d\n", 
1194                            (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
1195     if( _check_ws(pwsi, s) )
1196     {
1197         int fd = _get_sock_fd(s);
1198         if (!convert_sockopt(&level, &optname)) {
1199             SetLastError(WSAENOPROTOOPT);       /* Unknown option */
1200         } else {
1201             if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1202             {
1203                 close(fd);
1204                 return 0;
1205             }
1206             SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1207         }
1208         close(fd);
1209     }
1210     return SOCKET_ERROR;
1211 }
1212
1213 /***********************************************************************
1214  *              getsockopt()            (WINSOCK.7)
1215  */
1216 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1217                                   INT16 optname, char *optval, INT16 *optlen)
1218 {
1219     INT optlen32;
1220     INT *p = &optlen32;
1221     INT retVal;
1222     if( optlen ) optlen32 = *optlen; else p = NULL;
1223     retVal = WSOCK32_getsockopt( s, (UINT16)level, optname, optval, p );
1224     if( optlen ) *optlen = optlen32;
1225     return (INT16)retVal;
1226 }
1227
1228 /***********************************************************************
1229  *              htonl()                 (WINSOCK.8)(WSOCK32.8)
1230  */
1231 u_long WINAPI WINSOCK_htonl(u_long hostlong)   { return( htonl(hostlong) ); }
1232 /***********************************************************************
1233  *              htons()                 (WINSOCK.9)(WSOCK32.9)
1234  */
1235 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1236 /***********************************************************************
1237  *              inet_addr()             (WINSOCK.10)(WSOCK32.10)
1238  */
1239 u_long WINAPI WINSOCK_inet_addr(char *cp)      { return( inet_addr(cp) ); }
1240 /***********************************************************************
1241  *              ntohl()                 (WINSOCK.14)(WSOCK32.14)
1242  */
1243 u_long WINAPI WINSOCK_ntohl(u_long netlong)    { return( ntohl(netlong) ); }
1244 /***********************************************************************
1245  *              ntohs()                 (WINSOCK.15)(WSOCK32.15)
1246  */
1247 u_short WINAPI WINSOCK_ntohs(u_short netshort)  { return( ntohs(netshort) ); }
1248
1249 /***********************************************************************
1250  *              inet_ntoa()             (WINSOCK.11)(WSOCK32.11)
1251  */
1252 char* WINAPI WSOCK32_inet_ntoa(struct in_addr in)
1253 {
1254   /* use "buffer for dummies" here because some applications have 
1255    * propensity to decode addresses in ws_hostent structure without 
1256    * saving them first...
1257    */
1258
1259     LPWSINFO      pwsi = WINSOCK_GetIData();
1260
1261     if( pwsi )
1262     {
1263         char*   s = inet_ntoa(in);
1264         if( s ) 
1265         {
1266             if( pwsi->dbuffer == NULL ) {
1267                 /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1268                 if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(16)) == NULL )
1269                 {
1270                     SetLastError(WSAENOBUFS);
1271                     return NULL;
1272                 }
1273             }
1274             strcpy(pwsi->dbuffer, s);
1275             return pwsi->dbuffer; 
1276         }
1277         SetLastError(wsaErrno());
1278     }
1279     return NULL;
1280 }
1281
1282 /**********************************************************************/
1283
1284 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1285 {
1286   char* retVal = WSOCK32_inet_ntoa(in);
1287   return SEGPTR_GET(retVal);
1288 }
1289
1290
1291 /**********************************************************************
1292  *              WSAIoctl                (WS2_32)
1293  *
1294  *
1295  *   FIXME:  Only SIO_GET_INTERFACE_LIST option implemented.
1296  */
1297 INT WINAPI WSAIoctl (SOCKET s,
1298                      DWORD   dwIoControlCode,
1299                      LPVOID  lpvInBuffer,
1300                      DWORD   cbInBuffer,
1301                      LPVOID  lpbOutBuffer,
1302                      DWORD   cbOutBuffer,
1303                      LPDWORD lpcbBytesReturned,
1304                      LPWSAOVERLAPPED lpOverlapped,
1305                      LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1306 {
1307    LPWSINFO pwsi = WINSOCK_GetIData();
1308
1309    if( _check_ws(pwsi, s) )
1310    {
1311       int fd = _get_sock_fd(s);
1312
1313       switch( dwIoControlCode )
1314       {
1315          case SIO_GET_INTERFACE_LIST:
1316          {
1317             INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1318             int i, numInt;
1319             struct ifreq ifInfo;
1320             char ifName[512];
1321             
1322
1323             TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1324             
1325             numInt = WSAIOCTL_GetInterfaceCount(); 
1326             if (numInt < 0)
1327             {
1328                ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1329                close(fd);
1330                WSASetLastError(WSAEINVAL);
1331                return (SOCKET_ERROR);
1332             }
1333             
1334             for (i=0; i<numInt; i++)
1335             {
1336                if (!WSAIOCTL_GetInterfaceName(i, ifName))
1337                {
1338                   ERR ("Error parsing /proc filesystem!\n");
1339                   close(fd);
1340                   WSASetLastError(WSAEINVAL);
1341                   return (SOCKET_ERROR);
1342                }
1343                
1344                ifInfo.ifr_addr.sa_family = AF_INET; 
1345             
1346                /* IP Address */
1347                strcpy (ifInfo.ifr_name, ifName);
1348                if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0) 
1349                {
1350                   ERR ("Error obtaining IP address\n");
1351                   close(fd);
1352                   WSASetLastError(WSAEINVAL);
1353                   return (SOCKET_ERROR);
1354                }
1355                else
1356                {
1357                   struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1358                
1359                   intArray->iiAddress.AddressIn.sin_family = AF_INET;
1360                   intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1361                   intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1362                }
1363                
1364                /* Broadcast Address */
1365                strcpy (ifInfo.ifr_name, ifName);
1366                if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1367                {
1368                   ERR ("Error obtaining Broadcast IP address\n");
1369                   close(fd);
1370                   WSASetLastError(WSAEINVAL);
1371                   return (SOCKET_ERROR);
1372                }
1373                else
1374                {
1375                   struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
1376                
1377                   intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET; 
1378                   intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1379                   intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr; 
1380                }
1381
1382                /* Subnet Mask */
1383                strcpy (ifInfo.ifr_name, ifName);
1384                if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1385                {
1386                   ERR ("Error obtaining Subnet IP address\n");
1387                   close(fd);
1388                   WSASetLastError(WSAEINVAL);
1389                   return (SOCKET_ERROR);
1390                }
1391                else
1392                {
1393                   /* Trying to avoid some compile problems across platforms.
1394                      (Linux, FreeBSD, Solaris...) */
1395                   #ifndef ifr_netmask
1396                     #ifndef ifr_addr
1397                        intArray->iiNetmask.AddressIn.sin_family = AF_INET; 
1398                        intArray->iiNetmask.AddressIn.sin_port = 0;
1399                        intArray->iiNetmask.AddressIn.sin_addr.ws_addr = 0; 
1400                        ERR ("Unable to determine Netmask on your platform!\n");
1401                     #else
1402                        struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1403             
1404                        intArray->iiNetmask.AddressIn.sin_family = AF_INET; 
1405                        intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1406                        intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr; 
1407                     #endif
1408                   #else
1409                      struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
1410             
1411                      intArray->iiNetmask.AddressIn.sin_family = AF_INET; 
1412                      intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1413                      intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr; 
1414                   #endif
1415                }
1416                
1417                /* Socket Status Flags */
1418                strcpy(ifInfo.ifr_name, ifName);
1419                if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0) 
1420                {
1421                   ERR ("Error obtaining status flags for socket!\n");
1422                   close(fd);
1423                   WSASetLastError(WSAEINVAL);
1424                   return (SOCKET_ERROR);
1425                }
1426                else
1427                {
1428                   /* FIXME - Is this the right flag to use? */
1429                   intArray->iiFlags = ifInfo.ifr_flags;
1430                }
1431                intArray++; /* Prepare for another interface */
1432             }
1433             
1434             /* Calculate the size of the array being returned */
1435             *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1436             break;
1437          }
1438
1439          default:
1440          {
1441             WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1442             close(fd);
1443             WSASetLastError(WSAEOPNOTSUPP);
1444             return (SOCKET_ERROR);
1445          }
1446       }
1447
1448       /* Function executed with no errors */
1449       close(fd);
1450       return (0); 
1451    }
1452    else
1453    {
1454       WSASetLastError(WSAENOTSOCK);
1455       return (SOCKET_ERROR);
1456    }
1457 }
1458
1459
1460 /* 
1461   Helper function for WSAIoctl - Get count of the number of interfaces
1462   by parsing /proc filesystem.
1463 */
1464 int WSAIOCTL_GetInterfaceCount(void)
1465 {
1466    FILE *procfs;
1467    char buf[512];  /* Size doesn't matter, something big */
1468    int  intcnt=0;
1469  
1470  
1471    /* Open /proc filesystem file for network devices */ 
1472    procfs = fopen(PROCFS_NETDEV_FILE, "r");
1473    if (!procfs) 
1474    {
1475       /* If we can't open the file, return an error */
1476       return (-1);
1477    }
1478    
1479    /* Omit first two lines, they are only headers */
1480    fgets(buf, sizeof buf, procfs);      
1481    fgets(buf, sizeof buf, procfs);
1482
1483    while (fgets(buf, sizeof buf, procfs)) 
1484    {
1485       /* Each line in the file represents a network interface */
1486       intcnt++;
1487    }
1488
1489    fclose(procfs);
1490    return(intcnt);
1491 }
1492
1493
1494 /*
1495    Helper function for WSAIoctl - Get name of device from interface number
1496    by parsing /proc filesystem.
1497 */
1498 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1499 {
1500    FILE *procfs;
1501    char buf[512]; /* Size doesn't matter, something big */
1502    int  i;
1503
1504    /* Open /proc filesystem file for network devices */ 
1505    procfs = fopen(PROCFS_NETDEV_FILE, "r");
1506    if (!procfs) 
1507    {
1508       /* If we can't open the file, return an error */
1509       return (-1);
1510    }
1511    
1512    /* Omit first two lines, they are only headers */
1513    fgets(buf, sizeof(buf), procfs);     
1514    fgets(buf, sizeof(buf), procfs);
1515
1516    for (i=0; i<intNumber; i++)
1517    {
1518       /* Skip the lines that don't interest us. */
1519       fgets(buf, sizeof(buf), procfs);
1520    }
1521    fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1522
1523    
1524    /* Parse out the line, grabbing only the name of the device
1525       to the intName variable 
1526       
1527       The Line comes in like this: (we only care about the device name)
1528       lo:   21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1529    */
1530    i=0; 
1531    while (isspace(buf[i])) /* Skip initial space(s) */
1532    {
1533       i++;
1534    }
1535
1536    while (buf[i]) 
1537    {
1538       if (isspace(buf[i]))
1539       {
1540          break;
1541       }
1542       
1543       if (buf[i] == ':')  /* FIXME: Not sure if this block (alias detection) works properly */
1544       {
1545          /* This interface could be an alias... */
1546          int hold = i;
1547          char *dotname = intName;
1548          *intName++ = buf[i++];
1549          
1550          while (isdigit(buf[i]))
1551          {
1552             *intName++ = buf[i++];
1553          }
1554          
1555          if (buf[i] != ':') 
1556          {
1557             /* ... It wasn't, so back up */
1558             i = hold;
1559             intName = dotname;
1560          }
1561  
1562          if (buf[i] == '\0')
1563          {
1564             fclose(procfs);
1565             return(FALSE);
1566          }
1567          
1568          i++;
1569          break;
1570       }
1571       
1572       *intName++ = buf[i++];
1573    }
1574    *intName++ = '\0';
1575
1576    fclose(procfs);
1577    return(TRUE);
1578  }
1579
1580
1581 /***********************************************************************
1582  *              ioctlsocket()           (WSOCK32.12)
1583  */
1584 INT WINAPI WSOCK32_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1585 {
1586   LPWSINFO      pwsi = WINSOCK_GetIData();
1587
1588   TRACE("(%08x): socket %04x, cmd %08lx, ptr %8x\n", 
1589                           (unsigned)pwsi, s, cmd, (unsigned) argp);
1590   if( _check_ws(pwsi, s) )
1591   {
1592     int         fd = _get_sock_fd(s);
1593     long        newcmd  = cmd;
1594
1595     switch( cmd )
1596     {
1597         case WS_FIONREAD:   
1598                 newcmd=FIONREAD; 
1599                 break;
1600
1601         case WS_FIONBIO:    
1602                 newcmd=FIONBIO;  
1603                 if( _get_sock_mask(s) )
1604                 {
1605                     /* AsyncSelect()'ed sockets are always nonblocking */
1606                     if (*argp) {
1607                         close(fd);
1608                         return 0;
1609                     }
1610                     SetLastError(WSAEINVAL); 
1611                     close(fd);
1612                     return SOCKET_ERROR; 
1613                 }
1614                 close(fd);
1615                 if (*argp)
1616                     _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1617                 else
1618                     _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1619                 return 0;
1620
1621         case WS_SIOCATMARK: 
1622                 newcmd=SIOCATMARK; 
1623                 break;
1624
1625         case WS_IOW('f',125,u_long): 
1626                 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1627                 SetLastError(WSAEINVAL); 
1628                 return SOCKET_ERROR;
1629
1630         default:          
1631                 /* Netscape tries hard to use bogus ioctl 0x667e */
1632                 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1633     }
1634     if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1635     {
1636         close(fd);
1637         return 0;
1638     }
1639     SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno()); 
1640     close(fd);
1641   }
1642   return SOCKET_ERROR;
1643 }
1644
1645 /***********************************************************************
1646  *              ioctlsocket()           (WINSOCK.12)
1647  */
1648 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1649 {
1650     return (INT16)WSOCK32_ioctlsocket( s, cmd, argp );
1651 }
1652
1653
1654 /***********************************************************************
1655  *              listen()                (WSOCK32.13)
1656  */
1657 INT WINAPI WSOCK32_listen(SOCKET s, INT backlog)
1658 {
1659     LPWSINFO      pwsi = WINSOCK_GetIData();
1660
1661     TRACE("(%08x): socket %04x, backlog %d\n", 
1662                             (unsigned)pwsi, s, backlog);
1663     if( _check_ws(pwsi, s) )
1664     {
1665         int fd = _get_sock_fd(s);
1666         if (listen(fd, backlog) == 0)
1667         {
1668             close(fd);
1669             _enable_event(s, FD_ACCEPT,
1670                           WS_FD_LISTENING,
1671                           WS_FD_CONNECT|WS_FD_CONNECTED);
1672             return 0;
1673         }
1674         SetLastError(wsaErrno());
1675     }
1676     else SetLastError(WSAENOTSOCK);
1677     return SOCKET_ERROR;
1678 }
1679
1680 /***********************************************************************
1681  *              listen()                (WINSOCK.13)
1682  */
1683 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1684 {
1685     return (INT16)WSOCK32_listen( s, backlog );
1686 }
1687
1688
1689 /***********************************************************************
1690  *              recv()                  (WSOCK32.16)
1691  */
1692 INT WINAPI WSOCK32_recv(SOCKET s, char *buf, INT len, INT flags)
1693 {
1694     LPWSINFO      pwsi = WINSOCK_GetIData();
1695
1696     TRACE("(%08x): socket %04x, buf %8x, len %d, "
1697                     "flags %d\n", (unsigned)pwsi, s, (unsigned)buf, 
1698                     len, flags);
1699     if( _check_ws(pwsi, s) )
1700     {
1701         int fd = _get_sock_fd(s);
1702         INT length;
1703
1704         if (_is_blocking(s))
1705         {
1706             /* block here */
1707             /* FIXME: OOB and exceptfds? */
1708             do_block(fd, 1);
1709         }
1710         if ((length = recv(fd, buf, len, flags)) >= 0) 
1711         { 
1712             TRACE(" -> %i bytes\n", length);
1713
1714             close(fd);
1715             _enable_event(s, FD_READ, 0, 0);
1716             return length;
1717         }
1718         SetLastError(wsaErrno());
1719         close(fd);
1720     }
1721     else SetLastError(WSAENOTSOCK);
1722     WARN(" -> ERROR\n");
1723     return SOCKET_ERROR;
1724 }
1725
1726 /***********************************************************************
1727  *              recv()                  (WINSOCK.16)
1728  */
1729 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1730 {
1731     return (INT16)WSOCK32_recv( s, buf, len, flags );
1732 }
1733
1734
1735 /***********************************************************************
1736  *              recvfrom()              (WSOCK32.17)
1737  */
1738 INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags, 
1739                                 struct sockaddr *from, INT *fromlen32)
1740 {
1741     LPWSINFO                 pwsi = WINSOCK_GetIData();
1742 #ifdef HAVE_IPX
1743     struct ws_sockaddr_ipx*  from2 = (struct ws_sockaddr_ipx *)from;
1744 #endif
1745
1746     TRACE("(%08x): socket %04x, ptr %08x, "
1747                     "len %d, flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1748                     len, flags);
1749 #if DEBUG_SOCKADDR
1750     if( from ) dump_sockaddr(from);
1751     else DPRINTF("from = NULL\n");
1752 #endif
1753
1754     if( _check_ws(pwsi, s) )
1755     {
1756         int fd = _get_sock_fd(s);
1757         int length;
1758
1759         if (_is_blocking(s))
1760         {
1761             /* block here */
1762             /* FIXME: OOB and exceptfds */
1763             do_block(fd, 1);
1764         }
1765         if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1766         {
1767             TRACE(" -> %i bytes\n", length);
1768
1769 #ifdef HAVE_IPX
1770         if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1771             from = (struct sockaddr *)
1772                                 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1773             memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1774             from2->sipx_family = WS_AF_IPX;
1775             from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1776             from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1777             memcpy(from2->sipx_node,
1778                         ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1779             free(from);
1780         }
1781 #endif
1782             close(fd);
1783             _enable_event(s, FD_READ, 0, 0);
1784             return (INT16)length;
1785         }
1786         SetLastError(wsaErrno());
1787         close(fd);
1788     }
1789     else SetLastError(WSAENOTSOCK);
1790     WARN(" -> ERROR\n");
1791 #ifdef HAVE_IPX
1792     if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1793         from = (struct sockaddr *)
1794                                 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1795         memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1796         from2->sipx_family = WS_AF_IPX;
1797         from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1798         from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1799         memcpy(from2->sipx_node,
1800                 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1801         free(from);
1802     }
1803 #endif
1804     return SOCKET_ERROR;
1805 }
1806
1807 /***********************************************************************
1808  *              recvfrom()              (WINSOCK.17)
1809  */
1810 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1811                                 struct sockaddr *from, INT16 *fromlen16)
1812 {
1813     INT fromlen32;
1814     INT *p = &fromlen32;
1815     INT retVal;
1816
1817     if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1818     retVal = WSOCK32_recvfrom( s, buf, len, flags, from, p );
1819     if( fromlen16 ) *fromlen16 = fromlen32;
1820     return (INT16)retVal;
1821 }
1822
1823 /***********************************************************************
1824  *              select()                (WINSOCK.18)(WSOCK32.18)
1825  */
1826 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1827                           struct timeval *timeout )
1828 {
1829     LPWSINFO      pwsi = WINSOCK_GetIData();
1830         
1831     TRACE("(%08x): read %8x, write %8x, excp %8x\n", 
1832     (unsigned) pwsi, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
1833
1834     if( pwsi )
1835     {
1836         int         highfd = 0;
1837         fd_set      readfds, writefds, exceptfds;
1838         fd_set     *p_read, *p_write, *p_except;
1839         int         readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1840
1841         p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd, readfd, b32);
1842         p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd, writefd, b32);
1843         p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd, exceptfd, b32);
1844
1845         if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1846         {
1847             fd_set_export(pwsi, &readfds, p_except, ws_readfds, readfd, b32);
1848             fd_set_export(pwsi, &writefds, p_except, ws_writefds, writefd, b32);
1849
1850             if (p_except && ws_exceptfds)
1851             {
1852 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1853 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1854                 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1855
1856                 for (i = j = 0; i < count; i++)
1857                 {
1858                     int fd = exceptfd[i];
1859                     if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1860                     {
1861                         if( b32 )
1862                                 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1863                         else
1864                                 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1865                     }
1866                     if( fd >= 0 ) close(fd);
1867                     exceptfd[i] = -1;
1868                 }
1869                 if( b32 )
1870                     wsfds32->fd_count = j;
1871                 else
1872                     wsfds16->fd_count = j;
1873 #undef wsfds32
1874 #undef wsfds16
1875             }
1876             return highfd; 
1877         }
1878         fd_set_unimport(ws_readfds, readfd, b32);
1879         fd_set_unimport(ws_writefds, writefd, b32);
1880         fd_set_unimport(ws_exceptfds, exceptfd, b32);
1881         if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1882         if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1883         if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1884
1885         if( highfd == 0 ) return 0;
1886         SetLastError(wsaErrno());
1887     } 
1888     return SOCKET_ERROR;
1889 }
1890
1891 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1892                               ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1893                               struct timeval *timeout)
1894 {
1895     return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1896 }
1897
1898 INT WINAPI WSOCK32_select(INT nfds, ws_fd_set32 *ws_readfds,
1899                               ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1900                               struct timeval *timeout)
1901 {
1902     /* struct timeval is the same for both 32- and 16-bit code */
1903     return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1904 }
1905
1906
1907 /***********************************************************************
1908  *              send()                  (WSOCK32.19)
1909  */
1910 INT WINAPI WSOCK32_send(SOCKET s, char *buf, INT len, INT flags)
1911 {
1912     LPWSINFO      pwsi = WINSOCK_GetIData();
1913
1914     TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n", 
1915                            (unsigned)pwsi, s, (unsigned) buf, len, flags);
1916     if( _check_ws(pwsi, s) )
1917     {
1918         int     fd = _get_sock_fd(s);
1919         int     length;
1920
1921         if (_is_blocking(s))
1922         {
1923             /* block here */
1924             /* FIXME: exceptfds */
1925             do_block(fd, 2);
1926         }
1927         if ((length = send(fd, buf, len, flags)) < 0 ) 
1928         {
1929             SetLastError(wsaErrno());
1930             if( GetLastError() == WSAEWOULDBLOCK )
1931                 _enable_event(s, FD_WRITE, 0, 0);
1932         }
1933         else
1934         {
1935             close(fd);
1936             return (INT16)length;
1937         }
1938         close(fd);
1939     }
1940     else SetLastError(WSAENOTSOCK);
1941     return SOCKET_ERROR;
1942 }
1943
1944 /***********************************************************************
1945  *              send()                  (WINSOCK.19)
1946  */
1947 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1948 {
1949     return WSOCK32_send( s, buf, len, flags );
1950 }
1951
1952 /***********************************************************************
1953  *              sendto()                (WSOCK32.20)
1954  */
1955 INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
1956                               struct sockaddr *to, INT tolen)
1957 {
1958     LPWSINFO                 pwsi = WINSOCK_GetIData();
1959 #ifdef HAVE_IPX
1960     struct ws_sockaddr_ipx*  to2 = (struct ws_sockaddr_ipx *)to;
1961 #endif
1962
1963     TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1964                           (unsigned)pwsi, s, (unsigned) buf, len, flags);
1965     if( _check_ws(pwsi, s) )
1966     {
1967         int     fd = _get_sock_fd(s);
1968         INT     length;
1969
1970         if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1971             ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1972 #ifdef HAVE_IPX
1973         else if (to &&
1974                 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1975         {
1976             to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1977             memset(to, '\0', sizeof(struct sockaddr_ipx));
1978             ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1979             ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1980             ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1981             memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1982                         to2->sipx_node, IPX_NODE_LEN);
1983             tolen = sizeof(struct sockaddr_ipx);
1984         }
1985 #endif
1986         if (_is_blocking(s))
1987         {
1988             /* block here */
1989             /* FIXME: exceptfds */
1990             do_block(fd, 2);
1991         }
1992         if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
1993         {
1994             SetLastError(wsaErrno());
1995             if( GetLastError() == WSAEWOULDBLOCK )
1996                 _enable_event(s, FD_WRITE, 0, 0);
1997         } 
1998         else {
1999 #ifdef HAVE_IPX
2000             if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
2001                 free(to);
2002             }
2003 #endif
2004             close(fd);
2005             return length;
2006         }
2007         close(fd);
2008     }
2009     else SetLastError(WSAENOTSOCK);
2010 #ifdef HAVE_IPX
2011     if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
2012         free(to);
2013     }
2014 #endif
2015     return SOCKET_ERROR;
2016 }
2017
2018 /***********************************************************************
2019  *              sendto()                (WINSOCK.20)
2020  */
2021 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2022                               struct sockaddr *to, INT16 tolen)
2023 {
2024     return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
2025 }
2026
2027 /***********************************************************************
2028  *              setsockopt()            (WSOCK32.21)
2029  */
2030 INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname, 
2031                                   char *optval, INT optlen)
2032 {
2033     LPWSINFO      pwsi = WINSOCK_GetIData();
2034
2035     TRACE("(%08x): socket %04x, lev %d, opt 0x%x, ptr %08x, len %d\n",
2036                           (unsigned)pwsi, s, level, optname, (int) optval, optlen);
2037     if( _check_ws(pwsi, s) )
2038     {
2039         struct  linger linger;
2040         int fd = _get_sock_fd(s);
2041         int woptval;
2042
2043         /* Is a privileged and useless operation, so we don't. */
2044         if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2045             FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2046             return 0;
2047         }
2048
2049         if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2050             /* This is unique to WinSock and takes special conversion */
2051             linger.l_onoff      = *((int*)optval) ? 0: 1;
2052             linger.l_linger     = 0;
2053             optname=SO_LINGER;
2054             optval = (char*)&linger;
2055             optlen = sizeof(struct linger);
2056             level = SOL_SOCKET;
2057         }else{
2058             if (!convert_sockopt(&level, &optname)) {
2059                 SetLastError(WSAENOPROTOOPT);
2060                 close(fd);
2061                 return SOCKET_ERROR;
2062             }
2063             if (optname == SO_LINGER && optval) {
2064                 /* yes, uses unsigned short in both win16/win32 */
2065                 linger.l_onoff  = ((UINT16*)optval)[0];
2066                 linger.l_linger = ((UINT16*)optval)[1];
2067                 /* FIXME: what is documented behavior if SO_LINGER optval
2068                    is null?? */
2069                 optval = (char*)&linger;
2070                 optlen = sizeof(struct linger);
2071             } else if (optlen < sizeof(int)){
2072                 woptval= *((INT16 *) optval);
2073                 optval= (char*) &woptval;
2074                 optlen=sizeof(int);
2075             }
2076         }
2077         if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2078             WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2079             close( fd);
2080             return 0;
2081         }
2082
2083         if (setsockopt(fd, level, optname, optval, optlen) == 0)
2084         {
2085             close(fd);
2086             return 0;
2087         }
2088         SetLastError(wsaErrno());
2089         close(fd);
2090     }
2091     else SetLastError(WSAENOTSOCK);
2092     return SOCKET_ERROR;
2093 }
2094
2095 /***********************************************************************
2096  *              setsockopt()            (WINSOCK.21)
2097  */
2098 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2099                                   char *optval, INT16 optlen)
2100 {
2101     if( !optval ) return SOCKET_ERROR;
2102     return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2103 }
2104
2105
2106 /***********************************************************************
2107  *              shutdown()              (WSOCK32.22)
2108  */
2109 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2110 {
2111     LPWSINFO      pwsi = WINSOCK_GetIData();
2112
2113     TRACE("(%08x): socket %04x, how %i\n",
2114                             (unsigned)pwsi, s, how );
2115     if( _check_ws(pwsi, s) )
2116     {
2117         int fd = _get_sock_fd(s);
2118             switch( how )
2119             {
2120                 case 0: /* drop receives */
2121                         _enable_event(s, 0, 0, WS_FD_READ);
2122 #ifdef SHUT_RD
2123                         how = SHUT_RD;
2124 #endif
2125                         break;
2126
2127                 case 1: /* drop sends */
2128                         _enable_event(s, 0, 0, WS_FD_WRITE);
2129 #ifdef SHUT_WR
2130                         how = SHUT_WR;
2131 #endif
2132                         break;
2133
2134                 case 2: /* drop all */
2135 #ifdef SHUT_RDWR
2136                         how = SHUT_RDWR;
2137 #endif
2138                 default:
2139                         WSAAsyncSelect( s, 0, 0, 0 );
2140                         break;
2141             }
2142
2143         if (shutdown(fd, how) == 0) 
2144         {
2145             if( how > 1 ) 
2146             {
2147                 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2148             }
2149             close(fd);
2150             return 0;
2151         }
2152         SetLastError(wsaErrno());
2153         close(fd);
2154     } 
2155     else SetLastError(WSAENOTSOCK);
2156     return SOCKET_ERROR;
2157 }
2158
2159 /***********************************************************************
2160  *              shutdown()              (WINSOCK.22)
2161  */
2162 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2163 {
2164     return (INT16)WSOCK32_shutdown( s, how );
2165 }
2166
2167
2168 /***********************************************************************
2169  *              socket()                (WSOCK32.23)
2170  */
2171 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2172 {
2173   LPWSINFO      pwsi = WINSOCK_GetIData();
2174   SOCKET ret;
2175
2176   TRACE("(%08x): af=%d type=%d protocol=%d\n", 
2177                           (unsigned)pwsi, af, type, protocol);
2178
2179   if( pwsi )
2180   {
2181     /* check the socket family */
2182     switch(af) 
2183     {
2184 #ifdef HAVE_IPX
2185         case WS_AF_IPX: af = AF_IPX;
2186 #endif
2187         case AF_INET:
2188         case AF_UNSPEC: break;
2189         default:        SetLastError(WSAEAFNOSUPPORT); 
2190                         return INVALID_SOCKET;
2191     }
2192
2193     /* check the socket type */
2194     switch(type) 
2195     {
2196         case SOCK_STREAM:
2197         case SOCK_DGRAM:
2198         case SOCK_RAW:  break;
2199         default:        SetLastError(WSAESOCKTNOSUPPORT); 
2200                         return INVALID_SOCKET;
2201     }
2202
2203     /* check the protocol type */
2204     if ( protocol < 0 )  /* don't support negative values */
2205     { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2206
2207     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
2208         switch(protocol) 
2209         {
2210           case IPPROTO_TCP:
2211              if (type == SOCK_STREAM) { af = AF_INET; break; }
2212           case IPPROTO_UDP:
2213              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
2214           default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2215         }
2216
2217     SERVER_START_REQ
2218     {
2219         struct create_socket_request *req = server_alloc_req( sizeof(*req), 0 );
2220         req->family   = af;
2221         req->type     = type;
2222         req->protocol = protocol;
2223         req->access   = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2224         req->inherit  = TRUE;
2225         sock_server_call( REQ_CREATE_SOCKET );
2226         ret = req->handle;
2227     }
2228     SERVER_END_REQ;
2229     if ( ((int) ret) >= 0)
2230     {
2231         TRACE("\tcreated %04x\n", ret );
2232         return ret;
2233     }
2234
2235     if (GetLastError() == WSAEACCES) /* raw socket denied */
2236     {
2237         if (type == SOCK_RAW)
2238             MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2239         else
2240             MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2241         SetLastError(WSAESOCKTNOSUPPORT);
2242     }
2243   }
2244  
2245   WARN("\t\tfailed!\n");
2246   return INVALID_SOCKET;
2247 }
2248
2249 /***********************************************************************
2250  *              socket()                (WINSOCK.23)
2251  */
2252 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2253 {
2254     return (SOCKET16)WSOCK32_socket( af, type, protocol );
2255 }
2256     
2257
2258 /* ----------------------------------- DNS services
2259  *
2260  * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2261  * Also, we have to use wsock32 stubs to convert structures and
2262  * error codes from Unix to WSA, hence there is no direct mapping in 
2263  * the relay32/wsock32.spec.
2264  */
2265
2266 static char*    NULL_STRING = "NULL";
2267
2268 /***********************************************************************
2269  *              gethostbyaddr()         (WINSOCK.51)(WSOCK32.51)
2270  */
2271 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2272 {
2273     WIN_hostent *retval = NULL;
2274     LPWSINFO            pwsi = WINSOCK_GetIData();
2275
2276     if( pwsi )
2277     {
2278         struct hostent* host;
2279 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2280         char *extrabuf;
2281         int ebufsize=1024;
2282         struct hostent hostentry;
2283         int locerr=ENOBUFS;
2284         host = NULL;
2285         extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2286         while(extrabuf) { 
2287             int res = gethostbyaddr_r(addr, len, type, 
2288                     &hostentry, extrabuf, ebufsize, &host, &locerr);
2289             if( res != ERANGE) break;
2290             ebufsize *=2;
2291             extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2292         }
2293         if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2294 #else
2295         EnterCriticalSection( &csWSgetXXXbyYYY );
2296         host = gethostbyaddr(addr, len, type);
2297         if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2298 #endif
2299         if( host != NULL )
2300         {
2301             if( WS_dup_he(pwsi, host, dup_flag) )
2302                 retval = (WIN_hostent*)(pwsi->he);
2303             else 
2304                 SetLastError(WSAENOBUFS);
2305         }
2306 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2307         HeapFree(GetProcessHeap(),0,extrabuf);
2308 #else
2309         LeaveCriticalSection( &csWSgetXXXbyYYY );
2310 #endif
2311     }
2312     return retval;
2313 }
2314
2315 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2316 {
2317     WIN_hostent* retval;
2318     TRACE("ptr %08x, len %d, type %d\n",
2319                             (unsigned) addr, len, type);
2320     retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2321     return SEGPTR_GET(retval);
2322 }
2323
2324 WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2325                                                 INT type)
2326 {
2327     TRACE("ptr %08x, len %d, type %d\n",
2328                              (unsigned) addr, len, type);
2329     return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2330 }
2331
2332 /***********************************************************************
2333  *              gethostbyname()         (WINSOCK.52)(WSOCK32.52)
2334  */
2335 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2336 {
2337     WIN_hostent *retval = NULL;
2338     LPWSINFO              pwsi = WINSOCK_GetIData();
2339
2340     if( pwsi )
2341     {
2342         struct hostent*     host;
2343 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2344         char *extrabuf;
2345         int ebufsize=1024;
2346         struct hostent hostentry;
2347         int locerr = ENOBUFS;
2348         host = NULL;
2349         extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2350         while(extrabuf) { 
2351             int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2352             if( res != ERANGE) break;
2353             ebufsize *=2;
2354             extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2355         }
2356         if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2357 #else
2358         EnterCriticalSection( &csWSgetXXXbyYYY );
2359         host = gethostbyname(name);
2360         if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2361 #endif
2362         if( host  != NULL )
2363         {
2364              if( WS_dup_he(pwsi, host, dup_flag) )
2365                  retval = (WIN_hostent*)(pwsi->he);
2366              else SetLastError(WSAENOBUFS);
2367         }
2368 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2369         HeapFree(GetProcessHeap(),0,extrabuf);
2370 #else
2371         LeaveCriticalSection( &csWSgetXXXbyYYY );
2372 #endif
2373     }
2374     return retval;
2375 }
2376
2377 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2378 {
2379     WIN_hostent* retval;
2380     TRACE("%s\n", (name)?name:NULL_STRING);
2381     retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2382     return SEGPTR_GET(retval);
2383 }
2384
2385 WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2386 {
2387     TRACE("%s\n", (name)?name:NULL_STRING);
2388     return __ws_gethostbyname( name, WS_DUP_LINEAR );
2389 }
2390
2391
2392 /***********************************************************************
2393  *              getprotobyname()        (WINSOCK.53)(WSOCK32.53)
2394  */
2395 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2396 {
2397     WIN_protoent* retval = NULL;
2398     LPWSINFO              pwsi = WINSOCK_GetIData();
2399
2400     if( pwsi )
2401     {
2402         struct protoent*     proto;
2403         EnterCriticalSection( &csWSgetXXXbyYYY );
2404         if( (proto = getprotobyname(name)) != NULL )
2405         {
2406             if( WS_dup_pe(pwsi, proto, dup_flag) )
2407                 retval = (WIN_protoent*)(pwsi->pe);
2408             else SetLastError(WSAENOBUFS);
2409         }
2410         else {
2411             MESSAGE("protocol %s not found; You might want to add "
2412                     "this to /etc/protocols\n", debugstr_a(name) );
2413             SetLastError(WSANO_DATA);
2414         }
2415         LeaveCriticalSection( &csWSgetXXXbyYYY );
2416     } else SetLastError(WSANOTINITIALISED);
2417     return retval;
2418 }
2419
2420 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2421 {
2422     WIN_protoent* retval;
2423     TRACE("%s\n", (name)?name:NULL_STRING);
2424     retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2425     return SEGPTR_GET(retval);
2426 }
2427
2428 WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2429 {
2430     TRACE("%s\n", (name)?name:NULL_STRING);
2431     return __ws_getprotobyname(name, WS_DUP_LINEAR);
2432 }
2433
2434
2435 /***********************************************************************
2436  *              getprotobynumber()      (WINSOCK.54)(WSOCK32.54)
2437  */
2438 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2439 {
2440     WIN_protoent* retval = NULL;
2441     LPWSINFO              pwsi = WINSOCK_GetIData();
2442
2443     if( pwsi )
2444     {
2445         struct protoent*     proto;
2446         EnterCriticalSection( &csWSgetXXXbyYYY );
2447         if( (proto = getprotobynumber(number)) != NULL )
2448         {
2449             if( WS_dup_pe(pwsi, proto, dup_flag) )
2450                 retval = (WIN_protoent*)(pwsi->pe);
2451             else SetLastError(WSAENOBUFS);
2452         }
2453         else {
2454             MESSAGE("protocol number %d not found; You might want to add "
2455                     "this to /etc/protocols\n", number );
2456             SetLastError(WSANO_DATA);
2457         }
2458         LeaveCriticalSection( &csWSgetXXXbyYYY );
2459     } else SetLastError(WSANOTINITIALISED);
2460     return retval;
2461 }
2462
2463 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2464 {
2465     WIN_protoent* retval;
2466     TRACE("%i\n", number);
2467     retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2468     return SEGPTR_GET(retval);
2469 }
2470
2471 WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2472 {
2473     TRACE("%i\n", number);
2474     return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2475 }
2476
2477
2478 /***********************************************************************
2479  *              getservbyname()         (WINSOCK.55)(WSOCK32.55)
2480  */
2481 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2482 {
2483     WIN_servent* retval = NULL;
2484     LPWSINFO              pwsi = WINSOCK_GetIData();
2485
2486     if( pwsi )
2487     {
2488         struct servent*     serv;
2489         int i = wsi_strtolo( pwsi, name, proto );
2490
2491         if( i ) {
2492             EnterCriticalSection( &csWSgetXXXbyYYY );
2493             serv = getservbyname(pwsi->buffer,
2494                                  proto ? (pwsi->buffer + i) : NULL);
2495             if( serv != NULL )
2496             {
2497                 if( WS_dup_se(pwsi, serv, dup_flag) )
2498                     retval = (WIN_servent*)(pwsi->se);
2499                 else SetLastError(WSAENOBUFS);
2500             }
2501             else {
2502                 MESSAGE("service %s protocol %s not found; You might want to add "
2503                         "this to /etc/services\n", debugstr_a(pwsi->buffer),
2504                         proto ? debugstr_a(pwsi->buffer+i):"*"); 
2505                 SetLastError(WSANO_DATA);
2506             }
2507             LeaveCriticalSection( &csWSgetXXXbyYYY );
2508         }
2509         else SetLastError(WSAENOBUFS);
2510     } else SetLastError(WSANOTINITIALISED);
2511     return retval;
2512 }
2513
2514 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2515 {
2516     WIN_servent* retval;
2517     TRACE("'%s', '%s'\n",
2518                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2519     retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2520     return SEGPTR_GET(retval);
2521 }
2522
2523 WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2524 {
2525     TRACE("'%s', '%s'\n",
2526                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2527     return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2528 }
2529
2530
2531 /***********************************************************************
2532  *              getservbyport()         (WINSOCK.56)(WSOCK32.56)
2533  */
2534 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2535 {
2536     WIN_servent* retval = NULL;
2537     LPWSINFO              pwsi = WINSOCK_GetIData();
2538
2539     if( pwsi )
2540     {
2541         struct servent*     serv;
2542         if (!proto || wsi_strtolo( pwsi, proto, NULL )) {
2543             EnterCriticalSection( &csWSgetXXXbyYYY );
2544             if( (serv = getservbyport(port, (proto) ? pwsi->buffer : NULL)) != NULL ) {
2545                 if( WS_dup_se(pwsi, serv, dup_flag) )
2546                     retval = (WIN_servent*)(pwsi->se);
2547                 else SetLastError(WSAENOBUFS);
2548             }
2549             else {
2550                 MESSAGE("service on port %lu protocol %s not found; You might want to add "
2551                         "this to /etc/services\n", (unsigned long)ntohl(port),
2552                         proto ? debugstr_a(pwsi->buffer) : "*"); 
2553                 SetLastError(WSANO_DATA);
2554             }
2555             LeaveCriticalSection( &csWSgetXXXbyYYY );
2556         }
2557         else SetLastError(WSAENOBUFS);
2558     } else SetLastError(WSANOTINITIALISED);
2559     return retval;
2560 }
2561
2562 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2563 {
2564     WIN_servent* retval;
2565     TRACE("%d (i.e. port %d), '%s'\n",
2566                             (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2567     retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2568     return SEGPTR_GET(retval);
2569 }
2570
2571 WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2572 {
2573     TRACE("%d (i.e. port %d), '%s'\n",
2574                             (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2575     return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2576 }
2577
2578
2579 /***********************************************************************
2580  *              gethostname()           (WSOCK32.57)
2581  */
2582 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2583 {
2584     LPWSINFO              pwsi = WINSOCK_GetIData();
2585
2586     TRACE("(%08x): name %s, len %d\n",
2587                           (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
2588     if( pwsi )
2589     {
2590         if (gethostname(name, namelen) == 0) return 0;
2591         SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2592     }
2593     return SOCKET_ERROR;
2594 }
2595
2596 /***********************************************************************
2597  *              gethostname()           (WINSOCK.57)
2598  */
2599 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2600 {
2601     return (INT16)WSOCK32_gethostname(name, namelen);
2602 }
2603
2604
2605 /* ------------------------------------- Windows sockets extensions -- *
2606  *                                                                     *
2607  * ------------------------------------------------------------------- */
2608
2609 /***********************************************************************
2610  *              WSAEnumNetworkEvents
2611  */
2612 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2613 {
2614     LPWSINFO      pwsi = WINSOCK_GetIData();
2615
2616     TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2617                           (unsigned)pwsi, s, hEvent, (unsigned)lpEvent );
2618     if( _check_ws(pwsi, s) )
2619     {
2620         SERVER_START_REQ
2621         {
2622             struct get_socket_event_request *req = server_alloc_req( sizeof(*req),
2623                                                                      sizeof(lpEvent->iErrorCode) );
2624             req->handle  = s;
2625             req->service = TRUE;
2626             req->s_event = 0;
2627             req->c_event = hEvent;
2628             sock_server_call( REQ_GET_SOCKET_EVENT );
2629             lpEvent->lNetworkEvents = req->pmask;
2630             memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
2631         }
2632         SERVER_END_REQ;
2633         return 0;
2634     }
2635     else SetLastError(WSAEINVAL);
2636     return SOCKET_ERROR; 
2637 }
2638
2639 /***********************************************************************
2640  *              WSAEventSelect
2641  */
2642 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2643 {
2644     LPWSINFO      pwsi = WINSOCK_GetIData();
2645
2646     TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2647                           (unsigned)pwsi, s, hEvent, (unsigned)lEvent );
2648     if( _check_ws(pwsi, s) )
2649     {
2650         SERVER_START_REQ
2651         {
2652             struct set_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
2653             req->handle = s;
2654             req->mask   = lEvent;
2655             req->event  = hEvent;
2656             sock_server_call( REQ_SET_SOCKET_EVENT );
2657         }
2658         SERVER_END_REQ;
2659         return 0;
2660     }
2661     else SetLastError(WSAEINVAL);
2662     return SOCKET_ERROR; 
2663 }
2664
2665 /***********************************************************************
2666  *      WSAAsyncSelect()                (WINSOCK.101)(WSOCK32.101)
2667  */
2668
2669 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2670 {
2671     ws_select_info *info = (ws_select_info*)ptr;
2672     LPWSINFO      pwsi = info->pwsi;
2673     unsigned int i, pmask, orphan = FALSE;
2674     int errors[FD_MAX_EVENTS];
2675
2676     TRACE("socket %08x, event %08x\n", info->sock, info->event);
2677     SetLastError(0);
2678     SERVER_START_REQ
2679     {
2680         struct get_socket_event_request *req = server_alloc_req( sizeof(*req), sizeof(errors) );
2681         req->handle  = info->sock;
2682         req->service = TRUE;
2683         req->s_event = info->event; /* <== avoid race conditions */
2684         req->c_event = info->event;
2685         sock_server_call( REQ_GET_SOCKET_EVENT );
2686         pmask = req->pmask;
2687         memcpy( errors, server_data_ptr(req), server_data_size(req) );
2688     }
2689     SERVER_END_REQ;
2690     if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2691     {
2692         /* orphaned event (socket closed or something) */
2693         pmask = WS_FD_SERVEVENT;
2694         orphan = TRUE;
2695     }
2696
2697     /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2698     if (pmask & WS_FD_SERVEVENT) {
2699         int q;
2700         for (q=0; q<WS_ACCEPT_QUEUE; q++)
2701             if (pwsi->accept_old[q] == info->sock) {
2702                 /* there's only one service thread per pwsi, no lock necessary */
2703                 HANDLE as = pwsi->accept_new[q];
2704                 if (as) {
2705                     pwsi->accept_new[q] = 0;
2706                     pwsi->accept_old[q] = 0;
2707                     WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2708                 }
2709             }
2710         pmask &= ~WS_FD_SERVEVENT;
2711     }
2712     /* dispatch network events */
2713     for (i=0; i<FD_MAX_EVENTS; i++)
2714         if (pmask & (1<<i)) {
2715             TRACE("post: event bit %d, error %d\n", i, errors[i]);
2716             PostMessageA(info->hWnd, info->uMsg, info->sock,
2717                          WSAMAKESELECTREPLY(1<<i, errors[i]));
2718         }
2719     /* cleanup */
2720     if (orphan)
2721     {
2722         TRACE("orphaned event, self-destructing\n");
2723         /* SERVICE_Delete closes the event object */
2724         SERVICE_Delete( info->service );
2725         WS_FREE(info);
2726     }
2727 }
2728
2729 /**********************************************************************/
2730
2731 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2732 {
2733     LPWSINFO      pwsi = WINSOCK_GetIData();
2734
2735     TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2736                           (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2737     if( _check_ws(pwsi, s) )
2738     {
2739         if( lEvent )
2740         {
2741             ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2742             if( info )
2743             {
2744                 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2745                 INT err;
2746                 
2747                 info->sock   = s;
2748                 info->event  = hObj;
2749                 info->hWnd   = hWnd;
2750                 info->uMsg   = uMsg;
2751                 info->lEvent = lEvent;
2752                 info->pwsi   = pwsi;
2753                 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2754
2755                 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2756                 if (err) {
2757                     /* SERVICE_Delete closes the event object */
2758                     SERVICE_Delete( info->service );
2759                     WS_FREE(info);
2760                     return err;
2761                 }
2762
2763                 return 0; /* success */
2764             }
2765             else SetLastError(WSAENOBUFS);
2766         } 
2767         else
2768         {
2769             WSAEventSelect(s, 0, 0);
2770             return 0;
2771         }
2772     } 
2773     else SetLastError(WSAEINVAL);
2774     return SOCKET_ERROR; 
2775 }
2776
2777 /**********************************************************************/
2778
2779 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2780 {
2781     return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2782 }
2783
2784 /***********************************************************************
2785  *              WSARecvEx16()                   (WINSOCK.1107)
2786  *
2787  * See description for WSARecvEx()
2788  */
2789 INT16     WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2790   FIXME("(WSARecvEx16) partial packet return value not set \n");
2791
2792   return WINSOCK_recv16(s, buf, len, *flags);
2793 }
2794
2795
2796 /***********************************************************************
2797  *      WSACreateEvent()          (WS2_32.???)
2798  *
2799  */
2800 WSAEVENT WINAPI WSACreateEvent(void)
2801 {
2802     /* Create a manual-reset event, with initial state: unsignealed */
2803     TRACE("\n");
2804     
2805     return CreateEventA(NULL, TRUE, FALSE, NULL);    
2806 }
2807
2808 /***********************************************************************
2809  *      WSACloseEvent()          (WS2_32.???)
2810  *
2811  */
2812 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2813 {
2814     TRACE ("event=0x%x\n", event);
2815
2816     return CloseHandle(event);
2817 }
2818
2819 /***********************************************************************
2820  *      WSASocketA()          (WS2_32.???)
2821  *
2822  */
2823 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2824                          LPWSAPROTOCOL_INFOA lpProtocolInfo,
2825                          GROUP g, DWORD dwFlags)
2826 {
2827    /* 
2828       FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2829       g, dwFlags) are ignored.
2830    */
2831    
2832    TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n", 
2833          af, type, protocol, lpProtocolInfo, g, dwFlags );
2834
2835    return ( WSOCK32_socket (af, type, protocol) );
2836 }
2837
2838
2839 /***********************************************************************
2840  *      __WSAFDIsSet()                  (WINSOCK.151)
2841  */
2842 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2843 {
2844   int i = set->fd_count;
2845   
2846   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2847     
2848   while (i--)
2849       if (set->fd_array[i] == s) return 1;
2850   return 0;
2851 }                                                            
2852
2853 /***********************************************************************
2854  *      __WSAFDIsSet()                  (WSOCK32.151)
2855  */
2856 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2857 {
2858   int i = set->fd_count;
2859
2860   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2861
2862   while (i--)
2863       if (set->fd_array[i] == s) return 1;
2864   return 0;
2865 }
2866
2867 /***********************************************************************
2868  *      WSAIsBlocking()                 (WINSOCK.114)(WSOCK32.114)
2869  */
2870 BOOL WINAPI WSAIsBlocking(void)
2871 {
2872   /* By default WinSock should set all its sockets to non-blocking mode
2873    * and poll in PeekMessage loop when processing "blocking" ones. This 
2874    * function is supposed to tell if the program is in this loop. Our 
2875    * blocking calls are truly blocking so we always return FALSE.
2876    *
2877    * Note: It is allowed to call this function without prior WSAStartup().
2878    */
2879
2880   TRACE("\n");
2881   return FALSE;
2882 }
2883
2884 /***********************************************************************
2885  *      WSACancelBlockingCall()         (WINSOCK.113)(WSOCK32.113)
2886  */
2887 INT WINAPI WSACancelBlockingCall(void)
2888 {
2889   LPWSINFO              pwsi = WINSOCK_GetIData();
2890
2891   TRACE("(%08x)\n", (unsigned)pwsi);
2892
2893   if( pwsi ) return 0;
2894   return SOCKET_ERROR;
2895 }
2896
2897
2898 /***********************************************************************
2899  *      WSASetBlockingHook16()          (WINSOCK.109)
2900  */
2901 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2902 {
2903   FARPROC16             prev;
2904   LPWSINFO              pwsi = WINSOCK_GetIData();
2905
2906   TRACE("(%08x): hook %08x\n", 
2907                (unsigned)pwsi, (unsigned) lpBlockFunc);
2908   if( pwsi ) 
2909   { 
2910       prev = (FARPROC16)pwsi->blocking_hook; 
2911       pwsi->blocking_hook = (DWORD)lpBlockFunc; 
2912       pwsi->flags &= ~WSI_BLOCKINGHOOK;
2913       return prev; 
2914   }
2915   return 0;
2916 }
2917
2918
2919 /***********************************************************************
2920  *      WSASetBlockingHook()
2921  */
2922 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2923 {
2924   FARPROC             prev;
2925   LPWSINFO              pwsi = WINSOCK_GetIData();
2926
2927   TRACE("(%08x): hook %08x\n",
2928                (unsigned)pwsi, (unsigned) lpBlockFunc);
2929   if( pwsi ) {
2930       prev = (FARPROC)pwsi->blocking_hook;
2931       pwsi->blocking_hook = (DWORD)lpBlockFunc;
2932       pwsi->flags |= WSI_BLOCKINGHOOK;
2933       return prev;
2934   }
2935   return NULL;
2936 }
2937
2938
2939 /***********************************************************************
2940  *      WSAUnhookBlockingHook16()       (WINSOCK.110)
2941  */
2942 INT16 WINAPI WSAUnhookBlockingHook16(void)
2943 {
2944     LPWSINFO              pwsi = WINSOCK_GetIData();
2945
2946     TRACE("(%08x)\n", (unsigned)pwsi);
2947     if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
2948     return SOCKET_ERROR;
2949 }
2950
2951
2952 /***********************************************************************
2953  *      WSAUnhookBlockingHook()
2954  */
2955 INT WINAPI WSAUnhookBlockingHook(void)
2956 {
2957     LPWSINFO              pwsi = WINSOCK_GetIData();
2958
2959     TRACE("(%08x)\n", (unsigned)pwsi);
2960     if( pwsi )
2961     {
2962         pwsi->blocking_hook = 0;
2963         pwsi->flags &= ~WSI_BLOCKINGHOOK;
2964         return 0;
2965     }
2966     return SOCKET_ERROR;
2967 }
2968
2969
2970 /* ----------------------------------- end of API stuff */
2971
2972 /* ----------------------------------- helper functions -
2973  *
2974  * TODO: Merge WS_dup_..() stuff into one function that
2975  * would operate with a generic structure containing internal
2976  * pointers (via a template of some kind).
2977  */
2978
2979 static int list_size(char** l, int item_size)
2980 {
2981   int i,j = 0;
2982   if(l)
2983   { for(i=0;l[i];i++) 
2984         j += (item_size) ? item_size : strlen(l[i]) + 1;
2985     j += (i + 1) * sizeof(char*); }
2986   return j;
2987 }
2988
2989 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2990
2991    /* base is either either equal to ref or 0 or SEGPTR */
2992
2993    char*                p = ref;
2994    char**               l_to = (char**)ref;
2995    int                  i,j,k;
2996
2997    for(j=0;l_src[j];j++) ;
2998    p += (j + 1) * sizeof(char*);
2999    for(i=0;i<j;i++)
3000    { l_to[i] = base + (p - ref);
3001      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3002      memcpy(p, l_src[i], k); p += k; }
3003    l_to[i] = NULL;
3004    return (p - ref);
3005 }
3006
3007 /* ----- hostent */
3008
3009 static int hostent_size(struct hostent* p_he)
3010 {
3011   int size = 0;
3012   if( p_he )
3013   { size  = sizeof(struct hostent); 
3014     size += strlen(p_he->h_name) + 1;
3015     size += list_size(p_he->h_aliases, 0);  
3016     size += list_size(p_he->h_addr_list, p_he->h_length ); }
3017   return size;
3018 }
3019
3020 /* duplicate hostent entry
3021  * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3022  * Dito for protoent and servent.
3023  */
3024 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
3025 {
3026     /* Convert hostent structure into ws_hostent so that the data fits 
3027      * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or 
3028      * relative to pwsi->buffer depending on "flag" value. Returns size
3029      * of the data copied (also in the pwsi->buflen).
3030      */
3031
3032     int size = hostent_size(p_he);
3033     if( size )
3034     {
3035         char *p_name,*p_aliases,*p_addr,*p_base,*p;
3036         char *p_to;
3037         struct ws_hostent16 *p_to16;
3038         struct ws_hostent32 *p_to32;
3039
3040         _check_buffer_he(pwsi, size);
3041         p_to = (char *)pwsi->he;
3042         p_to16 = (struct ws_hostent16*)pwsi->he;
3043         p_to32 = (struct ws_hostent32*)pwsi->he;
3044
3045         p = p_to;
3046         p_base = (flag & WS_DUP_OFFSET) ? NULL
3047             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3048         p += (flag & WS_DUP_SEGPTR) ?
3049             sizeof(struct ws_hostent16) : sizeof(struct ws_hostent32);
3050         p_name = p;
3051         strcpy(p, p_he->h_name); p += strlen(p) + 1;
3052         p_aliases = p;
3053         p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3054         p_addr = p;
3055         list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3056
3057         if (flag & WS_DUP_SEGPTR) /* Win16 */
3058         {
3059             p_to16->h_addrtype = (INT16)p_he->h_addrtype; 
3060             p_to16->h_length = (INT16)p_he->h_length;
3061             p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3062             p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3063             p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3064             size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3065         }
3066         else /* Win32 */
3067         {
3068             p_to32->h_addrtype = p_he->h_addrtype; 
3069             p_to32->h_length = p_he->h_length;
3070             p_to32->h_name = (p_base + (p_name - p_to));
3071             p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3072             p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3073             size += (sizeof(struct ws_hostent32) - sizeof(struct hostent));
3074         }
3075     }
3076     return size;
3077 }
3078
3079 /* ----- protoent */
3080
3081 static int protoent_size(struct protoent* p_pe)
3082 {
3083   int size = 0;
3084   if( p_pe )
3085   { size  = sizeof(struct protoent);
3086     size += strlen(p_pe->p_name) + 1;
3087     size += list_size(p_pe->p_aliases, 0); }
3088   return size;
3089 }
3090
3091 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
3092 {
3093     int size = protoent_size(p_pe);
3094     if( size )
3095     {
3096         char *p_to;
3097         struct ws_protoent16 *p_to16;
3098         struct ws_protoent32 *p_to32;
3099         char *p_name,*p_aliases,*p_base,*p;
3100
3101         _check_buffer_pe(pwsi, size);
3102         p_to = (char *)pwsi->pe;
3103         p_to16 = (struct ws_protoent16*)pwsi->pe;
3104         p_to32 = (struct ws_protoent32*)pwsi->pe;
3105         p = p_to;
3106         p_base = (flag & WS_DUP_OFFSET) ? NULL
3107             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3108         p += (flag & WS_DUP_SEGPTR) ?
3109             sizeof(struct ws_protoent16) : sizeof(struct ws_protoent32);
3110         p_name = p;
3111         strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3112         p_aliases = p;
3113         list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3114
3115         if (flag & WS_DUP_SEGPTR) /* Win16 */
3116         {
3117             p_to16->p_proto = (INT16)p_pe->p_proto;
3118             p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3119             p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to)); 
3120             size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3121         }
3122         else /* Win32 */
3123         {
3124             p_to32->p_proto = p_pe->p_proto;
3125             p_to32->p_name = (p_base) + (p_name - p_to);
3126             p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to)); 
3127             size += (sizeof(struct ws_protoent32) - sizeof(struct protoent));
3128         }
3129     }
3130     return size;
3131 }
3132
3133 /* ----- servent */
3134
3135 static int servent_size(struct servent* p_se)
3136 {
3137   int size = 0;
3138   if( p_se )
3139   { size += sizeof(struct servent);
3140     size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3141     size += list_size(p_se->s_aliases, 0); }
3142   return size;
3143 }
3144
3145 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
3146 {
3147     int size = servent_size(p_se);
3148     if( size )
3149     {
3150         char *p_name,*p_aliases,*p_proto,*p_base,*p;
3151         char *p_to;
3152         struct ws_servent16 *p_to16;
3153         struct ws_servent32 *p_to32;
3154
3155         _check_buffer_se(pwsi, size);
3156         p_to = (char *)pwsi->se;
3157         p_to16 = (struct ws_servent16*)pwsi->se;
3158         p_to32 = (struct ws_servent32*)pwsi->se;
3159         p = p_to;
3160         p_base = (flag & WS_DUP_OFFSET) ? NULL 
3161             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3162         p += (flag & WS_DUP_SEGPTR) ?
3163             sizeof(struct ws_servent16) : sizeof(struct ws_servent32);
3164         p_name = p;
3165         strcpy(p, p_se->s_name); p += strlen(p) + 1;
3166         p_proto = p;
3167         strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3168         p_aliases = p;
3169         list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3170
3171         if (flag & WS_DUP_SEGPTR) /* Win16 */
3172         { 
3173             p_to16->s_port = (INT16)p_se->s_port;
3174             p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3175             p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3176             p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3177             size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3178         }
3179         else /* Win32 */
3180         {
3181             p_to32->s_port = p_se->s_port;
3182             p_to32->s_name = (p_base + (p_name - p_to));
3183             p_to32->s_proto = (p_base + (p_proto - p_to));
3184             p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3185             size += (sizeof(struct ws_servent32) - sizeof(struct servent));
3186         }
3187     }
3188     return size;
3189 }
3190
3191 /* ----------------------------------- error handling */
3192
3193 UINT16 wsaErrno(void)
3194 {
3195     int loc_errno = errno; 
3196     WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3197
3198     switch(loc_errno)
3199     {
3200         case EINTR:             return WSAEINTR;
3201         case EBADF:             return WSAEBADF;
3202         case EPERM:
3203         case EACCES:            return WSAEACCES;
3204         case EFAULT:            return WSAEFAULT;
3205         case EINVAL:            return WSAEINVAL;
3206         case EMFILE:            return WSAEMFILE;
3207         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
3208         case EINPROGRESS:       return WSAEINPROGRESS;
3209         case EALREADY:          return WSAEALREADY;
3210         case ENOTSOCK:          return WSAENOTSOCK;
3211         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
3212         case EMSGSIZE:          return WSAEMSGSIZE;
3213         case EPROTOTYPE:        return WSAEPROTOTYPE;
3214         case ENOPROTOOPT:       return WSAENOPROTOOPT;
3215         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
3216         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
3217         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
3218         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
3219         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
3220         case EADDRINUSE:        return WSAEADDRINUSE;
3221         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
3222         case ENETDOWN:          return WSAENETDOWN;
3223         case ENETUNREACH:       return WSAENETUNREACH;
3224         case ENETRESET:         return WSAENETRESET;
3225         case ECONNABORTED:      return WSAECONNABORTED;
3226         case EPIPE:
3227         case ECONNRESET:        return WSAECONNRESET;
3228         case ENOBUFS:           return WSAENOBUFS;
3229         case EISCONN:           return WSAEISCONN;
3230         case ENOTCONN:          return WSAENOTCONN;
3231         case ESHUTDOWN:         return WSAESHUTDOWN;
3232         case ETOOMANYREFS:      return WSAETOOMANYREFS;
3233         case ETIMEDOUT:         return WSAETIMEDOUT;
3234         case ECONNREFUSED:      return WSAECONNREFUSED;
3235         case ELOOP:             return WSAELOOP;
3236         case ENAMETOOLONG:      return WSAENAMETOOLONG;
3237         case EHOSTDOWN:         return WSAEHOSTDOWN;
3238         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
3239         case ENOTEMPTY:         return WSAENOTEMPTY;
3240 #ifdef EPROCLIM
3241         case EPROCLIM:          return WSAEPROCLIM;
3242 #endif
3243 #ifdef EUSERS
3244         case EUSERS:            return WSAEUSERS;
3245 #endif
3246 #ifdef EDQUOT
3247         case EDQUOT:            return WSAEDQUOT;
3248 #endif
3249 #ifdef ESTALE
3250         case ESTALE:            return WSAESTALE;
3251 #endif
3252 #ifdef EREMOTE
3253         case EREMOTE:           return WSAEREMOTE;
3254 #endif
3255
3256        /* just in case we ever get here and there are no problems */
3257         case 0:                 return 0;
3258         default:
3259                 WARN("Unknown errno %d!\n", loc_errno);
3260                 return WSAEOPNOTSUPP;
3261     }
3262 }
3263
3264 UINT16 wsaHerrno(int loc_errno)
3265 {
3266
3267     WARN("h_errno %d.\n", loc_errno);
3268
3269     switch(loc_errno)
3270     {
3271         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
3272         case TRY_AGAIN:         return WSATRY_AGAIN;
3273         case NO_RECOVERY:       return WSANO_RECOVERY;
3274         case NO_DATA:           return WSANO_DATA; 
3275         case ENOBUFS:           return WSAENOBUFS;
3276
3277         case 0:                 return 0;
3278         default:
3279                 WARN("Unknown h_errno %d!\n", loc_errno);
3280                 return WSAEOPNOTSUPP;
3281     }
3282 }