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

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