// Created by Cyrus Patel <cyp@fb14.uni-mainz.de>
//
// Copyright distributed.net 1997-1999 - All Rights Reserved
// For use in distributed.net projects only.
// Any other distribution or use of this source violates copyright.
//
/*
   This module containts the shim layer between Winsock DLL and Windows386 
   (Watcom 386 flat memory model extension for win16).

   Little endian byte format is assumed throughout.
   
   winsock.h header must be #included with the following wrapper:

   #include <windows.h> // use default shimming/redefs
   #ifdef __WINDOWS_386__
     #undef FAR
     #define FAR
   #endif
   #include <winsock.h> // use the 16 bit version 
   #ifdef __WINDOWS_386__
     #undef FAR
     #define FAR far
     #undef FD_ISSET // macro applies a FAR cast that results in truncation
     #define FD_ISSET(fd, set) __WSAFDIsSet(fd, set) //...so discard the cast
   #endif
*/
// $Log: w32sock.cpp,v $
// Revision 1.8  1999/01/19 04:51:38  cyp
// fixed initialization sequence and win16 ioctlsocket()
//
// Revision 1.7  1999/01/11 23:41:57  michmarc
// Updates to prototypes, casts, and use WS2_32.DLL for AlphaNT instead of
// WINSOCK.DLL to make code happy for VC6 + Alpha
//
// Revision 1.6  1999/01/01 02:45:20  cramer
// Part 1 of 1999 Copyright updates...
//
// Revision 1.5  1998/12/21 15:02:00  cyp
// Added select() support.
//
// Revision 1.4  1998/12/16 07:13:38  cyp
// win16 changes. Fixed gethostbyname * * *
//
// Revision 1.3  1998/11/02 05:15:06  cyp
// Added code to search for winsock.dll before using LoadLibrary().
//
// Revision 1.2  1998/10/26 04:25:55  cyp
// Everything works now (tested under win16 Novell, Microsoft and Trumpet 
// stacks, as well as the win32 M$ stack)
//
// Revision 1.2  1998/10/19 07:56:11  cyp
// Created
//
#if (!defined(lint) && defined(__showids__))
const char *w32sock_cpp(void) {
return "@(#)$Id: w32sock.cpp,v 1.8 1999/01/19 04:51:38 cyp Exp $"; }
#endif

#include "w32sock.h"
#include <stdio.h>
#include <string.h>

#if defined(_M_ALPHA)
  #define WINSOCK_DLL_FILENAME "WS2_32.DLL"
  #undef PASCAL
  #define PASCAL
#elif defined(__WINDOWS_386__)
  #define WINSOCK_DLL_FILENAME "WINSOCK.DLL"
  #if defined(__WINDOWS_386__)
  #undef FAR
  #define FAR
  #endif
#else
  #define WINSOCK_DLL_FILENAME "WINSOCK.DLL"
#endif

/* ----------------------------------------------- */

#ifdef NO_W32SOCK /* dummy functions */
int closesocket(SOCKET s)
{ s=s; return -1; }  
int send(SOCKET s,char *buff,int len,int flags)
{ s=s; buff=buff; len=len; flags=flags; return -1; }
int recv(SOCKET s,char *buff,int len,int flags)
{ s=s; buff=buff; len=len; flags=flags; return -1; }
#endif

/* ---------------------------------------- */

#ifndef NO_W32SOCK

static struct 
{
  int initlevel;
  int internalinit; /* if autoinitialized from WSAStartup */
  int lasterror;
} w32sockstatics = {0,0,0};


//import winsock symbol should always be able to find the lib
//because WSAStartup calls __w32sockinitdeinit which loads the lib
static FARPROC ImportWinsockSymbol(LPCSTR lpszProcName)
{
  if (w32sockstatics.initlevel <= 0)
    return (FARPROC)0;
  HMODULE ws = GetModuleHandle("WINSOCK");
  if (ws)
    return GetProcAddress(ws, lpszProcName);
  return (FARPROC)0;
}  

static HINSTANCE __LoadLibrary( LPCSTR lpszLibName )
{
  OFSTRUCT ofstruct;
  ofstruct.cBytes = sizeof(ofstruct);
  HINSTANCE hinst = 0;

  #ifndef OF_SEARCH
  #define OF_SEARCH 0x0400
  #endif
  if ( OpenFile( lpszLibName, &ofstruct, OF_EXIST|OF_SEARCH) >= 0 )
    {
    hinst = LoadLibrary( ofstruct.szPathName );
    if ((UINT)hinst <= 32)
      hinst = 0;
    }
  return hinst;  
}


