Click here to Skip to main content
15,881,882 members
Articles / Web Development / HTML

A Comprehensive CE Class Library to Replace ATL and MFC

Rate me:
Please Sign up or sign in to vote.
4.48/5 (14 votes)
4 Oct 2000CPOL 278.1K   998   70  
A collection of classes for CE that do not use ATL or MFC, plus an FTP client, database viewer, and sample application that solves beam deflection equations.
/////////////////////////////////////////////////////////////////////////////
// RAS API wrapper for the majority of the useful stuff.
//
// Does the structure version initialization as well as
// wrapping the calls in a more digestable form
//
// Also, thunks the RAS DLL so that it doesn't get loaded
// until the first call is made

#include "StdAfx.h"

#include "CeRas.h"
#include "resource.h"

#pragma warning(disable: 4390) // empty statement
#pragma warning(disable: 4509) // SEH warning

#ifdef _DEBUG
// we want to do something with this soon, to be able to
// debug memory leaks
//#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

enum
{
	EVENT_STATUS = 1,
	EVENT_INFO,
	EVENT_WARNING,
	EVENT_ERROR
};

#define RASEXCEPTION(dwRet)			return -1
#define RASEXCEPTION_VOID(dwRet)	return

/////////////////////////////////////////////////////////////////////////////
// CeRasDevInfo implementation

#ifndef _WIN32_WCE
/*
void CeRasDevInfo::GetAll(CeRasDevInfoArray& arDevInfo)
{
    LPRASDEVINFO lpRasDevice = NULL;
    DWORD cbBuf = 0;
    DWORD cDevice = 0;
	DWORD dwRet;

	// get the number of devices so we can figure out
	// the size of the buffer we need
    if (0 != (dwRet = ::RasEnumDevices(NULL, &cbBuf, &cDevice)))
    {
        if (NULL != (lpRasDevice = (LPRASDEVINFO) new BYTE[cbBuf]))
		{
			lpRasDevice->dwSize = sizeof(RASDEVINFO);
	        dwRet = ::RasEnumDevices(lpRasDevice, &cbBuf, &cDevice);
		}
        else
            dwRet = ERROR_NOT_ENOUGH_MEMORY;
    }

	if (0 != dwRet) // other error
	{
		if (lpRasDevice)
			delete[] (BYTE*) lpRasDevice;
		RASEXCEPTION(dwRet);
	}

	// copy all the entries into the array
	arDevInfo.SetSize(cDevice);
	if (0 == cDevice)
		return;

	BYTE* lpBytes = (BYTE*) arDevInfo.GetData();
	LPRASDEVINFO lpDev = lpRasDevice;
	int nSize = cbBuf / cDevice;	// actual structure size
	for (DWORD ii = 0; ii < cDevice; ii++)
	{
		memcpy(lpBytes, lpDev, sizeof (RASDEVINFO));
		lpBytes += nSize;
		lpDev = (LPRASDEVINFO) ((BYTE*)lpDev) + nSize;
	}

	if (lpRasDevice)
		delete[] (BYTE*) lpRasDevice;
}
*/


#endif // ! WIN32_WCE

/////////////////////////////////////////////////////////////////////////////
// CeRasEntry

