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

1520 lines
44 KiB
C++

//////////////////////////////////////////////////////////////////////////////
/*++
Copyright (C) Microsoft Corporation
Module Name:
PolicyNode.cpp
Abstract:
Implementation file for the CPolicyNode class.
Revision History:
mmaguire 12/15/97 - created
--*/
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// BEGIN INCLUDES
//
// standard includes:
//
#include "Precompiled.h"
//
// where we can find declaration for main class in this file:
//
#include "PolicyNode.h"
#include "Component.h"
#include "SnapinNode.cpp" // Template implementation
//
//
// where we can find declarations needed in this file:
//
#include "PoliciesNode.h"
#include "PolicyPage1.h"
#include "rapwz_name.h"
#include "rapwz_cond.h"
#include "rapwz_allow.h"
#include "rapwz_profile.h"
#include "NapUtil.h"
#include "ChangeNotification.h"
#include "rapwiz.h"
//
// END INCLUDES
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/*++
CPolicyNode::CPolicyNode
Constructor
--*/
//////////////////////////////////////////////////////////////////////////////
CPolicyNode::CPolicyNode( CSnapInItem * pParentNode,
LPTSTR pszServerAddress,
CIASAttrList* pAttrList,
BOOL fBrandNewNode,
BOOL fUseActiveDirectory,
bool isWin2k
)
:CSnapinNode<CPolicyNode, CComponentData, CComponent>( pParentNode ),
m_isWin2k(isWin2k)
{
TRACE_FUNCTION("CPolicyNode::CPolicyNode");
_ASSERTE( pAttrList != NULL );
// For the help files
m_helpIndex = (!((CPoliciesNode *)m_pParentNode )->m_fExtendingIAS)?RAS_HELP_INDEX:0;
// Here we store an index to which of these images we
// want to be used to display this node
m_scopeDataItem.nImage = IDBI_NODE_POLICY;
//
// initialize the merit value. This value will be set when the node is added
// to a MeritNodeArray.
// This is handled in call back API: SetMerit()
//
m_nMeritValue = 0;
// initialize the machine name
m_pszServerAddress = pszServerAddress;
// no property page when initialized
m_pPolicyPage1 = NULL ;
//
// initialize the condition attribute list
//
m_pAttrList = pAttrList;
// yes, it is a new node
m_fBrandNewNode = fBrandNewNode;
// are we using active directory
m_fUseActiveDirectory = fUseActiveDirectory;
//
// get the location for the policy
//
TCHAR tszLocationStr[IAS_MAX_STRING];
HINSTANCE hInstance = _Module.GetResourceInstance();
if ( m_fUseActiveDirectory)
{
// active directory
int iRes = LoadString(hInstance,
IDS_POLICY_LOCATION_ACTIVEDS,
tszLocationStr,
IAS_MAX_STRING
);
_ASSERT( iRes > 0 );
}
else
{
// local or remote machine
if (m_pszServerAddress && _tcslen(m_pszServerAddress)>0)
{
_tcscpy(tszLocationStr, m_pszServerAddress);
}
else
{
// local machine
int iRes = LoadString(hInstance,
IDS_POLICY_LOCATION_LOCAL,
tszLocationStr,
IAS_MAX_STRING
);
_ASSERT( iRes > 0 );
if ( !tszLocationStr )
{
// resource has been corrupted -- we hard code it then.
// this way we will guarantee tzLocationStr won't be NULL.
_tcscpy(tszLocationStr, _T("Local Machine"));
}
}
}
m_ptzLocation = new TCHAR[_tcslen(tszLocationStr)+1];
if ( m_ptzLocation )
{
_tcscpy(m_ptzLocation, tszLocationStr);
}
// to remember the object, so can use used within UPdateToolbarBotton
m_pControBarNotifySnapinObj = NULL;
}
//////////////////////////////////////////////////////////////////////////////
/*++
CPolicyNode::~CPolicyNode
Destructor
--*/
//////////////////////////////////////////////////////////////////////////////
CPolicyNode::~CPolicyNode()
{
TRACE_FUNCTION("CPolicyNode::~CPolicyNode");
if ( m_ptzLocation )
{
delete[] m_ptzLocation;
}
}
//////////////////////////////////////////////////////////////////////////////
/*++
CPolicyNode::CreatePropertyPages
See CSnapinNode::CreatePropertyPages (which this method overrides) for detailed info.
--*/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPolicyNode::CreatePropertyPages (
LPPROPERTYSHEETCALLBACK pPropertySheetCallback
, LONG_PTR hNotificationHandle
, IUnknown* pUnk
, DATA_OBJECT_TYPES type
)
{
TRACE_FUNCTION("CPolicyNode::CreatePropertyPages");
HRESULT hr = S_OK;
#ifndef NO_ADD_POLICY_WIZARD
if( IsBrandNew() )
{
// We are adding a new policy -- use the wizard pages.
// four old pages
CNewRAPWiz_Name * pNewRAPWiz_Name = NULL;
CNewRAPWiz_Condition * pNewRAPWiz_Condition = NULL;
CNewRAPWiz_AllowDeny * pNewRAPWiz_AllowDeny = NULL;
CNewRAPWiz_EditProfile * pNewRAPWiz_EditProfile = NULL;
// four new pages
CPolicyWizard_Start* pNewRAPWiz_Start = NULL;
CPolicyWizard_Scenarios* pNewRAPWiz_Scenarios = NULL;
CPolicyWizard_Groups* pNewRAPWiz_Group = NULL;
CPolicyWizard_Authentication* pNewRAPWiz_Authentication = NULL;
CPolicyWizard_Encryption* pNewRAPWiz_Encryption = NULL;
CPolicyWizard_Encryption_VPN* pNewRAPWiz_Encryption_VPN = NULL;
CPolicyWizard_Encryption_Wireless* pNewRAPWiz_Encryption_Wireless = NULL;
CPolicyWizard_EAP* pNewRAPWiz_EAP = NULL;
CPolicyWizard_Finish* pNewRAPWiz_Finish = NULL;
try
{
TCHAR lpszTabName[IAS_MAX_STRING];
int nLoadStringResult;
//===================================
//
// new pages wizard pages
//
// wizard data object
CComPtr<CRapWizardData> spRapWizData;
CComObject<CRapWizardData>* pRapWizData;
CComObject<CRapWizardData>::CreateInstance(&pRapWizData);
spRapWizData = pRapWizData;
// set context information
spRapWizData->SetInfo(m_pszServerAddress, this, m_spDictionarySdo, m_spPolicySdo, m_spProfileSdo, m_spPoliciesCollectionSdo, m_spProfilesCollectionSdo, m_spSdoServiceControl, m_pAttrList);
//
// Create each of the four old wizard pages.
nLoadStringResult = LoadString( _Module.GetResourceInstance(), IDS_ADD_POLICY_WIZ_TAB_NAME, lpszTabName, IAS_MAX_STRING );
_ASSERT( nLoadStringResult > 0 );
// scenario page
pNewRAPWiz_Start = new CPolicyWizard_Start(spRapWizData, hNotificationHandle, lpszTabName);
// scenario page
pNewRAPWiz_Scenarios = new CPolicyWizard_Scenarios(spRapWizData, hNotificationHandle, lpszTabName);
// group page
pNewRAPWiz_Group = new CPolicyWizard_Groups(spRapWizData, hNotificationHandle, lpszTabName);
// authen page
pNewRAPWiz_Authentication = new CPolicyWizard_Authentication(spRapWizData, hNotificationHandle, lpszTabName);
// encryption page
pNewRAPWiz_Encryption = new CPolicyWizard_Encryption(spRapWizData, hNotificationHandle, lpszTabName);
pNewRAPWiz_Encryption_VPN = new CPolicyWizard_Encryption_VPN(spRapWizData, hNotificationHandle, lpszTabName);
pNewRAPWiz_Encryption_Wireless = new CPolicyWizard_Encryption_Wireless(spRapWizData, hNotificationHandle, lpszTabName);
// EAP page
pNewRAPWiz_EAP = new CPolicyWizard_EAP(spRapWizData, hNotificationHandle, lpszTabName);
// finish page
pNewRAPWiz_Finish = new CPolicyWizard_Finish(spRapWizData, hNotificationHandle, lpszTabName);
// These pages will take care of deleting themselves when they
// receive the PSPCB_RELEASE message.
// We specify TRUE for the bOwnsNotificationHandle parameter in one of the pages
// so that this page's destructor will be responsible for freeing the
// notification handle. Only one page per sheet should do this.
pNewRAPWiz_Name = new CNewRAPWiz_Name(spRapWizData, hNotificationHandle, lpszTabName, TRUE );
if( ! pNewRAPWiz_Name ) throw E_OUTOFMEMORY;
pNewRAPWiz_Condition = new CNewRAPWiz_Condition(spRapWizData, hNotificationHandle, m_pAttrList, lpszTabName );
if( ! pNewRAPWiz_Condition) throw E_OUTOFMEMORY;
pNewRAPWiz_AllowDeny = new CNewRAPWiz_AllowDeny(spRapWizData, hNotificationHandle, lpszTabName );
if( ! pNewRAPWiz_AllowDeny ) throw E_OUTOFMEMORY;
pNewRAPWiz_EditProfile = new CNewRAPWiz_EditProfile(
spRapWizData,
hNotificationHandle,
m_pAttrList,
lpszTabName,
m_isWin2k
);
if( ! pNewRAPWiz_EditProfile ) throw E_OUTOFMEMORY;
// Marshall pointers to pNewRAPWiz_Name
// Pass the pages our SDO's. These don't need to be marshalled
// as wizard pages run in the same thread.
// Add each of the pages to the MMC property sheet.
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_Start->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_Name->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_Scenarios->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_Group->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_Authentication->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_Encryption->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_Encryption_VPN->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_Encryption_Wireless->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_EAP->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_Condition->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_AllowDeny->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_EditProfile->Create() );
if( FAILED(hr) ) throw hr;
hr = pPropertySheetCallback->AddPage( pNewRAPWiz_Finish->Create() );
if( FAILED(hr) ) throw hr;
// This node is no longer new.
SetBrandNew(FALSE);
}
catch(...)
{
// Delete whatever was successfully allocated.
delete pNewRAPWiz_Name;
delete pNewRAPWiz_Condition;
delete pNewRAPWiz_AllowDeny;
delete pNewRAPWiz_EditProfile;
delete pNewRAPWiz_Scenarios;
delete pNewRAPWiz_Authentication;
delete pNewRAPWiz_Encryption;
delete pNewRAPWiz_Encryption_VPN;
delete pNewRAPWiz_Encryption_Wireless;
delete pNewRAPWiz_EAP;
delete pNewRAPWiz_Finish;
ShowErrorDialog( NULL, IDS_ERROR_CANT_CREATE_OBJECT, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
return E_OUTOFMEMORY;
}
}
else
{
// We are editing an existing policy -- use the property sheet.
// This page will take care of deleting itself when it
// receives the PSPCB_RELEASE message.
//
TCHAR tszTabName[IAS_MAX_STRING];
HINSTANCE hInstance = _Module.GetResourceInstance();
// load tab name, currently "Settings"
int iRes = LoadString(hInstance,
IDS_POLICY_PROPERTY_PAGE_TABNAME,
tszTabName,
IAS_MAX_STRING
);
if ( iRes <= 0 )
{
_tcscpy(tszTabName, _T("Settings"));
}
m_pPolicyPage1 = new CPolicyPage1(
hNotificationHandle,
this,
m_pAttrList,
tszTabName,
TRUE,
m_isWin2k
);
if( NULL == m_pPolicyPage1 )
{
hr = HRESULT_FROM_WIN32(GetLastError());
ErrorTrace(ERROR_NAPMMC_POLICYNODE, ("Can't create property pages, err = %x"), hr);
goto failure;
}
//
// marshall the Policy Sdo pointer
//
hr = CoMarshalInterThreadInterfaceInStream(
IID_ISdo //Reference to the identifier of the interface
, m_spPolicySdo //Pointer to the interface to be marshaled
, &( m_pPolicyPage1->m_pStreamPolicySdoMarshall ) //Address of output variable that receives the IStream interface pointer for the marshaled interface
);
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_MARSHALL, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
goto failure;
}
//
// marshall the Dictionary Sdo pointer
//
hr = CoMarshalInterThreadInterfaceInStream(
IID_ISdoDictionaryOld
, m_spDictionarySdo
, &( m_pPolicyPage1->m_pStreamDictionarySdoMarshall )
);
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_MARSHALL, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
goto failure;
}
//
// marshall the Profile Sdo pointer
//
hr = CoMarshalInterThreadInterfaceInStream(
IID_ISdo
, m_spProfileSdo
, &( m_pPolicyPage1->m_pStreamProfileSdoMarshall )
);
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_MARSHALL, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
goto failure;
}
//
// marshall the Profile collection Sdo pointer
//
hr = CoMarshalInterThreadInterfaceInStream(
IID_ISdoCollection
, m_spProfilesCollectionSdo
, &( m_pPolicyPage1->m_pStreamProfilesCollectionSdoMarshall )
);
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_MARSHALL, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
goto failure;
}
//
// marshall the Policy collection Sdo pointer
//
hr = CoMarshalInterThreadInterfaceInStream(
IID_ISdoCollection
, m_spPoliciesCollectionSdo
, &( m_pPolicyPage1->m_pStreamPoliciesCollectionSdoMarshall )
);
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_MARSHALL, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
goto failure;
}
// Marshall the Service Control Sdo pointer.
hr = CoMarshalInterThreadInterfaceInStream(
IID_ISdoServiceControl
, m_spSdoServiceControl
, &( m_pPolicyPage1->m_pStreamSdoServiceControlMarshall )
);
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_MARSHALL, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
goto failure;
}
// add the property pages
hr = pPropertySheetCallback->AddPage(m_pPolicyPage1->Create());
_ASSERT( SUCCEEDED( hr ) );
return hr;
failure:
if (m_pPolicyPage1)
{
delete m_pPolicyPage1;
m_pPolicyPage1 = NULL;
}
return hr;
}
return hr;
#else // NO_ADD_POLICY_WIZARD
// This page will take care of deleting itself when it
// receives the PSPCB_RELEASE message.
//
TCHAR tszTabName[IAS_MAX_STRING];
HINSTANCE hInstance = _Module.GetResourceInstance();
// load tab name, currently "Settings"
int iRes = LoadString(hInstance,
IDS_POLICY_PROPERTY_PAGE_TABNAME,
tszTabName,
IAS_MAX_STRING
);
if ( iRes <= 0 )
{
_tcscpy(tszTabName, _T("Settings"));
}
m_pPolicyPage1 = new CPolicyPage1(
hNotificationHandle,
this,
m_pAttrList,
tszTabName,
TRUE,
m_isWin2k
);
if( NULL == m_pPolicyPage1 )
{
hr = HRESULT_FROM_WIN32(GetLastError());
ErrorTrace(ERROR_NAPMMC_POLICYNODE, ("Can't create property pages, err = %x"), hr);
goto failure;
}
//
// marshall the Policy Sdo pointer
//
hr = CoMarshalInterThreadInterfaceInStream(
IID_ISdo //Reference to the identifier of the interface
, m_spPolicySdo //Pointer to the interface to be marshaled
, &( m_pPolicyPage1->m_pStreamPolicySdoMarshall ) //Address of output variable that receives the IStream interface pointer for the marshaled interface
);
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_MARSHALL, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
goto failure;
}
//
// marshall the Dictionary Sdo pointer
//
hr = CoMarshalInterThreadInterfaceInStream(
IID_ISdoDictionaryOld
, m_spDictionarySdo
, &( m_pPolicyPage1->m_pStreamDictionarySdoMarshall )
);
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_MARSHALL, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
goto failure;
}
//
// marshall the Profile Sdo pointer
//
hr = CoMarshalInterThreadInterfaceInStream(
IID_ISdo
, m_spProfileSdo
, &( m_pPolicyPage1->m_pStreamProfileSdoMarshall )
);
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_MARSHALL, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
goto failure;
}
//
// marshall the Profile collection Sdo pointer
//
hr = CoMarshalInterThreadInterfaceInStream(
IID_ISdoCollection
, m_spProfilesCollectionSdo
, &( m_pPolicyPage1->m_pStreamProfilesCollectionSdoMarshall )
);
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_MARSHALL, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
goto failure;
}
//
// marshall the Policy collection Sdo pointer
//
hr = CoMarshalInterThreadInterfaceInStream(
IID_ISdoCollection
, m_spPoliciesCollectionSdo
, &( m_pPolicyPage1->m_pStreamPoliciesCollectionSdoMarshall )
);
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_MARSHALL, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
goto failure;
}
// add the property pages
hr = pPropertySheetCallback->AddPage(m_pPolicyPage1->Create());
_ASSERT( SUCCEEDED( hr ) );
return hr;
failure:
if (m_pPolicyPage1)
{
delete m_pPolicyPage1;
m_pPolicyPage1 = NULL;
}
return hr;
#endif // NO_ADD_POLICY_WIZARD
}
//////////////////////////////////////////////////////////////////////////////
/*++
CPolicyNode::QueryPagesFor
See CSnapinNode::QueryPagesFor (which this method overrides) for detailed info.
--*/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPolicyNode::QueryPagesFor ( DATA_OBJECT_TYPES type )
{
TRACE_FUNCTION("CPolicyNode::QueryPagesFor");
// S_OK means we have pages to display
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////
/*++
CPolicyNode::GetResultPaneColInfo
See CSnapinNode::GetResultPaneColInfo (which this method overrides) for detailed info.
--*/
//////////////////////////////////////////////////////////////////////////////
OLECHAR* CPolicyNode::GetResultPaneColInfo(int nCol)
{
TRACE_FUNCTION("CPolicyNode::GetResultPaneColInfo");
if (nCol == 0 && m_bstrDisplayName != NULL)
return m_bstrDisplayName;
switch( nCol )
{
case 0:
return m_bstrDisplayName;
break;
case 1:
// display the merit value for this policy node
wsprintf(m_tszMeritString, L"%d", m_nMeritValue);
return m_tszMeritString;
break;
case 2: return m_ptzLocation;
break;
default:
// ISSUE: error -- should we assert here?
return L"@Invalid column";
}
}
//////////////////////////////////////////////////////////////////////////////
/*++
CPolicyNode::OnRename
See CSnapinNode::OnRename (which this method overrides) for detailed info.
--*/
//////////////////////////////////////////////////////////////////////////////
HRESULT CPolicyNode::OnRename(
LPARAM arg
, LPARAM param
, IComponentData * pComponentData
, IComponent * pComponent
, DATA_OBJECT_TYPES type
)
{
TRACE_FUNCTION("CPolicyNode::OnRename");
// Check for preconditions:
_ASSERTE( pComponentData != NULL || pComponent != NULL );
CComPtr<IConsole> spConsole;
HRESULT hr = S_FALSE;
CComVariant spVariant;
CComBSTR bstrError;
try
{
// We need IConsole
if( pComponentData != NULL )
{
spConsole = ((CComponentData*)pComponentData)->m_spConsole;
}
else
{
spConsole = ((CComponent*)pComponent)->m_spConsole;
}
_ASSERTE( spConsole != NULL );
// This returns S_OK if a property sheet for this object already exists
// and brings that property sheet to the foreground.
// It returns S_FALSE if the property sheet wasn't found.
hr = BringUpPropertySheetForNode(
this
, pComponentData
, pComponent
, spConsole
);
if( FAILED( hr ) )
{
return hr;
}
if( S_OK == hr )
{
// We found a property sheet already up for this node.
ShowErrorDialog( NULL, IDS_ERROR_CLOSE_PROPERTY_SHEET, NULL, S_OK, USE_DEFAULT, GetComponentData()->m_spConsole );
return hr;
}
// We didn't find a property sheet already up for this node.
_ASSERTE( S_FALSE == hr );
{
::CString str = (OLECHAR *) param;
str.TrimLeft();
str.TrimRight();
if (str.IsEmpty())
{
ShowErrorDialog( NULL, IDS_ERROR__POLICYNAME_EMPTY);
hr = S_FALSE;
return hr;
}
}
// Make a BSTR out of the new name.
spVariant.vt = VT_BSTR;
spVariant.bstrVal = SysAllocString( (OLECHAR *) param );
_ASSERTE( spVariant.bstrVal != NULL );
// Try to change the name of the policy -- pass the new BSTR to the Sdo.
hr = m_spPolicySdo->PutProperty( PROPERTY_SDO_NAME, &spVariant );
if( FAILED( hr ) )
{
ErrorTrace(DEBUG_NAPMMC_POLICYNODE, "Couldn't put policy name, err = %x", hr);
throw hr;
}
// Need to change the name of the associated profile as well.
hr = m_spProfileSdo->PutProperty( PROPERTY_SDO_NAME, &spVariant );
if( FAILED( hr ) )
{
ErrorTrace(DEBUG_NAPMMC_POLICYNODE, "Couldn't put profile name, err = %x", hr);
throw hr;
}
hr = m_spProfileSdo->Apply();
if( FAILED( hr ) )
{
ErrorTrace(DEBUG_NAPMMC_POLICYNODE, "Couldn't apply profile change, err = %x", hr);
throw hr;
}
// Set the profile association in the policy.
hr = m_spPolicySdo->PutProperty(PROPERTY_POLICY_PROFILE_NAME, &spVariant );
if( FAILED(hr) )
{
ErrorTrace(DEBUG_NAPMMC_POLICYNODE, "Couldn't put profile name for this policy, err = %x", hr);
throw hr;
}
hr = m_spPolicySdo->Apply();
if( FAILED( hr ) )
{
ErrorTrace(DEBUG_NAPMMC_POLICYNODE, "Couldn't apply policy change, err = %x", hr);
throw hr;
}
// ISSUE: We will need to invest some time here to make sure that if the two calls above fail,
// we change things back to a state where they will work -- this seems to be mostly a
// limitation of the SDO's here -- what if my attempt to change it back fails?
// Tell the service to reload data.
HRESULT hrTemp = m_spSdoServiceControl->ResetService();
if( FAILED( hrTemp ) )
{
ErrorTrace(ERROR_NAPMMC_POLICYNODE, "ISdoServiceControl::ResetService() failed, err = %x", hrTemp);
}
m_bstrDisplayName = spVariant.bstrVal;
// Insure that MMC refreshes all views of this object
// to reflect the renaming.
CChangeNotification *pChangeNotification = new CChangeNotification();
pChangeNotification->m_dwFlags = CHANGE_UPDATE_RESULT_NODE;
pChangeNotification->m_pNode = this;
hr = spConsole->UpdateAllViews( NULL, (LPARAM) pChangeNotification, 0);
pChangeNotification->Release();
}
catch(...)
{
if(hr == DB_E_NOTABLE) // assume, the RPC connection has problem
{
ShowErrorDialog(NULL, IDS_ERROR__NOTABLE_TO_WRITE_SDO, NULL, S_OK, USE_DEFAULT, GetComponentData()->m_spConsole);
}
else if(hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) || hr == E_INVALIDARG)
{
ShowErrorDialog(NULL, IDS_ERROR_INVALID_POLICYNAME, NULL, S_OK, USE_DEFAULT, GetComponentData()->m_spConsole);
}
else
{
ShowErrorDialog(NULL, IDS_ERROR_RENAMEPOLICY, NULL, S_OK, USE_DEFAULT, GetComponentData()->m_spConsole);
}
hr = S_FALSE;
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
/*++
CPolicyNode::OnDelete
See CSnapinNode::OnDelete (which this method overrides) for detailed info.
--*/
//////////////////////////////////////////////////////////////////////////////
HRESULT CPolicyNode::OnDelete(
LPARAM arg
, LPARAM param
, IComponentData * pComponentData
, IComponent * pComponent
, DATA_OBJECT_TYPES type
, BOOL fSilent
)
{
TRACE_FUNCTION("CPolicyNode::OnDelete");
// Check for preconditions:
_ASSERTE( pComponentData != NULL || pComponent != NULL );
_ASSERTE( m_pParentNode != NULL );
HRESULT hr = S_OK;
// First try to see if a property sheet for this node is already up.
// If so, bring it to the foreground.
// It seems to be acceptable to query IPropertySheetCallback for an IPropertySheetProvider.
// 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 );
// This returns S_OK if a property sheet for this object already exists
// and brings that property sheet to the foreground.
// It returns S_FALSE if the property sheet wasn't found.
hr = BringUpPropertySheetForNode(
this
, pComponentData
, pComponent
, spConsole
);
if( FAILED( hr ) )
{
return hr;
}
if( S_OK == hr )
{
// We found a property sheet already up for this node.
ShowErrorDialog( NULL, IDS_ERROR_CLOSE_PROPERTY_SHEET, NULL, S_OK, USE_DEFAULT, GetComponentData()->m_spConsole );
return hr;
}
// We didn't find a property sheet already up for this node.
_ASSERTE( S_FALSE == hr );
if( FALSE == fSilent )
{
// Is this the last policy?
if ( ((CPoliciesNode *)m_pParentNode )->GetChildrenCount() == 1 )
{
int iLoadStringResult;
WCHAR szPolicyDeleteQuery[IAS_MAX_STRING];
WCHAR szTemp[IAS_MAX_STRING];
iLoadStringResult = LoadString( _Module.GetResourceInstance(), IDS_ERROR_ZERO_POLICY, szTemp, IAS_MAX_STRING );
_ASSERT( iLoadStringResult > 0 );
swprintf( szPolicyDeleteQuery, szTemp, m_bstrDisplayName );
int iResult = ShowErrorDialog(
NULL
, 1
, szPolicyDeleteQuery
, S_OK
, IDS_POLICY_NODE__DELETE_POLICY__PROMPT_TITLE
, spConsole
, MB_YESNO | MB_ICONQUESTION
);
if( IDYES != iResult )
{
// The user didn't confirm the delete operation.
return S_FALSE;
}
}
else
{
// It is not the last policy, but we want to ask the user
// to confirm the policy deletion anyway.
int iLoadStringResult;
WCHAR szPolicyDeleteQuery[IAS_MAX_STRING];
WCHAR szTemp[IAS_MAX_STRING];
iLoadStringResult = LoadString( _Module.GetResourceInstance(), IDS_POLICY_NODE__DELETE_POLICY__PROMPT, szTemp, IAS_MAX_STRING );
_ASSERT( iLoadStringResult > 0 );
swprintf( szPolicyDeleteQuery, szTemp, m_bstrDisplayName );
int iResult = ShowErrorDialog(
NULL
, 1
, szPolicyDeleteQuery
, S_OK
, IDS_POLICY_NODE__DELETE_POLICY__PROMPT_TITLE
, spConsole
, MB_YESNO | MB_ICONQUESTION
);
if( IDYES != iResult )
{
// The user didn't confirm the delete operation.
return S_FALSE;
}
}
}
// Try to delete the underlying data.
hr = ((CPoliciesNode *) m_pParentNode )->RemoveChild( this );
if( SUCCEEDED( hr ) )
{
delete this;
}
// Looks like RemoveChild takes care of putting up an error dialog if anything went wrong.
return hr;
}
//////////////////////////////////////////////////////////////////////////////
/*++
CPolicyNode::SetVerbs
See CSnapinNode::SetVerbs (which this method overrides) for detailed info.
--*/
//////////////////////////////////////////////////////////////////////////////
HRESULT CPolicyNode::SetVerbs( IConsoleVerb * pConsoleVerb )
{
TRACE_FUNCTION("CPolicyNode::SetVerbs");
HRESULT hr = S_OK;
// We want the user to be able to choose Properties on this node
hr = pConsoleVerb->SetVerbState( MMC_VERB_PROPERTIES, ENABLED, TRUE );
// We want Properties to be the default
hr = pConsoleVerb->SetDefaultVerb( MMC_VERB_PROPERTIES );
// We want the user to be able to delete this node
hr = pConsoleVerb->SetVerbState( MMC_VERB_DELETE, ENABLED, TRUE );
// We want the user to be able to rename this node
hr = pConsoleVerb->SetVerbState( MMC_VERB_RENAME, ENABLED, TRUE );
// We want to enable copy/paste
hr = pConsoleVerb->SetVerbState( MMC_VERB_COPY, ENABLED, FALSE);
hr = pConsoleVerb->SetVerbState( MMC_VERB_PASTE, ENABLED, FALSE );
return hr;
}
HRESULT CPolicyNode::ControlbarNotify(IControlbar *pControlbar,
IExtendControlbar *pExtendControlbar,
CSimpleMap<UINT, IUnknown*>* pToolbarMap,
MMC_NOTIFY_TYPE event,
LPARAM arg,
LPARAM param,
CSnapInObjectRootBase* pObj,
DATA_OBJECT_TYPES type)
{
m_pControBarNotifySnapinObj = pObj;
return CSnapinNode< CPolicyNode, CComponentData, CComponent >::ControlbarNotify(pControlbar,
pExtendControlbar,
pToolbarMap,
event,
arg,
param,
pObj,
type);
}
//+---------------------------------------------------------------------------
//
// Function: CPolicyNode::OnPolicyMoveUp
//
// Synopsis: move the policy node one level up
//
// Arguments: bool &bHandled - is this command handled?
// CSnapInObjectRoot* pObj -
//
// Returns: HRESULT -
//
// History: Created Header byao 3/5/98 9:56:37 PM
//
//+---------------------------------------------------------------------------
HRESULT CPolicyNode::OnPolicyMoveUp( bool &bHandled, CSnapInObjectRootBase* pObj )
{
// HACK ... HACK -- not supposed to assume this
// but at least we can do something better is this is true
CComponent* pComp = NULL;
try{
pComp = dynamic_cast<CComponent*>(pObj);
}
catch(...)
{
}
if(pComp
&& pComp->m_nLastClickedColumn == 1 /* order */
&& (pComp->m_dwLastSortOptions & RSI_DESCENDING) != 0) // DESCENDING
{
((CPoliciesNode *) m_pParentNode )->MoveDownChild( this );
}
else // normal
{
((CPoliciesNode *) m_pParentNode )->MoveUpChild( this );
}
bHandled = TRUE;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: CPolicyNode::OnPolicyMoveDown
//
// Synopsis: move down the policy node one level
//
// Arguments: bool &bHandled -
// CSnapInObjectRoot* pObj -
//
// Returns: HRESULT -
//
// History: Created Header byao 3/5/98 9:57:31 PM
//
//+---------------------------------------------------------------------------
HRESULT CPolicyNode::OnPolicyMoveDown( bool &bHandled, CSnapInObjectRootBase* pObj )
{
// HACK ... HACK -- not supposed to assume this
// but at least we can do something better is this is true
CComponent* pComp = NULL;
try{
pComp = dynamic_cast<CComponent*>(pObj);
}
catch(...)
{
}
if(pComp
&& pComp->m_nLastClickedColumn == 1 /* order */
&& (pComp->m_dwLastSortOptions & RSI_DESCENDING) != 0) // DESCENDING
{
((CPoliciesNode *) m_pParentNode )->MoveUpChild( this );
}
else // normal
{
((CPoliciesNode *) m_pParentNode )->MoveDownChild( this );
}
bHandled = TRUE;
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////
/*++
CPolicyNode::GetComponentData
This method returns our unique CComponentData object representing the scope
pane of this snapin.
It relies upon the fact that each node has a pointer to its parent,
except for the root node, which instead has a member variable pointing
to CComponentData.
This would be a useful function to use if, for example, you need a reference
to some IConsole but you weren't passed one. You can use GetComponentData
and then use the IConsole pointer which is a member variable of our
CComponentData object.
--*/
//////////////////////////////////////////////////////////////////////////////
CComponentData * CPolicyNode::GetComponentData( void )
{
TRACE_FUNCTION("CPolicyNode::GetComponentData");
return ((CPoliciesNode *) m_pParentNode)->GetComponentData();
}
//+---------------------------------------------------------------------------
//
// Function: SetMerit
//
// Class: CPolicyNode
//
// Synopsis: set the merit value of the policy node
//
// Arguments: int nMeritValue - Merit value
//
// Returns: TRUE : succeed
// FALSE - otherwise
//
// History: Created byao 2/9/98 1:43:37 PM
//
// Note: when this node is added to the array list, the add API will call
// back this function to set the merit value
//+---------------------------------------------------------------------------
BOOL CPolicyNode::SetMerit(int nMeritValue)
{
TRACE_FUNCTION("CPolicyNode::SetMerit");
HRESULT hr = S_OK;
if(m_nMeritValue != nMeritValue)
{
m_nMeritValue = nMeritValue;
//
// set this property in the SDO policy object also
//
CComVariant var;
V_VT(&var) = VT_I4;
V_I4(&var) = m_nMeritValue;
hr = m_spPolicySdo->PutProperty( PROPERTY_POLICY_MERIT, &var);
//
// save this property.
//
m_spPolicySdo->Apply();
}
return (SUCCEEDED(hr));
}
//+---------------------------------------------------------------------------
//
// Function: GetMerit
//
// Class: CPolicyNode
//
// Synopsis: get the merit value of the policy node
//
// Arguments: None
//
// Returns: merit value
//
// History: Created byao 2/9/98 1:43:37 PM
//
//+---------------------------------------------------------------------------
int CPolicyNode::GetMerit()
{
return m_nMeritValue;
}
//+---------------------------------------------------------------------------
//
// Function: SetSdo
//
// Class: CPolicyNode
//
// Synopsis: Initialize the Sdo pointers in the policy object
//
// Arguments: ISdo * pSdoPolicy - pointer to the policy SDO
//
// Returns: HRESULT - how does it go?
//
// History: Created Header byao 2/15/98 6:08:40 PM
//
//+---------------------------------------------------------------------------
HRESULT CPolicyNode::SetSdo( ISdo * pPolicySdo
, ISdoDictionaryOld * pDictionarySdo
, ISdo* pProfileSdo
, ISdoCollection* pProfilesCollectionSdo
, ISdoCollection* pPoliciesCollectionSdo
, ISdoServiceControl * pSdoServiceControl
)
{
TRACE_FUNCTION("CPolicyNode::SetSdo");
// Check for preconditions:
_ASSERTE( pPolicySdo != NULL );
_ASSERTE( pDictionarySdo != NULL );
_ASSERTE( pProfileSdo != NULL );
_ASSERTE( pProfilesCollectionSdo != NULL );
_ASSERTE( pProfilesCollectionSdo != NULL );
_ASSERTE( pSdoServiceControl != NULL );
// Save our sdo pointer.
m_spPolicySdo = pPolicySdo;
m_spDictionarySdo = pDictionarySdo;
m_spProfileSdo = pProfileSdo;
m_spProfilesCollectionSdo = pProfilesCollectionSdo;
m_spPoliciesCollectionSdo = pPoliciesCollectionSdo;
m_spSdoServiceControl = pSdoServiceControl;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: LoadSdoData
//
// Class: CPolicyNode
//
// Synopsis: Load data from SDO pointers
//
// Returns: HRESULT - how does it go?
//
// History: Created Header byao 3/10/98 6:08:40 PM
//
//+---------------------------------------------------------------------------
HRESULT CPolicyNode::LoadSdoData()
{
TRACE_FUNCTION("CPolicyNode::LoadSdoData");
HRESULT hr = S_OK;
CComVariant var;
if ( !m_spPolicySdo )
{
return E_INVALIDARG;
}
// Set the display name for this object.
hr = m_spPolicySdo->GetProperty( PROPERTY_SDO_NAME, &var );
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_SDO_ERROR_GETPROP_POLICYNAME, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
return hr;
}
_ASSERTE( V_VT(&var) == VT_BSTR );
m_bstrDisplayName = V_BSTR(&var);
var.Clear();
hr = m_spPolicySdo->GetProperty( PROPERTY_POLICY_MERIT, &var );
if ( FAILED(hr) )
{
ShowErrorDialog( NULL, IDS_ERROR_SDO_ERROR_GETPROP_POLICYMERIT, NULL, hr, USE_DEFAULT, GetComponentData()->m_spConsole );
return hr;
}
_ASSERTE( V_VT(&var) == VT_I4);
m_nMeritValue = V_I4(&var);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CPolicyNode::UpdateMenuState
//
// Synopsis: update MoveUp/MoveDown menu status according to the policy order
//
// Arguments: UINT id -
// LPTSTR pBuf -
// UINT *flags -
//
// Returns: Nothing
//
// History: Created Header byao 6/2/98 5:31:53 PM
//
//+---------------------------------------------------------------------------
void CPolicyNode::UpdateMenuState(UINT id, LPTSTR pBuf, UINT *flags)
{
TRACE_FUNCTION("CPolicyNode::UpdateMenuState");
// Check for preconditions:
BOOL bReverse = FALSE;
// need to trap this call ControlBarNotify and remember the component --- in pObj and then ...
if(m_pControBarNotifySnapinObj)
{
CComponent* pComp = NULL;
try{
pComp = dynamic_cast<CComponent*>(m_pControBarNotifySnapinObj);
}
catch(...)
{
}
if(pComp
&& pComp->m_nLastClickedColumn == 1 /* order */
&& (pComp->m_dwLastSortOptions & RSI_DESCENDING) != 0) // DESCENDING
{
bReverse = TRUE;
}
}
// Set the state of the appropriate context menu items.
if( (id == ID_MENUITEM_POLICY_TOP__MOVE_UP && !bReverse) || (id == ID_MENUITEM_POLICY_TOP__MOVE_DOWN && bReverse))
{
if ( 1 == m_nMeritValue )
{
//
// we should disable the MoveUp menu when it's already the first
//
*flags = MFS_GRAYED;
}
else
{
*flags = MFS_ENABLED;
}
}
else
{
if( (id == ID_MENUITEM_POLICY_TOP__MOVE_DOWN && !bReverse) || (id == ID_MENUITEM_POLICY_TOP__MOVE_UP && bReverse))
{
if ( m_nMeritValue == ((CPoliciesNode *)m_pParentNode)->GetChildrenCount() )
{
//
// we should disable the MoveDown menu when it's already the last
//
*flags = MFS_GRAYED;
}
else
{
*flags = MFS_ENABLED;
}
}
}
}
//+---------------------------------------------------------------------------
//
// Function: CPolicyNode::UpdateToolbarButton
//
// Synopsis: update MoveUp/MoveDown toolbar button
//
// Arguments: UINT id -
// BYTE fsState -
//
// Returns: Nothing
//
// History: Created Header byao 6/2/98 5:31:53 PM
//
//+---------------------------------------------------------------------------
BOOL CPolicyNode::UpdateToolbarButton(UINT id, BYTE fsState)
{
TRACE_FUNCTION("CPolicyNode::UpdateToolbarButton");
BOOL bReverse = FALSE;
// need to trap this call ControlBarNotify and remember the component --- in pObj and then ...
if(m_pControBarNotifySnapinObj)
{
CComponent* pComp = NULL;
try{
pComp = dynamic_cast<CComponent*>(m_pControBarNotifySnapinObj);
}
catch(...)
{
}
if(pComp
&& pComp->m_nLastClickedColumn == 1 /* order */
&& (pComp->m_dwLastSortOptions & RSI_DESCENDING) != 0) // DESCENDING
{
bReverse = TRUE;
}
}
// Check for preconditions:
// None.
// Set whether the buttons should be enabled.
if (fsState == ENABLED)
{
if(( id == ID_BUTTON_POLICY_MOVEUP && (!bReverse)) || (id == ID_BUTTON_POLICY_MOVEDOWN && bReverse))
{
if ( 1 == m_nMeritValue )
{
return FALSE;
}
else
{
return TRUE;
}
}
else
{
if(( id == ID_BUTTON_POLICY_MOVEDOWN && (!bReverse)) || (id == ID_BUTTON_POLICY_MOVEUP && bReverse))
{
if ( m_nMeritValue == ((CPoliciesNode *)m_pParentNode)->GetChildrenCount() )
{
return FALSE;
}
else
{
return TRUE;
}
}
}
}
// For all other possible button ID's and states, the correct answer here is FALSE.
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
/*++
CPolicyNode::OnPropertyChange
This is our own custom response to the MMCN_PROPERTY_CHANGE notification.
MMC never actually sends this notification to our snapin with a specific lpDataObject,
so it would never normally get routed to a particular node but we have arranged it
so that our property pages can pass the appropriate CSnapInItem pointer as the param
argument. In our CComponent::Notify override, we map the notification message to
the appropriate node using the param argument.
--*/
//////////////////////////////////////////////////////////////////////////////
HRESULT CPolicyNode::OnPropertyChange(
LPARAM arg
, LPARAM param
, IComponentData * pComponentData
, IComponent * pComponent
, DATA_OBJECT_TYPES type
)
{
TRACE_FUNCTION("CPolicyNode::OnPropertyChange");
// Check for preconditions:
// None.
return LoadSdoData();
}