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