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