Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

A comprehensive CE class library to replace ATL and MFC

, 4 Oct 2000 CPOL
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.
kgwince-old.zip
WinCe
BeamEx
app.ico
BeamEx.dsp
BeamEx.dsw
BeamEx.ini
BeamEx.plg
bitmap1.bmp
bmp00001.bmp
bmp00002.bmp
calc.bmp
calc16.bmp
circ_cross.ico
cir_cross.ico
cross_4.ico
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico00005.ico
ico00008.ico
ico00009.ico
ico00010.ico
icon1.ico
icon2.ico
icon4.ico
id_downl.bmp
Install
BeamEx.inf
BeamEx.ini
BeamEx.MIPS_PPCBW.CAB
BeamEx.MIPS_PPCColor.CAB
BeamEx.SH3_PPCColor.CAB
Setup.exe
i_cross.ico
l_cross.ico
magenic.ico
mssccprj.scc
obl_corss.ico
obl_cross.ico
options.bmp
options1.bmp
ping16.bmp
rect_cross.ico
scene_5.ico
scene_6.ico
tri_cross.ico
vssver.scc
CeLib
CeLabel.inl
CeLib.aps
CeLib.dsp
CeLib.dsw
CeLib.old
CeLib.plg
CeLib.vcp
CeMisc.inl
CeProperty.inl
CeTab.inl
CeWnd.inl
mssccprj.scc
vssver.scc
WinLib.dsp
WinLib.dsw
dbView
bitmap1.bmp
bmp00001.bmp
db5.bmp
dbView.aps
DbView.dsp
dbView.dsw
dbView.old
dbView.plg
DbView.vcp
deldb.bp2
deldb5.bmp
delrec.bp2
delrecor.bmp
help16.bmp
help4.bmp
icon1.ico
icon2.ico
Install
dbView.inf
dbView.ini
Setup.exe
magenic.bmp
magenic.ico
mssccprj.scc
vssver.scc
ftpView
appicon.ico
bitmap1.bmp
bitmap2.bmp
bitmap3.bmp
bitmap4.bmp
bmp00001.bmp
bmp00002.bmp
db5.bmp
deldb.bp2
delrec.bp2
FtpView.dsp
ftpView.dsw
FtpView.old
ftpView.plg
FtpView.vcl
FtpView.vcp
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico171.ico
ico35.ico
icon1.ico
icon2.ico
imagelis.bmp
IMAGES.bmp
Install
ftpView.inf
ftpView.ini
Setup.exe
vssver.scc
magenic.bmp
magenic.ico
mssccprj.scc
options.bmp
options1.bmp
seperato.bmp
vssver.scc
Setup
ico101.ico
Setup.aps
Setup.dsp
setup.ico
Setup.plg
WinCe.dsw
WinLib.dsw
kgwince.zip
app.ico
BeamEx.dsp
BeamEx.dsw
BeamEx.ini
BeamEx.plg
BeamEx.vcl
BeamEx.vcp
bitmap1.bmp
bmp00001.bmp
bmp00002.bmp
calc.bmp
calc16.bmp
circ_cross.ico
cir_cross.ico
cross_4.ico
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico00005.ico
ico00008.ico
ico00009.ico
ico00010.ico
icon1.ico
icon2.ico
icon4.ico
id_downl.bmp
BeamEx.inf
BeamEx.ini
Setup.exe
i_cross.ico
l_cross.ico
magenic.ico
mssccprj.scc
obl_corss.ico
obl_cross.ico
options.bmp
options1.bmp
ping16.bmp
rect_cross.ico
scene_5.ico
scene_6.ico
tri_cross.ico
vssver.scc
CeFtp.vcp
CeFtp.vcw
CeLabel.inl
CeLib.aps
CeLib.dsp
CeLib.dsw
CeLib.plg
CeLib.vcl
CeLib.vcp
CeMisc.inl
CeProperty.inl
CeTab.inl
CeWnd.inl
mssccprj.scc
vssver.scc
WinLib.dsp
WinLib.dsw
bitmap1.bmp
bitmap2.bmp
bmp00001.bmp
db5.bmp
DbView.dsp
dbView.dsw
dbView.plg
DbView.vcl
DbView.vcp
deldb.bp2
deldb5.bmp
delrec.bp2
delrecor.bmp
help16.bmp
help4.bmp
icon1.ico
icon2.ico
dbView.inf
dbView.ini
Setup.exe
magenic.bmp
magenic.ico
menu1_5.bmp
mssccprj.scc
vssver.scc
appicon.ico
bitmap1.bmp
bitmap2.bmp
bitmap3.bmp
bitmap4.bmp
bmp00001.bmp
bmp00002.bmp
db5.bmp
deldb.bp2
delrec.bp2
FtpView.dsp
ftpView.dsw
ftpView.plg
FtpView.vcl
FtpView.vcp
FtpView.vcw
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico171.ico
ico35.ico
icon1.ico
icon2.ico
imagelis.bmp
IMAGES.bmp
ftpView.inf
ftpView.ini
Setup.exe
vssver.scc
magenic.bmp
magenic.ico
mssccprj.scc
newmenu.bmp
options.bmp
options1.bmp
rcdata1.bin
seperato.bmp
toolbar1.bmp
vssver.scc
WinCe.dsw
WinCe.vcw
/////////////////////////////////////////////////////////////////////////////
// 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)

Share

About the Author

Kenny G

United States United States
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141220.1 | Last Updated 5 Oct 2000
Article Copyright 2000 by Kenny G
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid