/**********************************************************************
 *
 * d_winsock.cpp
 * Copyright (C) 1996
 * 
 * A component of the fnord webserver written by bmorin@wpi.edu.
 *
 * Altered for use with the Greenstone digital library software by the
 * New Zealand Digital Library Project at the University of Waikato,
 * New Zealand.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *********************************************************************/

#include <windows.h>
#include "d_winsock.h"


typedef SOCKET (PASCAL FAR *accept_Type)(SOCKET s, struct sockaddr FAR *addr, 
					 int FAR *addrlen);
typedef int (PASCAL FAR *bind_Type)(SOCKET s, const struct sockaddr FAR *addr, int namelen);
typedef int (PASCAL FAR *closesocket_Type)(SOCKET s);
typedef int (PASCAL FAR *connect_Type)(SOCKET s, const struct sockaddr FAR *name, 
				       int namelen);
typedef int (PASCAL FAR *ioctlsocket_Type)(SOCKET s, long cmd, u_long FAR *argp);
typedef int (PASCAL FAR *getpeername_Type)(SOCKET s, struct sockaddr FAR *name,
					   int FAR * namelen);
typedef int (PASCAL FAR *getsockname_Type)(SOCKET s, struct sockaddr FAR *name,
					   int FAR * namelen);
typedef int (PASCAL FAR *getsockopt_Type)(SOCKET s, int level, int optname,
					  char FAR * optval, int FAR *optlen);
typedef u_long (PASCAL FAR *htonl_Type)(u_long hostlong);
typedef u_short (PASCAL FAR *htons_Type)(u_short hostshort);
typedef unsigned long (PASCAL FAR *inet_addr_Type)(const char FAR * cp);
typedef char FAR * (PASCAL FAR *inet_ntoa_Type)(struct in_addr in);
typedef int (PASCAL FAR *listen_Type)(SOCKET s, int backlog);
typedef u_long (PASCAL FAR *ntohl_Type)(u_long netlong);
typedef u_short (PASCAL FAR *ntohs_Type)(u_short netshort);
typedef int (PASCAL FAR *recv_Type)(SOCKET s, char FAR * buf, int len, int flags);
typedef int (PASCAL FAR *recvfrom_Type)(SOCKET s, char FAR * buf, int len, int flags,
					struct sockaddr FAR *from, int FAR * fromlen);
typedef int (PASCAL FAR *select_Type)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds,
				      fd_set FAR *exceptfds, const struct timeval FAR *timeout);
typedef int (PASCAL FAR *send_Type)(SOCKET s, const char FAR * buf, int len, int flags);
typedef int (PASCAL FAR *sendto_Type)(SOCKET s, const char FAR * buf, int len, int flags,
				      const struct sockaddr FAR *to, int tolen);
typedef int (PASCAL FAR *setsockopt_Type)(SOCKET s, int level, int optname,
					  const char FAR * optval, int optlen);
typedef int (PASCAL FAR *shutdown_Type)(SOCKET s, int how);
typedef SOCKET (PASCAL FAR *socket_Type)(int af, int type, int protocol);
typedef struct hostent FAR * (PASCAL FAR *gethostbyaddr_Type)(const char FAR * addr,
							      int len, int type);
typedef struct hostent FAR * (PASCAL FAR *gethostbyname_Type)(const char FAR * name);
typedef int (PASCAL FAR *gethostname_Type) (char FAR * name, int namelen);
typedef struct servent FAR * (PASCAL FAR *getservbyport_Type)(int port, const char FAR * proto);
typedef struct servent FAR * (PASCAL FAR *getservbyname_Type)(const char FAR * name,
							      const char FAR * proto);