// Entry initialized with defaults for new entries
CeRasEntry::CeRasEntry(LPCTSTR lpszDevName/*=NULL*/, LPCTSTR lpszPhone/*=NULL*/, LPCTSTR lpszAreaCode/*=NULL*/, LPCTSTR lpszCountryCode/*=NULL*/)
{
	memset((_rasentry *)this, 0, sizeof _rasentry);
	dwSize = sizeof _rasentry;

	// Flags we use
	dwfOptions =
		RASEO_ModemLights	|			// not used yet
		RASEO_IpHeaderCompression |
		RASEO_SwCompression |
		RASEO_NetworkLogon |			// login to remote
		RASEO_UseCountryAndAreaCodes;	// allows dialing prefixes (eg, 9,)

	// required for Windows 95!!!!!
	DWORD dw;
	if (lpszCountryCode != NULL && (0 != (dw = _tcstol(lpszCountryCode, NULL, 10))))
		// use specified
		dwCountryID = dw;
	else
		// US Default
		dwCountryID = 1;

	//
	// Location/phone number.
	//
	if (lpszAreaCode)
		_tcscpy(szAreaCode, lpszAreaCode);

	if (lpszPhone)
		_tcscpy(szLocalPhoneNumber, lpszPhone);

	dwfNetProtocols = RASNP_Ip;		// TCP/UDP/IP Only
	dwFramingProtocol = RASFP_Ppp;	// PPP Only

	//
	// Device
	//
	_tcscpy(szDeviceType, RASDT_Modem);
	if (NULL != lpszDevName)
		_tcscpy(szDeviceName, lpszDevName);
}


CeRasEntry::~CeRasEntry()
{
}


void CeRasEntry::SetDevice(LPCTSTR lpszDevName)
{
	ASSERT(NULL != lpszDevName);
	_tcscpy(szDeviceName, lpszDevName);
}

void CeRasEntry::SetPhone(LPCTSTR lpszPhoneNumber, LPCTSTR  lpszAreaCode/*=NULL*/, LPCTSTR lpszCountryCode/*=NULL*/)
{
	ASSERT(NULL != lpszPhoneNumber);

	// required for Windows 95!!!!!
	DWORD dw;
	if (lpszCountryCode != NULL && (0 != (dw = _tcstol(lpszCountryCode, NULL, 10))))
		// use specified
		dwCountryID = dw;
	else
		// US Default
		dwCountryID = 1;

	//
	// Location/phone number.
	//
	if (lpszAreaCode)
		_tcscpy(szAreaCode, lpszAreaCode);

	_tcscpy(szLocalPhoneNumber, lpszPhoneNumber);
}


// get/set entry using this object
void CeRasEntry::Get(LPCTSTR szName, LPBYTE* lpbDevInfo /*= NULL*/)
{
	DWORD dwSize = 0;
	DWORD dwSizeDevInfo = 0;
	LPRASENTRY lpEntry = NULL;

	DWORD dwRet = ::RasGetEntryProperties(
				NULL,
				(LPTSTR) szName,
			#ifdef _WIN32_WCE
				(LPBYTE) lpEntry,
			#else
				lpEntry,
			#endif
				&dwSize,
				NULL,
				&dwSizeDevInfo);

	if (0 != dwRet && ERROR_BUFFER_TOO_SMALL != dwRet)
	{
		RASEXCEPTION_VOID(dwRet);
	}

	if (ERROR_BUFFER_TOO_SMALL == dwRet)
	{
		lpEntry = (LPRASENTRY) new BYTE[dwSize];
		if (! lpEntry)
			RASEXCEPTION_VOID(ERROR_NOT_ENOUGH_MEMORY);
		// sometimes the RasGetEntryProperties() call
		// leaves stuff unitializated, clear all fields before call
		memset(lpEntry, 0, dwSize);
		lpEntry->dwSize = dwSize;
	}

	if (NULL != lpbDevInfo && 0 != dwSizeDevInfo)
		*lpbDevInfo = new BYTE[dwSizeDevInfo];

	dwRet = ::RasGetEntryProperties(
				NULL,
				(LPTSTR) szName,
			#ifdef _WIN32_WCE
				(LPBYTE) lpEntry,
			#else
				lpEntry,
			#endif
				&dwSize,
				*lpbDevInfo,
				&dwSizeDevInfo);

	if (0 == dwRet)
	{
		// copy only the bytes we know about
		memcpy((RASENTRY *) this, lpEntry, sizeof _rasentry);
		// fix up the size, in case we screwed it up
		lpEntry->dwSize = sizeof _rasentry;
	}

#ifndef _WIN32_WCE
	/*
	if (dwAlternateOffset)
	{
		// we have additional number to dial,
		// let's extract them from the buffer
		LPCTSTR lpsz = (LPCTSTR) ((BYTE *) lpEntry + dwAlternateOffset);

		do
		{
			m_arAdditional.Add(lpsz);

			// find the end of this string
			for ( ; *lpsz != _T('\0'); lpsz++)
				;	// just find the end

			// add one more, since the list is double NULL terminated
			// this tells us if we're finished
			lpsz++;

		} while (*lpsz != _T('\0'));
	}
*/
#endif

	// free the buffer
	delete[] (BYTE*) lpEntry;

	// throw exception on error
	if (0 != dwRet)
	{
		RASEXCEPTION_VOID(dwRet);
	}

	// can't handle alternate phone numbers yet!!!!
	// will have to allocate something for those later, as well as
	// do something about adding them....
}


