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