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