typedef struct protoent FAR * (PASCAL FAR *getprotobynumber_Type)(int proto);
typedef struct protoent FAR * (PASCAL FAR *getprotobyname_Type)(const char FAR * name);
typedef int (PASCAL FAR *WSAStartup_Type)(WORD wVersionRequired, LPWSADATA lpWSAData);
typedef int (PASCAL FAR *WSACleanup_Type)(void);
typedef void (PASCAL FAR *WSASetLastError_Type)(int iError);
typedef int (PASCAL FAR *WSAGetLastError_Type)(void);
typedef BOOL (PASCAL FAR *WSAIsBlocking_Type)(void);
typedef int (PASCAL FAR *WSAUnhookBlockingHook_Type)(void);
typedef FARPROC (PASCAL FAR *WSASetBlockingHook_Type)(FARPROC lpBlockFunc);
typedef int (PASCAL FAR *WSACancelBlockingCall_Type)(void);
typedef HANDLE (PASCAL FAR *WSAAsyncGetServByName_Type)(HWND hWnd, u_int wMsg,
							const char FAR * name,
							const char FAR * proto,
							char FAR * buf, int buflen);
typedef HANDLE (PASCAL FAR *WSAAsyncGetServByPort_Type)(HWND hWnd, u_int wMsg, int port,
							const char FAR * proto, char FAR * buf,
							int buflen);
typedef HANDLE (PASCAL FAR *WSAAsyncGetProtoByName_Type)(HWND hWnd, u_int wMsg,
							 const char FAR * name, char FAR * buf,
							 int buflen);
typedef HANDLE (PASCAL FAR *WSAAsyncGetProtoByNumber_Type)(HWND hWnd, u_int wMsg,
							   int number, char FAR * buf,
							   int buflen);
typedef HANDLE (PASCAL FAR *WSAAsyncGetHostByName_Type)(HWND hWnd, u_int wMsg,
							const char FAR * name, char FAR * buf,
							int buflen);
typedef HANDLE (PASCAL FAR *WSAAsyncGetHostByAddr_Type)(HWND hWnd, u_int wMsg,
							const char FAR * addr, int len, int type,
							char FAR * buf, int buflen);
typedef int (PASCAL FAR *WSACancelAsyncRequest_Type)(HANDLE hAsyncTaskHandle);
typedef int (PASCAL FAR *WSAAsyncSelect_Type)(SOCKET s, HWND hWnd, u_int wMsg,
					      long lEvent);



static accept_Type accept_Ptr = NULL;
static bind_Type bind_Ptr = NULL;
static closesocket_Type closesocket_Ptr = NULL;
static connect_Type connect_Ptr = NULL;
static ioctlsocket_Type ioctlsocket_Ptr = NULL;
static getpeername_Type getpeername_Ptr = NULL;
static getsockname_Type getsockname_Ptr = NULL;
static getsockopt_Type getsockopt_Ptr = NULL;
static htonl_Type htonl_Ptr = NULL;
static htons_Type htons_Ptr = NULL;
static inet_addr_Type inet_addr_Ptr = NULL;
static inet_ntoa_Type inet_ntoa_Ptr = NULL;
static listen_Type listen_Ptr = NULL;
static ntohl_Type ntohl_Ptr = NULL;
static ntohs_Type ntohs_Ptr = NULL;
static recv_Type recv_Ptr = NULL;
static recvfrom_Type recvfrom_Ptr = NULL;
static select_Type select_Ptr = NULL;
static send_Type send_Ptr = NULL;
static sendto_Type sendto_Ptr = NULL;
static setsockopt_Type setsockopt_Ptr = NULL;
static shutdown_Type shutdown_Ptr = NULL;
static socket_Type socket_Ptr = NULL;
static gethostbyaddr_Type gethostbyaddr_Ptr = NULL;
static gethostbyname_Type gethostbyname_Ptr = NULL;
static gethostname_Type gethostname_Ptr = NULL;
static getservbyport_Type getservbyport_Ptr = NULL;
static getservbyname_Type getservbyname_Ptr = NULL;
static getprotobynumber_Type getprotobynumber_Ptr = NULL;
static getprotobyname_Type getprotobyname_Ptr = NULL;
static WSAStartup_Type WSAStartup_Ptr = NULL;
static WSACleanup_Type WSACleanup_Ptr = NULL;
static WSASetLastError_Type WSASetLastError_Ptr = NULL;
static WSAGetLastError_Type WSAGetLastError_Ptr = NULL;
static WSAIsBlocking_Type WSAIsBlocking_Ptr = NULL;
static WSAUnhookBlockingHook_Type WSAUnhookBlockingHook_Ptr = NULL;
static WSASetBlockingHook_Type WSASetBlockingHook_Ptr = NULL;
static WSACancelBlockingCall_Type WSACancelBlockingCall_Ptr = NULL;
static WSAAsyncGetServByName_Type WSAAsyncGetServByName_Ptr = NULL;
static WSAAsyncGetServByPort_Type WSAAsyncGetServByPort_Ptr = NULL;
static WSAAsyncGetProtoByName_Type WSAAsyncGetProtoByName_Ptr = NULL;
static WSAAsyncGetProtoByNumber_Type WSAAsyncGetProtoByNumber_Ptr = NULL;
static WSAAsyncGetHostByName_Type WSAAsyncGetHostByName_Ptr = NULL;
static WSAAsyncGetHostByAddr_Type WSAAsyncGetHostByAddr_Ptr = NULL;
static WSACancelAsyncRequest_Type WSACancelAsyncRequest_Ptr = NULL;
static WSAAsyncSelect_Type WSAAsyncSelect_Ptr = NULL;


