NT loader: don't stop loading a hive when an error occurs.
[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                 if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(32)) == NULL )
1147                 {
1148                     SetLastError(WSAENOBUFS);
1149                     return NULL;
1150                 }
1151             strncpy(pwsi->dbuffer, s, 32 );
1152             return pwsi->dbuffer; 
1153         }
1154         SetLastError(wsaErrno());
1155     }
1156     return NULL;
1157 }
1158
1159 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1160 {
1161   char* retVal = WINSOCK_inet_ntoa(in);
1162   return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
1163 }
1164
1165 /***********************************************************************
1166  *              ioctlsocket()           (WSOCK32.12)
1167  */
1168 INT WINAPI WINSOCK_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1169 {
1170   LPWSINFO      pwsi = WINSOCK_GetIData();
1171
1172   TRACE("(%08x): socket %04x, cmd %08lx, ptr %8x\n", 
1173                           (unsigned)pwsi, s, cmd, (unsigned) argp);
1174   if( _check_ws(pwsi, s) )
1175   {
1176     int         fd = _get_sock_fd(s);
1177     long        newcmd  = cmd;
1178
1179     switch( cmd )
1180     {
1181         case WS_FIONREAD:   
1182                 newcmd=FIONREAD; 
1183                 break;
1184
1185         case WS_FIONBIO:    
1186                 newcmd=FIONBIO;  
1187                 if( _get_sock_mask(s) )
1188                 {
1189                     /* AsyncSelect()'ed sockets are always nonblocking */
1190                     SetLastError(WSAEINVAL); 
1191                     close(fd);
1192                     return SOCKET_ERROR; 
1193                 }
1194                 close(fd);
1195                 if (*argp)
1196                     _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1197                 else
1198                     _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1199                 return 0;
1200
1201         case WS_SIOCATMARK: 
1202                 newcmd=SIOCATMARK; 
1203                 break;
1204
1205         case WS_IOW('f',125,u_long): 
1206                 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1207                 SetLastError(WSAEINVAL); 
1208                 return SOCKET_ERROR;
1209
1210         default:          
1211                 /* Netscape tries hard to use bogus ioctl 0x667e */
1212                 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1213     }
1214     if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1215     {
1216         close(fd);
1217         return 0;
1218     }
1219     SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno()); 
1220     close(fd);
1221   }
1222   return SOCKET_ERROR;
1223 }
1224
1225 /***********************************************************************
1226  *              ioctlsocket()           (WINSOCK.12)
1227  */
1228 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1229 {
1230     return (INT16)WINSOCK_ioctlsocket( s, cmd, argp );
1231 }
1232
1233
1234 /***********************************************************************
1235  *              listen()                (WSOCK32.13)
1236  */
1237 INT WINAPI WINSOCK_listen(SOCKET s, INT backlog)
1238 {
1239     LPWSINFO      pwsi = WINSOCK_GetIData();
1240
1241     TRACE("(%08x): socket %04x, backlog %d\n", 
1242                             (unsigned)pwsi, s, backlog);
1243     if( _check_ws(pwsi, s) )
1244     {
1245         int fd = _get_sock_fd(s);
1246         if (listen(fd, backlog) == 0)
1247         {
1248             close(fd);
1249             _enable_event(s, FD_ACCEPT,
1250                           WS_FD_LISTENING,
1251                           WS_FD_CONNECT|WS_FD_CONNECTED);
1252             return 0;
1253         }
1254         SetLastError(wsaErrno());
1255     }
1256     else SetLastError(WSAENOTSOCK);
1257     return SOCKET_ERROR;
1258 }
1259
1260 /***********************************************************************
1261  *              listen()                (WINSOCK.13)
1262  */
1263 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1264 {
1265     return (INT16)WINSOCK_listen( s, backlog );
1266 }
1267
1268
1269 /***********************************************************************
1270  *              recv()                  (WSOCK32.16)
1271  */
1272 INT WINAPI WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
1273 {
1274     LPWSINFO      pwsi = WINSOCK_GetIData();
1275
1276     TRACE("(%08x): socket %04x, buf %8x, len %d, "
1277                     "flags %d\n", (unsigned)pwsi, s, (unsigned)buf, 
1278                     len, flags);
1279     if( _check_ws(pwsi, s) )
1280     {
1281         int fd = _get_sock_fd(s);
1282         INT length;
1283
1284         if (_is_blocking(s))
1285         {
1286             /* block here */
1287             /* FIXME: OOB and exceptfds? */
1288             do_block(fd, 1);
1289         }
1290         if ((length = recv(fd, buf, len, flags)) >= 0) 
1291         { 
1292             TRACE(" -> %i bytes\n", length);
1293
1294             close(fd);
1295             _enable_event(s, FD_READ, 0, 0);
1296             return length;
1297         }
1298         SetLastError(wsaErrno());
1299         close(fd);
1300     }
1301     else SetLastError(WSAENOTSOCK);
1302     WARN(" -> ERROR\n");
1303     return SOCKET_ERROR;
1304 }
1305
1306 /***********************************************************************
1307  *              recv()                  (WINSOCK.16)
1308  */
1309 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1310 {
1311     return (INT16)WINSOCK_recv( s, buf, len, flags );
1312 }
1313
1314
1315 /***********************************************************************
1316  *              recvfrom()              (WSOCK32.17)
1317  */
1318 INT WINAPI WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags, 
1319                                 struct sockaddr *from, INT *fromlen32)
1320 {
1321     LPWSINFO                 pwsi = WINSOCK_GetIData();
1322 #ifdef HAVE_IPX
1323     struct ws_sockaddr_ipx*  from2 = (struct ws_sockaddr_ipx *)from;
1324 #endif
1325
1326     TRACE("(%08x): socket %04x, ptr %08x, "
1327                     "len %d, flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1328                     len, flags);
1329 #if DEBUG_SOCKADDR
1330     if( from ) dump_sockaddr(from);
1331     else DPRINTF("from = NULL\n");
1332 #endif
1333
1334     if( _check_ws(pwsi, s) )
1335     {
1336         int fd = _get_sock_fd(s);
1337         int length;
1338
1339         if (_is_blocking(s))
1340         {
1341             /* block here */
1342             /* FIXME: OOB and exceptfds */
1343             do_block(fd, 1);
1344         }
1345         if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1346         {
1347             TRACE(" -> %i bytes\n", length);
1348
1349 #ifdef HAVE_IPX
1350         if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1351             from = (struct sockaddr *)
1352                                 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1353             memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1354             from2->sipx_family = WS_AF_IPX;
1355             from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1356             from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1357             memcpy(from2->sipx_node,
1358                         ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1359             free(from);
1360         }
1361 #endif
1362             close(fd);
1363             _enable_event(s, FD_READ, 0, 0);
1364             return (INT16)length;
1365         }
1366         SetLastError(wsaErrno());
1367         close(fd);
1368     }
1369     else SetLastError(WSAENOTSOCK);
1370     WARN(" -> ERROR\n");
1371 #ifdef HAVE_IPX
1372     if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1373         from = (struct sockaddr *)
1374                                 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1375         memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1376         from2->sipx_family = WS_AF_IPX;
1377         from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1378         from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1379         memcpy(from2->sipx_node,
1380                 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1381         free(from);
1382     }
1383 #endif
1384     return SOCKET_ERROR;
1385 }
1386
1387 /***********************************************************************
1388  *              recvfrom()              (WINSOCK.17)
1389  */
1390 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1391                                 struct sockaddr *from, INT16 *fromlen16)
1392 {
1393     INT fromlen32;
1394     INT *p = &fromlen32;
1395     INT retVal;
1396
1397     if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1398     retVal = WINSOCK_recvfrom( s, buf, len, flags, from, p );
1399     if( fromlen16 ) *fromlen16 = fromlen32;
1400     return (INT16)retVal;
1401 }
1402
1403 /***********************************************************************
1404  *              select()                (WINSOCK.18)(WSOCK32.18)
1405  */
1406 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1407                           struct timeval *timeout )
1408 {
1409     LPWSINFO      pwsi = WINSOCK_GetIData();
1410         
1411     TRACE("(%08x): read %8x, write %8x, excp %8x\n", 
1412     (unsigned) pwsi, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
1413
1414     if( pwsi )
1415     {
1416         int         highfd = 0;
1417         fd_set      readfds, writefds, exceptfds;
1418         fd_set     *p_read, *p_write, *p_except;
1419         int         readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1420
1421         p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd, readfd, b32);
1422         p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd, writefd, b32);
1423         p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd, exceptfd, b32);
1424
1425         if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1426         {
1427             fd_set_export(pwsi, &readfds, p_except, ws_readfds, readfd, b32);
1428             fd_set_export(pwsi, &writefds, p_except, ws_writefds, writefd, b32);
1429
1430             if (p_except && ws_exceptfds)
1431             {
1432 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1433 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1434                 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1435
1436                 for (i = j = 0; i < count; i++)
1437                 {
1438                     int fd = exceptfd[i];
1439                     if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1440                     {
1441                         if( b32 )
1442                                 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1443                         else
1444                                 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1445                     }
1446                     if( fd >= 0 ) close(fd);
1447                     exceptfd[i] = -1;
1448                 }
1449                 if( b32 )
1450                     wsfds32->fd_count = j;
1451                 else
1452                     wsfds16->fd_count = j;
1453 #undef wsfds32
1454 #undef wsfds16
1455             }
1456             return highfd; 
1457         }
1458         fd_set_unimport(ws_readfds, readfd, b32);
1459         fd_set_unimport(ws_writefds, writefd, b32);
1460         fd_set_unimport(ws_exceptfds, exceptfd, b32);
1461         if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1462         if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1463         if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1464
1465         if( highfd == 0 ) return 0;
1466         SetLastError(wsaErrno());
1467     } 
1468     return SOCKET_ERROR;
1469 }
1470
1471 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1472                               ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1473                               struct timeval *timeout)
1474 {
1475     return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1476 }
1477
1478 INT WINAPI WINSOCK_select(INT nfds, ws_fd_set32 *ws_readfds,
1479                               ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1480                               struct timeval *timeout)
1481 {
1482     /* struct timeval is the same for both 32- and 16-bit code */
1483     return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1484 }
1485
1486
1487 /***********************************************************************
1488  *              send()                  (WSOCK32.19)
1489  */
1490 INT WINAPI WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
1491 {
1492     LPWSINFO      pwsi = WINSOCK_GetIData();
1493
1494     TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n", 
1495                            (unsigned)pwsi, s, (unsigned) buf, len, flags);
1496     if( _check_ws(pwsi, s) )
1497     {
1498         int     fd = _get_sock_fd(s);
1499         int     length;
1500
1501         if (_is_blocking(s))
1502         {
1503             /* block here */
1504             /* FIXME: exceptfds */
1505             do_block(fd, 2);
1506         }
1507         if ((length = send(fd, buf, len, flags)) < 0 ) 
1508         {
1509             SetLastError(wsaErrno());
1510             if( GetLastError() == WSAEWOULDBLOCK )
1511                 _enable_event(s, FD_WRITE, 0, 0);
1512         }
1513         else
1514         {
1515             close(fd);
1516             return (INT16)length;
1517         }
1518         close(fd);
1519     }
1520     else SetLastError(WSAENOTSOCK);
1521     return SOCKET_ERROR;
1522 }
1523
1524 /***********************************************************************
1525  *              send()                  (WINSOCK.19)
1526  */
1527 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1528 {
1529     return WINSOCK_send( s, buf, len, flags );
1530 }
1531
1532 /***********************************************************************
1533  *              sendto()                (WSOCK32.20)
1534  */
1535 INT WINAPI WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
1536                               struct sockaddr *to, INT tolen)
1537 {
1538     LPWSINFO                 pwsi = WINSOCK_GetIData();
1539 #ifdef HAVE_IPX
1540     struct ws_sockaddr_ipx*  to2 = (struct ws_sockaddr_ipx *)to;
1541 #endif
1542
1543     TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1544                           (unsigned)pwsi, s, (unsigned) buf, len, flags);
1545     if( _check_ws(pwsi, s) )
1546     {
1547         int     fd = _get_sock_fd(s);
1548         INT     length;
1549
1550         if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1551             ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1552 #ifdef HAVE_IPX
1553         else if (to &&
1554                 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1555         {
1556             to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1557             memset(to, '\0', sizeof(struct sockaddr_ipx));
1558             ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1559             ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1560             ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1561             memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1562                         to2->sipx_node, IPX_NODE_LEN);
1563             tolen = sizeof(struct sockaddr_ipx);
1564         }
1565 #endif
1566         if (_is_blocking(s))
1567         {
1568             /* block here */
1569             /* FIXME: exceptfds */
1570             do_block(fd, 2);
1571         }
1572         if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
1573         {
1574             SetLastError(wsaErrno());
1575             if( GetLastError() == WSAEWOULDBLOCK )
1576                 _enable_event(s, FD_WRITE, 0, 0);
1577         } 
1578         else {
1579 #ifdef HAVE_IPX
1580             if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1581                 free(to);
1582             }
1583 #endif
1584             close(fd);
1585             return length;
1586         }
1587         close(fd);
1588     }
1589     else SetLastError(WSAENOTSOCK);
1590 #ifdef HAVE_IPX
1591     if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1592         free(to);
1593     }
1594 #endif
1595     return SOCKET_ERROR;
1596 }
1597
1598 /***********************************************************************
1599  *              sendto()                (WINSOCK.20)
1600  */
1601 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1602                               struct sockaddr *to, INT16 tolen)
1603 {
1604     return (INT16)WINSOCK_sendto( s, buf, len, flags, to, tolen );
1605 }
1606
1607 /***********************************************************************
1608  *              setsockopt()            (WSOCK32.21)
1609  */
1610 INT WINAPI WINSOCK_setsockopt(SOCKET16 s, INT level, INT optname, 
1611                                   char *optval, INT optlen)
1612 {
1613     LPWSINFO      pwsi = WINSOCK_GetIData();
1614
1615     TRACE("(%08x): socket %04x, lev %d, opt %d, ptr %08x, len %d\n",
1616                           (unsigned)pwsi, s, level, optname, (int) optval, optlen);
1617     if( _check_ws(pwsi, s) )
1618     {
1619         struct  linger linger;
1620         int fd = _get_sock_fd(s);
1621
1622         convert_sockopt(&level, &optname);
1623         if (optname == SO_LINGER && optval) {
1624                 /* yes, uses unsigned short in both win16/win32 */
1625                 linger.l_onoff  = ((UINT16*)optval)[0];
1626                 linger.l_linger = ((UINT16*)optval)[1];
1627                 /* FIXME: what is documented behavior if SO_LINGER optval
1628                    is null?? */
1629                 optval = (char*)&linger;
1630                 optlen = sizeof(struct linger);
1631         }
1632         if (setsockopt(fd, level, optname, optval, optlen) == 0)
1633         {
1634             close(fd);
1635             return 0;
1636         }
1637         SetLastError(wsaErrno());
1638         close(fd);
1639     }
1640     else SetLastError(WSAENOTSOCK);
1641     return SOCKET_ERROR;
1642 }
1643
1644 /***********************************************************************
1645  *              setsockopt()            (WINSOCK.21)
1646  */
1647 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
1648                                   char *optval, INT16 optlen)
1649 {
1650     if( !optval ) return SOCKET_ERROR;
1651     return (INT16)WINSOCK_setsockopt( s, (UINT16)level, optname, optval, optlen );
1652 }
1653
1654
1655 /***********************************************************************
1656  *              shutdown()              (WSOCK32.22)
1657  */
1658 INT WINAPI WINSOCK_shutdown(SOCKET s, INT how)
1659 {
1660     LPWSINFO      pwsi = WINSOCK_GetIData();
1661
1662     TRACE("(%08x): socket %04x, how %i\n",
1663                             (unsigned)pwsi, s, how );
1664     if( _check_ws(pwsi, s) )
1665     {
1666         int fd = _get_sock_fd(s);
1667             switch( how )
1668             {
1669                 case 0: /* drop receives */
1670                         _enable_event(s, 0, 0, WS_FD_READ);
1671 #ifdef SHUT_RD
1672                         how = SHUT_RD;
1673 #endif
1674                         break;
1675
1676                 case 1: /* drop sends */
1677                         _enable_event(s, 0, 0, WS_FD_WRITE);
1678 #ifdef SHUT_WR
1679                         how = SHUT_WR;
1680 #endif
1681                         break;
1682
1683                 case 2: /* drop all */
1684 #ifdef SHUT_RDWR
1685                         how = SHUT_RDWR;
1686 #endif
1687                 default:
1688                         WSAAsyncSelect( s, 0, 0, 0 );
1689                         break;
1690             }
1691
1692         if (shutdown(fd, how) == 0) 
1693         {
1694             if( how > 1 ) 
1695             {
1696                 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
1697             }
1698             close(fd);
1699             return 0;
1700         }
1701         SetLastError(wsaErrno());
1702         close(fd);
1703     } 
1704     else SetLastError(WSAENOTSOCK);
1705     return SOCKET_ERROR;
1706 }
1707
1708 /***********************************************************************
1709  *              shutdown()              (WINSOCK.22)
1710  */
1711 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
1712 {
1713     return (INT16)WINSOCK_shutdown( s, how );
1714 }
1715
1716
1717 /***********************************************************************
1718  *              socket()                (WSOCK32.23)
1719  */
1720 SOCKET WINAPI WINSOCK_socket(INT af, INT type, INT protocol)
1721 {
1722   LPWSINFO      pwsi = WINSOCK_GetIData();
1723   struct create_socket_request *req = get_req_buffer();
1724
1725   TRACE("(%08x): af=%d type=%d protocol=%d\n", 
1726                           (unsigned)pwsi, af, type, protocol);
1727
1728   if( pwsi )
1729   {
1730     /* check the socket family */
1731     switch(af) 
1732     {
1733 #ifdef HAVE_IPX
1734         case WS_AF_IPX: af = AF_IPX;
1735 #endif
1736         case AF_INET:
1737         case AF_UNSPEC: break;
1738         default:        SetLastError(WSAEAFNOSUPPORT); 
1739                         return INVALID_SOCKET;
1740     }
1741
1742     /* check the socket type */
1743     switch(type) 
1744     {
1745         case SOCK_STREAM:
1746         case SOCK_DGRAM:
1747         case SOCK_RAW:  break;
1748         default:        SetLastError(WSAESOCKTNOSUPPORT); 
1749                         return INVALID_SOCKET;
1750     }
1751
1752     /* check the protocol type */
1753     if ( protocol < 0 )  /* don't support negative values */
1754     { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
1755
1756     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
1757         switch(protocol) 
1758         {
1759           case IPPROTO_TCP:
1760              if (type == SOCK_STREAM) { af = AF_INET; break; }
1761           case IPPROTO_UDP:
1762              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
1763           default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
1764         }
1765
1766     req->family   = af;
1767     req->type     = type;
1768     req->protocol = protocol;
1769     req->access   = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1770     req->inherit  = TRUE;
1771     server_call( REQ_CREATE_SOCKET );
1772     if ( req->handle >= 0)
1773     {
1774         TRACE("\tcreated %04x\n", req->handle);
1775
1776         return req->handle;
1777     }
1778
1779     if (GetLastError() == WSAEACCES) /* raw socket denied */
1780     {
1781         if (type == SOCK_RAW)
1782             MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
1783         else
1784             MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
1785         SetLastError(WSAESOCKTNOSUPPORT);
1786     }
1787   }
1788  
1789   WARN("\t\tfailed!\n");
1790   return INVALID_SOCKET;
1791 }
1792
1793 /***********************************************************************
1794  *              socket()                (WINSOCK.23)
1795  */
1796 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
1797 {
1798     return (SOCKET16)WINSOCK_socket( af, type, protocol );
1799 }
1800     
1801
1802 /* ----------------------------------- DNS services
1803  *
1804  * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
1805  * Also, we have to use wsock32 stubs to convert structures and
1806  * error codes from Unix to WSA, hence there is no direct mapping in 
1807  * the relay32/wsock32.spec.
1808  */
1809
1810 static char*    NULL_STRING = "NULL";
1811
1812 /***********************************************************************
1813  *              gethostbyaddr()         (WINSOCK.51)(WSOCK32.51)
1814  */
1815 static struct WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
1816 {
1817     LPWSINFO            pwsi = WINSOCK_GetIData();
1818
1819     if( pwsi )
1820     {
1821         struct hostent* host;
1822         if( (host = gethostbyaddr(addr, len, type)) != NULL )
1823             if( WS_dup_he(pwsi, host, dup_flag) )
1824                 return (struct WIN_hostent*)(pwsi->he);
1825             else 
1826                 SetLastError(WSAENOBUFS);
1827         else 
1828             SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1829     }
1830     return NULL;
1831 }
1832
1833 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
1834 {
1835     struct WIN_hostent* retval;
1836     TRACE("ptr %08x, len %d, type %d\n",
1837                             (unsigned) addr, len, type);
1838     retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
1839     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
1840 }
1841
1842 struct WIN_hostent* WINAPI WINSOCK_gethostbyaddr(const char *addr, INT len,
1843                                                 INT type)
1844 {
1845     TRACE("ptr %08x, len %d, type %d\n",
1846                              (unsigned) addr, len, type);
1847     return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
1848 }
1849
1850 /***********************************************************************
1851  *              gethostbyname()         (WINSOCK.52)(WSOCK32.52)
1852  */
1853 static struct WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
1854 {
1855     LPWSINFO              pwsi = WINSOCK_GetIData();
1856
1857     if( pwsi )
1858     {
1859         struct hostent*     host;
1860         if( (host = gethostbyname(name)) != NULL )
1861              if( WS_dup_he(pwsi, host, dup_flag) )
1862                  return (struct WIN_hostent*)(pwsi->he);
1863              else SetLastError(WSAENOBUFS);
1864         else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1865     }
1866     return NULL;
1867 }
1868
1869 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
1870 {
1871     struct WIN_hostent* retval;
1872     TRACE("%s\n", (name)?name:NULL_STRING);
1873     retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
1874     return (retval)? SEGPTR_GET(retval) : ((SEGPTR)NULL) ;
1875 }
1876
1877 struct WIN_hostent* WINAPI WINSOCK_gethostbyname(const char* name)
1878 {
1879     TRACE("%s\n", (name)?name:NULL_STRING);
1880     return __ws_gethostbyname( name, WS_DUP_LINEAR );
1881 }
1882
1883
1884 /***********************************************************************
1885  *              getprotobyname()        (WINSOCK.53)(WSOCK32.53)
1886  */
1887 static struct WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
1888 {
1889     LPWSINFO              pwsi = WINSOCK_GetIData();
1890
1891     if( pwsi )
1892     {
1893         struct protoent*     proto;
1894         if( (proto = getprotobyname(name)) != NULL )
1895             if( WS_dup_pe(pwsi, proto, dup_flag) )
1896                 return (struct WIN_protoent*)(pwsi->pe);
1897             else SetLastError(WSAENOBUFS);
1898         else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1899     }
1900     return NULL;
1901 }
1902
1903 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
1904 {
1905     struct WIN_protoent* retval;
1906     TRACE("%s\n", (name)?name:NULL_STRING);
1907     retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
1908     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
1909 }
1910
1911 struct WIN_protoent* WINAPI WINSOCK_getprotobyname(const char* name)
1912 {
1913     TRACE("%s\n", (name)?name:NULL_STRING);
1914     return __ws_getprotobyname(name, WS_DUP_LINEAR);
1915 }
1916
1917
1918 /***********************************************************************
1919  *              getprotobynumber()      (WINSOCK.54)(WSOCK32.54)
1920  */
1921 static struct WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
1922 {
1923     LPWSINFO              pwsi = WINSOCK_GetIData();
1924
1925     if( pwsi )
1926     {
1927         struct protoent*     proto;
1928         if( (proto = getprotobynumber(number)) != NULL )
1929             if( WS_dup_pe(pwsi, proto, dup_flag) )
1930                 return (struct WIN_protoent*)(pwsi->pe);
1931             else SetLastError(WSAENOBUFS);
1932         else SetLastError(WSANO_DATA);
1933     }
1934     return NULL;
1935 }
1936
1937 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
1938 {
1939     struct WIN_protoent* retval;
1940     TRACE("%i\n", number);
1941     retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
1942     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
1943 }
1944
1945 struct WIN_protoent* WINAPI WINSOCK_getprotobynumber(INT number)
1946 {
1947     TRACE("%i\n", number);
1948     return __ws_getprotobynumber(number, WS_DUP_LINEAR);
1949 }
1950
1951
1952 /***********************************************************************
1953  *              getservbyname()         (WINSOCK.55)(WSOCK32.55)
1954  */
1955 struct WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
1956 {
1957     LPWSINFO              pwsi = WINSOCK_GetIData();
1958
1959     if( pwsi )
1960     {
1961         struct servent*     serv;
1962         int i = wsi_strtolo( pwsi, name, proto );
1963
1964         if( i )
1965             if( (serv = getservbyname(pwsi->buffer, pwsi->buffer + i)) != NULL )
1966                 if( WS_dup_se(pwsi, serv, dup_flag) )
1967                     return (struct WIN_servent*)(pwsi->se);
1968                 else SetLastError(WSAENOBUFS);
1969             else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1970         else SetLastError(WSAENOBUFS);
1971     }
1972     return NULL;
1973 }
1974
1975 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
1976 {
1977     struct WIN_servent* retval;
1978     TRACE("'%s', '%s'\n",
1979                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
1980     retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
1981     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
1982 }
1983
1984 struct WIN_servent* WINAPI WINSOCK_getservbyname(const char *name, const char *proto)
1985 {
1986     TRACE("'%s', '%s'\n",
1987                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
1988     return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
1989 }
1990
1991
1992 /***********************************************************************
1993  *              getservbyport()         (WINSOCK.56)(WSOCK32.56)
1994  */
1995 static struct WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
1996 {
1997     LPWSINFO              pwsi = WINSOCK_GetIData();
1998
1999     if( pwsi )
2000     {
2001         struct servent*     serv;
2002         int i = wsi_strtolo( pwsi, proto, NULL );
2003
2004         if( i )
2005             if( (serv = getservbyport(port, pwsi->buffer)) != NULL )
2006                 if( WS_dup_se(pwsi, serv, dup_flag) )
2007                     return (struct WIN_servent*)(pwsi->se);
2008                 else SetLastError(WSAENOBUFS);
2009             else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2010         else SetLastError(WSAENOBUFS);
2011     }
2012     return NULL;
2013 }
2014
2015 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2016 {
2017     struct WIN_servent* retval;
2018     TRACE("%i, '%s'\n",
2019                             (int)port, (proto)?proto:NULL_STRING);
2020     retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2021     return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2022 }
2023
2024 struct WIN_servent* WINAPI WINSOCK_getservbyport(INT port, const char *proto)
2025 {
2026     TRACE("%i, '%s'\n",
2027                             (int)port, (proto)?proto:NULL_STRING);
2028     return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2029 }
2030
2031
2032 /***********************************************************************
2033  *              gethostname()           (WSOCK32.57)
2034  */
2035 INT WINAPI WINSOCK_gethostname(char *name, INT namelen)
2036 {
2037     LPWSINFO              pwsi = WINSOCK_GetIData();
2038
2039     TRACE("(%08x): name %s, len %d\n",
2040                           (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
2041     if( pwsi )
2042     {
2043         if (gethostname(name, namelen) == 0) return 0;
2044         SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2045     }
2046     return SOCKET_ERROR;
2047 }
2048
2049 /***********************************************************************
2050  *              gethostname()           (WINSOCK.57)
2051  */
2052 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2053 {
2054     return (INT16)WINSOCK_gethostname(name, namelen);
2055 }
2056
2057
2058 /* ------------------------------------- Windows sockets extensions -- *
2059  *                                                                     *
2060  * ------------------------------------------------------------------- */
2061
2062 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2063 {
2064     LPWSINFO      pwsi = WINSOCK_GetIData();
2065     struct get_socket_event_request *req = get_req_buffer();
2066
2067     TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2068                           (unsigned)pwsi, s, hEvent, (unsigned)lpEvent );
2069     if( _check_ws(pwsi, s) )
2070     {
2071         req->handle  = s;
2072         req->service = TRUE;
2073         req->s_event = 0;
2074         server_call( REQ_GET_SOCKET_EVENT );
2075         lpEvent->lNetworkEvents = req->pmask;
2076         memcpy(lpEvent->iErrorCode, req->errors, sizeof(lpEvent->iErrorCode));
2077         if (hEvent)
2078             ResetEvent(hEvent);
2079         return 0;
2080     }
2081     else SetLastError(WSAEINVAL);
2082     return SOCKET_ERROR; 
2083 }
2084
2085 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2086 {
2087     LPWSINFO      pwsi = WINSOCK_GetIData();
2088     struct set_socket_event_request *req = get_req_buffer();
2089
2090     TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2091                           (unsigned)pwsi, s, hEvent, (unsigned)lEvent );
2092     if( _check_ws(pwsi, s) )
2093     {
2094         req->handle = s;
2095         req->mask   = lEvent;
2096         req->event  = hEvent;
2097         server_call( REQ_SET_SOCKET_EVENT );
2098         return 0;
2099     }
2100     else SetLastError(WSAEINVAL);
2101     return SOCKET_ERROR; 
2102 }
2103
2104 /***********************************************************************
2105  *      WSAAsyncSelect()                (WINSOCK.101)(WSOCK32.101)
2106  */
2107
2108 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2109 {
2110     /* FIXME: accepted socket uses same event object as listening socket by default
2111      * (at least before a new WSAAsyncSelect is issued), must handle it somehow */
2112     ws_select_info *info = (ws_select_info*)ptr;
2113     struct get_socket_event_request *req = get_req_buffer();
2114     unsigned int i, pmask;
2115
2116     TRACE("socket %08x, event %08x\n", info->sock, info->event);
2117     SetLastError(0);
2118     req->handle  = info->sock;
2119     req->service = TRUE;
2120     req->s_event = info->event; /* <== avoid race conditions */
2121     server_call( REQ_GET_SOCKET_EVENT );
2122     if ( GetLastError() == WSAEINVAL )
2123     {
2124         /* orphaned event (socket closed or something) */
2125         TRACE("orphaned event, self-destructing\n");
2126         SERVICE_Delete( info->service );
2127         WS_FREE(info);
2128         return;
2129     }
2130     /* dispatch network events */
2131     pmask = req->pmask;
2132     for (i=0; i<FD_MAX_EVENTS; i++)
2133         if (pmask & (1<<i)) {
2134             TRACE("post: event bit %d, error %d\n", i, req->errors[i]);
2135             PostMessageA(info->hWnd, info->uMsg, info->sock,
2136                          WSAMAKESELECTREPLY(1<<i, req->errors[i]));
2137         }
2138 }
2139
2140 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2141 {
2142     LPWSINFO      pwsi = WINSOCK_GetIData();
2143
2144     TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2145                           (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2146     if( _check_ws(pwsi, s) )
2147     {
2148         if( lEvent )
2149         {
2150             ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2151             if( info )
2152             {
2153                 HANDLE hObj = CreateEventA( NULL, FALSE, FALSE, NULL );
2154                 INT err;
2155                 
2156                 info->sock  = s;
2157                 info->event = hObj;
2158                 info->hWnd  = hWnd;
2159                 info->uMsg  = uMsg;
2160                 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2161
2162                 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2163                 if (err) {
2164                     SERVICE_Delete( info->service );
2165                     WS_FREE(info);
2166                     return err;
2167                 }
2168
2169                 return 0; /* success */
2170             }
2171             else SetLastError(WSAENOBUFS);
2172         } 
2173         else
2174         {
2175             WSAEventSelect(s, 0, 0);
2176             return 0;
2177         }
2178     } 
2179     else SetLastError(WSAEINVAL);
2180     return SOCKET_ERROR; 
2181 }
2182
2183 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2184 {
2185     return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2186 }
2187
2188 /***********************************************************************
2189  *              WSARecvEx()                     (WSOCK32.1107)
2190  *
2191  * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
2192  * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
2193  * into the flags parameter when a partial packet is read. This only applies to
2194  * sockets using the datagram protocol. This method does not seem to be implemented
2195  * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
2196  * flag when a fragmented packet arrives.
2197  */
2198 INT     WINAPI   WSARecvEx(SOCKET s, char *buf, INT len, INT *flags) {
2199   FIXME("(WSARecvEx) partial packet return value not set \n");
2200
2201   return WINSOCK_recv(s, buf, len, *flags);
2202 }
2203
2204
2205 /***********************************************************************
2206  *              WSARecvEx16()                   (WINSOCK.1107)
2207  *
2208  * See description for WSARecvEx()
2209  */
2210 INT16     WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2211   FIXME("(WSARecvEx16) partial packet return value not set \n");
2212
2213   return WINSOCK_recv16(s, buf, len, *flags);
2214 }
2215
2216
2217 /***********************************************************************
2218  *      __WSAFDIsSet()                  (WINSOCK.151)
2219  */
2220 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2221 {
2222   int i = set->fd_count;
2223   
2224   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2225     
2226   while (i--)
2227       if (set->fd_array[i] == s) return 1;
2228   return 0;
2229 }                                                            
2230
2231 /***********************************************************************
2232  *      __WSAFDIsSet()                  (WSOCK32.151)
2233  */
2234 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2235 {
2236   int i = set->fd_count;
2237
2238   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2239
2240   while (i--)
2241       if (set->fd_array[i] == s) return 1;
2242   return 0;
2243 }
2244
2245 /***********************************************************************
2246  *      WSAIsBlocking()                 (WINSOCK.114)(WSOCK32.114)
2247  */
2248 BOOL WINAPI WSAIsBlocking(void)
2249 {
2250   /* By default WinSock should set all its sockets to non-blocking mode
2251    * and poll in PeekMessage loop when processing "blocking" ones. This 
2252    * function is supposed to tell if the program is in this loop. Our 
2253    * blocking calls are truly blocking so we always return FALSE.
2254    *
2255    * Note: It is allowed to call this function without prior WSAStartup().
2256    */
2257
2258   TRACE("\n");
2259   return FALSE;
2260 }
2261
2262 /***********************************************************************
2263  *      WSACancelBlockingCall()         (WINSOCK.113)(WSOCK32.113)
2264  */
2265 INT WINAPI WSACancelBlockingCall(void)
2266 {
2267   LPWSINFO              pwsi = WINSOCK_GetIData();
2268
2269   TRACE("(%08x)\n", (unsigned)pwsi);
2270
2271   if( pwsi ) return 0;
2272   return SOCKET_ERROR;
2273 }
2274
2275
2276 /***********************************************************************
2277  *      WSASetBlockingHook16()          (WINSOCK.109)
2278  */
2279 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2280 {
2281   FARPROC16             prev;
2282   LPWSINFO              pwsi = WINSOCK_GetIData();
2283
2284   TRACE("(%08x): hook %08x\n", 
2285                (unsigned)pwsi, (unsigned) lpBlockFunc);
2286   if( pwsi ) 
2287   { 
2288       prev = (FARPROC16)pwsi->blocking_hook; 
2289       pwsi->blocking_hook = (DWORD)lpBlockFunc; 
2290       pwsi->flags &= ~WSI_BLOCKINGHOOK;
2291       return prev; 
2292   }
2293   return 0;
2294 }
2295
2296
2297 /***********************************************************************
2298  *      WSASetBlockingHook32()
2299  */
2300 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2301 {
2302   FARPROC             prev;
2303   LPWSINFO              pwsi = WINSOCK_GetIData();
2304
2305   TRACE("(%08x): hook %08x\n",
2306                (unsigned)pwsi, (unsigned) lpBlockFunc);
2307   if( pwsi ) {
2308       prev = (FARPROC)pwsi->blocking_hook;
2309       pwsi->blocking_hook = (DWORD)lpBlockFunc;
2310       pwsi->flags |= WSI_BLOCKINGHOOK;
2311       return prev;
2312   }
2313   return NULL;
2314 }
2315
2316
2317 /***********************************************************************
2318  *      WSAUnhookBlockingHook16()       (WINSOCK.110)
2319  */
2320 INT16 WINAPI WSAUnhookBlockingHook16(void)
2321 {
2322     LPWSINFO              pwsi = WINSOCK_GetIData();
2323
2324     TRACE("(%08x)\n", (unsigned)pwsi);
2325     if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
2326     return SOCKET_ERROR;
2327 }
2328
2329
2330 /***********************************************************************
2331  *      WSAUnhookBlockingHook32()
2332  */
2333 INT WINAPI WSAUnhookBlockingHook(void)
2334 {
2335     LPWSINFO              pwsi = WINSOCK_GetIData();
2336
2337     TRACE("(%08x)\n", (unsigned)pwsi);
2338     if( pwsi )
2339     {
2340         pwsi->blocking_hook = 0;
2341         pwsi->flags &= ~WSI_BLOCKINGHOOK;
2342         return 0;
2343     }
2344     return SOCKET_ERROR;
2345 }
2346
2347 /*
2348  *      TCP/IP action codes.
2349  */
2350
2351
2352 #define WSCNTL_TCPIP_QUERY_INFO             0x00000000
2353 #define WSCNTL_TCPIP_SET_INFO               0x00000001
2354 #define WSCNTL_TCPIP_ICMP_ECHO              0x00000002
2355 #define WSCNTL_TCPIP_TEST                   0x00000003
2356
2357
2358 /***********************************************************************
2359  *      WsControl()
2360  *
2361  * WsControl seems to be an undocumented Win95 function. A lot of 
2362  * discussion about WsControl can be found on the net, e.g.
2363  * Subject:      Re: WSOCK32.DLL WsControl Exported Function
2364  * From:         "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
2365  * Date:         1997/08/17
2366  */
2367
2368 DWORD WINAPI WsControl(DWORD protocoll,DWORD action,
2369                       LPVOID inbuf,LPDWORD inbuflen,
2370                       LPVOID outbuf,LPDWORD outbuflen) 
2371 {
2372
2373   switch (action) {
2374   case WSCNTL_TCPIP_ICMP_ECHO:
2375     {
2376       unsigned int addr = *(unsigned int*)inbuf;
2377 #if 0
2378       int timeout= *(unsigned int*)(inbuf+4);
2379       short x1 = *(unsigned short*)(inbuf+8);
2380       short sendbufsize = *(unsigned short*)(inbuf+10);
2381       char x2 = *(unsigned char*)(inbuf+12);
2382       char ttl = *(unsigned char*)(inbuf+13);
2383       char service = *(unsigned char*)(inbuf+14);
2384       char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
2385 #endif      
2386       
2387       FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr);
2388       break;
2389     }
2390   default:
2391     FIXME("(%lx,%lx,%p,%p,%p,%p) stub\n",
2392           protocoll,action,inbuf,inbuflen,outbuf,outbuflen);
2393   }
2394   return FALSE;
2395 }
2396 /*********************************************************
2397  *       WS_s_perror         WSOCK32.1108 
2398  */
2399 void WINAPI WS_s_perror(LPCSTR message)
2400 {
2401     FIXME("(%s): stub\n",message);
2402     return;
2403 }
2404
2405
2406 /* ----------------------------------- end of API stuff */
2407
2408 /* ----------------------------------- helper functions -
2409  *
2410  * TODO: Merge WS_dup_..() stuff into one function that
2411  * would operate with a generic structure containing internal
2412  * pointers (via a template of some kind).
2413  */
2414
2415 static int list_size(char** l, int item_size)
2416 {
2417   int i,j = 0;
2418   if(l)
2419   { for(i=0;l[i];i++) 
2420         j += (item_size) ? item_size : strlen(l[i]) + 1;
2421     j += (i + 1) * sizeof(char*); }
2422   return j;
2423 }
2424
2425 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2426
2427    /* base is either either equal to ref or 0 or SEGPTR */
2428
2429    char*                p = ref;
2430    char**               l_to = (char**)ref;
2431    int                  i,j,k;
2432
2433    for(j=0;l_src[j];j++) ;
2434    p += (j + 1) * sizeof(char*);
2435    for(i=0;i<j;i++)
2436    { l_to[i] = base + (p - ref);
2437      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2438      memcpy(p, l_src[i], k); p += k; }
2439    l_to[i] = NULL;
2440    return (p - ref);
2441 }
2442
2443 /* ----- hostent */
2444
2445 static int hostent_size(struct hostent* p_he)
2446 {
2447   int size = 0;
2448   if( p_he )
2449   { size  = sizeof(struct hostent); 
2450     size += strlen(p_he->h_name) + 1;
2451     size += list_size(p_he->h_aliases, 0);  
2452     size += list_size(p_he->h_addr_list, p_he->h_length ); }
2453   return size;
2454 }
2455
2456 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
2457 {
2458    /* Convert hostent structure into ws_hostent so that the data fits 
2459     * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or 
2460     * relative to pwsi->buffer depending on "flag" value. Returns size
2461     * of the data copied (also in the pwsi->buflen).
2462     */
2463
2464    int size = hostent_size(p_he);
2465
2466    if( size )
2467    {
2468      struct ws_hostent* p_to;
2469      char* p_name,*p_aliases,*p_addr,*p_base,*p;
2470
2471      _check_buffer_he(pwsi, size);
2472      p_to = (struct ws_hostent*)pwsi->he;
2473      p = (char*)pwsi->he;
2474      p_base = (flag & WS_DUP_OFFSET) ? NULL
2475                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2476      p += sizeof(struct ws_hostent);
2477      p_name = p;
2478      strcpy(p, p_he->h_name); p += strlen(p) + 1;
2479      p_aliases = p;
2480      p += list_dup(p_he->h_aliases, p, p_base + (p - (char*)pwsi->he), 0);
2481      p_addr = p;
2482      list_dup(p_he->h_addr_list, p, p_base + (p - (char*)pwsi->he), p_he->h_length);
2483
2484      p_to->h_addrtype = (INT16)p_he->h_addrtype; 
2485      p_to->h_length = (INT16)p_he->h_length;
2486      p_to->h_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->he));
2487      p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->he));
2488      p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - (char*)pwsi->he));
2489
2490      size += (sizeof(struct ws_hostent) - sizeof(struct hostent));
2491    }
2492    return size;
2493 }
2494
2495 /* ----- protoent */
2496
2497 static int protoent_size(struct protoent* p_pe)
2498 {
2499   int size = 0;
2500   if( p_pe )
2501   { size  = sizeof(struct protoent);
2502     size += strlen(p_pe->p_name) + 1;
2503     size += list_size(p_pe->p_aliases, 0); }
2504   return size;
2505 }
2506
2507 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
2508 {
2509    int size = protoent_size(p_pe);
2510    if( size )
2511    {
2512      struct ws_protoent* p_to;
2513      char* p_name,*p_aliases,*p_base,*p;
2514
2515      _check_buffer_pe(pwsi, size);
2516      p_to = (struct ws_protoent*)pwsi->pe;
2517      p = (char*)pwsi->pe; 
2518      p_base = (flag & WS_DUP_OFFSET) ? NULL
2519                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2520      p += sizeof(struct ws_protoent);
2521      p_name = p;
2522      strcpy(p, p_pe->p_name); p += strlen(p) + 1;
2523      p_aliases = p;
2524      list_dup(p_pe->p_aliases, p, p_base + (p - (char*)pwsi->pe), 0);
2525
2526      p_to->p_proto = (INT16)p_pe->p_proto;
2527      p_to->p_name = (SEGPTR)(p_base) + (p_name - (char*)pwsi->pe);
2528      p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - (char*)pwsi->pe)); 
2529
2530      size += (sizeof(struct ws_protoent) - sizeof(struct protoent));
2531    }
2532    return size;
2533 }
2534
2535 /* ----- servent */
2536
2537 static int servent_size(struct servent* p_se)
2538 {
2539   int size = 0;
2540   if( p_se )
2541   { size += sizeof(struct servent);
2542     size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
2543     size += list_size(p_se->s_aliases, 0); }
2544   return size;
2545 }
2546
2547 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
2548 {
2549    int size = servent_size(p_se);
2550    if( size )
2551    {
2552      struct ws_servent* p_to;
2553      char* p_name,*p_aliases,*p_proto,*p_base,*p;
2554
2555      _check_buffer_se(pwsi, size);
2556      p_to = (struct ws_servent*)pwsi->se;
2557      p = (char*)pwsi->se;
2558      p_base = (flag & WS_DUP_OFFSET) ? NULL 
2559                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2560      p += sizeof(struct ws_servent);
2561      p_name = p;
2562      strcpy(p, p_se->s_name); p += strlen(p) + 1;
2563      p_proto = p;
2564      strcpy(p, p_se->s_proto); p += strlen(p) + 1;
2565      p_aliases = p;
2566      list_dup(p_se->s_aliases, p, p_base + (p - (char*)pwsi->se), 0);
2567
2568      p_to->s_port = (INT16)p_se->s_port;
2569      p_to->s_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->se));
2570      p_to->s_proto = (SEGPTR)(p_base + (p_proto - (char*)pwsi->se));
2571      p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->se)); 
2572
2573      size += (sizeof(struct ws_servent) - sizeof(struct servent));
2574    }
2575    return size;
2576 }
2577
2578 /* ----------------------------------- error handling */
2579
2580 UINT16 wsaErrno(void)
2581 {
2582     int loc_errno = errno; 
2583 #ifdef HAVE_STRERROR
2584     WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
2585 #else
2586     WARN("errno %d\n", loc_errno);
2587 #endif
2588
2589     switch(loc_errno)
2590     {
2591         case EINTR:             return WSAEINTR;
2592         case EBADF:             return WSAEBADF;
2593         case EPERM:
2594         case EACCES:            return WSAEACCES;
2595         case EFAULT:            return WSAEFAULT;
2596         case EINVAL:            return WSAEINVAL;
2597         case EMFILE:            return WSAEMFILE;
2598         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
2599         case EINPROGRESS:       return WSAEINPROGRESS;
2600         case EALREADY:          return WSAEALREADY;
2601         case ENOTSOCK:          return WSAENOTSOCK;
2602         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
2603         case EMSGSIZE:          return WSAEMSGSIZE;
2604         case EPROTOTYPE:        return WSAEPROTOTYPE;
2605         case ENOPROTOOPT:       return WSAENOPROTOOPT;
2606         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
2607         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
2608         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
2609         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
2610         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
2611         case EADDRINUSE:        return WSAEADDRINUSE;
2612         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
2613         case ENETDOWN:          return WSAENETDOWN;
2614         case ENETUNREACH:       return WSAENETUNREACH;
2615         case ENETRESET:         return WSAENETRESET;
2616         case ECONNABORTED:      return WSAECONNABORTED;
2617         case EPIPE:
2618         case ECONNRESET:        return WSAECONNRESET;
2619         case ENOBUFS:           return WSAENOBUFS;
2620         case EISCONN:           return WSAEISCONN;
2621         case ENOTCONN:          return WSAENOTCONN;
2622         case ESHUTDOWN:         return WSAESHUTDOWN;
2623         case ETOOMANYREFS:      return WSAETOOMANYREFS;
2624         case ETIMEDOUT:         return WSAETIMEDOUT;
2625         case ECONNREFUSED:      return WSAECONNREFUSED;
2626         case ELOOP:             return WSAELOOP;
2627         case ENAMETOOLONG:      return WSAENAMETOOLONG;
2628         case EHOSTDOWN:         return WSAEHOSTDOWN;
2629         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
2630         case ENOTEMPTY:         return WSAENOTEMPTY;
2631 #ifdef EPROCLIM
2632         case EPROCLIM:          return WSAEPROCLIM;
2633 #endif
2634 #ifdef EUSERS
2635         case EUSERS:            return WSAEUSERS;
2636 #endif
2637 #ifdef EDQUOT
2638         case EDQUOT:            return WSAEDQUOT;
2639 #endif
2640 #ifdef ESTALE
2641         case ESTALE:            return WSAESTALE;
2642 #endif
2643 #ifdef EREMOTE
2644         case EREMOTE:           return WSAEREMOTE;
2645 #endif
2646
2647        /* just in case we ever get here and there are no problems */
2648         case 0:                 return 0;
2649         default:
2650                 WARN("Unknown errno %d!\n", loc_errno);
2651                 return WSAEOPNOTSUPP;
2652     }
2653 }
2654
2655 UINT16 wsaHerrno(void)
2656 {
2657     int         loc_errno = h_errno;
2658
2659     WARN("h_errno %d.\n", loc_errno);
2660
2661     switch(loc_errno)
2662     {
2663         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
2664         case TRY_AGAIN:         return WSATRY_AGAIN;
2665         case NO_RECOVERY:       return WSANO_RECOVERY;
2666         case NO_DATA:           return WSANO_DATA; 
2667
2668         case 0:                 return 0;
2669         default:
2670                 WARN("Unknown h_errno %d!\n", loc_errno);
2671                 return WSAEOPNOTSUPP;
2672     }
2673 }