Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

953 lines
28 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: copypast.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "stdafx.h"
  11. #include "objfmts.h"
  12. #include "copypast.h"
  13. #include "multisel.h"
  14. #include "dbg.h"
  15. #include "rsltitem.h"
  16. ///////////////////////////////////////////////////////////////////////////////
  17. ///////////////////////////////////////////////////////////////////////////////
  18. /***************************************************************************\
  19. |
  20. | NOTE: DataObject Cleanup works by these rules (see CNode::CDataObjectCleanup):
  21. |
  22. | 1. Data object created for cut , copy or dragdrop registers every node added to it
  23. | 2. Nodes are registered in the static multimap, mapping node to the data object it belongs to.
  24. | 3. Node destructor checks the map and triggers cleanup for all affected data objects.
  25. | 4. Data Object cleanup is: a) unregistering its nodes,
  26. | b) release contained data objects
  27. | b) entering invalid state (allowing only removal of cut objects to succeed)
  28. | c) revoking itself from clipboard if it is on the clipboard.
  29. | It will not do any of following: a) release references to IComponents as long as is alive
  30. | b) prevent MMCN_CUTORMOVE to be send by invoking RemoveCutItems()
  31. |
  32. \***************************************************************************/
  33. /***************************************************************************\
  34. *
  35. * METHOD: CMMCClipBoardDataObject~CMMCClipBoardDataObject
  36. *
  37. * PURPOSE: Destructor. Informs CNode's that they are no longer on clipboard
  38. *
  39. \***************************************************************************/
  40. CMMCClipBoardDataObject::~CMMCClipBoardDataObject()
  41. {
  42. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::~CMMCClipBoardDataObject"));
  43. // inform all nodes put to clipboard about being removed from there
  44. // but do not ask to force clenup on itself - it is not needed (we are in desrtuctor)
  45. // and it is harmfull to cleanup ole in such a case (see bug #164789)
  46. sc = CNode::CDataObjectCleanup::ScUnadviseDataObject( this , false/*bForceDataObjectCleanup*/);
  47. if (sc)
  48. sc.TraceAndClear();
  49. }
  50. /***************************************************************************\
  51. *
  52. * METHOD: CMMCClipBoardDataObject::GetSourceProcessId
  53. *
  54. * PURPOSE: returns process id of the source data object
  55. *
  56. * PARAMETERS:
  57. * DWORD *pdwProcID - [out] id of source process
  58. *
  59. * RETURNS:
  60. * HRESULT - result code
  61. *
  62. \***************************************************************************/
  63. STDMETHODIMP CMMCClipBoardDataObject::GetSourceProcessId( DWORD *pdwProcID )
  64. {
  65. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetSourceProcessID"));
  66. // should not be called on this object (too late)
  67. if ( !m_bObjectValid )
  68. return (sc = E_UNEXPECTED).ToHr();
  69. // parameter check
  70. sc = ScCheckPointers(pdwProcID);
  71. if (sc)
  72. return sc.ToHr();
  73. // return the id
  74. *pdwProcID = ::GetCurrentProcessId();
  75. return sc.ToHr();
  76. }
  77. /***************************************************************************\
  78. *
  79. * METHOD: CMMCClipBoardDataObject::GetAction
  80. *
  81. * PURPOSE: returns ction which created the data object
  82. *
  83. * PARAMETERS:
  84. * DATA_SOURCE_ACTION *peAction [out] - action
  85. *
  86. * RETURNS:
  87. * HRESULT - result code.
  88. *
  89. \***************************************************************************/
  90. STDMETHODIMP CMMCClipBoardDataObject::GetAction( DATA_SOURCE_ACTION *peAction )
  91. {
  92. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::IsCreatedForCopy"));
  93. // should not be called on this object (too late)
  94. if ( !m_bObjectValid )
  95. return (sc = E_UNEXPECTED).ToHr();
  96. // parameter check
  97. sc = ScCheckPointers(peAction);
  98. if (sc)
  99. return sc.ToHr();
  100. // return the action
  101. *peAction = m_eOperation;
  102. return sc.ToHr();
  103. }
  104. /***************************************************************************\
  105. *
  106. * METHOD: CMMCClipBoardDataObject::GetCount
  107. *
  108. * PURPOSE: Retuns the count of contined snapin data objects
  109. *
  110. * PARAMETERS:
  111. * DWORD *pdwCount [out] - count of objects
  112. *
  113. * RETURNS:
  114. * HRESULT - result code. S_OK, or error code
  115. *
  116. \***************************************************************************/
  117. STDMETHODIMP CMMCClipBoardDataObject::GetCount( DWORD *pdwCount )
  118. {
  119. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetCount"));
  120. // should not be called on this object (too late)
  121. if ( !m_bObjectValid )
  122. return (sc = E_UNEXPECTED).ToHr();
  123. // parameter check
  124. sc = ScCheckPointers(pdwCount);
  125. if (sc)
  126. return sc.ToHr();
  127. *pdwCount = m_SelectionObjects.size();
  128. return sc.ToHr();
  129. }
  130. /***************************************************************************\
  131. *
  132. * METHOD: CMMCClipBoardDataObject::GetDataObject
  133. *
  134. * PURPOSE: Returns one of contained snapin data objects
  135. *
  136. * PARAMETERS:
  137. * DWORD dwIndex [in] - index of reqested object
  138. * IDataObject **ppObject [out] - requested object
  139. * DWORD *pdwFlags [out] - object flags
  140. *
  141. * RETURNS:
  142. * HRESULT - result code. S_OK, or error code
  143. *
  144. \***************************************************************************/
  145. STDMETHODIMP CMMCClipBoardDataObject::GetDataObject( DWORD dwIdx, IDataObject **ppObject, DWORD *pdwFlags )
  146. {
  147. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetDataObject"));
  148. // should not be called on this object (too late)
  149. if ( !m_bObjectValid )
  150. return (sc = E_UNEXPECTED).ToHr();
  151. // check out param
  152. sc = ScCheckPointers(ppObject, pdwFlags);
  153. if (sc)
  154. return sc.ToHr();
  155. // init out param
  156. *ppObject = NULL;
  157. *pdwFlags = 0;
  158. // more parameter check
  159. if ( dwIdx >= m_SelectionObjects.size() )
  160. return (sc = E_INVALIDARG).ToHr();
  161. // return the object
  162. IDataObjectPtr spObject = m_SelectionObjects[dwIdx].spDataObject;
  163. *ppObject = spObject.Detach();
  164. *pdwFlags = m_SelectionObjects[dwIdx].dwSnapinOptions;
  165. return sc.ToHr();
  166. }
  167. ///////////////////////////////////////////////////////////////////////////////
  168. /***************************************************************************\
  169. *
  170. * METHOD: CMMCClipBoardDataObject::ScGetSingleSnapinObject
  171. *
  172. * PURPOSE: Returns interface to data object created by the source snapin
  173. * NOTE: returns S_FALSE (and NULL ptr) when snapin count is not
  174. * equal to one
  175. *
  176. * PARAMETERS:
  177. * IDataObject **ppDataObject [out] - interface to data object
  178. *
  179. * RETURNS:
  180. * HRESULT - result code. S_OK, or error code
  181. *
  182. \***************************************************************************/
  183. SC CMMCClipBoardDataObject::ScGetSingleSnapinObject( IDataObject **ppDataObject )
  184. {
  185. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetContainedSnapinObject"));
  186. // should not be called on this object (too late)
  187. if ( !m_bObjectValid )
  188. return sc = E_UNEXPECTED;
  189. // parameter check
  190. sc = ScCheckPointers( ppDataObject );
  191. if (sc)
  192. return sc;
  193. // init out parameter
  194. *ppDataObject = NULL;
  195. // we can only resolve to the snapin if we have only one of them
  196. if ( m_SelectionObjects.size() != 1 )
  197. return sc = S_FALSE;
  198. // ask for snapins DO
  199. IDataObjectPtr spDataObject = m_SelectionObjects[0].spDataObject;
  200. // return
  201. *ppDataObject = spDataObject.Detach();
  202. return sc;
  203. }
  204. /***************************************************************************\
  205. *
  206. * METHOD: CMMCClipBoardDataObject::GetDataHere
  207. *
  208. * PURPOSE: Implements IDataObject::GetDataHere. Forwards to snapin or fails
  209. *
  210. * PARAMETERS:
  211. * LPFORMATETC lpFormatetc
  212. * LPSTGMEDIUM lpMedium
  213. *
  214. * RETURNS:
  215. * HRESULT - result code. S_OK, or error code
  216. *
  217. \***************************************************************************/
  218. STDMETHODIMP CMMCClipBoardDataObject::GetDataHere(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium)
  219. {
  220. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetDataHere"));
  221. // should not be called on this object (too late)
  222. if ( !m_bObjectValid )
  223. return (sc = E_UNEXPECTED).ToHr();
  224. // parameter check
  225. sc = ScCheckPointers(lpFormatetc, lpMedium);
  226. if (sc)
  227. return sc.ToHr();
  228. // try to get the snapin
  229. IDataObjectPtr spDataObject;
  230. sc = ScGetSingleSnapinObject( &spDataObject );
  231. if (sc)
  232. return sc.ToHr();
  233. // we do not support any clipboard format at all ourselves
  234. if (sc == S_FALSE)
  235. return (sc = DATA_E_FORMATETC).ToHr();
  236. // recheck
  237. sc = ScCheckPointers( spDataObject, E_UNEXPECTED );
  238. if (sc)
  239. return sc.ToHr();
  240. // forward to the snapin
  241. sc = spDataObject->GetDataHere(lpFormatetc, lpMedium);
  242. if (sc)
  243. return sc.ToHr();
  244. return sc.ToHr();
  245. }
  246. /***************************************************************************\
  247. *
  248. * METHOD: CMMCClipBoardDataObject::GetData
  249. *
  250. * PURPOSE: Implements IDataObject::GetData. Forwards to snapin or fails
  251. *
  252. * PARAMETERS:
  253. * LPFORMATETC lpFormatetcIn
  254. * LPSTGMEDIUM lpMedium
  255. *
  256. * RETURNS:
  257. * HRESULT - result code. S_OK, or error code
  258. *
  259. \***************************************************************************/
  260. STDMETHODIMP CMMCClipBoardDataObject::GetData(LPFORMATETC lpFormatetcIn, LPSTGMEDIUM lpMedium)
  261. {
  262. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetData"));
  263. // should not be called on this object (too late)
  264. if ( !m_bObjectValid )
  265. return (sc = E_UNEXPECTED).ToHr();
  266. // parameter check
  267. sc = ScCheckPointers(lpFormatetcIn, lpMedium);
  268. if (sc)
  269. return sc.ToHr();
  270. // try to get the snapin
  271. IDataObjectPtr spDataObject;
  272. sc = ScGetSingleSnapinObject( &spDataObject );
  273. if (sc)
  274. return sc.ToHr();
  275. // we do not support any clipboard format at all ourselves
  276. if (sc == S_FALSE)
  277. return (sc = DATA_E_FORMATETC).ToHr();
  278. // recheck
  279. sc = ScCheckPointers( spDataObject, E_UNEXPECTED );
  280. if (sc)
  281. return sc.ToHr();
  282. // forward to the snapin
  283. sc = spDataObject->GetData(lpFormatetcIn, lpMedium);
  284. if (sc)
  285. {
  286. HRESULT hr = sc.ToHr();
  287. sc.Clear(); // ignore the error
  288. return hr;
  289. }
  290. return sc.ToHr();
  291. }
  292. /***************************************************************************\
  293. *
  294. * METHOD: CMMCClipBoardDataObject::EnumFormatEtc
  295. *
  296. * PURPOSE: Implements IDataObject::EnumFormatEtc. Forwards to snapin or fails
  297. *
  298. * PARAMETERS:
  299. * DWORD dwDirection
  300. * LPENUMFORMATETC* ppEnumFormatEtc
  301. *
  302. * RETURNS:
  303. * HRESULT - result code. S_OK, or error code
  304. *
  305. \***************************************************************************/
  306. STDMETHODIMP CMMCClipBoardDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC* ppEnumFormatEtc)
  307. {
  308. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::EnumFormatEtc"));
  309. // should not be called on this object (too late)
  310. if ( !m_bObjectValid )
  311. return (sc = E_UNEXPECTED).ToHr();
  312. // parameter check
  313. sc = ScCheckPointers(ppEnumFormatEtc);
  314. if (sc)
  315. return sc.ToHr();
  316. // init out parameter
  317. *ppEnumFormatEtc = NULL;
  318. IEnumFORMATETCPtr spEnum;
  319. std::vector<FORMATETC> vecFormats;
  320. // add own entry
  321. if (dwDirection == DATADIR_GET)
  322. {
  323. FORMATETC fmt ={GetWrapperCF(), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  324. vecFormats.push_back( fmt );
  325. }
  326. // try to get the snapin
  327. IDataObjectPtr spDataObject;
  328. sc = ScGetSingleSnapinObject( &spDataObject );
  329. if (sc)
  330. return sc.ToHr();
  331. // add snapins formats (when we have one-and-only snapin)
  332. IEnumFORMATETCPtr spEnumSnapin;
  333. if (sc == S_OK)
  334. {
  335. // recheck
  336. sc = ScCheckPointers( spDataObject, E_UNEXPECTED );
  337. if (sc)
  338. return sc.ToHr();
  339. // forward to the snapin
  340. sc = spDataObject->EnumFormatEtc(dwDirection, &spEnumSnapin);
  341. if ( !sc.IsError() )
  342. {
  343. // recheck the pointer
  344. sc = ScCheckPointers( spEnumSnapin );
  345. if (sc)
  346. return sc.ToHr();
  347. // reset the enumeration
  348. sc = spEnumSnapin->Reset();
  349. if (sc)
  350. return sc.ToHr();
  351. FORMATETC frm;
  352. ZeroMemory( &frm, sizeof(frm) );
  353. while ( (sc = spEnumSnapin->Next( 1, &frm, NULL )) == S_OK )
  354. {
  355. vecFormats.push_back( frm );
  356. }
  357. // trap the error
  358. if (sc)
  359. return sc.ToHr();
  360. }
  361. else
  362. {
  363. sc.Clear(); // ignore the error - some snapins does not implement it
  364. }
  365. }
  366. if ( vecFormats.size() == 0 ) // have nothing to return ?
  367. return (sc = E_FAIL).ToHr();
  368. // create the enumerator
  369. sc = ::GetObjFormats( vecFormats.size(), vecFormats.begin(), (void **)ppEnumFormatEtc );
  370. if (sc)
  371. return sc.ToHr();
  372. return sc.ToHr();
  373. }
  374. /***************************************************************************\
  375. *
  376. * METHOD: CMMCClipBoardDataObject::QueryGetData
  377. *
  378. * PURPOSE: Implements IDataObject::QueryGetData. Forwards to snapin or fails
  379. *
  380. * PARAMETERS:
  381. * LPFORMATETC lpFormatetc
  382. *
  383. * RETURNS:
  384. * HRESULT - result code. S_OK, or error code
  385. *
  386. \***************************************************************************/
  387. STDMETHODIMP CMMCClipBoardDataObject::QueryGetData(LPFORMATETC lpFormatetc)
  388. {
  389. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::QueryGetData"));
  390. // should not be called on this object (too late)
  391. if ( !m_bObjectValid )
  392. return (sc = E_UNEXPECTED).ToHr();
  393. // parameter check
  394. sc = ScCheckPointers(lpFormatetc);
  395. if (sc)
  396. return sc.ToHr();
  397. // try to get the snapin
  398. IDataObjectPtr spDataObject;
  399. sc = ScGetSingleSnapinObject( &spDataObject );
  400. if (sc)
  401. return sc.ToHr();
  402. // we do not support any clipboard format at all ourselves
  403. if (sc == S_FALSE)
  404. return DV_E_FORMATETC; // not assigning to sc - not an error
  405. // recheck
  406. sc = ScCheckPointers( spDataObject, E_UNEXPECTED );
  407. if (sc)
  408. return sc.ToHr();
  409. // forward to the snapin
  410. sc = spDataObject->QueryGetData(lpFormatetc);
  411. if (sc)
  412. {
  413. HRESULT hr = sc.ToHr();
  414. sc.Clear(); // ignore the error
  415. return hr;
  416. }
  417. return sc.ToHr();
  418. }
  419. /***************************************************************************\
  420. *
  421. * METHOD: CMMCClipBoardDataObject::RemoveCutItems
  422. *
  423. * PURPOSE: Called to remove copied objects from the source snapin
  424. *
  425. * PARAMETERS:
  426. * DWORD dwIndex [in] snapin index
  427. * IDataObject *pCutDataObject [in] items to be removed
  428. *
  429. * RETURNS:
  430. * SC - result code
  431. *
  432. \***************************************************************************/
  433. STDMETHODIMP CMMCClipBoardDataObject::RemoveCutItems( DWORD dwIndex, IDataObject *pCutDataObject )
  434. {
  435. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::RemoveCutItems"));
  436. // this is the only method allowed to be called on invalid object
  437. // check param
  438. sc = ScCheckPointers(pCutDataObject);
  439. if (sc)
  440. return sc.ToHr();
  441. // more parameter check
  442. if ( dwIndex >= m_SelectionObjects.size() )
  443. return (sc = E_INVALIDARG).ToHr();
  444. // get to the snapin
  445. IComponent *pComponent = m_SelectionObjects[dwIndex].spComponent;
  446. sc = ScCheckPointers( pComponent, E_UNEXPECTED );
  447. if (sc)
  448. return sc.ToHr();
  449. sc = pComponent->Notify( NULL, MMCN_CUTORMOVE,
  450. reinterpret_cast<LONG_PTR>(pCutDataObject), 0 );
  451. if (sc)
  452. return sc.ToHr();
  453. return sc.ToHr();
  454. }
  455. ///////////////////////////////////////////////////////////////////////////////
  456. /***************************************************************************\
  457. *
  458. * METHOD: CMMCClipBoardDataObject::ScCreateInstance
  459. *
  460. * PURPOSE: Helper method (static) to create instance of CMMCClipBoardDataObject
  461. *
  462. * PARAMETERS:
  463. * DATA_SOURCE_ACTION operation [in] why the object is created
  464. * CMTNode *pTiedObj [in] object to trigger revoking
  465. * CMMCClipBoardDataObject **ppRawObject [out] raw pointer
  466. * IMMCClipboardDataObject **ppInterface [out] pointer to interface
  467. *
  468. * RETURNS:
  469. * SC - result code
  470. *
  471. \***************************************************************************/
  472. SC CMMCClipBoardDataObject::ScCreateInstance(DATA_SOURCE_ACTION operation,
  473. CMMCClipBoardDataObject **ppRawObject,
  474. IMMCClipboardDataObject **ppInterface)
  475. {
  476. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScCreateInstance"));
  477. // parameter check;
  478. sc = ScCheckPointers( ppRawObject, ppInterface );
  479. if (sc)
  480. return sc;
  481. // out param initialization
  482. *ppInterface = NULL;
  483. *ppRawObject = NULL;
  484. typedef CComObject<CMMCClipBoardDataObject> CreatedObj;
  485. CreatedObj *pCreatedObj;
  486. sc = CreatedObj::CreateInstance( &pCreatedObj );
  487. if (sc)
  488. return sc;
  489. // add first reference if non null;
  490. IMMCClipboardDataObjectPtr spMMCDataObject = pCreatedObj;
  491. // recheck
  492. sc = ScCheckPointers( spMMCDataObject, E_UNEXPECTED );
  493. if (sc)
  494. {
  495. delete pCreatedObj;
  496. return sc;
  497. }
  498. // init the object
  499. static_cast<CMMCClipBoardDataObject *>(pCreatedObj)->m_eOperation = operation;
  500. // return 'em
  501. *ppInterface = spMMCDataObject.Detach();
  502. *ppRawObject = pCreatedObj;
  503. return sc;
  504. }
  505. /***************************************************************************\
  506. *
  507. * METHOD: CMMCClipBoardDataObject::ScAddSnapinDataObject
  508. *
  509. * PURPOSE: Part of creating DO for the operation
  510. * Adds snapins data to be carried inside
  511. *
  512. * PARAMETERS:
  513. * IComponent *pComponent [in] - source snapin, which data id added
  514. * IDataObject *pObject [in] - data object supplied by snapin
  515. * bool bCopyEnabled [in] - if snapin allows to copy the data
  516. * bool bCutEnabled [in] - if snapin allows to move the data
  517. *
  518. * RETURNS:
  519. * SC - result code
  520. *
  521. \***************************************************************************/
  522. SC CMMCClipBoardDataObject::ScAddSnapinDataObject( const CNodePtrArray& nodes,
  523. IComponent *pComponent,
  524. IDataObject *pObject,
  525. bool bCopyEnabled, bool bCutEnabled )
  526. {
  527. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScAddSnapinDataObject"));
  528. // parameter check
  529. sc = ScCheckPointers( pComponent, pObject );
  530. if (sc)
  531. return sc;
  532. // create the object;
  533. ObjectEntry object;
  534. object.dwSnapinOptions = (bCopyEnabled ? COPY_ALLOWED : 0) |
  535. (bCutEnabled ? MOVE_ALLOWED : 0);
  536. object.spComponent = pComponent;
  537. object.spDataObject = pObject;
  538. // register the nodes to invalidate this data object on destruction
  539. for ( CNodePtrArray::const_iterator it = nodes.begin(); it != nodes.end(); ++it )
  540. {
  541. CNode *pNode = *it;
  542. sc = ScCheckPointers( pNode, E_UNEXPECTED );
  543. if (sc)
  544. return sc;
  545. // register node to revoke this object from destructor
  546. sc = CNode::CDataObjectCleanup::ScRegisterNode( pNode, this );
  547. if (sc)
  548. return sc;
  549. }
  550. // add to the array
  551. m_SelectionObjects.push_back(object);
  552. return sc;
  553. }
  554. /***************************************************************************\
  555. *
  556. * METHOD: CMMCClipBoardDataObject::GetNodeCopyAndCutVerbs
  557. *
  558. * PURPOSE: Calculates if copy and cut verb are enabled for node
  559. *
  560. * PARAMETERS:
  561. * CNode* pNode [in] node to examine
  562. * IDataObject *pDataObject [in] snapin's data object
  563. * bool bScopePane [in] Scope or result (item for which the verb states needed).
  564. * LPARAM lvData [in] If result then the LVDATA.
  565. * bool *pCopyEnabled [out] true == Copy verb enabled
  566. * bool *bCutEnabled [out] true == Cut verb enabled
  567. *
  568. * RETURNS:
  569. * SC - result code
  570. *
  571. \***************************************************************************/
  572. SC CMMCClipBoardDataObject::ScGetNodeCopyAndCutVerbs( CNode* pNode, IDataObject *pDataObject,
  573. bool bScopePane, LPARAM lvData,
  574. bool *pbCopyEnabled, bool *pbCutEnabled )
  575. {
  576. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScGetNodeCopyAndCutVerbs"));
  577. // paramter check
  578. sc = ScCheckPointers(pNode, pDataObject, pbCopyEnabled, pbCutEnabled);
  579. if (sc)
  580. return sc;
  581. // init out parameters
  582. *pbCopyEnabled = *pbCutEnabled = false;
  583. // Create temp verb with given context.
  584. CComObject<CTemporaryVerbSet> stdVerbTemp;
  585. sc = stdVerbTemp.ScInitialize(pDataObject, pNode, bScopePane, lvData);
  586. BOOL bFlag = FALSE;
  587. stdVerbTemp.GetVerbState(MMC_VERB_COPY, ENABLED, &bFlag);
  588. *pbCopyEnabled = bFlag;
  589. stdVerbTemp.GetVerbState(MMC_VERB_CUT, ENABLED, &bFlag);
  590. *pbCutEnabled = bFlag;
  591. return sc;
  592. }
  593. /***************************************************************************\
  594. *
  595. * METHOD: CMMCClipBoardDataObject::ScCreate
  596. *
  597. * PURPOSE: helper. Creates and initializes CMMCClipBoardDataObject
  598. *
  599. * PARAMETERS:
  600. * DATA_SOURCE_ACTION operation [in] - for which operation (d&d, cut, copy)
  601. * CNode* pNode [in] - Node to tie to
  602. * bool bScopePane [in] - if it is scope pane operation
  603. * bool bMultiSelect [in] - if it is multiselection
  604. * LPARAM lvData [in] - lvdata for result item
  605. * IMMCClipboardDataObject **ppMMCDO [out] - created data object
  606. * bool& bContainsItems [out] - If snapin does not support cut/copy then
  607. * dataobjets will not be added and this is
  608. * not an error
  609. *
  610. * RETURNS:
  611. * SC - result code
  612. *
  613. \***************************************************************************/
  614. SC CMMCClipBoardDataObject::ScCreate( DATA_SOURCE_ACTION operation,
  615. CNode* pNode, bool bScopePane,
  616. bool bMultiSelect, LPARAM lvData,
  617. IMMCClipboardDataObject **ppMMCDataObject,
  618. bool& bContainsItems )
  619. {
  620. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::Create"));
  621. bContainsItems = false;
  622. // parameter check
  623. sc = ScCheckPointers( ppMMCDataObject, pNode );
  624. if (sc)
  625. return sc;
  626. // init out param
  627. *ppMMCDataObject = NULL;
  628. // get MT node, view data;
  629. CMTNode* pMTNode = pNode->GetMTNode();
  630. CViewData *pViewData = pNode->GetViewData();
  631. sc = ScCheckPointers( pMTNode, pViewData, E_UNEXPECTED );
  632. if (sc)
  633. return sc;
  634. // create data object to be used for data transfer
  635. CMMCClipBoardDataObject *pResultObject = NULL;
  636. IMMCClipboardDataObjectPtr spResultInterface;
  637. sc = ScCreateInstance(operation, &pResultObject, &spResultInterface);
  638. if (sc)
  639. return sc;
  640. // recheck pointers
  641. sc = ScCheckPointers( pResultObject, spResultInterface, E_UNEXPECTED );
  642. if (sc)
  643. return sc;
  644. // valid from the start
  645. pResultObject->m_bObjectValid = true;
  646. // add data to the object...
  647. if (!bMultiSelect) // single selection
  648. {
  649. // get snapins data object
  650. IDataObjectPtr spDataObject;
  651. CComponent* pCComponent;
  652. bool bScopeItem = bScopePane;
  653. sc = pNode->ScGetDataObject(bScopePane, lvData, bScopeItem, &spDataObject, &pCComponent);
  654. if (sc)
  655. return sc;
  656. // recheck data object
  657. if ( IS_SPECIAL_DATAOBJECT ( spDataObject.GetInterfacePtr() ) )
  658. {
  659. spDataObject.Detach();
  660. return sc = E_UNEXPECTED;
  661. }
  662. sc = ScCheckPointers(pCComponent, E_UNEXPECTED);
  663. if (sc)
  664. return sc;
  665. IComponent *pComponent = pCComponent->GetIComponent();
  666. sc = ScCheckPointers(pComponent, E_UNEXPECTED);
  667. if (sc)
  668. return sc;
  669. // add snapin's data object to transfer object
  670. sc = pResultObject->ScAddDataObjectForItem( pNode, bScopePane, lvData,
  671. pComponent, spDataObject,
  672. bContainsItems );
  673. if (sc)
  674. return sc;
  675. if (! bContainsItems)
  676. return sc;
  677. }
  678. else // result pane : multi selection
  679. {
  680. // get pointer to multiselection
  681. CMultiSelection *pMultiSel = pViewData->GetMultiSelection();
  682. sc = ScCheckPointers( pMultiSel, E_UNEXPECTED );
  683. if (sc)
  684. return sc;
  685. sc = pMultiSel->ScGetSnapinDataObjects(pResultObject);
  686. if (sc)
  687. return sc;
  688. }
  689. // if no items were added, something is wrong
  690. DWORD dwCount = 0;
  691. sc = pResultObject->GetCount( &dwCount );
  692. if (sc)
  693. return sc;
  694. if ( dwCount == 0 )
  695. return sc = E_UNEXPECTED;
  696. bContainsItems = true;
  697. // return interface
  698. *ppMMCDataObject = spResultInterface.Detach();
  699. return sc;
  700. }
  701. /***************************************************************************\
  702. *
  703. * METHOD: CMMCClipBoardDataObject::ScAddDataObjectForItem
  704. *
  705. * PURPOSE: Adds data object for one item
  706. *
  707. * PARAMETERS:
  708. * CNode* pNode [in] - node to add (or one owning the item)
  709. * bool bScopePane [in] - if operation is on scope pane
  710. * LPARAM lvData [in] - if result pane the LVDATA
  711. * IComponent *pComponent [in] - snapins interface
  712. * IDataObject *pDataObject [in] - data object to add
  713. * bool& bContainsItems [out] - Are there any dataobjects added?
  714. *
  715. * RETURNS:
  716. * SC - result code
  717. *
  718. \***************************************************************************/
  719. SC CMMCClipBoardDataObject::ScAddDataObjectForItem( CNode* pNode, bool bScopePane,
  720. LPARAM lvData, IComponent *pComponent,
  721. IDataObject *pDataObject ,
  722. bool& bContainsItems)
  723. {
  724. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScAddDataObjectForScopeNode"));
  725. // Init out param.
  726. bContainsItems = false;
  727. // paramter check
  728. sc = ScCheckPointers( pNode, pComponent, pDataObject );
  729. if (sc)
  730. return sc;
  731. // get the verbs
  732. bool bCopyEnabled = false;
  733. bool bCutEnabled = false;
  734. sc = ScGetNodeCopyAndCutVerbs( pNode, pDataObject, bScopePane, lvData, &bCopyEnabled, &bCutEnabled);
  735. if (sc)
  736. return sc;
  737. // see it the data matches our criteria
  738. // (needs to allow something at least)
  739. if ( ( (m_eOperation == ACTION_COPY) && (bCopyEnabled == false) )
  740. || ( (m_eOperation == ACTION_CUT) && (bCutEnabled == false) )
  741. || ( (bCutEnabled == false) && (bCopyEnabled == false) ) )
  742. return sc = S_FALSE;
  743. // add to the list
  744. sc = ScAddSnapinDataObject( CNodePtrArray(1, pNode), pComponent, pDataObject, bCopyEnabled, bCutEnabled );
  745. if (sc)
  746. return sc;
  747. bContainsItems = true;
  748. return sc;
  749. }
  750. /***************************************************************************\
  751. *
  752. * METHOD: CMMCClipBoardDataObject::GetWrapperCF
  753. *
  754. * PURPOSE: Helper. registers and returns own clipboard format
  755. *
  756. * PARAMETERS:
  757. *
  758. * RETURNS:
  759. * CLIPFORMAT
  760. *
  761. \***************************************************************************/
  762. CLIPFORMAT CMMCClipBoardDataObject::GetWrapperCF()
  763. {
  764. static CLIPFORMAT s_cf = 0;
  765. if (s_cf == 0)
  766. s_cf = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_MMC_INTERNAL"));
  767. return s_cf;
  768. }
  769. /***************************************************************************\
  770. *
  771. * METHOD: CMMCClipBoardDataObject::ScEnsureNotInClipboard
  772. *
  773. * PURPOSE: called to remove data from clipbord when comonent is destoyed
  774. *
  775. * PARAMETERS:
  776. *
  777. * RETURNS:
  778. * SC - result code
  779. *
  780. \***************************************************************************/
  781. SC CMMCClipBoardDataObject::ScInvalidate( void )
  782. {
  783. DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScEnsureNotInClipboard"));
  784. // not valid anymore
  785. m_bObjectValid = false;
  786. // release data objects
  787. for ( int i = 0; i< m_SelectionObjects.size(); i++)
  788. m_SelectionObjects[i].spDataObject = NULL;
  789. // check the clipboard
  790. sc = ::OleIsCurrentClipboard( this );
  791. if (sc)
  792. return sc;
  793. // it is on clipboard - remove
  794. if (sc == S_OK)
  795. OleSetClipboard(NULL);
  796. return sc;
  797. }
  798. ///////////////////////////////////////////////////////////////////////////////
  799. ///////////////////////////////////////////////////////////////////////////////