windows-nt/Source/XPSP1/NT/admin/activec/nodemgr/copypast.cpp
2020-09-26 16:20:57 +08:00

954 lines
28 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1999 - 1999
//
// File: copypast.cpp
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "objfmts.h"
#include "copypast.h"
#include "multisel.h"
#include "dbg.h"
#include "rsltitem.h"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/***************************************************************************\
|
| NOTE: DataObject Cleanup works by these rules (see CNode::CDataObjectCleanup):
|
| 1. Data object created for cut , copy or dragdrop registers every node added to it
| 2. Nodes are registered in the static multimap, mapping node to the data object it belongs to.
| 3. Node destructor checks the map and triggers cleanup for all affected data objects.
| 4. Data Object cleanup is: a) unregistering its nodes,
| b) release contained data objects
| b) entering invalid state (allowing only removal of cut objects to succeed)
| c) revoking itself from clipboard if it is on the clipboard.
| It will not do any of following: a) release references to IComponents as long as is alive
| b) prevent MMCN_CUTORMOVE to be send by invoking RemoveCutItems()
|
\***************************************************************************/
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject~CMMCClipBoardDataObject
*
* PURPOSE: Destructor. Informs CNode's that they are no longer on clipboard
*
\***************************************************************************/
CMMCClipBoardDataObject::~CMMCClipBoardDataObject()
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::~CMMCClipBoardDataObject"));
// inform all nodes put to clipboard about being removed from there
// but do not ask to force clenup on itself - it is not needed (we are in desrtuctor)
// and it is harmfull to cleanup ole in such a case (see bug #164789)
sc = CNode::CDataObjectCleanup::ScUnadviseDataObject( this , false/*bForceDataObjectCleanup*/);
if (sc)
sc.TraceAndClear();
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::GetSourceProcessId
*
* PURPOSE: returns process id of the source data object
*
* PARAMETERS:
* DWORD *pdwProcID - [out] id of source process
*
* RETURNS:
* HRESULT - result code
*
\***************************************************************************/
STDMETHODIMP CMMCClipBoardDataObject::GetSourceProcessId( DWORD *pdwProcID )
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetSourceProcessID"));
// should not be called on this object (too late)
if ( !m_bObjectValid )
return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(pdwProcID);
if (sc)
return sc.ToHr();
// return the id
*pdwProcID = ::GetCurrentProcessId();
return sc.ToHr();
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::GetAction
*
* PURPOSE: returns ction which created the data object
*
* PARAMETERS:
* DATA_SOURCE_ACTION *peAction [out] - action
*
* RETURNS:
* HRESULT - result code.
*
\***************************************************************************/
STDMETHODIMP CMMCClipBoardDataObject::GetAction( DATA_SOURCE_ACTION *peAction )
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::IsCreatedForCopy"));
// should not be called on this object (too late)
if ( !m_bObjectValid )
return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(peAction);
if (sc)
return sc.ToHr();
// return the action
*peAction = m_eOperation;
return sc.ToHr();
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::GetCount
*
* PURPOSE: Retuns the count of contined snapin data objects
*
* PARAMETERS:
* DWORD *pdwCount [out] - count of objects
*
* RETURNS:
* HRESULT - result code. S_OK, or error code
*
\***************************************************************************/
STDMETHODIMP CMMCClipBoardDataObject::GetCount( DWORD *pdwCount )
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetCount"));
// should not be called on this object (too late)
if ( !m_bObjectValid )
return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(pdwCount);
if (sc)
return sc.ToHr();
*pdwCount = m_SelectionObjects.size();
return sc.ToHr();
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::GetDataObject
*
* PURPOSE: Returns one of contained snapin data objects
*
* PARAMETERS:
* DWORD dwIndex [in] - index of reqested object
* IDataObject **ppObject [out] - requested object
* DWORD *pdwFlags [out] - object flags
*
* RETURNS:
* HRESULT - result code. S_OK, or error code
*
\***************************************************************************/
STDMETHODIMP CMMCClipBoardDataObject::GetDataObject( DWORD dwIdx, IDataObject **ppObject, DWORD *pdwFlags )
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetDataObject"));
// should not be called on this object (too late)
if ( !m_bObjectValid )
return (sc = E_UNEXPECTED).ToHr();
// check out param
sc = ScCheckPointers(ppObject, pdwFlags);
if (sc)
return sc.ToHr();
// init out param
*ppObject = NULL;
*pdwFlags = 0;
// more parameter check
if ( dwIdx >= m_SelectionObjects.size() )
return (sc = E_INVALIDARG).ToHr();
// return the object
IDataObjectPtr spObject = m_SelectionObjects[dwIdx].spDataObject;
*ppObject = spObject.Detach();
*pdwFlags = m_SelectionObjects[dwIdx].dwSnapinOptions;
return sc.ToHr();
}
///////////////////////////////////////////////////////////////////////////////
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::ScGetSingleSnapinObject
*
* PURPOSE: Returns interface to data object created by the source snapin
* NOTE: returns S_FALSE (and NULL ptr) when snapin count is not
* equal to one
*
* PARAMETERS:
* IDataObject **ppDataObject [out] - interface to data object
*
* RETURNS:
* HRESULT - result code. S_OK, or error code
*
\***************************************************************************/
SC CMMCClipBoardDataObject::ScGetSingleSnapinObject( IDataObject **ppDataObject )
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetContainedSnapinObject"));
// should not be called on this object (too late)
if ( !m_bObjectValid )
return sc = E_UNEXPECTED;
// parameter check
sc = ScCheckPointers( ppDataObject );
if (sc)
return sc;
// init out parameter
*ppDataObject = NULL;
// we can only resolve to the snapin if we have only one of them
if ( m_SelectionObjects.size() != 1 )
return sc = S_FALSE;
// ask for snapins DO
IDataObjectPtr spDataObject = m_SelectionObjects[0].spDataObject;
// return
*ppDataObject = spDataObject.Detach();
return sc;
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::GetDataHere
*
* PURPOSE: Implements IDataObject::GetDataHere. Forwards to snapin or fails
*
* PARAMETERS:
* LPFORMATETC lpFormatetc
* LPSTGMEDIUM lpMedium
*
* RETURNS:
* HRESULT - result code. S_OK, or error code
*
\***************************************************************************/
STDMETHODIMP CMMCClipBoardDataObject::GetDataHere(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium)
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetDataHere"));
// should not be called on this object (too late)
if ( !m_bObjectValid )
return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(lpFormatetc, lpMedium);
if (sc)
return sc.ToHr();
// try to get the snapin
IDataObjectPtr spDataObject;
sc = ScGetSingleSnapinObject( &spDataObject );
if (sc)
return sc.ToHr();
// we do not support any clipboard format at all ourselves
if (sc == S_FALSE)
return (sc = DATA_E_FORMATETC).ToHr();
// recheck
sc = ScCheckPointers( spDataObject, E_UNEXPECTED );
if (sc)
return sc.ToHr();
// forward to the snapin
sc = spDataObject->GetDataHere(lpFormatetc, lpMedium);
if (sc)
return sc.ToHr();
return sc.ToHr();
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::GetData
*
* PURPOSE: Implements IDataObject::GetData. Forwards to snapin or fails
*
* PARAMETERS:
* LPFORMATETC lpFormatetcIn
* LPSTGMEDIUM lpMedium
*
* RETURNS:
* HRESULT - result code. S_OK, or error code
*
\***************************************************************************/
STDMETHODIMP CMMCClipBoardDataObject::GetData(LPFORMATETC lpFormatetcIn, LPSTGMEDIUM lpMedium)
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetData"));
// should not be called on this object (too late)
if ( !m_bObjectValid )
return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(lpFormatetcIn, lpMedium);
if (sc)
return sc.ToHr();
// try to get the snapin
IDataObjectPtr spDataObject;
sc = ScGetSingleSnapinObject( &spDataObject );
if (sc)
return sc.ToHr();
// we do not support any clipboard format at all ourselves
if (sc == S_FALSE)
return (sc = DATA_E_FORMATETC).ToHr();
// recheck
sc = ScCheckPointers( spDataObject, E_UNEXPECTED );
if (sc)
return sc.ToHr();
// forward to the snapin
sc = spDataObject->GetData(lpFormatetcIn, lpMedium);
if (sc)
{
HRESULT hr = sc.ToHr();
sc.Clear(); // ignore the error
return hr;
}
return sc.ToHr();
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::EnumFormatEtc
*
* PURPOSE: Implements IDataObject::EnumFormatEtc. Forwards to snapin or fails
*
* PARAMETERS:
* DWORD dwDirection
* LPENUMFORMATETC* ppEnumFormatEtc
*
* RETURNS:
* HRESULT - result code. S_OK, or error code
*
\***************************************************************************/
STDMETHODIMP CMMCClipBoardDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC* ppEnumFormatEtc)
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::EnumFormatEtc"));
// should not be called on this object (too late)
if ( !m_bObjectValid )
return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(ppEnumFormatEtc);
if (sc)
return sc.ToHr();
// init out parameter
*ppEnumFormatEtc = NULL;
IEnumFORMATETCPtr spEnum;
std::vector<FORMATETC> vecFormats;
// add own entry
if (dwDirection == DATADIR_GET)
{
FORMATETC fmt ={GetWrapperCF(), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
vecFormats.push_back( fmt );
}
// try to get the snapin
IDataObjectPtr spDataObject;
sc = ScGetSingleSnapinObject( &spDataObject );
if (sc)
return sc.ToHr();
// add snapins formats (when we have one-and-only snapin)
IEnumFORMATETCPtr spEnumSnapin;
if (sc == S_OK)
{
// recheck
sc = ScCheckPointers( spDataObject, E_UNEXPECTED );
if (sc)
return sc.ToHr();
// forward to the snapin
sc = spDataObject->EnumFormatEtc(dwDirection, &spEnumSnapin);
if ( !sc.IsError() )
{
// recheck the pointer
sc = ScCheckPointers( spEnumSnapin );
if (sc)
return sc.ToHr();
// reset the enumeration
sc = spEnumSnapin->Reset();
if (sc)
return sc.ToHr();
FORMATETC frm;
ZeroMemory( &frm, sizeof(frm) );
while ( (sc = spEnumSnapin->Next( 1, &frm, NULL )) == S_OK )
{
vecFormats.push_back( frm );
}
// trap the error
if (sc)
return sc.ToHr();
}
else
{
sc.Clear(); // ignore the error - some snapins does not implement it
}
}
if ( vecFormats.size() == 0 ) // have nothing to return ?
return (sc = E_FAIL).ToHr();
// create the enumerator
sc = ::GetObjFormats( vecFormats.size(), vecFormats.begin(), (void **)ppEnumFormatEtc );
if (sc)
return sc.ToHr();
return sc.ToHr();
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::QueryGetData
*
* PURPOSE: Implements IDataObject::QueryGetData. Forwards to snapin or fails
*
* PARAMETERS:
* LPFORMATETC lpFormatetc
*
* RETURNS:
* HRESULT - result code. S_OK, or error code
*
\***************************************************************************/
STDMETHODIMP CMMCClipBoardDataObject::QueryGetData(LPFORMATETC lpFormatetc)
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::QueryGetData"));
// should not be called on this object (too late)
if ( !m_bObjectValid )
return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(lpFormatetc);
if (sc)
return sc.ToHr();
// try to get the snapin
IDataObjectPtr spDataObject;
sc = ScGetSingleSnapinObject( &spDataObject );
if (sc)
return sc.ToHr();
// we do not support any clipboard format at all ourselves
if (sc == S_FALSE)
return DV_E_FORMATETC; // not assigning to sc - not an error
// recheck
sc = ScCheckPointers( spDataObject, E_UNEXPECTED );
if (sc)
return sc.ToHr();
// forward to the snapin
sc = spDataObject->QueryGetData(lpFormatetc);
if (sc)
{
HRESULT hr = sc.ToHr();
sc.Clear(); // ignore the error
return hr;
}
return sc.ToHr();
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::RemoveCutItems
*
* PURPOSE: Called to remove copied objects from the source snapin
*
* PARAMETERS:
* DWORD dwIndex [in] snapin index
* IDataObject *pCutDataObject [in] items to be removed
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
STDMETHODIMP CMMCClipBoardDataObject::RemoveCutItems( DWORD dwIndex, IDataObject *pCutDataObject )
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::RemoveCutItems"));
// this is the only method allowed to be called on invalid object
// check param
sc = ScCheckPointers(pCutDataObject);
if (sc)
return sc.ToHr();
// more parameter check
if ( dwIndex >= m_SelectionObjects.size() )
return (sc = E_INVALIDARG).ToHr();
// get to the snapin
IComponent *pComponent = m_SelectionObjects[dwIndex].spComponent;
sc = ScCheckPointers( pComponent, E_UNEXPECTED );
if (sc)
return sc.ToHr();
sc = pComponent->Notify( NULL, MMCN_CUTORMOVE,
reinterpret_cast<LONG_PTR>(pCutDataObject), 0 );
if (sc)
return sc.ToHr();
return sc.ToHr();
}
///////////////////////////////////////////////////////////////////////////////
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::ScCreateInstance
*
* PURPOSE: Helper method (static) to create instance of CMMCClipBoardDataObject
*
* PARAMETERS:
* DATA_SOURCE_ACTION operation [in] why the object is created
* CMTNode *pTiedObj [in] object to trigger revoking
* CMMCClipBoardDataObject **ppRawObject [out] raw pointer
* IMMCClipboardDataObject **ppInterface [out] pointer to interface
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCClipBoardDataObject::ScCreateInstance(DATA_SOURCE_ACTION operation,
CMMCClipBoardDataObject **ppRawObject,
IMMCClipboardDataObject **ppInterface)
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScCreateInstance"));
// parameter check;
sc = ScCheckPointers( ppRawObject, ppInterface );
if (sc)
return sc;
// out param initialization
*ppInterface = NULL;
*ppRawObject = NULL;
typedef CComObject<CMMCClipBoardDataObject> CreatedObj;
CreatedObj *pCreatedObj;
sc = CreatedObj::CreateInstance( &pCreatedObj );
if (sc)
return sc;
// add first reference if non null;
IMMCClipboardDataObjectPtr spMMCDataObject = pCreatedObj;
// recheck
sc = ScCheckPointers( spMMCDataObject, E_UNEXPECTED );
if (sc)
{
delete pCreatedObj;
return sc;
}
// init the object
static_cast<CMMCClipBoardDataObject *>(pCreatedObj)->m_eOperation = operation;
// return 'em
*ppInterface = spMMCDataObject.Detach();
*ppRawObject = pCreatedObj;
return sc;
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::ScAddSnapinDataObject
*
* PURPOSE: Part of creating DO for the operation
* Adds snapins data to be carried inside
*
* PARAMETERS:
* IComponent *pComponent [in] - source snapin, which data id added
* IDataObject *pObject [in] - data object supplied by snapin
* bool bCopyEnabled [in] - if snapin allows to copy the data
* bool bCutEnabled [in] - if snapin allows to move the data
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCClipBoardDataObject::ScAddSnapinDataObject( const CNodePtrArray& nodes,
IComponent *pComponent,
IDataObject *pObject,
bool bCopyEnabled, bool bCutEnabled )
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScAddSnapinDataObject"));
// parameter check
sc = ScCheckPointers( pComponent, pObject );
if (sc)
return sc;
// create the object;
ObjectEntry object;
object.dwSnapinOptions = (bCopyEnabled ? COPY_ALLOWED : 0) |
(bCutEnabled ? MOVE_ALLOWED : 0);
object.spComponent = pComponent;
object.spDataObject = pObject;
// register the nodes to invalidate this data object on destruction
for ( CNodePtrArray::const_iterator it = nodes.begin(); it != nodes.end(); ++it )
{
CNode *pNode = *it;
sc = ScCheckPointers( pNode, E_UNEXPECTED );
if (sc)
return sc;
// register node to revoke this object from destructor
sc = CNode::CDataObjectCleanup::ScRegisterNode( pNode, this );
if (sc)
return sc;
}
// add to the array
m_SelectionObjects.push_back(object);
return sc;
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::GetNodeCopyAndCutVerbs
*
* PURPOSE: Calculates if copy and cut verb are enabled for node
*
* PARAMETERS:
* CNode* pNode [in] node to examine
* IDataObject *pDataObject [in] snapin's data object
* bool bScopePane [in] Scope or result (item for which the verb states needed).
* LPARAM lvData [in] If result then the LVDATA.
* bool *pCopyEnabled [out] true == Copy verb enabled
* bool *bCutEnabled [out] true == Cut verb enabled
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCClipBoardDataObject::ScGetNodeCopyAndCutVerbs( CNode* pNode, IDataObject *pDataObject,
bool bScopePane, LPARAM lvData,
bool *pbCopyEnabled, bool *pbCutEnabled )
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScGetNodeCopyAndCutVerbs"));
// paramter check
sc = ScCheckPointers(pNode, pDataObject, pbCopyEnabled, pbCutEnabled);
if (sc)
return sc;
// init out parameters
*pbCopyEnabled = *pbCutEnabled = false;
// Create temp verb with given context.
CComObject<CTemporaryVerbSet> stdVerbTemp;
sc = stdVerbTemp.ScInitialize(pDataObject, pNode, bScopePane, lvData);
BOOL bFlag = FALSE;
stdVerbTemp.GetVerbState(MMC_VERB_COPY, ENABLED, &bFlag);
*pbCopyEnabled = bFlag;
stdVerbTemp.GetVerbState(MMC_VERB_CUT, ENABLED, &bFlag);
*pbCutEnabled = bFlag;
return sc;
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::ScCreate
*
* PURPOSE: helper. Creates and initializes CMMCClipBoardDataObject
*
* PARAMETERS:
* DATA_SOURCE_ACTION operation [in] - for which operation (d&d, cut, copy)
* CNode* pNode [in] - Node to tie to
* bool bScopePane [in] - if it is scope pane operation
* bool bMultiSelect [in] - if it is multiselection
* LPARAM lvData [in] - lvdata for result item
* IMMCClipboardDataObject **ppMMCDO [out] - created data object
* bool& bContainsItems [out] - If snapin does not support cut/copy then
* dataobjets will not be added and this is
* not an error
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCClipBoardDataObject::ScCreate( DATA_SOURCE_ACTION operation,
CNode* pNode, bool bScopePane,
bool bMultiSelect, LPARAM lvData,
IMMCClipboardDataObject **ppMMCDataObject,
bool& bContainsItems )
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::Create"));
bContainsItems = false;
// parameter check
sc = ScCheckPointers( ppMMCDataObject, pNode );
if (sc)
return sc;
// init out param
*ppMMCDataObject = NULL;
// get MT node, view data;
CMTNode* pMTNode = pNode->GetMTNode();
CViewData *pViewData = pNode->GetViewData();
sc = ScCheckPointers( pMTNode, pViewData, E_UNEXPECTED );
if (sc)
return sc;
// create data object to be used for data transfer
CMMCClipBoardDataObject *pResultObject = NULL;
IMMCClipboardDataObjectPtr spResultInterface;
sc = ScCreateInstance(operation, &pResultObject, &spResultInterface);
if (sc)
return sc;
// recheck pointers
sc = ScCheckPointers( pResultObject, spResultInterface, E_UNEXPECTED );
if (sc)
return sc;
// valid from the start
pResultObject->m_bObjectValid = true;
// add data to the object...
if (!bMultiSelect) // single selection
{
// get snapins data object
IDataObjectPtr spDataObject;
CComponent* pCComponent;
bool bScopeItem = bScopePane;
sc = pNode->ScGetDataObject(bScopePane, lvData, bScopeItem, &spDataObject, &pCComponent);
if (sc)
return sc;
// recheck data object
if ( IS_SPECIAL_DATAOBJECT ( spDataObject.GetInterfacePtr() ) )
{
spDataObject.Detach();
return sc = E_UNEXPECTED;
}
sc = ScCheckPointers(pCComponent, E_UNEXPECTED);
if (sc)
return sc;
IComponent *pComponent = pCComponent->GetIComponent();
sc = ScCheckPointers(pComponent, E_UNEXPECTED);
if (sc)
return sc;
// add snapin's data object to transfer object
sc = pResultObject->ScAddDataObjectForItem( pNode, bScopePane, lvData,
pComponent, spDataObject,
bContainsItems );
if (sc)
return sc;
if (! bContainsItems)
return sc;
}
else // result pane : multi selection
{
// get pointer to multiselection
CMultiSelection *pMultiSel = pViewData->GetMultiSelection();
sc = ScCheckPointers( pMultiSel, E_UNEXPECTED );
if (sc)
return sc;
sc = pMultiSel->ScGetSnapinDataObjects(pResultObject);
if (sc)
return sc;
}
// if no items were added, something is wrong
DWORD dwCount = 0;
sc = pResultObject->GetCount( &dwCount );
if (sc)
return sc;
if ( dwCount == 0 )
return sc = E_UNEXPECTED;
bContainsItems = true;
// return interface
*ppMMCDataObject = spResultInterface.Detach();
return sc;
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::ScAddDataObjectForItem
*
* PURPOSE: Adds data object for one item
*
* PARAMETERS:
* CNode* pNode [in] - node to add (or one owning the item)
* bool bScopePane [in] - if operation is on scope pane
* LPARAM lvData [in] - if result pane the LVDATA
* IComponent *pComponent [in] - snapins interface
* IDataObject *pDataObject [in] - data object to add
* bool& bContainsItems [out] - Are there any dataobjects added?
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCClipBoardDataObject::ScAddDataObjectForItem( CNode* pNode, bool bScopePane,
LPARAM lvData, IComponent *pComponent,
IDataObject *pDataObject ,
bool& bContainsItems)
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScAddDataObjectForScopeNode"));
// Init out param.
bContainsItems = false;
// paramter check
sc = ScCheckPointers( pNode, pComponent, pDataObject );
if (sc)
return sc;
// get the verbs
bool bCopyEnabled = false;
bool bCutEnabled = false;
sc = ScGetNodeCopyAndCutVerbs( pNode, pDataObject, bScopePane, lvData, &bCopyEnabled, &bCutEnabled);
if (sc)
return sc;
// see it the data matches our criteria
// (needs to allow something at least)
if ( ( (m_eOperation == ACTION_COPY) && (bCopyEnabled == false) )
|| ( (m_eOperation == ACTION_CUT) && (bCutEnabled == false) )
|| ( (bCutEnabled == false) && (bCopyEnabled == false) ) )
return sc = S_FALSE;
// add to the list
sc = ScAddSnapinDataObject( CNodePtrArray(1, pNode), pComponent, pDataObject, bCopyEnabled, bCutEnabled );
if (sc)
return sc;
bContainsItems = true;
return sc;
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::GetWrapperCF
*
* PURPOSE: Helper. registers and returns own clipboard format
*
* PARAMETERS:
*
* RETURNS:
* CLIPFORMAT
*
\***************************************************************************/
CLIPFORMAT CMMCClipBoardDataObject::GetWrapperCF()
{
static CLIPFORMAT s_cf = 0;
if (s_cf == 0)
s_cf = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_MMC_INTERNAL"));
return s_cf;
}
/***************************************************************************\
*
* METHOD: CMMCClipBoardDataObject::ScEnsureNotInClipboard
*
* PURPOSE: called to remove data from clipbord when comonent is destoyed
*
* PARAMETERS:
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCClipBoardDataObject::ScInvalidate( void )
{
DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScEnsureNotInClipboard"));
// not valid anymore
m_bObjectValid = false;
// release data objects
for ( int i = 0; i< m_SelectionObjects.size(); i++)
m_SelectionObjects[i].spDataObject = NULL;
// check the clipboard
sc = ::OleIsCurrentClipboard( this );
if (sc)
return sc;
// it is on clipboard - remove
if (sc == S_OK)
OleSetClipboard(NULL);
return sc;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////