2025-04-27 07:49:33 -04:00

298 lines
5.8 KiB
C++

//
// DWINSOCK.C Dynamic WinSock
//
// Functions for dynamically linking to
// best available WinSock.
//
// Dynamically links to WS2_32.DLL or
// if WinSock 2 isn't available, it
// dynamically links to WSOCK32.DLL.
//
//
#include "dnwsocki.h"
//
// Declare global function pointers
//
#define DWINSOCK_GLOBAL
#include "dwnsock1.inc"
#include "dwnsock2.inc"
//
// Internal Functions and data
//
static BOOL MapFunctionPointers(LPDWSSTATE lpState, BOOL fMapVersion2);
static int IPXAddressToString(LPSOCKADDR_IPX pAddr,
DWORD dwAddrLen,
LPTSTR lpAddrStr,
LPDWORD pdwStrLen);
////////////////////////////////////////////////////////////
int DWSInitWinSock(LPDWSSTATE lpState )
{
WORD wVersionRequested;
BOOL f2Loaded = TRUE;
WSADATA wsaData;
int nRet;
if (lpState == NULL)
return 0;
//
// Attempt to dynamically load WS2_32.DLL
//
#ifdef WINNT
lpState->hndlWinSock = LoadLibrary(TEXT("WS2_32.DLL"));
if (lpState->hndlWinSock == NULL)
{
return 0;
}
#else // WIN95
//
// Try Winsock 2 first
//
lpState->hndlWinSock = LoadLibrary(TEXT("WS2_32.DLL"));
if (lpState->hndlWinSock != NULL)
{
goto SkipWinsock1Load;
}
//
// Couldn't load WinSock 2, try 1.1
//
f2Loaded = FALSE;
lpState->hndlWinSock = LoadLibrary(TEXT("WSOCK32.DLL"));
if (lpState->hndlWinSock == NULL)
return 0;
SkipWinsock1Load:
#endif // WIN95
//
// Use GetProcAddress to initialize
// the function pointers
//
if (!MapFunctionPointers(lpState, f2Loaded))
return 0;
//
// If WinSock 2 was loaded, ask for 2.2 otherwise 1.1
//
if (f2Loaded)
wVersionRequested = MAKEWORD(2,2);
else
wVersionRequested = MAKEWORD(1,1);
//
// Call WSAStartup()
//
nRet = p_WSAStartup(wVersionRequested, &wsaData);
if (nRet)
{
FreeLibrary(lpState->hndlWinSock);
return 0;
}
if (wVersionRequested != wsaData.wVersion)
{
FreeLibrary(lpState->hndlWinSock);
return 0;
}
// Save Max UDP for use with 1.1
lpState->nMaxUdp = wsaData.iMaxUdpDg;
//
// Return 1 or 2
//
lpState->nVersion = f2Loaded ? 2 : 1;
return(lpState->nVersion);
}
////////////////////////////////////////////////////////////
BOOL DWSFreeWinSock(LPDWSSTATE lpState)
{
if (lpState == NULL)
return FALSE;
if (p_WSACleanup != NULL)
p_WSACleanup();
lpState->nVersion = 0;
return(FreeLibrary(lpState->hndlWinSock));
}
////////////////////////////////////////////////////////////
BOOL MapFunctionPointers(LPDWSSTATE lpState, BOOL fMapVersion2)
{
// we set the local lib handle for use with the
// macros
HINSTANCE hndlWinSock = lpState->hndlWinSock;
//
// This variable must be declared
// with this name in order to use
// #define DWINSOCK_GETPROCADDRESS
//
BOOL fOK = TRUE;
//
// GetProcAddress for functions
// available in both 1.1 and 2
//
#define DWINSOCK_GETPROCADDRESS
#include "dwnsock1.inc"
//
// If that went OK, and we're supposed
// to map version 2, then do GetProcAddress
// for functions only available in WinSock 2
//
if (fOK && fMapVersion2)
{
#include "dwnsock2.inc"
}
return fOK;
}
////////////////////////////////////////////////////////////
char NibbleToHex(BYTE b)
{
if (b < 10)
return (b + '0');
return (b - 10 + 'A');
}
void BinToHex(PBYTE pBytes, int nNbrBytes, LPSTR lpStr)
{
BYTE b;
while(nNbrBytes--)
{
// High order nibble first
b = (*pBytes >> 4);
*lpStr = NibbleToHex(b);
lpStr++;
// Then low order nibble
b = (*pBytes & 0x0F);
*lpStr = NibbleToHex(b);
lpStr++;
pBytes++;
}
*lpStr = '\0';
}
////////////////////////////////////////////////////////////
//
// Workaround for WSAAddressToString()/IPX bug
//
int IPXAddressToString(LPSOCKADDR_IPX pAddr,
DWORD dwAddrLen,
LPTSTR lpAddrStr,
LPDWORD pdwStrLen)
{
char szAddr[32];
char szTmp[20];
char *cp = szAddr;
//
// Check destination length
//
if (*pdwStrLen < 27)
{
p_WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
//
// Convert network number
//
BinToHex((PBYTE)&pAddr->sa_netnum, 4, szTmp);
strcpy(szAddr, szTmp);
strcat(szAddr, ",");
// Node Number
BinToHex((PBYTE)&pAddr->sa_nodenum, 6, szTmp);
strcat(szAddr, szTmp);
strcat(szAddr, ":");
// IPX Address Socket number
BinToHex((PBYTE)&pAddr->sa_socket, 2, szTmp);
strcat(szAddr, szTmp);
#ifdef UNICODE
//
// Convert inet_ntoa string to wide char
//
int nRet = MultiByteToWideChar(CP_ACP,
0,
szAddr,
-1,
lpAddrStr,
*pdwStrLen);
if (nRet == 0)
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
p_WSASetLastError(WSAEFAULT);
else
p_WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
#else
//
// ANSI -- Check the string length
//
if (strlen(szAddr) > *pdwStrLen)
{
p_WSASetLastError(WSAEFAULT);
*pdwStrLen = strlen(szAddr);
return SOCKET_ERROR;
}
strcpy(lpAddrStr, szAddr);
*pdwStrLen = strlen(szAddr);
#endif
return 0;
}
//
// Workaround for WSAAddressToString()/IPX bug
//
int IPXAddressToStringNoSocket(LPSOCKADDR pSAddr,
DWORD dwAddrLen,
LPSTR lpAddrStr,
LPDWORD pdwStrLen)
{
char szAddr[32];
char szTmp[20];
char *cp = szAddr;
LPSOCKADDR_IPX pAddr = (LPSOCKADDR_IPX) pSAddr;
//
// Check destination length
//
if (*pdwStrLen < 27)
{
p_WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
//
// Convert network number
//
BinToHex((PBYTE)&pAddr->sa_netnum, 4, szTmp);
strcpy(szAddr, szTmp);
strcat(szAddr, ",");
// Node Number
BinToHex((PBYTE)&pAddr->sa_nodenum, 6, szTmp);
strcat(szAddr, szTmp);
strcpy(lpAddrStr, szAddr);
*pdwStrLen = strlen(szAddr);
return 0;
}