void CeRasEntry::Set(LPCTSTR szName, LPBYTE lpbDevInfo /*= NULL*/)
{
	DWORD dwSize = sizeof _rasentry;
	DWORD dwSizeDevInfo = 0;

	DWORD dwRet = ::RasValidateEntryName(NULL, (LPTSTR)(LPCTSTR)szName);
	if (0 != dwRet)
	{
		RASEXCEPTION_VOID(dwRet);
	}

	dwRet = ::RasSetEntryProperties(
				NULL,
				(LPTSTR)(LPCTSTR)szName,
			#ifdef _WIN32_WCE
				(LPBYTE) this,
			#else
				this,
			#endif
				dwSize,
				lpbDevInfo,
				dwSizeDevInfo);
	if (0 != dwRet)
	{
		RASEXCEPTION_VOID(dwRet);
	}
}


#ifndef _WIN32_WCE

// Set the windows 95 options available to us
void CeRasEntry::SetWin95(LPCTSTR lpszEntryName)
{
	// Device setting information
	typedef struct  tagDEVCFGDR
	{
		DWORD       dwSize;
		DWORD       dwVersion;
		WORD        fwOptions;
		WORD        wWaitBong;
	} DEVCFGHDR;

	const DWORD TERMINAL_PRE = 0x01;
	const DWORD TERMINAL_POST = 0x02;
	const DWORD MANUAL_DIAL = 0x04;
	const DWORD LAUNCH_LIGHTS = 0x08;

	typedef struct tagDEVCFG
	{
		DEVCFGHDR   dfgHdr;
		COMMCONFIG  commconfig;
	} DEVCFG, *PDEVCFG, FAR* LPDEVCFG;


	RASENTRY Info = {0};
	PDEVCFG pDevCfg;
	DWORD dwSize, dwDevInfo;
	dwSize = Info.dwSize = sizeof (RASENTRY);
	dwDevInfo = 0;
	DWORD dwErr;

	// First find out the size of the device-specific structure.
	// This call and will fail, but dwDevInfo will return the correct size.
	::RasGetEntryProperties (NULL, (LPTSTR) lpszEntryName, &Info,
		&dwSize, NULL, &dwDevInfo  );

	if (dwDevInfo <= 0)
		return;

	if (! (pDevCfg = (LPDEVCFG)	::LocalAlloc (LPTR, dwDevInfo)))
		return;

	dwErr = ::RasGetEntryProperties(
				NULL,
				(LPTSTR) lpszEntryName,
				&Info,
				&dwSize,
				(LPBYTE) pDevCfg,
				&dwDevInfo);

	if (dwErr)
	{
		RASEXCEPTION_VOID(dwErr);
	}

	// Verify that the TAPI provider used is the correct version of the
	// Unimodem driver. Check the size of the structure, version. and
	// provider sub-type.
	if (((pDevCfg->dfgHdr).dwSize < sizeof (DEVCFG)) ||
		((pDevCfg->dfgHdr).dwVersion != 0x00010003) ||
		((pDevCfg->commconfig).dwProviderSubType != PST_MODEM))
	{
		TRACE0(_T("TAPI provider is not UNIMODEM\n"));
		return;
    }

	// Set the launch lights flag
	(pDevCfg->dfgHdr).fwOptions |= LAUNCH_LIGHTS;

	// Set the Modem flags we need (turn off the speaker volume)
	PMODEMSETTINGS pModemSettings = (PMODEMSETTINGS)
		((BYTE*) &(pDevCfg->commconfig) + (pDevCfg->commconfig).dwProviderOffset);
	pModemSettings->dwSpeakerMode = MDMSPKR_OFF;

	dwErr = ::RasSetEntryProperties(
					NULL,
					(LPTSTR) lpszEntryName,
					&Info,
					dwSize,
					(LPBYTE) pDevCfg,
					dwDevInfo);
	if (dwErr)
	{
		RASEXCEPTION_VOID(dwErr);
	}
}

