|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.