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