| /* |
| * based on Windows Sockets 1.1 specs |
| * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT) |
| * |
| * (C) 1993,1994 John Brezak, Erik Bos. |
| */ |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <signal.h> |
| #include <sys/types.h> |
| #include <sys/ipc.h> |
| #include <sys/socket.h> |
| #include <netinet/in.h> |
| #include <arpa/inet.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <netdb.h> |
| #include <unistd.h> |
| #include "heap.h" |
| #include "winsock.h" |
| |
| #define DEBUG_WINSOCK |
| |
| static WORD wsa_errno; |
| static int wsa_initted; |
| static key_t wine_key = 0; |
| static FARPROC BlockFunction; |
| static fd_set fd_in_use; |
| |
| struct ipc_packet { |
| long mtype; |
| HANDLE handle; |
| HWND hWnd; |
| WORD wMsg; |
| LONG lParam; |
| }; |
| #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long)) |
| |
| #define MTYPE 0xb0b0eb05 |
| |
| struct WinSockHeap { |
| char ntoa_buffer[32]; |
| |
| struct hostent hostent_addr; |
| struct hostent hostent_name; |
| struct protoent protoent_name; |
| struct protoent protoent_number; |
| struct servent servent_name; |
| struct servent servent_port; |
| |
| struct hostent WSAhostent_addr; |
| struct hostent WSAhostent_name; |
| struct protoent WSAprotoent_name; |
| struct protoent WSAprotoent_number; |
| struct servent WSAservent_name; |
| struct servent WSAservent_port; |
| }; |
| static struct WinSockHeap *heap; |
| |
| #define dump_sockaddr(a) \ |
| fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \ |
| ((struct sockaddr_in *)a)->sin_family, \ |
| inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \ |
| ntohs(((struct sockaddr_in *)a)->sin_port)) |
| |
| static WORD wsaerrno(void) |
| { |
| #ifdef DEBUG_WINSOCK |
| #ifndef sun |
| #if defined(__FreeBSD__) |
| fprintf(stderr, "winsock: errno %d, (%s).\n", |
| errno, sys_errlist[errno]); |
| #else |
| fprintf(stderr, "winsock: errno %d, (%s).\n", |
| errno, strerror(errno)); |
| #endif |
| #else |
| fprintf(stderr, "winsock: errno %d\n", errno); |
| #endif |
| #endif |
| |
| switch(errno) |
| { |
| case EINTR: return WSAEINTR; |
| case EACCES: return WSAEACCES; |
| case EFAULT: return WSAEFAULT; |
| case EINVAL: return WSAEINVAL; |
| case EMFILE: return WSAEMFILE; |
| case EWOULDBLOCK: return WSAEWOULDBLOCK; |
| case EINPROGRESS: return WSAEINPROGRESS; |
| case EALREADY: return WSAEALREADY; |
| case EBADF: |
| case ENOTSOCK: return WSAENOTSOCK; |
| case EDESTADDRREQ: return WSAEDESTADDRREQ; |
| case EMSGSIZE: return WSAEMSGSIZE; |
| case EPROTOTYPE: return WSAEPROTOTYPE; |
| case ENOPROTOOPT: return WSAENOPROTOOPT; |
| case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT; |
| case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT; |
| case EOPNOTSUPP: return WSAEOPNOTSUPP; |
| case EPFNOSUPPORT: return WSAEPFNOSUPPORT; |
| case EAFNOSUPPORT: return WSAEAFNOSUPPORT; |
| case EADDRINUSE: return WSAEADDRINUSE; |
| case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL; |
| case ENETDOWN: return WSAENETDOWN; |
| case ENETUNREACH: return WSAENETUNREACH; |
| case ENETRESET: return WSAENETRESET; |
| case ECONNABORTED: return WSAECONNABORTED; |
| case ECONNRESET: return WSAECONNRESET; |
| case ENOBUFS: return WSAENOBUFS; |
| case EISCONN: return WSAEISCONN; |
| case ENOTCONN: return WSAENOTCONN; |
| case ESHUTDOWN: return WSAESHUTDOWN; |
| case ETOOMANYREFS: return WSAETOOMANYREFS; |
| case ETIMEDOUT: return WSAETIMEDOUT; |
| case ECONNREFUSED: return WSAECONNREFUSED; |
| case ELOOP: return WSAELOOP; |
| case ENAMETOOLONG: return WSAENAMETOOLONG; |
| case EHOSTDOWN: return WSAEHOSTDOWN; |
| case EHOSTUNREACH: return WSAEHOSTUNREACH; |
| case ENOTEMPTY: return WSAENOTEMPTY; |
| /* case EPROCLIM: return WSAEPROCLIM; */ |
| case EUSERS: return WSAEUSERS; |
| case EDQUOT: return WSAEDQUOT; |
| case ESTALE: return WSAESTALE; |
| case EREMOTE: return WSAEREMOTE; |
| |
| default: |
| fprintf(stderr, "winsock: unknown errorno %d!\n", errno); |
| return WSAEOPNOTSUPP; |
| } |
| } |
| |
| static WORD errno_to_wsaerrno(void) |
| { |
| wsa_errno = wsaerrno(); |
| } |
| |
| SOCKET Winsock_accept(SOCKET s, struct sockaddr FAR *addr, INT FAR *addrlen) |
| { |
| int sock; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, addrlen); |
| #endif |
| |
| if ((sock = accept(s, addr, (int *) addrlen)) < 0) { |
| errno_to_wsaerrno(); |
| return INVALID_SOCKET; |
| } |
| return sock; |
| } |
| |
| INT Winsock_bind(SOCKET s, struct sockaddr FAR *name, INT namelen) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen); |
| dump_sockaddr(name); |
| #endif |
| |
| if (bind(s, name, namelen) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return 0; |
| } |
| |
| INT Winsock_closesocket(SOCKET s) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_closesocket: socket %d\n", s); |
| #endif |
| |
| FD_CLR(s, &fd_in_use); |
| |
| if (close(s) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return 0; |
| } |
| |
| INT Winsock_connect(SOCKET s, struct sockaddr FAR *name, INT namelen) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen); |
| dump_sockaddr(name); |
| #endif |
| |
| if (connect(s, name, namelen) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return 0; |
| } |
| |
| INT Winsock_getpeername(SOCKET s, struct sockaddr FAR *name, INT FAR *namelen) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen); |
| dump_sockaddr(name); |
| #endif |
| |
| if (getpeername(s, name, (int *) namelen) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return 0; |
| } |
| |
| INT Winsock_getsockname(SOCKET s, struct sockaddr FAR *name, INT FAR *namelen) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen); |
| #endif |
| if (getsockname(s, name, (int *) namelen) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return 0; |
| } |
| |
| INT Winsock_getsockopt(SOCKET s, INT loptname, char FAR *optval, INT FAR *optlen) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, loptname, (int) optval, (int) *optlen); |
| #endif |
| if (getsockopt(s, 0, (int) loptname, optval, (int *) optlen) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return 0; |
| } |
| |
| u_long Winsock_htonl(u_long hostlong) |
| { |
| return( htonl(hostlong) ); |
| } |
| |
| u_short Winsock_htons(u_short hostshort) |
| { |
| return( htons(hostshort) ); |
| } |
| |
| u_long Winsock_inet_addr(char FAR *cp) |
| { |
| return( inet_addr(cp) ); |
| } |
| |
| char *Winsock_inet_ntoa(struct in_addr in) |
| { |
| char *s; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_inet_ntoa: %8x\n", in); |
| #endif |
| |
| if ((s = inet_ntoa(in)) == NULL) { |
| errno_to_wsaerrno(); |
| return NULL; |
| } |
| |
| strncpy(heap->ntoa_buffer, s, sizeof(heap->ntoa_buffer) ); |
| |
| return (char *) &heap->ntoa_buffer; |
| } |
| |
| INT Winsock_ioctlsocket(SOCKET s, long cmd, u_long FAR *argp) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_ioctl: socket %d, cmd %d, ptr %8x\n", s, cmd, (int) argp); |
| #endif |
| |
| if (ioctl(s, cmd, argp) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return 0; |
| } |
| |
| INT Winsock_listen(SOCKET s, INT backlog) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_listen: socket %d, backlog %d\n", s, backlog); |
| #endif |
| |
| if (listen(s, backlog) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return 0; |
| } |
| |
| u_long Winsock_ntohl(u_long netlong) |
| { |
| return( ntohl(netlong) ); |
| } |
| |
| u_short Winsock_ntohs(u_short netshort) |
| { |
| return( ntohs(netshort) ); |
| } |
| |
| INT Winsock_recv(SOCKET s, char FAR *buf, INT len, INT flags) |
| { |
| int length; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags); |
| #endif |
| |
| if ((length = recv(s, buf, len, flags)) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return length; |
| } |
| |
| INT Winsock_recvfrom(SOCKET s, char FAR *buf, INT len, INT flags, |
| struct sockaddr FAR *from, int FAR *fromlen) |
| { |
| int length; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_recvfrom: socket %d, ptr %8x, length %d, flags %d\n", s, buf, len, flags); |
| #endif |
| |
| if ((length = recvfrom(s, buf, len, flags, from, fromlen)) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return length; |
| } |
| |
| INT Winsock_select(INT nfds, fd_set FAR *readfds, fd_set FAR *writefds, |
| fd_set FAR *exceptfds, struct timeval FAR *timeout) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_select: fd # %d, ptr %8x, ptr %8x, ptr %*X\n", nfds, readfds, writefds, exceptfds); |
| #endif |
| |
| return(select(nfds, readfds, writefds, exceptfds, timeout)); |
| } |
| |
| INT Winsock_send(SOCKET s, char FAR *buf, INT len, INT flags) |
| { |
| int length; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_send: socket %d, ptr %8x, length %d, flags %d\n", s, buf, len, flags); |
| #endif |
| |
| if ((length = send(s, buf, len, flags)) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return length; |
| } |
| |
| INT Winsock_sendto(SOCKET s, char FAR *buf, INT len, INT flags, |
| struct sockaddr FAR *to, INT tolen) |
| { |
| int length; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_sendto: socket %d, ptr %8x, length %d, flags %d\n", s, buf, len, flags); |
| #endif |
| |
| if ((length = sendto(s, buf, len, flags, to, tolen)) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return length; |
| } |
| |
| INT Winsock_setsockopt(SOCKET s, INT level, INT optname, const char FAR *optval, |
| INT optlen) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen); |
| #endif |
| |
| if (setsockopt(s, level, optname, optval, optlen) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return 0; |
| } |
| |
| INT Winsock_shutdown(SOCKET s, INT how) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_shutdown: socket s %d, how %d\n", s, how); |
| #endif |
| |
| if (shutdown(s, how) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return 0; |
| } |
| |
| SOCKET Winsock_socket(INT af, INT type, INT protocol) |
| { |
| int sock; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol); |
| #endif |
| |
| if ((sock = socket(af, type, protocol)) < 0) { |
| errno_to_wsaerrno(); |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_socket: failed !\n"); |
| #endif |
| return INVALID_SOCKET; |
| } |
| |
| if (sock > 0xffff) { |
| wsa_errno = WSAEMFILE; |
| return INVALID_SOCKET; |
| } |
| |
| FD_SET(sock, &fd_in_use); |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_socket: fd %d\n", sock); |
| #endif |
| return sock; |
| } |
| |
| struct hostent *Winsock_gethostbyaddr(const char FAR *addr, INT len, INT type) |
| { |
| struct hostent *host; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type); |
| #endif |
| |
| if ((host = gethostbyaddr(addr, len, type)) == NULL) { |
| errno_to_wsaerrno(); |
| return NULL; |
| } |
| memcpy(&heap->hostent_addr, host, sizeof(struct hostent)); |
| |
| return (struct hostent *) &heap->hostent_addr; |
| } |
| |
| struct hostent *Winsock_gethostbyname(const char FAR *name) |
| { |
| struct hostent *host; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_gethostbyname: name %s\n", name); |
| #endif |
| |
| if ((host = gethostbyname(name)) == NULL) { |
| errno_to_wsaerrno(); |
| return NULL; |
| } |
| memcpy(&heap->hostent_name, host, sizeof(struct hostent)); |
| |
| return (struct hostent *) &heap->hostent_name; |
| } |
| |
| int Winsock_gethostname(char FAR *name, INT namelen) |
| { |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_gethostname: name %d, len %d\n", name, namelen); |
| #endif |
| |
| if (gethostname(name, namelen) < 0) { |
| errno_to_wsaerrno(); |
| return SOCKET_ERROR; |
| } |
| return 0; |
| } |
| |
| struct protoent *Winsock_getprotobyname(char FAR *name) |
| { |
| struct protoent *proto; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_getprotobyname: name %s\n", name); |
| #endif |
| |
| if ((proto = getprotobyname(name)) == NULL) { |
| errno_to_wsaerrno(); |
| return NULL; |
| } |
| memcpy(&heap->protoent_name, proto, sizeof(struct protoent)); |
| |
| return (struct protoent *) &heap->protoent_name; |
| } |
| |
| struct protoent *Winsock_getprotobynumber(INT number) |
| { |
| struct protoent *proto; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_getprotobynumber: num %d\n", number); |
| #endif |
| |
| if ((proto = getprotobynumber(number)) == NULL) { |
| errno_to_wsaerrno(); |
| return NULL; |
| } |
| memcpy(&heap->protoent_number, proto, sizeof(struct protoent)); |
| |
| return (struct protoent *) &heap->protoent_number; |
| } |
| |
| struct servent *Winsock_getservbyname(const char FAR *name, const char FAR *proto) |
| { |
| struct servent *service; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_getservbyname: name %s, proto %s\n", name, proto); |
| #endif |
| |
| if ((service = getservbyname(name, proto)) == NULL) { |
| errno_to_wsaerrno(); |
| return NULL; |
| } |
| memcpy(&heap->servent_name, service, sizeof(struct servent)); |
| |
| return (struct servent *) &heap->servent_name; |
| } |
| |
| struct servent *Winsock_getservbyport(INT port, const char FAR *proto) |
| { |
| struct servent *service; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_getservbyport: port %d, name %s\n", port, proto); |
| #endif |
| |
| if ((service = getservbyport(port, proto)) == NULL) { |
| errno_to_wsaerrno(); |
| return NULL; |
| } |
| memcpy(&heap->servent_port, service, sizeof(struct servent)); |
| |
| return (struct servent *) &heap->servent_port; |
| } |
| |
| /******************** winsock specific functions ************************ |
| * |
| */ |
| |
| #define AllocWSAHandle() getpid() |
| |
| static void recv_message(int sig) |
| { |
| struct ipc_packet message; |
| |
| if (msgrcv(wine_key, &message, IPC_PACKET_SIZE, MTYPE, IPC_NOWAIT) == -1) |
| perror("wine: msgrcv"); |
| |
| fprintf(stderr, |
| "WSA: PostMessage (hwnd %d, wMsg %d, wParam %d, lParam %d)\n", |
| message.hWnd, |
| message.wMsg, |
| message.handle, |
| message.lParam); |
| |
| PostMessage(message.hWnd, message.wMsg, message.handle, message.lParam); |
| |
| signal(SIGUSR1, recv_message); |
| } |
| |
| |
| static void send_message(HANDLE handle, HWND hWnd, u_int wMsg, long lParam) |
| { |
| struct ipc_packet message; |
| |
| message.mtype = MTYPE; |
| message.handle = handle; |
| message.hWnd = hWnd; |
| message.wMsg = wMsg; |
| message.lParam = lParam; |
| |
| fprintf(stderr, |
| "WSA: send (hwnd %d, wMsg %d, handle %d, lParam %d)\n", |
| hWnd, wMsg, handle, lParam); |
| |
| if (msgsnd(wine_key, &message, IPC_PACKET_SIZE, IPC_NOWAIT) == -1) |
| perror("wine: msgsnd"); |
| |
| kill(getppid(), SIGUSR1); |
| } |
| |
| |
| HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char FAR *addr, |
| INT len, INT type, char FAR *buf, INT buflen) |
| { |
| HANDLE handle; |
| struct hostent *host; |
| |
| handle = AllocWSAHandle(); |
| |
| if (fork()) { |
| return handle; |
| } else { |
| if ((host = gethostbyaddr(addr, len, type)) == NULL) { |
| send_message(hWnd, wMsg, handle, wsaerrno() << 16); |
| exit(0); |
| } |
| memcpy(buf, host, buflen); |
| send_message(hWnd, wMsg, handle, 0); |
| exit(0); |
| } |
| } |
| |
| |
| HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char FAR *name, |
| char FAR *buf, INT buflen) |
| { |
| HANDLE handle; |
| struct hostent *host; |
| |
| handle = AllocWSAHandle(); |
| |
| if (fork()) { |
| return handle; |
| } else { |
| if ((host = gethostbyname(name)) == NULL) { |
| send_message(hWnd, wMsg, handle, wsaerrno() << 16); |
| exit(0); |
| } |
| memcpy(buf, host, buflen); |
| send_message(hWnd, wMsg, handle, 0); |
| exit(0); |
| } |
| } |
| |
| |
| HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, const char FAR *name, |
| char FAR *buf, INT buflen) |
| { |
| HANDLE handle; |
| struct protoent *proto; |
| |
| handle = AllocWSAHandle(); |
| |
| if (fork()) { |
| return handle; |
| } else { |
| if ((proto = getprotobyname(name)) == NULL) { |
| send_message(hWnd, wMsg, handle, wsaerrno() << 16); |
| exit(0); |
| } |
| memcpy(buf, proto, buflen); |
| send_message(hWnd, wMsg, handle, 0); |
| exit(0); |
| } |
| } |
| |
| |
| HANDLE WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number, |
| char FAR *buf, INT buflen) |
| { |
| HANDLE handle; |
| struct protoent *proto; |
| |
| handle = AllocWSAHandle(); |
| |
| if (fork()) { |
| return handle; |
| } else { |
| if ((proto = getprotobynumber(number)) == NULL) { |
| send_message(hWnd, wMsg, handle, wsaerrno() << 16); |
| exit(0); |
| } |
| memcpy(buf, proto, buflen); |
| send_message(hWnd, wMsg, handle, 0); |
| exit(0); |
| } |
| } |
| |
| |
| HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, const char FAR *name, |
| const char FAR *proto, char FAR *buf, INT buflen) |
| { |
| HANDLE handle; |
| struct servent *service; |
| |
| handle = AllocWSAHandle(); |
| |
| if (fork()) { |
| return handle; |
| } else { |
| if ((service = getservbyname(name, proto)) == NULL) { |
| send_message(hWnd, wMsg, handle, wsaerrno() << 16); |
| exit(0); |
| } |
| memcpy(buf, service, buflen); |
| send_message(hWnd, wMsg, handle, 0); |
| exit(0); |
| } |
| } |
| |
| |
| HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char FAR |
| *proto, char FAR *buf, INT buflen) |
| { |
| HANDLE handle; |
| struct servent *service; |
| |
| handle = AllocWSAHandle(); |
| |
| if (fork()) { |
| return handle; |
| } else { |
| if ((service = getservbyport(port, proto)) == NULL) { |
| send_message(hWnd, wMsg, handle, wsaerrno() << 16); |
| exit(0); |
| } |
| memcpy(buf, service, buflen); |
| send_message(hWnd, wMsg, handle, 0); |
| exit(0); |
| } |
| } |
| |
| INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent) |
| { |
| long event; |
| fd_set read_fds, write_fds, except_fds; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_AsyncSelect: socket %d, HWND %d, wMsg %d, event %d\n", s, hWnd, wMsg, lEvent); |
| #endif |
| |
| /* remove outstanding asyncselect() processes */ |
| /* kill */ |
| |
| if (wMsg == 0 && lEvent == 0) |
| return 0; |
| |
| if (fork()) { |
| return 0; |
| } else { |
| while (1) { |
| FD_ZERO(&read_fds); |
| FD_ZERO(&write_fds); |
| FD_ZERO(&except_fds); |
| |
| if (lEvent & FD_READ) |
| FD_SET(s, &read_fds); |
| if (lEvent & FD_WRITE) |
| FD_SET(s, &write_fds); |
| |
| fcntl(s, F_SETFL, O_NONBLOCK); |
| select(s + 1, &read_fds, &write_fds, &except_fds, NULL); |
| |
| event = 0; |
| if (FD_ISSET(s, &read_fds)) |
| event |= FD_READ; |
| if (FD_ISSET(s, &write_fds)) |
| event |= FD_WRITE; |
| |
| send_message(hWnd, wMsg, s, (wsaerrno() << 16) | event); |
| } |
| } |
| } |
| |
| INT WSAFDIsSet(INT fd, fd_set *set) |
| { |
| return( FD_ISSET(fd, set) ); |
| } |
| |
| INT WSACancelAsyncRequest(HANDLE hAsyncTaskHandle) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_AsyncRequest: handle %d\n", hAsyncTaskHandle); |
| #endif |
| |
| return 0; |
| } |
| |
| INT WSACancelBlockingCall(void) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_CancelBlockCall\n"); |
| #endif |
| return 0; |
| } |
| |
| INT WSAGetLastError(void) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_GetLastError\n"); |
| #endif |
| |
| return wsa_errno; |
| } |
| |
| void WSASetLastError(INT iError) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_SetLastErorr %d\n", iError); |
| #endif |
| |
| wsa_errno = iError; |
| } |
| |
| BOOL WSAIsBlocking(void) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_IsBlocking\n"); |
| #endif |
| } |
| |
| FARPROC WSASetBlockingHook(FARPROC lpBlockFunc) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_SetBlockHook %8x, STUB!\n", lpBlockFunc); |
| #endif |
| BlockFunction = lpBlockFunc; |
| |
| return lpBlockFunc; |
| } |
| |
| INT WSAUnhookBlockingHook(void) |
| { |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSA_UnhookBlockingHook\n"); |
| #endif |
| BlockFunction = NULL; |
| |
| return 0; |
| } |
| |
| WSADATA Winsock_data = { |
| 0x0101, |
| 0x0101, |
| "WINE Sockets", |
| #ifdef linux |
| "LINUX/i386", |
| #endif |
| #ifdef __NetBSD__ |
| "NetBSD/i386", |
| #endif |
| #ifdef sunos |
| "SunOS", |
| #endif |
| 128, |
| 1024, |
| NULL |
| }; |
| |
| INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData) |
| { |
| int HeapHandle; |
| MDESC *MyHeap; |
| |
| #ifdef DEBUG_WINSOCK |
| fprintf(stderr, "WSAStartup: verReq=%x\n", wVersionRequested); |
| #endif |
| |
| if (LOBYTE(wVersionRequested) < 1 || |
| (LOBYTE(wVersionRequested) == 1 && |
| HIBYTE(wVersionRequested) < 1)) |
| return WSAVERNOTSUPPORTED; |
| |
| if (!lpWSAData) |
| return WSAEINVAL; |
| |
| /* alloc winsock heap */ |
| |
| if ((HeapHandle = GlobalAlloc(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0) |
| return WSASYSNOTREADY; |
| |
| heap = (struct WinSockHeap *) GlobalLock(HeapHandle); |
| HEAP_Init(&MyHeap, heap, sizeof(struct WinSockHeap)); |
| bcopy(&Winsock_data, lpWSAData, sizeof(Winsock_data)); |
| |
| /* ipc stuff */ |
| |
| if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1) |
| perror("wine: msgget"); |
| |
| signal(SIGUSR1, recv_message); |
| |
| /* clear */ |
| |
| FD_ZERO(&fd_in_use); |
| |
| wsa_initted = 1; |
| return(0); |
| } |
| |
| INT WSACleanup(void) |
| { |
| int fd; |
| |
| if (wine_key) |
| if (msgctl(wine_key, IPC_RMID, NULL) == -1) |
| perror("wine: shmctl"); |
| |
| for (fd = 0; fd != FD_SETSIZE; fd++) |
| if (FD_ISSET(fd, &fd_in_use)) |
| close(fd); |
| |
| wsa_initted = 0; |
| return 0; |
| } |