Release 950522
[wine] / misc / winsocket.c
1 /*
2  * based on Windows Sockets 1.1 specs
3  * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4  * 
5  * (C) 1993,1994 John Brezak, Erik Bos.
6  */
7  
8 #include <stdio.h>
9 #include <string.h>
10 #include <signal.h>
11 #include <sys/types.h>
12 #include <sys/ipc.h>
13 #include <sys/ioctl.h>
14 #include <sys/msg.h>
15 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <fcntl.h>
19 #include <errno.h>
20 #include <netdb.h>
21 #include <unistd.h>
22 #include "winsock.h"
23 #include "stddebug.h"
24 #include "debug.h"
25
26 static WORD wsa_errno;
27 static int wsa_initted;
28 static key_t wine_key = 0;
29 static FARPROC BlockFunction;
30 static fd_set fd_in_use;
31
32 struct ipc_packet {
33         long    mtype;
34         HANDLE  handle;
35         HWND    hWnd;
36         WORD    wMsg;
37         LONG    lParam;
38 };
39
40 #pragma pack(1)
41
42 #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long))
43 #define MTYPE 0xb0b0eb05
44 #define WINE_PACKED __attribute__ ((packed))
45
46 struct WIN_hostent  {
47         char    *h_name WINE_PACKED;            /* official name of host */
48         char    **h_aliases WINE_PACKED;        /* alias list */
49         int     h_addrtype WINE_PACKED;         /* host address type */
50         int     h_length WINE_PACKED;           /* length of address */
51         char    **h_addr_list WINE_PACKED;      /* list of addresses from name server */
52         char    *names[2];
53         char    hostname[200];
54 };
55
56 struct  WIN_protoent {
57         char    *p_name WINE_PACKED;            /* official protocol name */
58         char    **p_aliases WINE_PACKED;        /* alias list */
59         int     p_proto WINE_PACKED;            /* protocol # */
60 };
61
62 struct  WIN_servent {
63         char    *s_name WINE_PACKED;            /* official service name */
64         char    **s_aliases WINE_PACKED;        /* alias list */
65         int     s_port WINE_PACKED;             /* port # */
66         char    *s_proto WINE_PACKED;           /* protocol to use */
67 };
68
69 struct WinSockHeap {
70         char    ntoa_buffer[32];
71
72         struct  WIN_hostent hostent_addr;
73         struct  WIN_hostent hostent_name;
74         struct  WIN_protoent protoent_name;
75         struct  WIN_protoent protoent_number;
76         struct  WIN_servent servent_name;
77         struct  WIN_servent servent_port;
78
79         struct  WIN_hostent WSAhostent_addr;
80         struct  WIN_hostent WSAhostent_name;
81         struct  WIN_protoent WSAprotoent_name;
82         struct  WIN_protoent WSAprotoent_number;        
83         struct  WIN_servent WSAservent_name;
84         struct  WIN_servent WSAservent_port;
85 };
86 static struct WinSockHeap *heap;
87
88 #pragma pack(4)
89
90 #define dump_sockaddr(a) \
91         fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
92                         ((struct sockaddr_in *)a)->sin_family, \
93                         inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
94                         ntohs(((struct sockaddr_in *)a)->sin_port))
95
96 static WORD wsaerrno(void)
97 {
98 #ifdef DEBUG_WINSOCK
99 #ifndef sun
100 #if defined(__FreeBSD__)
101                 fprintf(stderr, "winsock: errno %d, (%s).\n", 
102                                         errno, sys_errlist[errno]);
103 #else
104                 fprintf(stderr, "winsock: errno %d, (%s).\n", 
105                                         errno, strerror(errno));
106 #endif
107 #else
108                 fprintf(stderr, "winsock: errno %d\n", errno);
109 #endif
110 #endif
111
112         switch(errno)
113         {
114         case EINTR:             return WSAEINTR;
115         case EACCES:            return WSAEACCES;
116         case EFAULT:            return WSAEFAULT;
117         case EINVAL:            return WSAEINVAL;
118         case EMFILE:            return WSAEMFILE;
119         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
120         case EINPROGRESS:       return WSAEINPROGRESS;
121         case EALREADY:          return WSAEALREADY;
122         case EBADF:
123         case ENOTSOCK:          return WSAENOTSOCK;
124         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
125         case EMSGSIZE:          return WSAEMSGSIZE;
126         case EPROTOTYPE:        return WSAEPROTOTYPE;
127         case ENOPROTOOPT:       return WSAENOPROTOOPT;
128         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
129         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
130         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
131         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
132         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
133         case EADDRINUSE:        return WSAEADDRINUSE;
134         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
135         case ENETDOWN:          return WSAENETDOWN;
136         case ENETUNREACH:       return WSAENETUNREACH;
137         case ENETRESET:         return WSAENETRESET;
138         case ECONNABORTED:      return WSAECONNABORTED;
139         case ECONNRESET:        return WSAECONNRESET;
140         case ENOBUFS:           return WSAENOBUFS;
141         case EISCONN:           return WSAEISCONN;
142         case ENOTCONN:          return WSAENOTCONN;
143         case ESHUTDOWN:         return WSAESHUTDOWN;
144         case ETOOMANYREFS:      return WSAETOOMANYREFS;
145         case ETIMEDOUT:         return WSAETIMEDOUT;
146         case ECONNREFUSED:      return WSAECONNREFUSED;
147         case ELOOP:             return WSAELOOP;
148         case ENAMETOOLONG:      return WSAENAMETOOLONG;
149         case EHOSTDOWN:         return WSAEHOSTDOWN;
150         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
151         case ENOTEMPTY:         return WSAENOTEMPTY;
152 #ifdef EPROCLIM
153         case EPROCLIM:          return WSAEPROCLIM;
154 #endif
155         case EUSERS:            return WSAEUSERS;
156         case EDQUOT:            return WSAEDQUOT;
157         case ESTALE:            return WSAESTALE;
158         case EREMOTE:           return WSAEREMOTE;
159
160         default:
161                 fprintf(stderr, "winsock: unknown errorno %d!\n", errno);
162                 return WSAEOPNOTSUPP;
163         }
164 }
165
166 static void errno_to_wsaerrno(void)
167 {
168         wsa_errno = wsaerrno();
169 }
170
171 static void convert_sockopt(INT *level, INT *optname)
172 {
173 /* $%#%!@! why couldn't they use the same values for both winsock and unix ? */
174
175         switch (*level) {
176                 case -1: 
177                         *level = SOL_SOCKET;
178                         switch (*optname) {
179                         case 0x01:      *optname = SO_DEBUG;
180                                         break;
181                         case 0x04:      *optname = SO_REUSEADDR;
182                                         break;
183                         case 0x08:      *optname = SO_KEEPALIVE;
184                                         break;
185                         case 0x10:      *optname = SO_DONTROUTE;
186                                         break;
187                         case 0x20:      *optname = SO_BROADCAST;
188                                         break;
189                         case 0x80:      *optname = SO_LINGER;
190                                         break;
191                         case 0x100:     *optname = SO_OOBINLINE;
192                                         break;
193                         case 0x1001:    *optname = SO_SNDBUF;
194                                         break;
195                         case 0x1002:    *optname = SO_RCVBUF;
196                                         break;
197                         case 0x1007:    *optname = SO_ERROR;
198                                         break;
199                         case 0x1008:    *optname = SO_TYPE;
200                                         break;
201                         default: 
202                                         fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
203                                         break;
204                         }
205                         break;
206                 case 6: *optname = IPPROTO_TCP;
207         }
208 }
209
210 #ifndef WINELIB
211 static void CONVERT_HOSTENT(struct WIN_hostent *heap, struct hostent *host)
212 {
213
214 }
215
216 static void CONVERT_PROTOENT(struct WIN_protoent *heap, struct protoent *proto)
217 {
218
219 }
220
221 static void CONVERT_SERVENT(struct WIN_servent *heap, struct servent *serv)
222 {
223
224 }
225 #else
226 #define CONVERT_HOSTENT(a,b)    memcpy(a, &b, sizeof(a))
227 #define CONVERT_PROTOENT(a,b)   memcpy(a, &b, sizeof(a))
228 #define CONVERT_SERVENT(a,b)    memcpy(a, &b, sizeof(a))
229 #endif
230
231 SOCKET WINSOCK_accept(SOCKET s, struct sockaddr *addr, INT *addrlen)
232 {
233         int sock;
234
235         dprintf_winsock(stddeb, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, *addrlen);
236
237         if ((sock = accept(s, addr, (int *) addrlen)) < 0) {
238                 errno_to_wsaerrno();
239                 return INVALID_SOCKET;
240         }
241         return sock;
242 }
243
244 INT WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
245 {
246         dprintf_winsock(stddeb, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
247         dump_sockaddr(name);
248
249         if (bind(s, name, namelen) < 0) {
250                 errno_to_wsaerrno();
251                 return SOCKET_ERROR;
252         }
253         return 0;
254 }
255
256 INT WINSOCK_closesocket(SOCKET s)
257 {
258         dprintf_winsock(stddeb, "WSA_closesocket: socket %d\n", s);
259
260         FD_CLR(s, &fd_in_use);
261
262         if (close(s) < 0) {
263                 errno_to_wsaerrno();
264                 return SOCKET_ERROR;
265         }
266         return 0;
267 }
268
269 INT WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen)
270 {
271         dprintf_winsock(stddeb, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
272         dump_sockaddr(name);
273
274         if (connect(s, name, namelen) < 0) {
275                 errno_to_wsaerrno();
276                 return SOCKET_ERROR;
277         }
278         return 0;
279 }
280
281 INT WINSOCK_getpeername(SOCKET s, struct sockaddr *name, INT *namelen)
282 {
283         dprintf_winsock(stddeb, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
284         dump_sockaddr(name);
285
286         if (getpeername(s, name, (int *) namelen) < 0) {
287                 errno_to_wsaerrno();
288                 return SOCKET_ERROR;
289         }
290         return 0;
291 }
292
293 INT WINSOCK_getsockname(SOCKET s, struct sockaddr *name, INT *namelen)
294 {
295         dprintf_winsock(stddeb, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
296         if (getsockname(s, name, (int *) namelen) < 0) {
297                 errno_to_wsaerrno();
298                 return SOCKET_ERROR;
299         }
300         return 0;
301 }
302
303 INT
304 WINSOCK_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
305 {
306         dprintf_winsock(stddeb, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen);
307         convert_sockopt(&level, &optname);
308
309         if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) {
310                 errno_to_wsaerrno();
311                 return SOCKET_ERROR;
312         }
313         return 0;
314 }
315
316 u_long WINSOCK_htonl(u_long hostlong)
317 {
318         return( htonl(hostlong) );
319 }         
320
321 u_short WINSOCK_htons(u_short hostshort)
322 {
323         return( htons(hostshort) );
324 }
325
326 u_long WINSOCK_inet_addr(char *cp)
327 {
328         return( inet_addr(cp) );
329 }
330
331 char *WINSOCK_inet_ntoa(struct in_addr in)
332 {
333         char *s;
334
335 /*      dprintf_winsock(stddeb, "WSA_inet_ntoa: %8lx\n", (int) in);*/
336
337         if ((s = inet_ntoa(in)) == NULL) {
338                 errno_to_wsaerrno();
339                 return NULL;
340         }
341
342         strncpy(heap->ntoa_buffer, s, sizeof(heap->ntoa_buffer) );
343
344         return (char *) &heap->ntoa_buffer;
345 }
346
347 INT WINSOCK_ioctlsocket(SOCKET s, long cmd, u_long *argp)
348 {
349         dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %ld, ptr %8x\n", s, cmd, (int) argp);
350
351         if (ioctl(s, cmd, argp) < 0) {
352                 errno_to_wsaerrno();
353                 return SOCKET_ERROR;
354         }
355         return 0;
356 }
357
358 INT WINSOCK_listen(SOCKET s, INT backlog)
359 {
360         dprintf_winsock(stddeb, "WSA_listen: socket %d, backlog %d\n", s, backlog);
361
362         if (listen(s, backlog) < 0) {
363                 errno_to_wsaerrno();
364                 return SOCKET_ERROR;
365         }
366         return 0;
367 }
368
369 u_long WINSOCK_ntohl(u_long netlong)
370 {
371         return( ntohl(netlong) );
372 }
373
374 u_short WINSOCK_ntohs(u_short netshort)
375 {
376         return( ntohs(netshort) );
377 }
378
379 INT WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
380 {
381         int length;
382
383         dprintf_winsock(stddeb, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags);
384
385         if ((length = recv(s, buf, len, flags)) < 0) {
386                 errno_to_wsaerrno();
387                 return SOCKET_ERROR;
388         }
389         return length;
390 }
391
392 INT WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags, 
393                 struct sockaddr *from, int *fromlen)
394 {
395         int length;
396
397         dprintf_winsock(stddeb, "WSA_recvfrom: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long)buf, len, flags);
398
399         if ((length = recvfrom(s, buf, len, flags, from, fromlen)) < 0) {
400                 errno_to_wsaerrno();
401                 return SOCKET_ERROR;
402         }
403         return length;
404 }
405
406 INT WINSOCK_select(INT nfds, fd_set *readfds, fd_set *writefds,
407         fd_set *exceptfds, struct timeval *timeout)
408 {
409         dprintf_winsock(stddeb, "WSA_select: fd # %d, ptr %8lx, ptr %8lx, ptr %8lX\n", nfds, (unsigned long) readfds, (unsigned long) writefds, (unsigned long) exceptfds);
410
411         return(select(nfds, readfds, writefds, exceptfds, timeout));
412 }
413
414 INT WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
415 {
416         int length;
417
418         dprintf_winsock(stddeb, "WSA_send: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
419
420         if ((length = send(s, buf, len, flags)) < 0) {
421                 errno_to_wsaerrno();
422                 return SOCKET_ERROR;
423         }
424         return length;
425 }
426
427 INT WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
428                 struct sockaddr *to, INT tolen)
429 {
430         int length;
431
432         dprintf_winsock(stddeb, "WSA_sendto: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
433
434         if ((length = sendto(s, buf, len, flags, to, tolen)) < 0) {
435                 errno_to_wsaerrno();
436                 return SOCKET_ERROR;
437         }
438         return length;
439 }
440
441 INT WINSOCK_setsockopt(SOCKET s, INT level, INT optname, const char *optval, 
442                         INT optlen)
443 {
444         dprintf_winsock(stddeb, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen);
445         convert_sockopt(&level, &optname);
446         
447         if (setsockopt(s, level, optname, optval, optlen) < 0) {
448                 errno_to_wsaerrno();
449                 return SOCKET_ERROR;
450         }
451         return 0;
452 }                                         
453
454 INT WINSOCK_shutdown(SOCKET s, INT how)
455 {
456         dprintf_winsock(stddeb, "WSA_shutdown: socket s %d, how %d\n", s, how);
457
458         if (shutdown(s, how) < 0) {
459                 errno_to_wsaerrno();
460                 return SOCKET_ERROR;
461         }
462         return 0;
463 }
464
465 SOCKET WINSOCK_socket(INT af, INT type, INT protocol)
466 {
467     int sock;
468
469     dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol);
470
471     if ((sock = socket(af, type, protocol)) < 0) {
472             errno_to_wsaerrno();
473             dprintf_winsock(stddeb, "WSA_socket: failed !\n");
474             return INVALID_SOCKET;
475     }
476     
477     if (sock > 0xffff) {
478         wsa_errno = WSAEMFILE;
479         return INVALID_SOCKET;
480     }
481
482     FD_SET(sock, &fd_in_use);
483
484     dprintf_winsock(stddeb, "WSA_socket: fd %d\n", sock);
485     return sock;
486 }
487
488 struct WIN_hostent *WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
489 {
490         struct hostent *host;
491
492         dprintf_winsock(stddeb, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type);
493
494         if ((host = gethostbyaddr(addr, len, type)) == NULL) {
495                 errno_to_wsaerrno();
496                 return NULL;
497         }
498         CONVERT_HOSTENT(&heap->hostent_addr, host);
499
500         return &heap->hostent_addr;
501 }
502
503 struct WIN_hostent *WINSOCK_gethostbyname(const char *name)
504 {
505         struct hostent *host;
506
507         dprintf_winsock(stddeb, "WSA_gethostbyname: %s\n", name);
508
509         if ((host = gethostbyname(name)) == NULL) {
510                 errno_to_wsaerrno();
511                 return NULL;
512         }
513         CONVERT_HOSTENT(&heap->hostent_name, host);
514
515         return &heap->hostent_name;
516 }
517
518 INT WINSOCK_gethostname(char *name, INT namelen)
519 {
520         dprintf_winsock(stddeb, "WSA_gethostname: name %s, len %d\n", name, namelen);
521
522         if (gethostname(name, namelen) < 0) {
523                 errno_to_wsaerrno();
524                 return SOCKET_ERROR;
525         }
526         return 0;
527 }          
528
529 struct WIN_protoent *WINSOCK_getprotobyname(char *name)
530 {
531         struct protoent *proto;
532
533         dprintf_winsock(stddeb, "WSA_getprotobyname: name %s\n", name);
534
535         if ((proto = getprotobyname(name)) == NULL) {
536                 errno_to_wsaerrno();
537                 return NULL;
538         }
539         CONVERT_PROTOENT(&heap->protoent_name, proto);
540
541         return &heap->protoent_name;
542 }
543
544 struct WIN_protoent *WINSOCK_getprotobynumber(INT number)
545 {
546         struct protoent *proto;
547
548         dprintf_winsock(stddeb, "WSA_getprotobynumber: num %d\n", number);
549
550         if ((proto = getprotobynumber(number)) == NULL) {
551                 errno_to_wsaerrno();
552                 return NULL;
553         }
554         CONVERT_PROTOENT(&heap->protoent_number, proto);
555
556         return &heap->protoent_number;
557 }
558
559 struct WIN_servent *WINSOCK_getservbyname(const char *name, const char *proto)
560 {
561         struct servent *service;
562
563         if (proto == NULL)
564                 proto = "tcp";
565
566         dprintf_winsock(stddeb, "WSA_getservbyname: name %s, proto %s\n", name, proto);
567
568         if ((service = getservbyname(name, proto)) == NULL) {
569                 errno_to_wsaerrno();
570                 return NULL;
571         }
572         CONVERT_SERVENT(&heap->servent_name, service);
573
574         return &heap->servent_name;
575 }
576
577 struct WIN_servent *WINSOCK_getservbyport(INT port, const char *proto)
578 {
579         struct servent *service;
580
581         dprintf_winsock(stddeb, "WSA_getservbyport: port %d, name %s\n", port, proto);
582
583         if ((service = getservbyport(port, proto)) == NULL) {
584                 errno_to_wsaerrno();
585                 return NULL;
586         }
587         CONVERT_SERVENT(&heap->servent_port, service);
588
589         return &heap->servent_port;
590 }
591
592 /******************** winsock specific functions ************************
593  *
594  */
595 static HANDLE new_handle = 0;
596
597 static HANDLE AllocWSAHandle(void)
598 {
599         return new_handle++;
600 }
601
602 static void recv_message(int sig)
603 {
604         struct ipc_packet message;
605
606         if (msgrcv(wine_key, &message, IPC_PACKET_SIZE, MTYPE, IPC_NOWAIT) == -1)
607                 perror("wine: msgrcv");
608
609         fprintf(stderr, 
610                 "WSA: PostMessage (hwnd %d, wMsg %d, wParam %d, lParam %ld)\n",
611                 message.hWnd,
612                 message.wMsg,
613                 message.handle,
614                 message.lParam);
615
616         PostMessage(message.hWnd, message.wMsg, message.handle, message.lParam);
617                 
618         signal(SIGUSR1, recv_message);
619 }
620
621
622 static void send_message(HANDLE handle, HWND hWnd, u_int wMsg, long lParam)
623 {
624         struct ipc_packet message;
625         
626         message.mtype = MTYPE;
627         message.handle = handle;
628         message.hWnd = hWnd;
629         message.wMsg = wMsg;
630         message.lParam = lParam;
631
632         fprintf(stderr, 
633                 "WSA: send (hwnd %d, wMsg %d, handle %d, lParam %ld)\n",
634                 hWnd, wMsg, handle, lParam);
635         
636         if (msgsnd(wine_key, &message,  IPC_PACKET_SIZE, IPC_NOWAIT) == -1)
637                 perror("wine: msgsnd");
638                 
639         kill(getppid(), SIGUSR1);
640 }
641
642
643 HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char *addr,
644                  INT len, INT type, char *buf, INT buflen)
645 {
646         HANDLE handle;
647         struct hostent *host;
648
649         handle = AllocWSAHandle();
650
651         if (fork()) {
652                 return handle;
653         } else {
654                 if ((host = gethostbyaddr(addr, len, type)) == NULL) {
655                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
656                         exit(0);
657                 }
658                 memcpy(buf, host, buflen);
659                 send_message(hWnd, wMsg, handle, 0);
660                 exit(0);
661         }
662 }
663
664
665 HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char *name, 
666                         char *buf, INT buflen)
667 {
668         HANDLE handle;
669         struct hostent *host;
670
671         handle = AllocWSAHandle();
672
673         if (fork()) {
674                 return handle;
675         } else {
676                 if ((host = gethostbyname(name)) == NULL) {
677                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
678                         exit(0);
679                 }
680                 memcpy(buf, host, buflen);
681                 send_message(hWnd, wMsg, handle, 0);
682                 exit(0);
683         }
684 }                     
685
686
687 HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, const char *name, 
688                         char *buf, INT buflen)
689 {
690         HANDLE handle;
691         struct protoent *proto;
692
693         handle = AllocWSAHandle();
694
695         if (fork()) {
696                 return handle;
697         } else {
698                 if ((proto = getprotobyname(name)) == NULL) {
699                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
700                         exit(0);
701                 }
702                 memcpy(buf, proto, buflen);
703                 send_message(hWnd, wMsg, handle, 0);
704                 exit(0);
705         }
706 }
707
708
709 HANDLE WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number, 
710                         char *buf, INT buflen)
711 {
712         HANDLE handle;
713         struct protoent *proto;
714
715         handle = AllocWSAHandle();
716
717         if (fork()) {
718                 return handle;
719         } else {
720                 if ((proto = getprotobynumber(number)) == NULL) {
721                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
722                         exit(0);
723                 }
724                 memcpy(buf, proto, buflen);
725                 send_message(hWnd, wMsg, handle, 0);
726                 exit(0);
727         }
728 }
729
730
731 HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, const char *name, 
732                         const char *proto, char *buf, INT buflen)
733 {
734         HANDLE handle;
735         struct servent *service;
736
737         handle = AllocWSAHandle();
738
739         if (fork()) {
740                 return handle;
741         } else {
742                 if ((service = getservbyname(name, proto)) == NULL) {
743                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
744                         exit(0);
745                 }
746                 memcpy(buf, service, buflen);
747                 send_message(hWnd, wMsg, handle, 0);
748                 exit(0);
749         }
750 }
751
752
753 HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char 
754                         *proto, char *buf, INT buflen)
755 {
756         HANDLE handle;
757         struct servent *service;
758
759         handle = AllocWSAHandle();
760
761         if (fork()) {
762                 return handle;
763         } else {
764                 if ((service = getservbyport(port, proto)) == NULL) {
765                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
766                         exit(0);
767                 }
768                 memcpy(buf, service, buflen);
769                 send_message(hWnd, wMsg, handle, 0);
770                 exit(0);
771         }
772 }
773
774 INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent)
775 {
776         long event;
777         fd_set read_fds, write_fds, except_fds;
778
779         dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND %d, wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
780
781         /* remove outstanding asyncselect() processes */
782         /* kill */
783
784         if (wMsg == 0 && lEvent == 0) 
785                 return 0;
786
787         if (fork()) {
788                 return 0;
789         } else {
790                 while (1) {
791                         FD_ZERO(&read_fds);
792                         FD_ZERO(&write_fds);
793                         FD_ZERO(&except_fds);
794
795                         if (lEvent & FD_READ)
796                                 FD_SET(s, &read_fds);
797                         if (lEvent & FD_WRITE)
798                                 FD_SET(s, &write_fds);
799
800                         fcntl(s, F_SETFL, O_NONBLOCK);
801                         select(s + 1, &read_fds, &write_fds, &except_fds, NULL);
802
803                         event = 0;
804                         if (FD_ISSET(s, &read_fds))
805                                 event |= FD_READ;
806                         if (FD_ISSET(s, &write_fds))
807                                 event |= FD_WRITE;
808
809                         send_message(hWnd, wMsg, s, (wsaerrno() << 16) | event);
810                 }
811         }
812 }
813
814 INT WSAFDIsSet(INT fd, fd_set *set)
815 {
816         return( FD_ISSET(fd, set) );
817 }
818
819 INT WSACancelAsyncRequest(HANDLE hAsyncTaskHandle)
820 {
821         dprintf_winsock(stddeb, "WSA_AsyncRequest: handle %d\n", hAsyncTaskHandle);
822
823         return 0;
824 }
825
826 INT WSACancelBlockingCall(void)
827 {
828         dprintf_winsock(stddeb, "WSA_CancelBlockCall\n");
829         return 0;
830 }
831           
832 INT WSAGetLastError(void)
833 {
834         dprintf_winsock(stddeb, "WSA_GetLastError\n");
835
836     return wsa_errno;
837 }
838
839 void WSASetLastError(INT iError)
840 {
841         dprintf_winsock(stddeb, "WSA_SetLastErorr %d\n", iError);
842
843     wsa_errno = iError;
844 }
845
846 BOOL WSAIsBlocking(void)
847 {
848         dprintf_winsock(stddeb, "WSA_IsBlocking\n");
849
850         return 0;
851 }
852
853 FARPROC WSASetBlockingHook(FARPROC lpBlockFunc)
854 {
855         dprintf_winsock(stddeb, "WSA_SetBlockHook %8lx, STUB!\n", (unsigned long) lpBlockFunc);
856         BlockFunction = lpBlockFunc;
857
858         return (FARPROC) lpBlockFunc;
859 }
860
861 INT WSAUnhookBlockingHook(void)
862 {
863         dprintf_winsock(stddeb, "WSA_UnhookBlockingHook\n");
864         BlockFunction = NULL;
865
866         return 0;
867 }
868
869 WSADATA WINSOCK_data = {
870         0x0101,
871         0x0101,
872         "WINE Sockets",
873 #ifdef linux
874         "LINUX/i386",
875 #endif
876 #ifdef __NetBSD__
877         "NetBSD/i386",
878 #endif
879 #ifdef sunos
880         "SunOS",
881 #endif
882         128,
883         1024,
884         NULL
885 };
886
887 INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
888 {
889     int HeapHandle;
890
891     dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
892
893     if (LOBYTE(wVersionRequested) < 1 ||
894         (LOBYTE(wVersionRequested) == 1 &&
895          HIBYTE(wVersionRequested) < 1))
896         return WSAVERNOTSUPPORTED;
897
898     if (!lpWSAData)
899         return WSAEINVAL;
900
901         /* alloc winsock heap */
902
903     if ((HeapHandle = GlobalAlloc(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0)
904         return WSASYSNOTREADY;
905
906     heap = (struct WinSockHeap *) GlobalLock(HeapHandle);
907     bcopy(&WINSOCK_data, lpWSAData, sizeof(WINSOCK_data));
908
909     /* ipc stuff */
910
911     if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
912         perror("wine: msgget");
913
914     signal(SIGUSR1, recv_message);
915
916     /* clear */
917     
918     FD_ZERO(&fd_in_use);
919
920     wsa_initted = 1;
921     return(0);
922 }
923
924 INT WSACleanup(void)
925 {
926         int fd;
927
928         if (wine_key)
929                 if (msgctl(wine_key, IPC_RMID, NULL) == -1)
930                         perror("wine: shmctl");
931
932         for (fd = 0; fd != FD_SETSIZE; fd++)
933                 if (FD_ISSET(fd, &fd_in_use))
934                         close(fd);
935
936         wsa_initted = 0;
937         return 0;
938 }