Annotation of mstools/ole20/samples/outline/cntrbase.c, revision 1.1.1.1

1.1       root        1: /*************************************************************************
                      2: **
                      3: **    OLE 2 Container Sample Code
                      4: **
                      5: **    cntrbase.c
                      6: **    
                      7: **    This file contains all interfaces, methods and related support
                      8: **    functions for the basic OLE Container application. The
                      9: **    basic OLE Container application supports being a container for
                     10: **    embedded and linked objects.
                     11: **    The basic Container application includes the following
                     12: **    implementation objects: 
                     13: **    
                     14: **    ContainerDoc Object
                     15: **      no required interfaces for basic functionality
                     16: **      (see linking.c for linking related support)
                     17: **      (see clipbrd.c for clipboard related support)
                     18: **      (see dragdrop.c for drag/drop related support)
                     19: **    
                     20: **    ContainerLine Object
                     21: **    (see cntrline.c for all ContainerLine functions and interfaces)
                     22: **      exposed interfaces:
                     23: **          IOleClientSite
                     24: **          IAdviseSink
                     25: **
                     26: **    (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
                     27: **
                     28: *************************************************************************/
                     29: 
                     30: #include "outline.h"
                     31: #include <geticon.h>    // for OleStdGetUserTypeOfClass
                     32: 
                     33: 
                     34: OLEDBGDATA
                     35: 
                     36: 
                     37: extern LPOUTLINEAPP             g_lpApp;
                     38: extern IOleUILinkContainerVtbl  g_CntrDoc_OleUILinkContainerVtbl;
                     39: 
                     40: 
                     41: // REVIEW: should use string resource for messages
                     42: char ErrMsgShowObj[] = "Could not show object server!";
                     43: char ErrMsgInsertObj[] = "Insert Object failed!";
                     44: char ErrMsgConvertObj[] = "Convert Object failed!";
                     45: char ErrMsgCantConvert[] = "Unable to convert the selection!";
                     46: char ErrMsgActivateAsObj[] = "Activate As Object failed!";
                     47: 
                     48: extern char ErrMsgSaving[];
                     49: extern char ErrMsgOpening[];
                     50: 
                     51: 
                     52: /* ContainerDoc_Init
                     53:  * -----------------
                     54:  *
                     55:  *  Initialize the fields of a new ContainerDoc object. The doc is initially
                     56:  *  not associated with a file or an (Untitled) document. This function sets
                     57:  *  the docInitType to DOCTYPE_UNKNOWN. After calling this function the
                     58:  *  caller should call:
                     59:  *      1.) Doc_InitNewFile to set the ContainerDoc to (Untitled)
                     60:  *      2.) Doc_LoadFromFile to associate the ContainerDoc with a file.
                     61:  *  This function creates a new window for the document.
                     62:  *
                     63:  *  NOTE: the window is initially created with a NIL size. it must be
                     64:  *        sized and positioned by the caller. also the document is initially
                     65:  *        created invisible. the caller must call Doc_ShowWindow
                     66:  *        after sizing it to make the document window visible.
                     67:  */
                     68: BOOL ContainerDoc_Init(LPCONTAINERDOC lpContainerDoc, BOOL fDataTransferDoc)
                     69: {
                     70:     LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
                     71:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
                     72: 
                     73:     lpOutlineDoc->m_cfSaveFormat             = lpContainerApp->m_cfCntrOutl;
                     74:     lpContainerDoc->m_nNextObjNo            = 0L;
                     75:     lpContainerDoc->m_lpStg                 = NULL;
                     76:     lpContainerDoc->m_lpNewStg              = NULL;
                     77:     lpContainerDoc->m_fEmbeddedObjectAvail  = FALSE;
                     78:     lpContainerDoc->m_clsidOleObjCopied     = CLSID_NULL;
                     79:     lpContainerDoc->m_dwAspectOleObjCopied  = DVASPECT_CONTENT;
                     80:     lpContainerDoc->m_lpSrcContainerLine    = NULL;
                     81:     lpContainerDoc->m_fShowObject           = TRUE;
                     82: 
                     83: #if defined( INPLACE_CNTR )
                     84:     lpContainerDoc->m_lpLastIpActiveLine    = NULL;
                     85:     lpContainerDoc->m_lpLastUIActiveLine    = NULL;
                     86:     lpContainerDoc->m_hwndUIActiveObj       = NULL;
                     87:     lpContainerDoc->m_fAddMyUI              = TRUE; // UI needs to be added
                     88:     lpContainerDoc->m_cIPActiveObjects         = 0;    
                     89:        
                     90: #if defined( INPLACE_CNTRSVR )
                     91:     lpContainerDoc->m_lpTopIPFrame          =
                     92:                     (LPOLEINPLACEUIWINDOW)&lpContainerDoc->m_OleInPlaceFrame;
                     93:     lpContainerDoc->m_lpTopIPDoc            =
                     94:                     (LPOLEINPLACEUIWINDOW)&lpContainerDoc->m_OleInPlaceDoc;
                     95:     lpContainerDoc->m_hSharedMenu           = NULL;
                     96:     lpContainerDoc->m_hOleMenu              = NULL;
                     97: 
                     98: #endif  // INPLACE_CNTRSVR
                     99: #endif  // INPLACE_CNTR
                    100: 
                    101:     INIT_INTERFACEIMPL(
                    102:             &lpContainerDoc->m_OleUILinkContainer,
                    103:             &g_CntrDoc_OleUILinkContainerVtbl,
                    104:             lpContainerDoc
                    105:     );
                    106: 
                    107:     return TRUE;
                    108: }
                    109: 
                    110: 
                    111: /* ContainerDoc_GetNextLink
                    112:  * ------------------------
                    113:  *
                    114:  *  Update all links in the document. A dialog box will be popped up showing
                    115:  *     the progress of the update and allow the user to quit by pushing the
                    116:  *  stop button
                    117:  */
                    118: LPCONTAINERLINE ContainerDoc_GetNextLink(
                    119:                LPCONTAINERDOC lpContainerDoc, 
                    120:                LPCONTAINERLINE lpContainerLine
                    121: )
                    122: {
                    123:     LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                    124:     DWORD dwNextLink = 0;
                    125:     LPLINE lpLine;
                    126:     static int nIndex = 0;
                    127:        
                    128:        if (lpContainerLine==NULL)
                    129:                nIndex = 0;
                    130: 
                    131:     for ( ; nIndex < lpLL->m_nNumLines; nIndex++) {
                    132:         lpLine = LineList_GetLine(lpLL, nIndex);
                    133: 
                    134:         if (lpLine
                    135:             && (Line_GetLineType(lpLine) == CONTAINERLINETYPE)
                    136:             && ContainerLine_IsOleLink((LPCONTAINERLINE)lpLine)) {
                    137:                        
                    138:                        nIndex++;
                    139:                        return (LPCONTAINERLINE)lpLine;
                    140:                }
                    141:        }
                    142: 
                    143:     return NULL;
                    144: }
                    145: 
                    146: 
                    147: 
                    148: /* ContainerDoc_UpdateLinks
                    149:  * ------------------------
                    150:  *
                    151:  *  Update all links in the document. A dialog box will be popped up showing
                    152:  *     the progress of the update and allow the user to quit by pushing the
                    153:  *  stop button
                    154:  */
                    155: void ContainerDoc_UpdateLinks(LPCONTAINERDOC lpContainerDoc)
                    156: {
                    157:        int                             cLinks;
                    158:        HWND                    hwndDoc = ((LPOUTLINEDOC)lpContainerDoc)->m_hWndDoc;
                    159:        HCURSOR                 hCursor;
                    160:        LPCONTAINERLINE lpContainerLine = NULL;
                    161:        HRESULT                 hrErr;
                    162:        DWORD                   dwUpdateOpt;
                    163:        
                    164:        hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
                    165:        
                    166:        /* get total number of automatic links */
                    167:        cLinks = 0;
                    168:        while (lpContainerLine = ContainerDoc_GetNextLink(
                    169:                                                                        lpContainerDoc, 
                    170:                                                                        lpContainerLine)) {
                    171:                hrErr = CntrDoc_LinkCont_GetLinkUpdateOptions(
                    172:                                (LPOLEUILINKCONTAINER)&lpContainerDoc->m_OleUILinkContainer,
                    173:                                (DWORD)lpContainerLine,
                    174:                                (LPDWORD)&dwUpdateOpt
                    175:                );
                    176:                if (hrErr == NOERROR) {
                    177:                        if (dwUpdateOpt==OLEUPDATE_ALWAYS)
                    178:                                cLinks++;
                    179:                }
                    180:                else
                    181:                        OleDbgOutHResult("IOleUILinkContainer::GetLinkUpdateOptions returned",hrErr);
                    182:                
                    183:        }
                    184:        
                    185:     SetCursor(hCursor);
                    186:        
                    187:        if ((cLinks > 0) && !OleUIUpdateLinks(
                    188:                        (LPOLEUILINKCONTAINER)&lpContainerDoc->m_OleUILinkContainer, 
                    189:                        hwndDoc, 
                    190:                        (LPSTR)APPNAME, 
                    191:                        cLinks)) {
                    192:                if (ID_PU_LINKS == OleUIPromptUser(
                    193:                                IDD_CANNOTUPDATELINK, 
                    194:                                hwndDoc,
                    195:                                (LPSTR)APPNAME)) {
                    196:                        ContainerDoc_EditLinksCommand(lpContainerDoc);
                    197:                }
                    198:        }
                    199: }
                    200: 
                    201:        
                    202: 
                    203: /* ContainerDoc_SetShowObjectFlag
                    204:  * ------------------------------
                    205:  *
                    206:  *  Set/Clear the ShowObject flag of ContainerDoc
                    207:  */
                    208: void ContainerDoc_SetShowObjectFlag(LPCONTAINERDOC lpContainerDoc, BOOL fShow)
                    209: {
                    210:     if (!lpContainerDoc)
                    211:         return;
                    212: 
                    213:     lpContainerDoc->m_fShowObject = fShow;
                    214: }
                    215: 
                    216: 
                    217: /* ContainerDoc_GetShowObjectFlag
                    218:  * ------------------------------
                    219:  *
                    220:  *  Get the ShowObject flag of ContainerDoc
                    221:  */
                    222: BOOL ContainerDoc_GetShowObjectFlag(LPCONTAINERDOC lpContainerDoc)
                    223: {
                    224:     if (!lpContainerDoc)
                    225:         return FALSE;
                    226: 
                    227:     return lpContainerDoc->m_fShowObject;
                    228: }
                    229: 
                    230: 
                    231: /* ContainerDoc_InsertOleObjectCommand
                    232:  * -----------------------------------
                    233:  *
                    234:  * Insert a new OLE object in the ContainerDoc.
                    235:  */
                    236: void ContainerDoc_InsertOleObjectCommand(LPCONTAINERDOC lpContainerDoc)
                    237: {
                    238:     LPLINELIST              lpLL =&((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                    239:     LPLINE                  lpLine = NULL;
                    240:     HDC                     hDC;
                    241:     int                     nTab = 0;
                    242:     int                     nIndex = LineList_GetFocusLineIndex(lpLL);
                    243:     LPCONTAINERLINE         lpContainerLine=NULL;
                    244:     char                    szStgName[CWCSTORAGENAME];
                    245:     UINT                    uRet;
                    246:     OLEUIINSERTOBJECT       io;
                    247:     char                    szFile[OLEUI_CCHPATHMAX];
                    248:     DWORD                   dwOleCreateType;
                    249:     BOOL                    fDisplayAsIcon;
                    250:     HCURSOR                 hPrevCursor;
                    251: 
                    252:     //String initially NULL.
                    253:     _fmemset((LPSTR)szFile, 0, OLEUI_CCHPATHMAX);
                    254: 
                    255:     _fmemset((LPOLEUIINSERTOBJECT)&io, 0, sizeof(io));
                    256:     io.cbStruct=sizeof(io);
                    257:     io.dwFlags=IOF_SELECTCREATENEW | IOF_SHOWHELP;
                    258:     io.hWndOwner=((LPOUTLINEDOC)lpContainerDoc)->m_hWndDoc;
                    259: 
                    260:     io.lpszFile=(LPSTR)szFile;
                    261:     io.cchFile=sizeof(szFile);
                    262: 
                    263:     OLEDBG_BEGIN3("OleUIInsertObject called\r\n")
                    264:     uRet=OleUIInsertObject((LPOLEUIINSERTOBJECT)&io);
                    265:     OLEDBG_END3
                    266: 
                    267:     if (OLEUI_OK != uRet)
                    268:         return;     // user canceled dialog
                    269: 
                    270:     // this may take a while, put up hourglass cursor
                    271:     hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
                    272: 
                    273:     fDisplayAsIcon = (io.dwFlags & IOF_CHECKDISPLAYASICON ? TRUE : FALSE);
                    274: 
                    275:     // make up a storage name for the OLE object
                    276:     ContainerDoc_GetNextStgName(lpContainerDoc, szStgName, sizeof(szStgName));
                    277: 
                    278:     /* default the new line to have the same indent as previous line */
                    279:     lpLine = LineList_GetLine(lpLL, nIndex);
                    280:     if (lpLine)
                    281:         nTab = Line_GetTabLevel(lpLine);
                    282: 
                    283:     hDC = LineList_GetDC(lpLL);
                    284: 
                    285:     //Only try to create new objects IF Create New was selected
                    286:     if ((io.dwFlags & IOF_SELECTCREATENEW))
                    287:         dwOleCreateType = IOF_SELECTCREATENEW;
                    288:     else
                    289:         {
                    290:         if ((io.dwFlags & IOF_SELECTCREATEFROMFILE))
                    291:             dwOleCreateType = IOF_SELECTCREATEFROMFILE;
                    292: 
                    293:         if ((io.dwFlags & IOF_CHECKLINK))
                    294:             dwOleCreateType = IOF_CHECKLINK;
                    295:         }
                    296: 
                    297:     lpContainerLine = ContainerLine_Create(
                    298:             dwOleCreateType,
                    299:             hDC,
                    300:             nTab,
                    301:             lpContainerDoc,
                    302:             &io.clsid,
                    303:             (LPSTR)szFile,
                    304:             fDisplayAsIcon,
                    305:             io.hMetaPict,
                    306:             szStgName
                    307:     );
                    308: 
                    309:     if (!lpContainerLine)
                    310:         goto error;         // creation of OLE object FAILED
                    311: 
                    312:     if (io.hMetaPict) {
                    313:         OleUIMetafilePictIconFree(io.hMetaPict);    // clean up metafile
                    314:     }
                    315: 
                    316:     /* add a ContainerLine object to the document's LineList. The
                    317:     **    ContainerLine manages the rectangle on the screen occupied by
                    318:     **    the OLE object. later when the app is updated to support
                    319:     **    extended layout, there could be more than one Line associated
                    320:     **    with the OLE object.
                    321:     */
                    322: 
                    323:     LineList_AddLine(lpLL, (LPLINE)lpContainerLine, nIndex);
                    324: 
                    325:     /* before calling DoVerb(OLEIVERB_SHOW), check to see if the object
                    326:     **    has any initial extents.
                    327:     */
                    328:     ContainerLine_UpdateExtent(lpContainerLine, NULL);
                    329: 
                    330:     /* If a new embedded object was created, tell the object server to
                    331:     **    make itself visible (show itself).
                    332:     */
                    333:     if (dwOleCreateType == IOF_SELECTCREATENEW) {
                    334:         if (! ContainerLine_DoVerb(lpContainerLine, OLEIVERB_SHOW, TRUE, 
                    335:                                TRUE)) {
                    336:             OutlineApp_ErrorMessage(g_lpApp, ErrMsgShowObj);
                    337:         }
                    338: 
                    339:         /* OLE2NOTE: we will immediately force a save of the object
                    340:         **    to guarantee that a valid initial object is saved
                    341:         **    with our document. if the object is a OLE 1.0 object,
                    342:         **    then it may exit without update. by forcing this
                    343:         **    initial save we consistently always have a valid
                    344:         **    object even if it is a OLE 1.0 object that exited
                    345:         **    without saving. if we did NOT do this save here, then
                    346:         **    we would have to worry about deleting the object if
                    347:         **    it was a OLE 1.0 object that closed without saving.
                    348:         **    the OLE 2.0 User Model dictates that the object
                    349:         **    should always be valid after CreateNew performed. the
                    350:         **    user must explicitly delete it.
                    351:         */
                    352:         ContainerLine_SaveOleObject(
                    353:                 lpContainerLine, 
                    354:                 lpContainerLine->m_lpStg, 
                    355:                 TRUE,  /* fSameAsLoad */
                    356:                 TRUE,  /* fRemember */
                    357:                 TRUE   /* fForceUpdate */
                    358:                );
                    359:     }
                    360: 
                    361:     OutlineDoc_SetModified((LPOUTLINEDOC)lpContainerDoc, TRUE, TRUE, TRUE);
                    362: 
                    363:     LineList_ReleaseDC(lpLL, hDC);
                    364: 
                    365:     SetCursor(hPrevCursor);     // restore original cursor
                    366: 
                    367:     return;
                    368: 
                    369: error:
                    370:     // NOTE: if ContainerLine_Create failed
                    371:     LineList_ReleaseDC(lpLL, hDC);
                    372: 
                    373:     if (OLEUI_OK == uRet && io.hMetaPict)
                    374:         OleUIMetafilePictIconFree(io.hMetaPict);    // clean up metafile
                    375: 
                    376:     SetCursor(hPrevCursor);     // restore original cursor
                    377:     OutlineApp_ErrorMessage(g_lpApp, ErrMsgInsertObj);
                    378: }
                    379: 
                    380: 
                    381: 
                    382: void ContainerDoc_EditLinksCommand(LPCONTAINERDOC lpContainerDoc)
                    383: {
                    384:     UINT        uRet;
                    385:     OLEUIEDITLINKS      el;
                    386:     LPCONTAINERLINE lpContainerLine = NULL;
                    387:     LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                    388: 
                    389:     _fmemset((LPOLEUIEDITLINKS)&el,0,sizeof(el));
                    390:     el.cbStruct=sizeof(el);
                    391:     el.dwFlags=ELF_SHOWHELP;  //what else?
                    392:     el.hWndOwner=((LPOUTLINEDOC)lpContainerDoc)->m_hWndDoc;
                    393:     el.lpOleUILinkContainer =
                    394:             (LPOLEUILINKCONTAINER)&lpContainerDoc->m_OleUILinkContainer;
                    395: 
                    396:     OLEDBG_BEGIN3("OleUIEditLinks called\r\n")
                    397:     uRet=OleUIEditLinks((LPOLEUIEDITLINKS)&el);
                    398:     OLEDBG_END3
                    399: 
                    400:     OleDbgAssert((uRet==1) || (uRet==OLEUI_CANCEL));
                    401: 
                    402: }
                    403: 
                    404: 
                    405: /* Convert command - brings up the "Convert" dialog
                    406:  */
                    407: void ContainerDoc_ConvertCommand(
                    408:         LPCONTAINERDOC      lpContainerDoc, 
                    409:         BOOL                fServerNotRegistered
                    410: )
                    411: {
                    412:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
                    413:     OLEUICONVERT ct;
                    414:     UINT         uRet;
                    415:     LPDATAOBJECT  lpDataObj;
                    416:     LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                    417:     LPCONTAINERLINE lpContainerLine = NULL;
                    418:     BOOL         fSelIsOleObject;
                    419:     int          nIndex;
                    420:     STGMEDIUM    medium;
                    421:     LPSTR        lpErrMsg = NULL;
                    422:     HRESULT      hrErr;
                    423:     HCURSOR      hPrevCursor;
                    424:        BOOL             fRunServer=FALSE;
                    425:     BOOL         fMustRun = FALSE;
                    426:     BOOL         fObjConverted = FALSE;
                    427:     BOOL         fDisplayChanged = FALSE;
                    428:     BOOL         fHaveCLSID = FALSE;
                    429:     BOOL         fHaveFmtUserType = FALSE;
                    430:     char         szUserType[128];
                    431:     BOOL         fMustActivate;
                    432: 
                    433:     /* OLE2NOTE: if we came to the Convert dialog because the user
                    434:     **    activated a non-registered object, then we should activate
                    435:     **    the object after the user has converted it or setup an
                    436:     **    ActivateAs server.
                    437:     */
                    438:     fMustActivate = fServerNotRegistered;
                    439: 
                    440:     _fmemset((LPOLEUICONVERT)&ct,0,sizeof(ct));
                    441: 
                    442:     fSelIsOleObject = ContainerDoc_IsSelAnOleObject(
                    443:             (LPCONTAINERDOC)lpContainerDoc,
                    444:             &IID_IDataObject,
                    445:             (LPUNKNOWN FAR*)&lpDataObj,
                    446:             &nIndex,
                    447:             (LPCONTAINERLINE FAR*)&lpContainerLine
                    448:     );
                    449: 
                    450:     lpErrMsg = ErrMsgCantConvert;
                    451: 
                    452:     if (! fSelIsOleObject) 
                    453:         goto error;     // can NOT do Convert.
                    454: 
                    455:     if (! lpContainerLine) {
                    456:         OleStdRelease((LPUNKNOWN)lpDataObj);
                    457:         goto error;     // can NOT do Convert.
                    458:     }
                    459: 
                    460:     ct.cbStruct  = sizeof(OLEUICONVERT);
                    461:     ct.dwFlags   = CF_SHOWHELPBUTTON;
                    462:     ct.hWndOwner = lpContainerDoc->m_OleDoc.m_OutlineDoc.m_hWndDoc;
                    463:     ct.lpszCaption = (LPSTR)NULL;
                    464:     ct.lpfnHook  = NULL;
                    465:     ct.lCustData = 0;
                    466:     ct.hInstance = NULL;
                    467:     ct.lpszTemplate = NULL;
                    468:     ct.hResource = 0;
                    469:     ct.fIsLinkedObject = ContainerLine_IsOleLink(lpContainerLine);
                    470:     ct.dvAspect = lpContainerLine->m_dwDrawAspect;
                    471: 
                    472:     if (! ct.fIsLinkedObject) {
                    473:         /* OLE2NOTE: the object is an embedded object. we should first
                    474:         **    attempt to read the actual object CLSID, file data
                    475:         **    format, and full user type name that is written inside of
                    476:         **    the object's storage as this should be the most
                    477:         **    definitive information. if this fails we will ask the
                    478:         **    object what its class is and attempt to get the rest of
                    479:         **    the information out of the REGDB.
                    480:         */
                    481:         hrErr=ReadClassStg(lpContainerLine->m_lpStg,(CLSID FAR*)&(ct.clsid));
                    482:         if (hrErr == NOERROR) 
                    483:             fHaveCLSID = TRUE;
                    484:         else {
                    485:             OleDbgOutHResult("ReadClassStg returned", hrErr);
                    486:         }
                    487:         hrErr = ReadFmtUserTypeStg(
                    488:                 lpContainerLine->m_lpStg, 
                    489:                 (CLIPFORMAT FAR*)&ct.wFormat, 
                    490:                 (LPSTR FAR*)&ct.lpszUserType);
                    491:         if (hrErr == NOERROR) 
                    492:             fHaveFmtUserType = TRUE;
                    493:         else {
                    494:             OleDbgOutHResult("ReadFmtUserTypeStg returned", hrErr);
                    495:         }
                    496:     }
                    497: 
                    498:     if (! fHaveCLSID) {
                    499:         hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetUserClassID(
                    500:                 lpContainerLine->m_lpOleObj,
                    501:                 (CLSID FAR*)&ct.clsid
                    502:         );
                    503:         if (hrErr != NOERROR) 
                    504:             ct.clsid = CLSID_NULL;
                    505:     }
                    506:     if (! fHaveFmtUserType) {
                    507:         ct.wFormat = 0;
                    508:         if (OleStdGetUserTypeOfClass(
                    509:                 (CLSID FAR*)&ct.clsid,szUserType,sizeof(szUserType),NULL)) {
                    510:             ct.lpszUserType = OleStdCopyString(szUserType, NULL);
                    511:         } else {
                    512:             ct.lpszUserType = NULL;
                    513:         }
                    514:     }
                    515: 
                    516:     if (lpContainerLine->m_dwDrawAspect == DVASPECT_ICON) {
                    517:         ct.hMetaPict = OleStdGetData(
                    518:                 lpDataObj,
                    519:                 CF_METAFILEPICT,
                    520:                 NULL,
                    521:                 DVASPECT_ICON,
                    522:                 (LPSTGMEDIUM)&medium
                    523:         );
                    524:     } else {
                    525:         ct.hMetaPict = NULL;
                    526:     }
                    527:     OleStdRelease((LPUNKNOWN)lpDataObj);
                    528: 
                    529:     OLEDBG_BEGIN3("OleUIConvert called\r\n")
                    530:     uRet = OleUIConvert(&ct);
                    531:     OLEDBG_END3
                    532: 
                    533:     // this may take a while, put up hourglass cursor
                    534:     hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
                    535: 
                    536:     if (uRet == OLEUI_OK) {
                    537: 
                    538:         /*****************************************************************
                    539:         **  OLE2NOTE: the convert dialog actually allows the user to
                    540:         **    change two orthogonal properties of the object: the
                    541:         **    object's type/server and the object's display aspect.
                    542:         **    first we will execute the ConvertTo/ActivateAs action and
                    543:         **    then we will deal with any display aspect change. we want
                    544:         **    to be careful to only call IOleObject::Update once
                    545:         **    because this is an expensive operation; it results in
                    546:         **    launching the object's server.
                    547:         *****************************************************************/
                    548: 
                    549:         if (ct.dwFlags & CF_SELECTCONVERTTO &&
                    550:                 ! IsEqualCLSID(&ct.clsid, &ct.clsidNew)) {
                    551: 
                    552:             /* user selected CONVERT.
                    553:             **
                    554:             ** OLE2NOTE: to achieve the "Convert To" at this point we
                    555:             **    need to take the following steps:
                    556:             **    1. unload the object.
                    557:             **    2. write the NEW CLSID and NEW user type name
                    558:             **       string into the storage of the object,
                    559:             **       BUT write the OLD format tag.
                    560:             **    3. force an update to force the actual conversion of
                    561:             **       the data bits.
                    562:             */
                    563:             lpErrMsg = ErrMsgConvertObj; // setup correct msg in case of error
                    564: 
                    565:             ContainerLine_UnloadOleObject(lpContainerLine);
                    566: 
                    567:             OLEDBG_BEGIN2("OleStdDoConvert called \r\n")
                    568:             hrErr = OleStdDoConvert(
                    569:                     lpContainerLine->m_lpStg, (REFCLSID)&ct.clsidNew);
                    570:             OLEDBG_END2
                    571:             if (hrErr != NOERROR) 
                    572:                 goto error;
                    573: 
                    574:             // Reload the object
                    575:             ContainerLine_LoadOleObject(lpContainerLine);
                    576:             
                    577:             /* we need to force the object to run to complete the
                    578:             **    conversion. set flag to force OleRun to be called at 
                    579:             **    end of function. 
                    580:             */
                    581:             fMustRun = TRUE;
                    582:             fObjConverted = TRUE;
                    583: 
                    584:         } else if (ct.dwFlags & CF_SELECTACTIVATEAS) {
                    585:             /* user selected ACTIVATE AS.
                    586:             **
                    587:             ** OLE2NOTE: to achieve the "Activate As" at this point we
                    588:             **    need to take the following steps:
                    589:             **    1. unload ALL objects of the OLD class that app knows about
                    590:             **    2. add the TreatAs tag in the registration database
                    591:             **    by calling CoTreatAsClass().
                    592:             **    3. lazily it can reload the objects; when the objects
                    593:             **    are reloaded the TreatAs will take effect.
                    594:             */
                    595:             lpErrMsg = ErrMsgActivateAsObj; // setup msg in case of error
                    596: 
                    597:             ContainerDoc_UnloadAllOleObjectsOfClass(
                    598:                     lpContainerDoc, (REFCLSID)&ct.clsid);
                    599: 
                    600:             OLEDBG_BEGIN2("OleStdDoTreatAsClass called \r\n")
                    601:                        hrErr = OleStdDoTreatAsClass(ct.lpszUserType, (REFCLSID)&ct.clsid,
                    602:                                        (REFCLSID)&ct.clsidNew);
                    603:             OLEDBG_END2
                    604: 
                    605:             // Reload the object
                    606:             ContainerLine_LoadOleObject(lpContainerLine);
                    607: 
                    608:             fMustActivate = TRUE;   // we should activate this object
                    609:         }
                    610:         
                    611:         /*****************************************************************
                    612:         **  OLE2NOTE: now we will try to change the display if
                    613:         **    necessary. 
                    614:         *****************************************************************/
                    615: 
                    616:         if (lpContainerLine->m_lpOleObj && 
                    617:                 ct.dvAspect != lpContainerLine->m_dwDrawAspect) {
                    618:             /* user has selected to change display aspect between icon
                    619:             **    aspect and content aspect.
                    620:             **    
                    621:             ** OLE2NOTE: if we got here because the server was not
                    622:             **    registered, then we will NOT delete the object's
                    623:             **    original display aspect. because we do not have the
                    624:             **    original server, we can NEVER get it back. this is a
                    625:             **    safety precaution.
                    626:             */
                    627:             
                    628:             hrErr = OleStdSwitchDisplayAspect(
                    629:                     lpContainerLine->m_lpOleObj,
                    630:                     &lpContainerLine->m_dwDrawAspect,
                    631:                     ct.dvAspect,
                    632:                     ct.hMetaPict,
                    633:                     !fServerNotRegistered,   /* fDeleteOldAspect */
                    634:                     TRUE,                    /* fSetupViewAdvise */
                    635:                     (LPADVISESINK)&lpContainerLine->m_AdviseSink,
                    636:                     (BOOL FAR*)&fMustRun
                    637:             );
                    638: 
                    639:             if (hrErr == NOERROR) 
                    640:                 fDisplayChanged = TRUE;
                    641: 
                    642: #if defined( INPLACE_CNTR )
                    643:                 ContainerDoc_UpdateInPlaceObjectRects(
                    644:                         lpContainerLine->m_lpDoc, nIndex);
                    645: #endif
                    646:             
                    647:         } else if (ct.dvAspect == DVASPECT_ICON && ct.fObjectsIconChanged) {
                    648:             hrErr = OleStdSetIconInCache(
                    649:                     lpContainerLine->m_lpOleObj,
                    650:                     ct.hMetaPict
                    651:             );
                    652: 
                    653:             if (hrErr == NOERROR) 
                    654:                 fDisplayChanged = TRUE;
                    655:         }
                    656: 
                    657:                /* we deliberately run the object so that the update won't shut
                    658:                ** the server down. 
                    659:                */
                    660:                if ((fMustActivate || fMustRun) 
                    661:                 && !OleIsRunning(lpContainerLine->m_lpOleObj)) {
                    662:                        ContainerLine_RunOleObject(lpContainerLine);
                    663:                        fRunServer = TRUE;
                    664:                }
                    665: 
                    666:         if (fDisplayChanged) {
                    667:             /* the Object's display was changed, force a repaint of
                    668:             **    the line. note the extents of the object may have
                    669:             **    changed.
                    670:             */
                    671:             ContainerLine_UpdateExtent(lpContainerLine, NULL);
                    672:             LineList_ForceLineRedraw(lpLL, nIndex, TRUE);
                    673:         }
                    674:         
                    675:         if (fDisplayChanged || fObjConverted) {
                    676:             /* mark ContainerDoc as now dirty. if display changed, then
                    677:             **    the extents of the object may have changed.
                    678:             */
                    679:             OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, fDisplayChanged);
                    680:         }
                    681:                
                    682:                if (fMustActivate)
                    683:                        ContainerLine_DoVerb(lpContainerLine, OLEIVERB_SHOW, FALSE,FALSE);
                    684:         else if (fRunServer) {
                    685:             /* if we launched the server in order to get an update of
                    686:             **    the presentation, then we must shut the server down
                    687:             */
                    688:             ContainerLine_CloseOleObject(lpContainerLine);
                    689:         }
                    690:     }
                    691: 
                    692: 
                    693:     if (ct.hMetaPict)
                    694:         OleUIMetafilePictIconFree(ct.hMetaPict);    // clean up metafile
                    695: 
                    696:     SetCursor(hPrevCursor);     // restore original cursor
                    697: 
                    698:     return;
                    699: 
                    700: error:
                    701:        if (fRunServer)
                    702:                ContainerLine_CloseOleObject(lpContainerLine);
                    703: 
                    704:     if (ct.lpszUserType)
                    705:         OleStdFreeString(ct.lpszUserType, NULL);
                    706: 
                    707:     if (ct.hMetaPict)
                    708:         OleUIMetafilePictIconFree(ct.hMetaPict);    // clean up metafile
                    709: 
                    710:     SetCursor(hPrevCursor);     // restore original cursor
                    711:     if (lpErrMsg) 
                    712:         OutlineApp_ErrorMessage(g_lpApp, lpErrMsg);
                    713:        
                    714: }
                    715: 
                    716: 
                    717: /* ContainerDoc_CloseAllOleObjects
                    718: ** -------------------------------
                    719: **    Close all OLE objects. This forces all OLE objects to transition
                    720: **    from the running state to the loaded state.
                    721: **
                    722: **    Returns TRUE if all objects closed successfully  
                    723: **            FALSE if any object could not be closed.
                    724: */
                    725: BOOL ContainerDoc_CloseAllOleObjects(LPCONTAINERDOC lpContainerDoc)
                    726: {
                    727:     LPLINELIST  lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                    728:     int         i;
                    729:     LPLINE      lpLine;
                    730:     BOOL        fStatus = TRUE;
                    731: 
                    732:     for (i = 0; i < lpLL->m_nNumLines; i++) {
                    733:         lpLine=LineList_GetLine(lpLL, i);
                    734: 
                    735:         if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE))
                    736:             if (! ContainerLine_CloseOleObject((LPCONTAINERLINE)lpLine))
                    737:                 fStatus = FALSE;
                    738:     }
                    739:     
                    740:     return fStatus;
                    741: }
                    742: 
                    743: 
                    744: /* ContainerDoc_UnloadAllOleObjectsOfClass
                    745: ** ---------------------------------------
                    746: **    Unload all OLE objects of a particular class. this is necessary
                    747: **    when a class level "ActivateAs" (aka. TreatAs) is setup. the user
                    748: **    can do this with the Convert dialog. for the TreatAs to take
                    749: **    effect, all objects of the class have to loaded and reloaded.
                    750: */
                    751: void ContainerDoc_UnloadAllOleObjectsOfClass(
                    752:         LPCONTAINERDOC      lpContainerDoc,
                    753:         REFCLSID            rClsid
                    754: )
                    755: {
                    756:     LPLINELIST  lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                    757:     int         i;
                    758:     LPLINE      lpLine;
                    759:     CLSID       clsid;
                    760:     HRESULT     hrErr;
                    761: 
                    762:     for (i = 0; i < lpLL->m_nNumLines; i++) {
                    763:         lpLine=LineList_GetLine(lpLL, i);
                    764: 
                    765:         if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
                    766:             LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
                    767:             
                    768:             if (! lpContainerLine->m_lpOleObj) 
                    769:                 continue;       // this object is NOT loaded
                    770: 
                    771:             hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetUserClassID(
                    772:                     lpContainerLine->m_lpOleObj,
                    773:                     (CLSID FAR*)&clsid
                    774:             );
                    775:             if (hrErr == NOERROR && 
                    776:                     ( IsEqualCLSID((CLSID FAR*)&clsid,rClsid) 
                    777:                       || IsEqualCLSID(rClsid,&CLSID_NULL) ) ) {
                    778:                 ContainerLine_UnloadOleObject(lpContainerLine);
                    779:             }
                    780:         }
                    781:     }
                    782: }
                    783: 
                    784: 
                    785: /* ContainerDoc_UpdateExtentOfAllOleObjects
                    786: ** ----------------------------------------
                    787: **    Update the extents of any OLE object that is marked that its size
                    788: **    may  have changed. when an IAdviseSink::OnViewChange notification
                    789: **    is received, the corresponding ContainerLine is marked
                    790: **    (m_fDoGetExtent==TRUE) and a message (WM_U_UPDATEOBJECTEXTENT) is
                    791: **    posted to the document indicating that there are dirty objects.
                    792: **    when this message is received, this function is called.
                    793: */
                    794: void ContainerDoc_UpdateExtentOfAllOleObjects(LPCONTAINERDOC lpContainerDoc)
                    795: {
                    796:     LPLINELIST  lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                    797:     int         i;
                    798:     LPLINE      lpLine;
                    799:     BOOL        fStatus = TRUE;
                    800: 
                    801:     for (i = 0; i < lpLL->m_nNumLines; i++) {
                    802:         lpLine=LineList_GetLine(lpLL, i);
                    803: 
                    804:         if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
                    805:             LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
                    806:             
                    807:             if (lpContainerLine->m_fDoGetExtent)
                    808:                                ContainerLine_UpdateExtent(lpContainerLine, NULL);
                    809:         }
                    810:     }
                    811: }
                    812: 
                    813: 
                    814: BOOL ContainerDoc_SaveToFile(
                    815:         LPCONTAINERDOC          lpContainerDoc,
                    816:         LPCSTR                  lpszFileName,
                    817:         UINT                    uFormat,
                    818:         BOOL                    fRemember
                    819: )
                    820: {
                    821:     LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
                    822:     LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
                    823:     LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc;
                    824:     LPSTORAGE lpDestStg;
                    825:     BOOL fStatus;
                    826:     BOOL fMustRelDestStg = FALSE;
                    827:     HRESULT hrErr;
                    828: 
                    829:     if (fRemember) {
                    830:         if (lpszFileName) {
                    831:             fStatus = OutlineDoc_SetFileName(
                    832:                     lpOutlineDoc, (LPSTR)lpszFileName, NULL);
                    833:             if (! fStatus) goto error;
                    834:         }
                    835: 
                    836:         /* The ContainerDoc keeps its storage open at all times. it is not
                    837:         **    necessary to reopen the file.
                    838:         ** if SaveAs is pending, then lpNewStg is the new destination for
                    839:         **    the save operation, else the existing storage is the dest.
                    840:         */
                    841:         lpDestStg = (lpContainerDoc->m_lpNewStg ?
                    842:                         lpContainerDoc->m_lpNewStg : lpContainerDoc->m_lpStg);
                    843:     } else {
                    844:         if (! lpszFileName)
                    845:             goto error;
                    846: 
                    847:         /* OLE2NOTE: since we are preforming a SaveCopyAs operation, we
                    848:         **    do not need to have the DocFile open in STGM_TRANSACTED mode.
                    849:         **    there is less overhead to use STGM_DIRECT mode.
                    850:         */
                    851:         hrErr = StgCreateDocfile(
                    852:                 lpszFileName,
                    853:                 STGM_READWRITE|STGM_DIRECT|STGM_SHARE_DENY_WRITE|STGM_CREATE,
                    854:                 0,
                    855:                 &lpDestStg
                    856:         );
                    857:         if (! OleDbgVerifySz(hrErr == NOERROR, "Could not create Docfile"))
                    858:             goto error;
                    859:         fMustRelDestStg = TRUE;
                    860:     }
                    861: 
                    862:     /*  OLE2NOTE: we must be sure to write our class ID into our
                    863:     **    storage. this information is used by OLE to determine the
                    864:     **    class of the data stored in our storage. Even for top
                    865:     **    "file-level" objects this information should be written to
                    866:     **    the file.
                    867:     */
                    868:     hrErr = WriteClassStg(lpDestStg, &CLSID_APP);
                    869:     if(hrErr != NOERROR) goto error;
                    870: 
                    871:     fStatus = OutlineDoc_SaveSelToStg(
                    872:             lpOutlineDoc,
                    873:             NULL,           // save all lines
                    874:             uFormat,
                    875:             lpDestStg,
                    876:             TRUE            // remember this stg
                    877:         );
                    878: 
                    879:     if (fStatus)
                    880:         fStatus = OleStdCommitStorage(lpDestStg);
                    881: 
                    882:     if (fRemember) {
                    883:         /* if SaveAs was pending, then release the old storage and remember
                    884:         **    the new storage as the active current storage. all data from
                    885:         **    the old storage has been copied into the new storage.
                    886:         */
                    887:         if (lpContainerDoc->m_lpNewStg) {
                    888:             OleStdRelease((LPUNKNOWN)lpContainerDoc->m_lpStg);  // free old stg
                    889:             lpContainerDoc->m_lpStg = lpContainerDoc->m_lpNewStg;   // save new stg
                    890:             lpContainerDoc->m_lpNewStg = NULL;
                    891:         }
                    892:         if (! fStatus) goto error;
                    893: 
                    894:         OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE);
                    895: 
                    896:         /* OLE2NOTE: we must note the time this File-Based object has
                    897:         **    been saved in the RunningObjectTable. this is necessary
                    898:         **    for Container applications which support linking to
                    899:         **    embedded objects. These change times are used as the
                    900:         **    basis for IOleObject::IsUpToDate.  It is important to set
                    901:         **    the time of the file-based object following a save
                    902:         **    operation to exactly the time of the saved file. this
                    903:         **    helps IOleObject::IsUpToDate to give the correct answer
                    904:         **    after a file has been saved. 
                    905:         */
                    906:         OleStdNoteFileChangeTime(
                    907:                 lpOutlineDoc->m_szFileName, lpOleDoc->m_dwRegROT);
                    908:     }
                    909: 
                    910:     if (fMustRelDestStg)
                    911:         OleStdRelease((LPUNKNOWN)lpDestStg);
                    912:     return TRUE;
                    913: 
                    914: error:
                    915:     if (fMustRelDestStg)
                    916:         OleStdRelease((LPUNKNOWN)lpDestStg);
                    917:     OutlineApp_ErrorMessage(g_lpApp, ErrMsgSaving);
                    918:     return FALSE;
                    919: }
                    920: 
                    921: 
                    922: /* ContainerDoc_ContainerLineDoVerbCommand
                    923: ** ---------------------------------------
                    924: **    Execute a verb of the OLE object in the current focus line.
                    925: */
                    926: void ContainerDoc_ContainerLineDoVerbCommand(
                    927:         LPCONTAINERDOC          lpContainerDoc,
                    928:         LONG                    iVerb
                    929: )
                    930: {
                    931:     LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                    932:     int nIndex = LineList_GetFocusLineIndex(lpLL);
                    933:     LPLINE lpLine = LineList_GetLine(lpLL, nIndex);
                    934:     HCURSOR                 hPrevCursor;
                    935: 
                    936:     if (! lpLine || (Line_GetLineType(lpLine) != CONTAINERLINETYPE) ) return;
                    937: 
                    938:     // this may take a while, put up hourglass cursor
                    939:     hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
                    940: 
                    941:     ContainerLine_DoVerb((LPCONTAINERLINE) lpLine, iVerb, TRUE, TRUE);
                    942: 
                    943:     SetCursor(hPrevCursor);     // restore original cursor
                    944: }
                    945: 
                    946: 
                    947: /* ContainerDoc_GetNextStgName
                    948: ** ---------------------------
                    949: **    Generate the next unused name for a sub-storage to be used by an
                    950: **    OLE object. The ContainerDoc keeps a counter. The storages for
                    951: **    OLE objects are simply numbered (eg. Obj 0, Obj 1). A "long"
                    952: **    integer worth of storage names should be more than enough than we
                    953: **    will ever need.
                    954: **
                    955: **    NOTE: when an OLE object is transfered via drag/drop or the
                    956: **    clipboard, we attempt to keep the currently assigned name for the
                    957: **    object (if not currently in use). thus it is possible that an
                    958: **    object with a the next default name (eg. "Obj 5") already exists
                    959: **    in the current document if an object with this name was privously
                    960: **    transfered (pasted or dropped). we therefore loop until we find
                    961: **    the next lowest unused name.
                    962: */
                    963: void ContainerDoc_GetNextStgName(
                    964:         LPCONTAINERDOC          lpContainerDoc,
                    965:         LPSTR                   lpszStgName,
                    966:         int                     nLen
                    967: )
                    968: {
                    969:     wsprintf(lpszStgName, "%s %ld",
                    970:             (LPSTR)DEFOBJNAMEPREFIX,
                    971:             ++(lpContainerDoc->m_nNextObjNo)
                    972:     );
                    973: 
                    974:     while (ContainerDoc_IsStgNameUsed(lpContainerDoc, lpszStgName) == TRUE) {
                    975:         wsprintf(lpszStgName, "%s %ld",
                    976:                 (LPSTR)DEFOBJNAMEPREFIX,
                    977:                 ++(lpContainerDoc->m_nNextObjNo)
                    978:         );
                    979:     }
                    980: }
                    981: 
                    982: 
                    983: /* ContainerDoc_IsStgNameUsed
                    984: ** --------------------------
                    985: **    Check if a given StgName is already in use.
                    986: */
                    987: BOOL ContainerDoc_IsStgNameUsed(
                    988:         LPCONTAINERDOC          lpContainerDoc,
                    989:         LPSTR                   lpszStgName
                    990: )
                    991: {
                    992:     LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                    993:     int i;
                    994:     LPLINE lpLine;
                    995: 
                    996:     for (i = 0; i < lpLL->m_nNumLines; i++) {
                    997:         lpLine=LineList_GetLine(lpLL, i);
                    998: 
                    999:         if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
                   1000:             if (lstrcmp(lpszStgName,
                   1001:                     ((LPCONTAINERLINE)lpLine)->m_szStgName) == 0) {
                   1002:                 return TRUE;    // Match FOUND!
                   1003:             }
                   1004:         }
                   1005:     }
                   1006:     return FALSE;   // if we get here, then NO match was found.
                   1007: }
                   1008: 
                   1009: 
                   1010: LPSTORAGE ContainerDoc_GetStg(LPCONTAINERDOC lpContainerDoc)
                   1011: {
                   1012:     return lpContainerDoc->m_lpStg;
                   1013: }
                   1014: 
                   1015: 
                   1016: /* ContainerDoc_GetSingleOleObject
                   1017: ** -------------------------------
                   1018: **    If the entire document contains a single OLE object, then
                   1019: **    return the desired interface of the object.
                   1020: **
                   1021: **    Returns NULL if there is are multiple lines in the document or
                   1022: **    the single line is not a ContainerLine.
                   1023: */
                   1024: LPUNKNOWN ContainerDoc_GetSingleOleObject(
                   1025:         LPCONTAINERDOC          lpContainerDoc,
                   1026:         REFIID                  riid,
                   1027:         LPCONTAINERLINE FAR*    lplpContainerLine
                   1028: )
                   1029: {
                   1030:     LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                   1031:     LPLINE lpLine;
                   1032:     LPUNKNOWN lpObj = NULL;
                   1033: 
                   1034:     if (lplpContainerLine)
                   1035:         *lplpContainerLine = NULL;
                   1036: 
                   1037:     if (lpLL->m_nNumLines != 1)
                   1038:         return NULL;    // doc does NOT contain a single line
                   1039: 
                   1040:     lpLine=LineList_GetLine(lpLL, 0);
                   1041: 
                   1042:     if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE))
                   1043:         lpObj = ContainerLine_GetOleObject((LPCONTAINERLINE)lpLine, riid);
                   1044: 
                   1045:     if (lplpContainerLine)
                   1046:         *lplpContainerLine = (LPCONTAINERLINE)lpLine;
                   1047: 
                   1048:     return lpObj;
                   1049: }
                   1050: 
                   1051: 
                   1052: /* ContainerDoc_IsSelAnOleObject
                   1053: ** -----------------------------
                   1054: **    Check if the selection is a single selection of an OLE object.
                   1055: **    if so, then optionally return the desired interface of the object
                   1056: **    and/or index of the ContainerLine containing the OLE object.
                   1057: **
                   1058: **    Returns FALSE if there is a multiple selection or the single
                   1059: **    selection is not a ContainerLine.
                   1060: */
                   1061: BOOL ContainerDoc_IsSelAnOleObject(
                   1062:         LPCONTAINERDOC          lpContainerDoc,
                   1063:         REFIID                  riid,
                   1064:         LPUNKNOWN FAR*          lplpvObj,
                   1065:         int FAR*                lpnIndex,
                   1066:         LPCONTAINERLINE FAR*    lplpContainerLine
                   1067: )
                   1068: {
                   1069:     LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                   1070:     LINERANGE lrSel;
                   1071:     int nNumSel;
                   1072:     LPLINE lpLine;
                   1073: 
                   1074:     if (lplpvObj) *lplpvObj = NULL;
                   1075:     if (lpnIndex) *lpnIndex = -1;
                   1076:     if (lplpContainerLine) *lplpContainerLine = NULL;
                   1077: 
                   1078:     nNumSel = LineList_GetSel(lpLL, (LPLINERANGE)&lrSel);
                   1079:     if (nNumSel != 1)
                   1080:         return FALSE;   // selection is not a single line
                   1081: 
                   1082:     lpLine = LineList_GetLine(lpLL, lrSel.m_nStartLine);
                   1083: 
                   1084:     if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
                   1085:         if (lpnIndex)
                   1086:             *lpnIndex = lrSel.m_nStartLine;
                   1087:         if (lplpContainerLine) 
                   1088:             *lplpContainerLine = (LPCONTAINERLINE)lpLine;
                   1089:         if (riid) {
                   1090:             *lplpvObj = ContainerLine_GetOleObject(
                   1091:                     (LPCONTAINERLINE)lpLine,
                   1092:                     riid
                   1093:             );
                   1094:         }
                   1095: 
                   1096:         return (*lplpvObj ? TRUE : FALSE);
                   1097:     }
                   1098: 
                   1099:     return FALSE;
                   1100: }
                   1101: 
                   1102: 
                   1103: /*************************************************************************
                   1104: ** ContainerDoc::IOleUILinkContainer interface implementation
                   1105: *************************************************************************/
                   1106: 
                   1107: STDMETHODIMP CntrDoc_LinkCont_QueryInterface(
                   1108:         LPOLEUILINKCONTAINER    lpThis,
                   1109:         REFIID                  riid,
                   1110:         LPVOID FAR*             lplpvObj
                   1111: )
                   1112: {
                   1113:     LPOLEDOC lpOleDoc = (LPOLEDOC)
                   1114:             ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc;
                   1115: 
                   1116:     return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
                   1117: }
                   1118: 
                   1119: 
                   1120: STDMETHODIMP_(ULONG) CntrDoc_LinkCont_AddRef(LPOLEUILINKCONTAINER lpThis)
                   1121: {
                   1122:     LPOLEDOC lpOleDoc = (LPOLEDOC)
                   1123:             ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc;
                   1124: 
                   1125:     OleDbgAddRefMethod(lpThis, "IOleUILinkContainer");
                   1126: 
                   1127:     return OleDoc_AddRef(lpOleDoc);
                   1128: }
                   1129: 
                   1130: 
                   1131: STDMETHODIMP_(ULONG) CntrDoc_LinkCont_Release(LPOLEUILINKCONTAINER lpThis)
                   1132: {
                   1133:     LPOLEDOC lpOleDoc = (LPOLEDOC)
                   1134:             ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc;
                   1135: 
                   1136:     OleDbgReleaseMethod(lpThis, "IOleUILinkContainer");
                   1137: 
                   1138:     return OleDoc_Release(lpOleDoc);
                   1139: }
                   1140: 
                   1141: 
                   1142: STDMETHODIMP_(DWORD) CntrDoc_LinkCont_GetNextLink(
                   1143:         LPOLEUILINKCONTAINER    lpThis,
                   1144:         DWORD                   dwLink
                   1145: )
                   1146: {
                   1147:     LPCONTAINERDOC lpContainerDoc =
                   1148:             ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc;
                   1149:        LPCONTAINERLINE lpContainerLine = NULL;
                   1150: 
                   1151:     OLEDBG_BEGIN2("CntrDoc_LinkCont_GetNextLink\r\n")
                   1152: 
                   1153:        lpContainerLine = ContainerDoc_GetNextLink(
                   1154:                        lpContainerDoc, 
                   1155:                        (LPCONTAINERLINE)dwLink
                   1156:        );
                   1157: 
                   1158:     OLEDBG_END2
                   1159:     return (DWORD)lpContainerLine;
                   1160: }
                   1161: 
                   1162: 
                   1163: STDMETHODIMP CntrDoc_LinkCont_SetLinkUpdateOptions(
                   1164:         LPOLEUILINKCONTAINER    lpThis,
                   1165:         DWORD                   dwLink,
                   1166:         DWORD                   dwUpdateOpt
                   1167: )
                   1168: {
                   1169:     LPCONTAINERDOC lpContainerDoc =
                   1170:             ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc;
                   1171:     LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink;
                   1172:     LPOLELINK lpOleLink;
                   1173:     SCODE sc = S_OK;
                   1174:     HRESULT hrErr;
                   1175: 
                   1176:     OLEDBG_BEGIN2("CntrDoc_LinkCont_SetLinkUpdateOptions\r\n")
                   1177: 
                   1178:     OleDbgAssert(lpContainerLine);
                   1179: 
                   1180:     lpOleLink = (LPOLELINK)ContainerLine_GetOleObject(
                   1181:             lpContainerLine,
                   1182:             &IID_IOleLink
                   1183:     );
                   1184: 
                   1185:     if (! lpOleLink) {
                   1186:         sc = E_FAIL;
                   1187:         goto error;
                   1188:     }
                   1189: 
                   1190:     OLEDBG_BEGIN2("IOleLink::SetUpdateOptions called\r\n")
                   1191:     hrErr = lpOleLink->lpVtbl->SetUpdateOptions(
                   1192:             lpOleLink,
                   1193:             dwUpdateOpt
                   1194:     );
                   1195:     OLEDBG_END2
                   1196: 
                   1197:     OleStdRelease((LPUNKNOWN)lpOleLink);
                   1198: 
                   1199:     if (hrErr != NOERROR) {
                   1200:         OleDbgOutHResult("IOleLink::SetUpdateOptions returned", hrErr);
                   1201:         sc = GetScode(hrErr);
                   1202:         goto error;
                   1203:     }
                   1204: 
                   1205:     OLEDBG_END2
                   1206:     return ResultFromScode(sc);
                   1207: 
                   1208: error:
                   1209:     OLEDBG_END2
                   1210:     return ResultFromScode(sc);
                   1211: }
                   1212: 
                   1213: 
                   1214: STDMETHODIMP CntrDoc_LinkCont_GetLinkUpdateOptions(
                   1215:         LPOLEUILINKCONTAINER    lpThis,
                   1216:         DWORD                   dwLink,
                   1217:         DWORD FAR*              lpdwUpdateOpt
                   1218: )
                   1219: {
                   1220:     LPCONTAINERDOC lpContainerDoc =
                   1221:             ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc;
                   1222:     LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink;
                   1223:     LPOLELINK lpOleLink;
                   1224:     SCODE sc = S_OK;
                   1225:     HRESULT hrErr;
                   1226: 
                   1227:     OLEDBG_BEGIN2("CntrDoc_LinkCont_GetLinkUpdateOptions\r\n")
                   1228: 
                   1229:     OleDbgAssert(lpContainerLine);
                   1230: 
                   1231:     lpOleLink = (LPOLELINK)ContainerLine_GetOleObject(
                   1232:             lpContainerLine,
                   1233:             &IID_IOleLink
                   1234:     );
                   1235: 
                   1236:     if (! lpOleLink) {
                   1237:         sc = E_FAIL;
                   1238:         goto error;
                   1239:     }
                   1240: 
                   1241:     OLEDBG_BEGIN2("IOleLink::GetUpdateOptions called\r\n")
                   1242:     hrErr = lpOleLink->lpVtbl->GetUpdateOptions(
                   1243:             lpOleLink,
                   1244:             lpdwUpdateOpt
                   1245:     );
                   1246:     OLEDBG_END2
                   1247: 
                   1248:     OleStdRelease((LPUNKNOWN)lpOleLink);
                   1249: 
                   1250:     if (hrErr != NOERROR) {
                   1251:         OleDbgOutHResult("IOleLink::GetUpdateOptions returned", hrErr);
                   1252:         sc = GetScode(hrErr);
                   1253:         goto error;
                   1254:     }
                   1255: 
                   1256:     OLEDBG_END2
                   1257:     return ResultFromScode(sc);
                   1258: 
                   1259: error:
                   1260:     OLEDBG_END2
                   1261:     return ResultFromScode(sc);
                   1262: }
                   1263: 
                   1264: 
                   1265: STDMETHODIMP CntrDoc_LinkCont_SetLinkSource(
                   1266:         LPOLEUILINKCONTAINER   lpThis,
                   1267:                DWORD                                   dwLink,
                   1268:         LPSTR                                  lpszDisplayName,
                   1269:                ULONG                                   lenFileName,            
                   1270:         ULONG FAR*                             lpchEaten,
                   1271:                BOOL                                    fValidateSource
                   1272: )
                   1273: {
                   1274:     LPCONTAINERDOC lpContainerDoc =
                   1275:             ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc;
                   1276:     LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink;
                   1277:     SCODE       sc = S_OK;
                   1278:     HRESULT     hrErr;
                   1279:     LPOLELINK   lpOleLink = NULL;
                   1280:     LPBC        lpbc = NULL;
                   1281:     LPMONIKER   lpmk = NULL;
                   1282:        LPOLEOBJECT lpLinkSrcOleObj = NULL;
                   1283:        CLSID       clsid = CLSID_NULL;
                   1284: 
                   1285: 
                   1286:     OLEDBG_BEGIN2("CntrDoc_LinkCont_SetLinkSource\r\n")
                   1287: 
                   1288:     OleDbgAssert(lpContainerLine);
                   1289: 
                   1290:        lpContainerLine->m_fLinkUnavailable = TRUE;
                   1291:        
                   1292:        if (fValidateSource) {
                   1293: 
                   1294:         /* OLE2NOTE: validate the link source by parsing the string
                   1295:         **    into a Moniker. if this is successful, then the string is
                   1296:         **    valid.
                   1297:         */
                   1298:         hrErr = CreateBindCtx(0, (LPBC FAR*)&lpbc);
                   1299:         if (hrErr != NOERROR) {
                   1300:             sc = GetScode(hrErr);   // ERROR: OOM
                   1301:             goto cleanup;
                   1302:         }
                   1303: 
                   1304:                OLEDBG_BEGIN2("MkParseDisplayName called\r\n")
                   1305:                hrErr = MkParseDisplayName(
                   1306:                                lpbc, lpszDisplayName, lpchEaten, (LPMONIKER FAR*)&lpmk);
                   1307:                OLEDBG_END2
                   1308: 
                   1309:                if (hrErr != NOERROR) {
                   1310:                        sc = GetScode(hrErr);   // ERROR in parsing moniker!
                   1311:                        goto cleanup;
                   1312:                }
                   1313:         /* OLE2NOTE: the link source was validated; it successfully
                   1314:         **    parsed into a Moniker. we can set the source of the link
                   1315:         **    directly with this Moniker. if we want the link to be
                   1316:         **    able to know the correct class for the new link source,
                   1317:         **    we must bind to the moniker and get the CLSID. if we do
                   1318:         **    not do this then methods like IOleObject::GetUserType
                   1319:         **    will return nothing (NULL strings).
                   1320:         */
                   1321:         
                   1322:         hrErr = lpmk->lpVtbl->BindToObject(
                   1323:                 lpmk,lpbc,NULL,&IID_IOleObject,(LPVOID FAR*)&lpLinkSrcOleObj);
                   1324:                if (hrErr == NOERROR) {
                   1325:                        hrErr = lpLinkSrcOleObj->lpVtbl->GetUserClassID(
                   1326:                                                        lpLinkSrcOleObj,
                   1327:                                                        (CLSID FAR*)&clsid);
                   1328:                        lpContainerLine->m_fLinkUnavailable = FALSE;                    
                   1329:                }
                   1330:                else
                   1331:                        lpContainerLine->m_fLinkUnavailable = TRUE;
                   1332:        }
                   1333:        else {
                   1334:                LPMONIKER       lpmkFile = NULL;
                   1335:                LPMONIKER       lpmkItem = NULL;
                   1336:                char            szName[OLEUI_CCHPATHMAX];
                   1337:                
                   1338:                lstrcpyn((LPSTR)szName, lpszDisplayName, (int)lenFileName + 1);
                   1339:                
                   1340:                OLEDBG_BEGIN2("CreateFileMoniker called\r\n")           
                   1341:                CreateFileMoniker((LPSTR)szName, (LPMONIKER FAR*)&lpmkFile);
                   1342:                OLEDBG_END2
                   1343:                        
                   1344:                if (!lpmkFile)
                   1345:                        goto cleanup;
                   1346: 
                   1347:         if (lstrlen(lpszDisplayName) > (int)lenFileName) {     // have item name
                   1348:             lstrcpy((LPSTR)szName, lpszDisplayName + lenFileName + 1);
                   1349:                
                   1350:             OLEDBG_BEGIN2("CreateItemMoniker called\r\n")
                   1351:             CreateItemMoniker(
                   1352:                                        OLESTDDELIM, (LPSTR)szName, (LPMONIKER FAR*)&lpmkItem);
                   1353:             OLEDBG_END2
                   1354:                        
                   1355:             if (!lpmkItem) {
                   1356:                 OleStdRelease((LPUNKNOWN)lpmkFile);
                   1357:                 goto cleanup;
                   1358:             }
                   1359:                        
                   1360:                        OLEDBG_BEGIN2("CreateGenericComposite called\r\n")
                   1361:                        CreateGenericComposite(lpmkFile, lpmkItem, (LPMONIKER FAR*)&lpmk);
                   1362:                        OLEDBG_END2
                   1363:        
                   1364:                        if (lpmkFile)
                   1365:                                OleStdRelease((LPUNKNOWN)lpmkFile);
                   1366:                        if (lpmkItem)
                   1367:                                OleStdRelease((LPUNKNOWN)lpmkItem);
                   1368:                
                   1369:                        if (!lpmk)
                   1370:                                goto cleanup;
                   1371:                }
                   1372:                else
                   1373:                        lpmk = lpmkFile;
                   1374:        }
                   1375:        
                   1376:     lpOleLink = (LPOLELINK)ContainerLine_GetOleObject(
                   1377:             lpContainerLine,
                   1378:             &IID_IOleLink
                   1379:     );
                   1380: 
                   1381:     if (! lpOleLink) {
                   1382:         OleDbgAssert(lpOleLink != NULL);
                   1383:         sc = E_FAIL;
                   1384:         goto cleanup;
                   1385:     }
                   1386:     
                   1387:     if (lpmk) {
                   1388:         
                   1389:         OLEDBG_BEGIN2("IOleLink::SetSourceMoniker called\r\n")
                   1390:         hrErr = lpOleLink->lpVtbl->SetSourceMoniker(
                   1391:                 lpOleLink, lpmk, (REFCLSID)&clsid);
                   1392:         OLEDBG_END2
                   1393: 
                   1394:         if (FAILED(GetScode(hrErr))) {
                   1395:             OleDbgOutHResult("IOleLink::SetSourceMoniker returned",hrErr);
                   1396:             sc = GetScode(hrErr);
                   1397:             goto cleanup;
                   1398:         }
                   1399: 
                   1400:         /* OLE2NOTE: above we forced the link source moniker to bind.
                   1401:         **    because we deliberately hold on to the bind context
                   1402:         **    (lpbc) the link source object will not shut down. during
                   1403:         **    the call to IOleLink::SetSourceMoniker, the link will
                   1404:         **    connect to the running link source (the link internally
                   1405:         **    calls BindIfRunning). it is important to initially allow
                   1406:         **    the link to bind to the running object so that it can get
                   1407:         **    an update of the presentation for its cache. we do not
                   1408:         **    want the connection from our link to the link source be
                   1409:         **    the only reason the link source stays running. thus we
                   1410:         **    deliberately for the link to release (unbind) the source
                   1411:         **    object, we then release the bind context, and then we
                   1412:         **    allow the link to rebind to the link source if it is
                   1413:         **    running anyway.
                   1414:         */
                   1415:         if (lpbc && lpmk->lpVtbl->IsRunning(lpmk,lpbc,NULL,NULL) == NOERROR) {
                   1416: 
                   1417:             OLEDBG_BEGIN2("IOleLink::Update called\r\n")
                   1418:             hrErr = lpOleLink->lpVtbl->Update(lpOleLink, NULL);
                   1419:             OLEDBG_END2
                   1420: 
                   1421: #if defined( _DEBUG )
                   1422:             if (FAILED(GetScode(hrErr))) 
                   1423:                 OleDbgOutHResult("IOleLink::Update returned",hrErr);
                   1424: #endif
                   1425: 
                   1426:             OLEDBG_BEGIN2("IOleLink::UnbindSource called\r\n")
                   1427:             hrErr = lpOleLink->lpVtbl->UnbindSource(lpOleLink);
                   1428:             OLEDBG_END2
                   1429: 
                   1430: #if defined( _DEBUG )
                   1431:             if (FAILED(GetScode(hrErr))) 
                   1432:                 OleDbgOutHResult("IOleLink::UnbindSource returned",hrErr);
                   1433: #endif
                   1434: 
                   1435:             if (lpLinkSrcOleObj) {
                   1436:                 OleStdRelease((LPUNKNOWN)lpLinkSrcOleObj);
                   1437:                 lpLinkSrcOleObj = NULL;
                   1438:             }
                   1439: 
                   1440:             if (lpbc) {
                   1441:                 OleStdRelease((LPUNKNOWN)lpbc);
                   1442:                 lpbc = NULL;
                   1443:             }
                   1444: 
                   1445:             OLEDBG_BEGIN2("IOleLink::BindIfRunning called\r\n")
                   1446:             hrErr = lpOleLink->lpVtbl->BindIfRunning(lpOleLink);
                   1447:             OLEDBG_END2
                   1448: 
                   1449: #if defined( _DEBUG )
                   1450:             if (FAILED(GetScode(hrErr))) 
                   1451:                 OleDbgOutHResult("IOleLink::BindIfRunning returned",hrErr);
                   1452: #endif
                   1453:         }        
                   1454:     } else {
                   1455:         /* OLE2NOTE: the link source was NOT validated; it was NOT
                   1456:         **    successfully parsed into a Moniker. we can only set the
                   1457:         **    display name string as the source of the link. this link
                   1458:         **    is not able to bind.
                   1459:         */
                   1460:         OLEDBG_BEGIN2("IOleLink::SetSourceDisplayName called\r\n")
                   1461:         hrErr = lpOleLink->lpVtbl->SetSourceDisplayName(
                   1462:                 lpOleLink, (LPCSTR)lpszDisplayName);
                   1463:         OLEDBG_END2
                   1464: 
                   1465:         if (hrErr != NOERROR) {
                   1466:             OleDbgOutHResult("IOleLink::SetSourceDisplayName returned",hrErr);
                   1467:             sc = GetScode(hrErr);
                   1468:             goto cleanup;
                   1469:         }
                   1470:     }
                   1471: 
                   1472: cleanup:
                   1473:     if (lpOleLink)
                   1474:         OleStdRelease((LPUNKNOWN)lpOleLink);
                   1475:     if (lpLinkSrcOleObj) 
                   1476:         OleStdRelease((LPUNKNOWN)lpLinkSrcOleObj);
                   1477:     if (lpmk)
                   1478:         OleStdRelease((LPUNKNOWN)lpmk);
                   1479:     if (lpbc)
                   1480:         OleStdRelease((LPUNKNOWN)lpbc);
                   1481: 
                   1482:     OLEDBG_END2
                   1483:     return ResultFromScode(sc);
                   1484: }
                   1485: 
                   1486: 
                   1487: STDMETHODIMP CntrDoc_LinkCont_GetLinkSource(
                   1488:         LPOLEUILINKCONTAINER    lpThis,
                   1489:         DWORD                   dwLink,
                   1490:         LPSTR FAR*              lplpszDisplayName,
                   1491:         ULONG FAR*              lplenFileName,
                   1492:         LPSTR FAR*              lplpszFullLinkType,
                   1493:         LPSTR FAR*              lplpszShortLinkType,
                   1494:         BOOL FAR*               lpfSourceAvailable,
                   1495:         BOOL FAR*               lpfIsSelected
                   1496: )
                   1497: {
                   1498:     LPCONTAINERDOC lpContainerDoc =
                   1499:             ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc;
                   1500:     LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink;
                   1501:     LPOLELINK       lpOleLink = NULL;
                   1502:     LPOLEOBJECT     lpOleObj = NULL;
                   1503:     LPMONIKER       lpmk = NULL;
                   1504:     LPMONIKER       lpmkFirst = NULL;
                   1505:     LPBC            lpbc = NULL;
                   1506:     SCODE           sc = S_OK;
                   1507:     HRESULT         hrErr;
                   1508: 
                   1509:     OLEDBG_BEGIN2("CntrDoc_LinkCont_GetLinkSource\r\n")
                   1510: 
                   1511:     /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
                   1512:     *lplpszDisplayName  = NULL;
                   1513:     *lplpszFullLinkType = NULL;
                   1514:     *lplpszShortLinkType= NULL;
                   1515:     *lplenFileName      = 0;
                   1516:     *lpfSourceAvailable = !lpContainerLine->m_fLinkUnavailable;
                   1517: 
                   1518:     OleDbgAssert(lpContainerLine);
                   1519: 
                   1520:     lpOleLink = (LPOLELINK)ContainerLine_GetOleObject(
                   1521:             lpContainerLine,
                   1522:             &IID_IOleLink
                   1523:     );
                   1524: 
                   1525:     if (! lpOleLink) {
                   1526:         OLEDBG_END2
                   1527:         return ResultFromScode(E_FAIL);
                   1528:     }
                   1529: 
                   1530:     OLEDBG_BEGIN2("IOleLink::GetSourceMoniker called\r\n")
                   1531:     hrErr = lpOleLink->lpVtbl->GetSourceMoniker(
                   1532:             lpOleLink,
                   1533:             (LPMONIKER FAR*)&lpmk
                   1534:     );
                   1535:     OLEDBG_END2
                   1536: 
                   1537:     if (hrErr == NOERROR) {
                   1538:         /* OLE2NOTE: the link has the Moniker form of the link source;
                   1539:         **    this is therefore a validated link source. if the first
                   1540:         **    part of the Moniker is a FileMoniker, then we need to
                   1541:         **    return the length of the filename string. we need to
                   1542:         **    return the ProgID associated with the link source as the
                   1543:         **    "lpszShortLinkType". we need to return the
                   1544:         **    FullUserTypeName associated with the link source as the
                   1545:         **    "lpszFullLinkType".
                   1546:         */
                   1547:                
                   1548:         lpOleObj = (LPOLEOBJECT)OleStdQueryInterface(
                   1549:                 (LPUNKNOWN)lpOleLink, &IID_IOleObject);
                   1550:         if (lpOleObj) {
                   1551:             lpOleObj->lpVtbl->GetUserType(
                   1552:                     lpOleObj,
                   1553:                     USERCLASSTYPE_FULL,
                   1554:                     lplpszFullLinkType
                   1555:             );
                   1556:             lpOleObj->lpVtbl->GetUserType(
                   1557:                     lpOleObj,
                   1558:                     USERCLASSTYPE_SHORT,
                   1559:                     lplpszShortLinkType
                   1560:             );
                   1561:             OleStdRelease((LPUNKNOWN)lpOleObj);
                   1562:         }
                   1563:         *lplenFileName = OleStdGetLenFilePrefixOfMoniker(lpmk);
                   1564:         lpmk->lpVtbl->Release(lpmk);
                   1565:     }
                   1566: 
                   1567:     OLEDBG_BEGIN2("IOleLink::GetSourceDisplayName called\r\n")
                   1568:     hrErr = lpOleLink->lpVtbl->GetSourceDisplayName(
                   1569:             lpOleLink,
                   1570:             lplpszDisplayName
                   1571:     );
                   1572:     OLEDBG_END2
                   1573: 
                   1574:     OleStdRelease((LPUNKNOWN)lpOleLink);
                   1575: 
                   1576:     if (hrErr != NOERROR) {
                   1577:         OleDbgOutHResult("IOleLink::GetSourceDisplayName returned", hrErr);
                   1578:         OLEDBG_END2
                   1579:         return hrErr;
                   1580:     }
                   1581: 
                   1582:     OLEDBG_END2
                   1583:         
                   1584:     if (lpfIsSelected)
                   1585:         *lpfIsSelected = Line_IsSelected((LPLINE)lpContainerLine);
                   1586: 
                   1587:     return NOERROR;
                   1588: }
                   1589: 
                   1590: 
                   1591: STDMETHODIMP CntrDoc_LinkCont_OpenLinkSource(
                   1592:         LPOLEUILINKCONTAINER    lpThis,
                   1593:         DWORD                   dwLink
                   1594: )
                   1595: {
                   1596:     LPCONTAINERDOC lpContainerDoc =
                   1597:             ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc;
                   1598:     LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink;
                   1599:     SCODE sc = S_OK;
                   1600: 
                   1601:     OLEDBG_BEGIN2("CntrDoc_LinkCont_OpenLinkSource\r\n")
                   1602: 
                   1603:     OleDbgAssert(lpContainerLine);
                   1604: 
                   1605:     if (! ContainerLine_DoVerb(lpContainerLine, OLEIVERB_SHOW, TRUE, FALSE)) {
                   1606:         OutlineApp_ErrorMessage(g_lpApp, ErrMsgShowObj);
                   1607:         sc = E_FAIL;
                   1608:     }
                   1609:        
                   1610:        lpContainerLine->m_fLinkUnavailable = (sc != S_OK);
                   1611: 
                   1612:     OLEDBG_END2
                   1613:     return ResultFromScode(sc);
                   1614: }
                   1615: 
                   1616: 
                   1617: STDMETHODIMP CntrDoc_LinkCont_UpdateLink(
                   1618:         LPOLEUILINKCONTAINER    lpThis,
                   1619:         DWORD                   dwLink,
                   1620:                BOOL                                    fErrorMessage,
                   1621:                BOOL                                    fErrorAction            // ignore if fErrorMessage
                   1622:                                                                                                        //              is FALSE
                   1623: )
                   1624: {
                   1625:     LPCONTAINERDOC lpContainerDoc =
                   1626:             ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc;
                   1627:     LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink;
                   1628:     SCODE sc = S_OK;
                   1629:     HRESULT hrErr;
                   1630: 
                   1631:     OLEDBG_BEGIN2("CntrDoc_LinkCont_UpdateLink\r\n")
                   1632: 
                   1633:     OleDbgAssert(lpContainerLine);
                   1634: 
                   1635:     if (! lpContainerLine->m_lpOleObj)
                   1636:         ContainerLine_LoadOleObject(lpContainerLine);
                   1637: 
                   1638:        if (!fErrorMessage) {
                   1639:                OLEDBG_BEGIN2("IOleObject::IsUpToDate called\r\n")
                   1640:                hrErr = lpContainerLine->m_lpOleObj->lpVtbl->IsUpToDate(
                   1641:                                lpContainerLine->m_lpOleObj
                   1642:                );
                   1643:                OLEDBG_END2
                   1644:        }       
                   1645:        
                   1646:        if (hrErr != NOERROR) {
                   1647:                OLEDBG_BEGIN2("IOleObject::Update called\r\n")
                   1648:                hrErr = lpContainerLine->m_lpOleObj->lpVtbl->Update(
                   1649:                                lpContainerLine->m_lpOleObj
                   1650:                );
                   1651:                OLEDBG_END2
                   1652:        }
                   1653: 
                   1654:        lpContainerLine->m_fLinkUnavailable = (hrErr != NOERROR);
                   1655:                
                   1656:     if (hrErr != NOERROR) {
                   1657:         OleDbgOutHResult("IOleObject::Update returned", hrErr);
                   1658:         sc = GetScode(hrErr);
                   1659:                if (fErrorMessage)
                   1660:                        ProcessError(hrErr, lpContainerLine, fErrorAction);
                   1661:     }
                   1662:     /* OLE2NOTE: if the update of the object requires us to update our
                   1663:     **    display, then we will automatically be sent a OnViewChange
                   1664:     **    advise. thus we do not need to take any action here to force
                   1665:     **    a repaint.
                   1666:     */
                   1667: 
                   1668:     OLEDBG_END2
                   1669:     return ResultFromScode(sc);
                   1670: }
                   1671: 
                   1672: 
                   1673: /* CntrDoc_LinkCont_CancelLink
                   1674: ** ---------------------------
                   1675: **    Convert the link to a static picture.
                   1676: **    
                   1677: **    OLE2NOTE: OleCreateStaticFromData can be used to create a static
                   1678: **    picture object.
                   1679: */
                   1680: STDMETHODIMP CntrDoc_LinkCont_CancelLink(
                   1681:         LPOLEUILINKCONTAINER    lpThis,
                   1682:         DWORD                   dwLink
                   1683: )
                   1684: {
                   1685:     LPCONTAINERDOC lpContainerDoc =
                   1686:             ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc;
                   1687:        LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink;
                   1688:     LPLINELIST          lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
                   1689:     LPLINE              lpLine = NULL;
                   1690:     HDC                 hDC;
                   1691:     int                 nTab = 0;
                   1692:     char                szStgName[CWCSTORAGENAME];
                   1693:     LPCONTAINERLINE     lpNewContainerLine = NULL;
                   1694:     LPDATAOBJECT        lpSrcDataObj;
                   1695:     LPOLELINK           lpOleLink;
                   1696:     int nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine);
                   1697: 
                   1698:     OLEDBG_BEGIN2("CntrDoc_LinkCont_CancelLink\r\n")
                   1699: 
                   1700:     /* we will first break the connection of the link to its source. */
                   1701:     lpOleLink = (LPOLELINK)ContainerLine_GetOleObject(
                   1702:             lpContainerLine,
                   1703:             &IID_IOleLink
                   1704:     );
                   1705:     if (lpOleLink) {
                   1706:         OLEDBG_BEGIN2("IOleLink::SetSourceMoniker called\r\n")
                   1707:         lpOleLink->lpVtbl->SetSourceMoniker(
                   1708:                 lpOleLink, NULL, (REFCLSID)&CLSID_NULL);
                   1709:         OLEDBG_END2
                   1710:         OleStdRelease((LPUNKNOWN)lpOleLink);
                   1711:     }
                   1712:         
                   1713:     lpSrcDataObj = (LPDATAOBJECT)ContainerLine_GetOleObject(
                   1714:             lpContainerLine,&IID_IDataObject);
                   1715:     if (! lpSrcDataObj) 
                   1716:         goto error;
                   1717: 
                   1718:     ContainerDoc_GetNextStgName(lpContainerDoc, szStgName, sizeof(szStgName));
                   1719:     nTab = Line_GetTabLevel((LPLINE)lpContainerLine);
                   1720:     hDC = LineList_GetDC(lpLL);
                   1721: 
                   1722:     lpNewContainerLine = ContainerLine_CreateFromData(
                   1723:             hDC,
                   1724:             nTab,
                   1725:             lpContainerDoc,
                   1726:             lpSrcDataObj,
                   1727:             OLECREATEFROMDATA_STATIC,
                   1728:             0,   /* no special cfFormat required */
                   1729:             FALSE,  /* fDisplayAsIcon */
                   1730:             NULL,   /* hMetaPict */
                   1731:             szStgName
                   1732:     );
                   1733:     LineList_ReleaseDC(lpLL, hDC);
                   1734: 
                   1735:     OleStdRelease((LPUNKNOWN)lpSrcDataObj);
                   1736: 
                   1737:     if (! lpNewContainerLine)
                   1738:         goto error;
                   1739:        
                   1740:     OutlineDoc_SetModified((LPOUTLINEDOC)lpContainerDoc, TRUE, TRUE, FALSE);
                   1741: 
                   1742:     LineList_ReplaceLine(lpLL, (LPLINE)lpNewContainerLine, nIndex);
                   1743: 
                   1744:     OLEDBG_END2
                   1745:        return ResultFromScode(NOERROR);
                   1746: 
                   1747: error:
                   1748:     OutlineApp_ErrorMessage(g_lpApp, "Could not break the link.");
                   1749:     OLEDBG_END2
                   1750:     return ResultFromScode(E_FAIL);
                   1751: }

unix.superglobalmegacorp.com

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