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