Annotation of mstools/ole20/samples/outline/clipbrd.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.