#endif

void CeRasEntry::Delete(LPCTSTR lpszEntry)
{
	DWORD dwErr = ::RasDeleteEntry(NULL, (LPTSTR)(LPCTSTR)lpszEntry);
//	if (0 != dwErr && ERROR_INVALID_NAME != dwErr)
//		throw new CeRasException(dwErr);
}


void CeRasEntry::Rename(LPCTSTR lpszNewEntry, LPCTSTR lpszOldEntry)
{
	DWORD dwErr = ::RasRenameEntry(NULL, (LPTSTR)(LPCTSTR)lpszOldEntry, (LPTSTR)(LPCTSTR)lpszNewEntry);
	if (0 != dwErr)
	{
		RASEXCEPTION_VOID(dwErr);
	}
}


int CeRasEntry::GetAll(RASENTRYNAME** lpEntries)
{
	*lpEntries = NULL;

    DWORD cbBuf = 0;
    DWORD cEntry = 0;
    DWORD dwRet;
	LPRASENTRYNAME lpRasEntry = NULL;

	lpRasEntry = (LPRASENTRYNAME) new BYTE[sizeof(RASENTRYNAME)];
    if (lpRasEntry == NULL)
		return -1;

    // enumerate connections
	cbBuf = lpRasEntry->dwSize = sizeof(RASENTRYNAME);
	dwRet = ::RasEnumEntries(NULL, NULL, lpRasEntry, &cbBuf, &cEntry);
    if (dwRet == ERROR_BUFFER_TOO_SMALL)
    {
		delete[] (BYTE*) lpRasEntry;
        if (NULL != (lpRasEntry = (LPRASENTRYNAME) new BYTE[cbBuf]))
		{
			lpRasEntry->dwSize = sizeof _rasentryname;
	        dwRet = ::RasEnumEntries(NULL, NULL, lpRasEntry, &cbBuf, &cEntry);
		}
        else
            return -1;
    }

	if (0 != dwRet) // other error
	{
		if (lpRasEntry)
			delete[] (BYTE*) lpRasEntry;

		RASEXCEPTION(dwRet);
	}

	*lpEntries = lpRasEntry;
	return cEntry;
}

// when there are NO dot's in the address, it is assumed to be a long
// integer and is converted acordingly
long CeRasEntry::StringToIP(LPCTSTR strIP)
{
	return 0;
}

RASIPADDR CeRasEntry::StringToRASIP(LPCTSTR szIP)
{
	RASIPADDR rasIP;
	memset(&rasIP, 0, sizeof(RASIPADDR));

	CeString strIP(szIP);

	if (strIP.Find(_T('.')) < 0)
	{
		// long address
		return rasIP;
	}

	TCHAR szNum[16];
	int nOctet;
	for (int ii = 0, nPos = 0; ii < 4; ii++)
	{
		for (int jj = 0; nPos < strIP.GetLength() && strIP[nPos] != _T('.'); nPos++, jj++)
			szNum[jj] = strIP[nPos];
		szNum[jj] = 0;
		nPos++; // move off of the '.'

		// octet
		nOctet = _tcstol(szNum, NULL, 10);

		switch (ii)
		{
		case 0: rasIP.a = nOctet; break;
		case 1: rasIP.b = nOctet; break;
		case 2: rasIP.c = nOctet; break;
		case 3: rasIP.d = nOctet; break;
		}
	}

	return rasIP;
}

