|
|
/*
* ComponentData.cxx * * * Copyright (c) 1998-1999 Microsoft Corporation * * PURPOSE: Defines the CComponentData class. * * * OWNER: ptousig */
#include "headers.hxx"
// -----------------------------------------------------------------------------
CComponentData::CComponentData(CBaseSnapin *psnapin) { Trace(tagBaseSnapinIComponentData, _T("--> CComponentData::CComponentData(psnapin=0x%08X)"), psnapin);
ASSERT(psnapin);
m_psnapin = psnapin; m_fIsRealComponentData = FALSE; m_pitemStandaloneRoot = NULL;
Trace(tagBaseSnapinIComponentData, _T("<-- CComponentData::CComponentData has constructed 0x%08X"), this); }
// -----------------------------------------------------------------------------
// Destructor doesn't do anything, but it's useful to have one for debugging
// purposes.
//
CComponentData::~CComponentData(void) { Trace(tagBaseSnapinIComponentData, _T("--> CComponentData::~CComponentData(), this=0x%08X"), this);
Psnapin()->ScOwnerDying(this); if (m_pitemStandaloneRoot) { Psnapin()->ScReleaseIfRootItem(m_pitemStandaloneRoot); }
Trace(tagBaseSnapinIComponentData, _T("<-- CComponentData::~CComponentData has destructed 0x%08X"), this); }
// -----------------------------------------------------------------------------
// This version of Pitem() is a shortcut, it forwards the call to the
// CBaseSnapin with the correct CComponentData parameter.
//
CBaseSnapinItem *CComponentData::Pitem( LPDATAOBJECT lpDataObject, HSCOPEITEM hscopeitem, long cookie) { return Psnapin()->Pitem(this, NULL, lpDataObject, hscopeitem, cookie); }
// -----------------------------------------------------------------------------
// The registration routine expects to find this method on the CComponentData
// but the real implementation is on the CBaseSnapin, so we just forward
// the call.
//
SC CComponentData::ScRegister(BOOL fRegister) { CBaseSnapin* pSnapin = Psnapin(); return pSnapin->ScRegister(fRegister); }
// -----------------------------------------------------------------------------
// Is called by the MMC to initialize the object. We QueryInterface
// for pointers to the name space and console, which we cache in
// local variables. This is called only once, when the user clicks on
// the snapin.
//
// $REVIEW (ptousig) I am not sure which of interfaces we are allowed to QI
// for from the parameter. The MMC docs are no help (as usual),
//
SC CComponentData::ScInitialize(LPUNKNOWN pUnknown) { SC sc = S_OK; IImageListPtr ipScopeImageList;
ASSERT(pUnknown != NULL); ASSERT(m_ipConsoleNameSpace == NULL);
m_fIsRealComponentData = TRUE;
sc = Psnapin()->ScInitBitmaps(); if (sc) goto Error;
// These are CComQIPtr so they will call QueryInterface.
m_ipConsoleNameSpace = pUnknown; m_ipConsole = pUnknown; m_ipResultData = pUnknown; m_ipPropertySheetProvider = pUnknown;
// Get a pointer to the scope pane's IImageList.
sc = m_ipConsole->QueryScopeImageList(&ipScopeImageList); if (sc) goto Error;
// Set the icon strip for the scope pane.
sc = ipScopeImageList->ImageListSetStrip( reinterpret_cast<long *>(static_cast<HBITMAP>(Psnapin()->BitmapSmall())), reinterpret_cast<long *>(static_cast<HBITMAP>(Psnapin()->BitmapLarge())), 0, RGB(255, 0, 255)); if (sc) goto Error;
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScInitialize"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Handles component data event notification.
// See MMC docs for the meaning of 'arg' and 'param'.
//
SC CComponentData::ScNotify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, long arg, long param) { SC sc = S_OK;
switch (event) { case MMCN_BTN_CLICK: sc = ScOnButtonClick(lpDataObject, (MMC_CONSOLE_VERB) param); break;
case MMCN_DELETE: sc = ScOnDelete(lpDataObject); break;
case MMCN_RENAME: sc = Psnapin()->ScOnRename(lpDataObject, reinterpret_cast<LPCTSTR>(param), IpConsole()); break;
case MMCN_EXPAND: sc = ScOnExpand(lpDataObject, arg != FALSE, param); break;
case MMCN_EXPANDSYNC: sc = ScOnExpandSync(lpDataObject, reinterpret_cast<MMC_EXPANDSYNC_STRUCT *>(param)); break;
case MMCN_PROPERTY_CHANGE: sc = Psnapin()->ScOnPropertyChange(arg != FALSE, param, IpConsoleNameSpace(), IpConsole()); break;
case MMCN_REMOVE_CHILDREN: sc = ScOnRemoveChildren(lpDataObject, arg); break;
default: sc = S_FALSE; ASSERT(_T("CComponentData::ScNotify: unimplemented event %x")); break; }
if (sc) goto Error;
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScNotify"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Releases all interfaces.
//
SC CComponentData::ScDestroy(void) { m_ipConsole.Release(); m_ipConsoleNameSpace.Release(); m_ipResultData.Release(); m_ipPropertySheetProvider.Release();
return S_OK; }
/*+-------------------------------------------------------------------------*
* * CComponentData::ScQueryDispatch * * PURPOSE: Dummy implementation. Does nothing. * * PARAMETERS: * MMC_COOKIE cookie : * DATA_OBJECT_TYPES type : * LPDISPATCH* ppDispatch : * * RETURNS: * SC * *+-------------------------------------------------------------------------*/ SC CComponentData::ScQueryDispatch(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDISPATCH* ppDispatch) { DECLARE_SC(sc, TEXT("CComponentData::ScQueryDispatch"));
CBaseSnapinItem *pitem = NULL;
// The component data can handle cookie types of CCT_SNAPIN_MANAGER and CCT_SCOPE.
// CCT_RESULT are handled by CComponent.
ASSERT(type==CCT_SCOPE);
//
// If the cookie does not correspond to a known object, return E_UNEXPECTED.
// This is correct and is also a workaround for an MMC bug. See X5:74405.
//
if (cookie && (Psnapin()->Pcookielist()->find(cookie) == Psnapin()->Pcookielist()->end() ) ) { sc = E_UNEXPECTED; return sc; }
pitem = Pitem(NULL, 0, cookie); ASSERT(pitem);
sc = pitem->ScQueryDispatch(cookie, type, ppDispatch); if (sc) return sc;
return sc; }
// -----------------------------------------------------------------------------
// Load information from the first root item.
//
// $REVIEW (ptousig) Why does the root item implement ScLoad() ?
// If a snapin extends two nodes it has two root items, yet
// only one of which will be saved/loaded.
//
SC CComponentData::ScLoad(IStream *pstream) { SC sc = S_OK;
// Load the snapin's serialized information.
sc = Psnapin()->ScLoad(pstream); if (sc) goto Error;
// Load the root item's serialized information.
// Only makes sense for standalone snapins.
sc = Pitem()->ScLoad(pstream); if (sc) goto Error;
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScLoad"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Determines whether any settings have changed since the last time the file
// was saved.
//
// $REVIEW (ptousig) We are never dirty !!! Shouldn't we ask the Pitem() ?
//
SC CComponentData::ScIsDirty(void) { return S_FALSE; }
// -----------------------------------------------------------------------------
// If one of the commands added to the context menu is
// subsequently selected, MMC calls Command.
//
// Even though this method "looks" like the one in CComponent,
// the use of the Pitem() shortcut makes them different. This
// version does not pass a component to the real Pitem().
//
SC CComponentData::ScCommand(long nCommandID, LPDATAOBJECT pDataObject) { SC sc = S_OK; CBaseSnapinItem *pitem = NULL;
pitem = Pitem(pDataObject); ASSERT(pitem);
sc = pitem->ScCommand(nCommandID); if (sc) goto Error;
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScCommand"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Gets display information for a scope pane item
// Warning: This is called very very often (on WM_PAINT) so it is important
// we don't take any high latency actions (ie Network or Disk access).
//
SC CComponentData::ScGetDisplayInfo(LPSCOPEDATAITEM pScopeItem) { SC sc = S_OK; CBaseSnapinItem *pitem = NULL;
pitem = Pitem(NULL, 0, pScopeItem->lParam); ASSERT(pitem);
sc = pitem->ScGetDisplayInfo(pScopeItem); if (sc) goto Error;
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScGetDisplayInfo"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
HRESULT CComponentData::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB) { DECLARE_SC(sc,_T("CComponentData::CompareObjects")); Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::CompareObjects(lpDataObjectA=0x%08X, lpDataObjectB=0x%08X), this=0x%08X"), StrSnapinClassName(), lpDataObjectA, lpDataObjectB, this); ADMIN_TRY; sc=Psnapin()->ScCompareObjects(lpDataObjectA, lpDataObjectB); ADMIN_CATCH_HR Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::CompareObjects is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::GetDisplayInfo(LPSCOPEDATAITEM pItem) { DECLARE_SC(sc,_T("CComponentData::GetDisplayInfo")); Trace(tagBaseSnapinIComponentDataGetDisplayInfo, _T("--> %s::IComponentData::GetDisplayInfo(cookie=0x%08X), this=0x%08X"), StrSnapinClassName(), pItem->lParam, this); ADMIN_TRY; sc=ScGetDisplayInfo(pItem); ADMIN_CATCH_HR Trace(tagBaseSnapinIComponentDataGetDisplayInfo, _T("<-- %s::IComponentData::GetDisplayInfo is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::QueryDataObject(long cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT * ppDataObject) { DECLARE_SC(sc,_T("CComponentData::QueryDataObject")); Trace(tagBaseSnapinIComponentDataQueryDataObject, _T("--> %s::IComponentData::QueryDataObject(cookie=0x%08X, type=%s), this=0x%08X"), StrSnapinClassName(), cookie, SzGetDebugNameOfDATA_OBJECT_TYPES(type), this); ADMIN_TRY; //
// If we receive E_UNEXPECTED we don't want to call MMCHrFromSc because
// that will bring up an error message. We don't want an error message
// in this case because of a known MMC bug (see bug X5:74405).
// The bug says that we might receive QueryDataObject on items that
// we were told no longer exists (by MMCN_REMOVE_CHILDREN).
//
sc = ScQueryDataObject(cookie, type, ppDataObject); ADMIN_CATCH_HR Trace(tagBaseSnapinIComponentDataQueryDataObject, _T("<-- %s::IComponentData::QueryDataObject is returning hr=%s, *ppDataObject=0x%08X"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), *ppDataObject); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, long arg, long param) { DECLARE_SC(sc,_T("CComponentData::Notify")); Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::Notify(lpDataObject=0x%08X, event=%s, arg=0x%08X, param=0x%08X), this=0x%08X"), StrSnapinClassName(), lpDataObject, SzGetDebugNameOfMMC_NOTIFY_TYPE(event), arg, param, this); ADMIN_TRY; sc=ScNotify(lpDataObject, event, arg, param); ADMIN_CATCH_HR Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::Notify is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::CreateComponent(LPCOMPONENT * ppComponent) { DECLARE_SC(sc,_T("CComponentData::CreateComponent")); Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::CreateComponent(...), this=0x%08X"), StrSnapinClassName(), this); ADMIN_TRY; sc=ScCreateComponent(ppComponent); ADMIN_CATCH_HR Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::CreateComponent is returning hr=%s, *ppComponent=0x%08X"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), *ppComponent); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::Initialize(LPUNKNOWN pUnknown) { DECLARE_SC(sc,_T("CComponentData::Initialize")); Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::Initialize(pUnknown=0x%08X), this=0x%08X"), StrSnapinClassName(), pUnknown, this); ADMIN_TRY; sc=ScInitialize(pUnknown); ADMIN_CATCH_HR Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::Initialize is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::Destroy(void) { DECLARE_SC(sc,_T("CComponentData::Destroy")); Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::Destroy(), , this=0x%08X"), StrSnapinClassName(), this); ADMIN_TRY; sc=ScDestroy(); ADMIN_CATCH_HR Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::Destroy is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::QueryDispatch(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDISPATCH* ppDispatch) { DECLARE_SC(sc,_T("CComponentData::QueryDispatch")); Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::QueryDispatch(), , this=0x%08X"), StrSnapinClassName(), this); ADMIN_TRY; sc=ScQueryDispatch(cookie, type, ppDispatch); ADMIN_CATCH_HR Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::QueryDispatch is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::AddMenuItems(LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK ipContextMenuCallback, long *pInsertionAllowed) { DECLARE_SC(sc,_T("CComponentData::AddMenuItems")); Trace(tagBaseSnapinIExtendContextMenu, _T("--> %s::IExtendContextMenu::AddMenuItems(pDataObject=0x%08X), this=0x%08X"), StrSnapinClassName(), pDataObject, this); ADMIN_TRY; // By calling Pitem() at this time, we will force the creation of the ghost
// root node, if necessary.
Pitem(pDataObject); sc=Psnapin()->ScAddMenuItems(pDataObject, ipContextMenuCallback, pInsertionAllowed); ADMIN_CATCH_HR Trace(tagBaseSnapinIExtendContextMenu, _T("<-- %s::IExtendContextMenu::AddMenuItems is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::Command(long nCommandID, LPDATAOBJECT pDataObject) { DECLARE_SC(sc,_T("CComponentData::Command")); Trace(tagBaseSnapinIExtendContextMenu, _T("--> %s::IExtendContextMenu::Command(nCommandID=%ld, pDataObject=0x%08X), this=0x%08X"), StrSnapinClassName(), nCommandID, pDataObject, this); ADMIN_TRY; sc=ScCommand(nCommandID, pDataObject); ADMIN_CATCH_HR Trace(tagBaseSnapinIExtendContextMenu, _T("<-- %s::IExtendContextMenu::Command is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, long handle, LPDATAOBJECT lpDataObject) { DECLARE_SC(sc,_T("CComponentData::CreatePropertyPages")); Trace(tagBaseSnapinIExtendPropertySheet, _T("--> %s::IExtendPropertySheet::CreatePropertyPages(lpDataObject=0x%08X), this=0x%08X"), StrSnapinClassName(), lpDataObject, this); ADMIN_TRY; // Why are we ignoring E_UNEXPECTED ?
// Because when we are called by the snapin manager, and the user hits cancel we
// need to return E_UNEXPECTED to MMC.
sc = ScCreatePropertyPages(lpProvider, handle, lpDataObject); ADMIN_CATCH_HR Trace(tagBaseSnapinIExtendPropertySheet, _T("<-- %s::IExtendPropertySheet::CreatePropertyPages is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::QueryPagesFor(LPDATAOBJECT lpDataObject) { DECLARE_SC(sc,_T("CComponentData::QueryPagesFor")); Trace(tagBaseSnapinIExtendPropertySheet, _T("--> %s::IExtendPropertySheet::QueryPagesFor(lpDataObject=0x%08X), this=0x%08X"), StrSnapinClassName(), lpDataObject, this); ADMIN_TRY; sc=ScQueryPagesFor(lpDataObject); ADMIN_CATCH_HR Trace(tagBaseSnapinIExtendPropertySheet, _T("<-- %s::IExtendPropertySheet::QueryPagesFor is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::GetSizeMax(ULARGE_INTEGER *pcbSize) { DECLARE_SC(sc,_T("CComponentData::GetSizeMax")); Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::GetSizeMax(...), , this=0x%08X"), StrSnapinClassName(), this); ADMIN_TRY; pcbSize->LowPart = cMaxStreamSizeLow; pcbSize->HighPart = cMaxStreamSizeHigh; ADMIN_CATCH_HR Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::GetSizeMax is returning hr=%s, (*pcbSize).LowPart=%d"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), (*pcbSize).LowPart); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::IsDirty(void) { DECLARE_SC(sc,_T("CComponentData::IsDirty")); Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::IsDirty(), this=0x%08X"), StrSnapinClassName(), this); ADMIN_TRY; sc=ScIsDirty(); ADMIN_CATCH_HR Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::IsDirty is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::Load(IStream *pstream) { DECLARE_SC(sc,_T("CComponentData::Load")); Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::Load(...), this=0x%08X"), StrSnapinClassName(), this); ADMIN_TRY; sc=ScLoad(pstream); ADMIN_CATCH_HR Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::Load is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::Save(IStream *pstream, BOOL fClearDirty) { DECLARE_SC(sc,_T("CComponentData::Save")); Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::Save(fClearDirty=%S), this=0x%08X"), StrSnapinClassName(), fClearDirty ? "TRUE" : "FALSE", this); ADMIN_TRY; sc=ScSave(pstream, fClearDirty); ADMIN_CATCH_HR Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::Save is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::InitNew(void) { DECLARE_SC(sc,_T("CComponentData::InitNew")); // We don't have anything to do, but we still want to log the call.
Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::InitNew(), this=0x%08X"), StrSnapinClassName(), this); Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::InitNew is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::GetClassID(CLSID *pclsid) { DECLARE_SC(sc,_T("CComponentData::GetClassID")); Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::GetClassID(...), this=0x%08X"), StrSnapinClassName(), this); ADMIN_TRY; *pclsid = *(Psnapin()->PclsidSnapin()); ADMIN_CATCH_HR Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::GetClassID is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr())); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
HRESULT CComponentData::Compare(RDCOMPARE * prdc, int * pnResult) { DECLARE_SC(sc,_T("CComponentData::Compare")); Trace(tagBaseSnapinIResultDataCompare, _T("--> %s::IResultDataCompare::Compare(cookieA=0x%08X, cookieB=0x%08X), this=0x%08X"), StrSnapinClassName(), prdc->prdch1->cookie, prdc->prdch2->cookie, this); ADMIN_TRY; ASSERT(pnResult); ASSERT(prdc); ASSERT(prdc->prdch1); ASSERT(prdc->prdch2); sc=Psnapin()->ScCompare(prdc->prdch1->cookie, prdc->prdch2->cookie, prdc->nColumn, pnResult); ADMIN_CATCH_HR Trace(tagBaseSnapinIResultDataCompare, _T("<-- %s::IResultDataCompare::Compare is returning hr=%s, *pnResult=%d"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), *pnResult); return(sc.ToHr()); }
// -----------------------------------------------------------------------------
// Returns the full path of the compiled file (.chm) for the snapin.
//
HRESULT CComponentData::GetHelpTopic(LPOLESTR *lpCompiledHelpFile) { DECLARE_SC(sc,_T("CComponentData::GetHelpTopic")); tstring strCompiledHelpFile; USES_CONVERSION;
Trace(tagBaseSnapinISnapinHelp, _T("--> %s::ISnapinHelp::GetHelpTopic(...), this=0x%08X"), StrSnapinClassName(), this); ADMIN_TRY;
if (lpCompiledHelpFile == NULL) { sc = E_POINTER; goto Error; }
// Automatically displays an error box.
sc = Psnapin()->ScGetHelpTopic(strCompiledHelpFile); if (sc) goto Error;
if (strCompiledHelpFile.empty()) { sc=S_FALSE; } else { *lpCompiledHelpFile = reinterpret_cast<LPOLESTR>(CoTaskMemAlloc( (strCompiledHelpFile.length()+1)*sizeof(TCHAR)) ); sc = ScCheckPointers(*lpCompiledHelpFile, E_OUTOFMEMORY); if (sc) goto Error;
wcscpy(*lpCompiledHelpFile, T2CW(strCompiledHelpFile.data()) ); }
if (sc) goto Error; // an exception was caught
Cleanup: Trace(tagBaseSnapinISnapinHelp, _T("<-- %s::ISnapinHelp::GetHelpTopic is returning hr=%s, lpCompiledHelpFile=\"%s\""), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), strCompiledHelpFile.data()); return(sc.ToHr()); Error: TraceError(_T("CComponentData::GetHelpTopic"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Creates a data object of the appropriate type, and returns the IDataObject interface
// on it
//
SC CComponentData::ScQueryDataObject(long cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject) { SC sc = S_OK; CBaseSnapinItem *pitem = NULL;
// The component data can handle cookie types of CCT_SNAPIN_MANAGER and CCT_SCOPE.
// CCT_RESULT are handled by CComponent.
ASSERT(type==CCT_SNAPIN_MANAGER || type==CCT_SCOPE);
//
// If the cookie does not correspond to a known object, return E_UNEXPECTED.
// This is correct and is also a workaround for an MMC bug. See X5:74405.
//
if (cookie && (Psnapin()->Pcookielist()->find(cookie) == Psnapin()->Pcookielist()->end() ) ) { sc = E_UNEXPECTED; goto Cleanup; }
pitem = Pitem(NULL, 0, cookie); ASSERT(pitem);
sc = pitem->ScQueryDataObject(cookie, type, ppDataObject); if (sc) goto Error;
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScQueryDataObject"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Handles the MMCN_EXPAND notification sent to IComponentData::Notify
//
SC CComponentData::ScOnExpand(LPDATAOBJECT lpDataObject, BOOL fExpand, HSCOPEITEM hscopeitem) { SC sc = S_OK; CBaseSnapinItem *pitem = NULL;
if (fExpand == FALSE) // do nothing on a "contract"
goto Cleanup;
pitem = Pitem(lpDataObject, hscopeitem); ASSERT(pitem);
// Use this opportunity to correlate the CSnapinItem and the HSCOPEITEM.
// $REVIEW (ptousig) Should be done inside Pitem().
pitem->SetHscopeitem(hscopeitem); pitem->SetComponentData(this);
if (pitem->PitemChild()) { // We have a list of partial children. We need to remove
// them because we are going to ask the snapin to enumerate
// all of it's children. Do not get rid of this node.
// This can happen if a node creates new children before it is
// expanded.
//
// $REVIEW (ptousig) Creating a child when the parent is not expanded
// should simply not add the child.
//
sc = pitem->ScDeleteSubTree(FALSE); if (sc) goto Error; }
// If we're creating the children, make sure there aren't any around.
ASSERT(pitem->PitemChild() == NULL);
sc = pitem->ScCreateChildren(); if (sc) goto Error;
if (pitem->PitemChild()) { // Add or remove children to/from the console.
sc = pitem->PitemChild()->ScInsertScopeItem(this, fExpand, hscopeitem); if (sc) goto Error; }
pitem->SetWasExpanded(TRUE);
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScOnExpand"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Called by the MMC to delete the cookies for the entire subtree under a node. This
// is only to clean up allocated objects. Do NOT call IConsoleNameSpace::DeleteItem.
//
SC CComponentData::ScOnRemoveChildren(LPDATAOBJECT lpDataObject, HSCOPEITEM hscopeitem) { SC sc = S_OK; CBaseSnapinItem *pitem = NULL;
pitem = Pitem(lpDataObject, hscopeitem); ASSERT(pitem);
// Get rid of the children.
sc = pitem->ScDeleteSubTree(FALSE); if (sc) goto Error;
// Release the given node if it is one of the root nodes
sc = Psnapin()->ScReleaseIfRootItem(pitem); if (sc) goto Error;
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScOnRemoveChildren"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Allows a snapin to control whether it will populate the scope pane
// in the background or not.
//
SC CComponentData::ScOnExpandSync(LPDATAOBJECT lpDataObject, MMC_EXPANDSYNC_STRUCT *pmes) { // We don't care.
return S_OK; }
// -----------------------------------------------------------------------------
// The user has asked to delete this node.
//
SC CComponentData::ScOnDelete(LPDATAOBJECT pDataObject) { SC sc = S_OK; CBaseSnapinItem *pitem = NULL; BOOL fDeleted = FALSE; BOOL fPagesUp = FALSE; tstring strMsg;
pitem = Pitem(pDataObject); ASSERT(pitem);
// The ComponentData should only receive notifications for scope pane items.
ASSERT(pitem->FIsContainer());
sc = pitem->ScIsPropertySheetOpen(&fPagesUp); if (sc) goto Error;
if (fPagesUp) { ASSERT(FALSE && "Add below resource"); //strMsg.LoadString(_Module.GetResourceInstance(), idsPropsUpNoDelete);
strMsg += (*pitem->PstrDisplayName()); MMCErrorBox(strMsg.data()); goto Cleanup; }
// Ask the item to delete the underlying object.
sc = pitem->ScOnDelete(&fDeleted); if (sc) goto Error;
if (fDeleted == FALSE) // The item did not want to be deleted.
goto Cleanup;
// Container items need to be deleted from the document
// Delete the item and everything below it.
sc = IpConsoleNameSpace()->DeleteItem(pitem->Hscopeitem(), TRUE); if (sc) goto Error; pitem->SetHscopeitem(0);
// At this point, the item exists only in the tree, if at all.
// Remove it from the tree.
pitem->Unlink(); // Get rid of it for good from the tree of items.
pitem->Pdataobject()->Release();
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScOnDelete"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Toolbar button clicked.
//
SC CComponentData::ScOnButtonClick(LPDATAOBJECT lpDataObject, MMC_CONSOLE_VERB mcvVerb) { return S_OK; }
// -----------------------------------------------------------------------------
// Used to insert a new item into the tree of items, and, if the item is a container,
// into the namespace as well. The tree and the namespace are document, not view,
// concept. This insertion is done only once.
//
SC CComponentData::ScOnDocumentChangeInsertItem(CBaseSnapinItem *pitemNew) { SC sc = S_OK; CBaseSnapinItem * pitemParent = NULL;
ASSERT(pitemNew);
// Insert exactly once.
if (pitemNew->FInserted()) goto Cleanup;
// The parent should have already been filled in
pitemParent = pitemNew->PitemParent(); ASSERT(pitemParent);
if (pitemParent->FIncludesChild(pitemNew) == FALSE) { sc = pitemParent->ScAddChild(pitemNew); if (sc) goto Error; }
if (pitemNew->FIsContainer()) { if (pitemParent->FWasExpanded()) { sc = pitemNew->ScInsertScopeItem(this, TRUE, pitemParent->Hscopeitem()); if (sc) goto Error; } }
// Only insert the item once.
pitemNew->SetInserted(TRUE);
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScOnDocumentChangeInsertItem"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Tests whether the given item has already enumerated its children.
//
SC CComponentData::ScWasExpandedOnce(CBaseSnapinItem *pitem, BOOL *pfWasExpanded) { SC sc = S_OK; SCOPEDATAITEM sdi;
if (pitem->Hscopeitem() == 0) { //
// If we don't have an HSCOPEITEM then we are not displayed in
// the scope pane, therefore we have never been expanded (and
// probably never will).
//
*pfWasExpanded = FALSE; goto Cleanup; }
//
// Ask for the state member of SCOPEDATAITEM
//
::ZeroMemory(&sdi, sizeof(SCOPEDATAITEM)); sdi.mask = SDI_STATE; sdi.ID = pitem->Hscopeitem();
sc = IpConsoleNameSpace()->GetItem(&sdi); if (sc) goto Error;
//
// If the MMC_SCOPE_ITEM_STATE_EXPANDEDONCE is on it means we have
// been asked to expand ourselves at least once before.
//
*pfWasExpanded = (sdi.nState & MMC_SCOPE_ITEM_STATE_EXPANDEDONCE) != 0;
Cleanup: return sc;
Error: TraceError(_T("CComponentData::ScWasExpandedOnce"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Adds property pages for the given data object, taking into account the context and also
// whether the data object is for a new object that is being created.
//
SC CComponentData::ScCreatePropertyPages(LPPROPERTYSHEETCALLBACK ipPropertySheetCallback, long handle, LPDATAOBJECT pDataObject) { SC sc = S_OK; CBaseSnapinItem *pitem = NULL;
pitem = Pitem(pDataObject); ASSERT(pitem);
if (pitem->FIsSnapinManager()) { sc = pitem->ScCreateSnapinMgrPropertyPages(ipPropertySheetCallback); if (sc) goto Error; } else { // Simple version
sc = pitem->ScCreatePropertyPages(ipPropertySheetCallback); if (sc) goto Error;
// Complete version - for snapins that need all information (like Recipients)
sc = pitem->ScCreatePropertyPages(ipPropertySheetCallback, handle); if (sc) goto Error; }
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScCreatePropertyPages"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Save information from the first root item.
//
// $REVIEW (ptousig) Why does the root item implement ScSave() ?
// If a snapin extends two nodes it has two root items, yet
// only one of which will be saved/loaded.
//
SC CComponentData::ScSave(IStream *pstream, BOOL fClearDirty) { SC sc = S_OK;
// Save the snapin's serialized information.
sc = Psnapin()->ScSave(pstream, fClearDirty); if (sc) goto Error;
// Load the root item's serialized information.
// Only makes sense for standalone snapins.
sc = Pitem()->ScSave(pstream, fClearDirty); if (sc) goto Error;
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScSave"), sc); goto Cleanup; }
// -----------------------------------------------------------------------------
// Given a dataobject, determines whether or not pages exist.
// Actually, need to return S_OK here in both cases. If no pages exist
// it is CreatePropertyPages that should return S_FALSE. Sad but true.
//
SC CComponentData::ScQueryPagesFor(LPDATAOBJECT pDataObject) { SC sc = S_OK; CBaseSnapinItem * pitem = NULL;
pitem = Pitem(pDataObject); ASSERT(pitem);
sc = pitem->ScQueryPagesFor(); if (sc) goto Error;
Cleanup: return sc; Error: TraceError(_T("CComponentData::ScQueryPagesFor"), sc); goto Cleanup; }
|