|
|
//
// cmponent.cpp : Declaration of Component.
//
// This COM object is primarily concerned with
// the result pane items.
//
// Cory West <[email protected]>
// Copyright (c) Microsoft Corporation 1997
//
#include "stdafx.h"
#include "macros.h"
USE_HANDLE_MACROS("SCHMMGMT(cmponent.cpp)")
#include "dataobj.h"
#include "cmponent.h" // Component
#include "compdata.h" // ComponentData
#include "schmutil.h"
#include "attrgen.hpp"
#include "stdcmpnt.cpp" // CComponent
//
// These arrays describe the result pane layout for when
// any particular object is selected.
//
UINT g_aColumns0[5] = {
IDS_COLUMN_NAME, IDS_COLUMN_TYPE, IDS_COLUMN_STATUS, IDS_COLUMN_DESCRIPTION, 0 };
UINT g_aColumns1[5] = {
IDS_COLUMN_NAME, IDS_COLUMN_SYNTAX, IDS_COLUMN_STATUS, IDS_COLUMN_DESCRIPTION, 0 };
UINT g_aColumns2[6] = {
IDS_COLUMN_NAME, IDS_COLUMN_TYPE, IDS_COLUMN_SYSTEM, IDS_COLUMN_DESCRIPTION, IDS_COLUMN_PARENT, 0 };
UINT g_aColumns3[2] = { IDS_COLUMN_NAME, 0 }; UINT* g_Columns[SCHMMGMT_NUMTYPES] = {
g_aColumns3, // SCHMMGMT_SCHMMGMT
g_aColumns0, // SCHMMGMT_CLASSES
g_aColumns1, // SCHMMGMT_ATTRIBUTES
g_aColumns2, // SCHMMGMT_CLASS
g_aColumns0, // SCHMMGMT_ATTRIBUTE // @@ Is this used?
};
UINT** g_aColumns = g_Columns;
//
// These control the column widths, which I will not change.
//
int g_aColumnWidths0[4] = {150,150,75,150}; int g_aColumnWidths1[5] = {150,75,75,150,150}; int g_aColumnWidths2[1] = {150};
int* g_ColumnWidths[SCHMMGMT_NUMTYPES] = {
g_aColumnWidths2, // SCHMMGMT_SCHMMGMT
g_aColumnWidths0, // SCHMMGMT_CLASSES
g_aColumnWidths0, // SCHMMGMT_ATTRIBUTES
g_aColumnWidths1, // SCHMMGMT_CLASS
g_aColumnWidths0, // SCHMMGMT_ATTRIBUTE
};
int** g_aColumnWidths = g_ColumnWidths;
//
// Constructors and destructors.
//
Component::Component() : m_pSvcMgmtToolbar( NULL ), m_pSchmMgmtToolbar( NULL ), m_pControlbar( NULL ), m_bDirty(false) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); m_pViewedCookie = NULL; }
Component::~Component() { TRACE_METHOD(Component,Destructor); VERIFY( SUCCEEDED(ReleaseAll()) ); }
HRESULT Component::ReleaseAll() { MFC_TRY;
TRACE_METHOD(Component,ReleaseAll);
SAFE_RELEASE(m_pSvcMgmtToolbar); SAFE_RELEASE(m_pSchmMgmtToolbar); SAFE_RELEASE(m_pControlbar);
return CComponent::ReleaseAll();
MFC_CATCH; }
//
// Support routines in ISchmMgmtComponent.
//
HRESULT Component::LoadColumns( Cookie* pcookie ) {
TEST_NONNULL_PTR_PARAM(pcookie); AFX_MANAGE_STATE(AfxGetStaticModuleState()); return LoadColumnsFromArrays( (INT)(pcookie->m_objecttype) ); }
HRESULT Component::OnViewChange( LPDATAOBJECT, LPARAM data, LPARAM function ) /***
This is called when IConsole->UpdateAllViews() is called. The data is a schema object type as follows:
if function == 0 (SCHMMGMT_UPDATEVIEW_REFRESH)
SCHMMGMT_ATTIBUTES - We need to refresh the attributes folder displays. SCHMMGMT_CLASS - We need to refresh _ALL_ class attribute displays. We don't try and trace the inheritance graphs and do a selective refresh, that's too complicated. SCHMMGMT_SCHMMGMT - Refresh EVERYTHING because we reloaded the schema cache.
else if function == 1 (SCHMMGMT_UPDATEVIEW_DELETE_RESULT_ITEM)
data is the Cookie pointer ***/ { //
// Refresh this result view.
//
if ( function == SCHMMGMT_UPDATEVIEW_REFRESH ) { if ( m_pViewedCookie ) {
if ( ( data == m_pViewedCookie->m_objecttype ) || ( data == SCHMMGMT_SCHMMGMT ) ) {
m_pResultData->DeleteAllRsltItems(); PopulateListbox( m_pViewedCookie );
} } } else if ( function == SCHMMGMT_UPDATEVIEW_DELETE_RESULT_ITEM ) { HRESULTITEM item; // FUTURE-2002-03/94/2002-dantra-Although this is a safe usage of ZeroMemory, suggest changing
// the definition of item to HRESULTITEM item = {0}; and removing the ZeroMemory call.
ZeroMemory( &item, sizeof(HRESULTITEM) );
HRESULT hr = m_pResultData->FindItemByLParam( data, &item ); if ( SUCCEEDED(hr) ) { hr = m_pResultData->DeleteItem( item, 0 ); ASSERT( SUCCEEDED(hr) );
} }
return S_OK; }
HRESULT Component::OnNotifySelect( LPDATAOBJECT lpDataObject, BOOL ) /***
This called in response to MMCN_SELECT. This routine will set the default verb and enable the toolbar buttons.
***/ { CCookie* pBaseParentCookie = NULL; HRESULT hr = ExtractData( lpDataObject, CSchmMgmtDataObject::m_CFRawCookie, OUT reinterpret_cast<PBYTE>(&pBaseParentCookie), sizeof(pBaseParentCookie) );
ASSERT( SUCCEEDED(hr) ); Cookie* pParentCookie = ActiveCookie(pBaseParentCookie); ASSERT( NULL != pParentCookie );
m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH,ENABLED,TRUE);
switch ( pParentCookie->m_objecttype ) {
case SCHMMGMT_CLASSES: case SCHMMGMT_ATTRIBUTES:
break;
case SCHMMGMT_CLASS: { //
// Set the default verb to display the properties of the selected object.
//
m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE); m_pConsoleVerb->SetDefaultVerb(MMC_VERB_PROPERTIES);
// if the schema class is defunct and the forest version is Whistler or higher
// then allow delete
/* Feature was removed for Whistler
ComponentData& Scope = QueryComponentDataRef(); if ( Scope.GetBasePathsInfo()->GetForestBehaviorVersion() >= 2) { SchemaObject *pSchemaObject = Scope.g_SchemaCache.LookupSchemaObjectByCN( pParentCookie->strSchemaObject, SCHMMGMT_CLASS );
if ( pSchemaObject && pSchemaObject->isDefunct ) { m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE); } } */ } break;
case SCHMMGMT_ATTRIBUTE:
if ( ( pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTE ) && ( pParentCookie->pParentCookie ) && ( pParentCookie->pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTES ) ) {
//
// Set the default verb to display the properties of the selected object.
//
m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE); m_pConsoleVerb->SetDefaultVerb(MMC_VERB_PROPERTIES);
// if the schema class is defunct and the forest version is Whistler or higher
// then allow delete
/* Feature was removed for Whistler
ComponentData& Scope = QueryComponentDataRef(); if ( Scope.GetBasePathsInfo()->GetForestBehaviorVersion() >= 2) { SchemaObject *pSchemaObject = Scope.g_SchemaCache.LookupSchemaObjectByCN( pParentCookie->strSchemaObject, SCHMMGMT_ATTRIBUTE );
if ( pSchemaObject && pSchemaObject->isDefunct ) { m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE); } } */ } else {
m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, TRUE); }
break;
default:
//
// Otherwise set the default verb to open/expand the folder.
//
m_pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN); break; }
return S_OK; }
HRESULT Component::Show( CCookie* pcookie, LPARAM arg, HSCOPEITEM hScopeItem ) /***
This is called in response to MMCN_SHOW.
***/ { TEST_NONNULL_PTR_PARAM(pcookie); HRESULT hr = S_OK;
do { if ( TRUE == arg ) // showing...
{ if( QueryComponentDataRef().IsSetDelayedRefreshOnShow() ) { HSCOPEITEM hItem = QueryComponentDataRef().GetDelayedRefreshOnShowItem(); ASSERT( hItem == hScopeItem );
QueryComponentDataRef().SetDelayedRefreshOnShow( NULL );
hr = m_pConsole->SelectScopeItem( hItem ); // will call GetResultViewType & Show
ASSERT_BREAK_ON_FAILED_HRESULT(hr); } else if( QueryComponentDataRef().IsErrorSet() ) { CComPtr<IUnknown> pUnknown; CComPtr<IMessageView> pMessageView; hr = m_pConsole->QueryResultView(&pUnknown); ASSERT_BREAK_ON_FAILED_HRESULT(hr);
hr = pUnknown->QueryInterface(IID_IMessageView, (PVOID*)&pMessageView); ASSERT_BREAK_ON_FAILED_HRESULT(hr);
pMessageView->SetTitleText( CComBSTR( QueryComponentDataRef().GetErrorTitle() ) ); pMessageView->SetBodyText( CComBSTR( QueryComponentDataRef().GetErrorText() ) ); pMessageView->SetIcon(Icon_Error); } else { m_pViewedCookie = (Cookie*)pcookie; LoadColumns( m_pViewedCookie ); hr = PopulateListbox( m_pViewedCookie ); } } else // hiding...
{ if( !QueryComponentDataRef().IsErrorSet() ) { if ( NULL == m_pResultData ) { ASSERT( FALSE ); hr = E_UNEXPECTED; break; }
m_pViewedCookie = NULL; } }
} while( FALSE );
return hr; }
HRESULT Component::OnNotifyAddImages( LPDATAOBJECT, LPIMAGELIST lpImageList, HSCOPEITEM ) /***
This routine is called in response to MMCN_ADD_IMAGES. Here's what mmc.idl says about this:
Sent to IComponent to add images for the result pane. The primary snapin should add images for both folders and leaf items.
arg = ptr to result panes IImageList. param = HSCOPEITEM of selected/deselected item
***/ { return QueryComponentDataRef().LoadIcons(lpImageList,TRUE); }
HRESULT Component::OnNotifyDelete( LPDATAOBJECT lpDataObject) { CThemeContextActivator activator;
CCookie* pBaseParentCookie = NULL;
HRESULT hr = ExtractData( lpDataObject, CSchmMgmtDataObject::m_CFRawCookie, reinterpret_cast<PBYTE>(&pBaseParentCookie), sizeof(pBaseParentCookie) ); ASSERT( SUCCEEDED(hr) );
Cookie* pParentCookie = ActiveCookie(pBaseParentCookie); ASSERT( NULL != pParentCookie );
UINT promptID = 0; LPARAM updateType = SCHMMGMT_CLASS;
if (pParentCookie->m_objecttype == SCHMMGMT_CLASS) { promptID = IDS_DELETE_CLASS_PROMPT; updateType = SCHMMGMT_CLASS; } else if (pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTE) { promptID = IDS_DELETE_ATTR_PROMPT; updateType = SCHMMGMT_ATTRIBUTES; } else { // We should never get called to delete anything but
// class and attribute nodes
ASSERT(FALSE); return E_FAIL; }
if( IDYES == AfxMessageBox( promptID, MB_YESNO | MB_ICONWARNING )) { hr = DeleteAttribute(pParentCookie); if ( SUCCEEDED(hr) ) { // Remove the node from the UI
hr = m_pConsole->UpdateAllViews( lpDataObject, (LPARAM)pParentCookie, SCHMMGMT_UPDATEVIEW_DELETE_RESULT_ITEM ); ASSERT( SUCCEEDED(hr) ); } else { CString szDeleteError; szDeleteError.Format(IDS_ERRMSG_DELETE_FAILED_ATTRIBUTE, GetErrorMessage(hr, TRUE)); DoErrMsgBox( ::GetActiveWindow(), TRUE, szDeleteError ); } }
return hr; }
HRESULT Component::DeleteAttribute( Cookie* pcookie ) /***
This deletes an attribute from the schema
***/ { HRESULT hr = S_OK;
do { if ( !pcookie ) { hr = E_INVALIDARG; break; }
ComponentData& Scope = QueryComponentDataRef();
SchemaObject* pObject = Scope.g_SchemaCache.LookupSchemaObjectByCN( pcookie->strSchemaObject, SCHMMGMT_ATTRIBUTE );
if ( !pObject ) { hr = E_FAIL; break; }
CString szAdsPath; Scope.GetSchemaObjectPath( pObject->commonName, szAdsPath );
hr = DeleteObject( szAdsPath, pcookie, g_AttributeFilter ); } while (false);
return hr; }
HRESULT Component::PopulateListbox( Cookie* pcookie ) /***
This populates the result pane when the result pane contains data that is not directly derived from the data in the scope pane.
***/ { switch ( pcookie->m_objecttype ) {
case SCHMMGMT_SCHMMGMT: case SCHMMGMT_CLASSES:
//
// We don't care about these - the result
// pane contains only scope items.
//
break;
case SCHMMGMT_ATTRIBUTES:
//
// List the specified items in the result pane
// with some informational data.
//
return FastInsertAttributeResultCookies( pcookie );
break;
case SCHMMGMT_CLASS:
//
// This results in the attributes used in this
// class and other class data being displayed.
//
return FastInsertClassAttributesResults( pcookie ); break;
case SCHMMGMT_ATTRIBUTE:
//
// This is not a scope pane item and can have no
// corresponding result pane data!!
//
ASSERT(FALSE); break;
}
return S_OK; }
HRESULT Component::FastInsertAttributeResultCookies( Cookie* pParentCookie ) /***
When the "Attributes" folder is selected, this puts the attributes in the result pane.
pParentCookie is the cookie for the parent object.
This routine is similar to ComponentData::FastInsertClassScopeCookies.
****/ {
HRESULT hr; SchemaObject *pObject, *pHead; Cookie *pNewCookie; RESULTDATAITEM ResultItem; LPCWSTR lpcszMachineName = pParentCookie->QueryNonNULLMachineName(); ComponentData& Scope = QueryComponentDataRef();
//
// Initialize the result item.
//
// FUTURE-2002-03/94/2002-dantra-Although this is a safe usage of ZeroMemory, suggest changing
// the definition RESULTDATAITEM ResultItem = {0} and removing the ZeroMemory call.
::ZeroMemory( &ResultItem, sizeof( ResultItem ) ); ResultItem.nCol = 0; ResultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM; ResultItem.str = MMC_CALLBACK; ResultItem.nImage = iIconAttribute; //
// Rather than having a clean class interface to the cache, we
// walk the cache data structures ourselves. This isn't super
// clean, but it's simple.
//
// Since we do this, we have to make sure that the cache is loaded.
//
Scope.g_SchemaCache.LoadCache();
pObject = Scope.g_SchemaCache.pSortedAttribs;
//
// If there's no sorted list, we can't insert anything!!!!
//
if ( !pObject ) { ASSERT( FALSE ); DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_NO_SCHEMA_PATH ); return S_OK; }
//
// Delete whatever was in the view before
// and do the insert.
//
pHead = pObject;
do {
if ( Scope.m_fViewDefunct || !pObject->isDefunct ) { //
// Insert this result.
//
pNewCookie= new Cookie( SCHMMGMT_ATTRIBUTE, lpcszMachineName );
if ( pNewCookie ) {
pNewCookie->pParentCookie = pParentCookie; pNewCookie->strSchemaObject = pObject->commonName;
pParentCookie->m_listScopeCookieBlocks.AddHead( (CBaseCookieBlock*)pNewCookie );
ResultItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pNewCookie); hr = m_pResultData->InsertItem( &ResultItem );
if ( SUCCEEDED(hr) ) {
pNewCookie->SetResultHandle( ResultItem.itemID );
} else {
delete pNewCookie; }
} }
pObject = pObject->pSortedListFlink;
} while ( pObject != pHead );
return S_OK; }
HRESULT Component::FastInsertClassAttributesResults( Cookie* pClassCookie ) /***
This routine displays all the attributes for a class.
***/ { HRESULT hr = S_OK; SchemaObject *pObject, *pTop; CString top = L"top"; ComponentData& Scope = QueryComponentDataRef();
//
// Call the attribute display routine. This routine
// will call itself recursively to display the
// inheritance structure of the class.
//
pObject = Scope.g_SchemaCache.LookupSchemaObjectByCN( pClassCookie->strSchemaObject, SCHMMGMT_CLASS );
if ( pObject ) {
CStringList szProcessedList; hr = RecursiveDisplayClassAttributesResults( pClassCookie, pObject, szProcessedList);
Scope.g_SchemaCache.ReleaseRef( pObject ); }
//
// Process "top" just once.
//
pTop = Scope.g_SchemaCache.LookupSchemaObject( top, SCHMMGMT_CLASS );
if ( pTop ) {
ProcessResultList( pClassCookie, pTop->systemMayContain, TRUE, TRUE, pTop ); ProcessResultList( pClassCookie, pTop->mayContain, TRUE, FALSE, pTop ); ProcessResultList( pClassCookie, pTop->systemMustContain, FALSE, TRUE, pTop ); ProcessResultList( pClassCookie, pTop->mustContain, FALSE, FALSE, pTop );
Scope.g_SchemaCache.ReleaseRef( pTop ); }
return hr;
}
HRESULT Component::RecursiveDisplayClassAttributesResults( Cookie *pParentCookie, SchemaObject* pObject, CStringList& szProcessedList ) /***
Display all the attributes for this class.
***/ {
ListEntry *pList; SchemaObject *pInheritFrom; ComponentData& Scope = QueryComponentDataRef();
//
// Don't process "top" here since everyone inherits from it.
//
if ( pObject->ldapDisplayName == L"top" ) { return S_OK; }
DebugTrace( L"RecursiveDisplayClassAttributesResults: %ls\n", const_cast<LPWSTR>((LPCTSTR)pObject->ldapDisplayName) );
//
// Insert all the attributes for this class.
// The second parameter dictates whether these
// are optional or not. The third parameter
// is the source of the attribute.
//
ProcessResultList( pParentCookie, pObject->systemMayContain, TRUE, TRUE, pObject ); ProcessResultList( pParentCookie, pObject->mayContain, TRUE, FALSE, pObject ); ProcessResultList( pParentCookie, pObject->systemMustContain, FALSE, TRUE, pObject ); ProcessResultList( pParentCookie, pObject->mustContain, FALSE, FALSE, pObject );
//
// For each auxiliary class, insert those attributes.
//
pList = pObject->systemAuxiliaryClass;
while ( pList ) {
pInheritFrom = Scope.g_SchemaCache.LookupSchemaObject( pList->Attribute, SCHMMGMT_CLASS , Scope.m_fViewDefunct); //
// Don't recursively process the item if we already processed it
//
if ( pInheritFrom && szProcessedList.Find(pList->Attribute) == NULL) { RecursiveDisplayClassAttributesResults( pParentCookie, pInheritFrom, szProcessedList ); szProcessedList.AddTail(pList->Attribute); Scope.g_SchemaCache.ReleaseRef( pInheritFrom ); }
pList = pList->pNext; }
pList = pObject->auxiliaryClass;
while ( pList ) {
pInheritFrom = Scope.g_SchemaCache.LookupSchemaObject( pList->Attribute, SCHMMGMT_CLASS, Scope.m_fViewDefunct); //
// Don't recursively process the item if we already processed it
//
if ( pInheritFrom && szProcessedList.Find(pList->Attribute) == NULL ) { RecursiveDisplayClassAttributesResults( pParentCookie, pInheritFrom, szProcessedList ); szProcessedList.AddTail(pList->Attribute); Scope.g_SchemaCache.ReleaseRef( pInheritFrom ); }
pList = pList->pNext; }
//
// If this is an inherited class, insert those attributes.
//
pInheritFrom = Scope.g_SchemaCache.LookupSchemaObject( pObject->subClassOf, SCHMMGMT_CLASS, Scope.m_fViewDefunct); if ( pInheritFrom ) { RecursiveDisplayClassAttributesResults( pParentCookie, pInheritFrom, szProcessedList ); Scope.g_SchemaCache.ReleaseRef( pInheritFrom ); }
return S_OK;
}
HRESULT Component::ProcessResultList( Cookie *pParentCookie, ListEntry *pList, BOOLEAN fOptional, BOOLEAN fSystem, SchemaObject* pSrcObject ) {
HRESULT hr; Cookie *pNewCookie; RESULTDATAITEM ResultItem; LPCWSTR lpcszMachineName = pParentCookie->QueryNonNULLMachineName(); ListEntry *pCurrent = NULL; SchemaObject *pAttribute=NULL;
ComponentData& Scope = QueryComponentDataRef(); //
// Initialize the result item.
//
// FUTURE-2002-03/94/2002-dantra-Although this is a safe usage of ZeroMemory, suggest changing
// the definition RESULTDATAITEM ResultItem = {0} and removing the ZeroMemory call.
::ZeroMemory( &ResultItem, sizeof( ResultItem ) ); ResultItem.nCol = 0; ResultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM; ResultItem.str = MMC_CALLBACK; ResultItem.nImage = iIconAttribute;
for (pCurrent = pList ; pCurrent != NULL; pCurrent = pCurrent->pNext) {
//
// Point to the actual attribute.
//
pAttribute = Scope.g_SchemaCache.LookupSchemaObject( pCurrent->Attribute, SCHMMGMT_ATTRIBUTE, Scope.m_fViewDefunct);
if(pAttribute==NULL) { ASSERT(pAttribute!=NULL); // All attributes should be in the cache
continue; }
//
// Make a new cookie.
//
pNewCookie = new Cookie( SCHMMGMT_ATTRIBUTE, lpcszMachineName );
if ( pNewCookie ) { //
// Record the optional status and the source.
//
if ( fOptional ) { pNewCookie->Mandatory = FALSE; } else { pNewCookie->Mandatory = TRUE; }
if ( fSystem ) { pNewCookie->System = TRUE; } else { pNewCookie->System = FALSE; }
pNewCookie->strSrcSchemaObject = pSrcObject->commonName; pNewCookie->pParentCookie = pParentCookie;
pNewCookie->strSchemaObject = pAttribute->commonName; Scope.g_SchemaCache.ReleaseRef( pAttribute );
//
// Insert the result pane item.
//
pParentCookie->m_listScopeCookieBlocks.AddHead( (CBaseCookieBlock*)pNewCookie );
ResultItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pNewCookie); hr = m_pResultData->InsertItem( &ResultItem );
if ( SUCCEEDED(hr) ) { pNewCookie->SetResultHandle( ResultItem.itemID ); } else { delete pNewCookie; } } }
return S_OK; }
STDMETHODIMP Component::AddMenuItems( LPDATAOBJECT, LPCONTEXTMENUCALLBACK piCallback, long* pInsertionsAllowed ) { HRESULT hr = S_OK; if (*pInsertionsAllowed & CCM_INSERTIONALLOWED_VIEW) { ComponentData& Scope = QueryComponentDataRef(); hr=_InsertMenuHelper ( piCallback, CCM_INSERTIONPOINTID_PRIMARY_VIEW, VIEW_DEFUNCT_OBJECTS, TRUE, Scope.m_fViewDefunct ); ASSERT(SUCCEEDED(hr)); } return hr; }
STDMETHODIMP Component::Command( long lCommandID, LPDATAOBJECT obj ) { switch ( lCommandID ) { case VIEW_DEFUNCT_OBJECTS: ComponentData& Scope = QueryComponentDataRef(); Scope.m_fViewDefunct=!Scope.m_fViewDefunct; OnNotifyRefresh(obj); CCookie* pBaseParentCookie = NULL; HRESULT hr = ExtractData( obj, CSchmMgmtDataObject::m_CFRawCookie, reinterpret_cast<PBYTE>(&pBaseParentCookie), sizeof(pBaseParentCookie) ); if( SUCCEEDED(hr) && pBaseParentCookie ) { this->m_pConsole->SelectScopeItem(pBaseParentCookie->m_hScopeItem); }
// The only real info we save is the menu state
// so let's flag that a save might be required
m_bDirty=true;
break; } return S_OK;
}
HRESULT Component::OnNotifyRefresh(LPDATAOBJECT obj) { ComponentData& Scope = QueryComponentDataRef(); Scope.RefreshScopeView(); m_pConsole->UpdateAllViews( obj, SCHMMGMT_SCHMMGMT, SCHMMGMT_UPDATEVIEW_REFRESH);
return S_OK; }
HRESULT Component::OnNotifySnapinHelp (LPDATAOBJECT) { // return ShowHelpTopic( L"sag_adschema.htm" );
CComQIPtr<IDisplayHelp,&IID_IDisplayHelp> spDisplayHelp = m_pConsole; if ( !spDisplayHelp ) { ASSERT(FALSE); return E_UNEXPECTED; }
CString strHelpTopic = L"ADConcepts.chm::/sag_adschema.htm"; HRESULT hr = spDisplayHelp->ShowTopic (T2OLE ((LPWSTR)(LPCWSTR) strHelpTopic)); ASSERT (SUCCEEDED (hr));
return hr; }
HRESULT Component::OnNotifyContextHelp (LPDATAOBJECT) { // return ShowHelpTopic( L"schmmgmt_top.htm" );
CComQIPtr<IDisplayHelp,&IID_IDisplayHelp> spDisplayHelp = m_pConsole; if ( !spDisplayHelp ) { ASSERT(FALSE); return E_UNEXPECTED; }
CString strHelpTopic = L"ADConcepts.chm::/schmmgmt_top.htm"; HRESULT hr = spDisplayHelp->ShowTopic (T2OLE ((LPWSTR)(LPCWSTR) strHelpTopic)); ASSERT (SUCCEEDED (hr));
return hr; }
STDMETHODIMP Component::QueryPagesFor( LPDATAOBJECT pDataObject ) {
MFC_TRY;
if ( NULL == pDataObject ) { ASSERT(FALSE); return E_POINTER; }
HRESULT hr;
CCookie* pBaseParentCookie = NULL;
hr = ExtractData( pDataObject, CSchmMgmtDataObject::m_CFRawCookie, reinterpret_cast<PBYTE>(&pBaseParentCookie), sizeof(pBaseParentCookie) );
ASSERT( SUCCEEDED(hr) );
Cookie* pParentCookie = ActiveCookie(pBaseParentCookie); ASSERT( NULL != pParentCookie );
if ( ( pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTE ) && ( pParentCookie->pParentCookie ) && ( pParentCookie->pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTES ) ) { return S_OK; }
return S_FALSE;
MFC_CATCH; }
//
// This adds pages to the property sheet if appropriate.
// The handle parameter must be saved in the property page
// object to notify the parent when modified.
//
STDMETHODIMP Component::CreatePropertyPages( LPPROPERTYSHEETCALLBACK pCallBack, LONG_PTR, LPDATAOBJECT pDataObject ) {
MFC_TRY; CWaitCursor wait;
//
// Validate the parameters.
//
if ( ( NULL == pCallBack ) || ( NULL == pDataObject ) ) {
ASSERT(FALSE); return E_POINTER; }
//
// Make sure this is a class object that we are calling up.
//
CCookie* pBaseParentCookie = NULL;
HRESULT hr = ExtractData( pDataObject, CSchmMgmtDataObject::m_CFRawCookie, reinterpret_cast<PBYTE>(&pBaseParentCookie), sizeof(pBaseParentCookie) ); ASSERT( SUCCEEDED(hr) );
Cookie* pParentCookie = ActiveCookie(pBaseParentCookie); ASSERT( NULL != pParentCookie ); ASSERT( pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTE );
//
// Create the page.
//
HPROPSHEETPAGE hPage; AttributeGeneralPage *pGeneralPage = new AttributeGeneralPage( this, pDataObject );
if ( pGeneralPage ) { pGeneralPage->Load( *pParentCookie ); MMCPropPageCallback( &pGeneralPage->m_psp ); hPage= MyCreatePropertySheetPage( &pGeneralPage->m_psp ); hr = pCallBack->AddPage( hPage ); }
return S_OK;
MFC_CATCH; }
HRESULT __stdcall Component::Compare( LPARAM, MMC_COOKIE cookieA, MMC_COOKIE cookieB, int* result) { if (!result) { return E_INVALIDARG; }
if (!m_pViewedCookie) { ASSERT(false); *result = 0; return S_OK; }
Cookie* c1 = (Cookie*) ActiveBaseCookie(reinterpret_cast<CCookie*>(cookieA));
Cookie* c2 = (Cookie*) ActiveBaseCookie(reinterpret_cast<CCookie*>(cookieB));
PWSTR t1 = QueryBaseComponentDataRef().QueryResultColumnText(*c1, *result); PWSTR t2 = QueryBaseComponentDataRef().QueryResultColumnText(*c2, *result);
// All columns use a case-insensitive comparison, as many columns contain
// display names from the directory (which are case-insensitive). That we
// also use a case insensitive compare for the other columns is harmless.
// another trick: we are inverting the results from the compare. This is
// because we initially insert the items in the list in sorted order. So
// the first sort request from the user really is intended to reverse-sort
// the list.
*result = -(_wcsicmp(t1, t2));
return S_OK; }
STDMETHODIMP Component::GetResultViewType(MMC_COOKIE cookie, BSTR* ppViewType, long* pViewOptions) { MFC_TRY; if( QueryComponentDataRef().IsErrorSet() ) { *pViewOptions = MMC_VIEW_OPTIONS_NOLISTVIEWS;
LPOLESTR psz = NULL; StringFromCLSID(CLSID_MessageView, &psz);
USES_CONVERSION;
if (psz != NULL) { *ppViewType = psz; return S_OK; } else { return S_FALSE; } } else { return CComponent::GetResultViewType( cookie, ppViewType, pViewOptions ); }
MFC_CATCH; }
HRESULT SaveDWordHelper(IStream* pStm, DWORD dw) { ULONG nBytesWritten; HRESULT hr = pStm->Write((void*)&dw, sizeof(DWORD),&nBytesWritten); if (nBytesWritten < sizeof(DWORD)) hr = STG_E_CANTSAVE; return hr; }
HRESULT LoadDWordHelper(IStream* pStm, DWORD* pdw) { ULONG nBytesRead; HRESULT hr = pStm->Read((void*)pdw,sizeof(DWORD), &nBytesRead); ASSERT(nBytesRead == sizeof(DWORD)); return hr; } ///////////////////////////////////////////////////////////////////////////////
//// IPersistStream interface members
STDMETHODIMP Component::GetClassID(CLSID *pClassID) { ASSERT(pClassID != NULL);
// Copy the CLSID for this snapin
*pClassID=CLSID_SchmMgmt; return S_OK; }
STDMETHODIMP Component::IsDirty() { return m_bDirty ? S_OK : S_FALSE; }
// IMPORTANT NOTICE: this value has to be bumped up EVERY time
// a change is made to the stream format
#define DS_STREAM_VERSION ((DWORD)0x01)
STDMETHODIMP Component::Load(IStream *pStm) { ASSERT(pStm);
// read the version ##
DWORD dwVersion; HRESULT hr = LoadDWordHelper(pStm, &dwVersion); if ( FAILED(hr) ||(dwVersion != DS_STREAM_VERSION) ) return E_FAIL;
// read m_fViewDefunct
DWORD auxView; hr = LoadDWordHelper(pStm, &auxView); if (FAILED(hr)) return hr;
ComponentData& Scope = QueryComponentDataRef(); Scope.m_fViewDefunct = (bool)auxView;
return hr;
}
STDMETHODIMP Component::Save(IStream *pStm, BOOL fClearDirty) { ASSERT(pStm);
// write the version ##
HRESULT hr = SaveDWordHelper(pStm, DS_STREAM_VERSION); if (FAILED(hr)) return hr;
ComponentData& Scope = QueryComponentDataRef(); hr = SaveDWordHelper(pStm, Scope.m_fViewDefunct); if (FAILED(hr)) return hr;
if(fClearDirty) m_bDirty=false;
return hr; }
STDMETHODIMP Component::GetSizeMax(ULARGE_INTEGER *pcbSize) { ASSERT(pcbSize); ASSERT(FALSE);
//
// Arbitrary values but I don't think we ever get called
//
pcbSize->LowPart = 0xffff; pcbSize->HighPart= 0x0; return S_OK; }
|