void CeRasEntry::IPHelper()
{
}

/////////////////////////////////////////////////////////////////////////////
// CeRasConn implementation

//IMPLEMENT_DYNAMIC(CeRasConn, CObject)

CeRasConn::CeRasConnMapper CeRasConn::s_mapConn;

CeRasConn::CeRasConn()
{
	memset((_rasconn *) this, 0, sizeof _rasconn);
	dwSize = sizeof _rasconn;

	m_lpRasDialParams = NULL;
	m_bSynchronous = TRUE;

	// Connection complete status
	m_bComplete = FALSE;

	// Dialing status for active dial
	m_unMsg = 0;
	m_rascs = (RASCONNSTATE) 0;
	m_dwError = 0;
	m_dwExtendedError = 0;
	m_dwTimeOut = 150000U;	// 2.5 minutes, default
	m_nRetries = 0;
}

CeRasConn::~CeRasConn()
{
	if (IsConnected())
		Hangup();
}


/////////////////////////////////////////////////////////////////////////////
// CeRasConn diagnostics

CeString CeRasConn::GetStatus(RASCONNSTATE rasconnstate)
{
	UINT nResID = IDS_RAS_UNDEFINED_STATE;

    switch (rasconnstate)
    {
        case RASCS_OpenPort:            nResID = IDS_RAS_OPENPORT; break;
        case RASCS_PortOpened:          nResID = IDS_RAS_PORTOPENED; break;       
        case RASCS_ConnectDevice:       nResID = IDS_RAS_CONNECTDEVICE; break;    
        case RASCS_DeviceConnected:     nResID = IDS_RAS_DEVICECONNECTED; break;  
        case RASCS_AllDevicesConnected: nResID = IDS_RAS_ALLDEVICESCONNECTED; break;
        case RASCS_Authenticate:        nResID = IDS_RAS_AUTHENTICATE; break;
        case RASCS_AuthNotify:          nResID = IDS_RAS_AUTHNOTIFY; break;
        case RASCS_AuthRetry:           nResID = IDS_RAS_AUTHRETRY; break;
        case RASCS_AuthCallback:        nResID = IDS_RAS_AUTHCALLBACK; break;
        case RASCS_AuthChangePassword:  nResID = IDS_RAS_AUTHCHANGEPASSWORD; break;
        case RASCS_AuthProject:         nResID = IDS_RAS_AUTHPROJECT;  break;
        case RASCS_AuthLinkSpeed:       nResID = IDS_RAS_AUTHLINKSPEED; break;
        case RASCS_AuthAck:             nResID = IDS_RAS_AUTHACK; break;
        case RASCS_ReAuthenticate:      nResID = IDS_RAS_REAUTHENTICATE; break;
        case RASCS_Authenticated:       nResID = IDS_RAS_AUTHENTICATED; break;
        case RASCS_PrepareForCallback:  nResID = IDS_RAS_PREPAREFORCALLBACK; break;
        case RASCS_WaitForModemReset:   nResID = IDS_RAS_WAITFORMODEMRESET; break;
        case RASCS_WaitForCallback:     nResID = IDS_RAS_WAITFORCALLBACK; break;
		case RASCS_Projected:			nResID = IDS_RAS_PROJECTED; break;
        case RASCS_Interactive:         nResID = IDS_RAS_INTERACTIVE; break;
        case RASCS_RetryAuthentication: nResID = IDS_RAS_RETRYAUTHENTICATION; break;
        case RASCS_CallbackSetByCaller: nResID = IDS_RAS_CALLBACKSETBYCALLER; break;
        case RASCS_PasswordExpired:     nResID = IDS_RAS_PASSWORDEXPIRED; break;
        case RASCS_Connected:           nResID = IDS_RAS_CONNECTED; break;
        case RASCS_Disconnected:        nResID = IDS_RAS_DISCONNECTED; break;

#if !defined(_WIN32_WCE)
	#if (WINVER >= 0x400)
		case RASCS_StartAuthentication:	nResID = IDS_RAS_STARTAUTHENTICATION; break;
		case RASCS_CallbackComplete:	nResID = IDS_RAS_CALLBACKCOMPLETE; break;
		case RASCS_LogonNetwork:		nResID = IDS_RAS_LOGONNETWORK; break;
	#endif
		case RASCS_SubEntryConnected:	nResID = IDS_RAS_SUBENTRYCONNECTED; break;
		case RASCS_SubEntryDisconnected:nResID = IDS_RAS_SUBENTRYDISCONNECTED; break;
#endif
    }

	CeString str;
	str.LoadString(nResID, NULL);

	return str;
}

