/////////////////////////////////////////////////////////////////////////////
// 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,
#if _WIN32_WCE <= 211
(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,
#if _WIN32_WCE <= 211
(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,
#if defined(_WIN32_WCE) && _WIN32_WCE <= 211
(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;
}