Leaked source code of windows server 2003
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.

1930 lines
39 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: gendata.cpp
  7. //
  8. // Contents: implementation of CGenDataObject
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: dd-mmm-yy Author Comment
  15. // 06-Jun-94 alexgo added support for OLE1 tests
  16. // 24-Mar-94 alexgo author
  17. //
  18. //--------------------------------------------------------------------------
  19. #include "oletest.h"
  20. #include "gendata.h"
  21. static const CLSID CLSID_TestCLSID = {0xaabbccee, 0x1122, 0x3344, { 0x55, 0x66,
  22. 0x77, 0x88, 0x99, 0x00, 0xaa, 0xbb }};
  23. static const char szTestString[] = "A carefully chosen test string";
  24. static const OLECHAR wszTestStream[] = OLESTR("TestStream");
  25. static const char szNativeData[] = "Ole1Test NATIVE data";
  26. static const char szOwnerLinkData[] = "PBrush\0foo.bmp\00 0 200 160\0\0";
  27. //+-------------------------------------------------------------------------
  28. //
  29. // Member: CGenDataObject::CGenDataObject
  30. //
  31. // Synopsis: constructor
  32. //
  33. // Effects:
  34. //
  35. // Arguments:
  36. //
  37. // Requires:
  38. //
  39. // Returns:
  40. //
  41. // Signals:
  42. //
  43. // Modifies:
  44. //
  45. // Derivation:
  46. //
  47. // Algorithm:
  48. //
  49. // History: dd-mmm-yy Author Comment
  50. // 06-Jun-94 alexgo added OLE1 support
  51. // 24-Mar-94 alexgo author
  52. //
  53. // Notes:
  54. //
  55. //--------------------------------------------------------------------------
  56. CGenDataObject::CGenDataObject( )
  57. {
  58. m_refs = 0;
  59. m_fQICalled = FALSE;
  60. // now set up the formats that we support
  61. m_cfTestStorage = RegisterClipboardFormat("OleTest Storage Format");
  62. m_cfEmbeddedObject = RegisterClipboardFormat("Embedded Object");
  63. m_cfEmbedSource = RegisterClipboardFormat("Embed Source");
  64. m_cfLinkSource = RegisterClipboardFormat("Link Source");
  65. m_cfObjectDescriptor = RegisterClipboardFormat("Object Descriptor");
  66. m_cfLinkSrcDescriptor = RegisterClipboardFormat("Link Source "
  67. "Descriptor");
  68. m_cfOwnerLink = RegisterClipboardFormat("OwnerLink");
  69. m_cfNative = RegisterClipboardFormat("Native");
  70. m_cfObjectLink = RegisterClipboardFormat("ObjectLink");
  71. // now set up the array of formatetc's. SetupOle1Mode must be
  72. // called if you want OLE1 formats
  73. m_rgFormats = new FORMATETC[2];
  74. assert(m_rgFormats);
  75. m_rgFormats[0].cfFormat = m_cfTestStorage;
  76. m_rgFormats[0].ptd = NULL;
  77. m_rgFormats[0].dwAspect = DVASPECT_CONTENT;
  78. m_rgFormats[0].lindex = -1;
  79. m_rgFormats[0].tymed = TYMED_ISTORAGE;
  80. m_rgFormats[1].cfFormat = m_cfEmbeddedObject;
  81. m_rgFormats[1].ptd = NULL;
  82. m_rgFormats[1].dwAspect = DVASPECT_CONTENT;
  83. m_rgFormats[1].lindex = -1;
  84. m_rgFormats[1].tymed = TYMED_ISTORAGE;
  85. m_cFormats = 2;
  86. }
  87. //+-------------------------------------------------------------------------
  88. //
  89. // Member: CGenDataObject::QueryInterface
  90. //
  91. // Synopsis: returns requested interfaces
  92. //
  93. // Effects:
  94. //
  95. // Arguments: [riid] -- the requested interface
  96. // [ppvObj] -- where to put the interface pointer
  97. //
  98. // Requires:
  99. //
  100. // Returns: HRESULT
  101. //
  102. // Signals:
  103. //
  104. // Modifies:
  105. //
  106. // Derivation: IDataObject
  107. //
  108. // Algorithm:
  109. //
  110. // History: dd-mmm-yy Author Comment
  111. // 24-Mar-94 alexgo author
  112. //
  113. // Notes:
  114. //
  115. //--------------------------------------------------------------------------
  116. STDMETHODIMP CGenDataObject::QueryInterface( REFIID riid, LPVOID *ppvObj )
  117. {
  118. HRESULT hresult = NOERROR;
  119. m_fQICalled = TRUE;
  120. if( IsEqualIID(riid, IID_IUnknown) ||
  121. IsEqualIID(riid, IID_IDataObject) )
  122. {
  123. *ppvObj = this;
  124. AddRef();
  125. }
  126. else
  127. {
  128. *ppvObj = NULL;
  129. hresult = ResultFromScode(E_NOINTERFACE);
  130. }
  131. return hresult;
  132. }
  133. //+-------------------------------------------------------------------------
  134. //
  135. // Member: CGenDataObject::AddRef
  136. //
  137. // Synopsis: increments the reference count
  138. //
  139. // Effects:
  140. //
  141. // Arguments: void
  142. //
  143. // Requires:
  144. //
  145. // Returns: ULONG-- the new reference count
  146. //
  147. // Signals:
  148. //
  149. // Modifies:
  150. //
  151. // Derivation: IDataObject
  152. //
  153. // Algorithm:
  154. //
  155. // History: dd-mmm-yy Author Comment
  156. // 24-Mar-94 alexgo author
  157. //
  158. // Notes:
  159. //
  160. //--------------------------------------------------------------------------
  161. STDMETHODIMP_(ULONG) CGenDataObject::AddRef( )
  162. {
  163. return ++m_refs;
  164. }
  165. //+-------------------------------------------------------------------------
  166. //
  167. // Member: CGenDataObject::Release
  168. //
  169. // Synopsis: decrements the reference count on the object
  170. //
  171. // Effects:
  172. //
  173. // Arguments: void
  174. //
  175. // Requires:
  176. //
  177. // Returns: ULONG -- the new reference count
  178. //
  179. // Signals:
  180. //
  181. // Modifies:
  182. //
  183. // Derivation: IDataObject
  184. //
  185. // Algorithm:
  186. //
  187. // History: dd-mmm-yy Author Comment
  188. // 24-Mar-94 alexgo author
  189. //
  190. // Notes:
  191. //
  192. //--------------------------------------------------------------------------
  193. STDMETHODIMP_(ULONG) CGenDataObject::Release( )
  194. {
  195. ULONG cRefs;
  196. if( (cRefs = --m_refs ) == 0 )
  197. {
  198. delete this;
  199. }
  200. return cRefs;
  201. }
  202. //+-------------------------------------------------------------------------
  203. //
  204. // Member: CGenDataObject::GetData
  205. //
  206. // Synopsis: retrieves data of the specified format
  207. //
  208. // Effects:
  209. //
  210. // Arguments: [pformatetc] -- the requested format
  211. // [pmedium] -- where to put the data
  212. //
  213. // Requires:
  214. //
  215. // Returns: HRESULT
  216. //
  217. // Signals:
  218. //
  219. // Modifies:
  220. //
  221. // Derivation: IDataObject
  222. //
  223. // Algorithm:
  224. //
  225. // History: dd-mmm-yy Author Comment
  226. // 06-Jun-94 alexgo added OLE1 support
  227. // 24-Mar-94 alexgo author
  228. //
  229. // Notes:
  230. //
  231. //--------------------------------------------------------------------------
  232. STDMETHODIMP CGenDataObject::GetData( LPFORMATETC pformatetc, LPSTGMEDIUM
  233. pmedium)
  234. {
  235. HRESULT hresult = NOERROR;
  236. if( (pformatetc->cfFormat == m_cfTestStorage ||
  237. pformatetc->cfFormat == m_cfEmbeddedObject ) &&
  238. (pformatetc->tymed & TYMED_ISTORAGE) )
  239. {
  240. pmedium->tymed = TYMED_ISTORAGE;
  241. pmedium->pstg = GetTestStorage();
  242. assert(pmedium->pstg);
  243. }
  244. // test for OLE1 formats
  245. else if( pformatetc->cfFormat == m_cfOwnerLink &&
  246. (m_fOle1 & OLE1_OFFER_OWNERLINK ) &&
  247. (pformatetc->tymed & TYMED_HGLOBAL) )
  248. {
  249. pmedium->tymed = TYMED_HGLOBAL;
  250. pmedium->hGlobal = GetOwnerOrObjectLink();
  251. assert(pmedium->hGlobal);
  252. }
  253. else if( pformatetc->cfFormat == m_cfObjectLink &&
  254. (m_fOle1 & OLE1_OFFER_OBJECTLINK ) &&
  255. (pformatetc->tymed & TYMED_HGLOBAL) )
  256. {
  257. pmedium->tymed = TYMED_HGLOBAL;
  258. pmedium->hGlobal = GetOwnerOrObjectLink();
  259. assert(pmedium->hGlobal);
  260. }
  261. else if( pformatetc->cfFormat == m_cfNative &&
  262. (m_fOle1 & OLE1_OFFER_NATIVE ) &&
  263. (pformatetc->tymed &TYMED_HGLOBAL ) )
  264. {
  265. pmedium->tymed = TYMED_HGLOBAL;
  266. pmedium->hGlobal = GetNativeData();
  267. }
  268. else
  269. {
  270. hresult = ResultFromScode(E_FAIL);
  271. }
  272. return hresult;
  273. }
  274. //+-------------------------------------------------------------------------
  275. //
  276. // Member: CGenDataObject::GetDataHere
  277. //
  278. // Synopsis: retrieves data of the specified format
  279. //
  280. // Effects:
  281. //
  282. // Arguments: [pformatetc] -- the requested format
  283. // [pmedium] -- where to put the data
  284. //
  285. // Requires:
  286. //
  287. // Returns: HRESULT
  288. //
  289. // Signals:
  290. //
  291. // Modifies:
  292. //
  293. // Derivation: IDataObject
  294. //
  295. // Algorithm:
  296. //
  297. // History: dd-mmm-yy Author Comment
  298. // 24-Mar-94 alexgo author
  299. //
  300. // Notes:
  301. //
  302. //--------------------------------------------------------------------------
  303. STDMETHODIMP CGenDataObject::GetDataHere( LPFORMATETC pformatetc, LPSTGMEDIUM
  304. pmedium)
  305. {
  306. (void)pformatetc;
  307. (void)pmedium;
  308. return ResultFromScode(E_NOTIMPL);
  309. }
  310. //+-------------------------------------------------------------------------
  311. //
  312. // Member: CGenDataObject::QueryGetData
  313. //
  314. // Synopsis: queries whether a GetData call would succeed
  315. //
  316. // Effects:
  317. //
  318. // Arguments: [pformatetc] -- the requested format
  319. //
  320. // Requires:
  321. //
  322. // Returns: HRESULT
  323. //
  324. // Signals:
  325. //
  326. // Modifies:
  327. //
  328. // Derivation: IDataObject
  329. //
  330. // Algorithm:
  331. //
  332. // History: dd-mmm-yy Author Comment
  333. // 24-Mar-94 alexgo author
  334. //
  335. // Notes:
  336. //
  337. //--------------------------------------------------------------------------
  338. STDMETHODIMP CGenDataObject::QueryGetData( LPFORMATETC pformatetc )
  339. {
  340. (void)pformatetc;
  341. return ResultFromScode(E_NOTIMPL);
  342. }
  343. //+-------------------------------------------------------------------------
  344. //
  345. // Member: CGenDataObject::GetCanonicalFormatEtc
  346. //
  347. // Synopsis: retrieve the canonical format
  348. //
  349. // Effects:
  350. //
  351. // Arguments: [pformatetc] -- the requested format
  352. // [pformatetcOut] -- the canonical format
  353. //
  354. // Requires:
  355. //
  356. // Returns: HRESULT
  357. //
  358. // Signals:
  359. //
  360. // Modifies:
  361. //
  362. // Derivation: IDataObject
  363. //
  364. // Algorithm:
  365. //
  366. // History: dd-mmm-yy Author Comment
  367. // 24-Mar-94 alexgo author
  368. //
  369. // Notes:
  370. //
  371. //--------------------------------------------------------------------------
  372. STDMETHODIMP CGenDataObject::GetCanonicalFormatEtc( LPFORMATETC pformatetc,
  373. LPFORMATETC pformatetcOut)
  374. {
  375. (void)pformatetc;
  376. (void)pformatetcOut;
  377. return ResultFromScode(E_NOTIMPL);
  378. }
  379. //+-------------------------------------------------------------------------
  380. //
  381. // Member: CGenDataObject::SetData
  382. //
  383. // Synopsis: sets data of the specified format
  384. //
  385. // Effects:
  386. //
  387. // Arguments: [pformatetc] -- the format of the data
  388. // [pmedium] -- the data
  389. //
  390. // Requires:
  391. //
  392. // Returns: HRESULT
  393. //
  394. // Signals:
  395. //
  396. // Modifies:
  397. //
  398. // Derivation: IDataObject
  399. //
  400. // Algorithm:
  401. //
  402. // History: dd-mmm-yy Author Comment
  403. // 24-Mar-94 alexgo author
  404. //
  405. // Notes:
  406. //
  407. //--------------------------------------------------------------------------
  408. STDMETHODIMP CGenDataObject::SetData( LPFORMATETC pformatetc, LPSTGMEDIUM
  409. pmedium, BOOL fRelease)
  410. {
  411. (void)pformatetc;
  412. (void)pmedium;
  413. (void)fRelease;
  414. return ResultFromScode(E_NOTIMPL);
  415. }
  416. //+-------------------------------------------------------------------------
  417. //
  418. // Member: CGenDataObject::EnumFormatEtc
  419. //
  420. // Synopsis: return an enumerator for the available data formats
  421. //
  422. // Effects:
  423. //
  424. // Arguments: [dwDirection] -- the direction (GET or SET)
  425. // [ppenum] -- where to put the enumerator
  426. //
  427. // Requires:
  428. //
  429. // Returns: HRESULT
  430. //
  431. // Signals:
  432. //
  433. // Modifies:
  434. //
  435. // Derivation: IDataObject
  436. //
  437. // Algorithm:
  438. //
  439. // History: dd-mmm-yy Author Comment
  440. // 24-Mar-94 alexgo author
  441. //
  442. // Notes:
  443. //
  444. //--------------------------------------------------------------------------
  445. STDMETHODIMP CGenDataObject::EnumFormatEtc( DWORD dwDirection,
  446. LPENUMFORMATETC * ppenum )
  447. {
  448. HRESULT hresult;
  449. if( dwDirection == DATADIR_GET )
  450. {
  451. hresult = CGenEnumFormatEtc::Create( ppenum, m_rgFormats,
  452. m_cFormats);
  453. assert(hresult == NOERROR);
  454. return hresult;
  455. }
  456. else
  457. {
  458. return ResultFromScode(E_NOTIMPL);
  459. }
  460. }
  461. //+-------------------------------------------------------------------------
  462. //
  463. // Member: CGenDataObject::DAdvise
  464. //
  465. // Synopsis: register a data advise
  466. //
  467. // Effects:
  468. //
  469. // Arguments: [pformatetc] -- the requested format
  470. // [dwAdvf] -- advise flags
  471. // [pAdvSink] -- the advise sink
  472. // [pdwConnection] -- where to put the connection ID
  473. //
  474. // Requires:
  475. //
  476. // Returns: HRESULT
  477. //
  478. // Signals:
  479. //
  480. // Modifies:
  481. //
  482. // Derivation: IDataObject
  483. //
  484. // Algorithm:
  485. //
  486. // History: dd-mmm-yy Author Comment
  487. // 24-Mar-94 alexgo author
  488. //
  489. // Notes:
  490. //
  491. //--------------------------------------------------------------------------
  492. STDMETHODIMP CGenDataObject::DAdvise( LPFORMATETC pformatetc, DWORD dwAdvf,
  493. IAdviseSink * pAdvSink, DWORD *pdwConnection )
  494. {
  495. (void)pformatetc;
  496. (void)dwAdvf;
  497. (void)pAdvSink;
  498. (void)pdwConnection;
  499. return ResultFromScode(E_NOTIMPL);
  500. }
  501. //+-------------------------------------------------------------------------
  502. //
  503. // Member: CGenDataObject::DUnadvise
  504. //
  505. // Synopsis: unadvises an advise connection
  506. //
  507. // Effects:
  508. //
  509. // Arguments: [dwConnection] -- the connection to remove
  510. //
  511. // Requires:
  512. //
  513. // Returns: HRESULT
  514. //
  515. // Signals:
  516. //
  517. // Modifies:
  518. //
  519. // Derivation: IDataObject
  520. //
  521. // Algorithm:
  522. //
  523. // History: dd-mmm-yy Author Comment
  524. // 24-Mar-94 alexgo author
  525. //
  526. // Notes:
  527. //
  528. //--------------------------------------------------------------------------
  529. STDMETHODIMP CGenDataObject::DUnadvise(DWORD dwConnection)
  530. {
  531. (void)dwConnection;
  532. return ResultFromScode(E_NOTIMPL);
  533. }
  534. //+-------------------------------------------------------------------------
  535. //
  536. // Member: CGenDataObject::EnumDAdvise
  537. //
  538. // Synopsis: enumerates data advises
  539. //
  540. // Effects:
  541. //
  542. // Arguments: [ppenum] -- where to put the enumerator
  543. //
  544. // Requires:
  545. //
  546. // Returns: HRESULT
  547. //
  548. // Signals:
  549. //
  550. // Modifies:
  551. //
  552. // Derivation: IDataObject
  553. //
  554. // Algorithm:
  555. //
  556. // History: dd-mmm-yy Author Comment
  557. // 24-Mar-94 alexgo author
  558. //
  559. // Notes:
  560. //
  561. //--------------------------------------------------------------------------
  562. STDMETHODIMP CGenDataObject::EnumDAdvise( LPENUMSTATDATA *ppenum)
  563. {
  564. (void)ppenum;
  565. return ResultFromScode(E_NOTIMPL);
  566. }
  567. //+-------------------------------------------------------------------------
  568. //
  569. // Member: CGenDataObject::VerifyMedium
  570. //
  571. // Synopsis: verifies the contents of the given medium
  572. //
  573. // Effects:
  574. //
  575. // Arguments: [pmedium] -- the medium to verify
  576. //
  577. // Requires:
  578. //
  579. // Returns: BOOL
  580. //
  581. // Signals:
  582. //
  583. // Modifies:
  584. //
  585. // Derivation:
  586. //
  587. // Algorithm: For OLE1 formats, the following must be true:
  588. // cfEmbeddedObject:
  589. // must have OWNERLINK and !NATIVE
  590. // or OWNERLINK precedes NATIVE
  591. // cfEmbedSource:
  592. // must have NATIVE && OWNERLINK and
  593. // OWNERLINK must not precede NATIVE
  594. // cfObjectDescriptor:
  595. // same as EmbedSource
  596. // cfLinkSource:
  597. // must have either OBJECTLINK or
  598. // OWNERLINK must precede NATIVE
  599. // cfLinkSrcDescriptor:
  600. // same as LinkSource
  601. //
  602. // History: dd-mmm-yy Author Comment
  603. // 06-Jun-94 alexgo added OLE1 support
  604. // 15-Apr-94 alexgo author
  605. //
  606. // Notes:
  607. //
  608. //--------------------------------------------------------------------------
  609. BOOL CGenDataObject::VerifyFormatAndMedium( FORMATETC *pformatetc,
  610. STGMEDIUM *pmedium )
  611. {
  612. // if any of these flags are set, then we were offering OLE1
  613. // data. Do relevant tests.
  614. if( (m_fOle1 & (OLE1_OFFER_OWNERLINK | OLE1_OFFER_OBJECTLINK |
  615. OLE1_OFFER_NATIVE) ) )
  616. {
  617. // now do individual tests for formats
  618. if( pformatetc->cfFormat == m_cfEmbedSource ||
  619. pformatetc->cfFormat == m_cfObjectDescriptor)
  620. {
  621. if( (m_fOle1 & OLE1_OFFER_NATIVE) &&
  622. (m_fOle1 & OLE1_OFFER_OWNERLINK) &&
  623. !(m_fOle1 & OLE1_OWNERLINK_PRECEDES_NATIVE) )
  624. {
  625. return TRUE;
  626. }
  627. }
  628. else if( pformatetc->cfFormat == m_cfLinkSource ||
  629. pformatetc->cfFormat == m_cfLinkSrcDescriptor)
  630. {
  631. if( (m_fOle1 & OLE1_OFFER_OBJECTLINK) ||
  632. ((m_fOle1 & OLE1_OFFER_OWNERLINK) &&
  633. (m_fOle1 & OLE1_OFFER_NATIVE) &&
  634. (m_fOle1 & OLE1_OWNERLINK_PRECEDES_NATIVE)))
  635. {
  636. return TRUE;
  637. }
  638. }
  639. // no 'else' so we check for cfObjectDescriptor again
  640. if( pformatetc->cfFormat == m_cfEmbeddedObject ||
  641. pformatetc->cfFormat == m_cfObjectDescriptor )
  642. {
  643. if( ((m_fOle1 & OLE1_OFFER_NATIVE) &&
  644. (m_fOle1 & OLE1_OFFER_OWNERLINK) &&
  645. (m_fOle1 & OLE1_OWNERLINK_PRECEDES_NATIVE)) ||
  646. ((m_fOle1 & OLE1_OFFER_OWNERLINK) &&
  647. !(m_fOle1 & OLE1_OFFER_NATIVE)) )
  648. {
  649. return TRUE;
  650. }
  651. }
  652. // fall through and do rest of testing, in case we didn't
  653. // hit one of the synthesized formats.
  654. }
  655. if( pformatetc->cfFormat == m_cfTestStorage ||
  656. pformatetc->cfFormat == m_cfEmbeddedObject )
  657. {
  658. return VerifyTestStorage( pformatetc, pmedium );
  659. }
  660. else if( pformatetc->cfFormat == m_cfOwnerLink ||
  661. pformatetc->cfFormat == m_cfObjectLink )
  662. {
  663. return VerifyOwnerOrObjectLink(pformatetc, pmedium);
  664. }
  665. else if( pformatetc->cfFormat == m_cfNative )
  666. {
  667. return VerifyNativeData(pformatetc, pmedium);
  668. }
  669. return FALSE;
  670. }
  671. //+-------------------------------------------------------------------------
  672. //
  673. // Member: CGenDataObject::VerifyTestStorage
  674. //
  675. // Synopsis: verifies the test storage format
  676. //
  677. // Effects:
  678. //
  679. // Arguments:
  680. //
  681. // Requires:
  682. //
  683. // Returns: BOOL
  684. //
  685. // Signals:
  686. //
  687. // Modifies:
  688. //
  689. // Derivation:
  690. //
  691. // Algorithm:
  692. //
  693. // History: dd-mmm-yy Author Comment
  694. // 15-Apr-94 alexgo author; tax day :-(
  695. //
  696. // Notes:
  697. //
  698. //--------------------------------------------------------------------------
  699. BOOL CGenDataObject::VerifyTestStorage( FORMATETC *pformatetc,
  700. STGMEDIUM *pmedium)
  701. {
  702. IStream * pstm;
  703. STATSTG statstg;
  704. char szBuf[sizeof(szTestString)];
  705. HRESULT hresult;
  706. if( pmedium->tymed != TYMED_ISTORAGE )
  707. {
  708. //REVIEW: we may want to convert and test different
  709. //mediums at a later date
  710. return FALSE;
  711. }
  712. // check the class ID
  713. pmedium->pstg->Stat(&statstg, STATFLAG_NONAME);
  714. if( !IsEqualCLSID(statstg.clsid, CLSID_TestCLSID) )
  715. {
  716. OutputString("Failed CLSID check on storage in "
  717. "VerifyTestStorage!!\r\n");
  718. return FALSE;
  719. }
  720. // now open the test stream
  721. hresult = pmedium->pstg->OpenStream(wszTestStream, NULL, (STGM_READ |
  722. STGM_SHARE_EXCLUSIVE), 0, &pstm);
  723. if( hresult != NOERROR )
  724. {
  725. OutputString("OpenStream in VerifyTestStorage failed! (%lx)"
  726. "\r\n", hresult);
  727. return FALSE;
  728. }
  729. hresult = pstm->Read((void *)szBuf, sizeof(szTestString), NULL);
  730. if( hresult != NOERROR )
  731. {
  732. OutputString("Stream->Read failed in VerifyTestStorage (%lx)"
  733. "\r\n", hresult);
  734. pstm->Release();
  735. return FALSE;
  736. }
  737. if( strcmp(szBuf, szTestString) != 0 )
  738. {
  739. OutputString("'%s' != '%s'\r\n", szBuf, szTestString);
  740. return FALSE;
  741. }
  742. pstm->Release();
  743. return TRUE;
  744. }
  745. //+-------------------------------------------------------------------------
  746. //
  747. // Member: CGenDataObject::GetTestStorage (private)
  748. //
  749. // Synopsis:
  750. //
  751. // Effects:
  752. //
  753. // Arguments:
  754. //
  755. // Requires:
  756. //
  757. // Returns: a new storage
  758. //
  759. // Signals:
  760. //
  761. // Modifies:
  762. //
  763. // Derivation:
  764. //
  765. // Algorithm:
  766. //
  767. // History: dd-mmm-yy Author Comment
  768. // 15-Apr-94 alexgo author
  769. //
  770. // Notes:
  771. //
  772. //--------------------------------------------------------------------------
  773. IStorage * CGenDataObject::GetTestStorage( void )
  774. {
  775. IStorage * pstg;
  776. IStream * pstm;
  777. HRESULT hresult;
  778. // create the docfile
  779. hresult = StgCreateDocfile(NULL, (STGM_READWRITE | STGM_DIRECT |
  780. STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE), NULL,
  781. &pstg);
  782. if( hresult != NOERROR )
  783. {
  784. OutputString("GetTestStorage: CreateDocfile failed!! (%lx)"
  785. "\r\n", hresult);
  786. return NULL;
  787. }
  788. // set the class ID
  789. hresult = pstg->SetClass(CLSID_TestCLSID);
  790. // now create the stream
  791. hresult = pstg->CreateStream(wszTestStream, (STGM_READWRITE |
  792. STGM_SHARE_EXCLUSIVE ), 0, 0, &pstm);
  793. if( hresult != NOERROR )
  794. {
  795. OutputString("GetTestStorage: CreateStream failed! (%lx)\r\n",
  796. hresult);
  797. pstg->Release();
  798. return NULL;
  799. }
  800. hresult = pstm->Write((void *)szTestString, sizeof(szTestString),
  801. NULL);
  802. if( hresult != NOERROR )
  803. {
  804. OutputString("GetTestStorage: Stream->Write failed! (%lx)\r\n",
  805. hresult);
  806. pstm->Release();
  807. pstg->Release();
  808. return NULL;
  809. }
  810. pstm->Release();
  811. return pstg;
  812. }
  813. //+-------------------------------------------------------------------------
  814. //
  815. // Member: CGenDataObject::GetOwnerOrObjectLink (private)
  816. //
  817. // Synopsis: Creates either cfOwnerLink or cfObjectLink for a dummy
  818. // Paintbrush (ole1) object
  819. //
  820. // Effects: allocates an HGLOBAL
  821. //
  822. // Arguments: void
  823. //
  824. // Requires:
  825. //
  826. // Returns: HGLOBAL
  827. //
  828. // Signals:
  829. //
  830. // Modifies:
  831. //
  832. // Derivation:
  833. //
  834. // Algorithm:
  835. //
  836. // History: dd-mmm-yy Author Comment
  837. // 06-Jun-94 alexgo author
  838. //
  839. // Notes:
  840. //
  841. //--------------------------------------------------------------------------
  842. HGLOBAL CGenDataObject::GetOwnerOrObjectLink( void )
  843. {
  844. HGLOBAL hglobal;
  845. char *pdata;
  846. hglobal = GlobalAlloc(GMEM_MOVEABLE, sizeof(szOwnerLinkData));
  847. assert(hglobal);
  848. pdata = (char *)GlobalLock(hglobal);
  849. assert(pdata);
  850. memcpy(pdata, szOwnerLinkData, sizeof(szOwnerLinkData));
  851. GlobalUnlock(hglobal);
  852. return hglobal;
  853. }
  854. //+-------------------------------------------------------------------------
  855. //
  856. // Member: CGenDataObject::GetNativeData (private)
  857. //
  858. // Synopsis: Creates OLE1 Native data
  859. //
  860. // Effects: allocates an hglobal
  861. //
  862. // Arguments: void
  863. //
  864. // Requires:
  865. //
  866. // Returns: HGLOBAL
  867. //
  868. // Signals:
  869. //
  870. // Modifies:
  871. //
  872. // Derivation:
  873. //
  874. // Algorithm:
  875. //
  876. // History: dd-mmm-yy Author Comment
  877. // 06-Jun-94 alexgo author
  878. //
  879. // Notes:
  880. //
  881. //--------------------------------------------------------------------------
  882. HGLOBAL CGenDataObject::GetNativeData( void )
  883. {
  884. HGLOBAL hglobal;
  885. char *pdata;
  886. hglobal = GlobalAlloc(GMEM_MOVEABLE, sizeof(szNativeData) + 1);
  887. assert(hglobal);
  888. pdata = (char *)GlobalLock(hglobal);
  889. assert(pdata);
  890. memcpy(pdata, szNativeData, sizeof(szNativeData)+1);
  891. GlobalUnlock(hglobal);
  892. return hglobal;
  893. }
  894. //+-------------------------------------------------------------------------
  895. //
  896. // Member: CGenDataObject::VerifyOwnerOrObjectLink
  897. //
  898. // Synopsis: verifies that the owner or object link data is correct
  899. //
  900. // Effects:
  901. //
  902. // Arguments: [pformatetc] -- the formatetc describing the data
  903. // [pmedium] -- the data
  904. //
  905. // Requires: pformatetc must be for OwnerLink or ObjectLink
  906. //
  907. // Returns: BOOL
  908. //
  909. // Signals:
  910. //
  911. // Modifies:
  912. //
  913. // Derivation:
  914. //
  915. // Algorithm:
  916. //
  917. // History: dd-mmm-yy Author Comment
  918. // 06-Jun-94 alexgo author
  919. //
  920. // Notes:
  921. // NB!!: must be expanded to cover container-side cases
  922. //
  923. //--------------------------------------------------------------------------
  924. BOOL CGenDataObject::VerifyOwnerOrObjectLink( FORMATETC *pformatetc,
  925. STGMEDIUM *pmedium )
  926. {
  927. char * pdata;
  928. BOOL fRet = FALSE;
  929. assert(pformatetc->cfFormat == m_cfOwnerLink ||
  930. pformatetc->cfFormat == m_cfObjectLink );
  931. // check standard stuff
  932. if( !(pformatetc->tymed & TYMED_HGLOBAL ) ||
  933. pformatetc->dwAspect != DVASPECT_CONTENT ||
  934. pformatetc->ptd != NULL ||
  935. pformatetc->lindex != -1 ||
  936. pmedium->tymed != TYMED_HGLOBAL )
  937. {
  938. return FALSE;
  939. }
  940. // if we offered the data natively from OLE1, then
  941. // check the contents.
  942. // this conditional tests to see if the format in question
  943. // was originally offered by us
  944. if( ((m_fOle1 & OLE1_OFFER_OWNERLINK) &&
  945. pformatetc->cfFormat == m_cfOwnerLink) ||
  946. ((m_fOle1 & OLE1_OFFER_OBJECTLINK) &&
  947. pformatetc->cfFormat == m_cfObjectLink) )
  948. {
  949. pdata = (char *)GlobalLock(pmedium->hGlobal);
  950. if( memcmp(pdata, szOwnerLinkData,
  951. sizeof(szOwnerLinkData)) == 0 )
  952. {
  953. fRet = TRUE;
  954. }
  955. GlobalUnlock(pmedium->hGlobal);
  956. }
  957. // else CHECK SYNTHESIZED OLE1 FORMATS WHEN IMPLEMENTED
  958. return fRet;
  959. }
  960. //+-------------------------------------------------------------------------
  961. //
  962. // Member: CGenDataObject::VerifyNativeData (private)
  963. //
  964. // Synopsis: verifies OLE1 Native data
  965. //
  966. // Effects:
  967. //
  968. // Arguments: [pformatetc] -- formatetc for the data
  969. // [pmedium] -- location of the native data
  970. //
  971. // Requires:
  972. //
  973. // Returns:
  974. //
  975. // Signals:
  976. //
  977. // Modifies:
  978. //
  979. // Derivation:
  980. //
  981. // Algorithm:
  982. //
  983. // History: dd-mmm-yy Author Comment
  984. // 06-Jun-95 alexgo author
  985. // Notes:
  986. //
  987. //--------------------------------------------------------------------------
  988. BOOL CGenDataObject::VerifyNativeData( FORMATETC *pformatetc,
  989. STGMEDIUM *pmedium )
  990. {
  991. char * pdata;
  992. BOOL fRet = FALSE;
  993. assert(pformatetc->cfFormat == m_cfNative );
  994. // check standard stuff
  995. if( !(pformatetc->tymed & TYMED_HGLOBAL) ||
  996. pformatetc->dwAspect != DVASPECT_CONTENT ||
  997. pformatetc->ptd != NULL ||
  998. pformatetc->lindex != -1 ||
  999. pmedium->tymed != TYMED_HGLOBAL )
  1000. {
  1001. return FALSE;
  1002. }
  1003. // if we offered the data natively from OLE1, then
  1004. // check the contents.
  1005. // this conditional tests to see if the format in question
  1006. // was originally offered by us
  1007. if( (m_fOle1 & OLE1_OFFER_NATIVE) )
  1008. {
  1009. pdata = (char *)GlobalLock(pmedium->hGlobal);
  1010. if( memcmp(pdata, szNativeData,
  1011. sizeof(szNativeData)) == 0 )
  1012. {
  1013. fRet = TRUE;
  1014. }
  1015. GlobalUnlock(pmedium->hGlobal);
  1016. }
  1017. // else CHECK SYNTHESIZED OLE1 FORMATS WHEN IMPLEMENTED
  1018. return fRet;
  1019. }
  1020. //+-------------------------------------------------------------------------
  1021. //
  1022. // Member: CGenDataObject::SetupOle1Mode (public)
  1023. //
  1024. // Synopsis: Sets the data object up for OLE1 compatibility mode
  1025. //
  1026. // Effects:
  1027. //
  1028. // Arguments: [fFlags] -- specifies various OLE1 options
  1029. //
  1030. // Requires:
  1031. //
  1032. // Returns: void
  1033. //
  1034. // Signals:
  1035. //
  1036. // Modifies:
  1037. //
  1038. // Derivation:
  1039. //
  1040. // Algorithm:
  1041. //
  1042. // History: dd-mmm-yy Author Comment
  1043. // 06-Jun-94 alexgo author
  1044. //
  1045. // Notes:
  1046. // The default test information in the data object will be
  1047. // lost by this call. Simply create a new data object if
  1048. // it is needed again.
  1049. //
  1050. //--------------------------------------------------------------------------
  1051. void CGenDataObject::SetupOle1Mode( Ole1TestFlags fFlags )
  1052. {
  1053. DWORD count = 0, i = 0;
  1054. UINT cfFormats[3]; // OLE1 formats offered
  1055. if( fFlags == 0 )
  1056. {
  1057. // don't need to do anything
  1058. return;
  1059. }
  1060. // the formats we had previously
  1061. delete m_rgFormats;
  1062. // first figure out how many formats we need
  1063. if( (fFlags & OLE1_OFFER_NATIVE) )
  1064. {
  1065. if( !((fFlags & OLE1_OWNERLINK_PRECEDES_NATIVE) &&
  1066. (fFlags & OLE1_OFFER_OWNERLINK)) )
  1067. {
  1068. cfFormats[i] = m_cfNative;
  1069. i++;
  1070. }
  1071. count++;
  1072. }
  1073. if( (fFlags & OLE1_OFFER_OWNERLINK) )
  1074. {
  1075. cfFormats[i] = m_cfOwnerLink;
  1076. i++;
  1077. if( (fFlags & OLE1_OWNERLINK_PRECEDES_NATIVE) &&
  1078. (fFlags & OLE1_OFFER_NATIVE) )
  1079. {
  1080. cfFormats[i] = m_cfNative;
  1081. i++;
  1082. }
  1083. count++;
  1084. }
  1085. if( (fFlags & OLE1_OFFER_OBJECTLINK) )
  1086. {
  1087. cfFormats[i] = m_cfObjectLink;
  1088. count++;
  1089. }
  1090. m_rgFormats = new FORMATETC[count];
  1091. assert(m_rgFormats);
  1092. for(i = 0; i < count; i++ )
  1093. {
  1094. m_rgFormats[i].cfFormat = cfFormats[i];
  1095. m_rgFormats[i].ptd = NULL;
  1096. m_rgFormats[i].dwAspect = DVASPECT_CONTENT;
  1097. m_rgFormats[i].lindex = -1;
  1098. m_rgFormats[i].tymed = TYMED_HGLOBAL;
  1099. }
  1100. m_cFormats = count;
  1101. m_fOle1 = fFlags;
  1102. return;
  1103. }
  1104. //+-------------------------------------------------------------------------
  1105. //
  1106. // Member: CGenDataObject::SetOle1ToClipboard
  1107. //
  1108. // Synopsis: stuffs available OLE1 formats to the clipboard
  1109. //
  1110. // Effects:
  1111. //
  1112. // Arguments: void
  1113. //
  1114. // Requires: SetOle1Mode *must* have been called
  1115. //
  1116. // Returns: HRESULT
  1117. //
  1118. // Signals:
  1119. //
  1120. // Modifies:
  1121. //
  1122. // Derivation:
  1123. //
  1124. // Algorithm:
  1125. //
  1126. // History: dd-mmm-yy Author Comment
  1127. // 06-Jun-94 alexgo author
  1128. //
  1129. // Notes:
  1130. //
  1131. //--------------------------------------------------------------------------
  1132. HRESULT CGenDataObject::SetOle1ToClipboard( void )
  1133. {
  1134. HRESULT hresult = NOERROR;
  1135. DWORD i;
  1136. HGLOBAL hglobal;
  1137. assert((m_fOle1 & (OLE1_OFFER_OWNERLINK | OLE1_OFFER_OBJECTLINK |
  1138. OLE1_OFFER_NATIVE)));
  1139. if( !OpenClipboard(vApp.m_hwndMain) )
  1140. {
  1141. return ResultFromScode(CLIPBRD_E_CANT_OPEN);
  1142. }
  1143. if( !EmptyClipboard() )
  1144. {
  1145. CloseClipboard();
  1146. return ResultFromScode(CLIPBRD_E_CANT_EMPTY);
  1147. }
  1148. for( i = 0 ; i < m_cFormats; i++ )
  1149. {
  1150. if( m_rgFormats[i].cfFormat == m_cfNative )
  1151. {
  1152. hglobal = GetNativeData();
  1153. SetClipboardData(m_cfNative, hglobal);
  1154. }
  1155. else if( m_rgFormats[i].cfFormat == m_cfOwnerLink )
  1156. {
  1157. hglobal = GetOwnerOrObjectLink();
  1158. SetClipboardData(m_cfOwnerLink, hglobal);
  1159. }
  1160. else if( m_rgFormats[i].cfFormat == m_cfObjectLink )
  1161. {
  1162. hglobal = GetOwnerOrObjectLink();
  1163. SetClipboardData(m_cfObjectLink, hglobal);
  1164. }
  1165. else
  1166. {
  1167. hresult = ResultFromScode(E_UNEXPECTED);
  1168. }
  1169. }
  1170. CloseClipboard();
  1171. return hresult;
  1172. }
  1173. //+-------------------------------------------------------------------------
  1174. //
  1175. // Member: CGenDataObject::HasQIBeenCalled (public)
  1176. //
  1177. // Synopsis: returns wether or not QueryInterface has been called on
  1178. // this data object. Used in testing OleQueryCreateFromData
  1179. //
  1180. // Effects:
  1181. //
  1182. // Arguments: none
  1183. //
  1184. // Requires:
  1185. //
  1186. // Returns: TRUE/FALSE
  1187. //
  1188. // Signals:
  1189. //
  1190. // Modifies:
  1191. //
  1192. // Derivation:
  1193. //
  1194. // Algorithm:
  1195. //
  1196. // History: dd-mmm-yy Author Comment
  1197. // 23-Aug-94 alexgo author
  1198. //
  1199. // Notes:
  1200. //
  1201. //--------------------------------------------------------------------------
  1202. BOOL CGenDataObject::HasQIBeenCalled()
  1203. {
  1204. return m_fQICalled;
  1205. }
  1206. //+-------------------------------------------------------------------------
  1207. //
  1208. // Member: CGenDataObject::SetDatFormats
  1209. //
  1210. // Synopsis: sets the formats that the data object will offer
  1211. //
  1212. // Effects:
  1213. //
  1214. // Arguments: [fFlags] -- formats to offer
  1215. //
  1216. // Requires:
  1217. //
  1218. // Returns: void
  1219. //
  1220. // Signals:
  1221. //
  1222. // Modifies:
  1223. //
  1224. // Derivation:
  1225. //
  1226. // Algorithm:
  1227. //
  1228. // History: dd-mmm-yy Author Comment
  1229. // 23-Aug-94 alexgo author
  1230. //
  1231. // Notes:
  1232. //
  1233. //--------------------------------------------------------------------------
  1234. void CGenDataObject::SetDataFormats( DataFlags fFlags )
  1235. {
  1236. DWORD cFormats = 0;
  1237. DWORD flags = (DWORD)fFlags;
  1238. DWORD i =0;
  1239. if( m_rgFormats )
  1240. {
  1241. delete m_rgFormats;
  1242. m_rgFormats = NULL;
  1243. }
  1244. if( flags == 0 )
  1245. {
  1246. return;
  1247. }
  1248. // count the number of formats to offer
  1249. cFormats++;
  1250. while( flags &= (flags -1) )
  1251. {
  1252. cFormats++;
  1253. }
  1254. m_rgFormats = new FORMATETC[cFormats];
  1255. assert(m_rgFormats);
  1256. memset(m_rgFormats, 0, sizeof(FORMATETC)*cFormats);
  1257. if( fFlags & OFFER_TESTSTORAGE )
  1258. {
  1259. m_rgFormats[i].cfFormat = m_cfTestStorage;
  1260. m_rgFormats[i].ptd = NULL;
  1261. m_rgFormats[i].dwAspect = DVASPECT_CONTENT;
  1262. m_rgFormats[i].lindex = -1;
  1263. m_rgFormats[i].tymed = TYMED_ISTORAGE;
  1264. i++;
  1265. }
  1266. if( fFlags & OFFER_EMBEDDEDOBJECT )
  1267. {
  1268. m_rgFormats[i].cfFormat = m_cfEmbeddedObject;
  1269. m_rgFormats[i].ptd = NULL;
  1270. m_rgFormats[i].dwAspect = DVASPECT_CONTENT;
  1271. m_rgFormats[i].lindex = -1;
  1272. m_rgFormats[i].tymed = TYMED_ISTORAGE;
  1273. i++;
  1274. }
  1275. m_cFormats = i;
  1276. }
  1277. //
  1278. // Generic Data Object formatetc enumerator
  1279. //
  1280. //+-------------------------------------------------------------------------
  1281. //
  1282. // Member: CGenEnumFormatEtc::QueryInterface
  1283. //
  1284. // Synopsis: returns requested interfaces
  1285. //
  1286. // Effects:
  1287. //
  1288. // Arguments: [riid] -- the requested interface
  1289. // [ppvObj] -- where to put the interface pointer
  1290. //
  1291. // Requires:
  1292. //
  1293. // Returns: HRESULT
  1294. //
  1295. // Signals:
  1296. //
  1297. // Modifies:
  1298. //
  1299. // Derivation: IEnumFORMATETC
  1300. //
  1301. // Algorithm:
  1302. //
  1303. // History: dd-mmm-yy Author Comment
  1304. // 15-Apr-94 alexgo author
  1305. //
  1306. // Notes:
  1307. //
  1308. //--------------------------------------------------------------------------
  1309. STDMETHODIMP CGenEnumFormatEtc::QueryInterface( REFIID riid, LPVOID *ppvObj )
  1310. {
  1311. HRESULT hresult = NOERROR;
  1312. if( IsEqualIID(riid, IID_IUnknown) ||
  1313. IsEqualIID(riid, IID_IEnumFORMATETC) )
  1314. {
  1315. *ppvObj = this;
  1316. AddRef();
  1317. }
  1318. else
  1319. {
  1320. *ppvObj = NULL;
  1321. hresult = ResultFromScode(E_NOINTERFACE);
  1322. }
  1323. return hresult;
  1324. }
  1325. //+-------------------------------------------------------------------------
  1326. //
  1327. // Member: CGenEnumFormatEtc::AddRef
  1328. //
  1329. // Synopsis: increments the reference count
  1330. //
  1331. // Effects:
  1332. //
  1333. // Arguments: void
  1334. //
  1335. // Requires:
  1336. //
  1337. // Returns: ULONG-- the new reference count
  1338. //
  1339. // Signals:
  1340. //
  1341. // Modifies:
  1342. //
  1343. // Derivation: IEnumFORMATETC
  1344. //
  1345. // Algorithm:
  1346. //
  1347. // History: dd-mmm-yy Author Comment
  1348. // 15-Apr-94 alexgo author
  1349. //
  1350. // Notes:
  1351. //
  1352. //--------------------------------------------------------------------------
  1353. STDMETHODIMP_(ULONG) CGenEnumFormatEtc::AddRef( )
  1354. {
  1355. return ++m_refs;
  1356. }
  1357. //+-------------------------------------------------------------------------
  1358. //
  1359. // Member: CGenEnumFormatEtc::Release
  1360. //
  1361. // Synopsis: decrements the reference count on the object
  1362. //
  1363. // Effects:
  1364. //
  1365. // Arguments: void
  1366. //
  1367. // Requires:
  1368. //
  1369. // Returns: ULONG -- the new reference count
  1370. //
  1371. // Signals:
  1372. //
  1373. // Modifies:
  1374. //
  1375. // Derivation: IEnumFORMATETC
  1376. //
  1377. // Algorithm:
  1378. //
  1379. // History: dd-mmm-yy Author Comment
  1380. // 15-Apr-94 alexgo author
  1381. //
  1382. // Notes:
  1383. //
  1384. //--------------------------------------------------------------------------
  1385. STDMETHODIMP_(ULONG) CGenEnumFormatEtc::Release( )
  1386. {
  1387. ULONG cRefs;
  1388. if( (cRefs = --m_refs ) == 0 )
  1389. {
  1390. delete this;
  1391. }
  1392. return cRefs;
  1393. }
  1394. //+-------------------------------------------------------------------------
  1395. //
  1396. // Member: CGenEnumFormatEtc::Next
  1397. //
  1398. // Synopsis: gets the next [celt] formats
  1399. //
  1400. // Effects:
  1401. //
  1402. // Arguments: [celt] -- the number of elements to fetch
  1403. // [rgelt] -- where to put them
  1404. // [pceltFetched] -- the number of formats actually fetched
  1405. //
  1406. // Requires:
  1407. //
  1408. // Returns: NOERROR
  1409. //
  1410. // Signals:
  1411. //
  1412. // Modifies:
  1413. //
  1414. // Derivation: IEnumFORMATETC
  1415. //
  1416. // Algorithm:
  1417. //
  1418. // History: dd-mmm-yy Author Comment
  1419. // 15-Apr-94 alexgo author
  1420. //
  1421. // Notes:
  1422. //
  1423. //--------------------------------------------------------------------------
  1424. STDMETHODIMP CGenEnumFormatEtc::Next( ULONG celt, FORMATETC *rgelt,
  1425. ULONG *pceltFetched)
  1426. {
  1427. HRESULT hresult = NOERROR;
  1428. ULONG cFetched;
  1429. if( celt > m_cTotal - m_iCurrent )
  1430. {
  1431. cFetched = m_cTotal - m_iCurrent;
  1432. hresult = ResultFromScode(S_FALSE);
  1433. }
  1434. else
  1435. {
  1436. cFetched = celt;
  1437. }
  1438. memcpy( rgelt, m_rgFormats + m_iCurrent,
  1439. cFetched * sizeof(FORMATETC) );
  1440. m_iCurrent += cFetched;
  1441. if( pceltFetched )
  1442. {
  1443. *pceltFetched = cFetched;
  1444. }
  1445. return hresult;
  1446. }
  1447. //+-------------------------------------------------------------------------
  1448. //
  1449. // Member: CGenEnumFormatEtc::Skip
  1450. //
  1451. // Synopsis: skips the next [celt] formats
  1452. //
  1453. // Effects:
  1454. //
  1455. // Arguments: [celt] -- the number of elements to skip
  1456. //
  1457. // Requires:
  1458. //
  1459. // Returns: NOERROR
  1460. //
  1461. // Signals:
  1462. //
  1463. // Modifies:
  1464. //
  1465. // Derivation: IEnumFORMATETC
  1466. //
  1467. // Algorithm:
  1468. //
  1469. // History: dd-mmm-yy Author Comment
  1470. // 15-Apr-94 alexgo author
  1471. //
  1472. // Notes:
  1473. //
  1474. //--------------------------------------------------------------------------
  1475. STDMETHODIMP CGenEnumFormatEtc::Skip( ULONG celt )
  1476. {
  1477. HRESULT hresult = NOERROR;
  1478. m_iCurrent += celt;
  1479. if( m_iCurrent > m_cTotal )
  1480. {
  1481. // whoops, skipped to far ahead. Set us to the max limit.
  1482. m_iCurrent = m_cTotal;
  1483. hresult = ResultFromScode(S_FALSE);
  1484. }
  1485. return hresult;
  1486. }
  1487. //+-------------------------------------------------------------------------
  1488. //
  1489. // Member: CGenEnumFormatEtc::Reset
  1490. //
  1491. // Synopsis: resets the seek pointer to zero
  1492. //
  1493. // Effects:
  1494. //
  1495. // Arguments: void
  1496. //
  1497. // Requires:
  1498. //
  1499. // Returns: NOERROR
  1500. //
  1501. // Signals:
  1502. //
  1503. // Modifies:
  1504. //
  1505. // Derivation: IEnumFORMATETC
  1506. //
  1507. // Algorithm:
  1508. //
  1509. // History: dd-mmm-yy Author Comment
  1510. // 15-Apr-94 alexgo author
  1511. //
  1512. // Notes:
  1513. //
  1514. //--------------------------------------------------------------------------
  1515. STDMETHODIMP CGenEnumFormatEtc::Reset( void )
  1516. {
  1517. m_iCurrent = 0;
  1518. return NOERROR;
  1519. }
  1520. //+-------------------------------------------------------------------------
  1521. //
  1522. // Member: CGenEnumFormatEtc::Clone
  1523. //
  1524. // Synopsis: clones the enumerator
  1525. //
  1526. // Effects:
  1527. //
  1528. // Arguments: [ppIEnum] -- where to put the cloned enumerator
  1529. //
  1530. // Requires:
  1531. //
  1532. // Returns: HRESULT
  1533. //
  1534. // Signals:
  1535. //
  1536. // Modifies:
  1537. //
  1538. // Derivation: IEnumFORMATETC
  1539. //
  1540. // Algorithm:
  1541. //
  1542. // History: dd-mmm-yy Author Comment
  1543. // 15-Apr-94 alexgo author
  1544. //
  1545. // Notes:
  1546. //
  1547. //--------------------------------------------------------------------------
  1548. STDMETHODIMP CGenEnumFormatEtc::Clone( IEnumFORMATETC **ppIEnum )
  1549. {
  1550. HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
  1551. CGenEnumFormatEtc * pClipEnum;
  1552. *ppIEnum = NULL;
  1553. pClipEnum = new CGenEnumFormatEtc();
  1554. // ref count will be 1 and m_iCurrent will be zero.
  1555. if( pClipEnum )
  1556. {
  1557. pClipEnum->m_cTotal = m_cTotal;
  1558. pClipEnum->m_rgFormats = new FORMATETC[m_cTotal];
  1559. pClipEnum->m_iCurrent = m_iCurrent;
  1560. assert(pClipEnum->m_rgFormats);
  1561. if( pClipEnum->m_rgFormats )
  1562. {
  1563. // copy our formatetc's into the cloned enumerator's
  1564. // array
  1565. memcpy(pClipEnum->m_rgFormats, m_rgFormats,
  1566. m_cTotal * sizeof(FORMATETC) );
  1567. *ppIEnum = pClipEnum;
  1568. hresult = NOERROR;
  1569. }
  1570. else
  1571. {
  1572. delete pClipEnum;
  1573. }
  1574. }
  1575. return hresult;
  1576. }
  1577. //+-------------------------------------------------------------------------
  1578. //
  1579. // Member: CGenEnumFormatEtc::CGenEnumFormatEtc, private
  1580. //
  1581. // Synopsis: constructor
  1582. //
  1583. // Effects:
  1584. //
  1585. // Arguments: void
  1586. //
  1587. // Requires:
  1588. //
  1589. // Returns:
  1590. //
  1591. // Signals:
  1592. //
  1593. // Modifies:
  1594. //
  1595. // Derivation:
  1596. //
  1597. // Algorithm:
  1598. //
  1599. // History: dd-mmm-yy Author Comment
  1600. // 15-Apr-94 alexgo author
  1601. //
  1602. // Notes:
  1603. //
  1604. //--------------------------------------------------------------------------
  1605. CGenEnumFormatEtc::CGenEnumFormatEtc( void )
  1606. {
  1607. m_refs = 1; // give the intial reference
  1608. m_rgFormats = NULL;
  1609. m_iCurrent = 0;
  1610. m_cTotal = 0;
  1611. }
  1612. //+-------------------------------------------------------------------------
  1613. //
  1614. // Member: CGenEnumFormatEtc::~CGenEnumFormatEtc, private
  1615. //
  1616. // Synopsis: destructor
  1617. //
  1618. // Effects:
  1619. //
  1620. // Arguments: void
  1621. //
  1622. // Requires:
  1623. //
  1624. // Returns:
  1625. //
  1626. // Signals:
  1627. //
  1628. // Modifies:
  1629. //
  1630. // Derivation:
  1631. //
  1632. // Algorithm:
  1633. //
  1634. // History: dd-mmm-yy Author Comment
  1635. // 15-Apr-94 alexgo author
  1636. //
  1637. // Notes:
  1638. //
  1639. //--------------------------------------------------------------------------
  1640. CGenEnumFormatEtc::~CGenEnumFormatEtc( void )
  1641. {
  1642. if( m_rgFormats )
  1643. {
  1644. delete m_rgFormats;
  1645. }
  1646. }
  1647. //+-------------------------------------------------------------------------
  1648. //
  1649. // Member: CGenEnumFormatEtc::Create, static, public
  1650. //
  1651. // Synopsis: Creates a clipboard formatetc enumerator
  1652. //
  1653. // Effects:
  1654. //
  1655. // Arguments: [ppIEnum] -- where to put the enumerator
  1656. //
  1657. // Requires: the clipboard must be open
  1658. //
  1659. // Returns: HRESULT
  1660. //
  1661. // Signals:
  1662. //
  1663. // Modifies:
  1664. //
  1665. // Derivation:
  1666. //
  1667. // Algorithm:
  1668. //
  1669. // History: dd-mmm-yy Author Comment
  1670. // 15-Apr-94 alexgo author
  1671. //
  1672. // Notes:
  1673. //
  1674. //--------------------------------------------------------------------------
  1675. HRESULT CGenEnumFormatEtc::Create( IEnumFORMATETC **ppIEnum,
  1676. FORMATETC *prgFormats, DWORD cFormats )
  1677. {
  1678. HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
  1679. CGenEnumFormatEtc * pClipEnum;
  1680. *ppIEnum = NULL;
  1681. pClipEnum = new CGenEnumFormatEtc();
  1682. assert(pClipEnum);
  1683. // now allocate memory for the array
  1684. pClipEnum->m_rgFormats = new FORMATETC[cFormats];
  1685. assert(pClipEnum->m_rgFormats);
  1686. pClipEnum->m_cTotal = cFormats;
  1687. memcpy(pClipEnum->m_rgFormats, prgFormats,
  1688. cFormats * sizeof(FORMATETC));
  1689. *ppIEnum = pClipEnum;
  1690. return NOERROR;
  1691. }
  1692.