CeString CeRasConn::GetStatus()
{
	ASSERT(NULL != hrasconn);

	CeRasConnStatus rasStatus;
	GetStatus(rasStatus);
	return GetStatus((RASCONNSTATE) rasStatus.rasconnstate);
}


DWORD CeRasConn::GetStatus(CeRasConnStatus& rasStatus)
{
	return ::RasGetConnectStatus(hrasconn, &rasStatus);

//	DWORD dwErr = ::RasGetConnectStatus(hrasconn, &rasState);
//	if (0 != dwErr)
//		throw new CeRasException(dwErr);
}


BOOL CeRasConn::IsConnected()
{
	if (NULL == hrasconn)
		return FALSE;

	CeRasConnStatus rasStatus;
	GetStatus(rasStatus);
	return (RASCS_Connected == rasStatus.rasconnstate);
}



// RASDial notification function
// Note: this is passed to a Win32 RAS API function so it must be static
//       or it gets expects the 'this' pointer pushed on the stack
//       which it won't be when getting called from a C API
VOID WINAPI CeRasConn::RasDialNotificationFn(HRASCONN hrasconn, UINT unMsg, RASCONNSTATE rascs, DWORD dwError, DWORD dwExtendedError)
{
//	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	if (hrasconn)
	{
		CeRasConn *pConn = s_mapConn.GetMapping(hrasconn);

		if (pConn)
		{
			// call the user first
			pConn->OnDialStatus(unMsg, rascs, dwError, dwExtendedError);

			if (0 != dwError || RASCS_Connected == rascs || RASCS_Disconnected == rascs)
			{
				pConn->LogEvent(EVENT_INFO, _T("Dialing complete."));
				pConn->SetDialComplete(dwError);
			}
		}
	}
}


inline BOOL IsErrorRetriable(DWORD dwError)
{
	return (dwError == ERROR_PORT_ALREADY_OPEN ||
			dwError == ERROR_OUT_OF_BUFFERS ||
			dwError == ERROR_REMOTE_DISCONNECTION ||
			dwError == ERROR_USER_DISCONNECTION ||
			dwError == ERROR_PORT_NOT_AVAILABLE ||
			dwError == ERROR_SERVER_NOT_RESPONDING ||
			dwError == ERROR_DEVICE_NOT_READY  ||
			dwError == ERROR_LINE_BUSY ||
			dwError == ERROR_NO_ANSWER ||
			dwError == ERROR_NO_CARRIER ||
			dwError == ERROR_NO_DIALTONE);
}


