|
|
/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/ /**********************************************************************/
/*
general.cpp General classes for the DHCP snapin
FILE HISTORY:
*/
#include "stdafx.h"
#include "options.h"
#include "nodes.h"
const TCHAR g_szDefaultHelpTopic[] = _T("\\help\\dhcpconcepts.chm::/sag_dhcptopnode.htm");
/////////////////////////////////////////////////////////////////////
//
// CTimerArray implementation
//
/////////////////////////////////////////////////////////////////////
CTimerMgr::CTimerMgr() {
}
CTimerMgr::~CTimerMgr() { CTimerDesc * pTimerDesc;
for (INT_PTR i = GetUpperBound(); i >= 0; --i) { pTimerDesc = GetAt(i); if (pTimerDesc->uTimer != 0) FreeTimer(i);
delete pTimerDesc; }
}
int CTimerMgr::AllocateTimer ( ITFSNode * pNode, CDhcpServer * pServer, UINT uTimerValue, TIMERPROC TimerProc ) { CSingleLock slTimerMgr(&m_csTimerMgr);
// get a lock on the timer mgr for the scope of this
// function.
slTimerMgr.Lock();
CTimerDesc * pTimerDesc = NULL;
// look for an empty slot
for (INT_PTR i = GetUpperBound(); i >= 0; --i) { pTimerDesc = GetAt(i); if (pTimerDesc->uTimer == 0) break; }
// did we find one? if not allocate one
if (i < 0) { pTimerDesc = new CTimerDesc; Add(pTimerDesc); i = GetUpperBound(); }
//
// fix null pointer dereference
//
if ( pTimerDesc == NULL ) { return -1; }
pTimerDesc->uTimer = SetTimer(NULL, (UINT) i, uTimerValue, TimerProc); if (pTimerDesc->uTimer == 0) return -1;
pTimerDesc->spNode.Set(pNode); pTimerDesc->pServer = pServer; pTimerDesc->timerProc = TimerProc;
return (int)i; }
void CTimerMgr::FreeTimer ( UINT_PTR uEventId ) { CSingleLock slTimerMgr(&m_csTimerMgr);
// get a lock on the timer mgr for the scope of this
// function.
slTimerMgr.Lock();
CTimerDesc * pTimerDesc;
Assert(uEventId <= (UINT) GetUpperBound()); if (uEventId > (UINT) GetUpperBound()) return;
pTimerDesc = GetAt((int) uEventId); ::KillTimer(NULL, pTimerDesc->uTimer);
pTimerDesc->spNode.Release(); pTimerDesc->pServer = NULL; pTimerDesc->uTimer = 0; }
CTimerDesc * CTimerMgr::GetTimerDesc ( UINT_PTR uEventId ) { CSingleLock slTimerMgr(&m_csTimerMgr);
// the caller of this function should lock the timer mgr
// while accessing this pointer
CTimerDesc * pTimerDesc;
for (INT_PTR i = GetUpperBound(); i >= 0; --i) { pTimerDesc = GetAt(i); if (pTimerDesc->uTimer == uEventId) return pTimerDesc; }
return NULL; }
void CTimerMgr::ChangeInterval ( UINT_PTR uEventId, UINT uNewInterval ) { CSingleLock slTimerMgr(&m_csTimerMgr);
// get a lock on the timer mgr for the scope of this
// function.
slTimerMgr.Lock();
Assert(uEventId <= (UINT) GetUpperBound()); if (uEventId > (UINT) GetUpperBound()) return;
CTimerDesc tempTimerDesc; CTimerDesc * pTimerDesc;
pTimerDesc = GetAt((int) uEventId);
// kill the old timer
::KillTimer(NULL, pTimerDesc->uTimer);
// set a new one with the new interval
pTimerDesc->uTimer = ::SetTimer(NULL, (UINT) uEventId, uNewInterval, pTimerDesc->timerProc); }
/////////////////////////////////////////////////////////////////////
//
// CDhcpClient implementation
//
/////////////////////////////////////////////////////////////////////
CDhcpClient::CDhcpClient ( const DHCP_CLIENT_INFO * pdhcClientInfo ) : m_bReservation( FALSE ) { Assert(pdhcClientInfo);
InitializeData(pdhcClientInfo);
m_bClientType = CLIENT_TYPE_UNSPECIFIED; }
CDhcpClient::CDhcpClient ( const DHCP_CLIENT_INFO_V4 * pdhcClientInfo ) : m_bReservation( FALSE ) { Assert(pdhcClientInfo);
InitializeData(reinterpret_cast<const DHCP_CLIENT_INFO *>(pdhcClientInfo));
m_bClientType = pdhcClientInfo->bClientType; }
void CDhcpClient::InitializeData ( const DHCP_CLIENT_INFO * pdhcClientInfo ) { DWORD err = 0;
CATCH_MEM_EXCEPTION { m_dhcpIpAddress = pdhcClientInfo->ClientIpAddress; m_dhcpIpMask = pdhcClientInfo->SubnetMask; m_dtExpires = pdhcClientInfo->ClientLeaseExpires;
if ( pdhcClientInfo->ClientName ) { m_strName = pdhcClientInfo->ClientName; }
if ( pdhcClientInfo->ClientComment ) { m_strComment = pdhcClientInfo->ClientComment; }
if ( pdhcClientInfo->OwnerHost.HostName ) { m_strHostName = pdhcClientInfo->OwnerHost.HostName; }
if ( pdhcClientInfo->OwnerHost.NetBiosName ) { m_strHostNetbiosName = pdhcClientInfo->OwnerHost.NetBiosName; }
//
// Convert the hardware addres
//
for ( DWORD i = 0 ; i < pdhcClientInfo->ClientHardwareAddress.DataLength ; i++ ) { m_baHardwareAddress.SetAtGrow( i, pdhcClientInfo->ClientHardwareAddress.Data[i] ) ; } } END_MEM_EXCEPTION( err ) ; }
CDhcpClient::~CDhcpClient() { }
CDhcpClient::CDhcpClient() : m_dhcpIpAddress( 0 ), m_dhcpIpMask( 0 ), m_dhcpIpHost( 0 ), m_bReservation( FALSE ) { m_dtExpires.dwLowDateTime = DHCP_DATE_TIME_ZERO_LOW ; m_dtExpires.dwHighDateTime = DHCP_DATE_TIME_ZERO_HIGH ; }
void CDhcpClient::SetHardwareAddress ( const CByteArray & caByte ) { INT_PTR cMax = caByte.GetSize(); m_baHardwareAddress.SetSize( cMax );
for ( int i = 0 ; i < cMax ; i++ ) { m_baHardwareAddress.SetAt( i, caByte.GetAt( i ) ); } }
/////////////////////////////////////////////////////////////////////
//
// CDhcpIpRange implementation
//
/////////////////////////////////////////////////////////////////////
CDhcpIpRange::CDhcpIpRange ( DHCP_IP_RANGE dhcpIpRange ) { *this = dhcpIpRange; m_RangeType = DhcpIpRanges; }
CDhcpIpRange::CDhcpIpRange() { m_dhcpIpRange.StartAddress = DHCP_IP_ADDRESS_INVALID; m_dhcpIpRange.EndAddress = DHCP_IP_ADDRESS_INVALID; m_RangeType = DhcpIpRanges; }
CDhcpIpRange::~CDhcpIpRange() { }
//
// Sort helper function
//
/*int
CDhcpIpRange::OrderByAddress ( const CObjectPlus * pobIpRange ) const { const CDhcpIpRange * pipr = (CDhcpIpRange *) pobIpRange;
//
// Derive a comparison result for the end address
//
int iEndResult = QueryAddr( FALSE ) < QueryAddr( FALSE ) ? -1 : QueryAddr( FALSE ) != QueryAddr( FALSE );
//
// Use start address as major sort key, end address as minor.
//
return QueryAddr( TRUE ) < pipr->QueryAddr( TRUE ) ? -1 : ( QueryAddr( TRUE ) != pipr->QueryAddr( TRUE ) ? 1 : iEndResult ); } */
CDhcpIpRange & CDhcpIpRange::operator = ( const DHCP_IP_RANGE dhcpIpRange ) { m_dhcpIpRange = dhcpIpRange;
return *this; }
DHCP_IP_ADDRESS CDhcpIpRange::SetAddr ( DHCP_IP_ADDRESS dhcpIpAddress, BOOL bStart ) { DHCP_IP_ADDRESS dhcpIpAddressOld;
if ( bStart ) { dhcpIpAddressOld = m_dhcpIpRange.StartAddress; m_dhcpIpRange.StartAddress = dhcpIpAddress; } else { dhcpIpAddressOld = m_dhcpIpRange.EndAddress; m_dhcpIpRange.EndAddress = dhcpIpAddress; }
return dhcpIpAddressOld; }
BOOL CDhcpIpRange::IsOverlap ( DHCP_IP_RANGE dhcpIpRange ) { BOOL bOverlap = FALSE;
if (m_dhcpIpRange.StartAddress <= dhcpIpRange.StartAddress) { if (m_dhcpIpRange.StartAddress == dhcpIpRange.StartAddress) { bOverlap = TRUE; } else if (m_dhcpIpRange.EndAddress >= dhcpIpRange.StartAddress) { bOverlap = TRUE; } } else if (m_dhcpIpRange.StartAddress <= dhcpIpRange.EndAddress) { bOverlap = TRUE; }
return bOverlap; }
//
// Return TRUE if this range is an improper subset of the given range.
//
BOOL CDhcpIpRange::IsSubset ( DHCP_IP_RANGE dhcpIpRange ) { return (dhcpIpRange.StartAddress <= m_dhcpIpRange.StartAddress) && (dhcpIpRange.EndAddress >= m_dhcpIpRange.EndAddress); }
//
// Return TRUE if this range is an improper superset of the given range.
//
BOOL CDhcpIpRange::IsSuperset ( DHCP_IP_RANGE dhcpIpRange ) { return (dhcpIpRange.StartAddress >= m_dhcpIpRange.StartAddress) && (dhcpIpRange.EndAddress <= m_dhcpIpRange.EndAddress); }
void CDhcpIpRange::SetRangeType(UINT uRangeType) { m_RangeType = uRangeType; }
UINT CDhcpIpRange::GetRangeType() { return m_RangeType; }
/////////////////////////////////////////////////////////////////////
//
// CDhcpOptionValue implementation
//
/////////////////////////////////////////////////////////////////////
CDhcpOptionValue::CDhcpOptionValue ( DHCP_OPTION_DATA_TYPE dhcpOptionDataType, INT cUpperBound ) : m_dhcpOptionDataType( dhcpOptionDataType ), m_nUpperBound( -1 ), m_pdhcpOptionDataStruct(NULL) { m_dhcpOptionValue.pCObj = NULL;
LONG err = InitValue( dhcpOptionDataType, cUpperBound ); if ( err ) { ASSERT(FALSE); //ReportError( err );
} }
//
// Copy constructor.
//
CDhcpOptionValue::CDhcpOptionValue ( const CDhcpOptionValue & cOptionValue ) : m_dhcpOptionDataType( DhcpByteOption ), m_nUpperBound( -1 ), m_pdhcpOptionDataStruct(NULL) { DWORD err = 0; m_dhcpOptionValue.pCObj = NULL;
err = SetData(&cOptionValue); if ( err ) { ASSERT(FALSE); //ReportError( err );
} }
CDhcpOptionValue::CDhcpOptionValue ( const CDhcpOptionValue * pdhcpValue ) : m_dhcpOptionDataType( DhcpByteOption ), m_nUpperBound( -1 ), m_pdhcpOptionDataStruct(NULL) { LONG err = 0; m_dhcpOptionValue.pCObj = NULL;
ASSERT( pdhcpValue != NULL );
err = SetData(pdhcpValue); if (err) { ASSERT(FALSE); //ReportError( err );
} }
CDhcpOptionValue::CDhcpOptionValue ( const DHCP_OPTION & dhpType ) : m_dhcpOptionDataType( DhcpByteOption ), m_nUpperBound( -1 ), m_pdhcpOptionDataStruct(NULL) { LONG err = 0; m_dhcpOptionValue.pCObj = NULL;
err = SetData((const LPDHCP_OPTION_DATA) &dhpType.DefaultValue); if ( err ) { ASSERT(FALSE); //ReportError( err );
} }
CDhcpOptionValue::CDhcpOptionValue ( const DHCP_OPTION_VALUE & dhpOptionValue ) : m_dhcpOptionDataType( DhcpByteOption ), m_nUpperBound( -1 ), m_pdhcpOptionDataStruct(NULL) { LONG err = 0; m_dhcpOptionValue.pCObj = NULL;
err = SetData((const LPDHCP_OPTION_DATA) &dhpOptionValue.Value); if ( err ) { ASSERT(FALSE); //ReportError( err );
} }
CDhcpOptionValue::~ CDhcpOptionValue () { FreeValue();
if (m_pdhcpOptionDataStruct) FreeOptionDataStruct(); }
CDhcpOptionValue & CDhcpOptionValue::operator = ( const CDhcpOptionValue & dhpValue ) { SetData(&dhpValue);
return *this; }
BOOL CDhcpOptionValue::SetDataType ( DHCP_OPTION_DATA_TYPE dhcType, INT cUpperBound ) { if ( dhcType > DhcpEncapsulatedDataOption ) { return FALSE; }
InitValue( dhcType, cUpperBound );
return TRUE; }
void CDhcpOptionValue::SetUpperBound ( INT cNewBound ) { if (cNewBound <= 0) cNewBound = 1;
if (m_dhcpOptionDataType != DhcpBinaryDataOption && m_dhcpOptionDataType != DhcpEncapsulatedDataOption) { m_nUpperBound = cNewBound; }
switch ( m_dhcpOptionDataType ) { case DhcpByteOption: case DhcpWordOption: case DhcpDWordOption: case DhcpIpAddressOption: m_dhcpOptionValue.paDword->SetSize( cNewBound ); break;
case DhcpStringDataOption: m_dhcpOptionValue.paString->SetSize( cNewBound ); break;
case DhcpDWordDWordOption: m_dhcpOptionValue.paDwordDword->SetSize( cNewBound ); break;
case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: m_dhcpOptionValue.paBinary->SetSize( cNewBound ); break;
default: Trace0("CDhcpOptionValue: attempt to set upper bound on invalid value type"); ASSERT( FALSE ); break; }
}
BOOL CDhcpOptionValue::IsValid () const { return m_nUpperBound > 0; }
void CDhcpOptionValue::FreeValue () { //
// If there's not a value, return now.
//
if ( m_dhcpOptionValue.pCObj == NULL || m_nUpperBound < 0 ) { m_dhcpOptionValue.pCObj = NULL; return; }
switch ( m_dhcpOptionDataType ) { case DhcpByteOption: case DhcpWordOption: case DhcpDWordOption: case DhcpIpAddressOption: delete m_dhcpOptionValue.paDword; break;
case DhcpStringDataOption: delete m_dhcpOptionValue.paString; break;
case DhcpDWordDWordOption: delete m_dhcpOptionValue.paDwordDword; break;
case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: delete m_dhcpOptionValue.paBinary; break;
default: ASSERT( FALSE ); delete m_dhcpOptionValue.pCObj; break; }
m_nUpperBound = -1; m_dhcpOptionDataType = DhcpByteOption; m_dhcpOptionValue.pCObj = NULL; }
//
// Initialize the data value properly
//
LONG CDhcpOptionValue::InitValue ( DHCP_OPTION_DATA_TYPE dhcDataType, // The type of value
INT cUpperBound, // Maximum upper bound
BOOL bProvideDefaultValue // Should an empty default value be provided?
) { LONG err = 0;
//
// Release any older value.
//
FreeValue();
//
// Initialize the new value
//
m_dhcpOptionDataType = dhcDataType; m_nUpperBound = cUpperBound <= 0 ? 1 : cUpperBound;
CATCH_MEM_EXCEPTION { switch ( m_dhcpOptionDataType ) { case DhcpByteOption: case DhcpWordOption: case DhcpDWordOption: case DhcpIpAddressOption: m_dhcpOptionValue.paDword = new CDWordArray; if ( bProvideDefaultValue) { m_dhcpOptionValue.paDword->SetAtGrow( 0, 0 ); } break;
case DhcpStringDataOption: m_dhcpOptionValue.paString = new CStringArray; if ( bProvideDefaultValue ) { m_dhcpOptionValue.paString->SetAtGrow( 0, _T("") ); } break;
case DhcpDWordDWordOption: m_dhcpOptionValue.paDwordDword = new CDWordDWordArray; if ( bProvideDefaultValue ) { DWORD_DWORD dwdwValue; dwdwValue.DWord1 = 0; dwdwValue.DWord2 = 0; m_dhcpOptionValue.paDwordDword->SetAtGrow( 0, dwdwValue ); } break;
case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: m_dhcpOptionValue.paBinary = new CByteArray; if ( bProvideDefaultValue ) { m_dhcpOptionValue.paBinary->SetAtGrow( 0, 0 ); } break;
default: err = IDS_INVALID_OPTION_DATA; break; } } END_MEM_EXCEPTION(err)
return err; }
void CDhcpOptionValue::RemoveAll() {
// Remove all the entries for this option value
LONG err = 0; err = InitValue( QueryDataType(), QueryUpperBound(), TRUE );
ASSERT( err == 0 ); } // CDhcpOptionValue::RemoveAll()
LONG CDhcpOptionValue::SetData ( const DHCP_OPTION_DATA * podData ) { LONG err = 0;
if ( err = InitValue( podData->Elements[0].OptionType, podData->NumElements, FALSE ) ) { return err; }
CATCH_MEM_EXCEPTION { for ( INT i = 0; i < m_nUpperBound; i++ ) { const DHCP_OPTION_DATA_ELEMENT * pElem = &podData->Elements[i];
switch ( m_dhcpOptionDataType ) { case DhcpByteOption: m_dhcpOptionValue.paDword->SetAtGrow(i, pElem->Element.ByteOption ); break;
case DhcpWordOption: m_dhcpOptionValue.paDword->SetAtGrow(i, pElem->Element.WordOption ); break;
case DhcpDWordOption: m_dhcpOptionValue.paDword->SetAtGrow(i, pElem->Element.DWordOption ); break;
case DhcpIpAddressOption: m_dhcpOptionValue.paDword->Add(pElem->Element.IpAddressOption ); break;
case DhcpDWordDWordOption: { /*
CByteArray * paByte = m_dhcpOptionValue.paBinary;
paByte->SetSize( (sizeof (DWORD) / sizeof (BYTE)) * 2 );
DWORD dw = pElem->Element.DWordDWordOption.DWord1;
for ( INT j = 0; j < 4; j++ ) { paByte->SetAtGrow(j, (UCHAR)(dw & 0xff) ); dw >>= 8; } dw = pElem->Element.DWordDWordOption.DWord2;
for ( ; j < 8; j++ ) { paByte->SetAtGrow(j, (UCHAR)(dw & 0xff) ); dw >>= 8; } */
m_dhcpOptionValue.paDwordDword->SetAtGrow(i, pElem->Element.DWordDWordOption); } break;
case DhcpStringDataOption: { CString strTemp;
if ( pElem->Element.StringDataOption == NULL ) { strTemp = _T(""); } else { strTemp = pElem->Element.StringDataOption; } m_dhcpOptionValue.paString->SetAtGrow(i, strTemp); } break;
case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: { CByteArray * paByte = m_dhcpOptionValue.paBinary; INT c = pElem->Element.BinaryDataOption.DataLength; paByte->SetSize( c ); for ( INT j = 0; j < c; j++ ) { paByte->SetAtGrow(j, pElem->Element.BinaryDataOption.Data[j] ); } } break;
default: err = IDS_INVALID_OPTION_DATA; } // End switch
if ( err ) { break; } } // End for
} END_MEM_EXCEPTION(err)
return err; }
LONG CDhcpOptionValue::SetData ( const CDhcpOptionValue * pOptionValue ) { LONG err = 0;
if ( err = InitValue( pOptionValue->QueryDataType(), pOptionValue->QueryUpperBound(), FALSE ) ) { return err; }
CATCH_MEM_EXCEPTION { for ( INT i = 0; i < m_nUpperBound; i++ ) { switch ( m_dhcpOptionDataType ) { case DhcpByteOption: m_dhcpOptionValue.paDword->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paDword->GetAt(i)); break;
case DhcpWordOption: m_dhcpOptionValue.paDword->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paDword->GetAt(i)); break;
case DhcpDWordOption: m_dhcpOptionValue.paDword->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paDword->GetAt(i)); break;
case DhcpIpAddressOption: m_dhcpOptionValue.paDword->Add(pOptionValue->m_dhcpOptionValue.paDword->GetAt(i)); break;
case DhcpDWordDWordOption: { /*
CByteArray * paByte = m_dhcpOptionValue.paBinary;
paByte->SetSize( (sizeof (DWORD) / sizeof (BYTE)) * 2 ); for ( INT j = 0; j < 8; j++ ) { paByte->SetAtGrow(j, pOptionValue->m_dhcpOptionValue.paBinary->GetAt(j)); } */ m_dhcpOptionValue.paDwordDword->Add(pOptionValue->m_dhcpOptionValue.paDwordDword->GetAt(i)); } break;
case DhcpStringDataOption: { m_dhcpOptionValue.paString->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paString->GetAt(i)); } break;
case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: { CByteArray * paByte = m_dhcpOptionValue.paBinary; INT_PTR c = pOptionValue->m_dhcpOptionValue.paBinary->GetSize(); paByte->SetSize( c ); for ( INT_PTR j = 0; j < c; j++ ) { paByte->SetAtGrow(j, pOptionValue->m_dhcpOptionValue.paBinary->GetAt(j)); } } break;
default: err = IDS_INVALID_OPTION_DATA; } // End switch
if ( err ) { break; } } // End for
} END_MEM_EXCEPTION(err)
return err; }
INT CDhcpOptionValue::QueryBinary ( INT index ) const { if ( m_dhcpOptionValue.paBinary->GetUpperBound() < index ) { return -1; }
return m_dhcpOptionValue.paBinary->GetAt( index ); }
const CByteArray * CDhcpOptionValue::QueryBinaryArray () const { return m_dhcpOptionValue.paBinary; }
//
// Return a string representation of the current value.
//
// If fLineFeed is true, seperate each individual value
// by a linefeed. Otherwise, by a comma.
//
LONG CDhcpOptionValue::QueryDisplayString ( CString & strResult, BOOL fLineFeed ) const { CString strBuf; INT i, c;
LONG err = 0;
LPCTSTR pszDwordDwordMask = _T("0x%08lX%08lX"); LPCTSTR pszMaskDec = _T("%ld"); LPCTSTR pszMaskHex = _T("0x%x"); LPCTSTR pszMaskStr1 = _T("%s"); LPCTSTR pszMaskStr2 = _T("\"%s\""); LPCTSTR pszMaskBin = _T("%2.2x"); LPCTSTR pszMask; LPCTSTR pszMaskEllipsis = _T("..."); LPCTSTR pszSepComma = _T(", "); LPCTSTR pszSepLF = _T("\r\n");
CATCH_MEM_EXCEPTION { strResult.Empty(); for ( i = 0; i < m_nUpperBound; i++ ) { strBuf.Empty(); if ( i ) { strResult += fLineFeed ? pszSepLF : pszSepComma; } switch ( QueryDataType()) { case DhcpByteOption: case DhcpWordOption: case DhcpDWordOption: pszMask = pszMaskHex; strBuf.Format(pszMask, QueryNumber(i)); break; case DhcpStringDataOption: pszMask = m_nUpperBound > 1 ? pszMaskStr2 : pszMaskStr1; strBuf.Format( pszMask, m_dhcpOptionValue.paString->ElementAt( i )); break; case DhcpIpAddressOption: if (!QueryIpAddr(i)) { // Set the string to "<None>" iff the list is empty
if (!i) strResult.LoadString (IDS_INFO_FORMAT_IP_NONE); break; } ::UtilCvtIpAddrToWstr(QueryIpAddr(i), &strBuf); break; case DhcpDWordDWordOption: { DWORD_DWORD dwdwValue = QueryDwordDword(i); pszMask = pszDwordDwordMask; strBuf.Format(pszMask, dwdwValue.DWord1, dwdwValue.DWord2); } break; case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: for ( c = 0; c < m_dhcpOptionValue.paBinary->GetSize(); c++ ) { if (c) { strBuf += _T(" "); } DWORD dwValue = (BYTE) m_dhcpOptionValue.paBinary->GetAt( c ); CString strTemp; strTemp.Format(pszMaskBin, dwValue); strBuf += strTemp; } // for
break;
default: strResult.LoadString(IDS_INFO_TYPNAM_INVALID); break; } // switch
strResult += strBuf; } // for
} // CATCH....
END_MEM_EXCEPTION(err)
return err; }
//
// Return a string representation of the current value.
//
//
LONG CDhcpOptionValue::QueryRouteArrayDisplayString ( CString & strResult ) const { BOOL fLineFeed = FALSE; CString strBuf; INT i, c;
LONG err = 0;
LPCTSTR pszDwordDwordMask = _T("0x%08lX%08lX"); LPCTSTR pszMaskDec = _T("%ld"); LPCTSTR pszMaskHex = _T("0x%x"); LPCTSTR pszMaskStr1 = _T("%s"); LPCTSTR pszMaskStr2 = _T("\"%s\""); LPCTSTR pszMaskBin = _T("%2.2x"); LPCTSTR pszMask; LPCTSTR pszMaskEllipsis = _T("..."); LPCTSTR pszSepComma = _T(", "); LPCTSTR pszSepLF = _T("\r\n");
CATCH_MEM_EXCEPTION { strResult.Empty();
int bEmpty = TRUE; for ( i = 0; i < m_nUpperBound; i++ ) { if ( i ) { strResult += fLineFeed ? pszSepLF : pszSepComma; }
int nDataSize = (int)m_dhcpOptionValue.paBinary->GetSize(); LPBYTE pData = (LPBYTE) m_dhcpOptionValue.paBinary->GetData(); // convert pData to list of ip addresses as per RFC
while( nDataSize > sizeof(DWORD) ) { // first 1 byte contains the # of bits in subnetmask
nDataSize --; BYTE nBitsMask = *pData ++; DWORD Mask = (~0); if( nBitsMask < 32 ) Mask <<= (32-nBitsMask); // based on the # of bits, the next few bytes contain
// the subnet address for the 1-bits of subnet mask
int nBytesDest = (nBitsMask+7)/8; if( nBytesDest > 4 ) nBytesDest = 4; DWORD Dest = 0; memcpy( &Dest, pData, nBytesDest ); pData += nBytesDest; nDataSize -= nBytesDest; // subnet address is obviously in network order.
Dest = ntohl(Dest); // now the four bytes would be the router address
DWORD Router = 0; if( nDataSize < sizeof(DWORD) ) { Assert( FALSE ); break; } memcpy(&Router, pData, sizeof(DWORD)); Router = ntohl( Router ); pData += sizeof(DWORD); nDataSize -= sizeof(DWORD); // now fill the list box..
CString strDest, strMask, strRouter; ::UtilCvtIpAddrToWstr(Dest, &strDest); ::UtilCvtIpAddrToWstr(Mask, &strMask); ::UtilCvtIpAddrToWstr(Router, &strRouter);
strBuf += strDest; strBuf += fLineFeed ? pszSepLF : pszSepComma; strBuf += strMask; strBuf += fLineFeed ? pszSepLF : pszSepComma; strBuf += strRouter; bEmpty = FALSE;
strBuf += pszSepLF; } strResult += strBuf; }
if( bEmpty ) { strResult.LoadString( IDS_INFO_FORMAT_IP_NONE ); } } END_MEM_EXCEPTION(err)
return err; }
LONG CDhcpOptionValue::SetString ( LPCTSTR pszNewValue, INT index ) { if ( m_dhcpOptionDataType != DhcpStringDataOption ) { return ERROR_INVALID_PARAMETER; }
ASSERT( m_dhcpOptionValue.paString != NULL );
LONG err = 0;
CATCH_MEM_EXCEPTION { m_dhcpOptionValue.paString->SetAtGrow( index, pszNewValue ); } END_MEM_EXCEPTION(err)
return err; }
LONG CDhcpOptionValue::RemoveString ( INT index ) { if ( m_dhcpOptionDataType != DhcpStringDataOption ) { return ERROR_INVALID_PARAMETER; }
ASSERT( m_dhcpOptionValue.paString != NULL );
LONG err = 0;
CATCH_MEM_EXCEPTION { m_dhcpOptionValue.paString->RemoveAt( index ); } END_MEM_EXCEPTION(err)
return err; }
LONG CDhcpOptionValue::SetNumber ( INT nValue, INT index ) { if ( m_dhcpOptionDataType != DhcpByteOption && m_dhcpOptionDataType != DhcpWordOption && m_dhcpOptionDataType != DhcpDWordOption && m_dhcpOptionDataType != DhcpIpAddressOption && m_dhcpOptionDataType != DhcpBinaryDataOption && m_dhcpOptionDataType != DhcpEncapsulatedDataOption ) { return ERROR_INVALID_PARAMETER; }
ASSERT( m_dhcpOptionValue.paDword != NULL );
LONG err = 0;
CATCH_MEM_EXCEPTION { if ( m_dhcpOptionDataType != DhcpBinaryDataOption && m_dhcpOptionDataType != DhcpEncapsulatedDataOption) { m_dhcpOptionValue.paDword->SetAtGrow( index, (DWORD) nValue ); } else { m_dhcpOptionValue.paBinary->SetAtGrow( index, (BYTE) nValue ); } } END_MEM_EXCEPTION(err)
return err; }
LONG CDhcpOptionValue::RemoveNumber ( INT index ) { if ( m_dhcpOptionDataType != DhcpByteOption && m_dhcpOptionDataType != DhcpWordOption && m_dhcpOptionDataType != DhcpDWordOption && m_dhcpOptionDataType != DhcpIpAddressOption && m_dhcpOptionDataType != DhcpBinaryDataOption && m_dhcpOptionDataType != DhcpEncapsulatedDataOption ) { return ERROR_INVALID_PARAMETER; }
ASSERT( m_dhcpOptionValue.paDword != NULL );
LONG err = 0;
CATCH_MEM_EXCEPTION { if ( m_dhcpOptionDataType != DhcpBinaryDataOption && m_dhcpOptionDataType != DhcpEncapsulatedDataOption ) { m_dhcpOptionValue.paDword->RemoveAt( index ); } else { m_dhcpOptionValue.paBinary->RemoveAt( index ); } } END_MEM_EXCEPTION(err)
return err; }
LONG CDhcpOptionValue::QueryNumber ( INT index ) const { if ( m_dhcpOptionDataType != DhcpByteOption && m_dhcpOptionDataType != DhcpWordOption && m_dhcpOptionDataType != DhcpDWordOption && m_dhcpOptionDataType != DhcpIpAddressOption && m_dhcpOptionDataType != DhcpBinaryDataOption && m_dhcpOptionDataType != DhcpEncapsulatedDataOption ) { return -1; }
LONG cResult;
if ( m_dhcpOptionDataType == DhcpBinaryDataOption || m_dhcpOptionDataType == DhcpEncapsulatedDataOption ) { ASSERT( m_dhcpOptionValue.paBinary != NULL ); cResult = index < m_dhcpOptionValue.paBinary->GetSize() ? m_dhcpOptionValue.paBinary->GetAt( index ) : -1; } else { ASSERT( m_dhcpOptionValue.paDword != NULL ); cResult = index < m_dhcpOptionValue.paDword->GetSize() ? m_dhcpOptionValue.paDword->GetAt( index ) : -1; }
return cResult; }
LPCTSTR CDhcpOptionValue::QueryString ( INT index ) const { if ( m_dhcpOptionDataType != DhcpStringDataOption ) { return NULL; }
const CString & str = m_dhcpOptionValue.paString->ElementAt( index );
return str; }
DHCP_IP_ADDRESS CDhcpOptionValue::QueryIpAddr ( INT index ) const { return (DHCP_IP_ADDRESS) QueryNumber( index ); }
LONG CDhcpOptionValue::SetIpAddr ( DHCP_IP_ADDRESS dhcIpAddr, INT index ) { return SetNumber( (INT) dhcIpAddr, index ); }
LONG CDhcpOptionValue::RemoveIpAddr ( INT index ) { return RemoveNumber( index ); }
BOOL CDhcpOptionValue :: CreateBinaryData ( const DHCP_BINARY_DATA * podBin, DHCP_BINARY_DATA * pobData ) { //
// Note: CObject::operator new asserts if data length is zero
//
pobData->Data = new BYTE [ podBin->DataLength + 1 ] ; if ( pobData == NULL ) { return FALSE ; }
pobData->DataLength = podBin->DataLength ;
::memcpy( pobData->Data, podBin->Data, pobData->DataLength ) ;
return TRUE ; }
BOOL CDhcpOptionValue :: CreateBinaryData ( const CByteArray * paByte, DHCP_BINARY_DATA * pobData ) { //
// Note: CObject::operator new asserts if data length is zero
//
pobData->Data = new BYTE [ (UINT) (paByte->GetSize() + 1) ] ; if ( pobData == NULL ) { return NULL ; }
pobData->DataLength = (DWORD) paByte->GetSize() ;
for ( INT i = 0 ; i < paByte->GetSize() ; i++ ) { pobData->Data[i] = paByte->GetAt( i ) ; }
return TRUE ; }
DWORD_DWORD CDhcpOptionValue::QueryDwordDword ( int index ) const { return m_dhcpOptionValue.paDwordDword->ElementAt( index ); }
LONG CDhcpOptionValue::SetDwordDword ( DWORD_DWORD dwdwValue, int index ) { LONG err = 0;
CATCH_MEM_EXCEPTION { m_dhcpOptionValue.paDwordDword->SetAtGrow( index, dwdwValue ); } END_MEM_EXCEPTION(err)
return err; }
LONG CDhcpOptionValue::RemoveDwordDword ( int index ) { LONG err = 0;
CATCH_MEM_EXCEPTION { m_dhcpOptionValue.paDwordDword->RemoveAt( index ); } END_MEM_EXCEPTION(err)
return err; }
LONG CDhcpOptionValue::CreateOptionDataStruct ( // const CDhcpOptionValue * pdhcpOptionValue,
LPDHCP_OPTION_DATA * ppOptionData, BOOL bForceType ) { DHCP_OPTION_DATA * podNew = NULL ; DHCP_OPTION_DATA_ELEMENT * podeNew ; LONG err = 0 ;
FreeOptionDataStruct() ;
INT cElem = QueryUpperBound(); INT cElemMin = cElem ? cElem : 1; INT i, cBytes ;
TCHAR * pwcsz ;
if ( cElem < 0 || (cElem < 1 && ! bForceType) ) { //ASSERT( FALSE ) ;
return ERROR_INVALID_PARAMETER ; }
CATCH_MEM_EXCEPTION { //
// Allocate the base structure and the array of elements.
//
cBytes = sizeof *podNew + (cElemMin * sizeof *podeNew) ; podNew = (DHCP_OPTION_DATA *) new BYTE [ cBytes ] ; podeNew = (DHCP_OPTION_DATA_ELEMENT *) ( ((BYTE *) podNew) + sizeof *podNew ) ;
::ZeroMemory(podNew, cBytes);
podNew->NumElements = cElem; podNew->Elements = podeNew;
//
// Initialize each element. If we're forcing an option type def,
// just initialize to empty data.
//
if ( cElem == 0 && bForceType ) { podNew->NumElements = 1 ; podeNew[0].OptionType = QueryDataType() ;
switch ( podeNew[0].OptionType ) { case DhcpByteOption: case DhcpWordOption: case DhcpDWordOption: case DhcpIpAddressOption: case DhcpDWordDWordOption: podeNew[0].Element.DWordDWordOption.DWord1 = 0 ; podeNew[0].Element.DWordDWordOption.DWord2 = 0 ; break ;
case DhcpStringDataOption: podeNew[0].Element.StringDataOption = new WCHAR [1] ; podeNew[0].Element.StringDataOption[0] = 0 ; break ;
case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: podeNew[0].Element.BinaryDataOption.DataLength = 0 ; podeNew[0].Element.BinaryDataOption.Data = new BYTE [1] ; break ;
default: err = IDS_INVALID_OPTION_DATA ; } } else for ( i = 0 ; i < cElem ; i++ ) { podeNew[i].OptionType = QueryDataType() ;
switch ( podeNew[i].OptionType ) { case DhcpByteOption: podeNew[i].Element.ByteOption = (BYTE) QueryNumber( i ) ; break ;
case DhcpWordOption: podeNew[i].Element.WordOption = (WORD) QueryNumber( i ) ; break ;
case DhcpDWordOption: podeNew[i].Element.DWordOption = QueryNumber( i ) ; break ;
case DhcpDWordDWordOption: podeNew[i].Element.DWordDWordOption = QueryDwordDword( i ); break ;
case DhcpIpAddressOption: podeNew[i].Element.IpAddressOption = QueryIpAddr( i ) ; break ;
case DhcpStringDataOption: { //CString * pstrTemp = new CString (QueryString(i));
CString strTemp = QueryString(i); int nLength = strTemp.GetLength() + 1; TCHAR * pString = new TCHAR[nLength];
::ZeroMemory(pString, nLength * sizeof(TCHAR));
::CopyMemory(pString, strTemp, strTemp.GetLength() * sizeof(TCHAR));
podeNew[i].Element.StringDataOption = pString; break; }
case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: podNew->NumElements = 1;
if ( !CreateBinaryData(QueryBinaryArray(), &podeNew[i].Element.BinaryDataOption) ) { err = ERROR_NOT_ENOUGH_MEMORY ; break ; } break ;
default: err = IDS_INVALID_OPTION_DATA ; }
if ( err ) { break ; } } } END_MEM_EXCEPTION(err)
if ( err == 0 ) { m_pdhcpOptionDataStruct = podNew; *ppOptionData = podNew; }
return err ; }
LONG CDhcpOptionValue::FreeOptionDataStruct() { LONG err = 0;
if ( m_pdhcpOptionDataStruct == NULL ) { return 0 ; }
//
// We must deconstruct the struct build in CreateData()
//
INT cElem = m_pdhcpOptionDataStruct->NumElements ;
for ( INT i = 0 ; i < cElem ; i++ ) { switch ( m_pdhcpOptionDataStruct->Elements[i].OptionType ) { case DhcpByteOption: case DhcpWordOption: case DhcpDWordOption: case DhcpDWordDWordOption: case DhcpIpAddressOption: break;
case DhcpStringDataOption: delete m_pdhcpOptionDataStruct->Elements[i].Element.StringDataOption ; break ;
case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: delete m_pdhcpOptionDataStruct->Elements[i].Element.BinaryDataOption.Data ; break ;
default: err = IDS_INVALID_OPTION_DATA ; break; } if ( err ) { break ; } }
//
// Finally, delete the main structure
//
delete m_pdhcpOptionDataStruct ; m_pdhcpOptionDataStruct = NULL ;
return err ; }
/////////////////////////////////////////////////////////////////////
//
// CDhcpOption implementation
//
/////////////////////////////////////////////////////////////////////
//
// Normal constructor: just wrapper the data given
//
CDhcpOption::CDhcpOption ( const DHCP_OPTION & dhpOption ) : m_dhcpOptionValue( dhpOption ), m_dhcpOptionId( dhpOption.OptionID ), m_dhcpOptionType( dhpOption.OptionType ), m_bDirty(FALSE), m_dwErr(0) { LONG err = 0 ;
CATCH_MEM_EXCEPTION { if ( !(SetName(dhpOption.OptionName) && SetComment(dhpOption.OptionComment) ) ) { err = ERROR_NOT_ENOUGH_MEMORY ; } } END_MEM_EXCEPTION(err)
if ( err ) { ASSERT(FALSE); //ReportError( err ) ;
} }
//
// Constructor taking just a value structure. We must query
// the scope for the name, etc.
//
CDhcpOption::CDhcpOption ( const DHCP_OPTION_VALUE & dhcpOptionValue, LPCTSTR pszVendor, LPCTSTR pszUserClass ) : m_dhcpOptionValue( dhcpOptionValue ), m_dhcpOptionId( dhcpOptionValue.OptionID ), m_bDirty(FALSE), m_dwErr(0), m_strVendor(pszVendor), m_strClassName(pszUserClass) { }
//
// Copy constructor
//
CDhcpOption::CDhcpOption ( const CDhcpOption & dhcpOption ) : m_dhcpOptionId( dhcpOption.m_dhcpOptionId ), m_dhcpOptionType( dhcpOption.m_dhcpOptionType ), m_strName( dhcpOption.m_strName ), m_strComment( dhcpOption.m_strComment ), m_dhcpOptionValue( dhcpOption.QueryDataType() ), m_bDirty(FALSE), m_dwErr(0), m_strVendor( dhcpOption.m_strVendor ), m_strClassName ( dhcpOption.m_strClassName ) { m_dhcpOptionValue = dhcpOption.QueryValue(); }
//
// Constructor using a base type and an overriding value.
//
CDhcpOption::CDhcpOption ( const CDhcpOption & dhpType, const DHCP_OPTION_VALUE & dhcOptionValue ) : m_dhcpOptionId( dhpType.m_dhcpOptionId ), m_dhcpOptionType( dhpType.QueryOptType() ), m_strName( dhpType.m_strName ), m_strComment( dhpType.m_strComment ), m_dhcpOptionValue( dhcOptionValue ), m_bDirty(FALSE), m_dwErr(0), m_strVendor(dhpType.m_strVendor), m_strClassName(dhpType.m_strClassName) { }
//
// Constructor for dynamic instances
//
CDhcpOption::CDhcpOption ( DHCP_OPTION_ID nId, DHCP_OPTION_DATA_TYPE dhcType, LPCTSTR pszOptionName, LPCTSTR pszComment, DHCP_OPTION_TYPE dhcOptType ) : m_dhcpOptionId( nId ), m_dhcpOptionType( dhcOptType ), m_dhcpOptionValue( dhcType, TRUE ), m_strName( pszOptionName ), m_strComment( pszComment ), m_bDirty(FALSE), m_dwErr(0) { }
CDhcpOption::~ CDhcpOption () { }
INT CDhcpOption::MaxSizeOfType ( DHCP_OPTION_DATA_TYPE dhcType ) { INT nResult = -1 ;
switch ( dhcType ) { case DhcpByteOption: nResult = sizeof(CHAR) ; break ;
case DhcpWordOption: nResult = sizeof(WORD) ; break ;
case DhcpDWordOption: nResult = sizeof(DWORD) ; break ;
case DhcpIpAddressOption: nResult = sizeof(DHCP_IP_ADDRESS) ; break ;
case DhcpDWordDWordOption: nResult = sizeof(DWORD_DWORD); break ;
case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: case DhcpStringDataOption: nResult = STRING_LENGTH_MAX ; break ;
default: break; } return nResult ; }
void CDhcpOption::SetOptType ( DHCP_OPTION_TYPE dhcOptType ) { m_dhcpOptionType = dhcOptType; }
LONG CDhcpOption::Update ( const CDhcpOptionValue & dhpOptionValue ) { m_dhcpOptionValue = dhpOptionValue;
return 0; }
BOOL CDhcpOption::SetName ( LPCTSTR pszName ) { m_strName = pszName; return TRUE; }
BOOL CDhcpOption::SetComment ( LPCTSTR pszComment ) { m_strComment = pszComment; return TRUE; }
void CDhcpOption::QueryDisplayName ( CString & cStr ) const { cStr.Format(_T("%3.3d %s"), (int) QueryId(), (LPCTSTR) m_strName); }
/*---------------------------------------------------------------------------
Class COptionValueEnum Enumerates the options for a given level. Generates a list of nodes. Author: EricDav ---------------------------------------------------------------------------*/ COptionValueEnum::COptionValueEnum() { }
/*---------------------------------------------------------------------------
COptionValueEnum::Init() - Author: EricDav ---------------------------------------------------------------------------*/ DWORD COptionValueEnum::Init ( LPCTSTR pServer, LARGE_INTEGER & liVersion, DHCP_OPTION_SCOPE_INFO & dhcpOptionScopeInfo ) { m_strServer = pServer; m_liVersion.QuadPart = liVersion.QuadPart;
m_dhcpOptionScopeInfo = dhcpOptionScopeInfo;
return 0; }
/*---------------------------------------------------------------------------
COptionValueEnum::Copy() Copies another value enum Author: EricDav ---------------------------------------------------------------------------*/ void COptionValueEnum::Copy(COptionValueEnum * pEnum) { CDhcpOption * pOption = NULL;
pEnum->Reset(); while (pOption = pEnum->Next()) { AddTail(pOption); }
m_liVersion.QuadPart = pEnum->m_liVersion.QuadPart; m_dhcpOptionScopeInfo = pEnum->m_dhcpOptionScopeInfo; }
/*---------------------------------------------------------------------------
COptionValueEnum::Remove() removes an option from the list Author: EricDav ---------------------------------------------------------------------------*/ void COptionValueEnum::Remove(DHCP_OPTION_ID optionId, LPCTSTR pszVendor, LPCTSTR pszClass) { CDhcpOption * pOption = NULL;
Reset(); while (pOption = Next()) { if ( pOption->QueryId() == optionId && (lstrcmp(pOption->GetVendor(), pszVendor) == 0) && (lstrcmp(pOption->GetClassName(), pszClass) == 0) ) { COptionList::Remove(pOption); delete pOption; break; } } }
/*---------------------------------------------------------------------------
COptionValueEnum::Enum() Calls the appropriate enum function depending upon version Author: EricDav ---------------------------------------------------------------------------*/ DWORD COptionValueEnum::Enum() { DWORD dwErr;
RemoveAll();
if (m_liVersion.QuadPart >= DHCP_NT5_VERSION) { // enumerate standard plus the vendor and class ID based options
dwErr = EnumOptionsV5(); } else { // Enumerate the standard options
dwErr = EnumOptions(); }
// reset our position pointer to the head
Reset();
return dwErr; }
/*---------------------------------------------------------------------------
COptionValueEnum::EnumOptions() Description Author: EricDav ---------------------------------------------------------------------------*/ DWORD COptionValueEnum::EnumOptions() { LPDHCP_OPTION_VALUE_ARRAY pOptionValues = NULL; DWORD dwOptionsRead = 0, dwOptionsTotal = 0; DWORD err = ERROR_SUCCESS; HRESULT hr = hrOK; DHCP_RESUME_HANDLE dhcpResumeHandle = NULL;
err = ::DhcpEnumOptionValues((LPWSTR) ((LPCTSTR) m_strServer), &m_dhcpOptionScopeInfo, &dhcpResumeHandle, 0xFFFFFFFF, &pOptionValues, &dwOptionsRead, &dwOptionsTotal); Trace4("Server %s - DhcpEnumOptionValues returned %lx, read %d, Total %d.\n", m_strServer, err, dwOptionsRead, dwOptionsTotal); if (dwOptionsRead && dwOptionsTotal && pOptionValues) { for (DWORD i = 0; i < dwOptionsRead; i++) { //
// Filter out the "special" option values that we don't want the
// user to see.
//
// CODEWORK: don't filter vendor specifc options... all vendor
// specifc options are visible.
//
if (FilterOption(pOptionValues->Values[i].OptionID)) continue; //
// Create the result pane item for this element
//
CDhcpOption * pOption = new CDhcpOption(pOptionValues->Values[i], NULL, NULL);
AddTail(pOption); }
::DhcpRpcFreeMemory(pOptionValues); }
if (err == ERROR_NO_MORE_ITEMS) err = ERROR_SUCCESS;
return err; }
/*---------------------------------------------------------------------------
COptionValueEnum::EnumOptionsV5() Description Author: EricDav ---------------------------------------------------------------------------*/ DWORD COptionValueEnum::EnumOptionsV5() { LPDHCP_OPTION_VALUE_ARRAY pOptionValues = NULL; LPDHCP_ALL_OPTION_VALUES pAllOptions = NULL; DWORD dwNumOptions, err, i;
err = ::DhcpGetAllOptionValues((LPWSTR) ((LPCTSTR) m_strServer), 0, &m_dhcpOptionScopeInfo, &pAllOptions); Trace2("Server %s - DhcpGetAllOptionValues (Global) returned %lx\n", m_strServer, err);
if (err == ERROR_NO_MORE_ITEMS || err == ERROR_SUCCESS) { if (pAllOptions == NULL) { // This happens when stressing the server. Perhaps when server is OOM.
err = ERROR_OUTOFMEMORY; return err; }
// get the list of options (vendor and non-vendor) defined for
// the NULL class (no class)
for (i = 0; i < pAllOptions->NumElements; i++) { CreateOptions(pAllOptions->Options[i].OptionsArray, pAllOptions->Options[i].ClassName, pAllOptions->Options[i].VendorName); }
if (pAllOptions) ::DhcpRpcFreeMemory(pAllOptions); }
if (err == ERROR_NO_MORE_ITEMS) err = ERROR_SUCCESS;
return err; }
/*---------------------------------------------------------------------------
COptionValueEnum::CreateOptions() Description Author: EricDav ---------------------------------------------------------------------------*/ HRESULT COptionValueEnum::CreateOptions ( LPDHCP_OPTION_VALUE_ARRAY pOptionValues, LPCTSTR pClassName, LPCTSTR pszVendor ) { HRESULT hr = hrOK; SPITFSNode spNode; CDhcpOptionItem * pOptionItem; CString strDynBootpClassName;
if (pOptionValues == NULL) return hr;
Trace1("COptionValueEnum::CreateOptions - Creating %d options\n", pOptionValues->NumElements);
COM_PROTECT_TRY { for (DWORD i = 0; i < pOptionValues->NumElements; i++) { //
// Filter out the "special" option values that we don't want the
// user to see.
//
// don't filter vendor specifc options... all vendor
// specifc options are visible.
//
// also don't filter out class based options
// except for dynamic bootp class
if ( (FilterOption(pOptionValues->Values[i].OptionID) && pClassName == NULL && !pszVendor) || (FilterOption(pOptionValues->Values[i].OptionID) && (pClassName && m_strDynBootpClassName.CompareNoCase(pClassName) == 0) && !pszVendor) ) { continue; } //
// Create the option
//
CDhcpOption * pOption = new CDhcpOption(pOptionValues->Values[i], pszVendor, pClassName);
AddTail(pOption); } } COM_PROTECT_CATCH
return hr; }
/////////////////////////////////////////////////////////////////////
//
// CDhcpDefaultOptionsOnServer implementation
//
/////////////////////////////////////////////////////////////////////
LPCTSTR pszResourceName = _T("DHCPOPT") ; LPCTSTR pszResourceType = _T("TEXT") ; const int cchFieldMax = 500 ;
OPT_TOKEN aOptToken [] = { { DhcpIpAddressOption, _T("IP Addr") }, { DhcpIpAddressOption, _T("IPAddr") }, { DhcpIpAddressOption, _T("IP Address") }, { DhcpIpAddressOption, _T("IP Pairs") }, { DhcpByteOption, _T("byte") }, { DhcpByteOption, _T("boolean") }, { DhcpByteOption, _T("octet") }, { DhcpWordOption, _T("short") }, { DhcpDWordOption, _T("long") }, { DhcpDWordDWordOption, _T("double") }, { DhcpStringDataOption, _T("string") }, { DhcpBinaryDataOption, _T("binary") }, { DhcpEncapsulatedDataOption, _T("encapsulated") }, { -1, _T("generated") }, { -1, NULL } };
CDhcpDefaultOptionsOnServer::CDhcpDefaultOptionsOnServer() { m_pos = NULL; }
CDhcpDefaultOptionsOnServer::~CDhcpDefaultOptionsOnServer() { RemoveAll(); }
LONG CDhcpDefaultOptionsOnServer::RemoveAll() { //
// Clean the list of all old entries
//
while (!m_listOptions.IsEmpty()) { delete m_listOptions.RemoveHead(); }
return 0; }
CDhcpOption * CDhcpDefaultOptionsOnServer::First() { Reset(); return Next(); }
CDhcpOption * CDhcpDefaultOptionsOnServer::Next() { return m_pos == NULL ? NULL : m_listOptions.GetNext( m_pos ) ; }
void CDhcpDefaultOptionsOnServer::Reset() { m_pos = m_listOptions.GetCount() ? m_listOptions.GetHeadPosition() : NULL ; }
CDhcpOption * CDhcpDefaultOptionsOnServer::Find ( DHCP_OPTION_ID dhcpOptionId, LPCTSTR pszVendor ) { POSITION pos = m_listOptions.GetHeadPosition(); CDhcpOption* pCurrent; CDhcpOption* pFound = NULL; CString strVendor = pszVendor;
while (pos != NULL) { pCurrent = m_listOptions.GetNext(pos);
// check the options IDs and the vendor classes match
if ( (pCurrent->QueryId() == dhcpOptionId) && ( (!pszVendor && !pCurrent->GetVendor()) || (pCurrent->GetVendor() && (strVendor.CompareNoCase(pCurrent->GetVendor()) == 0) ) ) ) { pFound = pCurrent; break; } }
return pFound; }
// Sorts the options by ID
LONG CDhcpDefaultOptionsOnServer::SortById() { return m_listOptions.SortById(); }
LONG CDhcpDefaultOptionsOnServer::Enumerate ( LPCWSTR pServer, LARGE_INTEGER liVersion ) { if (liVersion.QuadPart >= DHCP_NT5_VERSION) { return EnumerateV5(pServer); } else { return EnumerateV4(pServer); } }
LONG CDhcpDefaultOptionsOnServer::EnumerateV4 ( LPCWSTR pServer ) { //
// Use new API to get the param types
//
LPDHCP_OPTION_ARRAY pOptionsArray = NULL; DHCP_RESUME_HANDLE dhcpResumeHandle = NULL; LPDHCP_OPTION Options, pCurOption; DWORD i; DWORD dwNumOptions; DWORD dwOptionsRead; LONG err;
err = ::DhcpEnumOptions(pServer, &dhcpResumeHandle, 0xFFFFFFFF, // get all.
&pOptionsArray, &dwOptionsRead, &m_dwOptionsTotal ); if ( err ) { return err; }
//
// Discard all the old data
//
RemoveAll() ;
if (pOptionsArray == NULL) { // This happens when stressing the server. Perhaps when server is OOM.
return ERROR_OUTOFMEMORY; }
try { Options = pOptionsArray->Options; dwNumOptions = pOptionsArray->NumElements; if ((dwNumOptions > 0) && (Options == NULL)) { ASSERT(FALSE && _T("Data Inconsistency")); return ERROR_OUTOFMEMORY; // Just in case
}
for(i = 0; i < dwNumOptions; i++) { //
// Create the new type object.
//
pCurOption = Options + i; CDhcpOption * pdhcpOption = new CDhcpOption(*pCurOption);
//
// Add the new host to the list.
//
m_listOptions.AddTail(pdhcpOption); } } catch (...) { err = ERROR_NOT_ENOUGH_MEMORY; }
::DhcpRpcFreeMemory(pOptionsArray); pOptionsArray = NULL;
Reset();
return err; }
LONG CDhcpDefaultOptionsOnServer::EnumerateV5 ( LPCWSTR pServer ) { //
// Use new API to get the param types
//
LPDHCP_OPTION Options, pCurOption; DWORD i; DWORD dwNumOptions = 0; DWORD dwOptionsRead = 0; DWORD dwFlags = 0; LONG err = 0; LPDHCP_ALL_OPTIONS pAllOptions = NULL;
err = ::DhcpGetAllOptions((LPWSTR) pServer, dwFlags, &pAllOptions);
if ( err ) { if ( NULL != pAllOptions ) { ::DhcpRpcFreeMemory( pAllOptions ); } return err; }
//
// Discard all the old data
//
RemoveAll() ;
if (pAllOptions == NULL) { // This happens when stressing the server. Perhaps when server is OOM.
return ERROR_OUTOFMEMORY; }
try { // first pull out the non-vendor options
if (pAllOptions->NonVendorOptions != NULL) { Options = pAllOptions->NonVendorOptions->Options; dwNumOptions = pAllOptions->NonVendorOptions->NumElements; } if ((dwNumOptions > 0) && (Options == NULL)) { ASSERT(FALSE && _T("Data Inconsistency")); ::DhcpRpcFreeMemory( pAllOptions ); return ERROR_OUTOFMEMORY; // Just in case
}
for (i = 0; i < dwNumOptions; i++) { //
// Create the new type object.
//
pCurOption = Options + i; CDhcpOption * pdhcpOption = new CDhcpOption(*pCurOption);
//
// Add the new host to the list.
//
m_listOptions.AddTail(pdhcpOption); }
// now the vendor options
for (i = 0; i < pAllOptions->NumVendorOptions; i++) { pCurOption = &pAllOptions->VendorOptions[i].Option;
CDhcpOption * pdhcpOption = new CDhcpOption(*pCurOption);
pdhcpOption->SetVendor(pAllOptions->VendorOptions[i].VendorName);
//
// Add the new host to the list.
//
m_listOptions.AddTail(pdhcpOption); } } catch (...) { err = ERROR_NOT_ENOUGH_MEMORY; }
if (pAllOptions) ::DhcpRpcFreeMemory(pAllOptions);
SortById(); Reset();
return err; }
/////////////////////////////////////////////////////////////////////
//
// CDhcpDefaultOptionsMasterList implementation
//
/////////////////////////////////////////////////////////////////////
CDhcpDefaultOptionsMasterList::CDhcpDefaultOptionsMasterList() { m_pos = NULL; }
CDhcpDefaultOptionsMasterList::~CDhcpDefaultOptionsMasterList() { //
// Delete all entries in the list
//
while (!m_listOptions.IsEmpty()) { delete m_listOptions.RemoveHead(); } }
CDhcpOption * CDhcpDefaultOptionsMasterList::First() { Reset(); return Next(); }
CDhcpOption * CDhcpDefaultOptionsMasterList::Next() { return m_pos == NULL ? NULL : m_listOptions.GetNext( m_pos ) ; }
void CDhcpDefaultOptionsMasterList::Reset() { m_pos = m_listOptions.GetCount() ? m_listOptions.GetHeadPosition() : NULL ; }
int CDhcpDefaultOptionsMasterList::GetCount() { return (int)m_listOptions.GetCount(); }
long CDhcpDefaultOptionsMasterList::BuildList() { AFX_MANAGE_STATE(AfxGetStaticModuleState());
LONG err = 0 ; CDhcpOption * pOption; HRSRC hRes = NULL ; HGLOBAL hText = NULL ; LPTSTR pszText = NULL ; LPCTSTR pcszText ; size_t cchText = 0; UINT uBufSize = 0; LPTSTR * szParms; TCHAR szUnknown[] = _T("(Unknown)"); // This is just to prevent a GP fault (should not be in resource)
CATCH_MEM_EXCEPTION { do { //
// IMPORTANT!!! There is no way to determine from the .mc file how many
// options are defined. This number is therefore hard-coded
// here, and should reflect the highest parameter number in
// the .mc file.
//
// The extra 16 entries are for safety
// when calling FormatMessage().
szParms = new LPTSTR[IDS_OPTION_MAX + 16];
Trace0("BuildList - Now building list of option parameters\n");
CString strOptionText;
// Initialize the extra entries to something that will not GP fault.
for (int i = 0; i < 16; i++) { szParms[IDS_OPTION_MAX+i] = szUnknown; }
//
// Don't mess with the order of the ID definitions!!!
//
for (i = 0; i < IDS_OPTION_MAX; ++i) { if (strOptionText.LoadString(IDS_OPTION1 + i)) { ASSERT(strOptionText.GetLength() > 0);
uBufSize += strOptionText.GetLength(); szParms[i] = new TCHAR[strOptionText.GetLength()+1];
::_tcscpy(szParms[i], (LPCTSTR)strOptionText); } else { //
// Failed to load the string from the resource
// for some reason.
//
CString strTemp; strTemp.LoadString(IDS_OPTION1 + i); Trace1("BuildList - WARNING: Failed to load option text %s\n", strTemp); err = ::GetLastError(); szParms[i] = szUnknown; // Prevent from GP faulting
break; } }
if (err != ERROR_SUCCESS) { break; }
// allocate a buffer big enough to hold the data
uBufSize *= sizeof(TCHAR); uBufSize *= 2;
pszText = (LPTSTR) malloc(uBufSize); if (pszText == NULL) { err = ERROR_OUTOFMEMORY; break; }
//
// Since we are a COM object, get our instance handle to use so that FormatMessage
// looks in the right place for our resources.
//
HINSTANCE hInst = _Module.GetModuleInstance();
while (cchText == 0) { cchText = ::FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, (HMODULE) hInst, // hModule
DHCP_OPTIONS, // dwMessageId loaded from a system dll
0L, // dwLanguageId
OUT (LPTSTR)pszText, uBufSize/sizeof(TCHAR), (va_list *)szParms);
if (cchText == 0) { err = ::GetLastError(); Trace1("BuildList - FormatMessage failed - error %d\n", err);
// grow the buffer and try again
uBufSize += uBufSize/2; LPTSTR pTemp = (LPTSTR) realloc(pszText, uBufSize); if ( NULL == pTemp ) { err = ERROR_OUTOFMEMORY; break; } else { pszText = pTemp; } } else { // done
break; } }
//
// Walk the resource, parsing each line. If the line converts
// to a tangible type, add it to the list.
//
for ( pcszText = pszText ; pcszText ; ) { scanNextParamType( &pcszText, &pOption);
if ( pOption ) { m_listOptions.AddTail(pOption) ; } }
} while ( FALSE ) ; } END_MEM_EXCEPTION( err )
for (int i = 0; i < IDS_OPTION_MAX; ++i) { if (szParms[i] != szUnknown) delete[] szParms[i]; }
delete[] szParms; free(pszText);
Reset();
return NOERROR; }
BOOL CDhcpDefaultOptionsMasterList::scanNextParamType ( LPCTSTR * ppszText, CDhcpOption * * ppOption ) { TCHAR szField [ cchFieldMax ] ; TCHAR szName [ cchFieldMax ] ; TCHAR szComment [ cchFieldMax ] ; BOOL bResult = TRUE ; BOOL bArray = FALSE ; int eofld, cch, itype, cbLgt ; LPCTSTR pszText = *ppszText ; CDhcpOption * pOption = NULL ; const DWORD INVALID_OPTION_ID = 0xFFFF; DHCP_OPTION_ID did = INVALID_OPTION_ID; DHCP_OPTION_DATA_TYPE dtype = (DHCP_OPTION_DATA_TYPE)0;
for ( eofld = OPTF_OPTION ; pszText = scanNextField( pszText, szField, sizeof szField ) ; eofld++ ) { cch = ::_tcslen( szField ) ;
switch ( eofld ) { case OPTF_OPTION: if ( cch > 0 && allDigits( szField ) ) { did = (DHCP_OPTION_ID) ::_ttoi( szField ) ; } else { bResult = FALSE; } break ;
case OPTF_NAME: if ( ::_tcslen( szField ) == 0 ) { bResult = FALSE; break ; } ::_tcscpy( szName, szField ) ; break ;
case OPTF_TYPE: if ( (itype = recognizeToken( aOptToken, szField )) < 0 ) { Trace2("options CSV ID %d, cannot reconize type %s\n", did, szField); bResult = FALSE ; break ; } dtype = (DHCP_OPTION_DATA_TYPE) itype ; break ;
case OPTF_ARRAY_FLAG: bArray = szField[0] == 'y' || szField[0] == 'Y' ; break ;
case OPTF_LENGTH: cbLgt = ::_ttoi( szField ) ; break ; case OPTF_DESCRIPTION: ::_tcscpy( szComment, szField ) ; break ;
case OPTF_REMARK: case OPTF_MAX: break ; }
if ( eofld == OPTF_REMARK || ! bResult ) { pszText = skipToNextLine( pszText ) ; if ( *pszText == 0 ) { pszText = NULL ; } break; } }
if (( bResult ) && ( INVALID_OPTION_ID != did )) { pOption = new CDhcpOption( did, dtype, szName, szComment, bArray ? DhcpArrayTypeOption : DhcpUnaryElementTypeOption ) ; }
if ( bResult ) { *ppOption = pOption ; } else { delete pOption ; *ppOption = NULL ; }
*ppszText = pszText ; return pszText != NULL ; }
LPCTSTR CDhcpDefaultOptionsMasterList::scanNextField ( LPCTSTR pszLine, LPTSTR pszOut, int cFieldSize ) { //
// Skip junk; return NULL if end-of-buffer.
//
if ( ! skipWs( & pszLine ) ) { return NULL ; }
int cch = 0 ; BOOL bDone = FALSE ; LPTSTR pszField = pszOut ; TCHAR ch ;
if ( *pszLine == '\"' ) { //
// Quoted string.
//
while ( ch = *++pszLine ) { if ( ch == '\r' ) { continue ; } if ( ch == '\n' || ch == '\"' || cch == cFieldSize ) { break ; } *pszField++ = ch ; cch++ ; } if ( ch == '\"' ) { pszLine++ ; } } else while ( ! bDone ) { ch = *pszLine++ ;
ASSERT( ch != 0 ) ;
switch ( ch ) { case '\n': pszLine-- ; // Don't scan past the NL
case ',': case '\r': bDone = TRUE ; break ; default: if ( cch < cFieldSize ) { *pszField++ = ch ; cch++ ; } break ; } }
//
// Trim spaces off the end of the field.
//
while ( pszField > pszOut && *(pszField-1) == ' ' ) { pszField-- ; } *pszField = 0 ; return pszLine ; }
BOOL CDhcpDefaultOptionsMasterList::allDigits ( LPCTSTR psz ) { for ( ; *psz ; psz++ ) { if ( ! isdigit( *psz ) ) { return FALSE ; } }
return TRUE ; }
int CDhcpDefaultOptionsMasterList::recognizeToken ( OPT_TOKEN * apToken, LPCTSTR pszToken ) { int i ; for ( i = 0 ; apToken[i].pszOptTypeName && ::lstrcmpi( apToken[i].pszOptTypeName, pszToken ) != 0 ; i++ ) ;
return apToken[i].eOptType ; }
LPCTSTR CDhcpDefaultOptionsMasterList::skipToNextLine ( LPCTSTR pszLine ) { for ( ; *pszLine && *pszLine != '\n' ; pszLine++ ) ; if ( *pszLine ) { pszLine++ ; // Don't overscan buffer delimiter.
} return pszLine ; }
BOOL CDhcpDefaultOptionsMasterList::skipWs ( LPCTSTR * ppszLine ) { LPCTSTR pszLine ; BOOL bResult = FALSE ;
for ( pszLine = *ppszLine ; *pszLine ; pszLine++ ) { switch ( *pszLine ) { case ' ': case '\r': case '\t': break ; default: bResult = TRUE ; break ; } if ( bResult ) { break ; } }
*ppszLine = pszLine ; return *pszLine != 0 ; }
|