Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3401 lines
102 KiB

  1. /*************************************************************************
  2. **
  3. ** OLE 2 Sample Code
  4. **
  5. ** clipbrd.c
  6. **
  7. ** This file contains the major interfaces, methods and related support
  8. ** functions for implementing clipboard data transfer. The code
  9. ** contained in this file is used by BOTH the Container and Server
  10. ** (Object) versions of the Outline sample code.
  11. ** (see file dragdrop.c for Drag/Drop support implementation)
  12. **
  13. ** OleDoc Object
  14. ** exposed interfaces:
  15. ** IDataObject
  16. **
  17. ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
  18. **
  19. *************************************************************************/
  20. #include "outline.h"
  21. OLEDBGDATA
  22. extern LPOUTLINEAPP g_lpApp;
  23. // REVIEW: should use string resource for messages
  24. char ErrMsgPasting[] = "Could not paste data from clipboard!";
  25. char ErrMsgBadFmt[] = "Invalid format selected!";
  26. char ErrMsgPasteFailed[] = "Could not paste data from clipboard!";
  27. char ErrMsgClipboardChanged[] = "Contents of clipboard have changed!\r\nNo paste performed.";
  28. /*************************************************************************
  29. ** OleDoc::IDataObject interface implementation
  30. *************************************************************************/
  31. // IDataObject::QueryInterface
  32. STDMETHODIMP OleDoc_DataObj_QueryInterface (
  33. LPDATAOBJECT lpThis,
  34. REFIID riid,
  35. LPVOID FAR* lplpvObj
  36. )
  37. {
  38. LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc;
  39. return OleDoc_QueryInterface((LPOLEDOC)lpOleDoc, riid, lplpvObj);
  40. }
  41. // IDataObject::AddRef
  42. STDMETHODIMP_(ULONG) OleDoc_DataObj_AddRef(LPDATAOBJECT lpThis)
  43. {
  44. LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc;
  45. OleDbgAddRefMethod(lpThis, "IDataObject");
  46. return OleDoc_AddRef((LPOLEDOC)lpOleDoc);
  47. }
  48. // IDataObject::Release
  49. STDMETHODIMP_(ULONG) OleDoc_DataObj_Release (LPDATAOBJECT lpThis)
  50. {
  51. LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc;
  52. OleDbgReleaseMethod(lpThis, "IDataObject");
  53. return OleDoc_Release((LPOLEDOC)lpOleDoc);
  54. }
  55. // IDataObject::GetData
  56. STDMETHODIMP OleDoc_DataObj_GetData (
  57. LPDATAOBJECT lpThis,
  58. LPFORMATETC lpFormatetc,
  59. LPSTGMEDIUM lpMedium
  60. )
  61. {
  62. LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc;
  63. HRESULT hrErr;
  64. OLEDBG_BEGIN2("OleDoc_DataObj_GetData\r\n")
  65. #if defined( OLE_SERVER )
  66. // Call OLE Server specific version of this function
  67. hrErr = ServerDoc_GetData((LPSERVERDOC)lpOleDoc, lpFormatetc, lpMedium);
  68. #endif
  69. #if defined( OLE_CNTR )
  70. // Call OLE Container specific version of this function
  71. hrErr = ContainerDoc_GetData(
  72. (LPCONTAINERDOC)lpOleDoc,
  73. lpFormatetc,
  74. lpMedium
  75. );
  76. #endif
  77. OLEDBG_END2
  78. return hrErr;
  79. }
  80. // IDataObject::GetDataHere
  81. STDMETHODIMP OleDoc_DataObj_GetDataHere (
  82. LPDATAOBJECT lpThis,
  83. LPFORMATETC lpFormatetc,
  84. LPSTGMEDIUM lpMedium
  85. )
  86. {
  87. LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc;
  88. HRESULT hrErr;
  89. OLEDBG_BEGIN2("OleDoc_DataObj_GetDataHere\r\n")
  90. #if defined( OLE_SERVER )
  91. // Call OLE Server specific version of this function
  92. hrErr = ServerDoc_GetDataHere(
  93. (LPSERVERDOC)lpOleDoc,
  94. lpFormatetc,
  95. lpMedium
  96. );
  97. #endif
  98. #if defined( OLE_CNTR )
  99. // Call OLE Container specific version of this function
  100. hrErr = ContainerDoc_GetDataHere(
  101. (LPCONTAINERDOC)lpOleDoc,
  102. lpFormatetc,
  103. lpMedium
  104. );
  105. #endif
  106. OLEDBG_END2
  107. return hrErr;
  108. }
  109. // IDataObject::QueryGetData
  110. STDMETHODIMP OleDoc_DataObj_QueryGetData (
  111. LPDATAOBJECT lpThis,
  112. LPFORMATETC lpFormatetc
  113. )
  114. {
  115. LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc;
  116. HRESULT hrErr;
  117. OLEDBG_BEGIN2("OleDoc_DataObj_QueryGetData\r\n");
  118. #if defined( OLE_SERVER )
  119. // Call OLE Server specific version of this function
  120. hrErr = ServerDoc_QueryGetData((LPSERVERDOC)lpOleDoc, lpFormatetc);
  121. #endif
  122. #if defined( OLE_CNTR )
  123. // Call OLE Container specific version of this function
  124. hrErr = ContainerDoc_QueryGetData((LPCONTAINERDOC)lpOleDoc, lpFormatetc);
  125. #endif
  126. OLEDBG_END2
  127. return hrErr;
  128. }
  129. // IDataObject::GetCanonicalFormatEtc
  130. STDMETHODIMP OleDoc_DataObj_GetCanonicalFormatEtc(
  131. LPDATAOBJECT lpThis,
  132. LPFORMATETC lpformatetc,
  133. LPFORMATETC lpformatetcOut
  134. )
  135. {
  136. HRESULT hrErr;
  137. OleDbgOut2("OleDoc_DataObj_GetCanonicalFormatEtc\r\n");
  138. if (!lpformatetcOut)
  139. return ResultFromScode(E_INVALIDARG);
  140. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  141. lpformatetcOut->ptd = NULL;
  142. if (!lpformatetc)
  143. return ResultFromScode(E_INVALIDARG);
  144. // OLE2NOTE: we must validate that the format requested is supported
  145. if ((hrErr=lpThis->lpVtbl->QueryGetData(lpThis,lpformatetc)) != NOERROR)
  146. return hrErr;
  147. /* OLE2NOTE: an app that is insensitive to target device (as the
  148. ** Outline Sample is) should fill in the lpformatOut parameter
  149. ** but NULL out the "ptd" field; it should return NOERROR if the
  150. ** input formatetc->ptd what non-NULL. this tells the caller
  151. ** that it is NOT necessary to maintain a separate screen
  152. ** rendering and printer rendering. if should return
  153. ** DATA_S_SAMEFORMATETC if the input and output formatetc's are
  154. ** identical.
  155. */
  156. *lpformatetcOut = *lpformatetc;
  157. if (lpformatetc->ptd == NULL)
  158. return ResultFromScode(DATA_S_SAMEFORMATETC);
  159. else {
  160. lpformatetcOut->ptd = NULL;
  161. return NOERROR;
  162. }
  163. }
  164. // IDataObject::SetData
  165. STDMETHODIMP OleDoc_DataObj_SetData (
  166. LPDATAOBJECT lpThis,
  167. LPFORMATETC lpFormatetc,
  168. LPSTGMEDIUM lpMedium,
  169. BOOL fRelease
  170. )
  171. {
  172. LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc;
  173. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  174. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  175. SCODE sc = S_OK;
  176. OLEDBG_BEGIN2("OleDoc_DataObj_SetData\r\n")
  177. /* OLE2NOTE: a document that is used to transfer data (either via
  178. ** the clipboard or drag/drop) does NOT accept SetData on ANY
  179. ** format!
  180. */
  181. if (lpOutlineDoc->m_fDataTransferDoc) {
  182. sc = E_FAIL;
  183. goto error;
  184. }
  185. #if defined( OLE_SERVER )
  186. if (lpFormatetc->cfFormat == lpOutlineApp->m_cfOutline) {
  187. OLEDBG_BEGIN2("ServerDoc_SetData: CF_OUTLINE\r\n")
  188. OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
  189. OutlineDoc_ClearAllLines(lpOutlineDoc);
  190. OutlineDoc_PasteOutlineData(lpOutlineDoc,lpMedium->hGlobal,-1);
  191. OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
  192. OLEDBG_END3
  193. } else if (lpFormatetc->cfFormat == CF_TEXT) {
  194. OLEDBG_BEGIN2("ServerDoc_SetData: CF_TEXT\r\n")
  195. OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
  196. OutlineDoc_ClearAllLines(lpOutlineDoc);
  197. OutlineDoc_PasteTextData(lpOutlineDoc,lpMedium->hGlobal,-1);
  198. OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
  199. OLEDBG_END3
  200. } else {
  201. sc = DV_E_FORMATETC;
  202. }
  203. #endif // OLE_SERVER
  204. #if defined( OLE_CNTR )
  205. /* the Container-Only version of Outline does NOT offer
  206. ** IDataObject interface from its User documents. this is
  207. ** required by objects which can be embedded or linked. the
  208. ** Container-only app only allows linking to its contained
  209. ** objects, NOT the data of the container itself.
  210. */
  211. OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n");
  212. sc = E_NOTIMPL;
  213. #endif // OLE_CNTR
  214. error:
  215. /* OLE2NOTE: if fRelease==TRUE, then we must take
  216. ** responsibility to release the lpMedium. we should only do
  217. ** this if we are going to return NOERROR. if we do NOT
  218. ** accept the data, then we should NOT release the lpMedium.
  219. ** if fRelease==FALSE, then the caller retains ownership of
  220. ** the data.
  221. */
  222. if (sc == S_OK && fRelease)
  223. ReleaseStgMedium(lpMedium);
  224. OLEDBG_END2
  225. return ResultFromScode(sc);
  226. }
  227. // IDataObject::EnumFormatEtc
  228. STDMETHODIMP OleDoc_DataObj_EnumFormatEtc(
  229. LPDATAOBJECT lpThis,
  230. DWORD dwDirection,
  231. LPENUMFORMATETC FAR* lplpenumFormatEtc
  232. )
  233. {
  234. LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc;
  235. HRESULT hrErr;
  236. OLEDBG_BEGIN2("OleDoc_DataObj_EnumFormatEtc\r\n")
  237. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  238. *lplpenumFormatEtc = NULL;
  239. #if defined( OLE_SERVER )
  240. /* OLE2NOTE: a user document only needs to enumerate the static list
  241. ** of formats that are registered for our app in the
  242. ** registration database. OLE provides a default enumerator
  243. ** which enumerates from the registration database. this default
  244. ** enumerator is requested by returning OLE_S_USEREG. it is NOT
  245. ** required that a user document (ie. non-DataTransferDoc)
  246. ** enumerate the OLE formats: CF_LINKSOURCE, CF_EMBEDSOURCE, or
  247. ** CF_EMBEDDEDOBJECT.
  248. **
  249. ** An object implemented as a server EXE (as this sample
  250. ** is) may simply return OLE_S_USEREG to instruct the OLE
  251. ** DefHandler to call the OleReg* helper API which uses info in
  252. ** the registration database. Alternatively, the OleRegEnumFormatEtc
  253. ** API may be called directly. Objects implemented as a server
  254. ** DLL may NOT return OLE_S_USEREG; they must call the OleReg*
  255. ** API or provide their own implementation. For EXE based
  256. ** objects it is more efficient to return OLE_S_USEREG, because
  257. ** in then the enumerator is instantiated in the callers
  258. ** process space and no LRPC remoting is required.
  259. */
  260. if (! ((LPOUTLINEDOC)lpOleDoc)->m_fDataTransferDoc)
  261. return ResultFromScode(OLE_S_USEREG);
  262. // Call OLE Server specific version of this function
  263. hrErr = ServerDoc_EnumFormatEtc(
  264. (LPSERVERDOC)lpOleDoc,
  265. dwDirection,
  266. lplpenumFormatEtc
  267. );
  268. #endif
  269. #if defined( OLE_CNTR )
  270. // Call OLE Container specific version of this function
  271. hrErr = ContainerDoc_EnumFormatEtc(
  272. (LPCONTAINERDOC)lpOleDoc,
  273. dwDirection,
  274. lplpenumFormatEtc
  275. );
  276. #endif
  277. OLEDBG_END2
  278. return hrErr;
  279. }
  280. // IDataObject::DAdvise
  281. STDMETHODIMP OleDoc_DataObj_DAdvise(
  282. LPDATAOBJECT lpThis,
  283. FORMATETC FAR* lpFormatetc,
  284. DWORD advf,
  285. LPADVISESINK lpAdvSink,
  286. DWORD FAR* lpdwConnection
  287. )
  288. {
  289. LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc;
  290. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  291. SCODE sc;
  292. OLEDBG_BEGIN2("OleDoc_DataObj_DAdvise\r\n")
  293. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  294. *lpdwConnection = 0;
  295. /* OLE2NOTE: a document that is used to transfer data (either via
  296. ** the clipboard or drag/drop) does NOT support Advise notifications.
  297. */
  298. if (lpOutlineDoc->m_fDataTransferDoc) {
  299. sc = OLE_E_ADVISENOTSUPPORTED;
  300. goto error;
  301. }
  302. #if defined( OLE_SERVER )
  303. {
  304. HRESULT hrErr;
  305. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  306. /* OLE2NOTE: we should validate if the caller is setting up an
  307. ** Advise for a data type that we support. we must
  308. ** explicitly allow an advise for the "wildcard" advise.
  309. */
  310. if ( !( lpFormatetc->cfFormat == 0 &&
  311. lpFormatetc->ptd == NULL &&
  312. lpFormatetc->dwAspect == -1L &&
  313. lpFormatetc->lindex == -1L &&
  314. lpFormatetc->tymed == -1L) &&
  315. (hrErr = OleDoc_DataObj_QueryGetData(lpThis, lpFormatetc))
  316. != NOERROR) {
  317. sc = GetScode(hrErr);
  318. goto error;
  319. }
  320. if (lpServerDoc->m_OleDoc.m_fObjIsClosing)
  321. {
  322. // We don't accept any more Advise's once we're closing
  323. sc = OLE_E_ADVISENOTSUPPORTED;
  324. goto error;
  325. }
  326. if (lpServerDoc->m_lpDataAdviseHldr == NULL &&
  327. CreateDataAdviseHolder(&lpServerDoc->m_lpDataAdviseHldr)
  328. != NOERROR) {
  329. sc = E_OUTOFMEMORY;
  330. goto error;
  331. }
  332. OLEDBG_BEGIN2("IDataAdviseHolder::Advise called\r\n");
  333. hrErr = lpServerDoc->m_lpDataAdviseHldr->lpVtbl->Advise(
  334. lpServerDoc->m_lpDataAdviseHldr,
  335. (LPDATAOBJECT)&lpOleDoc->m_DataObject,
  336. lpFormatetc,
  337. advf,
  338. lpAdvSink,
  339. lpdwConnection
  340. );
  341. OLEDBG_END2
  342. OLEDBG_END2
  343. return hrErr;
  344. }
  345. #endif // OLE_SVR
  346. #if defined( OLE_CNTR )
  347. {
  348. /* the Container-Only version of Outline does NOT offer
  349. ** IDataObject interface from its User documents. this is
  350. ** required by objects which can be embedded or linked. the
  351. ** Container-only app only allows linking to its contained
  352. ** objects, NOT the data of the container itself.
  353. */
  354. OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n");
  355. sc = E_NOTIMPL;
  356. goto error;
  357. }
  358. #endif // OLE_CNTR
  359. error:
  360. OLEDBG_END2
  361. return ResultFromScode(sc);
  362. }
  363. // IDataObject::DUnadvise
  364. STDMETHODIMP OleDoc_DataObj_DUnadvise(LPDATAOBJECT lpThis, DWORD dwConnection)
  365. {
  366. LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc;
  367. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  368. SCODE sc;
  369. OLEDBG_BEGIN2("OleDoc_DataObj_DUnadvise\r\n")
  370. /* OLE2NOTE: a document that is used to transfer data (either via
  371. ** the clipboard or drag/drop) does NOT support Advise notifications.
  372. */
  373. if (lpOutlineDoc->m_fDataTransferDoc) {
  374. sc = OLE_E_ADVISENOTSUPPORTED;
  375. goto error;
  376. }
  377. #if defined( OLE_SERVER )
  378. {
  379. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  380. HRESULT hrErr;
  381. if (lpServerDoc->m_lpDataAdviseHldr == NULL) {
  382. sc = E_FAIL;
  383. goto error;
  384. }
  385. OLEDBG_BEGIN2("IDataAdviseHolder::Unadvise called\r\n");
  386. hrErr = lpServerDoc->m_lpDataAdviseHldr->lpVtbl->Unadvise(
  387. lpServerDoc->m_lpDataAdviseHldr,
  388. dwConnection
  389. );
  390. OLEDBG_END2
  391. OLEDBG_END2
  392. return hrErr;
  393. }
  394. #endif
  395. #if defined( OLE_CNTR )
  396. {
  397. /* the Container-Only version of Outline does NOT offer
  398. ** IDataObject interface from its User documents. this is
  399. ** required by objects which can be embedded or linked. the
  400. ** Container-only app only allows linking to its contained
  401. ** objects, NOT the data of the container itself.
  402. */
  403. OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n");
  404. sc = E_NOTIMPL;
  405. goto error;
  406. }
  407. #endif
  408. error:
  409. OLEDBG_END2
  410. return ResultFromScode(sc);
  411. }
  412. // IDataObject::EnumDAdvise
  413. STDMETHODIMP OleDoc_DataObj_EnumDAdvise(
  414. LPDATAOBJECT lpThis,
  415. LPENUMSTATDATA FAR* lplpenumAdvise
  416. )
  417. {
  418. LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc;
  419. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  420. SCODE sc;
  421. OLEDBG_BEGIN2("OleDoc_DataObj_EnumDAdvise\r\n")
  422. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  423. *lplpenumAdvise = NULL;
  424. /* OLE2NOTE: a document that is used to transfer data (either via
  425. ** the clipboard or drag/drop) does NOT support Advise notifications.
  426. */
  427. if (lpOutlineDoc->m_fDataTransferDoc) {
  428. sc = OLE_E_ADVISENOTSUPPORTED;
  429. goto error;
  430. }
  431. #if defined( OLE_SERVER )
  432. {
  433. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  434. HRESULT hrErr;
  435. if (lpServerDoc->m_lpDataAdviseHldr == NULL) {
  436. sc = E_FAIL;
  437. goto error;
  438. }
  439. OLEDBG_BEGIN2("IDataAdviseHolder::EnumAdvise called\r\n");
  440. hrErr = lpServerDoc->m_lpDataAdviseHldr->lpVtbl->EnumAdvise(
  441. lpServerDoc->m_lpDataAdviseHldr,
  442. lplpenumAdvise
  443. );
  444. OLEDBG_END2
  445. OLEDBG_END2
  446. return hrErr;
  447. }
  448. #endif
  449. #if defined( OLE_CNTR )
  450. {
  451. /* the Container-Only version of Outline does NOT offer
  452. ** IDataObject interface from its User documents. this is
  453. ** required by objects which can be embedded or linked. the
  454. ** Container-only app only allows linking to its contained
  455. ** objects, NOT the data of the container itself.
  456. */
  457. OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n");
  458. sc = E_NOTIMPL;
  459. goto error;
  460. }
  461. #endif
  462. error:
  463. OLEDBG_END2
  464. return ResultFromScode(sc);
  465. }
  466. /*************************************************************************
  467. ** OleDoc Supprt Functions common to both Container and Server versions
  468. *************************************************************************/
  469. /* OleDoc_CopyCommand
  470. * ------------------
  471. * Copy selection to clipboard.
  472. * Post to the clipboard the formats that the app can render.
  473. * the actual data is not rendered at this time. using the
  474. * delayed rendering technique, Windows will send the clipboard
  475. * owner window either a WM_RENDERALLFORMATS or a WM_RENDERFORMAT
  476. * message when the actual data is requested.
  477. *
  478. * OLE2NOTE: the normal delayed rendering technique where Windows
  479. * sends the clipboard owner window either a WM_RENDERALLFORMATS or
  480. * a WM_RENDERFORMAT message when the actual data is requested is
  481. * NOT exposed to the app calling OleSetClipboard. OLE internally
  482. * creates its own window as the clipboard owner and thus our app
  483. * will NOT get these WM_RENDER messages.
  484. */
  485. void OleDoc_CopyCommand(LPOLEDOC lpSrcOleDoc)
  486. {
  487. LPOUTLINEDOC lpSrcOutlineDoc = (LPOUTLINEDOC)lpSrcOleDoc;
  488. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  489. LPOUTLINEDOC lpClipboardDoc;
  490. /* squirrel away a copy of the current selection to the ClipboardDoc */
  491. lpClipboardDoc = OutlineDoc_CreateDataTransferDoc(lpSrcOutlineDoc);
  492. if (! lpClipboardDoc)
  493. return; // Error: could not create DataTransferDoc
  494. lpOutlineApp->m_lpClipboardDoc = (LPOUTLINEDOC)lpClipboardDoc;
  495. /* OLE2NOTE: initially the Doc object is created with a 0 ref
  496. ** count. in order to have a stable Doc object during the
  497. ** process of initializing the Doc instance and transfering it
  498. ** to the clipboard, we intially AddRef the Doc ref cnt and later
  499. ** Release it. This initial AddRef is artificial; it is simply
  500. ** done to guarantee that a harmless QueryInterface followed by
  501. ** a Release does not inadvertantly force our object to destroy
  502. ** itself prematurely.
  503. */
  504. OleDoc_AddRef((LPOLEDOC)lpClipboardDoc);
  505. /* OLE2NOTE: the OLE 2.0 style to put data onto the clipboard is to
  506. ** give the clipboard a pointer to an IDataObject interface that
  507. ** is able to statisfy IDataObject::GetData calls to render
  508. ** data. in our case we give the pointer to the ClipboardDoc
  509. ** which holds a cloned copy of the current user's selection.
  510. */
  511. OLEDBG_BEGIN2("OleSetClipboard called\r\n")
  512. OleSetClipboard((LPDATAOBJECT)&((LPOLEDOC)lpClipboardDoc)->m_DataObject);
  513. OLEDBG_END2
  514. OleDoc_Release((LPOLEDOC)lpClipboardDoc); // rel artificial AddRef above
  515. }
  516. /* OleDoc_PasteCommand
  517. ** -------------------
  518. ** Paste default format data from the clipboard.
  519. ** In this function we choose the highest fidelity format that the
  520. ** source clipboard IDataObject* offers that we understand.
  521. **
  522. ** OLE2NOTE: clipboard handling in an OLE 2.0 application is
  523. ** different than normal Windows clipboard handling. Data from the
  524. ** clipboard is retieved by getting the IDataObject* pointer
  525. ** returned by calling OleGetClipboard.
  526. */
  527. void OleDoc_PasteCommand(LPOLEDOC lpOleDoc)
  528. {
  529. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  530. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  531. LPDATAOBJECT lpClipboardDataObj = NULL;
  532. BOOL fLink = FALSE;
  533. BOOL fLocalDataObj = FALSE;
  534. BOOL fStatus;
  535. HRESULT hrErr;
  536. hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj);
  537. if (hrErr != NOERROR)
  538. return; // Clipboard seems to be empty or can't be accessed
  539. OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
  540. /* check if the data on the clipboard is local to our application
  541. ** instance.
  542. */
  543. if (lpOutlineApp->m_lpClipboardDoc) {
  544. LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc;
  545. if (lpClipboardDataObj == (LPDATAOBJECT)&lpOleDoc->m_DataObject)
  546. fLocalDataObj = TRUE;
  547. }
  548. fStatus = OleDoc_PasteFromData(
  549. lpOleDoc,
  550. lpClipboardDataObj,
  551. fLocalDataObj,
  552. fLink
  553. );
  554. OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
  555. if (! fStatus)
  556. OutlineApp_ErrorMessage(g_lpApp,"Could not paste data from clipboard!");
  557. if (lpClipboardDataObj)
  558. OleStdRelease((LPUNKNOWN)lpClipboardDataObj);
  559. }
  560. /* OleDoc_PasteSpecialCommand
  561. ** --------------------------
  562. ** Allow the user to paste data in a particular format from the
  563. ** clipboard. The paste special command displays a dialog to the
  564. ** user that allows him to choose the format to be pasted from the
  565. ** list of formats available.
  566. **
  567. ** OLE2NOTE: the PasteSpecial dialog is one of the standard OLE 2.0
  568. ** UI dialogs for which the dialog is implemented and in the OLE2UI
  569. ** library.
  570. **
  571. ** OLE2NOTE: clipboard handling in an OLE 2.0 application is
  572. ** different than normal Windows clipboard handling. Data from the
  573. ** clipboard is retieved by getting the IDataObject* pointer
  574. ** returned by calling OleGetClipboard.
  575. */
  576. void OleDoc_PasteSpecialCommand(LPOLEDOC lpOleDoc)
  577. {
  578. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  579. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  580. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  581. LPDATAOBJECT lpClipboardDataObj = NULL;
  582. CLIPFORMAT cfFormat;
  583. int nFmtEtc;
  584. UINT uInt;
  585. BOOL fLink = FALSE;
  586. BOOL fLocalDataObj = FALSE;
  587. BOOL fStatus;
  588. HRESULT hrErr;
  589. OLEUIPASTESPECIAL ouiPasteSpl;
  590. BOOL fDisplayAsIcon;
  591. hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj);
  592. if (hrErr != NOERROR)
  593. return; // Clipboard seems to be empty or can't be accessed
  594. /* check if the data on the clipboard is local to our application
  595. ** instance.
  596. */
  597. if (lpOutlineApp->m_lpClipboardDoc) {
  598. LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc;
  599. if (lpClipboardDataObj == (LPDATAOBJECT)&lpOleDoc->m_DataObject)
  600. fLocalDataObj = TRUE;
  601. }
  602. /* Display the PasteSpecial dialog and allow the user to select the
  603. ** format to paste.
  604. */
  605. _fmemset((LPOLEUIPASTESPECIAL)&ouiPasteSpl, 0, sizeof(ouiPasteSpl));
  606. ouiPasteSpl.cbStruct = sizeof(ouiPasteSpl); //Structure Size
  607. ouiPasteSpl.dwFlags = PSF_SELECTPASTE | PSF_SHOWHELP; //IN-OUT: Flags
  608. ouiPasteSpl.hWndOwner = lpOutlineApp->m_lpDoc->m_hWndDoc; //Owning window
  609. ouiPasteSpl.lpszCaption = "Paste Special"; //Dialog caption bar contents
  610. ouiPasteSpl.lpfnHook = NULL; //Hook callback
  611. ouiPasteSpl.lCustData = 0; //Custom data to pass to hook
  612. ouiPasteSpl.hInstance = NULL; //Instance for customized template name
  613. ouiPasteSpl.lpszTemplate = NULL; //Customized template name
  614. ouiPasteSpl.hResource = NULL; //Customized template handle
  615. ouiPasteSpl.arrPasteEntries = lpOleApp->m_arrPasteEntries;
  616. ouiPasteSpl.cPasteEntries = lpOleApp->m_nPasteEntries;
  617. ouiPasteSpl.lpSrcDataObj = lpClipboardDataObj;
  618. ouiPasteSpl.arrLinkTypes = lpOleApp->m_arrLinkTypes;
  619. ouiPasteSpl.cLinkTypes = lpOleApp->m_nLinkTypes;
  620. ouiPasteSpl.cClsidExclude = 0;
  621. OLEDBG_BEGIN3("OleUIPasteSpecial called\r\n")
  622. uInt = OleUIPasteSpecial(&ouiPasteSpl);
  623. OLEDBG_END3
  624. fDisplayAsIcon =
  625. (ouiPasteSpl.dwFlags & PSF_CHECKDISPLAYASICON ? TRUE : FALSE);
  626. if (uInt == OLEUI_OK) {
  627. nFmtEtc = ouiPasteSpl.nSelectedIndex;
  628. fLink = ouiPasteSpl.fLink;
  629. if (nFmtEtc < 0 || nFmtEtc >= lpOleApp->m_nPasteEntries) {
  630. OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgBadFmt);
  631. goto error;
  632. }
  633. OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
  634. cfFormat = lpOleApp->m_arrPasteEntries[nFmtEtc].fmtetc.cfFormat;
  635. fStatus = OleDoc_PasteFormatFromData(
  636. lpOleDoc,
  637. cfFormat,
  638. lpClipboardDataObj,
  639. fLocalDataObj,
  640. fLink,
  641. fDisplayAsIcon,
  642. ouiPasteSpl.hMetaPict,
  643. (LPSIZEL)&ouiPasteSpl.sizel
  644. );
  645. OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
  646. if (! fStatus) {
  647. OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgPasteFailed);
  648. goto error;
  649. }
  650. } else if (uInt == OLEUI_PSERR_CLIPBOARDCHANGED) {
  651. /* OLE2NOTE: this error code is returned when the contents of
  652. ** the clipboard change while the PasteSpecial dialog is up.
  653. ** in this situation the PasteSpecial dialog automatically
  654. ** brings itself down and NO paste operation should be performed.
  655. */
  656. OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgClipboardChanged);
  657. }
  658. error:
  659. if (lpClipboardDataObj)
  660. OleStdRelease((LPUNKNOWN)lpClipboardDataObj);
  661. if (uInt == OLEUI_OK && ouiPasteSpl.hMetaPict)
  662. // clean up metafile
  663. OleUIMetafilePictIconFree(ouiPasteSpl.hMetaPict);
  664. }
  665. /* OleDoc_CreateDataTransferDoc
  666. * ----------------------------
  667. *
  668. * Create a document to be use to transfer data (either via a
  669. * drag/drop operation of the clipboard). Copy the selection of the
  670. * source doc to the data transfer document. A data transfer document is
  671. * the same as a document that is created by the user except that it is
  672. * NOT made visible to the user. it is specially used to hold a copy of
  673. * data that the user should not be able to change.
  674. *
  675. * OLE2NOTE: in the OLE version the data transfer document is used
  676. * specifically to provide an IDataObject* that renders the data copied.
  677. */
  678. LPOUTLINEDOC OleDoc_CreateDataTransferDoc(LPOLEDOC lpSrcOleDoc)
  679. {
  680. LPOUTLINEDOC lpSrcOutlineDoc = (LPOUTLINEDOC)lpSrcOleDoc;
  681. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  682. LPOUTLINEDOC lpDestOutlineDoc;
  683. LPLINELIST lpSrcLL = &lpSrcOutlineDoc->m_LineList;
  684. LINERANGE lrSel;
  685. int nCopied;
  686. lpDestOutlineDoc = OutlineApp_CreateDoc(lpOutlineApp, TRUE);
  687. if (! lpDestOutlineDoc) return NULL;
  688. // set the ClipboardDoc to an (Untitled) doc.
  689. if (! OutlineDoc_InitNewFile(lpDestOutlineDoc))
  690. goto error;
  691. LineList_GetSel(lpSrcLL, (LPLINERANGE)&lrSel);
  692. nCopied = LineList_CopySelToDoc(
  693. lpSrcLL,
  694. (LPLINERANGE)&lrSel,
  695. lpDestOutlineDoc
  696. );
  697. if (nCopied != (lrSel.m_nEndLine - lrSel.m_nStartLine + 1)) {
  698. OleDbgAssertSz(FALSE,"OleDoc_CreateDataTransferDoc: entire selection NOT copied\r\n");
  699. goto error; // ERROR: all lines could NOT be copied
  700. }
  701. #if defined( OLE_SERVER )
  702. {
  703. LPOLEDOC lpSrcOleDoc = (LPOLEDOC)lpSrcOutlineDoc;
  704. LPOLEDOC lpDestOleDoc = (LPOLEDOC)lpDestOutlineDoc;
  705. LPSERVERDOC lpDestServerDoc = (LPSERVERDOC)lpDestOutlineDoc;
  706. LPMONIKER lpmkDoc = NULL;
  707. LPMONIKER lpmkItem = NULL;
  708. /* If source document is able to provide a moniker, then the
  709. ** destination document (lpDestOutlineDoc) should offer
  710. ** CF_LINKSOURCE via its IDataObject interface that it gives
  711. ** to the clipboard or the drag/drop operation.
  712. **
  713. ** OLE2NOTE: we want to ask the source document if it can
  714. ** produce a moniker, but we do NOT want to FORCE moniker
  715. ** assignment at this point. we only want to FORCE moniker
  716. ** assignment later if a Paste Link occurs (ie. GetData for
  717. ** CF_LINKSOURCE). if the source document is able to give
  718. ** a moniker, then we store a pointer to the source document
  719. ** so we can ask it at a later time to get the moniker. we
  720. ** also save the range of the current selection so we can
  721. ** generate a proper item name later when Paste Link occurs.
  722. ** Also we need to give a string which identifies the source
  723. ** of the copy in the CF_OBJECTDESCRIPTOR format. this
  724. ** string is used to display in the PasteSpecial dialog. we
  725. ** get and store a TEMPFORUSER moniker which identifies the
  726. ** source of copy.
  727. */
  728. lpDestOleDoc->m_lpSrcDocOfCopy = lpSrcOleDoc;
  729. lpmkDoc = OleDoc_GetFullMoniker(lpSrcOleDoc, GETMONIKER_TEMPFORUSER);
  730. if (lpmkDoc != NULL) {
  731. lpDestOleDoc->m_fLinkSourceAvail = TRUE;
  732. lpDestServerDoc->m_lrSrcSelOfCopy = lrSel;
  733. OleStdRelease((LPUNKNOWN)lpmkDoc);
  734. }
  735. }
  736. #endif
  737. #if defined( OLE_CNTR )
  738. {
  739. LPOLEDOC lpSrcOleDoc = (LPOLEDOC)lpSrcOutlineDoc;
  740. LPOLEDOC lpDestOleDoc = (LPOLEDOC)lpDestOutlineDoc;
  741. LPCONTAINERDOC lpDestContainerDoc = (LPCONTAINERDOC)lpDestOutlineDoc;
  742. /* If one line was copied from the source document, and it was a
  743. ** single OLE object, then the destination document should
  744. ** offer additional data formats to allow the transfer of
  745. ** the OLE object via IDataObject::GetData. Specifically, the
  746. ** following additional data formats are offered if a single
  747. ** OLE object is copied:
  748. ** CF_EMBEDDEDOBJECT
  749. ** CF_OBJECTDESCRIPTOR (should be given even w/o object)
  750. ** CF_METAFILEPICT (note: dwAspect depends on object)
  751. ** CF_LINKSOURCE -- if linking is possible
  752. ** CF_LINKSOURCEDESCRIPTOR -- if linking is possible
  753. **
  754. ** optionally the container may give
  755. ** <data format available in OLE object's cache>
  756. */
  757. if (nCopied == 1) {
  758. LPOLEOBJECT lpSrcOleObj;
  759. LPCONTAINERLINE lpSrcContainerLine;
  760. DWORD dwStatus;
  761. lpSrcContainerLine = (LPCONTAINERLINE)LineList_GetLine(
  762. lpSrcLL,
  763. lrSel.m_nStartLine
  764. );
  765. if (! lpSrcContainerLine)
  766. goto error;
  767. lpDestOleDoc->m_lpSrcDocOfCopy = lpSrcOleDoc;
  768. if ((((LPLINE)lpSrcContainerLine)->m_lineType==CONTAINERLINETYPE)
  769. && ((lpSrcOleObj=lpSrcContainerLine->m_lpOleObj)!=NULL)) {
  770. lpDestContainerDoc->m_fEmbeddedObjectAvail = TRUE;
  771. lpSrcOleObj->lpVtbl->GetUserClassID(
  772. lpSrcOleObj,
  773. &lpDestContainerDoc->m_clsidOleObjCopied
  774. );
  775. lpDestContainerDoc->m_dwAspectOleObjCopied =
  776. lpSrcContainerLine->m_dwDrawAspect;
  777. /* OLE2NOTE: if the object is allowed to be linked
  778. ** to from the inside (ie. we are allowed to
  779. ** give out a moniker which binds to the running
  780. ** OLE object), then we want to offer
  781. ** CF_LINKSOURCE format. if the object is an OLE
  782. ** 2.0 embedded object then it is allowed to be
  783. ** linked to from the inside. if the object is
  784. ** either an OleLink or an OLE 1.0 embedding
  785. ** then it can not be linked to from the inside.
  786. ** if we were a container/server app then we
  787. ** could offer linking to the outside of the
  788. ** object (ie. a pseudo object within our
  789. ** document). we are a container only app that
  790. ** does not support linking to ranges of its data.
  791. */
  792. lpSrcOleObj->lpVtbl->GetMiscStatus(
  793. lpSrcOleObj,
  794. DVASPECT_CONTENT, /* aspect is not important */
  795. (LPDWORD)&dwStatus
  796. );
  797. if (! (dwStatus & OLEMISC_CANTLINKINSIDE)) {
  798. /* Our container supports linking to an embedded
  799. ** object. We want the lpDestContainerDoc to
  800. ** offer CF_LINKSOURCE via the IDataObject
  801. ** interface that it gives to the clipboard or
  802. ** the drag/drop operation. The link source will
  803. ** be identified by a composite moniker
  804. ** comprised of the FileMoniker of the source
  805. ** document and an ItemMoniker which identifies
  806. ** the OLE object inside the container. we do
  807. ** NOT want to force moniker assignment to the
  808. ** OLE object now (at copy time); we only want
  809. ** to FORCE moniker assignment later if a Paste
  810. ** Link occurs (ie. GetData for CF_LINKSOURCE).
  811. ** thus we store a pointer to the source document
  812. ** and the source ContainerLine so we can
  813. ** generate a proper ItemMoniker later when
  814. ** Paste Link occurs.
  815. */
  816. lpDestOleDoc->m_fLinkSourceAvail = TRUE;
  817. lpDestContainerDoc->m_lpSrcContainerLine =
  818. lpSrcContainerLine;
  819. }
  820. }
  821. }
  822. }
  823. #endif // OLE_CNTR
  824. return lpDestOutlineDoc;
  825. error:
  826. if (lpDestOutlineDoc)
  827. OutlineDoc_Destroy(lpDestOutlineDoc);
  828. return NULL;
  829. }
  830. /* OleDoc_PasteFromData
  831. ** --------------------
  832. **
  833. ** Paste data from an IDataObject*. The IDataObject* may come from
  834. ** the clipboard (GetClipboard) or from a drag/drop operation.
  835. ** In this function we choose the best format that we prefer.
  836. **
  837. ** Returns TRUE if data was successfully pasted.
  838. ** FALSE if data could not be pasted.
  839. */
  840. BOOL OleDoc_PasteFromData(
  841. LPOLEDOC lpOleDoc,
  842. LPDATAOBJECT lpSrcDataObj,
  843. BOOL fLocalDataObj,
  844. BOOL fLink
  845. )
  846. {
  847. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  848. CLIPFORMAT cfFormat;
  849. BOOL fDisplayAsIcon = FALSE;
  850. SIZEL sizelInSrc = {0, 0};
  851. HGLOBAL hMem = NULL;
  852. HGLOBAL hMetaPict = NULL;
  853. STGMEDIUM medium;
  854. if (fLink) {
  855. #if defined( OLE_SERVER )
  856. return FALSE; // server version of app does NOT support links
  857. #endif
  858. #if defined( OLE_CNTR )
  859. // container version of app only supports OLE object type links
  860. cfFormat = lpOleApp->m_cfLinkSource;
  861. #endif
  862. } else {
  863. int nFmtEtc;
  864. nFmtEtc = OleStdGetPriorityClipboardFormat(
  865. lpSrcDataObj,
  866. lpOleApp->m_arrPasteEntries,
  867. lpOleApp->m_nPasteEntries
  868. );
  869. if (nFmtEtc < 0)
  870. return FALSE; // there is no format we like
  871. cfFormat = lpOleApp->m_arrPasteEntries[nFmtEtc].fmtetc.cfFormat;
  872. }
  873. /* OLE2NOTE: we need to check what dwDrawAspect is being
  874. ** transfered. if the data is an object that is displayed as an
  875. ** icon in the source, then we want to keep it as an icon. the
  876. ** aspect the object is displayed in at the source is transfered
  877. ** via the CF_OBJECTDESCRIPTOR format for a Paste operation.
  878. */
  879. if (hMem = OleStdGetData(
  880. lpSrcDataObj,
  881. lpOleApp->m_cfObjectDescriptor,
  882. NULL,
  883. DVASPECT_CONTENT,
  884. (LPSTGMEDIUM)&medium)) {
  885. LPOBJECTDESCRIPTOR lpOD = GlobalLock(hMem);
  886. fDisplayAsIcon = (lpOD->dwDrawAspect == DVASPECT_ICON ? TRUE : FALSE);
  887. sizelInSrc = lpOD->sizel; // size of object/picture in source (opt.)
  888. GlobalUnlock(hMem);
  889. ReleaseStgMedium((LPSTGMEDIUM)&medium); // equiv to GlobalFree
  890. if (fDisplayAsIcon) {
  891. hMetaPict = OleStdGetData(
  892. lpSrcDataObj,
  893. CF_METAFILEPICT,
  894. NULL,
  895. DVASPECT_ICON,
  896. (LPSTGMEDIUM)&medium
  897. );
  898. if (hMetaPict == NULL)
  899. fDisplayAsIcon = FALSE; // give up; failed to get icon MFP
  900. }
  901. }
  902. return OleDoc_PasteFormatFromData(
  903. lpOleDoc,
  904. cfFormat,
  905. lpSrcDataObj,
  906. fLocalDataObj,
  907. fLink,
  908. fDisplayAsIcon,
  909. hMetaPict,
  910. (LPSIZEL)&sizelInSrc
  911. );
  912. if (hMetaPict)
  913. ReleaseStgMedium((LPSTGMEDIUM)&medium); // properly free METAFILEPICT
  914. }
  915. /* OleDoc_PasteFormatFromData
  916. ** --------------------------
  917. **
  918. ** Paste a particular data format from a IDataObject*. The
  919. ** IDataObject* may come from the clipboard (GetClipboard) or from a
  920. ** drag/drop operation.
  921. **
  922. ** Returns TRUE if data was successfully pasted.
  923. ** FALSE if data could not be pasted.
  924. */
  925. BOOL OleDoc_PasteFormatFromData(
  926. LPOLEDOC lpOleDoc,
  927. CLIPFORMAT cfFormat,
  928. LPDATAOBJECT lpSrcDataObj,
  929. BOOL fLocalDataObj,
  930. BOOL fLink,
  931. BOOL fDisplayAsIcon,
  932. HGLOBAL hMetaPict,
  933. LPSIZEL lpSizelInSrc
  934. )
  935. {
  936. #if defined( OLE_SERVER )
  937. /* call server specific version of the function. */
  938. return ServerDoc_PasteFormatFromData(
  939. (LPSERVERDOC)lpOleDoc,
  940. cfFormat,
  941. lpSrcDataObj,
  942. fLocalDataObj,
  943. fLink
  944. );
  945. #endif
  946. #if defined( OLE_CNTR )
  947. /* call container specific version of the function. */
  948. return ContainerDoc_PasteFormatFromData(
  949. (LPCONTAINERDOC)lpOleDoc,
  950. cfFormat,
  951. lpSrcDataObj,
  952. fLocalDataObj,
  953. fLink,
  954. fDisplayAsIcon,
  955. hMetaPict,
  956. lpSizelInSrc
  957. );
  958. #endif
  959. }
  960. /* OleDoc_QueryPasteFromData
  961. ** -------------------------
  962. **
  963. ** Check if the IDataObject* offers data in a format that we can
  964. ** paste. The IDataObject* may come from the clipboard
  965. ** (GetClipboard) or from a drag/drop operation.
  966. **
  967. ** Returns TRUE if paste can be performed
  968. ** FALSE if paste is not possible.
  969. */
  970. BOOL OleDoc_QueryPasteFromData(
  971. LPOLEDOC lpOleDoc,
  972. LPDATAOBJECT lpSrcDataObj,
  973. BOOL fLink
  974. )
  975. {
  976. #if defined( OLE_SERVER )
  977. return ServerDoc_QueryPasteFromData(
  978. (LPSERVERDOC) lpOleDoc,
  979. lpSrcDataObj,
  980. fLink
  981. );
  982. #endif
  983. #if defined( OLE_CNTR )
  984. return ContainerDoc_QueryPasteFromData(
  985. (LPCONTAINERDOC) lpOleDoc,
  986. lpSrcDataObj,
  987. fLink
  988. );
  989. #endif
  990. }
  991. /* OleDoc_GetExtent
  992. * ----------------
  993. *
  994. * Get the extent (width, height) of the entire document in Himetric.
  995. */
  996. void OleDoc_GetExtent(LPOLEDOC lpOleDoc, LPSIZEL lpsizel)
  997. {
  998. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  999. LineList_CalcSelExtentInHimetric(lpLL, NULL, lpsizel);
  1000. }
  1001. /* OleDoc_GetObjectDescriptorData
  1002. * ------------------------------
  1003. *
  1004. * Return a handle to an object's data in CF_OBJECTDESCRIPTOR form
  1005. *
  1006. */
  1007. HGLOBAL OleDoc_GetObjectDescriptorData(LPOLEDOC lpOleDoc, LPLINERANGE lplrSel)
  1008. {
  1009. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  1010. /* Only our data transfer doc renders CF_OBJECTDESCRIPTOR */
  1011. OleDbgAssert(lpOutlineDoc->m_fDataTransferDoc);
  1012. #if defined( OLE_SERVER )
  1013. {
  1014. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  1015. SIZEL sizel;
  1016. POINTL pointl;
  1017. LPSTR lpszSrcOfCopy = NULL;
  1018. IBindCtx FAR *pbc = NULL;
  1019. HGLOBAL hObjDesc;
  1020. DWORD dwStatus = 0;
  1021. LPOUTLINEDOC lpSrcDocOfCopy=(LPOUTLINEDOC)lpOleDoc->m_lpSrcDocOfCopy;
  1022. LPMONIKER lpSrcMonikerOfCopy = ServerDoc_GetSelFullMoniker(
  1023. (LPSERVERDOC)lpOleDoc->m_lpSrcDocOfCopy,
  1024. &lpServerDoc->m_lrSrcSelOfCopy,
  1025. GETMONIKER_TEMPFORUSER
  1026. );
  1027. SvrDoc_OleObj_GetMiscStatus(
  1028. (LPOLEOBJECT)&lpServerDoc->m_OleObject,
  1029. DVASPECT_CONTENT,
  1030. &dwStatus
  1031. );
  1032. OleDoc_GetExtent(lpOleDoc, &sizel);
  1033. pointl.x = pointl.y = 0;
  1034. if (lpSrcMonikerOfCopy) {
  1035. CreateBindCtx(0, (LPBC FAR*)&pbc);
  1036. CallIMonikerGetDisplayNameA(
  1037. lpSrcMonikerOfCopy, pbc, NULL, &lpszSrcOfCopy);
  1038. pbc->lpVtbl->Release(pbc);
  1039. lpSrcMonikerOfCopy->lpVtbl->Release(lpSrcMonikerOfCopy);
  1040. } else {
  1041. /* this document has no moniker; use our FullUserTypeName
  1042. ** as the description of the source of copy.
  1043. */
  1044. lpszSrcOfCopy = FULLUSERTYPENAME;
  1045. }
  1046. hObjDesc = OleStdGetObjectDescriptorData(
  1047. CLSID_APP,
  1048. DVASPECT_CONTENT,
  1049. sizel,
  1050. pointl,
  1051. dwStatus,
  1052. FULLUSERTYPENAME,
  1053. lpszSrcOfCopy
  1054. );
  1055. if (lpSrcMonikerOfCopy && lpszSrcOfCopy)
  1056. OleStdFreeString(lpszSrcOfCopy, NULL);
  1057. return hObjDesc;
  1058. }
  1059. #endif
  1060. #if defined( OLE_CNTR )
  1061. {
  1062. LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
  1063. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  1064. LPCONTAINERLINE lpContainerLine;
  1065. HGLOBAL hObjDesc;
  1066. BOOL fSelIsOleObject = FALSE;
  1067. LPOLEOBJECT lpOleObj;
  1068. SIZEL sizel;
  1069. POINTL pointl;
  1070. if ( lpLL->m_nNumLines == 1 ) {
  1071. fSelIsOleObject = ContainerDoc_IsSelAnOleObject(
  1072. lpContainerDoc,
  1073. &IID_IOleObject,
  1074. (LPUNKNOWN FAR*)&lpOleObj,
  1075. NULL, /* we don't need the line index */
  1076. (LPCONTAINERLINE FAR*)&lpContainerLine
  1077. );
  1078. }
  1079. pointl.x = pointl.y = 0;
  1080. if (fSelIsOleObject) {
  1081. /* OLE2NOTE: a single OLE object is being transfered via
  1082. ** this DataTransferDoc. we need to generate the
  1083. ** CF_ObjectDescrioptor which describes the OLE object.
  1084. */
  1085. LPOUTLINEDOC lpSrcOutlineDoc =
  1086. (LPOUTLINEDOC)lpOleDoc->m_lpSrcDocOfCopy;
  1087. LPSTR lpszSrcOfCopy = lpSrcOutlineDoc->m_szFileName;
  1088. BOOL fFreeSrcOfCopy = FALSE;
  1089. SIZEL sizelOleObject;
  1090. LPLINE lpLine = (LPLINE)lpContainerLine;
  1091. /* if the object copied can be linked to then get a
  1092. ** TEMPFORUSER form of the moniker which identifies the
  1093. ** source of copy. we do not want to force the
  1094. ** assignment of the moniker until CF_LINKSOURCE is
  1095. ** rendered.
  1096. ** if the object copied can not be a link source then use
  1097. ** the source filename to identify the source of copy.
  1098. ** there is no need to generate a moniker for the object
  1099. ** copied.
  1100. */
  1101. if (lpOleDoc->m_fLinkSourceAvail &&
  1102. lpContainerDoc->m_lpSrcContainerLine) {
  1103. LPBINDCTX pbc = NULL;
  1104. LPMONIKER lpSrcMonikerOfCopy = ContainerLine_GetFullMoniker(
  1105. lpContainerDoc->m_lpSrcContainerLine,
  1106. GETMONIKER_TEMPFORUSER
  1107. );
  1108. if (lpSrcMonikerOfCopy) {
  1109. CreateBindCtx(0, (LPBC FAR*)&pbc);
  1110. if (pbc != NULL) {
  1111. CallIMonikerGetDisplayNameA(
  1112. lpSrcMonikerOfCopy, pbc, NULL, &lpszSrcOfCopy);
  1113. pbc->lpVtbl->Release(pbc);
  1114. fFreeSrcOfCopy = TRUE;
  1115. }
  1116. lpSrcMonikerOfCopy->lpVtbl->Release(lpSrcMonikerOfCopy);
  1117. }
  1118. }
  1119. /* OLE2NOTE: Get size that object is being drawn. If the
  1120. ** object has been scaled because the user resized the
  1121. ** object, then we want to pass the scaled size of the
  1122. ** object in the ObjectDescriptor rather than the size
  1123. ** that the object would return via
  1124. ** IOleObject::GetExtent and IViewObject2::GetExtent. in
  1125. ** this way if the object is transfered to another container
  1126. ** (via clipboard or drag/drop), then the object will
  1127. ** remain the scaled size.
  1128. */
  1129. sizelOleObject.cx = lpLine->m_nWidthInHimetric;
  1130. sizelOleObject.cy = lpLine->m_nHeightInHimetric;
  1131. hObjDesc = OleStdGetObjectDescriptorDataFromOleObject(
  1132. lpOleObj,
  1133. lpszSrcOfCopy,
  1134. lpContainerLine->m_dwDrawAspect,
  1135. pointl,
  1136. (LPSIZEL)&sizelOleObject
  1137. );
  1138. if (fFreeSrcOfCopy && lpszSrcOfCopy)
  1139. OleStdFreeString(lpszSrcOfCopy, NULL);
  1140. OleStdRelease((LPUNKNOWN)lpOleObj);
  1141. return hObjDesc;
  1142. } else {
  1143. /* OLE2NOTE: the data being transfered via this
  1144. ** DataTransferDoc is NOT a single OLE object. thus in
  1145. ** this case the CF_ObjectDescriptor data should
  1146. ** describe our container app itself.
  1147. */
  1148. OleDoc_GetExtent(lpOleDoc, &sizel);
  1149. return OleStdGetObjectDescriptorData(
  1150. CLSID_NULL, /* not used if no object formats */
  1151. DVASPECT_CONTENT,
  1152. sizel,
  1153. pointl,
  1154. 0,
  1155. NULL, /* UserTypeName not used if no obj fmt's */
  1156. FULLUSERTYPENAME /* string to identify source of copy */
  1157. );
  1158. }
  1159. }
  1160. #endif // OLE_CNTR
  1161. }
  1162. #if defined( OLE_SERVER )
  1163. /*************************************************************************
  1164. ** ServerDoc Supprt Functions Used by Server versions
  1165. *************************************************************************/
  1166. /* ServerDoc_PasteFormatFromData
  1167. ** -----------------------------
  1168. **
  1169. ** Paste a particular data format from a IDataObject*. The
  1170. ** IDataObject* may come from the clipboard (GetClipboard) or from a
  1171. ** drag/drop operation.
  1172. **
  1173. ** NOTE: fLink is specified then FALSE if returned because the
  1174. ** Server only version of the app can not support links.
  1175. **
  1176. ** Returns TRUE if data was successfully pasted.
  1177. ** FALSE if data could not be pasted.
  1178. */
  1179. BOOL ServerDoc_PasteFormatFromData(
  1180. LPSERVERDOC lpServerDoc,
  1181. CLIPFORMAT cfFormat,
  1182. LPDATAOBJECT lpSrcDataObj,
  1183. BOOL fLocalDataObj,
  1184. BOOL fLink
  1185. )
  1186. {
  1187. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpServerDoc)->m_LineList;
  1188. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1189. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  1190. int nIndex;
  1191. int nCount = 0;
  1192. HGLOBAL hData;
  1193. STGMEDIUM medium;
  1194. LINERANGE lrSel;
  1195. if (LineList_GetCount(lpLL) == 0)
  1196. nIndex = -1; // pasting to empty list
  1197. else
  1198. nIndex=LineList_GetFocusLineIndex(lpLL);
  1199. if (fLink) {
  1200. /* We should paste a Link to the data, but we do not support links */
  1201. return FALSE;
  1202. } else {
  1203. if (cfFormat == lpOutlineApp->m_cfOutline) {
  1204. hData = OleStdGetData(
  1205. lpSrcDataObj,
  1206. lpOutlineApp->m_cfOutline,
  1207. NULL,
  1208. DVASPECT_CONTENT,
  1209. (LPSTGMEDIUM)&medium
  1210. );
  1211. if (hData == NULL)
  1212. return FALSE;
  1213. nCount = OutlineDoc_PasteOutlineData(
  1214. (LPOUTLINEDOC)lpServerDoc,
  1215. hData,
  1216. nIndex
  1217. );
  1218. // OLE2NOTE: we must free data handle by releasing the medium
  1219. ReleaseStgMedium((LPSTGMEDIUM)&medium);
  1220. } else if(cfFormat == CF_TEXT) {
  1221. hData = OleStdGetData(
  1222. lpSrcDataObj,
  1223. CF_TEXT,
  1224. NULL,
  1225. DVASPECT_CONTENT,
  1226. (LPSTGMEDIUM)&medium
  1227. );
  1228. if (hData == NULL)
  1229. return FALSE;
  1230. nCount = OutlineDoc_PasteTextData(
  1231. (LPOUTLINEDOC)lpServerDoc,
  1232. hData,
  1233. nIndex
  1234. );
  1235. // OLE2NOTE: we must free data handle by releasing the medium
  1236. ReleaseStgMedium((LPSTGMEDIUM)&medium);
  1237. }
  1238. }
  1239. lrSel.m_nEndLine = nIndex + 1;
  1240. lrSel.m_nStartLine = nIndex + nCount;
  1241. LineList_SetSel(lpLL, &lrSel);
  1242. return TRUE;
  1243. }
  1244. /* ServerDoc_QueryPasteFromData
  1245. ** ----------------------------
  1246. **
  1247. ** Check if the IDataObject* offers data in a format that we can
  1248. ** paste. The IDataObject* may come from the clipboard
  1249. ** (GetClipboard) or from a drag/drop operation.
  1250. ** In this function we look if one of the following formats is
  1251. ** offered:
  1252. ** CF_OUTLINE
  1253. ** CF_TEXT
  1254. **
  1255. ** NOTE: fLink is specified then FALSE if returned because the
  1256. ** Server only version of the app can not support links.
  1257. **
  1258. ** Returns TRUE if paste can be performed
  1259. ** FALSE if paste is not possible.
  1260. */
  1261. BOOL ServerDoc_QueryPasteFromData(
  1262. LPSERVERDOC lpServerDoc,
  1263. LPDATAOBJECT lpSrcDataObj,
  1264. BOOL fLink
  1265. )
  1266. {
  1267. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  1268. if (fLink) {
  1269. /* we do not support links */
  1270. return FALSE;
  1271. } else {
  1272. int nFmtEtc;
  1273. nFmtEtc = OleStdGetPriorityClipboardFormat(
  1274. lpSrcDataObj,
  1275. lpOleApp->m_arrPasteEntries,
  1276. lpOleApp->m_nPasteEntries
  1277. );
  1278. if (nFmtEtc < 0)
  1279. return FALSE; // there is no format we like
  1280. }
  1281. return TRUE;
  1282. }
  1283. /* ServerDoc_GetData
  1284. * -----------------
  1285. *
  1286. * Render data from the document on a CALLEE allocated STGMEDIUM.
  1287. * This routine is called via IDataObject::GetData.
  1288. */
  1289. HRESULT ServerDoc_GetData (
  1290. LPSERVERDOC lpServerDoc,
  1291. LPFORMATETC lpformatetc,
  1292. LPSTGMEDIUM lpMedium
  1293. )
  1294. {
  1295. LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
  1296. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
  1297. LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp;
  1298. LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp;
  1299. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp;
  1300. HRESULT hrErr;
  1301. SCODE sc;
  1302. // OLE2NOTE: we must set out pointer parameters to NULL
  1303. lpMedium->pUnkForRelease = NULL;
  1304. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  1305. lpMedium->tymed = TYMED_NULL;
  1306. lpMedium->pUnkForRelease = NULL; // we transfer ownership to caller
  1307. lpMedium->hGlobal = NULL;
  1308. if(lpformatetc->cfFormat == lpOutlineApp->m_cfOutline) {
  1309. // Verify caller asked for correct medium
  1310. if (!(lpformatetc->tymed & TYMED_HGLOBAL)) {
  1311. sc = DV_E_FORMATETC;
  1312. goto error;
  1313. }
  1314. lpMedium->hGlobal = OutlineDoc_GetOutlineData (lpOutlineDoc,NULL);
  1315. if (! lpMedium->hGlobal) {
  1316. sc = E_OUTOFMEMORY;
  1317. goto error;
  1318. }
  1319. lpMedium->tymed = TYMED_HGLOBAL;
  1320. OleDbgOut3("ServerDoc_GetData: rendered CF_OUTLINE\r\n");
  1321. return NOERROR;
  1322. } else if (lpformatetc->cfFormat == CF_METAFILEPICT &&
  1323. (lpformatetc->dwAspect & DVASPECT_CONTENT) ) {
  1324. // Verify caller asked for correct medium
  1325. if (!(lpformatetc->tymed & TYMED_MFPICT)) {
  1326. sc = DV_E_FORMATETC;
  1327. goto error;
  1328. }
  1329. lpMedium->hGlobal = ServerDoc_GetMetafilePictData(lpServerDoc,NULL);
  1330. if (! lpMedium->hGlobal) {
  1331. sc = E_OUTOFMEMORY;
  1332. goto error;
  1333. }
  1334. lpMedium->tymed = TYMED_MFPICT;
  1335. OleDbgOut3("ServerDoc_GetData: rendered CF_METAFILEPICT\r\n");
  1336. return NOERROR;
  1337. } else if (lpformatetc->cfFormat == CF_METAFILEPICT &&
  1338. (lpformatetc->dwAspect & DVASPECT_ICON) ) {
  1339. CLSID clsid;
  1340. // Verify caller asked for correct medium
  1341. if (!(lpformatetc->tymed & TYMED_MFPICT)) {
  1342. sc = DV_E_FORMATETC;
  1343. goto error;
  1344. }
  1345. /* OLE2NOTE: we should return the default icon for our class.
  1346. ** we must be carefull to use the correct CLSID here.
  1347. ** if we are currently preforming a "TreatAs (aka. ActivateAs)"
  1348. ** operation then we need to use the class of the object
  1349. ** written in the storage of the object. otherwise we would
  1350. ** use our own class id.
  1351. */
  1352. if (ServerDoc_GetClassID(lpServerDoc, (LPCLSID)&clsid) != NOERROR) {
  1353. sc = DV_E_FORMATETC;
  1354. goto error;
  1355. }
  1356. lpMedium->hGlobal=GetIconOfClass(g_lpApp->m_hInst,(REFCLSID)&clsid, NULL, FALSE);
  1357. if (! lpMedium->hGlobal) {
  1358. sc = E_OUTOFMEMORY;
  1359. goto error;
  1360. }
  1361. lpMedium->tymed = TYMED_MFPICT;
  1362. OleDbgOut3("ServerDoc_GetData: rendered CF_METAFILEPICT (icon)\r\n");
  1363. return NOERROR;
  1364. } else if (lpformatetc->cfFormat == CF_TEXT) {
  1365. // Verify caller asked for correct medium
  1366. if (!(lpformatetc->tymed & TYMED_HGLOBAL)) {
  1367. sc = DV_E_FORMATETC;
  1368. goto error;
  1369. }
  1370. lpMedium->hGlobal = OutlineDoc_GetTextData (
  1371. (LPOUTLINEDOC)lpServerDoc,
  1372. NULL
  1373. );
  1374. if (! lpMedium->hGlobal) {
  1375. sc = E_OUTOFMEMORY;
  1376. goto error;
  1377. }
  1378. lpMedium->tymed = TYMED_HGLOBAL;
  1379. OleDbgOut3("ServerDoc_GetData: rendered CF_TEXT\r\n");
  1380. return NOERROR;
  1381. }
  1382. /* the above are the only formats supports by a user document (ie.
  1383. ** a non-data transfer doc). if the document is used for
  1384. ** purposes of data transfer, then additional formats are offered.
  1385. */
  1386. if (! lpOutlineDoc->m_fDataTransferDoc) {
  1387. sc = DV_E_FORMATETC;
  1388. goto error;
  1389. }
  1390. /* OLE2NOTE: ObjectDescriptor and LinkSrcDescriptor will
  1391. ** contain the same data for the pure container and pure server
  1392. ** type applications. only a container/server application may
  1393. ** have different content for ObjectDescriptor and
  1394. ** LinkSrcDescriptor. if a container/server copies a link for
  1395. ** example, then the ObjectDescriptor would give the class
  1396. ** of the link source but the LinkSrcDescriptor would give the
  1397. ** class of the container/server itself. in this situation if a
  1398. ** paste operation occurs, an equivalent link is pasted, but if
  1399. ** a pastelink operation occurs, then a link to a pseudo object
  1400. ** in the container/server is created.
  1401. */
  1402. if (lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor ||
  1403. (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor &&
  1404. lpOleDoc->m_fLinkSourceAvail)) {
  1405. // Verify caller asked for correct medium
  1406. if (!(lpformatetc->tymed & TYMED_HGLOBAL)) {
  1407. sc = DV_E_FORMATETC;
  1408. goto error;
  1409. }
  1410. lpMedium->hGlobal = OleDoc_GetObjectDescriptorData (
  1411. (LPOLEDOC)lpServerDoc,
  1412. NULL
  1413. );
  1414. if (! lpMedium->hGlobal) {
  1415. sc = E_OUTOFMEMORY;
  1416. goto error;
  1417. }
  1418. lpMedium->tymed = TYMED_HGLOBAL;
  1419. OleDbgOut3("ServerDoc_GetData: rendered CF_OBJECTDESCRIPTOR\r\n");
  1420. return NOERROR;
  1421. } else if (lpformatetc->cfFormat == lpOleApp->m_cfEmbedSource) {
  1422. hrErr = OleStdGetOleObjectData(
  1423. (LPPERSISTSTORAGE)&lpServerDoc->m_PersistStorage,
  1424. lpformatetc,
  1425. lpMedium,
  1426. FALSE /* fUseMemory -- (use file-base stg) */
  1427. );
  1428. if (hrErr != NOERROR) {
  1429. sc = GetScode(hrErr);
  1430. goto error;
  1431. }
  1432. OleDbgOut3("ServerDoc_GetData: rendered CF_EMBEDSOURCE\r\n");
  1433. return NOERROR;
  1434. } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) {
  1435. if (lpOleDoc->m_fLinkSourceAvail) {
  1436. LPMONIKER lpmk;
  1437. lpmk = ServerDoc_GetSelFullMoniker(
  1438. (LPSERVERDOC)lpOleDoc->m_lpSrcDocOfCopy,
  1439. &lpServerDoc->m_lrSrcSelOfCopy,
  1440. GETMONIKER_FORCEASSIGN
  1441. );
  1442. if (lpmk) {
  1443. hrErr = OleStdGetLinkSourceData(
  1444. lpmk,
  1445. (LPCLSID)&CLSID_APP,
  1446. lpformatetc,
  1447. lpMedium
  1448. );
  1449. OleStdRelease((LPUNKNOWN)lpmk);
  1450. if (hrErr != NOERROR) {
  1451. sc = GetScode(hrErr);
  1452. goto error;
  1453. }
  1454. OleDbgOut3("ServerDoc_GetData: rendered CF_LINKSOURCE\r\n");
  1455. return NOERROR;
  1456. } else {
  1457. sc = E_FAIL;
  1458. goto error;
  1459. }
  1460. } else {
  1461. sc = DV_E_FORMATETC;
  1462. goto error;
  1463. }
  1464. } else {
  1465. sc = DV_E_FORMATETC;
  1466. goto error;
  1467. }
  1468. return NOERROR;
  1469. error:
  1470. return ResultFromScode(sc);
  1471. }
  1472. /* ServerDoc_GetDataHere
  1473. * ---------------------
  1474. *
  1475. * Render data from the document on a CALLER allocated STGMEDIUM.
  1476. * This routine is called via IDataObject::GetDataHere.
  1477. */
  1478. HRESULT ServerDoc_GetDataHere (
  1479. LPSERVERDOC lpServerDoc,
  1480. LPFORMATETC lpformatetc,
  1481. LPSTGMEDIUM lpMedium
  1482. )
  1483. {
  1484. LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
  1485. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
  1486. LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp;
  1487. LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp;
  1488. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp;
  1489. HRESULT hrErr;
  1490. SCODE sc;
  1491. // OLE2NOTE: lpMedium is an IN parameter. we should NOT set
  1492. // lpMedium->pUnkForRelease to NULL
  1493. /* our user document does not support any formats for GetDataHere.
  1494. ** if the document is used for
  1495. ** purposes of data transfer, then additional formats are offered.
  1496. */
  1497. if (! lpOutlineDoc->m_fDataTransferDoc) {
  1498. sc = DV_E_FORMATETC;
  1499. goto error;
  1500. }
  1501. if (lpformatetc->cfFormat == lpOleApp->m_cfEmbedSource) {
  1502. hrErr = OleStdGetOleObjectData(
  1503. (LPPERSISTSTORAGE)&lpServerDoc->m_PersistStorage,
  1504. lpformatetc,
  1505. lpMedium,
  1506. FALSE /* fUseMemory -- (use file-base stg) */
  1507. );
  1508. if (hrErr != NOERROR) {
  1509. sc = GetScode(hrErr);
  1510. goto error;
  1511. }
  1512. OleDbgOut3("ServerDoc_GetDataHere: rendered CF_EMBEDSOURCE\r\n");
  1513. return NOERROR;
  1514. } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) {
  1515. if (lpOleDoc->m_fLinkSourceAvail) {
  1516. LPMONIKER lpmk;
  1517. lpmk = ServerDoc_GetSelFullMoniker(
  1518. (LPSERVERDOC)lpOleDoc->m_lpSrcDocOfCopy,
  1519. &lpServerDoc->m_lrSrcSelOfCopy,
  1520. GETMONIKER_FORCEASSIGN
  1521. );
  1522. if (lpmk) {
  1523. hrErr = OleStdGetLinkSourceData(
  1524. lpmk,
  1525. (LPCLSID)&CLSID_APP,
  1526. lpformatetc,
  1527. lpMedium
  1528. );
  1529. OleStdRelease((LPUNKNOWN)lpmk);
  1530. if (hrErr != NOERROR) {
  1531. sc = GetScode(hrErr);
  1532. goto error;
  1533. }
  1534. OleDbgOut3("ServerDoc_GetDataHere: rendered CF_LINKSOURCE\r\n");
  1535. return NOERROR;
  1536. } else {
  1537. sc = E_FAIL;
  1538. goto error;
  1539. }
  1540. } else {
  1541. sc = DV_E_FORMATETC;
  1542. goto error;
  1543. }
  1544. } else {
  1545. /* Caller is requesting data to be returned in Caller allocated
  1546. ** medium, but we do NOT support this. we only support
  1547. ** global memory blocks that WE allocate for the caller.
  1548. */
  1549. sc = DV_E_FORMATETC;
  1550. goto error;
  1551. }
  1552. return NOERROR;
  1553. error:
  1554. return ResultFromScode(sc);
  1555. }
  1556. /* ServerDoc_QueryGetData
  1557. * ----------------------
  1558. *
  1559. * Answer if a particular data format is supported via GetData/GetDataHere.
  1560. * This routine is called via IDataObject::QueryGetData.
  1561. */
  1562. HRESULT ServerDoc_QueryGetData (LPSERVERDOC lpServerDoc,LPFORMATETC lpformatetc)
  1563. {
  1564. LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
  1565. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
  1566. LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp;
  1567. LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp;
  1568. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp;
  1569. /* Caller is querying if we support certain format but does not
  1570. ** want any data actually returned.
  1571. */
  1572. if (lpformatetc->cfFormat == lpOutlineApp->m_cfOutline ||
  1573. lpformatetc->cfFormat == CF_TEXT) {
  1574. // we only support HGLOBAL
  1575. return OleStdQueryFormatMedium(lpformatetc, TYMED_HGLOBAL);
  1576. } else if (lpformatetc->cfFormat == CF_METAFILEPICT &&
  1577. (lpformatetc->dwAspect &
  1578. (DVASPECT_CONTENT | DVASPECT_ICON)) ) {
  1579. return OleStdQueryFormatMedium(lpformatetc, TYMED_MFPICT);
  1580. }
  1581. /* the above are the only formats supports by a user document (ie.
  1582. ** a non-data transfer doc). if the document is used for
  1583. ** purposes of data transfer, then additional formats are offered.
  1584. */
  1585. if (! lpOutlineDoc->m_fDataTransferDoc)
  1586. return ResultFromScode(DV_E_FORMATETC);
  1587. if (lpformatetc->cfFormat == lpOleApp->m_cfEmbedSource) {
  1588. return OleStdQueryOleObjectData(lpformatetc);
  1589. } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource &&
  1590. lpOleDoc->m_fLinkSourceAvail) {
  1591. return OleStdQueryLinkSourceData(lpformatetc);
  1592. } else if (lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor) {
  1593. return OleStdQueryObjectDescriptorData(lpformatetc);
  1594. } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor &&
  1595. lpOleDoc->m_fLinkSourceAvail) {
  1596. return OleStdQueryObjectDescriptorData(lpformatetc);
  1597. }
  1598. return ResultFromScode(DV_E_FORMATETC);
  1599. }
  1600. /* ServerDoc_EnumFormatEtc
  1601. * -----------------------
  1602. *
  1603. * Return an enumerator which enumerates the data accepted/offered by
  1604. * the document.
  1605. * This routine is called via IDataObject::EnumFormatEtc.
  1606. */
  1607. HRESULT ServerDoc_EnumFormatEtc(
  1608. LPSERVERDOC lpServerDoc,
  1609. DWORD dwDirection,
  1610. LPENUMFORMATETC FAR* lplpenumFormatEtc
  1611. )
  1612. {
  1613. LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
  1614. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  1615. int nActualFmts;
  1616. SCODE sc = S_OK;
  1617. /* OLE2NOTE: the enumeration of formats for a data transfer
  1618. ** document is not a static list. the list of formats offered
  1619. ** may or may not include CF_LINKSOURCE depending on whether a
  1620. ** moniker is available for our document. thus we can NOT use
  1621. ** the default OLE enumerator which enumerates the formats that
  1622. ** are registered for our app in the registration database.
  1623. */
  1624. if (dwDirection == DATADIR_GET) {
  1625. nActualFmts = lpOleApp->m_nDocGetFmts;
  1626. /* If the document does not have a Moniker, then exclude
  1627. ** CF_LINKSOURCE and CF_LINKSRCDESCRIPTOR from the list of
  1628. ** formats available. these formats are deliberately listed
  1629. ** last in the array of possible "Get" formats.
  1630. */
  1631. if (! lpOleDoc->m_fLinkSourceAvail)
  1632. nActualFmts -= 2;
  1633. *lplpenumFormatEtc = OleStdEnumFmtEtc_Create(
  1634. nActualFmts, lpOleApp->m_arrDocGetFmts);
  1635. if (*lplpenumFormatEtc == NULL)
  1636. sc = E_OUTOFMEMORY;
  1637. } else if (dwDirection == DATADIR_SET) {
  1638. /* OLE2NOTE: a document that is used to transfer data
  1639. ** (either via the clipboard or drag/drop does NOT
  1640. ** accept SetData on ANY format!
  1641. */
  1642. sc = E_NOTIMPL;
  1643. goto error;
  1644. } else {
  1645. sc = E_INVALIDARG;
  1646. goto error;
  1647. }
  1648. error:
  1649. return ResultFromScode(sc);
  1650. }
  1651. /* ServerDoc_GetMetafilePictData
  1652. * -----------------------------
  1653. *
  1654. * Return a handle to an object's picture data in metafile format.
  1655. *
  1656. *
  1657. * RETURNS: A handle to the object's data in metafile format.
  1658. *
  1659. */
  1660. HGLOBAL ServerDoc_GetMetafilePictData(
  1661. LPSERVERDOC lpServerDoc,
  1662. LPLINERANGE lplrSel
  1663. )
  1664. {
  1665. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1666. LPOUTLINEDOC lpOutlineDoc=(LPOUTLINEDOC)lpServerDoc;
  1667. LPLINELIST lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList;
  1668. LPLINE lpLine;
  1669. LPMETAFILEPICT lppict = NULL;
  1670. HGLOBAL hMFPict = NULL;
  1671. HMETAFILE hMF = NULL;
  1672. RECT rect;
  1673. RECT rectWBounds;
  1674. HDC hDC;
  1675. int i;
  1676. int nWidth;
  1677. int nStart = (lplrSel ? lplrSel->m_nStartLine : 0);
  1678. int nEnd =(lplrSel ? lplrSel->m_nEndLine : LineList_GetCount(lpLL)-1);
  1679. int nLines = nEnd - nStart + 1;
  1680. UINT fuAlign;
  1681. POINT point;
  1682. SIZE size;
  1683. hDC = CreateMetaFile(NULL);
  1684. rect.left = 0;
  1685. rect.right = 0;
  1686. rect.bottom = 0;
  1687. if (nLines > 0) {
  1688. // calculate the total height/width of LineList in HIMETRIC
  1689. for(i = nStart; i <= nEnd; i++) {
  1690. lpLine = LineList_GetLine(lpLL,i);
  1691. if (! lpLine)
  1692. continue;
  1693. nWidth = Line_GetTotalWidthInHimetric(lpLine);
  1694. rect.right = max(rect.right, nWidth);
  1695. rect.bottom -= Line_GetHeightInHimetric(lpLine);
  1696. }
  1697. SetMapMode(hDC, MM_ANISOTROPIC);
  1698. SetWindowOrgEx(hDC, 0, 0, &point);
  1699. SetWindowExtEx(hDC, rect.right, rect.bottom, &size);
  1700. rectWBounds = rect;
  1701. // Set the default font size, and font face name
  1702. SelectObject(hDC, OutlineApp_GetActiveFont(lpOutlineApp));
  1703. FillRect(hDC, (LPRECT) &rect, GetStockObject(WHITE_BRUSH));
  1704. rect.bottom = 0;
  1705. fuAlign = SetTextAlign(hDC, TA_LEFT | TA_TOP | TA_NOUPDATECP);
  1706. /* While more lines print out the text */
  1707. for(i = nStart; i <= nEnd; i++) {
  1708. lpLine = LineList_GetLine(lpLL,i);
  1709. if (! lpLine)
  1710. continue;
  1711. rect.top = rect.bottom;
  1712. rect.bottom -= Line_GetHeightInHimetric(lpLine);
  1713. /* Draw the line */
  1714. Line_Draw(lpLine, hDC, &rect, &rectWBounds, FALSE /*fHighlight*/);
  1715. }
  1716. SetTextAlign(hDC, fuAlign);
  1717. }
  1718. // Get handle to the metafile.
  1719. if (!(hMF = CloseMetaFile (hDC)))
  1720. return NULL;
  1721. if (!(hMFPict = GlobalAlloc (GMEM_SHARE | GMEM_ZEROINIT,
  1722. sizeof (METAFILEPICT)))) {
  1723. DeleteMetaFile (hMF);
  1724. return NULL;
  1725. }
  1726. if (!(lppict = (LPMETAFILEPICT)GlobalLock(hMFPict))) {
  1727. DeleteMetaFile (hMF);
  1728. GlobalFree (hMFPict);
  1729. return NULL;
  1730. }
  1731. lppict->mm = MM_ANISOTROPIC;
  1732. lppict->hMF = hMF;
  1733. lppict->xExt = rect.right;
  1734. lppict->yExt = - rect.bottom; // add minus sign to make it +ve
  1735. GlobalUnlock (hMFPict);
  1736. return hMFPict;
  1737. }
  1738. #endif // OLE_SERVER
  1739. #if defined( OLE_CNTR )
  1740. /*************************************************************************
  1741. ** ContainerDoc Supprt Functions Used by Container versions
  1742. *************************************************************************/
  1743. /* Paste OLE Link from clipboard */
  1744. void ContainerDoc_PasteLinkCommand(LPCONTAINERDOC lpContainerDoc)
  1745. {
  1746. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1747. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  1748. LPDATAOBJECT lpClipboardDataObj = NULL;
  1749. BOOL fLink = TRUE;
  1750. BOOL fLocalDataObj = FALSE;
  1751. BOOL fDisplayAsIcon = FALSE;
  1752. SIZEL sizelInSrc;
  1753. HCURSOR hPrevCursor;
  1754. HGLOBAL hMem = NULL;
  1755. HGLOBAL hMetaPict = NULL;
  1756. STGMEDIUM medium;
  1757. BOOL fStatus;
  1758. HRESULT hrErr;
  1759. hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj);
  1760. if (hrErr != NOERROR)
  1761. return; // Clipboard seems to be empty or can't be accessed
  1762. // this may take a while, put up hourglass cursor
  1763. hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1764. /* check if the data on the clipboard is local to our application
  1765. ** instance.
  1766. */
  1767. if (lpOutlineApp->m_lpClipboardDoc) {
  1768. LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc;
  1769. if (lpClipboardDataObj == (LPDATAOBJECT)&lpOleDoc->m_DataObject)
  1770. fLocalDataObj = TRUE;
  1771. }
  1772. /* OLE2NOTE: we need to check what dwDrawAspect is being
  1773. ** transfered. if the data is an object that is displayed as an
  1774. ** icon in the source, then we want to keep it as an icon. the
  1775. ** aspect the object is displayed in at the source is transfered
  1776. ** via the CF_LINKSOURCEDESCRIPTOR format for a PasteLink
  1777. ** operation.
  1778. */
  1779. if (hMem = OleStdGetData(
  1780. lpClipboardDataObj,
  1781. lpOleApp->m_cfLinkSrcDescriptor,
  1782. NULL,
  1783. DVASPECT_CONTENT,
  1784. (LPSTGMEDIUM)&medium)) {
  1785. LPOBJECTDESCRIPTOR lpOD = GlobalLock(hMem);
  1786. fDisplayAsIcon = (lpOD->dwDrawAspect == DVASPECT_ICON ? TRUE : FALSE);
  1787. sizelInSrc = lpOD->sizel; // size of object/picture in source (opt.)
  1788. GlobalUnlock(hMem);
  1789. ReleaseStgMedium((LPSTGMEDIUM)&medium); // equiv to GlobalFree
  1790. if (fDisplayAsIcon) {
  1791. hMetaPict = OleStdGetData(
  1792. lpClipboardDataObj,
  1793. CF_METAFILEPICT,
  1794. NULL,
  1795. DVASPECT_ICON,
  1796. (LPSTGMEDIUM)&medium
  1797. );
  1798. if (hMetaPict == NULL)
  1799. fDisplayAsIcon = FALSE; // give up; failed to get icon MFP
  1800. }
  1801. }
  1802. fStatus = ContainerDoc_PasteFormatFromData(
  1803. lpContainerDoc,
  1804. lpOleApp->m_cfLinkSource,
  1805. lpClipboardDataObj,
  1806. fLocalDataObj,
  1807. fLink,
  1808. fDisplayAsIcon,
  1809. hMetaPict,
  1810. (LPSIZEL)&sizelInSrc
  1811. );
  1812. if (!fStatus)
  1813. OutlineApp_ErrorMessage(g_lpApp, ErrMsgPasting);
  1814. if (hMetaPict)
  1815. ReleaseStgMedium((LPSTGMEDIUM)&medium); // properly free METAFILEPICT
  1816. if (lpClipboardDataObj)
  1817. OleStdRelease((LPUNKNOWN)lpClipboardDataObj);
  1818. SetCursor(hPrevCursor); // restore original cursor
  1819. }
  1820. /* ContainerDoc_PasteFormatFromData
  1821. ** --------------------------------
  1822. **
  1823. ** Paste a particular data format from a IDataObject*. The
  1824. ** IDataObject* may come from the clipboard (GetClipboard) or from a
  1825. ** drag/drop operation.
  1826. **
  1827. ** Returns TRUE if data was successfully pasted.
  1828. ** FALSE if data could not be pasted.
  1829. */
  1830. BOOL ContainerDoc_PasteFormatFromData(
  1831. LPCONTAINERDOC lpContainerDoc,
  1832. CLIPFORMAT cfFormat,
  1833. LPDATAOBJECT lpSrcDataObj,
  1834. BOOL fLocalDataObj,
  1835. BOOL fLink,
  1836. BOOL fDisplayAsIcon,
  1837. HGLOBAL hMetaPict,
  1838. LPSIZEL lpSizelInSrc
  1839. )
  1840. {
  1841. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
  1842. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1843. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  1844. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  1845. int nIndex;
  1846. int nCount = 0;
  1847. HGLOBAL hData;
  1848. STGMEDIUM medium;
  1849. FORMATETC formatetc;
  1850. HRESULT hrErr;
  1851. LINERANGE lrSel;
  1852. if (LineList_GetCount(lpLL) == 0)
  1853. nIndex = -1; // pasting to empty list
  1854. else
  1855. nIndex=LineList_GetFocusLineIndex(lpLL);
  1856. if (fLink) {
  1857. /* We should paste a Link to the data */
  1858. if (cfFormat != lpOleApp->m_cfLinkSource)
  1859. return FALSE; // we only support OLE object type links
  1860. nCount = ContainerDoc_PasteOleObject(
  1861. lpContainerDoc,
  1862. lpSrcDataObj,
  1863. OLECREATEFROMDATA_LINK,
  1864. cfFormat,
  1865. nIndex,
  1866. fDisplayAsIcon,
  1867. hMetaPict,
  1868. lpSizelInSrc
  1869. );
  1870. return (nCount > 0 ? TRUE : FALSE);
  1871. } else {
  1872. if (cfFormat == lpContainerApp->m_cfCntrOutl) {
  1873. if (fLocalDataObj) {
  1874. /* CASE I: IDataObject* is local to our app
  1875. **
  1876. ** if the source of the data is local to our
  1877. ** application instance, then we can get direct
  1878. ** access to the original OleDoc object that
  1879. ** corresponds to the IDataObject* given.
  1880. ** CF_CNTROUTL data is passed through a LPSTORAGE.
  1881. ** if we call OleGetData asking for CF_CNTROUTL, we
  1882. ** will be returned a copy of the existing open pStg
  1883. ** of the original source document. we can NOT open
  1884. ** streams and sub-storages again via this pStg
  1885. ** since it is already open within our same
  1886. ** application instance. we must copy the data from
  1887. ** the original OleDoc source document.
  1888. */
  1889. LPLINELIST lpSrcLL;
  1890. LPOLEDOC lpLocalSrcDoc =
  1891. ((struct CDocDataObjectImpl FAR*)lpSrcDataObj)->lpOleDoc;
  1892. /* copy all lines from SrcDoc to DestDoc. */
  1893. lpSrcLL = &((LPOUTLINEDOC)lpLocalSrcDoc)->m_LineList;
  1894. nCount = LineList_CopySelToDoc(
  1895. lpSrcLL,
  1896. NULL,
  1897. (LPOUTLINEDOC)lpContainerDoc
  1898. );
  1899. } else {
  1900. /* CASE II: IDataObject* is NOT local to our app
  1901. **
  1902. ** if the source of the data comes from another
  1903. ** application instance. we can call GetDataHere to
  1904. ** retrieve the CF_CNTROUTL data. CF_CNTROUTL data
  1905. ** is passed through a LPSTORAGE. we MUST use
  1906. ** IDataObject::GetDataHere. calling
  1907. ** IDataObject::GetData does NOT work because OLE
  1908. ** currently does NOT support remoting of a callee
  1909. ** allocated root storage back to the caller. this
  1910. ** hopefully will be supported in a future version.
  1911. ** in order to call GetDataHere we must allocate an
  1912. ** IStorage instance for the callee to write into.
  1913. ** we will allocate an IStorage docfile that will
  1914. ** delete-on-release. we could use either a
  1915. ** memory-based storage or a file-based storage.
  1916. */
  1917. LPSTORAGE lpTmpStg = OleStdCreateTempStorage(
  1918. FALSE /*fUseMemory*/,
  1919. STGM_READWRITE | STGM_TRANSACTED |STGM_SHARE_EXCLUSIVE
  1920. );
  1921. if (! lpTmpStg)
  1922. return FALSE;
  1923. formatetc.cfFormat = cfFormat;
  1924. formatetc.ptd = NULL;
  1925. formatetc.dwAspect = DVASPECT_CONTENT;
  1926. formatetc.tymed = TYMED_ISTORAGE;
  1927. formatetc.lindex = -1;
  1928. medium.tymed = TYMED_ISTORAGE;
  1929. medium.pstg = lpTmpStg;
  1930. medium.pUnkForRelease = NULL;
  1931. OLEDBG_BEGIN2("IDataObject::GetDataHere called\r\n")
  1932. hrErr = lpSrcDataObj->lpVtbl->GetDataHere(
  1933. lpSrcDataObj,
  1934. (LPFORMATETC)&formatetc,
  1935. (LPSTGMEDIUM)&medium
  1936. );
  1937. OLEDBG_END2
  1938. if (hrErr == NOERROR) {
  1939. nCount = ContainerDoc_PasteCntrOutlData(
  1940. lpContainerDoc,
  1941. lpTmpStg,
  1942. nIndex
  1943. );
  1944. }
  1945. OleStdVerifyRelease(
  1946. (LPUNKNOWN)lpTmpStg, "Temp stg NOT released!\r\n");
  1947. return ((hrErr == NOERROR) ? TRUE : FALSE);
  1948. }
  1949. } else if (cfFormat == lpOutlineApp->m_cfOutline) {
  1950. hData = OleStdGetData(
  1951. lpSrcDataObj,
  1952. lpOutlineApp->m_cfOutline,
  1953. NULL,
  1954. DVASPECT_CONTENT,
  1955. (LPSTGMEDIUM)&medium
  1956. );
  1957. nCount = OutlineDoc_PasteOutlineData(
  1958. (LPOUTLINEDOC)lpContainerDoc,
  1959. hData,
  1960. nIndex
  1961. );
  1962. // OLE2NOTE: we must free data handle by releasing the medium
  1963. ReleaseStgMedium((LPSTGMEDIUM)&medium);
  1964. } else if (cfFormat == lpOleApp->m_cfEmbedSource ||
  1965. cfFormat == lpOleApp->m_cfEmbeddedObject ||
  1966. cfFormat == lpOleApp->m_cfFileName) {
  1967. /* OLE2NOTE: OleCreateFromData API creates an OLE object if
  1968. ** CF_EMBEDDEDOBJECT, CF_EMBEDSOURCE, or CF_FILENAME are
  1969. ** available from the source data object. the
  1970. ** CF_FILENAME case arises when a file is copied to the
  1971. ** clipboard from the FileManager. if the file has an
  1972. ** associated class (see GetClassFile API), then an
  1973. ** object of that class is created. otherwise an OLE 1.0
  1974. ** Packaged object is created.
  1975. */
  1976. nCount = ContainerDoc_PasteOleObject(
  1977. lpContainerDoc,
  1978. lpSrcDataObj,
  1979. OLECREATEFROMDATA_OBJECT,
  1980. 0, /* N/A -- cfFormat */
  1981. nIndex,
  1982. fDisplayAsIcon,
  1983. hMetaPict,
  1984. lpSizelInSrc
  1985. );
  1986. return (nCount > 0 ? TRUE : FALSE);
  1987. } else if (cfFormat == CF_METAFILEPICT
  1988. || cfFormat == CF_DIB
  1989. || cfFormat == CF_BITMAP) {
  1990. /* OLE2NOTE: OleCreateStaticFromData API creates an static
  1991. ** OLE object if CF_METAFILEPICT, CF_DIB, or CF_BITMAP is
  1992. ** CF_EMBEDDEDOBJECT, CF_EMBEDSOURCE, or CF_FILENAME are
  1993. ** available from the source data object.
  1994. */
  1995. nCount = ContainerDoc_PasteOleObject(
  1996. lpContainerDoc,
  1997. lpSrcDataObj,
  1998. OLECREATEFROMDATA_STATIC,
  1999. cfFormat,
  2000. nIndex,
  2001. fDisplayAsIcon,
  2002. hMetaPict,
  2003. lpSizelInSrc
  2004. );
  2005. return (nCount > 0 ? TRUE : FALSE);
  2006. } else if(cfFormat == CF_TEXT) {
  2007. hData = OleStdGetData(
  2008. lpSrcDataObj,
  2009. CF_TEXT,
  2010. NULL,
  2011. DVASPECT_CONTENT,
  2012. (LPSTGMEDIUM)&medium
  2013. );
  2014. nCount = OutlineDoc_PasteTextData(
  2015. (LPOUTLINEDOC)lpContainerDoc,
  2016. hData,
  2017. nIndex
  2018. );
  2019. // OLE2NOTE: we must free data handle by releasing the medium
  2020. ReleaseStgMedium((LPSTGMEDIUM)&medium);
  2021. } else {
  2022. return FALSE; // no acceptable format available to paste
  2023. }
  2024. }
  2025. lrSel.m_nStartLine = nIndex + nCount;
  2026. lrSel.m_nEndLine = nIndex + 1;
  2027. LineList_SetSel(lpLL, &lrSel);
  2028. return TRUE;
  2029. }
  2030. /* ContainerDoc_PasteCntrOutlData
  2031. * -------------------------------
  2032. *
  2033. * Load the lines stored in a lpSrcStg (stored in CF_CNTROUTL format)
  2034. * into the document.
  2035. *
  2036. * Return the number of items added
  2037. */
  2038. int ContainerDoc_PasteCntrOutlData(
  2039. LPCONTAINERDOC lpDestContainerDoc,
  2040. LPSTORAGE lpSrcStg,
  2041. int nStartIndex
  2042. )
  2043. {
  2044. int nCount;
  2045. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  2046. LPOUTLINEDOC lpDestOutlineDoc = (LPOUTLINEDOC)lpDestContainerDoc;
  2047. LPOUTLINEDOC lpSrcOutlineDoc;
  2048. LPLINELIST lpSrcLL;
  2049. // create a temp document that will be used to load the lpSrcStg data.
  2050. lpSrcOutlineDoc = (LPOUTLINEDOC)OutlineApp_CreateDoc(lpOutlineApp, FALSE);
  2051. if ( ! lpSrcOutlineDoc )
  2052. return 0;
  2053. if (! OutlineDoc_LoadFromStg(lpSrcOutlineDoc, lpSrcStg))
  2054. goto error;
  2055. /* copy all lines from the SrcDoc to the DestDoc. */
  2056. lpSrcLL = &lpSrcOutlineDoc->m_LineList;
  2057. nCount = LineList_CopySelToDoc(lpSrcLL, NULL, lpDestOutlineDoc);
  2058. if (lpSrcOutlineDoc) // destroy temporary document.
  2059. OutlineDoc_Close(lpSrcOutlineDoc, OLECLOSE_NOSAVE);
  2060. return nCount;
  2061. error:
  2062. if (lpSrcOutlineDoc) // destroy temporary document.
  2063. OutlineDoc_Close(lpSrcOutlineDoc, OLECLOSE_NOSAVE);
  2064. return 0;
  2065. }
  2066. /* ContainerDoc_QueryPasteFromData
  2067. ** -------------------------------
  2068. **
  2069. ** Check if the IDataObject* offers data in a format that we can
  2070. ** paste. The IDataObject* may come from the clipboard
  2071. ** (GetClipboard) or from a drag/drop operation.
  2072. ** In this function we look if one of the following formats is
  2073. ** offered:
  2074. ** CF_OUTLINE
  2075. ** <OLE object -- CF_EMBEDSOURCE or CF_EMBEDDEDOBJECT>
  2076. ** CF_TEXT
  2077. **
  2078. ** NOTE: fLink is specified and CF_LINKSOURCE is available then TRUE
  2079. ** is returned, else FALSE.
  2080. **
  2081. ** Returns TRUE if paste can be performed
  2082. ** FALSE if paste is not possible.
  2083. */
  2084. BOOL ContainerDoc_QueryPasteFromData(
  2085. LPCONTAINERDOC lpContainerDoc,
  2086. LPDATAOBJECT lpSrcDataObj,
  2087. BOOL fLink
  2088. )
  2089. {
  2090. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  2091. if (fLink) {
  2092. /* check if we can paste a Link to the data */
  2093. if (OleQueryLinkFromData(lpSrcDataObj) != NOERROR)
  2094. return FALSE; // linking is NOT possible
  2095. } else {
  2096. int nFmtEtc;
  2097. nFmtEtc = OleStdGetPriorityClipboardFormat(
  2098. lpSrcDataObj,
  2099. lpOleApp->m_arrPasteEntries,
  2100. lpOleApp->m_nPasteEntries
  2101. );
  2102. if (nFmtEtc < 0)
  2103. return FALSE; // there is no format we like
  2104. }
  2105. return TRUE;
  2106. }
  2107. /* ContainerDoc_PasteOleObject
  2108. ** ---------------------------
  2109. **
  2110. ** Embed or link an OLE object. the source of the data is a pointer
  2111. ** to an IDataObject. normally this lpSrcDataObj comes from the
  2112. ** clipboard after call OleGetClipboard.
  2113. **
  2114. ** dwCreateType controls what type of object will created:
  2115. ** OLECREATEFROMDATA_LINK -- OleCreateLinkFromData will be called
  2116. ** OLECREATEFROMDATA_OBJECT -- OleCreateFromData will be called
  2117. ** OLECREATEFROMDATA_STATIC -- OleCreateStaticFromData will be called
  2118. ** cfFormat controls the type of static
  2119. ** a CONTAINERLINE object is created to manage the OLE object. this
  2120. ** CONTAINERLINE is added to the ContainerDoc after line nIndex.
  2121. **
  2122. */
  2123. int ContainerDoc_PasteOleObject(
  2124. LPCONTAINERDOC lpContainerDoc,
  2125. LPDATAOBJECT lpSrcDataObj,
  2126. DWORD dwCreateType,
  2127. CLIPFORMAT cfFormat,
  2128. int nIndex,
  2129. BOOL fDisplayAsIcon,
  2130. HGLOBAL hMetaPict,
  2131. LPSIZEL lpSizelInSrc
  2132. )
  2133. {
  2134. LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
  2135. LPLINE lpLine = NULL;
  2136. HDC hDC;
  2137. int nTab = 0;
  2138. char szStgName[CWCSTORAGENAME];
  2139. LPCONTAINERLINE lpContainerLine = NULL;
  2140. ContainerDoc_GetNextStgName(lpContainerDoc, szStgName, sizeof(szStgName));
  2141. /* default the new line to have the same indent as previous line */
  2142. lpLine = LineList_GetLine(lpLL, nIndex);
  2143. if (lpLine)
  2144. nTab = Line_GetTabLevel(lpLine);
  2145. hDC = LineList_GetDC(lpLL);
  2146. lpContainerLine = ContainerLine_CreateFromData(
  2147. hDC,
  2148. nTab,
  2149. lpContainerDoc,
  2150. lpSrcDataObj,
  2151. dwCreateType,
  2152. cfFormat,
  2153. fDisplayAsIcon,
  2154. hMetaPict,
  2155. szStgName
  2156. );
  2157. LineList_ReleaseDC(lpLL, hDC);
  2158. if (! lpContainerLine)
  2159. goto error;
  2160. /* add a ContainerLine object to the document's LineList. The
  2161. ** ContainerLine manages the rectangle on the screen occupied by
  2162. ** the OLE object. later when the app is updated to support
  2163. ** extended layout, there could be more than one Line associated
  2164. ** with the OLE object.
  2165. */
  2166. LineList_AddLine(lpLL, (LPLINE)lpContainerLine, nIndex);
  2167. /* OLE2NOTE: if the source of the OLE object just pasted, passed a
  2168. ** non-zero sizel in the ObjectDescriptor, then we will try to
  2169. ** keep the object the same size as it is in the source. this
  2170. ** may be a scaled size if the object had been resized in the
  2171. ** source container. if the source did not give a valid sizel,
  2172. ** then we will retrieve the size of the object by calling
  2173. ** IViewObject2::GetExtent.
  2174. */
  2175. if (lpSizelInSrc && (lpSizelInSrc->cx != 0 || lpSizelInSrc->cy != 0)) {
  2176. ContainerLine_UpdateExtent(lpContainerLine, lpSizelInSrc);
  2177. } else
  2178. ContainerLine_UpdateExtent(lpContainerLine, NULL);
  2179. OutlineDoc_SetModified((LPOUTLINEDOC)lpContainerDoc, TRUE, TRUE, TRUE);
  2180. return 1; // one line added to LineList
  2181. error:
  2182. // NOTE: if ContainerLine_CreateFromClip failed
  2183. OutlineApp_ErrorMessage(g_lpApp, "Paste Object failed!");
  2184. return 0; // no lines added to line list
  2185. }
  2186. /* ContainerDoc_GetData
  2187. * --------------------
  2188. *
  2189. * Render data from the document on a CALLEE allocated STGMEDIUM.
  2190. * This routine is called via IDataObject::GetData.
  2191. */
  2192. HRESULT ContainerDoc_GetData (
  2193. LPCONTAINERDOC lpContainerDoc,
  2194. LPFORMATETC lpformatetc,
  2195. LPSTGMEDIUM lpMedium
  2196. )
  2197. {
  2198. LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc;
  2199. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
  2200. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  2201. LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp;
  2202. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp;
  2203. HRESULT hrErr;
  2204. SCODE sc;
  2205. // OLE2NOTE: we must set out pointer parameters to NULL
  2206. lpMedium->pUnkForRelease = NULL;
  2207. /* OLE2NOTE: we must set all out pointer parameters to NULL. */
  2208. lpMedium->tymed = TYMED_NULL;
  2209. lpMedium->pUnkForRelease = NULL; // we transfer ownership to caller
  2210. lpMedium->hGlobal = NULL;
  2211. if (lpformatetc->cfFormat == lpContainerApp->m_cfCntrOutl) {
  2212. /* OLE2NOTE: currently OLE does NOT support remoting a root
  2213. ** level IStorage (either memory or file based) as an OUT
  2214. ** parameter. thus, we can NOT support GetData for this
  2215. ** TYMED_ISTORAGE based format. the caller MUST call GetDataHere.
  2216. */
  2217. sc = DV_E_FORMATETC;
  2218. goto error;
  2219. } else if (!lpContainerDoc->m_fEmbeddedObjectAvail &&
  2220. lpformatetc->cfFormat == lpOutlineApp->m_cfOutline) {
  2221. // Verify caller asked for correct medium
  2222. if (!(lpformatetc->tymed & TYMED_HGLOBAL)) {
  2223. sc = DV_E_FORMATETC;
  2224. goto error;
  2225. }
  2226. lpMedium->hGlobal = OutlineDoc_GetOutlineData(lpOutlineDoc, NULL);
  2227. if (! lpMedium->hGlobal) {
  2228. sc = E_OUTOFMEMORY;
  2229. goto error;
  2230. }
  2231. lpMedium->tymed = TYMED_HGLOBAL;
  2232. OleDbgOut3("ContainerDoc_GetData: rendered CF_OUTLINE\r\n");
  2233. return NOERROR;
  2234. } else if (!lpContainerDoc->m_fEmbeddedObjectAvail &&
  2235. lpformatetc->cfFormat == CF_TEXT) {
  2236. // Verify caller asked for correct medium
  2237. if (!(lpformatetc->tymed & TYMED_HGLOBAL)) {
  2238. sc = DV_E_FORMATETC;
  2239. goto error;
  2240. }
  2241. lpMedium->hGlobal = OutlineDoc_GetTextData (
  2242. (LPOUTLINEDOC)lpContainerDoc,
  2243. NULL
  2244. );
  2245. if (! lpMedium->hGlobal) {
  2246. sc = E_OUTOFMEMORY;
  2247. goto error;
  2248. }
  2249. lpMedium->tymed = TYMED_HGLOBAL;
  2250. OleDbgOut3("ContainerDoc_GetData: rendered CF_TEXT\r\n");
  2251. return NOERROR;
  2252. } else if ( lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor ||
  2253. (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor &&
  2254. lpOleDoc->m_fLinkSourceAvail) ) {
  2255. // Verify caller asked for correct medium
  2256. if (!(lpformatetc->tymed & TYMED_HGLOBAL)) {
  2257. sc = DV_E_FORMATETC;
  2258. goto error;
  2259. }
  2260. lpMedium->hGlobal = OleDoc_GetObjectDescriptorData (
  2261. (LPOLEDOC)lpContainerDoc,
  2262. NULL
  2263. );
  2264. if (! lpMedium->hGlobal) {
  2265. sc = E_OUTOFMEMORY;
  2266. goto error;
  2267. }
  2268. lpMedium->tymed = TYMED_HGLOBAL;
  2269. #if defined( _DEBUG )
  2270. if (lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor)
  2271. OleDbgOut3(
  2272. "ContainerDoc_GetData: rendered CF_OBJECTDESCRIPTOR\r\n");
  2273. else
  2274. OleDbgOut3(
  2275. "ContainerDoc_GetData: rendered CF_LINKSRCDESCRIPTOR\r\n");
  2276. #endif
  2277. return NOERROR;
  2278. } else if (lpContainerDoc->m_fEmbeddedObjectAvail) {
  2279. /* OLE2NOTE: if this document contains a single OLE object
  2280. ** (ie. cfEmbeddedObject data format is available), then
  2281. ** the formats offered via our IDataObject must include
  2282. ** the formats available from the OLE object itself.
  2283. ** thus, we delegate this call to the IDataObject* of the
  2284. ** OLE object.
  2285. */
  2286. if (lpformatetc->cfFormat == lpOleApp->m_cfEmbeddedObject) {
  2287. LPPERSISTSTORAGE lpPersistStg =
  2288. (LPPERSISTSTORAGE)ContainerDoc_GetSingleOleObject(
  2289. lpContainerDoc,
  2290. &IID_IPersistStorage,
  2291. NULL
  2292. );
  2293. if (! lpPersistStg)
  2294. return ResultFromScode(DV_E_FORMATETC);
  2295. /* render CF_EMBEDDEDOBJECT by asking the object to save
  2296. ** into a temporary, DELETEONRELEASE pStg allocated by us.
  2297. */
  2298. hrErr = OleStdGetOleObjectData(
  2299. lpPersistStg,
  2300. lpformatetc,
  2301. lpMedium,
  2302. FALSE /* fUseMemory -- (use file-base stg) */
  2303. );
  2304. OleStdRelease((LPUNKNOWN)lpPersistStg);
  2305. if (hrErr != NOERROR) {
  2306. sc = GetScode(hrErr);
  2307. goto error;
  2308. }
  2309. OleDbgOut3("ContainerDoc_GetData: rendered CF_EMBEDDEDOBJECT\r\n");
  2310. return hrErr;
  2311. } else if (lpformatetc->cfFormat == CF_METAFILEPICT) {
  2312. /* OLE2NOTE: as a container which draws objects, when a single
  2313. ** OLE object is copied, we can give the Metafile picture of
  2314. ** the object.
  2315. */
  2316. LPCONTAINERLINE lpContainerLine;
  2317. LPOLEOBJECT lpOleObj;
  2318. SIZEL sizelOleObject;
  2319. // Verify caller asked for correct medium
  2320. if (!(lpformatetc->tymed & TYMED_MFPICT)) {
  2321. sc = DV_E_FORMATETC;
  2322. goto error;
  2323. }
  2324. lpOleObj = (LPOLEOBJECT)ContainerDoc_GetSingleOleObject(
  2325. lpContainerDoc,
  2326. &IID_IOleObject,
  2327. (LPCONTAINERLINE FAR*)&lpContainerLine
  2328. );
  2329. if (! lpOleObj) {
  2330. sc = E_OUTOFMEMORY; // could not load object
  2331. goto error;
  2332. }
  2333. if (lpformatetc->dwAspect & lpContainerLine->m_dwDrawAspect) {
  2334. LPLINE lpLine = (LPLINE)lpContainerLine;
  2335. /* render CF_METAFILEPICT by drawing the object into
  2336. ** a metafile DC
  2337. */
  2338. /* OLE2NOTE: Get size that object is being drawn. If the
  2339. ** object has been scaled because the user resized the
  2340. ** object, then we want to render a metafile with the
  2341. ** scaled size.
  2342. */
  2343. sizelOleObject.cx = lpLine->m_nWidthInHimetric;
  2344. sizelOleObject.cy = lpLine->m_nHeightInHimetric;
  2345. lpMedium->hGlobal = OleStdGetMetafilePictFromOleObject(
  2346. lpOleObj,
  2347. lpContainerLine->m_dwDrawAspect,
  2348. (LPSIZEL)&sizelOleObject,
  2349. lpformatetc->ptd
  2350. );
  2351. OleStdRelease((LPUNKNOWN)lpOleObj);
  2352. if (! lpMedium->hGlobal) {
  2353. sc = E_OUTOFMEMORY;
  2354. goto error;
  2355. }
  2356. lpMedium->tymed = TYMED_MFPICT;
  2357. OleDbgOut3("ContainerDoc_GetData: rendered CF_METAFILEPICT\r\n");
  2358. return NOERROR;
  2359. } else {
  2360. // improper aspect requested
  2361. OleStdRelease((LPUNKNOWN)lpOleObj);
  2362. return ResultFromScode(DV_E_FORMATETC);
  2363. }
  2364. } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) {
  2365. if (lpOleDoc->m_fLinkSourceAvail) {
  2366. LPMONIKER lpmk;
  2367. lpmk = ContainerLine_GetFullMoniker(
  2368. lpContainerDoc->m_lpSrcContainerLine,
  2369. GETMONIKER_FORCEASSIGN
  2370. );
  2371. if (lpmk) {
  2372. hrErr = OleStdGetLinkSourceData(
  2373. lpmk,
  2374. &lpContainerDoc->m_clsidOleObjCopied,
  2375. lpformatetc,
  2376. lpMedium
  2377. );
  2378. OleStdRelease((LPUNKNOWN)lpmk);
  2379. if (hrErr != NOERROR) {
  2380. sc = GetScode(hrErr);
  2381. goto error;
  2382. }
  2383. OleDbgOut3("ContainerDoc_GetData: rendered CF_LINKSOURCE\r\n");
  2384. return hrErr;
  2385. } else {
  2386. sc = DV_E_FORMATETC;
  2387. goto error;
  2388. }
  2389. } else {
  2390. sc = DV_E_FORMATETC;
  2391. goto error;
  2392. }
  2393. }
  2394. #if defined( OPTIONAL_ADVANCED_DATA_TRANSFER )
  2395. /* OLE2NOTE: optionally, a container that wants to have a
  2396. ** potentially richer data transfer, can enumerate the data
  2397. ** formats from the OLE object's cache and offer them too. if
  2398. ** the object has a special handler, then it might be able to
  2399. ** render additional data formats. in this case, the
  2400. ** container must delegate the GetData call to the object if
  2401. ** it does not directly support the format.
  2402. **
  2403. ** CNTROUTL does NOT enumerate the cache; it implements the
  2404. ** simpler strategy of offering a static list of formats.
  2405. ** thus the delegation is NOT required.
  2406. */
  2407. else {
  2408. /* OLE2NOTE: we delegate this call to the IDataObject* of the
  2409. ** OLE object.
  2410. */
  2411. LPDATAOBJECT lpDataObj;
  2412. lpDataObj = (LPDATAOBJECT)ContainerDoc_GetSingleOleObject(
  2413. lpContainerDoc,
  2414. &IID_IDataObject,
  2415. NULL
  2416. );
  2417. if (! lpDataObj) {
  2418. sc = DV_E_FORMATETC;
  2419. goto error;
  2420. }
  2421. OLEDBG_BEGIN2("ContainerDoc_GetData: delegate to OLE obj\r\n")
  2422. hrErr=lpDataObj->lpVtbl->GetData(lpDataObj,lpformatetc,lpMedium);
  2423. OLEDBG_END2
  2424. OleStdRelease((LPUNKNOWN)lpDataObj);
  2425. return hrErr;
  2426. }
  2427. #endif // ! OPTIONAL_ADVANCED_DATA_TRANSFER
  2428. }
  2429. // if we get here then we do NOT support the requested format
  2430. sc = DV_E_FORMATETC;
  2431. error:
  2432. return ResultFromScode(sc);
  2433. }
  2434. /* ContainerDoc_GetDataHere
  2435. * ------------------------
  2436. *
  2437. * Render data from the document on a CALLER allocated STGMEDIUM.
  2438. * This routine is called via IDataObject::GetDataHere.
  2439. */
  2440. HRESULT ContainerDoc_GetDataHere (
  2441. LPCONTAINERDOC lpContainerDoc,
  2442. LPFORMATETC lpformatetc,
  2443. LPSTGMEDIUM lpMedium
  2444. )
  2445. {
  2446. LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc;
  2447. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
  2448. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  2449. LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp;
  2450. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp;
  2451. HRESULT hrErr;
  2452. // OLE2NOTE: lpMedium is an IN parameter. we should NOT set
  2453. // lpMedium->pUnkForRelease to NULL
  2454. // we only support IStorage medium
  2455. if (lpformatetc->cfFormat == lpContainerApp->m_cfCntrOutl) {
  2456. if (!(lpformatetc->tymed & TYMED_ISTORAGE))
  2457. return ResultFromScode(DV_E_FORMATETC);
  2458. if (lpMedium->tymed == TYMED_ISTORAGE) {
  2459. /* Caller has allocated the storage. we must copy all of our
  2460. ** data into his storage.
  2461. */
  2462. /* OLE2NOTE: we must be sure to write our class ID into our
  2463. ** storage. this information is used by OLE to determine the
  2464. ** class of the data stored in our storage.
  2465. */
  2466. if((hrErr=WriteClassStg(lpMedium->pstg,&CLSID_APP)) != NOERROR)
  2467. return hrErr;
  2468. OutlineDoc_SaveSelToStg(
  2469. (LPOUTLINEDOC)lpContainerDoc,
  2470. NULL, /* entire doc */
  2471. lpContainerApp->m_cfCntrOutl,
  2472. lpMedium->pstg,
  2473. FALSE, /* fSameAsLoad */
  2474. FALSE /* fRemember */
  2475. );
  2476. OleStdCommitStorage(lpMedium->pstg);
  2477. OleDbgOut3("ContainerDoc_GetDataHere: rendered CF_CNTROUTL\r\n");
  2478. return NOERROR;
  2479. } else {
  2480. // we only support IStorage medium
  2481. return ResultFromScode(DV_E_FORMATETC);
  2482. }
  2483. } else if (lpContainerDoc->m_fEmbeddedObjectAvail) {
  2484. /* OLE2NOTE: if this document contains a single OLE object
  2485. ** (ie. cfEmbeddedObject data format is available), then
  2486. ** the formats offered via our IDataObject must include
  2487. ** CF_EMBEDDEDOBJECT and the formats available from the OLE
  2488. ** object itself.
  2489. */
  2490. if (lpformatetc->cfFormat == lpOleApp->m_cfEmbeddedObject) {
  2491. LPPERSISTSTORAGE lpPersistStg =
  2492. (LPPERSISTSTORAGE)ContainerDoc_GetSingleOleObject(
  2493. lpContainerDoc,
  2494. &IID_IPersistStorage,
  2495. NULL
  2496. );
  2497. if (! lpPersistStg) {
  2498. return ResultFromScode(E_OUTOFMEMORY);
  2499. }
  2500. /* render CF_EMBEDDEDOBJECT by asking the object to save
  2501. ** into the IStorage allocated by the caller.
  2502. */
  2503. hrErr = OleStdGetOleObjectData(
  2504. lpPersistStg,
  2505. lpformatetc,
  2506. lpMedium,
  2507. FALSE /* fUseMemory -- N/A */
  2508. );
  2509. OleStdRelease((LPUNKNOWN)lpPersistStg);
  2510. if (hrErr != NOERROR) {
  2511. return hrErr;
  2512. }
  2513. OleDbgOut3("ContainerDoc_GetDataHere: rendered CF_EMBEDDEDOBJECT\r\n");
  2514. return hrErr;
  2515. } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) {
  2516. if (lpOleDoc->m_fLinkSourceAvail) {
  2517. LPMONIKER lpmk;
  2518. lpmk = ContainerLine_GetFullMoniker(
  2519. lpContainerDoc->m_lpSrcContainerLine,
  2520. GETMONIKER_FORCEASSIGN
  2521. );
  2522. if (lpmk) {
  2523. hrErr = OleStdGetLinkSourceData(
  2524. lpmk,
  2525. &lpContainerDoc->m_clsidOleObjCopied,
  2526. lpformatetc,
  2527. lpMedium
  2528. );
  2529. OleStdRelease((LPUNKNOWN)lpmk);
  2530. OleDbgOut3("ContainerDoc_GetDataHere: rendered CF_LINKSOURCE\r\n");
  2531. return hrErr;
  2532. } else {
  2533. return ResultFromScode(E_FAIL);
  2534. }
  2535. } else {
  2536. return ResultFromScode(DV_E_FORMATETC);
  2537. }
  2538. } else {
  2539. #if !defined( OPTIONAL_ADVANCED_DATA_TRANSFER )
  2540. return ResultFromScode(DV_E_FORMATETC);
  2541. #endif
  2542. #if defined( OPTIONAL_ADVANCED_DATA_TRANSFER )
  2543. /* OLE2NOTE: optionally, a container that wants to have a
  2544. ** potentially richer data transfer, can enumerate the data
  2545. ** formats from the OLE object's cache and offer them too. if
  2546. ** the object has a special handler, then it might be able to
  2547. ** render additional data formats. in this case, the
  2548. ** container must delegate the GetData call to the object if
  2549. ** it does not directly support the format.
  2550. **
  2551. ** CNTROUTL does NOT enumerate the cache; it implements the
  2552. ** simpler strategy of offering a static list of formats.
  2553. ** thus the delegation is NOT required.
  2554. */
  2555. /* OLE2NOTE: we delegate this call to the IDataObject* of the
  2556. ** OLE object.
  2557. */
  2558. LPDATAOBJECT lpDataObj;
  2559. lpDataObj = (LPDATAOBJECT)ContainerDoc_GetSingleOleObject(
  2560. lpContainerDoc,
  2561. &IID_IDataObject,
  2562. NULL
  2563. );
  2564. if (! lpDataObj)
  2565. return ResultFromScode(DV_E_FORMATETC);
  2566. OLEDBG_BEGIN2("ContainerDoc_GetDataHere: delegate to OLE obj\r\n")
  2567. hrErr = lpDataObj->lpVtbl->GetDataHere(
  2568. lpDataObj,
  2569. lpformatetc,
  2570. lpMedium
  2571. );
  2572. OLEDBG_END2
  2573. OleStdRelease((LPUNKNOWN)lpDataObj);
  2574. return hrErr;
  2575. #endif // OPTIONAL_ADVANCED_DATA_TRANSFER
  2576. }
  2577. } else {
  2578. return ResultFromScode(DV_E_FORMATETC);
  2579. }
  2580. }
  2581. /* ContainerDoc_QueryGetData
  2582. * -------------------------
  2583. *
  2584. * Answer if a particular data format is supported via GetData/GetDataHere.
  2585. * This routine is called via IDataObject::QueryGetData.
  2586. */
  2587. HRESULT ContainerDoc_QueryGetData (
  2588. LPCONTAINERDOC lpContainerDoc,
  2589. LPFORMATETC lpformatetc
  2590. )
  2591. {
  2592. LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc;
  2593. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
  2594. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  2595. LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp;
  2596. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp;
  2597. LPDATAOBJECT lpDataObj = NULL;
  2598. LPCONTAINERLINE lpContainerLine = NULL;
  2599. SCODE sc;
  2600. HRESULT hrErr;
  2601. if (lpContainerDoc->m_fEmbeddedObjectAvail) {
  2602. lpDataObj = (LPDATAOBJECT)ContainerDoc_GetSingleOleObject(
  2603. lpContainerDoc,
  2604. &IID_IDataObject,
  2605. (LPCONTAINERLINE FAR*)&lpContainerLine
  2606. );
  2607. }
  2608. /* Caller is querying if we support certain format but does not
  2609. ** want any data actually returned.
  2610. */
  2611. if (lpformatetc->cfFormat == lpContainerApp->m_cfCntrOutl) {
  2612. // we only support ISTORAGE medium
  2613. sc = GetScode( OleStdQueryFormatMedium(lpformatetc, TYMED_ISTORAGE) );
  2614. } else if (lpformatetc->cfFormat == lpOleApp->m_cfEmbeddedObject &&
  2615. lpContainerDoc->m_fEmbeddedObjectAvail ) {
  2616. sc = GetScode( OleStdQueryOleObjectData(lpformatetc) );
  2617. } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource &&
  2618. lpOleDoc->m_fLinkSourceAvail) {
  2619. sc = GetScode( OleStdQueryLinkSourceData(lpformatetc) );
  2620. // CF_TEXT and CF_OUTLINE are NOT supported when single object is copied
  2621. } else if (!lpContainerDoc->m_fEmbeddedObjectAvail &&
  2622. (lpformatetc->cfFormat == (lpOutlineApp)->m_cfOutline ||
  2623. lpformatetc->cfFormat == CF_TEXT) ) {
  2624. // we only support HGLOBAL medium
  2625. sc = GetScode( OleStdQueryFormatMedium(lpformatetc, TYMED_HGLOBAL) );
  2626. } else if ( lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor ||
  2627. (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor &&
  2628. lpOleDoc->m_fLinkSourceAvail) ) {
  2629. sc = GetScode( OleStdQueryObjectDescriptorData(lpformatetc) );
  2630. } else if (lpformatetc->cfFormat == CF_METAFILEPICT &&
  2631. lpContainerDoc->m_fEmbeddedObjectAvail && lpContainerLine &&
  2632. (lpformatetc->dwAspect & lpContainerLine->m_dwDrawAspect)) {
  2633. /* OLE2NOTE: as a container which draws objects, when a single
  2634. ** OLE object is copied, we can give the Metafile picture of
  2635. ** the object.
  2636. */
  2637. // we only support MFPICT medium
  2638. sc = GetScode( OleStdQueryFormatMedium(lpformatetc, TYMED_MFPICT) );
  2639. } else if (lpDataObj) {
  2640. /* OLE2NOTE: if this document contains a single OLE object
  2641. ** (ie. cfEmbeddedObject data format is available), then
  2642. ** the formats offered via our IDataObject must include
  2643. ** the formats available from the OLE object itself.
  2644. ** thus we delegate this call to the IDataObject* of the
  2645. ** OLE object.
  2646. */
  2647. OLEDBG_BEGIN2("ContainerDoc_QueryGetData: delegate to OLE obj\r\n")
  2648. hrErr = lpDataObj->lpVtbl->QueryGetData(lpDataObj, lpformatetc);
  2649. OLEDBG_END2
  2650. sc = GetScode(hrErr);
  2651. } else {
  2652. sc = DV_E_FORMATETC;
  2653. }
  2654. if (lpDataObj)
  2655. OleStdRelease((LPUNKNOWN)lpDataObj);
  2656. return ResultFromScode(sc);
  2657. }
  2658. /* ContainerDoc_SetData
  2659. * --------------------
  2660. *
  2661. * Set (modify) data of the document.
  2662. * This routine is called via IDataObject::SetData.
  2663. */
  2664. HRESULT ContainerDoc_SetData (
  2665. LPCONTAINERDOC lpContainerDoc,
  2666. LPFORMATETC lpformatetc,
  2667. LPSTGMEDIUM lpmedium,
  2668. BOOL fRelease
  2669. )
  2670. {
  2671. /* in the container version of Outline, only DataTransferDoc's support
  2672. ** IDataObject interface; the user documents do not support
  2673. ** IDataObject. DataTransferDoc's do not accept SetData calls.
  2674. */
  2675. return ResultFromScode(DV_E_FORMATETC);
  2676. }
  2677. /* ContainerDoc_EnumFormatEtc
  2678. * --------------------------
  2679. *
  2680. * Return an enumerator which enumerates the data accepted/offered by
  2681. * the document.
  2682. * This routine is called via IDataObject::SetData.
  2683. */
  2684. HRESULT ContainerDoc_EnumFormatEtc(
  2685. LPCONTAINERDOC lpContainerDoc,
  2686. DWORD dwDirection,
  2687. LPENUMFORMATETC FAR* lplpenumFormatEtc
  2688. )
  2689. {
  2690. LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc;
  2691. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
  2692. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  2693. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp;
  2694. int nActualFmts;
  2695. int i;
  2696. SCODE sc = S_OK;
  2697. /* the Container-Only version of Outline does NOT offer
  2698. ** IDataObject interface from its User documents.
  2699. */
  2700. if (! lpOutlineDoc->m_fDataTransferDoc)
  2701. return ResultFromScode(E_FAIL);
  2702. if (dwDirection == DATADIR_GET) {
  2703. if (lpContainerDoc->m_fEmbeddedObjectAvail) {
  2704. /* OLE2NOTE: if this document contains a single OLE object
  2705. ** (ie. cfEmbeddedObject data format is available), then
  2706. ** the formats offered via our enumerator must include
  2707. ** the formats available from the OLE object itself. we
  2708. ** have previously set up a special array of FORMATETC's
  2709. ** in OutlineDoc_CreateDataTransferDoc routine which includes
  2710. ** the combination of data we offer directly and data
  2711. ** offered by the OLE object.
  2712. */
  2713. /* If the document does not have a Moniker, then exclude
  2714. ** CF_LINKSOURCE CF_LINKSRCDESCRIPTOR from the list of
  2715. ** formats available. these formats are deliberately
  2716. ** listed last in the array of possible "Get" formats.
  2717. */
  2718. nActualFmts = lpContainerApp->m_nSingleObjGetFmts;
  2719. if (! lpOleDoc->m_fLinkSourceAvail)
  2720. nActualFmts -= 2;
  2721. // set correct dwDrawAspect for METAFILEPICT of object copied
  2722. for (i = 0; i < nActualFmts; i++) {
  2723. if (lpContainerApp->m_arrSingleObjGetFmts[i].cfFormat ==
  2724. CF_METAFILEPICT) {
  2725. lpContainerApp->m_arrSingleObjGetFmts[i].dwAspect =
  2726. lpContainerDoc->m_dwAspectOleObjCopied;
  2727. break; // DONE
  2728. }
  2729. }
  2730. *lplpenumFormatEtc = OleStdEnumFmtEtc_Create(
  2731. nActualFmts, lpContainerApp->m_arrSingleObjGetFmts);
  2732. if (*lplpenumFormatEtc == NULL)
  2733. sc = E_OUTOFMEMORY;
  2734. } else {
  2735. /* This document does NOT offer cfEmbeddedObject,
  2736. ** therefore we can simply enumerate the
  2737. ** static list of formats that we handle directly.
  2738. */
  2739. *lplpenumFormatEtc = OleStdEnumFmtEtc_Create(
  2740. lpOleApp->m_nDocGetFmts, lpOleApp->m_arrDocGetFmts);
  2741. if (*lplpenumFormatEtc == NULL)
  2742. sc = E_OUTOFMEMORY;
  2743. }
  2744. } else if (dwDirection == DATADIR_SET) {
  2745. /* OLE2NOTE: a document that is used to transfer data
  2746. ** (either via the clipboard or drag/drop does NOT
  2747. ** accept SetData on ANY format!
  2748. */
  2749. sc = E_NOTIMPL;
  2750. } else {
  2751. sc = E_NOTIMPL;
  2752. }
  2753. return ResultFromScode(sc);
  2754. }
  2755. #if defined( OPTIONAL_ADVANCED_DATA_TRANSFER )
  2756. /* OLE2NOTE: optionally, a container that wants to have a
  2757. ** potentially richer data transfer, can enumerate the data
  2758. ** formats from the OLE object's cache and offer them too. if
  2759. ** the object has a special handler, then it might be able to
  2760. ** render additional data formats.
  2761. **
  2762. ** CNTROUTL does NOT enumerate the cache; it implements the simpler
  2763. ** strategy of offering a static list of formats. the following
  2764. ** function is included in order to illustrates how enumerating the
  2765. ** cache could be done. CNTROUTL does NOT call this function.
  2766. **
  2767. */
  2768. /* ContainerDoc_SetupDocGetFmts
  2769. ** ----------------------------
  2770. ** Setup the combined list of formats that this data transfer
  2771. ** ContainerDoc which contains a single OLE object should offer.
  2772. **
  2773. ** OLE2NOTE: The list of formats that should be offered when a
  2774. ** single OLE object is being transfered include the following:
  2775. ** * any formats the container app wants to give
  2776. ** * CF_EMBEDDEDOBJECT
  2777. ** * CF_METAFILEPICT
  2778. ** * any formats that the OLE object's cache can offer directly
  2779. **
  2780. ** We will offer the following formats in the order given:
  2781. ** 1. CF_CNTROUTL
  2782. ** 2. CF_EMBEDDEDOBJECT
  2783. ** 3. CF_OBJECTDESCRIPTOR
  2784. ** 4. CF_METAFILEPICT
  2785. ** 5. <data formats from OLE object's cache>
  2786. ** 6. CF_LINKSOURCE
  2787. ** 7. CF_LINKSRCDESCRIPTOR
  2788. */
  2789. BOOL ContainerDoc_SetupDocGetFmts(
  2790. LPCONTAINERDOC lpContainerDoc,
  2791. LPCONTAINERLINE lpContainerLine
  2792. )
  2793. {
  2794. LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc;
  2795. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  2796. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  2797. LPOLECACHE lpOleCache;
  2798. HRESULT hrErr;
  2799. STATDATA StatData;
  2800. LPENUMSTATDATA lpEnumStatData = NULL;
  2801. LPFORMATETC lparrDocGetFmts = NULL;
  2802. UINT nOleObjFmts = 0;
  2803. UINT nTotalFmts;
  2804. UINT i;
  2805. UINT iFmt;
  2806. lpOleCache = (LPOLECACHE)OleStdQueryInterface(
  2807. (LPUNKNOWN)lpContainerLine->m_lpOleObj,
  2808. &IID_IOleCache
  2809. );
  2810. if (lpOleCache) {
  2811. OLEDBG_BEGIN2("IOleCache::EnumCache called\r\n")
  2812. hrErr = lpOleCache->lpVtbl->EnumCache(
  2813. lpOleCache,
  2814. (LPENUMSTATDATA FAR*)&lpEnumStatData
  2815. );
  2816. OLEDBG_END2
  2817. }
  2818. if (lpEnumStatData) {
  2819. /* Cache enumerator is available. count the number of
  2820. ** formats that the OLE object's cache offers.
  2821. */
  2822. while(lpEnumStatData->lpVtbl->Next(
  2823. lpEnumStatData,
  2824. 1,
  2825. (LPSTATDATA)&StatData,
  2826. NULL) == NOERROR) {
  2827. nOleObjFmts++;
  2828. // OLE2NOTE: we MUST free the TargetDevice
  2829. OleStdFree(StatData.formatetc.ptd);
  2830. }
  2831. lpEnumStatData->lpVtbl->Reset(lpEnumStatData); // reset for next loop
  2832. }
  2833. /* OLE2NOTE: the maximum total number of formats that our IDataObject
  2834. ** could offer equals the sum of the following:
  2835. ** n offered by the OLE object's cache
  2836. ** + n normally offered by our app
  2837. ** + 1 CF_EMBEDDEDOBJECT
  2838. ** + 1 CF_METAFILEPICT
  2839. ** + 1 CF_LINKSOURCE
  2840. ** + 1 CF_LINKSRCDESCRIPTOR
  2841. ** the actual number of formats that we can offer could be less
  2842. ** than this total if there is any clash between the formats
  2843. ** that we offer directly and those offered by the cache. if
  2844. ** there is a clash, the container's rendering overrides that of
  2845. ** the object. eg.: as a container transfering an OLE object we
  2846. ** should directly offer CF_METAFILEPICT to guarantee that this
  2847. ** format is always available. thus, if the cache offers
  2848. ** CF_METAFILEPICT then it is skipped.
  2849. */
  2850. nTotalFmts = nOleObjFmts + lpOleApp->m_nDocGetFmts + 4;
  2851. lparrDocGetFmts = (LPFORMATETC)New (nTotalFmts * sizeof(FORMATETC));
  2852. OleDbgAssertSz(lparrDocGetFmts != NULL,"Error allocating arrDocGetFmts");
  2853. if (lparrDocGetFmts == NULL)
  2854. return FALSE;
  2855. for (i = 0, iFmt = 0; i < lpOleApp->m_nDocGetFmts; i++) {
  2856. _fmemcpy((LPFORMATETC)&lparrDocGetFmts[iFmt++],
  2857. (LPFORMATETC)&lpOleApp->m_arrDocGetFmts[i],
  2858. sizeof(FORMATETC)
  2859. );
  2860. if (lpOleApp->m_arrDocGetFmts[i].cfFormat ==
  2861. lpContainerApp->m_cfCntrOutl) {
  2862. /* insert CF_EMBEDDEDOBJECT, CF_METAFILEPICT, and formats
  2863. ** available from the OLE object's cache following
  2864. ** CF_CNTROUTL.
  2865. */
  2866. lparrDocGetFmts[iFmt].cfFormat = lpOleApp->m_cfEmbeddedObject;
  2867. lparrDocGetFmts[iFmt].ptd = NULL;
  2868. lparrDocGetFmts[iFmt].dwAspect = DVASPECT_CONTENT;
  2869. lparrDocGetFmts[iFmt].tymed = TYMED_ISTORAGE;
  2870. lparrDocGetFmts[iFmt].lindex = -1;
  2871. iFmt++;
  2872. lparrDocGetFmts[iFmt].cfFormat = CF_METAFILEPICT;
  2873. lparrDocGetFmts[iFmt].ptd = NULL;
  2874. lparrDocGetFmts[iFmt].dwAspect = lpContainerLine->m_dwDrawAspect;
  2875. lparrDocGetFmts[iFmt].tymed = TYMED_MFPICT;
  2876. lparrDocGetFmts[iFmt].lindex = -1;
  2877. iFmt++;
  2878. if (lpEnumStatData) {
  2879. /* Cache enumerator is available. enumerate all of
  2880. ** the formats that the OLE object's cache offers.
  2881. */
  2882. while(lpEnumStatData->lpVtbl->Next(
  2883. lpEnumStatData,
  2884. 1,
  2885. (LPSTATDATA)&StatData,
  2886. NULL) == NOERROR) {
  2887. /* check if the format clashes with one of our fmts */
  2888. if (StatData.formatetc.cfFormat != CF_METAFILEPICT
  2889. && ! OleStdIsDuplicateFormat(
  2890. (LPFORMATETC)&StatData.formatetc,
  2891. lpOleApp->m_arrDocGetFmts,
  2892. lpOleApp->m_nDocGetFmts)) {
  2893. OleStdCopyFormatEtc(
  2894. &(lparrDocGetFmts[iFmt]),&StatData.formatetc);
  2895. iFmt++;
  2896. }
  2897. // OLE2NOTE: we MUST free the TargetDevice
  2898. OleStdFree(StatData.formatetc.ptd);
  2899. }
  2900. }
  2901. }
  2902. }
  2903. if (lpOleCache)
  2904. OleStdRelease((LPUNKNOWN)lpOleCache);
  2905. /* append CF_LINKSOURCE format */
  2906. lparrDocGetFmts[iFmt].cfFormat = lpOleApp->m_cfLinkSource;
  2907. lparrDocGetFmts[iFmt].ptd = NULL;
  2908. lparrDocGetFmts[iFmt].dwAspect = DVASPECT_CONTENT;
  2909. lparrDocGetFmts[iFmt].tymed = TYMED_ISTREAM;
  2910. lparrDocGetFmts[iFmt].lindex = -1;
  2911. iFmt++;
  2912. /* append CF_LINKSRCDESCRIPTOR format */
  2913. lparrDocGetFmts[iFmt].cfFormat = lpOleApp->m_cfLinkSrcDescriptor;
  2914. lparrDocGetFmts[iFmt].ptd = NULL;
  2915. lparrDocGetFmts[iFmt].dwAspect = DVASPECT_CONTENT;
  2916. lparrDocGetFmts[iFmt].tymed = TYMED_HGLOBAL;
  2917. lparrDocGetFmts[iFmt].lindex = -1;
  2918. iFmt++;
  2919. lpContainerDoc->m_lparrDocGetFmts = lparrDocGetFmts;
  2920. lpContainerDoc->m_nDocGetFmts = iFmt;
  2921. if (lpEnumStatData)
  2922. OleStdVerifyRelease(
  2923. (LPUNKNOWN)lpEnumStatData,
  2924. "Cache enumerator not released properly"
  2925. );
  2926. return TRUE;
  2927. }
  2928. #endif // OPTIONAL_ADVANCED_DATA_TRANSFER
  2929. #endif // OLE_CNTR