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