Send WM_CTLCOLOREDIT not WM_CTLCOLORSTATIC messages to parent of a
[wine] / misc / winsock.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  */
12  
13 #include "config.h"
14
15 #include <string.h>
16 #include <sys/types.h>
17 #ifdef HAVE_SYS_IPC_H
18 # include <sys/ipc.h>
19 #endif
20 #include <sys/ioctl.h>
21 #ifdef HAVE_SYS_FILIO_H
22 # include <sys/filio.h>
23 #endif
24 #if defined(__svr4__) || defined(__sun)
25 #include <sys/ioccom.h>
26 #ifdef HAVE_SYS_SOCKIO_H
27 # include <sys/sockio.h>
28 #endif
29 #endif
30
31 #if defined(__EMX__)
32 # include <sys/so_ioctl.h>
33 #endif
34
35 #ifdef HAVE_SYS_PARAM_H
36 # include <sys/param.h>
37 #endif
38
39 #ifdef HAVE_SYS_MSG_H
40 # include <sys/msg.h>
41 #endif
42 #ifdef HAVE_SYS_WAIT_H
43 # include <sys/wait.h>
44 #endif
45 #ifdef HAVE_SYS_SOCKET_H
46 #include <sys/socket.h>
47 #endif
48 #ifdef HAVE_NETINET_IN_H
49 # include <netinet/in.h>
50 #endif
51 #ifdef HAVE_NETINET_TCP_H
52 # include <netinet/tcp.h>
53 #endif
54 #ifdef HAVE_ARPA_INET_H
55 # include <arpa/inet.h>
56 #endif
57 #include <ctype.h>
58 #include <fcntl.h>
59 #include <errno.h>
60 #ifdef HAVE_SYS_ERRNO_H
61 #include <sys/errno.h>
62 #endif
63 #include <netdb.h>
64 #include <unistd.h>
65 #include <stdlib.h>
66 #ifdef HAVE_ARPA_NAMESER_H
67 # include <arpa/nameser.h>
68 #endif
69 #ifdef HAVE_RESOLV_H
70 # include <resolv.h>
71 #endif
72
73 #include "wine/winbase16.h"
74 #include "winsock2.h"
75 #include "winnt.h"
76 #include "heap.h"
77 #include "task.h"
78 #include "message.h"
79 #include "miscemu.h"
80 #include "services.h"
81 #include "server.h"
82 #include "debugtools.h"
83
84 DEFAULT_DEBUG_CHANNEL(winsock)
85
86 #define DEBUG_SOCKADDR 0
87 #define dump_sockaddr(a) \
88         DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
89                         ((struct sockaddr_in *)a)->sin_family, \
90                         inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
91                         ntohs(((struct sockaddr_in *)a)->sin_port))
92
93 /* ----------------------------------- internal data */
94
95 /* ws_... struct conversion flags */
96
97 #define WS_DUP_LINEAR           0x0001
98 #define WS_DUP_NATIVE           0x0000          /* not used anymore */
99 #define WS_DUP_OFFSET           0x0002          /* internal pointers are offsets */
100 #define WS_DUP_SEGPTR           0x0004          /* internal pointers are SEGPTRs */
101                                                 /* by default, internal pointers are linear */
102 typedef struct          /* WSAAsyncSelect() control struct */
103 {
104   HANDLE      service, event, sock;
105   HWND        hWnd;
106   UINT        uMsg;
107 } ws_select_info;  
108
109 #define WS_MAX_SOCKETS_PER_PROCESS      128     /* reasonable guess */
110 #define WS_MAX_UDP_DATAGRAM             1024
111
112 #define WSI_BLOCKINGCALL        0x00000001      /* per-thread info flags */
113 #define WSI_BLOCKINGHOOK        0x00000002      /* 32-bit callback */
114
115 typedef struct _WSINFO
116 {
117   DWORD                 dwThisProcess;
118   struct _WSINFO       *lpNextIData;
119
120   unsigned              flags;
121   INT16                 num_startup;            /* reference counter */
122   INT16                 num_async_rq;
123   INT16                 last_free;              /* entry in the socket table */
124   UINT16                buflen;
125   char*                 buffer;                 /* allocated from SEGPTR heap */
126   struct ws_hostent     *he;
127   int                   helen;
128   struct ws_servent     *se;
129   int                   selen;
130   struct ws_protoent    *pe;
131   int                   pelen;
132   char*                 dbuffer;                /* buffer for dummies (32 bytes) */
133
134   DWORD                 blocking_hook;
135 } WSINFO, *LPWSINFO;
136
137 /* function prototypes */
138 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag);
139 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
140 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
141
142 UINT16 wsaErrno(void);
143 UINT16 wsaHerrno(void);
144                                                       
145 static HANDLE   _WSHeap = 0;
146
147 #define WS_ALLOC(size) \
148         HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
149 #define WS_FREE(ptr) \
150         HeapFree(_WSHeap, 0, (ptr) )
151
152 static INT         _ws_sock_ops[] =
153        { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
154          WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
155          WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER,
156 #ifdef SO_RCVTIMEO
157          WS_SO_RCVTIMEO,
158 #endif
159          0 };
160 static int           _px_sock_ops[] =
161        { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
162          SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
163          SO_LINGER,
164 #ifdef SO_RCVTIMEO
165          SO_RCVTIMEO,
166 #endif
167         };
168
169 static INT _ws_tcp_ops[] = {
170 #ifdef TCP_NODELAY
171         WS_TCP_NODELAY,
172 #endif
173         0
174 };
175 static int _px_tcp_ops[] = {
176 #ifdef TCP_NODELAY
177         TCP_NODELAY,
178 #endif
179         0
180 };
181
182 static int   _check_ws(LPWSINFO pwsi, SOCKET s);
183 static char* _check_buffer(LPWSINFO pwsi, int size);
184
185 static int _get_sock_fd(SOCKET s)
186 {
187     struct get_read_fd_request *req = get_req_buffer();
188     int fd;
189     
190     req->handle = s;
191     server_call_fd( REQ_GET_READ_FD, -1, &fd );
192     if (fd == -1)
193         FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
194     return fd;    
195 }
196
197 static void _enable_event(SOCKET s, unsigned int event,
198                           unsigned int sstate, unsigned int cstate)
199 {
200     struct enable_socket_event_request *req = get_req_buffer();
201     
202     req->handle = s;
203     req->mask   = event;
204     req->sstate = sstate;
205     req->cstate = cstate;
206     server_call( REQ_ENABLE_SOCKET_EVENT );
207 }
208
209 static int _is_blocking(SOCKET s)
210 {
211     struct get_socket_event_request *req = get_req_buffer();
212     
213     req->handle  = s;
214     req->service = FALSE;
215     req->s_event = 0;
216     server_call( REQ_GET_SOCKET_EVENT );
217     return (req->state & WS_FD_NONBLOCKING) == 0;
218 }
219
220 static unsigned int _get_sock_mask(SOCKET s)
221 {
222     struct get_socket_event_request *req = get_req_buffer();
223     
224     req->handle  = s;
225     req->service = FALSE;
226     req->s_event = 0;
227     server_call( REQ_GET_SOCKET_EVENT );
228     return req->mask;
229 }
230
231 static void _sync_sock_state(SOCKET s)
232 {
233     /* do a dummy wineserver request in order to let
234        the wineserver run through its select loop once */
235     (void)_is_blocking(s);
236 }
237
238 static int _get_sock_error(SOCKET s, unsigned int bit)
239 {
240     struct get_socket_event_request *req = get_req_buffer();
241     
242     req->handle  = s;
243     req->service = FALSE;
244     req->s_event = 0;
245     server_call( REQ_GET_SOCKET_EVENT );
246     return req->errors[bit];
247 }
248
249 static LPWSINFO lpFirstIData = NULL;
250
251 static LPWSINFO WINSOCK_GetIData(void)
252 {
253     DWORD pid = GetCurrentProcessId();
254     LPWSINFO iData;
255
256     for (iData = lpFirstIData; iData; iData = iData->lpNextIData) {
257         if (iData->dwThisProcess == pid)
258             break;
259     }
260     return iData;
261 }
262
263 static BOOL WINSOCK_CreateIData(void)
264 {
265     LPWSINFO iData;
266     
267     iData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WSINFO));
268     if (!iData)
269         return FALSE;
270     iData->dwThisProcess = GetCurrentProcessId();
271     iData->lpNextIData = lpFirstIData;
272     lpFirstIData = iData;
273     return TRUE;
274 }
275
276 static void WINSOCK_DeleteIData(void)
277 {
278     LPWSINFO iData = WINSOCK_GetIData();
279     LPWSINFO* ppid;
280     if (iData) {
281         for (ppid = &lpFirstIData; *ppid; ppid = &(*ppid)->lpNextIData) {
282             if (*ppid == iData) {
283                 *ppid = iData->lpNextIData;
284                 break;
285             }
286         }
287
288         if( iData->flags & WSI_BLOCKINGCALL )
289             TRACE("\tinside blocking call!\n");
290
291         /* delete scratch buffers */
292
293         if( iData->buffer ) SEGPTR_FREE(iData->buffer);
294         if( iData->dbuffer ) SEGPTR_FREE(iData->dbuffer);
295
296         HeapFree(GetProcessHeap(), 0, iData);
297     }
298 }
299
300 BOOL WINAPI WSOCK32_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
301 {
302     TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
303     switch (fdwReason) {
304     case DLL_PROCESS_DETACH:
305         WINSOCK_DeleteIData();
306         break;
307     }
308     return TRUE;
309 }
310
311 BOOL WINAPI WINSOCK_LibMain(DWORD fdwReason, HINSTANCE hInstDLL, WORD ds,
312                             WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
313 {
314     TRACE("0x%x 0x%lx\n", hInstDLL, fdwReason);
315     switch (fdwReason) {
316     case DLL_PROCESS_DETACH:
317         WINSOCK_DeleteIData();
318         break;
319     }
320     return TRUE;
321 }
322                                                                           
323 /***********************************************************************
324  *          convert_sockopt()
325  *
326  * Converts socket flags from Windows format.
327  */
328 static void convert_sockopt(INT *level, INT *optname)
329 {
330   int i;
331   switch (*level)
332   {
333      case WS_SOL_SOCKET:
334         *level = SOL_SOCKET;
335         for(i=0; _ws_sock_ops[i]; i++)
336             if( _ws_sock_ops[i] == *optname ) break;
337         if( _ws_sock_ops[i] ) *optname = _px_sock_ops[i];
338         else FIXME("Unknown SOL_SOCKET optname %d\n", *optname);
339         break;
340      case WS_IPPROTO_TCP:
341         *level = IPPROTO_TCP;
342         for(i=0; _ws_tcp_ops[i]; i++)
343                 if ( _ws_tcp_ops[i] == *optname ) break;
344         if( _ws_tcp_ops[i] ) *optname = _px_tcp_ops[i];
345         else FIXME("Unknown IPPROTO_TCP optname %d\n", *optname);
346         break;
347   }
348 }
349
350 /* ----------------------------------- Per-thread info (or per-process?) */
351
352 static int wsi_strtolo(LPWSINFO pwsi, const char* name, const char* opt)
353 {
354     /* Stuff a lowercase copy of the string into the local buffer */
355
356     int i = strlen(name) + 2;
357     char* p = _check_buffer(pwsi, i + ((opt)?strlen(opt):0));
358
359     if( p )
360     {
361         do *p++ = tolower(*name); while(*name++);
362         i = (p - (char*)(pwsi->buffer));
363         if( opt ) do *p++ = tolower(*opt); while(*opt++);
364         return i;
365     }
366     return 0;
367 }
368
369 static fd_set* fd_set_import( fd_set* fds, LPWSINFO pwsi, void* wsfds, int* highfd, int lfd[], BOOL b32 )
370 {
371     /* translate Winsock fd set into local fd set */
372
373     if( wsfds ) 
374     { 
375 #define wsfds16 ((ws_fd_set16*)wsfds)
376 #define wsfds32 ((ws_fd_set32*)wsfds)
377         int i, count;
378
379         FD_ZERO(fds);
380         count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
381
382         for( i = 0; i < count; i++ )
383         {
384              int s = (b32) ? wsfds32->fd_array[i]
385                            : wsfds16->fd_array[i];
386              if( _check_ws(pwsi, s) )
387              {
388                     int fd = _get_sock_fd(s);
389                     lfd[ i ] = fd;
390                     if( fd > *highfd ) *highfd = fd;
391                     FD_SET(fd, fds);
392              }
393              else lfd[ i ] = -1;
394         }
395 #undef wsfds32
396 #undef wsfds16
397         return fds;
398     }
399     return NULL;
400 }
401
402 inline static int sock_error_p(int s)
403 {
404     unsigned int optval, optlen;
405
406     optlen = sizeof(optval);
407     getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
408     if (optval) WARN("\t[%i] error: %d\n", s, optval);
409     return optval != 0;
410 }
411
412 static int fd_set_export( LPWSINFO pwsi, fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
413 {
414     int num_err = 0;
415
416     /* translate local fd set into Winsock fd set, adding
417      * errors to exceptfds (only if app requested it) */
418
419     if( wsfds )
420     {
421 #define wsfds16 ((ws_fd_set16*)wsfds)
422 #define wsfds32 ((ws_fd_set32*)wsfds)
423         int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
424
425         for( i = 0, j = 0; i < count; i++ )
426         {
427             if( lfd[i] >= 0 )
428             {
429                 int fd = lfd[i];
430                 if( FD_ISSET(fd, fds) )
431                 {
432                     if ( exceptfds && sock_error_p(fd) )
433                     {
434                         FD_SET(fd, exceptfds);
435                         num_err++;
436                     }
437                     else if( b32 )
438                              wsfds32->fd_array[j++] = wsfds32->fd_array[i];
439                          else
440                              wsfds16->fd_array[j++] = wsfds16->fd_array[i];
441                 }
442                 close(fd);
443                 lfd[i] = -1;
444             }
445         }
446
447         if( b32 ) wsfds32->fd_count = j;
448         else wsfds16->fd_count = j;
449
450         TRACE("\n");
451 #undef wsfds32
452 #undef wsfds16
453     }
454     return num_err;
455 }
456
457 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
458 {
459     if ( wsfds )
460     {
461 #define wsfds16 ((ws_fd_set16*)wsfds)
462 #define wsfds32 ((ws_fd_set32*)wsfds)
463         int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
464
465         for( i = 0; i < count; i++ )
466             if ( lfd[i] >= 0 )
467                 close(lfd[i]);
468
469         TRACE("\n");
470 #undef wsfds32
471 #undef wsfds16
472     }
473 }
474
475 static int do_block( int fd, int mask )
476 {
477     fd_set fds[3];
478     int i, r;
479
480     FD_ZERO(&fds[0]);
481     FD_ZERO(&fds[1]);
482     FD_ZERO(&fds[2]);
483     for (i=0; i<3; i++)
484         if (mask & (1<<i))
485             FD_SET(fd, &fds[i]);
486     i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
487     if (i <= 0) return -1;
488     r = 0;
489     for (i=0; i<3; i++)
490         if (FD_ISSET(fd, &fds[i]))
491             r |= 1<<i;
492     return r;
493 }
494
495 void* __ws_memalloc( int size )
496 {
497     return WS_ALLOC(size);
498 }
499
500 void __ws_memfree(void* ptr)
501 {
502     WS_FREE(ptr);
503 }
504
505
506 /* ----------------------------------- API ----- 
507  *
508  * Init / cleanup / error checking.
509  */
510
511 /***********************************************************************
512  *      WSAStartup16()                  (WINSOCK.115)
513  *
514  * Create socket control struct, attach it to the global list and
515  * update a pointer in the task struct.
516  */
517 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
518 {
519     WSADATA WINSOCK_data = { 0x0101, 0x0101,
520                           "WINE Sockets 1.1",
521                         #ifdef linux
522                                 "Linux/i386",
523                         #elif defined(__NetBSD__)
524                                 "NetBSD/i386",
525                         #elif defined(sunos)
526                                 "SunOS",
527                         #elif defined(__FreeBSD__)
528                                 "FreeBSD",
529                         #elif defined(__OpenBSD__)
530                                 "OpenBSD/i386",
531                         #else
532                                 "Unknown",
533                         #endif
534                            WS_MAX_SOCKETS_PER_PROCESS,
535                            WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
536     LPWSINFO            pwsi;
537
538     TRACE("verReq=%x\n", wVersionRequested);
539
540     if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
541         HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
542
543     if (!lpWSAData) return WSAEINVAL;
544
545     /* initialize socket heap */
546
547     if( !_WSHeap )
548     {
549         _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
550         if( !_WSHeap )
551         {
552             ERR("Fatal: failed to create WinSock heap\n");
553             return 0;
554         }
555     }
556     if( _WSHeap == 0 ) return WSASYSNOTREADY;
557
558     pwsi = WINSOCK_GetIData();
559     if( pwsi == NULL )
560     {
561         WINSOCK_CreateIData();
562         pwsi = WINSOCK_GetIData();
563         if (!pwsi) return WSASYSNOTREADY;
564     }
565     pwsi->num_startup++;
566
567     /* return winsock information */
568
569     memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
570
571     TRACE("succeeded\n");
572     return 0;
573 }
574
575 /***********************************************************************
576  *      WSAStartup32()                  (WSOCK32.115)
577  */
578 INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
579 {
580     return WSAStartup16( wVersionRequested, lpWSAData );
581 }
582
583 /***********************************************************************
584  *      WSACleanup()                    (WINSOCK.116)
585  */
586 INT WINAPI WSACleanup(void)
587 {
588     LPWSINFO pwsi = WINSOCK_GetIData();
589     if( pwsi ) {
590         if( --pwsi->num_startup > 0 ) return 0;
591
592         WINSOCK_DeleteIData();
593         return 0;
594     }
595     return SOCKET_ERROR;
596 }
597
598
599 /***********************************************************************
600  *      WSAGetLastError()               (WSOCK32.111)(WINSOCK.111)
601  */
602 INT WINAPI WSAGetLastError(void)
603 {
604         return GetLastError();
605 }
606
607 /***********************************************************************
608  *      WSASetLastError32()             (WSOCK32.112)
609  */
610 void WINAPI WSASetLastError(INT iError) {
611     SetLastError(iError);
612 }
613
614 /***********************************************************************
615  *      WSASetLastError16()             (WINSOCK.112)
616  */
617 void WINAPI WSASetLastError16(INT16 iError)
618 {
619     WSASetLastError(iError);
620 }
621
622 int _check_ws(LPWSINFO pwsi, SOCKET s)
623 {
624     if( pwsi )
625     {
626         int fd;
627         if( pwsi->flags & WSI_BLOCKINGCALL ) SetLastError(WSAEINPROGRESS);
628         if ( (fd = _get_sock_fd(s)) < 0 ) {
629             SetLastError(WSAENOTSOCK);
630             return 0;
631         }
632         /* FIXME: maybe check whether fd is really a socket? */
633         close( fd );
634         return 1;
635     }
636     return 0;
637 }
638
639 char* _check_buffer(LPWSINFO pwsi, int size)
640 {
641     if( pwsi->buffer && pwsi->buflen >= size ) return pwsi->buffer;
642     else SEGPTR_FREE(pwsi->buffer);
643
644     pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size)); 
645     return pwsi->buffer;
646 }
647
648 struct ws_hostent* _check_buffer_he(LPWSINFO pwsi, int size)
649 {
650     if( pwsi->he && pwsi->helen >= size ) return pwsi->he;
651     else SEGPTR_FREE(pwsi->he);
652
653     pwsi->he = (struct ws_hostent*)SEGPTR_ALLOC((pwsi->helen = size)); 
654     return pwsi->he;
655 }
656
657 struct ws_servent* _check_buffer_se(LPWSINFO pwsi, int size)
658 {
659     if( pwsi->se && pwsi->selen >= size ) return pwsi->se;
660     else SEGPTR_FREE(pwsi->se);
661
662     pwsi->se = (struct ws_servent*)SEGPTR_ALLOC((pwsi->selen = size)); 
663     return pwsi->se;
664 }
665
666 struct ws_protoent* _check_buffer_pe(LPWSINFO pwsi, int size)
667 {
668     if( pwsi->pe && pwsi->pelen >= size ) return pwsi->pe;
669     else SEGPTR_FREE(pwsi->pe);
670
671     pwsi->pe = (struct ws_protoent*)SEGPTR_ALLOC((pwsi->pelen = size)); 
672     return pwsi->pe;
673 }
674
675 /* ----------------------------------- i/o APIs */
676
677 /***********************************************************************
678  *              accept()                (WSOCK32.1)
679  */
680 SOCKET WINAPI WINSOCK_accept(SOCKET s, struct sockaddr *addr,
681                                  INT *addrlen32)
682 {
683     LPWSINFO                 pwsi = WINSOCK_GetIData();
684 #ifdef HAVE_IPX
685     struct ws_sockaddr_ipx*  addr2 = (struct ws_sockaddr_ipx *)addr;
686 #endif
687     struct accept_socket_request *req = get_req_buffer();
688
689     TRACE("(%08x): socket %04x\n", 
690                                   (unsigned)pwsi, (UINT16)s ); 
691     if( _check_ws(pwsi, s) )
692     {
693         if (_is_blocking(s))
694         {
695             /* block here */
696             int fd = _get_sock_fd(s);
697             do_block(fd, 5);
698             close(fd);
699             _sync_sock_state(s); /* let wineserver notice connection */
700             /* retrieve any error codes from it */
701             SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
702             /* FIXME: care about the error? */
703         }
704         req->lhandle = s;
705         req->access  = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
706         req->inherit = TRUE;
707         server_call( REQ_ACCEPT_SOCKET );
708         if( req->handle >= 0 )
709         {
710             int fd = _get_sock_fd( s = req->handle );
711             if( getpeername(fd, addr, addrlen32) != -1 )
712             {
713 #ifdef HAVE_IPX
714                 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
715                     addr = (struct sockaddr *)
716                                 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
717                     memcpy(addr, addr2,
718                                 addrlen32 ? *addrlen32 : sizeof(*addr2));
719                     addr2->sipx_family = WS_AF_IPX;
720                     addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
721                     addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
722                     memcpy(addr2->sipx_node,
723                         ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
724                     free(addr);
725                 }
726 #endif
727             } else SetLastError(wsaErrno());
728             close(fd);
729             return s;
730         }
731     }
732     return INVALID_SOCKET;
733 }
734
735 /***********************************************************************
736  *              accept()                (WINSOCK.1)
737  */
738 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
739                                  INT16* addrlen16 )
740 {
741     INT addrlen32 = addrlen16 ? *addrlen16 : 0;
742     SOCKET retSocket = WINSOCK_accept( s, addr, &addrlen32 );
743     if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
744     return (SOCKET16)retSocket;
745 }
746
747 /***********************************************************************
748  *              bind()                  (WSOCK32.2)
749  */
750 INT WINAPI WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
751 {
752     LPWSINFO                 pwsi = WINSOCK_GetIData();
753 #ifdef HAVE_IPX
754     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
755 #endif
756
757     TRACE("(%08x): socket %04x, ptr %8x, length %d\n", 
758                            (unsigned)pwsi, s, (int) name, namelen);
759 #if DEBUG_SOCKADDR
760     dump_sockaddr(name);
761 #endif
762
763     if ( _check_ws(pwsi, s) )
764     {
765       int fd = _get_sock_fd(s);
766       /* FIXME: what family does this really map to on the Unix side? */
767       if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
768         ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
769 #ifdef HAVE_IPX
770       else if (name &&
771                 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
772       {
773         name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
774         memset(name, '\0', sizeof(struct sockaddr_ipx));
775         ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
776         ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
777         ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
778         memcpy(((struct sockaddr_ipx *)name)->sipx_node,
779                 name2->sipx_node, IPX_NODE_LEN);
780         namelen = sizeof(struct sockaddr_ipx);
781       }
782 #endif
783       if ( namelen >= sizeof(*name) ) 
784       {
785         if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
786 #ifdef HAVE_IPX
787              || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
788 #endif
789            ))
790         {
791           if ( bind(fd, name, namelen) < 0 ) 
792           {
793              int        loc_errno = errno;
794              WARN("\tfailure - errno = %i\n", errno);
795              errno = loc_errno;
796              switch(errno)
797              {
798                 case EBADF: SetLastError(WSAENOTSOCK); break;
799                 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
800                 default: SetLastError(wsaErrno());break;
801              }
802           }
803           else {
804 #ifdef HAVE_IPX
805             if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
806                 free(name);
807 #endif
808             close(fd);
809             return 0; /* success */
810           }
811         } else SetLastError(WSAEAFNOSUPPORT);
812       } else SetLastError(WSAEFAULT);
813 #ifdef HAVE_IPX
814       if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
815         free(name);
816 #endif
817       close(fd);
818     }
819     return SOCKET_ERROR;
820 }
821
822 /***********************************************************************
823  *              bind()                  (WINSOCK.2)
824  */
825 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
826 {
827   return (INT16)WINSOCK_bind( s, name, namelen );
828 }
829
830 /***********************************************************************
831  *              closesocket()           (WSOCK32.3)
832  */
833 INT WINAPI WINSOCK_closesocket(SOCKET s)
834 {
835     LPWSINFO      pwsi = WINSOCK_GetIData();
836
837     TRACE("(%08x): socket %08x\n", (unsigned)pwsi, s);
838
839     if( _check_ws(pwsi, s) )
840     { 
841         if( CloseHandle(s) )
842             return 0;
843     }
844     return SOCKET_ERROR;
845 }
846
847 /***********************************************************************
848  *              closesocket()           (WINSOCK.3)
849  */
850 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
851 {
852     return (INT16)WINSOCK_closesocket(s);
853 }
854
855 /***********************************************************************
856  *              connect()               (WSOCK32.4)
857  */
858 INT WINAPI WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen)
859 {
860   LPWSINFO                 pwsi = WINSOCK_GetIData();
861 #ifdef HAVE_IPX
862   struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
863 #endif
864
865   TRACE("(%08x): socket %04x, ptr %8x, length %d\n", 
866                            (unsigned)pwsi, s, (int) name, namelen);
867 #if DEBUG_SOCKADDR
868   dump_sockaddr(name);
869 #endif
870
871   if( _check_ws(pwsi, s) )
872   {
873     int fd = _get_sock_fd(s);
874     if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
875         ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
876 #ifdef HAVE_IPX
877     else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
878     {
879         name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
880         memset(name, '\0', sizeof(struct sockaddr_ipx));
881         ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
882         ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
883         ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
884         memcpy(((struct sockaddr_ipx *)name)->sipx_node,
885                 name2->sipx_node, IPX_NODE_LEN);
886         namelen = sizeof(struct sockaddr_ipx);
887     }
888 #endif
889     if (connect(fd, name, namelen) == 0) {
890         close(fd);
891         goto connect_success;
892     }
893     if (errno == EINPROGRESS)
894     {
895         /* tell wineserver that a connection is in progress */
896         _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
897                       WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
898                       WS_FD_CONNECTED|WS_FD_LISTENING);
899         if (_is_blocking(s))
900         {
901             int result;
902             /* block here */
903             do_block(fd, 6);
904             _sync_sock_state(s); /* let wineserver notice connection */
905             /* retrieve any error codes from it */
906             result = _get_sock_error(s, FD_CONNECT_BIT);
907             if (result)
908                 SetLastError(result);
909             else {
910                 close(fd);
911                 goto connect_success;
912             }
913         }
914         else SetLastError(WSAEWOULDBLOCK);
915         close(fd);
916     }
917     else
918     {
919         SetLastError(wsaErrno());
920         close(fd);
921     }
922   }
923 #ifdef HAVE_IPX
924   if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
925     free(name);
926 #endif
927   return SOCKET_ERROR;
928 connect_success:
929 #ifdef HAVE_IPX
930     if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
931         free(name);
932 #endif
933     _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
934                   WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
935                   WS_FD_CONNECT|WS_FD_LISTENING);
936     return 0; 
937 }
938
939 /***********************************************************************
940  *              connect()               (WINSOCK.4)
941  */
942 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
943 {
944   return (INT16)WINSOCK_connect( s, name, namelen );
945 }
946
947 /***********************************************************************
948  *              getpeername()           (WSOCK32.5)
949  */
950 INT WINAPI WINSOCK_getpeername(SOCKET s, struct sockaddr *name,
951                                    INT *namelen)
952 {
953     LPWSINFO                 pwsi = WINSOCK_GetIData();
954 #ifdef HAVE_IPX
955     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
956 #endif
957
958     TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
959                            (unsigned)pwsi, s, (int) name, *namelen);
960     if( _check_ws(pwsi, s) )
961     {
962         int fd = _get_sock_fd(s);
963         if (getpeername(fd, name, namelen) == 0) {
964 #ifdef HAVE_IPX
965             if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
966                 name = (struct sockaddr *)
967                                 malloc(namelen ? *namelen : sizeof(*name2));
968                 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
969                 name2->sipx_family = WS_AF_IPX;
970                 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
971                 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
972                 memcpy(name2->sipx_node,
973                         ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
974                 free(name);
975             }
976 #endif
977             close(fd);
978             return 0; 
979         }
980         SetLastError(wsaErrno());
981         close(fd);
982     }
983     return SOCKET_ERROR;
984 }
985
986 /***********************************************************************
987  *              getpeername()           (WINSOCK.5)
988  */
989 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
990                                    INT16 *namelen16)
991 {
992     INT namelen32 = *namelen16;
993     INT retVal = WINSOCK_getpeername( s, name, &namelen32 );
994
995 #if DEBUG_SOCKADDR
996     dump_sockaddr(name);
997 #endif
998
999    *namelen16 = namelen32;
1000     return (INT16)retVal;
1001 }
1002
1003 /***********************************************************************
1004  *              getsockname()           (WSOCK32.6)
1005  */
1006 INT WINAPI WINSOCK_getsockname(SOCKET s, struct sockaddr *name,
1007                                    INT *namelen)
1008 {
1009     LPWSINFO                 pwsi = WINSOCK_GetIData();
1010 #ifdef HAVE_IPX
1011     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
1012 #endif
1013
1014     TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
1015                           (unsigned)pwsi, s, (int) name, (int) *namelen);
1016     if( _check_ws(pwsi, s) )
1017     {
1018         int fd = _get_sock_fd(s);
1019         if (getsockname(fd, name, namelen) == 0) {
1020 #ifdef HAVE_IPX
1021             if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1022                 name = (struct sockaddr *)
1023                                 malloc(namelen ? *namelen : sizeof(*name2));
1024                 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1025                 name2->sipx_family = WS_AF_IPX;
1026                 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1027                 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1028                 memcpy(name2->sipx_node,
1029                         ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1030                 free(name);
1031             }
1032 #endif
1033             close(fd);
1034             return 0; 
1035         }
1036         SetLastError(wsaErrno());
1037         close(fd);
1038     }
1039     return SOCKET_ERROR;
1040 }
1041
1042 /***********************************************************************
1043  *              getsockname()           (WINSOCK.6)
1044  */
1045 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1046                                    INT16 *namelen16)
1047 {
1048     INT retVal;
1049
1050     if( namelen16 )
1051     {
1052         INT namelen32 = *namelen16;
1053         retVal = WINSOCK_getsockname( s, name, &namelen32 );
1054        *namelen16 = namelen32;
1055
1056 #if DEBUG_SOCKADDR
1057     dump_sockaddr(name);
1058 #endif
1059
1060     }
1061     else retVal = SOCKET_ERROR;
1062     return (INT16)retVal;
1063 }
1064
1065
1066 /***********************************************************************
1067  *              getsockopt()            (WSOCK32.7)
1068  */
1069 INT WINAPI WINSOCK_getsockopt(SOCKET s, INT level, 
1070                                   INT optname, char *optval, INT *optlen)
1071 {
1072     LPWSINFO      pwsi = WINSOCK_GetIData();
1073
1074     TRACE("(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n", 
1075                            (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
1076     if( _check_ws(pwsi, s) )
1077     {
1078         int fd = _get_sock_fd(s);
1079         convert_sockopt(&level, &optname);
1080         if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1081         {
1082             close(fd);
1083             return 0;
1084         }
1085         SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1086         close(fd);
1087     }
1088     return SOCKET_ERROR;
1089 }
1090
1091 /***********************************************************************
1092  *              getsockopt()            (WINSOCK.7)
1093  */
1094 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1095                                   INT16 optname, char *optval, INT16 *optlen)
1096 {
1097     INT optlen32;
1098     INT *p = &optlen32;
1099     INT retVal;
1100     if( optlen ) optlen32 = *optlen; else p = NULL;
1101     retVal = WINSOCK_getsockopt( s, (UINT16)level, optname, optval, p );
1102     if( optlen ) *optlen = optlen32;
1103     return (INT16)retVal;
1104 }
1105
1106 /***********************************************************************
1107  *              htonl()                 (WINSOCK.8)(WSOCK32.8)
1108  */
1109 u_long WINAPI WINSOCK_htonl(u_long hostlong)   { return( htonl(hostlong) ); }
1110 /***********************************************************************
1111  *              htons()                 (WINSOCK.9)(WSOCK32.9)
1112  */
1113 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1114 /***********************************************************************
1115  *              inet_addr()             (WINSOCK.10)(WSOCK32.10)
1116  */
1117 u_long WINAPI WINSOCK_inet_addr(char *cp)      { return( inet_addr(cp) ); }
1118 /***********************************************************************
1119  *              htohl()                 (WINSOCK.14)(WSOCK32.14)
1120  */
1121 u_long WINAPI WINSOCK_ntohl(u_long netlong)    { return( ntohl(netlong) ); }
1122 /***********************************************************************
1123  *              ntohs()                 (WINSOCK.15)(WSOCK32.15)
1124  */
1125 u_short WINAPI WINSOCK_ntohs(u_short netshort)  { return( ntohs(netshort) ); }
1126
1127 /***********************************************************************
1128  *              inet_ntoa()             (WINSOCK.11)(WSOCK32.11)
1129  */
1130 char* WINAPI WINSOCK_inet_ntoa(struct in_addr in)
1131 {
1132   /* use "buffer for dummies" here because some applications have 
1133    * propensity to decode addresses in ws_hostent structure without 
1134    * saving them first...
1135    */
1136
1137     LPWSINFO      pwsi = WINSOCK_GetIData();
1138
1139     if( pwsi )
1140     {
1141         char*   s = inet_ntoa(in);
1142         if( s ) 
1143         {
1144             if( pwsi->dbuffer == NULL )
1145                 if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(32)) == NULL )
1146                 {
1147                     SetLastError(WSAENOBUFS);
1148                     return NULL;
1149                 }
1150             strncpy(pwsi->dbuffer, s, 32 );
1151             return pwsi->dbuffer; 
1152         }
1153         SetLastError(wsaErrno());
1154     }
1155     return NULL;
1156 }
1157
1158 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1159 {
1160   char* retVal = WINSOCK_inet_ntoa(in);
1161   return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
1162 }
1163
1164 /***********************************************************************
1165  *              ioctlsocket()           (WSOCK32.12)
1166  */
1167 INT WINAPI WINSOCK_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1168 {
1169   LPWSINFO      pwsi = WINSOCK_GetIData();
1170
1171   TRACE("(%08x): socket %04x, cmd %08lx, ptr %8x\n", 
1172                           (unsigned)pwsi, s, cmd, (unsigned) argp);
1173   if( _check_ws(pwsi, s) )
1174   {
1175     int         fd = _get_sock_fd(s);
1176     long        newcmd  = cmd;
1177
1178     switch( cmd )
1179     {
1180         case WS_FIONREAD:   
1181                 newcmd=FIONREAD; 
1182                 break;
1183
1184         case WS_FIONBIO:    
1185                 newcmd=FIONBIO;  
1186                 if( _get_sock_mask(s) )
1187                 {
1188                     /* AsyncSelect()'ed sockets are always nonblocking */
1189                     SetLastError(WSAEINVAL); 
1190                     close(fd);
1191                     return SOCKET_ERROR; 
1192                 }
1193                 close(fd);
1194                 if (*argp)
1195                     _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1196                 else
1197                     _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1198                 return 0;
1199
1200         case WS_SIOCATMARK: 
1201                 newcmd=SIOCATMARK; 
1202                 break;
1203
1204         case WS_IOW('f',125,u_long): 
1205                 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1206                 SetLastError(WSAEINVAL); 
1207                 return SOCKET_ERROR;
1208
1209         default:          
1210                 /* Netscape tries hard to use bogus ioctl 0x667e */
1211                 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1212     }
1213     if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1214     {
1215         close(fd);
1216         return 0;
1217     }
1218     SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno()); 
1219     close(fd);
1220   }
1221   return SOCKET_ERROR;
1222 }
1223
1224 /***********************************************************************
1225  *              ioctlsocket()           (WINSOCK.12)
1226  */
1227 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1228 {
1229     return (INT16)WINSOCK_ioctlsocket( s, cmd, argp );
1230 }
1231
1232
1233 /***********************************************************************
1234  *              listen()                (WSOCK32.13)
1235  */
1236 INT WINAPI WINSOCK_listen(SOCKET s, INT backlog)
1237 {
1238     LPWSINFO      pwsi = WINSOCK_GetIData();
1239
1240     TRACE("(%08x): socket %04x, backlog %d\n", 
1241                             (unsigned)pwsi, s, backlog);
1242     if( _check_ws(pwsi, s) )
1243     {
1244         int fd = _get_sock_fd(s);
1245         if (listen(fd, backlog) == 0)
1246         {
1247             close(fd);
1248             _enable_event(s, FD_ACCEPT,
1249                           WS_FD_LISTENING,
1250                           WS_FD_CONNECT|WS_FD_CONNECTED);
1251             return 0;
1252         }
1253         SetLastError(wsaErrno());
1254     }
1255     else SetLastError(WSAENOTSOCK);
1256     return SOCKET_ERROR;
1257 }
1258
1259 /***********************************************************************
1260  *              listen()                (WINSOCK.13)
1261  */
1262 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1263 {
1264     return (INT16)WINSOCK_listen( s, backlog );
1265 }
1266
1267
1268 /***********************************************************************
1269  *              recv()                  (WSOCK32.16)
1270  */
1271 INT WINAPI WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
1272 {
1273     LPWSINFO      pwsi = WINSOCK_GetIData();
1274
1275     TRACE("(%08x): socket %04x, buf %8x, len %d, "
1276                     "flags %d\n", (unsigned)pwsi, s, (unsigned)buf, 
1277                     len, flags);
1278     if( _check_ws(pwsi, s) )
1279     {
1280         int fd = _get_sock_fd(s);
1281         INT length;
1282
1283         if (_is_blocking(s))
1284         {
1285             /* block here */
1286             /* FIXME: OOB and exceptfds? */
1287             do_block(fd, 1);
1288         }
1289         if ((length = recv(fd, buf, len, flags)) >= 0) 
1290         { 
1291             TRACE(" -> %i bytes\n", length);
1292
1293             close(fd);
1294             _enable_event(s, FD_READ, 0, 0);
1295             return length;
1296         }
1297         SetLastError(wsaErrno());
1298         close(fd);
1299     }
1300     else SetLastError(WSAENOTSOCK);
1301     WARN(" -> ERROR\n");
1302     return SOCKET_ERROR;
1303 }
1304
1305 /***********************************************************************
1306  *              recv()                  (WINSOCK.16)
1307  */
1308 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1309 {
1310     return (INT16)WINSOCK_recv( s, buf, len, flags );
1311 }
1312
1313
1314 /***********************************************************************
1315  *              recvfrom()              (WSOCK32.17)
1316  */
1317 INT WINAPI WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags, 
1318                                 struct sockaddr *from, INT *fromlen32)
1319 {
1320     LPWSINFO                 pwsi = WINSOCK_GetIData();
1321 #ifdef HAVE_IPX
1322     struct ws_sockaddr_ipx*  from2 = (struct ws_sockaddr_ipx *)from;
1323 #endif
1324
1325     TRACE("(%08x): socket %04x, ptr %08x, "
1326                     "len %d, flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1327                     len, flags);
1328 #if DEBUG_SOCKADDR
1329     if( from ) dump_sockaddr(from);
1330     else DPRINTF("from = NULL\n");
1331 #endif
1332
1333     if( _check_ws(pwsi, s) )
1334     {
1335         int fd = _get_sock_fd(s);
1336         int length;
1337
1338         if (_is_blocking(s))
1339         {
1340             /* block here */
1341             /* FIXME: OOB and exceptfds */
1342             do_block(fd, 1);
1343         }
1344         if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1345         {
1346             TRACE(" -> %i bytes\n", length);
1347
1348 #ifdef HAVE_IPX
1349         if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1350             from = (struct sockaddr *)
1351                                 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1352             memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1353             from2->sipx_family = WS_AF_IPX;
1354             from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1355             from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1356             memcpy(from2->sipx_node,
1357                         ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1358             free(from);
1359         }
1360 #endif
1361             close(fd);
1362             _enable_event(s, FD_READ, 0, 0);
1363             return (INT16)length;
1364         }
1365         SetLastError(wsaErrno());
1366         close(fd);
1367     }
1368     else SetLastError(WSAENOTSOCK);
1369     WARN(" -> ERROR\n");
1370 #ifdef HAVE_IPX
1371     if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1372         from = (struct sockaddr *)
1373                                 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1374         memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1375         from2->sipx_family = WS_AF_IPX;
1376         from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1377         from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1378         memcpy(from2->sipx_node,
1379                 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1380         free(from);
1381     }
1382 #endif
1383     return SOCKET_ERROR;
1384 }
1385
1386 /***********************************************************************
1387  *              recvfrom()              (WINSOCK.17)
1388  */
1389 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1390                                 struct sockaddr *from, INT16 *fromlen16)
1391 {
1392     INT fromlen32;
1393     INT *p = &fromlen32;
1394     INT retVal;
1395
1396     if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1397     retVal = WINSOCK_recvfrom( s, buf, len, flags, from, p );
1398     if( fromlen16 ) *fromlen16 = fromlen32;
1399     return (INT16)retVal;
1400 }
1401
1402 /***********************************************************************
1403  *              select()                (WINSOCK.18)(WSOCK32.18)
1404  */
1405 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1406                           struct timeval *timeout )
1407 {
1408     LPWSINFO      pwsi = WINSOCK_GetIData();
1409         
1410     TRACE("(%08x): read %8x, write %8x, excp %8x\n", 
1411     (unsigned) pwsi, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
1412
1413     if( pwsi )
1414     {
1415         int         highfd = 0;
1416         fd_set      readfds, writefds, exceptfds;
1417         fd_set     *p_read, *p_write, *p_except;
1418         int         readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1419
1420         p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd, readfd, b32);
1421         p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd, writefd, b32);
1422         p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd, exceptfd, b32);
1423
1424         if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1425         {
1426             fd_set_export(pwsi, &readfds, p_except, ws_readfds, readfd, b32);
1427             fd_set_export(pwsi, &writefds, p_except, ws_writefds, writefd, b32);
1428
1429             if (p_except && ws_exceptfds)
1430             {
1431 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1432 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1433                 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1434
1435                 for (i = j = 0; i < count; i++)
1436                 {
1437                     int fd = exceptfd[i];
1438                     if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1439                     {
1440                         if( b32 )
1441                                 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1442                         else
1443                                 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1444                     }
1445                     if( fd >= 0 ) close(fd);
1446                     exceptfd[i] = -1;
1447                 }
1448                 if( b32 )
1449                     wsfds32->fd_count = j;
1450                 else
1451                     wsfds16->fd_count = j;
1452 #undef wsfds32
1453 #undef wsfds16
1454             }
1455             return highfd; 
1456         }
1457         fd_set_unimport(ws_readfds, readfd, b32);
1458         fd_set_unimport(ws_writefds, writefd, b32);
1459         fd_set_unimport(ws_exceptfds, exceptfd, b32);
1460         if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1461         if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1462         if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1463
1464         if( highfd == 0 ) return 0;
1465         SetLastError(wsaErrno());
1466     } 
1467     return SOCKET_ERROR;
1468 }
1469
1470 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1471                               ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1472                               struct timeval *timeout)
1473 {
1474     return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1475 }
1476
1477 INT WINAPI WINSOCK_select(INT nfds, ws_fd_set32 *ws_readfds,
1478                               ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1479                               struct timeval *timeout)
1480 {
1481     /* struct timeval is the same for both 32- and 16-bit code */
1482     return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1483 }
1484
1485
1486 /***********************************************************************
1487  *              send()                  (WSOCK32.19)
1488  */
1489 INT WINAPI WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
1490 {
1491     LPWSINFO      pwsi = WINSOCK_GetIData();
1492
1493     TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n", 
1494                            (unsigned)pwsi, s, (unsigned) buf, len, flags);
1495     if( _check_ws(pwsi, s) )
1496     {
1497         int     fd = _get_sock_fd(s);
1498         int     length;
1499
1500         if (_is_blocking(s))
1501         {
1502             /* block here */
1503             /* FIXME: exceptfds */
1504             do_block(fd, 2);
1505         }
1506         if ((length = send(fd, buf, len, flags)) < 0 ) 
1507         {
1508             SetLastError(wsaErrno());
1509             if( GetLastError() == WSAEWOULDBLOCK )
1510                 _enable_event(s, FD_WRITE, 0, 0);
1511         }
1512         else
1513         {
1514             close(fd);
1515             return (INT16)length;
1516         }
1517         close(fd);
1518     }
1519     else SetLastError(WSAENOTSOCK);
1520     return SOCKET_ERROR;
1521 }
1522
1523 /***********************************************************************
1524  *              send()                  (WINSOCK.19)
1525  */
1526 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1527 {
1528     return WINSOCK_send( s, buf, len, flags );
1529 }
1530
1531 /***********************************************************************
1532  *              sendto()                (WSOCK32.20)
1533  */
1534 INT WINAPI WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
1535                               struct sockaddr *to, INT tolen)
1536 {
1537     LPWSINFO                 pwsi = WINSOCK_GetIData();
1538 #ifdef HAVE_IPX
1539     struct ws_sockaddr_ipx*  to2 = (struct ws_sockaddr_ipx *)to;
1540 #endif
1541
1542     TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1543                           (unsigned)pwsi, s, (unsigned) buf, len, flags);
1544     if( _check_ws(pwsi, s) )
1545     {
1546         int     fd = _get_sock_fd(s);
1547         INT     length;
1548
1549         if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1550             ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1551 #ifdef HAVE_IPX
1552         else if (to &&
1553                 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1554         {
1555             to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1556             memset(to, '\0', sizeof(struct sockaddr_ipx));
1557             ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1558             ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1559             ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1560             memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1561                         to2->sipx_node, IPX_NODE_LEN);
1562             tolen = sizeof(struct sockaddr_ipx);
1563         }
1564 #endif
1565         if (_is_blocking(s))
1566         {
1567             /* block here */
1568             /* FIXME: exceptfds */
1569             do_block(fd, 2);
1570         }
1571         if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
1572         {
1573             SetLastError(wsaErrno());
1574             if( GetLastError() == WSAEWOULDBLOCK )
1575                 _enable_event(s, FD_WRITE, 0, 0);
1576         } 
1577         else {
1578 #ifdef HAVE_IPX
1579             if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1580                 free(to);
1581             }
1582 #endif
1583             close(fd);
1584             return length;
1585         }
1586         close(fd);
1587     }
1588     else SetLastError(WSAENOTSOCK);
1589 #ifdef HAVE_IPX
1590     if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1591         free(to);
1592     }
1593 #endif
1594     return SOCKET_ERROR;
1595 }
1596
1597 /***********************************************************************
1598  *              sendto()                (WINSOCK.20)
1599  */
1600 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1601                               struct sockaddr *to, INT16 tolen)
1602 {
1603     return (INT16)WINSOCK_sendto( s, buf, len, flags, to, tolen );
1604 }
1605
1606 /***********************************************************************
1607  *              setsockopt()            (WSOCK32.21)
1608  */
1609 INT WINAPI WINSOCK_setsockopt(SOCKET16 s, INT level, INT optname, 
1610                                   char *optval, INT optlen)
1611 {
1612     LPWSINFO      pwsi = WINSOCK_GetIData();
1613
1614     TRACE("(%08x): socket %04x, lev %d, opt %d, ptr %08x, len %d\n",
1615                           (unsigned)pwsi, s, level, optname, (int) optval, optlen);
1616     if( _check_ws(pwsi, s) )
1617     {
1618         struct  linger linger;
1619         int fd = _get_sock_fd(s);
1620
1621         convert_sockopt(&level, &optname);
1622         if (optname == SO_LINGER && optval) {
1623                 /* yes, uses unsigned short in both win16/win32 */
1624                 linger.l_onoff  = ((UINT16*)optval)[0];
1625                 linger.l_linger = ((UINT16*)optval)[1];
1626                 /* FIXME: what is documented behavior if SO_LINGER optval
1627                    is null?? */
1628                 optval = (char*)&linger;
1629                 optlen = sizeof(struct linger);
1630         }
1631         if (setsockopt(fd, level, optname, optval, optlen) == 0)
1632         {
1633             close(fd);
1634             return 0;
1635         }
1636         SetLastError(wsaErrno());
1637         close(fd);
1638     }
1639     else SetLastError(WSAENOTSOCK);
1640     return SOCKET_ERROR;
1641 }
1642
1643 /***********************************************************************
1644  *              setsockopt()            (WINSOCK.21)
1645  */
1646 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
1647                                   char *optval, INT16 optlen)
1648 {
1649     if( !optval ) return SOCKET_ERROR;
1650     return (INT16)WINSOCK_setsockopt( s, (UINT16)level, optname, optval, optlen );
1651 }
1652
1653
1654 /***********************************************************************
1655  *              shutdown()              (WSOCK32.22)
1656  */
1657 INT WINAPI WINSOCK_shutdown(SOCKET s, INT how)
1658 {
1659     LPWSINFO      pwsi = WINSOCK_GetIData();
1660
1661     TRACE("(%08x): socket %04x, how %i\n",
1662                             (unsigned)pwsi, s, how );
1663     if( _check_ws(pwsi, s) )
1664     {
1665         int fd = _get_sock_fd(s);
1666             switch( how )
1667             {
1668                 case 0: /* drop receives */
1669                         _enable_event(s, 0, 0, WS_FD_READ);
1670 #ifdef SHUT_RD
1671                         how = SHUT_RD;
1672 #endif
1673                         break;
1674
1675                 case 1: /* drop sends */
1676                         _enable_event(s, 0, 0, WS_FD_WRITE);
1677 #ifdef SHUT_WR
1678                         how = SHUT_WR;
1679 #endif
1680                         break;
1681
1682                 case 2: /* drop all */
1683 #ifdef SHUT_RDWR
1684                         how = SHUT_RDWR;
1685 #endif
1686                 default:
1687                         WSAAsyncSelect( s, 0, 0, 0 );
1688                         break;
1689             }
1690
1691         if (shutdown(fd, how) == 0) 
1692         {
1693             if( how > 1 ) 
1694             {
1695                 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
1696             }
1697             close(fd);
1698             return 0;
1699         }
1700         SetLastError(wsaErrno());
1701         close(fd);
1702     } 
1703     else SetLastError(WSAENOTSOCK);
1704     return SOCKET_ERROR;
1705 }
1706
1707 /***********************************************************************
1708  *              shutdown()              (WINSOCK.22)
1709  */
1710 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
1711 {
1712     return (INT16)WINSOCK_shutdown( s, how );
1713 }
1714
1715
1716 /***********************************************************************
1717  *              socket()                (WSOCK32.23)
1718  */
1719 SOCKET WINAPI WINSOCK_socket(INT af, INT type, INT protocol)
1720 {
1721   LPWSINFO      pwsi = WINSOCK_GetIData();
1722   struct create_socket_request *req = get_req_buffer();
1723
1724   TRACE("(%08x): af=%d type=%d protocol=%d\n", 
1725                           (unsigned)pwsi, af, type, protocol);
1726
1727   if( pwsi )
1728   {
1729     /* check the socket family */
1730     switch(af) 
1731     {
1732 #ifdef HAVE_IPX
1733         case WS_AF_IPX: af = AF_IPX;
1734 #endif
1735         case AF_INET:
1736         case AF_UNSPEC: break;
1737         default:        SetLastError(WSAEAFNOSUPPORT); 
1738                         return INVALID_SOCKET;
1739     }
1740
1741     /* check the socket type */
1742     switch(type) 
1743     {
1744         case SOCK_STREAM:
1745         case SOCK_DGRAM:
1746         case SOCK_RAW:  break;
1747         default:        SetLastError(WSAESOCKTNOSUPPORT); 
1748                         return INVALID_SOCKET;
1749     }
1750
1751     /* check the protocol type */
1752     if ( protocol < 0 )  /* don't support negative values */
1753     { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
1754
1755     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
1756         switch(protocol) 
1757         {
1758           case IPPROTO_TCP:
1759              if (type == SOCK_STREAM) { af = AF_INET; break; }
1760           case IPPROTO_UDP:
1761              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
1762           default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
1763         }
1764
1765     req->family   = af;
1766     req->type     = type;
1767     req->protocol = protocol;
1768     req->access   = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1769     req->inherit  = TRUE;
1770     server_call( REQ_CREATE_SOCKET );
1771     if ( req->handle >= 0)
1772     {
1773         TRACE("\tcreated %04x\n", req->handle);
1774
1775         return req->handle;
1776     }
1777
1778     if (GetLastError() == WSAEACCES) /* raw socket denied */
1779     {
1780         if (type == SOCK_RAW)
1781             MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
1782         else
1783             MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
1784         SetLastError(WSAESOCKTNOSUPPORT);
1785     }
1786   }
1787  
1788   WARN("\t\tfailed!\n");
1789   return INVALID_SOCKET;
1790 }
1791
1792 /***********************************************************************
1793  *              socket()                (WINSOCK.23)
1794  */
1795 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
1796 {
1797     return (SOCKET16)WINSOCK_socket( af, type, protocol );
1798 }
1799     
1800
1801 /* ----------------------------------- DNS services
1802  *
1803  * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
1804  * Also, we have to use wsock32 stubs to convert structures and
1805  * error codes from Unix to WSA, hence there is no direct mapping in 
1806  * the relay32/wsock32.spec.
1807  */
1808
1809 static char*    NULL_STRING = "NULL";
1810
1811 /***********************************************************************
1812  *              gethostbyaddr()         (WINSOCK.51)(WSOCK32.51)
1813  */
1814 static struct WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
1815 {
1816     LPWSINFO            pwsi = WINSOCK_GetIData();
1817
1818     if( pwsi )
1819     {
1820         struct hostent* host;
1821         if( (host = gethostbyaddr(addr, len, type)) != NULL )
1822             if( WS_dup_he(pwsi, host, dup_flag) )
1823                 return (struct WIN_hostent*)(pwsi->he);
1824             else 
1825                 SetLastError(WSAENOBUFS);
1826         else 
1827             SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1828     }
1829     return NULL;
1830 }
1831
1832 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
1833 {
1834     struct WIN_hostent* retval;
1835     TRACE("ptr %08x, len %d, type %d\n",
1836                             (unsigned) addr, len, type);
1837     retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
1838     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
1839 }
1840
1841 struct WIN_hostent* WINAPI WINSOCK_gethostbyaddr(const char *addr, INT len,
1842                                                 INT type)
1843 {
1844     TRACE("ptr %08x, len %d, type %d\n",
1845                              (unsigned) addr, len, type);
1846     return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
1847 }
1848
1849 /***********************************************************************
1850  *              gethostbyname()         (WINSOCK.52)(WSOCK32.52)
1851  */
1852 static struct WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
1853 {
1854     LPWSINFO              pwsi = WINSOCK_GetIData();
1855
1856     if( pwsi )
1857     {
1858         struct hostent*     host;
1859         if( (host = gethostbyname(name)) != NULL )
1860              if( WS_dup_he(pwsi, host, dup_flag) )
1861                  return (struct WIN_hostent*)(pwsi->he);
1862              else SetLastError(WSAENOBUFS);
1863         else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1864     }
1865     return NULL;
1866 }
1867
1868 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
1869 {
1870     struct WIN_hostent* retval;
1871     TRACE("%s\n", (name)?name:NULL_STRING);
1872     retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
1873     return (retval)? SEGPTR_GET(retval) : ((SEGPTR)NULL) ;
1874 }
1875
1876 struct WIN_hostent* WINAPI WINSOCK_gethostbyname(const char* name)
1877 {
1878     TRACE("%s\n", (name)?name:NULL_STRING);
1879     return __ws_gethostbyname( name, WS_DUP_LINEAR );
1880 }
1881
1882
1883 /***********************************************************************
1884  *              getprotobyname()        (WINSOCK.53)(WSOCK32.53)
1885  */
1886 static struct WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
1887 {
1888     LPWSINFO              pwsi = WINSOCK_GetIData();
1889
1890     if( pwsi )
1891     {
1892         struct protoent*     proto;
1893         if( (proto = getprotobyname(name)) != NULL )
1894             if( WS_dup_pe(pwsi, proto, dup_flag) )
1895                 return (struct WIN_protoent*)(pwsi->pe);
1896             else SetLastError(WSAENOBUFS);
1897         else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1898     }
1899     return NULL;
1900 }
1901
1902 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
1903 {
1904     struct WIN_protoent* retval;
1905     TRACE("%s\n", (name)?name:NULL_STRING);
1906     retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
1907     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
1908 }
1909
1910 struct WIN_protoent* WINAPI WINSOCK_getprotobyname(const char* name)
1911 {
1912     TRACE("%s\n", (name)?name:NULL_STRING);
1913     return __ws_getprotobyname(name, WS_DUP_LINEAR);
1914 }
1915
1916
1917 /***********************************************************************
1918  *              getprotobynumber()      (WINSOCK.54)(WSOCK32.54)
1919  */
1920 static struct WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
1921 {
1922     LPWSINFO              pwsi = WINSOCK_GetIData();
1923
1924     if( pwsi )
1925     {
1926         struct protoent*     proto;
1927         if( (proto = getprotobynumber(number)) != NULL )
1928             if( WS_dup_pe(pwsi, proto, dup_flag) )
1929                 return (struct WIN_protoent*)(pwsi->pe);
1930             else SetLastError(WSAENOBUFS);
1931         else SetLastError(WSANO_DATA);
1932     }
1933     return NULL;
1934 }
1935
1936 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
1937 {
1938     struct WIN_protoent* retval;
1939     TRACE("%i\n", number);
1940     retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
1941     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
1942 }
1943
1944 struct WIN_protoent* WINAPI WINSOCK_getprotobynumber(INT number)
1945 {
1946     TRACE("%i\n", number);
1947     return __ws_getprotobynumber(number, WS_DUP_LINEAR);
1948 }
1949
1950
1951 /***********************************************************************
1952  *              getservbyname()         (WINSOCK.55)(WSOCK32.55)
1953  */
1954 struct WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
1955 {
1956     LPWSINFO              pwsi = WINSOCK_GetIData();
1957
1958     if( pwsi )
1959     {
1960         struct servent*     serv;
1961         int i = wsi_strtolo( pwsi, name, proto );
1962
1963         if( i )
1964             if( (serv = getservbyname(pwsi->buffer, pwsi->buffer + i)) != NULL )
1965                 if( WS_dup_se(pwsi, serv, dup_flag) )
1966                     return (struct WIN_servent*)(pwsi->se);
1967                 else SetLastError(WSAENOBUFS);
1968             else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1969         else SetLastError(WSAENOBUFS);
1970     }
1971     return NULL;
1972 }
1973
1974 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
1975 {
1976     struct WIN_servent* retval;
1977     TRACE("'%s', '%s'\n",
1978                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
1979     retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
1980     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
1981 }
1982
1983 struct WIN_servent* WINAPI WINSOCK_getservbyname(const char *name, const char *proto)
1984 {
1985     TRACE("'%s', '%s'\n",
1986                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
1987     return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
1988 }
1989
1990
1991 /***********************************************************************
1992  *              getservbyport()         (WINSOCK.56)(WSOCK32.56)
1993  */
1994 static struct WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
1995 {
1996     LPWSINFO              pwsi = WINSOCK_GetIData();
1997
1998     if( pwsi )
1999     {
2000         struct servent*     serv;
2001         int i = wsi_strtolo( pwsi, proto, NULL );
2002
2003         if( i )
2004             if( (serv = getservbyport(port, pwsi->buffer)) != NULL )
2005                 if( WS_dup_se(pwsi, serv, dup_flag) )
2006                     return (struct WIN_servent*)(pwsi->se);
2007                 else SetLastError(WSAENOBUFS);
2008             else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2009         else SetLastError(WSAENOBUFS);
2010     }
2011     return NULL;
2012 }
2013
2014 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2015 {
2016     struct WIN_servent* retval;
2017     TRACE("%i, '%s'\n",
2018                             (int)port, (proto)?proto:NULL_STRING);
2019     retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2020     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2021 }
2022
2023 struct WIN_servent* WINAPI WINSOCK_getservbyport(INT port, const char *proto)
2024 {
2025     TRACE("%i, '%s'\n",
2026                             (int)port, (proto)?proto:NULL_STRING);
2027     return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2028 }
2029
2030
2031 /***********************************************************************
2032  *              gethostname()           (WSOCK32.57)
2033  */
2034 INT WINAPI WINSOCK_gethostname(char *name, INT namelen)
2035 {
2036     LPWSINFO              pwsi = WINSOCK_GetIData();
2037
2038     TRACE("(%08x): name %s, len %d\n",
2039                           (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
2040     if( pwsi )
2041     {
2042         if (gethostname(name, namelen) == 0) return 0;
2043         SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2044     }
2045     return SOCKET_ERROR;
2046 }
2047
2048 /***********************************************************************
2049  *              gethostname()           (WINSOCK.57)
2050  */
2051 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2052 {
2053     return (INT16)WINSOCK_gethostname(name, namelen);
2054 }
2055
2056
2057 /* ------------------------------------- Windows sockets extensions -- *
2058  *                                                                     *
2059  * ------------------------------------------------------------------- */
2060
2061 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2062 {
2063     LPWSINFO      pwsi = WINSOCK_GetIData();
2064     struct get_socket_event_request *req = get_req_buffer();
2065
2066     TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2067                           (unsigned)pwsi, s, hEvent, (unsigned)lpEvent );
2068     if( _check_ws(pwsi, s) )
2069     {
2070         req->handle  = s;
2071         req->service = TRUE;
2072         req->s_event = 0;
2073         server_call( REQ_GET_SOCKET_EVENT );
2074         lpEvent->lNetworkEvents = req->pmask;
2075         memcpy(lpEvent->iErrorCode, req->errors, sizeof(lpEvent->iErrorCode));
2076         if (hEvent)
2077             ResetEvent(hEvent);
2078         return 0;
2079     }
2080     else SetLastError(WSAEINVAL);
2081     return SOCKET_ERROR; 
2082 }
2083
2084 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2085 {
2086     LPWSINFO      pwsi = WINSOCK_GetIData();
2087     struct set_socket_event_request *req = get_req_buffer();
2088
2089     TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2090                           (unsigned)pwsi, s, hEvent, (unsigned)lEvent );
2091     if( _check_ws(pwsi, s) )
2092     {
2093         req->handle = s;
2094         req->mask   = lEvent;
2095         req->event  = hEvent;
2096         server_call( REQ_SET_SOCKET_EVENT );
2097         return 0;
2098     }
2099     else SetLastError(WSAEINVAL);
2100     return SOCKET_ERROR; 
2101 }
2102
2103 /***********************************************************************
2104  *      WSAAsyncSelect()                (WINSOCK.101)(WSOCK32.101)
2105  */
2106
2107 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2108 {
2109     /* FIXME: accepted socket uses same event object as listening socket by default
2110      * (at least before a new WSAAsyncSelect is issued), must handle it somehow */
2111     ws_select_info *info = (ws_select_info*)ptr;
2112     struct get_socket_event_request *req = get_req_buffer();
2113     unsigned int i, pmask;
2114
2115     TRACE("socket %08x, event %08x\n", info->sock, info->event);
2116     SetLastError(0);
2117     req->handle  = info->sock;
2118     req->service = TRUE;
2119     req->s_event = info->event; /* <== avoid race conditions */
2120     server_call( REQ_GET_SOCKET_EVENT );
2121     if ( GetLastError() == WSAEINVAL )
2122     {
2123         /* orphaned event (socket closed or something) */
2124         TRACE("orphaned event, self-destructing\n");
2125         SERVICE_Delete( info->service );
2126         WS_FREE(info);
2127         return;
2128     }
2129     /* dispatch network events */
2130     pmask = req->pmask;
2131     for (i=0; i<FD_MAX_EVENTS; i++)
2132         if (pmask & (1<<i)) {
2133             TRACE("post: event bit %d, error %d\n", i, req->errors[i]);
2134             PostMessageA(info->hWnd, info->uMsg, info->sock,
2135                          WSAMAKESELECTREPLY(1<<i, req->errors[i]));
2136         }
2137 }
2138
2139 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2140 {
2141     LPWSINFO      pwsi = WINSOCK_GetIData();
2142
2143     TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2144                           (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2145     if( _check_ws(pwsi, s) )
2146     {
2147         if( lEvent )
2148         {
2149             ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2150             if( info )
2151             {
2152                 HANDLE hObj = CreateEventA( NULL, FALSE, FALSE, NULL );
2153                 INT err;
2154                 
2155                 info->sock  = s;
2156                 info->event = hObj;
2157                 info->hWnd  = hWnd;
2158                 info->uMsg  = uMsg;
2159                 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2160
2161                 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2162                 if (err) {
2163                     SERVICE_Delete( info->service );
2164                     WS_FREE(info);
2165                     return err;
2166                 }
2167
2168                 return 0; /* success */
2169             }
2170             else SetLastError(WSAENOBUFS);
2171         } 
2172         else
2173         {
2174             WSAEventSelect(s, 0, 0);
2175             return 0;
2176         }
2177     } 
2178     else SetLastError(WSAEINVAL);
2179     return SOCKET_ERROR; 
2180 }
2181
2182 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2183 {
2184     return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2185 }
2186
2187
2188 /***********************************************************************
2189  *      __WSAFDIsSet()                  (WINSOCK.151)
2190  */
2191 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2192 {
2193   int i = set->fd_count;
2194   
2195   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2196     
2197   while (i--)
2198       if (set->fd_array[i] == s) return 1;
2199   return 0;
2200 }                                                            
2201
2202 /***********************************************************************
2203  *      __WSAFDIsSet()                  (WSOCK32.151)
2204  */
2205 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2206 {
2207   int i = set->fd_count;
2208
2209   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2210
2211   while (i--)
2212       if (set->fd_array[i] == s) return 1;
2213   return 0;
2214 }
2215
2216 /***********************************************************************
2217  *      WSAIsBlocking()                 (WINSOCK.114)(WSOCK32.114)
2218  */
2219 BOOL WINAPI WSAIsBlocking(void)
2220 {
2221   /* By default WinSock should set all its sockets to non-blocking mode
2222    * and poll in PeekMessage loop when processing "blocking" ones. This 
2223    * function is supposed to tell if the program is in this loop. Our 
2224    * blocking calls are truly blocking so we always return FALSE.
2225    *
2226    * Note: It is allowed to call this function without prior WSAStartup().
2227    */
2228
2229   TRACE("\n");
2230   return FALSE;
2231 }
2232
2233 /***********************************************************************
2234  *      WSACancelBlockingCall()         (WINSOCK.113)(WSOCK32.113)
2235  */
2236 INT WINAPI WSACancelBlockingCall(void)
2237 {
2238   LPWSINFO              pwsi = WINSOCK_GetIData();
2239
2240   TRACE("(%08x)\n", (unsigned)pwsi);
2241
2242   if( pwsi ) return 0;
2243   return SOCKET_ERROR;
2244 }
2245
2246
2247 /***********************************************************************
2248  *      WSASetBlockingHook16()          (WINSOCK.109)
2249  */
2250 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2251 {
2252   FARPROC16             prev;
2253   LPWSINFO              pwsi = WINSOCK_GetIData();
2254
2255   TRACE("(%08x): hook %08x\n", 
2256                (unsigned)pwsi, (unsigned) lpBlockFunc);
2257   if( pwsi ) 
2258   { 
2259       prev = (FARPROC16)pwsi->blocking_hook; 
2260       pwsi->blocking_hook = (DWORD)lpBlockFunc; 
2261       pwsi->flags &= ~WSI_BLOCKINGHOOK;
2262       return prev; 
2263   }
2264   return 0;
2265 }
2266
2267
2268 /***********************************************************************
2269  *      WSASetBlockingHook32()
2270  */
2271 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2272 {
2273   FARPROC             prev;
2274   LPWSINFO              pwsi = WINSOCK_GetIData();
2275
2276   TRACE("(%08x): hook %08x\n",
2277                (unsigned)pwsi, (unsigned) lpBlockFunc);
2278   if( pwsi ) {
2279       prev = (FARPROC)pwsi->blocking_hook;
2280       pwsi->blocking_hook = (DWORD)lpBlockFunc;
2281       pwsi->flags |= WSI_BLOCKINGHOOK;
2282       return prev;
2283   }
2284   return NULL;
2285 }
2286
2287
2288 /***********************************************************************
2289  *      WSAUnhookBlockingHook16()       (WINSOCK.110)
2290  */
2291 INT16 WINAPI WSAUnhookBlockingHook16(void)
2292 {
2293     LPWSINFO              pwsi = WINSOCK_GetIData();
2294
2295     TRACE("(%08x)\n", (unsigned)pwsi);
2296     if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
2297     return SOCKET_ERROR;
2298 }
2299
2300
2301 /***********************************************************************
2302  *      WSAUnhookBlockingHook32()
2303  */
2304 INT WINAPI WSAUnhookBlockingHook(void)
2305 {
2306     LPWSINFO              pwsi = WINSOCK_GetIData();
2307
2308     TRACE("(%08x)\n", (unsigned)pwsi);
2309     if( pwsi )
2310     {
2311         pwsi->blocking_hook = 0;
2312         pwsi->flags &= ~WSI_BLOCKINGHOOK;
2313         return 0;
2314     }
2315     return SOCKET_ERROR;
2316 }
2317
2318 /*
2319  *      TCP/IP action codes.
2320  */
2321
2322
2323 #define WSCNTL_TCPIP_QUERY_INFO             0x00000000
2324 #define WSCNTL_TCPIP_SET_INFO               0x00000001
2325 #define WSCNTL_TCPIP_ICMP_ECHO              0x00000002
2326 #define WSCNTL_TCPIP_TEST                   0x00000003
2327
2328
2329 /***********************************************************************
2330  *      WsControl()
2331  *
2332  * WsControl seems to be an undocumented Win95 function. A lot of 
2333  * discussion about WsControl can be found on the net, e.g.
2334  * Subject:      Re: WSOCK32.DLL WsControl Exported Function
2335  * From:         "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
2336  * Date:         1997/08/17
2337  */
2338
2339 DWORD WINAPI WsControl(DWORD protocoll,DWORD action,
2340                       LPVOID inbuf,LPDWORD inbuflen,
2341                       LPVOID outbuf,LPDWORD outbuflen) 
2342 {
2343
2344   switch (action) {
2345   case WSCNTL_TCPIP_ICMP_ECHO:
2346     {
2347       unsigned int addr = *(unsigned int*)inbuf;
2348 #if 0
2349       int timeout= *(unsigned int*)(inbuf+4);
2350       short x1 = *(unsigned short*)(inbuf+8);
2351       short sendbufsize = *(unsigned short*)(inbuf+10);
2352       char x2 = *(unsigned char*)(inbuf+12);
2353       char ttl = *(unsigned char*)(inbuf+13);
2354       char service = *(unsigned char*)(inbuf+14);
2355       char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
2356 #endif      
2357       
2358       FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr);
2359       break;
2360     }
2361   default:
2362     FIXME("(%lx,%lx,%p,%p,%p,%p) stub\n",
2363           protocoll,action,inbuf,inbuflen,outbuf,outbuflen);
2364   }
2365   return FALSE;
2366 }
2367 /*********************************************************
2368  *       WS_s_perror         WSOCK32.1108 
2369  */
2370 void WINAPI WS_s_perror(LPCSTR message)
2371 {
2372     FIXME("(%s): stub\n",message);
2373     return;
2374 }
2375
2376
2377 /* ----------------------------------- end of API stuff */
2378
2379 /* ----------------------------------- helper functions -
2380  *
2381  * TODO: Merge WS_dup_..() stuff into one function that
2382  * would operate with a generic structure containing internal
2383  * pointers (via a template of some kind).
2384  */
2385
2386 static int list_size(char** l, int item_size)
2387 {
2388   int i,j = 0;
2389   if(l)
2390   { for(i=0;l[i];i++) 
2391         j += (item_size) ? item_size : strlen(l[i]) + 1;
2392     j += (i + 1) * sizeof(char*); }
2393   return j;
2394 }
2395
2396 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2397
2398    /* base is either either equal to ref or 0 or SEGPTR */
2399
2400    char*                p = ref;
2401    char**               l_to = (char**)ref;
2402    int                  i,j,k;
2403
2404    for(j=0;l_src[j];j++) ;
2405    p += (j + 1) * sizeof(char*);
2406    for(i=0;i<j;i++)
2407    { l_to[i] = base + (p - ref);
2408      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2409      memcpy(p, l_src[i], k); p += k; }
2410    l_to[i] = NULL;
2411    return (p - ref);
2412 }
2413
2414 /* ----- hostent */
2415
2416 static int hostent_size(struct hostent* p_he)
2417 {
2418   int size = 0;
2419   if( p_he )
2420   { size  = sizeof(struct hostent); 
2421     size += strlen(p_he->h_name) + 1;
2422     size += list_size(p_he->h_aliases, 0);  
2423     size += list_size(p_he->h_addr_list, p_he->h_length ); }
2424   return size;
2425 }
2426
2427 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
2428 {
2429    /* Convert hostent structure into ws_hostent so that the data fits 
2430     * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or 
2431     * relative to pwsi->buffer depending on "flag" value. Returns size
2432     * of the data copied (also in the pwsi->buflen).
2433     */
2434
2435    int size = hostent_size(p_he);
2436
2437    if( size )
2438    {
2439      struct ws_hostent* p_to;
2440      char* p_name,*p_aliases,*p_addr,*p_base,*p;
2441
2442      _check_buffer_he(pwsi, size);
2443      p_to = (struct ws_hostent*)pwsi->he;
2444      p = (char*)pwsi->he;
2445      p_base = (flag & WS_DUP_OFFSET) ? NULL
2446                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2447      p += sizeof(struct ws_hostent);
2448      p_name = p;
2449      strcpy(p, p_he->h_name); p += strlen(p) + 1;
2450      p_aliases = p;
2451      p += list_dup(p_he->h_aliases, p, p_base + (p - (char*)pwsi->he), 0);
2452      p_addr = p;
2453      list_dup(p_he->h_addr_list, p, p_base + (p - (char*)pwsi->he), p_he->h_length);
2454
2455      p_to->h_addrtype = (INT16)p_he->h_addrtype; 
2456      p_to->h_length = (INT16)p_he->h_length;
2457      p_to->h_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->he));
2458      p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->he));
2459      p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - (char*)pwsi->he));
2460
2461      size += (sizeof(struct ws_hostent) - sizeof(struct hostent));
2462    }
2463    return size;
2464 }
2465
2466 /* ----- protoent */
2467
2468 static int protoent_size(struct protoent* p_pe)
2469 {
2470   int size = 0;
2471   if( p_pe )
2472   { size  = sizeof(struct protoent);
2473     size += strlen(p_pe->p_name) + 1;
2474     size += list_size(p_pe->p_aliases, 0); }
2475   return size;
2476 }
2477
2478 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
2479 {
2480    int size = protoent_size(p_pe);
2481    if( size )
2482    {
2483      struct ws_protoent* p_to;
2484      char* p_name,*p_aliases,*p_base,*p;
2485
2486      _check_buffer_pe(pwsi, size);
2487      p_to = (struct ws_protoent*)pwsi->pe;
2488      p = (char*)pwsi->pe; 
2489      p_base = (flag & WS_DUP_OFFSET) ? NULL
2490                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2491      p += sizeof(struct ws_protoent);
2492      p_name = p;
2493      strcpy(p, p_pe->p_name); p += strlen(p) + 1;
2494      p_aliases = p;
2495      list_dup(p_pe->p_aliases, p, p_base + (p - (char*)pwsi->pe), 0);
2496
2497      p_to->p_proto = (INT16)p_pe->p_proto;
2498      p_to->p_name = (SEGPTR)(p_base) + (p_name - (char*)pwsi->pe);
2499      p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - (char*)pwsi->pe)); 
2500
2501      size += (sizeof(struct ws_protoent) - sizeof(struct protoent));
2502    }
2503    return size;
2504 }
2505
2506 /* ----- servent */
2507
2508 static int servent_size(struct servent* p_se)
2509 {
2510   int size = 0;
2511   if( p_se )
2512   { size += sizeof(struct servent);
2513     size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
2514     size += list_size(p_se->s_aliases, 0); }
2515   return size;
2516 }
2517
2518 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
2519 {
2520    int size = servent_size(p_se);
2521    if( size )
2522    {
2523      struct ws_servent* p_to;
2524      char* p_name,*p_aliases,*p_proto,*p_base,*p;
2525
2526      _check_buffer_se(pwsi, size);
2527      p_to = (struct ws_servent*)pwsi->se;
2528      p = (char*)pwsi->se;
2529      p_base = (flag & WS_DUP_OFFSET) ? NULL 
2530                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2531      p += sizeof(struct ws_servent);
2532      p_name = p;
2533      strcpy(p, p_se->s_name); p += strlen(p) + 1;
2534      p_proto = p;
2535      strcpy(p, p_se->s_proto); p += strlen(p) + 1;
2536      p_aliases = p;
2537      list_dup(p_se->s_aliases, p, p_base + (p - (char*)pwsi->se), 0);
2538
2539      p_to->s_port = (INT16)p_se->s_port;
2540      p_to->s_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->se));
2541      p_to->s_proto = (SEGPTR)(p_base + (p_proto - (char*)pwsi->se));
2542      p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->se)); 
2543
2544      size += (sizeof(struct ws_servent) - sizeof(struct servent));
2545    }
2546    return size;
2547 }
2548
2549 /* ----------------------------------- error handling */
2550
2551 UINT16 wsaErrno(void)
2552 {
2553     int loc_errno = errno; 
2554 #ifdef HAVE_STRERROR
2555     WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
2556 #else
2557     WARN("errno %d\n", loc_errno);
2558 #endif
2559
2560     switch(loc_errno)
2561     {
2562         case EINTR:             return WSAEINTR;
2563         case EBADF:             return WSAEBADF;
2564         case EPERM:
2565         case EACCES:            return WSAEACCES;
2566         case EFAULT:            return WSAEFAULT;
2567         case EINVAL:            return WSAEINVAL;
2568         case EMFILE:            return WSAEMFILE;
2569         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
2570         case EINPROGRESS:       return WSAEINPROGRESS;
2571         case EALREADY:          return WSAEALREADY;
2572         case ENOTSOCK:          return WSAENOTSOCK;
2573         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
2574         case EMSGSIZE:          return WSAEMSGSIZE;
2575         case EPROTOTYPE:        return WSAEPROTOTYPE;
2576         case ENOPROTOOPT:       return WSAENOPROTOOPT;
2577         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
2578         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
2579         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
2580         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
2581         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
2582         case EADDRINUSE:        return WSAEADDRINUSE;
2583         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
2584         case ENETDOWN:          return WSAENETDOWN;
2585         case ENETUNREACH:       return WSAENETUNREACH;
2586         case ENETRESET:         return WSAENETRESET;
2587         case ECONNABORTED:      return WSAECONNABORTED;
2588         case EPIPE:
2589         case ECONNRESET:        return WSAECONNRESET;
2590         case ENOBUFS:           return WSAENOBUFS;
2591         case EISCONN:           return WSAEISCONN;
2592         case ENOTCONN:          return WSAENOTCONN;
2593         case ESHUTDOWN:         return WSAESHUTDOWN;
2594         case ETOOMANYREFS:      return WSAETOOMANYREFS;
2595         case ETIMEDOUT:         return WSAETIMEDOUT;
2596         case ECONNREFUSED:      return WSAECONNREFUSED;
2597         case ELOOP:             return WSAELOOP;
2598         case ENAMETOOLONG:      return WSAENAMETOOLONG;
2599         case EHOSTDOWN:         return WSAEHOSTDOWN;
2600         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
2601         case ENOTEMPTY:         return WSAENOTEMPTY;
2602 #ifdef EPROCLIM
2603         case EPROCLIM:          return WSAEPROCLIM;
2604 #endif
2605 #ifdef EUSERS
2606         case EUSERS:            return WSAEUSERS;
2607 #endif
2608 #ifdef EDQUOT
2609         case EDQUOT:            return WSAEDQUOT;
2610 #endif
2611 #ifdef ESTALE
2612         case ESTALE:            return WSAESTALE;
2613 #endif
2614 #ifdef EREMOTE
2615         case EREMOTE:           return WSAEREMOTE;
2616 #endif
2617
2618        /* just in case we ever get here and there are no problems */
2619         case 0:                 return 0;
2620         default:
2621                 WARN("Unknown errno %d!\n", loc_errno);
2622                 return WSAEOPNOTSUPP;
2623     }
2624 }
2625
2626 UINT16 wsaHerrno(void)
2627 {
2628     int         loc_errno = h_errno;
2629
2630     WARN("h_errno %d.\n", loc_errno);
2631
2632     switch(loc_errno)
2633     {
2634         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
2635         case TRY_AGAIN:         return WSATRY_AGAIN;
2636         case NO_RECOVERY:       return WSANO_RECOVERY;
2637         case NO_DATA:           return WSANO_DATA; 
2638
2639         case 0:                 return 0;
2640         default:
2641                 WARN("Unknown h_errno %d!\n", loc_errno);
2642                 return WSAEOPNOTSUPP;
2643     }
2644 }