static HINSTANCE wsock32lib = NULL;
static HINSTANCE winsocklib = NULL;



// set all the pointers back to null
static void ResetWSPtrs () {
  accept_Ptr = NULL;
  bind_Ptr = NULL;
  closesocket_Ptr = NULL;
  connect_Ptr = NULL;
  ioctlsocket_Ptr = NULL;
  getpeername_Ptr = NULL;
  getsockname_Ptr = NULL;
  getsockopt_Ptr = NULL;
  htonl_Ptr = NULL;
  htons_Ptr = NULL;
  inet_addr_Ptr = NULL;
  inet_ntoa_Ptr = NULL;
  listen_Ptr = NULL;
  ntohl_Ptr = NULL;
  ntohs_Ptr = NULL;
  recv_Ptr = NULL;
  recvfrom_Ptr = NULL;
  select_Ptr = NULL;
  send_Ptr = NULL;
  sendto_Ptr = NULL;
  setsockopt_Ptr = NULL;
  shutdown_Ptr = NULL;
  socket_Ptr = NULL;
  gethostbyaddr_Ptr = NULL;
  gethostbyname_Ptr = NULL;
  gethostname_Ptr = NULL;
  getservbyport_Ptr = NULL;
  getservbyname_Ptr = NULL;
  getprotobynumber_Ptr = NULL;
  getprotobyname_Ptr = NULL;
  WSAStartup_Ptr = NULL;
  WSACleanup_Ptr = NULL;
  WSASetLastError_Ptr = NULL;
  WSAGetLastError_Ptr = NULL;
  WSAIsBlocking_Ptr = NULL;
  WSAUnhookBlockingHook_Ptr = NULL;
  WSASetBlockingHook_Ptr = NULL;
  WSACancelBlockingCall_Ptr = NULL;
  WSAAsyncGetServByName_Ptr = NULL;
  WSAAsyncGetServByPort_Ptr = NULL;
  WSAAsyncGetProtoByName_Ptr = NULL;
  WSAAsyncGetProtoByNumber_Ptr = NULL;
  WSAAsyncGetHostByName_Ptr = NULL;
  WSAAsyncGetHostByAddr_Ptr = NULL;
  WSACancelAsyncRequest_Ptr = NULL;
  WSAAsyncSelect_Ptr = NULL;
}

