Release 951124
[wine/multimedia.git] / misc / winsocket.c
blob318c38e1436aa70dbeec984facf73eb6b441b265
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 */
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 #ifdef __svr4__
15 #include <sys/filio.h>
16 #include <sys/ioccom.h>
17 #endif
18 #include <sys/msg.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #include <fcntl.h>
23 #include <errno.h>
24 #include <netdb.h>
25 #include <unistd.h>
26 #undef TRANSPARENT
27 #include "winsock.h"
28 #include "toolhelp.h"
29 #include "stddebug.h"
30 #include "debug.h"
32 static WORD wsa_errno;
33 static int wsa_initted;
34 static key_t wine_key = 0;
35 static FARPROC BlockFunction;
36 static fd_set fd_in_use;
38 struct ipc_packet {
39 long mtype;
40 HANDLE handle;
41 HWND hWnd;
42 WORD wMsg;
43 LONG lParam;
46 #ifndef WINELIB
47 #pragma pack(1)
48 #endif
50 #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long))
51 #define MTYPE 0xb0b0eb05
53 /* These structures are Win16 only */
55 struct WIN_hostent {
56 SEGPTR h_name WINE_PACKED; /* official name of host */
57 SEGPTR h_aliases WINE_PACKED; /* alias list */
58 INT h_addrtype WINE_PACKED; /* host address type */
59 INT h_length WINE_PACKED; /* length of address */
60 char **h_addr_list WINE_PACKED; /* list of addresses from name server */
61 char *names[2];
62 char hostname[200];
65 struct WIN_protoent {
66 SEGPTR p_name WINE_PACKED; /* official protocol name */
67 SEGPTR p_aliases WINE_PACKED; /* alias list */
68 INT p_proto WINE_PACKED; /* protocol # */
71 struct WIN_servent {
72 SEGPTR s_name WINE_PACKED; /* official service name */
73 SEGPTR s_aliases WINE_PACKED; /* alias list */
74 INT s_port WINE_PACKED; /* port # */
75 SEGPTR s_proto WINE_PACKED; /* protocol to use */
78 struct WinSockHeap {
79 char ntoa_buffer[32];
81 struct WIN_hostent hostent_addr;
82 struct WIN_hostent hostent_name;
83 struct WIN_protoent protoent_name;
84 struct WIN_protoent protoent_number;
85 struct WIN_servent servent_name;
86 struct WIN_servent servent_port;
88 struct WIN_hostent WSAhostent_addr;
89 struct WIN_hostent WSAhostent_name;
90 struct WIN_protoent WSAprotoent_name;
91 struct WIN_protoent WSAprotoent_number;
92 struct WIN_servent WSAservent_name;
93 struct WIN_servent WSAservent_port;
94 /* 8K scratch buffer for aliases and friends are hopefully enough */
95 char scratch[8192];
97 static struct WinSockHeap *Heap;
98 static HANDLE HeapHandle;
99 #ifndef WINELIB32
100 static int ScratchPtr;
101 #endif
103 #ifndef WINELIB
104 #define GET_SEG_PTR(x) MAKELONG((int)((char*)(x)-(char*)Heap), \
105 GlobalHandleToSel(HeapHandle))
106 #else
107 #define GET_SEG_PTR(x) ((SEGPTR)x)
108 #endif
110 #ifndef WINELIB
111 #pragma pack(4)
112 #endif
114 #define dump_sockaddr(a) \
115 fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
116 ((struct sockaddr_in *)a)->sin_family, \
117 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
118 ntohs(((struct sockaddr_in *)a)->sin_port))
120 #ifndef WINELIB32
121 static void ResetScratch()
123 ScratchPtr=0;
126 static void *scratch_alloc(int size)
128 char *ret;
129 if(ScratchPtr+size > sizeof(Heap->scratch))
130 return 0;
131 ret = Heap->scratch + ScratchPtr;
132 ScratchPtr += size;
133 return ret;
136 static SEGPTR scratch_strdup(char * s)
138 char *ret=scratch_alloc(strlen(s)+1);
139 strcpy(ret,s);
140 return GET_SEG_PTR(ret);
142 #endif
144 static WORD wsaerrno(void)
146 #ifdef DEBUG_WINSOCK
147 #ifndef sun
148 #if defined(__FreeBSD__)
149 fprintf(stderr, "winsock: errno %d, (%s).\n",
150 errno, sys_errlist[errno]);
151 #else
152 fprintf(stderr, "winsock: errno %d, (%s).\n",
153 errno, strerror(errno));
154 #endif
155 #else
156 fprintf(stderr, "winsock: errno %d\n", errno);
157 #endif
158 #endif
160 switch(errno)
162 case EINTR: return WSAEINTR;
163 case EBADF: return WSAEBADF;
164 case EACCES: return WSAEACCES;
165 case EFAULT: return WSAEFAULT;
166 case EINVAL: return WSAEINVAL;
167 case EMFILE: return WSAEMFILE;
168 case EWOULDBLOCK: return WSAEWOULDBLOCK;
169 case EINPROGRESS: return WSAEINPROGRESS;
170 case EALREADY: return WSAEALREADY;
171 case ENOTSOCK: return WSAENOTSOCK;
172 case EDESTADDRREQ: return WSAEDESTADDRREQ;
173 case EMSGSIZE: return WSAEMSGSIZE;
174 case EPROTOTYPE: return WSAEPROTOTYPE;
175 case ENOPROTOOPT: return WSAENOPROTOOPT;
176 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
177 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
178 case EOPNOTSUPP: return WSAEOPNOTSUPP;
179 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
180 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
181 case EADDRINUSE: return WSAEADDRINUSE;
182 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
183 case ENETDOWN: return WSAENETDOWN;
184 case ENETUNREACH: return WSAENETUNREACH;
185 case ENETRESET: return WSAENETRESET;
186 case ECONNABORTED: return WSAECONNABORTED;
187 case ECONNRESET: return WSAECONNRESET;
188 case ENOBUFS: return WSAENOBUFS;
189 case EISCONN: return WSAEISCONN;
190 case ENOTCONN: return WSAENOTCONN;
191 case ESHUTDOWN: return WSAESHUTDOWN;
192 case ETOOMANYREFS: return WSAETOOMANYREFS;
193 case ETIMEDOUT: return WSAETIMEDOUT;
194 case ECONNREFUSED: return WSAECONNREFUSED;
195 case ELOOP: return WSAELOOP;
196 case ENAMETOOLONG: return WSAENAMETOOLONG;
197 case EHOSTDOWN: return WSAEHOSTDOWN;
198 case EHOSTUNREACH: return WSAEHOSTUNREACH;
199 case ENOTEMPTY: return WSAENOTEMPTY;
200 #ifdef EPROCLIM
201 case EPROCLIM: return WSAEPROCLIM;
202 #endif
203 case EUSERS: return WSAEUSERS;
204 #ifdef EDQUOT
205 case EDQUOT: return WSAEDQUOT;
206 #endif
207 case ESTALE: return WSAESTALE;
208 case EREMOTE: return WSAEREMOTE;
209 /* just in case we ever get here and there are no problems */
210 case 0: return 0;
212 default:
213 fprintf(stderr, "winsock: unknown errorno %d!\n", errno);
214 return WSAEOPNOTSUPP;
218 static void errno_to_wsaerrno(void)
220 wsa_errno = wsaerrno();
224 static WORD wsaherrno(void)
226 #if DEBUG_WINSOCK
227 #ifndef sun
228 #if defined(__FreeBSD__)
229 fprintf(stderr, "winsock: h_errno %d, (%s).\n",
230 h_errno, sys_errlist[h_errno]);
231 #else
232 fprintf(stderr, "winsock: h_errno %d.\n", h_errno);
233 herror("wine: winsock: wsaherrno");
234 #endif
235 #else
236 fprintf(stderr, "winsock: h_errno %d\n", h_errno);
237 #endif
238 #endif
240 switch(h_errno)
242 case TRY_AGAIN: return WSATRY_AGAIN;
243 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
244 case NO_RECOVERY: return WSANO_RECOVERY;
245 case NO_DATA: return WSANO_DATA;
246 /* just in case we ever get here and there are no problems */
247 case 0: return 0;
250 default:
251 fprintf(stderr, "winsock: unknown h_errorno %d!\n", h_errno);
252 return WSAEOPNOTSUPP;
257 static void herrno_to_wsaerrno(void)
259 wsa_errno = wsaherrno();
263 static void convert_sockopt(INT *level, INT *optname)
265 /* $%#%!#! why couldn't they use the same values for both winsock and unix ? */
267 switch (*level) {
268 case -1:
269 *level = SOL_SOCKET;
270 switch (*optname) {
271 case 0x01: *optname = SO_DEBUG;
272 break;
273 case 0x04: *optname = SO_REUSEADDR;
274 break;
275 case 0x08: *optname = SO_KEEPALIVE;
276 break;
277 case 0x10: *optname = SO_DONTROUTE;
278 break;
279 case 0x20: *optname = SO_BROADCAST;
280 break;
281 case 0x80: *optname = SO_LINGER;
282 break;
283 case 0x100: *optname = SO_OOBINLINE;
284 break;
285 case 0x1001: *optname = SO_SNDBUF;
286 break;
287 case 0x1002: *optname = SO_RCVBUF;
288 break;
289 case 0x1007: *optname = SO_ERROR;
290 break;
291 case 0x1008: *optname = SO_TYPE;
292 break;
293 default:
294 fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
295 break;
297 break;
298 case 6: *optname = IPPROTO_TCP;
302 #ifndef WINELIB
303 static SEGPTR copy_stringlist(char **list)
305 SEGPTR *s_list;
306 int i;
307 for(i=0;list[i];i++)
309 s_list = scratch_alloc(sizeof(SEGPTR)*(i+1));
310 for(i=0;list[i];i++)
312 void *copy = scratch_alloc(strlen(list[i])+1);
313 strcpy(copy,list[i]);
314 s_list[i]=GET_SEG_PTR(copy);
316 s_list[i]=0;
317 return GET_SEG_PTR(s_list);
321 static void CONVERT_HOSTENT(struct WIN_hostent *heapent, struct hostent *host)
323 SEGPTR *addr_list;
324 int i;
325 ResetScratch();
326 strcpy(heapent->hostname,host->h_name);
327 heapent->h_name = GET_SEG_PTR(heapent->hostname);
328 /* Convert aliases. Have to create array with FAR pointers */
329 if(!host->h_aliases)
330 heapent->h_aliases = 0;
331 else
332 heapent->h_aliases = copy_stringlist(host->h_aliases);
334 heapent->h_addrtype = host->h_addrtype;
335 heapent->h_length = host->h_length;
336 for(i=0;host->h_addr_list[i];i++)
338 addr_list=scratch_alloc(sizeof(SEGPTR)*(i+1));
339 heapent->h_addr_list = (char**)GET_SEG_PTR(addr_list);
340 for(i=0;host->h_addr_list[i];i++)
342 void *addr=scratch_alloc(host->h_length);
343 memcpy(addr,host->h_addr_list[i],host->h_length);
344 addr_list[i]=GET_SEG_PTR(addr);
346 addr_list[i]=0;
349 static void CONVERT_PROTOENT(struct WIN_protoent *heapent,
350 struct protoent *proto)
352 ResetScratch();
353 heapent->p_name= scratch_strdup(proto->p_name);
354 heapent->p_aliases=proto->p_aliases ?
355 copy_stringlist(proto->p_aliases) : 0;
356 heapent->p_proto = proto->p_proto;
359 static void CONVERT_SERVENT(struct WIN_servent *heapent, struct servent *serv)
361 ResetScratch();
362 heapent->s_name = scratch_strdup(serv->s_name);
363 heapent->s_aliases = serv->s_aliases ?
364 copy_stringlist(serv->s_aliases) : 0;
365 heapent->s_port = serv->s_port;
366 heapent->s_proto = scratch_strdup(serv->s_proto);
368 #else
369 #define CONVERT_HOSTENT(a,b) memcpy(a, &b, sizeof(a))
370 #define CONVERT_PROTOENT(a,b) memcpy(a, &b, sizeof(a))
371 #define CONVERT_SERVENT(a,b) memcpy(a, &b, sizeof(a))
372 #endif
374 SOCKET WINSOCK_accept(SOCKET s, struct sockaddr *addr, INT *addrlen)
376 int sock;
378 dprintf_winsock(stddeb, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, *addrlen);
380 if ((sock = accept(s, addr, (int *) addrlen)) < 0) {
381 errno_to_wsaerrno();
382 return INVALID_SOCKET;
384 return sock;
387 INT WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
389 dprintf_winsock(stddeb, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
390 dump_sockaddr(name);
392 if (bind(s, name, namelen) < 0) {
393 errno_to_wsaerrno();
394 return SOCKET_ERROR;
396 return 0;
399 INT WINSOCK_closesocket(SOCKET s)
401 dprintf_winsock(stddeb, "WSA_closesocket: socket %d\n", s);
403 FD_CLR(s, &fd_in_use);
405 if (close(s) < 0) {
406 errno_to_wsaerrno();
407 return SOCKET_ERROR;
409 return 0;
412 INT WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen)
414 dprintf_winsock(stddeb, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
415 dump_sockaddr(name);
417 if (connect(s, name, namelen) < 0) {
418 errno_to_wsaerrno();
419 return SOCKET_ERROR;
421 return 0;
424 INT WINSOCK_getpeername(SOCKET s, struct sockaddr *name, INT *namelen)
426 dprintf_winsock(stddeb, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
427 dump_sockaddr(name);
429 if (getpeername(s, name, (int *) namelen) < 0) {
430 if (h_errno < 0) {
431 errno_to_wsaerrno();
432 } else {
433 herrno_to_wsaerrno();
435 return SOCKET_ERROR;
437 return 0;
440 INT WINSOCK_getsockname(SOCKET s, struct sockaddr *name, INT *namelen)
442 dprintf_winsock(stddeb, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
443 if (getsockname(s, name, (int *) namelen) < 0) {
444 if (h_errno < 0) {
445 errno_to_wsaerrno();
446 } else {
447 herrno_to_wsaerrno();
449 return SOCKET_ERROR;
451 return 0;
455 WINSOCK_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
457 dprintf_winsock(stddeb, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen);
458 convert_sockopt(&level, &optname);
460 if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) {
461 errno_to_wsaerrno();
462 return SOCKET_ERROR;
464 return 0;
467 u_long WINSOCK_htonl(u_long hostlong)
469 return( htonl(hostlong) );
472 u_short WINSOCK_htons(u_short hostshort)
474 return( htons(hostshort) );
477 u_long WINSOCK_inet_addr(char *cp)
479 return( inet_addr(cp) );
482 char *WINSOCK_inet_ntoa(struct in_addr in)
484 char *s;
486 /* dprintf_winsock(stddeb, "WSA_inet_ntoa: %8lx\n", (int) in);*/
488 if ((s = inet_ntoa(in)) == NULL) {
489 errno_to_wsaerrno();
490 return NULL;
493 strncpy(Heap->ntoa_buffer, s, sizeof(Heap->ntoa_buffer) );
495 return (char *) GET_SEG_PTR(&Heap->ntoa_buffer);
498 INT WINSOCK_ioctlsocket(SOCKET s, u_long cmd, u_long *argp)
500 long newcmd;
501 u_long *newargp;
502 char *ctlname;
503 dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %lX, ptr %8x\n", s, cmd, (int) argp);
505 /* Why can't they all use the same ioctl numbers */
506 newcmd=cmd;
507 newargp=argp;
508 ctlname=0;
509 if(cmd == _IOR('f',127,u_long))
511 ctlname="FIONREAD";
512 newcmd=FIONREAD;
513 }else
514 if(cmd == _IOW('f',126,u_long) || cmd == _IOR('f',126,u_long))
516 ctlname="FIONBIO";
517 newcmd=FIONBIO;
518 }else
519 if(cmd == _IOW('f',125,u_long))
521 ctlname="FIOASYNC";
522 newcmd=FIOASYNC;
525 if(!ctlname)
526 fprintf(stderr,"Unknown winsock ioctl. Trying anyway\n");
527 else
528 dprintf_winsock(stddeb,"Recognized as %s\n", ctlname);
531 if (ioctl(s, newcmd, newargp) < 0) {
532 errno_to_wsaerrno();
533 return SOCKET_ERROR;
535 return 0;
538 INT WINSOCK_listen(SOCKET s, INT backlog)
540 dprintf_winsock(stddeb, "WSA_listen: socket %d, backlog %d\n", s, backlog);
542 if (listen(s, backlog) < 0) {
543 errno_to_wsaerrno();
544 return SOCKET_ERROR;
546 return 0;
549 u_long WINSOCK_ntohl(u_long netlong)
551 return( ntohl(netlong) );
554 u_short WINSOCK_ntohs(u_short netshort)
556 return( ntohs(netshort) );
559 INT WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
561 int length;
563 dprintf_winsock(stddeb, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags);
565 if ((length = recv(s, buf, len, flags)) < 0) {
566 errno_to_wsaerrno();
567 return SOCKET_ERROR;
569 return length;
572 INT WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags,
573 struct sockaddr *from, int *fromlen)
575 int length;
577 dprintf_winsock(stddeb, "WSA_recvfrom: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long)buf, len, flags);
579 if ((length = recvfrom(s, buf, len, flags, from, fromlen)) < 0) {
580 errno_to_wsaerrno();
581 return SOCKET_ERROR;
583 return length;
586 INT WINSOCK_select(INT nfds, fd_set *readfds, fd_set *writefds,
587 fd_set *exceptfds, struct timeval *timeout)
589 dprintf_winsock(stddeb, "WSA_select: fd # %d, ptr %8lx, ptr %8lx, ptr %8lX\n", nfds, (unsigned long) readfds, (unsigned long) writefds, (unsigned long) exceptfds);
591 return(select(nfds, readfds, writefds, exceptfds, timeout));
594 INT WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
596 int length;
598 dprintf_winsock(stddeb, "WSA_send: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
600 if ((length = send(s, buf, len, flags)) < 0) {
601 errno_to_wsaerrno();
602 return SOCKET_ERROR;
604 return length;
607 INT WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
608 struct sockaddr *to, INT tolen)
610 int length;
612 dprintf_winsock(stddeb, "WSA_sendto: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
614 if ((length = sendto(s, buf, len, flags, to, tolen)) < 0) {
615 errno_to_wsaerrno();
616 return SOCKET_ERROR;
618 return length;
621 INT WINSOCK_setsockopt(SOCKET s, INT level, INT optname, const char *optval,
622 INT optlen)
624 dprintf_winsock(stddeb, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen);
625 convert_sockopt(&level, &optname);
627 if (setsockopt(s, level, optname, optval, optlen) < 0) {
628 errno_to_wsaerrno();
629 return SOCKET_ERROR;
631 return 0;
634 INT WINSOCK_shutdown(SOCKET s, INT how)
636 dprintf_winsock(stddeb, "WSA_shutdown: socket s %d, how %d\n", s, how);
638 if (shutdown(s, how) < 0) {
639 errno_to_wsaerrno();
640 return SOCKET_ERROR;
642 return 0;
645 SOCKET WINSOCK_socket(INT af, INT type, INT protocol)
647 int sock;
649 dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol);
651 if ((sock = socket(af, type, protocol)) < 0) {
652 errno_to_wsaerrno();
653 dprintf_winsock(stddeb, "WSA_socket: failed !\n");
654 return INVALID_SOCKET;
657 if (sock > 0xffff) {
658 /* we set the value of wsa_errno directly, because
659 * only support socket numbers up to 0xffff. The
660 * value return indicates there are no descriptors available
662 wsa_errno = WSAEMFILE;
663 return INVALID_SOCKET;
666 FD_SET(sock, &fd_in_use);
668 dprintf_winsock(stddeb, "WSA_socket: fd %d\n", sock);
669 return sock;
673 struct WIN_hostent *
675 SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
677 struct hostent *host;
679 dprintf_winsock(stddeb, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type);
681 if ((host = gethostbyaddr(addr, len, type)) == NULL) {
682 if (h_errno < 0) {
683 errno_to_wsaerrno();
684 } else {
685 herrno_to_wsaerrno();
687 return NULL;
689 CONVERT_HOSTENT(&Heap->hostent_addr, host);
691 return GET_SEG_PTR(&Heap->hostent_addr);
695 struct WIN_hostent *
697 SEGPTR WINSOCK_gethostbyname(const char *name)
699 struct hostent *host;
701 dprintf_winsock(stddeb, "WSA_gethostbyname: %s\n", name);
703 if ((host = gethostbyname(name)) == NULL) {
704 if (h_errno < 0) {
705 errno_to_wsaerrno();
706 } else {
707 herrno_to_wsaerrno();
709 return NULL;
711 CONVERT_HOSTENT(&Heap->hostent_name, host);
713 return GET_SEG_PTR(&Heap->hostent_name);
716 INT WINSOCK_gethostname(char *name, INT namelen)
718 dprintf_winsock(stddeb, "WSA_gethostname: name %s, len %d\n", name, namelen);
720 if (gethostname(name, namelen) < 0) {
721 if (h_errno < 0) {
722 errno_to_wsaerrno();
723 } else {
724 herrno_to_wsaerrno();
726 return SOCKET_ERROR;
728 return 0;
732 struct WIN_protoent *
734 SEGPTR WINSOCK_getprotobyname(char *name)
736 struct protoent *proto;
738 dprintf_winsock(stddeb, "WSA_getprotobyname: name %s\n", name);
740 if ((proto = getprotobyname(name)) == NULL) {
741 if (h_errno < 0) {
742 errno_to_wsaerrno();
743 } else {
744 herrno_to_wsaerrno();
746 return NULL;
748 CONVERT_PROTOENT(&Heap->protoent_name, proto);
750 return GET_SEG_PTR(&Heap->protoent_name);
754 struct WIN_protoent *
756 SEGPTR WINSOCK_getprotobynumber(INT number)
758 struct protoent *proto;
760 dprintf_winsock(stddeb, "WSA_getprotobynumber: num %d\n", number);
762 if ((proto = getprotobynumber(number)) == NULL) {
763 if (h_errno < 0) {
764 errno_to_wsaerrno();
765 } else {
766 herrno_to_wsaerrno();
768 return NULL;
770 CONVERT_PROTOENT(&Heap->protoent_number, proto);
772 return GET_SEG_PTR(&Heap->protoent_number);
776 struct WIN_servent *
778 SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
780 struct servent *service;
782 if (proto == NULL)
783 proto = "tcp";
785 dprintf_winsock(stddeb, "WSA_getservbyname: name %s, proto %s\n", name, proto);
787 if ((service = getservbyname(name, proto)) == NULL) {
788 if (h_errno < 0) {
789 errno_to_wsaerrno();
790 } else {
791 herrno_to_wsaerrno();
793 return NULL;
795 CONVERT_SERVENT(&Heap->servent_name, service);
797 return GET_SEG_PTR(&Heap->servent_name);
801 struct WIN_servent *
803 SEGPTR WINSOCK_getservbyport(INT port, const char *proto)
805 struct servent *service;
807 dprintf_winsock(stddeb, "WSA_getservbyport: port %d, name %s\n", port, proto);
809 if ((service = getservbyport(port, proto)) == NULL) {
810 if (h_errno < 0) {
811 errno_to_wsaerrno();
812 } else {
813 herrno_to_wsaerrno();
815 return NULL;
817 CONVERT_SERVENT(&Heap->servent_port, service);
819 return GET_SEG_PTR(&Heap->servent_port);
822 /******************** winsock specific functions ************************
825 static HANDLE new_handle = 0;
827 static HANDLE AllocWSAHandle(void)
829 return new_handle++;
832 static void recv_message(int sig)
834 struct ipc_packet message;
836 /* FIXME: something about no message of desired type */
837 if (msgrcv(wine_key, (struct msgbuf*)&(message),
838 IPC_PACKET_SIZE, MTYPE, IPC_NOWAIT) == -1)
839 perror("wine: msgrcv");
841 fprintf(stderr,
842 "WSA: PostMessage (hwnd "NPFMT", wMsg %d, wParam "NPFMT", lParam %ld)\n",
843 message.hWnd,
844 message.wMsg,
845 message.handle,
846 message.lParam);
848 PostMessage(message.hWnd, message.wMsg, (WPARAM)message.handle, message.lParam);
850 signal(SIGUSR1, recv_message);
854 static void send_message( HWND hWnd, u_int wMsg, HANDLE handle, long lParam)
856 struct ipc_packet message;
858 message.mtype = MTYPE;
859 message.handle = handle;
860 message.hWnd = hWnd;
861 message.wMsg = wMsg;
862 message.lParam = lParam;
864 fprintf(stderr,
865 "WSA: send (hwnd "NPFMT", wMsg %d, handle "NPFMT", lParam %ld)\n",
866 hWnd, wMsg, handle, lParam);
868 /* FIXME: something about invalid argument */
869 if (msgsnd(wine_key, (struct msgbuf*)&(message),
870 IPC_PACKET_SIZE, IPC_NOWAIT) == -1)
871 perror("wine: msgsnd");
873 kill(getppid(), SIGUSR1);
877 HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char *addr,
878 INT len, INT type, char *buf, INT buflen)
880 HANDLE handle;
881 struct hostent *host;
883 handle = AllocWSAHandle();
885 if (fork()) {
886 return handle;
887 } else {
888 if ((host = gethostbyaddr(addr, len, type)) == NULL) {
889 if (h_errno < 0) {
890 errno_to_wsaerrno();
891 } else {
892 herrno_to_wsaerrno();
894 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
895 exit(0);
897 memcpy(buf, host, buflen);
898 send_message(hWnd, wMsg, handle, 0);
899 exit(0);
904 HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char *name,
905 char *buf, INT buflen)
907 HANDLE handle;
908 struct hostent *host;
910 handle = AllocWSAHandle();
912 if (fork()) {
913 return handle;
914 } else {
915 if ((host = gethostbyname(name)) == NULL) {
916 if (h_errno < 0) {
917 errno_to_wsaerrno();
918 } else {
919 herrno_to_wsaerrno();
921 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
922 exit(0);
924 memcpy(buf, host, buflen);
925 send_message(hWnd, wMsg, handle, 0);
926 exit(0);
931 HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, const char *name,
932 char *buf, INT buflen)
934 HANDLE handle;
935 struct protoent *proto;
937 handle = AllocWSAHandle();
939 if (fork()) {
940 return handle;
941 } else {
942 if ((proto = getprotobyname(name)) == NULL) {
943 if (h_errno < 0) {
944 errno_to_wsaerrno();
945 } else {
946 herrno_to_wsaerrno();
948 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
949 exit(0);
951 memcpy(buf, proto, buflen);
952 send_message(hWnd, wMsg, handle, 0);
953 exit(0);
958 HANDLE WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number,
959 char *buf, INT buflen)
961 HANDLE handle;
962 struct protoent *proto;
964 handle = AllocWSAHandle();
966 if (fork()) {
967 return handle;
968 } else {
969 if ((proto = getprotobynumber(number)) == NULL) {
970 if (h_errno < 0) {
971 errno_to_wsaerrno();
972 } else {
973 herrno_to_wsaerrno();
975 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
976 exit(0);
978 memcpy(buf, proto, buflen);
979 send_message(hWnd, wMsg, handle, 0);
980 exit(0);
985 HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, const char *name,
986 const char *proto, char *buf, INT buflen)
988 HANDLE handle;
989 struct servent *service;
991 handle = AllocWSAHandle();
993 if (fork()) {
994 return handle;
995 } else {
996 if ((service = getservbyname(name, proto)) == NULL) {
997 if (h_errno < 0) {
998 errno_to_wsaerrno();
999 } else {
1000 herrno_to_wsaerrno();
1002 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
1003 exit(0);
1005 memcpy(buf, service, buflen);
1006 send_message(hWnd, wMsg, handle, 0);
1007 exit(0);
1012 HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char
1013 *proto, char *buf, INT buflen)
1015 HANDLE handle;
1016 struct servent *service;
1018 handle = AllocWSAHandle();
1020 if (fork()) {
1021 return handle;
1022 } else {
1023 if ((service = getservbyport(port, proto)) == NULL) {
1024 if (h_errno < 0) {
1025 errno_to_wsaerrno();
1026 } else {
1027 herrno_to_wsaerrno();
1029 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
1030 exit(0);
1032 memcpy(buf, service, buflen);
1033 send_message(hWnd, wMsg, handle, 0);
1034 exit(0);
1038 INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent)
1040 long event;
1041 fd_set read_fds, write_fds, except_fds;
1043 dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND "NPFMT", wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
1045 /* remove outstanding asyncselect() processes */
1046 /* kill */
1048 if (wMsg == 0 && lEvent == 0)
1049 return 0;
1051 if (fork()) {
1052 return 0;
1053 } else {
1054 while (1) {
1055 FD_ZERO(&read_fds);
1056 FD_ZERO(&write_fds);
1057 FD_ZERO(&except_fds);
1059 if (lEvent & FD_READ)
1060 FD_SET(s, &read_fds);
1061 if (lEvent & FD_WRITE)
1062 FD_SET(s, &write_fds);
1064 fcntl(s, F_SETFL, O_NONBLOCK);
1065 select(s + 1, &read_fds, &write_fds, &except_fds, NULL);
1067 event = 0;
1068 if (FD_ISSET(s, &read_fds))
1069 event |= FD_READ;
1070 if (FD_ISSET(s, &write_fds))
1071 event |= FD_WRITE;
1072 /* FIXME: the first time through we get a winsock error of 2, why? */
1073 send_message(hWnd, wMsg, (HANDLE)s, (wsaerrno() << 16) | event);
1078 INT WSAFDIsSet(INT fd, fd_set *set)
1080 return( FD_ISSET(fd, set) );
1083 INT WSACancelAsyncRequest(HANDLE hAsyncTaskHandle)
1085 dprintf_winsock(stddeb, "WSA_AsyncRequest: handle "NPFMT"\n", hAsyncTaskHandle);
1087 return 0;
1090 INT WSACancelBlockingCall(void)
1092 dprintf_winsock(stddeb, "WSA_CancelBlockCall\n");
1093 return 0;
1096 INT WSAGetLastError(void)
1098 dprintf_winsock(stddeb, "WSA_GetLastError = %x\n", wsa_errno);
1100 return wsa_errno;
1103 void WSASetLastError(INT iError)
1105 dprintf_winsock(stddeb, "WSA_SetLastErorr %d\n", iError);
1107 wsa_errno = iError;
1110 BOOL WSAIsBlocking(void)
1112 dprintf_winsock(stddeb, "WSA_IsBlocking\n");
1114 return 0;
1117 FARPROC WSASetBlockingHook(FARPROC lpBlockFunc)
1119 dprintf_winsock(stddeb, "WSA_SetBlockHook %8lx, STUB!\n", (unsigned long) lpBlockFunc);
1120 BlockFunction = lpBlockFunc;
1122 return (FARPROC) lpBlockFunc;
1125 INT WSAUnhookBlockingHook(void)
1127 dprintf_winsock(stddeb, "WSA_UnhookBlockingHook\n");
1128 BlockFunction = NULL;
1130 return 0;
1133 WSADATA WINSOCK_data = {
1134 0x0101,
1135 0x0101,
1136 "WINE Sockets",
1137 #ifdef linux
1138 "LINUX/i386",
1139 #endif
1140 #ifdef __NetBSD__
1141 "NetBSD/i386",
1142 #endif
1143 #ifdef sunos
1144 "SunOS",
1145 #endif
1146 128,
1147 1024,
1148 NULL
1151 INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
1154 dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
1156 if (LOBYTE(wVersionRequested) < 1 ||
1157 (LOBYTE(wVersionRequested) == 1 &&
1158 HIBYTE(wVersionRequested) < 1))
1159 return WSAVERNOTSUPPORTED;
1161 if (!lpWSAData)
1162 return WSAEINVAL;
1164 /* alloc winsock heap */
1166 if ((HeapHandle = GlobalAlloc(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0)
1167 return WSASYSNOTREADY;
1169 Heap = (struct WinSockHeap *) GlobalLock(HeapHandle);
1170 bcopy(&WINSOCK_data, lpWSAData, sizeof(WINSOCK_data));
1172 /* ipc stuff */
1174 if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
1175 perror("wine: msgget");
1177 signal(SIGUSR1, recv_message);
1179 /* clear */
1181 FD_ZERO(&fd_in_use);
1183 wsa_initted = 1;
1184 return(0);
1187 INT WSACleanup(void)
1189 int fd;
1191 if (wine_key)
1192 if (msgctl(wine_key, IPC_RMID, NULL) == -1)
1193 perror("wine: shmctl");
1195 for (fd = 0; fd != FD_SETSIZE; fd++)
1196 if (FD_ISSET(fd, &fd_in_use))
1197 close(fd);
1199 wsa_initted = 0;
1200 return 0;