mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-16 03:36:37 +00:00
2787be8766
Sun May 21 12:30:30 1995 Alexandre Julliard (julliard@sunsite.unc.edu) * [debugger/hash.c] [debugger/info.c] Added support for symbolic segmented addresses. Add symbols for all built-in API entry points. * [if1632/relay.c] [include/dlls.h] Removed dll_table structure, as we now use the built-in module structures. * [if1632/relay.c] [loader/main.c] Removed winestat option, as it was no longer very meaningful. * [include/stackframe.h] New macro MAKE_SEGPTR that creates a segmented pointer to a local variable on the 32-bit stack. * [loader/module.c] Added support for multiple instances of an application. Implemented LoadModule() and FreeModule(). * [loader/ne_image.c] [loader/task.c] Moved initialisation of built-in DLLs to InitTask(). * [memory/global.c] Implemented discardable blocks. * [misc/file.c] Search path of current executable in OpenFile(). Fixed bug with searching in Windows path. * [misc/lstr.c] Hard-coded translation tables for Ansi<->Oem. * [misc/user.c] Moved some global initializations to InitApp(), because they need a task context to be performed. * [objects/dc.c] Handle R2_BLACK and R2_WHITE specially so that they work correctly with palette displays. * [tools/build.c] Suppressed generation of the C file for DLL specs, because it's no longer needed. Output all the assembly code directly to stdout. Some changes to integrate Win32 support from Martin von Loewis. * [windows/msgbox.c] Moved message box code from misc/ to windows/. Mon May 15 23:40:04 1995 Martin Ayotte (wine@trgcorp.mksinfo.qc.ca) * [misc/audio.c] [misc/mcicda.c] [misc/mcianim.c] [misc/midi.c] [misc/mmaux.c] [misc/mmsystem.c] Modify code & use pointers conversion macros. Make cdaudio & wave devices work again (only using some applets). * [misc/profile.c] Change getc() to fgetc() where needed. Mon May 15 22:10:56 1995 Martin von Loewis <loewis@informatik.hu-berlin.de> * [if1632/Imakefile] added entries for the new files gdi32.spec, kernel32.spec, user32.spec, shell32.spec and winprocs32.spec. * [if1632/commdlg.spec][if1632/kernel.spec][if1632/shell.spec] [if1632/storage.spec][if1632/system.spec][if1632/user.spec] ChooseFont, RESERVED5, InternalExtractIcon: Marked as stubs ExtractAssociatedIcon, DoEnvironmentSubst, DumpIcon: stub implementations provided marked storage.dll,storege.sys functions as stubs * [include/pe_image.h] Added structures WIN32_builtin and WIN32_function * [include/peexe.h] PE_Import_Directory: renamed reserved fields to TimeDate, Forwarder, Thunk_List * [include/winerror.h] New file. * [loader/main.c] called RELAY32_Init * [loader/pe_image.c] xmmap: map BSS anonymous dump_imports: renamed to fixup_imports, do the fixup of imported symbols PE_LoadImage: pass raw data size to xmmap * [loader/resource.c] DumpIcon: new function * [misc/kernel32.c] New file. * [misc/main.c] make stdout and stderr unbuffered * [misc/shell.c] DoEnvironmentSubst: new function * [objects/font.c] FONT_MatchFont: try oblique if there is no italic * [rc/Imakefile][rc/parser.l] yywrap: new function Don't link with libfl.a on Linux * [tools/build.c] Added keywords stdcall, subsystem, base GenerateForWin32: new function BuildSpecFiles: call GenerateForWin32 if subsystem is win32 Mon May 15 10:38:14 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de> * [controls/listbox.c] [controls/combo.c] [windows/defwnd.c] Minor fixes. * [misc/message.c] [misc/main.c] [rc/sysres*.rc] [include/texts.h] Rewrote message box handling. * [windows/dialog.c] Dialogs should be invisible until after WM_INITDIALOG is seent. Don't switch to invisible dialog items on a TAB keypress. * [windows/mdi.c] Send WM_NCPAINT message in MDIRestoreChild(). * [windows/painting.c] Fixed typo (&& -> &). * [windows/message.c] [if1632/user.spec] Implemented PostAppMessage(). * [windows/event.c] SetCapture(0) should act like ReleaseCapture(). Tue May 9 11:55:52 1995 Eddie C. Dost (ecd@dressler.de) * [Imakefile] Changed CDEBUGFLAGS for systems running __ELF__ (temporarily) Added ASFLAGS to exported variables. * [debugger/readline/Imakefile] Moved defines for libreadline from DEFINES to EXTRA_DEFINES * [memory/local.c] [miscemu/int21.c] Added some more debugging outputs. Mon May 8 00:55:27 MET DST 1995 Dag Asheim (dash@ifi.uio.no) * [misc/message.c] Fixed a "FIXME" concerning norwegian translation. Sun May 7 23:25:23 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de> * [*/*] Removed warnings in a couple of files and deleted some obsolete code. * [controls/listbox.c] Cleanup, speed improvements & lots of bug fixes. * [controls/combo.c] Mostly rewritten. This is still very buggy, but not quite as bad as before. * [include/commdlg.h] [misc/commdlg.c] Removed the need for sysres.dll. Small bug fixes. * [objects/oembitmap.c] [include/bitmaps/<many>] [include/windows.h] [loader/library.c] [loader/main.c] [rc/sysres*.rc] Removed sysres.dll and replaced the remaining bitmaps/icons with XPM equivalents. * [misc/message.c] [windows/nonclient.c] [misc/main.c] [if1632/winprocs.spec] "About Wine..." now brings up a standard ShellAbout() window with the Wine icon and the list of contributors. * [misc/shell.c] Fixed ShellAbout()/AboutDialogProc() to show the right icon. * [windows/event.c] Small hack for non-alphanumeric keys: Dont't send the ascii value in the WM_KEYDOWN message, but some unused code instead. Should be done properly by sending different codes for each key. The edit control used to get a VK_DELETE message each time the user typed '.'. * [windows/class.c] Removed a check for CS_GLOBALCLASS in CLASS_FindClassByName(). This used to be no problem, but breaks Resource Workshop in 950403. * [objects/dib.c] New diagnostic for a bug I've been encountering. If it shows up, please report it. Sun May 7 23:11:18 EDT 1995 William Magro (wmagro@tc.cornell.edu) * [objects/color.c] Handle situation when 'dc' exists, but palette mapping does not. (Fixes kidpix2 demo.) Sun May 7 03:32:00 1995 Charles M. Hannum (mycroft@mit.edu) * [loader/ldt.c] LDT_Print: Only show the number of entries that the kernel returned. Make this work for NetBSD. Fri May 5 02:53:26 1995 Charles M. Hannum (mycroft@mit.edu) * [debugger/dbg.y] [include/wine.h] [loader/signal.c] Modify cs and ds selector values for NetBSD-current. * [debugger/debug.l] $sp, $esp: Use RN_ESP_AT_SIGNAL rather than RN_ESP. * [debugger/regpos.h] Modify sigcontext format for NetBSD-current. SC_ESP: Use RN_ESP_AT_SIGNAL rather than RN_ESP. * [include/ldt.h] SELECTOR_TO_ENTRY: Explicitly clear the top half of the selector value, since only 16 bits of it may have been saved. * [misc/winsocket.c] Set structure packing with `#pragma pack' to accomodate other/older compilers. Tue May 2 18:15:01 1995 Paal Beyer (beyer@idt.unit.no) * [misc/commdlg.c] Fixed path-names so when changing directory the listboxes changes too. * [debugger/dbg.y debugger/debug.l wine.ini] Added SymbolTableFile to wine.ini so symbols can be read without standing in the directory containing wine.sym. Added the possibility to specify full name of wine.sym from the debugger prompt.
939 lines
21 KiB
C
939 lines
21 KiB
C
/*
|
|
* 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/ioctl.h>
|
|
#include <sys/msg.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 "winsock.h"
|
|
#include "stddebug.h"
|
|
#include "debug.h"
|
|
|
|
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;
|
|
};
|
|
|
|
#pragma pack(1)
|
|
|
|
#define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long))
|
|
#define MTYPE 0xb0b0eb05
|
|
#define WINE_PACKED __attribute__ ((packed))
|
|
|
|
struct WIN_hostent {
|
|
char *h_name WINE_PACKED; /* official name of host */
|
|
char **h_aliases WINE_PACKED; /* alias list */
|
|
int h_addrtype WINE_PACKED; /* host address type */
|
|
int h_length WINE_PACKED; /* length of address */
|
|
char **h_addr_list WINE_PACKED; /* list of addresses from name server */
|
|
char *names[2];
|
|
char hostname[200];
|
|
};
|
|
|
|
struct WIN_protoent {
|
|
char *p_name WINE_PACKED; /* official protocol name */
|
|
char **p_aliases WINE_PACKED; /* alias list */
|
|
int p_proto WINE_PACKED; /* protocol # */
|
|
};
|
|
|
|
struct WIN_servent {
|
|
char *s_name WINE_PACKED; /* official service name */
|
|
char **s_aliases WINE_PACKED; /* alias list */
|
|
int s_port WINE_PACKED; /* port # */
|
|
char *s_proto WINE_PACKED; /* protocol to use */
|
|
};
|
|
|
|
struct WinSockHeap {
|
|
char ntoa_buffer[32];
|
|
|
|
struct WIN_hostent hostent_addr;
|
|
struct WIN_hostent hostent_name;
|
|
struct WIN_protoent protoent_name;
|
|
struct WIN_protoent protoent_number;
|
|
struct WIN_servent servent_name;
|
|
struct WIN_servent servent_port;
|
|
|
|
struct WIN_hostent WSAhostent_addr;
|
|
struct WIN_hostent WSAhostent_name;
|
|
struct WIN_protoent WSAprotoent_name;
|
|
struct WIN_protoent WSAprotoent_number;
|
|
struct WIN_servent WSAservent_name;
|
|
struct WIN_servent WSAservent_port;
|
|
};
|
|
static struct WinSockHeap *heap;
|
|
|
|
#pragma pack(4)
|
|
|
|
#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;
|
|
#ifdef EPROCLIM
|
|
case EPROCLIM: return WSAEPROCLIM;
|
|
#endif
|
|
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 void errno_to_wsaerrno(void)
|
|
{
|
|
wsa_errno = wsaerrno();
|
|
}
|
|
|
|
static void convert_sockopt(INT *level, INT *optname)
|
|
{
|
|
/* $%#%!@! why couldn't they use the same values for both winsock and unix ? */
|
|
|
|
switch (*level) {
|
|
case -1:
|
|
*level = SOL_SOCKET;
|
|
switch (*optname) {
|
|
case 0x01: *optname = SO_DEBUG;
|
|
break;
|
|
case 0x04: *optname = SO_REUSEADDR;
|
|
break;
|
|
case 0x08: *optname = SO_KEEPALIVE;
|
|
break;
|
|
case 0x10: *optname = SO_DONTROUTE;
|
|
break;
|
|
case 0x20: *optname = SO_BROADCAST;
|
|
break;
|
|
case 0x80: *optname = SO_LINGER;
|
|
break;
|
|
case 0x100: *optname = SO_OOBINLINE;
|
|
break;
|
|
case 0x1001: *optname = SO_SNDBUF;
|
|
break;
|
|
case 0x1002: *optname = SO_RCVBUF;
|
|
break;
|
|
case 0x1007: *optname = SO_ERROR;
|
|
break;
|
|
case 0x1008: *optname = SO_TYPE;
|
|
break;
|
|
default:
|
|
fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
|
|
break;
|
|
}
|
|
break;
|
|
case 6: *optname = IPPROTO_TCP;
|
|
}
|
|
}
|
|
|
|
#ifndef WINELIB
|
|
static void CONVERT_HOSTENT(struct WIN_hostent *heap, struct hostent *host)
|
|
{
|
|
|
|
}
|
|
|
|
static void CONVERT_PROTOENT(struct WIN_protoent *heap, struct protoent *proto)
|
|
{
|
|
|
|
}
|
|
|
|
static void CONVERT_SERVENT(struct WIN_servent *heap, struct servent *serv)
|
|
{
|
|
|
|
}
|
|
#else
|
|
#define CONVERT_HOSTENT(a,b) memcpy(a, &b, sizeof(a))
|
|
#define CONVERT_PROTOENT(a,b) memcpy(a, &b, sizeof(a))
|
|
#define CONVERT_SERVENT(a,b) memcpy(a, &b, sizeof(a))
|
|
#endif
|
|
|
|
SOCKET WINSOCK_accept(SOCKET s, struct sockaddr *addr, INT *addrlen)
|
|
{
|
|
int sock;
|
|
|
|
dprintf_winsock(stddeb, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, *addrlen);
|
|
|
|
if ((sock = accept(s, addr, (int *) addrlen)) < 0) {
|
|
errno_to_wsaerrno();
|
|
return INVALID_SOCKET;
|
|
}
|
|
return sock;
|
|
}
|
|
|
|
INT WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
|
|
dump_sockaddr(name);
|
|
|
|
if (bind(s, name, namelen) < 0) {
|
|
errno_to_wsaerrno();
|
|
return SOCKET_ERROR;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
INT WINSOCK_closesocket(SOCKET s)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_closesocket: socket %d\n", s);
|
|
|
|
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 *name, INT namelen)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
|
|
dump_sockaddr(name);
|
|
|
|
if (connect(s, name, namelen) < 0) {
|
|
errno_to_wsaerrno();
|
|
return SOCKET_ERROR;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
INT WINSOCK_getpeername(SOCKET s, struct sockaddr *name, INT *namelen)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
|
|
dump_sockaddr(name);
|
|
|
|
if (getpeername(s, name, (int *) namelen) < 0) {
|
|
errno_to_wsaerrno();
|
|
return SOCKET_ERROR;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
INT WINSOCK_getsockname(SOCKET s, struct sockaddr *name, INT *namelen)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
|
|
if (getsockname(s, name, (int *) namelen) < 0) {
|
|
errno_to_wsaerrno();
|
|
return SOCKET_ERROR;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
INT
|
|
WINSOCK_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen);
|
|
convert_sockopt(&level, &optname);
|
|
|
|
if (getsockopt(s, (int) level, optname, 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 *cp)
|
|
{
|
|
return( inet_addr(cp) );
|
|
}
|
|
|
|
char *WINSOCK_inet_ntoa(struct in_addr in)
|
|
{
|
|
char *s;
|
|
|
|
/* dprintf_winsock(stddeb, "WSA_inet_ntoa: %8lx\n", (int) in);*/
|
|
|
|
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 *argp)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %ld, ptr %8x\n", s, cmd, (int) argp);
|
|
|
|
if (ioctl(s, cmd, argp) < 0) {
|
|
errno_to_wsaerrno();
|
|
return SOCKET_ERROR;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
INT WINSOCK_listen(SOCKET s, INT backlog)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_listen: socket %d, backlog %d\n", s, backlog);
|
|
|
|
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 *buf, INT len, INT flags)
|
|
{
|
|
int length;
|
|
|
|
dprintf_winsock(stddeb, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags);
|
|
|
|
if ((length = recv(s, buf, len, flags)) < 0) {
|
|
errno_to_wsaerrno();
|
|
return SOCKET_ERROR;
|
|
}
|
|
return length;
|
|
}
|
|
|
|
INT WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags,
|
|
struct sockaddr *from, int *fromlen)
|
|
{
|
|
int length;
|
|
|
|
dprintf_winsock(stddeb, "WSA_recvfrom: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long)buf, len, flags);
|
|
|
|
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 *readfds, fd_set *writefds,
|
|
fd_set *exceptfds, struct timeval *timeout)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_select: fd # %d, ptr %8lx, ptr %8lx, ptr %8lX\n", nfds, (unsigned long) readfds, (unsigned long) writefds, (unsigned long) exceptfds);
|
|
|
|
return(select(nfds, readfds, writefds, exceptfds, timeout));
|
|
}
|
|
|
|
INT WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
|
|
{
|
|
int length;
|
|
|
|
dprintf_winsock(stddeb, "WSA_send: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
|
|
|
|
if ((length = send(s, buf, len, flags)) < 0) {
|
|
errno_to_wsaerrno();
|
|
return SOCKET_ERROR;
|
|
}
|
|
return length;
|
|
}
|
|
|
|
INT WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
|
|
struct sockaddr *to, INT tolen)
|
|
{
|
|
int length;
|
|
|
|
dprintf_winsock(stddeb, "WSA_sendto: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
|
|
|
|
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 *optval,
|
|
INT optlen)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen);
|
|
convert_sockopt(&level, &optname);
|
|
|
|
if (setsockopt(s, level, optname, optval, optlen) < 0) {
|
|
errno_to_wsaerrno();
|
|
return SOCKET_ERROR;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
INT WINSOCK_shutdown(SOCKET s, INT how)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_shutdown: socket s %d, how %d\n", s, how);
|
|
|
|
if (shutdown(s, how) < 0) {
|
|
errno_to_wsaerrno();
|
|
return SOCKET_ERROR;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
SOCKET WINSOCK_socket(INT af, INT type, INT protocol)
|
|
{
|
|
int sock;
|
|
|
|
dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol);
|
|
|
|
if ((sock = socket(af, type, protocol)) < 0) {
|
|
errno_to_wsaerrno();
|
|
dprintf_winsock(stddeb, "WSA_socket: failed !\n");
|
|
return INVALID_SOCKET;
|
|
}
|
|
|
|
if (sock > 0xffff) {
|
|
wsa_errno = WSAEMFILE;
|
|
return INVALID_SOCKET;
|
|
}
|
|
|
|
FD_SET(sock, &fd_in_use);
|
|
|
|
dprintf_winsock(stddeb, "WSA_socket: fd %d\n", sock);
|
|
return sock;
|
|
}
|
|
|
|
struct WIN_hostent *WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
|
|
{
|
|
struct hostent *host;
|
|
|
|
dprintf_winsock(stddeb, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type);
|
|
|
|
if ((host = gethostbyaddr(addr, len, type)) == NULL) {
|
|
errno_to_wsaerrno();
|
|
return NULL;
|
|
}
|
|
CONVERT_HOSTENT(&heap->hostent_addr, host);
|
|
|
|
return &heap->hostent_addr;
|
|
}
|
|
|
|
struct WIN_hostent *WINSOCK_gethostbyname(const char *name)
|
|
{
|
|
struct hostent *host;
|
|
|
|
dprintf_winsock(stddeb, "WSA_gethostbyname: %s\n", name);
|
|
|
|
if ((host = gethostbyname(name)) == NULL) {
|
|
errno_to_wsaerrno();
|
|
return NULL;
|
|
}
|
|
CONVERT_HOSTENT(&heap->hostent_name, host);
|
|
|
|
return &heap->hostent_name;
|
|
}
|
|
|
|
INT WINSOCK_gethostname(char *name, INT namelen)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_gethostname: name %s, len %d\n", name, namelen);
|
|
|
|
if (gethostname(name, namelen) < 0) {
|
|
errno_to_wsaerrno();
|
|
return SOCKET_ERROR;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct WIN_protoent *WINSOCK_getprotobyname(char *name)
|
|
{
|
|
struct protoent *proto;
|
|
|
|
dprintf_winsock(stddeb, "WSA_getprotobyname: name %s\n", name);
|
|
|
|
if ((proto = getprotobyname(name)) == NULL) {
|
|
errno_to_wsaerrno();
|
|
return NULL;
|
|
}
|
|
CONVERT_PROTOENT(&heap->protoent_name, proto);
|
|
|
|
return &heap->protoent_name;
|
|
}
|
|
|
|
struct WIN_protoent *WINSOCK_getprotobynumber(INT number)
|
|
{
|
|
struct protoent *proto;
|
|
|
|
dprintf_winsock(stddeb, "WSA_getprotobynumber: num %d\n", number);
|
|
|
|
if ((proto = getprotobynumber(number)) == NULL) {
|
|
errno_to_wsaerrno();
|
|
return NULL;
|
|
}
|
|
CONVERT_PROTOENT(&heap->protoent_number, proto);
|
|
|
|
return &heap->protoent_number;
|
|
}
|
|
|
|
struct WIN_servent *WINSOCK_getservbyname(const char *name, const char *proto)
|
|
{
|
|
struct servent *service;
|
|
|
|
if (proto == NULL)
|
|
proto = "tcp";
|
|
|
|
dprintf_winsock(stddeb, "WSA_getservbyname: name %s, proto %s\n", name, proto);
|
|
|
|
if ((service = getservbyname(name, proto)) == NULL) {
|
|
errno_to_wsaerrno();
|
|
return NULL;
|
|
}
|
|
CONVERT_SERVENT(&heap->servent_name, service);
|
|
|
|
return &heap->servent_name;
|
|
}
|
|
|
|
struct WIN_servent *WINSOCK_getservbyport(INT port, const char *proto)
|
|
{
|
|
struct servent *service;
|
|
|
|
dprintf_winsock(stddeb, "WSA_getservbyport: port %d, name %s\n", port, proto);
|
|
|
|
if ((service = getservbyport(port, proto)) == NULL) {
|
|
errno_to_wsaerrno();
|
|
return NULL;
|
|
}
|
|
CONVERT_SERVENT(&heap->servent_port, service);
|
|
|
|
return &heap->servent_port;
|
|
}
|
|
|
|
/******************** winsock specific functions ************************
|
|
*
|
|
*/
|
|
static HANDLE new_handle = 0;
|
|
|
|
static HANDLE AllocWSAHandle(void)
|
|
{
|
|
return new_handle++;
|
|
}
|
|
|
|
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 %ld)\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 %ld)\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 *addr,
|
|
INT len, INT type, char *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 *name,
|
|
char *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 *name,
|
|
char *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 *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 *name,
|
|
const char *proto, char *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
|
|
*proto, char *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;
|
|
|
|
dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND %d, wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
|
|
|
|
/* 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)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_AsyncRequest: handle %d\n", hAsyncTaskHandle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
INT WSACancelBlockingCall(void)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_CancelBlockCall\n");
|
|
return 0;
|
|
}
|
|
|
|
INT WSAGetLastError(void)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_GetLastError\n");
|
|
|
|
return wsa_errno;
|
|
}
|
|
|
|
void WSASetLastError(INT iError)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_SetLastErorr %d\n", iError);
|
|
|
|
wsa_errno = iError;
|
|
}
|
|
|
|
BOOL WSAIsBlocking(void)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_IsBlocking\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
FARPROC WSASetBlockingHook(FARPROC lpBlockFunc)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_SetBlockHook %8lx, STUB!\n", (unsigned long) lpBlockFunc);
|
|
BlockFunction = lpBlockFunc;
|
|
|
|
return (FARPROC) lpBlockFunc;
|
|
}
|
|
|
|
INT WSAUnhookBlockingHook(void)
|
|
{
|
|
dprintf_winsock(stddeb, "WSA_UnhookBlockingHook\n");
|
|
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;
|
|
|
|
dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
|
|
|
|
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);
|
|
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;
|
|
}
|