Release 950727
[wine/multimedia.git] / misc / winsocket.c
blob2fdd5a6c595f20db1b5a05c404a694c6b670ebd0
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 #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 "toolhelp.h"
24 #include "stddebug.h"
25 #include "debug.h"
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;
33 struct ipc_packet {
34 long mtype;
35 HANDLE handle;
36 HWND hWnd;
37 WORD wMsg;
38 LONG lParam;
41 #ifndef WINELIB
42 #pragma pack(1)
43 #endif
45 #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long))
46 #define MTYPE 0xb0b0eb05
48 /* These structures are Win16 only */
50 struct WIN_hostent {
51 SEGPTR h_name WINE_PACKED; /* official name of host */
52 SEGPTR h_aliases WINE_PACKED; /* alias list */
53 INT h_addrtype WINE_PACKED; /* host address type */
54 INT h_length WINE_PACKED; /* length of address */
55 char **h_addr_list WINE_PACKED; /* list of addresses from name server */
56 char *names[2];
57 char hostname[200];
60 struct WIN_protoent {
61 SEGPTR p_name WINE_PACKED; /* official protocol name */
62 SEGPTR p_aliases WINE_PACKED; /* alias list */
63 INT p_proto WINE_PACKED; /* protocol # */
66 struct WIN_servent {
67 SEGPTR s_name WINE_PACKED; /* official service name */
68 SEGPTR s_aliases WINE_PACKED; /* alias list */
69 INT s_port WINE_PACKED; /* port # */
70 SEGPTR s_proto WINE_PACKED; /* protocol to use */
73 struct WinSockHeap {
74 char ntoa_buffer[32];
76 struct WIN_hostent hostent_addr;
77 struct WIN_hostent hostent_name;
78 struct WIN_protoent protoent_name;
79 struct WIN_protoent protoent_number;
80 struct WIN_servent servent_name;
81 struct WIN_servent servent_port;
83 struct WIN_hostent WSAhostent_addr;
84 struct WIN_hostent WSAhostent_name;
85 struct WIN_protoent WSAprotoent_name;
86 struct WIN_protoent WSAprotoent_number;
87 struct WIN_servent WSAservent_name;
88 struct WIN_servent WSAservent_port;
89 /* 8K scratch buffer for aliases and friends are hopefully enough */
90 char scratch[8192];
92 static struct WinSockHeap *Heap;
93 static int HeapHandle;
94 static int ScratchPtr;
96 #ifndef WINELIB
97 #define GET_SEG_PTR(x) MAKELONG((int)((char*)(x)-(char*)Heap), \
98 GlobalHandleToSel(HeapHandle))
99 #else
100 #define GET_SEG_PTR(x) (x)
101 #endif
103 #ifndef WINELIB
104 #pragma pack(4)
105 #endif
107 #define dump_sockaddr(a) \
108 fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
109 ((struct sockaddr_in *)a)->sin_family, \
110 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
111 ntohs(((struct sockaddr_in *)a)->sin_port))
113 static void ResetScratch()
115 ScratchPtr=0;
118 static void *scratch_alloc(int size)
120 char *ret;
121 if(ScratchPtr+size > sizeof(Heap->scratch))
122 return 0;
123 ret = Heap->scratch + ScratchPtr;
124 ScratchPtr += size;
125 return ret;
128 static SEGPTR scratch_strdup(char * s)
130 char *ret=scratch_alloc(strlen(s)+1);
131 strcpy(ret,s);
132 return GET_SEG_PTR(ret);
135 static WORD wsaerrno(void)
137 #ifdef DEBUG_WINSOCK
138 #ifndef sun
139 #if defined(__FreeBSD__)
140 fprintf(stderr, "winsock: errno %d, (%s).\n",
141 errno, sys_errlist[errno]);
142 #else
143 fprintf(stderr, "winsock: errno %d, (%s).\n",
144 errno, strerror(errno));
145 #endif
146 #else
147 fprintf(stderr, "winsock: errno %d\n", errno);
148 #endif
149 #endif
151 switch(errno)
153 case EINTR: return WSAEINTR;
154 case EACCES: return WSAEACCES;
155 case EFAULT: return WSAEFAULT;
156 case EINVAL: return WSAEINVAL;
157 case EMFILE: return WSAEMFILE;
158 case EWOULDBLOCK: return WSAEWOULDBLOCK;
159 case EINPROGRESS: return WSAEINPROGRESS;
160 case EALREADY: return WSAEALREADY;
161 case EBADF:
162 case ENOTSOCK: return WSAENOTSOCK;
163 case EDESTADDRREQ: return WSAEDESTADDRREQ;
164 case EMSGSIZE: return WSAEMSGSIZE;
165 case EPROTOTYPE: return WSAEPROTOTYPE;
166 case ENOPROTOOPT: return WSAENOPROTOOPT;
167 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
168 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
169 case EOPNOTSUPP: return WSAEOPNOTSUPP;
170 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
171 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
172 case EADDRINUSE: return WSAEADDRINUSE;
173 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
174 case ENETDOWN: return WSAENETDOWN;
175 case ENETUNREACH: return WSAENETUNREACH;
176 case ENETRESET: return WSAENETRESET;
177 case ECONNABORTED: return WSAECONNABORTED;
178 case ECONNRESET: return WSAECONNRESET;
179 case ENOBUFS: return WSAENOBUFS;
180 case EISCONN: return WSAEISCONN;
181 case ENOTCONN: return WSAENOTCONN;
182 case ESHUTDOWN: return WSAESHUTDOWN;
183 case ETOOMANYREFS: return WSAETOOMANYREFS;
184 case ETIMEDOUT: return WSAETIMEDOUT;
185 case ECONNREFUSED: return WSAECONNREFUSED;
186 case ELOOP: return WSAELOOP;
187 case ENAMETOOLONG: return WSAENAMETOOLONG;
188 case EHOSTDOWN: return WSAEHOSTDOWN;
189 case EHOSTUNREACH: return WSAEHOSTUNREACH;
190 case ENOTEMPTY: return WSAENOTEMPTY;
191 #ifdef EPROCLIM
192 case EPROCLIM: return WSAEPROCLIM;
193 #endif
194 case EUSERS: return WSAEUSERS;
195 case EDQUOT: return WSAEDQUOT;
196 case ESTALE: return WSAESTALE;
197 case EREMOTE: return WSAEREMOTE;
199 default:
200 fprintf(stderr, "winsock: unknown errorno %d!\n", errno);
201 return WSAEOPNOTSUPP;
205 static void errno_to_wsaerrno(void)
207 wsa_errno = wsaerrno();
210 static void convert_sockopt(INT *level, INT *optname)
212 /* $%#%!@! why couldn't they use the same values for both winsock and unix ? */
214 switch (*level) {
215 case -1:
216 *level = SOL_SOCKET;
217 switch (*optname) {
218 case 0x01: *optname = SO_DEBUG;
219 break;
220 case 0x04: *optname = SO_REUSEADDR;
221 break;
222 case 0x08: *optname = SO_KEEPALIVE;
223 break;
224 case 0x10: *optname = SO_DONTROUTE;
225 break;
226 case 0x20: *optname = SO_BROADCAST;
227 break;
228 case 0x80: *optname = SO_LINGER;
229 break;
230 case 0x100: *optname = SO_OOBINLINE;
231 break;
232 case 0x1001: *optname = SO_SNDBUF;
233 break;
234 case 0x1002: *optname = SO_RCVBUF;
235 break;
236 case 0x1007: *optname = SO_ERROR;
237 break;
238 case 0x1008: *optname = SO_TYPE;
239 break;
240 default:
241 fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
242 break;
244 break;
245 case 6: *optname = IPPROTO_TCP;
249 #ifndef WINELIB
250 static SEGPTR copy_stringlist(char **list)
252 SEGPTR *s_list;
253 int i;
254 for(i=0;list[i];i++)
256 s_list = scratch_alloc(sizeof(SEGPTR)*(i+1));
257 for(i=0;list[i];i++)
259 void *copy = scratch_alloc(strlen(list[i])+1);
260 strcpy(copy,list[i]);
261 s_list[i]=GET_SEG_PTR(copy);
263 s_list[i]=0;
264 return GET_SEG_PTR(s_list);
268 static void CONVERT_HOSTENT(struct WIN_hostent *heapent, struct hostent *host)
270 SEGPTR *addr_list;
271 int i;
272 ResetScratch();
273 strcpy(heapent->hostname,host->h_name);
274 heapent->h_name = GET_SEG_PTR(heapent->hostname);
275 /* Convert aliases. Have to create array with FAR pointers */
276 if(!host->h_aliases)
277 heapent->h_aliases = 0;
278 else
279 heapent->h_aliases = copy_stringlist(host->h_aliases);
281 heapent->h_addrtype = host->h_addrtype;
282 heapent->h_length = host->h_length;
283 for(i=0;host->h_addr_list[i];i++)
285 addr_list=scratch_alloc(sizeof(SEGPTR)*(i+1));
286 heapent->h_addr_list = GET_SEG_PTR(addr_list);
287 for(i=0;host->h_addr_list[i];i++)
289 void *addr=scratch_alloc(host->h_length);
290 memcpy(addr,host->h_addr_list[i],host->h_length);
291 addr_list[i]=GET_SEG_PTR(addr);
293 addr_list[i]=0;
296 static void CONVERT_PROTOENT(struct WIN_protoent *heapent,
297 struct protoent *proto)
299 ResetScratch();
300 heapent->p_name= scratch_strdup(proto->p_name);
301 heapent->p_aliases=proto->p_aliases ?
302 copy_stringlist(proto->p_aliases) : 0;
303 heapent->p_proto = proto->p_proto;
306 static void CONVERT_SERVENT(struct WIN_servent *heapent, struct servent *serv)
308 ResetScratch();
309 heapent->s_name = scratch_strdup(serv->s_name);
310 heapent->s_aliases = serv->s_aliases ?
311 copy_stringlist(serv->s_aliases) : 0;
312 heapent->s_port = serv->s_port;
313 heapent->s_proto = scratch_strdup(serv->s_proto);
315 #else
316 #define CONVERT_HOSTENT(a,b) memcpy(a, &b, sizeof(a))
317 #define CONVERT_PROTOENT(a,b) memcpy(a, &b, sizeof(a))
318 #define CONVERT_SERVENT(a,b) memcpy(a, &b, sizeof(a))
319 #endif
321 SOCKET WINSOCK_accept(SOCKET s, struct sockaddr *addr, INT *addrlen)
323 int sock;
325 dprintf_winsock(stddeb, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, *addrlen);
327 if ((sock = accept(s, addr, (int *) addrlen)) < 0) {
328 errno_to_wsaerrno();
329 return INVALID_SOCKET;
331 return sock;
334 INT WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
336 dprintf_winsock(stddeb, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
337 dump_sockaddr(name);
339 if (bind(s, name, namelen) < 0) {
340 errno_to_wsaerrno();
341 return SOCKET_ERROR;
343 return 0;
346 INT WINSOCK_closesocket(SOCKET s)
348 dprintf_winsock(stddeb, "WSA_closesocket: socket %d\n", s);
350 FD_CLR(s, &fd_in_use);
352 if (close(s) < 0) {
353 errno_to_wsaerrno();
354 return SOCKET_ERROR;
356 return 0;
359 INT WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen)
361 dprintf_winsock(stddeb, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
362 dump_sockaddr(name);
364 if (connect(s, name, namelen) < 0) {
365 errno_to_wsaerrno();
366 return SOCKET_ERROR;
368 return 0;
371 INT WINSOCK_getpeername(SOCKET s, struct sockaddr *name, INT *namelen)
373 dprintf_winsock(stddeb, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
374 dump_sockaddr(name);
376 if (getpeername(s, name, (int *) namelen) < 0) {
377 errno_to_wsaerrno();
378 return SOCKET_ERROR;
380 return 0;
383 INT WINSOCK_getsockname(SOCKET s, struct sockaddr *name, INT *namelen)
385 dprintf_winsock(stddeb, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
386 if (getsockname(s, name, (int *) namelen) < 0) {
387 errno_to_wsaerrno();
388 return SOCKET_ERROR;
390 return 0;
394 WINSOCK_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
396 dprintf_winsock(stddeb, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen);
397 convert_sockopt(&level, &optname);
399 if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) {
400 errno_to_wsaerrno();
401 return SOCKET_ERROR;
403 return 0;
406 u_long WINSOCK_htonl(u_long hostlong)
408 return( htonl(hostlong) );
411 u_short WINSOCK_htons(u_short hostshort)
413 return( htons(hostshort) );
416 u_long WINSOCK_inet_addr(char *cp)
418 return( inet_addr(cp) );
421 char *WINSOCK_inet_ntoa(struct in_addr in)
423 char *s;
425 /* dprintf_winsock(stddeb, "WSA_inet_ntoa: %8lx\n", (int) in);*/
427 if ((s = inet_ntoa(in)) == NULL) {
428 errno_to_wsaerrno();
429 return NULL;
432 strncpy(Heap->ntoa_buffer, s, sizeof(Heap->ntoa_buffer) );
434 return (char *) GET_SEG_PTR(&Heap->ntoa_buffer);
437 INT WINSOCK_ioctlsocket(SOCKET s, u_long cmd, u_long *argp)
439 long newcmd;
440 u_long *newargp;
441 char *ctlname;
442 dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %lX, ptr %8x\n", s, cmd, (int) argp);
444 /* Why can't they all use the same ioctl numbers */
445 newcmd=cmd;
446 newargp=argp;
447 ctlname=0;
448 if(cmd == _IOR('f',127,u_long))
450 ctlname="FIONREAD";
451 newcmd=FIONREAD;
452 }else
453 if(cmd == _IOW('f',126,u_long) || cmd == _IOR('f',126,u_long))
455 ctlname="FIONBIO";
456 newcmd=FIONBIO;
457 }else
458 if(cmd == _IOW('f',125,u_long))
460 ctlname="FIOASYNC";
461 newcmd=FIOASYNC;
464 if(!ctlname)
465 fprintf(stderr,"Unknown winsock ioctl. Trying anyway\n");
466 else
467 dprintf_winsock(stddeb,"Recognized as %s\n", ctlname);
470 if (ioctl(s, newcmd, newargp) < 0) {
471 errno_to_wsaerrno();
472 return SOCKET_ERROR;
474 return 0;
477 INT WINSOCK_listen(SOCKET s, INT backlog)
479 dprintf_winsock(stddeb, "WSA_listen: socket %d, backlog %d\n", s, backlog);
481 if (listen(s, backlog) < 0) {
482 errno_to_wsaerrno();
483 return SOCKET_ERROR;
485 return 0;
488 u_long WINSOCK_ntohl(u_long netlong)
490 return( ntohl(netlong) );
493 u_short WINSOCK_ntohs(u_short netshort)
495 return( ntohs(netshort) );
498 INT WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
500 int length;
502 dprintf_winsock(stddeb, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags);
504 if ((length = recv(s, buf, len, flags)) < 0) {
505 errno_to_wsaerrno();
506 return SOCKET_ERROR;
508 return length;
511 INT WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags,
512 struct sockaddr *from, int *fromlen)
514 int length;
516 dprintf_winsock(stddeb, "WSA_recvfrom: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long)buf, len, flags);
518 if ((length = recvfrom(s, buf, len, flags, from, fromlen)) < 0) {
519 errno_to_wsaerrno();
520 return SOCKET_ERROR;
522 return length;
525 INT WINSOCK_select(INT nfds, fd_set *readfds, fd_set *writefds,
526 fd_set *exceptfds, struct timeval *timeout)
528 dprintf_winsock(stddeb, "WSA_select: fd # %d, ptr %8lx, ptr %8lx, ptr %8lX\n", nfds, (unsigned long) readfds, (unsigned long) writefds, (unsigned long) exceptfds);
530 return(select(nfds, readfds, writefds, exceptfds, timeout));
533 INT WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
535 int length;
537 dprintf_winsock(stddeb, "WSA_send: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
539 if ((length = send(s, buf, len, flags)) < 0) {
540 errno_to_wsaerrno();
541 return SOCKET_ERROR;
543 return length;
546 INT WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
547 struct sockaddr *to, INT tolen)
549 int length;
551 dprintf_winsock(stddeb, "WSA_sendto: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
553 if ((length = sendto(s, buf, len, flags, to, tolen)) < 0) {
554 errno_to_wsaerrno();
555 return SOCKET_ERROR;
557 return length;
560 INT WINSOCK_setsockopt(SOCKET s, INT level, INT optname, const char *optval,
561 INT optlen)
563 dprintf_winsock(stddeb, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen);
564 convert_sockopt(&level, &optname);
566 if (setsockopt(s, level, optname, optval, optlen) < 0) {
567 errno_to_wsaerrno();
568 return SOCKET_ERROR;
570 return 0;
573 INT WINSOCK_shutdown(SOCKET s, INT how)
575 dprintf_winsock(stddeb, "WSA_shutdown: socket s %d, how %d\n", s, how);
577 if (shutdown(s, how) < 0) {
578 errno_to_wsaerrno();
579 return SOCKET_ERROR;
581 return 0;
584 SOCKET WINSOCK_socket(INT af, INT type, INT protocol)
586 int sock;
588 dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol);
590 if ((sock = socket(af, type, protocol)) < 0) {
591 errno_to_wsaerrno();
592 dprintf_winsock(stddeb, "WSA_socket: failed !\n");
593 return INVALID_SOCKET;
596 if (sock > 0xffff) {
597 wsa_errno = WSAEMFILE;
598 return INVALID_SOCKET;
601 FD_SET(sock, &fd_in_use);
603 dprintf_winsock(stddeb, "WSA_socket: fd %d\n", sock);
604 return sock;
608 struct WIN_hostent *
610 SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
612 struct hostent *host;
614 dprintf_winsock(stddeb, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type);
616 if ((host = gethostbyaddr(addr, len, type)) == NULL) {
617 errno_to_wsaerrno();
618 return NULL;
620 CONVERT_HOSTENT(&Heap->hostent_addr, host);
622 return GET_SEG_PTR(&Heap->hostent_addr);
626 struct WIN_hostent *
628 SEGPTR WINSOCK_gethostbyname(const char *name)
630 struct hostent *host;
632 dprintf_winsock(stddeb, "WSA_gethostbyname: %s\n", name);
634 if ((host = gethostbyname(name)) == NULL) {
635 errno_to_wsaerrno();
636 return NULL;
638 CONVERT_HOSTENT(&Heap->hostent_name, host);
640 return GET_SEG_PTR(&Heap->hostent_name);
643 INT WINSOCK_gethostname(char *name, INT namelen)
645 dprintf_winsock(stddeb, "WSA_gethostname: name %s, len %d\n", name, namelen);
647 if (gethostname(name, namelen) < 0) {
648 errno_to_wsaerrno();
649 return SOCKET_ERROR;
651 return 0;
655 struct WIN_protoent *
657 SEGPTR WINSOCK_getprotobyname(char *name)
659 struct protoent *proto;
661 dprintf_winsock(stddeb, "WSA_getprotobyname: name %s\n", name);
663 if ((proto = getprotobyname(name)) == NULL) {
664 errno_to_wsaerrno();
665 return NULL;
667 CONVERT_PROTOENT(&Heap->protoent_name, proto);
669 return GET_SEG_PTR(&Heap->protoent_name);
673 struct WIN_protoent *
675 SEGPTR WINSOCK_getprotobynumber(INT number)
677 struct protoent *proto;
679 dprintf_winsock(stddeb, "WSA_getprotobynumber: num %d\n", number);
681 if ((proto = getprotobynumber(number)) == NULL) {
682 errno_to_wsaerrno();
683 return NULL;
685 CONVERT_PROTOENT(&Heap->protoent_number, proto);
687 return GET_SEG_PTR(&Heap->protoent_number);
691 struct WIN_servent *
693 SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
695 struct servent *service;
697 if (proto == NULL)
698 proto = "tcp";
700 dprintf_winsock(stddeb, "WSA_getservbyname: name %s, proto %s\n", name, proto);
702 if ((service = getservbyname(name, proto)) == NULL) {
703 errno_to_wsaerrno();
704 return NULL;
706 CONVERT_SERVENT(&Heap->servent_name, service);
708 return GET_SEG_PTR(&Heap->servent_name);
712 struct WIN_servent *
714 SEGPTR WINSOCK_getservbyport(INT port, const char *proto)
716 struct servent *service;
718 dprintf_winsock(stddeb, "WSA_getservbyport: port %d, name %s\n", port, proto);
720 if ((service = getservbyport(port, proto)) == NULL) {
721 errno_to_wsaerrno();
722 return NULL;
724 CONVERT_SERVENT(&Heap->servent_port, service);
726 return GET_SEG_PTR(&Heap->servent_port);
729 /******************** winsock specific functions ************************
732 static HANDLE new_handle = 0;
734 static HANDLE AllocWSAHandle(void)
736 return new_handle++;
739 static void recv_message(int sig)
741 struct ipc_packet message;
743 if (msgrcv(wine_key, &message, IPC_PACKET_SIZE, MTYPE, IPC_NOWAIT) == -1)
744 perror("wine: msgrcv");
746 fprintf(stderr,
747 "WSA: PostMessage (hwnd %d, wMsg %d, wParam %d, lParam %ld)\n",
748 message.hWnd,
749 message.wMsg,
750 message.handle,
751 message.lParam);
753 PostMessage(message.hWnd, message.wMsg, message.handle, message.lParam);
755 signal(SIGUSR1, recv_message);
759 static void send_message(HANDLE handle, HWND hWnd, u_int wMsg, long lParam)
761 struct ipc_packet message;
763 message.mtype = MTYPE;
764 message.handle = handle;
765 message.hWnd = hWnd;
766 message.wMsg = wMsg;
767 message.lParam = lParam;
769 fprintf(stderr,
770 "WSA: send (hwnd %d, wMsg %d, handle %d, lParam %ld)\n",
771 hWnd, wMsg, handle, lParam);
773 if (msgsnd(wine_key, &message, IPC_PACKET_SIZE, IPC_NOWAIT) == -1)
774 perror("wine: msgsnd");
776 kill(getppid(), SIGUSR1);
780 HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char *addr,
781 INT len, INT type, char *buf, INT buflen)
783 HANDLE handle;
784 struct hostent *host;
786 handle = AllocWSAHandle();
788 if (fork()) {
789 return handle;
790 } else {
791 if ((host = gethostbyaddr(addr, len, type)) == NULL) {
792 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
793 exit(0);
795 memcpy(buf, host, buflen);
796 send_message(hWnd, wMsg, handle, 0);
797 exit(0);
802 HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char *name,
803 char *buf, INT buflen)
805 HANDLE handle;
806 struct hostent *host;
808 handle = AllocWSAHandle();
810 if (fork()) {
811 return handle;
812 } else {
813 if ((host = gethostbyname(name)) == NULL) {
814 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
815 exit(0);
817 memcpy(buf, host, buflen);
818 send_message(hWnd, wMsg, handle, 0);
819 exit(0);
824 HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, const char *name,
825 char *buf, INT buflen)
827 HANDLE handle;
828 struct protoent *proto;
830 handle = AllocWSAHandle();
832 if (fork()) {
833 return handle;
834 } else {
835 if ((proto = getprotobyname(name)) == NULL) {
836 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
837 exit(0);
839 memcpy(buf, proto, buflen);
840 send_message(hWnd, wMsg, handle, 0);
841 exit(0);
846 HANDLE WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number,
847 char *buf, INT buflen)
849 HANDLE handle;
850 struct protoent *proto;
852 handle = AllocWSAHandle();
854 if (fork()) {
855 return handle;
856 } else {
857 if ((proto = getprotobynumber(number)) == NULL) {
858 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
859 exit(0);
861 memcpy(buf, proto, buflen);
862 send_message(hWnd, wMsg, handle, 0);
863 exit(0);
868 HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, const char *name,
869 const char *proto, char *buf, INT buflen)
871 HANDLE handle;
872 struct servent *service;
874 handle = AllocWSAHandle();
876 if (fork()) {
877 return handle;
878 } else {
879 if ((service = getservbyname(name, proto)) == NULL) {
880 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
881 exit(0);
883 memcpy(buf, service, buflen);
884 send_message(hWnd, wMsg, handle, 0);
885 exit(0);
890 HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char
891 *proto, char *buf, INT buflen)
893 HANDLE handle;
894 struct servent *service;
896 handle = AllocWSAHandle();
898 if (fork()) {
899 return handle;
900 } else {
901 if ((service = getservbyport(port, proto)) == NULL) {
902 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
903 exit(0);
905 memcpy(buf, service, buflen);
906 send_message(hWnd, wMsg, handle, 0);
907 exit(0);
911 INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent)
913 long event;
914 fd_set read_fds, write_fds, except_fds;
916 dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND %d, wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
918 /* remove outstanding asyncselect() processes */
919 /* kill */
921 if (wMsg == 0 && lEvent == 0)
922 return 0;
924 if (fork()) {
925 return 0;
926 } else {
927 while (1) {
928 FD_ZERO(&read_fds);
929 FD_ZERO(&write_fds);
930 FD_ZERO(&except_fds);
932 if (lEvent & FD_READ)
933 FD_SET(s, &read_fds);
934 if (lEvent & FD_WRITE)
935 FD_SET(s, &write_fds);
937 fcntl(s, F_SETFL, O_NONBLOCK);
938 select(s + 1, &read_fds, &write_fds, &except_fds, NULL);
940 event = 0;
941 if (FD_ISSET(s, &read_fds))
942 event |= FD_READ;
943 if (FD_ISSET(s, &write_fds))
944 event |= FD_WRITE;
946 send_message(hWnd, wMsg, s, (wsaerrno() << 16) | event);
951 INT WSAFDIsSet(INT fd, fd_set *set)
953 return( FD_ISSET(fd, set) );
956 INT WSACancelAsyncRequest(HANDLE hAsyncTaskHandle)
958 dprintf_winsock(stddeb, "WSA_AsyncRequest: handle %d\n", hAsyncTaskHandle);
960 return 0;
963 INT WSACancelBlockingCall(void)
965 dprintf_winsock(stddeb, "WSA_CancelBlockCall\n");
966 return 0;
969 INT WSAGetLastError(void)
971 dprintf_winsock(stddeb, "WSA_GetLastError = %x\n", wsa_errno);
973 return wsa_errno;
976 void WSASetLastError(INT iError)
978 dprintf_winsock(stddeb, "WSA_SetLastErorr %d\n", iError);
980 wsa_errno = iError;
983 BOOL WSAIsBlocking(void)
985 dprintf_winsock(stddeb, "WSA_IsBlocking\n");
987 return 0;
990 FARPROC WSASetBlockingHook(FARPROC lpBlockFunc)
992 dprintf_winsock(stddeb, "WSA_SetBlockHook %8lx, STUB!\n", (unsigned long) lpBlockFunc);
993 BlockFunction = lpBlockFunc;
995 return (FARPROC) lpBlockFunc;
998 INT WSAUnhookBlockingHook(void)
1000 dprintf_winsock(stddeb, "WSA_UnhookBlockingHook\n");
1001 BlockFunction = NULL;
1003 return 0;
1006 WSADATA WINSOCK_data = {
1007 0x0101,
1008 0x0101,
1009 "WINE Sockets",
1010 #ifdef linux
1011 "LINUX/i386",
1012 #endif
1013 #ifdef __NetBSD__
1014 "NetBSD/i386",
1015 #endif
1016 #ifdef sunos
1017 "SunOS",
1018 #endif
1019 128,
1020 1024,
1021 NULL
1024 INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
1027 dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
1029 if (LOBYTE(wVersionRequested) < 1 ||
1030 (LOBYTE(wVersionRequested) == 1 &&
1031 HIBYTE(wVersionRequested) < 1))
1032 return WSAVERNOTSUPPORTED;
1034 if (!lpWSAData)
1035 return WSAEINVAL;
1037 /* alloc winsock heap */
1039 if ((HeapHandle = GlobalAlloc(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0)
1040 return WSASYSNOTREADY;
1042 Heap = (struct WinSockHeap *) GlobalLock(HeapHandle);
1043 bcopy(&WINSOCK_data, lpWSAData, sizeof(WINSOCK_data));
1045 /* ipc stuff */
1047 if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
1048 perror("wine: msgget");
1050 signal(SIGUSR1, recv_message);
1052 /* clear */
1054 FD_ZERO(&fd_in_use);
1056 wsa_initted = 1;
1057 return(0);
1060 INT WSACleanup(void)
1062 int fd;
1064 if (wine_key)
1065 if (msgctl(wine_key, IPC_RMID, NULL) == -1)
1066 perror("wine: shmctl");
1068 for (fd = 0; fd != FD_SETSIZE; fd++)
1069 if (FD_ISSET(fd, &fd_in_use))
1070 close(fd);
1072 wsa_initted = 0;
1073 return 0;