Release 970525
[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 John Brezak, Erik Bos, Alex Korobka.
6  */
7  
8 #include <stdio.h>
9 #include <string.h>
10 #include <signal.h>
11 #include <sys/types.h>
12 #include <sys/ipc.h>
13 #include <sys/ioctl.h>
14 #if defined(__svr4__)
15 #include <sys/filio.h>
16 #include <sys/ioccom.h>
17 #include <sys/sockio.h>
18 #endif
19 #if defined(__EMX__)
20 #include <sys/so_ioctl.h>
21 #include <sys/param.h>
22 #endif
23 #include <sys/msg.h>
24 #include <sys/wait.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <netdb.h>
31 #include <unistd.h>
32
33 #include "windows.h"
34 #include "winnt.h"
35 #include "heap.h"
36 #include "ldt.h"
37 #include "winsock.h"
38 #include "stddebug.h"
39 #include "debug.h"
40
41 #define dump_sockaddr(a) \
42         fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
43                         ((struct sockaddr_in *)a)->sin_family, \
44                         inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
45                         ntohs(((struct sockaddr_in *)a)->sin_port))
46
47 extern void SIGNAL_MaskAsyncEvents( BOOL32 );
48
49 #pragma pack(4)
50
51 /* ----------------------------------- internal data */
52
53 extern int h_errno;
54 extern void __sigio(int);
55
56 ws_async_ctl            async_ctl;
57 int                     async_qid = -1;
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 INT16         _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 INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent);
87 static int notify_client(ws_socket* pws, unsigned flag);
88
89 static int _check_ws(LPWSINFO pwsi, ws_socket* pws);
90 static int _check_buffer(LPWSINFO pwsi, int size);
91
92 static void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base);
93 static void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base);
94 static void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base);
95
96 static int cancel_async_select(ws_socket*);
97
98 static void convert_sockopt(INT16 *level, INT16 *optname)
99 {
100   int           i;
101   switch (*level)
102   {
103      case WS_SOL_SOCKET:
104         *level = SOL_SOCKET;
105         for(i=0; _ws_sock_ops[i]; i++)
106             if( _ws_sock_ops[i] == *optname ) break;
107         if( _ws_sock_ops[i] ) *optname = (INT16)_px_sock_ops[i];
108         else fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
109         break;
110      case WS_IPPROTO_TCP:
111         *optname = IPPROTO_TCP;
112   }
113 }
114
115 static void _ws_global_init()
116 {
117    if( !_ws_stub )
118    {
119      _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
120      if( !(_ws_stub = WS_ALLOC(0x10)) )
121        fprintf(stderr,"Fatal: failed to create WinSock heap\n");
122    }
123    if( async_qid == -1 ) 
124      if( (async_qid = msgget(IPC_PRIVATE, IPC_CREAT | 0x1FF)) == -1 )
125        fprintf(stderr,"Fatal: failed to create WinSock resource\n");
126 }
127
128 /* ----------------------------------- Per-thread info */
129
130 static void wsi_link(LPWSINFO pwsi)
131 { if( _wsi_list ) _wsi_list->prev = pwsi;
132   pwsi->next = _wsi_list; _wsi_list = pwsi; 
133 }
134
135 static void wsi_unlink(LPWSINFO pwsi)
136 {
137   if( pwsi == _wsi_list ) _wsi_list = pwsi->next;
138   else 
139   { pwsi->prev->next = pwsi->next;
140     if( pwsi->next ) pwsi->next->prev = pwsi->prev; } 
141 }
142
143 static LPWSINFO wsi_find(HTASK16 hTask)
144 { LPWSINFO pwsi = _wsi_list;
145   while( pwsi && pwsi->tid != hTask ) pwsi = pwsi->next;
146   return pwsi; 
147 }
148
149 static ws_socket* wsi_alloc_socket(LPWSINFO pwsi, int fd)
150 {
151   if( pwsi->last_free >= 0 )
152   {
153     int i = pwsi->last_free;
154
155     pwsi->last_free = pwsi->sock[i].flags;
156     pwsi->sock[i].fd = fd;
157     pwsi->sock[i].flags = 0;
158     return &pwsi->sock[i];
159   }
160   return NULL;
161 }
162
163 static void fd_set_normalize(fd_set* fds, LPWSINFO pwsi, ws_fd_set* ws, int* highfd)
164 {
165   FD_ZERO(fds);
166   if(ws) 
167   { 
168     int         i;
169     ws_socket*  pws;
170     for(i=0;i<(ws->fd_count);i++) 
171     {
172       pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
173       if( _check_ws(pwsi, pws) ) 
174       { 
175         if( pws->fd > *highfd ) *highfd = pws->fd; 
176         FD_SET(pws->fd, fds); 
177       }
178     }
179   }
180 }
181
182 /*
183  * Note weirdness here: sockets with errors belong in exceptfds, but
184  * are given to us in readfds or writefds, so move them to exceptfds if
185  * there is an error. Note that this means that exceptfds may have mysterious
186  * sockets set in it that the program never asked for.
187  */
188
189 __inline__ static int sock_error_p(int s)
190 {
191     unsigned int optval, optlen;
192
193     optlen = sizeof(optval);
194     getsockopt(s, SOL_SOCKET, SO_ERROR, &optval, &optlen);
195     if (optval) dprintf_winsock(stddeb, "error: %d\n", optval);
196     return optval != 0;
197 }
198
199 static void fd_set_update(LPWSINFO pwsi, fd_set* fds, ws_fd_set* ws,
200                           fd_set *errorfds)
201 {
202     if( ws )
203     {
204         int i, j, count = ws->fd_count;
205
206         for( i = 0, j = 0; i < count; i++ )
207         {
208             ws_socket *pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
209             int fd = pws->fd;
210
211             if( _check_ws(pwsi, pws) && FD_ISSET(fd, fds) )
212             {
213                 /* if error, move to errorfds */
214                 if (errorfds && (FD_ISSET(fd, errorfds) || sock_error_p(fd)))
215                     FD_SET(fd, errorfds);
216                 else
217                     ws->fd_array[j++] = ws->fd_array[i];
218             }
219         }
220         ws->fd_count = j;
221         dprintf_winsock(stddeb, "\n");
222     }
223     return;
224 }
225
226 static void fd_set_update_except(LPWSINFO pwsi, fd_set *fds, ws_fd_set *ws,
227                                  fd_set *errorfds)
228 {
229     if (ws)
230     {
231         int i, j, count = ws->fd_count;
232
233         for (i=j=0; i < count; i++)
234         {
235             ws_socket *pws = (ws_socket *)WS_HANDLE2PTR(ws->fd_array[i]);
236
237             if (_check_ws(pwsi, pws) && (FD_ISSET(pws->fd, fds)
238                                          || FD_ISSET(pws->fd, errorfds)))
239             ws->fd_array[j++] = ws->fd_array[i];
240         }
241         ws->fd_count = j;
242     }
243     return;
244 }
245
246 /* ----------------------------------- API ----- 
247  *
248  * Init / cleanup / error checking.
249  */
250
251 INT16 WSAStartup(UINT16 wVersionRequested, LPWSADATA lpWSAData)
252 {
253   WSADATA WINSOCK_data = { 0x0101, 0x0101,
254                           "WINE Sockets 1.1",
255                         #ifdef linux
256                                 "Linux/i386",
257                         #elif defined(__NetBSD__)
258                                 "NetBSD/i386",
259                         #elif defined(sunos)
260                                 "SunOS",
261                         #elif defined(__FreeBSD__)
262                                 "FreeBSD",
263                         #else
264                                 "Unknown",
265                         #endif
266                            WS_MAX_SOCKETS_PER_THREAD,
267                            WS_MAX_UDP_DATAGRAM, NULL };
268   HTASK16               tid = GetCurrentTask();
269   LPWSINFO              pwsi;
270
271   dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
272
273   if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
274       HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
275
276   if (!lpWSAData) return WSAEINVAL;
277
278   _ws_global_init();
279   if( _WSHeap == 0 ) return WSASYSNOTREADY;
280   
281   pwsi = wsi_find(GetCurrentTask());
282   if( pwsi == NULL )
283   {
284     if( (pwsi = (LPWSINFO)WS_ALLOC( sizeof(WSINFO))) )
285     {
286       int i = 0;
287       pwsi->tid = tid;
288       for( i = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++ )
289       { 
290         pwsi->sock[i].fd = -1; 
291         pwsi->sock[i].flags = i + 1; 
292       }
293       pwsi->sock[WS_MAX_SOCKETS_PER_THREAD - 1].flags = -1;
294     } 
295     else return WSASYSNOTREADY;
296     wsi_link(pwsi);
297   } else pwsi->num_startup++;
298
299   /* return winsock information */
300   memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
301
302   dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
303   return(0);
304 }
305
306 void WINSOCK_Shutdown()
307 {
308   if( async_qid != -1 )
309     if( msgctl(async_qid, IPC_RMID, NULL) == -1 )
310           fprintf(stderr,"failed to delete WS message queue.\n");
311     else async_qid = -1;
312 }
313
314 INT16 WSACleanup(void)
315 {
316   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
317
318   /* FIXME: do global cleanup if no current task */
319
320   dprintf_winsock(stddeb, "WSACleanup(%08x)\n", (unsigned)pwsi);
321   if( pwsi )
322   {
323       int       i, j, n;
324
325       if( pwsi->num_startup-- ) return 0;
326
327       SIGNAL_MaskAsyncEvents( TRUE );
328       WINSOCK_cancel_async_op(GetCurrentTask());
329       SIGNAL_MaskAsyncEvents( FALSE );
330
331       wsi_unlink(pwsi);
332       if( _wsi_list == NULL ) WINSOCK_Shutdown();
333
334       if( pwsi->flags & WSI_BLOCKINGCALL )
335           dprintf_winsock(stddeb,"\tinside blocking call!\n");
336       if( pwsi->num_async_rq )
337           dprintf_winsock(stddeb,"\thave %i outstanding async ops!\n", pwsi->num_async_rq );
338
339       for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++)
340         if( pwsi->sock[i].fd != -1 )
341         { 
342           n += cancel_async_select(&pwsi->sock[i]);
343           close(pwsi->sock[i].fd); j++; 
344         }
345       if( j ) 
346           dprintf_winsock(stddeb,"\tclosed %i sockets, killed %i async selects!\n", j, n);
347
348       if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer);
349       if( pwsi->dbuffer ) SEGPTR_FREE(pwsi->dbuffer);
350       WS_FREE(pwsi);
351       return 0;
352   }
353   return SOCKET_ERROR;
354 }
355
356 INT16 WSAGetLastError(void)
357 {
358   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
359   INT16         ret;
360
361   dprintf_winsock(stddeb, "WSAGetLastError(%08x)", (unsigned)pwsi);
362
363   ret = (pwsi) ? pwsi->err : WSANOTINITIALISED;
364
365   dprintf_winsock(stddeb, " = %i\n", (int)ret);
366   return ret;
367 }
368
369 void WSASetLastError(INT16 iError)
370 {
371   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
372
373   dprintf_winsock(stddeb, "WSASetLastError(%08x): %d\n", (unsigned)pwsi, (int)iError);
374
375   if( pwsi ) pwsi->err = iError;
376 }
377
378 int _check_ws(LPWSINFO pwsi, ws_socket* pws)
379 {
380   if( pwsi )
381     if( pwsi->flags & WSI_BLOCKINGCALL ) pwsi->err = WSAEINPROGRESS;
382     else if( WSI_CHECK_RANGE(pwsi, pws) ) return 1;
383     else pwsi->err = WSAENOTSOCK;
384   return 0;
385 }
386
387 int _check_buffer(LPWSINFO pwsi, int size)
388 {
389   if( pwsi->buffer && pwsi->buflen >= size ) return 1;
390   else SEGPTR_FREE(pwsi->buffer);
391   pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size)); 
392   return (pwsi->buffer != NULL);
393 }
394
395 /* ----- socket operations */
396
397 SOCKET16 WINSOCK_accept(SOCKET16 s, struct sockaddr *addr, INT16 *addrlen16)
398 {
399   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
400   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
401
402   dprintf_winsock(stddeb, "WS_ACCEPT(%08x): socket %04x\n", 
403                                    (unsigned)pwsi, (UINT16)s); 
404   if( _check_ws(pwsi, pws) )
405   {
406      int        sock, fd_flags, addrlen32 = *addrlen16;
407
408      /* this is how block info is supposed to be used -
409       * WSAIsBlocking() would then check WSI_BLOCKINGCALL bit.
410       */
411
412      fd_flags = fcntl(pws->fd, F_GETFL, 0);
413      if( !(fd_flags & O_NONBLOCK) ) pwsi->flags |= WSI_BLOCKINGCALL; 
414
415      if( (sock = accept(pws->fd, addr, &addrlen32)) >= 0 )
416      {
417         ws_socket*      pnew = wsi_alloc_socket(pwsi, sock); 
418         notify_client(pws, WS_FD_ACCEPT);
419         if( pnew )
420         {
421           if( pws->p_aop )
422               init_async_select(pnew, pws->p_aop->hWnd,
423                                       pws->p_aop->uMsg,
424                                       pws->p_aop->flags & ~WS_FD_ACCEPT );
425
426           pwsi->flags &= ~WSI_BLOCKINGCALL; 
427           return (SOCKET16)WS_PTR2HANDLE(pnew);
428         } 
429         else pwsi->err = WSAENOBUFS;
430      } 
431      else pwsi->err = wsaErrno();
432
433      pwsi->flags &= ~WSI_BLOCKINGCALL;
434   }
435   return INVALID_SOCKET;
436 }
437
438 INT16 WINSOCK_bind(SOCKET16 s, struct sockaddr *name, INT16 namelen)
439 {
440   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
441   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
442
443   dprintf_winsock(stddeb, "WS_BIND(%08x): socket %04x, ptr %8x, length %d\n", 
444                            (unsigned)pwsi, s, (int) name, namelen);
445 #if 0
446   dump_sockaddr(name);
447 #endif
448
449   if ( _check_ws(pwsi, pws) )
450     if (namelen >= sizeof(*name)) 
451        if ( ((struct sockaddr_in *)name)->sin_family == AF_INET )
452           if ( bind(pws->fd, name, namelen) < 0 ) 
453           {
454              int        loc_errno = errno;
455              dprintf_winsock(stddeb,"\tfailure - errno = %i\n", errno);
456              errno = loc_errno;
457              switch(errno)
458              {
459                 case EBADF: pwsi->err = WSAENOTSOCK; break;
460                 case EADDRNOTAVAIL: pwsi->err = WSAEINVAL; break;
461                 default: pwsi->err = wsaErrno();
462              }
463           }
464           else return 0;
465        else pwsi->err = WSAEAFNOSUPPORT;
466     else pwsi->err = WSAEFAULT;
467   return SOCKET_ERROR;
468 }
469
470 INT16 WINSOCK_closesocket(SOCKET16 s)
471 {
472   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
473   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
474
475   dprintf_winsock(stddeb, "WS_CLOSE(%08x): socket %08x\n", (unsigned)pwsi, s);
476
477   if( _check_ws(pwsi, pws) )
478   { 
479     int         fd = pws->fd;
480
481     cancel_async_select(pws);
482     pws->fd = -1;
483     pws->flags = (unsigned)pwsi->last_free;
484     pwsi->last_free = pws - &pwsi->sock[0];
485     if (close(fd) == 0) return 0;
486     pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
487   }
488   return SOCKET_ERROR;
489 }
490
491 INT16 WINSOCK_connect(SOCKET16 s, struct sockaddr *name, INT16 namelen)
492 {
493   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
494   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
495
496   dprintf_winsock(stddeb, "WS_CONNECT(%08x): socket %04x, ptr %8x, length %d\n", 
497                            (unsigned)pwsi, s, (int) name, namelen);
498 #if 0
499   dump_sockaddr(name);
500 #endif
501
502   if( _check_ws(pwsi, pws) )
503   {
504     if (connect(pws->fd, name, namelen) == 0) 
505     { 
506         if( pws->p_aop )
507             /* we need to notify handler process if
508              * connect() succeeded NOT in response to winsock message
509              */
510             notify_client(pws, WS_FD_CONNECTED);
511
512         pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT); 
513         return 0; 
514     }
515     pwsi->err = (errno == EINPROGRESS) ? WSAEWOULDBLOCK : wsaErrno();
516   }
517   return SOCKET_ERROR;
518 }
519
520 INT16 WINSOCK_getpeername(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
521 {
522   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
523   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
524
525   dprintf_winsock(stddeb, "WS_GETPEERNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
526                            (unsigned)pwsi, s, (int) name, *namelen);
527   if( _check_ws(pwsi, pws) )
528   {
529     int namelen32 = *namelen;
530     if (getpeername(pws->fd, name, &namelen32) == 0) 
531     { 
532 #if 0
533         dump_sockaddr(name);
534 #endif
535        *namelen = (INT16)namelen32; 
536         return 0; 
537     }
538     pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
539   }
540   return SOCKET_ERROR;
541 }
542
543 INT16 WINSOCK_getsockname(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
544 {
545   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
546   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
547
548   dprintf_winsock(stddeb, "WS_GETSOCKNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
549                           (unsigned)pwsi, s, (int) name, (int) *namelen);
550   if( _check_ws(pwsi, pws) )
551   {
552     int namelen32 = *namelen;
553     if (getsockname(pws->fd, name, &namelen32) == 0)
554     { 
555         *namelen = (INT16)namelen32; 
556          return 0; 
557     }
558     pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
559   }
560   return SOCKET_ERROR;
561 }
562
563 INT16 WINSOCK_getsockopt(SOCKET16 s, INT16 level, 
564                          INT16 optname, char *optval, INT16 *optlen)
565 {
566   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
567   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
568
569   dprintf_winsock(stddeb, "WS_GETSOCKOPT(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n", 
570                            (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
571
572   if( _check_ws(pwsi, pws) )
573   {
574      int        optlen32 = *optlen;
575
576      convert_sockopt(&level, &optname);
577      if (getsockopt(pws->fd, (int) level, optname, optval, &optlen32) == 0 )
578      { *optlen = (INT16)optlen32; return 0; }
579      pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
580   }
581   return SOCKET_ERROR;
582 }
583
584 u_long  WINSOCK_htonl(u_long hostlong)   { return( htonl(hostlong) ); }
585 u_short WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
586 u_long  WINSOCK_inet_addr(char *cp)      { return( inet_addr(cp) ); }
587 u_long  WINSOCK_ntohl(u_long netlong)    { return( ntohl(netlong) ); }
588 u_short WINSOCK_ntohs(u_short netshort)  { return( ntohs(netshort) ); }
589
590 SEGPTR WINSOCK_inet_ntoa(struct in_addr in)
591 {
592   /* use "buffer for dummies" here because some applications have 
593    * propensity to decode addresses in ws_hostent structure without 
594    * saving them first...
595    */
596
597   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
598
599   if( pwsi )
600   {
601     char*       s = inet_ntoa(in);
602     if( s ) 
603     {
604         if( pwsi->dbuffer == NULL )
605             if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(32)) == NULL )
606             {
607                 pwsi->err = WSAENOBUFS;
608                 return (SEGPTR)NULL;
609             }
610         strncpy(pwsi->dbuffer, s, 32 );
611         return SEGPTR_GET(pwsi->dbuffer); 
612     }
613     pwsi->err = wsaErrno();
614   }
615   return (SEGPTR)NULL;
616 }
617
618 INT16 WINSOCK_ioctlsocket(SOCKET16 s, UINT32 cmd, UINT32 *argp)
619 {
620   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
621   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
622
623   dprintf_winsock(stddeb, "WS_IOCTL(%08x): socket %04x, cmd %08x, ptr %8x\n", 
624                           (unsigned)pwsi, s, cmd, (unsigned) argp);
625   if( _check_ws(pwsi, pws) )
626   {
627     long        newcmd  = cmd;
628
629     switch( cmd )
630     {
631         case WS_FIONREAD:   
632                 newcmd=FIONREAD; 
633                 break;
634
635         case WS_FIONBIO:    
636                 newcmd=FIONBIO;  
637                 if( pws->p_aop && *argp == 0 ) 
638                 {
639                     pwsi->err = WSAEINVAL; 
640                     return SOCKET_ERROR; 
641                 }
642                 break;
643
644         case WS_SIOCATMARK: 
645                 newcmd=SIOCATMARK; 
646                 break;
647
648         case WS_IOW('f',125,u_long): 
649                 fprintf(stderr,"Warning: WS1.1 shouldn't be using async I/O\n");
650                 pwsi->err = WSAEINVAL; 
651                 return SOCKET_ERROR;
652
653         default:          
654                 /* Netscape tries hard to use bogus ioctl 0x667e */
655                 dprintf_winsock(stddeb,"\tunknown WS_IOCTL cmd (%08x)\n", cmd);
656     }
657     if( ioctl(pws->fd, newcmd, (char*)argp ) == 0 ) return 0;
658     pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno(); 
659   }
660   return SOCKET_ERROR;
661 }
662
663 INT16 WINSOCK_listen(SOCKET16 s, INT16 backlog)
664 {
665   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
666   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
667
668   dprintf_winsock(stddeb, "WS_LISTEN(%08x): socket %04x, backlog %d\n", 
669                           (unsigned)pwsi, s, backlog);
670   if( _check_ws(pwsi, pws) )
671   {
672     if( !pws->p_aop )
673     {
674       int  fd_flags = fcntl(pws->fd, F_GETFL, 0);
675       if( !(fd_flags & O_NONBLOCK) ) pws->flags |= WS_FD_ACCEPT;
676     }
677     else notify_client(pws, WS_FD_ACCEPT);
678
679     if (listen(pws->fd, backlog) == 0) return 0;
680     pwsi->err = wsaErrno();
681   }
682   return SOCKET_ERROR;
683 }
684
685 INT16 WINSOCK_recv(SOCKET16 s, char *buf, INT16 len, INT16 flags)
686 {
687   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
688   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
689
690   dprintf_winsock(stddeb, "WS_RECV(%08x): socket %04x, buf %8x, len %d, flags %d",
691                           (unsigned)pwsi, s, (unsigned)buf, len, flags);
692   if( _check_ws(pwsi, pws) )
693   {
694     int length;
695     if ((length = recv(pws->fd, buf, len, flags)) >= 0) 
696     { 
697         dprintf_winsock(stddeb, " -> %i bytes\n", length);
698         notify_client(pws, WS_FD_READ);
699         return (INT16)length;
700     }
701     pwsi->err = wsaErrno();
702   }
703   dprintf_winsock(stddeb, " -> ERROR\n");
704   return SOCKET_ERROR;
705 }
706
707 INT16 WINSOCK_recvfrom(SOCKET16 s, char *buf, INT16 len, INT16 flags, 
708                 struct sockaddr *from, INT16 *fromlen16)
709 {
710   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
711   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
712
713   dprintf_winsock(stddeb, "WS_RECVFROM(%08x): socket %04x, ptr %08x, len %d, flags %d\n",
714                           (unsigned)pwsi, s, (unsigned)buf, len, flags);
715   if( _check_ws(pwsi, pws) )
716   {
717     int length, fromlen32 = *fromlen16;
718
719     if ((length = recvfrom(pws->fd, buf, len, flags, from, &fromlen32)) >= 0)
720     {   
721       *fromlen16 = fromlen32; 
722        notify_client(pws, WS_FD_READ);
723        return (INT16)length;
724     }
725     pwsi->err = wsaErrno();
726   }
727   return SOCKET_ERROR;
728 }
729
730 INT16 WINSOCK_select(INT16 nfds, ws_fd_set *ws_readfds,
731                                  ws_fd_set *ws_writefds,
732                                  ws_fd_set *ws_exceptfds, struct timeval *timeout)
733 {
734   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
735         
736   dprintf_winsock(stddeb, "WS_SELECT(%08x): nfds %d (ignored), read %8x, write %8x, excp %8x\n", 
737           (unsigned) pwsi, nfds, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
738
739   if( pwsi )
740   {
741      int         highfd = 0;
742      fd_set      readfds, writefds, exceptfds, errorfds;
743
744      fd_set_normalize(&readfds, pwsi, ws_readfds, &highfd);
745      fd_set_normalize(&writefds, pwsi, ws_writefds, &highfd);
746      fd_set_normalize(&exceptfds, pwsi, ws_exceptfds, &highfd);
747      FD_ZERO(&errorfds);
748
749      if( (highfd = select(highfd + 1, &readfds, &writefds, &exceptfds, timeout)) >= 0 )
750      {
751           if( highfd )
752           {
753             fd_set_update(pwsi, &readfds, ws_readfds, &errorfds);
754             fd_set_update(pwsi, &writefds, ws_writefds, &errorfds);
755             fd_set_update_except(pwsi, &exceptfds, ws_exceptfds, &errorfds);
756           }
757           return highfd; 
758      }
759      pwsi->err = wsaErrno();
760   } 
761   return SOCKET_ERROR;
762 }
763
764 INT16 WINSOCK_send(SOCKET16 s, char *buf, INT16 len, INT16 flags)
765 {
766   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
767   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
768
769   dprintf_winsock(stddeb, "WS_SEND(%08x): socket %04x, ptr %08x, length %d, flags %d\n", 
770                           (unsigned)pwsi, s, (unsigned) buf, len, flags);
771   if( _check_ws(pwsi, pws) )
772   {
773     int         length;
774     if ((length = send(pws->fd, buf, len, flags)) < 0 ) 
775     {  
776         length = SOCKET_ERROR;
777         pwsi->err = wsaErrno();
778     }
779     notify_client(pws, WS_FD_WRITE);
780     return (INT16)length;
781   }
782   return SOCKET_ERROR;
783 }
784
785 INT16 WINSOCK_sendto(SOCKET16 s, char *buf, INT16 len, INT16 flags,
786                      struct sockaddr *to, INT16 tolen)
787 {
788   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
789   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
790
791   dprintf_winsock(stddeb, "WS_SENDTO(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
792                           (unsigned)pwsi, s, (unsigned) buf, len, flags);
793   if( _check_ws(pwsi, pws) )
794   {
795     int         length;
796
797     if ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 )
798     {
799         length = SOCKET_ERROR;
800         pwsi->err = wsaErrno();
801     }
802     notify_client(pws, WS_FD_WRITE);
803     return (INT16)length;
804   }
805   return SOCKET_ERROR;
806 }
807
808 INT16 WINSOCK_setsockopt(SOCKET16 s, INT16 level, INT16 optname, 
809                          char *optval, INT16 optlen)
810 {
811   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
812   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
813
814   dprintf_winsock(stddeb, "WS_SETSOCKOPT(%08x): socket %04x, level %d, opt %d, ptr %08x, len %d\n",
815                           (unsigned)pwsi, s, level, optname, (int) optval, optlen);
816   if( _check_ws(pwsi, pws) )
817   {
818     int         linger32[2];
819     convert_sockopt(&level, &optname);
820     if( optname == SO_LINGER )
821     {
822         INT16*     ptr = (INT16*)optval;
823         linger32[0] = ptr[0];
824         linger32[1] = ptr[1]; 
825         optval = (char*)&linger32;
826         optlen = sizeof(linger32);
827     }
828     if (setsockopt(pws->fd, level, optname, optval, optlen) == 0) return 0;
829     pwsi->err = wsaErrno();
830   }
831   return SOCKET_ERROR;
832 }
833
834 INT16 WINSOCK_shutdown(SOCKET16 s, INT16 how)
835 {
836   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
837   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
838
839   dprintf_winsock(stddeb, "WS_SHUTDOWN(%08x): socket %04x, how %i\n",
840                            (unsigned)pwsi, s, how );
841   if( _check_ws(pwsi, pws) )
842   {
843     pws->flags |= WS_FD_INACTIVE;
844     cancel_async_select(pws);
845
846     if (shutdown(pws->fd, how) == 0) return 0;
847     pwsi->err = wsaErrno();
848   }
849   return SOCKET_ERROR;
850 }
851
852 SOCKET16 WINSOCK_socket(INT16 af, INT16 type, INT16 protocol)
853 {
854   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
855
856   dprintf_winsock(stddeb, "WS_SOCKET(%08x): af=%d type=%d protocol=%d\n", 
857                           (unsigned)pwsi, af, type, protocol);
858
859   if( pwsi )
860   {
861     int         sock;
862
863     /* check the socket family */
864     switch(af) 
865     {
866         case AF_INET:
867         case AF_UNSPEC: break;
868         default:        pwsi->err = WSAEAFNOSUPPORT; return INVALID_SOCKET;
869     }
870
871     /* check the socket type */
872     switch(type) 
873     {
874         case SOCK_STREAM:
875         case SOCK_DGRAM:
876         case SOCK_RAW: break;
877         default:       pwsi->err = WSAESOCKTNOSUPPORT; return INVALID_SOCKET;
878     }
879
880     /* check the protocol type */
881     if ( protocol < 0 )  /* don't support negative values */
882     { pwsi->err = WSAEPROTONOSUPPORT; return INVALID_SOCKET; }
883
884     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
885         switch(protocol) 
886         {
887           case IPPROTO_TCP:
888              if (type == SOCK_STREAM) { af = AF_INET; break; }
889           case IPPROTO_UDP:
890              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
891           default: pwsi->err = WSAEPROTOTYPE; return INVALID_SOCKET;
892         }
893
894     if ((sock = socket(af, type, protocol)) >= 0) 
895     {
896         ws_socket*      pnew = wsi_alloc_socket(pwsi, sock);
897
898         dprintf_winsock(stddeb,"\tcreated %04x (handle %i)\n", sock, (UINT16)WS_PTR2HANDLE(pnew));
899
900         if( pnew ) return (SOCKET16)WS_PTR2HANDLE(pnew);
901         {
902           close(sock);
903           pwsi->err = WSAENOBUFS;
904           return INVALID_SOCKET;
905         }
906     }
907
908     if (errno == EPERM) /* raw socket denied */
909     {
910         fprintf(stderr, "WS_SOCKET: not enough privileges\n");
911         pwsi->err = WSAESOCKTNOSUPPORT;
912     } else pwsi->err = wsaErrno();
913   }
914  
915   dprintf_winsock(stddeb, "\t\tfailed!\n");
916   return INVALID_SOCKET;
917 }
918     
919
920 /* ----- database functions 
921  *
922  * Note that ws_...ent structures we return have SEGPTR pointers inside them.
923  */
924
925 static char*    NULL_STRING = "NULL";
926
927 /*
928 struct WIN_hostent *
929 */
930 SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT16 len, INT16 type)
931 {
932   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
933
934   dprintf_winsock(stddeb, "WS_GetHostByAddr(%08x): ptr %8x, len %d, type %d\n", 
935                           (unsigned)pwsi, (unsigned) addr, len, type);
936   if( pwsi )
937   {
938     struct hostent*     host;
939     if( (host = gethostbyaddr(addr, len, type)) != NULL )
940       if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
941           return SEGPTR_GET(pwsi->buffer);
942       else pwsi->err = WSAENOBUFS;
943     else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
944   } 
945   return NULL;
946 }
947
948 /*
949 struct WIN_hostent *
950 */
951 SEGPTR WINSOCK_gethostbyname(const char *name)
952 {
953   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
954
955   dprintf_winsock(stddeb, "WS_GetHostByName(%08x): %s\n",
956                           (unsigned)pwsi, (name)?name:"NULL");
957   if( pwsi )
958   {
959     struct hostent*     host;
960     if( (host = gethostbyname(name)) != NULL )
961       if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
962           return SEGPTR_GET(pwsi->buffer);
963       else pwsi->err = WSAENOBUFS;
964     else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
965   }
966   return NULL;
967 }
968
969 INT16 WINSOCK_gethostname(char *name, INT16 namelen)
970 {
971   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
972
973   dprintf_winsock(stddeb, "WS_GetHostName(%08x): name %s, len %d\n", 
974                           (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
975   if( pwsi )
976   {
977     if (gethostname(name, namelen) == 0) return 0;
978     pwsi->err = (errno == EINVAL) ? WSAEFAULT : wsaErrno();
979   }
980   return SOCKET_ERROR;
981 }
982
983 /*
984 struct WIN_protoent *
985 */
986 SEGPTR WINSOCK_getprotobyname(char *name)
987 {
988   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
989
990   dprintf_winsock(stddeb, "WS_GetProtoByName(%08x): %s\n",
991                           (unsigned)pwsi, (name)?name:NULL_STRING);
992   if( pwsi )
993   {
994     struct protoent*     proto;
995     if( (proto = getprotobyname(name)) != NULL )
996       if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
997           return SEGPTR_GET(pwsi->buffer);
998       else pwsi->err = WSAENOBUFS;
999     else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1000   }
1001   return NULL;
1002 }
1003
1004 /*
1005 struct WIN_protoent *
1006 */
1007 SEGPTR WINSOCK_getprotobynumber(INT16 number)
1008 {
1009   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1010
1011   dprintf_winsock(stddeb, "WS_GetProtoByNumber(%08x): %i\n", (unsigned)pwsi, number);
1012
1013   if( pwsi )
1014   {
1015     struct protoent*     proto;
1016     if( (proto = getprotobynumber(number)) != NULL )
1017       if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
1018           return SEGPTR_GET(pwsi->buffer);
1019       else pwsi->err = WSAENOBUFS;
1020     else pwsi->err = WSANO_DATA;
1021   }
1022   return NULL;
1023 }
1024
1025 /*
1026 struct WIN_servent *
1027 */
1028 SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
1029 {
1030   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1031
1032   dprintf_winsock(stddeb, "WS_GetServByName(%08x): '%s', '%s'\n", 
1033                           (unsigned)pwsi, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
1034
1035   if( pwsi )
1036   {
1037     struct servent*     serv;
1038     if( (serv = getservbyname(name, proto)) != NULL )
1039       if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
1040           return SEGPTR_GET(pwsi->buffer);
1041       else pwsi->err = WSAENOBUFS;
1042     else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1043   }
1044   return NULL;
1045 }
1046
1047 /*
1048 struct WIN_servent *
1049 */
1050 SEGPTR WINSOCK_getservbyport(INT16 port, const char *proto)
1051 {
1052   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1053
1054   dprintf_winsock(stddeb, "WS_GetServByPort(%08x): %i, '%s'\n",
1055                           (unsigned)pwsi, (int)port, (proto)?proto:NULL_STRING);
1056   if( pwsi )
1057   {
1058     struct servent*     serv;
1059     if( (serv = getservbyport(port, proto)) != NULL )
1060       if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
1061           return SEGPTR_GET(pwsi->buffer);
1062       else pwsi->err = WSAENOBUFS;
1063     else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1064   }
1065   return NULL;
1066 }
1067
1068
1069 /* ----------------------------------- Windows sockets extensions -- *
1070  *                                                                   *
1071  * ----------------------------------------------------------------- */
1072
1073 static int aop_control(ws_async_op* p_aop, int flag )
1074 {
1075   unsigned      lLength;
1076
1077   read(p_aop->fd[0], &lLength, sizeof(unsigned));
1078   if( LOWORD(lLength) )
1079     if( (int)LOWORD(lLength) <= p_aop->buflen )
1080     {
1081       char* buffer = (char*)PTR_SEG_TO_LIN(p_aop->buffer_base);
1082       read(p_aop->fd[0], buffer, LOWORD(lLength));
1083       switch( p_aop->flags )
1084       {
1085         case WSMSG_ASYNC_HOSTBYNAME:
1086         case WSMSG_ASYNC_HOSTBYADDR: 
1087              fixup_wshe((struct ws_hostent*)buffer, p_aop->buffer_base); break;
1088         case WSMSG_ASYNC_PROTOBYNAME:
1089         case WSMSG_ASYNC_PROTOBYNUM:
1090              fixup_wspe((struct ws_protoent*)buffer, p_aop->buffer_base); break;
1091         case WSMSG_ASYNC_SERVBYNAME:
1092         case WSMSG_ASYNC_SERVBYPORT:
1093              fixup_wsse((struct ws_servent*)buffer, p_aop->buffer_base); break;
1094         default:
1095              if( p_aop->flags ) fprintf(stderr,"Received unknown async request!\n"); 
1096              return AOP_CONTROL_REMOVE;
1097       }
1098     }
1099     else lLength =  ((UINT32)LOWORD(lLength)) | ((unsigned)WSAENOBUFS << 16);
1100
1101 #if 0
1102   printf("async op completed: hWnd [%04x], uMsg [%04x], aop [%04x], event [%08x]\n",
1103          p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
1104 #endif
1105
1106   PostMessage16(p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
1107   return AOP_CONTROL_REMOVE;
1108 }
1109
1110
1111 static HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, LPCSTR init,
1112                                  INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen, UINT32 flag)
1113 {
1114   /* queue 'flag' request and fork off its handler */
1115
1116   async_ctl.ws_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op));
1117
1118   if( async_ctl.ws_aop )
1119   {
1120       HANDLE16        handle = (HANDLE16)WS_PTR2HANDLE(async_ctl.ws_aop);
1121
1122       if( pipe(async_ctl.ws_aop->fd) == 0 )
1123       {
1124         async_ctl.init = (char*)init;
1125         async_ctl.lLength = len;
1126         async_ctl.lEvent = type;
1127
1128         async_ctl.ws_aop->hWnd = hWnd;
1129         async_ctl.ws_aop->uMsg = uMsg;
1130
1131         async_ctl.ws_aop->buffer_base = sbuf; async_ctl.ws_aop->buflen = buflen;
1132         async_ctl.ws_aop->flags = flag;
1133         async_ctl.ws_aop->aop_control = &aop_control;
1134         WINSOCK_link_async_op( async_ctl.ws_aop );
1135
1136         async_ctl.ws_aop->pid = fork();
1137         if( async_ctl.ws_aop->pid )
1138         {
1139             close(async_ctl.ws_aop->fd[1]);        /* write endpoint */
1140
1141            /* Damn, BSD'ish SIGIO doesn't work on pipes/streams
1142             *
1143             * async_io(async_ctl.ws_aop->fd[0], 1);
1144             */
1145
1146             dprintf_winsock(stddeb, "\tasync_op = %04x (child %i)\n",
1147                                     handle, async_ctl.ws_aop->pid);
1148             return handle;
1149         } else
1150                 /* child process */
1151                  {
1152                    close(async_ctl.ws_aop->fd[0]); /* read endpoint */
1153                    switch(flag)
1154                    {
1155                      case WSMSG_ASYNC_HOSTBYADDR:
1156                      case WSMSG_ASYNC_HOSTBYNAME:
1157                         WS_do_async_gethost(pwsi,flag);
1158                      case WSMSG_ASYNC_PROTOBYNUM:
1159                      case WSMSG_ASYNC_PROTOBYNAME:
1160                         WS_do_async_getproto(pwsi,flag);
1161                      case WSMSG_ASYNC_SERVBYPORT:
1162                      case WSMSG_ASYNC_SERVBYNAME:
1163                         WS_do_async_getserv(pwsi,flag);
1164                    }
1165                    _exit(0); /* skip atexit()'ed cleanup */
1166                  }
1167       }
1168       WS_FREE(async_ctl.ws_aop);
1169       pwsi->err = wsaErrno();
1170   } else pwsi->err = WSAEWOULDBLOCK;
1171   return 0;
1172 }
1173
1174 HANDLE16 WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
1175                                INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen)
1176 {
1177   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1178
1179   dprintf_winsock(stddeb, "WS_AsyncGetHostByAddr(%08x): hwnd %04x, msg %04x, addr %08x[%i]\n",
1180                           (unsigned)pwsi, hWnd, uMsg, (unsigned)addr , len );
1181
1182   if( pwsi ) 
1183     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, addr, len,
1184                             type, sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR );
1185   return 0;
1186 }
1187
1188
1189 HANDLE16 WSAAsyncGetHostByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
1190                                SEGPTR sbuf, INT16 buflen)
1191 {
1192   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1193
1194   dprintf_winsock(stddeb, "WS_AsyncGetHostByName(%08x): hwnd %04x, msg %04x, host %s, buffer %i\n",
1195                           (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen );
1196
1197   if( pwsi )
1198     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
1199                             0, sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME );
1200   return 0;
1201 }                     
1202
1203
1204 HANDLE16 WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
1205                                 SEGPTR sbuf, INT16 buflen)
1206 {
1207   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1208
1209   dprintf_winsock(stddeb, "WS_AsyncGetProtoByName(%08x): hwnd %04x, msg %04x, protocol %s\n",
1210                           (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING );
1211
1212   if( pwsi )
1213     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
1214                             0, sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME );
1215   return 0;
1216 }
1217
1218
1219 HANDLE16 WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 uMsg, INT16 number, 
1220                                   SEGPTR sbuf, INT16 buflen)
1221 {
1222   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1223
1224   dprintf_winsock(stddeb, "WS_AsyncGetProtoByNumber(%08x): hwnd %04x, msg %04x, num %i\n",
1225                           (unsigned)pwsi, hWnd, uMsg, number );
1226
1227   if( pwsi )
1228     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, NULL, 0,
1229                             number, sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM );
1230   return 0;
1231 }
1232
1233
1234 HANDLE16 WSAAsyncGetServByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
1235                                LPCSTR proto, SEGPTR sbuf, INT16 buflen)
1236 {
1237   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1238
1239   dprintf_winsock(stddeb, "WS_AsyncGetServByName(%08x): hwnd %04x, msg %04x, name %s, proto %s\n",
1240                    (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING );
1241
1242   if( pwsi )
1243   { 
1244     async_ctl.buffer = (char*)proto;
1245     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
1246                             0, sbuf, buflen, WSMSG_ASYNC_SERVBYNAME );
1247   }
1248   return 0;
1249 }
1250
1251
1252 HANDLE16 WSAAsyncGetServByPort(HWND16 hWnd, UINT16 uMsg, INT16 port, 
1253                                LPCSTR proto, SEGPTR sbuf, INT16 buflen)
1254 {
1255   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1256
1257   dprintf_winsock(stddeb, "WS_AsyncGetServByPort(%08x): hwnd %04x, msg %04x, port %i, proto %s\n",
1258                            (unsigned)pwsi, hWnd, uMsg, port, (proto)?proto:NULL_STRING );
1259
1260   if( pwsi )
1261     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, proto, 0,
1262                             port, sbuf, buflen, WSMSG_ASYNC_SERVBYPORT );
1263   return 0;
1264 }
1265
1266 INT16 WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
1267 {
1268   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1269   ws_async_op*          p_aop = (ws_async_op*)WS_HANDLE2PTR(hAsyncTaskHandle);
1270
1271   dprintf_winsock(stddeb, "WS_CancelAsyncRequest(%08x): handle %04x\n", 
1272                            (unsigned)pwsi, hAsyncTaskHandle);
1273   if( pwsi )
1274     if( WINSOCK_check_async_op(p_aop) )
1275     {
1276         kill(p_aop->pid, SIGKILL); 
1277         waitpid(p_aop->pid, NULL, 0); /* just in case */
1278         close(p_aop->fd[0]);
1279         WINSOCK_unlink_async_op(p_aop);
1280         WS_FREE(p_aop);
1281         return 0;
1282     }
1283     else pwsi->err = WSAEINVAL;
1284   return SOCKET_ERROR;
1285 }
1286
1287 /* ----- asynchronous select() */
1288
1289 int cancel_async_select(ws_socket* pws)
1290 {
1291   if( pws->p_aop )
1292   {
1293     kill(pws->p_aop->pid, SIGKILL);
1294     waitpid(pws->p_aop->pid, NULL, 0);
1295     WS_FREE(pws->p_aop); 
1296     pws->p_aop = NULL;
1297     return 1;
1298   }
1299   return 0;
1300 }
1301
1302 void _sigusr1_handler_parent(int sig)
1303 {
1304   /* child process puts MTYPE_CLIENT data packet into the
1305    * 'async_qid' message queue and signals us with SIGUSR1.
1306    * This handler reads the queue and posts 'uMsg' notification
1307    * message.
1308    */
1309
1310   ipc_packet            ipack;
1311
1312   signal( SIGUSR1, _sigusr1_handler_parent);
1313   while( msgrcv(async_qid, (struct msgbuf*)&ipack,
1314           MTYPE_CLIENT_SIZE, MTYPE_CLIENT, IPC_NOWAIT) != -1 )
1315   {
1316     if( ipack.wParam && abs((short)ipack.wParam) < 32768 )
1317     {
1318       ws_socket*        pws = (ws_socket*)WS_HANDLE2PTR(ipack.wParam);
1319       if( pws->p_aop && abs((char*)_ws_stub - (char*)pws->p_aop) < 32768 )
1320       {
1321           pws->flags &= ~(ipack.lParam);
1322 #if 0
1323           printf("async event - hWnd %04x, uMsg %04x [%08x]\n",
1324                   pws->p_aop->hWnd, pws->p_aop->uMsg, ipack.lParam );
1325 #endif
1326           PostMessage16(pws->p_aop->hWnd, pws->p_aop->uMsg, 
1327                         (WPARAM16)ipack.wParam, (LPARAM)ipack.lParam );
1328       }
1329       else fprintf(stderr,"AsyncSelect:stray async_op in socket %04x!\n", ipack.wParam);
1330     }
1331     else fprintf(stderr,"AsyncSelect:stray socket at %04x!\n", ipack.wParam);
1332   }
1333 }
1334
1335 int notify_client( ws_socket* pws, unsigned flag )
1336 {
1337   if( pws->p_aop && ((pws->p_aop->flags & flag) ||
1338                      (flag == WS_FD_CONNECTED && pws->flags & WS_FD_CONNECT)) )
1339   {
1340      async_ctl.ip.mtype = MTYPE_PARENT;
1341      async_ctl.ip.lParam = flag;
1342      while( msgsnd(async_qid, (struct msgbuf*)&(async_ctl.ip),
1343                                MTYPE_PARENT_SIZE, 0) == -1 )
1344      { 
1345         if( errno == EINTR ) continue;
1346         else
1347         {
1348             perror("AsyncSelect(parent)"); 
1349             cancel_async_select(pws);
1350             pws->flags &= WS_FD_INTERNAL;
1351             return 0;
1352         }
1353      }
1354      kill(pws->p_aop->pid, SIGUSR1);
1355      return 1;
1356   }
1357   return 0;
1358 }
1359
1360 INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
1361 {
1362     ws_async_op*        p_aop;
1363
1364     if( cancel_async_select(pws) )  /* delete old async handler if any */
1365       pws->flags &= WS_FD_INTERNAL;
1366
1367     if( lEvent == 0 ) return 0;
1368
1369     /* setup async handler - some data may be redundant */
1370
1371     WINSOCK_unblock_io(pws->fd, 1);
1372     if( (p_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op))) )
1373     {
1374       p_aop->hWnd = hWnd;
1375       p_aop->uMsg = uMsg;
1376       pws->p_aop = p_aop;
1377
1378       async_ctl.lEvent = p_aop->flags = lEvent;
1379       async_ctl.ws_sock = pws;
1380       async_ctl.ip.wParam = (UINT16)WS_PTR2HANDLE(pws);
1381       async_ctl.ip.lParam = 0;
1382
1383       p_aop->pid = fork();
1384       if( p_aop->pid != -1 )
1385         if( p_aop->pid == 0 ) WINSOCK_do_async_select(); /* child process */
1386         else pws->flags |= lEvent;
1387
1388       signal( SIGUSR1, _sigusr1_handler_parent );
1389       return 0;                                  /* Wine process */
1390     }
1391     return SOCKET_ERROR;
1392 }
1393
1394 INT16 WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
1395 {
1396   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
1397   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
1398
1399   dprintf_winsock(stddeb, "WS_AsyncSelect(%08x): %04x, hWnd %04x, uMsg %04x, event %08x\n",
1400                           (unsigned)pwsi, s, hWnd, uMsg, (unsigned)lEvent );
1401   if( _check_ws(pwsi, pws) )
1402     if( init_async_select(pws, hWnd, uMsg, lEvent) == 0 ) return 0;
1403     else pwsi->err = WSAENOBUFS;
1404   return SOCKET_ERROR; 
1405 }
1406
1407 /* ----- miscellaneous */
1408
1409 INT16 __WSAFDIsSet(SOCKET16 fd, ws_fd_set *set)
1410 {
1411   int i = set->fd_count;
1412   
1413   dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set);
1414     
1415   while (i--)
1416       if (set->fd_array[i] == fd) return 1;
1417   return 0;
1418 }                                                            
1419
1420 BOOL16 WSAIsBlocking(void)
1421 {
1422   /* By default WinSock should set all its sockets to non-blocking mode
1423    * and poll in PeekMessage loop when processing "blocking" ones. This 
1424    * function * is supposed to tell if program is in this loop. Our 
1425    * blocking calls are truly blocking so we always return FALSE.
1426    *
1427    * Note: It is allowed to call this function without prior WSAStartup().
1428    */
1429
1430   dprintf_winsock(stddeb, "WS_IsBlocking()\n");
1431   return FALSE;
1432 }
1433
1434 INT16 WSACancelBlockingCall(void)
1435 {
1436   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1437
1438   dprintf_winsock(stddeb, "WS_CancelBlockingCall(%08x)\n", (unsigned)pwsi);
1439
1440   if( pwsi ) return 0;
1441   return SOCKET_ERROR;
1442 }
1443
1444 FARPROC16 WSASetBlockingHook16(FARPROC16 lpBlockFunc)
1445 {
1446   FARPROC16             prev;
1447   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1448
1449   dprintf_winsock(stddeb, "WS_SetBlockingHook(%08x): hook %08x\n", 
1450                           (unsigned)pwsi, (unsigned) lpBlockFunc);
1451
1452   if( pwsi ) { 
1453       prev = pwsi->blocking_hook; 
1454       pwsi->blocking_hook = lpBlockFunc; 
1455       return prev; 
1456   }
1457   return 0;
1458 }
1459
1460 FARPROC32 WSASetBlockingHook32(FARPROC32 lpBlockFunc)
1461 {
1462     fprintf( stderr, "Empty stub WSASetBlockingHook32(%p)\n", lpBlockFunc );
1463     return NULL;
1464 }
1465
1466 INT16 WSAUnhookBlockingHook(void)
1467 {
1468   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1469
1470   dprintf_winsock(stddeb, "WS_UnhookBlockingHook(%08x)\n", (unsigned)pwsi);
1471   if( pwsi ) return (INT16)(INT32)(pwsi->blocking_hook = (FARPROC16)NULL);
1472   return SOCKET_ERROR;
1473 }
1474
1475 VOID
1476 WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,LPDWORD x5,LPDWORD x6) 
1477 {
1478         fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n",
1479                 x1,x2,x3,x4,x5,x6
1480         );
1481         fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
1482                 x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0
1483         );
1484         return;
1485 }
1486 /* ----------------------------------- end of API stuff */
1487
1488
1489
1490 /* ----------------------------------- helper functions */
1491
1492 static int list_size(char** l, int item_size)
1493 {
1494   int i,j = 0;
1495   if(l)
1496   { for(i=0;l[i];i++) 
1497         j += (item_size) ? item_size : strlen(l[i]) + 1;
1498     j += (i + 1) * sizeof(char*); }
1499   return j;
1500 }
1501
1502 static int list_dup(char** l_src, char* ref, char* base, int item_size)
1503
1504    /* base is either either equal to ref or 0 or SEGPTR */
1505
1506    char*                p = ref;
1507    char**               l_to = (char**)ref;
1508    int                  i,j,k;
1509
1510    for(j=0;l_src[j];j++) ;
1511    p += (j + 1) * sizeof(char*);
1512    for(i=0;i<j;i++)
1513    { l_to[i] = base + (p - ref);
1514      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
1515      memcpy(p, l_src[i], k); p += k; }
1516    l_to[i] = NULL;
1517    return (p - ref);
1518 }
1519
1520 /* ----- hostent */
1521
1522 static int hostent_size(struct hostent* p_he)
1523 {
1524   int size = 0;
1525   if( p_he )
1526   { size  = sizeof(struct hostent); 
1527     size += strlen(p_he->h_name) + 1;
1528     size += list_size(p_he->h_aliases, 0);  
1529     size += list_size(p_he->h_addr_list, p_he->h_length ); }
1530   return size;
1531 }
1532
1533 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
1534 {
1535    /* Duplicate hostent structure and flatten data (with its pointers)
1536     * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or 
1537     * relative to 0 depending on "flag" value. Return data size (also 
1538     * in the pwsi->buflen).
1539     */
1540
1541    int size = hostent_size(p_he);
1542    if( size )
1543    {
1544      char*           p_name,*p_aliases,*p_addr,*p_base,*p;
1545
1546      _check_buffer(pwsi, size);
1547      p = pwsi->buffer;
1548      p_base = (flag & WS_DUP_OFFSET) ? NULL
1549                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
1550      p += (flag & WS_DUP_SEGPTR) ? sizeof(struct ws_hostent) : sizeof(struct hostent);
1551      p_name = p;
1552      strcpy(p, p_he->h_name); p += strlen(p) + 1;
1553      p_aliases = p;
1554      p += list_dup(p_he->h_aliases, p, p_base + (p - pwsi->buffer), 0);
1555      p_addr = p;
1556      list_dup(p_he->h_addr_list, p, p_base + (p - pwsi->buffer), p_he->h_length);
1557      if( !(flag & WS_DUP_SEGPTR) )
1558      { struct hostent* p_to = (struct hostent*)pwsi->buffer;
1559        p_to->h_addrtype = p_he->h_addrtype; p_to->h_length = p_he->h_length;
1560        p_to->h_name = p_base + (p_name - pwsi->buffer);
1561        p_to->h_aliases = (char**)(p_base + (p_aliases - pwsi->buffer));
1562        p_to->h_addr_list = (char**)(p_base + (p_addr - pwsi->buffer)); }
1563      else
1564      { struct ws_hostent* p_to = (struct ws_hostent*)pwsi->buffer;
1565        p_to->h_addrtype = (INT16)p_he->h_addrtype; 
1566        p_to->h_length = (INT16)p_he->h_length;
1567        p_to->h_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
1568        p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
1569        p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - pwsi->buffer));
1570
1571        return (size + sizeof(struct ws_hostent) - sizeof(struct hostent)); }
1572    }
1573    return size;
1574 }
1575
1576 void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base)
1577 {
1578    /* add 'base' to ws_hostent pointers to convert them from offsets */ 
1579
1580    int i;
1581    unsigned*    p_aliases,*p_addr;
1582
1583    p_aliases = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_aliases); 
1584    p_addr = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_addr_list);
1585    ((unsigned)(p_wshe->h_name)) += (unsigned)base;
1586    ((unsigned)(p_wshe->h_aliases)) += (unsigned)base;
1587    ((unsigned)(p_wshe->h_addr_list)) += (unsigned)base;
1588    for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
1589    for(i=0;p_addr[i];i++) p_addr[i] += (unsigned)base;
1590 }
1591
1592 /* ----- protoent */
1593
1594 static int protoent_size(struct protoent* p_pe)
1595 {
1596   int size = 0;
1597   if( p_pe )
1598   { size  = sizeof(struct protoent);
1599     size += strlen(p_pe->p_name) + 1;
1600     size += list_size(p_pe->p_aliases, 0); }
1601   return size;
1602 }
1603
1604 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
1605 {
1606    int size = protoent_size(p_pe);
1607    if( size )
1608    {
1609      char*            p_name,*p_aliases,*p_base,*p;
1610
1611      _check_buffer(pwsi, size);
1612      p = pwsi->buffer; 
1613      p_base = (flag & WS_DUP_OFFSET) ? NULL
1614                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
1615      p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_protoent) : sizeof(struct protoent);
1616      p_name = p;
1617      strcpy(p, p_pe->p_name); p += strlen(p) + 1;
1618      p_aliases = p;
1619      list_dup(p_pe->p_aliases, p, p_base + (p - pwsi->buffer), 0);
1620      if( !(flag & WS_DUP_NATIVE) )
1621      { struct protoent* p_to = (struct protoent*)pwsi->buffer;
1622        p_to->p_proto = p_pe->p_proto;
1623        p_to->p_name = p_base + (p_name - pwsi->buffer); 
1624        p_to->p_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
1625      else
1626      { struct ws_protoent* p_to = (struct ws_protoent*)pwsi->buffer;
1627        p_to->p_proto = (INT16)p_pe->p_proto;
1628        p_to->p_name = (SEGPTR)(p_base) + (p_name - pwsi->buffer);
1629        p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - pwsi->buffer)); 
1630        return (size + sizeof(struct ws_protoent) - sizeof(struct protoent)); }
1631    }
1632    return size;
1633 }
1634
1635 void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base)
1636 {
1637    int i;
1638    unsigned*       p_aliases = (unsigned*)((char*)p_wspe + (unsigned)p_wspe->p_aliases); 
1639    ((unsigned)(p_wspe->p_name)) += (unsigned)base;
1640    ((unsigned)(p_wspe->p_aliases)) += (unsigned)base;
1641    for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
1642 }
1643
1644 /* ----- servent */
1645
1646 static int servent_size(struct servent* p_se)
1647 {
1648   int size = 0;
1649   if( p_se )
1650   { size += sizeof(struct servent);
1651     size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
1652     size += list_size(p_se->s_aliases, 0); }
1653   return size;
1654 }
1655
1656 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
1657 {
1658    int size = servent_size(p_se);
1659    if( size )
1660    {
1661      char*           p_name,*p_aliases,*p_proto,*p_base,*p;
1662
1663      _check_buffer(pwsi, size);
1664      p = pwsi->buffer;
1665      p_base = (flag & WS_DUP_OFFSET) ? NULL 
1666                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
1667      p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_servent) : sizeof(struct servent);
1668      p_name = p;
1669      strcpy(p, p_se->s_name); p += strlen(p) + 1;
1670      p_proto = p;
1671      strcpy(p, p_se->s_proto); p += strlen(p) + 1;
1672      p_aliases = p;
1673      list_dup(p_se->s_aliases, p, p_base + (p - pwsi->buffer), 0);
1674
1675      if( !(flag & WS_DUP_SEGPTR) )
1676      { struct servent* p_to = (struct servent*)pwsi->buffer;
1677        p_to->s_port = p_se->s_port;
1678        p_to->s_name = p_base + (p_name - pwsi->buffer); 
1679        p_to->s_proto = p_base + (p_proto - pwsi->buffer);
1680        p_to->s_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
1681      else
1682      { struct ws_servent* p_to = (struct ws_servent*)pwsi->buffer;
1683        p_to->s_port = (INT16)p_se->s_port;
1684        p_to->s_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
1685        p_to->s_proto = (SEGPTR)(p_base + (p_proto - pwsi->buffer));
1686        p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer)); 
1687        return (size + sizeof(struct ws_servent) - sizeof(struct servent)); }
1688    }
1689    return size;
1690 }
1691
1692 void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base)
1693 {
1694    int i;
1695    unsigned*       p_aliases = (unsigned*)((char*)p_wsse + (unsigned)p_wsse->s_aliases);
1696    ((unsigned)(p_wsse->s_name)) += (unsigned)base;
1697    ((p_wsse->s_proto)) += (unsigned)base;
1698    ((p_wsse->s_aliases)) += (unsigned)base;
1699    for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
1700 }
1701
1702 /* ----------------------------------- error handling */
1703
1704 UINT16 wsaErrno(void)
1705 {
1706     int loc_errno = errno; 
1707 #if defined(__FreeBSD__)
1708        dprintf_winsock(stderr, "winsock: errno %d, (%s).\n", 
1709                                          errno, sys_errlist[errno]);
1710 #else
1711        dprintf_winsock(stderr, "winsock: errno %d\n", errno);
1712 #endif
1713
1714     switch(loc_errno)
1715     {
1716         case EINTR:             return WSAEINTR;
1717         case EBADF:             return WSAEBADF;
1718         case EACCES:            return WSAEACCES;
1719         case EFAULT:            return WSAEFAULT;
1720         case EINVAL:            return WSAEINVAL;
1721         case EMFILE:            return WSAEMFILE;
1722         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
1723         case EINPROGRESS:       return WSAEINPROGRESS;
1724         case EALREADY:          return WSAEALREADY;
1725         case ENOTSOCK:          return WSAENOTSOCK;
1726         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
1727         case EMSGSIZE:          return WSAEMSGSIZE;
1728         case EPROTOTYPE:        return WSAEPROTOTYPE;
1729         case ENOPROTOOPT:       return WSAENOPROTOOPT;
1730         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
1731         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
1732         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
1733         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
1734         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
1735         case EADDRINUSE:        return WSAEADDRINUSE;
1736         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
1737         case ENETDOWN:          return WSAENETDOWN;
1738         case ENETUNREACH:       return WSAENETUNREACH;
1739         case ENETRESET:         return WSAENETRESET;
1740         case ECONNABORTED:      return WSAECONNABORTED;
1741         case ECONNRESET:        return WSAECONNRESET;
1742         case ENOBUFS:           return WSAENOBUFS;
1743         case EISCONN:           return WSAEISCONN;
1744         case ENOTCONN:          return WSAENOTCONN;
1745         case ESHUTDOWN:         return WSAESHUTDOWN;
1746         case ETOOMANYREFS:      return WSAETOOMANYREFS;
1747         case ETIMEDOUT:         return WSAETIMEDOUT;
1748         case ECONNREFUSED:      return WSAECONNREFUSED;
1749         case ELOOP:             return WSAELOOP;
1750         case ENAMETOOLONG:      return WSAENAMETOOLONG;
1751         case EHOSTDOWN:         return WSAEHOSTDOWN;
1752         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
1753         case ENOTEMPTY:         return WSAENOTEMPTY;
1754 #ifdef EPROCLIM
1755         case EPROCLIM:          return WSAEPROCLIM;
1756 #endif
1757 #ifdef EUSERS
1758         case EUSERS:            return WSAEUSERS;
1759 #endif
1760 #ifdef EDQUOT
1761         case EDQUOT:            return WSAEDQUOT;
1762 #endif
1763 #ifdef ESTALE
1764         case ESTALE:            return WSAESTALE;
1765 #endif
1766 #ifdef EREMOTE
1767         case EREMOTE:           return WSAEREMOTE;
1768 #endif
1769
1770        /* just in case we ever get here and there are no problems */
1771         case 0:                 return 0;
1772         default:
1773                 fprintf(stderr, "winsock: unknown errno %d!\n", errno);
1774                 return WSAEOPNOTSUPP;
1775     }
1776 }
1777
1778 UINT16 wsaHerrno(void)
1779 {
1780     int         loc_errno = h_errno;
1781
1782 #if defined(__FreeBSD__)
1783     dprintf_winsock(stderr, "winsock: h_errno %d, (%s).\n", 
1784                     h_errno, sys_errlist[h_errno]);
1785 #else
1786     dprintf_winsock(stderr, "winsock: h_errno %d.\n", h_errno);
1787 #ifndef sun
1788     if( debugging_winsock )  herror("wine: winsock: wsaherrno");
1789 #endif
1790 #endif
1791
1792     switch(loc_errno)
1793     {
1794         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
1795         case TRY_AGAIN:         return WSATRY_AGAIN;
1796         case NO_RECOVERY:       return WSANO_RECOVERY;
1797         case NO_DATA:           return WSANO_DATA; 
1798
1799         case 0:                 return 0;
1800         default:
1801                 fprintf(stderr, "winsock: unknown h_errno %d!\n", h_errno);
1802                 return WSAEOPNOTSUPP;
1803     }
1804 }
1805
1806