void CeRasConn::Dial(LPRASDIALPARAMS lpRasDialParams, BOOL bSynchronous/*=TRUE*/, LPRASDIALEXTENSIONS lpRASDialExt/*=NULL*/)
{
	int nTries = 0;

 	// Set up the dial state specific parameters
	m_lpRasDialParams = lpRasDialParams;
	m_bSynchronous = bSynchronous;

	//
	// NOTE: RASDIALEXTENSIONS are IGNORED under Windows 95 as is
	//       the phonebook entry, defaults for the device and for the
	//       phone book are ALWAYS used under Windows 95
	//

 retry:

	nTries++;
	m_rascs = (RASCONNSTATE) 0;
	m_unMsg = 0;
	m_dwError = 0;
	m_dwExtendedError = 0;
	DWORD dwErr = 0;
	m_bComplete = FALSE;
	m_eventDialComplete.Reset();

	// should be a parameter
	BOOL bNoMessages = FALSE;

	if (m_bSynchronous && bNoMessages)
	{
		dwErr = ::RasDial(
			lpRASDialExt,
			NULL,
			m_lpRasDialParams,
			0, NULL,			// no callback type or function
			&hrasconn);
	}
	else
	{
		dwErr = ::RasDial(
			lpRASDialExt,
			NULL,
			m_lpRasDialParams,
			1, RasDialNotificationFn, // callback type and function
			&hrasconn);
	}

	if (0 != dwErr)
	{
		RASEXCEPTION_VOID(dwErr);
	}

	// Add a mapping between the RAS handle and this CeRasConn object
	// so that the callback function can complete synchronous connect status
	// and call the OnNotification() member
	if (hrasconn)
		s_mapConn.AddMapping(hrasconn, this);

	if (! m_bSynchronous)
		// let the caller handle the messaging and other stuff
		return;

	WaitForDialComplete();

	s_mapConn.RemoveMapping(hrasconn);
	
	if (0 != m_dwError)
	{
		// check to see if for some reason the handle is valid
		// and force a hangup
		if (NULL != hrasconn)
		{
			LogEvent(EVENT_INFO, _T("Resetting port after connection failure."));
			Hangup();
		}

		// we failed in the connect request, try again???
		if (IsErrorRetriable(m_dwError) && m_nRetries + 1 > nTries)
		{
			// 
			CeString str;
			LPTSTR lpsz = str.GetBufferSetLength(256);
//			CException* e = new CeRasException(m_dwError);
//			e->GetErrorMessage(lpsz, 256);
//			e->Delete();
			str.ReleaseBuffer();
			LogEvent(EVENT_ERROR, str);
			str.Format(_T("Retrying failed connection attempt.  Retry number %d."), nTries);
			LogEvent(EVENT_INFO, str);
			Sleep(10000);		// HACK/HACK let the line adjust before retry
			goto retry;
		}

		RASEXCEPTION_VOID(m_dwError);
	}
}

void CeRasConn::SetDialComplete(DWORD dwError)
{
	m_bComplete = TRUE;
	m_dwError = dwError;

	m_eventDialComplete.Set();
}


void CeRasConn::WaitForDialComplete()
{
	TRACE0("Waiting for Dial Complete.");

	DWORD dwRet = m_eventDialComplete.WaitFor(m_dwTimeOut);

	switch (dwRet)
	{
	case WAIT_ABANDONED:	// controlling thread terminated without signalling
		LogEvent(EVENT_ERROR, _T("Dial Complete: Wait Abandoned."));
		m_dwError = ERROR_EVENT_INVALID;	// had to pick something...
		// kill the dial attempt
		Hangup();
		break;

	case WAIT_FAILED:		// some error occured
		LogEvent(EVENT_ERROR, _T("Dial Complete: Wait failed."));
		m_dwError = ERROR_EVENT_INVALID; 	// had to pick something...
		// kill the dial attempt
		Hangup();
		break;

	case WAIT_TIMEOUT:		// wait timed out
		LogEvent(EVENT_WARNING, _T("Dial Complete: Wait timed out."));
		m_dwError = ERROR_REQUEST_TIMEOUT;
		// kill the dial attempt
		Hangup();
		break;

	case WAIT_OBJECT_0:
	default:
// The callback will log a more accurate success/error, this is redundant in the
// complete case.
//		LogEvent(EVENT_INFO, "Dial Complete: [Done]");
		break;
	}
}


//
// OnNotification			- callback method for dialing status
//
// UINT unMsg				- type of event that has occurred 
// RASCONNSTATE rascs		- connection state about to be entered 
// DWORD dwError			- error that may have occurred 
// DWORD dwExtendedError	- extended error information for some errors 
//

