Use min/max instead of MIN/MAX.
[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          WS_SO_DONTLINGER,  /* no unix equivalent */
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 WSOCK32_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 = WSOCK32_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 WSOCK32_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)WSOCK32_bind( s, name, namelen );
845 }
846
847 /***********************************************************************
848  *              closesocket()           (WSOCK32.3)
849  */
850 INT WINAPI WSOCK32_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)WSOCK32_closesocket(s);
870 }
871
872 /***********************************************************************
873  *              connect()               (WSOCK32.4)
874  */
875 INT WINAPI WSOCK32_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)WSOCK32_connect( s, name, namelen );
962 }
963
964 /***********************************************************************
965  *              getpeername()           (WSOCK32.5)
966  */
967 INT WINAPI WSOCK32_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 = WSOCK32_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 WSOCK32_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 = WSOCK32_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 WSOCK32_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 = WSOCK32_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  *              ntohl()                 (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 WSOCK32_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 = WSOCK32_inet_ntoa(in);
1180   return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
1181 }
1182
1183 /***********************************************************************
1184  *              ioctlsocket()           (WSOCK32.12)
1185  */
1186 INT WINAPI WSOCK32_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)WSOCK32_ioctlsocket( s, cmd, argp );
1253 }
1254
1255
1256 /***********************************************************************
1257  *              listen()                (WSOCK32.13)
1258  */
1259 INT WINAPI WSOCK32_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)WSOCK32_listen( s, backlog );
1288 }
1289
1290
1291 /***********************************************************************
1292  *              recv()                  (WSOCK32.16)
1293  */
1294 INT WINAPI WSOCK32_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)WSOCK32_recv( s, buf, len, flags );
1334 }
1335
1336
1337 /***********************************************************************
1338  *              recvfrom()              (WSOCK32.17)
1339  */
1340 INT WINAPI WSOCK32_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 = WSOCK32_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 WSOCK32_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 WSOCK32_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 WSOCK32_send( s, buf, len, flags );
1552 }
1553
1554 /***********************************************************************
1555  *              sendto()                (WSOCK32.20)
1556  */
1557 INT WINAPI WSOCK32_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)WSOCK32_sendto( s, buf, len, flags, to, tolen );
1627 }
1628
1629 /***********************************************************************
1630  *              setsockopt()            (WSOCK32.21)
1631  */
1632 INT WINAPI WSOCK32_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         convert_sockopt(&level, &optname);
1646         if(optname == WS_SO_DONTLINGER) {
1647             linger.l_onoff      = *((int*)optval) ? 0: 1;
1648             linger.l_linger     = 0;
1649             optname=SO_LINGER;
1650             optval = (char*)&linger;
1651             optlen = sizeof(struct linger);
1652         }else{
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)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
1687 }
1688
1689
1690 /***********************************************************************
1691  *              shutdown()              (WSOCK32.22)
1692  */
1693 INT WINAPI WSOCK32_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)WSOCK32_shutdown( s, how );
1749 }
1750
1751
1752 /***********************************************************************
1753  *              socket()                (WSOCK32.23)
1754  */
1755 SOCKET WINAPI WSOCK32_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)WSOCK32_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 WSOCK32_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 WSOCK32_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 WSOCK32_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 WSOCK32_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             serv = getservbyname(pwsi->buffer,
2001                                  proto ? (pwsi->buffer + i) : NULL);
2002             if( serv != NULL )
2003                 if( WS_dup_se(pwsi, serv, dup_flag) )
2004                     return (struct WIN_servent*)(pwsi->se);
2005                 else SetLastError(WSAENOBUFS);
2006             else {
2007                 MESSAGE("service %s protocol %s not found; maybe you have add "
2008                         "this to /etc/services\n", debugstr_a(pwsi->buffer),
2009                         proto ? debugstr_a(pwsi->buffer+i):"*"); 
2010                 SetLastError(WSANO_DATA);
2011             }
2012         }
2013         else SetLastError(WSAENOBUFS);
2014     } else SetLastError(WSANOTINITIALISED);
2015     return NULL;
2016 }
2017
2018 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2019 {
2020     struct WIN_servent* retval;
2021     TRACE("'%s', '%s'\n",
2022                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2023     retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2024     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2025 }
2026
2027 struct WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2028 {
2029     TRACE("'%s', '%s'\n",
2030                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2031     return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2032 }
2033
2034
2035 /***********************************************************************
2036  *              getservbyport()         (WINSOCK.56)(WSOCK32.56)
2037  */
2038 static struct WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2039 {
2040     LPWSINFO              pwsi = WINSOCK_GetIData();
2041
2042     if( pwsi )
2043     {
2044         struct servent*     serv;
2045         if (!proto || wsi_strtolo( pwsi, proto, NULL )) {
2046             if( (serv = getservbyport(port, (proto) ? pwsi->buffer : NULL)) != NULL ) {
2047                 if( WS_dup_se(pwsi, serv, dup_flag) )
2048                     return (struct WIN_servent*)(pwsi->se);
2049                 else SetLastError(WSAENOBUFS);
2050             }
2051             else {
2052                 MESSAGE("service on port %d protocol %s not found; maybe you have "
2053                         "add this to /etc/services\n", ntohl(port),
2054                         proto ? debugstr_a(pwsi->buffer) : "*"); 
2055                 SetLastError(WSANO_DATA);
2056             }
2057         }
2058         else SetLastError(WSAENOBUFS);
2059     } else SetLastError(WSANOTINITIALISED);
2060     return NULL;
2061 }
2062
2063 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2064 {
2065     struct WIN_servent* retval;
2066     TRACE("%i, '%s'\n",
2067                             (int)port, (proto)?proto:NULL_STRING);
2068     retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2069     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2070 }
2071
2072 struct WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2073 {
2074     TRACE("%i, '%s'\n",
2075                             (int)port, (proto)?proto:NULL_STRING);
2076     return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2077 }
2078
2079
2080 /***********************************************************************
2081  *              gethostname()           (WSOCK32.57)
2082  */
2083 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2084 {
2085     LPWSINFO              pwsi = WINSOCK_GetIData();
2086
2087     TRACE("(%08x): name %s, len %d\n",
2088                           (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
2089     if( pwsi )
2090     {
2091         if (gethostname(name, namelen) == 0) return 0;
2092         SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2093     }
2094     return SOCKET_ERROR;
2095 }
2096
2097 /***********************************************************************
2098  *              gethostname()           (WINSOCK.57)
2099  */
2100 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2101 {
2102     return (INT16)WSOCK32_gethostname(name, namelen);
2103 }
2104
2105
2106 /* ------------------------------------- Windows sockets extensions -- *
2107  *                                                                     *
2108  * ------------------------------------------------------------------- */
2109
2110 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2111 {
2112     LPWSINFO      pwsi = WINSOCK_GetIData();
2113     struct get_socket_event_request *req = get_req_buffer();
2114
2115     TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2116                           (unsigned)pwsi, s, hEvent, (unsigned)lpEvent );
2117     if( _check_ws(pwsi, s) )
2118     {
2119         req->handle  = s;
2120         req->service = TRUE;
2121         req->s_event = 0;
2122         sock_server_call( REQ_GET_SOCKET_EVENT );
2123         lpEvent->lNetworkEvents = req->pmask;
2124         memcpy(lpEvent->iErrorCode, req->errors, sizeof(lpEvent->iErrorCode));
2125         if (hEvent)
2126             ResetEvent(hEvent);
2127         return 0;
2128     }
2129     else SetLastError(WSAEINVAL);
2130     return SOCKET_ERROR; 
2131 }
2132
2133 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2134 {
2135     LPWSINFO      pwsi = WINSOCK_GetIData();
2136     struct set_socket_event_request *req = get_req_buffer();
2137
2138     TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2139                           (unsigned)pwsi, s, hEvent, (unsigned)lEvent );
2140     if( _check_ws(pwsi, s) )
2141     {
2142         req->handle = s;
2143         req->mask   = lEvent;
2144         req->event  = hEvent;
2145         sock_server_call( REQ_SET_SOCKET_EVENT );
2146         return 0;
2147     }
2148     else SetLastError(WSAEINVAL);
2149     return SOCKET_ERROR; 
2150 }
2151
2152 /***********************************************************************
2153  *      WSAAsyncSelect()                (WINSOCK.101)(WSOCK32.101)
2154  */
2155
2156 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2157 {
2158     /* FIXME: accepted socket uses same event object as listening socket by default
2159      * (at least before a new WSAAsyncSelect is issued), must handle it somehow */
2160     ws_select_info *info = (ws_select_info*)ptr;
2161     struct get_socket_event_request *req = get_req_buffer();
2162     unsigned int i, pmask;
2163
2164     TRACE("socket %08x, event %08x\n", info->sock, info->event);
2165     SetLastError(0);
2166     req->handle  = info->sock;
2167     req->service = TRUE;
2168     req->s_event = info->event; /* <== avoid race conditions */
2169     sock_server_call( REQ_GET_SOCKET_EVENT );
2170     if ( GetLastError() == WSAEINVAL )
2171     {
2172         /* orphaned event (socket closed or something) */
2173         TRACE("orphaned event, self-destructing\n");
2174         SERVICE_Delete( info->service );
2175         WS_FREE(info);
2176         return;
2177     }
2178     /* dispatch network events */
2179     pmask = req->pmask;
2180     for (i=0; i<FD_MAX_EVENTS; i++)
2181         if (pmask & (1<<i)) {
2182             TRACE("post: event bit %d, error %d\n", i, req->errors[i]);
2183             PostMessageA(info->hWnd, info->uMsg, info->sock,
2184                          WSAMAKESELECTREPLY(1<<i, req->errors[i]));
2185         }
2186 }
2187
2188 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2189 {
2190     LPWSINFO      pwsi = WINSOCK_GetIData();
2191
2192     TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2193                           (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2194     if( _check_ws(pwsi, s) )
2195     {
2196         if( lEvent )
2197         {
2198             ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2199             if( info )
2200             {
2201                 HANDLE hObj = CreateEventA( NULL, FALSE, FALSE, NULL );
2202                 INT err;
2203                 
2204                 info->sock  = s;
2205                 info->event = hObj;
2206                 info->hWnd  = hWnd;
2207                 info->uMsg  = uMsg;
2208                 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2209
2210                 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2211                 if (err) {
2212                     SERVICE_Delete( info->service );
2213                     WS_FREE(info);
2214                     return err;
2215                 }
2216
2217                 return 0; /* success */
2218             }
2219             else SetLastError(WSAENOBUFS);
2220         } 
2221         else
2222         {
2223             WSAEventSelect(s, 0, 0);
2224             return 0;
2225         }
2226     } 
2227     else SetLastError(WSAEINVAL);
2228     return SOCKET_ERROR; 
2229 }
2230
2231 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2232 {
2233     return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2234 }
2235
2236 /***********************************************************************
2237  *              WSARecvEx()                     (WSOCK32.1107)
2238  *
2239  * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
2240  * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
2241  * into the flags parameter when a partial packet is read. This only applies to
2242  * sockets using the datagram protocol. This method does not seem to be implemented
2243  * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
2244  * flag when a fragmented packet arrives.
2245  */
2246 INT     WINAPI   WSARecvEx(SOCKET s, char *buf, INT len, INT *flags) {
2247   FIXME("(WSARecvEx) partial packet return value not set \n");
2248
2249   return WSOCK32_recv(s, buf, len, *flags);
2250 }
2251
2252
2253 /***********************************************************************
2254  *              WSARecvEx16()                   (WINSOCK.1107)
2255  *
2256  * See description for WSARecvEx()
2257  */
2258 INT16     WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2259   FIXME("(WSARecvEx16) partial packet return value not set \n");
2260
2261   return WINSOCK_recv16(s, buf, len, *flags);
2262 }
2263
2264
2265 /***********************************************************************
2266  *      __WSAFDIsSet()                  (WINSOCK.151)
2267  */
2268 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2269 {
2270   int i = set->fd_count;
2271   
2272   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2273     
2274   while (i--)
2275       if (set->fd_array[i] == s) return 1;
2276   return 0;
2277 }                                                            
2278
2279 /***********************************************************************
2280  *      __WSAFDIsSet()                  (WSOCK32.151)
2281  */
2282 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2283 {
2284   int i = set->fd_count;
2285
2286   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2287
2288   while (i--)
2289       if (set->fd_array[i] == s) return 1;
2290   return 0;
2291 }
2292
2293 /***********************************************************************
2294  *      WSAIsBlocking()                 (WINSOCK.114)(WSOCK32.114)
2295  */
2296 BOOL WINAPI WSAIsBlocking(void)
2297 {
2298   /* By default WinSock should set all its sockets to non-blocking mode
2299    * and poll in PeekMessage loop when processing "blocking" ones. This 
2300    * function is supposed to tell if the program is in this loop. Our 
2301    * blocking calls are truly blocking so we always return FALSE.
2302    *
2303    * Note: It is allowed to call this function without prior WSAStartup().
2304    */
2305
2306   TRACE("\n");
2307   return FALSE;
2308 }
2309
2310 /***********************************************************************
2311  *      WSACancelBlockingCall()         (WINSOCK.113)(WSOCK32.113)
2312  */
2313 INT WINAPI WSACancelBlockingCall(void)
2314 {
2315   LPWSINFO              pwsi = WINSOCK_GetIData();
2316
2317   TRACE("(%08x)\n", (unsigned)pwsi);
2318
2319   if( pwsi ) return 0;
2320   return SOCKET_ERROR;
2321 }
2322
2323
2324 /***********************************************************************
2325  *      WSASetBlockingHook16()          (WINSOCK.109)
2326  */
2327 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2328 {
2329   FARPROC16             prev;
2330   LPWSINFO              pwsi = WINSOCK_GetIData();
2331
2332   TRACE("(%08x): hook %08x\n", 
2333                (unsigned)pwsi, (unsigned) lpBlockFunc);
2334   if( pwsi ) 
2335   { 
2336       prev = (FARPROC16)pwsi->blocking_hook; 
2337       pwsi->blocking_hook = (DWORD)lpBlockFunc; 
2338       pwsi->flags &= ~WSI_BLOCKINGHOOK;
2339       return prev; 
2340   }
2341   return 0;
2342 }
2343
2344
2345 /***********************************************************************
2346  *      WSASetBlockingHook32()
2347  */
2348 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2349 {
2350   FARPROC             prev;
2351   LPWSINFO              pwsi = WINSOCK_GetIData();
2352
2353   TRACE("(%08x): hook %08x\n",
2354                (unsigned)pwsi, (unsigned) lpBlockFunc);
2355   if( pwsi ) {
2356       prev = (FARPROC)pwsi->blocking_hook;
2357       pwsi->blocking_hook = (DWORD)lpBlockFunc;
2358       pwsi->flags |= WSI_BLOCKINGHOOK;
2359       return prev;
2360   }
2361   return NULL;
2362 }
2363
2364
2365 /***********************************************************************
2366  *      WSAUnhookBlockingHook16()       (WINSOCK.110)
2367  */
2368 INT16 WINAPI WSAUnhookBlockingHook16(void)
2369 {
2370     LPWSINFO              pwsi = WINSOCK_GetIData();
2371
2372     TRACE("(%08x)\n", (unsigned)pwsi);
2373     if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
2374     return SOCKET_ERROR;
2375 }
2376
2377
2378 /***********************************************************************
2379  *      WSAUnhookBlockingHook32()
2380  */
2381 INT WINAPI WSAUnhookBlockingHook(void)
2382 {
2383     LPWSINFO              pwsi = WINSOCK_GetIData();
2384
2385     TRACE("(%08x)\n", (unsigned)pwsi);
2386     if( pwsi )
2387     {
2388         pwsi->blocking_hook = 0;
2389         pwsi->flags &= ~WSI_BLOCKINGHOOK;
2390         return 0;
2391     }
2392     return SOCKET_ERROR;
2393 }
2394
2395 /*
2396  *      TCP/IP action codes.
2397  */
2398
2399
2400 #define WSCNTL_TCPIP_QUERY_INFO             0x00000000
2401 #define WSCNTL_TCPIP_SET_INFO               0x00000001
2402 #define WSCNTL_TCPIP_ICMP_ECHO              0x00000002
2403 #define WSCNTL_TCPIP_TEST                   0x00000003
2404
2405
2406 /***********************************************************************
2407  *      WsControl()
2408  *
2409  * WsControl seems to be an undocumented Win95 function. A lot of 
2410  * discussion about WsControl can be found on the net, e.g.
2411  * Subject:      Re: WSOCK32.DLL WsControl Exported Function
2412  * From:         "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
2413  * Date:         1997/08/17
2414  */
2415
2416 DWORD WINAPI WsControl(DWORD protocoll,DWORD action,
2417                       LPVOID inbuf,LPDWORD inbuflen,
2418                       LPVOID outbuf,LPDWORD outbuflen) 
2419 {
2420
2421   switch (action) {
2422   case WSCNTL_TCPIP_ICMP_ECHO:
2423     {
2424       unsigned int addr = *(unsigned int*)inbuf;
2425 #if 0
2426       int timeout= *(unsigned int*)(inbuf+4);
2427       short x1 = *(unsigned short*)(inbuf+8);
2428       short sendbufsize = *(unsigned short*)(inbuf+10);
2429       char x2 = *(unsigned char*)(inbuf+12);
2430       char ttl = *(unsigned char*)(inbuf+13);
2431       char service = *(unsigned char*)(inbuf+14);
2432       char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
2433 #endif      
2434       
2435       FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr);
2436       break;
2437     }
2438   default:
2439     FIXME("(%lx,%lx,%p,%p,%p,%p) stub\n",
2440           protocoll,action,inbuf,inbuflen,outbuf,outbuflen);
2441   }
2442   return FALSE;
2443 }
2444 /*********************************************************
2445  *       WS_s_perror         WSOCK32.1108 
2446  */
2447 void WINAPI WS_s_perror(LPCSTR message)
2448 {
2449     FIXME("(%s): stub\n",message);
2450     return;
2451 }
2452
2453
2454 /* ----------------------------------- end of API stuff */
2455
2456 /* ----------------------------------- helper functions -
2457  *
2458  * TODO: Merge WS_dup_..() stuff into one function that
2459  * would operate with a generic structure containing internal
2460  * pointers (via a template of some kind).
2461  */
2462
2463 static int list_size(char** l, int item_size)
2464 {
2465   int i,j = 0;
2466   if(l)
2467   { for(i=0;l[i];i++) 
2468         j += (item_size) ? item_size : strlen(l[i]) + 1;
2469     j += (i + 1) * sizeof(char*); }
2470   return j;
2471 }
2472
2473 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2474
2475    /* base is either either equal to ref or 0 or SEGPTR */
2476
2477    char*                p = ref;
2478    char**               l_to = (char**)ref;
2479    int                  i,j,k;
2480
2481    for(j=0;l_src[j];j++) ;
2482    p += (j + 1) * sizeof(char*);
2483    for(i=0;i<j;i++)
2484    { l_to[i] = base + (p - ref);
2485      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2486      memcpy(p, l_src[i], k); p += k; }
2487    l_to[i] = NULL;
2488    return (p - ref);
2489 }
2490
2491 /* ----- hostent */
2492
2493 static int hostent_size(struct hostent* p_he)
2494 {
2495   int size = 0;
2496   if( p_he )
2497   { size  = sizeof(struct hostent); 
2498     size += strlen(p_he->h_name) + 1;
2499     size += list_size(p_he->h_aliases, 0);  
2500     size += list_size(p_he->h_addr_list, p_he->h_length ); }
2501   return size;
2502 }
2503
2504 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
2505 {
2506    /* Convert hostent structure into ws_hostent so that the data fits 
2507     * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or 
2508     * relative to pwsi->buffer depending on "flag" value. Returns size
2509     * of the data copied (also in the pwsi->buflen).
2510     */
2511
2512    int size = hostent_size(p_he);
2513
2514    if( size )
2515    {
2516      struct ws_hostent* p_to;
2517      char* p_name,*p_aliases,*p_addr,*p_base,*p;
2518
2519      _check_buffer_he(pwsi, size);
2520      p_to = (struct ws_hostent*)pwsi->he;
2521      p = (char*)pwsi->he;
2522      p_base = (flag & WS_DUP_OFFSET) ? NULL
2523                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2524      p += sizeof(struct ws_hostent);
2525      p_name = p;
2526      strcpy(p, p_he->h_name); p += strlen(p) + 1;
2527      p_aliases = p;
2528      p += list_dup(p_he->h_aliases, p, p_base + (p - (char*)pwsi->he), 0);
2529      p_addr = p;
2530      list_dup(p_he->h_addr_list, p, p_base + (p - (char*)pwsi->he), p_he->h_length);
2531
2532      p_to->h_addrtype = (INT16)p_he->h_addrtype; 
2533      p_to->h_length = (INT16)p_he->h_length;
2534      p_to->h_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->he));
2535      p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->he));
2536      p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - (char*)pwsi->he));
2537
2538      size += (sizeof(struct ws_hostent) - sizeof(struct hostent));
2539    }
2540    return size;
2541 }
2542
2543 /* ----- protoent */
2544
2545 static int protoent_size(struct protoent* p_pe)
2546 {
2547   int size = 0;
2548   if( p_pe )
2549   { size  = sizeof(struct protoent);
2550     size += strlen(p_pe->p_name) + 1;
2551     size += list_size(p_pe->p_aliases, 0); }
2552   return size;
2553 }
2554
2555 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
2556 {
2557    int size = protoent_size(p_pe);
2558    if( size )
2559    {
2560      struct ws_protoent* p_to;
2561      char* p_name,*p_aliases,*p_base,*p;
2562
2563      _check_buffer_pe(pwsi, size);
2564      p_to = (struct ws_protoent*)pwsi->pe;
2565      p = (char*)pwsi->pe; 
2566      p_base = (flag & WS_DUP_OFFSET) ? NULL
2567                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2568      p += sizeof(struct ws_protoent);
2569      p_name = p;
2570      strcpy(p, p_pe->p_name); p += strlen(p) + 1;
2571      p_aliases = p;
2572      list_dup(p_pe->p_aliases, p, p_base + (p - (char*)pwsi->pe), 0);
2573
2574      p_to->p_proto = (INT16)p_pe->p_proto;
2575      p_to->p_name = (SEGPTR)(p_base) + (p_name - (char*)pwsi->pe);
2576      p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - (char*)pwsi->pe)); 
2577
2578      size += (sizeof(struct ws_protoent) - sizeof(struct protoent));
2579    }
2580    return size;
2581 }
2582
2583 /* ----- servent */
2584
2585 static int servent_size(struct servent* p_se)
2586 {
2587   int size = 0;
2588   if( p_se )
2589   { size += sizeof(struct servent);
2590     size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
2591     size += list_size(p_se->s_aliases, 0); }
2592   return size;
2593 }
2594
2595 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
2596 {
2597    int size = servent_size(p_se);
2598    if( size )
2599    {
2600      struct ws_servent* p_to;
2601      char* p_name,*p_aliases,*p_proto,*p_base,*p;
2602
2603      _check_buffer_se(pwsi, size);
2604      p_to = (struct ws_servent*)pwsi->se;
2605      p = (char*)pwsi->se;
2606      p_base = (flag & WS_DUP_OFFSET) ? NULL 
2607                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2608      p += sizeof(struct ws_servent);
2609      p_name = p;
2610      strcpy(p, p_se->s_name); p += strlen(p) + 1;
2611      p_proto = p;
2612      strcpy(p, p_se->s_proto); p += strlen(p) + 1;
2613      p_aliases = p;
2614      list_dup(p_se->s_aliases, p, p_base + (p - (char*)pwsi->se), 0);
2615
2616      p_to->s_port = (INT16)p_se->s_port;
2617      p_to->s_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->se));
2618      p_to->s_proto = (SEGPTR)(p_base + (p_proto - (char*)pwsi->se));
2619      p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->se)); 
2620
2621      size += (sizeof(struct ws_servent) - sizeof(struct servent));
2622    }
2623    return size;
2624 }
2625
2626 /* ----------------------------------- error handling */
2627
2628 UINT16 wsaErrno(void)
2629 {
2630     int loc_errno = errno; 
2631 #ifdef HAVE_STRERROR
2632     WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
2633 #else
2634     WARN("errno %d\n", loc_errno);
2635 #endif
2636
2637     switch(loc_errno)
2638     {
2639         case EINTR:             return WSAEINTR;
2640         case EBADF:             return WSAEBADF;
2641         case EPERM:
2642         case EACCES:            return WSAEACCES;
2643         case EFAULT:            return WSAEFAULT;
2644         case EINVAL:            return WSAEINVAL;
2645         case EMFILE:            return WSAEMFILE;
2646         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
2647         case EINPROGRESS:       return WSAEINPROGRESS;
2648         case EALREADY:          return WSAEALREADY;
2649         case ENOTSOCK:          return WSAENOTSOCK;
2650         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
2651         case EMSGSIZE:          return WSAEMSGSIZE;
2652         case EPROTOTYPE:        return WSAEPROTOTYPE;
2653         case ENOPROTOOPT:       return WSAENOPROTOOPT;
2654         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
2655         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
2656         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
2657         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
2658         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
2659         case EADDRINUSE:        return WSAEADDRINUSE;
2660         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
2661         case ENETDOWN:          return WSAENETDOWN;
2662         case ENETUNREACH:       return WSAENETUNREACH;
2663         case ENETRESET:         return WSAENETRESET;
2664         case ECONNABORTED:      return WSAECONNABORTED;
2665         case EPIPE:
2666         case ECONNRESET:        return WSAECONNRESET;
2667         case ENOBUFS:           return WSAENOBUFS;
2668         case EISCONN:           return WSAEISCONN;
2669         case ENOTCONN:          return WSAENOTCONN;
2670         case ESHUTDOWN:         return WSAESHUTDOWN;
2671         case ETOOMANYREFS:      return WSAETOOMANYREFS;
2672         case ETIMEDOUT:         return WSAETIMEDOUT;
2673         case ECONNREFUSED:      return WSAECONNREFUSED;
2674         case ELOOP:             return WSAELOOP;
2675         case ENAMETOOLONG:      return WSAENAMETOOLONG;
2676         case EHOSTDOWN:         return WSAEHOSTDOWN;
2677         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
2678         case ENOTEMPTY:         return WSAENOTEMPTY;
2679 #ifdef EPROCLIM
2680         case EPROCLIM:          return WSAEPROCLIM;
2681 #endif
2682 #ifdef EUSERS
2683         case EUSERS:            return WSAEUSERS;
2684 #endif
2685 #ifdef EDQUOT
2686         case EDQUOT:            return WSAEDQUOT;
2687 #endif
2688 #ifdef ESTALE
2689         case ESTALE:            return WSAESTALE;
2690 #endif
2691 #ifdef EREMOTE
2692         case EREMOTE:           return WSAEREMOTE;
2693 #endif
2694
2695        /* just in case we ever get here and there are no problems */
2696         case 0:                 return 0;
2697         default:
2698                 WARN("Unknown errno %d!\n", loc_errno);
2699                 return WSAEOPNOTSUPP;
2700     }
2701 }
2702
2703 UINT16 wsaHerrno(void)
2704 {
2705     int         loc_errno = h_errno;
2706
2707     WARN("h_errno %d.\n", loc_errno);
2708
2709     switch(loc_errno)
2710     {
2711         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
2712         case TRY_AGAIN:         return WSATRY_AGAIN;
2713         case NO_RECOVERY:       return WSANO_RECOVERY;
2714         case NO_DATA:           return WSANO_DATA; 
2715
2716         case 0:                 return 0;
2717         default:
2718                 WARN("Unknown h_errno %d!\n", loc_errno);
2719                 return WSAEOPNOTSUPP;
2720     }
2721 }