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.

5539 lines
143 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: clipdata.cpp
  7. //
  8. // Contents: implementation of CClipDataObject
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: dd-mmm-yy Author Comment
  15. // 01-Feb-95 t-ScottH added Dump method to CClipDataObject,
  16. // CEnumFormatEtcDataArray and added APIs
  17. // DumpCClipDataObject, DumpCEnumFormatEtcDataArray
  18. // 09-Jan-95 t-scotth changed VDATETHREAD to accept a pointer, and
  19. // ensured VDATETHREAD is before VDATEPTRIN and
  20. // VDATEPTROUT
  21. // 21-Nov-94 alexgo added thread validation
  22. // 11-Aug-94 alexgo added support for EmbeddedObject from
  23. // OLE1 formats.
  24. // 04-Jun-94 alexgo now converts OLE1 formats into OLE2
  25. // 30-May-94 alexgo now supports enhanced metafiles
  26. // 17-May-94 alexgo now use OleOpenClipboard instead of
  27. // OpenClipboard.
  28. // 11-May-94 alexgo eliminated allocations for 0
  29. // bytes from the enumerator.
  30. // 02-Apr-94 alexgo author
  31. //
  32. // Notes:
  33. // This file is laid out as follows:
  34. // ClipboardDataObject private methods
  35. // ClipboardDataObject IDataObject methods
  36. // OLE1 support functions (in alphabetical order)
  37. // Formatetc Enumerator methods
  38. //
  39. //--------------------------------------------------------------------------
  40. #include <le2int.h>
  41. #include <getif.hxx>
  42. #include "clipdata.h"
  43. #include "clipbrd.h"
  44. #include <ostm2stg.h> //for wCLSIDFromProgID and GenericObjectToIStorage
  45. #include <reghelp.hxx>
  46. #ifdef _DEBUG
  47. #include <dbgdump.h>
  48. #endif // _DEBUG
  49. // helper function used by the data object and formatetc enumerator
  50. HRESULT BmToPres(HANDLE hBM, PPRES ppres);
  51. BOOL CanRetrieveOle2FromOle1( UINT cf);
  52. HRESULT DibToPres(HANDLE hDib, PPRES ppres);
  53. BOOL IsOwnerLinkStdOleLink( void );
  54. HRESULT MfToPres( HANDLE hMFPict, PPRES ppres);
  55. HRESULT NativeToStorage(IStorage *pstg, HANDLE hNative);
  56. //+-------------------------------------------------------------------------
  57. //
  58. // Member: CClipDataObject::CClipDataObject
  59. //
  60. // Synopsis: constructor
  61. //
  62. // Effects:
  63. //
  64. // Arguments: void
  65. //
  66. // Requires:
  67. //
  68. // Returns: void
  69. //
  70. // Signals:
  71. //
  72. // Modifies:
  73. //
  74. // Derivation:
  75. //
  76. // Algorithm: initializes reference count to 1
  77. //
  78. // History: dd-mmm-yy Author Comment
  79. // 02-Apr-94 alexgo author
  80. //
  81. // Notes:
  82. //
  83. //--------------------------------------------------------------------------
  84. CClipDataObject::CClipDataObject( )
  85. {
  86. m_refs = 1;
  87. m_Internalrefs = 0; // Up To Caller to Place InternalRef.
  88. m_pFormatEtcDataArray = NULL;
  89. // OLE1 support stuff
  90. m_hOle1 = NULL;
  91. m_pUnkOle1 = NULL;
  92. // Data object to use to get the data.
  93. m_pDataObject = NULL;
  94. m_fTriedToGetDataObject = FALSE;
  95. }
  96. //+-------------------------------------------------------------------------
  97. //
  98. // Member: CClipDataObject::~CClipDataObject
  99. //
  100. // Synopsis: destructor
  101. //
  102. // Effects:
  103. //
  104. // Arguments: void
  105. //
  106. // Requires:
  107. //
  108. // Returns: void
  109. //
  110. // Signals:
  111. //
  112. // Modifies:
  113. //
  114. // Derivation:
  115. //
  116. // Algorithm: frees the formatetc array (if one exists)
  117. //
  118. // History: dd-mmm-yy Author Comment
  119. // 19-Apr-94 alexgo author
  120. //
  121. // Notes:
  122. //
  123. //--------------------------------------------------------------------------
  124. CClipDataObject::~CClipDataObject( )
  125. {
  126. if (m_pDataObject != NULL)
  127. {
  128. // Release our reference to the data object.
  129. m_pDataObject->Release();
  130. }
  131. if (m_pFormatEtcDataArray)
  132. {
  133. if (0 == --m_pFormatEtcDataArray->_cRefs)
  134. {
  135. PrivMemFree(m_pFormatEtcDataArray);
  136. m_pFormatEtcDataArray = NULL;
  137. }
  138. }
  139. }
  140. //+-------------------------------------------------------------------------
  141. //
  142. // Member: CClipDataObject::GetRealDataObjPtr (private)
  143. //
  144. // Synopsis: Get clip board data object from the clipboard
  145. //
  146. // Effects:
  147. //
  148. // Arguments: void
  149. //
  150. // Requires:
  151. //
  152. // Returns: void
  153. //
  154. // Signals:
  155. //
  156. // Modifies:
  157. //
  158. // Derivation:
  159. //
  160. // Algorithm: If we've tried this before, then return; otherwise:
  161. // Open the clipboard. Get the data object from the clipboard
  162. // if it is there. Close the clipboard and update our private
  163. // member.
  164. //
  165. // History: dd-mmm-yy Author Comment
  166. // 12-Aug-94 alexgo handle identity better
  167. // 17-Jun-94 alexgo optimized
  168. // 13-Jun-94 Ricksa author
  169. //
  170. // Notes: We must only try to get the real data object once in order
  171. // to preserve OLE identity. Recall that we call this function
  172. // if somebody does a QI for IUnknown. Now suppose that
  173. // GetInterfaceFromWindowProp fails for a 'benign' reason
  174. // (like we're in the middle of processing a send message).
  175. // Our QueryInterface will then return *our* IUnknown, thus
  176. // establishing the identity of this object to be CClipDataObject.
  177. //
  178. // Now suppose another call to QI for IUnknown is made. If
  179. // we simply noticed that m_pDataObject was NULL and called
  180. // GetInterfaceFromWindowProp again, it could succeed and we
  181. // would return a *different* IUnknown (thus violating OLE
  182. // object identity).
  183. //
  184. // For this reason, we only allow one call to
  185. // GetInterfaceFromWindowProp.
  186. //
  187. // Note that it is not strictly necessary to disable multiple
  188. // calls to GetInterfaceFromWindowProp for GetData and
  189. // GetDataHere methods. Neither of these methods affect
  190. // object identity. However, for the sake of consistency and
  191. // simplicity (!), we treat GetData and QI the same.
  192. //
  193. //--------------------------------------------------------------------------
  194. LPDATAOBJECT CClipDataObject::GetRealDataObjPtr( )
  195. {
  196. HGLOBAL hDataObject;
  197. HWND * phClipWnd;
  198. HWND hClipWnd = NULL;
  199. HRESULT hresult;
  200. #if DBG == 1
  201. BOOL fCloseClipSucceeded;
  202. #endif // DBG
  203. LEDebugOut((DEB_ITRACE,
  204. "%p _IN CClipDataObject::GetRealDataObjPtr ( )\n", this));
  205. // if we already have a data object, or we've already tried and failed
  206. // to get one, then we don't need to do any work here.
  207. if( m_pDataObject || m_fTriedToGetDataObject == TRUE )
  208. {
  209. goto logRtn;
  210. }
  211. // if cfDataObject is not on the clipboard, don't bother opening it;
  212. // we know that we can't get a data object.
  213. if( !SSIsClipboardFormatAvailable(g_cfDataObject))
  214. {
  215. goto errRtn;
  216. }
  217. //
  218. //
  219. // BEGIN: OPEN CLIPBOARD
  220. //
  221. //
  222. // Open the clipboard in preparation for the get
  223. hresult = OleOpenClipboard(NULL, NULL);
  224. if( hresult != NOERROR )
  225. {
  226. LEDebugOut((DEB_ERROR, "ERROR: OleOpenClipboard failed!\n"));
  227. goto errRtn;
  228. }
  229. hDataObject = SSGetClipboardData(g_cfDataObject);
  230. if( hDataObject )
  231. {
  232. phClipWnd = (HWND *)GlobalLock(hDataObject);
  233. LEERROR(phClipWnd == NULL, "GlobalLock failed!");
  234. if( phClipWnd )
  235. {
  236. hClipWnd = *phClipWnd;
  237. GlobalUnlock(hDataObject);
  238. }
  239. }
  240. #if DBG == 1
  241. fCloseClipSucceeded =
  242. #endif // DBG
  243. SSCloseClipboard();
  244. #if DBG == 1
  245. // We only report this error in debug
  246. if (!fCloseClipSucceeded)
  247. {
  248. LEDebugOut((DEB_ERROR, "ERROR: CloseClipboard failed!\n"));
  249. }
  250. #endif // DBG
  251. //
  252. //
  253. // END: CLOSE CLIPBOARD
  254. //
  255. //
  256. if( hClipWnd )
  257. {
  258. // See if we can get a data object
  259. hresult = GetInterfaceFromWindowProp( hClipWnd,
  260. IID_IDataObject,
  261. (IUnknown **) &m_pDataObject,
  262. CLIPBOARD_DATA_OBJECT_PROP );
  263. #if DBG ==1
  264. if( hresult != NOERROR )
  265. {
  266. Assert(m_pDataObject == NULL);
  267. }
  268. else
  269. {
  270. Assert(m_pDataObject != NULL);
  271. }
  272. #endif // DBG == 1
  273. }
  274. errRtn:
  275. logRtn:
  276. // if we didn't get a data object, then set a flag so we
  277. // don't try to do this again.
  278. m_fTriedToGetDataObject = TRUE;
  279. LEDebugOut((DEB_ITRACE,
  280. "%p OUT CClipDataObject::GetRealDataObjPtr ( ) "
  281. "[ %p ]\n", this, m_pDataObject));
  282. return m_pDataObject;
  283. }
  284. //+-------------------------------------------------------------------------
  285. //
  286. // Member: CClipDataObject::GetFormatEtcDataArray (private)
  287. //
  288. // Synopsis: if don't already have shared formats creates.
  289. //
  290. // Effects:
  291. //
  292. // Arguments: void
  293. //
  294. // Requires:
  295. //
  296. // Returns: HRESULT
  297. //
  298. // Signals:
  299. //
  300. // Modifies:
  301. //
  302. // Derivation:
  303. //
  304. // Algorithm:
  305. //
  306. // History: dd-mmm-yy Author Comment
  307. // 13-Jun-94 Ricksa author
  308. //
  309. // Notes:
  310. //
  311. //--------------------------------------------------------------------------
  312. HRESULT CClipDataObject::GetFormatEtcDataArray()
  313. {
  314. HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
  315. UINT cfFormat = NULL;
  316. ULONG i;
  317. ULONG cExtraFormats;
  318. FORMATETCDATA * pFormatEtcData;
  319. DWORD cTotal;
  320. DWORD dwSize;
  321. DWORD flatmediums, structuredmediums;
  322. #define MAX_OLE2FORMATS 4 // we can at most construct 4 OLE2
  323. // formats from OLE1 data
  324. if (m_pFormatEtcDataArray) // if already have the formats just return.
  325. return NOERROR;
  326. // 16bit apps do binary comparisons on the tymed instead
  327. // of bit-masking. This is a hack to make them work.
  328. if( IsWOWThread() )
  329. {
  330. flatmediums = TYMED_HGLOBAL;
  331. structuredmediums = TYMED_ISTORAGE;
  332. }
  333. else
  334. {
  335. flatmediums = (TYMED_HGLOBAL | TYMED_ISTREAM);
  336. structuredmediums = (TYMED_ISTORAGE | TYMED_ISTREAM |
  337. TYMED_HGLOBAL);
  338. }
  339. Assert(m_pFormatEtcDataArray == NULL);
  340. //
  341. // BEGIN: OPENCLIPBOARD
  342. //
  343. //
  344. hresult = OleOpenClipboard(NULL, NULL);
  345. if( hresult != NOERROR )
  346. {
  347. goto errRtn;
  348. }
  349. // first count the number of formats on the clipboard
  350. cTotal = CountClipboardFormats();
  351. // don't include OLE's private clipboard formats in the count
  352. if (SSIsClipboardFormatAvailable(g_cfDataObject))
  353. cTotal--;
  354. if (SSIsClipboardFormatAvailable(g_cfOlePrivateData))
  355. cTotal--;
  356. // now allocate memory for the array
  357. // if there are zero formats, then don't bother allocating
  358. // the memory
  359. Assert((LONG) cTotal >= 0);
  360. // here we will allocate enough memory for the formats
  361. // we know about plus enough to cover any OLE2 formats
  362. // that we might be able to synthesize from OLE1 formats
  363. dwSize = ((cTotal + MAX_OLE2FORMATS) * sizeof(FORMATETCDATA))
  364. + sizeof(FORMATETCDATAARRAY);
  365. m_pFormatEtcDataArray = (FORMATETCDATAARRAY *) PrivMemAlloc(dwSize);
  366. if( !m_pFormatEtcDataArray )
  367. {
  368. hresult = ResultFromScode(E_OUTOFMEMORY);
  369. if( !SSCloseClipboard() )
  370. {
  371. LEDebugOut((DEB_WARN, "WARNING: "
  372. "CloseClipboard failed!\n"));
  373. ; // no-op to keep the compiler happy
  374. }
  375. //
  376. // END: CLOSECLIPBOARD
  377. //
  378. goto errRtn;
  379. }
  380. _xmemset(m_pFormatEtcDataArray, 0,dwSize);
  381. m_pFormatEtcDataArray->_dwSig = 0;
  382. m_pFormatEtcDataArray->_dwSize = dwSize;
  383. m_pFormatEtcDataArray->_cRefs = 1;
  384. m_pFormatEtcDataArray->_fIs64BitArray = IS_WIN64;
  385. // first check to see if we can synthesize any OLE2 formats
  386. // from OLE1 data.
  387. cExtraFormats = 0;
  388. pFormatEtcData = &(m_pFormatEtcDataArray->_FormatEtcData[0]); // point to first value.
  389. // check for EmbedSource first
  390. if( CanRetrieveOle2FromOle1(g_cfEmbedSource) )
  391. {
  392. // set up a formatetc entry for EmbedSource
  393. INIT_FORETC(pFormatEtcData->_FormatEtc);
  394. pFormatEtcData->_FormatEtc.cfFormat =
  395. g_cfEmbedSource;
  396. pFormatEtcData->_FormatEtc.tymed =
  397. structuredmediums;
  398. cExtraFormats++;
  399. pFormatEtcData++;
  400. // we only want to support cfObjectDescriptor if we
  401. // can offer EmbedSource (which is why we're in this
  402. // if block)
  403. if( CanRetrieveOle2FromOle1(g_cfObjectDescriptor) )
  404. {
  405. INIT_FORETC(pFormatEtcData->_FormatEtc);
  406. pFormatEtcData->_FormatEtc.cfFormat =
  407. g_cfObjectDescriptor;
  408. pFormatEtcData->_FormatEtc.tymed =
  409. flatmediums;
  410. cExtraFormats++;
  411. pFormatEtcData++;
  412. }
  413. }
  414. // check for EmbeddedObject
  415. if( CanRetrieveOle2FromOle1(g_cfEmbeddedObject) )
  416. {
  417. // set up a formatetc entry for EmbedSource
  418. INIT_FORETC(pFormatEtcData->_FormatEtc);
  419. pFormatEtcData->_FormatEtc.cfFormat =
  420. g_cfEmbeddedObject;
  421. pFormatEtcData->_FormatEtc.tymed =
  422. structuredmediums;
  423. cExtraFormats++;
  424. pFormatEtcData++;
  425. // we only want to support cfObjectDescriptor if we
  426. // can offer EmbedEmbedded (which is why we're in this
  427. // if block)
  428. if( CanRetrieveOle2FromOle1(g_cfObjectDescriptor) )
  429. {
  430. INIT_FORETC(pFormatEtcData->_FormatEtc);
  431. pFormatEtcData->_FormatEtc.cfFormat =
  432. g_cfObjectDescriptor;
  433. pFormatEtcData->_FormatEtc.tymed =
  434. flatmediums;
  435. cExtraFormats++;
  436. pFormatEtcData++;
  437. }
  438. }
  439. // check for LinkSource
  440. if( CanRetrieveOle2FromOle1(g_cfLinkSource) )
  441. {
  442. INIT_FORETC(pFormatEtcData->_FormatEtc);
  443. pFormatEtcData->_FormatEtc.cfFormat =
  444. g_cfLinkSource;
  445. // for LinkSource in WOW, we want to explicitly offer
  446. // only ISTREAM tymed because that's what 16bit code
  447. // did.
  448. if( IsWOWThread() )
  449. {
  450. pFormatEtcData->_FormatEtc.tymed =
  451. TYMED_ISTREAM;
  452. }
  453. else
  454. {
  455. pFormatEtcData->_FormatEtc.tymed =
  456. flatmediums;
  457. }
  458. cExtraFormats++;
  459. pFormatEtcData++;
  460. // we only want to support cfLinkSrcDescriptor if we
  461. // can offer LinkSource
  462. if( CanRetrieveOle2FromOle1(g_cfLinkSrcDescriptor) )
  463. {
  464. INIT_FORETC(pFormatEtcData->_FormatEtc);
  465. pFormatEtcData->_FormatEtc.cfFormat =
  466. g_cfLinkSrcDescriptor;
  467. pFormatEtcData->_FormatEtc.tymed =
  468. flatmediums;
  469. cExtraFormats++;
  470. pFormatEtcData++;
  471. }
  472. }
  473. // Update Shared Format Header.
  474. Assert(cExtraFormats <= MAX_OLE2FORMATS);
  475. cTotal += cExtraFormats;
  476. m_pFormatEtcDataArray->_cFormats = cTotal;
  477. // now we need to go through and initialize each formatetc array
  478. // for the remaining formats available directly on the clipboard
  479. // NB: this includes any ole1 formats from which constructed OLE2
  480. // formats above. This will make it easier for apps, the interop
  481. // layer, and our api's to special case behaviour for backwards
  482. // compatibility with old apps.
  483. cfFormat = NULL;
  484. // we increment the loop counter at the bottom (so we can skip
  485. // private clipboard formats)
  486. // pFormatEtcData points to the proper starting position.
  487. for( i = cExtraFormats; i < cTotal; i++ )
  488. {
  489. // lindex == DEF_LINDEX
  490. // aspect == DVASPECT_CONTENT
  491. // ptd == NULL
  492. INIT_FORETC(pFormatEtcData->_FormatEtc);
  493. cfFormat = SSEnumClipboardFormats(cfFormat);
  494. Assert(cfFormat); // if it's NULL, something
  495. // really weird is happening.
  496. pFormatEtcData->_FormatEtc.cfFormat = (CLIPFORMAT) cfFormat;
  497. // try to make some reasonable guesses as to what's
  498. // there.
  499. switch( cfFormat )
  500. {
  501. case CF_BITMAP:
  502. case CF_PALETTE:
  503. pFormatEtcData->_FormatEtc.tymed = TYMED_GDI;
  504. break;
  505. case CF_METAFILEPICT:
  506. pFormatEtcData->_FormatEtc.tymed = TYMED_MFPICT;
  507. break;
  508. case CF_ENHMETAFILE:
  509. pFormatEtcData->_FormatEtc.tymed = TYMED_ENHMF;
  510. break;
  511. default:
  512. // check for Storage-based OLE2 formats.
  513. if( cfFormat == g_cfEmbedSource ||
  514. cfFormat == g_cfEmbeddedObject )
  515. {
  516. // we can get these on any structured and flat
  517. // mediums
  518. pFormatEtcData->_FormatEtc.tymed =
  519. structuredmediums;
  520. // In order to get here, the app must have
  521. // manually set these formats on the clipboard
  522. // (i.e. by not using OleSetClipboard()).
  523. // This is OK, but print out a warning.
  524. LEDebugOut((DEB_WARN, "WARNING: Ole2 formats "
  525. "unexpected on clipboard\n"));
  526. }
  527. else
  528. {
  529. // we don't know, so be safe and just answer
  530. // with flat mediums
  531. pFormatEtcData->_FormatEtc.tymed =
  532. flatmediums;
  533. }
  534. break;
  535. }
  536. ++pFormatEtcData;
  537. }
  538. if( !SSCloseClipboard() )
  539. {
  540. LEDebugOut((DEB_WARN, "WARNING: CloseClipboard failed!\n"));
  541. ; // no-op to keep the compiler happy
  542. }
  543. //
  544. //
  545. // END: CLOSECLIPBOARD
  546. //
  547. //
  548. hresult = NOERROR;
  549. errRtn:
  550. return hresult;
  551. }
  552. //+-------------------------------------------------------------------------
  553. //
  554. // Member: CClipDataObject::MatchFormatetc
  555. //
  556. // Synopsis: checks the given formatetc against the array of formatetc's
  557. // that is on the Native Clipboard.
  558. //
  559. // Effects:
  560. //
  561. // Arguments: [pformatetc] -- the formatetc to check
  562. // [fNativeOnly] -- If Set, return valid matches for only items that are on the Native clipboard.
  563. // [ptymed] -- where to stuff the tymed of the *original*
  564. // formatetc (may be NULL)
  565. //
  566. // Requires:
  567. //
  568. // Returns: FormatMatchFlag --
  569. // FORMAT_NOTFOUND - Format was not found in Enumerator or synthesized Data.
  570. // FORMAT_BADMATCH - Format or synthesized Found but doesn't match
  571. // FORMAT_GOODMATCH - Format Found in Enumerator or is valid synthesized data.
  572. //
  573. // Signals:
  574. //
  575. // Modifies:
  576. //
  577. // Derivation:
  578. //
  579. // Algorithm:
  580. //
  581. // History: dd-mmm-yy Author Comment
  582. // 18-Aug-94 alexgo author
  583. //
  584. // Notes:
  585. //
  586. //--------------------------------------------------------------------------
  587. typedef struct SYNTHESIZED_MAP
  588. {
  589. CLIPFORMAT cfSynthesized; // Synthesized Formats
  590. CLIPFORMAT cfOrig; // Original Format.
  591. } SYNTHESIZED_MAP;
  592. #define CF_MAXSYNTHESIZED CF_ENHMETAFILE // CF_ENHMETAFILE == 14 and >> cfFormat value we check.
  593. #define NumSynthesizedFormats 12 // Number of Synthesized formats in the Array.
  594. const SYNTHESIZED_MAP pSynthesized[] = {
  595. CF_DIB, CF_BITMAP,
  596. CF_BITMAP, CF_DIB,
  597. CF_PALETTE, CF_DIB,
  598. CF_PALETTE, CF_BITMAP,
  599. CF_METAFILEPICT,CF_ENHMETAFILE,
  600. CF_ENHMETAFILE, CF_METAFILEPICT,
  601. CF_TEXT, CF_OEMTEXT,
  602. CF_TEXT, CF_UNICODETEXT,
  603. CF_OEMTEXT, CF_TEXT,
  604. CF_OEMTEXT, CF_UNICODETEXT,
  605. CF_UNICODETEXT, CF_OEMTEXT,
  606. CF_UNICODETEXT, CF_TEXT
  607. };
  608. FormatMatchFlag CClipDataObject::MatchFormatetc( FORMATETC *pformatetc,BOOL fNativeOnly,
  609. TYMED *ptymed )
  610. {
  611. FORMATETC formatetc;
  612. ULONG i;
  613. FormatMatchFlag fFlag = FORMAT_NOTFOUND;
  614. FORMATETCDATA * pFormatEtcData = NULL;
  615. DWORD dwNumFormats;
  616. FORMATETC *pformatetcNative[CF_MAXSYNTHESIZED + 1];
  617. LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::MatchFormatetc ("
  618. " %p , %p)\n", this, pformatetc, ptymed));
  619. formatetc = *pformatetc;
  620. // some applications as for an Aspect of 0 which maps to content.
  621. if (0 == formatetc.dwAspect)
  622. formatetc.dwAspect = DVASPECT_CONTENT;
  623. // make sure all pFormatEtcs in array are initially NULL.
  624. _xmemset(pformatetcNative, 0, sizeof(FORMATETC *) * (CF_MAXSYNTHESIZED + 1));
  625. GetFormatEtcDataArray(); // Create SharedFormats from Native Clipboard if Necessary.
  626. if( ptymed )
  627. {
  628. *ptymed = TYMED_NULL;
  629. }
  630. if( m_pFormatEtcDataArray )
  631. {
  632. dwNumFormats = m_pFormatEtcDataArray->_cFormats;
  633. pFormatEtcData = &(m_pFormatEtcDataArray->_FormatEtcData[0]);
  634. for( i = 0; i < dwNumFormats; i++ )
  635. {
  636. FORMATETC tempformatetc = pFormatEtcData->_FormatEtc;
  637. // if the clipboard format matchs AND
  638. // the aspect matches AND
  639. // the tymed matches
  640. // then, return success
  641. if( tempformatetc.cfFormat ==
  642. formatetc.cfFormat)
  643. {
  644. // fix up the ptd if necessary
  645. if (tempformatetc.ptd)
  646. {
  647. tempformatetc.ptd = (DVTARGETDEVICE *)
  648. ((BYTE *) m_pFormatEtcDataArray + (ULONG_PTR) tempformatetc.ptd);
  649. }
  650. // we don't need to check TYMED because
  651. // this clipboard data object can satisfy
  652. // almost all valid TYMED's, and specfically,
  653. // more than will be contained in the
  654. // formatetc tymed field.
  655. if( ((tempformatetc.dwAspect & formatetc.dwAspect) == formatetc.dwAspect)
  656. && (tempformatetc.lindex == formatetc.lindex)
  657. && ( (tempformatetc.ptd == formatetc.ptd)
  658. || UtCompareTargetDevice(tempformatetc.ptd,formatetc.ptd))
  659. )
  660. {
  661. fFlag = FORMAT_GOODMATCH;
  662. // keep track of the tymed
  663. if( ptymed )
  664. {
  665. // this cast is a cute one;
  666. // formatetc.tymed is
  667. // actually declared to be
  668. // a DWORD, since compiler
  669. // type-checking is a bad
  670. // thing in OLE16.
  671. *ptymed = (TYMED)
  672. tempformatetc.tymed;
  673. }
  674. break;
  675. }
  676. else
  677. {
  678. fFlag = FORMAT_BADMATCH;
  679. if (fNativeOnly) // Only check first cfFormat match if only looking at native Clipboard.
  680. break;
  681. }
  682. }
  683. // if cfFormat is in predefined range and don't yet have a value for synthesized mapping, set it.
  684. // to point to the Current pFormatEtcData arrays formatEtc.
  685. if ( (tempformatetc.cfFormat <= CF_MAXSYNTHESIZED) && (NULL == pformatetcNative[tempformatetc.cfFormat]) )
  686. {
  687. pformatetcNative[tempformatetc.cfFormat] = &(pFormatEtcData->_FormatEtc);
  688. }
  689. ++pFormatEtcData;
  690. }
  691. // if no match was found in the Enumerator see if it can be synthesized from the
  692. // native clipboard.
  693. // if have enumerator and couldn't find in either enumerator or synthesized
  694. // aspect must be Content and should be one of our synthesized formats that was requested.
  695. if (FORMAT_NOTFOUND == fFlag && (formatetc.cfFormat <= CF_MAXSYNTHESIZED) )
  696. {
  697. for( i = 0; i < NumSynthesizedFormats; i++ )
  698. {
  699. // if format matches synthesized and the apspect has been set check the match
  700. // else it could have been set by another format that can be synthesized from.
  701. if ( (pSynthesized[i].cfSynthesized == formatetc.cfFormat) &&
  702. (pformatetcNative[(pSynthesized[i].cfOrig)] != NULL) )
  703. {
  704. FORMATETC tempformatetc = *(pformatetcNative[(pSynthesized[i].cfOrig)]);
  705. Assert(pSynthesized[i].cfOrig <= CF_MAXSYNTHESIZED);
  706. // fix up the ptd if necessary
  707. if (tempformatetc.ptd)
  708. {
  709. tempformatetc.ptd = (DVTARGETDEVICE *)
  710. ((BYTE *) m_pFormatEtcDataArray + (ULONG_PTR) tempformatetc.ptd);
  711. }
  712. if ( ((tempformatetc.dwAspect & formatetc.dwAspect) == formatetc.dwAspect)
  713. && (tempformatetc.lindex == formatetc.lindex)
  714. && ( (tempformatetc.ptd == formatetc.ptd)
  715. || UtCompareTargetDevice(tempformatetc.ptd,formatetc.ptd) )
  716. )
  717. {
  718. // leave tymed out param TYMED_NULL, GetData will figure this out as a not found case
  719. fFlag = FORMAT_GOODMATCH;
  720. }
  721. else
  722. {
  723. // This is a Bad Match.
  724. fFlag = FORMAT_BADMATCH;
  725. }
  726. break;
  727. }
  728. }
  729. }
  730. }
  731. // if format not found we return not found
  732. // This can happen if the format is not on the Clipboard or it is
  733. // one of the OLE synthesized formats,
  734. // If Didn't find match, the aspect is enforced to be content
  735. if ( (FORMAT_NOTFOUND == fFlag) && (formatetc.dwAspect != DVASPECT_CONTENT) )
  736. {
  737. fFlag = FORMAT_BADMATCH;
  738. }
  739. LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::MatchFormatetc ("
  740. "%lx )\n", this, fFlag));
  741. return fFlag;
  742. }
  743. //+-------------------------------------------------------------------------
  744. //
  745. // Member: CClipDataObject::Create (static)
  746. //
  747. // Synopsis: Creates a new Clipboard data object
  748. //
  749. // Effects:
  750. //
  751. // Arguments: [ppDataObj] -- where to put the data object
  752. // [cFormats] -- the count of formatetcs
  753. // [prgFormats] -- the array of formatetcs (may be NULL)
  754. //
  755. // Requires: the clipboard must be open
  756. //
  757. // Returns: HRESULT
  758. //
  759. // Signals:
  760. //
  761. // Modifies:
  762. //
  763. // Derivation:
  764. //
  765. // Algorithm: Creates a new data object, initializing an internal
  766. // formatetc array if g_cfOlePrivateData is available.
  767. //
  768. // History: dd-mmm-yy Author Comment
  769. // 19-Apr-94 alexgo author
  770. //
  771. // Notes:
  772. //
  773. //--------------------------------------------------------------------------
  774. HRESULT CClipDataObject::Create( IDataObject **ppDataObj,
  775. FORMATETCDATAARRAY *pFormatEtcDataArray)
  776. {
  777. HRESULT hresult = NOERROR;
  778. CClipDataObject * pClipData;
  779. VDATEHEAP();
  780. LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::Create ( %p )\n",
  781. NULL, ppDataObj));
  782. pClipData = new CClipDataObject();
  783. if( pClipData )
  784. {
  785. pClipData->m_pFormatEtcDataArray = pFormatEtcDataArray;
  786. *ppDataObj = pClipData;
  787. }
  788. else
  789. {
  790. hresult = ResultFromScode(E_OUTOFMEMORY);
  791. }
  792. Assert((NULL == pClipData->m_pFormatEtcDataArray) || (1 == pClipData->m_pFormatEtcDataArray->_cRefs));
  793. LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::Create ( %lx ) "
  794. "[ %lx ]\n", NULL, hresult, *ppDataObj));
  795. return hresult;
  796. }
  797. //+-------------------------------------------------------------------------
  798. //
  799. // Member: CClipDataObject::QueryInterface
  800. //
  801. // Synopsis: returns requested interfaces
  802. //
  803. // Effects:
  804. //
  805. // Arguments: [riid] -- the requested interface
  806. // [ppvObj] -- where to put the interface pointer
  807. //
  808. // Requires:
  809. //
  810. // Returns: HRESULT
  811. //
  812. // Signals:
  813. //
  814. // Modifies:
  815. //
  816. // Derivation: IDataObject
  817. //
  818. // Algorithm: Since we always create one of these data objects for
  819. // OleGetClipboard, we need to be careful about how we
  820. // handle QueryInterface since apps are free to QI for IFoo
  821. //
  822. // Identity laws: for each object with identity, QI for
  823. // IUnknown should always return the same
  824. // IUnknown. However, IFoo-->IUnknown-->IFoo
  825. // does NOT have to give you back the same
  826. // IFoo. We take advantage of this loophole.
  827. //
  828. // QI for:
  829. // IDataObject: always return a pointer to us (the fake
  830. // data object)
  831. // IFoo: if we can get a pointer back to the
  832. // original data object, delegate to it.
  833. // Note that a QI back to IDataObject will
  834. // not get back to this fake data object
  835. // IUnknown: as above, delegate to the real data object
  836. // if available. If we're in the remote case,
  837. // we'll end up getting the standard identity
  838. // object's IUnknown (unless the data object
  839. // was custom-marshalled).
  840. //
  841. // History: dd-mmm-yy Author Comment
  842. // 02-Apr-94 alexgo author
  843. //
  844. // Notes:
  845. //
  846. //--------------------------------------------------------------------------
  847. STDMETHODIMP CClipDataObject::QueryInterface( REFIID riid, LPVOID *ppvObj )
  848. {
  849. HRESULT hresult = NOERROR;
  850. VDATEHEAP();
  851. VDATETHREAD(this);
  852. LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::QueryInterface "
  853. "( %p , %p )\n", this, riid, ppvObj));
  854. // We always return our data object if IDataObject is requested.
  855. if(IsEqualIID(riid, IID_IDataObject) ||
  856. IsEqualIID(riid, IID_IUnknown))
  857. {
  858. *ppvObj = this;
  859. AddRef();
  860. goto logRtn;
  861. }
  862. // try to get the remote data object;
  863. // GetRealDataObjPtr will set m_pDataObject.
  864. GetRealDataObjPtr();
  865. if (m_pDataObject != NULL)
  866. {
  867. // If we have a real data object, the we use that to give us
  868. // the new interface since they probably want something strange
  869. hresult = m_pDataObject->QueryInterface(riid, ppvObj);
  870. }
  871. else
  872. {
  873. *ppvObj = NULL;
  874. hresult = ResultFromScode(E_NOINTERFACE);
  875. }
  876. logRtn:
  877. LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::QueryInterface "
  878. "( %lx ) [ %p ]\n", this, hresult, *ppvObj ));
  879. return hresult;
  880. }
  881. //+-------------------------------------------------------------------------
  882. //
  883. // Member: CClipDataObject::AddRef
  884. //
  885. // Synopsis: increments the reference count
  886. //
  887. // Effects:
  888. //
  889. // Arguments: void
  890. //
  891. // Requires:
  892. //
  893. // Returns: ULONG-- the new reference count
  894. //
  895. // Signals:
  896. //
  897. // Modifies:
  898. //
  899. // Derivation: IDataObject
  900. //
  901. // Algorithm:
  902. //
  903. // History: dd-mmm-yy Author Comment
  904. // 02-Apr-94 alexgo author
  905. //
  906. // Notes:
  907. //
  908. //--------------------------------------------------------------------------
  909. STDMETHODIMP_(ULONG) CClipDataObject::AddRef( )
  910. {
  911. VDATEHEAP();
  912. LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::AddRef ( )\n", this));
  913. ++m_refs;
  914. LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::AddRef ( %lu )\n",
  915. this, m_refs));
  916. return m_refs;
  917. }
  918. //+-------------------------------------------------------------------------
  919. //
  920. // Member: CClipDataObject::InternalAddRef
  921. //
  922. // Synopsis: Internal Reference count to ensure object stays alive
  923. // as long as Clipboard Code needs it.
  924. //
  925. // Effects:
  926. //
  927. // Arguments: void
  928. //
  929. // Requires:
  930. //
  931. // Returns: ULONG - Remaining Internal Reference Counts.
  932. //
  933. // Signals:
  934. //
  935. // Modifies:
  936. //
  937. // Derivation:
  938. //
  939. // Algorithm:
  940. //
  941. // History: dd-mmm-yy Author Comment
  942. // 11-Sep-96 rogerg author
  943. //
  944. // Notes:
  945. //
  946. //--------------------------------------------------------------------------
  947. ULONG CClipDataObject::InternalAddRef(void)
  948. {
  949. ++m_Internalrefs;
  950. Assert(m_Internalrefs == 1); // Should only have 1 InternalRef on Object.
  951. return m_Internalrefs;
  952. }
  953. //+-------------------------------------------------------------------------
  954. //
  955. // Member: CClipDataObject::Release
  956. //
  957. // Synopsis: decrements the reference count on the object
  958. //
  959. // Effects:
  960. //
  961. // Arguments: void
  962. //
  963. // Requires:
  964. //
  965. // Returns: ULONG -- the new reference count
  966. //
  967. // Signals:
  968. //
  969. // Modifies:
  970. //
  971. // Derivation: IDataObject
  972. //
  973. // Algorithm:
  974. //
  975. // History: dd-mmm-yy Author Comment
  976. // 02-Apr-94 alexgo author
  977. //
  978. // Notes:
  979. //
  980. //--------------------------------------------------------------------------
  981. STDMETHODIMP_(ULONG) CClipDataObject::Release( )
  982. {
  983. ULONG cRefs;
  984. VDATEHEAP();
  985. LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::Release ( )\n", this));
  986. Assert( (m_refs > 0) && (m_Internalrefs <= 1) );
  987. if( (cRefs = --m_refs ) == 0 )
  988. {
  989. // Release the Real DataObject even when still have internal since if
  990. // if Clipboard Object Changes DataObject may not be valid but would still
  991. // be use.
  992. if (m_pDataObject != NULL)
  993. {
  994. // Release our reference to the data object.
  995. m_pDataObject->Release();
  996. m_pDataObject = NULL;
  997. }
  998. m_fTriedToGetDataObject = FALSE;
  999. Assert(m_hOle1 == NULL);
  1000. Assert(m_pUnkOle1 == NULL);
  1001. if (m_Internalrefs == 0)
  1002. {
  1003. LEDebugOut((DEB_TRACE, "%p DELETED CClipDataObject\n", this));
  1004. delete this;
  1005. }
  1006. }
  1007. // using "this" below is OK, since we only want its value
  1008. LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::Release ( %lu )\n",
  1009. this, cRefs));
  1010. return cRefs;
  1011. }
  1012. //+-------------------------------------------------------------------------
  1013. //
  1014. // Member: CClipDataObject::InternalRelease
  1015. //
  1016. // Synopsis: Internal Reference count to ensure object stays alive
  1017. // as long as Clipboard Code needs it.
  1018. //
  1019. // Effects:
  1020. //
  1021. // Arguments: void
  1022. //
  1023. // Requires:
  1024. //
  1025. // Returns: DWORD - Number of Internal Reference Counts on the Object.
  1026. //
  1027. // Signals:
  1028. //
  1029. // Modifies:
  1030. //
  1031. // Derivation:
  1032. //
  1033. // Algorithm:
  1034. //
  1035. // History: dd-mmm-yy Author Comment
  1036. // 11-Sep-96 rogerg author
  1037. //
  1038. // Notes:
  1039. //
  1040. //--------------------------------------------------------------------------
  1041. ULONG CClipDataObject::InternalRelease(void)
  1042. {
  1043. ULONG cRefs;
  1044. Assert(m_Internalrefs == 1); // InternalRef should always either be 0 or 1.
  1045. if( (cRefs = --m_Internalrefs ) == 0 && (m_refs == 0) )
  1046. {
  1047. LEDebugOut((DEB_TRACE, "%p DELETED CClipDataObject\n", this));
  1048. delete this;
  1049. }
  1050. return cRefs;
  1051. }
  1052. //+-------------------------------------------------------------------------
  1053. //
  1054. // Member: CClipDataObject::GetData
  1055. //
  1056. // Synopsis: retrieves data of the specified format
  1057. //
  1058. // Effects:
  1059. //
  1060. // Arguments: [pformatetc] -- the requested format
  1061. // [pmedium] -- where to put the data
  1062. //
  1063. // Requires:
  1064. //
  1065. // Returns: HRESULT
  1066. //
  1067. // Signals:
  1068. //
  1069. // Modifies:
  1070. //
  1071. // Derivation: IDataObject
  1072. //
  1073. // Algorithm: General algorithm: we *always* duplicate data from the
  1074. // clipboard and offer it back to the caller in the desired
  1075. // format.
  1076. //
  1077. // GDI objects (BITMAPs, metafiles): these are duplicated
  1078. // via OleDuplicateData and offered back only if
  1079. // the requested tymed is correct (i.e. either
  1080. // TYMED_GDI or TYMED_MFPICT). We do not attempt
  1081. // to extract the bits and write them into a file,
  1082. // for example. Note that DIBs are really memory
  1083. // objects.
  1084. //
  1085. // for all other formats (which are flat):
  1086. //
  1087. // if asked for TYMED_FILE: create a temporary file and call
  1088. // GetDataHere.
  1089. // if asked for TYMED_ISTREAM: create a stream on an hglobal
  1090. // and call GetDataHere.
  1091. // if asked for TYMED_HGLOBAL: simply duplicate the data and
  1092. // return.
  1093. // if asked for TYMED_ISTORAGE, we will create a storage on
  1094. // an hglobal and call GetDataHere. GetDataHere
  1095. // will call StgIsStorageILockBytes to verify that
  1096. // the data in the HGlobal is really a flattened
  1097. // storage. This allows apps to pass app-defined
  1098. // formats as storages.
  1099. //
  1100. // Note that we do no checking on whether it is sensible
  1101. // for data in a particular flat format to be passed on
  1102. // a storage. StgIsStorageILockBytes will detect that
  1103. // we can't construct a storage on the flat data, so we
  1104. // will catch all illegal attempts to get storage data.
  1105. //
  1106. // Medium preferences:
  1107. // GDI objects: only one allowed (depends on format)
  1108. // Others: ISTORAGE, then HGLOBAL, then ISTREAM,
  1109. // then FILE. If we know the 'prefered' medium
  1110. // of the data (from the original formatetc),
  1111. // then we use the ordering above to find the
  1112. // first match between what the caller wants
  1113. // and the 'preferred' mediums of the data.
  1114. // Otherwise, we use the first medium from the
  1115. // above list that matches what the caller wants.
  1116. //
  1117. //
  1118. // OLE1 Compatibility:
  1119. // The basic problem: Ole1 objects only offer cfNative,
  1120. // cfOwnerLink, and/or cfObjectLink on the clipboard.
  1121. // We need to translate these into cfEmbedSource,
  1122. // cfLinkSource, etc.
  1123. // Basic Algorithm:
  1124. // First check to see if we can satisfy an OLE2 data
  1125. // request directly, without medium translation. If so,
  1126. // then we simply return the data to the user.
  1127. // Otherwise, we create the Ole2 data and then copy it
  1128. // into whatever medium the caller desired. Note that
  1129. // this potentially means an extra allocation, but apps
  1130. // are not likely to ask for ObjectDescriptor on a
  1131. // memory stream ;-)
  1132. //
  1133. //
  1134. // History: dd-mmm-yy Author Comment
  1135. // 04-Jun-94 alexgo added OLE1 support
  1136. // 02-Apr-94 alexgo author
  1137. //
  1138. // Notes:
  1139. //
  1140. //--------------------------------------------------------------------------
  1141. STDMETHODIMP CClipDataObject::GetData( LPFORMATETC pformatetc, LPSTGMEDIUM
  1142. pmedium)
  1143. {
  1144. HRESULT hresult = NOERROR;
  1145. HANDLE handle;
  1146. TYMED tymedOriginal = TYMED_NULL;
  1147. BOOL fMatchResult;
  1148. VDATEHEAP();
  1149. VDATETHREAD(this);
  1150. VDATEPTRIN(pformatetc, FORMATETC);
  1151. VDATEPTROUT(pmedium, STGMEDIUM);
  1152. LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::GetData ( %p , %p )\n",
  1153. this, pformatetc, pmedium));
  1154. // zero the pmedium structure.
  1155. _xmemset(pmedium, 0, sizeof(STGMEDIUM));
  1156. // try to get the remote data object
  1157. // GetRealDataObjPtr will set m_pDataObject.
  1158. GetRealDataObjPtr();
  1159. if (m_pDataObject != NULL)
  1160. {
  1161. // We have a data object, so just forward that call to the
  1162. // real data object and then exit the routine since it did
  1163. // all the work.
  1164. hresult = m_pDataObject->GetData(pformatetc, pmedium);
  1165. // WOW HACK alert! Some Win16 apps, like Word6 and XL,
  1166. // won't work if we continue and offer data in the requested
  1167. // format anyway. By failing here, we more closely mimic
  1168. // 16bit OLE behaviour
  1169. if (hresult == NOERROR || IsWOWThread() )
  1170. {
  1171. goto errRtn;
  1172. }
  1173. // If this GetData failed, we just fall through since the
  1174. // generic code may be able to handle the request
  1175. }
  1176. // first, we are going through and verify that we can satisfy
  1177. // the format and medium request. We will fetch the data in
  1178. // the subsequent switch statement.
  1179. // we first need to check to see if the clipboard format is a
  1180. // user-defined GDI format. We do not know how to duplicate
  1181. // these, so we can't satisfy the GetData request.
  1182. if( pformatetc->cfFormat >= CF_GDIOBJFIRST &&
  1183. pformatetc->cfFormat <= CF_GDIOBJLAST )
  1184. {
  1185. hresult = ResultFromScode(DV_E_FORMATETC);
  1186. goto errRtn;
  1187. }
  1188. // There is no DataObject or request for DataObject Failed
  1189. // then MatchFormat must return it found a match or the aspect
  1190. // requested must be content.
  1191. fMatchResult = MatchFormatetc(pformatetc,TRUE /*fNativeOnly */, &tymedOriginal);
  1192. if (FORMAT_BADMATCH == fMatchResult)
  1193. {
  1194. hresult = ResultFromScode(DV_E_FORMATETC);
  1195. goto errRtn;
  1196. }
  1197. // now check for "standard" formats
  1198. switch( pformatetc->cfFormat )
  1199. {
  1200. case CF_BITMAP:
  1201. case CF_PALETTE:
  1202. // TYMED_GDI is the only medium we support.
  1203. if( (pformatetc->tymed & TYMED_GDI) )
  1204. {
  1205. pmedium->tymed = TYMED_GDI;
  1206. }
  1207. else
  1208. {
  1209. hresult = ResultFromScode(DV_E_TYMED);
  1210. goto errRtn;
  1211. }
  1212. break;
  1213. case CF_METAFILEPICT:
  1214. // TYMED_MFPICT is the only medium we support
  1215. if( (pformatetc->tymed & TYMED_MFPICT) )
  1216. {
  1217. pmedium->tymed = TYMED_MFPICT;
  1218. }
  1219. else
  1220. {
  1221. hresult = ResultFromScode(DV_E_TYMED);
  1222. goto errRtn;
  1223. }
  1224. break;
  1225. case CF_ENHMETAFILE:
  1226. // TYMED_ENHMF is the only medium we support
  1227. if( (pformatetc->tymed & TYMED_ENHMF) )
  1228. {
  1229. pmedium->tymed = TYMED_ENHMF;
  1230. }
  1231. else
  1232. {
  1233. hresult = ResultFromScode(DV_E_TYMED);
  1234. goto errRtn;
  1235. }
  1236. break;
  1237. // all other formats
  1238. default:
  1239. // we prefer TYMED_ISTORAGE, then TYMED_HGLOBAL, then
  1240. // TYMED_ISTREAM
  1241. // first check for matches with the 'preferred'
  1242. // mediums of the data
  1243. if( tymedOriginal != TYMED_NULL )
  1244. {
  1245. if( ((pformatetc->tymed & TYMED_ISTORAGE)
  1246. & tymedOriginal) )
  1247. {
  1248. pmedium->tymed = TYMED_ISTORAGE;
  1249. break;
  1250. }
  1251. else if( ((pformatetc->tymed & TYMED_HGLOBAL)
  1252. & tymedOriginal))
  1253. {
  1254. pmedium->tymed = TYMED_HGLOBAL;
  1255. break;
  1256. }
  1257. else if( ((pformatetc->tymed & TYMED_ISTREAM)
  1258. & tymedOriginal))
  1259. {
  1260. pmedium->tymed = TYMED_ISTREAM;
  1261. break;
  1262. }
  1263. }
  1264. // if we didn't match above or if we don't know
  1265. // the preferred formats, then make a best guess
  1266. // and keep going.
  1267. if( (pformatetc->tymed & TYMED_ISTORAGE) )
  1268. {
  1269. pmedium->tymed = TYMED_ISTORAGE;
  1270. }
  1271. else if( (pformatetc->tymed & TYMED_HGLOBAL) )
  1272. {
  1273. pmedium->tymed = TYMED_HGLOBAL;
  1274. }
  1275. else if( (pformatetc->tymed & TYMED_ISTREAM) )
  1276. {
  1277. pmedium->tymed = TYMED_ISTREAM;
  1278. }
  1279. else
  1280. {
  1281. hresult = ResultFromScode(DV_E_TYMED);
  1282. goto errRtn;
  1283. }
  1284. break;
  1285. }
  1286. // if we get this far, we've successfully picked the medium
  1287. // on which we want to get our data. For each medium, grab
  1288. // the data.
  1289. // If we need to construct OLE2 formats from OLE1 data,
  1290. // then go ahead and try to fetch the data here. If we can
  1291. // fetch the data in the desired medium, then go ahead and return.
  1292. // This optimization saves 1 extra allocation and copy when
  1293. // retrieving OLE1 data.
  1294. if( CanRetrieveOle2FromOle1(pformatetc->cfFormat) )
  1295. {
  1296. //
  1297. //
  1298. // BEGIN: OPENCLIPBOARD
  1299. //
  1300. //
  1301. hresult = OleOpenClipboard(NULL, NULL);
  1302. if( hresult != NOERROR )
  1303. {
  1304. goto errRtn;
  1305. }
  1306. // now fetch the data. Since we're passing in the caller's
  1307. // pmedium, this call *may* fail (since GetOle2FromOle1
  1308. // *only* retrieves HGLOBAL or the native TYMED). If so,
  1309. // we'll fetch HGLOBAL from the OleGetClipboardData call
  1310. // below and then do the appropriate conversion.
  1311. hresult = GetOle2FromOle1(pformatetc->cfFormat, pmedium);
  1312. // no matter what the result, we want to close the
  1313. // clipboard
  1314. if( !SSCloseClipboard() )
  1315. {
  1316. LEDebugOut((DEB_WARN, "WARNING: CloseClipboard "
  1317. "failed!\n"));
  1318. ; // no-op
  1319. }
  1320. //
  1321. //
  1322. // END: CLOSECLIPBOARD
  1323. //
  1324. //
  1325. if( hresult == NOERROR )
  1326. {
  1327. // we successfully retrieved the Ole2 data the
  1328. // caller wanted. First reset our state
  1329. // (*without* freeing the data we're returning
  1330. // to the caller) and then go ahead and
  1331. // return.
  1332. FreeResources(JUST_RESET);
  1333. goto errRtn;
  1334. }
  1335. // FALL-THROUGH. If we weren't able
  1336. // to retrieve data in the desired format, it probably
  1337. // means the caller was asking for data on non-primary
  1338. // medium. The default processing below should take care of
  1339. // this.
  1340. // Recall that this code block is an optimization to
  1341. // avoid multiple allocations and copies in the "normal"
  1342. // case.
  1343. }
  1344. switch( pmedium->tymed )
  1345. {
  1346. case TYMED_HGLOBAL:
  1347. case TYMED_MFPICT:
  1348. case TYMED_ENHMF:
  1349. case TYMED_GDI:
  1350. // Mini-algorithm: Open the clipboard, fetch and
  1351. // duplicate the data, then close the clipboard.
  1352. // we only open the clipboard here because the
  1353. // GetDataHere call will open the clipboard for
  1354. // the other cases. (Recall that OpenClipboard and
  1355. // CloseClipboard are not balanced; only one CloseClipboard
  1356. // is necessary to actually close the clipboard).
  1357. //
  1358. //
  1359. // BEGIN: OPENCLIPBOARD
  1360. //
  1361. //
  1362. hresult = OleOpenClipboard(NULL, NULL);
  1363. if( hresult != NOERROR )
  1364. {
  1365. break;
  1366. }
  1367. hresult = OleGetClipboardData(pformatetc->cfFormat, &handle);
  1368. if( hresult == NOERROR )
  1369. {
  1370. // since hGlobal is in a union, we don't need to
  1371. // explicity assign for each medium type.
  1372. pmedium->hGlobal = OleDuplicateData(handle,
  1373. pformatetc->cfFormat, NULL);
  1374. if( !pmedium->hGlobal )
  1375. {
  1376. hresult = ResultFromScode(E_OUTOFMEMORY);
  1377. // FALL-THROUGH!!: this is deliberate; we want
  1378. // to close the clipboard and get out (which is
  1379. // what the code below does)
  1380. }
  1381. }
  1382. if( !SSCloseClipboard() )
  1383. {
  1384. LEDebugOut((DEB_WARN, "WARNING: CloseClipboard failed!"
  1385. "\n"));
  1386. // don't overwrite the original error code
  1387. if( hresult == NOERROR )
  1388. {
  1389. hresult =
  1390. ResultFromScode(CLIPBRD_E_CANT_CLOSE);
  1391. }
  1392. // FALL-THROUGH!! to the break below;
  1393. }
  1394. //
  1395. //
  1396. // END: CLOSECLIPBOARD
  1397. //
  1398. //
  1399. break;
  1400. case TYMED_ISTREAM:
  1401. // create a memory stream.
  1402. hresult = CreateStreamOnHGlobal(NULL,
  1403. TRUE /*fDeleteOnRelease*/, &(pmedium->pstm));
  1404. if( hresult != NOERROR )
  1405. {
  1406. break;
  1407. }
  1408. hresult = GetDataHere( pformatetc, pmedium );
  1409. break;
  1410. case TYMED_ISTORAGE:
  1411. // create a memory storage (ILockBytes on top of a
  1412. // a docfile).
  1413. hresult = UtCreateStorageOnHGlobal(NULL,
  1414. TRUE /*fDeleteOnRelease*/, &(pmedium->pstg),
  1415. NULL);
  1416. if( hresult != NOERROR )
  1417. {
  1418. break;
  1419. }
  1420. hresult = GetDataHere( pformatetc, pmedium );
  1421. break;
  1422. case TYMED_FILE:
  1423. // create a temporary file
  1424. pmedium->lpszFileName = (LPOLESTR)PubMemAlloc( MAX_PATH +1 );
  1425. if( !pmedium->lpszFileName )
  1426. {
  1427. hresult = ResultFromScode(E_OUTOFMEMORY);
  1428. break;
  1429. }
  1430. hresult = UtGetTempFileName( OLESTR("~OLE"),
  1431. pmedium->lpszFileName);
  1432. if( hresult == NOERROR )
  1433. {
  1434. hresult = GetDataHere( pformatetc, pmedium );
  1435. }
  1436. break;
  1437. default:
  1438. // should never get here
  1439. AssertSz(0, "Unknown TYMED for get Data");
  1440. hresult = ResultFromScode(E_UNEXPECTED);
  1441. break;
  1442. }
  1443. // NB!!! Do not put any extra processing here without modifying the
  1444. // error paths in the above switch (they just break, instead of
  1445. // doing a goto errRtn. This was done to avoid some duplicated
  1446. // code.
  1447. if( hresult != NOERROR )
  1448. {
  1449. // ReleaseStgMedium will correctly cleanup NULL and
  1450. // partially NULL mediums, so we can rely on it for
  1451. // general-purpose cleanup
  1452. ReleaseStgMedium(pmedium);
  1453. }
  1454. // no matter what the error code, we should reset our state and
  1455. // free any resources the OLE1 compatibility code may have allocated
  1456. FreeResources(RESET_AND_FREE);
  1457. errRtn:
  1458. LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::GetData ( %lx )\n",
  1459. this, hresult));
  1460. return hresult;
  1461. }
  1462. //+-------------------------------------------------------------------------
  1463. //
  1464. // Member: CClipDataObject::GetDataHere
  1465. //
  1466. // Synopsis: retrieves data of the specified format
  1467. //
  1468. // Effects:
  1469. //
  1470. // Arguments: [pformatetc] -- the requested format
  1471. // [pmedium] -- where to put the data, if NULL, then
  1472. // the call is treated as a Query.
  1473. //
  1474. // Requires:
  1475. //
  1476. // Returns: HRESULT
  1477. //
  1478. // Signals:
  1479. //
  1480. // Modifies:
  1481. //
  1482. // Derivation: IDataObject
  1483. //
  1484. // Algorithm: General algorithm: we *always* duplicate data from the
  1485. // clipboard and offer it back to the caller in the desired
  1486. // medium. Since this is GetDataHere, we attempt to copy the
  1487. // data into the medium provided by the caller.
  1488. //
  1489. // GDI objects (BITMAPs, metafiles): *cannot* be retrieved
  1490. // by GetDataHere, since we do not translate GDI
  1491. // objects into byte arrays and we cannot copy a
  1492. // metafile into a metafile (for example).
  1493. //
  1494. // for all other formats (which are flat):
  1495. //
  1496. // if asked for TYMED_FILE: open the file for create/append and
  1497. // write the data into it.
  1498. // if asked for TYMED_ISTREAM: write the data into the stream
  1499. // if asked for TYMED_HGLOBAL: verify first that the given
  1500. // hglobal is big enough; if so, then copy the clipboard
  1501. // data into it.
  1502. //
  1503. // if asked for TYMED_ISTORAGE: call StgIsStorageILockBytes
  1504. // to verify that the data in the HGlobal is really
  1505. // a flattened storage. This allows apps to pass
  1506. // app-defined formats as storages.
  1507. //
  1508. // OLE1 Compatibility:
  1509. // OleGetClipboardData will manufacture OLE2 formats from
  1510. // OLE1 data as necessary. We simply take this handle and
  1511. // copy it into the caller's medium (as with any other handle).
  1512. //
  1513. // History: dd-mmm-yy Author Comment
  1514. // 04-Jun-94 alexgo added OLE1 support
  1515. // 02-Apr-94 alexgo author
  1516. //
  1517. // Notes: The spec does not say that a NULL pmedium should be treated
  1518. // as a Query; however the 16bit code did that and it was fairly
  1519. // easy for us to duplicate that behaviour.
  1520. //
  1521. //--------------------------------------------------------------------------
  1522. STDMETHODIMP CClipDataObject::GetDataHere( LPFORMATETC pformatetc, LPSTGMEDIUM
  1523. pmedium)
  1524. {
  1525. HRESULT hresult = NOERROR;
  1526. HANDLE handle;
  1527. DWORD cbClipData = 0;
  1528. BOOL fMatchResult;
  1529. VDATEHEAP();
  1530. VDATETHREAD(this);
  1531. VDATEPTRIN(pformatetc, FORMATETC);
  1532. if( pmedium )
  1533. {
  1534. VDATEPTRIN(pmedium, STGMEDIUM);
  1535. }
  1536. LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::GetDataHere ( %p , %p"
  1537. " )\n", this, pformatetc, pmedium));
  1538. // try to get the remote data object
  1539. // GetRealDataObjPtr will set m_pDataObject.
  1540. GetRealDataObjPtr();
  1541. if (m_pDataObject != NULL)
  1542. {
  1543. // We have a data object, so just forward that call to the
  1544. // real data object and then exit the routine since it did
  1545. // all the work.
  1546. hresult = m_pDataObject->GetDataHere(pformatetc, pmedium);
  1547. // If this this failed, we just fall through since the
  1548. // generic code may be able to handle the request
  1549. // WOW HACK alert! Some Win16 apps, like Word6 and XL,
  1550. // won't work if we continue and offer data in the requested
  1551. // format anyway. By failing here, we more closely mimic
  1552. // 16bit OLE behaviour
  1553. if (hresult == NOERROR || IsWOWThread() )
  1554. {
  1555. goto logRtn;
  1556. }
  1557. // If this GetDataHere failed, we just fall through since the
  1558. // generic code may be able to handle the request
  1559. }
  1560. // eliminate the GDI case immediately
  1561. // we do not satisfy requests to GetDataHere for a GDI object
  1562. // note that DIB's are really memory objects.
  1563. if( (pformatetc->cfFormat == CF_BITMAP) ||
  1564. (pformatetc->cfFormat == CF_PALETTE) ||
  1565. (pformatetc->cfFormat == CF_METAFILEPICT) ||
  1566. (pformatetc->cfFormat == CF_ENHMETAFILE) ||
  1567. (pformatetc->cfFormat >= CF_GDIOBJFIRST &&
  1568. pformatetc->cfFormat <= CF_GDIOBJLAST ))
  1569. {
  1570. hresult = ResultFromScode(DV_E_FORMATETC);
  1571. goto logRtn;
  1572. }
  1573. // There is no DataObject or request for DataObject Failed
  1574. // then MatchFormat must return it found a match or the aspect
  1575. // requested must be content.
  1576. fMatchResult = MatchFormatetc(pformatetc,TRUE /*fNativeOnly */, NULL);
  1577. if (FORMAT_BADMATCH == fMatchResult)
  1578. {
  1579. hresult = ResultFromScode(DV_E_FORMATETC);
  1580. goto errRtn;
  1581. }
  1582. // If pmedium == NULL, then we will just
  1583. // query and leave. As noted above, this behavior is for 16bit
  1584. // compatibility.
  1585. if( !pmedium )
  1586. {
  1587. if( OleIsClipboardFormatAvailable(pformatetc->cfFormat) )
  1588. {
  1589. hresult = NOERROR;
  1590. }
  1591. else
  1592. {
  1593. hresult = ResultFromScode(DV_E_CLIPFORMAT);
  1594. }
  1595. goto logRtn;
  1596. }
  1597. //
  1598. //
  1599. // BEGIN: OPENCLIPBOARD
  1600. //
  1601. //
  1602. // open the clipboard and retrieve the data. Once we have it,
  1603. // we'll do a switch and stuff it into the right spot.
  1604. hresult = OleOpenClipboard(NULL, NULL);
  1605. if( hresult != NOERROR )
  1606. {
  1607. goto logRtn;
  1608. }
  1609. // now actually get the data
  1610. Assert(pmedium);
  1611. hresult = OleGetClipboardData(pformatetc->cfFormat, &handle);
  1612. if( hresult != NOERROR )
  1613. {
  1614. goto errRtn;
  1615. }
  1616. // now copy the data into the given medium
  1617. // for everything but storages, we need to know the size of the
  1618. // data coming off the clipboard.
  1619. // note that we have a general problem with comparing sizes--
  1620. // GlobalSize returns the size of the *allocated* block, which
  1621. // is not the same as the size of the real data (which, in
  1622. // general, we have no way of determining).
  1623. // When transfering from HGLOBAL to HGBOBAL, we therefore have
  1624. // a boundary case where we actually have enough room to copy
  1625. // the *real* data from the clipboard, but the global block
  1626. // from the clipboard is bigger (causing a failure)
  1627. // If an app really cares, GetData should be called instead.
  1628. if( pmedium->tymed != TYMED_ISTORAGE )
  1629. {
  1630. cbClipData = (ULONG) GlobalSize(handle);
  1631. if( cbClipData == 0 )
  1632. {
  1633. // got bad data from the clipboard
  1634. hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
  1635. goto errRtn;
  1636. }
  1637. }
  1638. switch( pmedium->tymed )
  1639. {
  1640. case TYMED_HGLOBAL:
  1641. // if there is enough room to stuff the data in the given
  1642. // hglobal, then do so.
  1643. hresult = UtHGLOBALtoHGLOBAL( handle, cbClipData,
  1644. pmedium->hGlobal);
  1645. break;
  1646. case TYMED_ISTREAM:
  1647. // copy the data into the medium's stream
  1648. hresult = UtHGLOBALtoStm( handle, cbClipData, pmedium->pstm);
  1649. break;
  1650. case TYMED_ISTORAGE:
  1651. // create a storage on top of the HGLOBAL and CopyTo to the
  1652. // medium's storage. Note that this will only work if
  1653. // the HGLOBAL originally had a storage dumped on it
  1654. hresult = UtHGLOBALtoStorage( handle, pmedium->pstg);
  1655. break;
  1656. case TYMED_FILE:
  1657. // append the data into the file
  1658. hresult = UtHGLOBALtoFile( handle, cbClipData,
  1659. pmedium->lpszFileName);
  1660. break;
  1661. default:
  1662. // we can't GetDataHere into GDI objects!!! (etc).
  1663. hresult = ResultFromScode(DV_E_TYMED);
  1664. break;
  1665. }
  1666. // NB!!: Be careful about adding extra code here; the above
  1667. // switch does nothing special for error cases.
  1668. errRtn:
  1669. if( !SSCloseClipboard() )
  1670. {
  1671. LEDebugOut((DEB_WARN, "WARNING: CloseClipboard failed!\n"));
  1672. if( hresult == NOERROR )
  1673. {
  1674. hresult = ResultFromScode(CLIPBRD_E_CANT_CLOSE);
  1675. }
  1676. }
  1677. //
  1678. //
  1679. // END: CLOSECLIPBOARD
  1680. //
  1681. //
  1682. // now free any resources we may have used for OLE1 compatibility
  1683. FreeResources(RESET_AND_FREE);
  1684. logRtn:
  1685. LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::GetDataHere ( %lx )\n",
  1686. this, hresult));
  1687. return hresult;
  1688. }
  1689. //+-------------------------------------------------------------------------
  1690. //
  1691. // Member: CClipDataObject::QueryGetData
  1692. //
  1693. // Synopsis: queries whether a GetData call would succeed
  1694. //
  1695. // Effects:
  1696. //
  1697. // Arguments: [pformatetc] -- the requested format
  1698. //
  1699. // Requires:
  1700. //
  1701. // Returns: HRESULT
  1702. //
  1703. // Signals:
  1704. //
  1705. // Modifies:
  1706. //
  1707. // Derivation: IDataObject
  1708. //
  1709. // Algorithm: we simply see if the requested clipboard format is on the
  1710. // clipboard.
  1711. //
  1712. // If we have an array of formatetcs (m_rgFormats from the
  1713. // g_cfOlePrivateData clipboard data), then we use that info
  1714. // to check. Otherwise, we will do as much checking as we can
  1715. // without actually fetching the data.
  1716. //
  1717. // Note that this is not 100% accurate (because
  1718. // we may not be able to get the data in the requested medium
  1719. // (such as TYMED_ISTORAGE)). Without actually doing a GetData
  1720. // call, however, this is the best we can do.
  1721. //
  1722. // History: dd-mmm-yy Author Comment
  1723. // 04-Jun-94 alexgo added OLE1 support
  1724. // 17-May-94 alexgo removed call to OpenClipboard
  1725. // 02-Apr-94 alexgo author
  1726. //
  1727. // Notes:
  1728. //
  1729. //--------------------------------------------------------------------------
  1730. STDMETHODIMP CClipDataObject::QueryGetData( LPFORMATETC pformatetc )
  1731. {
  1732. HRESULT hresult = NOERROR;
  1733. FormatMatchFlag fFlag;
  1734. VDATEHEAP();
  1735. VDATETHREAD(this);
  1736. VDATEPTRIN(pformatetc, FORMATETC);
  1737. LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::QueryGetData ( %p )\n",
  1738. this, pformatetc));
  1739. // we check if the clipboard format is available *before*
  1740. // checking the formatetc list as an optimization. If a previous
  1741. // attempt to render data had failed, then NT will remove that
  1742. // clipboard format from the clipboard.
  1743. if( OleIsClipboardFormatAvailable(pformatetc->cfFormat))
  1744. {
  1745. fFlag = MatchFormatetc(pformatetc,FALSE /*fNativeOnly */, NULL);
  1746. if( fFlag == FORMAT_GOODMATCH )
  1747. {
  1748. hresult = NOERROR;
  1749. goto errRtn;
  1750. }
  1751. else if( fFlag == FORMAT_BADMATCH )
  1752. {
  1753. hresult = ResultFromScode(DV_E_FORMATETC);
  1754. goto errRtn;
  1755. }
  1756. // even if we didn't match in the formatetc list,
  1757. // continue to check below. We can satisfy
  1758. // many more GetData requests than the app may
  1759. // have orginally.
  1760. // do all the verification we can without actually
  1761. // fetching the data
  1762. switch( pformatetc->cfFormat )
  1763. {
  1764. case CF_BITMAP:
  1765. case CF_PALETTE:
  1766. // GDI objects must be requested on TYMED_GDI
  1767. if( pformatetc->tymed != TYMED_GDI )
  1768. {
  1769. hresult = ResultFromScode(DV_E_TYMED);
  1770. }
  1771. break;
  1772. case CF_METAFILEPICT:
  1773. // metafiles must be on TYMED_MFPICT
  1774. if( pformatetc->tymed != TYMED_MFPICT )
  1775. {
  1776. hresult = ResultFromScode(DV_E_TYMED);
  1777. }
  1778. break;
  1779. case CF_ENHMETAFILE:
  1780. // enhanced metafiles must be on TYMED_ENHMF;
  1781. if( pformatetc->tymed != TYMED_ENHMF )
  1782. {
  1783. hresult = ResultFromScode(DV_E_TYMED);
  1784. }
  1785. break;
  1786. default:
  1787. // we cannot deal with special GDI objects
  1788. if( pformatetc->cfFormat >= CF_GDIOBJFIRST &&
  1789. pformatetc->cfFormat <= CF_GDIOBJLAST )
  1790. {
  1791. hresult = ResultFromScode(DV_E_FORMATETC);
  1792. break;
  1793. }
  1794. // we cannot put other formats onto metafiles
  1795. // or GDI objects
  1796. // failure case: if somebody requests
  1797. // TYMED_ISTORAGE but the actually hglobal on the
  1798. // clipboard does not contain storage-formated data
  1799. if( pformatetc->tymed == TYMED_GDI ||
  1800. pformatetc->tymed == TYMED_MFPICT ||
  1801. pformatetc->tymed == TYMED_ENHMF )
  1802. {
  1803. hresult = ResultFromScode(DV_E_TYMED);
  1804. }
  1805. break;
  1806. }
  1807. }
  1808. else
  1809. {
  1810. hresult = ResultFromScode(DV_E_CLIPFORMAT);
  1811. }
  1812. errRtn:
  1813. LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::QueryGetData "
  1814. "( %lx )\n", this, hresult));
  1815. return hresult;
  1816. }
  1817. //+-------------------------------------------------------------------------
  1818. //
  1819. // Member: CClipDataObject::GetCanonicalFormatEtc
  1820. //
  1821. // Synopsis: retrieve the canonical format
  1822. //
  1823. // Effects:
  1824. //
  1825. // Arguments: [pformatetc] -- the requested format
  1826. // [pformatetcOut] -- the canonical format
  1827. //
  1828. // Requires:
  1829. //
  1830. // Returns: HRESULT
  1831. //
  1832. // Signals:
  1833. //
  1834. // Modifies:
  1835. //
  1836. // Derivation: IDataObject
  1837. //
  1838. // Algorithm: Since we always return the same data for each clipboard
  1839. // format, this function is very simple (basically returns
  1840. // the input formatetc, with a NULL target device).
  1841. //
  1842. // History: dd-mmm-yy Author Comment
  1843. // 02-Apr-94 alexgo author
  1844. //
  1845. // Notes:
  1846. //
  1847. //--------------------------------------------------------------------------
  1848. STDMETHODIMP CClipDataObject::GetCanonicalFormatEtc( LPFORMATETC pformatetc,
  1849. LPFORMATETC pformatetcOut)
  1850. {
  1851. VDATEHEAP();
  1852. VDATETHREAD(this);
  1853. VDATEPTRIN(pformatetc, FORMATETC);
  1854. VDATEPTROUT(pformatetcOut, FORMATETC);
  1855. LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::GetCanonicalFormatEtc"
  1856. " ( %p , %p )\n", this, pformatetc, pformatetcOut));
  1857. // initialize the out param
  1858. INIT_FORETC(*pformatetcOut);
  1859. pformatetcOut->cfFormat = pformatetc->cfFormat;
  1860. pformatetcOut->tymed = pformatetc->tymed;
  1861. LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::GetCanonicalFormatEtc"
  1862. " ( %lx )\n", this, NOERROR ));
  1863. return NOERROR;
  1864. }
  1865. //+-------------------------------------------------------------------------
  1866. //
  1867. // Member: CClipDataObject::SetData
  1868. //
  1869. // Synopsis: sets data of the specified format
  1870. //
  1871. // Effects:
  1872. //
  1873. // Arguments: [pformatetc] -- the format of the data
  1874. // [pmedium] -- the data
  1875. //
  1876. // Requires:
  1877. //
  1878. // Returns: E_NOTIMPL
  1879. //
  1880. // Signals:
  1881. //
  1882. // Modifies:
  1883. //
  1884. // Derivation: IDataObject
  1885. //
  1886. // Algorithm:
  1887. //
  1888. // History: dd-mmm-yy Author Comment
  1889. // 02-Apr-94 alexgo author
  1890. //
  1891. // Notes:
  1892. //
  1893. //--------------------------------------------------------------------------
  1894. STDMETHODIMP CClipDataObject::SetData( LPFORMATETC pformatetc, LPSTGMEDIUM
  1895. pmedium, BOOL fRelease)
  1896. {
  1897. HRESULT hr;
  1898. VDATEHEAP();
  1899. VDATETHREAD(this);
  1900. VDATEREADPTRIN(pformatetc, FORMATETC);
  1901. VDATEREADPTRIN(pmedium, STGMEDIUM);
  1902. LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::SetData ( %p , %p )\n",
  1903. this, pformatetc, pmedium));
  1904. // try to get the remote data object
  1905. // GetRealDataObjPtr will set m_pDataObject.
  1906. GetRealDataObjPtr();
  1907. if (NULL != m_pDataObject)
  1908. {
  1909. hr = m_pDataObject->SetData(pformatetc,pmedium,fRelease);
  1910. }
  1911. else
  1912. {
  1913. hr = E_FAIL;
  1914. }
  1915. LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::SetData ( %lx )\n",
  1916. this, hr));
  1917. return hr;
  1918. }
  1919. //+-------------------------------------------------------------------------
  1920. //
  1921. // Member: CClipDataObject::EnumFormatEtc
  1922. //
  1923. // Synopsis: return an enumerator for the available data formats
  1924. //
  1925. // Effects:
  1926. //
  1927. // Arguments: [dwDirection] -- the direction (GET or SET)
  1928. // [ppenum] -- where to put the enumerator
  1929. //
  1930. // Requires:
  1931. //
  1932. // Returns: HRESULT
  1933. //
  1934. // Signals:
  1935. //
  1936. // Modifies:
  1937. //
  1938. // Derivation: IDataObject
  1939. //
  1940. // Algorithm: create a clipboard formatetc enumerator. Upon creation,
  1941. // we'll grab everything off clipboard we need (so that simple
  1942. // enumeration doesn't block access to the clipboard).
  1943. //
  1944. // History: dd-mmm-yy Author Comment
  1945. // 02-Apr-94 alexgo author
  1946. //
  1947. // Notes:
  1948. //
  1949. //--------------------------------------------------------------------------
  1950. STDMETHODIMP CClipDataObject::EnumFormatEtc( DWORD dwDirection,
  1951. LPENUMFORMATETC * ppenum )
  1952. {
  1953. HRESULT hresult;
  1954. VDATEHEAP();
  1955. VDATETHREAD(this);
  1956. VDATEPTROUT(ppenum, LPENUMFORMATETC);
  1957. LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::EnumFormatEtc ( %lx "
  1958. ", %p )\n", this, dwDirection, ppenum));
  1959. // we can only enumerate in the GET direction
  1960. *ppenum = NULL;
  1961. if( dwDirection != DATADIR_GET )
  1962. {
  1963. hresult = ResultFromScode(E_NOTIMPL);
  1964. goto errRtn;
  1965. }
  1966. GetFormatEtcDataArray(); // make sure dataArray is Set up.
  1967. if (m_pFormatEtcDataArray)
  1968. {
  1969. *ppenum = new CEnumFormatEtcDataArray(m_pFormatEtcDataArray,0);
  1970. }
  1971. hresult = *ppenum ? NOERROR : E_OUTOFMEMORY;
  1972. errRtn:
  1973. LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::EnumFormatEtc ( %lx )"
  1974. "\n", this, hresult));
  1975. return hresult;
  1976. }
  1977. //+-------------------------------------------------------------------------
  1978. //
  1979. // Member: CClipDataObject::DAdvise
  1980. //
  1981. // Synopsis: register a data advise
  1982. //
  1983. // Effects:
  1984. //
  1985. // Arguments: [pformatetc] -- the requested format
  1986. // [dwAdvf] -- advise flags
  1987. // [pAdvSink] -- the advise sink
  1988. // [pdwConnection] -- where to put the connection ID
  1989. //
  1990. // Requires:
  1991. //
  1992. // Returns: OLE_E_ADVISENOTSUPPORTED
  1993. //
  1994. // Signals:
  1995. //
  1996. // Modifies:
  1997. //
  1998. // Derivation: IDataObject
  1999. //
  2000. // Algorithm:
  2001. //
  2002. // History: dd-mmm-yy Author Comment
  2003. // 02-Apr-94 alexgo author
  2004. //
  2005. // Notes:
  2006. //
  2007. //--------------------------------------------------------------------------
  2008. STDMETHODIMP CClipDataObject::DAdvise( LPFORMATETC pformatetc, DWORD dwAdvf,
  2009. IAdviseSink * pAdvSink, DWORD *pdwConnection )
  2010. {
  2011. (void)pformatetc;
  2012. (void)dwAdvf;
  2013. (void)pAdvSink;
  2014. (void)pdwConnection;
  2015. VDATEHEAP();
  2016. VDATETHREAD(this);
  2017. LEDebugOut((DEB_WARN, "WARNING: DAdvise on the clipboard data"
  2018. "object is not supported!\n"));
  2019. return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
  2020. }
  2021. //+-------------------------------------------------------------------------
  2022. //
  2023. // Member: CClipDataObject::DUnadvise
  2024. //
  2025. // Synopsis: unadvises an advise connection
  2026. //
  2027. // Effects:
  2028. //
  2029. // Arguments: [dwConnection] -- the connection to remove
  2030. //
  2031. // Requires:
  2032. //
  2033. // Returns: OLE_E_ADVISENOTSUPPORTED
  2034. //
  2035. // Signals:
  2036. //
  2037. // Modifies:
  2038. //
  2039. // Derivation: IDataObject
  2040. //
  2041. // Algorithm:
  2042. //
  2043. // History: dd-mmm-yy Author Comment
  2044. // 02-Apr-94 alexgo author
  2045. //
  2046. // Notes:
  2047. //
  2048. //--------------------------------------------------------------------------
  2049. STDMETHODIMP CClipDataObject::DUnadvise(DWORD dwConnection)
  2050. {
  2051. (void)dwConnection;
  2052. VDATEHEAP();
  2053. VDATETHREAD(this);
  2054. LEDebugOut((DEB_WARN, "WARNING: DUnadvise on the clipboard data"
  2055. "object is not supported!\n"));
  2056. return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
  2057. }
  2058. //+-------------------------------------------------------------------------
  2059. //
  2060. // Member: CClipDataObject::EnumDAdvise
  2061. //
  2062. // Synopsis: enumerates data advises
  2063. //
  2064. // Effects:
  2065. //
  2066. // Arguments: [ppenum] -- where to put the enumerator
  2067. //
  2068. // Requires:
  2069. //
  2070. // Returns: OLE_E_ADVISENOTSUPPORTED
  2071. //
  2072. // Signals:
  2073. //
  2074. // Modifies:
  2075. //
  2076. // Derivation: IDataObject
  2077. //
  2078. // Algorithm:
  2079. //
  2080. // History: dd-mmm-yy Author Comment
  2081. // 02-Apr-94 alexgo author
  2082. //
  2083. // Notes:
  2084. //
  2085. //--------------------------------------------------------------------------
  2086. STDMETHODIMP CClipDataObject::EnumDAdvise( LPENUMSTATDATA *ppenum)
  2087. {
  2088. (void)ppenum;
  2089. VDATEHEAP();
  2090. VDATETHREAD(this);
  2091. LEDebugOut((DEB_WARN, "WARNING: EnumDAdvise on the clipboard data"
  2092. "object is not supported!\n"));
  2093. return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
  2094. }
  2095. //
  2096. // Private methods on CClipDataObject
  2097. //
  2098. //+-------------------------------------------------------------------------
  2099. //
  2100. // Member: CClipDataObject::FreeResources (private)
  2101. //
  2102. // Synopsis: frees any resources allocated by OLE1 compatibility
  2103. // code and resets state
  2104. //
  2105. // Effects:
  2106. //
  2107. // Arguments: [fFlags] -- either JUST_RESET or RESET_AND_FREE
  2108. //
  2109. // Requires:
  2110. //
  2111. // Returns: void
  2112. //
  2113. // Signals:
  2114. //
  2115. // Modifies:
  2116. //
  2117. // Derivation:
  2118. //
  2119. // Algorithm:
  2120. //
  2121. // History: dd-mmm-yy Author Comment
  2122. // 04-Jun-94 alexgo author
  2123. //
  2124. // Notes:
  2125. //
  2126. //--------------------------------------------------------------------------
  2127. void CClipDataObject::FreeResources( FreeResourcesFlags fFlags )
  2128. {
  2129. VDATEHEAP();
  2130. LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::FreeResources "
  2131. "( %lx )\n", this, fFlags));
  2132. if( (fFlags & RESET_AND_FREE) )
  2133. {
  2134. if( m_hOle1 )
  2135. {
  2136. GlobalFree(m_hOle1);
  2137. }
  2138. if( m_pUnkOle1 )
  2139. {
  2140. m_pUnkOle1->Release();
  2141. }
  2142. }
  2143. m_hOle1 = NULL;
  2144. m_pUnkOle1 = NULL;
  2145. LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::FreeResources "
  2146. "( )\n", this ));
  2147. }
  2148. //+-------------------------------------------------------------------------
  2149. //
  2150. // Member: CClipDataObject::GetAndTranslateOle1 (private)
  2151. //
  2152. // Synopsis: Retrieves either cfOwnerLink or cfObjectLink from the
  2153. // clipboard, reads the strings and converts to Unicode
  2154. //
  2155. // Effects: all strings will be allocated with the public allocator
  2156. //
  2157. // Arguments: [cf] -- the clipboard format to retrieve
  2158. // must be either cfOwnerLink or cfObjectLink
  2159. // [ppszClass] -- where to put the class name (may be NULL)
  2160. // [ppszFile] -- where to put the file name (may be NULL)
  2161. // [ppszItem] -- where to put the item name (may be NULL)
  2162. // [ppszItemA] -- where to put the ANSI item name
  2163. // (may be NULL)
  2164. //
  2165. // Requires: the clipboard must be open
  2166. //
  2167. // Returns: HRESULT
  2168. //
  2169. // Signals:
  2170. //
  2171. // Modifies:
  2172. //
  2173. // Derivation:
  2174. //
  2175. // Algorithm: cfOwnerLink and cfObjectLink are laid out as follows
  2176. // classname\0filename\0\itemname\0\0
  2177. // These strings are ANSI, so we must convert to unicode.
  2178. //
  2179. // History: dd-mmm-yy Author Comment
  2180. // 04-Jun-94 alexgo author
  2181. //
  2182. // Notes:
  2183. //
  2184. //--------------------------------------------------------------------------
  2185. HRESULT CClipDataObject::GetAndTranslateOle1( UINT cf, LPOLESTR *ppszClass,
  2186. LPOLESTR *ppszFile, LPOLESTR *ppszItem, LPSTR *ppszItemA )
  2187. {
  2188. LPSTR pszClassA = NULL,
  2189. pszFileA = NULL,
  2190. pszItemA = NULL;
  2191. HGLOBAL hOle1;
  2192. HRESULT hresult = NOERROR;
  2193. VDATEHEAP();
  2194. LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetAndTranslate"
  2195. "Ole1 ( %d , %p , %p , %p )\n", this, cf, ppszClass, ppszFile,
  2196. ppszItem));
  2197. Assert( cf == g_cfOwnerLink || cf == g_cfObjectLink );
  2198. // NULL out-params
  2199. if( ppszClass )
  2200. {
  2201. *ppszClass = NULL;
  2202. }
  2203. if( ppszFile )
  2204. {
  2205. *ppszFile = NULL;
  2206. }
  2207. if( ppszItem )
  2208. {
  2209. *ppszItem = NULL;
  2210. }
  2211. hOle1 = SSGetClipboardData(cf);
  2212. if( hOle1 == NULL )
  2213. {
  2214. LEDebugOut((DEB_WARN, "WARNING: GetClipboardData Failed!\n"));
  2215. hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
  2216. goto logRtn;
  2217. }
  2218. pszClassA = (LPSTR)GlobalLock(hOle1);
  2219. if( pszClassA == NULL )
  2220. {
  2221. LEDebugOut((DEB_WARN, "WARNING: GlobalLock failed!\n"));
  2222. hresult = ResultFromScode(E_OUTOFMEMORY);
  2223. goto logRtn;
  2224. }
  2225. if( ppszClass )
  2226. {
  2227. hresult = UtGetUNICODEData((ULONG) strlen(pszClassA) + 1, pszClassA,
  2228. NULL, ppszClass);
  2229. if( hresult != NOERROR )
  2230. {
  2231. goto errRtn;
  2232. }
  2233. }
  2234. pszFileA = pszClassA + strlen(pszClassA) + 1;
  2235. if( ppszFile )
  2236. {
  2237. hresult = UtGetUNICODEData((ULONG) strlen(pszFileA) + 1, pszFileA,
  2238. NULL, ppszFile );
  2239. if( hresult != NOERROR )
  2240. {
  2241. goto errRtn;
  2242. }
  2243. }
  2244. pszItemA = pszFileA + strlen(pszFileA) +1;
  2245. if( ppszItem )
  2246. {
  2247. hresult = UtGetUNICODEData((ULONG) strlen(pszItemA) + 1, pszItemA,
  2248. NULL, ppszItem);
  2249. if( hresult != NOERROR )
  2250. {
  2251. goto errRtn;
  2252. }
  2253. }
  2254. if( ppszItemA )
  2255. {
  2256. *ppszItemA = UtDupStringA(pszItemA);
  2257. if( !*ppszItemA )
  2258. {
  2259. hresult = ResultFromScode(E_OUTOFMEMORY);
  2260. // FALL-THROUGH! no need to goto the error
  2261. // handling code right below us
  2262. }
  2263. }
  2264. errRtn:
  2265. GlobalUnlock(hOle1);
  2266. if( hresult != NOERROR )
  2267. {
  2268. if( ppszClass && *ppszClass )
  2269. {
  2270. PubMemFree(*ppszClass);
  2271. *ppszClass = NULL;
  2272. }
  2273. if( ppszFile && *ppszFile )
  2274. {
  2275. PubMemFree(*ppszFile);
  2276. *ppszFile = NULL;
  2277. }
  2278. if( ppszItem && *ppszItem )
  2279. {
  2280. PubMemFree(*ppszItem);
  2281. *ppszItem = NULL;
  2282. }
  2283. #if DBG == 1
  2284. // if this assert goes off, then we added more code
  2285. // without modifying the error paths for ansi item strings
  2286. if( ppszItemA )
  2287. {
  2288. Assert(*ppszItem == NULL );
  2289. }
  2290. #endif // DBG ==1
  2291. }
  2292. logRtn:
  2293. LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetAndTranslate"
  2294. "Ole1 ( %lx ) [ %p , %p , %p ]\n", this, hresult,
  2295. (ppszClass)? *ppszClass : 0,
  2296. (ppszFile) ? *ppszFile : 0,
  2297. (ppszItem) ? *ppszItem : 0 ));
  2298. return hresult;
  2299. }
  2300. //+-------------------------------------------------------------------------
  2301. //
  2302. // Member: CClipDataObject::GetEmbeddedObjectFromOle1
  2303. //
  2304. // Synopsis: synthesizes cfEmbeddedObject from available OLE1
  2305. // data.
  2306. //
  2307. // Effects:
  2308. //
  2309. // Arguments: [pmedium] -- where to put the requested data
  2310. //
  2311. // Requires: The clipboard must be OPEN
  2312. // we must have verified that the correct formats are
  2313. // available before calling
  2314. //
  2315. // Returns: HRESULT
  2316. //
  2317. // Signals:
  2318. //
  2319. // Modifies:
  2320. //
  2321. // Derivation:
  2322. //
  2323. // Algorithm: create a memory-based stroage and stuff the following
  2324. // infomation in it:
  2325. // clsid StdOleLink
  2326. // an available presentation
  2327. // the class from OwnerLink data as the user type
  2328. // link information
  2329. //
  2330. // Much of this work is done by the helper function
  2331. // GenericObjectToIStorage
  2332. //
  2333. // History: dd-mmm-yy Author Comment
  2334. // 11-Aug-94 alexgo author
  2335. //
  2336. // Notes: This code is largely based from 16bit OLE sources
  2337. // REVIEW: we may want to rework portions of this code,
  2338. // particularly if we rewrite the GENOBJ code (in
  2339. // ostm2stg.cpp).
  2340. //
  2341. //--------------------------------------------------------------------------
  2342. HRESULT CClipDataObject::GetEmbeddedObjectFromOle1( STGMEDIUM *pmedium )
  2343. {
  2344. HRESULT hresult;
  2345. IStorage * pstg = NULL;
  2346. LPOLESTR pszClass = NULL;
  2347. ILockBytes * plockbytes = NULL;
  2348. BOOL fDeleteOnRelease = TRUE;
  2349. GENOBJ genobj;
  2350. HGLOBAL hglobal;
  2351. VDATEHEAP();
  2352. LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetEmbeddedObject"
  2353. "FromOle1 ( %p )\n", this, pmedium));
  2354. // if we are asking for EmbeddedObject on an hglobal, then we
  2355. // don't want to delete the hglobal when we release the storage
  2356. if( pmedium->tymed == TYMED_HGLOBAL )
  2357. {
  2358. fDeleteOnRelease = FALSE;
  2359. }
  2360. genobj.m_class.Set(CLSID_StdOleLink, NULL);
  2361. // the destructor for the generic object will free the
  2362. // presentation.
  2363. genobj.m_ppres = new PRES;
  2364. if( genobj.m_ppres == NULL )
  2365. {
  2366. hresult = ResultFromScode(E_OUTOFMEMORY);
  2367. goto errRtn;
  2368. }
  2369. genobj.m_fLink = TRUE;
  2370. genobj.m_lnkupdopt = UPDATE_ALWAYS;
  2371. if( SSIsClipboardFormatAvailable(CF_METAFILEPICT))
  2372. {
  2373. hglobal = SSGetClipboardData(CF_METAFILEPICT);
  2374. if( hglobal )
  2375. {
  2376. if( (hresult = MfToPres(hglobal, genobj.m_ppres))
  2377. != NOERROR)
  2378. {
  2379. goto errRtn;
  2380. }
  2381. }
  2382. else
  2383. {
  2384. LEDebugOut((DEB_WARN, "WARNING: Unable to "
  2385. "retrieve CF_METAFILEPICT\n"));
  2386. hresult = ResultFromScode(E_OUTOFMEMORY);
  2387. goto errRtn;
  2388. }
  2389. }
  2390. else if( SSIsClipboardFormatAvailable(CF_DIB) )
  2391. {
  2392. hglobal = SSGetClipboardData(CF_DIB);
  2393. if( hglobal )
  2394. {
  2395. // DibToPres will take ownership of the
  2396. // hglobal
  2397. HGLOBAL hTemp;
  2398. hTemp = UtDupGlobal(hglobal, GMEM_DDESHARE |
  2399. GMEM_MOVEABLE);
  2400. if( !hTemp )
  2401. {
  2402. hresult = ResultFromScode(E_OUTOFMEMORY);
  2403. goto errRtn;
  2404. }
  2405. if( (hresult = DibToPres(hTemp, genobj.m_ppres))
  2406. != NOERROR )
  2407. {
  2408. GlobalFree(hTemp);
  2409. goto errRtn;
  2410. }
  2411. }
  2412. else
  2413. {
  2414. LEDebugOut((DEB_WARN, "WARNING: Unable to "
  2415. "retrieve CF_DIB\n"));
  2416. hresult = ResultFromScode(E_OUTOFMEMORY);
  2417. goto errRtn;
  2418. }
  2419. }
  2420. else if (SSIsClipboardFormatAvailable(CF_BITMAP))
  2421. {
  2422. hglobal = SSGetClipboardData(CF_BITMAP);
  2423. if( hglobal )
  2424. {
  2425. if( (hresult = BmToPres(hglobal, genobj.m_ppres))
  2426. != NOERROR )
  2427. {
  2428. goto errRtn;
  2429. }
  2430. }
  2431. else
  2432. {
  2433. LEDebugOut((DEB_WARN, "WARNING: Unable to "
  2434. "retrieve CF_BITMAP\n"));
  2435. hresult = ResultFromScode(E_OUTOFMEMORY);
  2436. goto errRtn;
  2437. }
  2438. }
  2439. else
  2440. {
  2441. delete genobj.m_ppres;
  2442. genobj.m_ppres = NULL;
  2443. genobj.m_fNoBlankPres = TRUE;
  2444. }
  2445. hresult = GetAndTranslateOle1(g_cfOwnerLink, &pszClass,
  2446. &genobj.m_szTopic, &genobj.m_szItem, NULL);
  2447. if( hresult != NOERROR )
  2448. {
  2449. goto errRtn;
  2450. }
  2451. genobj.m_classLast.SetSz(pszClass);
  2452. // now we need to create a storage to stuff the generic object
  2453. // into.
  2454. hresult = UtCreateStorageOnHGlobal(NULL, fDeleteOnRelease,
  2455. &pstg, &plockbytes);
  2456. if( hresult != NOERROR )
  2457. {
  2458. goto errRtn;
  2459. }
  2460. hresult = GenericObjectToIStorage(genobj, pstg, NULL);
  2461. if (SUCCEEDED(hresult))
  2462. {
  2463. hresult = NOERROR;
  2464. }
  2465. if( IsOwnerLinkStdOleLink() &&
  2466. SSIsClipboardFormatAvailable( g_cfNative) )
  2467. {
  2468. // Case of copying an OLE 2 link from a 1.0 container.
  2469. // The first part of this function created a presentation
  2470. // stream from the presentation on the clipboard. The
  2471. // presentation is NOT already inside the Native data (i.e.,
  2472. // the cfEmbeddedObject) because we removed it to conserve
  2473. // space.
  2474. hglobal = SSGetClipboardData(g_cfNative);
  2475. if( hglobal == NULL )
  2476. {
  2477. LEDebugOut((DEB_WARN, "WARNING: GetClipboardData for "
  2478. "cfNative failed!\n"));
  2479. hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
  2480. goto errRtn;
  2481. }
  2482. // now stuff the native data into the storage, first
  2483. // removing any presentation streams that may have
  2484. // previously existed.
  2485. hresult = NativeToStorage(pstg, hglobal);
  2486. }
  2487. // finished!! now fill out the pmedium argument and return
  2488. if( pmedium->tymed == TYMED_ISTORAGE )
  2489. {
  2490. // hang onto the storage, in case we need to release
  2491. // it later
  2492. m_pUnkOle1 = (IUnknown *)pstg;
  2493. pmedium->pstg = pstg;
  2494. // NO AddRef
  2495. }
  2496. else
  2497. {
  2498. Assert(pmedium->tymed == TYMED_HGLOBAL);
  2499. hresult = GetHGlobalFromILockBytes(plockbytes,
  2500. &pmedium->hGlobal);
  2501. // GetHGLOBAL should never fail here because we
  2502. // just created the ILockBytes!!
  2503. Assert( hresult == NOERROR );
  2504. // in this case, we want to release the storage
  2505. // and save the hglobal for later delete
  2506. m_hOle1 = pmedium->hGlobal;
  2507. pstg->Release();
  2508. pstg = NULL;
  2509. }
  2510. errRtn:
  2511. // if there was an error, we need to blow away any storage
  2512. // that we may have created
  2513. if( hresult != NOERROR )
  2514. {
  2515. if( pszClass )
  2516. {
  2517. PubMemFree(pszClass);
  2518. }
  2519. if( pstg )
  2520. {
  2521. pstg->Release();
  2522. Assert(m_pUnkOle1 == NULL);
  2523. }
  2524. }
  2525. // no matter what, we need to release our lockbytes
  2526. if( plockbytes )
  2527. {
  2528. // in case of failure we need to make sure the HGLOBAL
  2529. // used by plockbytes also gets freed - fDeleteOnRelease
  2530. // tells if plockbytes->Release will do that work for us
  2531. if (FAILED(hresult) && !fDeleteOnRelease)
  2532. {
  2533. HRESULT hrCheck; // Preserve hresult
  2534. // GetHGlobal should never fail here because we just
  2535. // created the ILockBytes
  2536. hrCheck = GetHGlobalFromILockBytes(plockbytes,
  2537. &hglobal);
  2538. Assert(NOERROR == hrCheck);
  2539. // GlobalFree returns NULL on success
  2540. hglobal = GlobalFree(hglobal);
  2541. Assert(hglobal == NULL);
  2542. }
  2543. plockbytes->Release();
  2544. }
  2545. LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetEmbeddedObject"
  2546. "FromOle1 ( %lx ) \n", this, hresult));
  2547. return hresult;
  2548. }
  2549. //+-------------------------------------------------------------------------
  2550. //
  2551. // Member: CClipDataObject::GetEmbedSourceFromOle1 (private)
  2552. //
  2553. // Synopsis: synthesizes cfEmbedSource from available OLE1 data
  2554. //
  2555. // Effects:
  2556. //
  2557. // Arguments: [pmedium] -- where to put the resulting data
  2558. //
  2559. // Requires: The clipboard must be OPEN
  2560. // we must have verified that the correct formats are
  2561. // available before calling and *while* the clipboard
  2562. // is open (to avoid a race condition)
  2563. //
  2564. // Returns: HRESULT
  2565. //
  2566. // Signals:
  2567. //
  2568. // Modifies:
  2569. //
  2570. // Derivation:
  2571. //
  2572. // Algorithm: create a memory-based storage and stuff the following
  2573. // information in it:
  2574. // the clsid of the embedding
  2575. // the class name as the user type
  2576. // the native data in the OLE10_NATIVE_STREAM
  2577. // the item name in the OLE10_ITEMNAME_STREAM
  2578. //
  2579. // History: dd-mmm-yy Author Comment
  2580. // 17-Aug-94 alexgo fix the check for OLE2 data to handle
  2581. // OLE2 treat as from OLE1
  2582. // 03-Aug-94 AlexT Check for OLE 2 data
  2583. // 04-Jun-94 alexgo author
  2584. //
  2585. // Notes:
  2586. //
  2587. //--------------------------------------------------------------------------
  2588. HRESULT CClipDataObject::GetEmbedSourceFromOle1( STGMEDIUM *pmedium )
  2589. {
  2590. HRESULT hresult;
  2591. IStorage * pstg = NULL;
  2592. HGLOBAL hNative;
  2593. HGLOBAL hCopy = NULL;
  2594. LPOLESTR pszClass = NULL;
  2595. LPSTR pszItemA = NULL;
  2596. CLSID clsid;
  2597. ILockBytes * plockbytes = NULL;
  2598. BOOL fDeleteOnRelease = TRUE;
  2599. BOOL fIsOle1 = TRUE;
  2600. VDATEHEAP();
  2601. LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetEmbedSourceFrom"
  2602. "Ole1 ( %p )\n", this, pmedium));
  2603. Assert(SSIsClipboardFormatAvailable(g_cfOwnerLink));
  2604. Assert(SSIsClipboardFormatAvailable(g_cfNative));
  2605. // first fetch the class name of the object
  2606. hresult = GetAndTranslateOle1( g_cfOwnerLink, &pszClass, NULL, NULL,
  2607. &pszItemA );
  2608. if( hresult != NOERROR )
  2609. {
  2610. goto errRtn;
  2611. }
  2612. // now fetch the clsid for the embedding
  2613. hresult = wCLSIDFromProgID(pszClass, &clsid, TRUE);
  2614. if( hresult != NOERROR )
  2615. {
  2616. goto errRtn;
  2617. }
  2618. // if we are asking for EmbedSource on an hglobal, then we
  2619. // don't want to delete the hglobal when we release the storage
  2620. if( pmedium->tymed == TYMED_HGLOBAL )
  2621. {
  2622. fDeleteOnRelease = FALSE;
  2623. }
  2624. // now fetch the native data
  2625. hNative = SSGetClipboardData(g_cfNative);
  2626. if( hNative == NULL )
  2627. {
  2628. hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
  2629. goto errRtn;
  2630. }
  2631. if (!CoIsOle1Class(clsid))
  2632. {
  2633. // Just because the clsid is OLE2 does not mean that the
  2634. // underlying data is OLE2. For example, suppose a container
  2635. // copies an old OLE1 object to the clipboard, but the OLE2
  2636. // version of that object has been installed on the system.
  2637. // CLSIDFromProgID will return the *OLE2* class ID in this case.
  2638. // If we're in this case, then we should fall through and treat
  2639. // the data as normal OLE1 (StgOpenStorageOnILockBytes would
  2640. // fail in any event).
  2641. hresult = CreateILockBytesOnHGlobal(hNative, FALSE,
  2642. &plockbytes);
  2643. if( hresult != NOERROR )
  2644. {
  2645. goto errRtn;
  2646. }
  2647. hresult = StgIsStorageILockBytes(plockbytes);
  2648. plockbytes->Release();
  2649. plockbytes = NULL;
  2650. if( hresult == NOERROR )
  2651. {
  2652. // the hNative data really contains a serialized
  2653. // IStorage.
  2654. //
  2655. // This will arise in two cases:
  2656. // 1. Publisher 2.0, 16bit put data on the
  2657. // clipboard. They do not call OLE api's but
  2658. // instead synthesize the same data that 16bit
  2659. // OleSetClipboard would.
  2660. //
  2661. // 2. An OLE1.0 container copies an OLE2 embedding
  2662. // to the clipboard.
  2663. fIsOle1 = FALSE;
  2664. hCopy = UtDupGlobal(hNative,
  2665. GMEM_DDESHARE | GMEM_MOVEABLE);
  2666. if( NULL == hCopy )
  2667. {
  2668. hresult = E_OUTOFMEMORY;
  2669. goto errRtn;
  2670. }
  2671. // create plockbytes
  2672. hresult = CreateILockBytesOnHGlobal(hCopy,
  2673. fDeleteOnRelease,
  2674. &plockbytes);
  2675. if( hresult != NOERROR )
  2676. {
  2677. goto errRtn;
  2678. }
  2679. // the HGLOBAL in plockbytes can change, so we
  2680. // can't do anything with hCopy; we NULL it out
  2681. // to make sure we don't try to free it
  2682. hCopy = NULL;
  2683. hresult = StgOpenStorageOnILockBytes(plockbytes, NULL,
  2684. STGM_SALL,
  2685. NULL, 0, &pstg);
  2686. if (FAILED(hresult))
  2687. {
  2688. goto errRtn;
  2689. }
  2690. // We explicitly ignore any error returned by the
  2691. // following
  2692. UtDoStreamOperation(pstg, NULL, OPCODE_REMOVE,
  2693. STREAMTYPE_CACHE);
  2694. }
  2695. // else the data is really OLE1 and is just being emulated by
  2696. // an OLE2 object
  2697. // Just fall through to the code below which will
  2698. // stuff hNative into the OLE10_NATIVE_STREAM
  2699. }
  2700. // this will be TRUE if the clsid is OLE1 or if the clsid is OLE2
  2701. // but the data in hNative is OLE1 anyway (see comments above)
  2702. if( fIsOle1 == TRUE )
  2703. {
  2704. hresult = UtCreateStorageOnHGlobal( NULL, fDeleteOnRelease,
  2705. &pstg, &plockbytes);
  2706. if( hresult != NOERROR )
  2707. {
  2708. goto errRtn;
  2709. }
  2710. // we need to stuff the class id of the embedding into the
  2711. // storage
  2712. // REVIEW: this clsid may be an OLE2 class id. This could
  2713. // cause us trouble in treat as scenarios.
  2714. hresult = pstg->SetClass(clsid);
  2715. if( hresult != NOERROR )
  2716. {
  2717. goto errRtn;
  2718. }
  2719. // store the user type information, etc in our private data
  2720. // streams if RegisterClipboardFormat fails, it will return 0,
  2721. // which is OK for us.
  2722. hresult = WriteFmtUserTypeStg(pstg,
  2723. (CLIPFORMAT) RegisterClipboardFormat(pszClass),
  2724. pszClass);
  2725. if( hresult != NOERROR )
  2726. {
  2727. goto errRtn;
  2728. }
  2729. // now stuff the native data into the OLE10_NATIVE_STREAM
  2730. // this is a little worker function found in utstream.cpp
  2731. // which will stuff the hglobal to the OLE1 data into the
  2732. // right stream.
  2733. // the OLE1 DDE stuff also uses this function.
  2734. // REVIEW:
  2735. // the FALSE flag is confusing here, it's supposed to be
  2736. // fIsOle1Interop. 16bit clipboard sources passed FALSE when doing
  2737. // their 1.0 interop stuff, so we'll do that here. When we
  2738. // overhaul the main 1.0 interop stuff, we should change this flag
  2739. // to be something more intuitive.
  2740. hresult = StSave10NativeData(pstg, hNative, FALSE);
  2741. if( hresult != NOERROR )
  2742. {
  2743. goto errRtn;
  2744. }
  2745. // If we have an item name, then stuff that into
  2746. // OLE10_ITEMNAME_STREAM
  2747. if( pszItemA && pszItemA[0] != '\0' )
  2748. {
  2749. hresult = StSave10ItemName(pstg, pszItemA);
  2750. }
  2751. }
  2752. // this Commit call in non-intuitive. Basically, we may
  2753. // try to get the underlying hglobal (see below) *before*
  2754. // we release the storage. The commit guarantees that all
  2755. // the important state information gets flushed to the
  2756. // hglobal (which is not otherwise guaranteed).
  2757. hresult = pstg->Commit(STGC_DEFAULT);
  2758. if( hresult != NOERROR )
  2759. {
  2760. goto errRtn;
  2761. }
  2762. // FINIS!!
  2763. // now fill out all of the arguments
  2764. if( pmedium->tymed == TYMED_ISTORAGE )
  2765. {
  2766. // hang onto the storage, in case we need to release
  2767. // it later
  2768. m_pUnkOle1 = (IUnknown *)pstg;
  2769. pmedium->pstg = pstg;
  2770. // NO AddRef
  2771. }
  2772. else
  2773. {
  2774. Assert(pmedium->tymed == TYMED_HGLOBAL);
  2775. hresult = GetHGlobalFromILockBytes(plockbytes,
  2776. &pmedium->hGlobal);
  2777. // GetHGLOBAL should never fail here because we
  2778. // just created the ILockBytes!!
  2779. Assert( hresult == NOERROR );
  2780. // in this case, we want to release the storage
  2781. // and save the hglobal for later delete
  2782. m_hOle1 = pmedium->hGlobal;
  2783. pstg->Release();
  2784. pstg = NULL;
  2785. }
  2786. errRtn:
  2787. // we are done with our strings
  2788. if( pszClass )
  2789. {
  2790. PubMemFree(pszClass);
  2791. }
  2792. if( pszItemA )
  2793. {
  2794. PubMemFree(pszItemA);
  2795. }
  2796. // if there was an error, we need to blow away any storage
  2797. // that we may have created
  2798. if( hresult != NOERROR )
  2799. {
  2800. if( pstg )
  2801. {
  2802. pstg->Release();
  2803. m_pUnkOle1 = NULL;
  2804. }
  2805. }
  2806. // no matter what, we need to release our lockbytes.
  2807. if( plockbytes )
  2808. {
  2809. // in case of failure we need to make sure the HGLOBAL
  2810. // used by plockbytes also gets freed - fDeleteOnRelease
  2811. // tells if plockbytes->Release will do that work for us
  2812. if (FAILED(hresult) && !fDeleteOnRelease)
  2813. {
  2814. HRESULT hrCheck; // Preserve hresult
  2815. // GetHGlobal should never fail here because we just
  2816. // created the ILockBytes
  2817. hrCheck = GetHGlobalFromILockBytes(plockbytes, &hCopy);
  2818. Assert(NOERROR == hrCheck);
  2819. // hCopy will be freed below
  2820. }
  2821. plockbytes->Release();
  2822. }
  2823. if (NULL != hCopy)
  2824. {
  2825. // GlobalFree returns NULL on success
  2826. hCopy = GlobalFree(hCopy);
  2827. Assert(NULL == hCopy);
  2828. }
  2829. LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetEmbedSource"
  2830. "FromOle1 ( %lx ) \n", this, hresult));
  2831. return hresult;
  2832. }
  2833. //+-------------------------------------------------------------------------
  2834. //
  2835. // Member: CClipDataObject::GetLinkSourceFromOle1 (private)
  2836. //
  2837. // Synopsis: Synthesizes cfLinkSource format from OLE1 data
  2838. //
  2839. // Effects:
  2840. //
  2841. // Arguments: [pmedium] -- where to put the data
  2842. //
  2843. // Requires: the clipboard must be open
  2844. // we must have verified that the correct formats are
  2845. // available before calling and *while* the clipboard
  2846. // is open (to avoid a race condition)
  2847. //
  2848. // Returns: HRESULT
  2849. //
  2850. // Signals:
  2851. //
  2852. // Modifies:
  2853. //
  2854. // Derivation:
  2855. //
  2856. // Algorithm: Gets the clsid, filename, and item name for the OLE1 object
  2857. // and creates an OLE1 file moniker. This moniker is then
  2858. // saved into a memory stream
  2859. //
  2860. // History: dd-mmm-yy Author Comment
  2861. // 04-Jun-94 alexgo author
  2862. // 05-Aug-94 AlexT Link Source also needs class id
  2863. //
  2864. // Notes:
  2865. //
  2866. //--------------------------------------------------------------------------
  2867. HRESULT CClipDataObject::GetLinkSourceFromOle1( STGMEDIUM *pmedium )
  2868. {
  2869. HRESULT hresult;
  2870. IStream * pstm = NULL;
  2871. LPMONIKER pmkFile = NULL,
  2872. pmkFinal = NULL,
  2873. pmkItem = NULL;
  2874. IPersistStream *pPersistStream = NULL;
  2875. LPOLESTR pszClass = NULL,
  2876. pszFile = NULL,
  2877. pszItem = NULL;
  2878. CLSID clsid;
  2879. UINT cf;
  2880. BOOL fDeleteOnRelease = TRUE;
  2881. VDATEHEAP();
  2882. LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetLinkSourceFrom"
  2883. "Ole1 ( %p , %p )\n", this, pmedium ));
  2884. // fetch the info we need from cfOwnerLink or cfObjectLink
  2885. // If this function is called, we should have already determined
  2886. // that the formats were available in the correct order
  2887. // for creating links.
  2888. if( SSIsClipboardFormatAvailable(g_cfObjectLink) )
  2889. {
  2890. cf = g_cfObjectLink;
  2891. }
  2892. else
  2893. {
  2894. cf = g_cfOwnerLink;
  2895. Assert(SSIsClipboardFormatAvailable(g_cfOwnerLink));
  2896. }
  2897. hresult = GetAndTranslateOle1(cf, &pszClass, &pszFile,
  2898. &pszItem, NULL);
  2899. if( hresult != NOERROR )
  2900. {
  2901. goto errRtn;
  2902. }
  2903. // now fetch the clsid for the OLE1 server
  2904. hresult = wCLSIDFromProgID(pszClass, &clsid, TRUE);
  2905. if( hresult != NOERROR )
  2906. {
  2907. goto errRtn;
  2908. }
  2909. // now build up our moniker
  2910. hresult = CreateOle1FileMoniker(pszFile, clsid, &pmkFile);
  2911. if( hresult != NOERROR )
  2912. {
  2913. goto errRtn;
  2914. }
  2915. if( pszItem && pszItem[0] != OLESTR('\0') )
  2916. {
  2917. hresult = CreateItemMoniker(OLESTR("!"), pszItem,
  2918. &pmkItem);
  2919. if( hresult != NOERROR )
  2920. {
  2921. goto errRtn;
  2922. }
  2923. hresult = CreateGenericComposite(pmkFile, pmkItem,
  2924. &pmkFinal);
  2925. if( hresult != NOERROR )
  2926. {
  2927. goto errRtn;
  2928. }
  2929. }
  2930. else
  2931. {
  2932. pmkFinal = pmkFile;
  2933. // this addref is done so we can release all of our
  2934. // monikers at once (i.e., the variables pmkFinal
  2935. // and pmkFile will both be released)
  2936. pmkFinal->AddRef();
  2937. }
  2938. // pmkFinal now contains the moniker we need. Create a
  2939. // memory stream and save the moniker into it.
  2940. // if we are asking for LinkSource on an hglobal, then we
  2941. // don't want to delete the hglobal when we release the stream
  2942. if( pmedium->tymed == TYMED_HGLOBAL )
  2943. {
  2944. fDeleteOnRelease = FALSE;
  2945. }
  2946. hresult = CreateStreamOnHGlobal(NULL, fDeleteOnRelease, &pstm);
  2947. if( hresult != NOERROR )
  2948. {
  2949. goto errRtn;
  2950. }
  2951. hresult = pmkFinal->QueryInterface(IID_IPersistStream,
  2952. (LPLPVOID)&pPersistStream);
  2953. // we implemented this file moniker, it should support
  2954. // IPersistStream
  2955. Assert(hresult == NOERROR);
  2956. hresult = OleSaveToStream(pPersistStream, pstm);
  2957. if( hresult != NOERROR )
  2958. {
  2959. goto errRtn;
  2960. }
  2961. hresult = WriteClassStm(pstm, clsid);
  2962. if (hresult != NOERROR)
  2963. {
  2964. goto errRtn;
  2965. }
  2966. // no matter what, we should save the stream so we can clean
  2967. // up and release our resources if needed
  2968. if( pmedium->tymed == TYMED_ISTREAM )
  2969. {
  2970. // save the stream, in case we need to release it later
  2971. m_pUnkOle1 = (IUnknown *)pstm;
  2972. pmedium->pstm = pstm;
  2973. }
  2974. else
  2975. {
  2976. Assert(pmedium->tymed == TYMED_HGLOBAL);
  2977. hresult = GetHGlobalFromStream(pstm, &(pmedium->hGlobal));
  2978. // since we created the memory stream, the GetHGlobal
  2979. // should never fail
  2980. Assert(hresult == NOERROR);
  2981. // in this case, we want to release the stream and hang
  2982. // onto the hglobal
  2983. m_hOle1 = pmedium->hGlobal;
  2984. pstm->Release();
  2985. pstm = NULL;
  2986. }
  2987. errRtn:
  2988. if( pPersistStream )
  2989. {
  2990. pPersistStream->Release();
  2991. }
  2992. if( pmkFile )
  2993. {
  2994. pmkFile->Release();
  2995. }
  2996. if( pmkItem )
  2997. {
  2998. pmkItem->Release();
  2999. }
  3000. if( pmkFinal )
  3001. {
  3002. pmkFinal->Release();
  3003. }
  3004. if( pszClass )
  3005. {
  3006. PubMemFree(pszClass);
  3007. }
  3008. if( pszFile )
  3009. {
  3010. PubMemFree(pszFile);
  3011. }
  3012. if( pszItem )
  3013. {
  3014. PubMemFree(pszItem);
  3015. }
  3016. if( hresult != NOERROR )
  3017. {
  3018. if( pstm )
  3019. {
  3020. HRESULT hrCheck;
  3021. if (!fDeleteOnRelease)
  3022. {
  3023. // pstm->Release will not free the underlying
  3024. // HGLOBAL, so we need to do so ourselves
  3025. HGLOBAL hgFree;
  3026. hrCheck = GetHGlobalFromStream(pstm, &hgFree);
  3027. // since we created the memory stream, the GetHGlobal
  3028. // should never fail
  3029. Assert(hrCheck == NOERROR);
  3030. // GlobalFree returns NULL on success
  3031. hgFree = GlobalFree(hgFree);
  3032. Assert(NULL == hgFree);
  3033. }
  3034. pstm->Release();
  3035. m_pUnkOle1 = NULL;
  3036. }
  3037. }
  3038. LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetLinkSourceFrom"
  3039. "Ole1 ( %lx ) [ %p , %p ]\n", this, hresult));
  3040. return hresult;
  3041. }
  3042. //+-------------------------------------------------------------------------
  3043. //
  3044. // Member: CClipDataObject::GetObjectDescriptorFromOle1 (private)
  3045. //
  3046. // Synopsis: retrieves a UNICODE object descriptor from OLE1 data
  3047. //
  3048. // Effects:
  3049. //
  3050. // Arguments: [cf] -- the OLE1 clipboard format to use
  3051. // [pmedium] -- where to put the hglobal
  3052. //
  3053. // Requires: the clipboard must be open
  3054. // cf must be eith OwnerLink or ObjectLink
  3055. //
  3056. // Returns: HRESULT
  3057. //
  3058. // Signals:
  3059. //
  3060. // Modifies:
  3061. //
  3062. // Derivation:
  3063. //
  3064. // Algorithm: Calls CreateObjectDesciptor
  3065. //
  3066. // History: dd-mmm-yy Author Comment
  3067. // 04-Jun-94 alexgo author
  3068. //
  3069. // Notes:
  3070. //
  3071. //--------------------------------------------------------------------------
  3072. HRESULT CClipDataObject::GetObjectDescriptorFromOle1( UINT cf,
  3073. STGMEDIUM *pmedium )
  3074. {
  3075. HRESULT hresult;
  3076. HGLOBAL hglobal;
  3077. LPOLESTR pszClass = NULL,
  3078. pszFile = NULL,
  3079. pszItem = NULL,
  3080. pszSrcOfCopy = NULL;
  3081. CLSID clsid;
  3082. const SIZEL sizel = {0, 0};
  3083. const POINTL pointl = {0, 0};
  3084. OLECHAR szFullName[256];
  3085. LONG cb = sizeof(szFullName); // RegQueryValue takes
  3086. // bytes!!
  3087. VDATEHEAP();
  3088. LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetObjectDescriptor"
  3089. "FromOle1 ( %d , %p )\n", this, cf, pmedium));
  3090. Assert(cf == g_cfOwnerLink || cf == g_cfObjectLink);
  3091. // fetch the data we need
  3092. hresult = GetAndTranslateOle1( cf, &pszClass, &pszFile, &pszItem,
  3093. NULL);
  3094. if( hresult != NOERROR )
  3095. {
  3096. goto errRtn;
  3097. }
  3098. hresult = wCLSIDFromProgID(pszClass, &clsid, TRUE);
  3099. if( hresult != NOERROR )
  3100. {
  3101. goto errRtn;
  3102. }
  3103. // now fetch the full user name of the object. This info
  3104. // is found in the registry.
  3105. if( QueryClassesRootValue(pszClass, szFullName, &cb) != 0 )
  3106. {
  3107. // uh-oh, it failed for some reason. The class name
  3108. // (potentially OLE2Link) was probably not registered, so
  3109. // just use the class name.
  3110. //
  3111. // NB!! 16bit did no error checking for this case, so
  3112. // szFullName in their equivalent code would be left as
  3113. // a NULL string. This had the effect of making a
  3114. // blank entry in most paste-special dialogs.
  3115. _xstrcpy(szFullName, pszClass);
  3116. }
  3117. // build up the SourceOfCopy string. It will be a concatenation
  3118. // of the Filename and Item name that we retrieved from the
  3119. // Owner/ObjectLink OLE1 structures
  3120. pszSrcOfCopy = (LPOLESTR)PrivMemAlloc( (_xstrlen(pszFile) +
  3121. _xstrlen(pszItem) + 2) * sizeof(OLECHAR));
  3122. if( pszSrcOfCopy == NULL )
  3123. {
  3124. hresult = ResultFromScode(E_OUTOFMEMORY);
  3125. goto errRtn;
  3126. }
  3127. _xstrcpy(pszSrcOfCopy, pszFile);
  3128. if( pszItem && *pszItem != OLESTR('\0') )
  3129. {
  3130. _xstrcat(pszSrcOfCopy, OLESTR("\\"));
  3131. _xstrcat(pszSrcOfCopy, pszItem);
  3132. }
  3133. // create an object descriptor
  3134. hglobal = CreateObjectDescriptor(clsid, DVASPECT_CONTENT, &sizel,
  3135. &pointl,
  3136. (OLEMISC_CANTLINKINSIDE | OLEMISC_CANLINKBYOLE1),
  3137. szFullName, pszSrcOfCopy);
  3138. if( hglobal == NULL )
  3139. {
  3140. hresult = ResultFromScode(E_OUTOFMEMORY);
  3141. goto errRtn;
  3142. }
  3143. // now fill in out params
  3144. Assert(pmedium->tymed == TYMED_HGLOBAL);
  3145. pmedium->hGlobal = hglobal;
  3146. // we need to save the hglobal so we can free it later if need
  3147. // be
  3148. m_hOle1 = hglobal;
  3149. errRtn:
  3150. if( pszClass )
  3151. {
  3152. PubMemFree(pszClass);
  3153. }
  3154. if( pszFile )
  3155. {
  3156. PubMemFree(pszFile);
  3157. }
  3158. if( pszItem )
  3159. {
  3160. PubMemFree(pszItem);
  3161. }
  3162. if( pszSrcOfCopy )
  3163. {
  3164. // NB!! This was allocated with *private* memory
  3165. PrivMemFree(pszSrcOfCopy);
  3166. }
  3167. LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetObjectDescriptor"
  3168. "FromOle1 ( %lx )\n", this, hresult ));
  3169. return hresult;
  3170. }
  3171. //+-------------------------------------------------------------------------
  3172. //
  3173. // Member: CClipDataObject::GetOle2FromOle1 (private)
  3174. //
  3175. // Synopsis: synthesize the given ole2 format from available ole1 data
  3176. //
  3177. // Effects:
  3178. //
  3179. // Arguments: [cf] -- the clipboard format to synthesize
  3180. // [pmedium] -- where to put the data
  3181. //
  3182. // Requires: the clipboard must be open
  3183. // CanRetrieveOle2FromOle1 should have succeeded before calling
  3184. // this function
  3185. //
  3186. // Returns:
  3187. //
  3188. // Signals:
  3189. //
  3190. // Modifies:
  3191. //
  3192. // Derivation:
  3193. //
  3194. // Algorithm:
  3195. //
  3196. // History: dd-mmm-yy Author Comment
  3197. // 04-Jun-94 alexgo author
  3198. //
  3199. // Notes:
  3200. //
  3201. //--------------------------------------------------------------------------
  3202. HRESULT CClipDataObject::GetOle2FromOle1( UINT cf, STGMEDIUM *pmedium )
  3203. {
  3204. HRESULT hresult = ResultFromScode(DV_E_TYMED);
  3205. VDATEHEAP();
  3206. LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetOle2FromOle1 "
  3207. "( %d , %p )\n", this, cf, pmedium));
  3208. if( cf == g_cfEmbedSource )
  3209. {
  3210. // we can only fetch EmbedSource on an hglobal or storage
  3211. if( pmedium->tymed == TYMED_HGLOBAL ||
  3212. pmedium->tymed == TYMED_ISTORAGE )
  3213. {
  3214. hresult = GetEmbedSourceFromOle1(pmedium);
  3215. }
  3216. }
  3217. else if( cf == g_cfEmbeddedObject )
  3218. {
  3219. // we can only fetch EmbeddedObject on an hglobal or storage
  3220. if( pmedium->tymed == TYMED_HGLOBAL ||
  3221. pmedium->tymed == TYMED_ISTORAGE )
  3222. {
  3223. hresult = GetEmbeddedObjectFromOle1(pmedium);
  3224. }
  3225. }
  3226. else if( cf == g_cfLinkSource )
  3227. {
  3228. // we can only fetch LinkSource on an hglobal or stream
  3229. if( pmedium->tymed == TYMED_HGLOBAL ||
  3230. pmedium->tymed == TYMED_ISTREAM )
  3231. {
  3232. hresult = GetLinkSourceFromOle1(pmedium);
  3233. }
  3234. }
  3235. else if( cf == g_cfObjectDescriptor )
  3236. {
  3237. // we can only fetch this on an hglobal
  3238. if( pmedium->tymed == TYMED_HGLOBAL )
  3239. {
  3240. hresult = GetObjectDescriptorFromOle1(g_cfOwnerLink,
  3241. pmedium);
  3242. }
  3243. }
  3244. else if( cf == g_cfLinkSrcDescriptor )
  3245. {
  3246. // we can only fetch this on an hglobal. Note that
  3247. // a link source descriptor is really an object descriptor
  3248. // also, we can use either ObjectLink or OwnerLink as the
  3249. // the data source, but the only time it is valid to use
  3250. // OwnerLink is if ObjectLink is not available
  3251. if( pmedium->tymed == TYMED_HGLOBAL )
  3252. {
  3253. UINT cfOle1;
  3254. if( SSIsClipboardFormatAvailable(g_cfObjectLink) )
  3255. {
  3256. cfOle1 = g_cfObjectLink;
  3257. }
  3258. else
  3259. {
  3260. cfOle1 = g_cfOwnerLink;
  3261. }
  3262. hresult = GetObjectDescriptorFromOle1(cfOle1,
  3263. pmedium);
  3264. }
  3265. }
  3266. LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetOle2FromOle1 "
  3267. "( %lx )\n", this, hresult));
  3268. return hresult;
  3269. }
  3270. //+-------------------------------------------------------------------------
  3271. //
  3272. // Member: CClipDataObject::OleGetClipboardData (private)
  3273. //
  3274. // Synopsis: private replacement for GetClipboardData that synthesizes
  3275. // OLE2 formats from OLE1 data if necessary
  3276. //
  3277. // Effects:
  3278. //
  3279. // Arguments: [cf] -- the clipboard format to use
  3280. // [phglobal] -- where to put the fetched data
  3281. //
  3282. // Requires: the clipboard must be open
  3283. //
  3284. // Returns: HRESULT
  3285. //
  3286. // Signals:
  3287. //
  3288. // Modifies:
  3289. //
  3290. // Derivation:
  3291. //
  3292. // Algorithm: Try to fetch the request format; if that fails then
  3293. // try to synthesize the data from OLE1
  3294. //
  3295. // History: dd-mmm-yy Author Comment
  3296. // 04-Jun-94 alexgo author
  3297. //
  3298. // Notes:
  3299. //
  3300. //--------------------------------------------------------------------------
  3301. HRESULT CClipDataObject::OleGetClipboardData( UINT cf, HGLOBAL *phglobal )
  3302. {
  3303. HRESULT hresult = NOERROR;
  3304. VDATEHEAP();
  3305. LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::OleGetClipboard"
  3306. "Data ( %x , %p )\n", this, cf, phglobal ));
  3307. Assert(phglobal);
  3308. *phglobal = NULL;
  3309. // fetch the real data, if available
  3310. if( SSIsClipboardFormatAvailable(cf) )
  3311. {
  3312. *phglobal = SSGetClipboardData(cf);
  3313. }
  3314. else if( CanRetrieveOle2FromOle1(cf) )
  3315. {
  3316. STGMEDIUM medium;
  3317. medium.tymed = TYMED_HGLOBAL;
  3318. hresult = GetOle2FromOle1(cf, &medium);
  3319. if( hresult == NOERROR )
  3320. {
  3321. *phglobal = medium.hGlobal;
  3322. }
  3323. }
  3324. else
  3325. {
  3326. hresult = ResultFromScode(DV_E_FORMATETC);
  3327. }
  3328. LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::OleGetClipboardData"
  3329. " ( %lx ) [ %lx ]\n", this, hresult, *phglobal));
  3330. return hresult;
  3331. }
  3332. //+-------------------------------------------------------------------------
  3333. //
  3334. // Member: CClipDataObject::OleIsClipboardFormatAvailable (private)
  3335. //
  3336. // Synopsis: determines whether a clipboard format is available or
  3337. // can be synthesized from available formats
  3338. //
  3339. // Effects:
  3340. //
  3341. // Arguments: [cf] -- the clipboard format to check for
  3342. //
  3343. // Requires:
  3344. //
  3345. // Returns:
  3346. //
  3347. // Signals:
  3348. //
  3349. // Modifies:
  3350. //
  3351. // Derivation:
  3352. //
  3353. // Algorithm:
  3354. //
  3355. // History: dd-mmm-yy Author Comment
  3356. // 04-Jun-94 alexgo author
  3357. //
  3358. // Notes:
  3359. //
  3360. //--------------------------------------------------------------------------
  3361. BOOL CClipDataObject::OleIsClipboardFormatAvailable( UINT cf )
  3362. {
  3363. BOOL fRet;
  3364. VDATEHEAP();
  3365. LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::OleIsClipboard"
  3366. "FormatAvailable ( %d )\n", this, cf));
  3367. if( !SSIsClipboardFormatAvailable(cf) )
  3368. {
  3369. // if the clipboard format is not normally available, see
  3370. // if we can make it from available formats
  3371. fRet = CanRetrieveOle2FromOle1(cf);
  3372. }
  3373. else
  3374. {
  3375. fRet = TRUE;
  3376. }
  3377. LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::OleIsClipboard"
  3378. "FormatAvailable ( %lu )\n", this, fRet ));
  3379. return fRet;
  3380. }
  3381. //+-------------------------------------------------------------------------
  3382. //
  3383. // Member: CClipDataObject::Dump, public (_DEBUG only)
  3384. //
  3385. // Synopsis: return a string containing the contents of the data members
  3386. //
  3387. // Effects:
  3388. //
  3389. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  3390. // [ulFlag] - flag determining prefix of all newlines of the
  3391. // out character array (default is 0 - no prefix)
  3392. // [nIndentLevel] - will add a indent prefix after the other prefix
  3393. // for ALL newlines (including those with no prefix)
  3394. //
  3395. // Requires:
  3396. //
  3397. // Returns: HRESULT
  3398. //
  3399. // Signals:
  3400. //
  3401. // Modifies: [ppszDump] - argument
  3402. //
  3403. // Derivation:
  3404. //
  3405. // Algorithm: use dbgstream to create a string containing information on the
  3406. // content of data structures
  3407. //
  3408. // History: dd-mmm-yy Author Comment
  3409. // 01-Feb-95 t-ScottH author
  3410. //
  3411. // Notes:
  3412. //
  3413. //--------------------------------------------------------------------------
  3414. #ifdef _DEBUG
  3415. HRESULT CClipDataObject::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  3416. {
  3417. int i;
  3418. unsigned int ui;
  3419. char *pszPrefix;
  3420. char *pszCThreadCheck;
  3421. char *pszFORMATETC;
  3422. dbgstream dstrPrefix;
  3423. dbgstream dstrDump(500);
  3424. // determine prefix of newlines
  3425. if ( ulFlag & DEB_VERBOSE )
  3426. {
  3427. dstrPrefix << this << " _VB ";
  3428. }
  3429. // determine indentation prefix for all newlines
  3430. for (i = 0; i < nIndentLevel; i++)
  3431. {
  3432. dstrPrefix << DUMPTAB;
  3433. }
  3434. pszPrefix = dstrPrefix.str();
  3435. // put data members in stream
  3436. pszCThreadCheck = DumpCThreadCheck((CThreadCheck *)this, ulFlag, nIndentLevel + 1);
  3437. dstrDump << pszPrefix << "CThreadCheck:" << endl;
  3438. dstrDump << pszCThreadCheck;
  3439. CoTaskMemFree(pszCThreadCheck);
  3440. dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
  3441. dstrDump << pszPrefix << "Handle OLE2 -> OLE1 data = " << m_hOle1 << endl;
  3442. dstrDump << pszPrefix << "pIUnknown to OLE1 data = " << m_pUnkOle1 << endl;
  3443. dstrDump << pszPrefix << "pIDataObject = " << m_pDataObject << endl;
  3444. dstrDump << pszPrefix << "TriedToGetDataObject? = ";
  3445. if (m_fTriedToGetDataObject == TRUE)
  3446. {
  3447. dstrDump << "TRUE" << endl;
  3448. }
  3449. else
  3450. {
  3451. dstrDump << "FALSE" << endl;
  3452. }
  3453. // cleanup and provide pointer to character array
  3454. *ppszDump = dstrDump.str();
  3455. if (*ppszDump == NULL)
  3456. {
  3457. *ppszDump = UtDupStringA(szDumpErrorMessage);
  3458. }
  3459. CoTaskMemFree(pszPrefix);
  3460. return NOERROR;
  3461. }
  3462. #endif // _DEBUG
  3463. //+-------------------------------------------------------------------------
  3464. //
  3465. // Function: DumpCClipDataObject, public (_DEBUG only)
  3466. //
  3467. // Synopsis: calls the CClipDataObject::Dump method, takes care of errors and
  3468. // returns the zero terminated string
  3469. //
  3470. // Effects:
  3471. //
  3472. // Arguments: [pCDO] - pointer to CClipDataObject
  3473. // [ulFlag] - flag determining prefix of all newlines of the
  3474. // out character array (default is 0 - no prefix)
  3475. // [nIndentLevel] - will add a indent prefix after the other prefix
  3476. // for ALL newlines (including those with no prefix)
  3477. //
  3478. // Requires:
  3479. //
  3480. // Returns: character array of structure dump or error (null terminated)
  3481. //
  3482. // Signals:
  3483. //
  3484. // Modifies:
  3485. //
  3486. // Algorithm:
  3487. //
  3488. // History: dd-mmm-yy Author Comment
  3489. // 01-Feb-95 t-ScottH author
  3490. //
  3491. // Notes:
  3492. //
  3493. //--------------------------------------------------------------------------
  3494. #ifdef _DEBUG
  3495. char *DumpCClipDataObject(CClipDataObject *pCDO, ULONG ulFlag, int nIndentLevel)
  3496. {
  3497. HRESULT hresult;
  3498. char *pszDump;
  3499. if (pCDO == NULL)
  3500. {
  3501. return UtDupStringA(szDumpBadPtr);
  3502. }
  3503. hresult = pCDO->Dump(&pszDump, ulFlag, nIndentLevel);
  3504. if (hresult != NOERROR)
  3505. {
  3506. CoTaskMemFree(pszDump);
  3507. return DumpHRESULT(hresult);
  3508. }
  3509. return pszDump;
  3510. }
  3511. #endif // _DEBUG
  3512. //
  3513. // OLE1 support methods
  3514. //
  3515. //+-------------------------------------------------------------------------
  3516. //
  3517. // Function: BmToPres
  3518. //
  3519. // Synopsis: copies a bitmap into a presentation object
  3520. //
  3521. // Effects:
  3522. //
  3523. // Arguments: [hBM] -- handle to the bitmap
  3524. // [ppres] -- the presentation object
  3525. //
  3526. // Requires:
  3527. //
  3528. // Returns: HRESULT
  3529. //
  3530. // Signals:
  3531. //
  3532. // Modifies:
  3533. //
  3534. // Algorithm: converts the bitmap to a DIB and then calls DibToPres
  3535. //
  3536. // History: dd-mmm-yy Author Comment
  3537. // 11-Aug-94 alexgo port from 16bit
  3538. //
  3539. // Notes: This code is largely based from 16bit OLE sources
  3540. // REVIEW: we may want to rework portions of this code,
  3541. // particularly if we rewrite the PPRES/GENOBJ code (in
  3542. // ostm2stg.cpp).
  3543. //
  3544. //--------------------------------------------------------------------------
  3545. HRESULT BmToPres(HANDLE hBM, PPRES ppres)
  3546. {
  3547. HANDLE hDib;
  3548. HRESULT hresult;
  3549. VDATEHEAP();
  3550. LEDebugOut((DEB_ITRACE, "%p _IN BmToPres ( %lx , %p )\n", NULL,
  3551. hBM, ppres));
  3552. if( (hDib = UtConvertBitmapToDib((HBITMAP)hBM, NULL)) )
  3553. {
  3554. // this routine keeps hDib, it doesn't make a copy of it
  3555. hresult = DibToPres(hDib, ppres);
  3556. }
  3557. else
  3558. {
  3559. hresult = ResultFromScode(E_OUTOFMEMORY);
  3560. }
  3561. LEDebugOut((DEB_ITRACE, "%p OUT BmToPres ( %lx )\n", NULL, hresult));
  3562. return hresult;
  3563. }
  3564. //+-------------------------------------------------------------------------
  3565. //
  3566. // Member: CanRetrieveOle2FromOle1 (private)
  3567. //
  3568. // Synopsis: Determines whether we can synthesize the asked for
  3569. // ole2 format from the formats available on the clipboard.
  3570. // Also checks to see if the *real* OLE2 format is available.
  3571. //
  3572. // Effects: does not need to open the clipboard
  3573. //
  3574. // Arguments: [cf] -- the clipboard format to check for
  3575. //
  3576. // Requires:
  3577. //
  3578. // Returns: TRUE if we can synthesize the requested format AND the
  3579. // real format is NOT available
  3580. // FALSE otherwise
  3581. //
  3582. // Signals:
  3583. //
  3584. // Modifies:
  3585. //
  3586. // Derivation:
  3587. //
  3588. // Algorithm: for cfEmbedSource:
  3589. // cfNative and cfOwnerLink must be present and
  3590. // cfNative must precede cfOwnerLink and cfOwnerLink
  3591. // must not represent a StdOleLink
  3592. //
  3593. // for cfEmbeddedObject:
  3594. // cfOwnerLink must be present and cfNative
  3595. // must not be not present OR
  3596. //
  3597. // cfNative must come after cfOwnerLink OR
  3598. //
  3599. // cfNative precedes cfOwnerLink and
  3600. // cfOwnerLink represents a StdOleLink
  3601. //
  3602. // for cfLinkSource:
  3603. // cfObjectLink must be present OR
  3604. //
  3605. // both cfNative and cfOwnerLink must be present
  3606. // and cfOwnerLink must precede cfNative
  3607. //
  3608. // for cfObjectDescriptor or cfLinkSrcDescriptor
  3609. // either cfObjectLink or cfOwnerLink must be
  3610. // available
  3611. //
  3612. // History: dd-mmm-yy Author Comment
  3613. // 11-Aug-94 alexgo added support for EmbeddedObject
  3614. // retrieval ala 16bit OLE
  3615. // 04-Jun-94 alexgo author
  3616. //
  3617. // Notes: We don't want to synthesize OLE2 formats from OLE1
  3618. // if the real OLE2 formats are available because the OLE2
  3619. // formats probably contain more information.
  3620. //
  3621. // We sometimes need to open the clipboard to accurately
  3622. // fetch enough information to satisfy a query on
  3623. // EmbedSource, EmbeddedObject or LinkSource.
  3624. // Since the clipboard is a global resource, we
  3625. // must only open it for brief periods of time.
  3626. //
  3627. //--------------------------------------------------------------------------
  3628. BOOL CanRetrieveOle2FromOle1( UINT cf )
  3629. {
  3630. BOOL fRet = FALSE,
  3631. fOwnerLink = FALSE,
  3632. fNative = FALSE,
  3633. fOpenedClipboard = FALSE;
  3634. UINT cfFirst = 0, // the first format available
  3635. cfTemp;
  3636. HRESULT hresult;
  3637. VDATEHEAP();
  3638. LEDebugOut((DEB_ITRACE, "%p _IN CanRetrieveOle2From"
  3639. "Ole1 ( %d )\n", NULL, cf ));
  3640. if( SSIsClipboardFormatAvailable(g_cfOlePrivateData) )
  3641. {
  3642. // if we put the data on the clipboard, assume only OLE2
  3643. // data transfers
  3644. goto errRtn;
  3645. }
  3646. // first check for LinkSourceDescriptor or ObjectDescriptor, as
  3647. // we do not need to open the clipboard for these.
  3648. if( cf == g_cfObjectDescriptor )
  3649. {
  3650. // we must have either OwnerLink or ObjectLink
  3651. if( !SSIsClipboardFormatAvailable(g_cfObjectDescriptor) &&
  3652. (SSIsClipboardFormatAvailable(g_cfObjectLink) ||
  3653. SSIsClipboardFormatAvailable(g_cfOwnerLink) ) )
  3654. {
  3655. fRet = TRUE;
  3656. }
  3657. goto errRtn;
  3658. }
  3659. if( cf == g_cfLinkSrcDescriptor )
  3660. {
  3661. // we must have either OwnerLink or ObjectLink
  3662. if( !SSIsClipboardFormatAvailable(g_cfLinkSrcDescriptor) &&
  3663. (SSIsClipboardFormatAvailable(g_cfObjectLink) ||
  3664. SSIsClipboardFormatAvailable(g_cfOwnerLink) ) )
  3665. {
  3666. fRet = TRUE;
  3667. }
  3668. goto errRtn;
  3669. }
  3670. // now check for the remaining OLE2 formats EmbedSource,
  3671. // EmbeddedObject, and LinkSource.
  3672. if( (cf == g_cfEmbedSource) || (cf == g_cfEmbeddedObject) ||
  3673. (cf == g_cfLinkSource) )
  3674. {
  3675. // we need to open the clipboard so our calls to
  3676. // EnumClipboardFormats and GetClipboardData will work.
  3677. // however, the caller of this function may have already
  3678. // opened the clipboard, so we need to check for this.
  3679. //
  3680. //
  3681. // BEGIN: OPENCLIPBOARD
  3682. //
  3683. //
  3684. if( GetOpenClipboardWindow() !=
  3685. GetPrivateClipboardWindow(CLIP_QUERY) )
  3686. {
  3687. hresult = OleOpenClipboard(NULL, NULL);
  3688. if( hresult != NOERROR )
  3689. {
  3690. // if we can't open the clipboard,
  3691. // then we can't accurately determine
  3692. // if we can fetch the requested
  3693. // data. Assume that we can't
  3694. // and return.
  3695. fRet = FALSE;
  3696. goto errRtn;
  3697. }
  3698. fOpenedClipboard = TRUE;
  3699. }
  3700. // we now need to determine the ordering of the clipboard
  3701. // formats Native and OwnerLink. OLE1 specifies different
  3702. // behaviour based on the order in which these formats
  3703. // appear (see the Algorithm section for details)
  3704. fNative = SSIsClipboardFormatAvailable(g_cfNative);
  3705. fOwnerLink = SSIsClipboardFormatAvailable(g_cfOwnerLink);
  3706. if( fNative && fOwnerLink )
  3707. {
  3708. cfTemp = 0;
  3709. while( (cfTemp = SSEnumClipboardFormats(cfTemp)) != 0 )
  3710. {
  3711. if( cfTemp == g_cfNative )
  3712. {
  3713. cfFirst = g_cfNative;
  3714. break;
  3715. }
  3716. else if( cfTemp == g_cfOwnerLink )
  3717. {
  3718. cfFirst = g_cfOwnerLink;
  3719. break;
  3720. }
  3721. }
  3722. }
  3723. if( cf == g_cfEmbeddedObject )
  3724. {
  3725. // cfOwnerLink must be present and cfNative
  3726. // must not be not present OR
  3727. // cfNative must come after cfOwnerLink OR
  3728. // cfNative comes before cfOwnerLink and
  3729. // cfOwnerLink represents a StdOleLink
  3730. if( fOwnerLink && !fNative )
  3731. {
  3732. fRet = TRUE;
  3733. }
  3734. else if ( cfFirst == g_cfOwnerLink &&
  3735. fNative )
  3736. {
  3737. fRet = TRUE;
  3738. }
  3739. else if( cfFirst == g_cfNative && fOwnerLink &&
  3740. IsOwnerLinkStdOleLink() )
  3741. {
  3742. fRet = TRUE;
  3743. }
  3744. }
  3745. else if( cf == g_cfEmbedSource )
  3746. {
  3747. // cfNative and cfOwnerLink must be present
  3748. // cfNative must precede cfOwnerLink and
  3749. // OwnerLink must not represent a StdOleLink
  3750. if( cfFirst == g_cfNative && fOwnerLink &&
  3751. !IsOwnerLinkStdOleLink())
  3752. {
  3753. fRet = TRUE;
  3754. }
  3755. }
  3756. else
  3757. {
  3758. Assert(cf == g_cfLinkSource);
  3759. // cfObjectLink must be present OR
  3760. // both cfNative and cfOwnerLink must be present
  3761. // and cfOwnerLink must precede cfNative
  3762. if( SSIsClipboardFormatAvailable(g_cfObjectLink) )
  3763. {
  3764. fRet = TRUE;
  3765. }
  3766. else if( cfFirst == g_cfOwnerLink )
  3767. {
  3768. fRet = TRUE;
  3769. }
  3770. }
  3771. if( fOpenedClipboard )
  3772. {
  3773. if( !SSCloseClipboard() )
  3774. {
  3775. LEDebugOut((DEB_ERROR, "ERROR!: "
  3776. "CloseClipboard failed in "
  3777. "CanRetrieveOle2FromOle1!\n"));
  3778. // just keep going and hope for the best.
  3779. }
  3780. }
  3781. //
  3782. //
  3783. // END: CLOSECLIPBOARD
  3784. //
  3785. //
  3786. }
  3787. errRtn:
  3788. LEDebugOut((DEB_ITRACE, "%p OUT CanRetrieveOle2From"
  3789. "Ole1 ( %d )\n", NULL, fRet));
  3790. return fRet;
  3791. }
  3792. //+-------------------------------------------------------------------------
  3793. //
  3794. // Function: DibToPres
  3795. //
  3796. // Synopsis: stuffs a DIB into a presentation object
  3797. //
  3798. // Effects: takes ownership of hDib.
  3799. //
  3800. // Arguments: [hDib] -- the DIB
  3801. // [ppres] -- the presentation object
  3802. //
  3803. // Requires: hDib *must* be a copy; this function will take ownership
  3804. // of the hglobal.
  3805. //
  3806. // Returns: HRESULT
  3807. //
  3808. // Signals:
  3809. //
  3810. // Modifies:
  3811. //
  3812. // Algorithm: sets various fields in the presentation object
  3813. //
  3814. // History: dd-mmm-yy Author Comment
  3815. // 11-Aug-94 alexgo port from 16bit
  3816. //
  3817. // Notes: This code is largely based from 16bit OLE sources
  3818. // REVIEW: we may want to rework portions of this code,
  3819. // particularly if we rewrite the PPRES/GENOBJ code (in
  3820. // ostm2stg.cpp).
  3821. //
  3822. // We take ownership of hDib because this function is
  3823. // called by BmToPres, which allocates a DIB calls us.
  3824. //
  3825. //--------------------------------------------------------------------------
  3826. HRESULT DibToPres( HANDLE hDib, PPRES ppres)
  3827. {
  3828. BITMAPINFOHEADER * pbminfohdr;
  3829. HRESULT hresult = NOERROR;
  3830. VDATEHEAP();
  3831. LEDebugOut((DEB_ITRACE, "%p _IN DibToPres ( %lx , %p )\n", NULL,
  3832. hDib, ppres));
  3833. Assert (ppres);
  3834. pbminfohdr = (BITMAPINFOHEADER FAR*) GlobalLock (hDib);
  3835. if( pbminfohdr == NULL )
  3836. {
  3837. hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
  3838. goto errRtn;
  3839. }
  3840. // ftagClipFormat is defined in ostm2stg.h
  3841. ppres->m_format.m_ftag = ftagClipFormat;
  3842. ppres->m_format.m_cf = CF_DIB;
  3843. ppres->m_ulHeight = pbminfohdr->biHeight;
  3844. ppres->m_ulWidth = pbminfohdr->biWidth;
  3845. // the destructor for m_data (in ostm2stg.cpp) will GlobalUnlock
  3846. // m_pv and free m_h. Cute, ehh??
  3847. ppres->m_data.m_h = hDib;
  3848. ppres->m_data.m_pv = pbminfohdr;
  3849. ppres->m_data.m_cbSize = (ULONG) GlobalSize (hDib);
  3850. // we must free hDib
  3851. ppres->m_data.m_fNoFree = FALSE;
  3852. // Do not unlock hDib (done by ~CData in ostm2stg.cpp)
  3853. errRtn:
  3854. LEDebugOut((DEB_ITRACE, "%p OUT DibToPres ( %lx )\n", NULL, hresult));
  3855. return hresult;
  3856. }
  3857. //+-------------------------------------------------------------------------
  3858. //
  3859. // Function: IsOwnerLinkStdOleLink
  3860. //
  3861. // Synopsis: checks to see if the OwnerLink data on the clipboard
  3862. // really represents a StdOleLink.
  3863. //
  3864. // Effects:
  3865. //
  3866. // Arguments: void
  3867. //
  3868. // Requires: The clipboard *must* be open.
  3869. // cfOwnerLink must be on the clipboard.
  3870. //
  3871. // Returns: TRUE/FALSE
  3872. //
  3873. // Signals:
  3874. //
  3875. // Modifies:
  3876. //
  3877. // Algorithm: checks the class name in the OwnerLink data to see if it
  3878. // matches 'OLE2Link'.
  3879. //
  3880. // History: dd-mmm-yy Author Comment
  3881. // 11-Aug-94 alexgo author
  3882. //
  3883. // Notes: OwnerLink data is laid out as follows
  3884. // szClass\0szFile\0szItem\0\0
  3885. //
  3886. // where sz* are ANSI strings.
  3887. //
  3888. //--------------------------------------------------------------------------
  3889. BOOL IsOwnerLinkStdOleLink( void )
  3890. {
  3891. HGLOBAL hOwnerLink;
  3892. LPSTR pszClass;
  3893. BOOL fRet = FALSE;
  3894. VDATEHEAP();
  3895. LEDebugOut((DEB_ITRACE, "%p _IN IsOwnerLinkStdOleLink ( )\n", NULL));
  3896. Assert(SSIsClipboardFormatAvailable(g_cfOwnerLink));
  3897. Assert(GetOpenClipboardWindow() ==
  3898. GetPrivateClipboardWindow(CLIP_QUERY));
  3899. hOwnerLink = SSGetClipboardData(g_cfOwnerLink);
  3900. if( hOwnerLink )
  3901. {
  3902. pszClass = (LPSTR)GlobalLock(hOwnerLink);
  3903. if( pszClass )
  3904. {
  3905. // NB!! These are intentionally ANSI strings.
  3906. // OLE1 apps only understand ANSI
  3907. if( _xmemcmp(pszClass, "OLE2Link",
  3908. sizeof("OLE2Link")) == 0 )
  3909. {
  3910. fRet = TRUE;
  3911. }
  3912. GlobalUnlock(hOwnerLink);
  3913. }
  3914. }
  3915. LEDebugOut((DEB_ITRACE, "%p OUT IsOwnerLinkStdOleLink ( %lu )\n",
  3916. NULL, fRet));
  3917. return fRet;
  3918. }
  3919. //+-------------------------------------------------------------------------
  3920. //
  3921. // Function: MfToPres
  3922. //
  3923. // Synopsis: copies the given metafile into the presentation object
  3924. //
  3925. // Effects:
  3926. //
  3927. // Arguments: [hMfPict] -- the metafilepict handle
  3928. // [ppres] -- the presentation object
  3929. //
  3930. // Requires:
  3931. //
  3932. // Returns: HRESULT
  3933. //
  3934. // Signals:
  3935. //
  3936. // Modifies:
  3937. //
  3938. // Algorithm: copies the metafile and fills out relevant fields in
  3939. // the presentation object
  3940. //
  3941. // History: dd-mmm-yy Author Comment
  3942. // 11-Aug-94 alexgo port from 16bit
  3943. //
  3944. // Notes: This code is largely based from 16bit OLE sources
  3945. // REVIEW: we may want to rework portions of this code,
  3946. // particularly if we rewrite the PPRES/GENOBJ code (in
  3947. // ostm2stg.cpp).
  3948. //
  3949. //--------------------------------------------------------------------------
  3950. HRESULT MfToPres( HANDLE hMfPict, PPRES ppres )
  3951. {
  3952. HRESULT hresult;
  3953. LPMETAFILEPICT pMfPict = NULL;
  3954. HANDLE hglobal = NULL;
  3955. DWORD cbSize;
  3956. LPVOID pv = NULL;
  3957. VDATEHEAP();
  3958. LEDebugOut((DEB_ITRACE, "%p _IN MfToPres ( %lx , %p )\n", NULL,
  3959. hMfPict, ppres));
  3960. Assert (ppres);
  3961. pMfPict = (LPMETAFILEPICT) GlobalLock (hMfPict);
  3962. if( !pMfPict )
  3963. {
  3964. hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
  3965. goto errRtn;
  3966. }
  3967. ppres->m_format.m_ftag = ftagClipFormat;
  3968. ppres->m_format.m_cf = CF_METAFILEPICT;
  3969. ppres->m_ulHeight = pMfPict->yExt;
  3970. ppres->m_ulWidth = pMfPict->xExt;
  3971. // in order for the presentation object stuff to work right,
  3972. // we need to get the metafile bits in an HGLOBAL
  3973. cbSize = GetMetaFileBitsEx(pMfPict->hMF, 0, NULL);
  3974. if( cbSize == 0 )
  3975. {
  3976. hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
  3977. goto errRtn;
  3978. }
  3979. hglobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cbSize);
  3980. if( hglobal == NULL )
  3981. {
  3982. hresult = ResultFromScode(E_OUTOFMEMORY);
  3983. goto errRtn;
  3984. }
  3985. pv = GlobalLock(hglobal);
  3986. if( pv == NULL )
  3987. {
  3988. hresult = ResultFromScode(E_OUTOFMEMORY);
  3989. goto errRtn;
  3990. }
  3991. // now fetch the real bits
  3992. if( GetMetaFileBitsEx(pMfPict->hMF, cbSize, pv) == 0 )
  3993. {
  3994. hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
  3995. goto errRtn;
  3996. }
  3997. ppres->m_data.m_h = hglobal;
  3998. ppres->m_data.m_cbSize = cbSize;
  3999. ppres->m_data.m_pv = pv;
  4000. hresult = NOERROR;
  4001. errRtn:
  4002. if( pMfPict )
  4003. {
  4004. GlobalUnlock(hMfPict);
  4005. }
  4006. if( hresult != NOERROR )
  4007. {
  4008. if( pv )
  4009. {
  4010. GlobalUnlock(hglobal);
  4011. }
  4012. if( hglobal )
  4013. {
  4014. GlobalFree(hglobal);
  4015. }
  4016. }
  4017. LEDebugOut((DEB_ITRACE, "%p OUT MftoPres ( %lx )\n", NULL, hresult));
  4018. return hresult;
  4019. }
  4020. //+-------------------------------------------------------------------------
  4021. //
  4022. // Function: NativeToStorage
  4023. //
  4024. // Synopsis: takes the hglobal from cfNative and stuffs the data
  4025. // onto the given storage.
  4026. //
  4027. // Effects:
  4028. //
  4029. // Arguments: [pstg] -- the storage
  4030. // [hNative] -- the hglobal
  4031. //
  4032. // Requires: hNative must really have an IStorage in it
  4033. //
  4034. // Returns: HRESULT
  4035. //
  4036. // Signals:
  4037. //
  4038. // Modifies:
  4039. //
  4040. // Algorithm: layers a storage on top of the HGLOBAL, removes any
  4041. // presentation streams, and then copies into the given
  4042. // storage.
  4043. //
  4044. // History: dd-mmm-yy Author Comment
  4045. // 11-Aug-94 alexgo author
  4046. //
  4047. // Notes:
  4048. //
  4049. //--------------------------------------------------------------------------
  4050. HRESULT NativeToStorage( LPSTORAGE pstg, HANDLE hNative )
  4051. {
  4052. LPLOCKBYTES plockbyte = NULL;
  4053. LPSTORAGE pstgNative= NULL;
  4054. HRESULT hresult;
  4055. HGLOBAL hCopy = NULL;
  4056. VDATEHEAP();
  4057. LEDebugOut((DEB_ITRACE, "%p _IN NativeToStorage ( %p , %lx )\n",
  4058. NULL, pstg, hNative));
  4059. hCopy = UtDupGlobal(hNative, GMEM_DDESHARE | GMEM_MOVEABLE);
  4060. if( hCopy == NULL )
  4061. {
  4062. hresult = ResultFromScode(E_OUTOFMEMORY);
  4063. goto errRtn;
  4064. }
  4065. hresult = CreateILockBytesOnHGlobal( hCopy, TRUE /*fDeleteOnRelease*/,
  4066. &plockbyte);
  4067. if( hresult != NOERROR )
  4068. {
  4069. goto errRtn;
  4070. }
  4071. // This is really a 2.0 object disguised as a 1.0 object
  4072. // for the sake of its 1.0 container, so reconstitute
  4073. // the original IStorage from the native data.
  4074. hresult = StgIsStorageILockBytes(plockbyte);
  4075. if( hresult != NOERROR )
  4076. {
  4077. LEDebugOut((DEB_ERROR, "ERROR!: Native data is not based on an"
  4078. " IStorage!\n"));
  4079. goto errRtn;
  4080. }
  4081. hresult = StgOpenStorageOnILockBytes(plockbyte, NULL, STGM_DFRALL,
  4082. NULL, 0, &pstgNative);
  4083. if( hresult != NOERROR )
  4084. {
  4085. LEDebugOut((DEB_ERROR, "ERROR!: OpenStorage on Native data"
  4086. "failed!!\n"));
  4087. goto errRtn;
  4088. }
  4089. // now remove the any presentation streams from the native IStorage.
  4090. // we do this because the OLE1 container will just hang on to the
  4091. // hglobal although it may change (i.e. resize) the presenation.
  4092. // Any cached presentation streams may therefore be invalid.
  4093. // the caller of this function should reconstruct new presentation
  4094. // streams from data available on the clipboard.
  4095. hresult = UtDoStreamOperation(pstgNative,/* pstgSrc */
  4096. NULL, /* pstgDst */
  4097. OPCODE_REMOVE, /* operation to performed */
  4098. STREAMTYPE_CACHE); /* streams to be operated upon */
  4099. if( hresult != NOERROR )
  4100. {
  4101. LEDebugOut((DEB_ERROR, "ERROR!: Cache stream removal "
  4102. "failed for Native data-based IStorage!\n"));
  4103. goto errRtn;
  4104. }
  4105. hresult = pstgNative->CopyTo(0, NULL, NULL, pstg);
  4106. if( hresult != NOERROR )
  4107. {
  4108. goto errRtn;
  4109. }
  4110. errRtn:
  4111. if( pstgNative )
  4112. {
  4113. pstgNative->Release();
  4114. }
  4115. if( plockbyte )
  4116. {
  4117. plockbyte->Release();
  4118. }
  4119. LEDebugOut((DEB_ITRACE, "%p OUT NativeToStorage ( %lx )\n", NULL,
  4120. hresult));
  4121. return hresult;
  4122. }
  4123. //
  4124. // Enumerator implementation for enumerating a FromatEtcDataArray
  4125. //
  4126. //+-------------------------------------------------------------------------
  4127. //
  4128. // Member: CEnumFormatEtcDataArray::QueryInterface
  4129. //
  4130. // Synopsis: returns requested interfaces
  4131. //
  4132. // Effects:
  4133. //
  4134. // Arguments: [riid] -- the requested interface
  4135. // [ppvObj] -- where to put the interface pointer
  4136. //
  4137. // Requires:
  4138. //
  4139. // Returns: HRESULT
  4140. //
  4141. // Signals:
  4142. //
  4143. // Modifies:
  4144. //
  4145. // Derivation: IEnumFORMATETC
  4146. //
  4147. // Algorithm:
  4148. //
  4149. // History: dd-mmm-yy Author Comment
  4150. // 10-Apr-94 alexgo author
  4151. //
  4152. // Notes:
  4153. //
  4154. //--------------------------------------------------------------------------
  4155. STDMETHODIMP CEnumFormatEtcDataArray::QueryInterface( REFIID riid, LPVOID *ppvObj )
  4156. {
  4157. HRESULT hresult = NOERROR;
  4158. VDATEHEAP();
  4159. VDATETHREAD(this);
  4160. LEDebugOut((DEB_TRACE, "%p _IN CEnumFormatEtcDataArray::QueryInterface "
  4161. "( %p , %p )\n", this, riid, ppvObj));
  4162. if( IsEqualIID(riid, IID_IUnknown) ||
  4163. IsEqualIID(riid, IID_IEnumFORMATETC) )
  4164. {
  4165. *ppvObj = this;
  4166. AddRef();
  4167. }
  4168. else
  4169. {
  4170. *ppvObj = NULL;
  4171. hresult = ResultFromScode(E_NOINTERFACE);
  4172. }
  4173. LEDebugOut((DEB_TRACE, "%p OUT CEnumFormatEtcDataArray::QueryInterface "
  4174. "( %lx ) [ %p ]\n", this, *ppvObj ));
  4175. return hresult;
  4176. }
  4177. //+-------------------------------------------------------------------------
  4178. //
  4179. // Member: CEnumFormatEtcDataArray::AddRef
  4180. //
  4181. // Synopsis: increments the reference count
  4182. //
  4183. // Effects:
  4184. //
  4185. // Arguments: void
  4186. //
  4187. // Requires:
  4188. //
  4189. // Returns: ULONG-- the new reference count
  4190. //
  4191. // Signals:
  4192. //
  4193. // Modifies:
  4194. //
  4195. // Derivation: IEnumFORMATETC
  4196. //
  4197. // Algorithm:
  4198. //
  4199. // History: dd-mmm-yy Author Comment
  4200. // 10-Apr-94 alexgo author
  4201. //
  4202. // Notes:
  4203. //
  4204. //--------------------------------------------------------------------------
  4205. STDMETHODIMP_(ULONG) CEnumFormatEtcDataArray::AddRef( )
  4206. {
  4207. VDATEHEAP();
  4208. LEDebugOut((DEB_TRACE, "%p _IN CEnumFormatEtcDataArray::AddRef ( )\n",
  4209. this));
  4210. ++m_refs;
  4211. LEDebugOut((DEB_TRACE, "%p OUT CEnumFormatEtcDataArray::AddRef ( %lu )\n",
  4212. this, m_refs));
  4213. return m_refs;
  4214. }
  4215. //+-------------------------------------------------------------------------
  4216. //
  4217. // Member: CEnumFormatEtcDataArray::Release
  4218. //
  4219. // Synopsis: decrements the reference count on the object
  4220. //
  4221. // Effects:
  4222. //
  4223. // Arguments: void
  4224. //
  4225. // Requires:
  4226. //
  4227. // Returns: ULONG -- the new reference count
  4228. //
  4229. // Signals:
  4230. //
  4231. // Modifies:
  4232. //
  4233. // Derivation: IEnumFORMATETC
  4234. //
  4235. // Algorithm:
  4236. //
  4237. // History: dd-mmm-yy Author Comment
  4238. // 10-Apr-94 alexgo author
  4239. //
  4240. // Notes:
  4241. //
  4242. //--------------------------------------------------------------------------
  4243. STDMETHODIMP_(ULONG) CEnumFormatEtcDataArray::Release( )
  4244. {
  4245. ULONG cRefs;
  4246. VDATEHEAP();
  4247. LEDebugOut((DEB_TRACE, "%p _IN CEnumFormatEtcDataArray::Release ( )\n",
  4248. this));
  4249. if( (cRefs = --m_refs ) == 0 )
  4250. {
  4251. LEDebugOut((DEB_TRACE, "%p DELETED CEnumFormatEtcDataArray\n",
  4252. this));
  4253. delete this;
  4254. }
  4255. // using "this" below is OK, since we only want its value
  4256. LEDebugOut((DEB_TRACE, "%p OUT CEnumFormatEtcDataArray::Release ( %lu )\n",
  4257. this, cRefs));
  4258. return cRefs;
  4259. }
  4260. //+-------------------------------------------------------------------------
  4261. //
  4262. // Member: CEnumFormatEtcDataArray::Next
  4263. //
  4264. // Synopsis: gets the next [celt] formats
  4265. //
  4266. // Effects:
  4267. //
  4268. // Arguments: [celt] -- the number of elements to fetch
  4269. // [rgelt] -- where to put them
  4270. // [pceltFetched] -- the number of formats actually fetched
  4271. //
  4272. // Requires:
  4273. //
  4274. // Returns: NOERROR
  4275. //
  4276. // Signals:
  4277. //
  4278. // Modifies:
  4279. //
  4280. // Derivation: IEnumFORMATETC
  4281. //
  4282. // Algorithm:
  4283. //
  4284. // History: dd-mmm-yy Author Comment
  4285. // 10-Apr-94 alexgo author
  4286. //
  4287. // Notes:
  4288. //
  4289. //--------------------------------------------------------------------------
  4290. STDMETHODIMP CEnumFormatEtcDataArray::Next( ULONG celt,
  4291. FORMATETC *rgelt,
  4292. ULONG *pceltFetched)
  4293. {
  4294. if (celt == 0)
  4295. {
  4296. LEDebugOut((DEB_ERROR,
  4297. "CDragEnum::Next requested entries returned is invalid\n"));
  4298. return E_INVALIDARG;
  4299. }
  4300. if (!IsValidPtrOut(rgelt, sizeof(FORMATETC) * celt))
  4301. {
  4302. LEDebugOut((DEB_ERROR,
  4303. "CDragEnum::Next array to return entries invalid\n"));
  4304. return E_INVALIDARG;
  4305. }
  4306. if (pceltFetched)
  4307. {
  4308. if (!IsValidPtrOut(pceltFetched, sizeof(*pceltFetched)))
  4309. {
  4310. LEDebugOut((DEB_ERROR,
  4311. "CDragEnum::Next count to return invalid\n"));
  4312. return E_INVALIDARG;
  4313. }
  4314. }
  4315. else if (celt != 1)
  4316. {
  4317. LEDebugOut((DEB_ERROR,
  4318. "CDragEnum::count requested != 1 & count fetched is NULL\n"));
  4319. return E_INVALIDARG;
  4320. }
  4321. // handle the case where we have no data
  4322. if( m_pFormatEtcDataArray == NULL )
  4323. {
  4324. if( pceltFetched )
  4325. {
  4326. *pceltFetched = 0;
  4327. }
  4328. return S_FALSE;
  4329. }
  4330. // Calculate the maximum number that we can return
  4331. ULONG cToReturn = (m_cOffset < m_pFormatEtcDataArray->_cFormats)
  4332. ? m_pFormatEtcDataArray->_cFormats - m_cOffset
  4333. : 0;
  4334. // Are we going to return any?
  4335. if (cToReturn != 0)
  4336. {
  4337. // If the number requested is less that the maximum number
  4338. // we can return, the we will return all requested/
  4339. if (celt < cToReturn)
  4340. {
  4341. cToReturn = celt;
  4342. }
  4343. // Allocate and copy the DVTARGETDEVICE - a side effect of this
  4344. // loop is that our offset pointer gets updated to its value at
  4345. // the completion of the routine.
  4346. for (DWORD i = 0; i < cToReturn; i++, m_cOffset++)
  4347. {
  4348. memcpy(&rgelt[i], &(m_pFormatEtcDataArray->_FormatEtcData[m_cOffset]._FormatEtc),
  4349. sizeof(FORMATETC));
  4350. if (m_pFormatEtcDataArray->_FormatEtcData[m_cOffset]._FormatEtc.ptd != NULL)
  4351. {
  4352. // Create a pointer to the device target - Remember when
  4353. // we created the shared memory block we overroad the ptd
  4354. // field of the FORMATETC so that it is now the offset
  4355. // from the beginning of the shared memory. We reverse
  4356. // that here so we can copy the data for the consumer.
  4357. DVTARGETDEVICE *pdvtarget = (DVTARGETDEVICE *)
  4358. ((BYTE *) m_pFormatEtcDataArray
  4359. + (ULONG_PTR) m_pFormatEtcDataArray->_FormatEtcData[m_cOffset]._FormatEtc.ptd);
  4360. // Allocate a new DVTARGETDEVICE
  4361. DVTARGETDEVICE *pdvtargetNew = (DVTARGETDEVICE *)
  4362. CoTaskMemAlloc(pdvtarget->tdSize);
  4363. // Did the memory allocation succeed?
  4364. if (pdvtargetNew == NULL)
  4365. {
  4366. // NO! - so clean up. First we free any device targets
  4367. // that we might have allocated.
  4368. for (DWORD j = 0; j < i; j++)
  4369. {
  4370. if (rgelt[j].ptd != NULL)
  4371. {
  4372. CoTaskMemFree(rgelt[j].ptd);
  4373. }
  4374. }
  4375. // Then we restore the offset to its initial state
  4376. m_cOffset -= i;
  4377. return E_OUTOFMEMORY;
  4378. }
  4379. // Copy the old targetDevice to the new one
  4380. memcpy(pdvtargetNew, pdvtarget, pdvtarget->tdSize);
  4381. // Update output FORMATETC pointer
  4382. rgelt[i].ptd = pdvtargetNew;
  4383. }
  4384. }
  4385. }
  4386. if (pceltFetched)
  4387. {
  4388. *pceltFetched = cToReturn;
  4389. }
  4390. return (cToReturn == celt) ? NOERROR : S_FALSE;
  4391. }
  4392. //+-------------------------------------------------------------------------
  4393. //
  4394. // Member: CEnumFormatEtcDataArray::Skip
  4395. //
  4396. // Synopsis: skips the next [celt] formats
  4397. //
  4398. // Effects:
  4399. //
  4400. // Arguments: [celt] -- the number of elements to skip
  4401. //
  4402. // Requires:
  4403. //
  4404. // Returns: NOERROR
  4405. //
  4406. // Signals:
  4407. //
  4408. // Modifies:
  4409. //
  4410. // Derivation: IEnumFORMATETC
  4411. //
  4412. // Algorithm:
  4413. //
  4414. // History: dd-mmm-yy Author Comment
  4415. // 10-Apr-94 alexgo author
  4416. //
  4417. // Notes:
  4418. //
  4419. //--------------------------------------------------------------------------
  4420. STDMETHODIMP CEnumFormatEtcDataArray::Skip( ULONG celt )
  4421. {
  4422. HRESULT hresult = NOERROR;
  4423. VDATEHEAP();
  4424. VDATETHREAD(this);
  4425. LEDebugOut((DEB_TRACE, "%p _IN CEnumFormatEtcDataArray::Skip ( %lu )\n",
  4426. this, celt));
  4427. m_cOffset += celt;
  4428. if( m_cOffset > m_pFormatEtcDataArray->_cFormats )
  4429. {
  4430. // whoops, skipped to far ahead. Set us to the max limit.
  4431. m_cOffset = m_pFormatEtcDataArray->_cFormats ;
  4432. hresult = ResultFromScode(S_FALSE);
  4433. }
  4434. LEDebugOut((DEB_TRACE, "%p OUT CEnumFormatEtcDataArray::Skip ( %lx )\n",
  4435. this, hresult ));
  4436. return hresult;
  4437. }
  4438. //+-------------------------------------------------------------------------
  4439. //
  4440. // Member: CEnumFormatEtcDataArray::Reset
  4441. //
  4442. // Synopsis: resets the seek pointer to zero
  4443. //
  4444. // Effects:
  4445. //
  4446. // Arguments: void
  4447. //
  4448. // Requires:
  4449. //
  4450. // Returns: NOERROR
  4451. //
  4452. // Signals:
  4453. //
  4454. // Modifies:
  4455. //
  4456. // Derivation: IEnumFORMATETC
  4457. //
  4458. // Algorithm:
  4459. //
  4460. // History: dd-mmm-yy Author Comment
  4461. // 10-Apr-94 alexgo author
  4462. //
  4463. // Notes:
  4464. //
  4465. //--------------------------------------------------------------------------
  4466. STDMETHODIMP CEnumFormatEtcDataArray::Reset( void )
  4467. {
  4468. VDATEHEAP();
  4469. VDATETHREAD(this);
  4470. LEDebugOut((DEB_TRACE, "%p _IN CEnumFormatEtcDataArray::Reset ( )\n",
  4471. this));
  4472. m_cOffset = 0;
  4473. LEDebugOut((DEB_TRACE, "%p OUT CEnumFormatEtcDataArray::Reset ( %lx )\n",
  4474. this, NOERROR ));
  4475. return NOERROR;
  4476. }
  4477. //+-------------------------------------------------------------------------
  4478. //
  4479. // Member: CEnumFormatEtcDataArray::Clone
  4480. //
  4481. // Synopsis: clones the enumerator
  4482. //
  4483. // Effects:
  4484. //
  4485. // Arguments: [ppIEnum] -- where to put the cloned enumerator
  4486. //
  4487. // Requires:
  4488. //
  4489. // Returns: HRESULT
  4490. //
  4491. // Signals:
  4492. //
  4493. // Modifies:
  4494. //
  4495. // Derivation: IEnumFORMATETC
  4496. //
  4497. // Algorithm:
  4498. //
  4499. // History: dd-mmm-yy Author Comment
  4500. // 10-Apr-94 alexgo author
  4501. //
  4502. // Notes:
  4503. //
  4504. //--------------------------------------------------------------------------
  4505. STDMETHODIMP CEnumFormatEtcDataArray::Clone( IEnumFORMATETC **ppIEnum )
  4506. {
  4507. HRESULT hresult;
  4508. CEnumFormatEtcDataArray * pClipEnum;
  4509. VDATEHEAP();
  4510. VDATETHREAD(this);
  4511. VDATEPTROUT(ppIEnum, IEnumFORMATETC *);
  4512. LEDebugOut((DEB_TRACE, "%p _IN CEnumFormatEtcDataArray::Clone ( %p )\n",
  4513. this, ppIEnum));
  4514. *ppIEnum = new CEnumFormatEtcDataArray(m_pFormatEtcDataArray,m_cOffset);
  4515. hresult = *ppIEnum ? NOERROR : E_OUTOFMEMORY;
  4516. LEDebugOut((DEB_TRACE, "%p OUT CEnumFormatEtcDataArray::Clone ( %p )\n",
  4517. this, *ppIEnum));
  4518. return hresult;
  4519. }
  4520. //+-------------------------------------------------------------------------
  4521. //
  4522. // Member: CEnumFormatEtcDataArray::CEnumFormatEtcDataArray, private
  4523. //
  4524. // Synopsis: constructor
  4525. //
  4526. // Effects:
  4527. //
  4528. // Arguments: void
  4529. //
  4530. // Requires:
  4531. //
  4532. // Returns:
  4533. //
  4534. // Signals:
  4535. //
  4536. // Modifies:
  4537. //
  4538. // Derivation:
  4539. //
  4540. // Algorithm:
  4541. //
  4542. // History: dd-mmm-yy Author Comment
  4543. // 10-Apr-94 alexgo author
  4544. //
  4545. // Notes:
  4546. //
  4547. //--------------------------------------------------------------------------
  4548. CEnumFormatEtcDataArray::CEnumFormatEtcDataArray(FORMATETCDATAARRAY *pFormatEtcDataArray,DWORD cOffset)
  4549. {
  4550. Assert(pFormatEtcDataArray);
  4551. m_refs = 1; // give the intial reference
  4552. m_pFormatEtcDataArray = pFormatEtcDataArray;
  4553. m_cOffset = cOffset;
  4554. ++(m_pFormatEtcDataArray->_cRefs); // hold onto Shared formats.
  4555. }
  4556. //+-------------------------------------------------------------------------
  4557. //
  4558. // Member: CEnumFormatEtcDataArray::~CEnumFormatEtcDataArray, private
  4559. //
  4560. // Synopsis: destructor
  4561. //
  4562. // Effects:
  4563. //
  4564. // Arguments: void
  4565. //
  4566. // Requires:
  4567. //
  4568. // Returns:
  4569. //
  4570. // Signals:
  4571. //
  4572. // Modifies:
  4573. //
  4574. // Derivation:
  4575. //
  4576. // Algorithm:
  4577. //
  4578. // History: dd-mmm-yy Author Comment
  4579. // 10-Apr-94 alexgo author
  4580. //
  4581. // Notes:
  4582. //
  4583. //--------------------------------------------------------------------------
  4584. CEnumFormatEtcDataArray::~CEnumFormatEtcDataArray( void )
  4585. {
  4586. Assert(NULL != m_pFormatEtcDataArray);
  4587. if( m_pFormatEtcDataArray )
  4588. {
  4589. if (0 == --m_pFormatEtcDataArray->_cRefs)
  4590. {
  4591. PrivMemFree(m_pFormatEtcDataArray);
  4592. m_pFormatEtcDataArray = NULL;
  4593. }
  4594. }
  4595. }