void CeRasConn::OnDialStatus(UINT unMsg, RASCONNSTATE rascs, DWORD dwError, DWORD dwExtendedError)
{
	// do notification stuff here...
	TRACE1(_T("RASDial Status: %s\n"), (LPCTSTR) CeRasConn::GetStatus(rascs));
}


void CeRasConn::LogEvent(short nPriority, LPCTSTR szEvent) const
{
	TRACE2(_T("%d: %s"), nPriority, szEvent);
}


void CeRasConn::Hangup(BOOL bSynchronous/*=TRUE*/)
{
	CeString strConnectName;
	DWORD dwTries = 0;
	DWORD dwErr;
	CeRasConnStatus rasStatus;
	
	// We were passed a pointer, don't trust it
	dwErr = ::RasHangUp( hrasconn );
	
	if (S_OK == dwErr && bSynchronous)
	{
		// RasHangUp() is an asynchronous call, so loop if we
		// want syncronous
		DWORD dwErr;
		while (ERROR_INVALID_HANDLE != (dwErr = GetStatus(rasStatus)))
		{
			dwTries++;
			// Surrender the rest of our thread's time slice and a little more
			::Sleep( 250 );
		}
		
		hrasconn = NULL;
	}

	if (0 != dwErr)
	{
		RASEXCEPTION_VOID(dwErr);
	}
}

#if !defined(_WIN32_WCE)
void CeRasConn::GetProjectionInfo(LPRASAMB pInfo)
{
	DWORD dwErr = ::RasGetProjectionInfo(hrasconn, RASP_Amb, pInfo, &dwSize);
	if (dwErr)
	{
		RASEXCEPTION_VOID(dwErr);
	}
}

void CeRasConn::GetProjectionInfo(LPRASPPPNBF pInfo)
{
	DWORD dwErr = ::RasGetProjectionInfo(hrasconn, RASP_PppNbf, pInfo, &dwSize);
	if (dwErr)
	{
		RASEXCEPTION_VOID(dwErr);
	}
}

void CeRasConn::GetProjectionInfo(LPRASPPPIPX pInfo)
{
	DWORD dwErr = ::RasGetProjectionInfo(hrasconn, RASP_PppIpx, pInfo, &dwSize);
	if (dwErr)
	{
		RASEXCEPTION_VOID(dwErr);
	}
}

void CeRasConn::GetProjectionInfo(LPRASPPPIP pInfo)
{
	DWORD dwErr = ::RasGetProjectionInfo(hrasconn, RASP_PppIp, pInfo, &dwSize);
	if (dwErr)
	{
		RASEXCEPTION_VOID(dwErr);
	}
}
#endif // _WIN32_WCE

int CeRasConn::GetAll(RASCONN** ppConn)
{
	*ppConn = NULL;

    DWORD cbBuf;
    DWORD cConn = 0;
    DWORD dwRet = 0;
	LPRASCONN lpRasConn = NULL;
	
	lpRasConn = (LPRASCONN) new BYTE[sizeof(_rasconn)];
    if (lpRasConn == NULL)
		return -1;

    // enumerate connections
	cbBuf = lpRasConn->dwSize = sizeof _rasconn;
	dwRet = ::RasEnumConnections( lpRasConn, &cbBuf, &cConn );
    if (dwRet == ERROR_BUFFER_TOO_SMALL)
    {
		delete[] (BYTE*) lpRasConn;
        if ((lpRasConn = (LPRASCONN) new BYTE[cbBuf]) != NULL )
            dwRet = ::RasEnumConnections( lpRasConn, &cbBuf, &cConn );
        else
            return -1;
    }

    if (dwRet != 0) // other error
	{
		if (lpRasConn)
			delete[] (BYTE*) lpRasConn;
		RASEXCEPTION(dwRet);
	}

	if (0 == cConn)
	{
		if (lpRasConn)
			delete[] (BYTE*) lpRasConn;
		return 0;
	}

	*ppConn = lpRasConn;
	return cConn;
}


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions