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