// get the pointers to all the socket functions
static void SetupWSPtrs (HINSTANCE socketlib) {
  if (socketlib == NULL) return;

  accept_Ptr = (accept_Type)GetProcAddress(socketlib,"accept");
  bind_Ptr = (bind_Type)GetProcAddress(socketlib,"bind");
  closesocket_Ptr = (closesocket_Type)GetProcAddress(socketlib,"closesocket");
  connect_Ptr = (connect_Type)GetProcAddress(socketlib,"connect");
  ioctlsocket_Ptr = (ioctlsocket_Type)GetProcAddress(socketlib,"ioctlsocket");
  getpeername_Ptr = (getpeername_Type)GetProcAddress(socketlib,"getpeername");
  getsockname_Ptr = (getsockname_Type)GetProcAddress(socketlib,"getsockname");
  getsockopt_Ptr = (getsockopt_Type)GetProcAddress(socketlib,"getsockopt");
  htonl_Ptr = (htonl_Type)GetProcAddress(socketlib,"htonl");
  htons_Ptr = (htons_Type)GetProcAddress(socketlib,"htons");
  inet_addr_Ptr = (inet_addr_Type)GetProcAddress(socketlib,"inet_addr");
  inet_ntoa_Ptr = (inet_ntoa_Type)GetProcAddress(socketlib,"inet_ntoa");
  listen_Ptr = (listen_Type)GetProcAddress(socketlib,"listen");
  ntohl_Ptr = (ntohl_Type)GetProcAddress(socketlib,"ntohl");
  ntohs_Ptr = (ntohs_Type)GetProcAddress(socketlib,"ntohs");
  recv_Ptr = (recv_Type)GetProcAddress(socketlib,"recv");
  recvfrom_Ptr = (recvfrom_Type)GetProcAddress(socketlib,"recvfrom");
  select_Ptr = (select_Type)GetProcAddress(socketlib,"select");
  send_Ptr = (send_Type)GetProcAddress(socketlib,"send");
  sendto_Ptr = (sendto_Type)GetProcAddress(socketlib,"sendto");
  setsockopt_Ptr = (setsockopt_Type)GetProcAddress(socketlib,"setsockopt");
  shutdown_Ptr = (shutdown_Type)GetProcAddress(socketlib,"shutdown");
  socket_Ptr = (socket_Type)GetProcAddress(socketlib,"socket");
  gethostbyaddr_Ptr = (gethostbyaddr_Type)GetProcAddress(socketlib,"gethostbyaddr");
  gethostbyname_Ptr = (gethostbyname_Type)GetProcAddress(socketlib,"gethostbyname");
  gethostname_Ptr = (gethostname_Type)GetProcAddress(socketlib,"gethostname");
  getservbyport_Ptr = (getservbyport_Type)GetProcAddress(socketlib,"getservbyport");
  getservbyname_Ptr = (getservbyname_Type)GetProcAddress(socketlib,"getservbyname");
  getprotobynumber_Ptr = (getprotobynumber_Type)GetProcAddress(socketlib,"getprotobynumber");
  getprotobyname_Ptr = (getprotobyname_Type)GetProcAddress(socketlib,"getprotobyname");
  WSAStartup_Ptr = (WSAStartup_Type)GetProcAddress(socketlib,"WSAStartup");
  WSACleanup_Ptr = (WSACleanup_Type)GetProcAddress(socketlib,"WSACleanup");
  WSASetLastError_Ptr = (WSASetLastError_Type)GetProcAddress(socketlib,"WSASetLastError");
  WSAGetLastError_Ptr = (WSAGetLastError_Type)GetProcAddress(socketlib,"WSAGetLastError");
  WSAIsBlocking_Ptr = (WSAIsBlocking_Type)GetProcAddress(socketlib,"WSAIsBlocking");
  WSAUnhookBlockingHook_Ptr = 
    (WSAUnhookBlockingHook_Type)GetProcAddress(socketlib,"WSAUnhookBlockingHook");
  WSASetBlockingHook_Ptr = 
    (WSASetBlockingHook_Type)GetProcAddress(socketlib,"WSASetBlockingHook");
  WSACancelBlockingCall_Ptr = 
    (WSACancelBlockingCall_Type)GetProcAddress(socketlib,"WSACancelBlockingCall");
  WSAAsyncGetServByName_Ptr = 
    (WSAAsyncGetServByName_Type)GetProcAddress(socketlib,"WSAAsyncGetServByName");
  WSAAsyncGetServByPort_Ptr = 
    (WSAAsyncGetServByPort_Type)GetProcAddress(socketlib,"WSAAsyncGetServByPort");
  WSAAsyncGetProtoByName_Ptr = 
    (WSAAsyncGetProtoByName_Type)GetProcAddress(socketlib,"WSAAsyncGetProtoByName");
  WSAAsyncGetProtoByNumber_Ptr = 
    (WSAAsyncGetProtoByNumber_Type)GetProcAddress(socketlib,"WSAAsyncGetProtoByNumber");
  WSAAsyncGetHostByName_Ptr = 
    (WSAAsyncGetHostByName_Type)GetProcAddress(socketlib,"WSAAsyncGetHostByName");
  WSAAsyncGetHostByAddr_Ptr = 
    (WSAAsyncGetHostByAddr_Type)GetProcAddress(socketlib,"WSAAsyncGetHostByAddr");
  WSACancelAsyncRequest_Ptr = 
    (WSACancelAsyncRequest_Type)GetProcAddress(socketlib,"WSACancelAsyncRequest");
  WSAAsyncSelect_Ptr = (WSAAsyncSelect_Type)GetProcAddress(socketlib,"WSAAsyncSelect");
}



