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