|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1999 - 1999
//
// File: scopndcb.cpp
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "scopndcb.h"
#include "oncmenu.h"
#include "util.h"
#include "amcmsgid.h"
#include "multisel.h"
#include "nmutil.h"
#include "nodemgr.h"
#include "copypast.h"
#include "regutil.h"
#include "taskenum.h"
#include "nodepath.h"
#include "rsltitem.h"
#include "bookmark.h"
#include "tasks.h"
#include "viewpers.h"
#include "colwidth.h"
#include "conframe.h"
#include "constatbar.h"
#include "about.h"
#include "conview.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
//############################################################################
//############################################################################
//
// Trace Tags
//
//############################################################################
//############################################################################
#ifdef DBG
CTraceTag tagNodeCallback(TEXT("NodeCallback"), TEXT("NodeCallback")); #endif
void AddSubmenu_CreateNew(IContextMenuProvider* pICMP, BOOL fStaticFolder ); void AddSubmenu_Task(IContextMenuProvider* pICMP );
DEBUG_DECLARE_INSTANCE_COUNTER(CNodeCallback);
#define INVALID_COMPONENTID -9
void DeleteMultiSelData(CNode* pNode) { ASSERT(pNode != NULL); ASSERT(pNode->GetViewData() != NULL); CMultiSelection* pMultiSel = pNode->GetViewData()->GetMultiSelection(); if (pMultiSel != NULL) { pMultiSel->ReleaseMultiSelDataObject(); pMultiSel->Release(); pNode->GetViewData()->SetMultiSelection(NULL); } }
CNodeCallback::CNodeCallback() : m_pCScopeTree(NULL), m_pNodeUnderInit(NULL) { DEBUG_INCREMENT_INSTANCE_COUNTER(CNodeCallback); }
CNodeCallback::~CNodeCallback() { DEBUG_DECREMENT_INSTANCE_COUNTER(CNodeCallback); }
STDMETHODIMP CNodeCallback::Initialize(IScopeTree* pScopeTree) { MMC_TRY
IF_NULL_RETURN_INVALIDARG(pScopeTree);
m_pCScopeTree = dynamic_cast<CScopeTree*>(pScopeTree); ASSERT(m_pCScopeTree != NULL);
return S_OK;
MMC_CATCH }
STDMETHODIMP CNodeCallback::GetImages(HNODE hNode, int* piImage, int* piSelectedImage) { IF_NULL_RETURN_INVALIDARG(hNode);
MMC_TRY
// They should ask for at least one of the images.
if (piImage == NULL && piSelectedImage == NULL) return E_INVALIDARG;
// convert to real type
CNode* pNode = CNode::FromHandle(hNode);
if (piImage != NULL) *piImage = pNode->GetMTNode()->GetImage();
if (piSelectedImage != NULL) *piSelectedImage = pNode->GetMTNode()->GetOpenImage();
return S_OK;
MMC_CATCH }
STDMETHODIMP CNodeCallback::GetDisplayName(HNODE hNode, tstring& strName) { DECLARE_SC (sc, _T("CNodeCallback::GetDisplayName"));
/*
* clear out the output string */ strName.erase();
// convert to real type
CNode* pNode = CNode::FromHandle(hNode); sc = ScCheckPointers (pNode); if (sc) return (sc.ToHr());
strName = pNode->GetDisplayName(); return (sc.ToHr()); }
STDMETHODIMP CNodeCallback::GetWindowTitle(HNODE hNode, tstring& strTitle) { DECLARE_SC (sc, _T("CNodeCallback::GetWindowTitle"));
/*
* clear out the output string */ strTitle.erase();
// convert to real type
CNode* pNode = CNode::FromHandle(hNode); sc = ScCheckPointers (pNode); if (sc) return (sc.ToHr());
CComponent* pCC = pNode->GetPrimaryComponent(); sc = ScCheckPointers (pCC, E_UNEXPECTED); if (sc) return (sc.ToHr());
IDataObjectPtr spdtobj; sc = pCC->QueryDataObject(MMC_WINDOW_COOKIE, CCT_UNINITIALIZED, &spdtobj); if (sc) return (sc.ToHr());
USES_CONVERSION; static CLIPFORMAT cfWindowTitle = (CLIPFORMAT) RegisterClipboardFormat(OLE2T(CCF_WINDOW_TITLE));
sc = ExtractString(spdtobj, cfWindowTitle, strTitle); if (sc) return (sc.ToHr());
return (sc.ToHr()); }
inline HRESULT CNodeCallback::_InitializeNode(CNode* pNode) { ASSERT(pNode != NULL);
m_pNodeUnderInit = pNode; HRESULT hr = pNode->InitComponents(); m_pNodeUnderInit = NULL; return hr; }
STDMETHODIMP CNodeCallback::GetResultPane(HNODE hNode, CResultViewType& rvt, GUID *pGuidTaskpadID) { DECLARE_SC(sc, TEXT("CNodeCallback::GetResultPane"));
IF_NULL_RETURN_INVALIDARG(hNode);
MMC_TRY USES_CONVERSION;
// convert to real type
CNode* pNode = CNode::FromHandle(hNode); ASSERT(pNode != NULL);
if (pNode->IsInitialized() == FALSE) { sc = _InitializeNode(pNode); if(sc) return sc.ToHr(); }
sc = pNode->ScGetResultPane(rvt, pGuidTaskpadID); if(sc) return sc.ToHr();
return sc.ToHr();
MMC_CATCH }
//
// 'hNodeSel' is the curreently selected node in the scope pane. 'lDispInfo' is
// the LV disp info struct.
STDMETHODIMP CNodeCallback::GetDispInfo(HNODE hNodeSel, LV_ITEMW* plvi) { IF_NULL_RETURN_INVALIDARG2(hNodeSel, plvi);
if (theApp.ProcessingSnapinChanges() == TRUE) return E_FAIL;
// convert to real types
CNode* pNodeSel = CNode::FromHandle(hNodeSel);
if (IsBadWritePtr (plvi, sizeof(*plvi))) return E_INVALIDARG;
return pNodeSel->GetDispInfoForListItem(plvi); }
STDMETHODIMP CNodeCallback::AddCustomFolderImage (HNODE hNode, IImageListPrivate* pImageList) { CNode* pNode = CNode::FromHandle(hNode); if (pNode) { CSnapInNode* pSINode = dynamic_cast<CSnapInNode*>(pNode); if (pSINode) pSINode->SetResultImageList (pImageList); } return S_OK; }
STDMETHODIMP CNodeCallback::GetState(HNODE hNode, UINT* pnState) { IF_NULL_RETURN_INVALIDARG2(hNode, pnState);
MMC_TRY
// convert to real type
CNode* pNode = CNode::FromHandle(hNode);
*pnState = pNode->GetMTNode()->GetState();
return S_OK;
MMC_CATCH }
STDMETHODIMP CNodeCallback::Notify(HNODE hNode, NCLBK_NOTIFY_TYPE event, LONG_PTR arg, LPARAM param) { MMC_TRY
HRESULT hr = S_OK;
if (hNode == NULL) { switch (event) { case NCLBK_CONTEXTMENU: // Process further.
break;
case NCLBK_GETHELPDOC: return OnGetHelpDoc((HELPDOCINFO*)arg, (LPOLESTR*)param);
case NCLBK_UPDATEHELPDOC: return OnUpdateHelpDoc((HELPDOCINFO*)arg, (HELPDOCINFO*)param);
case NCLBK_DELETEHELPDOC: return OnDeleteHelpDoc((HELPDOCINFO*)arg);
// When the view is closed and NCLBK_SELECT is sent with HNODE NULL (as
// there is no selected node) handle this case.
case NCLBK_SELECT: return S_OK;
default: return E_INVALIDARG; } }
// convert to real type
CNode* pNode = CNode::FromHandle(hNode);
if (m_pNodeUnderInit && pNode && (m_pNodeUnderInit == pNode)) return E_FAIL;
// See if snapin-cache is being modified.
if (theApp.ProcessingSnapinChanges() == TRUE) { // If it is selection/de-selection of node then do not return error
// after the modifications are done (for snapin-cache) the node will
// be selected.
if ( (event == NCLBK_SELECT) || (event == NCLBK_MULTI_SELECT) ) return S_OK; else return E_FAIL; }
switch (event) { case NCLBK_ACTIVATE: hr = OnActvate(pNode, arg); break;
case NCLBK_CACHEHINT: pNode->OnCacheHint(arg, param); break;
case NCLBK_CLICK: ASSERT(0); break;
case NCLBK_CONTEXTMENU: hr = OnContextMenu(pNode, arg, param); break;
case NCLBK_DBLCLICK: hr = OnDblClk(pNode, arg); break;
case NCLBK_CUT: case NCLBK_COPY: OnCutCopy(pNode, static_cast<BOOL>(arg), param, (event == NCLBK_CUT)); break;
case NCLBK_DELETE: { hr = OnDelete(pNode, arg, param);
// 5. Purge the snapin cache
CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache(); ASSERT(pSnapInCache != NULL); if (pSnapInCache != NULL) pSnapInCache->Purge(); } break;
case NCLBK_EXPAND: hr = OnExpand(pNode, arg); break;
case NCLBK_EXPANDED: hr = OnExpanded(pNode); break;
case NCLBK_GETEXPANDEDVISUALLY: hr = (pNode->WasExpandedVisually() == true) ? S_OK : S_FALSE; break;
case NCLBK_SETEXPANDEDVISUALLY: pNode->SetExpandedVisually(static_cast<bool>(arg)); break;
case NCLBK_PROPERTIES: hr = OnProperties(pNode, static_cast<BOOL>(arg), param); break;
case NCLBK_REFRESH: hr = OnRefresh(pNode, static_cast<BOOL>(arg), param); break;
case NCLBK_NEW_TASKPAD_FROM_HERE: hr = OnNewTaskpadFromHere(pNode); break;
case NCLBK_EDIT_TASKPAD: hr = OnEditTaskpad(pNode); break;
case NCLBK_DELETE_TASKPAD: hr = OnDeleteTaskpad(pNode); break;
case NCLBK_PRINT: hr = OnPrint(pNode, static_cast<BOOL>(arg), param); break;
case NCLBK_NEW_NODE_UPDATE: hr = OnNewNodeUpdate(pNode, arg); break;
case NCLBK_RENAME: hr = OnRename(pNode, reinterpret_cast<SELECTIONINFO*>(arg), reinterpret_cast<LPOLESTR>(param)); break;
case NCLBK_MULTI_SELECT: OnMultiSelect(pNode, static_cast<BOOL>(arg)); break;
case NCLBK_SELECT: OnSelect(pNode, static_cast<BOOL>(arg), reinterpret_cast<SELECTIONINFO*>(param)); break;
case NCLBK_FINDITEM: OnFindResultItem(pNode, reinterpret_cast<RESULTFINDINFO*>(arg), reinterpret_cast<LRESULT*>(param)); break;
case NCLBK_COLUMN_CLICKED: hr = OnColumnClicked(pNode, param); break;
case NCLBK_CONTEXTHELP: hr = OnContextHelp(pNode, static_cast<BOOL>(arg), param); break;
case NCLBK_SNAPINHELP: hr = OnSnapInHelp(pNode, static_cast<BOOL>(arg), param); break;
case NCLBK_FILTER_CHANGE: hr = OnFilterChange(pNode, arg, param); break;
case NCLBK_FILTERBTN_CLICK: hr = OnFilterBtnClick(pNode, arg, reinterpret_cast<LPRECT>(param)); break;
case NCLBK_TASKNOTIFY: pNode->OnTaskNotify(arg, param); break;
case NCLBK_GETPRIMARYTASK: hr = OnGetPrimaryTask (pNode, param); break;
case NCLBK_MINIMIZED: hr = OnMinimize (pNode, arg); break;
case NCLBK_LISTPAD: hr = pNode->OnListPad(arg, param); break;
case NCLBK_WEBCONTEXTMENU: pNode->OnWebContextMenu(); break;
default: ASSERT(FALSE); break; }
return hr;
MMC_CATCH }
STDMETHODIMP CNodeCallback::GetMTNode(HNODE hNode, HMTNODE* phMTNode) { IF_NULL_RETURN_INVALIDARG2(hNode, phMTNode);
MMC_TRY
// convert to real type
CNode* pNode = CNode::FromHandle(hNode);
*phMTNode = CMTNode::ToHandle(pNode->GetMTNode());
return S_OK;
MMC_CATCH }
STDMETHODIMP CNodeCallback::SetResultItem(HNODE hNode, HRESULTITEM hri) { IF_NULL_RETURN_INVALIDARG(hNode);
MMC_TRY
// convert to real type
CNode* pNode = CNode::FromHandle(hNode); pNode->SetResultItem(hri); return S_OK;
MMC_CATCH }
STDMETHODIMP CNodeCallback::GetResultItem(HNODE hNode, HRESULTITEM* phri) { IF_NULL_RETURN_INVALIDARG(hNode);
MMC_TRY
// convert to real type
CNode* pNode = CNode::FromHandle(hNode); *phri = pNode->GetResultItem(); return S_OK;
MMC_CATCH }
STDMETHODIMP CNodeCallback::GetMTNodeID(HNODE hNode, MTNODEID* pnID) { IF_NULL_RETURN_INVALIDARG(pnID);
MMC_TRY
// convert to real type
CNode* pNode = CNode::FromHandle(hNode);
*pnID = pNode->GetMTNode()->GetID();
return S_OK;
MMC_CATCH }
/*+-------------------------------------------------------------------------*
* * CNodeCallback::IsTargetNodeOf * * PURPOSE: Is one node a target of another * * PARAMETERS: * HNODE hNode : The node that contains the target * HNODE hTestNode : The alleged target * * RETURNS: * STDMETHODIMP * S_OK - yes * S_FALSE - uses a different target node * E_FAIL - doesn't use a target node * *+-------------------------------------------------------------------------*/ STDMETHODIMP CNodeCallback::IsTargetNodeOf(HNODE hNode, HNODE hTestNode) { MMC_TRY
ASSERT(hNode && hTestNode);
CNode* pNode = CNode::FromHandle(hNode); CNode* pTestNode = CNode::FromHandle(hTestNode); ASSERT(pNode);
return pNode->IsTargetNode(pTestNode);
MMC_CATCH }
STDMETHODIMP CNodeCallback::GetPath(HNODE hNode, HNODE hRootNode, LPBYTE pbm) { DECLARE_SC(sc, TEXT("CNodeCallback::GetPath"));
sc = ScCheckPointers((PVOID)hNode, (PVOID)hRootNode, pbm); if(sc) return sc.ToHr();
MMC_TRY
// convert to real type
CNode* pNode = CNode::FromHandle(hNode); CNode* pRootNode = CNode::FromHandle(hRootNode); CBookmark* pbmOut = reinterpret_cast<CBookmark *>(pbm);
CBookmarkEx bm;
sc = bm.ScInitialize(pNode->GetMTNode(), pRootNode->GetMTNode(), true).ToHr(); if(sc) return sc.ToHr();
// set the out parameter.
*pbmOut = bm;
return sc.ToHr();
MMC_CATCH }
STDMETHODIMP CNodeCallback::GetStaticParentID(HNODE hNode, MTNODEID* pnID) { IF_NULL_RETURN_INVALIDARG2(hNode, pnID);
MMC_TRY
// convert to real type
CNode* pNode = CNode::FromHandle(hNode); CMTNode* pMTNode = pNode->GetMTNode(); ASSERT(pMTNode != NULL);
while (pMTNode != NULL && pMTNode->IsStaticNode() == FALSE) { pMTNode = pMTNode->Parent(); }
ASSERT(pMTNode != NULL);
if (pMTNode != NULL) { *pnID = pMTNode->GetID(); return S_OK; }
return E_UNEXPECTED;
MMC_CATCH }
// The path for the node is stored in pphMTNode. The path is an array of
// HMTNODE's starting from the console root, followed by its child node and
// continuing in this fashion till the HMTNODE of the root node.
STDMETHODIMP CNodeCallback::GetMTNodePath(HNODE hNode, HMTNODE** pphMTNode, long* plLength) { IF_NULL_RETURN_INVALIDARG3(hNode, pphMTNode, plLength);
MMC_TRY
// convert to real type
CNode* pNode = CNode::FromHandle(hNode);
CMTNode* pMTNode = pNode->GetMTNode(); pMTNode = pMTNode->Parent(); // skip this node
for (*plLength = 0; pMTNode != NULL; pMTNode = pMTNode->Parent()) ++(*plLength);
if (*plLength != 0) { HMTNODE* phMTNode = (HMTNODE*)CoTaskMemAlloc(sizeof(HMTNODE) * (*plLength)); if (phMTNode == NULL) { CHECK_HRESULT(E_OUTOFMEMORY); return E_OUTOFMEMORY; }
*pphMTNode = phMTNode;
pMTNode = pNode->GetMTNode(); pMTNode = pMTNode->Parent(); // skip this node
phMTNode = phMTNode + (*plLength - 1);
for (; pMTNode != NULL; pMTNode = pMTNode->Parent(), --phMTNode) *phMTNode = CMTNode::ToHandle(pMTNode);
ASSERT(++phMTNode == *pphMTNode); } else { pphMTNode = NULL; }
return S_OK;
MMC_CATCH }
/*+-------------------------------------------------------------------------*
* * CNodeCallback::GetNodeOwnerID * * PURPOSE: Get the ID of the snap-in component that owns this node. * If not a snap-in owned node, TVOWNED_MAGICWORD is returned. * * PARAMETERS: * HNODE hNode : Node to query * COMPONENTID* : ptr to returned ID * * RETURNS: * STDMETHODIMP * S_OK - ID returned * E_INVALIDARG - * E_FAIL - probably an invalid hNode * *+-------------------------------------------------------------------------*/
/*******************************************************************************
* >>>>>>>>>>>>>> READ THIS BEFORE USING GetNodeOwnerID <<<<<<<<<<<<<<<<<<<<<<< * * This method differs from the GetOwnerID method exposed by CNode (and CMTNode) * in that it returns a zero ID for snap-in static nodes, indicating that the * owner is the snap-in primary component. The CNode method returns * TVOWNED_MAGICWORD for snap-in static nodes, inidcating MMC ownership. For * most purposes the zero ID is more appropriate and I think the node method * should be changed. This requires looking at all uses of the owner ID and * verifying nothing will break. rswaney 5/5/99 *******************************************************************************/
STDMETHODIMP CNodeCallback::GetNodeOwnerID(HNODE hNode, COMPONENTID* pOwnerID) { IF_NULL_RETURN_INVALIDARG2(hNode, pOwnerID);
MMC_TRY
CNode* pNode = CNode::FromHandle(hNode);
if (pNode->IsStaticNode()) *pOwnerID = 0; else *pOwnerID = pNode->GetOwnerID();
return S_OK;
MMC_CATCH }
STDMETHODIMP CNodeCallback::GetNodeCookie(HNODE hNode, MMC_COOKIE* pCookie) { IF_NULL_RETURN_INVALIDARG2(hNode, pCookie);
MMC_TRY
// only dynamic nodes have cookies
CNode* pNode = CNode::FromHandle(hNode); if (!pNode->IsDynamicNode()) return E_FAIL;
*pCookie = pNode->GetUserParam();
return S_OK;
MMC_CATCH }
/*+-------------------------------------------------------------------------*
* * CNodeCallback::GetControl * * PURPOSE: See if there is a OCX with given CLSID for the given node. * If so return it. * * PARAMETERS: * HNODE hNode : * CLSID clsid : * IUnknown ** ppUnkControl : * * RETURNS: * STDMETHODIMP * *+-------------------------------------------------------------------------*/ STDMETHODIMP CNodeCallback::GetControl(HNODE hNode, CLSID clsid, IUnknown **ppUnkControl) { MMC_TRY DECLARE_SC(sc, TEXT("CNodeCallback::GetControl"));
sc = ScCheckPointers((void *)hNode, ppUnkControl); if(sc) return sc.ToHr();
// convert to real type
CNode* pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
*ppUnkControl = pNode->GetControl(clsid); if(!*ppUnkControl) return sc.ToHr();
// addref the interface for the client.
(*ppUnkControl)->AddRef();
return sc.ToHr();
MMC_CATCH }
/*+-------------------------------------------------------------------------*
* * CNodeCallback::SetControl * * PURPOSE: For the given node & clsid of OCX save the OCX window IUnknown*. * * PARAMETERS: * HNODE hNode : * CLSID clsid : * IUnknown* pUnknown : * * RETURNS: * STDMETHODIMP * *+-------------------------------------------------------------------------*/ STDMETHODIMP CNodeCallback::SetControl(HNODE hNode, CLSID clsid, IUnknown* pUnknown) { DECLARE_SC(sc, TEXT("CNodeCallback::SetControl")); sc = ScCheckPointers((void*)hNode, pUnknown); if (sc) return sc.ToHr();
// convert to real type
CNode* pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
pNode->SetControl(clsid, pUnknown);
return sc.ToHr();
}
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::GetControl
//
// Synopsis: For given node & IUnknown* of OCX get the OCX wrapper if one exists.
//
// Arguments: [hNode]
// [pUnkOCX]
// [ppUnkControl]
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::GetControl (HNODE hNode, LPUNKNOWN pUnkOCX, IUnknown **ppUnkControl) { DECLARE_SC(sc, _T("CNodeCallback::GetControl")); sc = ScCheckPointers((void*)hNode, pUnkOCX, ppUnkControl); if (sc) return sc.ToHr();
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
*ppUnkControl = pNode->GetControl(pUnkOCX); if(!*ppUnkControl) return sc.ToHr();
// addref the interface for the client.
(*ppUnkControl)->AddRef();
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: SetControl
//
// Synopsis: For given node & IUnknown of OCX save the IUnknown of
// OCX wrapper.
//
// Arguments: [hNode]
// [pUnkOCX]
// [pUnknown]
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::SetControl (HNODE hNode, LPUNKNOWN pUnkOCX, IUnknown* pUnknown) { DECLARE_SC(sc, _T("SetControl")); sc = ScCheckPointers((void*) hNode, pUnkOCX, pUnknown); if (sc) return sc.ToHr();
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
pNode->SetControl(pUnkOCX, pUnknown);
return (sc.ToHr()); }
STDMETHODIMP CNodeCallback::InitOCX(HNODE hNode, IUnknown* pUnknown) { DECLARE_SC(sc, TEXT("CNodeCallback::InitOCX"));
sc = ScCheckPointers((void *)hNode); if(sc) return sc.ToHr();
CNode* pNode = CNode::FromHandle(hNode); sc = pNode->OnInitOCX(pUnknown);
return sc.ToHr(); }
/////////////////////////////////////////////////////////////////////////////
// Notify handlers
HRESULT CNodeCallback::OnActvate(CNode* pNode, LONG_PTR arg) { DECLARE_SC (sc, _T("CNodeCallback::OnActvate")); sc = ScCheckPointers (pNode); if (sc) return (sc.ToHr());
return pNode->OnActvate(arg); }
HRESULT CNodeCallback::OnMinimize(CNode* pNode, LONG_PTR arg) { DECLARE_SC (sc, _T("CNodeCallback::OnMinimize")); sc = ScCheckPointers (pNode); if (sc) return (sc.ToHr());
return pNode->OnMinimize(arg); }
HRESULT CNodeCallback::OnDelete(CNode* pNode, BOOL bScopePaneSelected, LPARAM lvData) { DECLARE_SC(sc, TEXT("CNodeCallback::OnDelete"));
BOOL bScopeItemSelected; CNode *pSelectedNode = NULL; MMC_COOKIE cookie = -1;
sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lvData, &pSelectedNode, bScopeItemSelected, cookie); if (sc) return sc.ToHr();
sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED); if (sc) return sc.ToHr();
// If result-pane cookie should be valid.
ASSERT( (bScopeItemSelected) || cookie != LVDATA_ERROR); if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) ) return E_FAIL;
HRESULT hr = S_OK;
if (!bScopeItemSelected) { CMultiSelection* pMultiSel = pSelectedNode->GetViewData()->GetMultiSelection(); if (pMultiSel != NULL) { ASSERT(lvData == LVDATA_MULTISELECT); pMultiSel->ScVerbInvoked(MMC_VERB_DELETE); return S_OK; } else { ASSERT(lvData != LVDATA_MULTISELECT);
CComponent* pCC = pSelectedNode->GetPrimaryComponent(); ASSERT(pCC != NULL);
if (pCC != NULL) { if (IS_SPECIAL_LVDATA(lvData)) { LPDATAOBJECT pdobj = (lvData == LVDATA_CUSTOMOCX) ? DOBJ_CUSTOMOCX : DOBJ_CUSTOMWEB;
hr = pCC->Notify(pdobj, MMCN_DELETE, 0, 0); CHECK_HRESULT(hr); } else { IDataObjectPtr spdtobj; hr = pCC->QueryDataObject(cookie, CCT_RESULT, &spdtobj);
ASSERT( NULL != pCC->GetIComponent() );
if (SUCCEEDED(hr)) { hr = pCC->Notify(spdtobj, MMCN_DELETE, 0, 0); CHECK_HRESULT(hr); } } } } } else { CMTNode* pMTNode = pSelectedNode->GetMTNode(); if (pMTNode->Parent() == NULL) return S_FALSE;
if (pSelectedNode->IsStaticNode() == TRUE) // All static nodes can be deleted
{ ASSERT(m_pCScopeTree != NULL);
if (pMTNode->DoDelete(pSelectedNode->GetViewData()->GetMainFrame()) == false) return S_FALSE;
// Delete storage
hr = pMTNode->DestroyElements(); ASSERT(SUCCEEDED(hr));
// Delete the node.
m_pCScopeTree->DeleteNode(pMTNode);
} else // Tell the snapin that put up the dynamic node to delete.
{ CComponentData* pCD = pMTNode->GetPrimaryComponentData(); ASSERT(pCD != NULL);
IDataObjectPtr spDataObject; hr = pCD->QueryDataObject(pMTNode->GetUserParam(), CCT_SCOPE, &spDataObject); CHECK_HRESULT(hr);
ASSERT( NULL != pCD->GetIComponentData() );
if (hr == S_OK) { hr = pCD->Notify(spDataObject, MMCN_DELETE, 0, 0); CHECK_HRESULT(hr); } } }
return hr; }
HRESULT CNodeCallback::OnFindResultItem(CNode* pNode, RESULTFINDINFO* pFindInfo, LRESULT* pResult) { IF_NULL_RETURN_INVALIDARG3(pNode, pFindInfo, pResult);
// init result to -1 (item not found)
*pResult = -1;
CComponent* pCC = pNode->GetPrimaryComponent(); ASSERT(pCC != NULL); if (pCC == NULL) return E_FAIL;
IResultOwnerDataPtr spIResultOwnerData = pCC->GetIComponent(); if (spIResultOwnerData == NULL) return S_FALSE;
return spIResultOwnerData->FindItem(pFindInfo, reinterpret_cast<int*>(pResult)); }
HRESULT CNodeCallback::OnRename(CNode* pNode, SELECTIONINFO *pSelInfo, LPOLESTR pszNewName) { HRESULT hr = S_OK;
if (pSelInfo->m_bScope) { CMTNode* pMTNode = pNode->GetMTNode();
hr = pMTNode->OnRename(1, pszNewName); } else { CComponent* pCC = pNode->GetPrimaryComponent(); ASSERT(pCC != NULL); if (pCC != NULL) { IDataObjectPtr spDataObject; hr = pCC->QueryDataObject(pSelInfo->m_lCookie, CCT_RESULT, &spDataObject); if (FAILED(hr)) return hr;
hr = pCC->Notify(spDataObject, MMCN_RENAME, 1, reinterpret_cast<LPARAM>(pszNewName)); CHECK_HRESULT(hr); return hr; } }
if (hr == S_OK) { if (pNode->IsStaticNode() == TRUE) { USES_CONVERSION; pNode->SetDisplayName( W2T(pszNewName) ); }
// Now inform the views to modify as needed.
SViewUpdateInfo vui; // Snapin nodes result pane will be handled by the snapins
vui.flag = VUI_REFRESH_NODE; pNode->GetMTNode()->CreatePathList(vui.path); m_pCScopeTree->UpdateAllViews(VIEW_UPDATE_MODIFY, reinterpret_cast<LPARAM>(&vui)); }
return hr; }
HRESULT CNodeCallback::OnNewNodeUpdate(CNode* pNode, LONG_PTR lFlags) { pNode->GetMTNode()->SetPropertyPageIsDisplayed(FALSE);
// Inform the views to modify.
SViewUpdateInfo vui; vui.flag = lFlags; pNode->GetMTNode()->CreatePathList(vui.path); m_pCScopeTree->UpdateAllViews(VIEW_UPDATE_MODIFY, reinterpret_cast<LPARAM>(&vui)); return S_OK; }
HRESULT CNodeCallback::OnExpand(CNode* pNode, BOOL fExpand) { HRESULT hr = S_OK; ASSERT(pNode != 0);
// initialize the node if needed.
if ( fExpand && (pNode->WasExpandedAtLeastOnce() == FALSE) && (pNode->IsInitialized() == FALSE)) { hr = _InitializeNode(pNode); if ((FAILED(hr))) { return hr; } }
return pNode->OnExpand(fExpand); }
HRESULT CNodeCallback::OnExpanded(CNode* pNode) { ASSERT(pNode != 0);
pNode->SetExpandedAtLeastOnce();
return S_OK; }
HRESULT CNodeCallback::OnScopeSelect(CNode* pNode, BOOL bSelect, SELECTIONINFO* pSelInfo) { DECLARE_SC(sc, TEXT("CNodeCallback::OnScopeSelect")); sc = ScCheckPointers(pNode, pSelInfo); if (sc) return sc.ToHr();
// clear out the the status bar text if we're deselecting a node
if (! bSelect) { CViewData *pViewData = pNode->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return sc.ToHr();
CConsoleStatusBar* pStatusBar = pViewData->GetStatusBar();
if (pStatusBar != NULL) pStatusBar->ScSetStatusText (NULL); }
if (pNode->IsInitialized() == FALSE) { sc = _InitializeNode(pNode); if (sc) return sc.ToHr(); }
sc = pNode->OnScopeSelect(bSelect, pSelInfo); if(sc) return sc.ToHr();
#ifdef DBG
if (bSelect) Dbg(DEB_USER11, _T("Selecting %s node."), pNode->GetDisplayName()); #endif
return sc.ToHr(); }
STDMETHODIMP CNodeCallback::SetTaskPadList(HNODE hNode, LPUNKNOWN pUnknown) { IFramePrivate* pFramePrivate = GetIFramePrivateFromNode (hNode);
if (pFramePrivate == NULL) return E_UNEXPECTED;
return (pFramePrivate->SetTaskPadList(pUnknown)); }
IFramePrivate* GetIFramePrivateFromNode (CNode* pNode) { if (pNode == NULL) return (NULL);
return pNode->GetIFramePrivate(); }
void CNodeCallback::OnMultiSelect(CNode* pNode, BOOL bSelect) { Trace(tagNodeCallback, _T("----------------->>>>>>> MULTI_SELECT<%d>\n"), bSelect); SC sc; CViewData* pViewData = NULL;
if (NULL == pNode) { sc = E_UNEXPECTED; goto Error; }
pViewData = pNode->GetViewData(); if (NULL == pViewData) { sc = E_UNEXPECTED; goto Error; }
if (pViewData->IsVirtualList()) { if (bSelect == TRUE) DeleteMultiSelData(pNode); }
_OnMultiSelect(pNode, bSelect); if (bSelect == FALSE) DeleteMultiSelData(pNode);
// Update the std-verb tool-buttons.
sc = pViewData->ScUpdateStdbarVerbs(); if (sc) goto Error;
pViewData->UpdateToolbars(pViewData->GetToolbarsDisplayed());
Cleanup: return; Error: TraceError (_T("CNodeCallback::OnMultiSelect"), sc); goto Cleanup; }
void CNodeCallback::_OnMultiSelect(CNode* pNode, BOOL bSelect) { DECLARE_SC(sc, TEXT("CNodeCallback::_OnMultiSelect")); sc = ScCheckPointers(pNode); if (sc) return;
CViewData *pViewData = pNode->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return;
CMultiSelection* pMultiSelection = pNode->GetViewData()->GetMultiSelection();
if (pMultiSelection) { if (pMultiSelection->IsInUse()) return; else { /*
* If result pane items are selected by dragging a mouse (that forms Marquee) * or if snapin sets items to selected state then the items are selected one * by one. That is multi-select for 1 item, multi-select for 2 items and so-on. * There is no deselect inbetween, so if we already have a multiselection object * for 2 items then when we get multi-select for 3 items we need to destroy multiselection * object for 2 items. This is done below. * */ DeleteMultiSelData(pNode); pMultiSelection = NULL; } }
// set standard bars
CVerbSet* pVerbSet = dynamic_cast<CVerbSet*>(pViewData->GetVerbSet()); sc = ScCheckPointers(pVerbSet, E_UNEXPECTED); if (sc) return;
sc = pVerbSet->ScInitializeForMultiSelection(pNode, bSelect); if (sc) return;
if (pMultiSelection == NULL) { if (bSelect == FALSE) return;
CComponentPtrArray* prgComps = new CComponentPtrArray; if (pNode->IsInitialized() == FALSE) { sc = _InitializeNode(pNode); if (sc) return; }
// Create CMultiSelection
pMultiSelection = new CMultiSelection(pNode); sc = ScCheckPointers(pMultiSelection, E_OUTOFMEMORY); if (sc) return;
sc = pMultiSelection->Init(); if (sc) return;
pViewData->SetMultiSelection(pMultiSelection); }
pMultiSelection->SetScopeTree(m_pCScopeTree);
IDataObjectPtr spdobj; sc = pMultiSelection->GetMultiSelDataObject(&spdobj); if (sc) return;
sc = ScCheckPointers(spdobj, E_UNEXPECTED); if (sc) return;
// give the scope item a chance to do any initialization that it needs.
// For instance, the console taskpad uses this opportunity to gather information
// about the selected item's context menu.
SELECTIONINFO SelInfo; SelInfo.m_lCookie = LVDATA_MULTISELECT;
// Inform control bars of selection change.
CControlbarsCache* pCtrlbarsCache = dynamic_cast<CControlbarsCache*>(pNode->GetControlbarsCache()); sc = ScCheckPointers(pCtrlbarsCache, E_UNEXPECTED); if (sc) return;
pCtrlbarsCache->OnMultiSelect(pNode, pMultiSelection, spdobj, bSelect);
sc = pVerbSet->ScComputeVerbStates(); if (sc) return; }
void CNodeCallback::OnSelect(CNode* pNode, BOOL bSelect, SELECTIONINFO* pSelInfo) { Trace(tagNodeCallback, _T("----------------->>>>>>> SELECT<%d>\n"), bSelect); SC sc; CViewData* pViewData = NULL;
if (pSelInfo == NULL) { sc = E_UNEXPECTED; goto Error; }
Trace(tagNodeCallback, _T("====>> NCLBK_SELECT<%d, %d, %c>\n"), pSelInfo->m_bScope, bSelect, pSelInfo->m_bDueToFocusChange ? _T('F') : _T('S'));
if (NULL == pNode) { sc = E_UNEXPECTED; goto Error; }
pViewData = pNode->GetViewData(); if (NULL == pViewData) { sc = E_UNEXPECTED; goto Error; }
DeleteMultiSelData(pNode);
if (!bSelect) { // Reset controlbars
pNode->ResetControlbars(bSelect, pSelInfo);
// Reset standard verbs
sc = pNode->ScInitializeVerbs(bSelect, pSelInfo); if (sc) sc.TraceAndClear(); }
// For scoe sel change reset result pane.
if (pSelInfo->m_bScope == TRUE && pSelInfo->m_bDueToFocusChange == FALSE) { sc = OnScopeSelect(pNode, bSelect, pSelInfo); if (sc) goto Error; }
if (bSelect) { // Reset controlbars
pNode->ResetControlbars(bSelect, pSelInfo);
// Reset standard verbs
sc = pNode->ScInitializeVerbs(bSelect, pSelInfo); if (sc) sc.TraceAndClear(); }
// Update the std-verb tool-buttons.
sc = pViewData->ScUpdateStdbarVerbs();
// Dummy block
{ // Update the paste button
LPARAM lvData = pSelInfo->m_lCookie;
BOOL bScopePaneSelected = pSelInfo->m_bScope || pSelInfo->m_bBackground;
sc = UpdatePasteButton(CNode::ToHandle(pNode), bScopePaneSelected, lvData); if (sc) goto Error;
// Update toolbars.
pViewData->UpdateToolbars(pViewData->GetToolbarsDisplayed()); }
Cleanup: return; Error: TraceError (_T("CNodeCallback::OnSelect"), sc); goto Cleanup; }
HRESULT CNodeCallback::OnDblClk(CNode* pNode, LONG_PTR lvData) { DECLARE_SC(sc, TEXT("CNodeCallback::OnDblClk")); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
BOOL bScopePaneSelected = FALSE;
BOOL bScopeItemSelected; CNode *pSelectedNode = NULL; MMC_COOKIE cookie = -1;
sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lvData, &pSelectedNode, bScopeItemSelected, cookie); if (sc) return sc.ToHr();
sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED); if (sc) return sc.ToHr();
// If result-pane cookie should be valid.
if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) ) return (sc = E_FAIL).ToHr();
// Ignore double-click on LV background.
if (lvData == LVDATA_BACKGROUND) return sc.ToHr();
CComponent* pCC = pSelectedNode->GetPrimaryComponent(); sc = ScCheckPointers(pCC, E_UNEXPECTED); if (sc) return sc.ToHr();
// Get the dataobject of the item which was double-clicked.
IDataObjectPtr spdtobj;
if (!bScopeItemSelected) // leaf item
{ sc = pCC->QueryDataObject(cookie, CCT_RESULT, &spdtobj);
if (sc) { sc.TraceAndClear(); return sc.ToHr(); } } else { sc = pSelectedNode->QueryDataObject(CCT_SCOPE, &spdtobj); if (sc) { sc.TraceAndClear(); return sc.ToHr(); } }
sc = pCC->Notify(spdtobj, MMCN_DBLCLICK, 0, 0); if (sc) sc.TraceAndClear();
// Snapin has asked us to do default verb action, so findout default verb.
if (sc == S_FALSE) { CViewData *pViewData = pSelectedNode->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return sc.ToHr();
CVerbSet* pVerbSet = dynamic_cast<CVerbSet*>(pViewData->GetVerbSet()); sc = ScCheckPointers(pVerbSet, E_UNEXPECTED); if (sc) return sc.ToHr();
MMC_CONSOLE_VERB defaultVerb = MMC_VERB_NONE; pVerbSet->GetDefaultVerb(&defaultVerb); if (defaultVerb == MMC_VERB_OPEN) { return S_FALSE; } else if (defaultVerb == MMC_VERB_PROPERTIES) { OnProperties(pNode, bScopePaneSelected, lvData); } }
return S_OK; }
HRESULT CNodeCallback::OnContextMenu(CNode* pNode, LONG_PTR arg, LPARAM param) { DECLARE_SC(sc, TEXT("CNodeCallback::OnContextMenu"));
ASSERT(param != NULL); CContextMenuInfo& contextInfo = *reinterpret_cast<CContextMenuInfo*>(param);
BOOL b = static_cast<BOOL>(arg);
if ((pNode != NULL) && !pNode->IsInitialized()) { sc = pNode->InitComponents(); if(sc) return sc.ToHr(); }
// Create a CContextMenu and initialize it.
CContextMenu * pContextMenu = NULL; ContextMenuPtr spContextMenu;
sc = CContextMenu::ScCreateInstance(&spContextMenu, &pContextMenu); if(sc) return sc.ToHr();
sc = ScCheckPointers(pContextMenu, spContextMenu.GetInterfacePtr(), E_UNEXPECTED); if(sc) return sc.ToHr();
sc = pContextMenu->ScInitialize(pNode, this, m_pCScopeTree, contextInfo); if(sc) return sc.ToHr();
sc = pContextMenu->Display(b); return sc.ToHr(); }
/*+-------------------------------------------------------------------------*
* * CNodeCallback::CreateContextMenu * * PURPOSE: Creates a context menu for the specified node. * * PARAMETERS: * PNODE pNode : * PPCONTEXTMENU ppContextMenu : [OUT]: The context menu structure. * * RETURNS: * HRESULT * *+-------------------------------------------------------------------------*/ HRESULT CNodeCallback::CreateContextMenu( PNODE pNode, HNODE hNode, PPCONTEXTMENU ppContextMenu) { DECLARE_SC(sc, TEXT("CNodeCallback::CreateContextMenu"));
sc = ScCheckPointers(pNode, ppContextMenu); if(sc) return sc.ToHr();
sc = CContextMenu::ScCreateContextMenu(pNode, hNode, ppContextMenu, this, m_pCScopeTree);
return sc.ToHr(); }
/*+-------------------------------------------------------------------------*
* * CNodeCallback::CreateSelectionContextMenu * * PURPOSE: Creates a context menu for the current selection in the result pane. * * PARAMETERS: * HNODE hNodeScope : * CContextMenuInfo * pContextInfo : * PPCONTEXTMENU ppContextMenu : * * RETURNS: * HRESULT * *+-------------------------------------------------------------------------*/ HRESULT CNodeCallback::CreateSelectionContextMenu( HNODE hNodeScope, CContextMenuInfo *pContextInfo, PPCONTEXTMENU ppContextMenu) { DECLARE_SC(sc, TEXT("CNodeCallback::CreateSelectionContextMenu"));
sc = CContextMenu::ScCreateSelectionContextMenu(hNodeScope, pContextInfo, ppContextMenu, this, m_pCScopeTree); return sc.ToHr(); }
/*+-------------------------------------------------------------------------*
* * CNodeCallback::GetProperty * * PURPOSE: Returns the specified property for the specified list item by calling * IDataObject::GetData using a STREAM medium on the node's data * object. * * PARAMETERS: * HNODE hNodeScope : The parent scope item * BOOL bForScopeItem : TRUE if the list item is a scope item in the list. * LPARAM resultItemParam : The LPARAM of the result item * BSTR bstrPropertyName : The name of the clipboard format. * PBSTR pbstrPropertyValue : * * RETURNS: * HRESULT * *+-------------------------------------------------------------------------*/ HRESULT CNodeCallback::GetProperty(HNODE hNodeScope, BOOL bForScopeItem, LPARAM resultItemParam, BSTR bstrPropertyName, PBSTR pbstrPropertyValue) { DECLARE_SC(sc, TEXT("CNodeCallback::GetProperty"));
// check parameters
sc = ScCheckPointers(bstrPropertyName); if(sc) return sc.ToHr();
// initialize out parameter
*pbstrPropertyValue = NULL;
// convert the HNODE to a CNode *
CNode *pNodeScope = CNode::FromHandle(hNodeScope);
sc = ScCheckPointers(pNodeScope); if(sc) return sc.ToHr();
// create a data object for the specified item
IDataObjectPtr spDataObject;
bool bScopeItem; sc = pNodeScope->ScGetDataObject(bForScopeItem, resultItemParam, bScopeItem, &spDataObject); if(sc) return sc.ToHr();
// try to get the propeorty from the INodeProperties interface
sc = pNodeScope->ScGetPropertyFromINodeProperties(spDataObject, bForScopeItem, resultItemParam, bstrPropertyName, pbstrPropertyValue); if( (!sc.IsError()) && (sc.ToHr() != S_FALSE) ) // got it, exit
return sc.ToHr();
// didn't find it, continue
sc.Clear();
// get the property from data object
sc = ScGetProperty(spDataObject, bstrPropertyName, pbstrPropertyValue); if(sc) return sc.ToHr();
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CNodeCallback::ScGetProperty * * PURPOSE: Helper (static) method to access snapin property * * PARAMETERS: * IDataObject *pDataObject - [in] data object * BSTR bstrPropertyName - [in] property (clipboard fromat) name * PBSTR pbstrPropertyValue - [out] resulting value * * RETURNS: * SC - result code. NOTE: no error is returned if the snapin does not * support the specified clipboard format. In this case *pbstrPropertyValue * is set to NULL. * \***************************************************************************/ SC CNodeCallback::ScGetProperty(IDataObject *pDataObject, BSTR bstrPropertyName, PBSTR pbstrPropertyValue) { DECLARE_SC(sc, TEXT("ScGetProperty"));
// check parameters
sc = ScCheckPointers(pDataObject, bstrPropertyName, pbstrPropertyValue); if(sc) return sc;
// initialize out parameter
*pbstrPropertyValue = NULL;
// create a stream for the data object to use
IStreamPtr pStm; sc = CreateStreamOnHGlobal(NULL, true, &pStm); if(sc) return sc;
ULARGE_INTEGER zeroSize = {0, 0}; sc = pStm->SetSize(zeroSize); if(sc) return sc;
USES_CONVERSION; CLIPFORMAT cfClipFormat = (CLIPFORMAT)RegisterClipboardFormat(OLE2T(bstrPropertyName));
// First call ExtractString which uses GetData
CStr strOutput; sc = ExtractString (pDataObject, cfClipFormat, strOutput); if(!sc.IsError()) { *pbstrPropertyValue = ::SysAllocStringLen(T2COLE(strOutput), strOutput.GetLength()/*prevents the terminating zero from being added.*/); // allocate the string and return
return sc; }
// That didn't work, so try using GetDataHere.
FORMATETC fmt = {cfClipFormat, NULL, DVASPECT_CONTENT, -1, TYMED_ISTREAM}; STGMEDIUM stgm = {TYMED_ISTREAM, NULL, NULL}; stgm.pstm = pStm;
sc = pDataObject->GetDataHere(&fmt, &stgm); if(sc) { // ignore errors and return a blank string
sc.Clear(); return sc; }
STATSTG stagStg; ZeroMemory(&stagStg, sizeof(stagStg));
sc = pStm->Stat(&stagStg, STATFLAG_NONAME); // do not need the name in the statistics.
if(sc) return sc;
if(stagStg.cbSize.HighPart != 0) return sc = E_UNEXPECTED;
// go back to the beginning of the stream
LARGE_INTEGER dlibMove = {0, 0}; sc = pStm->Seek(dlibMove, STREAM_SEEK_SET, NULL); if(sc) return sc;
BSTR bstrValue = ::SysAllocStringLen(NULL, stagStg.cbSize.LowPart / sizeof(OLECHAR)); // one character is automatically added
if(!bstrValue) return sc = E_OUTOFMEMORY;
ULONG cbRead = 0; sc = pStm->Read(bstrValue, stagStg.cbSize.LowPart, &cbRead); if(sc) return sc;
// make sure that the count of characters is what was expected
if(cbRead != stagStg.cbSize.LowPart) { ::SysFreeString(bstrValue); return sc = E_UNEXPECTED; }
// set the output parameter
*pbstrPropertyValue = bstrValue;
return sc; }
/*+-------------------------------------------------------------------------*
* * CNodeCallback::GetNodetypeForListItem * * PURPOSE: Returns the node type for a list item. * * PARAMETERS: * HNODE hNodeScope : * BOOL bForScopeItem : * LPARAM resultItemParam : * PBSTR pbstrNodetype : * * RETURNS: * HRESULT * *+-------------------------------------------------------------------------*/ HRESULT CNodeCallback::GetNodetypeForListItem(HNODE hNodeScope, BOOL bForScopeItem, LPARAM resultItemParam, PBSTR pbstrNodetype) { DECLARE_SC(sc, TEXT("CNodeCallback::GetNodetypeForListItem"));
// check parameters
sc = ScCheckPointers(pbstrNodetype); if(sc) return sc.ToHr();
// initialize out parameter
*pbstrNodetype = NULL;
// convert the HNODE to a CNode *
CNode *pNodeScope = CNode::FromHandle(hNodeScope);
sc = ScCheckPointers(pNodeScope); if(sc) return sc.ToHr();
IDataObjectPtr spDataObject;
bool bScopeItem; sc = pNodeScope->ScGetDataObject(bForScopeItem, resultItemParam, bScopeItem, &spDataObject); if(sc) return sc.ToHr();
// at this point we should have a valid data object
sc = ScCheckPointers((LPDATAOBJECT)spDataObject); if(sc) return sc.ToHr();
sc = ScGetNodetype(spDataObject, pbstrNodetype); return sc.ToHr(); }
/*+-------------------------------------------------------------------------*
* * CNodeCallback::ScGetNodetype * * PURPOSE: Static function - returns the nodetype of a data object as a string. * * PARAMETERS: * IDataObject * pDataObject : * PBSTR pbstrNodetype : * * RETURNS: * SC * *+-------------------------------------------------------------------------*/ SC CNodeCallback::ScGetNodetype(IDataObject *pDataObject, PBSTR pbstrNodetype) { DECLARE_SC(sc, TEXT("CNodeCallback::ScGetNodetype"));
sc = ScCheckPointers(pDataObject, pbstrNodetype); if(sc) return sc;
// init out parameter
*pbstrNodetype = NULL;
GUID guidNodetype = GUID_NULL;
sc = ExtractObjectTypeGUID(pDataObject, &guidNodetype); if(sc) return sc;
OLECHAR szSnapInGUID[40]; int iRet = StringFromGUID2(guidNodetype, szSnapInGUID, countof(szSnapInGUID));
if(0 == iRet) return (sc = E_UNEXPECTED);
// allocate the string, with the correct length.
*pbstrNodetype = ::SysAllocString(szSnapInGUID); if(!*pbstrNodetype) return (sc = E_OUTOFMEMORY);
return sc; }
HRESULT CNodeCallback::OnSnapInHelp(CNode* pNode, BOOL bScope, MMC_COOKIE cookie) { if (bScope == FALSE && pNode->GetViewData()->IsVirtualList() == FALSE) { ASSERT(cookie != NULL); CResultItem* pri = CResultItem::FromHandle(cookie);
if ((pri != NULL) && pri->IsScopeItem()) { pNode = CNode::FromResultItem(pri); ASSERT(pNode != NULL); } }
CComponent* pCC = pNode->GetPrimaryComponent(); ASSERT(pCC != NULL);
HRESULT hr = pCC->Notify(NULL, MMCN_SNAPINHELP, 0, 0); CHECK_HRESULT(hr);
return hr; }
HRESULT CNodeCallback::OnContextHelp(CNode* pNode, BOOL bScope, MMC_COOKIE cookie) { ASSERT(pNode != NULL);
if (bScope == FALSE && pNode->GetViewData()->IsVirtualList() == FALSE) { ASSERT(cookie != NULL); if(cookie == NULL || IS_SPECIAL_COOKIE(cookie)) return E_UNEXPECTED;
CResultItem* pri = CResultItem::FromHandle(cookie); if (pri == NULL) return (E_UNEXPECTED);
cookie = pri->GetSnapinData();
bScope = pri->IsScopeItem(); if (bScope == TRUE) { pNode = CNode::FromResultItem(pri); ASSERT(pNode != NULL); } }
if (bScope == TRUE) { IDataObjectPtr spdtobj; HRESULT hr = pNode->GetMTNode()->QueryDataObject(CCT_SCOPE, &spdtobj); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return hr;
CComponent* pCC = pNode->GetPrimaryComponent(); if ( pCC == NULL ) return E_UNEXPECTED;
hr = pCC->Notify(spdtobj, MMCN_CONTEXTHELP, 0, 0); CHECK_HRESULT(hr); return hr; } else { CComponent* pCC = pNode->GetPrimaryComponent(); ASSERT(pCC != NULL); if ( pCC == NULL ) return E_UNEXPECTED;
IDataObjectPtr spdtobj; HRESULT hr = pCC->QueryDataObject(cookie, CCT_RESULT, &spdtobj); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return hr;
hr = pCC->Notify(spdtobj, MMCN_CONTEXTHELP, 0, 0); CHECK_HRESULT(hr); return hr; } }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::GetSnapinName
//
// Synopsis: Given the node get the snapin name
//
// Arguments: [hNode] - [in]
// [ppszName] - [out] ret val, caller should free using CoTaskMemFree
// [bValidName] - [out], is the name valid or not
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
HRESULT CNodeCallback::GetSnapinName (/*[in]*/HNODE hNode, /*[out]*/LPOLESTR* ppszName, /*[out]*/ bool& bValidName) { DECLARE_SC(sc, _T("CNodeCallback::GetSnapinName")); sc = ScCheckPointers( (void*) hNode, ppszName); if (sc) return sc.ToHr();
bValidName = false;
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode, E_UNEXPECTED); if (sc) return sc.ToHr();
*ppszName = NULL;
CSnapIn* pSnapIn = pNode->GetPrimarySnapIn(); sc = ScCheckPointers (pSnapIn, E_UNEXPECTED); if (sc) return (sc.ToHr());
WTL::CString strName; sc = pSnapIn->ScGetSnapInName(strName); if (sc) return (sc.ToHr());
if (strName.IsEmpty()) return sc.ToHr();
USES_CONVERSION; *ppszName = CoTaskDupString (T2COLE (strName)); if (*ppszName == NULL) return ((sc = E_OUTOFMEMORY).ToHr());
bValidName = true;
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: OnColumnClicked
//
// Synopsis: Ask snapin if it wants to sort and do so.
//
// Arguments: [pNode] - CNode* owner of list view.
// [nCol] - column that is clicked (to sort on this column).
//
// Returns: HRESULT
//
// History: 07-27-1999 AnandhaG renamed OnSort to OnColumnClicked
//--------------------------------------------------------------------
HRESULT CNodeCallback::OnColumnClicked(CNode* pNode, LONG_PTR nCol) { ASSERT(pNode != NULL);
pNode->OnColumnClicked(nCol); return S_OK; }
HRESULT CNodeCallback::OnPrint(CNode* pNode, BOOL bScopePane, LPARAM lvData) { DECLARE_SC(sc, TEXT("CNodeCallback::OnPrint")); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
if ((!bScopePane) && (LVDATA_MULTISELECT == lvData) ) { CViewData *pViewData = pNode->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return sc.ToHr();
CMultiSelection* pMultiSel = pViewData->GetMultiSelection(); sc = ScCheckPointers(pMultiSel, E_UNEXPECTED); if (sc) return sc.ToHr();
sc = pMultiSel->ScVerbInvoked(MMC_VERB_PRINT); if (sc) return sc.ToHr();
return sc.ToHr(); }
IDataObjectPtr spdtobj; IDataObject *pdtobj = NULL;
bool bScopeItem; sc = pNode->ScGetDataObject(bScopePane, lvData, bScopeItem, &pdtobj); if (sc) return sc.ToHr();
if (! IS_SPECIAL_DATAOBJECT(pdtobj)) spdtobj = pdtobj;
CComponent *pComponent = pNode->GetPrimaryComponent(); sc = ScCheckPointers(pComponent, pdtobj, E_UNEXPECTED); if (sc) return sc.ToHr();
sc = pComponent->Notify(pdtobj, MMCN_PRINT, 0, 0); if (sc) sc.TraceAndClear();
return sc.ToHr(); }
HRESULT CNodeCallback::OnEditTaskpad(CNode *pNode) { ASSERT(pNode);
ITaskCallbackPtr spTaskCallback = pNode->GetViewData()->m_spTaskCallback;
ASSERT(spTaskCallback.GetInterfacePtr());
return spTaskCallback->OnModifyTaskpad(); }
HRESULT CNodeCallback::OnDeleteTaskpad(CNode *pNode) { DECLARE_SC(sc, TEXT("CNodeCallback::OnDeleteTaskpad"));
ASSERT(pNode); sc = ScCheckPointers( pNode ); if ( sc ) return sc.ToHr();
ITaskCallbackPtr spTaskCallback = pNode->GetViewData()->m_spTaskCallback;
ASSERT(spTaskCallback.GetInterfacePtr());
// make the node dirty
CMTNode* pMTNode = pNode->GetMTNode(); sc = ScCheckPointers( pMTNode, E_UNEXPECTED ); if(sc) return sc.ToHr();
pMTNode->SetDirty();
return spTaskCallback->OnDeleteTaskpad(); }
/* CNodeCallback::OnNewTaskpadFromHere
* * PURPOSE: Displays property pages for a new taskpad * * PARAMETERS: * CNode* pNode: The node that the taskpad should target to. * * RETURNS: * HRESULT */ HRESULT CNodeCallback::OnNewTaskpadFromHere(CNode* pNode) { DECLARE_SC(sc, TEXT("CNodeCallback::OnNewTaskpadFromHere")); sc = ScCheckPointers(pNode, E_UNEXPECTED); if (sc) return sc.ToHr();
CConsoleTaskpad taskpad (pNode);
CTaskpadWizard dlg(pNode, taskpad, TRUE /*fNew*/, 0, FALSE, pNode->GetViewData());
bool fStartTaskWizard = true; sc = dlg.Show(pNode->GetViewData()->GetMainFrame() /*hWndParent*/, &fStartTaskWizard);
if (sc != S_OK) return sc.ToHr();
sc = ScCheckPointers(m_pCScopeTree, E_UNEXPECTED); if (sc) return sc.ToHr();
m_pCScopeTree->InsertConsoleTaskpad (&taskpad, pNode, fStartTaskWizard);
// modify the view settings for this node to ensure that the taskpad is shown after the reselect.
sc = pNode->ScSetTaskpadID(taskpad.GetID(), /*bSetViewSettingDirty*/ true); if (sc) return sc.ToHr();
m_pCScopeTree->UpdateAllViews(VIEW_RESELECT, 0);
return sc.ToHr(); }
HRESULT CNodeCallback::OnRefresh(CNode* pNode, BOOL bScopePaneSelected, LPARAM lvData) { DECLARE_SC(sc, TEXT("CNodeCallback::OnRefresh"));
BOOL bScopeItemSelected; CNode *pSelectedNode = NULL; MMC_COOKIE cookie = -1;
sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lvData, &pSelectedNode, bScopeItemSelected, cookie); if (sc) return sc.ToHr();
sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED); if (sc) return sc.ToHr();
// If result-pane cookie should be valid.
ASSERT( (bScopeItemSelected) || cookie != LVDATA_ERROR); if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) ) return E_FAIL;
// Before refreshing this node, if the user has made
// changes to list view persist it.
CViewData* pVD = pSelectedNode->GetViewData(); ASSERT(pVD != NULL);
if (bScopeItemSelected) { ASSERT(pNode != NULL); IDataObjectPtr spdtobj; HRESULT hr = pSelectedNode->GetMTNode()->QueryDataObject(CCT_SCOPE, &spdtobj); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return hr;
CMTNode* pMTNode = pSelectedNode->GetMTNode(); ASSERT(pMTNode != NULL);
LPARAM lScopeItem = CMTNode::ToScopeItem(pMTNode);
// Send notify to primary snap-in
pMTNode->AddRef(); pSelectedNode->GetPrimaryComponent()->Notify(spdtobj, MMCN_REFRESH, lScopeItem, 0); if (pMTNode->Release() == 0) return S_OK;
// If node has been expanded, then also send notify to all namespace
// extensions for this node
if (pMTNode->WasExpandedAtLeastOnce()) { do // dummy loop
{ // Get the node-type of this node
GUID guidNodeType; HRESULT hr = pMTNode->GetNodeType(&guidNodeType); CHECK_HRESULT(hr); if (FAILED(hr)) break;
// Get list of dynmaic extensions
LPCLSID pDynExtCLSID; int cDynExt = pMTNode->GetDynExtCLSID(&pDynExtCLSID);
// Create and init namespace extension iterator
CExtensionsIterator it; sc = it.ScInitialize(pMTNode->GetPrimarySnapIn(), guidNodeType, g_szNameSpace, pDynExtCLSID, cDynExt); if (sc) break;
CSnapInNode* pSINode = pSelectedNode->GetStaticParent(); ASSERT(pSINode != NULL);
// Send refresh to each extension's component
for (; it.IsEnd() == FALSE; it.Advance()) { CComponent* pCC = pSINode->GetComponent(it.GetCLSID()); if (pCC == NULL) continue;
HRESULT hr = pCC->Notify(spdtobj, MMCN_REFRESH, lScopeItem, 0); CHECK_HRESULT(hr); } } while (FALSE); } } else { CComponent* pCC = pSelectedNode->GetPrimaryComponent(); ASSERT(pCC != NULL);
if (IS_SPECIAL_LVDATA(lvData)) { LPDATAOBJECT pdobj = (lvData == LVDATA_CUSTOMOCX) ? DOBJ_CUSTOMOCX : DOBJ_CUSTOMWEB;
HRESULT hr = pCC->Notify(pdobj, MMCN_REFRESH, 0, 0); CHECK_HRESULT(hr); } else { IDataObjectPtr spdtobj; HRESULT hr = pCC->QueryDataObject(cookie, CCT_RESULT, &spdtobj); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return hr; pCC->Notify(spdtobj, MMCN_REFRESH, 0, 0); } }
// Set the view correctly using the persisted data.
do { if (NULL == pVD) break;
// After the refresh the snapin could have deleted the pSelectedNode or
// could have moved the selection. While setting view-data we
// just need the currently selected node (the owner of the view
// which is not affected by temp selection) and set the view.
CNode* pSelNode = pVD->GetSelectedNode(); if (NULL == pSelNode) break;
sc = pSelNode->ScRestoreSortFromPersistedData(); if (sc) return sc.ToHr(); } while ( FALSE );
return S_OK; }
UINT GetRelation(CMTNode* pMTNodeSrc, CMTNode* pMTNodeDest) { if (pMTNodeSrc == pMTNodeDest) return 1;
for(pMTNodeDest = pMTNodeDest->Parent(); pMTNodeDest; pMTNodeDest = pMTNodeDest->Parent()) { if (pMTNodeSrc == pMTNodeDest) return 2; }
return 0; }
STDMETHODIMP CNodeCallback::UpdatePasteButton(HNODE hNode, BOOL bScope, LPARAM lvData) { DECLARE_SC(sc, TEXT("CNodeCallback::UpdatePasteButton")); sc = ScCheckPointers(hNode); if (sc) return sc.ToHr();
bool bPasteAllowed = false; // Update only when item is being selected.
sc = QueryPasteFromClipboard(hNode, bScope, lvData, bPasteAllowed); if (sc) return sc.ToHr();
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode, E_UNEXPECTED); if (sc) return sc.ToHr();
CViewData *pViewData = pNode->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return sc.ToHr();
sc = pViewData->ScUpdateStdbarVerb (MMC_VERB_PASTE, TBSTATE_ENABLED, bPasteAllowed); if (sc) return sc.ToHr();
return sc.ToHr(); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::ScInitializeTempVerbSetForMultiSel
//
// Synopsis: For given node, initialize the tempverbset object
// provided. For this create a multi-selection object
// initialize it (multiselection object finds out what is
// selected in resultpane and sends MMCN_SELECT to appropriate
// snapins) and compute the verb states for the temp-verbset object.
//
// Arguments: [pNode] - [in] owner of resultpane.
// [tempverb] - [in] Temp verb set object which is initialzied.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CNodeCallback::ScInitializeTempVerbSetForMultiSel(CNode *pNode, CTemporaryVerbSet& tempVerb) { DECLARE_SC(sc, TEXT("CNodeCallback::ScInitializeTempVerbSetForMultiSel")); sc = ScCheckPointers(pNode); if (sc) return sc;
ASSERT(pNode->IsInitialized() == TRUE);
// 1. Create a multi-selection object.
CMultiSelection* pMultiSelection = new CMultiSelection(pNode); sc = ScCheckPointers(pMultiSelection, E_OUTOFMEMORY); if (sc) return sc;
IDataObjectPtr spdobj;
// 2. Initialize it, (it finds out what is selected in resultpane
// gets dataobjects from appropriate snapins and sends snapins
// MMCN_SELECT notifications).
sc = pMultiSelection->Init(); if (sc) goto Cleanup;
pMultiSelection->SetScopeTree(m_pCScopeTree);
sc = pMultiSelection->GetMultiSelDataObject(&spdobj); if (sc) goto Cleanup;
if (spdobj == NULL) goto Cleanup;
// 3. Init the verbset object.
sc = tempVerb.ScInitializeForMultiSelection(pNode, /*bSelect*/ true); if (sc) goto Cleanup;
tempVerb.SetMultiSelection(pMultiSelection);
// 4. Compute the verbs that are set by snapin along with given context.
sc = tempVerb.ScComputeVerbStates();
if (sc) goto Cleanup;
Cleanup: pMultiSelection->Release(); return sc; }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::_ScGetVerbState
//
// Synopsis: For given item (dataobject), the owner node see if given
// verb is set. A temp-verb-set object is created for this purpose.
//
// Arguments: [pNode] - [in]
// [verb] - [in]
// [pDOSel] - [in] Dataobject of the item whose verb we are interested.
// [bScopePane] - [in]
// [lResultCookie] - [in]
// [bMultiSelect] - [in]
// [bIsVerbSet] - [out] verb is set or not.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CNodeCallback::_ScGetVerbState( CNode* pNode, MMC_CONSOLE_VERB verb, IDataObject* pDOSel, BOOL bScopePane, LPARAM lResultCookie, BOOL bMultiSelect, BOOL& bIsVerbSet) { DECLARE_SC(sc, TEXT("CNodeCallback::_GetVerbState")); bIsVerbSet = FALSE;
sc = ScCheckPointers(pNode, pDOSel); if (sc) return sc;
CComObject<CTemporaryVerbSet> stdVerbTemp;
if (bMultiSelect) sc = ScInitializeTempVerbSetForMultiSel(pNode, stdVerbTemp); else sc = stdVerbTemp.ScInitialize(pDOSel, pNode, bScopePane, lResultCookie);
if (sc) return sc;
stdVerbTemp.GetVerbState(verb, ENABLED, &bIsVerbSet);
return sc; }
HRESULT CNodeCallback::OnCutCopy( CNode* pNode, BOOL bScope, LPARAM lvData, BOOL bCut) { DECLARE_SC(sc, TEXT("CNodeCallback::OnCutCopy"));
// parameter check
sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
// get the object
IMMCClipboardDataObjectPtr spClipBoardDataObject; bool bContainsItems = false; sc = CMMCClipBoardDataObject::ScCreate( (bCut ? ACTION_CUT : ACTION_COPY), pNode, bScope, (lvData == LVDATA_MULTISELECT)/*bMultiSel*/, lvData, &spClipBoardDataObject , bContainsItems); if (sc) return sc.ToHr();
// If snapin has cut or copy then dataobject should have been added.
if (! bContainsItems) return (sc = E_UNEXPECTED).ToHr();
// QI for IDataObject
IDataObjectPtr spDataObject = spClipBoardDataObject; sc = ScCheckPointers( spDataObject, E_UNEXPECTED ); if (sc) return sc.ToHr();
// Put the dataobject on the clipboard.
sc = OleSetClipboard( spDataObject ); if (sc) return sc.ToHr();
return sc.ToHr(); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::OnProperties
//
// Synopsis: Bring property sheet for given item.
//
// Arguments: CNode* - The node that owns result pane.
// BOOL - If true bring propsheet of above node else use LVData.
// LPARAM - If bScope = FALSE then use this data to get the LVData
// and bring its property sheet.
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
HRESULT CNodeCallback::OnProperties(CNode* pNode, BOOL bScopePaneSelected, LPARAM lvData) { DECLARE_SC(sc, _T("CNodeCallback::OnProperties")); sc = ScCheckPointers(pNode); if (sc) return (sc.ToHr());
// NOTE: All the code below should be moved into the CNode class
BOOL bScopeItemSelected = FALSE; CNode *pSelectedNode = NULL; MMC_COOKIE cookie = -1;
sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lvData, &pSelectedNode, bScopeItemSelected, cookie); if (sc) return sc.ToHr();
sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED); if (sc) return sc.ToHr();
// If result-pane cookie should be valid.
if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) ) return (sc = E_FAIL).ToHr();
if (bScopeItemSelected) { sc = ScDisplaySnapinNodePropertySheet(pSelectedNode); if(sc) return sc.ToHr(); } else { CViewData* pViewData = pSelectedNode->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return sc.ToHr();
if (pViewData->HasList()) { if (cookie == LVDATA_MULTISELECT) { sc = ScDisplayMultiSelPropertySheet(pSelectedNode); if(sc) return sc.ToHr(); } else { sc = ScDisplaySnapinLeafPropertySheet(pSelectedNode, cookie); if(sc) return sc.ToHr(); } } else { LPDATAOBJECT pdobj = (pViewData->HasOCX() ) ? DOBJ_CUSTOMOCX : DOBJ_CUSTOMWEB; CComponent* pCC = pSelectedNode->GetPrimaryComponent(); sc = ScCheckPointers(pCC, E_UNEXPECTED); if (sc) return sc.ToHr();
pCC->Notify(pdobj, MMCN_BTN_CLICK, 0, MMC_VERB_PROPERTIES); } }
return S_OK; }
HRESULT CNodeCallback::OnFilterChange(CNode* pNode, LONG_PTR nCode, LPARAM nCol) { IF_NULL_RETURN_INVALIDARG(pNode);
CComponent* pCC = pNode->GetPrimaryComponent(); ASSERT(pCC != NULL);
if (pCC != NULL) { HRESULT hr = pCC->Notify(DOBJ_NULL, MMCN_FILTER_CHANGE, nCode, nCol); return hr; }
return E_FAIL; }
HRESULT CNodeCallback::OnFilterBtnClick(CNode* pNode, LONG_PTR nCol, LPRECT pRect) { IF_NULL_RETURN_INVALIDARG2(pNode, pRect);
CComponent* pCC = pNode->GetPrimaryComponent(); ASSERT(pCC != NULL);
if (pCC != NULL) { HRESULT hr = pCC->Notify(DOBJ_NULL, MMCN_FILTERBTN_CLICK, nCol, (LPARAM)pRect); return hr; }
return E_FAIL; }
STDMETHODIMP CNodeCallback::IsExpandable(HNODE hNode) { MMC_TRY
// convert to real type
CNode* pNode = CNode::FromHandle(hNode); ASSERT(pNode != NULL);
CMTNode* pMTNode = pNode->GetMTNode(); ASSERT(pMTNode != NULL);
return pMTNode->IsExpandable();
MMC_CATCH }
HRESULT _GetConsoleVerb(CNode* pNode, LPCONSOLEVERB* ppConsoleVerb) { IF_NULL_RETURN_INVALIDARG2(pNode, ppConsoleVerb);
HRESULT hr = S_FALSE;
CComponent* pCC = pNode->GetPrimaryComponent(); ASSERT(pCC != NULL); if (pCC == NULL) return E_FAIL;
IFramePrivate* pIFP = pCC->GetIFramePrivate(); ASSERT(pIFP != NULL); if (pIFP == NULL) return E_FAIL;
IConsoleVerbPtr spConsoleVerb; hr = pIFP->QueryConsoleVerb(&spConsoleVerb);
if (SUCCEEDED(hr)) { *ppConsoleVerb = spConsoleVerb.Detach(); hr = S_OK; }
return hr; }
STDMETHODIMP CNodeCallback::GetConsoleVerb(HNODE hNode, LPCONSOLEVERB* ppConsoleVerb) { MMC_TRY
ASSERT(ppConsoleVerb != NULL);
return _GetConsoleVerb(CNode::FromHandle(hNode), ppConsoleVerb);
MMC_CATCH }
// lCookie valid if both bScope & bMultiSel are FALSE.
// lCookie is the index\lParam for virtual\regular LV
STDMETHODIMP CNodeCallback::GetDragDropDataObject( HNODE hNode, BOOL bScope, BOOL bMultiSel, LONG_PTR lvData, LPDATAOBJECT* ppDataObject, bool& bCopyAllowed, bool& bMoveAllowed) { DECLARE_SC(sc, TEXT("CNodeCallback::GetDragDropDataObject"));
// init allowed op's to false
bCopyAllowed = false; bMoveAllowed = false;
// parameter check
sc = ScCheckPointers(ppDataObject); if (sc) return sc.ToHr();
// init out parameter;
*ppDataObject = NULL;
// get the object
IMMCClipboardDataObjectPtr spClipBoardDataObject; bool bContainsItems = false; sc = CMMCClipBoardDataObject::ScCreate( ACTION_DRAG, CNode::FromHandle(hNode), bScope, bMultiSel, lvData, &spClipBoardDataObject, bContainsItems ); if (sc) return sc.ToHr();
// We asked for drag&drop dataobject. If snapin does not support cut/copy then
// the dataobjects will not be added which is not an error.
if (! bContainsItems) return sc.ToHr();
// QI for IDataObject
IDataObjectPtr spDataObject = spClipBoardDataObject; sc = ScCheckPointers( spDataObject, E_UNEXPECTED ); if (sc) return sc.ToHr();
// inspect data objects included to see what operations are allowed
// (note: (spDataObject==valid) -> (spClipBoardDataObject==valid) )
DWORD dwCount = 0; sc = spClipBoardDataObject->GetCount( &dwCount ); for ( DWORD dwIdx = 0; dwIdx < dwCount; dwIdx ++ ) { IDataObjectPtr spSnapinDO; DWORD dwOptions = 0; sc = spClipBoardDataObject->GetDataObject( dwIdx, &spSnapinDO, &dwOptions ); if (sc) return sc.ToHr();
// claculate allowed operations
bCopyAllowed = bCopyAllowed || ( dwOptions & COPY_ALLOWED ); bMoveAllowed = bMoveAllowed || ( dwOptions & MOVE_ALLOWED );
// enabling is inclusive, so very few tests are required
if ( bCopyAllowed && bMoveAllowed ) break; }
// return data object
*ppDataObject = spDataObject.Detach();
return sc.ToHr(); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::ScExtractLVData
//
// Synopsis: If listview item is selected, see if it is a scope item
// in non-virtual listview (virtual listviews cannot have
// scope items in them). If so extract that scope item else
// the cookie of result item.
//
// Arguments: [pNode] - [in, out] if scope item is selected in resultpane, then
// will contain this scope item on return.
// [bScope] - [in, out] Is scope item currently selected item (in scope or
// result pane).
// [lvData] - [in] LVDATA
// [cookie] - [in] lParam of result item.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CNodeCallback::ScExtractLVData(CNode* pNodeViewOwner, BOOL bScopePaneSelected, LONG_PTR lvData, CNode** ppSelectedNode, BOOL& bScopeItemSelected, MMC_COOKIE& cookie) { DECLARE_SC(sc, _T("CNodeCallback::ScExtractLVData")); sc = ScCheckPointers(pNodeViewOwner, ppSelectedNode); if (sc) return sc;
*ppSelectedNode = NULL; bScopeItemSelected = bScopePaneSelected; *ppSelectedNode = pNodeViewOwner;
if (bScopePaneSelected) { cookie = lvData; return sc; }
// Scope pane is not selected.
CViewData *pViewData = pNodeViewOwner->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return sc;
cookie = lvData;
if (IS_SPECIAL_LVDATA(lvData)) { if (lvData == LVDATA_BACKGROUND) bScopeItemSelected = TRUE; } else if (! pViewData->IsVirtualList()) { CResultItem* pri = CResultItem::FromHandle (lvData); sc = ScCheckPointers(pri, E_UNEXPECTED); if (sc) { cookie = LVDATA_ERROR; return sc; }
if (pri->IsScopeItem()) { bScopeItemSelected = TRUE; *ppSelectedNode = CNode::FromResultItem(pri); sc = ScCheckPointers(*ppSelectedNode, E_UNEXPECTED); if (sc) return sc;
cookie = -1; } else { cookie = pri->GetSnapinData(); }
ASSERT(!IS_SPECIAL_LVDATA(lvData) || !bScopeItemSelected); }
return (sc); }
STDMETHODIMP CNodeCallback::GetTaskEnumerator( HNODE hNode, LPCOLESTR pszTaskGroup, IEnumTASK** ppEnumTask) { IF_NULL_RETURN_INVALIDARG3(hNode, pszTaskGroup, ppEnumTask);
*ppEnumTask = NULL; // init
// convert to real type
CNode* pNode = CNode::FromHandle(hNode);
return pNode->GetTaskEnumerator(CComBSTR(pszTaskGroup), ppEnumTask);
}
STDMETHODIMP CNodeCallback::GetListPadInfo(HNODE hNode, IExtendTaskPad* pExtendTaskPad, LPCOLESTR szTaskGroup, MMC_ILISTPAD_INFO* pIListPadInfo) { IF_NULL_RETURN_INVALIDARG(hNode);
CNode* pNode = CNode::FromHandle(hNode); return pNode->GetListPadInfo(pExtendTaskPad, CComBSTR(szTaskGroup), pIListPadInfo); }
HRESULT CNodeCallback::OnGetPrimaryTask(CNode* pNode, LPARAM param) { IF_NULL_RETURN_INVALIDARG(pNode);
IExtendTaskPad** ppExtendTaskPad = reinterpret_cast<IExtendTaskPad**>(param); return pNode->OnGetPrimaryTask(ppExtendTaskPad); }
STDMETHODIMP CNodeCallback::UpdateWindowLayout(LONG_PTR lViewData, long lToolbarsDisplayed) { IF_NULL_RETURN_INVALIDARG(lViewData);
CViewData* pVD = reinterpret_cast<CViewData*>(lViewData); pVD->UpdateToolbars(lToolbarsDisplayed); return S_OK; }
HRESULT CNodeCallback::PreLoad(HNODE hNode) { DECLARE_SC(sc, TEXT("CNodeCallback::PreLoad"));
// parameter check
sc = ScCheckPointers( hNode ); if (sc) return sc.ToHr();
CNode* pNode = CNode::FromHandle (hNode); if (pNode->IsStaticNode() == FALSE || pNode->IsInitialized() == TRUE) return (sc = S_FALSE).ToHr();
// if the node is:
// 1. a snapin node;
// 2. marked as "PreLoad"; and,
// 3. not initialized yet.
// if all three, then send 'em a notify containing their HSCOPEITEM
CMTNode* pMTNode = pNode->GetMTNode(); sc = ScCheckPointers( pMTNode, E_FAIL ); if (sc) return sc.ToHr();
CMTSnapInNode* pMTSnapInNode = dynamic_cast<CMTSnapInNode*>(pMTNode); sc = ScCheckPointers( pMTSnapInNode, E_UNEXPECTED ); if (sc) return sc.ToHr();
if (!pMTSnapInNode->IsPreloadRequired()) return (sc = S_FALSE).ToHr();
if (pMTNode->IsInitialized() == FALSE) { sc = pMTSnapInNode->Init(); if (sc) return sc.ToHr(); }
//
// If the snap-in needs to be preloaded, the IComponent also needs
// to be init so that the sanpin can insert icons in the result
// pane if the parent node is selected in the scope pane.
//
ASSERT(pNode->IsInitialized() == FALSE); sc = _InitializeNode(pNode); if (sc) return sc.ToHr();
return sc.ToHr(); }
STDMETHODIMP CNodeCallback::SetTaskpad(HNODE hNodeSelected, GUID *pGuidTaskpad) { ASSERT(hNodeSelected != NULL); ASSERT(pGuidTaskpad != NULL);
CNode *pNode = CNode::FromHandle(hNodeSelected);
// See ScSetViewExtension for more info on parameters in the call.
HRESULT hr = pNode->ScSetViewExtension(pGuidTaskpad, /*bUseDefaultTaskPad*/ false, /*bSetViewSettingDirty*/ true).ToHr();
return hr; }
STDMETHODIMP CNodeCallback::OnCustomizeView (LONG_PTR lViewData) { ::OnCustomizeView ((CViewData*) lViewData); return (S_OK); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::SetViewSettings
//
// Synopsis: Modify the view settings data that is persisted.
//
// Arguments: [nViewID] - [in] the view id.
// [hbm] - [in] bookmark.
// [hvs] - [in] view-settings.
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::SetViewSettings(int nViewID, HBOOKMARK hbm, HVIEWSETTINGS hvs) { DECLARE_SC(sc, _T("CNodeCallback::SetViewSettings")); sc = ScCheckPointers( (void*)hbm, (void*) hvs); if (sc) return sc.ToHr();
CViewSettings *pViewSettings = reinterpret_cast<CViewSettings *>(hvs); CBookmark *pBookmark = reinterpret_cast<CBookmark*> (hbm); sc = CNode::ScSetFavoriteViewSettings(nViewID, *pBookmark, *pViewSettings); if (sc) return sc.ToHr();
return sc.ToHr(); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::ExecuteScopeItemVerb
//
// Synopsis: Invoke the given verb with given context. Also make sure
// the verb is enabled by snapin for this context.
//
// Arguments: [verb] - The verb to be invoked.
// [hNode] - The node for which above verb is invoked.
// [lpszNewName] - For "rename" represents new name.
//
// Returns: SC
//
//--------------------------------------------------------------------
HRESULT CNodeCallback::ExecuteScopeItemVerb (MMC_CONSOLE_VERB verb, HNODE hNode, LPOLESTR lpszNewName) { DECLARE_SC(sc, _T("CNodeCallback::ExecuteScopeItemVerb"));
CNode* pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if(sc) return sc.ToHr();
// Get data object for the item.
IDataObjectPtr spDataObject; sc = pNode->QueryDataObject(CCT_SCOPE, &spDataObject); if (sc) return (sc.ToHr());
BOOL bEnabled = FALSE; // see if the verb is enabled by the snapin.
sc = _ScGetVerbState( pNode, verb, spDataObject, /*bScopePane*/TRUE, /*lResultCookie = */ NULL, /*bMultiSel*/FALSE, bEnabled); if (sc) return sc.ToHr();
if (! bEnabled) // Verb not enabled.
return (sc = ScFromMMC(MMC_E_TheVerbNotEnabled)).ToHr();
switch(verb) { case MMC_VERB_PROPERTIES: sc = OnProperties(pNode, /*bScope*/ TRUE, /*LPARAM*/ NULL); if (sc) return sc.ToHr(); break;
case MMC_VERB_DELETE: sc = OnDelete(pNode, /*bScope*/ TRUE, /*LPARAM*/ NULL); if (sc) return sc.ToHr(); break;
case MMC_VERB_REFRESH: sc = OnRefresh(pNode, /*bScope*/ TRUE, /*LPARAM*/ NULL); if (sc) return sc.ToHr(); break;
case MMC_VERB_RENAME: { // To call Rename we must first initialize SELECTIONINFO.
SELECTIONINFO selInfo; ZeroMemory(&selInfo, sizeof(selInfo)); selInfo.m_bScope = TRUE; selInfo.m_eCmdID = MMC_VERB_RENAME;
sc = OnRename(pNode, &selInfo, lpszNewName); if (sc) return sc.ToHr(); } break;
case MMC_VERB_COPY: sc = OnCutCopy(pNode, /*bScope*/ TRUE, NULL, /*bCut*/ FALSE); if (sc) return sc.ToHr(); break;
default: sc = E_UNEXPECTED; break; }
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::ExecuteResultItemVerb
//
// Synopsis: Invoke the given verb with given context. Also make sure
// the verb is enabled by snapin for this context.
//
// Arguments: [verb] - The verb to be invoked.
// [hNode] - The node that owns result pane now.
// [lvData] - The list view selection context.
// [lpszNewName] - For "rename" represents new name else NULL.
//
// Returns: SC
//
//--------------------------------------------------------------------
HRESULT CNodeCallback::ExecuteResultItemVerb (MMC_CONSOLE_VERB verb, HNODE hNode, LPARAM lvData, LPOLESTR lpszNewName) { DECLARE_SC(sc, _T("CNodeCallback::ExecuteResultItemVerb")); CNode* pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode, E_UNEXPECTED); if (sc) return (sc.ToHr());
// We need to see if the given verb is enabled by the snapin. We need
// dataobject for given context for this. So get the context by calling
// ScExtractLVData().
BOOL bScopeItemSelected; CNode *pSelectedNode = NULL; MMC_COOKIE cookie = -1;
sc = CNodeCallback::ScExtractLVData(pNode, /*bScopePaneSelected*/ FALSE, lvData, &pSelectedNode, bScopeItemSelected, cookie); if (sc) return sc.ToHr();
sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED); if (sc) return sc.ToHr();
// Cookie should be valid for result pane.
if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) ) return (sc = E_FAIL).ToHr();
BOOL bMultiSelect = (LVDATA_MULTISELECT == lvData); if (bMultiSelect) cookie = MMC_MULTI_SELECT_COOKIE;
// Depending on whether this is scope item in result pane or result item
// ask ComponentData or Component the data object.
IDataObjectPtr spDataObject; if (bScopeItemSelected) { sc = pSelectedNode->QueryDataObject (CCT_SCOPE, &spDataObject); if (sc) return sc.ToHr(); } else { CComponent* pCC = pNode->GetPrimaryComponent(); sc = ScCheckPointers(pCC, E_UNEXPECTED); if (sc) return sc.ToHr();
sc = pCC->QueryDataObject(cookie, CCT_RESULT, &spDataObject); if (sc) return (sc.ToHr()); }
BOOL bEnabled = FALSE; // See if the verb is enabled for this selection.
sc = _ScGetVerbState( pSelectedNode , verb, spDataObject, /*bScopePaneSelected*/ FALSE, lvData, bMultiSelect, bEnabled); if (sc) return sc.ToHr();
if (! bEnabled) // Verb not enabled.
return (sc = ScFromMMC(MMC_E_TheVerbNotEnabled)).ToHr();
switch(verb) { case MMC_VERB_PROPERTIES: sc = OnProperties(pNode, /*bScope*/ FALSE, /*LPARAM*/ lvData); if (sc) return sc.ToHr(); break;
case MMC_VERB_DELETE: sc = OnDelete(pNode, /*bScope*/ FALSE, /*LPARAM*/ lvData); if (sc) return sc.ToHr(); break;
case MMC_VERB_REFRESH: sc = OnRefresh(pNode, /*bScope*/ FALSE, /*LPARAM*/ lvData); if (sc) return sc.ToHr(); break;
case MMC_VERB_RENAME: { // For Rename we should also call ScExtractLVData before calling OnRename.
// To call Rename we must first initialize SELECTIONINFO.
SELECTIONINFO selInfo; ZeroMemory(&selInfo, sizeof(selInfo)); selInfo.m_bScope = bScopeItemSelected; selInfo.m_lCookie = cookie; selInfo.m_eCmdID = MMC_VERB_RENAME;
sc = OnRename(pNode, &selInfo, lpszNewName); if (sc) return sc.ToHr(); } break;
case MMC_VERB_COPY: sc = OnCutCopy(pNode, /*bScope*/ FALSE, lvData, /*bCut*/ FALSE); if (sc) return sc.ToHr(); break;
default: sc = E_INVALIDARG; break; }
return (sc.ToHr()); }
/*+-------------------------------------------------------------------------*
* * FUNCTION: CNodeCallback::QueryCompDataDispatch * * PURPOSE: Get the disp interface for given scope node object from snapin. * * PARAMETERS: * PNODE - The Node object for which the disp interface is required. * PPDISPATCH [out] - Disp interface pointer returned by snapin. * * RETURNS: * HRESULT * *+-------------------------------------------------------------------------*/ STDMETHODIMP CNodeCallback::QueryCompDataDispatch(PNODE pNode, PPDISPATCH ppScopeNodeObject) { DECLARE_SC(sc, TEXT("CNodeCallback::QueryCompDataDispInterface")); sc = ScCheckPointers(m_pCScopeTree); if(sc) return sc.ToHr();
CMTNode *pMTNode = NULL; sc = m_pCScopeTree->ScGetNode(pNode, &pMTNode); if(sc) return sc.ToHr();
sc = ScCheckPointers(pMTNode, E_UNEXPECTED); if (sc) return sc.ToHr();
sc = pMTNode->ScQueryDispatch(CCT_SCOPE, ppScopeNodeObject); if (sc) return sc.ToHr();
return sc.ToHr(); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::QueryComponentDispatch
//
// Synopsis: Get the disp interface for given item in resultpane from snapin.
//
// Arguments:
// HNODE - The Scope Node which owns result pane.
// LVDATA - The LVDATA of selected item
// PPDISPATCH [out] - Disp interface pointer returned by snapin.
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
HRESULT CNodeCallback::QueryComponentDispatch (HNODE hNode, LPARAM lvData, PPDISPATCH SelectedObject) { DECLARE_SC(sc, _T("CNodeCallback::QueryComponentDispatch")); CNode* pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
BOOL bScopeItemSelected; CNode *pSelectedNode = NULL; MMC_COOKIE cookie = -1;
sc = CNodeCallback::ScExtractLVData(pNode, /*bScopePaneSelected*/ FALSE, lvData, &pSelectedNode, bScopeItemSelected, cookie); if (sc) return sc.ToHr();
/*
* In case of multiselection, set cookie to MMC_MULTI_SELECT_COOKIE * which snapins can understand. */ BOOL bMultiSelect = (LVDATA_MULTISELECT == lvData); if (bMultiSelect) { cookie = MMC_MULTI_SELECT_COOKIE; ASSERT(bScopeItemSelected == false); }
sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED); if (sc) return sc.ToHr();
// If result-pane cookie should be valid.
if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) ) return (sc = E_FAIL).ToHr();
// Scope item is selected in result pane.
if (bScopeItemSelected) { CMTNode* pMTNode = pSelectedNode->GetMTNode(); sc = ScCheckPointers(pMTNode, E_UNEXPECTED); if (sc) return sc.ToHr();
sc = pMTNode->ScQueryDispatch(CCT_SCOPE, SelectedObject); if (sc) return sc.ToHr(); } else { CComponent* pCC = pSelectedNode->GetPrimaryComponent(); sc = ScCheckPointers(pCC, E_UNEXPECTED); if (sc) return sc.ToHr();
sc = pCC->ScQueryDispatch(cookie, CCT_RESULT, SelectedObject); if (sc) return sc.ToHr(); }
return (sc.ToHr()); }
/***************************************************************************\
* * METHOD: CNodeCallback::ShowColumn * * PURPOSE: Shows/hides the column. Implements both UI part as snapin notifications * Used as helper implementing functionality for Column com object. * [uses CNode to perform the task] * * PARAMETERS: * HNODE hNodeSelected - scope node - oener of the view * int iColIndex - column index to perform action on * bool bVisible - show/hide flag for operation * * RETURNS: * SC - result code * \***************************************************************************/ STDMETHODIMP CNodeCallback::ShowColumn(HNODE hNodeSelected, int iColIndex, bool bShow) { DECLARE_SC(sc, TEXT("CNodeCallback::ShowColumn"));
// get CNode pointer
CNode* pNode = CNode::FromHandle(hNodeSelected); sc = ScCheckPointers(pNode, E_UNEXPECTED); if (sc) return sc.ToHr();
sc = pNode->ScShowColumn(iColIndex, bShow); if (sc) return sc.ToHr();
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CNodeCallback::GetSortColumn * * PURPOSE: retrieves index of sort column * Used as helper implementing functionality for Column com object. * [uses CNode to perform the task] * * PARAMETERS: * HNODE hNodeSelected - scope node - oener of the view * int *piSortCol - resulting index * * RETURNS: * SC - result code * \***************************************************************************/ STDMETHODIMP CNodeCallback::GetSortColumn(HNODE hNodeSelected, int *piSortCol) { DECLARE_SC(sc, TEXT("CNodeCallback::GetSortColumn"));
// get CNode pointer
CNode* pNode = CNode::FromHandle(hNodeSelected); sc = ScCheckPointers(pNode, E_UNEXPECTED); if (sc) return sc.ToHr();
sc = pNode->ScGetSortColumn(piSortCol); if (sc) return sc.ToHr();
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CNodeCallback::SetSortColumn * * PURPOSE: sorts result data by specified column * Used as helper implementing functionality for Column com object. * [uses CNode to perform the task] * * PARAMETERS: * HNODE hNodeSelected - scope node - oener of the view * int iSortCol - sort column index * bool bAscending - sort order * * RETURNS: * HRESULT * \***************************************************************************/ STDMETHODIMP CNodeCallback::SetSortColumn(HNODE hNodeSelected, int iSortCol, bool bAscending) { DECLARE_SC(sc, TEXT("CNodeCallback::SetSortColumn"));
// get CNode pointer
CNode* pNode = CNode::FromHandle(hNodeSelected); sc = ScCheckPointers(pNode, E_UNEXPECTED); if (sc) return sc.ToHr();
sc = pNode->ScSetSortColumn(iSortCol, bAscending); if (sc) return sc.ToHr();
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CNodeCallback::RestoreResultView * * PURPOSE: Called by conui to restore the result view with given data. * This method asks snapin (indirectly) to restore the view. * * PARAMETERS: * HNODE hNode - scope node - oener of the view * CResultViewType rvt - The resultview type data to be used for restore. * * RETURNS: * HRESULT S_OK if snapin used the data to restore the view * S_FALSE if snapin refused to restore. * \***************************************************************************/ STDMETHODIMP CNodeCallback::RestoreResultView(HNODE hNode, const CResultViewType& rvt) { DECLARE_SC(sc, TEXT("CNodeCallback::RestoreResultView"));
// get CNode pointer
CNode* pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
sc = pNode->ScRestoreResultView(rvt); if (sc) return sc.ToHr();
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CNodeCallback::GetNodeViewExtensions * * PURPOSE: Forwards calls to CNode to collect view extensions * * PARAMETERS: * HNODE hNodeScope * CViewExtInsertIterator it * * RETURNS: * HRESULT - result code * \***************************************************************************/ STDMETHODIMP CNodeCallback::GetNodeViewExtensions(/*[in]*/ HNODE hNodeScope, /*[out]*/ CViewExtInsertIterator it) { DECLARE_SC(sc, TEXT("CNodeCallback::GetNodeViewExtensions"));
// get CNode pointer
CNode* pNode = CNode::FromHandle(hNodeScope); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
sc = pNode->ScGetViewExtensions(it); if (sc) return sc.ToHr();
return sc.ToHr(); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::SaveColumnInfoList
//
// Synopsis: The column-data for given node has changed persist the
// new column data.
//
// Arguments: [hNode] - Node that owns result-pane.
// [columnsList] - The new column-data.
//
// Note: The sort-data is not given by this call, so do not change it.
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
HRESULT CNodeCallback::SaveColumnInfoList (HNODE hNode, const CColumnInfoList& columnsList) { DECLARE_SC(sc, _T("CNodeCallback::SaveColumnInfoList")); sc = ScCheckPointers(hNode); if (sc) return sc.ToHr();
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
CViewData *pViewData = pNode->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return sc.ToHr();
CLSID guidSnapin; CXMLAutoBinary columnID; sc = pNode->ScGetSnapinAndColumnDataID(guidSnapin, columnID); if (sc) return sc.ToHr();
CXMLBinaryLock sLock(columnID); SColumnSetID* pColID = NULL; sc = sLock.ScLock(&pColID); if (sc) return sc.ToHr();
sc = ScCheckPointers(pColID, E_UNEXPECTED); if (sc) return sc.ToHr();
// Get the old persisted column data. This contains width values
// for hidden columns which is used if the column is un-hidden.
CColumnSetData columnSetData; BOOL bRet = pViewData->RetrieveColumnData(guidSnapin, *pColID, columnSetData);
if (bRet) { CColumnInfoList* pColInfoListOld = columnSetData.get_ColumnInfoList();
if (columnsList.size() == pColInfoListOld->size()) { // Merge the persisted column width for hidden columns
// to the new list created.
CColumnInfoList::iterator itColInfo1; CColumnInfoList::iterator itColInfo2;
for (itColInfo1 = pColInfoListOld->begin(), itColInfo2 = columnsList.begin(); itColInfo1 != pColInfoListOld->end(); ++itColInfo1, ++itColInfo2) { if (itColInfo2->IsColHidden()) itColInfo2->SetColWidth(itColInfo1->GetColWidth()); } } }
// Set the new columns list in column-set-data.
columnSetData.set_ColumnInfoList(columnsList);
// Save the data.
sc = pViewData->ScSaveColumnInfoList(guidSnapin, *pColID, columnsList); if (sc) return sc.ToHr();
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::GetPersistedColumnInfoList
//
// Synopsis: The list-view requests the column-data (no sort data) to setup the headers
// before any items are inserted into the list-view.
// (Note: Modify headers after all columns are inserted before any list-view
// items will be inserted to reduce flicker).
//
// Arguments: [hNode] - node that owns result-pane for which column-data is needed.
// [pColumnsList] - [out param], the column-data.
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
HRESULT CNodeCallback::GetPersistedColumnInfoList (HNODE hNode, CColumnInfoList *pColumnsList) { DECLARE_SC(sc, _T("CNodeCallback::GetPersistedColumnInfoList")); sc = ScCheckPointers(hNode, pColumnsList); if (sc) return sc.ToHr();
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
CViewData *pViewData = pNode->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return sc.ToHr();
CLSID guidSnapin; CXMLAutoBinary columnID; sc = pNode->ScGetSnapinAndColumnDataID(guidSnapin, columnID); if (sc) return sc.ToHr();
CXMLBinaryLock sLock(columnID); SColumnSetID* pColID = NULL; sc = sLock.ScLock(&pColID); if (sc) return sc.ToHr();
sc = ScCheckPointers(pColID, E_UNEXPECTED); if (sc) return sc.ToHr();
// Get the old persisted column data. This contains width values
// for hidden columns which is used if the column is un-hidden.
CColumnSetData columnSetData; BOOL bRet = pViewData->RetrieveColumnData(guidSnapin, *pColID, columnSetData);
if (!bRet) return (sc = S_FALSE).ToHr();
CColumnInfoList *pColListOriginal = columnSetData.get_ColumnInfoList(); if (!pColListOriginal) return (sc = S_FALSE).ToHr();
*pColumnsList = *pColListOriginal;
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::DeletePersistedColumnData
//
// Synopsis: The column data for given node is invalid, remove it.
//
// Arguments: [hNode] - The node for which the data is invalid.
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
HRESULT CNodeCallback::DeletePersistedColumnData(HNODE hNode) { DECLARE_SC(sc, _T("CNodeCallback::DeletePersistedColumnData")); sc = ScCheckPointers(hNode); if (sc) return sc.ToHr();
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
CViewData *pViewData = pNode->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return sc.ToHr();
CLSID guidSnapin; CXMLAutoBinary columnID; sc = pNode->ScGetSnapinAndColumnDataID(guidSnapin, columnID); if (sc) return sc.ToHr();
CXMLBinaryLock sLock(columnID); SColumnSetID* pColID = NULL; sc = sLock.ScLock(&pColID); if (sc) return sc.ToHr();
sc = ScCheckPointers(pColID, E_UNEXPECTED); if (sc) return sc.ToHr();
// Get the old persisted column data. This contains width values
// for hidden columns which is used if the column is un-hidden.
pViewData->DeleteColumnData(guidSnapin, *pColID);
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::DoesAboutExist
//
// Synopsis: See if about information exists for given node's snapin.
//
// Arguments: [hNode] -
// [pbAboutExists] - out param, ptr to bool, true if about exists.
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::DoesAboutExist (HNODE hNode, bool *pbAboutExists) { DECLARE_SC(sc, _T("CNodeCallback::DoesAboutExist")); sc = ScCheckPointers(hNode, pbAboutExists); if (sc) return sc.ToHr();
*pbAboutExists = false;
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
// No about for console root eventhough it is a Folder snapin.
if (pNode->IsConsoleRoot()) return sc.ToHr();
CLSID clsidAbout; const CLSID& clsidSnapin = pNode->GetPrimarySnapInCLSID(); SC scNoTrace = ScGetAboutFromSnapinCLSID(clsidSnapin, clsidAbout); if (scNoTrace) return scNoTrace.ToHr();
CSnapinAbout snapinAbout; snapinAbout.GetSnapinInformation(clsidAbout); sc = snapinAbout.GetObjectStatus(); if (sc) return sc.ToHr();
*pbAboutExists = true;
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::ShowAboutInformation
//
// Synopsis: Given the context of currently selected item.
// Show its about information.
//
// Arguments: [hNode] - scope node that owns result pane.
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::ShowAboutInformation (HNODE hNode) { DECLARE_SC(sc, _T("CNodeCallback::ShowAboutInformation")); sc = ScCheckPointers(hNode); if (sc) return sc.ToHr();
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
CLSID clsidAbout; const CLSID& clsidSnapin = pNode->GetPrimarySnapInCLSID(); sc = ScGetAboutFromSnapinCLSID(clsidSnapin, clsidAbout); if (sc) return sc.ToHr();
CSnapinAbout snapinAbout; snapinAbout.GetSnapinInformation(clsidAbout);
USES_CONVERSION; tstring szSnapinName; if (GetSnapinNameFromCLSID(clsidSnapin, szSnapinName)) snapinAbout.SetSnapinName(T2COLE(szSnapinName.data()));
sc = snapinAbout.GetObjectStatus(); if (sc) return sc.ToHr();
snapinAbout.ShowAboutBox();
return (sc.ToHr()); }
/*+-------------------------------------------------------------------------*
* * CNodeCallback::ExecuteShellCommand * * PURPOSE: Executes a shell command with the specified parameters in the * specified directory with the correct window size * * PARAMETERS: * HNODE hNode : * BSTR Command : * BSTR Directory : * BSTR Parameters : * BSTR WindowState : * * RETURNS: * HRESULT * *+-------------------------------------------------------------------------*/ HRESULT CNodeCallback::ExecuteShellCommand(HNODE hNode, BSTR Command, BSTR Directory, BSTR Parameters, BSTR WindowState) { DECLARE_SC(sc, TEXT("CNodeCallback::ExecuteShellCommand"));
sc = ScCheckPointers(hNode); if (sc) return sc.ToHr();
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode); if (sc) return sc.ToHr();
sc = pNode->ScExecuteShellCommand(Command, Directory, Parameters, WindowState);
return sc.ToHr(); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::QueryPasteFromClipboard
//
// Synopsis: Given the context of paste target, get the clipboard dataobject
// and see if target allows paste.
//
// Arguments: [hNode] -
// [bScope] -
// [lCookie] - All above params describe paste target context.
// [bPasteAllowed] - [out]
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::QueryPasteFromClipboard (HNODE hNode, BOOL bScope, LPARAM lCookie, bool& bPasteAllowed) { DECLARE_SC(sc, _T("CNodeCallback::QueryPasteFromClipboard")); sc = ScCheckPointers(hNode); if (sc) return sc.ToHr();
// 1. Get the current dataobject from clipboard.
IDataObjectPtr spDOPaste; sc = OleGetClipboard(&spDOPaste); if (sc) return sc.ToHr();
sc = ScCheckPointers(spDOPaste, E_UNEXPECTED); if (sc) return sc.ToHr();
bool bCopyOperatationIsDefault = false; /*unused*/
sc = QueryPaste(hNode, bScope, lCookie, spDOPaste, bPasteAllowed, bCopyOperatationIsDefault); if (sc) return sc.ToHr();
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::QueryPaste
//
// Synopsis: Given the context for current selection which is the target
// for paste (or drop). Find out it can paste given dataobject.
//
// Arguments: [hNode] - The node owning the view.
// [bScope] - Selection on Scope or Result pane.
// [lCookie] - If result pane selected the cookie for selected result item.
// [pDataObjectToPaste] - The dataobject to be pasted.
// [bPasteAllowed] - [out param], paste was permitted or not.
// [bCopyOperatationIsDefault] - [out param], is copy default operation (for r-click&l-click drag&drop)
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::QueryPaste (HNODE hNode, BOOL bScopePaneSelected, LPARAM lCookie, IDataObject *pDataObjectToPaste, bool& bPasteAllowed, bool& bCopyOperatationIsDefault) { DECLARE_SC(sc, _T("CNodeCallback::NewQueryPaste")); bPasteAllowed = false; sc = ScCheckPointers(hNode, pDataObjectToPaste); if (sc) return sc.ToHr();
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode, E_UNEXPECTED); if (sc) return sc.ToHr();
// If result-pane cookie should be valid.
BOOL bScopeItemSelected; CNode *pSelectedNode = NULL; MMC_COOKIE cookie = -1;
sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lCookie, &pSelectedNode, bScopeItemSelected, cookie); if (sc) return sc.ToHr();
sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED); if (sc) return sc.ToHr();
if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) ) return (sc = E_FAIL).ToHr();
CViewData *pViewData = pSelectedNode->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return sc.ToHr();
// Do not allow paste into OCX/WEB/Multiselection
// We can allow paste into OCX/WEB if we expose IMMCClipboardDataObject
// interface. But paste into Multiselection should not be allowed as
// it is not intuitive.
if ( (!bScopeItemSelected) && IS_SPECIAL_COOKIE(lCookie)) return sc.ToHr();
/*
* In MMC1.2 the drop target is always scope node. In MMC2.0 * it can be any result item. If the snapin has RVTI_LIST_OPTIONS_ALLOWPASTE * set, then we need to provide proper parameters to below _GetVerbState. */ if ( (bScopeItemSelected == FALSE) && (! (RVTI_LIST_OPTIONS_ALLOWPASTE & pViewData->GetListOptions())) ) return sc.ToHr();
IDataObjectPtr spTargetDataObject; sc = pSelectedNode->ScGetDropTargetDataObject(bScopeItemSelected, lCookie, &spTargetDataObject); if (sc) return sc.ToHr();
sc = ScCheckPointers(spTargetDataObject, E_UNEXPECTED); if (sc) return sc.ToHr();
BOOL bFlag = FALSE; sc = _ScGetVerbState(pSelectedNode, MMC_VERB_PASTE, spTargetDataObject, bScopeItemSelected, lCookie, /*bMultiSel*/FALSE, bFlag); if (sc) return sc.ToHr();
if (!bFlag) return sc.ToHr();
// QI to see if it is MMC's data object
IMMCClipboardDataObjectPtr spMMCClipboardDataObj = pDataObjectToPaste;
if (spMMCClipboardDataObj) { // This is our own dataobject.
// 3. Get how, where it is created, and how many snapin objects are there.
DWORD dwSourceProcess = 0; sc = spMMCClipboardDataObj->GetSourceProcessId( &dwSourceProcess ); if (sc) return sc.ToHr();
// If from different process then ask snapin if it can handle out of proc dataobjects.
BOOL bSourceFromDifferentMMCProcess = ( dwSourceProcess != ::GetCurrentProcessId() );
DWORD dwNumObjects = 0; sc = spMMCClipboardDataObj->GetCount(&dwNumObjects); if (sc) return sc.ToHr();
// 4. For each snapin object, get the dataobject and ask target item if
// it can allow the source to be pasted.
for (DWORD index = 0; index < dwNumObjects; ++index) { IDataObjectPtr spSourceDataObject; DWORD dwFlags = 0; sc = spMMCClipboardDataObj->GetDataObject( index, &spSourceDataObject, &dwFlags ); if (sc) return sc.ToHr();
sc = ScCheckPointers(spSourceDataObject, E_UNEXPECTED); if (sc) return sc.ToHr();
// must have some operation allowed - else it is invalid entry
if ( dwFlags == 0 ) return (sc = E_UNEXPECTED).ToHr(); /*
* During construction of th MMCClipboardDataObject we have checked if * cut/copy is enabled before adding the snapin dataobject. * So we are sure now atleast cut or copy is enabled for each snapin * object and we dont have to check this again. */
bool bSnapinPasteAllowed = false; bool bSnapinWantsCopyAsDefault = false; sc = _ScQueryPaste (pSelectedNode, spTargetDataObject, spSourceDataObject, bSourceFromDifferentMMCProcess, bSnapinPasteAllowed, bSnapinWantsCopyAsDefault); if (sc) return sc.ToHr();
bPasteAllowed = bPasteAllowed || bSnapinPasteAllowed; bCopyOperatationIsDefault = bCopyOperatationIsDefault || bSnapinWantsCopyAsDefault; }
} else { // We do not recognize the dataobject and we dont know if it is from
// this MMC process or from any other process. So do not ask snapin if
// it can handle outofproc dataobjects or not. (This is MMC1.2 legacy case).
sc = _ScQueryPaste (pSelectedNode, spTargetDataObject, pDataObjectToPaste, /*bSourceFromDifferentMMCProcess = */ false, bPasteAllowed, bCopyOperatationIsDefault); if (sc) return sc.ToHr(); }
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::_ScQueryPaste
//
// Synopsis: Send MMCN_QUERY_PASTE(2) to the snapin.
//
// Arguments: [pNode] - Owner of result pane.
// [spTargetDataObject] - Target object where we want to paste.
// [spSourceDataObject] - The object that we want to paste.
// [bSourceFromDifferentMMCProcess] -
// [bPasteAllowed] - out param
// [bCopyOperationIsDefault] - out param
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CNodeCallback::_ScQueryPaste (CNode *pNode, IDataObject *pTargetDataObject, IDataObject *pSourceDataObject, bool bSourceFromDifferentMMCProcess, bool& bPasteAllowed, bool& bCopyOperatationIsDefault) { DECLARE_SC(sc, _T("CNodeCallback::_ScQueryPaste")); sc = ScCheckPointers(pNode, pTargetDataObject, pSourceDataObject); if (sc) return sc;
bCopyOperatationIsDefault = false; bPasteAllowed = false;
CComponent* pCC = pNode->GetPrimaryComponent(); sc = ScCheckPointers(pCC, E_UNEXPECTED); if (sc) return sc.ToHr();
BOOL bCanPasteOutOfProcDataObject = FALSE;
sc = pCC->Notify(NULL, MMCN_CANPASTE_OUTOFPROC, 0, reinterpret_cast<LPARAM>(&bCanPasteOutOfProcDataObject) );
// Snapins return E_* values so check if they are OK with above notification.
if ( sc != S_OK) { bCanPasteOutOfProcDataObject = false; sc.Clear(); }
// Source from diff MMC process & cannot handle outofproc dataobjects then return.
if (bSourceFromDifferentMMCProcess && (! bCanPasteOutOfProcDataObject) ) return sc.ToHr();
// Send MMCN_QUERY_PASTE
DWORD dwFlags = 0; sc = pCC->Notify(pTargetDataObject, MMCN_QUERY_PASTE, reinterpret_cast<LPARAM>(pSourceDataObject), reinterpret_cast<LPARAM>(&dwFlags)); if (sc) { // Clear any snapin returned errors.
sc.Clear(); return sc.ToHr(); }
if (sc == SC(S_OK)) bPasteAllowed = true;
bCopyOperatationIsDefault = (dwFlags & MMC_DEFAULT_OPERATION_COPY);
return (sc); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::Drop
//
// Synopsis: Given the drop object context & the source object to
// be dropped. Do paste operation.
//
// Arguments: [hNode] - The node owning the view.
// [bScope] - Selection on Scope or Result pane.
// [lCookie] - If result pane selected the cookie for selected result item.
// [pDataObjectToPaste] - The dataobject to be pasted.
// [bIsDragOperationMove]- Is the drag operation move or copy.
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::Drop (HNODE hNode, BOOL bScope, LPARAM lCookie, IDataObject *pDataObjectToPaste, BOOL bIsDragOperationMove) { DECLARE_SC(sc, _T("CNodeCallback::Drop")); sc = ScCheckPointers(hNode, pDataObjectToPaste); if (sc) return sc.ToHr();
sc = ScPaste(hNode, bScope, lCookie, pDataObjectToPaste, TRUE, bIsDragOperationMove); if (sc) return sc.ToHr();
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::Paste
//
// Synopsis: Given the target where the clipboard object is to be
// pasted. Paste the object.
//
// Arguments: [hNode] - The node owning the view.
// [bScope] - Selection on Scope or Result pane.
// [lCookie] - If result pane selected the cookie for selected result item.
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::Paste (HNODE hNode, BOOL bScope, LPARAM lCookie) { DECLARE_SC(sc, _T("CNodeCallback::Paste")); sc = ScCheckPointers(hNode); if (sc) return sc.ToHr();
IDataObjectPtr spDOPaste; sc = OleGetClipboard(&spDOPaste); if (sc) return sc.ToHr();
sc = ScCheckPointers(spDOPaste, E_UNEXPECTED); if (sc) return sc.ToHr();
sc = ScPaste(hNode, bScope, lCookie, spDOPaste, /*bDragDrop*/FALSE, FALSE); if (sc) return sc.ToHr();
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::ScPaste
//
// Synopsis: Given the current drop target (or paste target) context
// paste the given data object if it is drag&drop operation
// else paste the one from clipboard.
//
// Arguments: [hNode] - The node owning the view.
// [bScopePaneSelected] - Selection on Scope or Result pane.
// [lCookie] - If result pane selected the cookie for selected result item.
// [pDataObjectToPaste] - The dataobject to be pasted.
// [bDragDrop] - Is the operation drag & drop operation.
// [bIsDragOperationMove]- Is the drag operation move or copy.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CNodeCallback::ScPaste (HNODE hNode, BOOL bScopePaneSelected, LPARAM lCookie, IDataObject *pDataObjectToPaste, BOOL bDragDrop, BOOL bIsDragOperationMove) { DECLARE_SC(sc, _T("CNodeCallback::Paste")); sc = ScCheckPointers(hNode, pDataObjectToPaste); if (sc) return sc;
CNode *pNode = CNode::FromHandle(hNode); sc = ScCheckPointers(pNode, E_UNEXPECTED); if (sc) return sc;
// If result-pane cookie should be valid.
BOOL bScopeItemSelected; CNode *pSelectedNode = NULL; MMC_COOKIE cookie = -1;
sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lCookie, &pSelectedNode, bScopeItemSelected, cookie); if (sc) return sc;
sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED); if (sc) return sc;
if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) ) return (sc = E_FAIL);
CViewData *pViewData = pSelectedNode->GetViewData(); sc = ScCheckPointers(pViewData, E_UNEXPECTED); if (sc) return sc;
// Do not allow paste into OCX/WEB/Multiselection
// We can allow paste into OCX/WEB if we expose IMMCClipboardDataObject
// interface. But paste into Multiselection should not be allowed as
// it is not intuitive.
if ( (!bScopeItemSelected) && IS_SPECIAL_COOKIE(lCookie)) return sc;
/*
* In MMC1.2 the drop target is always scope node. In MMC2.0 * it can be any result item. * Make sure if the snapin has RVTI_LIST_OPTIONS_ALLOWPASTE. */ if ( (bScopeItemSelected == FALSE) && (! (RVTI_LIST_OPTIONS_ALLOWPASTE & pViewData->GetListOptions())) ) { ASSERT(0 && "UNEXPECTED: We can paste only into a folder!"); // We can paste only into a folder.
return (sc = E_FAIL); }
if (pSelectedNode->IsInitialized() == FALSE) { sc = _InitializeNode(pSelectedNode); if (sc) return sc; }
IDataObject* pTargetDataObject = NULL; sc = pSelectedNode->ScGetDropTargetDataObject(bScopeItemSelected, lCookie, &pTargetDataObject); if (sc) return sc;
IDataObjectPtr spTargetDataObject; if (! IS_SPECIAL_DATAOBJECT(pTargetDataObject)) spTargetDataObject = pTargetDataObject; // Addref the object
sc = ScCheckPointers(pTargetDataObject, E_UNEXPECTED); if (sc) return sc;
// QI to see if it is MMC's data object
IMMCClipboardDataObjectPtr spMMCClipboardDataObj = pDataObjectToPaste;
if (spMMCClipboardDataObj) { // This is our own dataobject.
// 3. Get how, where it is created, and how many snapin objects are there.
DATA_SOURCE_ACTION eSourceAction; sc = spMMCClipboardDataObj->GetAction( &eSourceAction ); if (sc) return sc;
BOOL bIsCreatedForCut = FALSE; BOOL bIsCreatedForCopy = FALSE;
if (bDragDrop) { bIsCreatedForCut = bIsDragOperationMove; bIsCreatedForCopy = !bIsDragOperationMove; } else { bIsCreatedForCut = ( eSourceAction == ACTION_CUT ); bIsCreatedForCopy = ( eSourceAction == ACTION_COPY ); }
DWORD dwNumObjects = 0; sc = spMMCClipboardDataObj->GetCount(&dwNumObjects); if (sc) return sc;
BOOL bDoCutOperation = FALSE; BOOL bDoCopyOperation = FALSE;
// 4. For each snapin object, get the dataobject and ask target to paste it.
// need to form the array of copy objects, so that we do not delete them while
// processing - this invalidates data object and prevents accessing the rest of
// items
std::vector<IDataObjectPtr> vecObjectsToCopy; std::vector<DWORD> vecObjectFlags;
vecObjectsToCopy.reserve(dwNumObjects); // small optimization
vecObjectFlags.reserve(dwNumObjects); // small optimization
// fill with data objects to copy
for (DWORD index = 0; index < dwNumObjects; ++index) { IDataObjectPtr spSourceDataObject; DWORD dwFlags = 0; sc = spMMCClipboardDataObj->GetDataObject( index, &spSourceDataObject, &dwFlags ); if (sc) return sc;
vecObjectsToCopy.push_back( spSourceDataObject ); vecObjectFlags.push_back( dwFlags ); }
// perform action on the data
for (index = 0; index < dwNumObjects; ++index) { IDataObjectPtr spSourceDataObject = vecObjectsToCopy[index]; DWORD dwFlags = vecObjectFlags[index];
sc = ScCheckPointers(spSourceDataObject, E_UNEXPECTED); if (sc) return sc;
BOOL bHasCutEnabled = ( dwFlags & MOVE_ALLOWED ); BOOL bHasCopyEnabled = ( dwFlags & COPY_ALLOWED );
/*
* In case of multiselection even if one of the selected * object enables cut, the cut operation can be performed. * * But when we paste the objects we need to see if source * enabled cut or not. If it did not enable then do nothing. * * Below is a table for this. * * Source object enables (only) * ------------------------------------------- * |Operation | Cut | Copy | * ------------------------------------------- * | | | | * | Cut | Cut | Do nothing | * Current | | | | * Operation|----------------------------------------- * | | | | * | Copy | Do nothing | Copy | * | | | | * ------------------------------------------- */ bDoCutOperation = (bIsCreatedForCut && bHasCutEnabled); bDoCopyOperation = (bIsCreatedForCopy && bHasCopyEnabled);
// See above table: this is "Do nothing".
if ( (!bDoCutOperation) && (!bDoCopyOperation) ) continue;
IDataObjectPtr spCutDataObject; sc = _ScPaste (pSelectedNode, pTargetDataObject, spSourceDataObject, &spCutDataObject, bDoCutOperation ); if (sc) return sc;
// remove cut items when required
if (bDoCutOperation && spCutDataObject != NULL) { sc = spMMCClipboardDataObj->RemoveCutItems( index, spCutDataObject ); if (sc) return sc; } }
// If this is cut operation that is initiated by cut/copy/paste and
// not by drag & drop operation then the dataobject in clipboard is
// ours. So clear the clipboard so that we dont use that dataobject.
if ( eSourceAction == ACTION_CUT ) OleSetClipboard(NULL); } else { // We do not recognize the dataobject and we dont know if it is from
// this MMC process or from any other process. We cannot decode this
// dataobject so we just send MMCN_PASTE and ignore any dataobject
// retuned by snapin for cut operation (this is legacy case).
// for drag operation we can give a hint to snapin
// what operation (copy/move) was attempted.
// however we are not ensuring deletion of source items
bool bCutOrMove = (bDragDrop && bIsDragOperationMove);
IDataObjectPtr spCutDataObject; sc = _ScPaste (pSelectedNode, pTargetDataObject, pDataObjectToPaste, &spCutDataObject, bCutOrMove ); if (sc) return sc; }
return sc; }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::_ScPaste
//
// Synopsis: Send MMCN_PASTE to snapin.
//
// Arguments: [pNode] - Owner of resultpane.
// [pTargetDataObject] - target where we need to paste.
// [pSourceDataObject] - source to be pasted.
// [ppCutDataObject] - (out) cut items
// [bCutOrMove]
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CNodeCallback::_ScPaste (CNode *pNode, IDataObject *pTargetDataObject, IDataObject *pSourceDataObject, IDataObject **ppCutDataObject, bool bCutOrMove) { DECLARE_SC(sc, _T("CNodeCallback::_ScSendPasteNotification")); sc = ScCheckPointers(pNode, pTargetDataObject, pSourceDataObject, ppCutDataObject); if (sc) return sc;
// init out param
*ppCutDataObject = NULL;
CComponent* pComponent = pNode->GetPrimaryComponent(); sc = ScCheckPointers(pComponent, E_UNEXPECTED); if (sc) return sc;
IDataObject* pDataObjectToBeCutBySource = NULL; sc = pComponent->Notify(pTargetDataObject, MMCN_PASTE, reinterpret_cast<LPARAM>(pSourceDataObject), bCutOrMove ? reinterpret_cast<LPARAM>(&pDataObjectToBeCutBySource) : NULL); if (sc) return sc;
if (! bCutOrMove) return sc;
// Exchange returns NULL dataobject. Do not trace error to be compatible with MMC1.2
if ( (pDataObjectToBeCutBySource) && (IS_SPECIAL_DATAOBJECT(pDataObjectToBeCutBySource) ) ) return (sc = E_UNEXPECTED);
// transfer control to the client ( no addref nor release in neaded )
*ppCutDataObject = pDataObjectToBeCutBySource;
return (sc); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::QueryViewSettingsPersistor
//
// Synopsis: Get the IPersistStream interface of CViewSettingsPersistor
// object to load the viewsettings (will not be asked for
// storing as saving is always XML format).
//
// Arguments: [ppStream] - [out]
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::QueryViewSettingsPersistor (IPersistStream** ppStream) { DECLARE_SC(sc, _T("CNodeCallback::QueryViewSettingsPersistor")); sc = ScCheckPointers(ppStream); if (sc) return sc.ToHr();
*ppStream = NULL;
// Call CNode static method to get IPersistStream interface.
sc = CNode::ScQueryViewSettingsPersistor(ppStream); if (sc) return sc.ToHr();
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::QueryViewSettingsPersistor
//
// Synopsis: Get the CXMLObject interface of CViewSettingsPersistor
// object to save/load the viewsettings from XML console file.
//
// Arguments: [ppXMLObject] - [out]
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::QueryViewSettingsPersistor (CXMLObject** ppXMLObject) { DECLARE_SC(sc, _T("CNodeCallback::QueryViewSettingsPersistor"));
sc = ScCheckPointers(ppXMLObject); if (sc) return sc.ToHr();
*ppXMLObject = NULL;
// Call CNode static method to get CXMLObject interface.
sc = CNode::ScQueryViewSettingsPersistor(ppXMLObject); if (sc) return sc.ToHr();
return (sc.ToHr()); }
//+-------------------------------------------------------------------
//
// Member: CNodeCallback::DocumentClosing
//
// Synopsis: The document is to be closed, so release any document
// related objects. (CViewSettingsPersistor).
//
// Arguments: None
//
// Returns: HRESULT
//
//--------------------------------------------------------------------
STDMETHODIMP CNodeCallback::DocumentClosing () { DECLARE_SC(sc, _T("CNodeCallback::DocumentClosing"));
// 1. Call CNode static method informing document closing.
sc = CNode::ScOnDocumentClosing(); if (sc) return sc.ToHr();
return (sc.ToHr()); }
|