|
|
//
// 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
|