static int __w32sockInitDeinit(int init_or_deinit )
{
  static HINSTANCE hinstWinsock = NULL;

  if (init_or_deinit == 0)   /* getstate */
    {
    if (w32sockstatics.initlevel <= 0)
      return 0;
    return (GetModuleHandle("WINSOCK") != NULL);
    }
  else if (init_or_deinit < 0)   /* deinitialize */
    {
    if ((--w32sockstatics.initlevel)==0)
      {
      if (hinstWinsock)
        {
        FreeLibrary(hinstWinsock);
        hinstWinsock = NULL;
        }
      }
    }    
  else if (init_or_deinit > 0)   /* initialize */
    {
    if ((++w32sockstatics.initlevel)==1)
      {
      hinstWinsock = __LoadLibrary(WINSOCK_DLL_FILENAME);
      if ((UINT) hinstWinsock < 32) 
        {
        hinstWinsock = NULL;
        --w32sockstatics.initlevel;
        return 0;
        }
      }
    }
  return 1;
}

/* ---------------------------------------- */

u_short PASCAL FAR htons(u_short s)
{ return ((((s)&0xff)<<8) | (((s)>>8)&0xff)); }
u_short PASCAL FAR ntohs(u_short s)
{  return htons(s); }
u_long PASCAL FAR htonl(u_long l)
{ return ((((l)&0xff)<<24) | (((l)>>24)&0xff) | (((l)&0xff00)<<8) | (((l)>>8)&0xff00)); }
u_long PASCAL FAR ntohl(u_long l)
{ return htonl(l); }
  
/* ---------------------------------------- */

static char *__inet_ultoa( u_long addr )
{
  static char buff[18];
  char *p = (char *)(&addr);
  sprintf( buff, "%d.%d.%d.%d", (p[0]&255),(p[1]&255),(p[2]&255),(p[3]&255) );
  return buff;
}  

char FAR * PASCAL FAR inet_ntoa( struct in_addr addr )
{ return __inet_ultoa( *((u_long *)(&addr)) ); }

/* ---------------------------------------- */

