You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
358 lines
7.5 KiB
358 lines
7.5 KiB
//
|
|
// 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"
|
|
|
|
|
|
#if ((! defined(DPNBUILD_ONLYWINSOCK2)) && (! defined(DPNBUILD_NOWINSOCK2)))
|
|
//
|
|
// Globals
|
|
//
|
|
HINSTANCE g_hWinSock2 = NULL;
|
|
|
|
//
|
|
// Declare global function pointers
|
|
//
|
|
#define DWINSOCK_GLOBAL
|
|
#include "dwnsock2.inc"
|
|
|
|
#endif // ! DPNBUILD_ONLYWINSOCK2 and ! DPNBUILD_NOWINSOCK2
|
|
|
|
|
|
//
|
|
// Internal Functions and data
|
|
//
|
|
#ifndef DPNBUILD_NOWINSOCK2
|
|
static BOOL MapWinsock2FunctionPointers(void);
|
|
#endif // ! DPNBUILD_NOWINSOCK2
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
|
|
static char NibbleToHex(BYTE b);
|
|
|
|
static void BinToHex(PBYTE pBytes, int nNbrBytes, LPSTR lpStr);
|
|
|
|
static int IPXAddressToString(LPSOCKADDR_IPX pAddr,
|
|
DWORD dwAddrLen,
|
|
LPTSTR lpAddrStr,
|
|
LPDWORD pdwStrLen);
|
|
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DWSInitWinSock"
|
|
|
|
int DWSInitWinSock( void )
|
|
{
|
|
WORD wVersionRequested;
|
|
WSADATA wsaData;
|
|
int iReturn;
|
|
|
|
|
|
#ifdef DPNBUILD_ONLYWINSOCK2
|
|
//
|
|
// Use Winsock 2.
|
|
//
|
|
wVersionRequested = MAKEWORD(2, 2);
|
|
#else // ! DPNBUILD_ONLYWINSOCK2
|
|
//
|
|
// Assume we will use Winsock 1.
|
|
//
|
|
wVersionRequested = MAKEWORD(1, 1);
|
|
|
|
#ifndef DPNBUILD_NOWINSOCK2
|
|
//
|
|
// Try to load Winsock 2 if allowed.
|
|
//
|
|
#ifndef DPNBUILD_NOREGISTRY
|
|
if (g_dwWinsockVersion != 1)
|
|
#endif // ! DPNBUILD_NOREGISTRY
|
|
{
|
|
#ifdef WIN95
|
|
OSVERSIONINFO osvi;
|
|
|
|
memset(&osvi, 0, sizeof(osvi));
|
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
|
if ((g_dwWinsockVersion == 2) || // if we explicitly are supposed to use WS2, or
|
|
(! GetVersionEx(&osvi)) || // if we can't get the OS information, or
|
|
(osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) || // if it's not Win9x, or
|
|
(HIBYTE(HIWORD(osvi.dwBuildNumber)) != 4) || // it's not the Win98 major version number, or
|
|
(LOBYTE(HIWORD(osvi.dwBuildNumber)) != 10)) // it's not Win98's minor version number (Gold = build 1998, SE = build 2222)
|
|
#endif // WIN95
|
|
{
|
|
g_hWinSock2 = LoadLibrary(TEXT("WS2_32.DLL"));
|
|
if (g_hWinSock2 != NULL)
|
|
{
|
|
//
|
|
// Use GetProcAddress to initialize
|
|
// the function pointers
|
|
//
|
|
if (!MapWinsock2FunctionPointers())
|
|
{
|
|
iReturn = -1;
|
|
goto Failure;
|
|
}
|
|
|
|
wVersionRequested = MAKEWORD(2, 2);
|
|
}
|
|
}
|
|
}
|
|
#endif // ! DPNBUILD_NOWINSOCK2
|
|
#endif // ! DPNBUILD_ONLYWINSOCK2
|
|
|
|
//
|
|
// Call WSAStartup()
|
|
//
|
|
iReturn = WSAStartup(wVersionRequested, &wsaData);
|
|
if (iReturn != 0)
|
|
{
|
|
goto Failure;
|
|
}
|
|
|
|
DPFX(DPFPREP, 3, "Using WinSock version %i.%i",
|
|
LOBYTE( wsaData.wVersion ), HIBYTE( wsaData.wVersion ) );
|
|
|
|
if (wVersionRequested != wsaData.wVersion)
|
|
{
|
|
DPFX(DPFPREP, 0, "WinSock version %i.%i in use doesn't match version requested %i.%i!",
|
|
LOBYTE( wsaData.wVersion ), HIBYTE( wsaData.wVersion ),
|
|
LOBYTE( wVersionRequested ), HIBYTE( wVersionRequested ) );
|
|
iReturn = -1;
|
|
goto Failure;
|
|
}
|
|
|
|
DNASSERT(iReturn == 0);
|
|
|
|
Exit:
|
|
|
|
return iReturn;
|
|
|
|
Failure:
|
|
|
|
#if ((! defined(DPNBUILD_ONLYWINSOCK2)) && (! defined(DPNBUILD_NOWINSOCK2)))
|
|
if (g_hWinSock2 != NULL)
|
|
{
|
|
FreeLibrary(g_hWinSock2);
|
|
g_hWinSock2 = NULL;
|
|
}
|
|
#endif // ! DPNBUILD_ONLYWINSOCK2 and ! DPNBUILD_NOWINSOCK2
|
|
|
|
DNASSERT(iReturn != 0);
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
void DWSFreeWinSock(void)
|
|
{
|
|
WSACleanup();
|
|
|
|
#if ((! defined(DPNBUILD_ONLYWINSOCK2)) && (! defined(DPNBUILD_NOWINSOCK2)))
|
|
if (g_hWinSock2 != NULL)
|
|
{
|
|
FreeLibrary(g_hWinSock2);
|
|
g_hWinSock2 = NULL;
|
|
}
|
|
#endif // ! DPNBUILD_ONLYWINSOCK2 and ! DPNBUILD_NOWINSOCK2
|
|
}
|
|
|
|
#if ((! defined(DPNBUILD_ONLYWINSOCK2)) && (! defined(DPNBUILD_NOWINSOCK2)))
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// GetWinsockVersion - get the version of Winsock
|
|
//
|
|
// Entry: Nothing
|
|
//
|
|
// Exit: Winsock version
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetWinsockVersion"
|
|
|
|
int GetWinsockVersion( void )
|
|
{
|
|
return ((g_hWinSock2 != NULL) ? 2 : 1);
|
|
}
|
|
//**********************************************************************
|
|
#endif // ! DPNBUILD_ONLYWINSOCK2 and ! DPNBUILD_NOWINSOCK2
|
|
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
|
|
//
|
|
// Workaround for WSAAddressToString()/IPX bug
|
|
//
|
|
int IPXAddressToStringNoSocket(LPSOCKADDR pSAddr,
|
|
DWORD dwAddrLen,
|
|
LPSTR lpAddrStr,
|
|
LPDWORD pdwStrLen)
|
|
{
|
|
char szAddr[32];
|
|
char szTmp[20];
|
|
LPSOCKADDR_IPX pAddr = (LPSOCKADDR_IPX) pSAddr;
|
|
//
|
|
// Check destination length
|
|
//
|
|
if (*pdwStrLen < 27)
|
|
{
|
|
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;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
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];
|
|
//
|
|
// Check destination length
|
|
//
|
|
if (*pdwStrLen < 27)
|
|
{
|
|
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)
|
|
{
|
|
WSASetLastError(WSAEFAULT);
|
|
}
|
|
else
|
|
{
|
|
WSASetLastError(WSAEINVAL);
|
|
}
|
|
return SOCKET_ERROR;
|
|
}
|
|
#else
|
|
//
|
|
// ANSI -- Check the string length
|
|
//
|
|
if (strlen(szAddr) > *pdwStrLen)
|
|
{
|
|
WSASetLastError(WSAEFAULT);
|
|
*pdwStrLen = strlen(szAddr);
|
|
return SOCKET_ERROR;
|
|
}
|
|
strcpy(lpAddrStr, szAddr);
|
|
*pdwStrLen = strlen(szAddr);
|
|
#endif // UNICODE
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif DPNBUILD_NOIPX
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
#ifndef DPNBUILD_NOWINSOCK2
|
|
BOOL MapWinsock2FunctionPointers(void)
|
|
{
|
|
//
|
|
// This variable must be declared
|
|
// with this name in order to use
|
|
// #define DWINSOCK_GETPROCADDRESS
|
|
//
|
|
BOOL fOK = TRUE;
|
|
|
|
#define DWINSOCK_GETPROCADDRESS
|
|
#include "dwnsock2.inc"
|
|
|
|
return fOK;
|
|
}
|
|
#endif // DPNBUILD_NOWINSOCK2
|
|
|