Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

509 lines
13 KiB

//////////////////////////////////////////////////////////////////////////////
/*++
Copyright (C) Microsoft Corporation, 1997 - 1999
Module Name:
NodeWithScopeChildrenList.cpp
Abstract:
Implementation file for the CNodeWithScopeChildrenList subclass.
This is the implementation portion of an inline template class.
Include it in the .cpp file of the class in which you want to
use the template.
Author:
Michael A. Maguire 12/01/97
Revision History:
mmaguire 12/01/97 - abstracted from CRootNode, which will be changed to subclass this class
--*/
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// BEGIN INCLUDES
//
// standard includes:
//
//
// where we can find declaration for main class in this file:
//
#include "NodeWithScopeChildrenList.h"
//
//
// where we can find declarations needed in this file:
//
#include "SnapinNode.cpp" // Template class implementation
//
// END INCLUDES
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/*++
CNodeWithScopeChildrenList::AddChild
Adds a child to the list of children.
This has to be public as it must be accessible even from a separate dialog
(e.g. a Connect to Server dialog) that may want to add a child.
Here we add the child item to the list of children and call InsertItem
to add the child to the scope pane.
This is one difference between adding nodes into the scope
pane and the result pane. When we were inserting a child into
the result pane, we didn't call InsertItem in the AddChild methods(s)
because we needed to worry about sending an UpdataAllViews
notification and repopulating the result pane in each view.
Because MMC takes care of replicating scope pane changes to all views,
we don't need to worry about this. Instead, we just do InsertItem once here.
--*/
//////////////////////////////////////////////////////////////////////////////
template < class T, class CChildNode >
HRESULT CNodeWithScopeChildrenList<T,CChildNode>::AddChild( CChildNode * pChildNode )
{
ATLTRACE(_T("# CNodeWithScopeChildrenList::AddChild\n"));
// Check for preconditions:
// None.
HRESULT hr = S_OK;
if( m_ScopeChildrenList.Add( pChildNode ) )
{
// Insert the item into the result pane now
// so that the new item will show up immediately
CComponentData *pComponentData = GetComponentData();
_ASSERTE(pComponentData != NULL );
// Need IConsoleNameSpace
CComQIPtr<IConsoleNameSpace, &IID_IConsoleNameSpace> spConsoleNameSpace( pComponentData->m_spConsole );
_ASSERT( spConsoleNameSpace != NULL );
// We hand our HSCOPEITEM as the parent ID for this child.
pChildNode->m_scopeDataItem.relativeID = (HSCOPEITEM) m_scopeDataItem.ID;
hr = spConsoleNameSpace->InsertItem( &(pChildNode->m_scopeDataItem) );
if (FAILED(hr))
{
return hr;
}
// Check: On return, the ID member of 'm_scopeDataItem'
// contains the handle to the newly inserted item.
_ASSERT( NULL != pChildNode->m_scopeDataItem.ID );
}
else
{
// Failed to add => out of memory
hr = E_OUTOFMEMORY;
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
/*++
CNodeWithScopeChildrenList::RemoveChild
Removes a child from the list of children.
This has to be public so that child nodes can ask their parent to be deleted
from the list of children when they receive the MMCN_DELETE notification.
--*/
//////////////////////////////////////////////////////////////////////////////
template < class T, class CChildNode >
HRESULT CNodeWithScopeChildrenList<T,CChildNode>::RemoveChild( CChildNode * pChildNode )
{
ATLTRACE(_T("# CNodeWithScopeChildrenList::RemoveChild\n"));
// Check for preconditions:
// None.
HRESULT hr = S_OK;
if( m_ScopeChildrenList.Remove( pChildNode ) )
{
// Need IConsoleNameSpace
CComponentData *pComponentData = GetComponentData();
_ASSERTE(pComponentData != NULL );
CComQIPtr<IConsoleNameSpace, &IID_IConsoleNameSpace> spConsoleNameSpace( pComponentData->m_spConsole );
_ASSERT( spConsoleNameSpace != NULL );
hr = spConsoleNameSpace->DeleteItem( pChildNode->m_scopeDataItem.ID, TRUE );
if (FAILED(hr))
{
return hr;
}
}
else
{
// If we failed to remove, probably the child was never in the list
// ISSUE: determine what do here -- this should never happen
_ASSERTE( FALSE );
hr = S_FALSE;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
/*++
CNodeWithScopeChildrenList::CNodeWithScopeChildrenList
Constructor
This is an base class which we don't want instantiated on its own,
so the contructor is protected
--*/
//////////////////////////////////////////////////////////////////////////////
template < class T, class CChildNode >
CNodeWithScopeChildrenList<T,CChildNode>::CNodeWithScopeChildrenList( CSnapInItem * pParentNode ): CSnapinNode< T >( pParentNode )
{
ATLTRACE(_T("# +++ CNodeWithScopeChildrenList::CNodeWithScopeChildrenList\n"));
// Check for preconditions:
// None.
// We have not yet loaded the child nodes' data
m_bScopeChildrenListPopulated = FALSE;
}
/////////////////////////////////////////////////////////////////////////////
/*++
CNodeWithScopeChildrenList::~CNodeWithScopeChildrenList
Destructor
--*/
//////////////////////////////////////////////////////////////////////////////
template < class T, class CChildNode >
CNodeWithScopeChildrenList<T,CChildNode>::~CNodeWithScopeChildrenList()
{
ATLTRACE(_T("# --- CNodeWithScopeChildrenList::~CNodeWithScopeChildrenList\n"));
// Check for preconditions:
// None.
// Delete each node in the list of children
CChildNode* pChildNode;
for (int i = 0; i < m_ScopeChildrenList.GetSize(); i++)
{
pChildNode = m_ScopeChildrenList[i];
delete pChildNode;
}
// Empty the list
m_ScopeChildrenList.RemoveAll();
}
/////////////////////////////////////////////////////////////////////////////
/*++
CNodeWithScopeChildrenList::PopulateScopeChildrenList
Override this in your derived class to populate the list of children nodes.
--*/
//////////////////////////////////////////////////////////////////////////////
template < class T, class CChildNode >
HRESULT CNodeWithScopeChildrenList<T,CChildNode>::PopulateScopeChildrenList( void )
{
ATLTRACE(_T("# CNodeWithScopeChildrenList::PopulateScopeChildren -- override in your derived class\n"));
// Check for preconditions:
// None.
// override in your derived class and do something like:
/*
CSomeChildNode *myChild1 = new CSomeChildNode();
m_CChildrenList.Add(myChild1);
CSomeChildNode *myChild2 = new CSomeChildNode();
m_CChildrenList.Add(myChild2);
CSomeChildNode *myChild3 = new CSomeChildNode();
m_CChildrenList.Add(myChild3);
*/
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////
/*++
CNodeWithScopeChildrenList::OnShow
Don't override this in your derived class. Instead, override methods
which it calls: InsertColumns
This method is an override of CSnapinNode::OnShow. When MMC passes the
MMCN_SHOW method for this node.
For more information, see CSnapinNode::OnShow.
--*/
//////////////////////////////////////////////////////////////////////////////
template < class T, class CChildNode >
HRESULT CNodeWithScopeChildrenList<T,CChildNode>::OnShow(
LPARAM arg
, LPARAM param
, IComponentData * pComponentData
, IComponent * pComponent
, DATA_OBJECT_TYPES type
)
{
ATLTRACE(_T("# CNodeScopeChildrenList::OnShow\n"));
// Check for preconditions:
_ASSERTE( pComponentData != NULL || pComponent != NULL );
HRESULT hr = S_FALSE;
//ISSUE: only do this if selected (arg = TRUE) -- what should we do if not selected?
// See sburns' localsec example
if( arg )
{
// arg <> 0 => we are being selected.
// Need IHeaderCtrl.
// But to get that, first we need IConsole
CComPtr<IConsole> spConsole;
if( pComponentData != NULL )
{
spConsole = ((CComponentData*)pComponentData)->m_spConsole;
}
else
{
// We should have a non-null pComponent
spConsole = ((CComponent*)pComponent)->m_spConsole;
}
_ASSERTE( spConsole != NULL );
CComQIPtr<IHeaderCtrl, &IID_IHeaderCtrl> spHeaderCtrl(spConsole);
_ASSERT( spHeaderCtrl != NULL );
hr = InsertColumns( spHeaderCtrl );
_ASSERT( S_OK == hr );
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
/*++
CNodeWithScopeChildrenList::InsertColumns
Override this in your derived class.
This method is called by OnShow when it needs you to set the appropriate
column headers to be displayed in the result pane for this node.
--*/
//////////////////////////////////////////////////////////////////////////////
template < class T, class CChildNode >
HRESULT CNodeWithScopeChildrenList<T,CChildNode>::InsertColumns( IHeaderCtrl* pHeaderCtrl )
{
ATLTRACE(_T("# CNodeWithScopeChildrenList::InsertColumns -- override in your derived class\n"));
// Check for preconditions:
_ASSERTE( pHeaderCtrl != NULL );
HRESULT hr;
// override in your derived class and do something like:
hr = pHeaderCtrl->InsertColumn( 0, L"@Column 1 -- override CNodeWithResultChildrenList::OnShowInsertColumns", 0, 120 );
_ASSERT( S_OK == hr );
hr = pHeaderCtrl->InsertColumn( 1, L"@Column 2 -- override CNodeWithResultChildrenList::OnShowInsertColumns", 0, 300 );
_ASSERT( S_OK == hr );
return hr;
}
//////////////////////////////////////////////////////////////////////////////
/*++
CNodeWithScopeChildren::OnExpand
Don't override this in your derived class. Instead, override methods
which it calls: PopulateScopeChildrenList
This method is an override of CSnapinNode::OnExpand. When MMC passes the
MMCN_EXPAND method for this node, we are to add children into the
scope pane. In this class we add them from a list we maintain.
For more information, see CSnapinNode::OnExpand.
--*/
//////////////////////////////////////////////////////////////////////////////
template < class T, class CChildNode >
HRESULT CNodeWithScopeChildrenList<T,CChildNode>::OnExpand(
LPARAM arg
, LPARAM param
, IComponentData * pComponentData
, IComponent * pComponent
, DATA_OBJECT_TYPES type
)
{
ATLTRACE(_T("# CNodeWithScopeChildren::OnExpand\n"));
// Check for preconditions:
_ASSERTE( pComponentData != NULL || pComponent != NULL );
HRESULT hr = S_FALSE;
if( TRUE == arg )
{
// Need IConsoleNameSpace
// But to get that, first we need IConsole
CComPtr<IConsole> spConsole;
if( pComponentData != NULL )
{
spConsole = ((CComponentData*)pComponentData)->m_spConsole;
}
else
{
// We should have a non-null pComponent
spConsole = ((CComponent*)pComponent)->m_spConsole;
}
_ASSERTE( spConsole != NULL );
CComQIPtr<IConsoleNameSpace, &IID_IConsoleNameSpace> spConsoleNameSpace(spConsole);
_ASSERT( spConsoleNameSpace != NULL );
hr = EnumerateScopeChildren( spConsoleNameSpace );
}
else // arg != TRUE so not expanding
{
// do nothing for now -- I don't think arg = FALSE is even implemented
// for MMC v. 1.0 or 1.1
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
/*++
CNodeWithScopeChildrenList::EnumerateScopeChildren
Don't override this in your derived class. Instead, override the method
it calls, PopulateScopeChildrenList.
--*/
//////////////////////////////////////////////////////////////////////////////
template < class T, class CChildNode >
HRESULT CNodeWithScopeChildrenList<T,CChildNode>::EnumerateScopeChildren( IConsoleNameSpace* pConsoleNameSpace )
{
ATLTRACE(_T("# CNodeWithScopeChildrenList::EnumerateScopeChildren\n"));
// Check for preconditions:
// None.
HRESULT hr;
if ( FALSE == m_bScopeChildrenListPopulated )
{
// We have not yet loaded all of our children into our list.
hr = PopulateScopeChildrenList();
if( FAILED(hr) )
{
return( hr );
}
// We've already loaded our children objects with
// data necessary to populate the result pane.
m_bScopeChildrenListPopulated = TRUE; // We only want to do this once.
}
// We don't need any code here to InsertItem the children into the
// scope pane as we did in the EnumerateScopeChildren method
// for CNodeWithResultChildrenList.
// This is one difference between adding nodes into the scope
// pane and the result pane. Because MMC takes care of replicating
// scope pane changes to all views, we don't need to worry about
// sending an UpdateAllViews notification and handling insertion
// there for each result pane. Instead, we just do InsertItem once.
// So for CNodeWithScopePaneChildren, we call InsertItem
// in the AddChild method which is called by PopulateScopeChildrenList
// above.
return S_OK;
}