// expects path to be NULL, a empty string, or a path which ends in a slash
// returns D_NOERROR on success,
// D_ERR_UNEXPECTED or D_ERR_LOADFAILED on failure
int d_LoadWinsock (char *path) {
  char dllname[2048]; // HARD LIMIT!!!!
  OSVERSIONINFO osver;

  if ((wsock32lib != NULL) || (winsocklib != NULL)) return D_ERR_UNEXPECTED;

  // set the error mode so that no nasty dialog boxes come
  // up when things aren't installed
  int olderrormode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS);

  // get the operating system version information
  memset(&osver, 0, sizeof(OSVERSIONINFO));
  osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  if (!GetVersionEx(&osver)) {
    SetErrorMode(olderrormode);
    return D_ERR_UNEXPECTED;
  }

  // see if we should load winsock before wsock32
  if ((osver.dwPlatformId == VER_PLATFORM_WIN32s) && (path != NULL)) {
    strcpy (dllname, path);
    strcat (dllname, "winsock.dll");

    // attempt to load the library
    winsocklib = LoadLibrary (dllname);
    if (winsocklib == NULL) {
      SetErrorMode(olderrormode);
      return D_ERR_LOADFAILED;
    }
  }

  // attempt to load wsock32
  int err = D_NOERROR;
  dllname[0] = '\0';
  if ((osver.dwPlatformId != VER_PLATFORM_WIN32s) && (path != NULL)) {
    strcpy (dllname, path);
  }
  strcat (dllname, "wsock32.dll");
  wsock32lib = LoadLibrary (dllname);
  if (wsock32lib == NULL) err = D_ERR_LOADFAILED;
  else SetupWSPtrs (wsock32lib);


  // perform a few tests

  // first try starting-up (and check the szDescription field)
  if (err == D_NOERROR) {
    WSADATA Data;
    memset(&Data, 0, sizeof(WSADATA));
    if ((d_WSAStartup(257, &Data) != 0) ||
	(Data.szDescription == NULL) || 
	(Data.szDescription[0] == '\0'))
      err = D_ERR_LOADFAILED;
  }

  // next try setting and getting an error
  if (err == D_NOERROR) {
    d_WSASetLastError (WSAENOTSOCK);
    if (d_WSAGetLastError () != WSAENOTSOCK) err = D_ERR_LOADFAILED;
    d_WSASetLastError (0);
  }

  // last try cleaning up (if an error occurs here we might
  // not be able to unload anything)
  if ((err == D_NOERROR) && (d_WSACleanup() == SOCKET_ERROR))
    err = D_ERR_LOADFAILED;

  // if an error occurred then we need to unload everything
  if (err != D_NOERROR) d_UnloadWinsock ();

  SetErrorMode(olderrormode);
  return err;
}

