//____________________________________________________________________________ // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: ctrlbar.cpp // // Contents: // // Classes: // // Functions: // // History: //____________________________________________________________________________ // #include "stdafx.h" #include "menubtn.h" #include "viewdata.h" #include "amcmsgid.h" #include "regutil.h" #include "commctrl.h" #include "multisel.h" #include "rsltitem.h" #include "conview.h" #include "util.h" #include "nodemgrdebug.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Snapin name needed for debug information. inline void Debug_SetControlbarSnapinName(const CLSID& clsidSnapin, CControlbar* pControlbar) { #ifdef DBG tstring tszSnapinName; bool bRet = GetSnapinNameFromCLSID(clsidSnapin, tszSnapinName); if (bRet) pControlbar->SetSnapinName(tszSnapinName.data()); #endif } ////////////////////////////////////////////////////////////////////////////// // IControlbar implementation DEBUG_DECLARE_INSTANCE_COUNTER(CControlbar); CControlbar::CControlbar() : m_pCache(NULL) { TRACE(_T("CControlbar::CControlbar()\n")); DEBUG_INCREMENT_INSTANCE_COUNTER(CControlbar); m_pMenuButton=NULL; m_ToolbarsList.clear(); #ifdef DBG dbg_cRef = 0; #endif } CControlbar::~CControlbar() { DECLARE_SC(sc, _T("CControlbar::~CControlbar")); DEBUG_DECREMENT_INSTANCE_COUNTER(CControlbar); // Remove the toolbars & menubuttons references. sc = ScCleanup(); // sc dtor will trace error if there is one. // release reference prior to m_ToolbarsList destruction // The destructor of CToolbar will try to remove itself from the list! m_spExtendControlbar = NULL; } //+------------------------------------------------------------------- // // Member: Create // // Synopsis: Create a toolbar or menubutton object // // Arguments: // [nType] - Type of object to be created (Toolbar or Menubutton). // [pExtendControlbar] - IExtendControlbar associated with this IControlbar. // [ppUnknown] - IUnknown* of the object created. // // Returns: HR // //-------------------------------------------------------------------- STDMETHODIMP CControlbar::Create(MMC_CONTROL_TYPE nType, LPEXTENDCONTROLBAR pExtendControlbar, LPUNKNOWN* ppUnknown) { DECLARE_SC_FOR_PUBLIC_INTERFACE(sc, _T("IControlbar::Create")); if (ppUnknown == NULL || pExtendControlbar == NULL) { sc = E_INVALIDARG; TraceSnapinError(_T("Invalid Arguments"), sc); return sc.ToHr(); } *ppUnknown = NULL; switch (nType) { case TOOLBAR: sc = ScCreateToolbar(pExtendControlbar, ppUnknown); break; case MENUBUTTON: sc = ScCreateMenuButton(pExtendControlbar, ppUnknown); break; default: sc = E_NOTIMPL; break; } if (sc) return sc.ToHr(); return (sc.ToHr()); } HRESULT CControlbar::ControlbarNotify(MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param) { ASSERT(m_spExtendControlbar != NULL); if (m_spExtendControlbar == NULL) return E_FAIL; HRESULT hr; // Deactivate if theming (fusion or V6 common-control) context before calling snapins. ULONG_PTR ulpCookie; if (! MmcDownlevelActivateActCtx(NULL, &ulpCookie)) return E_FAIL; __try { hr = m_spExtendControlbar->ControlbarNotify(event, arg, param); MmcDownlevelDeactivateActCtx(0, ulpCookie); } __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; TraceSnapinException(m_clsidSnapin, TEXT("IExtendControlbar::ControlbarNotify"), event); MmcDownlevelDeactivateActCtx(0, ulpCookie); } return hr; } //+------------------------------------------------------------------- // // Member: Attach // // Synopsis: Attach given toolbar or menubutton object // // Arguments: // [nType] - Toolbar or Menubutton. // [lpUnknown] - IUnknown* of the object to be attached. // // Returns: HR // //-------------------------------------------------------------------- STDMETHODIMP CControlbar::Attach(MMC_CONTROL_TYPE nType, LPUNKNOWN lpUnknown) { DECLARE_SC_FOR_PUBLIC_INTERFACE(sc, _T("IControlbar::Attach")); if (lpUnknown == NULL) { sc = E_INVALIDARG; TraceSnapinError(_T("Invalid Arguments"), sc); return sc.ToHr(); } switch (nType) { case TOOLBAR: sc = ScAttachToolbar(lpUnknown); break; case MENUBUTTON: sc = ScAttachMenuButtons(lpUnknown); break; case COMBOBOXBAR: sc = E_NOTIMPL; break; } if (sc) return sc.ToHr(); return (sc.ToHr()); } //+------------------------------------------------------------------- // // Member: Detach // // Synopsis: Detach given toolbar or menubutton object // // Arguments: [lpUnknown] - IUnknown* of the object to be detached // // Returns: HR // //-------------------------------------------------------------------- STDMETHODIMP CControlbar::Detach(LPUNKNOWN lpUnknown) { DECLARE_SC_FOR_PUBLIC_INTERFACE(sc, _T("IControlbar::Detach")); if (lpUnknown == NULL) { sc = E_INVALIDARG; TraceSnapinError(_T("Invalid Arguments"), sc); return sc.ToHr(); } // Is it a toolbar IToolbarPtr spToolbar = lpUnknown; if (spToolbar != NULL) { sc = ScDetachToolbar(spToolbar); return sc.ToHr(); } // Is it a menu button IMenuButtonPtr spMenuButton = lpUnknown; if (spMenuButton != NULL) { sc = ScDetachMenuButton(spMenuButton); return sc.ToHr(); } // The passed lpUnknown is neither toolbar nor menubutton. // The Snapin has passed invalid object. sc = E_INVALIDARG; TraceSnapinError(_T("lpUnknown passed is neither toolbar nor menubutton"), sc); return sc.ToHr(); } //+------------------------------------------------------------------- // // Member: ScDetachToolbar // // Synopsis: Detach given toolbar object // // Arguments: [lpToolbar] - IToolbar* of the object to be detached // // Returns: SC // //-------------------------------------------------------------------- SC CControlbar::ScDetachToolbar(LPTOOLBAR lpToolbar) { DECLARE_SC(sc, _T("CControlbar::SCDetachToolbar")); if (NULL == lpToolbar) return (sc = E_UNEXPECTED); // Get the CToolbar object. CToolbar* pToolbar = dynamic_cast(lpToolbar); if (NULL == pToolbar) return (sc = E_UNEXPECTED); // Get the CMMCToolbarIntf interface. CMMCToolbarIntf* pToolbarIntf = pToolbar->GetMMCToolbarIntf(); if (NULL == pToolbarIntf) return (sc = E_UNEXPECTED); // Detach the toolbar from UI. sc = pToolbarIntf->ScDetach(pToolbar); if (sc) return sc; // Remove the CControlbar reference. pToolbar->SetControlbar(NULL); // Remove the reference to the toolbar. m_ToolbarsList.remove(pToolbar); return sc; } //+------------------------------------------------------------------- // // Member: ScDetachMenuButton // // Synopsis: Detach given toolbar or menubutton object // // Arguments: [lpUnknown] - IUnknown* of the object to be detached // // Returns: HR // //-------------------------------------------------------------------- SC CControlbar::ScDetachMenuButton(LPMENUBUTTON lpMenuButton) { DECLARE_SC(sc, _T("CControlbar::ScDetachMenuButton")); if (NULL == lpMenuButton) return (sc = E_UNEXPECTED); CMenuButton* pMenuButton = dynamic_cast(lpMenuButton); if (NULL == pMenuButton) return (sc = E_UNEXPECTED); sc = pMenuButton->ScDetach(); if (sc) return sc; // If this is same as the cached menubutton object // then remove the (cached) ref. if (m_pMenuButton == pMenuButton) m_pMenuButton = NULL; else { // The IControlbar implementation is supposed to // have only one CMenuButton obj. How come it is // not same as one we have cached. sc = E_UNEXPECTED; } return sc; } //+------------------------------------------------------------------- // // Member: ScCreateToolbar // // Synopsis: Create a toolbar for the given snapin (IExtendControlbar). // // Arguments: [pExtendControlbar] - IExtendControlbar of the snapin. // [ppUnknown] - IUnknown* (IToolbar) of created toolbar. // // Returns: SC // //-------------------------------------------------------------------- SC CControlbar::ScCreateToolbar(LPEXTENDCONTROLBAR pExtendControlbar, LPUNKNOWN* ppUnknown) { DECLARE_SC(sc, _T("CControlbar::ScCreateToolbar")); if ( (NULL == pExtendControlbar) || (NULL == ppUnknown) ) return (sc = E_INVALIDARG); ASSERT(m_spExtendControlbar == NULL || m_spExtendControlbar == pExtendControlbar); // Create the new CToolbar object. CComObject* pToolbar = NULL; sc = CComObject::CreateInstance(&pToolbar); if (sc) return sc; if (NULL == pToolbar) return (sc = E_FAIL); sc = pToolbar->QueryInterface(IID_IToolbar, reinterpret_cast(ppUnknown)); if (sc) return sc; CMMCToolbarIntf* pToolbarIntf = NULL; // Get the toolbars mgr. CAMCViewToolbarsMgr* pAMCViewToolbarsMgr = GetAMCViewToolbarsMgr(); if (NULL == pAMCViewToolbarsMgr) { sc = E_UNEXPECTED; goto ToolbarUICreateError; } // Ask it to create the toolbar UI. sc = pAMCViewToolbarsMgr->ScCreateToolBar(&pToolbarIntf); if (sc) goto ToolbarUICreateError; // Let the IToolbar imp be aware of toolbar UI interface. pToolbar->SetMMCToolbarIntf(pToolbarIntf); Cleanup: return(sc); ToolbarUICreateError: // Destroy the CToolbar object created. if (*ppUnknown) (*ppUnknown)->Release(); *ppUnknown = NULL; goto Cleanup; } //+------------------------------------------------------------------- // // Member: ScCreateMenuButton // // Synopsis: Create a menu button object. // // Arguments: [pExtendControlbar] - IExtendControlbar of the snapin // that is creating MenuButton object. // [ppUnknown] - IUnknown if MenuButton object. // // Returns: SC // //-------------------------------------------------------------------- SC CControlbar::ScCreateMenuButton(LPEXTENDCONTROLBAR pExtendControlbar, LPUNKNOWN* ppUnknown) { DECLARE_SC(sc, _T("CControlbar::ScCreateMenuButton")); if ( (NULL == pExtendControlbar) || (NULL == ppUnknown) ) return (sc = E_INVALIDARG); ASSERT(m_spExtendControlbar == NULL || m_spExtendControlbar == pExtendControlbar); // Create the new IMenuButton object CComObject* pMenuButton; sc = CComObject::CreateInstance(&pMenuButton); if (sc) return sc; if (NULL == pMenuButton) return (sc = E_FAIL); sc = pMenuButton->QueryInterface(IID_IMenuButton, reinterpret_cast(ppUnknown)); if (sc) return sc; pMenuButton->SetControlbar(this); return sc; } //+------------------------------------------------------------------- // // Member: ScNotifySnapinOfToolBtnClick // // Synopsis: Notify the snapin about a tool button is click. // // Arguments: [hNode] - Node that owns result pane. // [bScopePane] - Scope or Result. // [lResultItemCookie] - If Result pane is selected the item param. // [nID] - Command ID of the tool button clicked. // // Returns: SC // //-------------------------------------------------------------------- SC CControlbar::ScNotifySnapinOfToolBtnClick(HNODE hNode, bool bScopePane, LPARAM lResultItemCookie, UINT nID) { DECLARE_SC(sc, _T("CControlbar::ScNotifySnapinOfToolBtnClick")); LPDATAOBJECT pDataObject = NULL; CNode* pNode = CNode::FromHandle(hNode); if (NULL == pNode) return (sc = E_UNEXPECTED); bool bScopeItem = bScopePane; // Get the data object of the currently selected item. sc = pNode->ScGetDataObject(bScopePane, lResultItemCookie, bScopeItem, &pDataObject); if (sc) return sc; ASSERT(m_spExtendControlbar != NULL); // Notify the snapin sc = ControlbarNotify(MMCN_BTN_CLICK, reinterpret_cast(pDataObject), static_cast(nID)); // Release the dataobject if it is not special dataobject. RELEASE_DATAOBJECT(pDataObject); if (sc) return sc; return sc; } //+------------------------------------------------------------------- // // Member: ScNotifySnapinOfMenuBtnClick // // Synopsis: Notify the snapin about a menu button is click. // // Arguments: [hNode] - Node that owns result pane. // [bScopePane] - Scope or Result. // [lResultItemCookie] - If Result pane is selected the item param. // [lpmenuButtonData] - MENUBUTTONDATA // // Returns: SC // //-------------------------------------------------------------------- SC CControlbar::ScNotifySnapinOfMenuBtnClick(HNODE hNode, bool bScopePane, LPARAM lResultItemCookie, LPMENUBUTTONDATA lpmenuButtonData) { DECLARE_SC(sc, _T("CControlbar::ScNotifySnapinOfMenuBtnClick")); LPDATAOBJECT pDataObject = NULL; CNode* pNode = CNode::FromHandle(hNode); if (NULL == pNode) return (sc = E_UNEXPECTED); bool bScopeItem = bScopePane; // Get the data object of the currently selected item. sc = pNode->ScGetDataObject(bScopePane, lResultItemCookie, bScopeItem, &pDataObject); if (sc) return sc; ASSERT(m_spExtendControlbar != NULL); // Notify the snapin sc = ControlbarNotify(MMCN_MENU_BTNCLICK, reinterpret_cast(pDataObject), reinterpret_cast(lpmenuButtonData)); // Release the dataobject if it is not special dataobject. RELEASE_DATAOBJECT(pDataObject); if (sc) return sc; return sc; } //+------------------------------------------------------------------- // // Member: ScAttachToolbar // // Synopsis: Attach given toolbar object // // Arguments: [lpUnknown] - IUnknown* of the object to be attached // // Returns: SC // //-------------------------------------------------------------------- SC CControlbar::ScAttachToolbar(LPUNKNOWN lpUnknown) { DECLARE_SC(sc, _T("CControlbar::ScAttachToolbar")); ASSERT(NULL != lpUnknown); IToolbarPtr spToolbar = lpUnknown; if (NULL == spToolbar) return (sc = E_UNEXPECTED); // Get the toolbar object (IToolbar implementation). CToolbar* pToolbarC = dynamic_cast(spToolbar.GetInterfacePtr()); if (NULL == pToolbarC) return (sc = E_UNEXPECTED); // Get the toolbar UI interface. CMMCToolbarIntf* pToolbarIntf = pToolbarC->GetMMCToolbarIntf(); if (NULL == pToolbarIntf) return (sc = E_UNEXPECTED); // Attach the toolbar. sc = pToolbarIntf->ScAttach(pToolbarC); if (sc) return sc; // Make the CToolbar aware of this IControlbar. pToolbarC->SetControlbar(this); // Add this CToolbar to our list of toolbars. ToolbarsList::iterator itToolbar = std::find(m_ToolbarsList.begin(), m_ToolbarsList.end(), pToolbarC); if (m_ToolbarsList.end() == itToolbar) { m_ToolbarsList.push_back(pToolbarC); } return sc; } //+------------------------------------------------------------------- // // Member: ScAttachMenuButtons // // Synopsis: Attach a menu button object. // // Arguments: [lpUnknown] - IUnknown if MenuButton object. // // Returns: HRESULT // // Note: Only one CMenuButton object per Controlbar/snapin. // Snapins can create many menu buttons using a // single CMenuButton object. //-------------------------------------------------------------------- SC CControlbar::ScAttachMenuButtons(LPUNKNOWN lpUnknown) { DECLARE_SC(sc, _T("CControlbar::ScAttachMenuButtons")); ASSERT(NULL != lpUnknown); CMenuButton* pMenuButton = dynamic_cast(lpUnknown); if (pMenuButton == NULL) return (sc = E_INVALIDARG); if (m_pMenuButton == pMenuButton) { // Already attached. sc = S_FALSE; TraceNodeMgrLegacy(_T("The menubutton is already attached"), sc); return sc; } else if (m_pMenuButton != NULL) { // There is already a CMenuButton object attached by this // Controlbar (Snapin). Detach that before attaching this // CMenuButton Object (See the note above). sc = m_pMenuButton->ScDetach(); if (sc) return sc; } // Cache the ref to CMenuButton object. // Used when selection moves away from the snapin. // MMC has to remove the menubutton put by this snapin. m_pMenuButton = pMenuButton; if (pMenuButton->GetControlbar() != this) pMenuButton->SetControlbar(this); sc = pMenuButton->ScAttach(); if (sc) return sc; return sc; } //+------------------------------------------------------------------- // // Member: ScCleanup // // Synopsis: Remove all the toolbars and menu buttons owned // by this controlbar. // // Arguments: None // // Returns: SC // //-------------------------------------------------------------------- SC CControlbar::ScCleanup() { DECLARE_SC(sc, _T("CControlbar::ScCleanup")); ASSERT(m_spExtendControlbar != NULL); if (m_spExtendControlbar != NULL) m_spExtendControlbar->SetControlbar(NULL); sc = ScDetachToolbars(); if (sc) return sc; // If there is a menu button, detach (remove it // from the UI). if (m_pMenuButton) { sc = m_pMenuButton->ScDetach(); m_pMenuButton = NULL; } return sc; } //+------------------------------------------------------------------- // // Member: ScDetachToolbars // // Synopsis: Detach all the toolbars. // // Arguments: None. // // Returns: SC // //-------------------------------------------------------------------- SC CControlbar::ScDetachToolbars() { DECLARE_SC(sc, _T("CControlbar::ScDetachToolbars")); ToolbarsList::iterator itToolbar = m_ToolbarsList.begin(); while (itToolbar != m_ToolbarsList.end()) { CToolbar* pToolbar = (*itToolbar); if (NULL == pToolbar) return (sc = E_UNEXPECTED); CMMCToolbarIntf* pToolbarIntf = pToolbar->GetMMCToolbarIntf(); if (NULL == pToolbarIntf) return (sc = E_UNEXPECTED); // Detach the toolbar UI. sc = pToolbarIntf->ScDetach(pToolbar); if (sc) return sc; // Detach the controlbar from toolbar. pToolbar->SetControlbar(NULL); // Remove the toolbar reference from the list. itToolbar = m_ToolbarsList.erase(itToolbar); } return (sc); } //+------------------------------------------------------------------- // // Member: ScShowToolbars // // Synopsis: Show/Hide all the toolbars. // // Arguments: [bool] - Show or Hide. // // Returns: SC // //-------------------------------------------------------------------- SC CControlbar::ScShowToolbars(bool bShow) { DECLARE_SC(sc, _T("CControlbar::ScShowToolbars")); ToolbarsList::iterator itToolbar = m_ToolbarsList.begin(); for (; itToolbar != m_ToolbarsList.end(); ++itToolbar) { CToolbar* pToolbar = (*itToolbar); if (NULL == pToolbar) return (sc = E_UNEXPECTED); CMMCToolbarIntf* pToolbarIntf = pToolbar->GetMMCToolbarIntf(); if (NULL == pToolbarIntf) return (sc = E_UNEXPECTED); sc = pToolbarIntf->ScShow(pToolbar, bShow); if (sc) return sc; } return sc; } CViewData* CControlbar::GetViewData() { ASSERT(m_pCache != NULL); return m_pCache->GetViewData(); } /////////////////////////////////////////////////////////////////////////// // // CSelData implementation // DEBUG_DECLARE_INSTANCE_COUNTER(CSelData); //+------------------------------------------------------------------- // // Member: ScReset // // Synopsis: Init all the data members. // // Arguments: None // // Returns: SC // //-------------------------------------------------------------------- SC CSelData::ScReset() { DECLARE_SC(sc, _T("CSelData::ScReset")); if (m_pCtrlbarPrimary != NULL) { sc = ScDestroyPrimaryCtrlbar(); if (sc) return sc; } sc = ScDestroyExtensionCtrlbars(); if (sc) return sc; m_bScopeSel = false; m_bSelect = false; m_pNodeScope = NULL; m_pMS = NULL; m_pCtrlbarPrimary = NULL; m_lCookie = -1; m_pCompPrimary = NULL; m_spDataObject = NULL; return sc; } //+------------------------------------------------------------------- // // Member: ScShowToolbars // // Synopsis: Show/Hide primary & extension toolbars. // // Arguments: [bool] - Show/Hide. // // Returns: SC // //-------------------------------------------------------------------- SC CSelData::ScShowToolbars(bool bShow) { DECLARE_SC(sc, _T("CSelData::ScShowToolbars")); if (m_pCtrlbarPrimary != NULL) { sc = m_pCtrlbarPrimary->ScShowToolbars(bShow); if (sc) return sc; } POSITION pos = m_listExtCBs.GetHeadPosition(); bool bReturn = true; while (pos != NULL) { CControlbar* pControlbar = m_listExtCBs.GetNext(pos); if (pControlbar) { sc = pControlbar->ScShowToolbars(bShow); if (sc) return sc; } } return sc; } CControlbar* CSelData::GetControlbar(const CLSID& clsidSnapin) { POSITION pos = m_listExtCBs.GetHeadPosition(); while (pos) { CControlbar* pControlbar = m_listExtCBs.GetNext(pos); if (pControlbar && pControlbar->IsSameSnapin(clsidSnapin) == TRUE) return pControlbar; } return NULL; } //+------------------------------------------------------------------- // // Member: ScDestroyPrimaryCtrlbar // // Synopsis: Ask primary controlbar to release its toolbar/menubutton // ref and cleanup our reference to the controlbar. // // Arguments: None // // Returns: SC // //-------------------------------------------------------------------- SC CSelData::ScDestroyPrimaryCtrlbar() { DECLARE_SC(sc, _T("CSelData::ScDestroyPrimaryCtrlbar")); if (NULL == m_pCtrlbarPrimary) return (sc = E_UNEXPECTED); sc = m_pCtrlbarPrimary->ScCleanup(); if (sc) return sc; /* * In CreateControlbar we had a ref on IControlbar * (detaching smart ptr). Let us now undo that ref. */ m_pCtrlbarPrimary->Release(); m_pCtrlbarPrimary = NULL; return sc; } //+------------------------------------------------------------------- // // Member: ScDestroyExtensionCtrlbars // // Synopsis: Ask extension controlbars to release their toolbar/menubutton // ref and cleanup our reference to the controlbars. // // Arguments: None // // Returns: SC // //-------------------------------------------------------------------- SC CSelData::ScDestroyExtensionCtrlbars() { DECLARE_SC(sc, _T("CSelData::ScDestroyExtensionCtrlbars")); POSITION pos = m_listExtCBs.GetHeadPosition(); while (pos != NULL) { CControlbar* pControlbar = m_listExtCBs.GetNext(pos); if (pControlbar) { sc = pControlbar->ScCleanup(); if (sc) return sc; /* * In CreateControlbar we had a ref on IControlbar * (detaching smart ptr). Let us now undo that ref. */ pControlbar->Release(); } } m_listExtCBs.RemoveAll(); return sc; } /////////////////////////////////////////////////////////////////////////// // // CControlbarsCache implementation // DEBUG_DECLARE_INSTANCE_COUNTER(CControlbarsCache); void CControlbarsCache::SetViewData(CViewData* pViewData) { ASSERT(pViewData != 0); m_pViewData = pViewData; } CViewData* CControlbarsCache::GetViewData() { ASSERT(m_pViewData != NULL); return m_pViewData; } CControlbar* CControlbarsCache::CreateControlbar(IExtendControlbarPtr& spECB, const CLSID& clsidSnapin) { DECLARE_SC(sc, _T("CControlbarsCache::CreateControlbar")); CComObject* pControlbar; sc = CComObject::CreateInstance(&pControlbar); if (sc) return NULL; IControlbarPtr spControlbar = pControlbar; if (NULL == spControlbar) { ASSERT(NULL != pControlbar); // QI fails but object is created how? sc = E_UNEXPECTED; return NULL; } pControlbar->SetCache(this); pControlbar->SetExtendControlbar(spECB, clsidSnapin); sc = spECB->SetControlbar(spControlbar); if (sc) return NULL; // spControlbar smart ptr (object will be destroyed). // Snapin must return S_OK to be valid if (S_OK == sc.ToHr()) { // Detach, thus hold a ref count on the Controlbar object // CSelData holds this reference & releases the ref in // ScDestroyPrimaryCtrlbar() or ScDestroyExtensionCtrlbars(). spControlbar.Detach(); // This is for debug info. Debug_SetControlbarSnapinName(clsidSnapin, pControlbar); return pControlbar; } return NULL; } HRESULT CControlbarsCache::OnMultiSelect( CNode* pNodeScope, CMultiSelection* pMultiSelection, IDataObject* pDOMultiSel, BOOL bSelect) { ASSERT(pNodeScope != NULL); ASSERT(pMultiSelection != NULL); ASSERT(pDOMultiSel != NULL); if (pNodeScope == NULL || pMultiSelection == NULL || pDOMultiSel == NULL) return E_FAIL; CSelData selData(false, (bool)bSelect); selData.m_pMS = pMultiSelection; if (selData == m_SelData) return S_FALSE; if (!bSelect) return _OnDeSelect(selData); selData.m_pCompPrimary = pMultiSelection->GetPrimarySnapinComponent(); CList extnSnapins; HRESULT hr = pMultiSelection->GetExtensionSnapins(g_szToolbar, extnSnapins); CHECK_HRESULT(hr); selData.m_spDataObject.Attach(pDOMultiSel, TRUE); return _ProcessSelection(selData, extnSnapins); } HRESULT CControlbarsCache::OnResultSelChange( CNode* pNode, MMC_COOKIE cookie, BOOL bSelected) { DECLARE_SC(sc, TEXT("CControlbarsCache::OnResultSelChange")); sc = ScCheckPointers (pNode); if (sc) return (sc.ToHr()); CSelData selData(false, (bool)bSelected); selData.m_lCookie = cookie; if (selData == m_SelData) return (sc = S_FALSE).ToHr(); if (!bSelected) { sc = _OnDeSelect(selData); return sc.ToHr(); } IDataObjectPtr spDataObject = NULL; CComponent* pCCResultItem = NULL; CList extnSnapins; BOOL bListPadItem = GetViewData()->HasListPad() && !IS_SPECIAL_LVDATA(cookie); if (GetViewData()->IsVirtualList()) { pCCResultItem = pNode->GetPrimaryComponent(); sc = ScCheckPointers(pCCResultItem, E_UNEXPECTED); if (sc) return sc.ToHr(); sc = pCCResultItem->QueryDataObject(cookie, CCT_RESULT, &spDataObject); if (sc) return sc.ToHr(); } else if ( (GetViewData()->HasOCX()) || (GetViewData()->HasWebBrowser() && !bListPadItem) ) { selData.m_pCompPrimary = pNode->GetPrimaryComponent(); sc = _ProcessSelection(selData, extnSnapins); return sc.ToHr(); } else { CResultItem* pri = CResultItem::FromHandle(cookie); sc = ScCheckPointers(pri, E_UNEXPECTED); if (sc) return sc.ToHr(); if (pri->IsScopeItem()) { // Get the data object from IComponentData pNode = CNode::FromResultItem (pri); sc = ScCheckPointers(pNode, E_UNEXPECTED); if (sc) return sc.ToHr(); if (pNode->IsInitialized() == FALSE) { sc = pNode->InitComponents(); if (sc) return sc.ToHr(); } pCCResultItem = pNode->GetPrimaryComponent(); sc = pNode->QueryDataObject(CCT_SCOPE, &spDataObject); if (sc) return sc.ToHr(); } else // Must be a leaf item inserted by a snapin { pCCResultItem = pNode->GetComponent(pri->GetOwnerID()); sc = ScCheckPointers(pCCResultItem, E_UNEXPECTED); if (sc) return sc.ToHr(); sc = pCCResultItem->QueryDataObject(pri->GetSnapinData(), CCT_RESULT, &spDataObject); if (sc) return sc.ToHr(); } } // Create extension snapin list if (spDataObject != NULL) { ASSERT(pCCResultItem != NULL); GUID guidObjType; sc = ::ExtractObjectTypeGUID(spDataObject, &guidObjType); if (sc) return sc.ToHr(); CSnapIn* pSnapIn = pNode->GetPrimarySnapIn(); CMTNode* pmtNode = pNode->GetMTNode(); sc = ScCheckPointers(pmtNode, E_UNEXPECTED); if (sc) return sc.ToHr(); CArray DynExtens; ExtractDynExtensions(spDataObject, DynExtens); CExtensionsIterator it; sc = it.ScInitialize(pSnapIn, guidObjType, g_szToolbar, DynExtens.GetData(), DynExtens.GetSize()); if (!sc.IsError()) { for (; !it.IsEnd(); it.Advance()) { extnSnapins.AddHead(const_cast(it.GetCLSID())); } } selData.m_pCompPrimary = pCCResultItem; selData.m_spDataObject.Attach(spDataObject.Detach()); } // Finally process selection sc = _ProcessSelection(selData, extnSnapins); if (sc) return sc.ToHr(); return sc.ToHr(); } HRESULT CControlbarsCache::OnScopeSelChange(CNode* pNode, BOOL bSelected) { DECLARE_SC(sc, TEXT("CControlbarsCache::OnScopeSelChange")); CSelData selData(true, (bool)bSelected); selData.m_pNodeScope = pNode; if (selData == m_SelData) return S_FALSE; if (!bSelected) return _OnDeSelect(selData); HRESULT hr = S_OK; IDataObjectPtr spDataObject; CComponent* pCCPrimary = NULL; CList extnSnapins; hr = pNode->QueryDataObject(CCT_SCOPE, &spDataObject); if (FAILED(hr)) return hr; pCCPrimary = pNode->GetPrimaryComponent(); GUID guidObjType; hr = ::ExtractObjectTypeGUID(spDataObject, &guidObjType); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return hr; CSnapIn* pSnapIn = pNode->GetPrimarySnapIn(); CArray DynExtens; ExtractDynExtensions(spDataObject, DynExtens); CExtensionsIterator it; sc = it.ScInitialize(pSnapIn, guidObjType, g_szToolbar, DynExtens.GetData(), DynExtens.GetSize()); if (!sc.IsError()) { for (; it.IsEnd() == FALSE; it.Advance()) { extnSnapins.AddHead(const_cast(it.GetCLSID())); } } // Finally process selection selData.m_pCompPrimary = pCCPrimary; selData.m_spDataObject.Attach(spDataObject.Detach()); return _ProcessSelection(selData, extnSnapins); } HRESULT CControlbarsCache::_OnDeSelect(CSelData& selData) { ASSERT(!selData.IsSelect()); if (selData.m_bScopeSel != m_SelData.m_bScopeSel) return S_FALSE; if ( (m_SelData.m_pCtrlbarPrimary != NULL && m_SelData.m_spDataObject == NULL) && (!GetViewData()->HasOCX() || !GetViewData()->HasWebBrowser()) && m_SelData.IsScope()) { return E_UNEXPECTED; } MMC_NOTIFY_TYPE eNotifyCode = MMCN_SELECT; LPARAM lDataObject; if (GetViewData()->IsVirtualList()) { eNotifyCode = MMCN_DESELECT_ALL; // Must use NULL data object for MMCN_DESELECT_ALL. lDataObject = 0; } else if ((GetViewData()->HasOCX()) && (!m_SelData.IsScope())) lDataObject = reinterpret_cast(DOBJ_CUSTOMOCX); else if ((GetViewData()->HasWebBrowser()) && (!m_SelData.IsScope())) { if (GetViewData()->HasListPad() && m_SelData.m_spDataObject != NULL) { lDataObject = reinterpret_cast( static_cast(m_SelData.m_spDataObject)); } else { lDataObject = reinterpret_cast(DOBJ_CUSTOMWEB); } } else { lDataObject = reinterpret_cast( static_cast(m_SelData.m_spDataObject)); } WORD wScope = static_cast(m_SelData.IsScope()); LPARAM arg = MAKELONG(wScope, FALSE); if (m_SelData.m_pCtrlbarPrimary != NULL) { m_SelData.m_pCtrlbarPrimary->ControlbarNotify(eNotifyCode, arg, lDataObject); } POSITION pos = m_SelData.m_listExtCBs.GetHeadPosition(); while (pos) { CControlbar* pCbar = m_SelData.m_listExtCBs.GetNext(pos); pCbar->ControlbarNotify(eNotifyCode, arg, lDataObject); } m_SelData.m_bSelect = false; m_SelData.m_spDataObject = NULL; // Release & set to NULL return S_OK; } HRESULT CControlbarsCache::_ProcessSelection( CSelData& selData, CList& extnSnapins) { LPARAM lDataObject = reinterpret_cast( static_cast(selData.m_spDataObject)); if (NULL == lDataObject) { if ( (GetViewData()->HasOCX()) && (!selData.IsScope()) ) lDataObject = reinterpret_cast(DOBJ_CUSTOMOCX); else if ( (GetViewData()->HasWebBrowser()) && (!selData.IsScope()) ) lDataObject = reinterpret_cast(DOBJ_CUSTOMWEB); } WORD wScope = static_cast(selData.IsScope()); long arg = MAKELONG(wScope, TRUE); m_SelData.m_bScopeSel = selData.m_bScopeSel; m_SelData.m_bSelect = selData.m_bSelect; m_SelData.m_pNodeScope = selData.m_pNodeScope; m_SelData.m_lCookie = selData.m_lCookie; m_SelData.m_spDataObject.Attach(selData.m_spDataObject.Detach()); // Handle primary controlbar first if (m_SelData.m_pCompPrimary != selData.m_pCompPrimary) { if (m_SelData.m_pCtrlbarPrimary != NULL) { // Ask controlbar to destroy its ref & destroy our ref // to controlbar. m_SelData.ScDestroyPrimaryCtrlbar(); } m_SelData.m_pCompPrimary = selData.m_pCompPrimary; if (m_SelData.m_pCompPrimary != NULL && m_SelData.m_pCtrlbarPrimary == NULL) { IExtendControlbarPtr spECBPrimary = m_SelData.m_pCompPrimary->GetIComponent(); if (spECBPrimary != NULL) { m_SelData.m_pCtrlbarPrimary = CreateControlbar(spECBPrimary, m_SelData.m_pCompPrimary->GetCLSID()); } } } if (m_SelData.m_pCtrlbarPrimary != NULL) { m_SelData.m_pCtrlbarPrimary->ControlbarNotify(MMCN_SELECT, arg, lDataObject); } // Handle extension controlbars CControlbarsList newCBs; POSITION pos = extnSnapins.GetHeadPosition(); while (pos) { CControlbar* pCbar = NULL; CLSID& clsid = extnSnapins.GetNext(pos); POSITION pos2 = m_SelData.m_listExtCBs.GetHeadPosition(); POSITION pos2Prev = 0; while (pos2) { pos2Prev = pos2; pCbar = m_SelData.m_listExtCBs.GetNext(pos2); ASSERT(pCbar != NULL); if (pCbar->IsSameSnapin(clsid) == TRUE) break; pCbar = NULL; } if (pCbar != NULL) { ASSERT(pos2Prev != 0); m_SelData.m_listExtCBs.RemoveAt(pos2Prev); } else { IExtendControlbarPtr spECB; HRESULT hr = spECB.CreateInstance(clsid, NULL, MMC_CLSCTX_INPROC); CHECK_HRESULT(hr); if (SUCCEEDED(hr)) pCbar = CreateControlbar(spECB, clsid); } if (pCbar != NULL) newCBs.AddHead(pCbar); } m_SelData.ScDestroyExtensionCtrlbars(); pos = newCBs.GetHeadPosition(); while (pos) { CControlbar* pCbar = newCBs.GetNext(pos); m_SelData.m_listExtCBs.AddHead(pCbar); pCbar->ControlbarNotify(MMCN_SELECT, arg, lDataObject); } newCBs.RemoveAll(); return S_OK; }