home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / mozock.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  18.9 KB  |  637 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "stdafx.h"
  20.  
  21. //    Purpose of this file is to implement an intermediate layer to our network
  22. //        services, the winsock.
  23. //    This intermediate layer will be able to function with and without a working
  24. //        winsock being present.
  25. //    The attempt to activate the winsock happens as would normally be expected,
  26. //        through the calling application's entry point to us, WSAStartup.
  27.  
  28.  
  29. //    Name of the winsock we would like to load.
  30. //    Diffs between OSs, Win32s is out in the cold if running 32 bits unless
  31. //        they also have a winsock name wsock32.dll.
  32. #ifdef XP_WIN16
  33. #define SZWINSOCK "winsock.dll"
  34. #else
  35. #define SZWINSOCK "wsock32.dll"
  36. #endif
  37.  
  38. //    Here is the enumeration for the winsock functions we have currently
  39. //        overridden (needed to run).  Add more when needed.
  40. //    We use these to access proc addresses, and to hold a table of strings
  41. //        to obtain the proc addresses.
  42. enum SockProc    {
  43.     sp_WSAAsyncGetHostByName = 0,
  44.     sp_WSAAsyncSelect,
  45.     sp_WSACleanup,
  46.     sp_WSAGetLastError,
  47.     sp_WSASetLastError,
  48.     sp_WSAStartup,
  49.     sp___WSAFDIsSet,
  50.     sp_accept,
  51.     sp_bind,
  52.     sp_closesocket,
  53.     sp_connect,
  54.     sp_gethostbyname,
  55.     sp_gethostbyaddr,
  56.     sp_gethostname,
  57.     sp_getpeername,
  58.     sp_getsockname,
  59.     sp_getsockopt,
  60.         sp_getprotobyname,
  61.     sp_htonl,
  62.     sp_htons,
  63.     sp_inet_addr,
  64.     sp_ioctlsocket,
  65.     sp_listen,
  66.     sp_ntohl,
  67.     sp_ntohs,
  68.     sp_recv,
  69.     sp_recvfrom,
  70.     sp_select,
  71.     sp_send,
  72.     sp_sendto,
  73.     sp_setsockopt,
  74.     sp_shutdown,
  75.     sp_socket,
  76.     sp_inet_ntoa,
  77.  
  78.     sp_MaxProcs    //    Total count.
  79. };
  80.  
  81. //    Array of function names used in GetProcAddress to fill in our
  82. //        proc array when needed.
  83. //    This array must match the enumerations exactly.
  84. char *spName[(SockProc)sp_MaxProcs] =    {
  85.     "WSAAsyncGetHostByName",
  86.     "WSAAsyncSelect",
  87.     "WSACleanup",
  88.     "WSAGetLastError",
  89.     "WSASetLastError",
  90.     "WSAStartup",
  91.     "__WSAFDIsSet",
  92.     "accept",
  93.     "bind",
  94.     "closesocket",
  95.     "connect",
  96.     "gethostbyname",
  97.     "gethostbyaddr",
  98.     "gethostname",
  99.     "getpeername",
  100.     "getsockname",
  101.     "getsockopt",
  102.         "getprotobyname",
  103.     "htonl",
  104.     "htons",
  105.     "inet_addr",
  106.     "ioctlsocket",
  107.     "listen",
  108.     "ntohl",
  109.     "ntohs",
  110.     "recv",
  111.         "recvfrom",
  112.     "select",
  113.     "send",
  114.         "sendto",
  115.     "setsockopt",
  116.     "shutdown",
  117.     "socket",
  118.     "inet_ntoa"
  119. };
  120.  
  121. //    Array of proc addresses to the winsock functions.
  122. //    These can be NULL, indicating their absence (as in the case we couldn't
  123. //        load the winsock.dll or one of the functions wasn't loaded).
  124. //    The procs assigned in must corellate with the enumerations exactly.
  125. FARPROC spArray[(SockProc)sp_MaxProcs];
  126.  
  127. //    Typedef all the different types of functions that we must cast the
  128. //        procs to in order to call without the compiler barfing.
  129. //    Prefix is always sp.
  130. //    Retval is next, spelled out.
  131. //    Parameters in their order are next, spelled out.
  132. typedef int (PASCAL FAR *sp_int_WORD_LPWSADATA)(WORD, LPWSADATA);
  133. typedef int (PASCAL FAR *sp_int_void)(void);
  134. typedef HANDLE (PASCAL FAR *sp_HANDLE_HWND_uint_ccharFARp_charFARp_int)(HWND, unsigned int, const char FAR *, char FAR *, int);
  135. typedef int (PASCAL FAR *sp_int_SOCKET_HWND_uint_long)(SOCKET, HWND, unsigned int, long);
  136. typedef void (PASCAL FAR *sp_void_int)(int);
  137. typedef int (PASCAL FAR *sp_int_SOCKET_fdsetFARp)(SOCKET, fd_set FAR *);
  138. typedef SOCKET(PASCAL FAR *sp_SOCKET_SOCKET_sockaddrFARp_intFARp)(SOCKET, struct sockaddr FAR *, int FAR *);
  139. typedef int (PASCAL FAR *sp_int_SOCKET_csockaddrFARp_int)(SOCKET, const struct sockaddr FAR *, int);
  140. typedef int (PASCAL FAR *sp_int_SOCKET)(SOCKET);
  141. typedef struct hostent FAR *(PASCAL FAR *sp_hostentFARp_ccharFARp)(const char FAR *);
  142. typedef struct hostent FAR *(PASCAL FAR *sp_hostentFARp_ccharFARp_int_int)(const char FAR *, int, int);
  143. typedef int (PASCAL FAR *sp_int_charFARp_int)(char FAR *, int);
  144. typedef int (PASCAL FAR *sp_int_SOCKET_sockaddrFARp_intFARp)(SOCKET, struct sockaddr FAR *, int FAR *);
  145. typedef int (PASCAL FAR *sp_int_SOCKET_int_int_charFARp_intFARp)(SOCKET, int, int, char FAR *, int FAR *);
  146. typedef u_long (PASCAL FAR *sp_ulong_ulong)(u_long);
  147. typedef u_short (PASCAL FAR *sp_ushort_ushort)(u_short);
  148. typedef unsigned long (PASCAL FAR *sp_ulong_ccharFARp)(const char FAR *);
  149. typedef int (PASCAL FAR *sp_int_SOCKET_long_ulongFARp)(SOCKET, long, u_long FAR *);
  150. typedef int (PASCAL FAR *sp_int_SOCKET_int)(SOCKET, int);
  151. typedef int (PASCAL FAR *sp_int_SOCKET_charFARp_int_int)(SOCKET, char FAR *, int, int);
  152. typedef int (PASCAL FAR *sp_int_SOCKET_charFARp_int_int_sockaddrFARp_intFARp)(SOCKET, char FAR *, int, int, struct sockaddr FAR*, int FAR *);
  153. typedef int (PASCAL FAR *sp_int_int_fdsetFARp_fdsetFARp_fdsetFARp_ctimevalFARp)(int, fd_set FAR *, fd_set FAR *, fd_set FAR *, const struct timeval FAR *);
  154. typedef int (PASCAL FAR *sp_int_SOCKET_ccharFARp_int_int)(SOCKET, const char FAR *, int, int);
  155. typedef int (PASCAL FAR *sp_int_SOCKET_ccharFARp_int_int_csockaddrFARp_int)(SOCKET, const char FAR *, int, int, const struct sockaddr FAR*, int);
  156. typedef int (PASCAL FAR *sp_int_SOCKET_int_int_ccharFARp_int)(SOCKET, int, int, const char FAR *, int);
  157. typedef SOCKET (PASCAL FAR *sp_SOCKET_int_int_int)(int, int, int);
  158. typedef char FAR * (PASCAL FAR *sp_charFARp_in_addr)(struct in_addr in);
  159. typedef struct protoent FAR * (PASCAL FAR *sp_protoentFARcchar)(const char FAR *);
  160.  
  161. //    Handle to the winsock, if loaded.
  162. HINSTANCE hWinsock = NULL;
  163.  
  164. #ifdef XP_WIN16
  165. //    Last error code for the winsock.
  166. int ispError = 0;
  167. #endif
  168.  
  169. //    Quick macro to tell if the winsock has actually loaded for a particular
  170. //        function.
  171. //  Debug version is a little more strict to make sure you get the names right.
  172. #ifdef DEBUG
  173. #define IsWinsockLoaded(sp)    (hWinsock != NULL && spArray[(SockProc)(sp)] != NULL)
  174. #else   //  A little faster
  175. #define IsWinsockLoaded(sp) (hWinsock != NULL)
  176. #endif
  177.  
  178. //    Here are the functions that we have taken over by not directly linking
  179. //        with the winsock import library or importing through the def file.
  180. extern "C"    {
  181.  
  182. int PASCAL FAR WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)    {
  183.     //    Before doing anything, clear out our proc array.
  184.     memset(spArray, 0, sizeof(spArray));
  185.  
  186.     //    Our default return value is failure, though we change this regardless.
  187.     int iRetval = WSAVERNOTSUPPORTED;
  188.  
  189.     //    attempt to load the real winsock.
  190.     hWinsock = LoadLibrary(SZWINSOCK);
  191. #ifdef XP_WIN32
  192.     if(hWinsock != NULL)    {
  193. #else
  194.     if(hWinsock > HINSTANCE_ERROR)    {
  195. #endif
  196.         //    Winsock was loaded.
  197.         //    Get the proc addresses for each needed function next.
  198.         int spTraverse;
  199.         for(spTraverse = 0; spTraverse < (SockProc)sp_MaxProcs; spTraverse++)    {
  200.             spArray[spTraverse] = GetProcAddress(hWinsock, spName[spTraverse]);
  201.             ASSERT(spArray[spTraverse]);    //    Bad winsock?  Bad function name?
  202.         }
  203.  
  204.         //    AllRight, attempt to make our first proxied call.
  205.         if(IsWinsockLoaded(sp_WSAStartup))    {
  206.             iRetval = ((sp_int_WORD_LPWSADATA)spArray[sp_WSAStartup])(wVersionRequested, lpWSAData);
  207.         }
  208.  
  209.         //    If the return value is still an error at this point, we unload the DLL,
  210.         //        so that we can act as though nothing happened and the user
  211.         //        gets no network access.
  212.         if(iRetval != 0)    {
  213.             //    Clear out our proc array.
  214.             memset(spArray, 0, sizeof(spArray));
  215.  
  216.             //    Free up the winsock.
  217.             FreeLibrary(hWinsock);
  218.             hWinsock = NULL;
  219.         }
  220.     }
  221. #ifdef XP_WIN16
  222.     else    {
  223.         //    Failed to load.
  224.         //    Set this to NULL so it is clear.
  225.         hWinsock = NULL;
  226.     }
  227. #endif
  228.  
  229.     //    Check our return value, if it isn't success, then we need to fake
  230.     //        our own winsock implementation.
  231.     if(iRetval != 0)    {
  232.         //    We always return success.
  233.         iRetval = 0;
  234.  
  235.         //    Fill in the structure.
  236.         //    Return the version requested as the version supported.
  237.         lpWSAData->wVersion = wVersionRequested;
  238.         lpWSAData->wHighVersion = wVersionRequested;
  239.  
  240.         //    Fill in a discription.
  241.         strcpy(lpWSAData->szDescription, "Mozock DLL internal implementation.");
  242.         strcpy(lpWSAData->szSystemStatus, "Winsock running, allowing no network access.");
  243.  
  244.         //    Report a nice round number for sockets and datagram sizes.
  245.         lpWSAData->iMaxSockets = 4096;
  246.         lpWSAData->iMaxUdpDg = 4096;
  247.  
  248.         //    No vendor information.
  249.         lpWSAData->lpVendorInfo = NULL;
  250.     }
  251.  
  252.     return(iRetval);
  253. }
  254.  
  255. int PASCAL FAR WSACleanup(void)    {
  256.     int iRetval = 0;
  257.  
  258.     //    Handling normally or internally.
  259.     if(IsWinsockLoaded(sp_WSACleanup))    {
  260.         //    Call their cleanup routine.
  261.         //    We could set the return value here, but it is meaning less.
  262.         //    We always return success.
  263.         iRetval = ((sp_int_void)spArray[sp_WSACleanup])();
  264.         ASSERT(iRetval == 0);
  265.         iRetval = 0;
  266.     }
  267.  
  268.     //    Wether or not it succeeded, we free off the library here.
  269.     //    Clear out our proc table too.
  270.     memset(spArray, 0, sizeof(spArray));
  271.     if(hWinsock != NULL)    {
  272.         FreeLibrary(hWinsock);
  273.         hWinsock = NULL;
  274.     }
  275.  
  276.     return(iRetval);
  277. }
  278.  
  279. HANDLE PASCAL FAR WSAAsyncGetHostByName(HWND hWnd, unsigned int wMsg, const char FAR *name, char FAR *buf, int buflen)    {
  280.     // Normal or shim.
  281.     if(IsWinsockLoaded(sp_WSAAsyncGetHostByName))    {
  282.         return(((sp_HANDLE_HWND_uint_ccharFARp_charFARp_int)spArray[sp_WSAAsyncGetHostByName])(hWnd, wMsg, name, buf, buflen));
  283.     }
  284.  
  285.     //    Must return error here.
  286.     //    Set our last error value to be that the net is down.
  287.     WSASetLastError(WSAENETDOWN);
  288.     return(NULL);
  289. }
  290.  
  291. int PASCAL FAR WSAAsyncSelect(SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent)    {
  292.     //    Normal or shim.
  293.     if(IsWinsockLoaded(sp_WSAAsyncSelect))    {
  294.         return(((sp_int_SOCKET_HWND_uint_long)spArray[sp_WSAAsyncSelect])(s, hWnd, wMsg, lEvent));
  295.     }
  296.  
  297.     //    Must return error here.
  298.     WSASetLastError(WSAENETDOWN);
  299.     return(SOCKET_ERROR);
  300. }
  301.  
  302. int PASCAL FAR WSAGetLastError(void)    {
  303.     //    See if someone else can handle.
  304.     if(IsWinsockLoaded(sp_WSAGetLastError))    {
  305.         return(((sp_int_void)spArray[sp_WSAGetLastError])());
  306.     }
  307.  
  308. #ifdef XP_WIN16
  309.     //    Fake it.
  310.     int iRetval = ispError;
  311.     ispError = 0;
  312.     return(iRetval);
  313. #else
  314.     //    Use default OS handler.
  315.     return(GetLastError());
  316. #endif
  317. }
  318.  
  319. void PASCAL FAR WSASetLastError(int iError)    {
  320.     //    See if someone else can handle.
  321.     if(IsWinsockLoaded(sp_WSASetLastError))    {
  322.         ((sp_void_int)spArray[sp_WSASetLastError])(iError);
  323.         return;
  324.     }
  325.  
  326. #ifdef XP_WIN16
  327.     //    Fake it.
  328.     ispError = iError;
  329.     return;
  330. #else
  331.     //    Use default OS handler.
  332.     SetLastError(iError);
  333.     return;
  334. #endif
  335. }
  336.  
  337. int PASCAL FAR __WSAFDIsSet(SOCKET fd, fd_set FAR *set)    {
  338.     //    See if someone else will handle.
  339.     if(IsWinsockLoaded(sp___WSAFDIsSet))    {
  340.         return(((sp_int_SOCKET_fdsetFARp)spArray[sp___WSAFDIsSet])(fd, set));
  341.     }
  342.  
  343.     //    Default implementation.
  344.     int i = set->fd_count;
  345.      while (i--)    {
  346.         if (set->fd_array[i] == fd)    {
  347.              return 1;
  348.         }
  349.     }
  350.      return 0;
  351. }
  352.  
  353. SOCKET PASCAL FAR accept(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen)    {
  354.     //    Internally or shim
  355.     if(IsWinsockLoaded(sp_accept))    {
  356.         return(((sp_SOCKET_SOCKET_sockaddrFARp_intFARp)spArray[sp_accept])(s, addr, addrlen));
  357.     }
  358.  
  359.     //    Fail.
  360.     WSASetLastError(WSAENETDOWN);
  361.     return(INVALID_SOCKET);
  362. }
  363.  
  364. int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR *name, int namelen)    {
  365.     //    Internally or shim
  366.     if(IsWinsockLoaded(sp_bind))    {
  367.         return(((sp_int_SOCKET_csockaddrFARp_int)spArray[sp_bind])(s, name, namelen));
  368.     }
  369.  
  370.     //    Fail.
  371.     WSASetLastError(WSAENETDOWN);
  372.     return(SOCKET_ERROR);
  373. }
  374.  
  375. int PASCAL FAR closesocket(SOCKET s)    {
  376.     //    Internally or shim.
  377.     if(IsWinsockLoaded(sp_closesocket))    {
  378.         return(((sp_int_SOCKET)spArray[sp_closesocket])(s));
  379.     }
  380.  
  381.     //    Error.
  382.     WSASetLastError(WSAENETDOWN);
  383.     return(SOCKET_ERROR);
  384. }
  385.  
  386. int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR *name, int namelen)    {
  387.     //    Internally or shim.
  388.     if(IsWinsockLoaded(sp_connect))    {
  389.         return(((sp_int_SOCKET_csockaddrFARp_int)spArray[sp_connect])(s, name, namelen));
  390.     }
  391.  
  392.     //    Err.
  393.     WSASetLastError(WSAENETDOWN);
  394.     return(SOCKET_ERROR);
  395. }
  396.  
  397. struct hostent FAR * PASCAL FAR gethostbyname(const char FAR *name)    {
  398.     if(IsWinsockLoaded(sp_gethostbyname))    {
  399.         return(((sp_hostentFARp_ccharFARp)spArray[sp_gethostbyname])(name));
  400.     }
  401.  
  402.     WSASetLastError(WSAENETDOWN);
  403.     return(NULL);
  404. }
  405.  
  406. struct hostent FAR * PASCAL FAR gethostbyaddr(const char FAR *addr, int len, int type)    {
  407.     if(IsWinsockLoaded(sp_gethostbyaddr))    {
  408.         return(((sp_hostentFARp_ccharFARp_int_int)spArray[sp_gethostbyaddr])(addr, len, type));
  409.     }
  410.  
  411.     WSASetLastError(WSAENETDOWN);
  412.     return(NULL);
  413. }
  414.  
  415. int PASCAL FAR gethostname(char FAR *name, int namelen)    {
  416.     if(IsWinsockLoaded(sp_gethostname))    {
  417.         return(((sp_int_charFARp_int)spArray[sp_gethostname])(name, namelen));
  418.     }
  419.  
  420.     WSASetLastError(WSAENETDOWN);
  421.     return(SOCKET_ERROR);
  422. }
  423.  
  424. int PASCAL FAR getpeername(SOCKET s, struct sockaddr FAR *name, int FAR *namelen)    {
  425.     if(IsWinsockLoaded(sp_getpeername))    {
  426.         return(((sp_int_SOCKET_sockaddrFARp_intFARp)spArray[sp_getpeername])(s, name, namelen));
  427.     }
  428.  
  429.     WSASetLastError(WSAENETDOWN);
  430.     return(SOCKET_ERROR);
  431. }
  432.  
  433. int PASCAL FAR getsockname(SOCKET s, struct sockaddr FAR *name, int FAR *namelen)    {
  434.     if(IsWinsockLoaded(sp_getsockname))    {
  435.         return(((sp_int_SOCKET_sockaddrFARp_intFARp)spArray[sp_getsockname])(s, name, namelen));
  436.     }
  437.  
  438.     WSASetLastError(WSAENETDOWN);
  439.     return(SOCKET_ERROR);
  440. }
  441.  
  442. int PASCAL FAR getsockopt(SOCKET s, int level, int optname, char FAR *optval, int FAR *optlen)    {
  443.     if(IsWinsockLoaded(sp_getsockopt))    {
  444.         return(((sp_int_SOCKET_int_int_charFARp_intFARp)spArray[sp_getsockopt])(s, level, optname, optval, optlen));
  445.     }
  446.  
  447.     WSASetLastError(WSAENETDOWN);
  448.     return(SOCKET_ERROR);
  449. }
  450.  
  451. struct protoent FAR * PASCAL getprotobyname(const char FAR * name) {
  452.     if(IsWinsockLoaded(sp_getprotobyname))    {
  453.         return(((sp_protoentFARcchar)spArray[sp_getprotobyname])(name));
  454.     }
  455.  
  456.     WSASetLastError(WSAENETDOWN);
  457.     return NULL;
  458. }
  459.  
  460. u_long PASCAL FAR htonl(u_long hostlong)    {
  461.     if(IsWinsockLoaded(sp_htonl))    {
  462.         return(((sp_ulong_ulong)spArray[sp_htonl])(hostlong));
  463.     }
  464.  
  465. #ifdef XP_WIN16
  466.     return
  467.         (((hostlong&0xff)<<24) + ((hostlong&0xff00)<<8) +
  468.          ((hostlong&0xff0000)>>8) + ((hostlong&0xff000000)>>24));
  469.  
  470. #else
  471.     //    Just return what was passed in.
  472.     return(hostlong);
  473. #endif
  474. }
  475.  
  476. u_short PASCAL FAR htons(u_short hostshort)    {
  477.     if(IsWinsockLoaded(sp_htons))    {
  478.         return(((sp_ushort_ushort)spArray[sp_htons])(hostshort));
  479.     }
  480.  
  481. #ifdef XP_WIN16
  482.     return (((hostshort&0xff)<<8) + ((hostshort&0xff00)>>8));
  483.  
  484. #else
  485.     //    Just return what was passed in.
  486.     return(hostshort);
  487. #endif
  488. }
  489.  
  490. u_long PASCAL FAR ntohl(u_long hostlong)    {
  491.     if(IsWinsockLoaded(sp_ntohl))    {
  492.         return(((sp_ulong_ulong)spArray[sp_ntohl])(hostlong));
  493.     }
  494.  
  495. #ifdef XP_WIN16
  496.     return
  497.         (((hostlong&0xff)<<24) + ((hostlong&0xff00)<<8) +
  498.          ((hostlong&0xff0000)>>8) + ((hostlong&0xff000000)>>24));
  499.  
  500. #else
  501.     //    Just return what was passed in.
  502.     return(hostlong);
  503. #endif
  504. }
  505.  
  506. u_short PASCAL FAR ntohs(u_short hostshort)    {
  507.     if(IsWinsockLoaded(sp_ntohs))    {
  508.         return(((sp_ushort_ushort)spArray[sp_ntohs])(hostshort));
  509.     }
  510.  
  511. #ifdef XP_WIN16
  512.     return (((hostshort&0xff)<<8) + ((hostshort&0xff00)>>8));
  513.  
  514. #else
  515.     //    Just return what was passed in.
  516.     return(hostshort);
  517. #endif
  518. }
  519.  
  520. unsigned long PASCAL FAR inet_addr(const char FAR *cp)    {
  521.     if(IsWinsockLoaded(sp_inet_addr))    {
  522.         return(((sp_ulong_ccharFARp)spArray[sp_inet_addr])(cp));
  523.     }
  524.  
  525.     return(INADDR_NONE);
  526. }
  527.  
  528. int PASCAL FAR ioctlsocket(SOCKET s, long cmd, u_long FAR *argp)    {
  529.     if(IsWinsockLoaded(sp_ioctlsocket))    {
  530.         return(((sp_int_SOCKET_long_ulongFARp)spArray[sp_ioctlsocket])(s, cmd, argp));
  531.     }
  532.  
  533.     WSASetLastError(WSAENETDOWN);
  534.     return(SOCKET_ERROR);
  535. }
  536.  
  537. int PASCAL FAR listen(SOCKET s, int backlog)    {
  538.     if(IsWinsockLoaded(sp_listen))    {
  539.         return(((sp_int_SOCKET_int)spArray[sp_listen])(s, backlog));
  540.     }
  541.  
  542.     WSASetLastError(WSAENETDOWN);
  543.     return(SOCKET_ERROR);
  544. }
  545.  
  546. int PASCAL FAR recv(SOCKET s, char FAR *buf, int len, int flags)    {
  547.     if(IsWinsockLoaded(sp_recv))    {
  548.         return(((sp_int_SOCKET_charFARp_int_int)spArray[sp_recv])(s, buf, len, flags));
  549.     }
  550.  
  551.     WSASetLastError(WSAENETDOWN);
  552.     return(SOCKET_ERROR);
  553. }
  554.  
  555. int PASCAL FAR recvfrom(SOCKET s, char FAR *buf, int len, int flags,
  556.         struct sockaddr FAR * from, int FAR * fromlen) {
  557.     if(IsWinsockLoaded(sp_recvfrom))    {
  558.         return (((sp_int_SOCKET_charFARp_int_int_sockaddrFARp_intFARp)spArray[sp_recvfrom])(s, buf, len, flags, from, fromlen));
  559.         }
  560.  
  561.     WSASetLastError(WSAENETDOWN);
  562.     return(SOCKET_ERROR);
  563. }
  564.  
  565. int PASCAL FAR select(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout)    {
  566.     //  If there's nothing to do, stop now before we go off into dll land.
  567.     //  Optimization, boyz.
  568.     if((readfds && readfds->fd_count) || (writefds && writefds->fd_count) || (exceptfds && exceptfds->fd_count))    {
  569.         if(IsWinsockLoaded(sp_select))    {
  570.                 return(((sp_int_int_fdsetFARp_fdsetFARp_fdsetFARp_ctimevalFARp)spArray[sp_select])(nfds, readfds, writefds, exceptfds, timeout));
  571.         }
  572.  
  573.         WSASetLastError(WSAENETDOWN);
  574.         return(SOCKET_ERROR);
  575.     }
  576.  
  577.     //  No need to go to the DLL, there is nothing to do.
  578.     return(0);
  579. }
  580.  
  581. int PASCAL FAR send(SOCKET s, const char FAR *buf, int len, int flags)    {
  582.     if(IsWinsockLoaded(sp_send))    {
  583.         return(((sp_int_SOCKET_ccharFARp_int_int)spArray[sp_send])(s, buf, len, flags));
  584.     }
  585.  
  586.     WSASetLastError(WSAENETDOWN);
  587.     return(SOCKET_ERROR);
  588. }
  589.  
  590. int PASCAL FAR sendto(SOCKET s, const char FAR *buf, int len, int flags,
  591.         const struct sockaddr FAR * to, int tolen) {
  592.     if(IsWinsockLoaded(sp_sendto))    {
  593.         return (((sp_int_SOCKET_ccharFARp_int_int_csockaddrFARp_int)spArray[sp_sendto])(s, buf, len, flags, to, tolen));
  594.         }
  595.  
  596.     WSASetLastError(WSAENETDOWN);
  597.     return(SOCKET_ERROR);
  598. }
  599.  
  600. int PASCAL FAR setsockopt(SOCKET s, int level, int optname, const char FAR *optval, int optlen)    {
  601.     if(IsWinsockLoaded(sp_setsockopt))    {
  602.         return(((sp_int_SOCKET_int_int_ccharFARp_int)spArray[sp_setsockopt])(s, level, optname, optval, optlen));
  603.     }    
  604.  
  605.     WSASetLastError(WSAENETDOWN);
  606.     return(SOCKET_ERROR);
  607. }
  608.  
  609. int PASCAL FAR shutdown(SOCKET s, int how)    {
  610.     if(IsWinsockLoaded(sp_shutdown))    {
  611.         return(((sp_int_SOCKET_int)spArray[sp_shutdown])(s, how));
  612.     }
  613.  
  614.     WSASetLastError(WSAENETDOWN);
  615.     return(SOCKET_ERROR);
  616. }
  617.  
  618. SOCKET PASCAL FAR socket(int af, int type, int protocol)    {
  619.     if(IsWinsockLoaded(sp_socket))    {
  620.         return(((sp_SOCKET_int_int_int)spArray[sp_socket])(af, type, protocol));
  621.     }
  622.  
  623.     WSASetLastError(WSAENETDOWN);
  624.     return(INVALID_SOCKET);
  625. }
  626.  
  627. char FAR * PASCAL FAR inet_ntoa(struct in_addr in) {
  628.     if(IsWinsockLoaded(sp_inet_ntoa))    {
  629.         return ((sp_charFARp_in_addr)spArray[sp_inet_ntoa])(in);
  630.     }
  631.  
  632.     WSASetLastError(WSAENETDOWN);
  633.     return NULL;
  634. }
  635.  
  636. };
  637.