Release 970928
[wine] / misc / winsock.c
1 /*
2  * based on Windows Sockets 1.1 specs
3  * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4  * 
5  * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
6  *
7  * TODO: 32-bit asynchronous services.
8  */
9  
10 #include <stdio.h>
11 #include <string.h>
12 #include <signal.h>
13 #include <sys/types.h>
14 #include <sys/ipc.h>
15 #include <sys/ioctl.h>
16 #if defined(__svr4__)
17 #include <sys/filio.h>
18 #include <sys/ioccom.h>
19 #include <sys/sockio.h>
20 #endif
21 #if defined(__EMX__)
22 #include <sys/so_ioctl.h>
23 #include <sys/param.h>
24 #endif
25 #include <sys/msg.h>
26 #include <sys/wait.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <netdb.h>
33 #include <unistd.h>
34
35 #include "windows.h"
36 #include "winnt.h"
37 #include "heap.h"
38 #include "ldt.h"
39 #include "task.h"
40 #include "message.h"
41 #include "winsock.h"
42 #include "miscemu.h"
43 #include "stddebug.h"
44 #include "debug.h"
45
46 #define DEBUG_SOCKADDR 0
47 #define dump_sockaddr(a) \
48         fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
49                         ((struct sockaddr_in *)a)->sin_family, \
50                         inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
51                         ntohs(((struct sockaddr_in *)a)->sin_port))
52
53 #pragma pack(4)
54
55 /* ----------------------------------- internal data */
56
57 extern int h_errno;
58
59 static HANDLE32         _WSHeap = 0;
60 static unsigned char*   _ws_stub = NULL;
61 static LPWSINFO         _wsi_list = NULL;
62
63 #define WS_ALLOC(size) \
64         HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
65 #define WS_FREE(ptr) \
66         HeapFree(_WSHeap, 0, (ptr) )
67
68 #define WS_PTR2HANDLE(ptr) \
69         ((short)((int)(ptr) - (int)_ws_stub))
70 #define WS_HANDLE2PTR(handle) \
71         ((unsigned)((int)_ws_stub + (int)(handle)))
72
73 #define WSI_CHECK_RANGE(pwsi, pws) \
74         ( ((unsigned)(pws) > (unsigned)(pwsi)) && \
75           ((unsigned)(pws) < ((unsigned)(pwsi) + sizeof(WSINFO))) )
76
77 static INT32         _ws_sock_ops[] =
78        { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
79          WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
80          WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER, 0 };
81 static int           _px_sock_ops[] =
82        { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
83          SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
84          SO_LINGER };
85
86 static int _check_ws(LPWSINFO pwsi, ws_socket* pws);
87 static int _check_buffer(LPWSINFO pwsi, int size);
88
89 extern void EVENT_AddIO( int fd, unsigned flag );
90 extern void EVENT_DeleteIO( int fd, unsigned flag );
91
92 /***********************************************************************
93  *          convert_sockopt()
94  *
95  * Converts socket flags from Windows format.
96  */
97 static void convert_sockopt(INT32 *level, INT32 *optname)
98 {
99   int i;
100   switch (*level)
101   {
102      case WS_SOL_SOCKET:
103         *level = SOL_SOCKET;
104         for(i=0; _ws_sock_ops[i]; i++)
105             if( _ws_sock_ops[i] == *optname ) break;
106         if( _ws_sock_ops[i] ) *optname = _px_sock_ops[i];
107         else fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
108         break;
109      case WS_IPPROTO_TCP:
110         *optname = IPPROTO_TCP;
111   }
112 }
113
114 /* ----------------------------------- Per-thread info (or per-process?) */
115
116 static LPWSINFO wsi_find(HTASK16 hTask)
117
118     TDB*           pTask = (TDB*)GlobalLock16(hTask);
119     if( pTask )
120     {
121         if( pTask->pwsi ) return pTask->pwsi;
122         else
123         {
124             LPWSINFO pwsi = _wsi_list;
125             while( pwsi && pwsi->tid != hTask ) pwsi = pwsi->next;
126             if( pwsi )
127                 fprintf(stderr,"loose wsi struct! pwsi=0x%08x, task=0x%04x\n", 
128                                         (unsigned)pwsi, hTask );
129             return pwsi; 
130         }
131     }
132     return NULL;
133 }
134
135 static ws_socket* wsi_alloc_socket(LPWSINFO pwsi, int fd)
136 {
137     /* Initialize a new entry in the socket table */
138
139     if( pwsi->last_free >= 0 )
140     {
141         int i = pwsi->last_free;
142
143         pwsi->last_free = pwsi->sock[i].flags;  /* free list */
144         pwsi->sock[i].fd = fd;
145         pwsi->sock[i].flags = 0;
146         return &pwsi->sock[i];
147     }
148     return NULL;
149 }
150
151 static fd_set* fd_set_import( fd_set* fds, LPWSINFO pwsi, ws_fd_set* ws, int* highfd )
152 {
153     /* translate Winsock fd set into local fd set */
154
155     if( ws ) 
156     { 
157         int     i;
158         ws_socket*  pws;
159
160         FD_ZERO(fds);
161         for( i = 0; i < (ws->fd_count) ; i++ ) 
162         {
163             pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
164             if( _check_ws(pwsi, pws) ) 
165             {
166                 if( pws->fd > *highfd ) *highfd = pws->fd; 
167                 FD_SET(pws->fd, fds); 
168             }
169         }
170         return fds;
171     }
172     return NULL;
173 }
174
175 __inline__ static int sock_error_p(int s)
176 {
177     unsigned int optval, optlen;
178
179     optlen = sizeof(optval);
180     getsockopt(s, SOL_SOCKET, SO_ERROR, &optval, &optlen);
181     if (optval) dprintf_winsock(stddeb, "\t[%i] error: %d\n", s, optval);
182     return optval != 0;
183 }
184
185 static int fd_set_export( LPWSINFO pwsi, fd_set* fds, fd_set* exceptfds, ws_fd_set* ws )
186 {
187     int num_err = 0;
188
189     /* translate local fd set into Winsock fd set, adding
190      * errors to exceptfds (only if app requested it) */
191
192     if( ws )
193     {
194         int i, j, count = ws->fd_count;
195
196         for( i = 0, j = 0; i < count; i++ )
197         {
198             ws_socket *pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
199             int fd = pws->fd;
200
201             if( _check_ws(pwsi, pws) && FD_ISSET(fd, fds) )
202             {
203                 if ( exceptfds && sock_error_p(fd) )
204                 {
205                     FD_SET(fd, exceptfds);
206                     num_err++;
207                 }
208                 else
209                     ws->fd_array[j++] = ws->fd_array[i];
210             }
211         }
212         ws->fd_count = j;
213         dprintf_winsock(stddeb, "\n");
214     }
215     return num_err;
216 }
217
218 HANDLE16 __ws_gethandle( void* ptr )
219 {
220     return (HANDLE16)WS_PTR2HANDLE(ptr);
221 }
222
223 void* __ws_memalloc( int size )
224 {
225     return WS_ALLOC(size);
226 }
227
228 void __ws_memfree(void* ptr)
229 {
230     WS_FREE(ptr);
231 }
232
233 /* ----------------------------------- API ----- 
234  *
235  * Init / cleanup / error checking.
236  */
237
238 /***********************************************************************
239  *      WSAStartup16()                  (WINSOCK.115)
240  *
241  * Create socket control struct, attach it to the global list and
242  * update a pointer in the task struct.
243  */
244 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
245 {
246     WSADATA WINSOCK_data = { 0x0101, 0x0101,
247                           "WINE Sockets 1.1",
248                         #ifdef linux
249                                 "Linux/i386",
250                         #elif defined(__NetBSD__)
251                                 "NetBSD/i386",
252                         #elif defined(sunos)
253                                 "SunOS",
254                         #elif defined(__FreeBSD__)
255                                 "FreeBSD",
256                         #elif defined(__OpenBSD__)
257                                 "OpenBSD/i386",
258                         #else
259                                 "Unknown",
260                         #endif
261                            WS_MAX_SOCKETS_PER_THREAD,
262                            WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
263     HTASK16             tid = GetCurrentTask();
264     LPWSINFO            pwsi;
265
266     dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
267
268     if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
269         HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
270
271     if (!lpWSAData) return WSAEINVAL;
272
273     /* initialize socket heap */
274
275     if( !_ws_stub )
276     {
277         _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
278         if( !(_ws_stub = WS_ALLOC(0x10)) )
279         {
280             fprintf(stderr,"Fatal: failed to create WinSock heap\n");
281             return 0;
282         }
283     }
284     if( _WSHeap == 0 ) return WSASYSNOTREADY;
285
286     /* create socket array for this task */
287   
288     pwsi = wsi_find(GetCurrentTask());
289     if( pwsi == NULL )
290     {
291         TDB* pTask = (TDB*)GlobalLock16( tid );
292
293         if( (pwsi = (LPWSINFO)WS_ALLOC( sizeof(WSINFO))) )
294         {
295             int i = 0;
296             pwsi->tid = tid;
297             for( i = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++ )
298             {
299                 pwsi->sock[i].fd = -1; 
300                 pwsi->sock[i].flags = i + 1; 
301             }
302             pwsi->sock[WS_MAX_SOCKETS_PER_THREAD - 1].flags = -1;
303         }
304         else return WSASYSNOTREADY;
305
306         /* add this control struct to the global list */
307
308         pwsi->prev = NULL;
309         if( _wsi_list ) 
310             _wsi_list->prev = pwsi;
311         pwsi->next = _wsi_list; 
312         _wsi_list = pwsi;
313         pTask->pwsi = pwsi;
314     }
315     else pwsi->num_startup++;
316
317     /* return winsock information */
318
319     memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
320
321     dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
322     return 0;
323 }
324
325 /***********************************************************************
326  *      WSAStartup32()                  (WSOCK32.115)
327  */
328 INT32 WINAPI WSAStartup32(UINT32 wVersionRequested, LPWSADATA lpWSAData)
329 {
330     return WSAStartup16( wVersionRequested, lpWSAData );
331 }
332
333 /***********************************************************************
334  *      WSACleanup()                    (WINSOCK.116)
335  *
336  * Cleanup functions of varying impact.
337  */
338 void WINSOCK_Shutdown()
339 {
340     /* Called on exit(), has to remove all outstanding async DNS processes.  */
341
342     WINSOCK_cancel_task_aops( 0, __ws_memfree );
343 }
344
345 INT32 WINSOCK_DeleteTaskWSI( TDB* pTask, LPWSINFO pwsi )
346 {
347     /* WSACleanup() backend, called on task termination as well.
348      * Real DLL would have registered its own signal handler with
349      * TaskSetSignalHandler() and waited until USIG_TERMINATION/USIG_GPF
350      * but this scheme is much more straightforward.
351      */
352
353     int i, j, n;
354
355     if( --pwsi->num_startup > 0 ) return 0;
356
357     SIGNAL_MaskAsyncEvents( TRUE );
358     if( pTask ) 
359         pTask->pwsi = NULL;
360     WINSOCK_cancel_task_aops( pTask->hSelf, __ws_memfree );
361     SIGNAL_MaskAsyncEvents( FALSE );
362
363     /* unlink socket control struct */
364
365     if( pwsi == _wsi_list ) 
366         _wsi_list = pwsi->next;
367     else
368         pwsi->prev->next = pwsi->next;
369     if( pwsi->next ) pwsi->next->prev = pwsi->prev; 
370
371     if( _wsi_list == NULL ) 
372         WINSOCK_Shutdown();     /* just in case */
373
374     if( pwsi->flags & WSI_BLOCKINGCALL )
375         dprintf_winsock(stddeb,"\tinside blocking call!\n");
376
377 /* FIXME: aop_control() doesn't decrement pwsi->num_async_rq
378  *
379  *    if( pwsi->num_async_rq )
380  *        dprintf_winsock(stddeb,"\thave %i outstanding async ops!\n", pwsi->num_async_rq );
381  */
382
383     for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++)
384         if( pwsi->sock[i].fd != -1 )
385         {
386             if( pwsi->sock[i].psop )
387             {
388                 n++;
389                 WSAAsyncSelect( (SOCKET16)WS_PTR2HANDLE(pwsi->sock + i), 0, 0, 0 );
390             }
391             close(pwsi->sock[i].fd); j++; 
392         }
393     if( j ) 
394           dprintf_winsock(stddeb,"\tclosed %i sockets, killed %i async selects!\n", j, n);
395
396     /* delete scratch buffers */
397
398     if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer);
399     if( pwsi->dbuffer ) SEGPTR_FREE(pwsi->dbuffer);
400         
401     memset( pwsi, 0, sizeof(WSINFO) );
402     WS_FREE(pwsi);
403     return 0;
404 }
405
406 INT32 WINAPI WSACleanup(void)
407 {
408     HTASK16     hTask = GetCurrentTask();
409
410     dprintf_winsock(stddeb, "WSACleanup(%04x)\n", hTask );
411     if( hTask )
412     {
413         LPWSINFO pwsi = wsi_find(hTask);
414         if( pwsi )
415             return WINSOCK_DeleteTaskWSI( (TDB*)GlobalLock16(hTask), pwsi );
416         return SOCKET_ERROR;
417     }
418     else
419         WINSOCK_Shutdown(); /* remove all outstanding DNS requests */
420     return 0;
421 }
422
423
424 /***********************************************************************
425  *      WSAGetLastError()               (WSOCK32.111)(WINSOCK.111)
426  */
427 INT32 WINAPI WSAGetLastError(void)
428 {
429     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
430     INT16               ret;
431
432     dprintf_winsock(stddeb, "WSAGetLastError(%08x)", (unsigned)pwsi);
433
434     ret = (pwsi) ? pwsi->err : WSANOTINITIALISED;
435
436     dprintf_winsock(stddeb, " = %i\n", (int)ret);
437     return ret;
438 }
439
440 /***********************************************************************
441  *      WSASetLastError32()             (WSOCK32.112)
442  */
443 void WINAPI WSASetLastError32(INT32 iError)
444 {
445     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
446
447     dprintf_winsock(stddeb, "WSASetLastError(%08x): %d\n", (unsigned)pwsi, (int)iError);
448     if( pwsi ) pwsi->err = iError;
449 }
450
451 /***********************************************************************
452  *      WSASetLastError16()             (WINSOCK.112)
453  */
454 void WINAPI WSASetLastError16(INT16 iError)
455 {
456     WSASetLastError32(iError);
457 }
458
459 int _check_ws(LPWSINFO pwsi, ws_socket* pws)
460 {
461     if( pwsi )
462         if( pwsi->flags & WSI_BLOCKINGCALL ) pwsi->err = WSAEINPROGRESS;
463         else if( WSI_CHECK_RANGE(pwsi, pws) ) return 1;
464                  else pwsi->err = WSAENOTSOCK;
465     return 0;
466 }
467
468 int _check_buffer(LPWSINFO pwsi, int size)
469 {
470     if( pwsi->buffer && pwsi->buflen >= size ) return 1;
471     else SEGPTR_FREE(pwsi->buffer);
472
473     pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size)); 
474     return (pwsi->buffer != NULL);
475 }
476
477 /* ----------------------------------- i/o APIs */
478
479 /***********************************************************************
480  *              accept()                (WSOCK32.1)
481  */
482 SOCKET32 WINAPI WINSOCK_accept32(SOCKET32 s, struct sockaddr *addr,
483                                  INT32 *addrlen32)
484 {
485     ws_socket*  pws  = (ws_socket*)WS_HANDLE2PTR((SOCKET16)s);
486     LPWSINFO    pwsi = wsi_find(GetCurrentTask());
487
488     dprintf_winsock(stddeb, "WS_ACCEPT(%08x): socket %04x\n", 
489                                   (unsigned)pwsi, (UINT16)s ); 
490     if( _check_ws(pwsi, pws) )
491     {
492         int     sock, fd_flags;
493
494         fd_flags = fcntl(pws->fd, F_GETFL, 0);
495
496         if( (sock = accept(pws->fd, addr, addrlen32)) >= 0 )
497         {
498             ws_socket*  pnew = wsi_alloc_socket(pwsi, sock); 
499             if( pnew )
500             {
501                 s = (SOCKET32)WS_PTR2HANDLE(pnew);
502                 if( pws->psop && pws->flags & WS_FD_ACCEPT )
503                 {
504                     EVENT_AddIO( pws->fd, EVENT_IO_READ );      /* reenabler */
505
506                     /* async select the accept()'ed socket */
507                     WSAAsyncSelect( s, pws->psop->hWnd, pws->psop->uMsg,
508                                     pws->flags & ~WS_FD_ACCEPT );
509                 }
510                 return s;
511             } 
512             else pwsi->err = WSAENOBUFS;
513         } 
514         else pwsi->err = wsaErrno();
515     }
516     return INVALID_SOCKET32;
517 }
518
519 /***********************************************************************
520  *              accept()                (WINSOCK.1)
521  */
522 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
523                                  INT16* addrlen16 )
524 {
525     INT32 addrlen32 = addrlen16 ? *addrlen16 : 0;
526     SOCKET32 retSocket = WINSOCK_accept32( s, addr, &addrlen32 );
527     if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
528     return (SOCKET16)retSocket;
529 }
530
531 /***********************************************************************
532  *              bind()                  (WSOCK32.2)
533  */
534 INT32 WINAPI WINSOCK_bind32(SOCKET32 s, struct sockaddr *name, INT32 namelen)
535 {
536     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
537     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
538
539     dprintf_winsock(stddeb, "WS_BIND(%08x): socket %04x, ptr %8x, length %d\n", 
540                            (unsigned)pwsi, s, (int) name, namelen);
541 #if DEBUG_SOCKADDR
542     dump_sockaddr(name);
543 #endif
544
545     if ( _check_ws(pwsi, pws) )
546       if ( namelen >= sizeof(*name) ) 
547         if ( ((struct sockaddr_in *)name)->sin_family == AF_INET )
548           if ( bind(pws->fd, name, namelen) < 0 ) 
549           {
550              int        loc_errno = errno;
551              dprintf_winsock(stddeb,"\tfailure - errno = %i\n", errno);
552              errno = loc_errno;
553              switch(errno)
554              {
555                 case EBADF: pwsi->err = WSAENOTSOCK; break;
556                 case EADDRNOTAVAIL: pwsi->err = WSAEINVAL; break;
557                 default: pwsi->err = wsaErrno();
558              }
559           }
560           else return 0; /* success */
561         else pwsi->err = WSAEAFNOSUPPORT;
562       else pwsi->err = WSAEFAULT;
563     return SOCKET_ERROR;
564 }
565
566 /***********************************************************************
567  *              bind()                  (WINSOCK.2)
568  */
569 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
570 {
571   return (INT16)WINSOCK_bind32( s, name, namelen );
572 }
573
574 /***********************************************************************
575  *              closesocket()           (WSOCK32.3)
576  */
577 INT32 WINAPI WINSOCK_closesocket32(SOCKET32 s)
578 {
579     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
580     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
581
582     dprintf_winsock(stddeb, "WS_CLOSE(%08x): socket %08x\n", (unsigned)pwsi, s);
583
584     if( _check_ws(pwsi, pws) )
585     { 
586         int     fd = pws->fd;
587
588         if( pws->psop ) WSAAsyncSelect( s, 0, 0, 0 );
589
590         pws->fd = -1;
591         pws->flags = (unsigned)pwsi->last_free;
592         pwsi->last_free = pws - &pwsi->sock[0]; /* add to free list */
593
594         if( close(fd) == 0 ) 
595             return 0;
596         pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
597     }
598     return SOCKET_ERROR;
599 }
600
601 /***********************************************************************
602  *              closesocket()           (WINSOCK.3)
603  */
604 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
605 {
606     return (INT16)WINSOCK_closesocket32(s);
607 }
608
609 /***********************************************************************
610  *              connect()               (WSOCK32.4)
611  */
612 INT32 WINAPI WINSOCK_connect32(SOCKET32 s, struct sockaddr *name, INT32 namelen)
613 {
614   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
615   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
616
617   dprintf_winsock(stddeb, "WS_CONNECT(%08x): socket %04x, ptr %8x, length %d\n", 
618                            (unsigned)pwsi, s, (int) name, namelen);
619 #if DEBUG_SOCKADDR
620   dump_sockaddr(name);
621 #endif
622
623   if( _check_ws(pwsi, pws) )
624   {
625     if (connect(pws->fd, name, namelen) == 0) 
626     { 
627         if( pws->psop && (pws->flags & WS_FD_CONNECT) )
628         {
629             /* application did AsyncSelect() but then went
630              * ahead and called connect() without waiting for 
631              * notification.
632              */
633
634             if( !(pws->flags & WS_FD_CONNECTED) )
635             {
636                 if( pws->flags & (WS_FD_READ | WS_FD_CLOSE) )
637                     EVENT_AddIO( pws->fd, EVENT_IO_READ );
638                 else
639                     EVENT_DeleteIO( pws->fd, EVENT_IO_READ );
640                 if( pws->flags & WS_FD_WRITE )
641                     EVENT_AddIO( pws->fd, EVENT_IO_WRITE );
642                 else
643                     EVENT_DeleteIO( pws->fd, EVENT_IO_WRITE );
644                 pws->flags |= WS_FD_CONNECTED;
645             }
646         }
647         pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT);
648         return 0; 
649     }
650     pwsi->err = (errno == EINPROGRESS) ? WSAEWOULDBLOCK : wsaErrno();
651   }
652   return SOCKET_ERROR;
653 }
654
655 /***********************************************************************
656  *              connect()               (WINSOCK.4)
657  */
658 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
659 {
660   return (INT16)WINSOCK_connect32( s, name, namelen );
661 }
662
663 /***********************************************************************
664  *              getpeername()           (WSOCK32.5)
665  */
666 INT32 WINAPI WINSOCK_getpeername32(SOCKET32 s, struct sockaddr *name,
667                                    INT32 *namelen)
668 {
669     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
670     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
671
672     dprintf_winsock(stddeb, "WS_GETPEERNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
673                            (unsigned)pwsi, s, (int) name, *namelen);
674     if( _check_ws(pwsi, pws) )
675     {
676         if (getpeername(pws->fd, name, namelen) == 0) 
677             return 0; 
678         pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
679     }
680     return SOCKET_ERROR;
681 }
682
683 /***********************************************************************
684  *              getpeername()           (WINSOCK.5)
685  */
686 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
687                                    INT16 *namelen16)
688 {
689     INT32 namelen32 = *namelen16;
690     INT32 retVal = WINSOCK_getpeername32( s, name, &namelen32 );
691
692 #if DEBUG_SOCKADDR
693     dump_sockaddr(name);
694 #endif
695
696    *namelen16 = namelen32;
697     return (INT16)retVal;
698 }
699
700 /***********************************************************************
701  *              getsockname()           (WSOCK32.6)
702  */
703 INT32 WINAPI WINSOCK_getsockname32(SOCKET32 s, struct sockaddr *name,
704                                    INT32 *namelen)
705 {
706     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
707     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
708
709     dprintf_winsock(stddeb, "WS_GETSOCKNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
710                           (unsigned)pwsi, s, (int) name, (int) *namelen);
711     if( _check_ws(pwsi, pws) )
712     {
713         if (getsockname(pws->fd, name, namelen) == 0)
714             return 0; 
715         pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
716     }
717     return SOCKET_ERROR;
718 }
719
720 /***********************************************************************
721  *              getsockname()           (WINSOCK.6)
722  */
723 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
724                                    INT16 *namelen16)
725 {
726     INT32 retVal;
727
728     if( namelen16 )
729     {
730         INT32 namelen32 = *namelen16;
731         retVal = WINSOCK_getsockname32( s, name, &namelen32 );
732        *namelen16 = namelen32;
733
734 #if DEBUG_SOCKADDR
735     dump_sockaddr(name);
736 #endif
737
738     }
739     else retVal = SOCKET_ERROR;
740     return (INT16)retVal;
741 }
742
743
744 /***********************************************************************
745  *              getsockopt()            (WSOCK32.7)
746  */
747 INT32 WINAPI WINSOCK_getsockopt32(SOCKET32 s, INT32 level, 
748                                   INT32 optname, char *optval, INT32 *optlen)
749 {
750     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
751     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
752
753     dprintf_winsock(stddeb, "WS_GETSOCKOPT(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n", 
754                            (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
755     if( _check_ws(pwsi, pws) )
756     {
757         convert_sockopt(&level, &optname);
758         if (getsockopt(pws->fd, (int) level, optname, optval, optlen) == 0 )
759             return 0;
760         pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
761     }
762     return SOCKET_ERROR;
763 }
764
765 /***********************************************************************
766  *              getsockopt()            (WINSOCK.7)
767  */
768 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
769                                   INT16 optname, char *optval, INT16 *optlen)
770 {
771     INT32 optlen32;
772     INT32 *p = &optlen32;
773     INT32 retVal;
774     if( optlen ) optlen32 = *optlen; else p = NULL;
775     retVal = WINSOCK_getsockopt32( s, level, optname, optval, p );
776     if( optlen ) *optlen = optlen32;
777     return (INT16)retVal;
778 }
779
780 /***********************************************************************
781  *              htonl()                 (WINSOCK.8)(WSOCK32.8)
782  */
783 u_long WINAPI WINSOCK_htonl(u_long hostlong)   { return( htonl(hostlong) ); }
784 /***********************************************************************
785  *              htons()                 (WINSOCK.9)(WSOCK32.9)
786  */
787 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
788 /***********************************************************************
789  *              inet_addr()             (WINSOCK.10)
790  */
791 u_long WINAPI WINSOCK_inet_addr(char *cp)      { return( inet_addr(cp) ); }
792 /***********************************************************************
793  *              htohl()                 (WINSOCK.14)(WSOCK32.14)
794  */
795 u_long WINAPI WINSOCK_ntohl(u_long netlong)    { return( ntohl(netlong) ); }
796 /***********************************************************************
797  *              ntohs()                 (WINSOCK.15)(WSOCK32.15)
798  */
799 u_short WINAPI WINSOCK_ntohs(u_short netshort)  { return( ntohs(netshort) ); }
800
801 /***********************************************************************
802  *              inet_ntoa()             (WINSOCK.11)
803  */
804 SEGPTR WINAPI WINSOCK_inet_ntoa(struct in_addr in)
805 {
806   /* use "buffer for dummies" here because some applications have 
807    * propensity to decode addresses in ws_hostent structure without 
808    * saving them first...
809    */
810
811   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
812
813   if( pwsi )
814   {
815     char*       s = inet_ntoa(in);
816     if( s ) 
817     {
818         if( pwsi->dbuffer == NULL )
819             if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(32)) == NULL )
820             {
821                 pwsi->err = WSAENOBUFS;
822                 return (SEGPTR)NULL;
823             }
824         strncpy(pwsi->dbuffer, s, 32 );
825         return SEGPTR_GET(pwsi->dbuffer); 
826     }
827     pwsi->err = wsaErrno();
828   }
829   return (SEGPTR)NULL;
830 }
831
832 /***********************************************************************
833  *              ioctlsocket()           (WSOCK32.12)
834  */
835 INT32 WINAPI WINSOCK_ioctlsocket32(SOCKET32 s, UINT32 cmd, UINT32 *argp)
836 {
837   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
838   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
839
840   dprintf_winsock(stddeb, "WS_IOCTL(%08x): socket %04x, cmd %08x, ptr %8x\n", 
841                           (unsigned)pwsi, s, cmd, (unsigned) argp);
842   if( _check_ws(pwsi, pws) )
843   {
844     long        newcmd  = cmd;
845
846     switch( cmd )
847     {
848         case WS_FIONREAD:   
849                 newcmd=FIONREAD; 
850                 break;
851
852         case WS_FIONBIO:    
853                 newcmd=FIONBIO;  
854                 if( pws->psop && *argp == 0 ) 
855                 {
856                     /* AsyncSelect()'ed sockets are always nonblocking */
857                     pwsi->err = WSAEINVAL; 
858                     return SOCKET_ERROR; 
859                 }
860                 break;
861
862         case WS_SIOCATMARK: 
863                 newcmd=SIOCATMARK; 
864                 break;
865
866         case WS_IOW('f',125,u_long): 
867                 fprintf(stderr,"Warning: WS1.1 shouldn't be using async I/O\n");
868                 pwsi->err = WSAEINVAL; 
869                 return SOCKET_ERROR;
870
871         default:          
872                 /* Netscape tries hard to use bogus ioctl 0x667e */
873                 dprintf_winsock(stddeb,"\tunknown WS_IOCTL cmd (%08x)\n", cmd);
874     }
875     if( ioctl(pws->fd, newcmd, (char*)argp ) == 0 ) return 0;
876     pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno(); 
877   }
878   return SOCKET_ERROR;
879 }
880
881 /***********************************************************************
882  *              ioctlsocket()           (WINSOCK.12)
883  */
884 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, UINT32 cmd, UINT32 *argp)
885 {
886     return (INT16)WINSOCK_ioctlsocket32( s, cmd, argp );
887 }
888
889
890 /***********************************************************************
891  *              listen()                (WSOCK32.13)
892  */
893 INT32 WINAPI WINSOCK_listen32(SOCKET32 s, INT32 backlog)
894 {
895     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
896     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
897
898     dprintf_winsock(stddeb, "WS_LISTEN(%08x): socket %04x, backlog %d\n", 
899                             (unsigned)pwsi, s, backlog);
900     if( _check_ws(pwsi, pws) )
901     {
902         if( !pws->psop )
903         {
904             int  fd_flags = fcntl(pws->fd, F_GETFL, 0);
905             if( !(fd_flags & O_NONBLOCK) ) pws->flags |= WS_FD_ACCEPT;
906         }
907         else if( !(pws->flags & WS_FD_CONNECTED) ) pws->flags |= WS_FD_LISTENING;
908
909         if (listen(pws->fd, backlog) == 0) return 0;
910         pwsi->err = wsaErrno();
911     }
912     else if( pwsi ) pwsi->err = WSAENOTSOCK;
913     return SOCKET_ERROR;
914 }
915
916 /***********************************************************************
917  *              listen()                (WINSOCK.13)
918  */
919 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
920 {
921     return (INT16)WINSOCK_listen32( s, backlog );
922 }
923
924
925 /***********************************************************************
926  *              recv()                  (WSOCK32.16)
927  */
928 INT32 WINAPI WINSOCK_recv32(SOCKET32 s, char *buf, INT32 len, INT32 flags)
929 {
930     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
931     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
932
933     dprintf_winsock(stddeb, "WS_RECV(%08x): socket %04x, buf %8x, len %d, flags %d",
934                           (unsigned)pwsi, s, (unsigned)buf, len, flags);
935     if( _check_ws(pwsi, pws) )
936     {
937         INT32 length;
938         if ((length = recv(pws->fd, buf, len, flags)) >= 0) 
939         { 
940             dprintf_winsock(stddeb, " -> %i bytes\n", length);
941
942             if( pws->psop && (pws->flags & (WS_FD_READ | WS_FD_CLOSE)) )
943                 EVENT_AddIO( pws->fd, EVENT_IO_READ );  /* reenabler */
944
945             return length;
946         }
947         pwsi->err = wsaErrno();
948     }
949     else if( pwsi ) pwsi->err = WSAENOTSOCK;
950     dprintf_winsock(stddeb, " -> ERROR\n");
951     return SOCKET_ERROR;
952 }
953
954 /***********************************************************************
955  *              recv()                  (WINSOCK.16)
956  */
957 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
958 {
959     return (INT16)WINSOCK_recv32( s, buf, len, flags );
960 }
961
962
963 /***********************************************************************
964  *              recvfrom()              (WSOCK32.17)
965  */
966 INT32 WINAPI WINSOCK_recvfrom32(SOCKET32 s, char *buf, INT32 len, INT32 flags, 
967                                 struct sockaddr *from, INT32 *fromlen32)
968 {
969     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
970     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
971
972     dprintf_winsock(stddeb, "WS_RECVFROM(%08x): socket %04x, ptr %08x, len %d, flags %d",
973                           (unsigned)pwsi, s, (unsigned)buf, len, flags);
974 #if DEBUG_SOCKADDR
975     if( from ) dump_sockaddr(from);
976     else fprintf(stderr, "\tfrom = NULL\n");
977 #endif
978
979     if( _check_ws(pwsi, pws) )
980     {
981         int length;
982
983         if ((length = recvfrom(pws->fd, buf, len, flags, from, fromlen32)) >= 0)
984         {
985             dprintf_winsock(stddeb, " -> %i bytes\n", length);
986
987             if( pws->psop && (pws->flags & (WS_FD_READ | WS_FD_CLOSE)) )
988                 EVENT_AddIO( pws->fd, EVENT_IO_READ );  /* reenabler */
989
990             return (INT16)length;
991         }
992         pwsi->err = wsaErrno();
993     }
994     else if( pwsi ) pwsi->err = WSAENOTSOCK;
995     dprintf_winsock(stddeb, " -> ERROR\n");
996     return SOCKET_ERROR;
997 }
998
999 /***********************************************************************
1000  *              recvfrom()              (WINSOCK.17)
1001  */
1002 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1003                                 struct sockaddr *from, INT16 *fromlen16)
1004 {
1005     INT32 fromlen32;
1006     INT32 *p = &fromlen32;
1007     INT32 retVal;
1008
1009     if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1010     retVal = WINSOCK_recvfrom32( s, buf, len, flags, from, p );
1011     if( fromlen16 ) *fromlen16 = fromlen32;
1012     return (INT16)retVal;
1013 }
1014
1015 /***********************************************************************
1016  *              select()                (WINSOCK.18)
1017  */
1018 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set *ws_readfds,
1019                               ws_fd_set *ws_writefds, ws_fd_set *ws_exceptfds,
1020                               struct timeval *timeout)
1021 {
1022     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
1023         
1024     dprintf_winsock(stddeb, "WS_SELECT(%08x): nfds %d (ignored), read %8x, write %8x, excp %8x\n", 
1025     (unsigned) pwsi, nfds, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
1026
1027     if( pwsi )
1028     {
1029         int         highfd = 0;
1030         fd_set      readfds, writefds, exceptfds;
1031         fd_set     *p_read, *p_write, *p_except;
1032
1033         p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd);
1034         p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd);
1035         p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd);
1036
1037         if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) >= 0 )
1038         {
1039             if( highfd )
1040             {
1041                 fd_set_export(pwsi, &readfds, p_except, ws_readfds);
1042                 fd_set_export(pwsi, &writefds, p_except, ws_writefds);
1043
1044                 if (p_except && ws_exceptfds)
1045                 {
1046                     int i, j, count = ws_exceptfds->fd_count;
1047
1048                     for (i = j = 0; i < count; i++)
1049                     {
1050                         ws_socket *pws = (ws_socket *)WS_HANDLE2PTR(ws_exceptfds->fd_array[i]);
1051                         if( _check_ws(pwsi, pws) && FD_ISSET(pws->fd, &exceptfds) )
1052                             ws_exceptfds->fd_array[j++] = ws_exceptfds->fd_array[i];
1053                     }
1054                     ws_exceptfds->fd_count = j;
1055                 }
1056             }
1057             return highfd; 
1058         }
1059         pwsi->err = wsaErrno();
1060     } 
1061     return SOCKET_ERROR;
1062 }
1063
1064 /***********************************************************************
1065  *              select()                (WSOCK32.18)
1066  */
1067 INT32 WINAPI WINSOCK_select32(INT32 nfds, ws_fd_set *ws_readfds,
1068                               ws_fd_set *ws_writefds, ws_fd_set *ws_exceptfds,
1069                               struct timeval *timeout)
1070 {
1071     /* struct timeval is the same for both 32- and 16-bit code */
1072     return WINSOCK_select16( (INT16)nfds, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1073 }
1074
1075
1076 /***********************************************************************
1077  *              send()                  (WSOCK32.19)
1078  */
1079 INT32 WINAPI WINSOCK_send32(SOCKET32 s, char *buf, INT32 len, INT32 flags)
1080 {
1081     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
1082     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
1083
1084     dprintf_winsock(stddeb, "WS_SEND(%08x): socket %04x, ptr %08x, length %d, flags %d\n", 
1085                           (unsigned)pwsi, s, (unsigned) buf, len, flags);
1086     if( _check_ws(pwsi, pws) )
1087     {
1088         int     length;
1089
1090         if ((length = send(pws->fd, buf, len, flags)) < 0 ) 
1091         {
1092             pwsi->err = wsaErrno();
1093             if( pwsi->err == WSAEWOULDBLOCK && 
1094                 pws->psop && pws->flags & WS_FD_WRITE )
1095                 EVENT_AddIO( pws->fd, EVENT_IO_WRITE ); /* reenabler */
1096         }
1097         else return (INT16)length;
1098     }
1099     else if( pwsi ) pwsi->err = WSAENOTSOCK;
1100     return SOCKET_ERROR;
1101 }
1102
1103 /***********************************************************************
1104  *              send()                  (WINSOCK.19)
1105  */
1106 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1107 {
1108     return WINSOCK_send32( s, buf, len, flags );
1109 }
1110
1111 /***********************************************************************
1112  *              sendto()                (WSOCK32.20)
1113  */
1114 INT32 WINAPI WINSOCK_sendto32(SOCKET32 s, char *buf, INT32 len, INT32 flags,
1115                               struct sockaddr *to, INT32 tolen)
1116 {
1117     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
1118     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
1119
1120     dprintf_winsock(stddeb, "WS_SENDTO(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1121                           (unsigned)pwsi, s, (unsigned) buf, len, flags);
1122     if( _check_ws(pwsi, pws) )
1123     {
1124         INT32   length;
1125
1126         if ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 )
1127         {
1128             pwsi->err = wsaErrno();
1129             if( pwsi->err == WSAEWOULDBLOCK &&
1130                 pws->psop && pws->flags & WS_FD_WRITE )
1131                 EVENT_AddIO( pws->fd, EVENT_IO_WRITE ); /* reenabler */
1132         } 
1133         else return length;
1134     }
1135     else if( pwsi ) pwsi->err = WSAENOTSOCK;
1136     return SOCKET_ERROR;
1137 }
1138
1139 /***********************************************************************
1140  *              sendto()                (WINSOCK.20)
1141  */
1142 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1143                               struct sockaddr *to, INT16 tolen)
1144 {
1145     return (INT16)WINSOCK_sendto32( s, buf, len, flags, to, tolen );
1146 }
1147
1148 /***********************************************************************
1149  *              setsockopt()            (WSOCK32.21)
1150  */
1151 INT32 WINAPI WINSOCK_setsockopt32(SOCKET16 s, INT32 level, INT32 optname, 
1152                                   char *optval, INT32 optlen)
1153 {
1154     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
1155     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
1156
1157     dprintf_winsock(stddeb, "WS_SETSOCKOPT(%08x): socket %04x, lev %d, opt %d, ptr %08x, len %d\n",
1158                           (unsigned)pwsi, s, level, optname, (int) optval, optlen);
1159     if( _check_ws(pwsi, pws) )
1160     {
1161         convert_sockopt(&level, &optname);
1162         if (setsockopt(pws->fd, level, optname, optval, optlen) == 0) return 0;
1163         pwsi->err = wsaErrno();
1164     }
1165     else if( pwsi ) pwsi->err = WSAENOTSOCK;
1166     return SOCKET_ERROR;
1167 }
1168
1169 /***********************************************************************
1170  *              setsockopt()            (WINSOCK.21)
1171  */
1172 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
1173                                   char *optval, INT16 optlen)
1174 {
1175     INT32 linger32[2];
1176     if( !optval ) return SOCKET_ERROR;
1177     if( optname == SO_LINGER )
1178     {
1179         INT16* ptr = (INT16*)optval;
1180         linger32[0] = ptr[0];
1181         linger32[1] = ptr[1];
1182         optval = (char*)&linger32;
1183         optlen = sizeof(linger32);
1184     }
1185     return (INT16)WINSOCK_setsockopt32( s, level, optname, optval, optlen );
1186 }
1187
1188
1189 /***********************************************************************
1190  *              shutdown()              (WSOCK32.22)
1191  */
1192 INT32 WINAPI WINSOCK_shutdown32(SOCKET32 s, INT32 how)
1193 {
1194     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
1195     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
1196
1197     dprintf_winsock(stddeb, "WS_SHUTDOWN(%08x): socket %04x, how %i\n",
1198                             (unsigned)pwsi, s, how );
1199     if( _check_ws(pwsi, pws) )
1200     {
1201         if( pws->psop )
1202             switch( how )
1203             {
1204                 case 0: /* drop receives */
1205                         if( pws->flags & (WS_FD_READ | WS_FD_CLOSE) )
1206                             EVENT_DeleteIO( pws->fd, EVENT_IO_READ );
1207                         pws->flags &= ~(WS_FD_READ | WS_FD_CLOSE);
1208                         break;
1209
1210                 case 1: /* drop sends */
1211                         if( pws->flags & WS_FD_WRITE )
1212                             EVENT_DeleteIO( pws->fd, EVENT_IO_WRITE );
1213                         pws->flags &= ~WS_FD_WRITE;
1214                         break;
1215
1216                 case 2: /* drop all */
1217                 default:
1218                         WSAAsyncSelect( s, 0, 0, 0 );
1219                         break;
1220             }
1221
1222         if (shutdown(pws->fd, how) == 0) 
1223         {
1224             if( how > 1 ) 
1225             {
1226                 pws->flags &= ~(WS_FD_CONNECTED | WS_FD_LISTENING);
1227                 pws->flags |= WS_FD_INACTIVE;
1228             }
1229             return 0;
1230         }
1231         pwsi->err = wsaErrno();
1232     } 
1233     else if( pwsi ) pwsi->err = WSAENOTSOCK;
1234     return SOCKET_ERROR;
1235 }
1236
1237 /***********************************************************************
1238  *              shutdown()              (WINSOCK.22)
1239  */
1240 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
1241 {
1242     return (INT16)WINSOCK_shutdown32( s, how );
1243 }
1244
1245
1246 /***********************************************************************
1247  *              socket()                (WSOCK32.23)
1248  */
1249 SOCKET32 WINAPI WINSOCK_socket32(INT32 af, INT32 type, INT32 protocol)
1250 {
1251   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
1252
1253   dprintf_winsock(stddeb, "WS_SOCKET(%08x): af=%d type=%d protocol=%d\n", 
1254                           (unsigned)pwsi, af, type, protocol);
1255
1256   if( pwsi )
1257   {
1258     int         sock;
1259
1260     /* check the socket family */
1261     switch(af) 
1262     {
1263         case AF_INET:
1264         case AF_UNSPEC: break;
1265         default:        pwsi->err = WSAEAFNOSUPPORT; 
1266                         return INVALID_SOCKET32;
1267     }
1268
1269     /* check the socket type */
1270     switch(type) 
1271     {
1272         case SOCK_STREAM:
1273         case SOCK_DGRAM:
1274         case SOCK_RAW:  break;
1275         default:        pwsi->err = WSAESOCKTNOSUPPORT; 
1276                         return INVALID_SOCKET32;
1277     }
1278
1279     /* check the protocol type */
1280     if ( protocol < 0 )  /* don't support negative values */
1281     { pwsi->err = WSAEPROTONOSUPPORT; return INVALID_SOCKET32; }
1282
1283     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
1284         switch(protocol) 
1285         {
1286           case IPPROTO_TCP:
1287              if (type == SOCK_STREAM) { af = AF_INET; break; }
1288           case IPPROTO_UDP:
1289              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
1290           default: pwsi->err = WSAEPROTOTYPE; return INVALID_SOCKET32;
1291         }
1292
1293     if ((sock = socket(af, type, protocol)) >= 0) 
1294     {
1295         ws_socket*      pnew = wsi_alloc_socket(pwsi, sock);
1296
1297         dprintf_winsock(stddeb,"\tcreated %04x (handle %i)\n", sock, (UINT16)WS_PTR2HANDLE(pnew));
1298
1299         if( pnew ) return (SOCKET16)WS_PTR2HANDLE(pnew);
1300         
1301         close(sock);
1302         pwsi->err = WSAENOBUFS;
1303         return INVALID_SOCKET32;
1304     }
1305
1306     if (errno == EPERM) /* raw socket denied */
1307     {
1308         fprintf(stderr, "WS_SOCKET: not enough privileges\n");
1309         pwsi->err = WSAESOCKTNOSUPPORT;
1310     } else pwsi->err = wsaErrno();
1311   }
1312  
1313   dprintf_winsock(stddeb, "\t\tfailed!\n");
1314   return INVALID_SOCKET32;
1315 }
1316
1317 /***********************************************************************
1318  *              socket()                (WINSOCK.23)
1319  */
1320 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
1321 {
1322     return (SOCKET16)WINSOCK_socket32( af, type, protocol );
1323 }
1324     
1325
1326 /* ----------------------------------- DNS services
1327  *
1328  * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
1329  * Also, we have to use wsock32 stubs to convert error codes from Unix
1330  * to WSA, hence no direct mapping in if1632/wsock32.spec.
1331  *
1332  * FIXME: Win32 may need "short" h_addrtype and h_length in
1333  * ...ent structures. If so, use WS_dup_...(pwsi, ..., 0) to
1334  * convert.
1335  */
1336
1337 static char*    NULL_STRING = "NULL";
1338
1339
1340 /***********************************************************************
1341  *              gethostbyaddr()         (WINSOCK.51)
1342  *
1343  *
1344 struct WIN_hostent *
1345  */
1346 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
1347 {
1348     LPWSINFO            pwsi = wsi_find(GetCurrentTask());
1349
1350     dprintf_winsock(stddeb, "WS_GetHostByAddr16(%08x): ptr %8x, len %d, type %d\n", 
1351                           (unsigned)pwsi, (unsigned) addr, len, type);
1352     if( pwsi )
1353     {
1354         struct hostent* host = gethostbyaddr(addr, len, type);
1355         if( host )
1356             if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
1357                 return SEGPTR_GET(pwsi->buffer);
1358             else 
1359                 pwsi->err = WSAENOBUFS;
1360         else 
1361             pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1362     }
1363     return (SEGPTR)NULL;
1364 }
1365
1366 /***********************************************************************
1367  *              gethostbyaddr()         (WSOCK32.51)
1368  */
1369 struct hostent*  WINAPI WINSOCK_gethostbyaddr32(const char *addr, INT32 len,
1370                                                 INT32 type)
1371 {
1372     LPWSINFO            pwsi = wsi_find(GetCurrentTask());
1373
1374     dprintf_winsock(stddeb, "WS_GetHostByAddr32(%08x): ptr %8x, len %d, type %d\n",
1375                             (unsigned)pwsi, (unsigned) addr, len, type);
1376     if( pwsi )
1377     {
1378         struct hostent* host = gethostbyaddr( addr, len, type );
1379         if( host ) 
1380             return host;
1381         pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1382     }
1383     return NULL;
1384 }
1385
1386 /***********************************************************************
1387  *              gethostbyname()         (WINSOCK.52) 
1388  *
1389  *
1390 struct WIN_hostent *
1391  */
1392 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
1393 {
1394     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1395
1396     dprintf_winsock(stddeb, "WS_GetHostByName16(%08x): %s\n",
1397                           (unsigned)pwsi, (name)?name:"NULL");
1398     if( pwsi )
1399     {
1400         struct hostent*     host;
1401         if( (host = gethostbyname(name)) != NULL )
1402             if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
1403                 return SEGPTR_GET(pwsi->buffer);
1404             else pwsi->err = WSAENOBUFS;
1405         else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1406   }
1407   return (SEGPTR)NULL;
1408 }
1409
1410 /***********************************************************************
1411  *              gethostbyname()         (WSOCK32,52)
1412  */
1413 struct hostent*  WINAPI WINSOCK_gethostbyname32(const char* name)
1414 {
1415     LPWSINFO            pwsi = wsi_find(GetCurrentTask());
1416
1417     dprintf_winsock(stddeb, "WS_GetHostByName32(%08x): %s\n",
1418                             (unsigned)pwsi, (name)?name:"NULL");
1419     if( pwsi )
1420     {
1421         struct hostent* host = gethostbyname( name );
1422         if( host )
1423             return host;
1424         pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1425     }
1426     return NULL;
1427 }
1428
1429 /***********************************************************************
1430  *              gethostname()           (WSOCK32.57)
1431  */
1432 INT32 WINAPI WINSOCK_gethostname32(char *name, INT32 namelen)
1433 {
1434     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1435
1436     dprintf_winsock(stddeb, "WS_GetHostName(%08x): name %s, len %d\n", 
1437                           (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
1438     if( pwsi )
1439     {
1440         if (gethostname(name, namelen) == 0) return 0;
1441         pwsi->err = (errno == EINVAL) ? WSAEFAULT : wsaErrno();
1442     }
1443     return SOCKET_ERROR;
1444 }
1445
1446 /***********************************************************************
1447  *              gethostname()           (WINSOCK.57)
1448  */
1449 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
1450 {
1451     return (INT16)WINSOCK_gethostname32(name, namelen);
1452 }
1453
1454 /***********************************************************************
1455  *              getprotobyname()        (WINSOCK.53)
1456  *
1457  *
1458 struct WIN_protoent *
1459  */
1460 SEGPTR WINAPI WINSOCK_getprotobyname16(char *name)
1461 {
1462     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1463
1464     dprintf_winsock(stddeb, "WS_GetProtoByName16(%08x): %s\n",
1465                           (unsigned)pwsi, (name)?name:NULL_STRING);
1466     if( pwsi )
1467     {
1468         struct protoent*     proto;
1469         if( (proto = getprotobyname(name)) != NULL )
1470             if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
1471                 return SEGPTR_GET(pwsi->buffer);
1472             else pwsi->err = WSAENOBUFS;
1473         else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1474     }
1475     return (SEGPTR)NULL;
1476 }
1477
1478 /***********************************************************************
1479  *              getprotobyname()        (WSOCK32.53)
1480  */
1481 struct protoent* WINAPI WINSOCK_getprotobyname32(char* name)
1482 {
1483     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1484
1485     dprintf_winsock(stddeb, "WS_GetProtoByName32(%08x): %s\n",
1486                           (unsigned)pwsi, (name)?name:NULL_STRING);
1487     if( pwsi )
1488     {
1489         struct protoent* proto;
1490         if( (proto = getprotobyname(name)) != NULL )
1491                 return proto;
1492         pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1493     }
1494     return NULL;
1495 }
1496
1497
1498 /***********************************************************************
1499  *              getprotobynumber()      (WINSOCK.54)
1500  *
1501  *
1502 struct WIN_protoent *
1503  */
1504 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
1505 {
1506     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1507
1508     dprintf_winsock(stddeb, "WS_GetProtoByNumber16(%08x): %i\n", (unsigned)pwsi, number);
1509
1510     if( pwsi )
1511     {
1512         struct protoent*     proto;
1513         if( (proto = getprotobynumber(number)) != NULL )
1514             if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
1515                 return SEGPTR_GET(pwsi->buffer);
1516             else pwsi->err = WSAENOBUFS;
1517         else pwsi->err = WSANO_DATA;
1518     }
1519     return (SEGPTR)NULL;
1520 }
1521
1522 /***********************************************************************
1523  *              getprotobynumber()      (WSOCK32.54)
1524  */
1525 struct protoent* WINAPI WINSOCK_getprotobynumber32(INT32 number)
1526 {
1527     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1528
1529     dprintf_winsock(stddeb, "WS_GetProtoByNumber32(%08x): %i\n", (unsigned)pwsi, number);
1530
1531     if( pwsi )
1532     {
1533         struct protoent* proto;
1534         if( (proto = getprotobynumber(number)) != NULL )
1535             return proto;
1536         pwsi->err = WSANO_DATA;
1537     }
1538     return NULL;
1539 }
1540
1541 /***********************************************************************
1542  *              getservbyname()         (WINSOCK.55)
1543  *
1544  *
1545 struct WIN_servent *
1546  */
1547 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
1548 {
1549     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1550
1551     dprintf_winsock(stddeb, "WS_GetServByName16(%08x): '%s', '%s'\n", 
1552                           (unsigned)pwsi, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
1553     if( pwsi )
1554     {
1555         struct servent*     serv;
1556         if( (serv = getservbyname(name, proto)) != NULL )
1557             if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
1558                 return SEGPTR_GET(pwsi->buffer);
1559             else pwsi->err = WSAENOBUFS;
1560         else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1561     }
1562     return (SEGPTR)NULL;
1563 }
1564
1565 /***********************************************************************
1566  *              getservbyname()         (WSOCK32.55)
1567  */
1568 struct servent* WINAPI WINSOCK_getservbyname32(const char *name, const char *proto)
1569 {
1570     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1571
1572     dprintf_winsock(stddeb, "WS_GetServByName32(%08x): '%s', '%s'\n",
1573                           (unsigned)pwsi, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
1574     if( pwsi )
1575     {
1576         struct servent* serv;
1577         if( (serv = getservbyname(name, proto)) != NULL )
1578             return serv;
1579         pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1580     }
1581     return NULL;
1582 }
1583
1584 /***********************************************************************
1585  *              getservbyport()         (WINSOCK.56)
1586  *
1587  *
1588 struct WIN_servent *
1589  */
1590 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
1591 {
1592     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1593
1594     dprintf_winsock(stddeb, "WS_GetServByPort16(%08x): %i, '%s'\n",
1595                           (unsigned)pwsi, (int)port, (proto)?proto:NULL_STRING);
1596     if( pwsi )
1597     {
1598         struct servent*     serv;
1599         if( (serv = getservbyport(port, proto)) != NULL )
1600             if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
1601                 return SEGPTR_GET(pwsi->buffer);
1602             else pwsi->err = WSAENOBUFS;
1603         else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1604     }
1605     return (SEGPTR)NULL;
1606 }
1607
1608 /***********************************************************************
1609  *              getservbyport()         (WSOCK32.56)
1610  */
1611 struct servent* WINAPI WINSOCK_getservbyport32(INT32 port, const char *proto)
1612 {
1613     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1614
1615     dprintf_winsock(stddeb, "WS_GetServByPort32(%08x): %i, '%s'\n",
1616                           (unsigned)pwsi, (int)port, (proto)?proto:NULL_STRING);
1617     if( pwsi )
1618     {
1619         struct servent* serv;
1620         if( (serv = getservbyport(port, proto)) != NULL )
1621             return serv;
1622         pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1623     }
1624     return NULL;
1625 }
1626
1627
1628 /* ------------------------------------- Windows sockets extensions -- *
1629  *                                                                     *
1630  * ------------------------------------------------------------------- */
1631
1632
1633 /***********************************************************************
1634  *          Asynchronous DNS services
1635  */
1636
1637 /* winsock_dns.c */
1638 extern HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, INT16 type, LPCSTR init,
1639                                  INT16 len, LPCSTR proto, SEGPTR sbuf, INT16 buflen, UINT32 flag);
1640
1641 /***********************************************************************
1642  *       WSAAsyncGetHostByAddr()        (WINSOCK.102)
1643  */
1644 HANDLE16 WINAPI WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
1645                                INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen)
1646 {
1647   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1648
1649   dprintf_winsock(stddeb, "WS_AsyncGetHostByAddr(%08x): hwnd %04x, msg %04x, addr %08x[%i]\n",
1650                           (unsigned)pwsi, hWnd, uMsg, (unsigned)addr , len );
1651
1652   if( pwsi ) 
1653     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, type, addr, len,
1654                             NULL, sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR );
1655   return 0;
1656 }
1657
1658
1659 /***********************************************************************
1660  *       WSAAsyncGetHostByName()        (WINSOCK.103)
1661  */
1662 HANDLE16 WINAPI WSAAsyncGetHostByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
1663                                       SEGPTR sbuf, INT16 buflen)
1664 {
1665   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1666
1667   dprintf_winsock(stddeb, "WS_AsyncGetHostByName(%08x): hwnd %04x, msg %04x, host %s, buffer %i\n",
1668                           (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen );
1669
1670   if( pwsi )
1671     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
1672                             NULL, sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME );
1673   return 0;
1674 }                     
1675
1676
1677 /***********************************************************************
1678  *       WSAAsyncGetProtoByName()       (WINSOCK.105)
1679  */
1680 HANDLE16 WINAPI WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
1681                                        SEGPTR sbuf, INT16 buflen)
1682 {
1683   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1684
1685   dprintf_winsock(stddeb, "WS_AsyncGetProtoByName(%08x): hwnd %04x, msg %04x, protocol %s\n",
1686                           (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING );
1687
1688   if( pwsi )
1689     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
1690                             NULL, sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME );
1691   return 0;
1692 }
1693
1694
1695 /***********************************************************************
1696  *       WSAAsyncGetProtoByNumber()     (WINSOCK.104)
1697  */
1698 HANDLE16 WINAPI WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 uMsg, INT16 number, 
1699                                          SEGPTR sbuf, INT16 buflen)
1700 {
1701   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1702
1703   dprintf_winsock(stddeb, "WS_AsyncGetProtoByNumber(%08x): hwnd %04x, msg %04x, num %i\n",
1704                           (unsigned)pwsi, hWnd, uMsg, number );
1705
1706   if( pwsi )
1707     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, number, NULL, 0,
1708                             NULL, sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM );
1709   return 0;
1710 }
1711
1712
1713 /***********************************************************************
1714  *       WSAAsyncGetServByName()        (WINSOCK.107)
1715  */
1716 HANDLE16 WINAPI WSAAsyncGetServByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
1717                                       LPCSTR proto, SEGPTR sbuf, INT16 buflen)
1718 {
1719   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1720
1721   dprintf_winsock(stddeb, "WS_AsyncGetServByName(%08x): hwnd %04x, msg %04x, name %s, proto %s\n",
1722                    (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING );
1723
1724   if( pwsi )
1725     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
1726                             proto, sbuf, buflen, WSMSG_ASYNC_SERVBYNAME );
1727   return 0;
1728 }
1729
1730 /***********************************************************************
1731  *       WSAAsyncGetServByPort()        (WINSOCK.106)
1732  */
1733 HANDLE16 WINAPI WSAAsyncGetServByPort(HWND16 hWnd, UINT16 uMsg, INT16 port, 
1734                                       LPCSTR proto, SEGPTR sbuf, INT16 buflen)
1735 {
1736   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1737
1738   dprintf_winsock(stddeb, "WS_AsyncGetServByPort(%08x): hwnd %04x, msg %04x, port %i, proto %s\n",
1739                            (unsigned)pwsi, hWnd, uMsg, port, (proto)?proto:NULL_STRING );
1740
1741   if( pwsi )
1742       return __WSAsyncDBQuery(pwsi, hWnd, uMsg, port, proto, 0,
1743                               NULL, sbuf, buflen, WSMSG_ASYNC_SERVBYPORT );
1744   return 0;
1745 }
1746
1747 /***********************************************************************
1748  *       WSACancelAsyncRequest()        (WINSOCK.108)
1749  */
1750 INT16 WINAPI WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
1751 {
1752   INT16                 retVal = SOCKET_ERROR;
1753   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1754   ws_async_op*          p_aop = (ws_async_op*)WS_HANDLE2PTR(hAsyncTaskHandle);
1755
1756   dprintf_winsock(stddeb, "WS_CancelAsyncRequest(%08x): handle %04x\n", 
1757                            (unsigned)pwsi, hAsyncTaskHandle);
1758   if( pwsi )
1759   {
1760       SIGNAL_MaskAsyncEvents( TRUE );   /* block SIGIO */
1761       if( WINSOCK_cancel_async_op(p_aop) )
1762       {
1763           WS_FREE(p_aop);
1764           pwsi->num_async_rq--;
1765           retVal = 0;
1766       }
1767       else pwsi->err = WSAEINVAL;
1768       SIGNAL_MaskAsyncEvents( FALSE );
1769   }
1770   return retVal;
1771 }
1772
1773 /***********************************************************************
1774  *      WSAAsyncSelect()                (WINSOCK.101)
1775  */
1776
1777 static ws_select_op* __ws_select_list = NULL;
1778
1779 BOOL32 WINSOCK_HandleIO( int* max_fd, int num_pending, fd_set io_set[3] )
1780 {
1781     /* This function is called by the event dispatcher
1782      * with io_set containing the result of select() */
1783
1784     ws_select_op*       psop = __ws_select_list;
1785     BOOL32              bPost = FALSE;
1786     DWORD               dwEvent, dwErrBytes;
1787     int                 num_posted;
1788
1789     dprintf_winsock(stddeb,"WINSOCK_HandleIO: %i pending descriptors\n", num_pending );
1790
1791     for( num_posted = dwEvent = 0 ; psop; psop = psop->next )
1792     {
1793         unsigned        flags = psop->pws->flags;
1794         int             fd = psop->pws->fd;
1795         int             r, w, e;
1796
1797         w = 0;
1798         if( (r = FD_ISSET( fd, &io_set[EVENT_IO_READ] )) ||
1799             (w = FD_ISSET( fd, &io_set[EVENT_IO_WRITE] )) ||
1800             (e = FD_ISSET( fd, &io_set[EVENT_IO_EXCEPT] )) )
1801         {
1802             /* This code removes WS_FD flags on one-shot events (WS_FD_CLOSE, 
1803              * WS_FD_CONNECT), otherwise it clears descriptors in the io_set.
1804              * Reenabling calls turn them back on.
1805              */
1806
1807             dprintf_winsock(stddeb,"\tchecking psop = 0x%08x\n", (unsigned) psop );
1808
1809             num_pending--;
1810
1811             /* Now figure out what kind of event we've got. The worst problem
1812              * we have to contend with is that some out of control applications 
1813              * really want to use mutually exclusive AsyncSelect() flags all at
1814              * the same time.
1815              */
1816
1817             if((flags & WS_FD_ACCEPT) && (flags & WS_FD_LISTENING))
1818             {
1819                 FD_CLR( fd, &io_set[EVENT_IO_WRITE] );
1820                 if( r )
1821                 {
1822                     FD_CLR( fd, &io_set[EVENT_IO_READ] ); /* reenabled by the next accept() */
1823                     dwEvent = WSAMAKESELECTREPLY( WS_FD_ACCEPT, 0 );
1824                     bPost = TRUE;
1825                 } 
1826                 else continue;
1827             }
1828             else if( flags & WS_FD_CONNECT )
1829             {
1830                 /* connecting socket */
1831
1832                 if( w || (w = FD_ISSET( fd, &io_set[EVENT_IO_WRITE] )) )
1833                 {
1834                     /* ready to write means that socket is connected */
1835
1836                     psop->pws->flags |= WS_FD_CONNECTED;
1837                     psop->pws->flags &= ~(WS_FD_CONNECT | WS_FD_INACTIVE);
1838                     dwEvent = WSAMAKESELECTREPLY( WS_FD_CONNECT, 0 );
1839
1840                     if( flags & (WS_FD_READ | WS_FD_CLOSE))
1841                         FD_SET( fd, &io_set[EVENT_IO_READ] );
1842                     else 
1843                         FD_CLR( fd, &io_set[EVENT_IO_READ] );
1844                     if( flags & WS_FD_WRITE ) 
1845                         FD_SET( fd, &io_set[EVENT_IO_WRITE] );
1846                     else 
1847                         FD_CLR( fd, &io_set[EVENT_IO_WRITE] );
1848                     bPost = TRUE;
1849                 }
1850                 else if( r )
1851                 {
1852                     /* failure - do read() to get correct errno */
1853
1854                     if( read( fd, &dwErrBytes, sizeof(dwErrBytes) ) == -1 )
1855                     {
1856                         dwEvent = WSAMAKESELECTREPLY( WS_FD_CONNECT, wsaErrno() );
1857                         bPost = TRUE;
1858                     }
1859                 }
1860                 /* otherwise bPost stays FALSE */
1861             }
1862             else 
1863             {
1864                 /* connected socket --
1865                  * removed WS_FD_OOB code for now.
1866                  */
1867
1868                 if( flags & WS_FD_WRITE &&
1869                    (w || (w = FD_ISSET( fd, &io_set[EVENT_IO_WRITE] ))) )
1870                 {
1871                     /* this will be reenabled when send() or sendto() fail with
1872                      * WSAEWOULDBLOCK */
1873
1874                     if( PostMessage16( psop->hWnd, psop->uMsg, (WPARAM16)WS_PTR2HANDLE(psop->pws), 
1875                                       (LPARAM)WSAMAKESELECTREPLY( WS_FD_WRITE, 0 ) ) )
1876                     {
1877                         dprintf_winsock(stddeb, "\t    hwnd %04x - %04x, %08x\n",
1878                                 psop->hWnd, psop->uMsg, (unsigned)MAKELONG(WS_FD_WRITE, 0) );
1879                         FD_CLR( fd, &io_set[EVENT_IO_WRITE] );
1880                         num_posted++;
1881                     }
1882                 }
1883
1884                 if( r && (flags & (WS_FD_READ | WS_FD_CLOSE)) )
1885                 {
1886                     int val = (flags & WS_FD_RAW);
1887
1888                      /* WS_FD_RAW is set by the WSAAsyncSelect() init */
1889
1890                     bPost = TRUE;
1891                     if( !val && ioctl( fd, FIONREAD, (char*)&dwErrBytes) == -1 )
1892                     {
1893                         /* weirdness */
1894
1895                         dwEvent = WSAMAKESELECTREPLY( WS_FD_READ, wsaErrno() );
1896                     }
1897                     else if( val || dwErrBytes )
1898                     {
1899                         /* got pending data, will be reenabled by recv() or recvfrom() */
1900
1901                         FD_CLR( fd, &io_set[EVENT_IO_READ] );
1902                         dwEvent = WSAMAKESELECTREPLY( WS_FD_READ, 0 );
1903                     }
1904                     else
1905                     {
1906                         /* 0 bytes to read - connection reset by peer? */
1907
1908                         do
1909                             val = read( fd, (char*)&dwErrBytes, sizeof(dwErrBytes));
1910                         while( errno == EINTR );
1911                         if( errno != EWOULDBLOCK )
1912                         {
1913                             switch( val )
1914                             {
1915                                 case  0: errno = ENETDOWN;      /* soft reset, fall through */
1916                                 case -1:                        /* hard reset */
1917                                          dwEvent = WSAMAKESELECTREPLY( WS_FD_CLOSE, wsaErrno() );
1918                                          break;
1919
1920                                 default: bPost = FALSE;
1921                                          continue;              /* FIXME: this is real bad */
1922                             }
1923                         }
1924                         else { bPost = FALSE; continue; }       /* more weirdness */
1925
1926                         /* this is it, this socket is closed */
1927
1928                         psop->pws->flags &= ~(WS_FD_READ | WS_FD_CLOSE | WS_FD_WRITE);
1929                         FD_CLR( fd, &io_set[EVENT_IO_READ] );
1930                         FD_CLR( fd, &io_set[EVENT_IO_WRITE] );
1931
1932                         if( *max_fd == (fd + 1) ) (*max_fd)--;
1933                     }
1934                 }
1935             }
1936
1937             if( bPost )
1938             {
1939                 dprintf_winsock(stddeb, "\t    hwnd %04x - %04x, %08x\n", 
1940                                 psop->hWnd, psop->uMsg, (unsigned)dwEvent );
1941                 PostMessage16( psop->hWnd, psop->uMsg, 
1942                               (WPARAM16)WS_PTR2HANDLE(psop->pws), (LPARAM)dwEvent );
1943                 bPost = FALSE;
1944                 num_posted++;
1945             }
1946         }
1947         if( num_pending <= 0 ) break;
1948     }
1949
1950     dprintf_winsock(stddeb, "\tdone, %i posted events\n", num_posted );
1951     return ( num_posted ) ? TRUE : FALSE;
1952 }
1953
1954
1955 INT16 WINAPI WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
1956 {
1957     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
1958     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
1959
1960     dprintf_winsock(stddeb, "WS_AsyncSelect(%08x): %04x, hWnd %04x, uMsg %04x, event %08x\n",
1961                           (unsigned)pwsi, s, hWnd, uMsg, (unsigned)lEvent );
1962     if( _check_ws(pwsi, pws) )
1963     {
1964         ws_select_op* psop;
1965
1966         if( (psop = pws->psop) )
1967         {
1968             /* delete previous control struct */
1969
1970             if( psop == __ws_select_list )
1971                 __ws_select_list = psop->next;
1972             else
1973                 psop->prev->next = psop->next; 
1974             if( psop->next ) psop->next->prev = psop->prev;
1975
1976             if( pws->flags & (WS_FD_ACCEPT | WS_FD_CONNECT | WS_FD_READ | WS_FD_CLOSE) )
1977                 EVENT_DeleteIO( pws->fd, EVENT_IO_READ );
1978             if( pws->flags & (WS_FD_CONNECT | WS_FD_WRITE) )
1979                 EVENT_DeleteIO( pws->fd, EVENT_IO_WRITE );
1980
1981             dprintf_winsock(stddeb,"\tremoving psop = 0x%08x\n", (unsigned) psop );
1982
1983             WS_FREE( pws->psop );
1984             pws->flags &= ~(WS_FD_RAW | WS_FD_ACCEPT | WS_FD_CONNECT | 
1985                             WS_FD_READ | WS_FD_WRITE | WS_FD_CLOSE);
1986             pws->psop = NULL;
1987         }
1988
1989         if( lEvent )
1990         {
1991             psop = (ws_select_op*)WS_ALLOC(sizeof(ws_select_op));
1992             if( psop )
1993             {
1994                 int sock_type, bytes = sizeof(int);
1995
1996                 WINSOCK_unblock_io( pws->fd, TRUE );
1997
1998                 psop->prev = NULL;
1999                 psop->next = __ws_select_list;
2000                 if( __ws_select_list )
2001                     __ws_select_list->prev = psop;
2002                 __ws_select_list = psop;
2003                 
2004                 psop->pws = pws;
2005                 psop->hWnd = hWnd;
2006                 psop->uMsg = uMsg;
2007
2008                 pws->psop = psop;
2009                 pws->flags |= (0x0000FFFF &lEvent);
2010                 getsockopt(pws->fd, SOL_SOCKET, SO_TYPE, &sock_type, &bytes);
2011                 if( sock_type == SOCK_RAW ) pws->flags |= WS_FD_RAW;
2012
2013                 if( lEvent & (WS_FD_ACCEPT | WS_FD_CONNECT | WS_FD_READ | WS_FD_CLOSE) )
2014                     EVENT_AddIO( pws->fd, EVENT_IO_READ );
2015                 if( lEvent & (WS_FD_CONNECT | WS_FD_WRITE) )
2016                     EVENT_AddIO( pws->fd, EVENT_IO_WRITE );
2017
2018                 /* TODO: handle WS_FD_ACCEPT right away if the socket is readable */
2019
2020                 dprintf_winsock(stddeb,"\tcreating psop = 0x%08x\n", (unsigned)psop );
2021
2022                 return 0; /* success */
2023             }
2024             else pwsi->err = WSAENOBUFS;
2025         } 
2026         else return 0;
2027     } 
2028     else if( pwsi ) pwsi->err = WSAEINVAL;
2029     return SOCKET_ERROR; 
2030 }
2031
2032
2033 /***********************************************************************
2034  *      __WSAFDIsSet()                  (WINSOCK.151)
2035  */
2036 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set *set)
2037 {
2038   int i = set->fd_count;
2039   
2040   dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n", s,(unsigned long)set);
2041     
2042   while (i--)
2043       if (set->fd_array[i] == s) return 1;
2044   return 0;
2045 }                                                            
2046
2047 /***********************************************************************
2048  *      __WSAFDIsSet()                  (WSOCK32.151)
2049  */
2050 INT32 WINAPI __WSAFDIsSet32(SOCKET32 s, ws_fd_set *set)
2051 {
2052     return __WSAFDIsSet16( (SOCKET16)s, set );
2053 }
2054
2055 /***********************************************************************
2056  *      WSAIsBlocking()                 (WINSOCK.114)(WSOCK32.114)
2057  */
2058 BOOL32 WINAPI WSAIsBlocking(void)
2059 {
2060   /* By default WinSock should set all its sockets to non-blocking mode
2061    * and poll in PeekMessage loop when processing "blocking" ones. This 
2062    * function is supposed to tell if program is in this loop. Our 
2063    * blocking calls are truly blocking so we always return FALSE.
2064    *
2065    * Note: It is allowed to call this function without prior WSAStartup().
2066    */
2067
2068   dprintf_winsock(stddeb, "WS_IsBlocking()\n");
2069   return FALSE;
2070 }
2071
2072 /***********************************************************************
2073  *      WSACancelBlockingCall()         (WINSOCK.113)(WSOCK32.113)
2074  */
2075 INT32 WINAPI WSACancelBlockingCall(void)
2076 {
2077   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
2078
2079   dprintf_winsock(stddeb, "WS_CancelBlockingCall(%08x)\n", (unsigned)pwsi);
2080
2081   if( pwsi ) return 0;
2082   return SOCKET_ERROR;
2083 }
2084
2085
2086 /***********************************************************************
2087  *      WSASetBlockingHook16()          (WINSOCK.109)
2088  */
2089 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2090 {
2091   FARPROC16             prev;
2092   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
2093
2094   dprintf_winsock(stddeb, "WS_SetBlockingHook16(%08x): hook %08x\n", 
2095                           (unsigned)pwsi, (unsigned) lpBlockFunc);
2096   if( pwsi ) 
2097   { 
2098       prev = (FARPROC16)pwsi->blocking_hook; 
2099       pwsi->blocking_hook = (DWORD)lpBlockFunc; 
2100       pwsi->flags &= ~WSI_BLOCKINGHOOK32;
2101       return prev; 
2102   }
2103   return 0;
2104 }
2105
2106
2107 /***********************************************************************
2108  *      WSASetBlockingHook32()
2109  */
2110 FARPROC32 WINAPI WSASetBlockingHook32(FARPROC32 lpBlockFunc)
2111 {
2112   FARPROC32             prev;
2113   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
2114
2115   dprintf_winsock(stddeb, "WS_SetBlockingHook32(%08x): hook %08x\n",
2116                           (unsigned)pwsi, (unsigned) lpBlockFunc);
2117   if( pwsi ) {
2118       prev = (FARPROC32)pwsi->blocking_hook;
2119       pwsi->blocking_hook = (DWORD)lpBlockFunc;
2120       pwsi->flags |= WSI_BLOCKINGHOOK32;
2121       return prev;
2122   }
2123   return NULL;
2124 }
2125
2126
2127 /***********************************************************************
2128  *      WSAUnhookBlockingHook16()       (WINSOCK.110)
2129  */
2130 INT16 WINAPI WSAUnhookBlockingHook16(void)
2131 {
2132     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
2133
2134     dprintf_winsock(stddeb, "WS_UnhookBlockingHook16(%08x)\n", (unsigned)pwsi);
2135     if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
2136     return SOCKET_ERROR;
2137 }
2138
2139
2140 /***********************************************************************
2141  *      WSAUnhookBlockingHook32()
2142  */
2143 INT32 WINAPI WSAUnhookBlockingHook32(void)
2144 {
2145     LPWSINFO              pwsi = wsi_find(GetCurrentTask());
2146
2147     dprintf_winsock(stddeb, "WS_UnhookBlockingHook32(%08x)\n", (unsigned)pwsi);
2148     if( pwsi )
2149     {
2150         pwsi->blocking_hook = 0;
2151         pwsi->flags &= ~WSI_BLOCKINGHOOK32;
2152         return 0;
2153     }
2154     return SOCKET_ERROR;
2155 }
2156
2157 /***********************************************************************
2158  *      WsControl()
2159  */
2160 VOID WINAPI WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,
2161                       LPDWORD x5,LPDWORD x6) 
2162 {
2163         fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n",
2164                 x1,x2,x3,x4,x5,x6
2165         );
2166         fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
2167                 x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0
2168         );
2169         return;
2170 }
2171 /* ----------------------------------- end of API stuff */
2172
2173
2174
2175 /* ----------------------------------- helper functions */
2176
2177 static int list_size(char** l, int item_size)
2178 {
2179   int i,j = 0;
2180   if(l)
2181   { for(i=0;l[i];i++) 
2182         j += (item_size) ? item_size : strlen(l[i]) + 1;
2183     j += (i + 1) * sizeof(char*); }
2184   return j;
2185 }
2186
2187 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2188
2189    /* base is either either equal to ref or 0 or SEGPTR */
2190
2191    char*                p = ref;
2192    char**               l_to = (char**)ref;
2193    int                  i,j,k;
2194
2195    for(j=0;l_src[j];j++) ;
2196    p += (j + 1) * sizeof(char*);
2197    for(i=0;i<j;i++)
2198    { l_to[i] = base + (p - ref);
2199      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2200      memcpy(p, l_src[i], k); p += k; }
2201    l_to[i] = NULL;
2202    return (p - ref);
2203 }
2204
2205 /* ----- hostent */
2206
2207 static int hostent_size(struct hostent* p_he)
2208 {
2209   int size = 0;
2210   if( p_he )
2211   { size  = sizeof(struct hostent); 
2212     size += strlen(p_he->h_name) + 1;
2213     size += list_size(p_he->h_aliases, 0);  
2214     size += list_size(p_he->h_addr_list, p_he->h_length ); }
2215   return size;
2216 }
2217
2218 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
2219 {
2220    /* Duplicate hostent structure and flatten data (with its pointers)
2221     * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or 
2222     * relative to pwsi->buffer depending on "flag" value. Returns size
2223     * of the data copied (also in the pwsi->buflen).
2224     */
2225
2226    int size = hostent_size(p_he);
2227    if( size )
2228    {
2229      char*           p_name,*p_aliases,*p_addr,*p_base,*p;
2230
2231      _check_buffer(pwsi, size);
2232      p = pwsi->buffer;
2233      p_base = (flag & WS_DUP_OFFSET) ? NULL
2234                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2235      p += (flag & WS_DUP_NATIVE) ? sizeof(struct hostent) : sizeof(struct ws_hostent);
2236      p_name = p;
2237      strcpy(p, p_he->h_name); p += strlen(p) + 1;
2238      p_aliases = p;
2239      p += list_dup(p_he->h_aliases, p, p_base + (p - pwsi->buffer), 0);
2240      p_addr = p;
2241      list_dup(p_he->h_addr_list, p, p_base + (p - pwsi->buffer), p_he->h_length);
2242      if( flag & WS_DUP_NATIVE )
2243      { struct hostent* p_to = (struct hostent*)pwsi->buffer;
2244        p_to->h_addrtype = p_he->h_addrtype; p_to->h_length = p_he->h_length;
2245        p_to->h_name = p_base + (p_name - pwsi->buffer);
2246        p_to->h_aliases = (char**)(p_base + (p_aliases - pwsi->buffer));
2247        p_to->h_addr_list = (char**)(p_base + (p_addr - pwsi->buffer)); }
2248      else
2249      { struct ws_hostent* p_to = (struct ws_hostent*)pwsi->buffer;
2250        p_to->h_addrtype = (INT16)p_he->h_addrtype; 
2251        p_to->h_length = (INT16)p_he->h_length;
2252        p_to->h_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
2253        p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
2254        p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - pwsi->buffer));
2255
2256        return (size + sizeof(struct ws_hostent) - sizeof(struct hostent)); }
2257    }
2258    return size;
2259 }
2260
2261 /* ----- protoent */
2262
2263 static int protoent_size(struct protoent* p_pe)
2264 {
2265   int size = 0;
2266   if( p_pe )
2267   { size  = sizeof(struct protoent);
2268     size += strlen(p_pe->p_name) + 1;
2269     size += list_size(p_pe->p_aliases, 0); }
2270   return size;
2271 }
2272
2273 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
2274 {
2275    int size = protoent_size(p_pe);
2276    if( size )
2277    {
2278      char*            p_name,*p_aliases,*p_base,*p;
2279
2280      _check_buffer(pwsi, size);
2281      p = pwsi->buffer; 
2282      p_base = (flag & WS_DUP_OFFSET) ? NULL
2283                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2284      p += (flag & WS_DUP_NATIVE)? sizeof(struct protoent) : sizeof(struct ws_protoent);
2285      p_name = p;
2286      strcpy(p, p_pe->p_name); p += strlen(p) + 1;
2287      p_aliases = p;
2288      list_dup(p_pe->p_aliases, p, p_base + (p - pwsi->buffer), 0);
2289      if( flag & WS_DUP_NATIVE )
2290      { struct protoent* p_to = (struct protoent*)pwsi->buffer;
2291        p_to->p_proto = p_pe->p_proto;
2292        p_to->p_name = p_base + (p_name - pwsi->buffer); 
2293        p_to->p_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
2294      else
2295      { struct ws_protoent* p_to = (struct ws_protoent*)pwsi->buffer;
2296        p_to->p_proto = (INT16)p_pe->p_proto;
2297        p_to->p_name = (SEGPTR)(p_base) + (p_name - pwsi->buffer);
2298        p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - pwsi->buffer)); 
2299        return (size + sizeof(struct ws_protoent) - sizeof(struct protoent)); }
2300    }
2301    return size;
2302 }
2303
2304 /* ----- servent */
2305
2306 static int servent_size(struct servent* p_se)
2307 {
2308   int size = 0;
2309   if( p_se )
2310   { size += sizeof(struct servent);
2311     size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
2312     size += list_size(p_se->s_aliases, 0); }
2313   return size;
2314 }
2315
2316 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
2317 {
2318    int size = servent_size(p_se);
2319    if( size )
2320    {
2321      char*           p_name,*p_aliases,*p_proto,*p_base,*p;
2322
2323      _check_buffer(pwsi, size);
2324      p = pwsi->buffer;
2325      p_base = (flag & WS_DUP_OFFSET) ? NULL 
2326                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2327      p += (flag & WS_DUP_NATIVE)? sizeof(struct servent) : sizeof(struct ws_servent);
2328      p_name = p;
2329      strcpy(p, p_se->s_name); p += strlen(p) + 1;
2330      p_proto = p;
2331      strcpy(p, p_se->s_proto); p += strlen(p) + 1;
2332      p_aliases = p;
2333      list_dup(p_se->s_aliases, p, p_base + (p - pwsi->buffer), 0);
2334
2335      if( flag & WS_DUP_NATIVE )
2336      { struct servent* p_to = (struct servent*)pwsi->buffer;
2337        p_to->s_port = p_se->s_port;
2338        p_to->s_name = p_base + (p_name - pwsi->buffer); 
2339        p_to->s_proto = p_base + (p_proto - pwsi->buffer);
2340        p_to->s_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
2341      else
2342      { struct ws_servent* p_to = (struct ws_servent*)pwsi->buffer;
2343        p_to->s_port = (INT16)p_se->s_port;
2344        p_to->s_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
2345        p_to->s_proto = (SEGPTR)(p_base + (p_proto - pwsi->buffer));
2346        p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer)); 
2347        return (size + sizeof(struct ws_servent) - sizeof(struct servent)); }
2348    }
2349    return size;
2350 }
2351
2352 /* ----------------------------------- error handling */
2353
2354 UINT16 wsaErrno(void)
2355 {
2356     int loc_errno = errno; 
2357 #if defined(__FreeBSD__)
2358        dprintf_winsock(stderr, "winsock: errno %d, (%s).\n", 
2359                                          errno, sys_errlist[errno]);
2360 #else
2361        dprintf_winsock(stderr, "winsock: errno %d\n", errno);
2362 #endif
2363
2364     switch(loc_errno)
2365     {
2366         case EINTR:             return WSAEINTR;
2367         case EBADF:             return WSAEBADF;
2368         case EACCES:            return WSAEACCES;
2369         case EFAULT:            return WSAEFAULT;
2370         case EINVAL:            return WSAEINVAL;
2371         case EMFILE:            return WSAEMFILE;
2372         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
2373         case EINPROGRESS:       return WSAEINPROGRESS;
2374         case EALREADY:          return WSAEALREADY;
2375         case ENOTSOCK:          return WSAENOTSOCK;
2376         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
2377         case EMSGSIZE:          return WSAEMSGSIZE;
2378         case EPROTOTYPE:        return WSAEPROTOTYPE;
2379         case ENOPROTOOPT:       return WSAENOPROTOOPT;
2380         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
2381         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
2382         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
2383         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
2384         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
2385         case EADDRINUSE:        return WSAEADDRINUSE;
2386         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
2387         case ENETDOWN:          return WSAENETDOWN;
2388         case ENETUNREACH:       return WSAENETUNREACH;
2389         case ENETRESET:         return WSAENETRESET;
2390         case ECONNABORTED:      return WSAECONNABORTED;
2391         case ECONNRESET:        return WSAECONNRESET;
2392         case ENOBUFS:           return WSAENOBUFS;
2393         case EISCONN:           return WSAEISCONN;
2394         case ENOTCONN:          return WSAENOTCONN;
2395         case ESHUTDOWN:         return WSAESHUTDOWN;
2396         case ETOOMANYREFS:      return WSAETOOMANYREFS;
2397         case ETIMEDOUT:         return WSAETIMEDOUT;
2398         case ECONNREFUSED:      return WSAECONNREFUSED;
2399         case ELOOP:             return WSAELOOP;
2400         case ENAMETOOLONG:      return WSAENAMETOOLONG;
2401         case EHOSTDOWN:         return WSAEHOSTDOWN;
2402         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
2403         case ENOTEMPTY:         return WSAENOTEMPTY;
2404 #ifdef EPROCLIM
2405         case EPROCLIM:          return WSAEPROCLIM;
2406 #endif
2407 #ifdef EUSERS
2408         case EUSERS:            return WSAEUSERS;
2409 #endif
2410 #ifdef EDQUOT
2411         case EDQUOT:            return WSAEDQUOT;
2412 #endif
2413 #ifdef ESTALE
2414         case ESTALE:            return WSAESTALE;
2415 #endif
2416 #ifdef EREMOTE
2417         case EREMOTE:           return WSAEREMOTE;
2418 #endif
2419
2420        /* just in case we ever get here and there are no problems */
2421         case 0:                 return 0;
2422         default:
2423                 fprintf(stderr, "winsock: unknown errno %d!\n", errno);
2424                 return WSAEOPNOTSUPP;
2425     }
2426 }
2427
2428 UINT16 wsaHerrno(void)
2429 {
2430     int         loc_errno = h_errno;
2431
2432 #if defined(__FreeBSD__)
2433     dprintf_winsock(stderr, "winsock: h_errno %d, (%s).\n", 
2434                     h_errno, sys_errlist[h_errno]);
2435 #else
2436     dprintf_winsock(stderr, "winsock: h_errno %d.\n", h_errno);
2437 #ifndef sun
2438     if( debugging_winsock )  herror("wine: winsock: wsaherrno");
2439 #endif
2440 #endif
2441
2442     switch(loc_errno)
2443     {
2444         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
2445         case TRY_AGAIN:         return WSATRY_AGAIN;
2446         case NO_RECOVERY:       return WSANO_RECOVERY;
2447         case NO_DATA:           return WSANO_DATA; 
2448
2449         case 0:                 return 0;
2450         default:
2451                 fprintf(stderr, "winsock: unknown h_errno %d!\n", h_errno);
2452                 return WSAEOPNOTSUPP;
2453     }
2454 }
2455
2456