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