void PASCAL FAR WSASetLastError(int iError)
{
  if (w32sockstatics.initlevel <= 0)
    return;

  w32sockstatics.lasterror = 0;
  FARPROC __proc = ImportWinsockSymbol( "WSASetLastError" );
  if (__proc)
    {
    #if defined(__WINDOWS_386__)
    _Call16(__proc,"w",iError);
    #else
    (*((void PASCAL FAR (*)(int))(__proc)))(iError);
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return;
}  

/* ---------------------------------------- */

int PASCAL FAR WSAGetLastError(void)
{
  if (w32sockstatics.initlevel <= 0)
    return WSANOTINITIALISED;  

  if (w32sockstatics.lasterror != 0)
    return w32sockstatics.lasterror;

  FARPROC __proc = ImportWinsockSymbol( "WSAGetLastError" );
  if (__proc)
    {
    #if defined(__WINDOWS_386__)
    return (0xffff & (_Call16(__proc,"")));
    #else
    return (*((int PASCAL FAR (*)(void))(__proc)))();
    #endif
    }
  return WSAEOPNOTSUPP;
}  

/* ---------------------------------------- */

int PASCAL FAR gethostname(char FAR * name, int namelen)
{
  w32sockstatics.lasterror = 0;
  FARPROC __gethostname = ImportWinsockSymbol( "gethostname" );
  if (__gethostname)
    {
    #if defined(__WINDOWS_386__)
    char buf[256];
    short rc = -1;
    DWORD alias = AllocAlias16( (void *)(&buf[0]) );
    buf[0]=0;
    if (alias)
      {
      rc = (short)_Call16(__gethostname,"dw", alias, sizeof(buf) );
      FreeAlias16( alias );
      }
    if (rc == 0)
      {
      if (strlen(buf) > namelen)
        rc = -1;
      else
        strcpy( name, buf );
      }
    return ((rc!=0)?(-1):(0));
    #else
    return (*((int PASCAL FAR (*)(char FAR *,int))(__gethostname)))(name, namelen);
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

SOCKET PASCAL FAR socket(int domain, int type, int protocol)
{
  w32sockstatics.lasterror = 0;
  FARPROC __socket = ImportWinsockSymbol( "socket" );
  if (__socket)
    {
    #if defined(__WINDOWS_386__)
    SOCKET ns = (SOCKET)(0xffff & (_Call16(__socket,"www",domain,type,protocol)));
    return ((ns == ((INVALID_SOCKET)&0xffff))?(INVALID_SOCKET):(ns));
    #else
    return (*(SOCKET PASCAL FAR (*)(int,int,int))(__socket))(domain,type,protocol);
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

int PASCAL FAR shutdown(SOCKET s, int how)
{
  w32sockstatics.lasterror = 0;
  FARPROC __shutdown = ImportWinsockSymbol( "shutdown" );
  if (__shutdown) 
    {
    #if defined(__WINDOWS_386__)
    return (((_Call16(__shutdown,"ww",s,how)) == 0)?(0):(-1));
    #else
    return (*((int PASCAL FAR (*)(SOCKET,int))(__shutdown)))(s,how);
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

int PASCAL FAR closesocket(SOCKET s)
{
  w32sockstatics.lasterror = 0;
  FARPROC __closesocket = ImportWinsockSymbol( "closesocket" );
  if (__closesocket) 
    {
    #if defined(__WINDOWS_386__)
    return ((_Call16(__closesocket,"w",s) == 0)?(0):(-1));
    #else
    return (*((int PASCAL FAR (*)(SOCKET))(__closesocket)))(s);
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

static int __getpeersockname( const char *procname, SOCKET s, 
                              struct sockaddr FAR *name, int FAR * namelen )
{
  w32sockstatics.lasterror = 0;
  FARPROC __proc = ImportWinsockSymbol( procname );
  if (__proc)
    {
    #if defined(__WINDOWS_386__)
    if (name && namelen)
      {
      WORD _namelen = (WORD)(*namelen);
      int rc = ((_Call16(__proc, "wpp", s, name, &_namelen)==0)?(0):(-1));
      *namelen = _namelen;
      return rc;
      }
    #else
      return (*((int PASCAL FAR (*)(SOCKET, struct sockaddr FAR *, int FAR *))
                                   (__proc)))( s, name, namelen );
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

int PASCAL FAR getpeername(SOCKET s, struct sockaddr FAR *name, int FAR * namelen)
{
  return __getpeersockname( "getpeername", s, name, namelen );
}  

/* ---------------------------------------- */

int PASCAL FAR getsockname(SOCKET s, struct sockaddr FAR *name, int FAR * namelen)
{
  return __getpeersockname( "getsockname", s, name, namelen );
}  

/* ---------------------------------------- */

SOCKET PASCAL FAR accept(SOCKET s, struct sockaddr FAR *addr,
                          int FAR *addrlen)
{
  w32sockstatics.lasterror = 0;
  FARPROC __accept = ImportWinsockSymbol( "accept" );
  if (__accept)
    {
    #if defined(__WINDOWS_386__)
    if (addr && addrlen)
      {
      WORD _addrlen = (WORD)(*addrlen);
      SOCKET ns = (0xffff & _Call16(__accept, "wpp", s, addr, &_addrlen));
      *addrlen = _addrlen;
      return ((ns == ((INVALID_SOCKET)&0xffff))?(INVALID_SOCKET):(ns));
      }
    return -1;
    #else
    return (*((SOCKET PASCAL FAR (*)(SOCKET, struct sockaddr FAR *, int FAR *))
         (__accept)))( s, addr, addrlen );
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

static int __bindconnect( const char *procname, SOCKET s, 
                          const struct sockaddr FAR *addr, int addrlen )
{
  w32sockstatics.lasterror = 0;
  FARPROC __proc = ImportWinsockSymbol( procname );
  if (__proc)
    {
    #if defined(__WINDOWS_386__)
    return ((_Call16(__proc, "wpw", s, addr, addrlen)==0)?(0):(-1));
    #else
    return (*((int PASCAL FAR (*)(SOCKET, const struct sockaddr FAR *, int))
                                 (__proc)))( s, addr, addrlen );
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR *addr, int namelen)
{
  return __bindconnect( "bind", s, addr, namelen );
}  

/* ---------------------------------------- */

int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR *name, int namelen)
{
  return __bindconnect( "connect", s, name, namelen );
}  

/* ---------------------------------------- */

int PASCAL FAR getsockopt(SOCKET s, int level, int optname,
                                           char FAR * optval, int FAR *optlen)
{
  w32sockstatics.lasterror = 0;
  FARPROC __proc = ImportWinsockSymbol( "getsockopt" );
  if (__proc)
    {
    #if defined(__WINDOWS_386__)
    return ((_Call16(__proc, "wwwpp", s, level, optname, optval, optlen)==0)?(0):(-1));
    #else
    return (*((int PASCAL FAR (*)(SOCKET, int, int, char FAR *, int FAR *))
                             (__proc)))( s, level, optname, optval, optlen );
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}

/* ---------------------------------------- */

int PASCAL FAR setsockopt(SOCKET s, int level, int optname,
                             const char FAR * optval, int optlen)
{
  w32sockstatics.lasterror = 0;
  FARPROC __proc = ImportWinsockSymbol( "setsockopt" );
  if (__proc)
    {
    #if defined(__WINDOWS_386__)
    return ((_Call16(__proc, "wwwpw", s, level, optname, optval, optlen)==0)?(0):(-1));
    #else
    return (*((int PASCAL FAR (*)(SOCKET, int, int, const char FAR *, int ))
                             (__proc)))( s, level, optname, optval, optlen );
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}

/* ---------------------------------------- */

int PASCAL FAR listen(SOCKET s, int backlog)
{
  w32sockstatics.lasterror = 0;
  FARPROC __proc = ImportWinsockSymbol( "listen" );
  if (__proc)
    {
    #if defined(__WINDOWS_386__)
    return ((_Call16(__proc, "ww", s, backlog )==0)?(0):(-1));
    #else
    return (*((int PASCAL FAR (*)(SOCKET, int ))(__proc)))( s, backlog );
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}

/* ---------------------------------------- */

int PASCAL FAR recvfrom(SOCKET s, char FAR * buf, int len, int flags,
                         struct sockaddr FAR *from, int FAR * fromlen)
{
  w32sockstatics.lasterror = 0;
  FARPROC __proc = ImportWinsockSymbol( "recvfrom" );
  if (__proc)
    {
    #if defined(__WINDOWS_386__)
    short rc = (short)_Call16(__proc, "wpwwpp", s, buf, len, flags, from, fromlen );
    return ((rc<0)?(-1):(rc));
    #else
    return (*((int PASCAL FAR (*)(SOCKET, char FAR *, int, int, 
                 struct sockaddr FAR *, int FAR * ))(__proc)))
                 ( s, buf, len, flags, from, fromlen );
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

int PASCAL FAR sendto(SOCKET s, const char FAR * buf, int len, int flags,
                       const struct sockaddr FAR *to, int tolen)
{
  w32sockstatics.lasterror = 0;
  FARPROC __proc = ImportWinsockSymbol( "sendto" );
  if (__proc)
    {
    #if defined(__WINDOWS_386__)
    short rc = (short)_Call16(__proc, "wpwwpw", s, buf, len, flags, to, tolen );
    return ((rc<0)?(-1):(rc));
    #else
    return (*((int PASCAL FAR (*)(SOCKET, const char FAR *, int, int, 
                 const struct sockaddr FAR *, int ))(__proc)))
                 ( s, buf, len, flags, to, tolen );
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

#if defined(__WINDOWS_386__)

struct fd_set_short {
  unsigned short fd_count;               /* how many are SET? */
  unsigned short fd_array[FD_SETSIZE];   /* an array of SOCKETs */
};

static void __map_int_to_short_fdset( fd_set FAR *argfds )
{
  if (argfds)
    {
    struct fd_set_short *shortfds;
    unsigned int i, count;

    shortfds = (struct fd_set_short *)argfds;
    count = (unsigned int)argfds->fd_count;
    shortfds->fd_count = (short)count;
    for (i=0;i<count;i++)
      shortfds->fd_array[i] = (short)argfds->fd_array[i];
    }
  return;
}  

static void __map_short_to_int_fdset( fd_set FAR *argfds )
{
  if (argfds)
    {
    struct fd_set_short *shortfds;
    unsigned int i, count;

    shortfds = (struct fd_set_short *)argfds;
    count = (unsigned int)shortfds->fd_count;
    for (i=count;i>0;)
      {
      --i;
      argfds->fd_array[i] = 
                (0xffff & ((unsigned int)(shortfds->fd_array[i])));
      }
    argfds->fd_count = count;
    }
  return;
}  
#endif

/* ---------------------------------------- */

int PASCAL FAR __WSAFDIsSet(SOCKET s, fd_set FAR *fds)
{
  w32sockstatics.lasterror = 0;
  FARPROC __proc = ImportWinsockSymbol( "__WSAFDIsSet" );
  if (__proc)
    {
    #if defined(__WINDOWS_386__)
    __map_int_to_short_fdset( fds );
    int rc = (( (_Call16(__proc, "wp", s, fds ) & 0xFFFF)==0)?(0):(1));
    __map_short_to_int_fdset( fds );
    return rc;
    #else
    return (*((int PASCAL FAR (*)(SOCKET, fd_set FAR *))(__proc)))( s, fds );
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return 0;
}

/* ---------------------------------------- */

int PASCAL FAR select(int nfds, fd_set FAR *readfds, fd_set FAR *writefds,
               fd_set FAR *exceptfds, const struct timeval FAR *timeout)
{
  w32sockstatics.lasterror = 0;
  FARPROC __proc = ImportWinsockSymbol( "select" );
  if (__proc)
    {
    #if defined(__WINDOWS_386__)
    __map_int_to_short_fdset( readfds );
    __map_int_to_short_fdset( writefds );
    __map_int_to_short_fdset( exceptfds );
    short rc = (short)((0xFFFF) & (_Call16(__proc, "wpppp", nfds, 
                      readfds, writefds, exceptfds, timeout )));
    __map_short_to_int_fdset( readfds );
    __map_short_to_int_fdset( writefds );
    __map_short_to_int_fdset( writefds );
    return ((rc<0)?(-1):(rc));
    #else
    return (*((int PASCAL FAR (*)(int, fd_set FAR *, fd_set FAR *, 
         fd_set FAR *, const struct timeval FAR * ))(__proc)))
                            ( nfds, readfds, writefds, exceptfds, timeout );
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}

/* ---------------------------------------- */

unsigned long PASCAL FAR inet_addr(const char FAR * cp)
{
  w32sockstatics.lasterror = 0;
  FARPROC __inet_addr = ImportWinsockSymbol( "inet_addr" );
  if (__inet_addr)
    {
    #if defined(__WINDOWS_386__)
    return (unsigned long)_Call16(__inet_addr, "p", cp );
    #else
    return (*((int PASCAL FAR (*)(const char FAR *))(__inet_addr)))(cp);
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}

/* ---------------------------------------- */

#if defined(__WINDOWS_386__)
struct hostent FAR * PASCAL FAR __parsehostent(int dobyname, DWORD hpp )
{
  static struct
    {
    char hostname[256]; char aliasbuf[256]; char  addrbuf[128];
    char *addrlist[32]; char *aliaslist[8];
    struct hostent hent;
    } ghn[2];

  dobyname = ((dobyname)?(1):(0));
  struct hostent far *hp;
  unsigned int index;
  
  if (hpp)
    {
    hp = (struct hostent far *)MK_FP32( (void *)hpp );
    if (hp)
      {
      if (hp->h_length <= 0) /* screwed up implementation */
        return (struct hostent FAR *)0;
      
      ghn[dobyname].hostname[0] = 0;
      ghn[dobyname].aliaslist[0]= (char *)0;
      ghn[dobyname].addrlist[0] = (char *)0;

      ghn[dobyname].hent.h_addrtype = hp->h_addrtype;
      ghn[dobyname].hent.h_length = hp->h_length;
      ghn[dobyname].hent.h_name = &(ghn[dobyname].hostname[0]);
      ghn[dobyname].hent.h_aliases = &(ghn[dobyname].aliaslist[0]);
      ghn[dobyname].hent.h_addr_list = &(ghn[dobyname].addrlist[0]);

      index = 0;
      if (hp->h_addr_list)
        {
        char far *cfp = (char far *)MK_FP32((void *)hp->h_addr_list);
        unsigned int pos = 0;
        unsigned int addrlen = (unsigned int)(ghn[dobyname].hent.h_length);

        index=0;
        while (cfp && ((pos + addrlen) < sizeof(ghn[dobyname].addrbuf)) &&
          index<((sizeof(ghn[dobyname].addrlist)/sizeof(ghn[dobyname].addrlist[0]))-1))
          {
          void *vp;
          char *cp = (char *)&vp; 
          unsigned int i;
          for (i=0;i<sizeof(vp);i++)
            *cp++=*cfp++;
          if (!vp)
            break;
          char far *ufp = (char far *)MK_FP32(vp);
          if (!ufp)
            break;
          ghn[dobyname].addrlist[index]=&(ghn[dobyname].addrbuf[pos]);
          for (i=0;i<((unsigned int)(addrlen));i++)
            ghn[dobyname].addrbuf[pos++]=*ufp++;

          index++;
          }
        ghn[dobyname].addrlist[index]=(char *)0;
        ghn[dobyname].hent.h_addr_list = &(ghn[dobyname].addrlist[0]);
        }

      index = 0;
      if (hp->h_aliases)
        {
        char far *cfp = (char far *)MK_FP32((void *)hp->h_aliases);
        unsigned int pos = 0;

        index=0;
        while (cfp && pos<sizeof(ghn[dobyname].aliasbuf) &&
          index<((sizeof(ghn[dobyname].aliaslist)/sizeof(ghn[dobyname].aliaslist[0]))-1))
          {
          void *vp;
          char *cp = (char *)&vp; 
          unsigned int i;
          for (i=0;i<sizeof(vp);i++)
            *cp++=*cfp++;
          if (!vp)
            break;
          char far *ufp = (char far *)MK_FP32(vp);
          if (!ufp)
            break;
          ghn[dobyname].aliaslist[index]=&(ghn[dobyname].aliasbuf[pos]);
          while (*ufp && (pos<(sizeof(ghn[dobyname].aliasbuf)-1)))
            ghn[dobyname].aliasbuf[pos++]=*ufp++;
          if (*ufp)
            break;
          index++;
          }
        ghn[dobyname].aliaslist[index]=(char *)0;
        ghn[dobyname].hent.h_aliases = &(ghn[dobyname].aliaslist[0]);
        }
        
      if (hp->h_name)
        {
        char far *cfp = (char far *)MK_FP32( (void *)hp->h_name );
        unsigned int pos = 0;

        while (*cfp && pos<(sizeof(ghn[dobyname].hostname)-1))
          ghn[dobyname].hostname[pos++] = *cfp++;
        ghn[dobyname].hostname[pos]=0;
        ghn[dobyname].hent.h_name = &(ghn[dobyname].hostname[0]);
        }
        
      return &(ghn[dobyname].hent);
      }
    }
  return (struct hostent FAR *)0;
}
      
#endif /* if defined(__WINDOWS_386__) */


/* ---------------------------------------- */

struct hostent FAR * PASCAL FAR gethostbyaddr(const char FAR * name, int len, int type)
{
  w32sockstatics.lasterror = 0;
  FARPROC __gethostbyaddr = ImportWinsockSymbol( "gethostbyaddr" );
  if (__gethostbyaddr)
    {
    #if defined(__WINDOWS_386__)
    return __parsehostent(0, _Call16(__gethostbyaddr,"pww",name,len,type));
    #else
    return (*((struct hostent FAR * PASCAL FAR (*)(const char FAR *,int,int))
                                         (__gethostbyaddr)))(name,len,type);
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return (hostent FAR *)0;
}    
      
/* ---------------------------------------- */
    
struct hostent FAR * PASCAL FAR gethostbyname(const char FAR * name)
{
  w32sockstatics.lasterror = 0;
  FARPROC __gethostbyname = ImportWinsockSymbol( "gethostbyname" );
  if (__gethostbyname)
    {
    #if defined(__WINDOWS_386__)
    return __parsehostent(1, _Call16(__gethostbyname,"p",name));
    #else
    return (*((struct hostent FAR * PASCAL FAR (*)(const char FAR *))
                                         (__gethostbyname)))(name);
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return (struct hostent FAR * )0;
}  

/* ---------------------------------------- */

int PASCAL FAR send(SOCKET s, const char FAR * buf, int len, int flags)
{
  w32sockstatics.lasterror = 0;
  FARPROC __send = ImportWinsockSymbol( "send" );
  if (__send)
    {
    #if defined(__WINDOWS_386__)
    short rc = (short)(0xFFFF & (_Call16(__send, "wpww", s, buf, len, flags)));
    return ((rc<0)?(-1):(((int)(rc))&0xFFFF));
    #else
    return (*((int PASCAL FAR (*)(SOCKET, const char FAR *, int, int))(__send)))
                                                         (s, buf, len, flags);
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

int PASCAL FAR recv (SOCKET s, char FAR * buf, int len, int flags)
{
  w32sockstatics.lasterror = 0;
  FARPROC __recv = ImportWinsockSymbol( "recv" );
  if (__recv)
    {
    #if defined(__WINDOWS_386__)
    short rc = (short)(0xFFFF & (_Call16(__recv, "wpww", s, buf, len, flags)));
    return ((rc<0)?(-1):(((int)(rc))&0xFFFF));
    #else
    return (*((int PASCAL FAR (*)(SOCKET, char FAR *, int, int))(__recv)))
                                                         (s, buf, len, flags);
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

int PASCAL FAR ioctlsocket(SOCKET s, long cmd, u_long FAR *argp)
{
  w32sockstatics.lasterror = 0;
  FARPROC __ioctlsocket = ImportWinsockSymbol( "ioctlsocket" );
  if (__ioctlsocket)
    {
    #if defined(__WINDOWS_386__)
    return (((_Call16(__ioctlsocket, "wdp", s, cmd, argp )&0xFFFF)==0)?(0):(-1));
    #else
    return (*((int PASCAL FAR (*)(SOCKET, long, u_long FAR *))(__ioctlsocket)))
                                                          ( s, cmd, argp);
    #endif
    }
  w32sockstatics.lasterror = WSAEOPNOTSUPP;
  return -1;
}  

/* ---------------------------------------- */

int PASCAL FAR WSAStartup(WORD wVerRequired, LPWSADATA lpWSAData)
{
  w32sockstatics.lasterror = WSANOTINITIALISED;
  int ec = WSASYSNOTREADY;

  if (!lpWSAData)
    return WSAEFAULT;
  
  int didinit = 0;
  if (w32sockstatics.initlevel == 0)
    {
    if (__w32sockInitDeinit( +1 ) == 0)
      return ec;
    w32sockstatics.internalinit = 1;
    didinit = 1;
    }
    
  FARPROC __WSAStartup = ImportWinsockSymbol( "WSAStartup" );
  if (__WSAStartup)
    {
    #if defined(__WINDOWS_386__)
    lpWSAData->szDescription[0]=0;
    lpWSAData->szSystemStatus[0]=0;
    ec = (_Call16( __WSAStartup, "wp", wVerRequired, lpWSAData )&0xFFFF);
    #else
    ec = (*((int PASCAL FAR (*)(WORD, LPWSADATA))(__WSAStartup)))
                                         (wVerRequired, lpWSAData);
    #endif
    if (ec == 0)
      {
      w32sockstatics.lasterror = 0;
      return 0;
      }
    }

  if (didinit)    
    {
    __w32sockInitDeinit( -1 );
    w32sockstatics.internalinit = 0;
    }

  return ec;
}

/* ---------------------------------------- */

int PASCAL FAR WSACleanup(void)
{
  w32sockstatics.lasterror = 0;
  int rc = -1; /* SOCKET_ERROR */

  FARPROC __WSACleanup = ImportWinsockSymbol( "WSACleanup" );
  if (__WSACleanup)
    {
    #if defined(__WINDOWS_386__)
    rc=(((_Call16(__WSACleanup,"") & 0xFFFF) == 0)?(0):(rc));
    #else
    rc=(*((int PASCAL FAR (*)(void))(__WSACleanup)))();
    #endif
    }

  if (w32sockstatics.initlevel == 1 && w32sockstatics.internalinit)
    {
    __w32sockInitDeinit( -1 );
    w32sockstatics.internalinit = 0;
    }

  w32sockstatics.lasterror = WSANOTINITIALISED;
  return rc;
}

/* ---------------------------------------- */

int w32sockInitialize(void) 
{ 
  if (__w32sockInitDeinit(+1))
    {
    WSADATA wsadata;
    if ( WSAStartup(0x101, &wsadata ) == 0)
      return 1;
    __w32sockInitDeinit(-1);
    }
  return 0;
}  
    
int w32sockDeinitialize(void) 
{ 
  if (__w32sockInitDeinit(0))
    {
    WSACleanup();
    __w32sockInitDeinit(-1);
    return 1;
    }
  return 0;
}  
    
int w32sockIsAlive(void) 
{ 
  return __w32sockInitDeinit(0); 
}

/* ---------------------------------------- */

#endif //no_winsock
