Windows2003-3790/net/mmc/dhcp/mscope.cpp
2020-09-30 16:53:55 +02:00

3162 lines
105 KiB
C++

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
/**********************************************************************/
/*
mscope.cpp
This file contains the implementation for the multicast scope node.
FILE HISTORY:
9/25/97 EricDav Created
*/
#include "stdafx.h"
#include "server.h" // Server definition
#include "nodes.h" // Result pane node definitions
#include "mscope.h" // mscope definition
#include "addexcl.h"
#include "mscopepp.h" // properties of the mScope
#include "dlgrecon.h" // reconcile dialog
/*---------------------------------------------------------------------------
GetLangTag
Sets the language tag based on the name
Author: EricDav
---------------------------------------------------------------------------*/
void
GetLangTag
(
CString & strLangTag
)
{
char b1[32], b2[32];
static char buff[80];
GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO639LANGNAME, b1, sizeof(b1));
GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO3166CTRYNAME, b2, sizeof(b2));
ZeroMemory(buff, sizeof(buff));
if (_stricmp(b1, b2))
sprintf(buff, "%s-%s", b1, b2);
else
strcpy(buff, b1);
strLangTag = buff;
}
/*---------------------------------------------------------------------------
Class CDhcpMScope implementation
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
Function Name Here
Description
Author: EricDav
---------------------------------------------------------------------------*/
CDhcpMScope::CDhcpMScope
(
ITFSComponentData* pTFSComponentData
) : CMTDhcpHandler(pTFSComponentData)
{
}
CDhcpMScope::~CDhcpMScope()
{
}
/*!--------------------------------------------------------------------------
CDhcpMScope::InitializeNode
Initializes node specific data
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::InitializeNode
(
ITFSNode * pNode
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CString strDisplayName;
BuildDisplayName(&strDisplayName, m_SubnetInfo.SubnetName);
SetDisplayName(strDisplayName);
if (m_SubnetInfo.SubnetState == DhcpSubnetDisabled)
{
m_strState.LoadString(IDS_SCOPE_INACTIVE);
}
else
{
m_strState.LoadString(IDS_SCOPE_ACTIVE);
}
// Make the node immediately visible
pNode->SetVisibilityState(TFS_VIS_SHOW);
pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
pNode->SetData(TFS_DATA_USER, (LPARAM) this);
pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_MSCOPE);
SetColumnStringIDs(&aColumns[DHCPSNAP_MSCOPE][0]);
SetColumnWidths(&aColumnWidths[DHCPSNAP_MSCOPE][0]);
return hrOK;
}
/*---------------------------------------------------------------------------
CDhcpMScope::OnCreateNodeId2
Returns a unique string for this node
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT CDhcpMScope::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
{
const GUID * pGuid = pNode->GetNodeType();
CString strNode, strGuid;
StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
strGuid.ReleaseBuffer();
// id string is server name, scope name and guid.
strNode = GetServerObject()->GetName();
strNode += GetName() + strGuid;
strId = strNode;
return hrOK;
}
/*---------------------------------------------------------------------------
CDhcpMScope::GetImageIndex
Description
Author: EricDav
---------------------------------------------------------------------------*/
int
CDhcpMScope::GetImageIndex(BOOL bOpenImage)
{
int nIndex = -1;
switch (m_nState)
{
// TODO: these need to be updated with new busy state icons
case loading:
if (bOpenImage)
nIndex = (IsEnabled()) ? ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN_BUSY : ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN_BUSY;
else
nIndex = (IsEnabled()) ? ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED_BUSY : ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED_BUSY;
return nIndex;
case notLoaded:
case loaded:
if (bOpenImage)
nIndex = (IsEnabled()) ? ICON_IDX_SCOPE_FOLDER_OPEN : ICON_IDX_SCOPE_INACTIVE_FOLDER_OPEN;
else
nIndex = (IsEnabled()) ? ICON_IDX_SCOPE_FOLDER_CLOSED : ICON_IDX_SCOPE_INACTIVE_FOLDER_CLOSED;
break;
case unableToLoad:
if (bOpenImage)
nIndex = (IsEnabled()) ? ICON_IDX_SCOPE_FOLDER_OPEN_LOST_CONNECTION : ICON_IDX_SCOPE_INACTIVE_FOLDER_OPEN_LOST_CONNECTION;
else
nIndex = (IsEnabled()) ? ICON_IDX_SCOPE_FOLDER_CLOSED_LOST_CONNECTION : ICON_IDX_SCOPE_INACTIVE_FOLDER_CLOSED_LOST_CONNECTION;
return nIndex;
default:
ASSERT(FALSE);
}
if (m_spServerNode && IsEnabled())
{
CDhcpServer * pServer = GetServerObject();
LPDHCP_MCAST_MIB_INFO pMibInfo = pServer->DuplicateMCastMibInfo();
if (!pMibInfo)
return nIndex;
LPMSCOPE_MIB_INFO pScopeMibInfo = pMibInfo->ScopeInfo;
// walk the list of scopes and find our info
for (UINT i = 0; i < pMibInfo->Scopes; i++)
{
// Find our scope stats
if ( (m_SubnetInfo.SubnetName.CompareNoCase(pScopeMibInfo[i].MScopeName) == 0) &&
(m_SubnetInfo.SubnetAddress == pScopeMibInfo[i].MScopeId) )
{
int nPercentInUse;
if ((pScopeMibInfo[i].NumAddressesInuse + pScopeMibInfo[i].NumAddressesFree) == 0)
nPercentInUse = 0;
else
nPercentInUse = (pScopeMibInfo[i].NumAddressesInuse * 100) / (pScopeMibInfo[i].NumAddressesInuse + pScopeMibInfo[i].NumAddressesFree);
// look to see if this scope meets the warning or red flag case
if (pScopeMibInfo[i].NumAddressesFree == 0)
{
// red flag case, no addresses free, this is the highest
// level of warning, so break out of the loop if we set this.
if (bOpenImage)
nIndex = ICON_IDX_SCOPE_FOLDER_OPEN_ALERT;
else
nIndex = ICON_IDX_SCOPE_FOLDER_CLOSED_ALERT;
break;
}
else
if (nPercentInUse >= SCOPE_WARNING_LEVEL)
{
// warning condition if Num Addresses in use is greater than
// some pre-defined threshold.
if (bOpenImage)
nIndex = ICON_IDX_SCOPE_FOLDER_OPEN_WARNING;
else
nIndex = ICON_IDX_SCOPE_FOLDER_CLOSED_WARNING;
}
break;
}
}
pServer->FreeDupMCastMibInfo(pMibInfo);
}
return nIndex;
}
/*---------------------------------------------------------------------------
Overridden base handler functions
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
CDhcpMScope::OnAddMenuItems
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CDhcpMScope::OnAddMenuItems
(
ITFSNode * pNode,
LPCONTEXTMENUCALLBACK pContextMenuCallback,
LPDATAOBJECT lpDataObject,
DATA_OBJECT_TYPES type,
DWORD dwType,
long * pInsertionAllowed
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
LONG fFlags = 0, fLoadingFlags = 0;
HRESULT hr = S_OK;
CString strMenuText;
if ( m_nState != loaded )
{
fFlags |= MF_GRAYED;
}
if ( m_nState == loading)
{
fLoadingFlags = MF_GRAYED;
}
if (type == CCT_SCOPE)
{
//
// these menu items go in the new menu,
// only visible from scope pane
//
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
{
strMenuText.LoadString(IDS_SCOPE_SHOW_STATISTICS);
hr = LoadAndAddMenuItem( pContextMenuCallback,
strMenuText,
IDS_SCOPE_SHOW_STATISTICS,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
fFlags );
ASSERT( SUCCEEDED(hr) );
// separator
hr = LoadAndAddMenuItem( pContextMenuCallback,
strMenuText,
0,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
MF_SEPARATOR);
ASSERT( SUCCEEDED(hr) );
// reconcile
strMenuText.LoadString(IDS_SCOPE_RECONCILE);
hr = LoadAndAddMenuItem( pContextMenuCallback,
strMenuText,
IDS_SCOPE_RECONCILE,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
fFlags );
ASSERT( SUCCEEDED(hr) );
// separator
hr = LoadAndAddMenuItem( pContextMenuCallback,
strMenuText,
0,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
MF_SEPARATOR);
ASSERT( SUCCEEDED(hr) );
// activate/deactivate
if (m_SubnetInfo.SubnetState == DhcpSubnetDisabled)
{
strMenuText.LoadString(IDS_SCOPE_ACTIVATE);
hr = LoadAndAddMenuItem( pContextMenuCallback,
strMenuText,
IDS_SCOPE_ACTIVATE,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
fFlags );
ASSERT( SUCCEEDED(hr) );
}
else
{
strMenuText.LoadString(IDS_SCOPE_DEACTIVATE);
hr = LoadAndAddMenuItem( pContextMenuCallback,
strMenuText,
IDS_SCOPE_DEACTIVATE,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
fFlags );
ASSERT( SUCCEEDED(hr) );
}
}
}
return hr;
}
/*---------------------------------------------------------------------------
CDhcpMScope::OnCommand
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CDhcpMScope::OnCommand
(
ITFSNode * pNode,
long nCommandId,
DATA_OBJECT_TYPES type,
LPDATAOBJECT pDataObject,
DWORD dwType
)
{
HRESULT hr = S_OK;
switch (nCommandId)
{
case IDS_ACTIVATE:
case IDS_DEACTIVATE:
case IDS_SCOPE_ACTIVATE:
case IDS_SCOPE_DEACTIVATE:
OnActivateScope(pNode);
break;
case IDS_REFRESH:
OnRefresh(pNode, pDataObject, dwType, 0, 0);
break;
case IDS_SCOPE_SHOW_STATISTICS:
OnShowScopeStats(pNode);
break;
case IDS_SCOPE_RECONCILE:
OnReconcileScope(pNode);
break;
case IDS_DELETE:
OnDelete(pNode);
break;
default:
break;
}
return hr;
}
/*---------------------------------------------------------------------------
CDhcpMScope::CreatePropertyPages
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CDhcpMScope::CreatePropertyPages
(
ITFSNode * pNode,
LPPROPERTYSHEETCALLBACK lpProvider,
LPDATAOBJECT pDataObject,
LONG_PTR handle,
DWORD dwType
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = hrOK;
DWORD dwError;
DWORD dwDynDnsFlags;
SPIComponentData spComponentData;
LARGE_INTEGER liVersion;
CDhcpServer * pServer;
DHCP_IP_RANGE dhcpIpRange;
//
// Create the property page
//
m_spNodeMgr->GetComponentData(&spComponentData);
CMScopeProperties * pScopeProp =
new CMScopeProperties(pNode, spComponentData, m_spTFSCompData, NULL);
// Get the Server version and set it in the property sheet
pServer = GetServerObject();
pServer->GetVersion(liVersion);
pScopeProp->SetVersion(liVersion);
// Set scope specific data in the prop sheet
pScopeProp->m_pageGeneral.m_SubnetInfo = m_SubnetInfo;
BEGIN_WAIT_CURSOR;
ZeroMemory(&dhcpIpRange, sizeof(dhcpIpRange));
dwError = GetIpRange(&dhcpIpRange);
if (dwError != ERROR_SUCCESS)
{
::DhcpMessageBox(dwError);
goto Cleanup;
}
pScopeProp->m_pageGeneral.m_ScopeCfg.m_dwStartAddress = dhcpIpRange.StartAddress;
pScopeProp->m_pageGeneral.m_ScopeCfg.m_dwEndAddress = dhcpIpRange.EndAddress;
pScopeProp->m_pageGeneral.m_uImage = GetImageIndex(FALSE);
dwError = GetLeaseTime(&pScopeProp->m_pageGeneral.m_ScopeCfg.m_dwLeaseTime);
END_WAIT_CURSOR;
GetLifetime(&pScopeProp->m_pageLifetime.m_Expiry);
//
// Object gets deleted when the page is destroyed
//
Assert(lpProvider != NULL);
return pScopeProp->CreateModelessSheet(lpProvider, handle);
Cleanup:
delete pScopeProp;
return hrFalse;
}
/*---------------------------------------------------------------------------
CDhcpMScope::OnPropertyChange
Description
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::OnPropertyChange
(
ITFSNode * pNode,
LPDATAOBJECT pDataobject,
DWORD dwType,
LPARAM arg,
LPARAM lParam
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CMScopeProperties * pScopeProp = reinterpret_cast<CMScopeProperties *>(lParam);
LONG_PTR changeMask = 0;
// tell the property page to do whatever now that we are back on the
// main thread
pScopeProp->OnPropertyChange(TRUE, &changeMask);
pScopeProp->AcknowledgeNotify();
if (changeMask)
pNode->ChangeNode(changeMask);
return hrOK;
}
/*!--------------------------------------------------------------------------
CDhcpMScope::GetString
Returns string information for display in the result pane columns
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP_(LPCTSTR)
CDhcpMScope::GetString
(
ITFSNode * pNode,
int nCol
)
{
switch (nCol) {
case 0:
return GetDisplayName();
case 1:
return m_strState;
case 2:
return m_SubnetInfo.SubnetComment;
}
return NULL;
}
STDMETHODIMP
CDhcpMScope::DestroyHandler( ITFSNode *pNode )
{
// Cleanup the stats dialog
WaitForStatisticsWindow( &m_dlgStats );
return CMTDhcpHandler::DestroyHandler( pNode );
} // CDhcpMScope::DestoryHandler()
/*---------------------------------------------------------------------------
CDhcpMScope::CompareItems
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP_(int)
CDhcpMScope::CompareItems
(
ITFSComponent * pComponent,
MMC_COOKIE cookieA,
MMC_COOKIE cookieB,
int nCol
)
{
SPITFSNode spNode1, spNode2;
m_spNodeMgr->FindNode(cookieA, &spNode1);
m_spNodeMgr->FindNode(cookieB, &spNode2);
int nCompare = 0;
return nCompare;
}
/*!--------------------------------------------------------------------------
CDhcpServer::OnDelete
The base handler calls this when MMC sends a MMCN_DELETE for a
scope pane item. We just call our delete command handler.
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::OnDelete
(
ITFSNode * pNode,
LPARAM arg,
LPARAM lParam
)
{
return OnDelete(pNode);
}
/*---------------------------------------------------------------------------
CDhcpMScope::OnResultDelete
This function is called when we are supposed to delete result
pane items. We build a list of selected items and then delete them.
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::OnResultDelete
(
ITFSComponent * pComponent,
LPDATAOBJECT pDataObject,
MMC_COOKIE cookie,
LPARAM arg,
LPARAM param
)
{
HRESULT hr = hrOK;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return hr;
}
/*!--------------------------------------------------------------------------
CDhcpMScope::OnGetResultViewType
MMC calls this to get the result view information
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::OnGetResultViewType
(
ITFSComponent * pComponent,
MMC_COOKIE cookie,
LPOLESTR * ppViewType,
long * pViewOptions
)
{
*pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
// we still want the default MMC result pane view, we just want
// multiselect, so return S_FALSE
return S_FALSE;
}
/*!--------------------------------------------------------------------------
CDhcpMScope::OnUpdateToolbarButtons
We override this function to show/hide the correct
activate/deactivate buttons
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::OnUpdateToolbarButtons
(
ITFSNode * pNode,
LPDHCPTOOLBARNOTIFY pToolbarNotify
)
{
HRESULT hr = hrOK;
if (pToolbarNotify->bSelect)
{
UpdateToolbarStates();
}
CMTDhcpHandler::OnUpdateToolbarButtons(pNode, pToolbarNotify);
return hr;
}
/*!--------------------------------------------------------------------------
CDhcpMScope::UpdateToolbarStates
Description
Author: EricDav
---------------------------------------------------------------------------*/
void
CDhcpMScope::UpdateToolbarStates()
{
if (( m_SubnetInfo.SubnetState == DhcpSubnetDisabled) ||
( m_SubnetInfo.SubnetState == DhcpSubnetDisabledSwitched ))
{
g_SnapinButtonStates[DHCPSNAP_MSCOPE][TOOLBAR_IDX_ACTIVATE] = ENABLED;
g_SnapinButtonStates[DHCPSNAP_MSCOPE][TOOLBAR_IDX_DEACTIVATE] = HIDDEN;
}
else
{
g_SnapinButtonStates[DHCPSNAP_MSCOPE][TOOLBAR_IDX_ACTIVATE] = HIDDEN;
g_SnapinButtonStates[DHCPSNAP_MSCOPE][TOOLBAR_IDX_DEACTIVATE] = ENABLED;
}
}
/*---------------------------------------------------------------------------
Command Handlers
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
CDhcpmScope::OnActivateScope
Message handler for the scope activate/deactivate menu
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::OnActivateScope
(
ITFSNode * pNode
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
DWORD err = 0;
int nOpenImage, nClosedImage;
DHCP_SUBNET_STATE dhcpOldState = m_SubnetInfo.SubnetState;
if (m_SubnetInfo.SubnetState == DhcpSubnetEnabled)
{
// if they want to disable the scope, confirm
if (AfxMessageBox(IDS_SCOPE_DISABLE_CONFIRM, MB_YESNO) != IDYES)
{
return err;
}
}
m_SubnetInfo.SubnetState = (m_SubnetInfo.SubnetState == DhcpSubnetDisabled) ?
DhcpSubnetEnabled : DhcpSubnetDisabled;
// Tell the scope to update it's state
err = SetInfo();
if (err != 0)
{
::DhcpMessageBox(err);
m_SubnetInfo.SubnetState = dhcpOldState;
}
else
{
// update the icon and the status text
if (m_SubnetInfo.SubnetState == DhcpSubnetDisabled)
{
nOpenImage = ICON_IDX_SCOPE_INACTIVE_FOLDER_OPEN;
nClosedImage = ICON_IDX_SCOPE_INACTIVE_FOLDER_CLOSED;
m_strState.LoadString(IDS_SCOPE_INACTIVE);
}
else
{
nOpenImage = GetImageIndex(TRUE);
nClosedImage = GetImageIndex(FALSE);
m_strState.LoadString(IDS_SCOPE_ACTIVE);
}
pNode->SetData(TFS_DATA_IMAGEINDEX, nClosedImage);
pNode->SetData(TFS_DATA_OPENIMAGEINDEX, nOpenImage);
VERIFY(SUCCEEDED(pNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM)));
// Update the toolbar button
UpdateToolbarStates();
SendUpdateToolbar(pNode, TRUE);
}
return err;
}
/*---------------------------------------------------------------------------
CDhcpMScope::OnReconcileScope
Reconciles the active leases database for this scope
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::OnReconcileScope
(
ITFSNode * pNode
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CReconcileDlg dlgRecon(pNode);
dlgRecon.m_bMulticast = TRUE;
dlgRecon.DoModal();
return hrOK;
}
/*---------------------------------------------------------------------------
CDhcpMScope::OnShowScopeStats()
Description
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::OnShowScopeStats
(
ITFSNode * pNode
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
HRESULT hr = S_OK;
CString strScopeAddress;
// Fill in some information in the stats object.
// CreateNewStatisticsWindow handles the case if the window is
// already visible.
m_dlgStats.SetNode(pNode);
m_dlgStats.SetServer(GetServerIpAddress());
m_dlgStats.SetScopeId(GetScopeId());
m_dlgStats.SetName(GetName());
CreateNewStatisticsWindow(&m_dlgStats,
::FindMMCMainWindow(),
IDD_STATS_NARROW);
return hr;
}
/*---------------------------------------------------------------------------
CDhcpMScope::OnDelete()
Description
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::OnDelete(ITFSNode * pNode)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
HRESULT hr = S_OK;
SPITFSNode spParent;
BOOL fAbortDelete = FALSE;
BOOL fDeactivated = FALSE;
LONG err = 0 ;
CDhcpMScope *pMScope;
// Any property sheets open?
pMScope = GETHANDLER( CDhcpMScope, pNode );
if ( pMScope->HasPropSheetsOpen()) {
AfxMessageBox( IDS_MSG_CLOSE_PROPSHEET );
return S_FALSE;
}
if (::DhcpMessageBox( IsEnabled() ?
IDS_MSG_DELETE_ACTIVE : IDS_MSG_DELETE_SCOPE,
MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION) == IDYES) {
pNode->GetParent(&spParent);
CDhcpServer * pServer = GETHANDLER(CDhcpServer, spParent);
err = pServer->DeleteMScope(pNode);
// delete the statistics window
WaitForStatisticsWindow( &m_dlgStats );
} // if
return hr;
}
/*---------------------------------------------------------------------------
Background thread functionality
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
CDhcpMScope:OnHaveData
Description
Author: EricDav
---------------------------------------------------------------------------*/
void
CDhcpMScope::OnHaveData
(
ITFSNode * pParentNode,
ITFSNode * pNewNode
)
{
LPARAM dwType = pNewNode->GetData(TFS_DATA_TYPE);
UpdateToolbarStates();
switch (dwType)
{
case DHCPSNAP_MSCOPE_LEASES:
pParentNode->AddChild(pNewNode);
m_spActiveLeases.Set(pNewNode);
break;
case DHCPSNAP_ADDRESS_POOL:
pParentNode->AddChild(pNewNode);
m_spAddressPool.Set(pNewNode);
break;
}
// now tell the view to update themselves
ExpandNode(pParentNode, TRUE);
}
/*---------------------------------------------------------------------------
CDhcpMScope::OnHaveData
Description
Author: EricDav
---------------------------------------------------------------------------*/
void
CDhcpMScope::OnHaveData
(
ITFSNode * pParentNode,
LPARAM Data,
LPARAM Type
)
{
// This is how we get non-node data back from the background thread.
if (Type == DHCP_QDATA_SUBNET_INFO)
{
LONG_PTR changeMask = 0;
LPDHCP_MSCOPE_INFO pdhcpSubnetInfo = reinterpret_cast<LPDHCP_MSCOPE_INFO>(Data);
// update the scope name and state based on the info
if (pdhcpSubnetInfo->MScopeName &&
m_SubnetInfo.SubnetName.CompareNoCase(pdhcpSubnetInfo->MScopeName) != 0)
{
SetName(pdhcpSubnetInfo->MScopeName);
changeMask = SCOPE_PANE_CHANGE_ITEM;
}
// update the comment
if (m_SubnetInfo.SubnetComment.CompareNoCase(pdhcpSubnetInfo->MScopeComment) != 0)
{
SetComment(pdhcpSubnetInfo->MScopeComment);
}
if (m_SubnetInfo.SubnetState != pdhcpSubnetInfo->MScopeState)
{
DHCP_SUBNET_STATE dhcpOldState = m_SubnetInfo.SubnetState;
m_SubnetInfo.SubnetState = pdhcpSubnetInfo->MScopeState;
pParentNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
pParentNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
// Update the toolbar button
UpdateToolbarStates();
SendUpdateToolbar(pParentNode, TRUE);
changeMask = SCOPE_PANE_CHANGE_ITEM;
}
// Update our internal struct
m_SubnetInfo.Set(pdhcpSubnetInfo);
if (pdhcpSubnetInfo)
::DhcpRpcFreeMemory(pdhcpSubnetInfo);
if (changeMask)
VERIFY(SUCCEEDED(pParentNode->ChangeNode(changeMask)));
}
}
/*---------------------------------------------------------------------------
CDhcpMScope::OnCreateQuery()
Description
Author: EricDav
---------------------------------------------------------------------------*/
ITFSQueryObject*
CDhcpMScope::OnCreateQuery(ITFSNode * pNode)
{
CDhcpMScopeQueryObj* pQuery = new CDhcpMScopeQueryObj(m_spTFSCompData, m_spNodeMgr);
if ( pQuery == NULL )
return pQuery;
pQuery->m_strServer = GetServerObject(pNode)->GetIpAddress();
pQuery->m_strName = GetName();
return pQuery;
}
/*---------------------------------------------------------------------------
CDhcpMScopeQueryObj::Execute()
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CDhcpMScopeQueryObj::Execute()
{
HRESULT hr = hrOK;
DWORD dwReturn;
LPDHCP_MSCOPE_INFO pMScopeInfo = NULL;
dwReturn = ::DhcpGetMScopeInfo(((LPWSTR) (LPCTSTR)m_strServer),
((LPWSTR) (LPCTSTR)m_strName),
&pMScopeInfo);
if (dwReturn == ERROR_SUCCESS && pMScopeInfo)
{
AddToQueue((LPARAM) pMScopeInfo, DHCP_QDATA_SUBNET_INFO);
}
else
{
Trace1("CDhcpMScopeQueryObj::Execute - DhcpGetMScopeInfo failed! %d\n", dwReturn);
PostError(dwReturn);
return hrFalse;
}
CreateSubcontainers();
return hrFalse;
}
/*---------------------------------------------------------------------------
CDhcpMScope::CreateSubcontainers()
Description
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScopeQueryObj::CreateSubcontainers()
{
HRESULT hr = hrOK;
SPITFSNode spNode;
//
// create the address pool Handler
//
CMScopeAddressPool *pAddressPool = new CMScopeAddressPool(m_spTFSCompData);
CreateContainerTFSNode(&spNode,
&GUID_DhcpMCastAddressPoolNodeType,
pAddressPool,
pAddressPool,
m_spNodeMgr);
// Tell the handler to initialize any specific data
pAddressPool->InitializeNode((ITFSNode *) spNode);
// Add the node as a child to this node
AddToQueue(spNode);
pAddressPool->Release();
spNode.Set(NULL);
//
// create the Active Leases Handler
//
CMScopeActiveLeases *pActiveLeases = new CMScopeActiveLeases(m_spTFSCompData);
CreateContainerTFSNode(&spNode,
&GUID_DhcpMCastActiveLeasesNodeType,
pActiveLeases,
pActiveLeases,
m_spNodeMgr);
// Tell the handler to initialize any specific data
pActiveLeases->InitializeNode((ITFSNode *) spNode);
// Add the node as a child to this node
AddToQueue(spNode);
pActiveLeases->Release();
return hr;
}
/*---------------------------------------------------------------------------
Helper functions
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::BuildDisplayName
(
CString * pstrDisplayName,
LPCTSTR pName
)
{
if (pstrDisplayName)
{
CString strStandard, strName;
strName = pName;
strStandard.LoadString(IDS_MSCOPE_FOLDER);
*pstrDisplayName = strStandard + _T(" [") + strName + _T("] ");
}
return hrOK;
}
HRESULT
CDhcpMScope::SetName
(
LPCWSTR pName
)
{
if (pName != NULL)
{
m_SubnetInfo.SubnetName = pName;
}
CString strDisplayName;
//
// Create the display name for this scope
// Convert DHCP_IP_ADDRES to a string and initialize this object
//
BuildDisplayName(&strDisplayName, pName);
SetDisplayName(strDisplayName);
return hrOK;
}
/*---------------------------------------------------------------------------
CDhcpMScope::GetServerIpAddress()
Description
Author: EricDav
---------------------------------------------------------------------------*/
LPCWSTR
CDhcpMScope::GetServerIpAddress()
{
CDhcpServer * pServer = GetServerObject();
return pServer->GetIpAddress();
}
/*---------------------------------------------------------------------------
CDhcpMScope::GetServerIpAddress
Description
Author: EricDav
---------------------------------------------------------------------------*/
void
CDhcpMScope::GetServerIpAddress(DHCP_IP_ADDRESS * pdhcpIpAddress)
{
CDhcpServer * pServer = GetServerObject();
pServer->GetIpAddress(pdhcpIpAddress);
}
/*---------------------------------------------------------------------------
CDhcpMScope::GetServerVersion
Description
Author: EricDav
---------------------------------------------------------------------------*/
void
CDhcpMScope::GetServerVersion
(
LARGE_INTEGER& liVersion
)
{
CDhcpServer * pServer = GetServerObject();
pServer->GetVersion(liVersion);
}
/*---------------------------------------------------------------------------
CDhcpMScope::InitMScopeInfo()
Updates the scope's information
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::InitMScopeInfo
(
LPDHCP_MSCOPE_INFO pMScopeInfo
)
{
HRESULT hr = hrOK;
m_SubnetInfo.Set(pMScopeInfo);
return hr;
}
/*---------------------------------------------------------------------------
CDhcpMScope::InitMScopeInfo()
Updates the scope's information
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CDhcpMScope::InitMScopeInfo
(
CSubnetInfo & subnetInfo
)
{
HRESULT hr = hrOK;
m_SubnetInfo = subnetInfo;
return hr;
}
/*---------------------------------------------------------------------------
CDhcpMScope::SetInfo()
Updates the scope's information
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::SetInfo
(
LPCTSTR pNewName
)
{
DWORD err = ERROR_SUCCESS;
DHCP_MSCOPE_INFO dhcpMScopeInfo = {0};
dhcpMScopeInfo.MScopeName = (pNewName) ? (LPWSTR) pNewName : (LPTSTR) ((LPCTSTR) m_SubnetInfo.SubnetName);
dhcpMScopeInfo.MScopeComment = (LPTSTR) ((LPCTSTR) m_SubnetInfo.SubnetComment);
dhcpMScopeInfo.MScopeId = m_SubnetInfo.SubnetAddress;
dhcpMScopeInfo.MScopeAddressPolicy = m_SubnetInfo.MScopeAddressPolicy;
dhcpMScopeInfo.MScopeState = m_SubnetInfo.SubnetState;
dhcpMScopeInfo.MScopeFlags = 0;
dhcpMScopeInfo.ExpiryTime = m_SubnetInfo.ExpiryTime;
dhcpMScopeInfo.TTL = m_SubnetInfo.TTL;
// gotta fill in the language ID based on the name
GetLangTag(m_SubnetInfo.LangTag);
dhcpMScopeInfo.LangTag = (LPWSTR) ((LPCTSTR) m_SubnetInfo.LangTag);
GetServerIpAddress(&dhcpMScopeInfo.PrimaryHost.IpAddress);
// Review : ericdav - do we need to fill these in?
dhcpMScopeInfo.PrimaryHost.NetBiosName = NULL;
dhcpMScopeInfo.PrimaryHost.HostName = NULL;
err = ::DhcpSetMScopeInfo(GetServerIpAddress(),
(LPWSTR) ((LPCTSTR) m_SubnetInfo.SubnetName),
&dhcpMScopeInfo,
FALSE);
// update the scope name if we are changing the name
if (err == ERROR_SUCCESS &&
pNewName)
{
m_SubnetInfo.SubnetName = pNewName;
}
return err;
}
/*---------------------------------------------------------------------------
CDhcpMScope::GetLeaseTime
Gets the lease time for this scope
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::GetLeaseTime
(
LPDWORD pdwLeaseTime
)
{
//
// Check option -- the lease duration
//
DWORD dwLeaseTime = 0;
DWORD err = ERROR_SUCCESS;
DHCP_OPTION_VALUE * poptValue = NULL;
err = GetOptionValue(MADCAP_OPTION_LEASE_TIME, &poptValue);
if (err != ERROR_SUCCESS)
{
Trace1("CDhcpScope::GetLeaseTime - couldn't get lease duration!! %d \n", err);
dwLeaseTime = 0;
}
else
{
if (poptValue->Value.Elements != NULL)
dwLeaseTime = poptValue->Value.Elements[0].Element.DWordOption;
if (poptValue)
::DhcpRpcFreeMemory(poptValue);
}
*pdwLeaseTime = dwLeaseTime;
return err;
}
/*---------------------------------------------------------------------------
CDhcpMScope::SetLeaseTime
Sets the lease time for this scope
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::SetLeaseTime
(
DWORD dwLeaseTime
)
{
DWORD err = 0;
//
// Set lease duration
//
CDhcpOption dhcpOption (MADCAP_OPTION_LEASE_TIME, DhcpDWordOption , _T(""), _T(""));
dhcpOption.QueryValue().SetNumber(dwLeaseTime);
err = SetOptionValue(&dhcpOption);
return err;
}
/*---------------------------------------------------------------------------
CDhcpMScope::GetLifetime
Gets the madcap scope lifetime
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::GetLifetime
(
DATE_TIME * pdtLifetime
)
{
DWORD err = ERROR_SUCCESS;
if (pdtLifetime)
{
pdtLifetime->dwLowDateTime = m_SubnetInfo.ExpiryTime.dwLowDateTime;
pdtLifetime->dwHighDateTime = m_SubnetInfo.ExpiryTime.dwHighDateTime;
}
return err;
}
/*---------------------------------------------------------------------------
CDhcpMScope::SetLifetime
Sets the madcap scope lifetime
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::SetLifetime
(
DATE_TIME * pdtLifetime
)
{
DWORD err = 0;
if (pdtLifetime)
{
m_SubnetInfo.ExpiryTime.dwLowDateTime = pdtLifetime->dwLowDateTime;
m_SubnetInfo.ExpiryTime.dwHighDateTime = pdtLifetime->dwHighDateTime;
}
return err;
}
/*---------------------------------------------------------------------------
CDhcpMScope::GetTTL
Gets the TTL for this multicast scope
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::GetTTL
(
LPBYTE pbTTL
)
{
DWORD err = 0;
if (pbTTL)
*pbTTL = m_SubnetInfo.TTL;
return err;
}
/*---------------------------------------------------------------------------
CDhcpMScope::SetTTL
Sets the least time for this scope
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::SetTTL
(
BYTE TTL
)
{
DWORD err = 0;
m_SubnetInfo.TTL = TTL;
return err;
}
/*---------------------------------------------------------------------------
CDhcpMScope::DeleteClient
Description
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::DeleteClient
(
DHCP_IP_ADDRESS dhcpClientIpAddress
)
{
DWORD dwErr = ERROR_SUCCESS;
DHCP_SEARCH_INFO dhcpClientInfo;
dhcpClientInfo.SearchType = DhcpClientIpAddress;
dhcpClientInfo.SearchInfo.ClientIpAddress = dhcpClientIpAddress;
dwErr = ::DhcpDeleteMClientInfo((LPWSTR) GetServerIpAddress(),
&dhcpClientInfo);
return dwErr;
}
/*---------------------------------------------------------------------------
CDhcpMScope::SetOptionValue
Sets the least time for this scope
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::SetOptionValue
(
CDhcpOption * pdhcType
)
{
DWORD err = 0;
DHCP_OPTION_DATA * pdhcOptionData;
DHCP_OPTION_SCOPE_INFO dhcScopeInfo;
CDhcpOptionValue * pcOptionValue = NULL;
ZeroMemory( & dhcScopeInfo, sizeof(dhcScopeInfo) );
CATCH_MEM_EXCEPTION
{
pcOptionValue = new CDhcpOptionValue( & pdhcType->QueryValue() ) ;
if ( pcOptionValue )
{
dhcScopeInfo.ScopeType = DhcpMScopeOptions;
dhcScopeInfo.ScopeInfo.MScopeInfo = (LPWSTR) ((LPCTSTR) m_SubnetInfo.SubnetName);
pcOptionValue->CreateOptionDataStruct(&pdhcOptionData, TRUE);
err = (DWORD) ::DhcpSetOptionValue(GetServerIpAddress(),
pdhcType->QueryId(),
&dhcScopeInfo,
pdhcOptionData);
}
delete pcOptionValue ;
}
END_MEM_EXCEPTION(err) ;
return err ;
}
/*---------------------------------------------------------------------------
CDhcpScope::GetOptionValue
Gets an option value for this scope
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::GetOptionValue
(
DHCP_OPTION_ID OptionID,
DHCP_OPTION_VALUE ** ppdhcOptionValue
)
{
DWORD err = 0 ;
DHCP_OPTION_SCOPE_INFO dhcScopeInfo ;
ZeroMemory( &dhcScopeInfo, sizeof(dhcScopeInfo) );
CATCH_MEM_EXCEPTION
{
dhcScopeInfo.ScopeType = DhcpMScopeOptions;
dhcScopeInfo.ScopeInfo.MScopeInfo = (LPWSTR) ((LPCTSTR) m_SubnetInfo.SubnetName);
err = (DWORD) ::DhcpGetOptionValue(GetServerIpAddress(),
OptionID,
&dhcScopeInfo,
ppdhcOptionValue );
}
END_MEM_EXCEPTION(err) ;
return err ;
}
/*---------------------------------------------------------------------------
CDhcpMScope::RemoveValue
Removes an option
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::RemoveOptionValue
(
DHCP_OPTION_ID dhcOptId
)
{
DWORD dwErr = ERROR_SUCCESS;
DHCP_OPTION_SCOPE_INFO dhcScopeInfo;
ZeroMemory( &dhcScopeInfo, sizeof(dhcScopeInfo) );
dhcScopeInfo.ScopeType = DhcpMScopeOptions;
dhcScopeInfo.ScopeInfo.MScopeInfo = (LPWSTR) ((LPCTSTR) m_SubnetInfo.SubnetName);
dwErr = ::DhcpRemoveOptionValue(GetServerIpAddress(),
dhcOptId,
&dhcScopeInfo);
return dwErr;
}
/*---------------------------------------------------------------------------
CDhcpMScope::AddElement
Description
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::AddElement
(
LPDHCP_SUBNET_ELEMENT_DATA_V4 pdhcpSubnetElementData
)
{
DWORD dwErr = ERROR_SUCCESS;
dwErr = ::DhcpAddMScopeElement((LPWSTR) GetServerIpAddress(),
(LPWSTR) ((LPCTSTR) m_SubnetInfo.SubnetName),
pdhcpSubnetElementData);
return dwErr;
}
/*---------------------------------------------------------------------------
CDhcpMScope::RemoveElement
Description
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::RemoveElement
(
LPDHCP_SUBNET_ELEMENT_DATA_V4 pdhcpSubnetElementData,
BOOL bForce
)
{
DWORD dwErr = ERROR_SUCCESS;
dwErr = ::DhcpRemoveMScopeElement((LPWSTR) GetServerIpAddress(),
(LPWSTR) ((LPCTSTR) m_SubnetInfo.SubnetName),
pdhcpSubnetElementData,
bForce ? DhcpFullForce : DhcpNoForce);
return dwErr;
}
/*---------------------------------------------------------------------------
CDhcpMScope::GetIpRange()
returns the scope's allocation range. Connects to the server
to get the information
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::GetIpRange
(
DHCP_IP_RANGE * pdhipr
)
{
BOOL bAlloced = FALSE;
DWORD dwError = ERROR_SUCCESS;
pdhipr->StartAddress = 0;
pdhipr->EndAddress = 0;
CMScopeAddressPool * pAddressPool = GetAddressPoolObject();
if (pAddressPool == NULL)
{
// the address pool folder isn't there yet...
// Create a temporary one for now...
pAddressPool = new CMScopeAddressPool(m_spTFSCompData);
bAlloced = TRUE;
}
// Get a query object from the address pool handler
CMScopeAddressPoolQueryObj * pQueryObject =
reinterpret_cast<CMScopeAddressPoolQueryObj *>(pAddressPool->OnCreateQuery(m_spAddressPool));
// if we created an address pool handler, then free it up now
if (bAlloced)
{
pQueryObject->m_strServer = GetServerIpAddress();
pQueryObject->m_strName = GetName();
pAddressPool->Release();
}
// tell the query object to get the ip ranges
pQueryObject->EnumerateIpRanges();
// check to see if there was any problems getting the information
dwError = pQueryObject->m_dwError;
if (dwError != ERROR_SUCCESS)
{
return dwError;
}
LPQUEUEDATA pQD;
while (pQD = pQueryObject->RemoveFromQueue())
{
Assert (pQD->Type == QDATA_PNODE);
SPITFSNode p;
p = reinterpret_cast<ITFSNode *>(pQD->Data);
delete pQD;
CDhcpAllocationRange * pAllocRange = GETHANDLER(CDhcpAllocationRange, p);
pdhipr->StartAddress = pAllocRange->QueryAddr(TRUE);
pdhipr->EndAddress = pAllocRange->QueryAddr(FALSE);
p.Release();
}
pQueryObject->Release();
return dwError;
}
/*---------------------------------------------------------------------------
CDhcpMScope::UpdateIpRange()
This function updates the IP range on the server. We also need
to remove any exclusion ranges that fall outside of the new
allocation range.
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::UpdateIpRange
(
DHCP_IP_RANGE * pdhipr
)
{
return SetIpRange(pdhipr, TRUE);
}
/*---------------------------------------------------------------------------
CDhcpMScope::QueryIpRange()
Returns the scope's allocation range (doesn't talk to the server
directly, only returns internally cached information).
Author: EricDav
---------------------------------------------------------------------------*/
void
CDhcpMScope::QueryIpRange
(
DHCP_IP_RANGE * pdhipr
)
{
pdhipr->StartAddress = 0;
pdhipr->EndAddress = 0;
SPITFSNodeEnum spNodeEnum;
SPITFSNode spCurrentNode;
ULONG nNumReturned = 0;
m_spAddressPool->GetEnum(&spNodeEnum);
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
while (nNumReturned)
{
if (spCurrentNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_ALLOCATION_RANGE)
{
// found the address
//
CDhcpAllocationRange * pAllocRange = GETHANDLER(CDhcpAllocationRange, spCurrentNode);
pdhipr->StartAddress = pAllocRange->QueryAddr(TRUE);
pdhipr->EndAddress = pAllocRange->QueryAddr(FALSE);
}
spCurrentNode.Release();
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
}
}
/*---------------------------------------------------------------------------
CDhcpMScope::SetIpRange
Set's the allocation range for this scope
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::SetIpRange
(
DHCP_IP_RANGE * pdhcpIpRange,
BOOL bUpdateOnServer
)
{
CDhcpIpRange dhcpIpRange = *pdhcpIpRange;
return SetIpRange(dhcpIpRange, bUpdateOnServer);
}
/*---------------------------------------------------------------------------
CDhcpMScope::SetIpRange
Set's the allocation range for this scope
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::SetIpRange
(
const CDhcpIpRange & dhcpIpRange,
BOOL bUpdateOnServer
)
{
DWORD err = 0;
if (bUpdateOnServer)
{
DHCP_SUBNET_ELEMENT_DATA_V4 dhcSubElData;
DHCP_IP_RANGE dhipOldRange;
err = GetIpRange(&dhipOldRange);
if (err != ERROR_SUCCESS)
{
return err;
}
dhcSubElData.ElementType = DhcpIpRanges;
dhcSubElData.Element.IpRange = &dhipOldRange;
//
// First update the information on the server
//
// Remove the old IP range; allow "not found" error in new scope.
//
(void)RemoveElement(&dhcSubElData);
//if ( err == 0 || err == ERROR_FILE_NOT_FOUND )
//{
DHCP_IP_RANGE dhcpNewIpRange = dhcpIpRange;
dhcSubElData.Element.IpRange = &dhcpNewIpRange;
if ( (err = AddElement( & dhcSubElData )) == 0 )
{
//m_ip_range = dhipr ;
}
else
{
Trace1("SetIpRange - AddElement failed %lx\n", err);
// something bad happened, try to put the old range back
dhcSubElData.Element.IpRange = &dhipOldRange;
if (AddElement(&dhcSubElData) != ERROR_SUCCESS)
{
Trace0("SetIpRange - cannot return ip range back to old state!!");
}
}
//}
}
//
// Find the address pool folder and update the UI object
//
SPITFSNodeEnum spNodeEnum;
SPITFSNode spCurrentNode;
ULONG nNumReturned = 0;
if (m_spAddressPool == NULL)
return err;
m_spAddressPool->GetEnum(&spNodeEnum);
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
while (nNumReturned)
{
if (spCurrentNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_ALLOCATION_RANGE)
{
// found the address
//
CDhcpAllocationRange * pAllocRange = GETHANDLER(CDhcpAllocationRange, spCurrentNode);
// now set them
//
pAllocRange->SetAddr(dhcpIpRange.QueryAddr(TRUE), TRUE);
pAllocRange->SetAddr(dhcpIpRange.QueryAddr(FALSE), FALSE);
// tell the UI to update
spCurrentNode->ChangeNode(RESULT_PANE_CHANGE_ITEM_DATA);
}
spCurrentNode.Release();
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
}
return err ;
}
/*---------------------------------------------------------------------------
CDhcpMScope::IsOverlappingRange
determines if the exclusion overlaps an existing range
Author: EricDav
---------------------------------------------------------------------------*/
BOOL
CDhcpMScope::IsOverlappingRange
(
CDhcpIpRange & dhcpIpRange
)
{
SPITFSNodeEnum spNodeEnum;
SPITFSNode spCurrentNode;
ULONG nNumReturned = 0;
BOOL bOverlap = FALSE;
m_spActiveLeases->GetEnum(&spNodeEnum);
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
while (nNumReturned)
{
if (spCurrentNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_EXCLUSION_RANGE)
{
// found the address
//
CDhcpExclusionRange * pExclusion = GETHANDLER(CDhcpExclusionRange, spCurrentNode);
if ( bOverlap = pExclusion->IsOverlap( dhcpIpRange ) )
{
spCurrentNode.Release();
break;
}
}
spCurrentNode.Release();
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
}
return bOverlap ;
}
/*---------------------------------------------------------------------------
CDhcpMScope::IsValidExclusion
determines if the exclusion is valid for this scope
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::IsValidExclusion
(
CDhcpIpRange & dhcpExclusionRange
)
{
DWORD err = 0;
DHCP_IP_RANGE dhcpIpRange;
err = GetIpRange (&dhcpIpRange);
CDhcpIpRange dhcpScopeRange(dhcpIpRange);
//
// Get the data into a range object.
//
if ( IsOverlappingRange( dhcpExclusionRange ) )
{
//
// Walk the current list, determining if the new range is valid.
// Then, if OK, verify that it's really a sub-range of the current range.
//
err = IDS_ERR_IP_RANGE_OVERLAP ;
}
else if ( ! dhcpExclusionRange.IsSubset( dhcpScopeRange ) )
{
//
// Guarantee that the new range is an (improper) subset of the scope's range
//
err = IDS_ERR_IP_RANGE_NOT_SUBSET ;
}
return err;
}
/*---------------------------------------------------------------------------
CDhcpMScope::StoreExceptionList
Adds a bunch of exclusions to the scope
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::StoreExceptionList
(
CExclusionList * plistExclusions
)
{
DHCP_SUBNET_ELEMENT_DATA dhcElement ;
DHCP_IP_RANGE dhipr ;
CDhcpIpRange * pobIpRange ;
DWORD err = 0, err1 = 0;
POSITION pos;
pos = plistExclusions->GetHeadPosition();
while ( pos )
{
pobIpRange = plistExclusions->GetNext(pos);
err1 = AddExclusion( *pobIpRange ) ;
if ( err1 != 0 )
{
err = err1;
Trace1("CDhcpScope::StoreExceptionList error adding range %d\n", err);
}
}
return err ;
}
/*---------------------------------------------------------------------------
CDhcpMScope::AddExclusion
Adds an individual exclusion to the server
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::AddExclusion
(
CDhcpIpRange & dhcpIpRange,
BOOL bAddToUI
)
{
DHCP_SUBNET_ELEMENT_DATA_V4 dhcElement ;
DHCP_IP_RANGE dhipr ;
DWORD err = 0;
dhcElement.ElementType = DhcpExcludedIpRanges ;
dhipr = dhcpIpRange ;
dhcElement.Element.ExcludeIpRange = & dhipr ;
Trace2("CDhcpMScope::AddExclusion add excluded range %lx %lx\n", dhipr.StartAddress, dhipr.EndAddress );
err = AddElement( & dhcElement ) ;
//if ( err != 0 && err != ERROR_DHCP_INVALID_RANGE)
if ( err != 0 )
{
Trace1("CDhcpMScope::AddExclusion error removing range %d\n", err);
}
if (m_spAddressPool != NULL)
{
CMScopeAddressPool * pAddrPool = GETHANDLER(CMScopeAddressPool, m_spAddressPool);
if (!err && bAddToUI && pAddrPool->m_bExpanded)
{
SPITFSNode spNewExclusion;
CDhcpExclusionRange * pExclusion =
new CDhcpExclusionRange(m_spTFSCompData, &((DHCP_IP_RANGE) dhcpIpRange));
CreateLeafTFSNode(&spNewExclusion,
&GUID_DhcpExclusionNodeType,
pExclusion,
pExclusion,
m_spNodeMgr);
// Tell the handler to initialize any specific data
pExclusion->InitializeNode((ITFSNode *) spNewExclusion);
// Add the node as a child to this node
m_spAddressPool->AddChild(spNewExclusion);
pExclusion->Release();
}
}
return err;
}
/*---------------------------------------------------------------------------
CDhcpMScope::RemoveExclusion
Removes and exclusion from the server
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CDhcpMScope::RemoveExclusion
(
CDhcpIpRange & dhcpIpRange
)
{
DHCP_SUBNET_ELEMENT_DATA_V4 dhcElement ;
DHCP_IP_RANGE dhipr ;
DWORD err = 0;
dhcElement.ElementType = DhcpExcludedIpRanges ;
dhipr = dhcpIpRange ;
dhcElement.Element.ExcludeIpRange = & dhipr ;
Trace2("CDhcpMScope::RemoveExclusion remove excluded range %lx %lx\n", dhipr.StartAddress, dhipr.EndAddress);
err = RemoveElement( & dhcElement ) ;
//if ( err != 0 && err != ERROR_DHCP_INVALID_RANGE)
if ( err != 0 )
{
Trace1("CDhcpMScope::RemoveExclusion error removing range %d\n", err);
}
return err;
}
/////////////////////////////////////////////////////////////////////
//
// CMScopeActiveLeases implementation
//
/////////////////////////////////////////////////////////////////////
/*---------------------------------------------------------------------------
Function Name Here
Description
Author: EricDav
---------------------------------------------------------------------------*/
CMScopeActiveLeases::CMScopeActiveLeases
(
ITFSComponentData * pComponentData
) : CMTDhcpHandler(pComponentData)
{
}
CMScopeActiveLeases::~CMScopeActiveLeases()
{
}
/*!--------------------------------------------------------------------------
CMScopeActiveLeases::InitializeNode
Initializes node specific data
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CMScopeActiveLeases::InitializeNode
(
ITFSNode * pNode
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
HRESULT hr = hrOK;
//
// Create the display name for this scope
//
CString strTemp;
strTemp.LoadString(IDS_ACTIVE_LEASES_FOLDER);
SetDisplayName(strTemp);
// Make the node immediately visible
pNode->SetVisibilityState(TFS_VIS_SHOW);
pNode->SetData(TFS_DATA_IMAGEINDEX, ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED);
pNode->SetData(TFS_DATA_OPENIMAGEINDEX, ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN);
pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
pNode->SetData(TFS_DATA_USER, (LPARAM) this);
pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_MSCOPE_LEASES);
pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
SetColumnStringIDs(&aColumns[DHCPSNAP_MSCOPE_LEASES][0]);
SetColumnWidths(&aColumnWidths[DHCPSNAP_MSCOPE_LEASES][0]);
return hr;
}
/*---------------------------------------------------------------------------
CMScopeActiveLeases::OnCreateNodeId2
Returns a unique string for this node
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT CMScopeActiveLeases::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
{
const GUID * pGuid = pNode->GetNodeType();
CString strNode, strGuid;
StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
strGuid.ReleaseBuffer();
// id string is server name, scope name and guid.
strNode = GetServerName(pNode);
strNode += GetScopeObject(pNode)->GetName() + strGuid;
strId = strNode;
return hrOK;
}
/*---------------------------------------------------------------------------
CMScopeActiveLeases::GetImageIndex
Description
Author: EricDav
---------------------------------------------------------------------------*/
int
CMScopeActiveLeases::GetImageIndex(BOOL bOpenImage)
{
int nIndex = -1;
switch (m_nState)
{
case notLoaded:
case loaded:
if (bOpenImage)
nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN;
else
nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED;
break;
case loading:
if (bOpenImage)
nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN_BUSY;
else
nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED_BUSY;
break;
case unableToLoad:
if (bOpenImage)
nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN_LOST_CONNECTION;
else
nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED_LOST_CONNECTION;
break;
default:
ASSERT(FALSE);
}
return nIndex;
}
/*---------------------------------------------------------------------------
Overridden base handler functions
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
CMScopeActiveLeases::OnAddMenuItems
Adds entries to the context sensitive menu
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CMScopeActiveLeases::OnAddMenuItems
(
ITFSNode * pNode,
LPCONTEXTMENUCALLBACK pContextMenuCallback,
LPDATAOBJECT lpDataObject,
DATA_OBJECT_TYPES type,
DWORD dwType,
long * pInsertionAllowed
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
LONG fFlags = 0;
HRESULT hr = S_OK;
CString strMenuText;
if ( (m_nState != loaded) )
{
fFlags |= MF_GRAYED;
}
if (type == CCT_SCOPE)
{
}
return hr;
}
/*---------------------------------------------------------------------------
CMScopeActiveLeases::OnCommand
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CMScopeActiveLeases::OnCommand
(
ITFSNode * pNode,
long nCommandId,
DATA_OBJECT_TYPES type,
LPDATAOBJECT pDataObject,
DWORD dwType
)
{
HRESULT hr = S_OK;
switch (nCommandId)
{
case IDS_REFRESH:
OnRefresh(pNode, pDataObject, dwType, 0, 0);
break;
default:
break;
}
return hr;
}
/*---------------------------------------------------------------------------
CMScopeActiveLeases::OnResultDelete
This function is called when we are supposed to delete result
pane items. We build a list of selected items and then delete them.
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CMScopeActiveLeases::OnResultDelete
(
ITFSComponent * pComponent,
LPDATAOBJECT pDataObject,
MMC_COOKIE cookie,
LPARAM arg,
LPARAM param
)
{
HRESULT hr = hrOK;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// translate the cookie into a node pointer
SPITFSNode spActiveLeases, spSelectedNode;
m_spNodeMgr->FindNode(cookie, &spActiveLeases);
pComponent->GetSelectedNode(&spSelectedNode);
Assert(spSelectedNode == spActiveLeases);
if (spSelectedNode != spActiveLeases)
return hr;
// build the list of selected nodes
CTFSNodeList listNodesToDelete;
hr = BuildSelectedItemList(pComponent, &listNodesToDelete);
//
// Confirm with the user
//
CString strMessage, strTemp;
int nNodes = (int)listNodesToDelete.GetCount();
if (nNodes > 1)
{
strTemp.Format(_T("%d"), nNodes);
AfxFormatString1(strMessage, IDS_DELETE_ITEMS, (LPCTSTR) strTemp);
}
else
{
strMessage.LoadString(IDS_DELETE_ITEM);
}
if (AfxMessageBox(strMessage, MB_YESNO) == IDNO)
{
return NOERROR;
}
//
// Loop through all items deleting
//
BEGIN_WAIT_CURSOR;
while (listNodesToDelete.GetCount() > 0)
{
SPITFSNode spActiveLeaseNode;
spActiveLeaseNode = listNodesToDelete.RemoveHead();
CDhcpMCastLease * pActiveLease = GETHANDLER(CDhcpMCastLease, spActiveLeaseNode);
//
// delete the node, check to see if it is a reservation
//
DWORD dwError = GetScopeObject(spActiveLeases)->DeleteClient(pActiveLease->GetIpAddress());
if (dwError == ERROR_SUCCESS)
{
//
// Client gone, now remove from UI
//
spActiveLeases->RemoveChild(spActiveLeaseNode);
}
else
{
::DhcpMessageBox(dwError);
RESTORE_WAIT_CURSOR;
Trace1("DeleteClient failed %lx\n", dwError);
hr = E_FAIL;
}
spActiveLeaseNode.Release();
}
END_WAIT_CURSOR;
return hr;
}
/*!--------------------------------------------------------------------------
CMScopeActiveLeases::OnGetResultViewType
MMC calls this to get the result view information
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT CMScopeActiveLeases::OnGetResultViewType
(
ITFSComponent * pComponent,
MMC_COOKIE cookie,
LPOLESTR * ppViewType,
long * pViewOptions
)
{
*pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
// we still want the default MMC result pane view, we just want
// multiselect, so return S_FALSE
return S_FALSE;
}
/*---------------------------------------------------------------------------
CMScopeActiveLeases::CompareItems
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP_(int)
CMScopeActiveLeases::CompareItems
(
ITFSComponent * pComponent,
MMC_COOKIE cookieA,
MMC_COOKIE cookieB,
int nCol
)
{
SPITFSNode spNode1, spNode2;
m_spNodeMgr->FindNode(cookieA, &spNode1);
m_spNodeMgr->FindNode(cookieB, &spNode2);
int nCompare = 0;
CDhcpMCastLease *pDhcpAL1 = GETHANDLER(CDhcpMCastLease, spNode1);
CDhcpMCastLease *pDhcpAL2 = GETHANDLER(CDhcpMCastLease, spNode2);
switch (nCol)
{
case 0:
{
// IP address compare
//
nCompare = CompareIpAddresses(pDhcpAL1, pDhcpAL2);
}
break;
case 1:
{
// Client Name compare
//
CString strAL1 = pDhcpAL1->GetString(pComponent, cookieA, nCol);
CString strAL2 = pDhcpAL2->GetString(pComponent, cookieA, nCol);
// Compare should not be case sensitive
//
nCompare = strAL1.CompareNoCase(strAL2);
}
break;
case 2:
{
// Lease start compare
//
CTime timeAL1, timeAL2;
pDhcpAL1->GetLeaseStartTime(timeAL1);
pDhcpAL2->GetLeaseStartTime(timeAL2);
if (timeAL1 < timeAL2)
nCompare = -1;
else
if (timeAL1 > timeAL2)
nCompare = 1;
}
break;
case 3:
{
// Lease expiration compare
//
CTime timeAL1, timeAL2;
pDhcpAL1->GetLeaseExpirationTime(timeAL1);
pDhcpAL2->GetLeaseExpirationTime(timeAL2);
if (timeAL1 < timeAL2)
nCompare = -1;
else
if (timeAL1 > timeAL2)
nCompare = 1;
}
break;
case 4:
{
CString strClientId1 = pDhcpAL1->GetClientId();
nCompare = strClientId1.CompareNoCase(pDhcpAL2->GetClientId());
}
break;
}
return nCompare;
}
/*---------------------------------------------------------------------------
Function Name Here
Description
Author: EricDav
---------------------------------------------------------------------------*/
int
CMScopeActiveLeases::CompareIpAddresses
(
CDhcpMCastLease * pDhcpAL1,
CDhcpMCastLease * pDhcpAL2
)
{
int nCompare = 0;
DHCP_IP_ADDRESS dhcpIp1 = pDhcpAL1->GetIpAddress();
DHCP_IP_ADDRESS dhcpIp2 = pDhcpAL2->GetIpAddress();
if (dhcpIp1 < dhcpIp2)
nCompare = -1;
else
if (dhcpIp1 > dhcpIp2)
nCompare = 1;
return nCompare;
}
/*---------------------------------------------------------------------------
Background thread functionality
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
CMScopeActiveLeases::OnCreateQuery()
Description
Author: EricDav
---------------------------------------------------------------------------*/
ITFSQueryObject*
CMScopeActiveLeases::OnCreateQuery(ITFSNode * pNode)
{
CMScopeActiveLeasesQueryObj* pQuery =
new CMScopeActiveLeasesQueryObj(m_spTFSCompData, m_spNodeMgr);
if ( pQuery == NULL )
return pQuery;
pQuery->m_strServer = GetServerIpAddress(pNode);
pQuery->m_dhcpResumeHandle = NULL;
pQuery->m_dwPreferredMax = 200;
CDhcpMScope * pScope = GetScopeObject(pNode);
if (pScope)
pQuery->m_strName = pScope->GetName();
else
Panic0("no scope in MScopeActiveLease::OnCreateQuery!");
GetServerVersion(pNode, pQuery->m_liDhcpVersion);
return pQuery;
}
/*---------------------------------------------------------------------------
CMScopeActiveLeasesQueryObj::Execute()
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CMScopeActiveLeasesQueryObj::Execute()
{
HRESULT hr = hrOK;
hr = EnumerateLeases();
return hr;
}
/*---------------------------------------------------------------------------
CMScopeActiveLeasesQueryObj::EnumerateLeases()
Description
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CMScopeActiveLeasesQueryObj::EnumerateLeases()
{
DWORD dwError = ERROR_MORE_DATA;
LPDHCP_MCLIENT_INFO_ARRAY pdhcpClientArray = NULL;
DWORD dwClientsRead = 0, dwClientsTotal = 0;
DWORD dwEnumedClients = 0;
while (dwError == ERROR_MORE_DATA)
{
if (m_strName.IsEmpty())
Panic0("CMScopeActiveLeasesQueryObj::EnumerateLeases() - m_strName is empty!!");
dwError = ::DhcpEnumMScopeClients(((LPWSTR) (LPCTSTR)m_strServer),
(LPWSTR) ((LPCTSTR) m_strName),
&m_dhcpResumeHandle,
m_dwPreferredMax,
&pdhcpClientArray,
&dwClientsRead,
&dwClientsTotal);
if (dwClientsRead && pdhcpClientArray)
{
//
// loop through all of the elements that were returned
//
for (DWORD i = 0; i < pdhcpClientArray->NumElements; i++)
{
CDhcpMCastLease * pDhcpMCastLease;
//
// Create the result pane item for this element
//
SPITFSNode spNode;
pDhcpMCastLease =
new CDhcpMCastLease(m_spTFSCompData);
CreateLeafTFSNode(&spNode,
&GUID_DhcpMCastLeaseNodeType,
pDhcpMCastLease,
pDhcpMCastLease,
m_spNodeMgr);
// Tell the handler to initialize any specific data
pDhcpMCastLease->InitMCastInfo(pdhcpClientArray->Clients[i]);
pDhcpMCastLease->InitializeNode(spNode);
AddToQueue(spNode);
pDhcpMCastLease->Release();
}
::DhcpRpcFreeMemory(pdhcpClientArray);
dwEnumedClients += dwClientsRead;
dwClientsRead = 0;
dwClientsTotal = 0;
pdhcpClientArray = NULL;
}
// Check the abort flag on the thread
if (FCheckForAbort() == hrOK)
break;
// check to see if we have an error and post it to the main thread if we do..
if (dwError != ERROR_NO_MORE_ITEMS &&
dwError != ERROR_SUCCESS &&
dwError != ERROR_MORE_DATA)
{
Trace1("DHCP snapin: EnumerateLeases error: %d\n", dwError);
m_dwErr = dwError;
PostError(dwError);
}
}
Trace1("DHCP snpain: Leases enumerated: %d\n", dwEnumedClients);
return hrFalse;
}
/*---------------------------------------------------------------------------
Class CMScopeAddressPool implementation
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
Function Name Here
Description
Author: EricDav
---------------------------------------------------------------------------*/
CMScopeAddressPool::CMScopeAddressPool
(
ITFSComponentData * pComponentData
) : CMTDhcpHandler(pComponentData)
{
}
CMScopeAddressPool::~CMScopeAddressPool()
{
}
/*!--------------------------------------------------------------------------
CMScopeAddressPool::InitializeNode
Initializes node specific data
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CMScopeAddressPool::InitializeNode
(
ITFSNode * pNode
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
HRESULT hr = hrOK;
//
// Create the display name for this scope
//
CString strTemp;
strTemp.LoadString(IDS_ADDRESS_POOL_FOLDER);
SetDisplayName(strTemp);
// Make the node immediately visible
pNode->SetVisibilityState(TFS_VIS_SHOW);
pNode->SetData(TFS_DATA_IMAGEINDEX, ICON_IDX_ADDR_POOL_FOLDER_CLOSED);
pNode->SetData(TFS_DATA_OPENIMAGEINDEX, ICON_IDX_ADDR_POOL_FOLDER_OPEN);
pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
pNode->SetData(TFS_DATA_USER, (LPARAM) this);
pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_ADDRESS_POOL);
pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
SetColumnStringIDs(&aColumns[DHCPSNAP_ADDRESS_POOL][0]);
SetColumnWidths(&aColumnWidths[DHCPSNAP_ADDRESS_POOL][0]);
return hr;
}
/*---------------------------------------------------------------------------
CMScopeAddressPool::OnCreateNodeId2
Returns a unique string for this node
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT CMScopeAddressPool::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
{
const GUID * pGuid = pNode->GetNodeType();
CString strNode, strGuid;
StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
strGuid.ReleaseBuffer();
// id string is server name, scope name and guid.
strNode = GetServerName(pNode);
strNode += GetScopeObject(pNode)->GetName() + strGuid;
strId = strNode;
return hrOK;
}
/*---------------------------------------------------------------------------
CMScopeAddressPool::GetImageIndex
Description
Author: EricDav
---------------------------------------------------------------------------*/
int
CMScopeAddressPool::GetImageIndex(BOOL bOpenImage)
{
int nIndex = -1;
switch (m_nState)
{
case notLoaded:
case loaded:
if (bOpenImage)
nIndex = ICON_IDX_ADDR_POOL_FOLDER_OPEN;
else
nIndex = ICON_IDX_ADDR_POOL_FOLDER_CLOSED;
break;
case loading:
if (bOpenImage)
nIndex = ICON_IDX_ADDR_POOL_FOLDER_OPEN_BUSY;
else
nIndex = ICON_IDX_ADDR_POOL_FOLDER_CLOSED_BUSY;
break;
case unableToLoad:
if (bOpenImage)
nIndex = ICON_IDX_ADDR_POOL_FOLDER_OPEN_LOST_CONNECTION;
else
nIndex = ICON_IDX_ADDR_POOL_FOLDER_CLOSED_LOST_CONNECTION;
break;
default:
ASSERT(FALSE);
}
return nIndex;
}
/*---------------------------------------------------------------------------
Overridden base handler functions
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
CMScopeAddressPool::OnAddMenuItems
Adds entries to the context sensitive menu
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CMScopeAddressPool::OnAddMenuItems
(
ITFSNode * pNode,
LPCONTEXTMENUCALLBACK pContextMenuCallback,
LPDATAOBJECT lpDataObject,
DATA_OBJECT_TYPES type,
DWORD dwType,
long * pInsertionAllowed
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
LONG fFlags = 0;
HRESULT hr = S_OK;
CString strMenuText;
if ( (m_nState != loaded) )
{
fFlags |= MF_GRAYED;
}
if (type == CCT_SCOPE)
{
// these menu items go in the new menu,
// only visible from scope pane
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
{
strMenuText.LoadString(IDS_CREATE_NEW_EXCLUSION);
hr = LoadAndAddMenuItem( pContextMenuCallback,
strMenuText,
IDS_CREATE_NEW_EXCLUSION,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
fFlags );
ASSERT( SUCCEEDED(hr) );
}
}
return hr;
}
/*---------------------------------------------------------------------------
CMScopeAddressPool::OnCommand
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CMScopeAddressPool::OnCommand
(
ITFSNode * pNode,
long nCommandId,
DATA_OBJECT_TYPES type,
LPDATAOBJECT pDataObject,
DWORD dwType
)
{
HRESULT hr = S_OK;
switch (nCommandId)
{
case IDS_CREATE_NEW_EXCLUSION:
OnCreateNewExclusion(pNode);
break;
case IDS_REFRESH:
OnRefresh(pNode, pDataObject, dwType, 0, 0);
break;
default:
break;
}
return hr;
}
/*---------------------------------------------------------------------------
Message handlers
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
CMScopeAddressPool::OnCreateNewExclusion
Description
Author: EricDav
---------------------------------------------------------------------------*/
DWORD
CMScopeAddressPool::OnCreateNewExclusion
(
ITFSNode * pNode
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
SPITFSNode spScopeNode;
pNode->GetParent(&spScopeNode);
CAddExclusion dlgAddExclusion(spScopeNode, TRUE /* multicast */);
dlgAddExclusion.DoModal();
return 0;
}
/*---------------------------------------------------------------------------
CMScopeAddressPool::OnResultDelete
This function is called when we are supposed to delete result
pane items. We build a list of selected items and then delete them.
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CMScopeAddressPool::OnResultDelete
(
ITFSComponent * pComponent,
LPDATAOBJECT pDataObject,
MMC_COOKIE cookie,
LPARAM arg,
LPARAM lParam
)
{
HRESULT hr = NOERROR;
BOOL bIsRes, bIsActive, bBadAddress;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// translate the cookie into a node pointer
SPITFSNode spAddressPool, spSelectedNode;
m_spNodeMgr->FindNode(cookie, &spAddressPool);
pComponent->GetSelectedNode(&spSelectedNode);
Assert(spSelectedNode == spAddressPool);
if (spSelectedNode != spAddressPool)
return hr;
// build the list of selected nodes
CTFSNodeList listNodesToDelete;
hr = BuildSelectedItemList(pComponent, &listNodesToDelete);
//
// Confirm with the user
//
CString strMessage, strTemp;
int nNodes = (int)listNodesToDelete.GetCount();
if (nNodes > 1)
{
strTemp.Format(_T("%d"), nNodes);
AfxFormatString1(strMessage, IDS_DELETE_ITEMS, (LPCTSTR) strTemp);
}
else
{
strMessage.LoadString(IDS_DELETE_ITEM);
}
if (AfxMessageBox(strMessage, MB_YESNO) == IDNO)
{
return NOERROR;
}
//
// Loop through all items deleting
//
BEGIN_WAIT_CURSOR;
while (listNodesToDelete.GetCount() > 0)
{
SPITFSNode spExclusionRangeNode;
spExclusionRangeNode = listNodesToDelete.RemoveHead();
CDhcpExclusionRange * pExclusion = GETHANDLER(CDhcpExclusionRange, spExclusionRangeNode);
if (spExclusionRangeNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_ALLOCATION_RANGE)
{
//
// This is the allocation range, can't delete
//
AfxMessageBox(IDS_CANNOT_DELETE_ALLOCATION_RANGE);
spExclusionRangeNode.Release();
continue;
}
//
// Try to remove it from the server
//
CDhcpIpRange dhcpIpRange((DHCP_IP_RANGE) *pExclusion);
DWORD dwError = GetScopeObject(spAddressPool)->RemoveExclusion(dhcpIpRange);
if (dwError != 0)
{
::DhcpMessageBox(dwError);
RESTORE_WAIT_CURSOR;
hr = E_FAIL;
continue;
}
//
// Remove from UI now
//
spAddressPool->RemoveChild(spExclusionRangeNode);
spExclusionRangeNode.Release();
}
END_WAIT_CURSOR;
return hr;
}
/*!--------------------------------------------------------------------------
CMScopeAddressPool::OnGetResultViewType
MMC calls this to get the result view information
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CMScopeAddressPool::OnGetResultViewType
(
ITFSComponent * pComponent,
MMC_COOKIE cookie,
LPOLESTR * ppViewType,
long * pViewOptions
)
{
*pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
// we still want the default MMC result pane view, we just want
// multiselect, so return S_FALSE
return S_FALSE;
}
/*---------------------------------------------------------------------------
CMScopeAddressPool::CompareItems
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP_(int)
CMScopeAddressPool::CompareItems
(
ITFSComponent * pComponent,
MMC_COOKIE cookieA,
MMC_COOKIE cookieB,
int nCol
)
{
SPITFSNode spNode1, spNode2;
m_spNodeMgr->FindNode(cookieA, &spNode1);
m_spNodeMgr->FindNode(cookieB, &spNode2);
int nCompare = 0;
CDhcpAllocationRange *pDhcpAR1 = GETHANDLER(CDhcpAllocationRange, spNode1);
CDhcpAllocationRange *pDhcpAR2 = GETHANDLER(CDhcpAllocationRange, spNode2);
switch (nCol)
{
case 0:
{
// Start IP address compare
//
DHCP_IP_ADDRESS dhcpIp1 = pDhcpAR1->QueryAddr(TRUE);
DHCP_IP_ADDRESS dhcpIp2 = pDhcpAR2->QueryAddr(TRUE);
if (dhcpIp1 < dhcpIp2)
nCompare = -1;
else
if (dhcpIp1 > dhcpIp2)
nCompare = 1;
// default is that they are equal
}
break;
case 1:
{
// End IP address compare
//
DHCP_IP_ADDRESS dhcpIp1 = pDhcpAR1->QueryAddr(FALSE);
DHCP_IP_ADDRESS dhcpIp2 = pDhcpAR2->QueryAddr(FALSE);
if (dhcpIp1 < dhcpIp2)
nCompare = -1;
else
if (dhcpIp1 > dhcpIp2)
nCompare = 1;
// default is that they are equal
}
break;
case 2:
{
// Description compare
//
CString strRange1 = pDhcpAR1->GetString(pComponent, cookieA, nCol);
CString strRange2 = pDhcpAR2->GetString(pComponent, cookieA, nCol);
// Compare should not be case sensitive
//
strRange1.MakeUpper();
strRange2.MakeUpper();
nCompare = strRange1.Compare(strRange2);
}
break;
}
return nCompare;
}
/*---------------------------------------------------------------------------
Background thread functionality
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
CMScopeAddressPool::OnCreateQuery()
Description
Author: EricDav
---------------------------------------------------------------------------*/
ITFSQueryObject*
CMScopeAddressPool::OnCreateQuery(ITFSNode * pNode)
{
CMScopeAddressPoolQueryObj* pQuery =
new CMScopeAddressPoolQueryObj(m_spTFSCompData, m_spNodeMgr);
if ( pQuery == NULL )
return pQuery;
pQuery->m_strServer = GetServerIpAddress(pNode);
CDhcpMScope * pScope = GetScopeObject(pNode);
if (pScope)
pQuery->m_strName = pScope->GetName();
pQuery->m_dhcpExclResumeHandle = NULL;
pQuery->m_dwExclPreferredMax = 0xFFFFFFFF;
pQuery->m_dhcpIpResumeHandle = NULL;
pQuery->m_dwIpPreferredMax = 0xFFFFFFFF;
return pQuery;
}
/*---------------------------------------------------------------------------
CMScopeAddressPoolQueryObj::Execute()
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP
CMScopeAddressPoolQueryObj::Execute()
{
HRESULT hr1 = EnumerateIpRanges();
HRESULT hr2 = EnumerateExcludedIpRanges();
if (hr1 == hrOK || hr2 == hrOK)
return hrOK;
else
return hrFalse;
}
/*---------------------------------------------------------------------------
Function Name Here
Description
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CMScopeAddressPoolQueryObj::EnumerateExcludedIpRanges()
{
DWORD dwError = ERROR_MORE_DATA;
DHCP_RESUME_HANDLE dhcpResumeHandle = 0;
LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 pdhcpSubnetElementArray = NULL;
DWORD dwElementsRead = 0, dwElementsTotal = 0;
while (dwError == ERROR_MORE_DATA)
{
dwError = ::DhcpEnumMScopeElements((LPWSTR) ((LPCTSTR) m_strServer),
(LPWSTR) ((LPCTSTR) m_strName),
DhcpExcludedIpRanges,
&m_dhcpExclResumeHandle,
m_dwExclPreferredMax,
&pdhcpSubnetElementArray,
&dwElementsRead,
&dwElementsTotal);
Trace3("Scope %s Excluded Ip Ranges read %d, total %d\n", m_strName, dwElementsRead, dwElementsTotal);
if (dwElementsRead && dwElementsTotal && pdhcpSubnetElementArray)
{
//
// loop through all of the elements that were returned
//
for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
{
//
// Create the result pane item for this element
//
SPITFSNode spNode;
CDhcpExclusionRange * pDhcpExclusionRange =
new CDhcpExclusionRange(m_spTFSCompData,
pdhcpSubnetElementArray->Elements[i].Element.ExcludeIpRange);
CreateLeafTFSNode(&spNode,
&GUID_DhcpExclusionNodeType,
pDhcpExclusionRange,
pDhcpExclusionRange,
m_spNodeMgr);
// Tell the handler to initialize any specific data
pDhcpExclusionRange->InitializeNode(spNode);
AddToQueue(spNode);
pDhcpExclusionRange->Release();
}
// Free up the memory from the RPC call
//
::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
}
// Check the abort flag on the thread
if (FCheckForAbort() == hrOK)
break;
// check to see if we have an error and post it to the main thread if we do..
if (dwError != ERROR_NO_MORE_ITEMS &&
dwError != ERROR_SUCCESS &&
dwError != ERROR_MORE_DATA)
{
Trace1("DHCP snapin: EnumerateExcludedIpRanges error: %d\n", dwError);
m_dwErr = dwError;
PostError(dwError);
}
}
return hrFalse;
}
/*---------------------------------------------------------------------------
Function Name Here
Description
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CMScopeAddressPoolQueryObj::EnumerateIpRanges()
{
DWORD dwError = ERROR_MORE_DATA;
LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 pdhcpSubnetElementArray = NULL;
DWORD dwElementsRead = 0, dwElementsTotal = 0;
while (dwError == ERROR_MORE_DATA)
{
dwError = ::DhcpEnumMScopeElements((LPWSTR) ((LPCTSTR) m_strServer),
(LPWSTR) ((LPCTSTR) m_strName),
DhcpIpRanges,
&m_dhcpIpResumeHandle,
m_dwIpPreferredMax,
&pdhcpSubnetElementArray,
&dwElementsRead,
&dwElementsTotal);
Trace4("Scope %s allocation ranges read %d, total %d, dwError = %lx\n",
m_strName, dwElementsRead, dwElementsTotal, dwError);
if ((dwError == ERROR_MORE_DATA) ||
( (dwElementsRead) && (dwError == ERROR_SUCCESS) ))
{
//
// Loop through the array that was returned
//
for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
{
//
// Create the result pane item for this element
//
SPITFSNode spNode;
CDhcpAllocationRange * pDhcpAllocRange =
new CDhcpAllocationRange(m_spTFSCompData,
pdhcpSubnetElementArray->Elements[i].Element.IpRange);
CreateLeafTFSNode(&spNode,
&GUID_DhcpAllocationNodeType,
pDhcpAllocRange,
pDhcpAllocRange,
m_spNodeMgr);
// Tell the handler to initialize any specific data
pDhcpAllocRange->InitializeNode(spNode);
AddToQueue(spNode);
pDhcpAllocRange->Release();
}
::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
}
else
if (dwError != ERROR_SUCCESS &&
dwError != ERROR_NO_MORE_ITEMS)
{
// set the error variable so that it can be looked at later
m_dwError = dwError;
}
// Check the abort flag on the thread
if (FCheckForAbort() == hrOK)
break;
// check to see if we have an error and post it to the main thread if we do..
if (dwError != ERROR_NO_MORE_ITEMS &&
dwError != ERROR_SUCCESS &&
dwError != ERROR_MORE_DATA)
{
Trace1("DHCP snapin: EnumerateAllocationRanges error: %d\n", dwError);
m_dwErr = dwError;
PostError(dwError);
}
}
return hrFalse;
}