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.

970 lines
22 KiB

  1. // SnapinDataObject.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "ScopePaneItem.h"
  5. #include "ResultsPaneItem.h"
  6. #include "SnapinDataObject.h"
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CSnapinDataObject
  14. UINT CSnapinDataObject::s_cfInternal = 0;
  15. UINT CSnapinDataObject::s_cfExtension = 0;
  16. // *CLEAN ME*
  17. LPCTSTR CF_SNAPIN_INTERNAL = _T("HealthMonitor");
  18. LPCTSTR CF_SNAPIN_EXTENSION = _T("HealthMonitorExtension");
  19. // *CLEAN ME*
  20. // {FBBB8DAE-AB34-11d2-BD62-0000F87A3912}
  21. static const GUID CLSID_SnapIn =
  22. { 0xfbbb8dae, 0xab34, 0x11d2, { 0xbd, 0x62, 0x0, 0x0, 0xf8, 0x7a, 0x39, 0x12 } };
  23. //{ 0x69a539f8, 0x9520, 0x11d2, { 0xbd, 0x4a, 0x0, 0x0, 0xf8, 0x7a, 0x39, 0x12 } };
  24. IMPLEMENT_DYNCREATE(CSnapinDataObject, CCmdTarget)
  25. CSnapinDataObject::CSnapinDataObject()
  26. {
  27. TRACEX(_T("CSnapinDataObject::CSnapinDataObject\n"));
  28. EnableAutomation();
  29. // To keep the application running as long as an OLE automation
  30. // object is active, the constructor calls AfxOleLockApp.
  31. AfxOleLockApp();
  32. if( ! RegisterClipboardFormats() )
  33. {
  34. TRACE(_T("FAILED : RegisterClipboardFormats failed.\n"));
  35. ASSERT(FALSE);
  36. }
  37. m_ulCookie = 0;
  38. m_ItemType = CCT_UNINITIALIZED;
  39. }
  40. CSnapinDataObject::~CSnapinDataObject()
  41. {
  42. // To terminate the application when all objects created with
  43. // with OLE automation, the destructor calls AfxOleUnlockApp.
  44. AfxOleUnlockApp();
  45. }
  46. /////////////////////////////////////////////////////////////////////////////
  47. // Clipboard Members
  48. inline bool CSnapinDataObject::RegisterClipboardFormats()
  49. {
  50. if( ! s_cfInternal )
  51. s_cfInternal = RegisterClipboardFormat(CF_SNAPIN_INTERNAL);
  52. if( ! s_cfExtension )
  53. s_cfExtension = RegisterClipboardFormat(CF_SNAPIN_EXTENSION);
  54. m_cfDisplayName = RegisterClipboardFormat(CCF_DISPLAY_NAME);
  55. m_cfSPIGuid = RegisterClipboardFormat(CCF_NODETYPE);
  56. m_cfSnapinCLSID = RegisterClipboardFormat(CCF_SNAPIN_CLASSID);
  57. return s_cfInternal && s_cfExtension && m_cfDisplayName && m_cfSPIGuid && m_cfSnapinCLSID;
  58. }
  59. /////////////////////////////////////////////////////////////////////////////
  60. // Item Members
  61. DATA_OBJECT_TYPES CSnapinDataObject::GetItemType()
  62. {
  63. TRACEX(_T("CSnapinDataObject::GetItemType\n"));
  64. TRACEARGn(m_ItemType);
  65. return m_ItemType;
  66. }
  67. ULONG CSnapinDataObject::GetCookie()
  68. {
  69. TRACEX(_T("CSnapinDataObject::GetCookie\n"));
  70. TRACEARGn(m_ulCookie);
  71. return m_ulCookie;
  72. }
  73. bool CSnapinDataObject::GetItem(CScopePaneItem*& pSPItem)
  74. {
  75. TRACEX(_T("CSnapinDataObject::GetItem(SPI)\n"));
  76. if( GetItemType() != CCT_SCOPE )
  77. {
  78. TRACE(_T("WARNING : Item is not of type CCT_SCOPE.\n"));
  79. pSPItem = NULL;
  80. return false;
  81. }
  82. pSPItem = (CScopePaneItem*)GetCookie();
  83. if( ! CHECKOBJPTR(pSPItem,RUNTIME_CLASS(CScopePaneItem),sizeof(CScopePaneItem)) )
  84. {
  85. TRACE(_T("FAILED : The cookie is invalid or corrupt.\n"));
  86. pSPItem = NULL;
  87. return false;
  88. }
  89. return true;
  90. }
  91. bool CSnapinDataObject::GetItem(CResultsPaneItem*& pRPItem)
  92. {
  93. TRACEX(_T("CSnapinDataObject::GetItem(RPI)\n"));
  94. if( GetItemType() != CCT_RESULT )
  95. {
  96. TRACE(_T("WARNING : Item is not of type CCT_RESULT.\n"));
  97. pRPItem = NULL;
  98. return false;
  99. }
  100. pRPItem = (CResultsPaneItem*)GetCookie();
  101. if( ! CHECKOBJPTR(pRPItem,RUNTIME_CLASS(CResultsPaneItem),sizeof(CResultsPaneItem)) )
  102. {
  103. TRACE(_T("FAILED : The cookie is invalid or corrupt.\n"));
  104. pRPItem = NULL;
  105. return false;
  106. }
  107. return true;
  108. }
  109. void CSnapinDataObject::SetItem(CScopePaneItem* pSPItem)
  110. {
  111. TRACEX(_T("CSnapinDataObject::SetItem(SPI)\n"));
  112. TRACEARGn(pSPItem);
  113. if( ! CHECKOBJPTR(pSPItem,RUNTIME_CLASS(CScopePaneItem),sizeof(CScopePaneItem)) )
  114. {
  115. TRACE(_T("FAILED : pSPItem is an invalid CScopePaneItem pointer.\n"));
  116. m_ulCookie = NULL;
  117. m_ItemType = CCT_UNINITIALIZED;
  118. return;
  119. }
  120. #ifndef IA64
  121. m_ulCookie = (ULONG)pSPItem;
  122. #endif // IA64
  123. m_ItemType = CCT_SCOPE;
  124. }
  125. void CSnapinDataObject::SetItem(CResultsPaneItem* pRPItem)
  126. {
  127. TRACEX(_T("CSnapinDataObject::SetItem(RPI)\n"));
  128. TRACEARGn(pRPItem);
  129. if( ! CHECKOBJPTR(pRPItem,RUNTIME_CLASS(CResultsPaneItem),sizeof(CResultsPaneItem)) )
  130. {
  131. TRACE(_T("FAILED : pRPItem is an invalid CResultsPaneItem pointer.\n"));
  132. m_ulCookie = NULL;
  133. m_ItemType = CCT_UNINITIALIZED;
  134. return;
  135. }
  136. #ifndef IA64
  137. m_ulCookie = (ULONG)pRPItem;
  138. #endif // IA64
  139. m_ItemType = CCT_RESULT;
  140. }
  141. /////////////////////////////////////////////////////////////////////////////
  142. // DataObject Members
  143. CSnapinDataObject* CSnapinDataObject::GetSnapinDataObject(LPDATAOBJECT lpDataObject)
  144. {
  145. TRACEX(_T("CSnapinDataObject::GetSnapinDataObject\n"));
  146. TRACEARGn(lpDataObject);
  147. if( ! CHECKPTR(lpDataObject,sizeof(IDataObject)) )
  148. {
  149. TRACE(_T("FAILED : lpDataObject pointer is invalid!\n"));
  150. return NULL;
  151. }
  152. HGLOBAL hGlobal = NULL;
  153. CSnapinDataObject* psdo = NULL;
  154. HRESULT hr = GetDataObject( lpDataObject, CSnapinDataObject::s_cfInternal, sizeof(CSnapinDataObject**), &hGlobal );
  155. if( hr == DV_E_FORMATETC || ! CHECKHRESULT(hr) )
  156. {
  157. return NULL;
  158. }
  159. psdo = *((CSnapinDataObject**)(hGlobal));
  160. if( ! CHECKOBJPTR(psdo,RUNTIME_CLASS(CSnapinDataObject),sizeof(CSnapinDataObject)) )
  161. {
  162. return NULL;
  163. }
  164. GlobalFree(hGlobal);
  165. return psdo;
  166. }
  167. HRESULT CSnapinDataObject::GetDataObject(LPDATAOBJECT lpDataObject, UINT cfClipFormat, ULONG nByteCount, HGLOBAL* phGlobal)
  168. {
  169. TRACEX(_T("CSnapinDataObject::GetDataObject\n"));
  170. TRACEARGn(lpDataObject);
  171. TRACEARGn(cfClipFormat);
  172. TRACEARGn(nByteCount);
  173. TRACEARGn(phGlobal);
  174. if( ! CHECKPTR(lpDataObject,sizeof(IDataObject)) )
  175. {
  176. TRACE(_T("FAILED : lpDataObject is invalid.\n"));
  177. return E_FAIL;
  178. }
  179. HRESULT hr = S_OK;
  180. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  181. FORMATETC formatetc = { (unsigned short)cfClipFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  182. *phGlobal = NULL;
  183. // Allocate memory for the stream
  184. stgmedium.hGlobal = GlobalAlloc( GMEM_SHARE, nByteCount );
  185. if( ! stgmedium.hGlobal )
  186. {
  187. hr = E_OUTOFMEMORY;
  188. TRACE(_T("FAILED : Out of Memory.\n"));
  189. return hr;
  190. }
  191. // Attempt to get data from the object
  192. hr = lpDataObject->GetDataHere( &formatetc, &stgmedium );
  193. if( hr == DV_E_FORMATETC || ! CHECKHRESULT(hr) )
  194. {
  195. TRACE(_T("lpDataObject->GetDataFromHere failed.\n"));
  196. GlobalFree(stgmedium.hGlobal);
  197. stgmedium.hGlobal = NULL;
  198. return hr;
  199. }
  200. // stgmedium now has the data we need
  201. *phGlobal = stgmedium.hGlobal;
  202. stgmedium.hGlobal = NULL;
  203. return hr;
  204. }
  205. /////////////////////////////////////////////////////////////////////////////
  206. // Write Members
  207. HRESULT CSnapinDataObject::WriteGuid(LPSTREAM pStream)
  208. {
  209. TRACEX(_T("CSnapinDataObject::WriteGuid\n"));
  210. TRACEARGn(pStream);
  211. if( ! CHECKPTR(pStream,sizeof(IStream)) )
  212. {
  213. TRACE(_T("FAILED : Invalid IStream pointer passed.\n"));
  214. return E_FAIL;
  215. }
  216. LPGUID pGuid = NULL;
  217. if( GetItemType() == CCT_SCOPE )
  218. {
  219. CScopePaneItem* pItem = NULL;
  220. if( ! GetItem(pItem) )
  221. {
  222. return S_OK;
  223. }
  224. ASSERT(pItem);
  225. pGuid = pItem->GetItemType();
  226. }
  227. else if( GetItemType() == CCT_RESULT )
  228. {
  229. CResultsPaneItem* pItem = NULL;
  230. if( ! GetItem(pItem) )
  231. {
  232. return S_OK;
  233. }
  234. ASSERT(pItem);
  235. pGuid = pItem->GetItemType();
  236. if( ! pGuid )
  237. {
  238. return S_OK;
  239. }
  240. }
  241. if( pGuid == NULL )
  242. {
  243. TRACE(_T("FAILED : CScopePaneItem::GetItemType returns NULL.\n"));
  244. return E_FAIL;
  245. }
  246. return pStream->Write( (LPVOID)pGuid, sizeof(GUID), NULL );
  247. }
  248. HRESULT CSnapinDataObject::WriteDisplayName(LPSTREAM pStream)
  249. {
  250. TRACEX(_T("CSnapinDataObject::WriteDisplayName\n"));
  251. TRACEARGn(pStream);
  252. if( ! CHECKPTR(pStream,sizeof(IStream)) )
  253. {
  254. TRACE(_T("FAILED : Invalid IStream pointer passed.\n"));
  255. return E_FAIL;
  256. }
  257. CString sDisplayName;
  258. switch(GetItemType())
  259. {
  260. case CCT_SCOPE:
  261. {
  262. CScopePaneItem* pItem = NULL;
  263. if( ! GetItem(pItem) )
  264. {
  265. TRACE(_T("FAILED : GetItem failed.\n"));
  266. return E_FAIL;
  267. }
  268. ASSERT(pItem);
  269. sDisplayName = pItem->GetDisplayName();
  270. }
  271. break;
  272. case CCT_RESULT:
  273. {
  274. CResultsPaneItem* pItem = NULL;
  275. if( ! GetItem(pItem) )
  276. {
  277. TRACE(_T("FAILED : GetItem failed.\n"));
  278. return E_FAIL;
  279. }
  280. ASSERT(pItem);
  281. sDisplayName = pItem->GetDisplayName();
  282. }
  283. break;
  284. }
  285. ULONG ulSizeofName = sDisplayName.GetLength() + 1;
  286. ulSizeofName *= sizeof(TCHAR);
  287. return pStream->Write(sDisplayName, ulSizeofName, NULL);
  288. }
  289. HRESULT CSnapinDataObject::WriteSnapinCLSID(LPSTREAM pStream)
  290. {
  291. TRACEX(_T("CSnapinDataObject::WriteSnapinCLSID\n"));
  292. TRACEARGn(pStream);
  293. if( ! CHECKPTR(pStream,sizeof(IStream)) )
  294. {
  295. TRACE(_T("FAILED : Invalid IStream pointer passed.\n"));
  296. return E_FAIL;
  297. }
  298. return pStream->Write(&CLSID_SnapIn,sizeof(CLSID_SnapIn),NULL);
  299. }
  300. HRESULT CSnapinDataObject::WriteDataObject(LPSTREAM pStream)
  301. {
  302. TRACEX(_T("CSnapinDataObject::WriteDataObject\n"));
  303. TRACEARGn(pStream);
  304. if( ! CHECKPTR(pStream,sizeof(IStream)) )
  305. {
  306. TRACE(_T("FAILED : Invalid IStream pointer passed.\n"));
  307. return E_FAIL;
  308. }
  309. CSnapinDataObject* pThis = this;
  310. return pStream->Write(&pThis,sizeof(CSnapinDataObject*),NULL);
  311. }
  312. HRESULT CSnapinDataObject::WriteExtensionData(LPSTREAM pStream)
  313. {
  314. TRACEX(_T("CSnapinDataObject::WriteExtensionData\n"));
  315. TRACEARGn(pStream);
  316. if( ! CHECKPTR(pStream,sizeof(IStream)) )
  317. {
  318. TRACE(_T("FAILED : Invalid IStream pointer passed.\n"));
  319. return E_FAIL;
  320. }
  321. switch(GetItemType())
  322. {
  323. case CCT_SCOPE:
  324. {
  325. CScopePaneItem* pItem = NULL;
  326. if( ! GetItem(pItem) )
  327. {
  328. TRACE(_T("FAILED : GetItem failed.\n"));
  329. return E_FAIL;
  330. }
  331. ASSERT(pItem);
  332. return pItem->WriteExtensionData(pStream);
  333. }
  334. break;
  335. case CCT_RESULT:
  336. {
  337. CResultsPaneItem* pItem = NULL;
  338. if( ! GetItem(pItem) )
  339. {
  340. TRACE(_T("FAILED : GetItem failed.\n"));
  341. return E_FAIL;
  342. }
  343. ASSERT(pItem);
  344. return pItem->WriteExtensionData(pStream);
  345. }
  346. break;
  347. }
  348. return E_FAIL;
  349. }
  350. /////////////////////////////////////////////////////////////////////////////
  351. // MFC Implementation Members
  352. void CSnapinDataObject::OnFinalRelease()
  353. {
  354. // When the last reference for an automation object is released
  355. // OnFinalRelease is called. The base class will automatically
  356. // deletes the object. Add additional cleanup required for your
  357. // object before calling the base class.
  358. CCmdTarget::OnFinalRelease();
  359. }
  360. BEGIN_MESSAGE_MAP(CSnapinDataObject, CCmdTarget)
  361. //{{AFX_MSG_MAP(CSnapinDataObject)
  362. // NOTE - the ClassWizard will add and remove mapping macros here.
  363. //}}AFX_MSG_MAP
  364. END_MESSAGE_MAP()
  365. BEGIN_DISPATCH_MAP(CSnapinDataObject, CCmdTarget)
  366. //{{AFX_DISPATCH_MAP(CSnapinDataObject)
  367. // NOTE - the ClassWizard will add and remove mapping macros here.
  368. //}}AFX_DISPATCH_MAP
  369. END_DISPATCH_MAP()
  370. // Note: we add support for IID_ISnapinDataObject to support typesafe binding
  371. // from VBA. This IID must match the GUID that is attached to the
  372. // dispinterface in the .ODL file.
  373. // {7D4A685E-9056-11D2-BD45-0000F87A3912}
  374. static const IID IID_ISnapinDataObject =
  375. { 0x7d4a685e, 0x9056, 0x11d2, { 0xbd, 0x45, 0x0, 0x0, 0xf8, 0x7a, 0x39, 0x12 } };
  376. BEGIN_INTERFACE_MAP(CSnapinDataObject, CCmdTarget)
  377. INTERFACE_PART(CSnapinDataObject, IID_ISnapinDataObject, Dispatch)
  378. INTERFACE_PART(CSnapinDataObject, IID_IDataObject, DataObject)
  379. END_INTERFACE_MAP()
  380. // {01CB0090-AFCB-11d2-BD6B-0000F87A3912}
  381. IMPLEMENT_OLECREATE_EX(CSnapinDataObject, "SnapIn.SnapinDataObject",
  382. 0x1cb0090, 0xafcb, 0x11d2, 0xbd, 0x6b, 0x0, 0x0, 0xf8, 0x7a, 0x39, 0x12);
  383. BOOL CSnapinDataObject::CSnapinDataObjectFactory::UpdateRegistry(BOOL bRegister)
  384. {
  385. if (bRegister)
  386. return AfxOleRegisterServerClass(m_clsid, m_lpszProgID, m_lpszProgID, m_lpszProgID, OAT_DISPATCH_OBJECT);
  387. else
  388. return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
  389. }
  390. /////////////////////////////////////////////////////////////////////////////
  391. // IDataObject Interface Part
  392. ULONG FAR EXPORT CSnapinDataObject::XDataObject::AddRef()
  393. {
  394. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  395. return pThis->ExternalAddRef();
  396. }
  397. ULONG FAR EXPORT CSnapinDataObject::XDataObject::Release()
  398. {
  399. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  400. return pThis->ExternalRelease();
  401. }
  402. HRESULT FAR EXPORT CSnapinDataObject::XDataObject::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
  403. {
  404. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  405. return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
  406. }
  407. HRESULT FAR EXPORT CSnapinDataObject::XDataObject::GetData(
  408. /* [unique][in] */ FORMATETC __RPC_FAR *pformatetcIn,
  409. /* [out] */ STGMEDIUM __RPC_FAR *pmedium)
  410. {
  411. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  412. TRACEX(_T("CSnapinDataObject::XDataObject::GetData"));
  413. TRACEARGn(pformatetcIn);
  414. TRACEARGn(pmedium);
  415. HRESULT hr = S_OK;
  416. // Make sure FORMATETC is something we can handle.
  417. if( !(DVASPECT_CONTENT & pformatetcIn->dwAspect) ||
  418. !(TYMED_HGLOBAL & pformatetcIn->tymed) )
  419. {
  420. hr = DATA_E_FORMATETC;
  421. }
  422. if( S_OK == hr )
  423. {
  424. if( s_cfExtension == pformatetcIn->cfFormat )
  425. {
  426. IStream *pStream = NULL;
  427. // Allocate memory for the stream
  428. pmedium->hGlobal = GlobalAlloc( GMEM_SHARE, 1024 );
  429. if( ! pmedium->hGlobal )
  430. {
  431. hr = E_OUTOFMEMORY;
  432. TRACE(_T("FAILED : Out of Memory.\n"));
  433. return hr;
  434. }
  435. hr = CreateStreamOnHGlobal( pmedium->hGlobal, FALSE, &pStream );
  436. hr = pThis->WriteExtensionData( pStream );
  437. pStream->Release();
  438. }
  439. else
  440. {
  441. hr = DATA_E_FORMATETC;
  442. }
  443. }
  444. return hr;
  445. }
  446. HRESULT FAR EXPORT CSnapinDataObject::XDataObject::GetDataHere(
  447. /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
  448. /* [out][in] */ STGMEDIUM __RPC_FAR *pmedium)
  449. {
  450. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  451. TRACEX(_T("CSnapinDataObject::XDataObject::GetDataHere"));
  452. TRACEARGn(pformatetc);
  453. TRACEARGn(pmedium);
  454. HRESULT hr = DV_E_FORMATETC; // Unknown format
  455. const CLIPFORMAT cf = pformatetc->cfFormat;
  456. IStream *pStream = NULL;
  457. pmedium->pUnkForRelease = NULL; // by OLE spec
  458. // Write data to the stream based
  459. // on the clipformat
  460. hr = CreateStreamOnHGlobal( pmedium->hGlobal, FALSE, &pStream );
  461. if( ! CHECKHRESULT(hr) )
  462. {
  463. TRACE(_T("FAILED : Failed on call to CreateStreamOnHGlobal.\n"));
  464. return hr; // Minimal error checking
  465. }
  466. if( pThis->m_cfDisplayName == cf )
  467. {
  468. hr = pThis->WriteDisplayName( pStream );
  469. }
  470. else if( pThis->s_cfInternal == cf )
  471. {
  472. hr = pThis->WriteDataObject( pStream );
  473. }
  474. else if( pThis->s_cfExtension == cf )
  475. {
  476. hr = pThis->WriteExtensionData( pStream );
  477. }
  478. else if( pThis->m_cfSPIGuid == cf )
  479. {
  480. hr = pThis->WriteGuid( pStream );
  481. }
  482. else if( pThis->m_cfSnapinCLSID == cf )
  483. {
  484. hr = pThis->WriteSnapinCLSID( pStream );
  485. }
  486. pStream->Release();
  487. return hr;
  488. }
  489. HRESULT FAR EXPORT CSnapinDataObject::XDataObject::QueryGetData(
  490. /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc)
  491. {
  492. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  493. TRACEX(_T("CSnapinDataObject::XDataObject::QueryGetData"));
  494. TRACEARGn(pformatetc);
  495. HRESULT hr = S_OK;
  496. // For this sample, we just do a simple test.
  497. if( s_cfExtension == pformatetc->cfFormat )
  498. hr = S_OK;
  499. else
  500. hr = S_FALSE;
  501. return hr;
  502. }
  503. HRESULT FAR EXPORT CSnapinDataObject::XDataObject::GetCanonicalFormatEtc(
  504. /* [unique][in] */ FORMATETC __RPC_FAR *pformatectIn,
  505. /* [out] */ FORMATETC __RPC_FAR *pformatetcOut)
  506. {
  507. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  508. TRACEX(_T("CSnapinDataObject::XDataObject::GetCanonicalFormatEtc"));
  509. TRACEARGn(pformatectIn);
  510. TRACEARGn(pformatetcOut);
  511. return E_NOTIMPL;
  512. }
  513. HRESULT FAR EXPORT CSnapinDataObject::XDataObject::SetData(
  514. /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
  515. /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium,
  516. /* [in] */ BOOL fRelease)
  517. {
  518. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  519. TRACEX(_T("CSnapinDataObject::XDataObject::SetData"));
  520. TRACEARGn(pformatetc);
  521. TRACEARGn(pmedium);
  522. TRACEARGn(fRelease);
  523. return E_NOTIMPL;
  524. }
  525. HRESULT FAR EXPORT CSnapinDataObject::XDataObject::EnumFormatEtc(
  526. /* [in] */ DWORD dwDirection,
  527. /* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenumFormatEtc)
  528. {
  529. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  530. TRACEX(_T("CSnapinDataObject::XDataObject::EnumFormatEtc"));
  531. TRACEARGn(dwDirection);
  532. TRACEARGn(ppenumFormatEtc);
  533. HRESULT hr = S_OK;
  534. static FORMATETC ForEtcArr[1]; // Use array so we can add more later
  535. ForEtcArr[0].cfFormat = (CLIPFORMAT)s_cfExtension;
  536. ForEtcArr[0].dwAspect = DVASPECT_CONTENT;
  537. ForEtcArr[0].ptd = NULL;
  538. ForEtcArr[0].tymed = TYMED_HGLOBAL;
  539. ForEtcArr[0].lindex = -1;
  540. switch( dwDirection )
  541. {
  542. case DATADIR_GET:
  543. *ppenumFormatEtc = new CEnumFormatEtc(1, ForEtcArr);
  544. break;
  545. case DATADIR_SET:
  546. default:
  547. *ppenumFormatEtc = NULL;
  548. break;
  549. }
  550. if( NULL == *ppenumFormatEtc )
  551. {
  552. hr = E_FAIL;
  553. }
  554. else
  555. {
  556. (*ppenumFormatEtc)->AddRef();
  557. hr = S_OK;
  558. }
  559. return hr;
  560. }
  561. HRESULT FAR EXPORT CSnapinDataObject::XDataObject::DAdvise(
  562. /* [in] */ FORMATETC __RPC_FAR *pformatetc,
  563. /* [in] */ DWORD advf,
  564. /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink,
  565. /* [out] */ DWORD __RPC_FAR *pdwConnection)
  566. {
  567. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  568. TRACEX(_T("CSnapinDataObject::XDataObject::DAdvise"));
  569. TRACEARGn(pformatetc);
  570. TRACEARGn(advf);
  571. TRACEARGn(pAdvSink);
  572. TRACEARGn(pdwConnection);
  573. return E_NOTIMPL;
  574. }
  575. HRESULT FAR EXPORT CSnapinDataObject::XDataObject::DUnadvise(
  576. /* [in] */ DWORD dwConnection)
  577. {
  578. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  579. TRACEX(_T("CSnapinDataObject::XDataObject::DUnadvise"));
  580. TRACEARGn(dwConnection);
  581. return E_NOTIMPL;
  582. }
  583. HRESULT FAR EXPORT CSnapinDataObject::XDataObject::EnumDAdvise(
  584. /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise)
  585. {
  586. METHOD_PROLOGUE(CSnapinDataObject, DataObject)
  587. TRACEX(_T("CSnapinDataObject::XDataObject::EnumDAdvise"));
  588. TRACEARGn(ppenumAdvise);
  589. return E_NOTIMPL;
  590. }
  591. /////////////////////////////////////////////////////////////////////////////
  592. // CSnapinDataObject message handlers
  593. /////////////////////////////////////////////////////////////////////////////
  594. // CEnumFormatEtc Implementation
  595. /*
  596. * CEnumFormatEtc::CEnumFormatEtc
  597. * CEnumFormatEtc::~CEnumFormatEtc
  598. *
  599. * Parameters (Constructor):
  600. * cFE ULONG number of FORMATETCs in pFE
  601. * prgFE LPFORMATETC to the array to enumerate.
  602. */
  603. CEnumFormatEtc::CEnumFormatEtc(ULONG cFE, LPFORMATETC prgFE)
  604. {
  605. UINT i;
  606. m_cRef=0;
  607. m_iCur=0;
  608. m_cfe=cFE;
  609. m_prgfe=new FORMATETC[(UINT)cFE];
  610. if (NULL!=m_prgfe)
  611. {
  612. for (i=0; i < cFE; i++)
  613. m_prgfe[i]=prgFE[i];
  614. }
  615. return;
  616. }
  617. CEnumFormatEtc::~CEnumFormatEtc(void)
  618. {
  619. if (NULL!=m_prgfe)
  620. delete [] m_prgfe;
  621. }
  622. /*
  623. * CEnumFormatEtc::QueryInterface
  624. * CEnumFormatEtc::AddRef
  625. * CEnumFormatEtc::Release
  626. *
  627. * Purpose:
  628. * IUnknown members for CEnumFormatEtc object. For QueryInterface
  629. * we only return out own interfaces and not those of the data
  630. * object. However, since enumerating formats only makes sense
  631. * when the data object is around, we insure that it stays as
  632. * long as we stay by calling an outer IUnknown for AddRef
  633. * and Release. But since we are not controlled by the lifetime
  634. * of the outer object, we still keep our own reference count in
  635. * order to free ourselves.
  636. */
  637. STDMETHODIMP CEnumFormatEtc::QueryInterface(REFIID riid, VOID ** ppv)
  638. {
  639. *ppv=NULL;
  640. /*
  641. * Enumerators are separate objects, not the data object, so
  642. * we only need to support out IUnknown and IEnumFORMATETC
  643. * interfaces here with no concern for aggregation.
  644. */
  645. if (IID_IUnknown==riid || IID_IEnumFORMATETC==riid)
  646. *ppv=this;
  647. //AddRef any interface we'll return.
  648. if (NULL!=*ppv)
  649. {
  650. ((LPUNKNOWN)*ppv)->AddRef();
  651. return NOERROR;
  652. }
  653. return ResultFromScode(E_NOINTERFACE);
  654. }
  655. STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef(void)
  656. {
  657. ++m_cRef;
  658. return m_cRef;
  659. }
  660. STDMETHODIMP_(ULONG) CEnumFormatEtc::Release(void)
  661. {
  662. if (0!=--m_cRef)
  663. return m_cRef;
  664. delete this;
  665. return 0;
  666. }
  667. /*
  668. * CEnumFormatEtc::Next
  669. *
  670. * Purpose:
  671. * Returns the next element in the enumeration.
  672. *
  673. * Parameters:
  674. * cFE ULONG number of FORMATETCs to return.
  675. * pFE LPFORMATETC in which to store the returned
  676. * structures.
  677. * pulFE ULONG * in which to return how many we
  678. * enumerated.
  679. *
  680. * Return Value:
  681. * HRESULT NOERROR if successful, S_FALSE otherwise,
  682. */
  683. STDMETHODIMP CEnumFormatEtc::Next(ULONG cFE, LPFORMATETC pFE, ULONG *pulFE)
  684. {
  685. ULONG cReturn=0L;
  686. if (NULL==m_prgfe)
  687. return ResultFromScode(S_FALSE);
  688. if (NULL==pulFE)
  689. {
  690. if (1L!=cFE)
  691. return ResultFromScode(E_POINTER);
  692. }
  693. else
  694. *pulFE=0L;
  695. if (NULL==pFE || m_iCur >= m_cfe)
  696. return ResultFromScode(S_FALSE);
  697. while (m_iCur < m_cfe && cFE > 0)
  698. {
  699. *pFE++=m_prgfe[m_iCur++];
  700. cReturn++;
  701. cFE--;
  702. }
  703. if (NULL!=pulFE)
  704. *pulFE=cReturn;
  705. return NOERROR;
  706. }
  707. /*
  708. * CEnumFormatEtc::Skip
  709. *
  710. * Purpose:
  711. * Skips the next n elements in the enumeration.
  712. *
  713. * Parameters:
  714. * cSkip ULONG number of elements to skip.
  715. *
  716. * Return Value:
  717. * HRESULT NOERROR if successful, S_FALSE if we could not
  718. * skip the requested number.
  719. */
  720. STDMETHODIMP CEnumFormatEtc::Skip(ULONG cSkip)
  721. {
  722. if (((m_iCur+cSkip) >= m_cfe) || NULL==m_prgfe)
  723. return ResultFromScode(S_FALSE);
  724. m_iCur+=cSkip;
  725. return NOERROR;
  726. }
  727. /*
  728. * CEnumFormatEtc::Reset
  729. *
  730. * Purpose:
  731. * Resets the current element index in the enumeration to zero.
  732. *
  733. * Parameters:
  734. * None
  735. *
  736. * Return Value:
  737. * HRESULT NOERROR
  738. */
  739. STDMETHODIMP CEnumFormatEtc::Reset(void)
  740. {
  741. m_iCur=0;
  742. return NOERROR;
  743. }
  744. /*
  745. * CEnumFormatEtc::Clone
  746. *
  747. * Purpose:
  748. * Returns another IEnumFORMATETC with the same state as ourselves.
  749. *
  750. * Parameters:
  751. * ppEnum LPENUMFORMATETC * in which to return the
  752. * new object.
  753. *
  754. * Return Value:
  755. * HRESULT NOERROR or a general error value.
  756. */
  757. STDMETHODIMP CEnumFormatEtc::Clone(LPENUMFORMATETC *ppEnum)
  758. {
  759. PCEnumFormatEtc pNew;
  760. *ppEnum=NULL;
  761. //Create the clone
  762. pNew=new CEnumFormatEtc(m_cfe, m_prgfe);
  763. if (NULL==pNew)
  764. return ResultFromScode(E_OUTOFMEMORY);
  765. pNew->AddRef();
  766. pNew->m_iCur=m_iCur;
  767. *ppEnum=pNew;
  768. return NOERROR;
  769. }