Release 951212
[wine/multimedia.git] / misc / winsocket.c
blob536e5db2b498b44ed9aa65df4ca82076d692b88a
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 #ifdef __FreeBSD__
39 extern int h_errno;
40 #endif /* __FreeBSD__ */
42 struct ipc_packet {
43 long mtype;
44 HANDLE handle;
45 HWND hWnd;
46 WORD wMsg;
47 LONG lParam;
50 #ifndef WINELIB
51 #pragma pack(1)
52 #endif
54 #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long))
55 /*#define MTYPE 0xb0b0eb05*/
56 #define MTYPE 0x30b0eb05
58 /* These structures are Win16 only */
60 struct WIN_hostent {
61 SEGPTR h_name WINE_PACKED; /* official name of host */
62 SEGPTR h_aliases WINE_PACKED; /* alias list */
63 INT h_addrtype WINE_PACKED; /* host address type */
64 INT h_length WINE_PACKED; /* length of address */
65 char **h_addr_list WINE_PACKED; /* list of addresses from name server */
66 char *names[2];
67 char hostname[200];
70 struct WIN_protoent {
71 SEGPTR p_name WINE_PACKED; /* official protocol name */
72 SEGPTR p_aliases WINE_PACKED; /* alias list */
73 INT p_proto WINE_PACKED; /* protocol # */
76 struct WIN_servent {
77 SEGPTR s_name WINE_PACKED; /* official service name */
78 SEGPTR s_aliases WINE_PACKED; /* alias list */
79 INT s_port WINE_PACKED; /* port # */
80 SEGPTR s_proto WINE_PACKED; /* protocol to use */
83 struct WinSockHeap {
84 char ntoa_buffer[32];
86 struct WIN_hostent hostent_addr;
87 struct WIN_hostent hostent_name;
88 struct WIN_protoent protoent_name;
89 struct WIN_protoent protoent_number;
90 struct WIN_servent servent_name;
91 struct WIN_servent servent_port;
93 struct WIN_hostent WSAhostent_addr;
94 struct WIN_hostent WSAhostent_name;
95 struct WIN_protoent WSAprotoent_name;
96 struct WIN_protoent WSAprotoent_number;
97 struct WIN_servent WSAservent_name;
98 struct WIN_servent WSAservent_port;
99 /* 8K scratch buffer for aliases and friends are hopefully enough */
100 char scratch[8192];
102 static struct WinSockHeap *Heap;
103 static HANDLE HeapHandle;
104 #ifndef WINELIB32
105 static int ScratchPtr;
106 #endif
108 #ifndef WINELIB
109 #define GET_SEG_PTR(x) MAKELONG((int)((char*)(x)-(char*)Heap), \
110 GlobalHandleToSel(HeapHandle))
111 #else
112 #define GET_SEG_PTR(x) ((SEGPTR)x)
113 #endif
115 #ifndef WINELIB
116 #pragma pack(4)
117 #endif
119 #define dump_sockaddr(a) \
120 fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
121 ((struct sockaddr_in *)a)->sin_family, \
122 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
123 ntohs(((struct sockaddr_in *)a)->sin_port))
125 #ifndef WINELIB32
126 static void ResetScratch()
128 ScratchPtr=0;
131 static void *scratch_alloc(int size)
133 char *ret;
134 if(ScratchPtr+size > sizeof(Heap->scratch))
135 return 0;
136 ret = Heap->scratch + ScratchPtr;
137 ScratchPtr += size;
138 return ret;
141 static SEGPTR scratch_strdup(char * s)
143 char *ret=scratch_alloc(strlen(s)+1);
144 strcpy(ret,s);
145 return GET_SEG_PTR(ret);
147 #endif
149 static WORD wsaerrno(void)
151 #ifdef DEBUG_WINSOCK
152 #ifndef sun
153 #if defined(__FreeBSD__)
154 fprintf(stderr, "winsock: errno %d, (%s).\n",
155 errno, sys_errlist[errno]);
156 #else
157 fprintf(stderr, "winsock: errno %d, (%s).\n",
158 errno, strerror(errno));
159 #endif
160 #else
161 fprintf(stderr, "winsock: errno %d\n", errno);
162 #endif
163 #endif
165 switch(errno)
167 case EINTR: return WSAEINTR;
168 case EBADF: return WSAEBADF;
169 case EACCES: return WSAEACCES;
170 case EFAULT: return WSAEFAULT;
171 case EINVAL: return WSAEINVAL;
172 case EMFILE: return WSAEMFILE;
173 case EWOULDBLOCK: return WSAEWOULDBLOCK;
174 case EINPROGRESS: return WSAEINPROGRESS;
175 case EALREADY: return WSAEALREADY;
176 case ENOTSOCK: return WSAENOTSOCK;
177 case EDESTADDRREQ: return WSAEDESTADDRREQ;
178 case EMSGSIZE: return WSAEMSGSIZE;
179 case EPROTOTYPE: return WSAEPROTOTYPE;
180 case ENOPROTOOPT: return WSAENOPROTOOPT;
181 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
182 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
183 case EOPNOTSUPP: return WSAEOPNOTSUPP;
184 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
185 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
186 case EADDRINUSE: return WSAEADDRINUSE;
187 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
188 case ENETDOWN: return WSAENETDOWN;
189 case ENETUNREACH: return WSAENETUNREACH;
190 case ENETRESET: return WSAENETRESET;
191 case ECONNABORTED: return WSAECONNABORTED;
192 case ECONNRESET: return WSAECONNRESET;
193 case ENOBUFS: return WSAENOBUFS;
194 case EISCONN: return WSAEISCONN;
195 case ENOTCONN: return WSAENOTCONN;
196 case ESHUTDOWN: return WSAESHUTDOWN;
197 case ETOOMANYREFS: return WSAETOOMANYREFS;
198 case ETIMEDOUT: return WSAETIMEDOUT;
199 case ECONNREFUSED: return WSAECONNREFUSED;
200 case ELOOP: return WSAELOOP;
201 case ENAMETOOLONG: return WSAENAMETOOLONG;
202 case EHOSTDOWN: return WSAEHOSTDOWN;
203 case EHOSTUNREACH: return WSAEHOSTUNREACH;
204 case ENOTEMPTY: return WSAENOTEMPTY;
205 #ifdef EPROCLIM
206 case EPROCLIM: return WSAEPROCLIM;
207 #endif
208 case EUSERS: return WSAEUSERS;
209 #ifdef EDQUOT
210 case EDQUOT: return WSAEDQUOT;
211 #endif
212 case ESTALE: return WSAESTALE;
213 case EREMOTE: return WSAEREMOTE;
214 /* just in case we ever get here and there are no problems */
215 case 0: return 0;
217 default:
218 fprintf(stderr, "winsock: unknown errorno %d!\n", errno);
219 return WSAEOPNOTSUPP;
223 static void errno_to_wsaerrno(void)
225 wsa_errno = wsaerrno();
229 static WORD wsaherrno(void)
231 #if DEBUG_WINSOCK
232 #ifndef sun
233 #if defined(__FreeBSD__)
234 fprintf(stderr, "winsock: h_errno %d, (%s).\n",
235 h_errno, sys_errlist[h_errno]);
236 #else
237 fprintf(stderr, "winsock: h_errno %d.\n", h_errno);
238 herror("wine: winsock: wsaherrno");
239 #endif
240 #else
241 fprintf(stderr, "winsock: h_errno %d\n", h_errno);
242 #endif
243 #endif
245 switch(h_errno)
247 case TRY_AGAIN: return WSATRY_AGAIN;
248 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
249 case NO_RECOVERY: return WSANO_RECOVERY;
250 case NO_DATA: return WSANO_DATA;
251 /* just in case we ever get here and there are no problems */
252 case 0: return 0;
255 default:
256 fprintf(stderr, "winsock: unknown h_errorno %d!\n", h_errno);
257 return WSAEOPNOTSUPP;
262 static void herrno_to_wsaerrno(void)
264 wsa_errno = wsaherrno();
268 static void convert_sockopt(INT *level, INT *optname)
270 /* $%#%!#! why couldn't they use the same values for both winsock and unix ? */
272 switch (*level) {
273 case -1:
274 *level = SOL_SOCKET;
275 switch (*optname) {
276 case 0x01: *optname = SO_DEBUG;
277 break;
278 case 0x04: *optname = SO_REUSEADDR;
279 break;
280 case 0x08: *optname = SO_KEEPALIVE;
281 break;
282 case 0x10: *optname = SO_DONTROUTE;
283 break;
284 case 0x20: *optname = SO_BROADCAST;
285 break;
286 case 0x80: *optname = SO_LINGER;
287 break;
288 case 0x100: *optname = SO_OOBINLINE;
289 break;
290 case 0x1001: *optname = SO_SNDBUF;
291 break;
292 case 0x1002: *optname = SO_RCVBUF;
293 break;
294 case 0x1007: *optname = SO_ERROR;
295 break;
296 case 0x1008: *optname = SO_TYPE;
297 break;
298 default:
299 fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
300 break;
302 break;
303 case 6: *optname = IPPROTO_TCP;
307 #ifndef WINELIB
308 static SEGPTR copy_stringlist(char **list)
310 SEGPTR *s_list;
311 int i;
312 for(i=0;list[i];i++)
314 s_list = scratch_alloc(sizeof(SEGPTR)*(i+1));
315 for(i=0;list[i];i++)
317 void *copy = scratch_alloc(strlen(list[i])+1);
318 strcpy(copy,list[i]);
319 s_list[i]=GET_SEG_PTR(copy);
321 s_list[i]=0;
322 return GET_SEG_PTR(s_list);
326 static void CONVERT_HOSTENT(struct WIN_hostent *heapent, struct hostent *host)
328 SEGPTR *addr_list;
329 int i;
330 ResetScratch();
331 strcpy(heapent->hostname,host->h_name);
332 heapent->h_name = GET_SEG_PTR(heapent->hostname);
333 /* Convert aliases. Have to create array with FAR pointers */
334 if(!host->h_aliases)
335 heapent->h_aliases = 0;
336 else
337 heapent->h_aliases = copy_stringlist(host->h_aliases);
339 heapent->h_addrtype = host->h_addrtype;
340 heapent->h_length = host->h_length;
341 for(i=0;host->h_addr_list[i];i++)
343 addr_list=scratch_alloc(sizeof(SEGPTR)*(i+1));
344 heapent->h_addr_list = (char**)GET_SEG_PTR(addr_list);
345 for(i=0;host->h_addr_list[i];i++)
347 void *addr=scratch_alloc(host->h_length);
348 memcpy(addr,host->h_addr_list[i],host->h_length);
349 addr_list[i]=GET_SEG_PTR(addr);
351 addr_list[i]=0;
354 static void CONVERT_PROTOENT(struct WIN_protoent *heapent,
355 struct protoent *proto)
357 ResetScratch();
358 heapent->p_name= scratch_strdup(proto->p_name);
359 heapent->p_aliases=proto->p_aliases ?
360 copy_stringlist(proto->p_aliases) : 0;
361 heapent->p_proto = proto->p_proto;
364 static void CONVERT_SERVENT(struct WIN_servent *heapent, struct servent *serv)
366 ResetScratch();
367 heapent->s_name = scratch_strdup(serv->s_name);
368 heapent->s_aliases = serv->s_aliases ?
369 copy_stringlist(serv->s_aliases) : 0;
370 heapent->s_port = serv->s_port;
371 heapent->s_proto = scratch_strdup(serv->s_proto);
373 #else
374 #define CONVERT_HOSTENT(a,b) memcpy(a, &b, sizeof(a))
375 #define CONVERT_PROTOENT(a,b) memcpy(a, &b, sizeof(a))
376 #define CONVERT_SERVENT(a,b) memcpy(a, &b, sizeof(a))
377 #endif
379 SOCKET WINSOCK_accept(SOCKET s, struct sockaddr *addr, INT *addrlen)
381 int sock;
383 dprintf_winsock(stddeb, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, *addrlen);
385 if ((sock = accept(s, addr, (int *) addrlen)) < 0) {
386 errno_to_wsaerrno();
387 return INVALID_SOCKET;
389 return sock;
392 INT WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
394 dprintf_winsock(stddeb, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
395 dump_sockaddr(name);
397 if (bind(s, name, namelen) < 0) {
398 errno_to_wsaerrno();
399 return SOCKET_ERROR;
401 return 0;
404 INT WINSOCK_closesocket(SOCKET s)
406 dprintf_winsock(stddeb, "WSA_closesocket: socket %d\n", s);
408 FD_CLR(s, &fd_in_use);
410 if (close(s) < 0) {
411 errno_to_wsaerrno();
412 return SOCKET_ERROR;
414 return 0;
417 INT WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen)
419 dprintf_winsock(stddeb, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
420 dump_sockaddr(name);
422 if (connect(s, name, namelen) < 0) {
423 errno_to_wsaerrno();
424 return SOCKET_ERROR;
426 return 0;
429 INT WINSOCK_getpeername(SOCKET s, struct sockaddr *name, INT *namelen)
431 dprintf_winsock(stddeb, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
432 dump_sockaddr(name);
434 if (getpeername(s, name, (int *) namelen) < 0) {
435 if (h_errno < 0) {
436 errno_to_wsaerrno();
437 } else {
438 herrno_to_wsaerrno();
440 return SOCKET_ERROR;
442 return 0;
445 INT WINSOCK_getsockname(SOCKET s, struct sockaddr *name, INT *namelen)
447 dprintf_winsock(stddeb, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
448 if (getsockname(s, name, (int *) namelen) < 0) {
449 if (h_errno < 0) {
450 errno_to_wsaerrno();
451 } else {
452 herrno_to_wsaerrno();
454 return SOCKET_ERROR;
456 return 0;
460 WINSOCK_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
462 dprintf_winsock(stddeb, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen);
463 convert_sockopt(&level, &optname);
465 if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) {
466 errno_to_wsaerrno();
467 return SOCKET_ERROR;
469 return 0;
472 u_long WINSOCK_htonl(u_long hostlong)
474 return( htonl(hostlong) );
477 u_short WINSOCK_htons(u_short hostshort)
479 return( htons(hostshort) );
482 u_long WINSOCK_inet_addr(char *cp)
484 return( inet_addr(cp) );
487 char *WINSOCK_inet_ntoa(struct in_addr in)
489 char *s;
491 /* dprintf_winsock(stddeb, "WSA_inet_ntoa: %8lx\n", (int) in);*/
493 if ((s = inet_ntoa(in)) == NULL) {
494 errno_to_wsaerrno();
495 return NULL;
498 strncpy(Heap->ntoa_buffer, s, sizeof(Heap->ntoa_buffer) );
500 return (char *) GET_SEG_PTR(&Heap->ntoa_buffer);
503 INT WINSOCK_ioctlsocket(SOCKET s, u_long cmd, u_long *argp)
505 long newcmd;
506 u_long *newargp;
507 char *ctlname;
508 dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %lX, ptr %8x\n", s, cmd, (int) argp);
510 /* Why can't they all use the same ioctl numbers */
511 newcmd=cmd;
512 newargp=argp;
513 ctlname=0;
514 if(cmd == _IOR('f',127,u_long))
516 ctlname="FIONREAD";
517 newcmd=FIONREAD;
518 }else
519 if(cmd == _IOW('f',126,u_long) || cmd == _IOR('f',126,u_long))
521 ctlname="FIONBIO";
522 newcmd=FIONBIO;
523 }else
524 if(cmd == _IOW('f',125,u_long))
526 ctlname="FIOASYNC";
527 newcmd=FIOASYNC;
530 if(!ctlname)
531 fprintf(stderr,"Unknown winsock ioctl. Trying anyway\n");
532 else
533 dprintf_winsock(stddeb,"Recognized as %s\n", ctlname);
536 if (ioctl(s, newcmd, newargp) < 0) {
537 errno_to_wsaerrno();
538 return SOCKET_ERROR;
540 return 0;
543 INT WINSOCK_listen(SOCKET s, INT backlog)
545 dprintf_winsock(stddeb, "WSA_listen: socket %d, backlog %d\n", s, backlog);
547 if (listen(s, backlog) < 0) {
548 errno_to_wsaerrno();
549 return SOCKET_ERROR;
551 return 0;
554 u_long WINSOCK_ntohl(u_long netlong)
556 return( ntohl(netlong) );
559 u_short WINSOCK_ntohs(u_short netshort)
561 return( ntohs(netshort) );
564 INT WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
566 int length;
568 dprintf_winsock(stddeb, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags);
570 if ((length = recv(s, buf, len, flags)) < 0) {
571 errno_to_wsaerrno();
572 return SOCKET_ERROR;
574 return length;
577 INT WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags,
578 struct sockaddr *from, int *fromlen)
580 int length;
582 dprintf_winsock(stddeb, "WSA_recvfrom: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long)buf, len, flags);
584 if ((length = recvfrom(s, buf, len, flags, from, fromlen)) < 0) {
585 errno_to_wsaerrno();
586 return SOCKET_ERROR;
588 return length;
591 INT WINSOCK_select(INT nfds, fd_set *readfds, fd_set *writefds,
592 fd_set *exceptfds, struct timeval *timeout)
594 dprintf_winsock(stddeb, "WSA_select: fd # %d, ptr %8lx, ptr %8lx, ptr %8lX\n", nfds, (unsigned long) readfds, (unsigned long) writefds, (unsigned long) exceptfds);
596 return(select(nfds, readfds, writefds, exceptfds, timeout));
599 INT WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
601 int length;
603 dprintf_winsock(stddeb, "WSA_send: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
605 if ((length = send(s, buf, len, flags)) < 0) {
606 errno_to_wsaerrno();
607 return SOCKET_ERROR;
609 return length;
612 INT WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
613 struct sockaddr *to, INT tolen)
615 int length;
617 dprintf_winsock(stddeb, "WSA_sendto: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
619 if ((length = sendto(s, buf, len, flags, to, tolen)) < 0) {
620 errno_to_wsaerrno();
621 return SOCKET_ERROR;
623 return length;
626 INT WINSOCK_setsockopt(SOCKET s, INT level, INT optname, const char *optval,
627 INT optlen)
629 dprintf_winsock(stddeb, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen);
630 convert_sockopt(&level, &optname);
632 if (setsockopt(s, level, optname, optval, optlen) < 0) {
633 errno_to_wsaerrno();
634 return SOCKET_ERROR;
636 return 0;
639 INT WINSOCK_shutdown(SOCKET s, INT how)
641 dprintf_winsock(stddeb, "WSA_shutdown: socket s %d, how %d\n", s, how);
643 if (shutdown(s, how) < 0) {
644 errno_to_wsaerrno();
645 return SOCKET_ERROR;
647 return 0;
650 SOCKET WINSOCK_socket(INT af, INT type, INT protocol)
652 int sock;
654 dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol);
656 if ((sock = socket(af, type, protocol)) < 0) {
657 errno_to_wsaerrno();
658 dprintf_winsock(stddeb, "WSA_socket: failed !\n");
659 return INVALID_SOCKET;
662 if (sock > 0xffff) {
663 /* we set the value of wsa_errno directly, because
664 * only support socket numbers up to 0xffff. The
665 * value return indicates there are no descriptors available
667 wsa_errno = WSAEMFILE;
668 return INVALID_SOCKET;
671 FD_SET(sock, &fd_in_use);
673 dprintf_winsock(stddeb, "WSA_socket: fd %d\n", sock);
674 return sock;
678 struct WIN_hostent *
680 SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
682 struct hostent *host;
684 dprintf_winsock(stddeb, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type);
686 if ((host = gethostbyaddr(addr, len, type)) == NULL) {
687 if (h_errno < 0) {
688 errno_to_wsaerrno();
689 } else {
690 herrno_to_wsaerrno();
692 return NULL;
694 CONVERT_HOSTENT(&Heap->hostent_addr, host);
696 return GET_SEG_PTR(&Heap->hostent_addr);
700 struct WIN_hostent *
702 SEGPTR WINSOCK_gethostbyname(const char *name)
704 struct hostent *host;
706 dprintf_winsock(stddeb, "WSA_gethostbyname: %s\n", name);
708 if ((host = gethostbyname(name)) == NULL) {
709 if (h_errno < 0) {
710 errno_to_wsaerrno();
711 } else {
712 herrno_to_wsaerrno();
714 return NULL;
716 CONVERT_HOSTENT(&Heap->hostent_name, host);
718 return GET_SEG_PTR(&Heap->hostent_name);
721 INT WINSOCK_gethostname(char *name, INT namelen)
723 dprintf_winsock(stddeb, "WSA_gethostname: name %s, len %d\n", name, namelen);
725 if (gethostname(name, namelen) < 0) {
726 if (h_errno < 0) {
727 errno_to_wsaerrno();
728 } else {
729 herrno_to_wsaerrno();
731 return SOCKET_ERROR;
733 return 0;
737 struct WIN_protoent *
739 SEGPTR WINSOCK_getprotobyname(char *name)
741 struct protoent *proto;
743 dprintf_winsock(stddeb, "WSA_getprotobyname: name %s\n", name);
745 if ((proto = getprotobyname(name)) == NULL) {
746 if (h_errno < 0) {
747 errno_to_wsaerrno();
748 } else {
749 herrno_to_wsaerrno();
751 return NULL;
753 CONVERT_PROTOENT(&Heap->protoent_name, proto);
755 return GET_SEG_PTR(&Heap->protoent_name);
759 struct WIN_protoent *
761 SEGPTR WINSOCK_getprotobynumber(INT number)
763 struct protoent *proto;
765 dprintf_winsock(stddeb, "WSA_getprotobynumber: num %d\n", number);
767 if ((proto = getprotobynumber(number)) == NULL) {
768 if (h_errno < 0) {
769 errno_to_wsaerrno();
770 } else {
771 herrno_to_wsaerrno();
773 return NULL;
775 CONVERT_PROTOENT(&Heap->protoent_number, proto);
777 return GET_SEG_PTR(&Heap->protoent_number);
781 struct WIN_servent *
783 SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
785 struct servent *service;
787 if (proto == NULL)
788 proto = "tcp";
790 dprintf_winsock(stddeb, "WSA_getservbyname: name %s, proto %s\n", name, proto);
792 if ((service = getservbyname(name, proto)) == NULL) {
793 if (h_errno < 0) {
794 errno_to_wsaerrno();
795 } else {
796 herrno_to_wsaerrno();
798 return NULL;
800 CONVERT_SERVENT(&Heap->servent_name, service);
802 return GET_SEG_PTR(&Heap->servent_name);
806 struct WIN_servent *
808 SEGPTR WINSOCK_getservbyport(INT port, const char *proto)
810 struct servent *service;
812 dprintf_winsock(stddeb, "WSA_getservbyport: port %d, name %s\n", port, proto);
814 if ((service = getservbyport(port, proto)) == NULL) {
815 if (h_errno < 0) {
816 errno_to_wsaerrno();
817 } else {
818 herrno_to_wsaerrno();
820 return NULL;
822 CONVERT_SERVENT(&Heap->servent_port, service);
824 return GET_SEG_PTR(&Heap->servent_port);
827 /******************** winsock specific functions ************************
830 static HANDLE new_handle = 0;
832 static HANDLE AllocWSAHandle(void)
834 return new_handle++;
837 static void recv_message(int sig)
839 static struct ipc_packet message;
840 static int message_is_valid = 0;
841 BOOL result;
843 signal(SIGUSR1, recv_message);
844 while (1) {
846 if (!message_is_valid) {
847 if (msgrcv(wine_key, (struct msgbuf*)&(message),
848 IPC_PACKET_SIZE, MTYPE, IPC_NOWAIT) == -1) {
849 perror("wine: msgrcv");
850 break;
854 result = PostMessage(message.hWnd, message.wMsg,
855 (WPARAM)message.handle, message.lParam);
856 if (result == FALSE) {
857 message_is_valid = 1;
858 break;
860 else
861 message_is_valid = 0;
868 static void send_message( HWND hWnd, u_int wMsg, HANDLE handle, long lParam)
870 struct ipc_packet message;
872 message.mtype = MTYPE;
873 message.handle = handle;
874 message.hWnd = hWnd;
875 message.wMsg = wMsg;
876 message.lParam = lParam;
878 if (msgsnd(wine_key, (struct msgbuf*)&(message),
879 IPC_PACKET_SIZE, 0/*IPC_NOWAIT*/) == -1)
880 perror("wine: msgsnd");
882 kill(getppid(), SIGUSR1);
886 HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char *addr,
887 INT len, INT type, char *buf, INT buflen)
889 HANDLE handle;
890 struct hostent *host;
892 handle = AllocWSAHandle();
894 if (fork()) {
895 return handle;
896 } else {
897 if ((host = gethostbyaddr(addr, len, type)) == NULL) {
898 if (h_errno < 0) {
899 errno_to_wsaerrno();
900 } else {
901 herrno_to_wsaerrno();
903 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
904 exit(0);
906 memcpy(buf, host, buflen);
907 send_message(hWnd, wMsg, handle, 0);
908 exit(0);
913 HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char *name,
914 char *buf, INT buflen)
916 HANDLE handle;
917 struct hostent *host;
919 handle = AllocWSAHandle();
921 if (fork()) {
922 return handle;
923 } else {
924 if ((host = gethostbyname(name)) == NULL) {
925 if (h_errno < 0) {
926 errno_to_wsaerrno();
927 } else {
928 herrno_to_wsaerrno();
930 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
931 exit(0);
933 memcpy(buf, host, buflen);
934 send_message(hWnd, wMsg, handle, 0);
935 exit(0);
940 HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, const char *name,
941 char *buf, INT buflen)
943 HANDLE handle;
944 struct protoent *proto;
946 handle = AllocWSAHandle();
948 if (fork()) {
949 return handle;
950 } else {
951 if ((proto = getprotobyname(name)) == NULL) {
952 if (h_errno < 0) {
953 errno_to_wsaerrno();
954 } else {
955 herrno_to_wsaerrno();
957 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
958 exit(0);
960 memcpy(buf, proto, buflen);
961 send_message(hWnd, wMsg, handle, 0);
962 exit(0);
967 HANDLE WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number,
968 char *buf, INT buflen)
970 HANDLE handle;
971 struct protoent *proto;
973 handle = AllocWSAHandle();
975 if (fork()) {
976 return handle;
977 } else {
978 if ((proto = getprotobynumber(number)) == NULL) {
979 if (h_errno < 0) {
980 errno_to_wsaerrno();
981 } else {
982 herrno_to_wsaerrno();
984 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
985 exit(0);
987 memcpy(buf, proto, buflen);
988 send_message(hWnd, wMsg, handle, 0);
989 exit(0);
994 HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, const char *name,
995 const char *proto, char *buf, INT buflen)
997 HANDLE handle;
998 struct servent *service;
1000 handle = AllocWSAHandle();
1002 if (fork()) {
1003 return handle;
1004 } else {
1005 if ((service = getservbyname(name, proto)) == NULL) {
1006 if (h_errno < 0) {
1007 errno_to_wsaerrno();
1008 } else {
1009 herrno_to_wsaerrno();
1011 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
1012 exit(0);
1014 memcpy(buf, service, buflen);
1015 send_message(hWnd, wMsg, handle, 0);
1016 exit(0);
1021 HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char
1022 *proto, char *buf, INT buflen)
1024 HANDLE handle;
1025 struct servent *service;
1027 handle = AllocWSAHandle();
1029 if (fork()) {
1030 return handle;
1031 } else {
1032 if ((service = getservbyport(port, proto)) == NULL) {
1033 if (h_errno < 0) {
1034 errno_to_wsaerrno();
1035 } else {
1036 herrno_to_wsaerrno();
1038 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
1039 exit(0);
1041 memcpy(buf, service, buflen);
1042 send_message(hWnd, wMsg, handle, 0);
1043 exit(0);
1047 INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent)
1049 long event;
1050 fd_set read_fds, write_fds, except_fds;
1052 dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND "NPFMT", wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
1054 /* remove outstanding asyncselect() processes */
1055 /* kill */
1057 if (wMsg == 0 && lEvent == 0)
1058 return 0;
1060 if (fork()) {
1061 return 0;
1062 } else {
1063 while (1) {
1064 FD_ZERO(&read_fds);
1065 FD_ZERO(&write_fds);
1066 FD_ZERO(&except_fds);
1068 if (lEvent & FD_READ)
1069 FD_SET(s, &read_fds);
1070 if (lEvent & FD_WRITE)
1071 FD_SET(s, &write_fds);
1073 fcntl(s, F_SETFL, O_NONBLOCK);
1074 select(s + 1, &read_fds, &write_fds, &except_fds, NULL);
1076 event = 0;
1077 if (FD_ISSET(s, &read_fds))
1078 event |= FD_READ;
1079 if (FD_ISSET(s, &write_fds))
1080 event |= FD_WRITE;
1081 /* FIXME: the first time through we get a winsock error of 2, why? */
1082 send_message(hWnd, wMsg, (HANDLE)s, (wsaerrno() << 16) | event);
1087 INT WSAFDIsSet(INT fd, fd_set *set)
1089 return( FD_ISSET(fd, set) );
1092 INT WSACancelAsyncRequest(HANDLE hAsyncTaskHandle)
1094 dprintf_winsock(stddeb, "WSA_AsyncRequest: handle "NPFMT"\n", hAsyncTaskHandle);
1096 return 0;
1099 INT WSACancelBlockingCall(void)
1101 dprintf_winsock(stddeb, "WSA_CancelBlockCall\n");
1102 return 0;
1105 INT WSAGetLastError(void)
1107 dprintf_winsock(stddeb, "WSA_GetLastError = %x\n", wsa_errno);
1109 return wsa_errno;
1112 void WSASetLastError(INT iError)
1114 dprintf_winsock(stddeb, "WSA_SetLastErorr %d\n", iError);
1116 wsa_errno = iError;
1119 BOOL WSAIsBlocking(void)
1121 dprintf_winsock(stddeb, "WSA_IsBlocking\n");
1123 return 0;
1126 FARPROC WSASetBlockingHook(FARPROC lpBlockFunc)
1128 dprintf_winsock(stddeb, "WSA_SetBlockHook %8lx, STUB!\n", (unsigned long) lpBlockFunc);
1129 BlockFunction = lpBlockFunc;
1131 return (FARPROC) lpBlockFunc;
1134 INT WSAUnhookBlockingHook(void)
1136 dprintf_winsock(stddeb, "WSA_UnhookBlockingHook\n");
1137 BlockFunction = NULL;
1139 return 0;
1142 WSADATA WINSOCK_data = {
1143 0x0101,
1144 0x0101,
1145 "WINE Sockets",
1146 #ifdef linux
1147 "LINUX/i386",
1148 #elif defined(__NetBSD__)
1149 "NetBSD/i386",
1150 #elif defined(sunos)
1151 "SunOS",
1152 #elif defined(__FreeBSD__)
1153 "FreeBSD",
1154 #else
1155 "Unknown",
1156 #endif
1157 128,
1158 1024,
1159 NULL
1162 INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
1165 dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
1167 if (LOBYTE(wVersionRequested) < 1 ||
1168 (LOBYTE(wVersionRequested) == 1 &&
1169 HIBYTE(wVersionRequested) < 1))
1170 return WSAVERNOTSUPPORTED;
1172 if (!lpWSAData)
1173 return WSAEINVAL;
1175 /* alloc winsock heap */
1177 if ((HeapHandle = GlobalAlloc(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0)
1178 return WSASYSNOTREADY;
1180 Heap = (struct WinSockHeap *) GlobalLock(HeapHandle);
1181 bcopy(&WINSOCK_data, lpWSAData, sizeof(WINSOCK_data));
1183 /* ipc stuff */
1185 if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
1186 perror("wine: msgget");
1188 signal(SIGUSR1, recv_message);
1190 /* clear */
1192 FD_ZERO(&fd_in_use);
1194 wsa_initted = 1;
1195 return(0);
1198 INT WSACleanup(void)
1200 int fd;
1202 if (wine_key)
1203 if (msgctl(wine_key, IPC_RMID, NULL) == -1)
1204 perror("wine: shmctl");
1206 for (fd = 0; fd != FD_SETSIZE; fd++)
1207 if (FD_ISSET(fd, &fd_in_use))
1208 close(fd);
1210 wsa_initted = 0;
1211 return 0;