// returns D_NOERROR on success,
// D_ERR_FREELIBFAILED on failure
int d_UnloadWinsock () {
  int err = D_NOERROR;

  // unload wsock32
  if ((wsock32lib != NULL) && !FreeLibrary (wsock32lib)) {
    err = D_ERR_FREELIBFAILED;
  }
  wsock32lib = NULL;

  // unload winsock
  if ((winsocklib != NULL) && !FreeLibrary (winsocklib)) {
    err = D_ERR_FREELIBFAILED;
  }
  winsocklib = NULL;
  
  // reset all the function pointers
  ResetWSPtrs ();

  return err;
}




// socket functions, these just call the dynamically loaded version

SOCKET d_accept (SOCKET s, struct sockaddr *addr, int *addrlen) {
  if (accept_Ptr != NULL) 
    return (*accept_Ptr)(s, addr, addrlen);
  return INVALID_SOCKET; // error winsock not loaded
}

int d_bind (SOCKET s, const struct sockaddr *addr, int namelen) {
  if (bind_Ptr != NULL) 
    return (*bind_Ptr)(s, addr, namelen);
  return WSANOTINITIALISED; // error winsock not loaded
}

int d_closesocket (SOCKET s) {
  if (closesocket_Ptr != NULL) 
    return (*closesocket_Ptr)(s);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_connect (SOCKET s, const struct sockaddr *name, int namelen) {
  if (connect_Ptr != NULL) 
    return (*connect_Ptr)(s, name, namelen);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_ioctlsocket (SOCKET s, long cmd, u_long *argp) {
  if (ioctlsocket_Ptr != NULL) 
    return (*ioctlsocket_Ptr)(s, cmd, argp);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_getpeername (SOCKET s, struct sockaddr *name, int *namelen) {
  if (getpeername_Ptr != NULL) 
    return (*getpeername_Ptr)(s, name, namelen);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_getsockname (SOCKET s, struct sockaddr *name, int *namelen) {
  if (getsockname_Ptr != NULL) 
    return (*getsockname_Ptr)(s, name, namelen);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_getsockopt (SOCKET s, int level, int optname, char *optval, int *optlen) {
  if (getsockopt_Ptr != NULL) 
    return (*getsockopt_Ptr)(s, level, optname, optval, optlen);
  return SOCKET_ERROR; // error winsock not loaded
}

u_long d_htonl (u_long hostlong) {
  if (htonl_Ptr != NULL) 
    return (*htonl_Ptr)(hostlong);
  return hostlong; // error winsock not loaded
}

u_short d_htons (u_short hostshort) {
  if (htons_Ptr != NULL) 
    return (*htons_Ptr)(hostshort);
  return hostshort; // error winsock not loaded
}

unsigned long d_inet_addr (const char *cp) {
  if (inet_addr_Ptr != NULL) 
    return (*inet_addr_Ptr)(cp);
  return INADDR_NONE; // error winsock not loaded
}

char *d_inet_ntoa (struct in_addr in) {
  if (inet_ntoa_Ptr != NULL) 
    return (*inet_ntoa_Ptr)(in);
  return NULL; // error winsock not loaded
}

int d_listen (SOCKET s, int backlog) {
  if (listen_Ptr != NULL) 
    return (*listen_Ptr)(s, backlog);
  return SOCKET_ERROR; // error winsock not loaded
}

u_long d_ntohl (u_long netlong) {
  if (ntohl_Ptr != NULL) 
    return (*ntohl_Ptr)(netlong);
  return netlong; // error winsock not loaded
}

u_short d_ntohs (u_short netshort) {
  if (ntohs_Ptr != NULL) 
    return (*ntohs_Ptr)(netshort);
  return netshort; // error winsock not loaded
}

int d_recv (SOCKET s, char *buf, int len, int flags) {
  if (recv_Ptr != NULL) 
    return (*recv_Ptr)(s, buf, len, flags);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_recvfrom (SOCKET s, char *buf, int len, int flags,
		struct sockaddr *from, int *fromlen) {
  if (recvfrom_Ptr != NULL) 
    return (*recvfrom_Ptr)(s, buf, len, flags, from, fromlen);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_select (int nfds, fd_set *readfds, fd_set *writefds,
	      fd_set *exceptfds, const struct timeval *timeout) {
  if (select_Ptr != NULL) 
    return (*select_Ptr)(nfds, readfds, writefds, exceptfds, timeout);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_send (SOCKET s, const char *buf, int len, int flags) {
  if (send_Ptr != NULL) 
    return (*send_Ptr)(s, buf, len, flags);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_sendto (SOCKET s, const char *buf, int len, int flags,
	      const struct sockaddr *to, int tolen) {
  if (sendto_Ptr != NULL) 
    return (*sendto_Ptr)(s, buf, len, flags, to, tolen);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_setsockopt (SOCKET s, int level, int optname,
		  const char *optval, int optlen) {
  if (setsockopt_Ptr != NULL) 
    return (*setsockopt_Ptr)(s, level, optname, optval, optlen);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_shutdown (SOCKET s, int how) {
  if (shutdown_Ptr != NULL) 
    return (*shutdown_Ptr)(s, how);
  return SOCKET_ERROR; // error winsock not loaded
}

SOCKET d_socket (int af, int type, int protocol) {
  if (socket_Ptr != NULL) 
    return (*socket_Ptr)(af, type, protocol);
  return INVALID_SOCKET; // error winsock not loaded
}

hostent *d_gethostbyaddr(const char *addr, int len, int type) {
  if (gethostbyaddr_Ptr != NULL) 
    return (*gethostbyaddr_Ptr)(addr, len, type);
  return NULL; // error winsock not loaded
}

hostent *d_gethostbyname(const char *name) {
  if (gethostbyname_Ptr != NULL) 
    return (*gethostbyname_Ptr)(name);
  return NULL; // error winsock not loaded
}

int d_gethostname (char *name, int namelen) {
  if (gethostname_Ptr != NULL) 
    return (*gethostname_Ptr)(name, namelen);
  return SOCKET_ERROR; // error winsock not loaded
}

servent *d_getservbyport(int port, const char *proto) {
  if (getservbyport_Ptr != NULL) 
    return (*getservbyport_Ptr)(port, proto);
  return NULL; // error winsock not loaded
}

servent *d_getservbyname(const char *name, const char *proto) {
  if (getservbyname_Ptr != NULL) 
    return (*getservbyname_Ptr)(name, proto);
  return NULL; // error winsock not loaded
}

protoent *d_getprotobynumber(int proto) {
  if (getprotobynumber_Ptr != NULL) 
    return (*getprotobynumber_Ptr)(proto);
  return NULL; // error winsock not loaded
}

protoent *d_getprotobyname(const char *name) {
  if (getprotobyname_Ptr != NULL) 
    return (*getprotobyname_Ptr)(name);
  return NULL; // error winsock not loaded
}

int d_WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData) {
  if (WSAStartup_Ptr != NULL) 
    return (*WSAStartup_Ptr)(wVersionRequired, lpWSAData);
  return WSASYSNOTREADY; // error winsock not loaded
}

int d_WSACleanup(void) {
  if (WSACleanup_Ptr != NULL) 
    return (*WSACleanup_Ptr)();
  return WSANOTINITIALISED; // error winsock not loaded
}

void d_WSASetLastError(int iError) {
  if (WSASetLastError_Ptr != NULL) (*WSASetLastError_Ptr)(iError);
}

int d_WSAGetLastError(void) {
  if (WSAGetLastError_Ptr != NULL) 
    return (*WSAGetLastError_Ptr)();
  return WSANOTINITIALISED; // error winsock not loaded
}

BOOL d_WSAIsBlocking(void) {
  if (WSAIsBlocking_Ptr != NULL) 
    return (*WSAIsBlocking_Ptr)();
  return FALSE; // error winsock not loaded
}

int d_WSAUnhookBlockingHook(void) {
  if (WSAUnhookBlockingHook_Ptr != NULL) 
    return (*WSAUnhookBlockingHook_Ptr)();
  return SOCKET_ERROR; // error winsock not loaded
}

FARPROC d_WSASetBlockingHook(FARPROC lpBlockFunc) {
  if (WSASetBlockingHook_Ptr != NULL) 
    return (*WSASetBlockingHook_Ptr)(lpBlockFunc);
  return NULL; // error winsock not loaded
}

int d_WSACancelBlockingCall(void) {
  if (WSACancelBlockingCall_Ptr != NULL) 
    return (*WSACancelBlockingCall_Ptr)();
  return SOCKET_ERROR; // error winsock not loaded
}

HANDLE d_WSAAsyncGetServByName(HWND hWnd, u_int wMsg,
			       const char *name,
			       const char *proto,
			       char *buf, int buflen) {
  if (WSAAsyncGetServByName_Ptr != NULL) 
    return (*WSAAsyncGetServByName_Ptr)(hWnd, wMsg, name, proto, buf, buflen);
  return NULL; // error winsock not loaded
}

HANDLE d_WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, int port,
			       const char *proto, char *buf,
			       int buflen) {
  if (WSAAsyncGetServByPort_Ptr != NULL) 
    return (*WSAAsyncGetServByPort_Ptr)(hWnd, wMsg, port, proto, buf, buflen);
  return NULL; // error winsock not loaded
}

HANDLE d_WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg,
				const char *name, char *buf,
				int buflen) {
  if (WSAAsyncGetProtoByName_Ptr != NULL) 
    return (*WSAAsyncGetProtoByName_Ptr)(hWnd, wMsg, name, buf, buflen);
  return NULL; // error winsock not loaded
}

HANDLE d_WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg,
				  int number, char *buf,
				  int buflen) {
  if (WSAAsyncGetProtoByNumber_Ptr != NULL) 
    return (*WSAAsyncGetProtoByNumber_Ptr)(hWnd, wMsg, number, buf, buflen);
  return NULL; // error winsock not loaded
}

HANDLE d_WSAAsyncGetHostByName(HWND hWnd, u_int wMsg,
			       const char *name, char *buf,
			       int buflen) {
  if (WSAAsyncGetHostByName_Ptr != NULL) 
    return (*WSAAsyncGetHostByName_Ptr)(hWnd, wMsg, name, buf, buflen);
  return NULL; // error winsock not loaded
}

HANDLE d_WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg,
                                        const char *addr, int len, int type,
                                        char *buf, int buflen) {
  if (WSAAsyncGetHostByAddr_Ptr != NULL) 
    return (*WSAAsyncGetHostByAddr_Ptr)(hWnd, wMsg, addr, len, type, buf, buflen);
  return NULL; // error winsock not loaded
}

int d_WSACancelAsyncRequest(HANDLE hAsyncTaskHandle) {
  if (WSACancelAsyncRequest_Ptr != NULL) 
    return (*WSACancelAsyncRequest_Ptr)(hAsyncTaskHandle);
  return SOCKET_ERROR; // error winsock not loaded
}

int d_WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg,
                               long lEvent) {
  if (WSAAsyncSelect_Ptr != NULL) 
    return (*WSAAsyncSelect_Ptr)(s, hWnd, wMsg, lEvent);
  return SOCKET_ERROR; // error winsock not loaded
}

