windows-nt/Source/XPSP1/NT/net/mmc/dhcp/optcfg.cpp
2020-09-26 16:20:57 +08:00

2761 lines
81 KiB
C++

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
/**********************************************************************/
/*
optcfg.cpp
Individual option property page
FILE HISTORY:
*/
#include "stdafx.h"
#include "optcfg.h"
#include "listview.h"
#include "server.h"
#include "nodes.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define MAX_COLUMNS 2
UINT COLUMN_HEADERS[MAX_COLUMNS] =
{
IDS_OPTCFG_NAME,
// IDS_OPTCFG_TYPE,
IDS_OPTCFG_COMMENT
};
int COLUMN_WIDTHS[MAX_COLUMNS] =
{
// 120, 55, 150
150, 175
};
const DWORD * OPTION_CONTROL_HELP_ARRAYS[] =
{
g_aHelpIDs_IDD_DATA_ENTRY_DWORD,
g_aHelpIDs_IDD_DATA_ENTRY_IPADDRESS,
g_aHelpIDs_IDD_DATA_ENTRY_IPADDRESS_ARRAY,
g_aHelpIDs_IDD_DATA_ENTRY_BINARY,
g_aHelpIDs_IDD_DATA_ENTRY_BINARY_ARRAY,
g_aHelpIDs_IDD_DATA_ENTRY_STRING,
g_aHelpIDs_IDD_DATA_ENTRY_ROUTE_ARRAY
};
// class CHelpMap
CHelpMap::CHelpMap()
{
m_pdwHelpMap = NULL;
}
CHelpMap::~CHelpMap()
{
ResetMap();
}
void
CHelpMap::BuildMap(DWORD pdwParentHelpMap[])
{
int i, j, nPos;
int nSize = 0;
int nCurSize;
ResetMap();
// calculate the size of the map
// subtract off the terminators
nSize += CountMap(pdwParentHelpMap);
for (i = 0; i < ARRAYLEN(OPTION_CONTROL_HELP_ARRAYS); i++)
{
nSize += CountMap(OPTION_CONTROL_HELP_ARRAYS[i]);
}
nSize += 2; // for terminator
m_pdwHelpMap = new DWORD[nSize];
memset(m_pdwHelpMap, 0, sizeof(*m_pdwHelpMap));
// fill in the parent help map
nPos = 0;
nCurSize = CountMap(pdwParentHelpMap);
for (i = 0; i < nCurSize; i++)
{
m_pdwHelpMap[nPos++] = pdwParentHelpMap[i++];
m_pdwHelpMap[nPos++] = pdwParentHelpMap[i];
}
// now add all of the possible option control help maps
for (i = 0; i < ARRAYLEN(OPTION_CONTROL_HELP_ARRAYS); i++)
{
nCurSize = CountMap(OPTION_CONTROL_HELP_ARRAYS[i]);
for (j = 0; j < nCurSize; j++)
{
m_pdwHelpMap[nPos++] = (OPTION_CONTROL_HELP_ARRAYS[i])[j++];
m_pdwHelpMap[nPos++] = (OPTION_CONTROL_HELP_ARRAYS[i])[j];
}
}
}
DWORD * CHelpMap::GetMap()
{
return m_pdwHelpMap;
}
int CHelpMap::CountMap(const DWORD * pdwHelpMap)
{
int i = 0;
while (pdwHelpMap[i] != 0)
{
i++;
}
return i++;
}
void CHelpMap::ResetMap()
{
if (m_pdwHelpMap)
{
delete m_pdwHelpMap;
m_pdwHelpMap = NULL;
}
}
DEBUG_DECLARE_INSTANCE_COUNTER(COptionsConfig);
/////////////////////////////////////////////////////////////////////////////
//
// COptionsConfig holder
//
/////////////////////////////////////////////////////////////////////////////
COptionsConfig::COptionsConfig
(
ITFSNode * pNode,
ITFSNode * pServerNode,
IComponentData * pComponentData,
ITFSComponentData * pTFSCompData,
COptionValueEnum * pOptionValueEnum,
LPCTSTR pszSheetName,
CDhcpOptionItem * pSelOption
) : CPropertyPageHolderBase(pNode, pComponentData, pszSheetName)
{
DEBUG_INCREMENT_INSTANCE_COUNTER(COptionsConfig);
//ASSERT(pFolderNode == GetContainerNode());
m_bAutoDeletePages = FALSE; // we have the pages as embedded members
AddPageToList((CPropertyPageBase*) &m_pageGeneral);
LARGE_INTEGER liServerVersion;
CDhcpServer * pServer = GETHANDLER(CDhcpServer, pServerNode);
pServer->GetVersion(m_liServerVersion);
if (m_liServerVersion.QuadPart >= DHCP_NT5_VERSION)
{
AddPageToList((CPropertyPageBase*) &m_pageAdvanced);
}
Assert(pTFSCompData != NULL);
m_spTFSCompData.Set(pTFSCompData);
m_spServerNode.Set(pServerNode);
// get all of the active options for this node
SPITFSNode spNode;
spNode = GetNode();
m_bInitialized = FALSE;
m_pOptionValueEnum = pOptionValueEnum;
if (pSelOption)
{
m_strStartVendor = pSelOption->GetVendor();
m_strStartClass = pSelOption->GetClassName();
m_dhcpStartId = pSelOption->GetOptionId();
}
else
{
m_dhcpStartId = 0xffffffff;
}
}
COptionsConfig::~COptionsConfig()
{
DEBUG_DECREMENT_INSTANCE_COUNTER(COptionsConfig);
RemovePageFromList((CPropertyPageBase*) &m_pageGeneral, FALSE);
RemovePageFromList((CPropertyPageBase*) &m_pageAdvanced, FALSE);
}
DWORD
COptionsConfig::InitData()
{
DWORD dwErr = NO_ERROR;
if (m_bInitialized)
return dwErr;
CDhcpServer * pServer = GETHANDLER(CDhcpServer, m_spServerNode);
CClassInfoArray ClassInfoArray;
pServer->GetClassInfoArray(ClassInfoArray);
// create a standard DHCP options vendor tracker and a set of default class options
CVendorTracker * pVendorTracker = AddVendorTracker(_T(""));
AddClassTracker(pVendorTracker, _T(""));
// walk the list of classes. For each vendor class, add a default user class.
for (int i = 0; i < ClassInfoArray.GetSize(); i++)
{
if (ClassInfoArray[i].bIsVendor)
{
// create a vendor tracker and a set of default class options
pVendorTracker = AddVendorTracker(ClassInfoArray[i].strName);
AddClassTracker(pVendorTracker, _T(""));
}
}
// now walk the list of vendor classes and add User class option lists
POSITION pos = m_listVendorClasses.GetHeadPosition();
while (pos)
{
pVendorTracker = m_listVendorClasses.GetNext(pos);
// now build option sets for each user class in each vendor
for (int j = 0; j < ClassInfoArray.GetSize(); j++)
{
if (!ClassInfoArray[j].bIsVendor)
AddClassTracker(pVendorTracker, ClassInfoArray[j].strName);
}
}
// now we need to update any active options with their current values
UpdateActiveOptions();
m_bInitialized = TRUE;
return dwErr;
}
void
COptionsConfig::SetTitle()
{
HWND hSheet = GetSheetWindow();
::SetWindowText(hSheet, m_stSheetTitle);
}
LPWSTR COptionsConfig::GetServerAddress()
{
CDhcpServer * pServer = GETHANDLER(CDhcpServer, m_spServerNode);
return (LPWSTR) pServer->GetIpAddress();
}
CVendorTracker *
COptionsConfig::AddVendorTracker(LPCTSTR pClassName)
{
CVendorTracker * pVendorTracker = new CVendorTracker();
pVendorTracker->SetClassName(pClassName);
m_listVendorClasses.AddTail(pVendorTracker);
return pVendorTracker;
}
void COptionsConfig::AddClassTracker(CVendorTracker * pVendorTracker, LPCTSTR pClassName)
{
SPITFSNode spServerNode;
spServerNode = GetServerNode();
CDhcpServer * pServer = GETHANDLER(CDhcpServer, spServerNode);
CClassTracker * pClassTracker = new CClassTracker();
pClassTracker->SetClassName(pClassName);
// add the new class tracker to the list.
pVendorTracker->m_listUserClasses.AddTail(pClassTracker);
// Get a pointer to the list of options on the server. We use this
// to build our list of available options for this class
CDhcpOption * pCurOption;
CDhcpDefaultOptionsOnServer * pDefOptions = pServer->GetDefaultOptionsList();
CString strVendor = pVendorTracker->GetClassName();
CString strUserClass = pClassName;
pCurOption = pDefOptions->First();
while (pCurOption)
{
DHCP_OPTION_ID id = pCurOption->QueryId();
// we filter out some options:
// 1 - standard options with no user class call FilterOption
// 2 - standard options with a user class call FilterUserClassOptions
if ( (strVendor.IsEmpty() && !FilterOption(id) && !pCurOption->IsVendor()) ||
(strVendor.IsEmpty() && !pCurOption->IsVendor() && !strUserClass.IsEmpty() && !FilterUserClassOption(id)) ||
(pCurOption->GetVendor() && strVendor.Compare(pCurOption->GetVendor()) == 0) )
{
// create an option item for this entry. We do this because
// these options are stored in the server node, but since this is a modeless
// dialog the values could change, so we'll take a snapshot of the data
// we can just use the copy constructor of the CDhcpOption
COptionTracker * pOptionTracker = new COptionTracker;
CDhcpOption * pNewOption = new CDhcpOption(*pCurOption);
pOptionTracker->m_pOption = pNewOption;
// add the option to the class tracker
pClassTracker->m_listOptions.AddTail(pOptionTracker);
}
pCurOption = pDefOptions->Next();
}
}
void COptionsConfig::UpdateActiveOptions()
{
// Now the known options are in the correct locations. We need to see
// what options are enabled for this node. We querried the server to make
// sure we have the latest information about active options.
m_pOptionValueEnum->Reset();
CDhcpOption * pOption;
while (pOption = m_pOptionValueEnum->Next())
{
DHCP_OPTION_ID optionId = pOption->QueryId();
// search all vendors options
POSITION pos = m_listVendorClasses.GetHeadPosition();
while (pos)
{
// search all vendor classes
CVendorTracker * pVendorTracker = m_listVendorClasses.GetNext(pos);
CString strVendor = pOption->GetVendor();
if (pVendorTracker->m_strClassName.Compare(strVendor) == 0)
{
// ok, the vendor class matches so lets check user classes
POSITION pos2 = pVendorTracker->m_listUserClasses.GetHeadPosition();
while (pos2)
{
CClassTracker * pClassTracker = pVendorTracker->m_listUserClasses.GetNext(pos2);
// check to see if this option belongs to this class
if ( (pClassTracker->m_strClassName.IsEmpty()) &&
(!pOption->IsClassOption()) )
{
// both are empty... match.
}
else
if ( ( pClassTracker->m_strClassName.IsEmpty() && pOption->IsClassOption() ) ||
( !pClassTracker->m_strClassName.IsEmpty() && !pOption->IsClassOption() ) )
{
// either the current option or the current class is null...
continue;
}
else
if (pClassTracker->m_strClassName.CompareNoCase(pOption->GetClassName()) != 0)
{
// both names are non-null and they don't match... keep looking
continue;
}
// Ok, the class the option belong to is the same as the one we are currently
// looking at. Loop through the default options for this class and update it's
// state and value.
POSITION posOption = pClassTracker->m_listOptions.GetHeadPosition();
while (posOption)
{
COptionTracker * pCurOptTracker = pClassTracker->m_listOptions.GetNext(posOption);
CDhcpOption * pCurOption = pCurOptTracker->m_pOption;
if ( (pCurOption->QueryId() == pOption->QueryId()) &&
( (pCurOption->IsVendor() && pOption->IsVendor()) ||
(!pCurOption->IsVendor() && !pOption->IsVendor()) ) )
{
// update this option
CDhcpOptionValue OptValue = pOption->QueryValue();
pCurOption->Update(OptValue);
pCurOptTracker->SetInitialState(OPTION_STATE_ACTIVE);
pCurOptTracker->SetCurrentState(OPTION_STATE_ACTIVE);
break;
}
} // while option list
} // while User class list
} // endif vendor class name compre
} // while list of vendor classes
}
}
void COptionsConfig::FillOptions(LPCTSTR pVendorName, LPCTSTR pUserClassName, CMyListCtrl & ListCtrl)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// look for the requested class and fill in the listbox
// with all options for that class
CString strVendorStandard, strClassStandard, strTargetVendor, strTargetClass;
CString strTypeVendor, strTypeStandard;
strVendorStandard.LoadString(IDS_INFO_NAME_DHCP_DEFAULT);
strClassStandard.LoadString(IDS_USER_STANDARD);
if (strVendorStandard.Compare(pVendorName) != 0)
strTargetVendor = pVendorName;
if (strClassStandard.Compare(pUserClassName) != 0)
strTargetClass = pUserClassName;
POSITION posv = m_listVendorClasses.GetHeadPosition();
while (posv)
{
// find the right vendor
CVendorTracker * pVendorTracker = m_listVendorClasses.GetNext(posv);
if (pVendorTracker->m_strClassName.Compare(strTargetVendor) == 0)
{
POSITION pos = NULL;
pos = pVendorTracker->m_listUserClasses.GetHeadPosition();
while (pos)
{
// now find the right user class
CClassTracker * pClassTracker = pVendorTracker->m_listUserClasses.GetNext(pos);
if (pClassTracker->m_strClassName.Compare(strTargetClass) == 0)
{
// this is the class, add all of the options to the listbox
CString strDisplay, strType, strComment;
POSITION posOption = NULL;
posOption = pClassTracker->m_listOptions.GetHeadPosition();
while (posOption)
{
COptionTracker * pOptionTracker = pClassTracker->m_listOptions.GetNext(posOption);
pOptionTracker->m_pOption->QueryDisplayName(strDisplay);
strComment = pOptionTracker->m_pOption->QueryComment();
strType = pOptionTracker->m_pOption->IsVendor() ? strTypeVendor : strTypeStandard;
int nIndex = ListCtrl.AddItem(strDisplay, strComment, LISTVIEWEX_NOT_CHECKED);
ListCtrl.SetItemData(nIndex, (LPARAM) pOptionTracker);
if (pOptionTracker->GetCurrentState() == OPTION_STATE_ACTIVE)
ListCtrl.CheckItem(nIndex);
}
break;
}
} // while
} // if
} // while
// Finally, Set the column widths so that all items are visible.
// Set the default column widths to the width of the widest column
int * aColWidth = (int *) alloca(MAX_COLUMNS * sizeof(int));
int nRow, nCol;
CString strTemp;
ZeroMemory(aColWidth, MAX_COLUMNS * sizeof(int));
CopyMemory(aColWidth, &COLUMN_WIDTHS, sizeof(MAX_COLUMNS * sizeof(int)));
// for each item, loop through each column and calculate the correct width
for (nRow = 0; nRow < ListCtrl.GetItemCount(); nRow++)
{
for (nCol = 0; nCol < MAX_COLUMNS; nCol++)
{
strTemp = ListCtrl.GetItemText(nRow, nCol);
if (aColWidth[nCol] < ListCtrl.GetStringWidth(strTemp))
aColWidth[nCol] = ListCtrl.GetStringWidth(strTemp);
}
}
// now update the column widths based on what we calculated
for (nCol = 0; nCol < MAX_COLUMNS; nCol++)
{
// GetStringWidth doesn't seem to report the right thing,
// so we have to add a fudge factor of 15.... oh well.
if (aColWidth[nCol] > 0)
ListCtrl.SetColumnWidth(nCol, aColWidth[nCol] + 15);
}
}
/////////////////////////////////////////////////////////////////////////////
// COptionsCfgBasic property page
IMPLEMENT_DYNCREATE(COptionsCfgPropPage, CPropertyPageBase)
COptionsCfgPropPage::COptionsCfgPropPage() :
CPropertyPageBase(COptionsCfgPropPage::IDD),
m_bInitialized(FALSE)
{
LoadBitmaps();
m_helpMap.BuildMap(DhcpGetHelpMap(COptionsCfgPropPage::IDD));
}
COptionsCfgPropPage::COptionsCfgPropPage(UINT nIDTemplate, UINT nIDCaption) :
CPropertyPageBase(nIDTemplate, nIDCaption),
m_bInitialized(FALSE)
{
//{{AFX_DATA_INIT(COptionsCfgPropPage)
//}}AFX_DATA_INIT
LoadBitmaps();
m_helpMap.BuildMap(DhcpGetHelpMap(COptionsCfgPropPage::IDD));
}
COptionsCfgPropPage::~COptionsCfgPropPage()
{
}
void
COptionsCfgPropPage::LoadBitmaps()
{
}
void COptionsCfgPropPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPageBase::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COptionsCfgPropPage)
DDX_Control(pDX, IDC_LIST_OPTIONS, m_listctrlOptions);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(COptionsCfgPropPage, CPropertyPageBase)
//{{AFX_MSG_MAP(COptionsCfgPropPage)
ON_WM_DESTROY()
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_OPTIONS, OnItemchangedListOptions)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_SELECTOPTION, OnSelectOption)
// Binary array controls
ON_EN_CHANGE(IDC_EDIT_VALUE, OnChangeEditValue)
ON_BN_CLICKED(IDC_BUTTON_VALUE_UP, OnButtonValueUp)
ON_BN_CLICKED(IDC_BUTTON_VALUE_DOWN, OnButtonValueDown)
ON_BN_CLICKED(IDC_BUTTON_VALUE_ADD, OnButtonValueAdd)
ON_BN_CLICKED(IDC_BUTTON_VALUE_DELETE, OnButtonValueDelete)
ON_BN_CLICKED(IDC_RADIO_DECIMAL, OnClickedRadioDecimal)
ON_BN_CLICKED(IDC_RADIO_HEX, OnClickedRadioHex)
ON_LBN_SELCHANGE(IDC_LIST_VALUES, OnSelchangeListValues)
// Byte, WORD and Long edit control
ON_EN_CHANGE(IDC_EDIT_DWORD, OnChangeEditDword)
// string edit control
ON_EN_CHANGE(IDC_EDIT_STRING_VALUE, OnChangeEditString)
// IP Address control
ON_EN_CHANGE(IDC_IPADDR_ADDRESS, OnChangeIpAddress)
// IP Address array controls
ON_EN_CHANGE(IDC_EDIT_SERVER_NAME, OnChangeEditServerName)
ON_EN_CHANGE(IDC_IPADDR_SERVER_ADDRESS, OnChangeIpAddressArray)
ON_BN_CLICKED(IDC_BUTTON_RESOLVE, OnButtonResolve)
ON_BN_CLICKED(IDC_BUTTON_IPADDR_UP, OnButtonIpAddrUp)
ON_BN_CLICKED(IDC_BUTTON_IPADDR_DOWN, OnButtonIpAddrDown)
ON_BN_CLICKED(IDC_BUTTON_IPADDR_ADD, OnButtonIpAddrAdd)
ON_BN_CLICKED(IDC_BUTTON_IPADDR_DELETE, OnButtonIpAddrDelete)
ON_LBN_SELCHANGE(IDC_LIST_IP_ADDRS, OnSelchangeListIpAddrs)
// binary and encapsulated data
ON_EN_CHANGE(IDC_VALUEDATA, OnChangeValueData)
// route array controls
ON_BN_CLICKED(IDC_BUTTON_ROUTE_ADD, OnButtonAddRoute)
ON_BN_CLICKED(IDC_BUTTON_ROUTE_DEL, OnButtonDelRoute)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COptionsCfgPropPage message handlers
afx_msg long COptionsCfgPropPage::OnSelectOption(UINT wParam, LONG lParam)
{
COptionsConfig * pOptionsConfig = (COptionsConfig *) GetHolder();
if (wParam != NULL)
{
CDhcpOptionItem * pOptItem = (CDhcpOptionItem *) ULongToPtr(wParam);
HWND hWnd = NULL;
pOptionsConfig->m_strStartVendor = pOptItem->GetVendor();
pOptionsConfig->m_strStartClass = pOptItem->GetClassName();
pOptionsConfig->m_dhcpStartId = pOptItem->GetOptionId();
if ( (!pOptionsConfig->m_strStartVendor.IsEmpty() ||
!pOptionsConfig->m_strStartClass.IsEmpty()) &&
GetWindowLongPtr(GetSafeHwnd(), GWLP_ID) != IDP_OPTION_ADVANCED)
{
// we're on the basic page, need to switch to advanced
::PostMessage(pOptionsConfig->GetSheetWindow(), PSM_SETCURSEL, (WPARAM)1, NULL);
hWnd = pOptionsConfig->m_pageAdvanced.GetSafeHwnd();
::PostMessage(hWnd, WM_SELECTCLASSES, (WPARAM) &pOptionsConfig->m_strStartVendor, (LPARAM) &pOptionsConfig->m_strStartClass);
}
else
if ( (pOptionsConfig->m_strStartVendor.IsEmpty() &&
pOptionsConfig->m_strStartClass.IsEmpty()) &&
GetWindowLongPtr(GetSafeHwnd(), GWLP_ID) != IDP_OPTION_BASIC)
{
// we're on the advanced page, need to switch to basic
::PostMessage(pOptionsConfig->GetSheetWindow(), PSM_SETCURSEL, (WPARAM)0, NULL);
hWnd = pOptionsConfig->m_pageGeneral.GetSafeHwnd();
}
::PostMessage(hWnd, WM_SELECTOPTION, 0, 0);
return 0;
}
for (int i = 0; i < m_listctrlOptions.GetItemCount(); i++)
{
COptionTracker * pCurOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(i));
if (pCurOptTracker->m_pOption->QueryId() == pOptionsConfig->m_dhcpStartId)
{
BOOL bDirty = IsDirty();
m_listctrlOptions.SelectItem(i);
m_listctrlOptions.EnsureVisible(i, FALSE);
SetDirty(bDirty);
break;
}
}
// reset this variable since we don't need it anymore
pOptionsConfig->m_dhcpStartId = -1;
return 0;
}
/*---------------------------------------------------------------------------
Handlers for the IP Array controls
---------------------------------------------------------------------------*/
void COptionsCfgPropPage::OnButtonIpAddrAdd()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CWndIpAddress * pIpAddr = reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_SERVER_ADDRESS));
DWORD dwIpAddress;
pIpAddr->GetAddress(&dwIpAddress);
if (dwIpAddress)
{
int nSelectedItem = m_listctrlOptions.GetSelectedItem();
// make sure that sometime is selected
Assert(nSelectedItem > -1);
if (nSelectedItem > -1)
{
CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_IP_ADDRS));
CEdit * pServerName = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_SERVER_NAME));
COptionTracker * pOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedItem));
// fill in the information in the option struct
CDhcpOption * pOption = pOptTracker->m_pOption;
CDhcpOptionValue & optValue = pOption->QueryValue();
// check to see if we need to grow the array or not
int nOldUpperBound = optValue.QueryUpperBound();
if ((nOldUpperBound == 1) &&
(optValue.QueryIpAddr() == 0))
{
// this array is empty. Don't need to grow it
nOldUpperBound -= 1;
}
else
{
// Set that the array is growing by 1
optValue.SetUpperBound(nOldUpperBound + 1);
}
optValue.SetIpAddr((DHCP_IP_ADDRESS) dwIpAddress, nOldUpperBound);
pOptTracker->SetDirty(TRUE);
// add to the list box
CString strAddress;
::UtilCvtIpAddrToWstr(dwIpAddress, &strAddress);
pListBox->AddString(strAddress);
// clear the server edit field and ip address
pServerName->SetWindowText(_T(""));
pIpAddr->ClearAddress();
pIpAddr->SetFocusField(0);
// finally, mark the page as dirty
SetDirty(TRUE);
}
}
else
{
::DhcpMessageBox(IDS_ERR_DLL_INVALID_ADDRESS);
}
}
void COptionsCfgPropPage::OnButtonIpAddrDelete()
{
int nSelectedOption = m_listctrlOptions.GetSelectedItem();
CEdit * pServerName = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_SERVER_NAME));
CWndIpAddress * pIpAddr = reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_SERVER_ADDRESS));
CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_IP_ADDRS));
DWORD dwIpAddress;
CString strIpAddress;
int nSelectedIndex = pListBox->GetCurSel();
// get the currently selected item
pListBox->GetText(nSelectedIndex, strIpAddress);
dwIpAddress = UtilCvtWstrToIpAddr(strIpAddress);
// remove from the option
COptionTracker * pOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedOption));
// pOptTracker can be null when the context moves to another option.
// However, this is not disabled, so the user can still try to delete
// an IP since it is active.
//
// Add a null check
if (0 != pOptTracker ) {
// fill in the information in the option struct
CDhcpOption * pOption = pOptTracker->m_pOption;
CDhcpOptionValue & optValue = pOption->QueryValue();
// the listbox should match our array, so we'll remove the same index
optValue.RemoveIpAddr(nSelectedIndex);
optValue.SetUpperBound(optValue.QueryUpperBound() - 1);
// remove from list box
pListBox->DeleteString(nSelectedIndex);
pIpAddr->SetAddress(dwIpAddress);
pServerName->SetWindowText(_T(""));
// mark the option and the page as dirty
pOptTracker->SetDirty(TRUE);
SetDirty(TRUE);
HandleActivationIpArray();
} // if
} // COptionsCfgPropPage::OnButtonIpAddrDelete()
void COptionsCfgPropPage::OnSelchangeListIpAddrs()
{
HandleActivationIpArray();
}
void COptionsCfgPropPage::OnChangeIpAddressArray()
{
HandleActivationIpArray();
}
void COptionsCfgPropPage::OnButtonResolve()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CEdit * pServerName = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_SERVER_NAME));
CString strServer;
DHCP_IP_ADDRESS dhipa = 0;
DWORD err = 0;
pServerName->GetWindowText(strServer);
//
// See what type of name it is.
//
switch (UtilCategorizeName(strServer))
{
case HNM_TYPE_IP:
dhipa = ::UtilCvtWstrToIpAddr( strServer ) ;
break ;
case HNM_TYPE_NB:
case HNM_TYPE_DNS:
err = ::UtilGetHostAddress( strServer, & dhipa ) ;
if (!err)
UtilCvtIpAddrToWstr(dhipa, &strServer);
break ;
default:
err = IDS_ERR_BAD_HOST_NAME ;
break ;
}
if (err)
{
::DhcpMessageBox(err);
}
else
{
CWndIpAddress * pIpAddr = reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_SERVER_ADDRESS));
pIpAddr->SetAddress(dhipa);
}
}
void COptionsCfgPropPage::OnChangeEditServerName()
{
HandleActivationIpArray();
}
void COptionsCfgPropPage::OnButtonIpAddrDown()
{
CButton * pIpAddrDown =
reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_DOWN));
CButton * pIpAddrUp =
reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_UP));
MoveValue(FALSE, FALSE);
if (pIpAddrDown->IsWindowEnabled())
pIpAddrDown->SetFocus();
else
pIpAddrUp->SetFocus();
}
void COptionsCfgPropPage::OnButtonIpAddrUp()
{
CButton * pIpAddrDown =
reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_DOWN));
CButton * pIpAddrUp =
reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_UP));
MoveValue(FALSE, TRUE);
if (pIpAddrUp->IsWindowEnabled())
pIpAddrUp->SetFocus();
else
pIpAddrDown->SetFocus();
}
/*---------------------------------------------------------------------------
Handlers for the number array controls
---------------------------------------------------------------------------*/
void COptionsCfgPropPage::OnButtonValueAdd()
{
int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
COptionTracker * pOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
CEdit * pValue = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_VALUE));
CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
// Get the OptionValue object
CDhcpOption * pOption = pOptTracker->m_pOption;
CDhcpOptionValue & optValue = pOption->QueryValue();
DWORD dwValue;
DWORD_DWORD dwdwValue;
DWORD dwMask = 0xFFFFFFFF ;
switch ( optValue.QueryDataType() )
{
case DhcpBinaryDataOption :
case DhcpByteOption:
dwMask = 0xFF ;
break ;
case DhcpWordOption:
dwMask = 0xFFFF ;
break ;
} // switch
if (optValue.QueryDataType() == DhcpDWordDWordOption)
{
CString strValue;
pValue->GetWindowText(strValue);
UtilConvertStringToDwordDword(strValue, &dwdwValue);
}
else
{
if (!FGetCtrlDWordValue(pValue->GetSafeHwnd(), &dwValue, 0, dwMask))
return;
}
DWORD err = 0 ;
CATCH_MEM_EXCEPTION
{
// Set that the array is growing by 1
int nOldUpperBound = optValue.QueryUpperBound();
optValue.SetUpperBound(nOldUpperBound + 1);
// now insert the new item as the last item in the array
(optValue.QueryDataType() == DhcpDWordDWordOption) ?
optValue.SetDwordDword(dwdwValue, nOldUpperBound) : optValue.SetNumber(dwValue, nOldUpperBound) ;
}
END_MEM_EXCEPTION(err)
if ( err )
{
::DhcpMessageBox( err ) ;
}
else
{
pOptTracker->SetDirty(TRUE);
SetDirty(TRUE);
}
//
// update controls. clear the edit control
//
pValue->SetWindowText(_T(""));
FillDataEntry(pOption);
HandleActivationValueArray();
}
void COptionsCfgPropPage::OnButtonValueDelete()
{
int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
COptionTracker * pOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
CEdit * pValue = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_VALUE));
CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
// Get the OptionValue object
CDhcpOption * pOption = pOptTracker->m_pOption;
CDhcpOptionValue & optValue = pOption->QueryValue();
/* DWORD dwValue;
DWORD dwMask = 0xFFFFFFFF ;
switch ( optValue.QueryDataType() )
{
case DhcpBinaryDataOption :
case DhcpByteOption:
dwMask = 0xFF ;
break ;
case DhcpWordOption:
dwMask = 0xFFFF ;
break ;
} // switch
*/
CString strValue;
int nListBoxIndex = pListBox->GetCurSel();
// get the currently selected item
pListBox->GetText(nListBoxIndex, strValue);
//if (!FGetCtrlDWordValue(pValue->GetSafeHwnd(), &dwValue, 0, dwMask))
// return;
// the listbox should match our array, so we'll remove the same index
(optValue.QueryDataType() == DhcpDWordDWordOption) ?
optValue.RemoveDwordDword(nListBoxIndex) : optValue.RemoveNumber(nListBoxIndex);
optValue.SetUpperBound(optValue.QueryUpperBound() - 1);
// remove from list box
pListBox->DeleteString(nListBoxIndex);
pValue->SetWindowText(strValue);
// mark the option and the page as dirty
pOptTracker->SetDirty(TRUE);
SetDirty(TRUE);
HandleActivationValueArray();
}
void COptionsCfgPropPage::OnButtonValueDown()
{
CButton * pValueDown =
reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_DOWN));
CButton * pValueUp =
reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_UP));
MoveValue(TRUE, FALSE);
if (pValueDown->IsWindowEnabled())
pValueDown->SetFocus();
else
pValueUp->SetFocus();
}
void COptionsCfgPropPage::OnButtonValueUp()
{
CButton * pValueDown =
reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_DOWN));
CButton * pValueUp =
reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_UP));
MoveValue(TRUE, TRUE);
if (pValueUp->IsWindowEnabled())
pValueUp->SetFocus();
else
pValueDown->SetFocus();
}
void COptionsCfgPropPage::MoveValue(BOOL bValues, BOOL bUp)
{
int nSelectedOption = m_listctrlOptions.GetSelectedItem();
// Get the option that describes this
COptionTracker * pOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedOption));
if ( 0 == pOptTracker ) {
return;
}
CDhcpOption * pOption = pOptTracker->m_pOption;
if ( 0 == pOption ) {
return;
}
CDhcpOptionValue & optValue = pOption->QueryValue();
// Get the correct listbox
CListBox * pListBox;
if (bValues)
{
// this is for values
pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
}
else
{
// this is for IpAddrs
pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_IP_ADDRS));
}
if ( 0 == pListBox ) {
return;
}
// now get which item is selected in the listbox
int cFocus = pListBox->GetCurSel();
// make sure it's valid for this operation
if ( (bUp && cFocus <= 0) ||
(!bUp && cFocus >= pListBox->GetCount()) )
{
return;
}
DWORD dwValue;
DWORD_DWORD dwdwValue;
DWORD err = 0 ;
// move the value up/down
CATCH_MEM_EXCEPTION
{
if (optValue.QueryDataType() == DhcpDWordDWordOption)
{
DWORD_DWORD dwUpValue;
DWORD_DWORD dwDownValue;
if (bUp)
{
dwdwValue = dwUpValue = optValue.QueryDwordDword(cFocus);
dwDownValue = optValue.QueryDwordDword(cFocus - 1);
optValue.SetDwordDword(dwUpValue, cFocus - 1);
optValue.SetDwordDword(dwDownValue, cFocus);
}
else
{
dwdwValue = dwDownValue = optValue.QueryDwordDword(cFocus);
dwUpValue = optValue.QueryDwordDword(cFocus + 1);
optValue.SetDwordDword(dwDownValue, cFocus + 1);
optValue.SetDwordDword(dwUpValue, cFocus);
}
}
else
{
DWORD dwUpValue;
DWORD dwDownValue;
if (bUp)
{
dwValue = dwUpValue = optValue.QueryNumber(cFocus);
dwDownValue = optValue.QueryNumber(cFocus - 1);
optValue.SetNumber(dwUpValue, cFocus - 1);
optValue.SetNumber(dwDownValue, cFocus);
}
else
{
dwValue = dwDownValue = optValue.QueryNumber(cFocus);
dwUpValue = optValue.QueryNumber(cFocus + 1);
optValue.SetNumber(dwDownValue, cFocus + 1);
optValue.SetNumber(dwUpValue, cFocus);
}
}
}
END_MEM_EXCEPTION(err)
if ( err )
{
::DhcpMessageBox( err ) ;
}
else
{
// everything is ok, mark this option and the prop sheet
pOptTracker->SetDirty(TRUE);
SetDirty(TRUE);
}
// update the data.
FillDataEntry(pOption);
for (int i = 0; i < pListBox->GetCount(); i++)
{
CString strTemp;
pListBox->GetText(i, strTemp);
if (optValue.QueryDataType() == DhcpDWordDWordOption)
{
DWORD_DWORD dwdwCur;
UtilConvertStringToDwordDword(strTemp, &dwdwCur);
if (dwdwCur.DWord1 == dwdwValue.DWord1 &&
dwdwCur.DWord2 == dwdwValue.DWord2)
{
pListBox->SetCurSel(i);
break;
}
}
else
{
DWORD dwIp = ::UtilCvtWstrToIpAddr(strTemp);
if (dwIp == dwValue)
{
pListBox->SetCurSel(i);
break;
}
}
}
// update the controls
if (bValues)
{
HandleActivationValueArray();
}
else
{
HandleActivationIpArray();
}
}
void COptionsCfgPropPage::OnChangeEditValue()
{
HandleActivationValueArray();
}
void COptionsCfgPropPage::OnClickedRadioDecimal()
{
int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
COptionTracker * pOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
CDhcpOption * pOption = pOptTracker->m_pOption;
FillDataEntry(pOption);
}
void COptionsCfgPropPage::OnClickedRadioHex()
{
int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
COptionTracker * pOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
CDhcpOption * pOption = pOptTracker->m_pOption;
FillDataEntry(pOption);
}
void COptionsCfgPropPage::OnSelchangeListValues()
{
HandleActivationValueArray();
}
/*---------------------------------------------------------------------------
Handlers for the binary and encapsulated data
---------------------------------------------------------------------------*/
void COptionsCfgPropPage::OnChangeValueData()
{
int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
COptionTracker * pOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
CEdit * pValue = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_VALUE));
CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
// Get the OptionValue object
CDhcpOption * pOption = pOptTracker->m_pOption;
CDhcpOptionValue & optValue = pOption->QueryValue();
// get the info from the control
HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(GetDlgItem(IDC_VALUEDATA)->GetSafeHwnd(), GWLP_USERDATA);
DWORD err = 0;
CATCH_MEM_EXCEPTION
{
// size we don't know what changed, we just have to copy all of the data
for (int i = 0; i < pHexEditData->cbBuffer; i++)
{
DWORD dwValue = (BYTE) pHexEditData->pBuffer[i];
optValue.SetNumber(dwValue, i);
}
}
END_MEM_EXCEPTION(err)
// mark the option and the page as dirty
pOptTracker->SetDirty(TRUE);
SetDirty(TRUE);
}
/*---------------------------------------------------------------------------
Handlers for the single number entry controls
---------------------------------------------------------------------------*/
void COptionsCfgPropPage::OnChangeEditDword()
{
HandleValueEdit();
}
/*---------------------------------------------------------------------------
Handlers for the single IP Address entry controls
---------------------------------------------------------------------------*/
void COptionsCfgPropPage::OnChangeIpAddress()
{
HandleValueEdit();
}
/*---------------------------------------------------------------------------
Handlers for the string entry controls
---------------------------------------------------------------------------*/
void COptionsCfgPropPage::OnChangeEditString()
{
HandleValueEdit();
}
/////////////////////////////////////////////////////////////////////////////
// CAddRoute dialog
CAddRoute::CAddRoute( CWnd *pParent)
: CBaseDialog( CAddRoute::IDD, pParent )
{
m_ipaDest.ClearAddress();
m_ipaMask.ClearAddress();
m_ipaRouter.ClearAddress();
m_bChange = FALSE;
}
void CAddRoute::DoDataExchange(CDataExchange* pDX)
{
CBaseDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAddRoute)
//}}AFX_DATA_MAP
DDX_Control(pDX, IDC_IPADDR_ADDRESS, m_ipaDest);
DDX_Control(pDX, IDC_IPADDR_ADDRESS2, m_ipaMask);
DDX_Control(pDX, IDC_IPADDR_ADDRESS3, m_ipaRouter);
}
BEGIN_MESSAGE_MAP(CAddRoute, CBaseDialog)
//{{AFX_MSG_MAP(CAddRoute)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAddReservation message handlers
BOOL CAddRoute::OnInitDialog()
{
CBaseDialog::OnInitDialog();
// set focus on the destination..
CWnd *pWnd = GetDlgItem(IDC_IPADDR_ADDRESS);
if( NULL != pWnd )
{
pWnd->SetFocus();
return FALSE;
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CAddRoute::OnOK()
{
DWORD err = 0;
UpdateData();
m_ipaDest.GetAddress( &Dest );
m_ipaMask.GetAddress( &Mask );
m_ipaRouter.GetAddress( &Router );
// validate the ip addresses
if( 0 == Router || (0 != Mask && 0 == Dest) ||
0 != ((~Mask) & Dest) ||
(0 != ((~Mask) & ((~Mask)+1)) ) )
{
::DhcpMessageBox( IDS_ERR_INVALID_ROUTE_ENTRY );
}
else
{
m_bChange = TRUE;
CBaseDialog::OnOK();
}
//CBaseDialog::OnOK();
}
/*---------------------------------------------------------------------------
Handlers for the route add data entry controls
---------------------------------------------------------------------------*/
void COptionsCfgPropPage::OnButtonAddRoute()
{
int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
COptionTracker * pOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
// Get the OptionValue object
CDhcpOption * pOption = pOptTracker->m_pOption;
CDhcpOptionValue & optValue = pOption->QueryValue();
// get the routes list control
CListCtrl *pList = reinterpret_cast<CListCtrl *>(
GetDlgItem( IDC_LIST_OF_ROUTES ) );
// get the add and remove buttons
CButton *pAdd = reinterpret_cast<CButton *>(
GetDlgItem(IDC_BUTTON_ROUTE_ADD) );
CButton *pRemove = reinterpret_cast<CButton *>(
GetDlgItem(IDC_BUTTON_ROUTE_DEL) );
// throw the add route UI
CAddRoute NewRoute(NULL);
NewRoute.DoModal();
if( NewRoute.m_bChange )
{
CString strDest, strMask, strRouter;
// obtain the three strings..
::UtilCvtIpAddrToWstr(NewRoute.Dest, &strDest);
::UtilCvtIpAddrToWstr(NewRoute.Mask, &strMask);
::UtilCvtIpAddrToWstr(NewRoute.Router, &strRouter);
LV_ITEM lvi;
lvi.mask = LVIF_TEXT;
lvi.iItem = pList->GetItemCount();
lvi.iSubItem = 0;
lvi.pszText = (LPTSTR)(LPCTSTR)strDest;
lvi.iImage = 0;
lvi.stateMask = 0;
int nItem = pList->InsertItem(&lvi);
pList->SetItemText(nItem, 1, strMask);
pList->SetItemText(nItem, 2, strRouter);
pOptTracker->SetDirty(TRUE);
SetDirty(TRUE);
}
// now walk through the list control and get the values and
// put them back onto the optValue
HandleActivationRouteArray( &optValue );
}
void COptionsCfgPropPage::OnButtonDelRoute()
{
int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
COptionTracker * pOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
// Get the OptionValue object
CDhcpOption * pOption = pOptTracker->m_pOption;
CDhcpOptionValue & optValue = pOption->QueryValue();
// get the routes list control
CListCtrl *pList = reinterpret_cast<CListCtrl *>(
GetDlgItem( IDC_LIST_OF_ROUTES ) );
// get the add and remove buttons
CButton *pAdd = reinterpret_cast<CButton *>(
GetDlgItem(IDC_BUTTON_ROUTE_ADD) );
CButton *pRemove = reinterpret_cast<CButton *>(
GetDlgItem(IDC_BUTTON_ROUTE_DEL) );
// get the selected column and delete it
int nItem = pList->GetNextItem(-1, LVNI_SELECTED);
while( nItem != -1 ) {
pList->DeleteItem( nItem ) ;
nItem = pList->GetNextItem(-1, LVNI_SELECTED);
pOptTracker->SetDirty(TRUE);
SetDirty(TRUE);
}
// now walk through the list control and get the values and
// put them back onto the optValue
HandleActivationRouteArray( &optValue );
}
BOOL COptionsCfgPropPage::OnInitDialog()
{
CPropertyPageBase::OnInitDialog();
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// set the title
((COptionsConfig *) GetHolder())->SetTitle();
// initialize the list control
InitListCtrl();
// initialize the option data
DWORD dwErr = ((COptionsConfig *) GetHolder())->InitData();
if (dwErr != ERROR_SUCCESS)
{
// CODEWORK: need to exit gracefull if this happens
::DhcpMessageBox(dwErr);
}
else
{
// Fill the options for this page type - basic, advanced, custom
((COptionsConfig *) GetHolder())->FillOptions(_T(""), _T(""), m_listctrlOptions);
}
// Create the type control switcher
m_cgsTypes.Create(this,IDC_DATA_ENTRY_ANCHOR,cgsPreCreateAll);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_NONE, IDD_DATA_ENTRY_NONE, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_DWORD, IDD_DATA_ENTRY_DWORD, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_IPADDRESS, IDD_DATA_ENTRY_IPADDRESS, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_IPADDRESS_ARRAY, IDD_DATA_ENTRY_IPADDRESS_ARRAY, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_STRING, IDD_DATA_ENTRY_STRING, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_BINARY_ARRAY, IDD_DATA_ENTRY_BINARY_ARRAY, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_BINARY, IDD_DATA_ENTRY_BINARY, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_ROUTE_ARRAY, IDD_DATA_ENTRY_ROUTE_ARRAY, NULL);
m_hexData.SubclassDlgItem(IDC_VALUEDATA, this);
SwitchDataEntry(-1, -1, 0, TRUE);
SetDirty(FALSE);
m_bInitialized = TRUE;
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void COptionsCfgPropPage::SelectOption(CDhcpOption * pOption)
{
for (int i = 0; i < m_listctrlOptions.GetItemCount(); i++)
{
COptionTracker * pCurOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(i));
if (pOption->QueryId() == pCurOptTracker->m_pOption->QueryId())
{
m_listctrlOptions.SelectItem(i);
m_listctrlOptions.EnsureVisible(i, FALSE);
}
}
}
void COptionsCfgPropPage::SwitchDataEntry(int datatype, int optiontype, BOOL fRouteArray, BOOL bEnable)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString strType;
if( fRouteArray )
{
// ignore any other types passed and use route_array type
m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_ROUTE_ARRAY);
}
else
switch(datatype)
{
case DhcpByteOption:
case DhcpWordOption:
case DhcpDWordOption:
case DhcpDWordDWordOption:
{
// build our string for the type of data
if ( (datatype == DhcpByteOption) ||
(datatype == DhcpEncapsulatedDataOption) )
{
strType.LoadString(IDS_INFO_TYPOPT_BYTE);
}
else
if (datatype == DhcpWordOption)
{
strType.LoadString(IDS_INFO_TYPOPT_WORD);
}
else
if (datatype == DhcpDWordOption)
{
strType.LoadString(IDS_INFO_TYPOPT_DWORD);
}
else
{
strType.LoadString(IDS_INFO_TYPOPT_DWDW);
}
if (optiontype == DhcpArrayTypeOption)
{
m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_BINARY_ARRAY);
CButton * pRadioDecimal =
reinterpret_cast<CButton *>(GetDlgItem(IDC_RADIO_DECIMAL));
pRadioDecimal->SetCheck(1);
// set some information text
CString strFrameText;
strFrameText.LoadString(IDS_DATA_ENTRY_FRAME);
strFrameText += _T(" ") + strType;
CWnd * pWnd = GetDlgItem(IDC_STATIC_BINARY_ARRAY_FRAME);
pWnd->SetWindowText(strFrameText);
}
else
{
m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_DWORD);
CWnd * pWnd = GetDlgItem(IDC_STATIC_TYPE);
pWnd->SetWindowText(strType);
}
}
break;
case DhcpBinaryDataOption:
case DhcpEncapsulatedDataOption:
{
m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_BINARY);
}
break;
case DhcpIpAddressOption:
if (optiontype == DhcpArrayTypeOption)
{
strType.LoadString(IDS_INFO_TYPOPT_BYTE);
m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_IPADDRESS_ARRAY);
CButton * pRadioDecimal =
reinterpret_cast<CButton *>(GetDlgItem(IDC_RADIO_DECIMAL));
pRadioDecimal->SetCheck(1);
// set some information text
CString strFrameText;
strFrameText.LoadString(IDS_DATA_ENTRY_FRAME);
strFrameText += _T(" ") + strType;
CWnd * pWnd = GetDlgItem(IDC_STATIC_BINARY_ARRAY_FRAME);
pWnd->SetWindowText(strFrameText);
}
else
m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_IPADDRESS);
break;
case DhcpStringDataOption:
if (optiontype == DhcpArrayTypeOption)
m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_BINARY_ARRAY);
else
m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_STRING);
break;
default:
m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_NONE);
break;
}
// enable/disable the current group
m_cgsTypes.EnableGroup(-1, bEnable);
}
const int ROUTE_LIST_COL_WIDTHS[3] = {
80, 80, 80
};
const int ROUTE_LIST_COL_HEADERS[3] = {
IDS_ROUTE_LIST_COL_DEST,
IDS_ROUTE_LIST_COL_MASK,
IDS_ROUTE_LIST_COL_ROUTER
};
void COptionsCfgPropPage::FillDataEntry(CDhcpOption * pOption)
{
CDhcpOptionValue & optValue = pOption->QueryValue();
int datatype = pOption->QueryDataType();
int optiontype = pOption->QueryOptType();
BOOL fRouteArray = (
!pOption->IsClassOption() &&
(DHCP_OPTION_ID_CSR == pOption->QueryId()) &&
optiontype == DhcpUnaryElementTypeOption &&
datatype == DhcpBinaryDataOption
);
CButton * pRadioHex =
reinterpret_cast<CButton *>(GetDlgItem(IDC_RADIO_HEX));
BOOL bUseHex = pRadioHex->GetCheck();
if( fRouteArray )
{
const CByteArray * pbaData = optValue.QueryBinaryArray();
int nDataSize = (int)pbaData->GetSize();
LPBYTE pData = (LPBYTE) pbaData->GetData();
// initialize the list control view with data
CListCtrl *pList =
reinterpret_cast<CListCtrl *>(GetDlgItem(IDC_LIST_OF_ROUTES));
Assert(pList);
pList->DeleteAllItems();
pList->SetExtendedStyle(LVS_EX_FULLROWSELECT);
pList->DeleteColumn(2);
pList->DeleteColumn(1);
pList->DeleteColumn(0);
LV_COLUMN lvc;
CString strColHeader;
for( int i = 0; i < 3; i ++ )
{
lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT |
LVCF_WIDTH ;
lvc.iSubItem = i;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = ROUTE_LIST_COL_WIDTHS[i];
strColHeader.LoadString(ROUTE_LIST_COL_HEADERS[i]);
lvc.pszText = (LPTSTR)(LPCTSTR)strColHeader;
pList->InsertColumn( i, &lvc );
}
// 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);
LV_ITEM lvi;
lvi.mask = LVIF_TEXT;
lvi.iItem = pList->GetItemCount();
lvi.iSubItem = 0;
lvi.pszText = (LPTSTR)(LPCTSTR) strDest;
lvi.iImage = 0;
lvi.stateMask = 0;
int nItem = pList->InsertItem(&lvi);
pList->SetItemText(nItem, 1, strMask);
pList->SetItemText(nItem, 2, strRouter);
}
HandleActivationRouteArray();
}
else
switch(datatype)
{
case DhcpByteOption:
case DhcpWordOption:
case DhcpDWordOption:
if (optiontype == DhcpArrayTypeOption)
{
CListBox * pListBox =
reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
Assert(pListBox);
pListBox->ResetContent();
for (int i = 0; i < optValue.QueryUpperBound(); i++)
{
long lValue = optValue.QueryNumber(i);
CString strValue;
if (bUseHex)
strValue.Format(_T("0x%x"), lValue);
else
strValue.Format(_T("%d"), lValue);
pListBox->AddString(strValue);
}
HandleActivationValueArray();
}
else
{
CString strValue;
optValue.QueryDisplayString(strValue);
CWnd * pWnd = GetDlgItem(IDC_EDIT_DWORD);
Assert(pWnd);
pWnd->SetWindowText(strValue);
}
break;
case DhcpIpAddressOption:
if (optiontype == DhcpArrayTypeOption)
{
CListBox * pListBox =
reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_IP_ADDRS));
Assert(pListBox);
pListBox->ResetContent();
for (int i = 0; i < optValue.QueryUpperBound(); i++)
{
CString strValue;
DHCP_IP_ADDRESS ipAddress = optValue.QueryIpAddr(i);
if (ipAddress)
{
::UtilCvtIpAddrToWstr(ipAddress, &strValue);
pListBox->AddString(strValue);
}
}
HandleActivationIpArray();
}
else
{
CWndIpAddress * pIpAddr =
reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_ADDRESS));
DHCP_IP_ADDRESS ipAddress = optValue.QueryIpAddr();
if (ipAddress)
pIpAddr->SetAddress(ipAddress);
else
pIpAddr->ClearAddress();
}
break;
case DhcpStringDataOption:
if (optiontype == DhcpArrayTypeOption)
{
CListBox * pListBox =
reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
Assert(pListBox);
pListBox->ResetContent();
for (int i = 0; i < optValue.QueryUpperBound(); i++)
{
long lValue = optValue.QueryNumber(i);
CString strValue;
if (bUseHex)
strValue.Format(_T("0x%x"), lValue);
else
strValue.Format(_T("%d"), lValue);
pListBox->AddString(strValue);
}
}
else
{
CWnd * pWnd = GetDlgItem(IDC_EDIT_STRING_VALUE);
pWnd->SetWindowText(optValue.QueryString());
}
break;
case DhcpDWordDWordOption:
if (optiontype == DhcpArrayTypeOption)
{
CListBox * pListBox =
reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
Assert(pListBox);
pListBox->ResetContent();
for (int i = 0; i < optValue.QueryUpperBound(); i++)
{
DWORD_DWORD dwdwValue = optValue.QueryDwordDword(i);
CString strValue;
::UtilConvertDwordDwordToString(&dwdwValue, &strValue, !bUseHex);
pListBox->AddString(strValue);
}
HandleActivationValueArray();
}
else
{
CString strValue;
optValue.QueryDisplayString(strValue);
CWnd * pWnd = GetDlgItem(IDC_EDIT_DWORD);
Assert(pWnd);
pWnd->SetWindowText(strValue);
}
break;
case DhcpBinaryDataOption:
case DhcpEncapsulatedDataOption:
{
const CByteArray * pbaData = optValue.QueryBinaryArray();
int nDataSize = (int)pbaData->GetSize();
LPBYTE pData = (LPBYTE) pbaData->GetData();
memset(m_BinaryBuffer, 0, sizeof(m_BinaryBuffer));
if (pData)
{
memcpy(m_BinaryBuffer, pData, nDataSize);
}
SendDlgItemMessage(IDC_VALUEDATA, HEM_SETBUFFER, (WPARAM)
nDataSize, (LPARAM) m_BinaryBuffer);
}
break;
default:
Assert(FALSE);
break;
}
}
void COptionsCfgPropPage::InitListCtrl()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// set image lists
m_StateImageList.Create(IDB_LIST_STATE, 16, 1, RGB(255, 0, 0));
m_listctrlOptions.SetImageList(NULL, LVSIL_NORMAL);
m_listctrlOptions.SetImageList(NULL, LVSIL_SMALL);
m_listctrlOptions.SetImageList(&m_StateImageList, LVSIL_STATE);
// insert a column so we can see the items
LV_COLUMN lvc;
CString strColumnHeader;
for (int i = 0; i < MAX_COLUMNS; i++)
{
lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
lvc.iSubItem = i;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = COLUMN_WIDTHS[i];
strColumnHeader.LoadString(COLUMN_HEADERS[i]);
lvc.pszText = (LPTSTR) (LPCTSTR) strColumnHeader;
m_listctrlOptions.InsertColumn(i, &lvc);
}
m_listctrlOptions.SetFullRowSel(TRUE);
}
void COptionsCfgPropPage::OnDestroy()
{
CImageList * pStateImageList = NULL;
// if the control has been initialized, we need to cleanup
if (m_listctrlOptions.GetSafeHwnd() != NULL)
{
pStateImageList = m_listctrlOptions.SetImageList(NULL, LVSIL_STATE);
if (pStateImageList)
//pStateImageList->DeleteImageList();
// The OptionTrackers get delete in the destructor
m_listctrlOptions.DeleteAllItems();
}
m_listctrlOptions.DestroyWindow();
CPropertyPageBase::OnDestroy();
}
void COptionsCfgPropPage::OnItemchangedListOptions(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if (pNMListView->uChanged & LVIF_STATE)
{
BOOL bUpdate = FALSE, bEnable = FALSE;
UINT uFlags = pNMListView->uOldState ^ pNMListView->uNewState;
COptionTracker * pCurOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(pNMListView->iItem));
CDhcpOption * pCurOption = pCurOptTracker->m_pOption;
BOOL bOldSelected = pNMListView->uOldState & LVIS_SELECTED;
BOOL bNewSelected = pNMListView->uNewState & LVIS_SELECTED;
BOOL bStateImageChanged = (pNMListView->uOldState & LVIS_STATEIMAGEMASK) !=
(pNMListView->uNewState & LVIS_STATEIMAGEMASK);
BOOL bIsSelected = m_listctrlOptions.IsSelected(pNMListView->iItem);
// has this item been selected?
if (!bOldSelected && bNewSelected)
{
// check to see if this item is checked
bEnable = m_listctrlOptions.GetCheck(pNMListView->iItem);
bUpdate = TRUE;
}
// has item been checked/unchecked?
if (bStateImageChanged && m_bInitialized)
{
// mark this as dirty and enable apply button
pCurOptTracker->SetDirty(TRUE);
SetDirty(TRUE);
// update the state in the option tracker
UINT uCurrentState = m_listctrlOptions.GetCheck(pNMListView->iItem) ? OPTION_STATE_ACTIVE : OPTION_STATE_INACTIVE;
pCurOptTracker->SetCurrentState(uCurrentState);
// we force the the selection of an item if the user changes it's checkbox state
if (!bIsSelected)
m_listctrlOptions.SelectItem(pNMListView->iItem);
}
// if we are changing the check box on a selected item, then update
if ((bStateImageChanged && bIsSelected))
{
bEnable = (pNMListView->uNewState & INDEXTOSTATEIMAGEMASK(LISTVIEWEX_CHECKED));
bUpdate = TRUE;
}
// item needs to be updated
if (bUpdate)
{
BOOL fRouteArray = (
!pCurOption->IsClassOption() &&
(DHCP_OPTION_ID_CSR == pCurOption->QueryId()) &&
DhcpUnaryElementTypeOption ==
pCurOption->QueryOptType() &&
DhcpBinaryDataOption == pCurOption->QueryDataType()
);
SwitchDataEntry(
pCurOption->QueryDataType(),
pCurOption->QueryOptType(), fRouteArray, bEnable);
FillDataEntry(pCurOption);
// This sets focus to the first control in the group to edit the value of the
// selected option. This causes a problem when using the keyboard to move down
// the list of options in that the focus keeps jumping from the listctrl to
// the option value edit fields...
/*
CWnd* pWndNext = GetNextDlgTabItem(&m_listctrlOptions);
if (pWndNext != NULL)
{
pWndNext->SetFocus();
}
*/
}
}
*pResult = 0;
}
BOOL COptionsCfgPropPage::OnSetActive()
{
return CPropertyPageBase::OnSetActive();
}
void COptionsCfgPropPage::HandleActivationIpArray()
{
CString strServerName;
CWndIpAddress * pIpAddr = reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_SERVER_ADDRESS));
CButton * pResolve = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_RESOLVE));
CButton * pAdd = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_ADD));
CButton * pRemove = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_DELETE));
CButton * pUp = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_UP));
CButton * pDown = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_DOWN));
CEdit * pServerName = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_SERVER_NAME));
CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_IP_ADDRS));
// set the resolve button
pServerName->GetWindowText(strServerName);
pResolve->EnableWindow(strServerName.GetLength() > 0);
// the add button
DWORD dwIpAddr = 0;
pIpAddr->GetAddress(&dwIpAddr);
if (GetFocus() == pAdd &&
dwIpAddr == 0)
{
pIpAddr->SetFocus();
SetDefID(IDOK);
}
pAdd->EnableWindow(dwIpAddr != 0);
// the remove button
if (GetFocus() == pRemove &&
pListBox->GetCurSel() < 0)
{
pIpAddr->SetFocus();
SetDefID(IDOK);
}
pRemove->EnableWindow(pListBox->GetCurSel() >= 0);
// up and down buttons
BOOL bEnableUp = (pListBox->GetCurSel() >= 0) && (pListBox->GetCurSel() != 0);
pUp->EnableWindow(bEnableUp);
BOOL bEnableDown = (pListBox->GetCurSel() >= 0) && (pListBox->GetCurSel() < pListBox->GetCount() - 1);
pDown->EnableWindow(bEnableDown);
}
void COptionsCfgPropPage::HandleActivationValueArray()
{
CButton * pAdd = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_ADD));
CButton * pRemove = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_DELETE));
CButton * pUp = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_UP));
CButton * pDown = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_DOWN));
CButton * pRadioDecimal = reinterpret_cast<CButton *>(GetDlgItem(IDC_RADIO_DECIMAL));
CEdit * pValue = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_VALUE));
CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
CString strValue;
// set the add button
pValue->GetWindowText(strValue);
if (GetFocus() == pAdd &&
strValue.GetLength() == 0)
{
pValue->SetFocus();
SetDefID(IDOK);
}
pAdd->EnableWindow(strValue.GetLength() > 0);
// the remove button
if (GetFocus() == pRemove &&
pListBox->GetCurSel() == LB_ERR)
{
pValue->SetFocus();
SetDefID(IDOK);
}
pRemove->EnableWindow(pListBox->GetCurSel() != LB_ERR);
// up and down buttons
BOOL bEnableUp = (pListBox->GetCurSel() != LB_ERR) && (pListBox->GetCurSel() > 0);
pUp->EnableWindow(bEnableUp);
BOOL bEnableDown = (pListBox->GetCurSel() != LB_ERR) && (pListBox->GetCurSel() < pListBox->GetCount() - 1);
pDown->EnableWindow(bEnableDown);
}
void COptionsCfgPropPage::HandleActivationRouteArray(
CDhcpOptionValue *optValue
)
{
// this route will enable the right dialog items and also set
// focus correctly.
// get the routes list control
CListCtrl *pList = reinterpret_cast<CListCtrl *>(
GetDlgItem( IDC_LIST_OF_ROUTES ) );
// get the add and remove buttons
CButton *pAdd = reinterpret_cast<CButton *>(
GetDlgItem(IDC_BUTTON_ROUTE_ADD) );
CButton *pRemove = reinterpret_cast<CButton *>(
GetDlgItem(IDC_BUTTON_ROUTE_DEL) );
// enable the remove button only if there are any
// elements at all
pAdd->EnableWindow(TRUE);
pRemove->EnableWindow( pList->GetItemCount() != 0 );
if( optValue )
{
// if there are no elements, then set focus on Add
if( pList->GetItemCount() == 0 )
{
pAdd->SetFocus();
}
else
{
pList->SetFocus();
pList->SetItemState( 0, LVIS_FOCUSED , LVIF_STATE );
}
// also, format the whole list of ip addresses into
// binary type.. allocate large enough buffer
int nItems = pList->GetItemCount();
LPBYTE Buffer = new BYTE [sizeof(DWORD)*4 * nItems];
if( NULL != Buffer )
{
int BufSize = 0;
for( int i = 0 ; i < nItems ; i ++ )
{
DHCP_IP_ADDRESS Dest, Mask, Router;
Dest = UtilCvtWstrToIpAddr(pList->GetItemText(i, 0));
Mask = UtilCvtWstrToIpAddr(pList->GetItemText(i, 1));
Router = UtilCvtWstrToIpAddr(pList->GetItemText(i, 2));
Dest = htonl(Dest);
Router = htonl(Router);
int nBitsInMask = 0;
while( Mask != 0 ) {
nBitsInMask ++; Mask = (Mask << 1);
}
// first add destination descriptor
// first byte contains # of bits in mask
// next few bytes contain the dest address for only
// the significant octets
Buffer[BufSize++] = (BYTE)nBitsInMask;
memcpy(&Buffer[BufSize], &Dest, (nBitsInMask+7)/8);
BufSize += (nBitsInMask+7)/8;
// now just copy the router address
memcpy(&Buffer[BufSize], &Router, sizeof(Router));
BufSize += sizeof(Router);
}
// now write back the option value
DHCP_OPTION_DATA_ELEMENT DataElement = {DhcpBinaryDataOption };
DHCP_OPTION_DATA Data = { 1, &DataElement };
DataElement.Element.BinaryDataOption.DataLength = BufSize;
DataElement.Element.BinaryDataOption.Data = Buffer;
optValue->SetData( &Data );
delete Buffer;
}
}
}
BOOL COptionsCfgPropPage::OnApply()
{
BOOL bErrors = FALSE;
DWORD err = 0;
LPCTSTR pClassName;
COptionsConfig * pOptConfig = reinterpret_cast<COptionsConfig *>(GetHolder());
LPWSTR pszServerAddr = pOptConfig->GetServerAddress();
if (IsDirty())
{
BEGIN_WAIT_CURSOR;
// loop through all vendors first
POSITION posv = ((COptionsConfig *) GetHolder())->m_listVendorClasses.GetHeadPosition();
while (posv)
{
CVendorTracker * pVendorTracker = ((COptionsConfig *) GetHolder())->m_listVendorClasses.GetNext(posv);
// loop through all classes and see if we have any options we need to update
POSITION pos = pVendorTracker->m_listUserClasses.GetHeadPosition();
while (pos)
{
CClassTracker * pClassTracker = pVendorTracker->m_listUserClasses.GetNext(pos);
pClassName = pClassTracker->m_strClassName.IsEmpty() ? NULL : (LPCTSTR) pClassTracker->m_strClassName;
POSITION posOption = pClassTracker->m_listOptions.GetHeadPosition();
while (posOption)
{
COptionTracker * pCurOptTracker = pClassTracker->m_listOptions.GetNext(posOption);
if (pCurOptTracker->IsDirty())
{
// we need to update this option
CDhcpOption * pCurOption = pCurOptTracker->m_pOption;
CDhcpOptionValue & optValue = pCurOption->QueryValue();
// check to see if the option has changed
if ((pCurOptTracker->GetInitialState() == OPTION_STATE_INACTIVE) &&
(pCurOptTracker->GetCurrentState() == OPTION_STATE_INACTIVE))
{
// the state hasn't changed, the user must have changed the
// state and then restored it to its original value
err = ERROR_SUCCESS;
}
else
if ((pCurOptTracker->GetInitialState() == OPTION_STATE_ACTIVE) &&
(pCurOptTracker->GetCurrentState() == OPTION_STATE_INACTIVE))
{
// if it is a vendor specific or class ID option, call the V5 api
if ( pOptConfig->m_liServerVersion.QuadPart >= DHCP_NT5_VERSION)
{
err = ::DhcpRemoveOptionValueV5(pszServerAddr,
pCurOption->IsVendor() ? DHCP_FLAGS_OPTION_IS_VENDOR : 0,
pCurOption->QueryId(),
(LPTSTR) pClassName,
(LPTSTR) pCurOption->GetVendor(),
&pOptConfig->m_pOptionValueEnum->m_dhcpOptionScopeInfo ) ;
}
else
{
// need to remove this option for either global, scope or res client
err = ::DhcpRemoveOptionValue(pszServerAddr,
pCurOption->QueryId(),
&pOptConfig->m_pOptionValueEnum->m_dhcpOptionScopeInfo ) ;
}
}
else
{
// check option 33
if ((pCurOption->QueryId() == 33 || pCurOption->QueryId() == 21) &&
(pCurOption->QueryValue().QueryUpperBound()) % 2 != 0)
{
// special case for option 33 & 21. Make sure it is a set of IP addres pairs
// and make sure we pick the right page to select
int nId = pClassName ? 1 : 0;
PropSheet_SetCurSel(GetHolder()->GetSheetWindow(), GetSafeHwnd(), nId);
SelectOption(pCurOption);
::DhcpMessageBox(IDS_ERR_OPTION_ADDR_PAIRS);
m_listctrlOptions.SetFocus();
return 0;
}
// we are just updating this option
DHCP_OPTION_DATA * pOptData;
err = optValue.CreateOptionDataStruct(&pOptData);
if (err)
{
::DhcpMessageBox(err);
RESTORE_WAIT_CURSOR;
bErrors = TRUE;
continue;
}
// if it is a vendor specific or class ID option, call the V5 api
if ( ((COptionsConfig *)GetHolder())->m_liServerVersion.QuadPart >= DHCP_NT5_VERSION )
{
err = ::DhcpSetOptionValueV5(pszServerAddr,
pCurOption->IsVendor() ? DHCP_FLAGS_OPTION_IS_VENDOR : 0,
pCurOption->QueryId(),
(LPTSTR) pClassName,
(LPTSTR) pCurOption->GetVendor(),
&pOptConfig->m_pOptionValueEnum->m_dhcpOptionScopeInfo,
pOptData);
}
else
{
err = ::DhcpSetOptionValue(pszServerAddr,
pCurOption->QueryId(),
&pOptConfig->m_pOptionValueEnum->m_dhcpOptionScopeInfo,
pOptData);
}
}
if (err)
{
::DhcpMessageBox(err);
RESTORE_WAIT_CURSOR;
bErrors = TRUE;
}
else
{
// all done with this option. Mark as clean and update
// the new initial state to the current state.
pCurOptTracker->SetDirty(FALSE);
pCurOptTracker->SetInitialState(pCurOptTracker->GetCurrentState());
}
} // endif option->IsDirty()
} // while user class options
} // while User class loop
} // while Vendor loop
END_WAIT_CURSOR;
}// endif IsDirty()
if (bErrors)
return 0;
else
{
BOOL bRet = CPropertyPageBase::OnApply();
if (bRet == FALSE)
{
// Something bad happened... grab the error code
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
::DhcpMessageBox(GetHolder()->GetError());
}
return bRet;
}
}
// need to refresh the UI on the main app thread...
BOOL COptionsCfgPropPage::OnPropertyChange(BOOL bScope, LONG_PTR *ChangeMask)
{
SPITFSNode spNode;
spNode = GetHolder()->GetNode();
CMTDhcpHandler * pMTHandler = GETHANDLER(CMTDhcpHandler, spNode);
pMTHandler->OnRefresh(spNode, NULL, 0, 0, 0);
return FALSE;
}
//
// See if any of the edit fields have been changed and perform the alteration.
// Return TRUE if the value was changed.
//
BOOL COptionsCfgPropPage::HandleValueEdit()
{
LONG err = 0;
int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
if (nSelectedIndex > -1)
{
COptionTracker * pOptTracker =
reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
CEdit * pDwordEdit = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_DWORD));
CWndIpAddress * pIpAddr = reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_ADDRESS));
CEdit * pString = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_STRING_VALUE));
CDhcpOptionValue & dhcValue = pOptTracker->m_pOption->QueryValue();
DHCP_OPTION_DATA_TYPE dhcType = dhcValue.QueryDataType();
DHCP_IP_ADDRESS dhipa ;
CString strEdit;
BOOL bModified = FALSE;
switch ( dhcType )
{
case DhcpByteOption:
case DhcpWordOption:
case DhcpDWordOption:
case DhcpBinaryDataOption:
{
DWORD dwResult;
DWORD dwMask = 0xFFFFFFFF;
if (dhcType == DhcpByteOption)
{
dwMask = 0xFF;
}
else if (dhcType == DhcpWordOption)
{
dwMask = 0xFFFF;
}
if (!FGetCtrlDWordValue(pDwordEdit->GetSafeHwnd(), &dwResult, 0, dwMask))
return FALSE;
// only mark this dirty if the value has changed as we may just
// be updating the UI
if (dwResult != (DWORD) dhcValue.QueryNumber(0))
{
bModified = TRUE ;
(void)dhcValue.SetNumber(dwResult, 0);
ASSERT(err == FALSE);
}
}
break ;
case DhcpDWordDWordOption:
{
DWORD_DWORD dwdw;
CString strValue;
pDwordEdit->GetWindowText(strValue);
UtilConvertStringToDwordDword(strValue, &dwdw);
// only mark this dirty if the value has changed as we may just
// be updating the UI
if ((dwdw.DWord1 != dhcValue.QueryDwordDword(0).DWord1) &&
(dwdw.DWord2 != dhcValue.QueryDwordDword(0).DWord2) )
{
bModified = TRUE;
dhcValue.SetDwordDword(dwdw, 0);
}
}
break;
case DhcpStringDataOption:
pString->GetWindowText( strEdit );
// only mark this dirty if the value has changed as we may just
// be updating the UI
if (strEdit.Compare(dhcValue.QueryString(0)) != 0)
{
bModified = TRUE;
err = dhcValue.SetString( strEdit, 0 );
}
break ;
case DhcpIpAddressOption:
if (!pIpAddr->GetModify())
{
break ;
}
if ( !pIpAddr->IsBlank() )
{
if ( !pIpAddr->GetAddress(&dhipa) )
{
err = ERROR_INVALID_PARAMETER;
break;
}
// only mark this dirty if the value has changed as we may just
// be updating the UI
if (dhipa != dhcValue.QueryIpAddr(0))
{
bModified = TRUE ;
err = dhcValue.SetIpAddr( dhipa, 0 );
}
}
break;
default:
Trace0("invalid value type in HandleValueEdit");
Assert( FALSE );
err = ERROR_INVALID_PARAMETER;
break;
}
if (err)
{
::DhcpMessageBox(err);
}
else if (bModified)
{
pOptTracker->SetDirty(TRUE);
SetDirty(TRUE);
}
}
return err == 0 ;
}
/////////////////////////////////////////////////////////////////////////////
//
// COptionCfgGeneral page
//
/////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(COptionCfgGeneral, COptionsCfgPropPage)
//{{AFX_MSG_MAP(COptionCfgGeneral)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
IMPLEMENT_DYNCREATE(COptionCfgGeneral, COptionsCfgPropPage)
COptionCfgGeneral::COptionCfgGeneral()
: COptionsCfgPropPage(IDP_OPTION_BASIC)
{
//{{AFX_DATA_INIT(COptionCfgGeneral)
//}}AFX_DATA_INIT
}
COptionCfgGeneral::COptionCfgGeneral(UINT nIDTemplate, UINT nIDCaption)
: COptionsCfgPropPage(nIDTemplate, nIDCaption)
{
}
COptionCfgGeneral::~COptionCfgGeneral()
{
}
void COptionCfgGeneral::DoDataExchange(CDataExchange* pDX)
{
COptionsCfgPropPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COptionCfgGeneral)
//}}AFX_DATA_MAP
}
BOOL COptionCfgGeneral::OnInitDialog()
{
COptionsCfgPropPage::OnInitDialog();
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// check to see if we should focus on a particular option
COptionsConfig * pOptionsConfig = (COptionsConfig *) GetHolder();
if (pOptionsConfig->m_dhcpStartId != 0xffffffff)
{
// check to see if this option is on the advanced page
if (!pOptionsConfig->m_strStartVendor.IsEmpty() ||
!pOptionsConfig->m_strStartClass.IsEmpty())
{
// this option is on the advanced page
::PostMessage(pOptionsConfig->GetSheetWindow(), PSM_SETCURSEL, (WPARAM)1, NULL);
return TRUE;
}
// find the option to select
OnSelectOption(0,0);
}
SetDirty(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
/////////////////////////////////////////////////////////////////////////////
//
// COptionCfgAdvanced page
//
/////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(COptionCfgAdvanced, COptionsCfgPropPage)
//{{AFX_MSG_MAP(COptionCfgAdvanced)
ON_CBN_SELENDOK(IDC_COMBO_USER_CLASS, OnSelendokComboUserClass)
ON_CBN_SELENDOK(IDC_COMBO_VENDOR_CLASS, OnSelendokComboVendorClass)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_SELECTCLASSES, OnSelectClasses)
END_MESSAGE_MAP()
IMPLEMENT_DYNCREATE(COptionCfgAdvanced, COptionsCfgPropPage)
COptionCfgAdvanced::COptionCfgAdvanced()
: COptionsCfgPropPage(IDP_OPTION_ADVANCED)
{
//{{AFX_DATA_INIT(COptionCfgAdvanced)
//}}AFX_DATA_INIT
m_helpMap.BuildMap(DhcpGetHelpMap(IDP_OPTION_ADVANCED));
}
COptionCfgAdvanced::COptionCfgAdvanced(UINT nIDTemplate, UINT nIDCaption)
: COptionsCfgPropPage(nIDTemplate, nIDCaption)
{
m_helpMap.BuildMap(DhcpGetHelpMap(IDP_OPTION_ADVANCED));
}
COptionCfgAdvanced::~COptionCfgAdvanced()
{
}
void COptionCfgAdvanced::DoDataExchange(CDataExchange* pDX)
{
COptionsCfgPropPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COptionCfgAdvanced)
DDX_Control(pDX, IDC_COMBO_USER_CLASS, m_comboUserClasses);
DDX_Control(pDX, IDC_COMBO_VENDOR_CLASS, m_comboVendorClasses);
//}}AFX_DATA_MAP
}
BOOL COptionCfgAdvanced::OnInitDialog()
{
CPropertyPageBase::OnInitDialog();
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// initialize the list control
InitListCtrl();
// initialize the option data
// this gets done in the general page init, only needs
// to be done once
/*
DWORD dwErr = ((COptionsConfig *) GetHolder())->InitData();
if (dwErr != ERROR_SUCCESS)
{
// CODEWORK: need to exit gracefull if this happens
::DhcpMessageBox(dwErr);
}
*/
// add the standard vendor class name
int nSel;
CString strVendor, strClass;
strVendor.LoadString(IDS_INFO_NAME_DHCP_DEFAULT);
nSel = m_comboVendorClasses.AddString(strVendor);
m_comboVendorClasses.SetCurSel(nSel);
// add the default user class name
strClass.LoadString(IDS_USER_STANDARD);
nSel = m_comboUserClasses.AddString(strClass);
m_comboUserClasses.SetCurSel(nSel);
// now add all the other classes
SPITFSNode spNode;
spNode = ((COptionsConfig *) GetHolder())->GetServerNode();
CDhcpServer * pServer = GETHANDLER(CDhcpServer, spNode);
CClassInfoArray ClassInfoArray;
// add all the classes to the appropriate classes to the dropdown
pServer->GetClassInfoArray(ClassInfoArray);
for (int i = 0; i < ClassInfoArray.GetSize(); i++)
{
if (!ClassInfoArray[i].bIsVendor)
m_comboUserClasses.AddString(ClassInfoArray[i].strName);
else
m_comboVendorClasses.AddString(ClassInfoArray[i].strName);
}
// now fill the options listbox with whatever class is selected
((COptionsConfig *) GetHolder())->FillOptions(strVendor, strClass, m_listctrlOptions);
m_bNoClasses = FALSE;
// Create the type control switcher
m_cgsTypes.Create(this,IDC_DATA_ENTRY_ANCHOR,cgsPreCreateAll);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_NONE, IDD_DATA_ENTRY_NONE, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_DWORD, IDD_DATA_ENTRY_DWORD, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_IPADDRESS, IDD_DATA_ENTRY_IPADDRESS, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_IPADDRESS_ARRAY, IDD_DATA_ENTRY_IPADDRESS_ARRAY, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_STRING, IDD_DATA_ENTRY_STRING, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_BINARY_ARRAY, IDD_DATA_ENTRY_BINARY_ARRAY, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_BINARY, IDD_DATA_ENTRY_BINARY, NULL);
m_cgsTypes.AddGroup(IDC_DATA_ENTRY_ROUTE_ARRAY, IDD_DATA_ENTRY_ROUTE_ARRAY, NULL);
SwitchDataEntry(-1, -1, 0, TRUE);
m_bInitialized = TRUE;
// check to see if we should focus on a particular option
COptionsConfig * pOptionsConfig = (COptionsConfig *) GetHolder();
if (pOptionsConfig->m_dhcpStartId != 0xffffffff)
{
// yes, first select the appropriate vendor/ user class
Assert(!pOptionsConfig->m_strStartVendor.IsEmpty() ||
!pOptionsConfig->m_strStartClass.IsEmpty());
if (!pOptionsConfig->m_strStartVendor.IsEmpty())
m_comboVendorClasses.SelectString(-1, pOptionsConfig->m_strStartVendor);
if (!pOptionsConfig->m_strStartClass.IsEmpty())
m_comboUserClasses.SelectString(-1, pOptionsConfig->m_strStartClass);
// update the list of options
OnSelendokComboVendorClass();
// now find the option
OnSelectOption(0,0);
}
SetDirty(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void COptionCfgAdvanced::OnSelendokComboUserClass()
{
OnSelendokComboVendorClass();
}
void COptionCfgAdvanced::OnSelendokComboVendorClass()
{
// If we have classes defined then its time to switch up the list ctrl
if (m_bNoClasses == FALSE)
{
CString strSelectedVendor, strSelectedClass;
int nSelVendorIndex = m_comboVendorClasses.GetCurSel();
int nSelClassIndex = m_comboUserClasses.GetCurSel();
m_comboVendorClasses.GetLBText(nSelVendorIndex, strSelectedVendor);
m_comboUserClasses.GetLBText(nSelClassIndex, strSelectedClass);
// mark the page as not initiailzed while we redo the options
m_bInitialized = FALSE;
m_listctrlOptions.DeleteAllItems();
((COptionsConfig *) GetHolder())->FillOptions(strSelectedVendor, strSelectedClass, m_listctrlOptions);
m_bInitialized = TRUE;
}
}
long COptionCfgAdvanced::OnSelectClasses(UINT wParam, LONG lParam)
{
CString * pstrVendor = (CString *) ULongToPtr(wParam);
CString * pstrClass = (CString *) ULongToPtr(lParam);
if (pstrVendor->IsEmpty())
pstrVendor->LoadString(IDS_INFO_NAME_DHCP_DEFAULT);
if (pstrClass->IsEmpty())
pstrClass->LoadString(IDS_USER_STANDARD);
m_comboVendorClasses.SelectString(-1, *pstrVendor);
m_comboUserClasses.SelectString(-1, *pstrClass);
// update the list of options
OnSelendokComboVendorClass();
return 0;
}