|
|
1.1 ! root 1: /************************************************************************* ! 2: ** ! 3: ** OLE 2 Server Sample Code ! 4: ** ! 5: ** svrbase.c ! 6: ** ! 7: ** This file contains all interfaces, methods and related support ! 8: ** functions for the basic OLE Object (Server) application. The ! 9: ** basic OLE Object application supports embedding an object and ! 10: ** linking to a file-based or embedded object as a whole. The basic ! 11: ** Object application includes the following implementation objects: ! 12: ** ! 13: ** ClassFactory (aka. ClassObject) Object (see file classfac.c) ! 14: ** exposed interfaces: ! 15: ** IClassFactory interface ! 16: ** ! 17: ** ServerDoc Object ! 18: ** exposed interfaces: ! 19: ** IUnknown ! 20: ** IOleObject interface ! 21: ** IPersistStorage interface ! 22: ** IDataObject interface ! 23: ** ! 24: ** ServerApp Object ! 25: ** exposed interfaces: ! 26: ** IUnknown ! 27: ** ! 28: ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved ! 29: ** ! 30: *************************************************************************/ ! 31: ! 32: ! 33: #include "outline.h" ! 34: #include <regdb.h> ! 35: #include <enumfetc.h> ! 36: #include <geticon.h> ! 37: ! 38: OLEDBGDATA ! 39: ! 40: extern LPOUTLINEAPP g_lpApp; ! 41: extern IOleObjectVtbl g_SvrDoc_OleObjectVtbl; ! 42: extern IPersistStorageVtbl g_SvrDoc_PersistStorageVtbl; ! 43: ! 44: #if defined( INPLACE_SVR ) ! 45: extern IOleInPlaceObjectVtbl g_SvrDoc_OleInPlaceObjectVtbl; ! 46: extern IOleInPlaceActiveObjectVtbl g_SvrDoc_OleInPlaceActiveObjectVtbl; ! 47: #endif // INPLACE_SVR ! 48: ! 49: #if defined( SVR_TREATAS ) ! 50: extern IStdMarshalInfoVtbl g_SvrDoc_StdMarshalInfoVtbl; ! 51: #endif // SVR_TREATAS ! 52: ! 53: ! 54: // REVIEW: should use string resource for messages ! 55: extern char ErrMsgSaving[]; ! 56: extern char ErrMsgFormatNotSupported[]; ! 57: static char ErrMsgPSSaveFail[] = "PSSave failed"; ! 58: extern char g_szUpdateCntrDoc[] = "&Update %s"; ! 59: extern char g_szExitNReturnToCntrDoc[] = "E&xit && Return to %s"; ! 60: ! 61: ! 62: /************************************************************************* ! 63: ** ServerDoc::IOleObject interface implementation ! 64: *************************************************************************/ ! 65: ! 66: // IOleObject::QueryInterface method ! 67: ! 68: STDMETHODIMP SvrDoc_OleObj_QueryInterface( ! 69: LPOLEOBJECT lpThis, ! 70: REFIID riid, ! 71: LPVOID FAR* lplpvObj ! 72: ) ! 73: { ! 74: LPSERVERDOC lpServerDoc = ! 75: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 76: ! 77: return OleDoc_QueryInterface((LPOLEDOC)lpServerDoc, riid, lplpvObj); ! 78: } ! 79: ! 80: ! 81: // IOleObject::AddRef method ! 82: ! 83: STDMETHODIMP_(ULONG) SvrDoc_OleObj_AddRef(LPOLEOBJECT lpThis) ! 84: { ! 85: LPSERVERDOC lpServerDoc = ! 86: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 87: ! 88: OleDbgAddRefMethod(lpThis, "IOleObject"); ! 89: ! 90: return OleDoc_AddRef((LPOLEDOC)lpServerDoc); ! 91: } ! 92: ! 93: ! 94: // IOleObject::Release method ! 95: ! 96: STDMETHODIMP_(ULONG) SvrDoc_OleObj_Release(LPOLEOBJECT lpThis) ! 97: { ! 98: LPSERVERDOC lpServerDoc = ! 99: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 100: ! 101: OleDbgReleaseMethod(lpThis, "IOleObject"); ! 102: ! 103: return OleDoc_Release((LPOLEDOC)lpServerDoc); ! 104: } ! 105: ! 106: ! 107: // IOleObject::SetClientSite method ! 108: ! 109: STDMETHODIMP SvrDoc_OleObj_SetClientSite( ! 110: LPOLEOBJECT lpThis, ! 111: LPOLECLIENTSITE lpclientSite ! 112: ) ! 113: { ! 114: LPSERVERDOC lpServerDoc = ! 115: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 116: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 117: ! 118: OLEDBG_BEGIN2("SvrDoc_OleObj_SetClientSite\r\n") ! 119: ! 120: // SetClientSite is only valid to call on an embedded object ! 121: if (lpOutlineDoc->m_docInitType != DOCTYPE_EMBEDDED) { ! 122: OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED); ! 123: OLEDBG_END2 ! 124: return ResultFromScode(E_UNEXPECTED); ! 125: } ! 126: ! 127: /* if we currently have a client site ptr, then release it. */ ! 128: if (lpServerDoc->m_lpOleClientSite) ! 129: OleStdRelease((LPUNKNOWN)lpServerDoc->m_lpOleClientSite); ! 130: ! 131: lpServerDoc->m_lpOleClientSite = (LPOLECLIENTSITE) lpclientSite; ! 132: // OLE2NOTE: to be able to hold onto clientSite pointer, we must AddRef it ! 133: if (lpclientSite) ! 134: lpclientSite->lpVtbl->AddRef(lpclientSite); ! 135: ! 136: OLEDBG_END2 ! 137: return NOERROR; ! 138: } ! 139: ! 140: ! 141: // IOleObject::GetClientSite method ! 142: ! 143: STDMETHODIMP SvrDoc_OleObj_GetClientSite( ! 144: LPOLEOBJECT lpThis, ! 145: LPOLECLIENTSITE FAR* lplpClientSite ! 146: ) ! 147: { ! 148: LPSERVERDOC lpServerDoc = ! 149: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 150: ! 151: OleDbgOut2("SvrDoc_OleObj_GetClientSite\r\n"); ! 152: ! 153: /* OLE2NOTE: we MUST AddRef this interface pointer to give the ! 154: ** caller a personal copy of the pointer ! 155: */ ! 156: lpServerDoc->m_lpOleClientSite->lpVtbl->AddRef( ! 157: lpServerDoc->m_lpOleClientSite ! 158: ); ! 159: *lplpClientSite = lpServerDoc->m_lpOleClientSite; ! 160: ! 161: return NOERROR; ! 162: ! 163: } ! 164: ! 165: ! 166: // IOleObject::SetHostNames method ! 167: ! 168: STDMETHODIMP SvrDoc_OleObj_SetHostNames( ! 169: LPOLEOBJECT lpThis, ! 170: LPCSTR szContainerApp, ! 171: LPCSTR szContainerObj ! 172: ) ! 173: { ! 174: LPSERVERDOC lpServerDoc = ! 175: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 176: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 177: ! 178: OleDbgOut2("SvrDoc_OleObj_SetHostNames\r\n"); ! 179: ! 180: lstrcpy((LPSTR)lpServerDoc->m_szContainerApp, szContainerApp); ! 181: lstrcpy((LPSTR)lpServerDoc->m_szContainerObj, szContainerObj); ! 182: ! 183: /* The Window title for an embedded object is constructed as ! 184: ** follows: ! 185: ** <server app name> - <obj short type> in <cont. doc name> ! 186: ** ! 187: ** here we construct the current document title portion of the ! 188: ** name which follows the '-'. OutlineDoc_SetTitle prepends the ! 189: ** "<server app name> - " to the document title. ! 190: */ ! 191: // REVIEW: this string should be loaded from string resource ! 192: wsprintf(lpOutlineDoc->m_szFileName, "%s in %s", ! 193: (LPSTR)SHORTUSERTYPENAME, (LPSTR)lpServerDoc->m_szContainerObj); ! 194: ! 195: lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName; ! 196: OutlineDoc_SetTitle(lpOutlineDoc); ! 197: ! 198: /* OLE2NOTE: update the application menus correctly for an embedded ! 199: ** object. the changes include: ! 200: ** 1 Remove File/New and File/Open (SDI ONLY) ! 201: ** 2 Change File/Save As.. to File/Save Copy As.. ! 202: ** 3 Change File menu so it contains "Update" instead of "Save" ! 203: ** 4 Change File/Exit to File/Exit & Return to <client doc>" ! 204: */ ! 205: ServerDoc_UpdateMenu(lpServerDoc); ! 206: ! 207: return NOERROR; ! 208: } ! 209: ! 210: ! 211: // IOleObject::Close method ! 212: ! 213: STDMETHODIMP SvrDoc_OleObj_Close( ! 214: LPOLEOBJECT lpThis, ! 215: DWORD dwSaveOption ! 216: ) ! 217: { ! 218: LPSERVERDOC lpServerDoc = ! 219: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 220: BOOL fStatus; ! 221: ! 222: OLEDBG_BEGIN2("SvrDoc_OleObj_Close\r\n") ! 223: ! 224: // REVIEW: dwSaveOption not yet supported ! 225: ! 226: /* OLE2NOTE: the OLE 2.0 user model is that embedded objects should ! 227: ** always be saved when closed WITHOUT any prompting to the ! 228: ** user. this is the recommendation irregardless of whether the ! 229: ** object is activated in-place or open in its own window. ! 230: ** this is a CHANGE from the OLE 1.0 user model where it ! 231: ** was the guideline that servers always prompt to save changes. ! 232: ** thus OLE 2.0 compound document oriented container's should ! 233: ** always pass dwSaveOption==OLECLOSE_SAVEIFDIRTY. it is ! 234: ** possible that for programmatic uses a container may want to ! 235: ** specify a different dwSaveOption. the implementation of ! 236: ** various save options can be tricky, particularly considering ! 237: ** cases involving in-place activation. the following would be ! 238: ** reasonable behavior: ! 239: ** ! 240: ** (1) OLECLOSE_SAVEIFDIRTY: if dirty, save. close. ! 241: ** (2) OLECLOSE_NOSAVE: close. ! 242: ** (3) OLECLOSE_PROMPTSAVE: ! 243: ** (a) object visible, but not in-place: ! 244: ** if not dirty, close. ! 245: ** switch(prompt) ! 246: ** case IDYES: save. close. ! 247: ** case IDNO: close. ! 248: ** case IDCANCEL: return OLE_E_PROMPTSAVECANCELLED ! 249: ** (b) object invisible (includes UIDeactivated object) ! 250: ** if dirty, save. close. ! 251: ** NOTE: NO PROMPT. it is not appropriate to prompt ! 252: ** if the object is not visible. ! 253: ** (c) object is in-place active: ! 254: ** if dirty, save. close. ! 255: ** NOTE: NO PROMPT. it is not appropriate to prompt ! 256: ** if the object is active in-place. ! 257: */ ! 258: ! 259: fStatus = OutlineDoc_Close((LPOUTLINEDOC)lpServerDoc, dwSaveOption); ! 260: OleDbgAssertSz(fStatus == TRUE, "SvrDoc_OleObj_Close failed\r\n"); ! 261: ! 262: OLEDBG_END2 ! 263: return (fStatus ? NOERROR : ResultFromScode(E_FAIL)); ! 264: } ! 265: ! 266: ! 267: // IOleObject::SetMoniker method ! 268: ! 269: STDMETHODIMP SvrDoc_OleObj_SetMoniker( ! 270: LPOLEOBJECT lpThis, ! 271: DWORD dwWhichMoniker, ! 272: LPMONIKER lpmk ! 273: ) ! 274: { ! 275: LPSERVERDOC lpServerDoc = ! 276: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 277: LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; ! 278: LPMONIKER lpmkFull; ! 279: HRESULT hrErr; ! 280: SCODE sc; ! 281: ! 282: OLEDBG_BEGIN2("SvrDoc_OleObj_SetMoniker\r\n") ! 283: ! 284: /* only our container should call IOleObject::SetMoniker. if we ! 285: ** don't have a ClientSite assigned then ignore this attempt to ! 286: ** set our moniker. ! 287: */ ! 288: if (lpServerDoc->m_lpOleClientSite == NULL) { ! 289: sc = E_FAIL; ! 290: goto error; ! 291: } ! 292: ! 293: /* retrieve our full, absolute moniker from our container. the ! 294: ** moniker passed to the current method is either the relative ! 295: ** moniker of the object or the moniker of our container. we ! 296: ** require the full moniker in order to register as running. ! 297: */ ! 298: hrErr = lpServerDoc->m_lpOleClientSite->lpVtbl->GetMoniker( ! 299: lpServerDoc->m_lpOleClientSite, ! 300: OLEGETMONIKER_ONLYIFTHERE, ! 301: OLEWHICHMK_OBJFULL, ! 302: &lpmkFull ! 303: ); ! 304: if (hrErr != NOERROR) { ! 305: sc = GetScode(hrErr); ! 306: goto error; ! 307: } ! 308: ! 309: /* Register the document as running with the new moniker and ! 310: ** notify any clients that our moniker has changed. ! 311: */ ! 312: OleDoc_DocRenamedUpdate(lpOleDoc, lpmkFull); ! 313: ! 314: if (lpmkFull) ! 315: OleStdRelease((LPUNKNOWN)lpmkFull); ! 316: ! 317: OLEDBG_END2 ! 318: return NOERROR; ! 319: ! 320: error: ! 321: OLEDBG_END2 ! 322: return ResultFromScode(sc); ! 323: } ! 324: ! 325: ! 326: // IOleObject::GetMoniker method ! 327: ! 328: STDMETHODIMP SvrDoc_OleObj_GetMoniker( ! 329: LPOLEOBJECT lpThis, ! 330: DWORD dwAssign, ! 331: DWORD dwWhichMoniker, ! 332: LPMONIKER FAR* lplpmk ! 333: ) ! 334: { ! 335: LPSERVERDOC lpServerDoc = ! 336: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 337: HRESULT hrErr; ! 338: SCODE sc; ! 339: ! 340: OLEDBG_BEGIN2("SvrDoc_OleObj_GetMoniker\r\n") ! 341: ! 342: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ ! 343: *lplpmk = NULL; ! 344: ! 345: if (lpServerDoc->m_lpOleClientSite != NULL) { ! 346: OleDbgAssert(((LPOUTLINEDOC)lpServerDoc)->m_docInitType==DOCTYPE_EMBEDDED); ! 347: ! 348: /* document is an embedded object. retrieve our moniker from ! 349: ** our container. ! 350: */ ! 351: OLEDBG_BEGIN2("IOleClientSite::GetMoniker called\r\n") ! 352: hrErr = lpServerDoc->m_lpOleClientSite->lpVtbl->GetMoniker( ! 353: lpServerDoc->m_lpOleClientSite, ! 354: dwAssign, ! 355: dwWhichMoniker, ! 356: lplpmk ! 357: ); ! 358: OLEDBG_END2 ! 359: ! 360: } else if (((LPOUTLINEDOC)lpServerDoc)->m_docInitType == DOCTYPE_FROMFILE) { ! 361: ! 362: // document is a file-based document => return a FileMoniker ! 363: hrErr = CreateFileMoniker( ! 364: ((LPOUTLINEDOC)lpServerDoc)->m_szFileName, ! 365: lplpmk ! 366: ); ! 367: ! 368: } else { ! 369: // document is either New or not yet fully initialized => no moniker ! 370: sc = E_FAIL; ! 371: goto error; ! 372: } ! 373: ! 374: OLEDBG_END2 ! 375: return hrErr; ! 376: ! 377: error: ! 378: OLEDBG_END2 ! 379: return ResultFromScode(sc); ! 380: } ! 381: ! 382: ! 383: // IOleObject::InitFromData method ! 384: ! 385: STDMETHODIMP SvrDoc_OleObj_InitFromData( ! 386: LPOLEOBJECT lpThis, ! 387: LPDATAOBJECT lpDataObject, ! 388: BOOL fCreation, ! 389: DWORD reserved ! 390: ) ! 391: { ! 392: LPSERVERDOC lpServerDoc = ! 393: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 394: ! 395: OLEDBG_BEGIN2("SvrDoc_OleObj_InitFromData\r\n") ! 396: ! 397: // REVIEW: NOT YET IMPLEMENTED ! 398: ! 399: OLEDBG_END2 ! 400: return ResultFromScode(E_NOTIMPL); ! 401: } ! 402: ! 403: ! 404: // IOleObject::GetClipboardData method ! 405: ! 406: STDMETHODIMP SvrDoc_OleObj_GetClipboardData( ! 407: LPOLEOBJECT lpThis, ! 408: DWORD reserved, ! 409: LPDATAOBJECT FAR* lplpDataObject ! 410: ) ! 411: { ! 412: LPSERVERDOC lpServerDoc = ! 413: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 414: ! 415: OLEDBG_BEGIN2("SvrDoc_OleObj_GetClipboardData\r\n") ! 416: ! 417: // REVIEW: NOT YET IMPLEMENTED ! 418: ! 419: OLEDBG_END2 ! 420: return ResultFromScode(E_NOTIMPL); ! 421: } ! 422: ! 423: ! 424: // IOleObject::DoVerb method ! 425: ! 426: STDMETHODIMP SvrDoc_OleObj_DoVerb( ! 427: LPOLEOBJECT lpThis, ! 428: LONG lVerb, ! 429: LPMSG lpmsg, ! 430: LPOLECLIENTSITE lpActiveSite, ! 431: LONG lindex, ! 432: HWND hwndParent, ! 433: LPCRECT lprcPosRect ! 434: ) ! 435: { ! 436: LPSERVERDOC lpServerDoc = ! 437: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 438: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 439: SCODE sc = S_OK; ! 440: ! 441: OLEDBG_BEGIN2("SvrDoc_OleObj_DoVerb\r\n") ! 442: ! 443: switch (lVerb) { ! 444: ! 445: default: ! 446: /* OLE2NOTE: when an unknown verb number is given, the ! 447: ** server must take careful action: ! 448: ** 1. if it is one of the specially defined OLEIVERB ! 449: ** (negative numbered) verbs, the app should return an ! 450: ** error (E_NOTIMPL) and perform no action. ! 451: ** ! 452: ** 2. if the verb is a application specific verb ! 453: ** (positive numbered verb), then the app should ! 454: ** return the special scode (OLEOBJ_S_INVALIDVERB). BUT, ! 455: ** we should still perform our normal primary verb action. ! 456: */ ! 457: if (lVerb < 0) { ! 458: OLEDBG_END2 ! 459: return ResultFromScode(E_NOTIMPL); ! 460: } else { ! 461: sc = OLEOBJ_S_INVALIDVERB; ! 462: } ! 463: ! 464: // deliberatly fall through to Primary Verb ! 465: ! 466: case 0: ! 467: case OLEIVERB_SHOW: ! 468: ! 469: #if defined( INPLACE_SVR ) ! 470: /* OLE2NOTE: if our window is already open (visible) then ! 471: ** we should simply surface the open window. if not, ! 472: ** then we can do our primary action of in-place ! 473: ** activation. ! 474: */ ! 475: if ( lpServerDoc->m_lpOleClientSite ! 476: && ! (IsWindowVisible(lpOutlineDoc->m_hWndDoc) && ! 477: ! lpServerDoc->m_fInPlaceActive) ) { ! 478: ServerDoc_DoInPlaceActivate( ! 479: lpServerDoc, lVerb, lpmsg, lpActiveSite); ! 480: } ! 481: #endif // INPLACE_SVR ! 482: ! 483: OutlineDoc_ShowWindow(lpOutlineDoc); ! 484: break; ! 485: ! 486: case 1: ! 487: case OLEIVERB_OPEN: ! 488: #if defined( INPLACE_SVR ) ! 489: ServerDoc_DoInPlaceDeactivate(lpServerDoc); ! 490: #endif // INPLACE_SVR ! 491: OutlineDoc_ShowWindow(lpOutlineDoc); ! 492: break; ! 493: ! 494: ! 495: case OLEIVERB_HIDE: ! 496: #if defined( INPLACE_SVR ) ! 497: if (lpServerDoc->m_fInPlaceActive) { ! 498: ! 499: SvrDoc_IPObj_UIDeactivate( ! 500: (LPOLEINPLACEOBJECT)&lpServerDoc->m_OleInPlaceObject); ! 501: ! 502: #if defined( SVR_INSIDEOUT ) ! 503: /* OLE2NOTE: an inside-out style in-place server will ! 504: ** NOT hide its window in UIDeactive (an outside-in ! 505: ** style object will hide its window in ! 506: ** UIDeactivate). thus we need to explicitly hide ! 507: ** our window now. ! 508: */ ! 509: ServerDoc_DoInPlaceHide(lpServerDoc); ! 510: #endif // INSIEDOUT ! 511: ! 512: } else { ! 513: OleDoc_HideWindow((LPOLEDOC)lpServerDoc, FALSE /*fShutdown*/); ! 514: } ! 515: #endif // INPLACE_SVR ! 516: break; ! 517: ! 518: #if defined( INPLACE_SVR ) ! 519: case OLEIVERB_UIACTIVATE: ! 520: ! 521: #if defined( SVR_INSIDEOUT ) ! 522: /* OLE2NOTE: only an inside-out style object supports ! 523: ** INPLACEACTIVATE verb ! 524: */ ! 525: case OLEIVERB_INPLACEACTIVATE: ! 526: #endif // INSIEDOUT ! 527: /* OLE2NOTE: if our window is already open (visible) then ! 528: ** we can NOT activate in-place. ! 529: */ ! 530: if (IsWindowVisible(lpOutlineDoc->m_hWndDoc) && ! 531: ! lpServerDoc->m_fInPlaceActive ) { ! 532: sc = OLE_E_NOT_INPLACEACTIVE; ! 533: } else { ! 534: sc = GetScode( ServerDoc_DoInPlaceActivate( ! 535: lpServerDoc, lVerb, lpmsg, lpActiveSite) ); ! 536: if (SUCCEEDED(sc)) ! 537: OutlineDoc_ShowWindow(lpOutlineDoc); ! 538: } ! 539: break; ! 540: #endif // INPLACE_SVR ! 541: } ! 542: ! 543: OLEDBG_END2 ! 544: return ResultFromScode(sc); ! 545: } ! 546: ! 547: ! 548: // IOleObject::EnumVerbs method ! 549: ! 550: STDMETHODIMP SvrDoc_OleObj_EnumVerbs( ! 551: LPOLEOBJECT lpThis, ! 552: LPENUMOLEVERB FAR* lplpenumOleVerb ! 553: ) ! 554: { ! 555: OleDbgOut2("SvrDoc_OleObj_EnumVerbs\r\n"); ! 556: ! 557: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ ! 558: *lplpenumOleVerb = NULL; ! 559: ! 560: // Tell OLE to enumerate our verbs using the REGDB ! 561: return ResultFromScode(OLE_S_USEREG); ! 562: } ! 563: ! 564: ! 565: // IOleObject::Update method ! 566: ! 567: STDMETHODIMP SvrDoc_OleObj_Update(LPOLEOBJECT lpThis) ! 568: { ! 569: OleDbgOut2("SvrDoc_OleObj_Update\r\n"); ! 570: ! 571: /* OLE2NOTE: a server-only app is always "up-to-date". ! 572: ** a container-app which contains links where the link source ! 573: ** has changed since the last update of the link would be ! 574: ** considered "out-of-date". the "Update" method instructs the ! 575: ** object to get an update from any out-of-date links. ! 576: */ ! 577: ! 578: return NOERROR; ! 579: } ! 580: ! 581: ! 582: // IOleObject::IsUpToDate method ! 583: ! 584: STDMETHODIMP SvrDoc_OleObj_IsUpToDate(LPOLEOBJECT lpThis) ! 585: { ! 586: OleDbgOut2("SvrDoc_OleObj_IsUpToDate\r\n"); ! 587: ! 588: /* OLE2NOTE: a server-only app is always "up-to-date". ! 589: ** a container-app which contains links where the link source ! 590: ** has changed since the last update of the link would be ! 591: ** considered "out-of-date". ! 592: */ ! 593: return NOERROR; ! 594: } ! 595: ! 596: ! 597: // IOleObject::GetUserClassID method ! 598: ! 599: STDMETHODIMP SvrDoc_OleObj_GetUserClassID( ! 600: LPOLEOBJECT lpThis, ! 601: LPCLSID lpClassID ! 602: ) ! 603: { ! 604: LPSERVERDOC lpServerDoc = ! 605: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 606: ! 607: OleDbgOut2("SvrDoc_OleObj_GetClassID\r\n"); ! 608: ! 609: /* OLE2NOTE: we must be carefull to return the correct CLSID here. ! 610: ** if we are currently preforming a "TreatAs (aka. ActivateAs)" ! 611: ** operation then we need to return the class of the object ! 612: ** written in the storage of the object. otherwise we would ! 613: ** return our own class id. ! 614: */ ! 615: return ServerDoc_GetClassID(lpServerDoc, lpClassID); ! 616: } ! 617: ! 618: ! 619: // IOleObject::GetUserType method ! 620: ! 621: STDMETHODIMP SvrDoc_OleObj_GetUserType( ! 622: LPOLEOBJECT lpThis, ! 623: DWORD dwFormOfType, ! 624: LPSTR FAR* lpszUserType ! 625: ) ! 626: { ! 627: OleDbgOut2("SvrDoc_OleObj_GetUserType\r\n"); ! 628: ! 629: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ ! 630: *lpszUserType = NULL; ! 631: ! 632: // Tell OLE to enumerate our verbs using the REGDB ! 633: return ResultFromScode(OLE_S_USEREG); ! 634: ! 635: #if defined( LATER ) ! 636: LPSERVERDOC lpServerDoc = ! 637: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 638: ! 639: /* OLE2NOTE: we must be carefull to return the correct UserType here. ! 640: ** if we are currently preforming a "TreatAs (aka. ActivateAs)" ! 641: ** operation then we need to return the UserType of the object ! 642: ** written in the storage of the object. otherwise we would ! 643: ** return our own UserType. ! 644: */ ! 645: return ServerDoc_GetUserType(lpServerDoc, dwFormOfType, lpszUserType); ! 646: #endif ! 647: } ! 648: ! 649: ! 650: // IOleObject::SetExtent method ! 651: ! 652: STDMETHODIMP SvrDoc_OleObj_SetExtent( ! 653: LPOLEOBJECT lpThis, ! 654: DWORD dwDrawAspect, ! 655: LPSIZEL lplgrc ! 656: ) ! 657: { ! 658: OleDbgOut2("SvrDoc_OleObj_SetExtent\r\n"); ! 659: ! 660: /* SVROUTL does NOT allow the object's size to be set by its ! 661: ** container. the size of the ServerDoc object is determined by ! 662: ** the data contained within the document. ! 663: */ ! 664: return ResultFromScode(S_FALSE); ! 665: } ! 666: ! 667: ! 668: // IOleObject::GetExtent method ! 669: ! 670: STDMETHODIMP SvrDoc_OleObj_GetExtent( ! 671: LPOLEOBJECT lpThis, ! 672: DWORD dwDrawAspect, ! 673: LPSIZEL lpsizel ! 674: ) ! 675: { ! 676: LPOLEDOC lpOleDoc = ! 677: (LPOLEDOC)((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 678: ! 679: OleDbgOut2("SvrDoc_OleObj_GetExtent\r\n"); ! 680: ! 681: if (dwDrawAspect == DVASPECT_CONTENT ! 682: || dwDrawAspect == DVASPECT_THUMBNAIL ! 683: || dwDrawAspect == DVASPECT_DOCPRINT) ! 684: { ! 685: OleDoc_GetExtent(lpOleDoc, lpsizel); ! 686: return NOERROR; ! 687: } ! 688: ! 689: #if defined( LATER ) ! 690: ! 691: else if (dwDrawAspect == DVASPECT_THUMBNAIL) ! 692: { ! 693: /* as our thumbnail we will render only the first page of the ! 694: ** document. calculate extents of our thumbnail rendering. ! 695: ** ! 696: ** OLE2NOTE: thumbnails are most often used by applications in ! 697: ** FindFile or FileOpen type dialogs to give the user a ! 698: ** quick view of the contents of the file or object. ! 699: */ ! 700: OleDoc_GetThumbnailExtent(lpOleDoc, lpsizel); ! 701: return NOERROR; ! 702: } ! 703: #endif ! 704: ! 705: else ! 706: { ! 707: return ResultFromScode(E_INVALIDARG); ! 708: } ! 709: } ! 710: ! 711: ! 712: // IOleObject::Advise method ! 713: ! 714: STDMETHODIMP SvrDoc_OleObj_Advise( ! 715: LPOLEOBJECT lpThis, ! 716: LPADVISESINK lpAdvSink, ! 717: LPDWORD lpdwConnection ! 718: ) ! 719: { ! 720: LPSERVERDOC lpServerDoc = ! 721: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 722: HRESULT hrErr; ! 723: SCODE sc; ! 724: ! 725: OLEDBG_BEGIN2("SvrDoc_OleObj_Advise\r\n"); ! 726: ! 727: if (lpServerDoc->m_lpOleAdviseHldr == NULL && ! 728: CreateOleAdviseHolder(&lpServerDoc->m_lpOleAdviseHldr) != NOERROR) { ! 729: sc = E_OUTOFMEMORY; ! 730: goto error; ! 731: } ! 732: ! 733: OLEDBG_BEGIN2("IOleAdviseHolder::Advise called\r\n") ! 734: hrErr = lpServerDoc->m_lpOleAdviseHldr->lpVtbl->Advise( ! 735: lpServerDoc->m_lpOleAdviseHldr, ! 736: lpAdvSink, ! 737: lpdwConnection ! 738: ); ! 739: OLEDBG_END2 ! 740: ! 741: OLEDBG_END2 ! 742: return hrErr; ! 743: ! 744: error: ! 745: OLEDBG_END2 ! 746: return ResultFromScode(sc); ! 747: } ! 748: ! 749: ! 750: // IOleObject::Unadvise method ! 751: ! 752: STDMETHODIMP SvrDoc_OleObj_Unadvise(LPOLEOBJECT lpThis, DWORD dwConnection) ! 753: { ! 754: LPSERVERDOC lpServerDoc = ! 755: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 756: HRESULT hrErr; ! 757: SCODE sc; ! 758: ! 759: OLEDBG_BEGIN2("SvrDoc_OleObj_Unadvise\r\n"); ! 760: ! 761: if (lpServerDoc->m_lpOleAdviseHldr == NULL) { ! 762: sc = E_FAIL; ! 763: goto error; ! 764: } ! 765: ! 766: OLEDBG_BEGIN2("IOleAdviseHolder::Unadvise called\r\n") ! 767: hrErr = lpServerDoc->m_lpOleAdviseHldr->lpVtbl->Unadvise( ! 768: lpServerDoc->m_lpOleAdviseHldr, ! 769: dwConnection ! 770: ); ! 771: OLEDBG_END2 ! 772: ! 773: OLEDBG_END2 ! 774: return hrErr; ! 775: ! 776: error: ! 777: OLEDBG_END2 ! 778: return ResultFromScode(sc); ! 779: } ! 780: ! 781: ! 782: // IOleObject::EnumAdvise method ! 783: ! 784: STDMETHODIMP SvrDoc_OleObj_EnumAdvise( ! 785: LPOLEOBJECT lpThis, ! 786: LPENUMSTATDATA FAR* lplpenumAdvise ! 787: ) ! 788: { ! 789: LPSERVERDOC lpServerDoc = ! 790: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 791: HRESULT hrErr; ! 792: SCODE sc; ! 793: ! 794: OLEDBG_BEGIN2("SvrDoc_OleObj_EnumAdvise\r\n"); ! 795: ! 796: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ ! 797: *lplpenumAdvise = NULL; ! 798: ! 799: if (lpServerDoc->m_lpOleAdviseHldr == NULL) { ! 800: sc = E_FAIL; ! 801: goto error; ! 802: } ! 803: ! 804: OLEDBG_BEGIN2("IOleAdviseHolder::EnumAdvise called\r\n") ! 805: hrErr = lpServerDoc->m_lpOleAdviseHldr->lpVtbl->EnumAdvise( ! 806: lpServerDoc->m_lpOleAdviseHldr, ! 807: lplpenumAdvise ! 808: ); ! 809: OLEDBG_END2 ! 810: ! 811: OLEDBG_END2 ! 812: return hrErr; ! 813: ! 814: error: ! 815: OLEDBG_END2 ! 816: return ResultFromScode(sc); ! 817: } ! 818: ! 819: ! 820: // IOleObject::GetMiscStatus method ! 821: ! 822: STDMETHODIMP SvrDoc_OleObj_GetMiscStatus( ! 823: LPOLEOBJECT lpThis, ! 824: DWORD dwAspect, ! 825: DWORD FAR* lpdwStatus ! 826: ) ! 827: { ! 828: LPSERVERDOC lpServerDoc = ! 829: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; ! 830: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 831: ! 832: OleDbgOut2("SvrDoc_OleObj_GetMiscStatus\r\n"); ! 833: ! 834: *lpdwStatus = 0; ! 835: ! 836: /* OLE2NOTE: check if the data copied is compatible to be ! 837: ** linked by an OLE 1.0 container. it is compatible if ! 838: ** either the data is an untitled document, a file, or a ! 839: ** selection of data within a file. if the data is part of ! 840: ** an embedded object, then it is NOT compatible to be ! 841: ** linked by an OLE 1.0 container. if it is compatible then ! 842: ** we must include OLEMISC_CANLINKBYOLE1 as part of the ! 843: ** dwStatus flags transfered via CF_OBJECTDESCRIPTOR or ! 844: ** CF_LINKSRCDESCRIPTOR. ! 845: */ ! 846: if (lpOutlineDoc->m_docInitType == DOCTYPE_NEW || ! 847: lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE) ! 848: *lpdwStatus |= OLEMISC_CANLINKBYOLE1; ! 849: ! 850: #if defined( INPLACE_SVR ) ! 851: if (dwAspect == DVASPECT_CONTENT) ! 852: *lpdwStatus |= (OLEMISC_INSIDEOUT | OLEMISC_ACTIVATEWHENVISIBLE); ! 853: #endif // INPLACE_SVR ! 854: ! 855: return NOERROR; ! 856: } ! 857: ! 858: ! 859: // IOleObject::SetColorScheme method ! 860: ! 861: STDMETHODIMP SvrDoc_OleObj_SetColorScheme( ! 862: LPOLEOBJECT lpThis, ! 863: LPLOGPALETTE lpLogpal ! 864: ) ! 865: { ! 866: OleDbgOut2("SvrDoc_OleObj_SetColorScheme\r\n"); ! 867: ! 868: // REVIEW: NOT YET IMPLEMENTED ! 869: ! 870: return ResultFromScode(E_NOTIMPL); ! 871: } ! 872: ! 873: ! 874: /************************************************************************* ! 875: ** ServerDoc::IPersistStorage interface implementation ! 876: *************************************************************************/ ! 877: ! 878: // IPersistStorage::QueryInterface method ! 879: ! 880: STDMETHODIMP SvrDoc_PStg_QueryInterface( ! 881: LPPERSISTSTORAGE lpThis, ! 882: REFIID riid, ! 883: LPVOID FAR* lplpvObj ! 884: ) ! 885: { ! 886: LPSERVERDOC lpServerDoc = ! 887: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; ! 888: ! 889: return OleDoc_QueryInterface((LPOLEDOC)lpServerDoc, riid, lplpvObj); ! 890: } ! 891: ! 892: ! 893: // IPersistStorage::AddRef method ! 894: ! 895: STDMETHODIMP_(ULONG) SvrDoc_PStg_AddRef(LPPERSISTSTORAGE lpThis) ! 896: { ! 897: LPSERVERDOC lpServerDoc = ! 898: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; ! 899: ! 900: OleDbgAddRefMethod(lpThis, "IPersistStorage"); ! 901: ! 902: return OleDoc_AddRef((LPOLEDOC)lpServerDoc); ! 903: } ! 904: ! 905: ! 906: // IPersistStorage::Release method ! 907: ! 908: STDMETHODIMP_(ULONG) SvrDoc_PStg_Release(LPPERSISTSTORAGE lpThis) ! 909: { ! 910: LPSERVERDOC lpServerDoc = ! 911: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; ! 912: ! 913: OleDbgReleaseMethod(lpThis, "IPersistStorage"); ! 914: ! 915: return OleDoc_Release((LPOLEDOC)lpServerDoc); ! 916: } ! 917: ! 918: ! 919: // IPersistStorage::GetClassID method ! 920: ! 921: STDMETHODIMP SvrDoc_PStg_GetClassID( ! 922: LPPERSISTSTORAGE lpThis, ! 923: LPCLSID lpClassID ! 924: ) ! 925: { ! 926: LPSERVERDOC lpServerDoc = ! 927: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; ! 928: ! 929: OleDbgOut2("SvrDoc_PStg_GetClassID\r\n"); ! 930: ! 931: /* OLE2NOTE: we must be carefull to return the correct CLSID here. ! 932: ** if we are currently preforming a "TreatAs (aka. ActivateAs)" ! 933: ** operation then we need to return the class of the object ! 934: ** written in the storage of the object. otherwise we would ! 935: ** return our own class id. ! 936: */ ! 937: return ServerDoc_GetClassID(lpServerDoc, lpClassID); ! 938: } ! 939: ! 940: ! 941: // IPersistStorage::IsDirty method ! 942: ! 943: STDMETHODIMP SvrDoc_PStg_IsDirty(LPPERSISTSTORAGE lpThis) ! 944: { ! 945: LPSERVERDOC lpServerDoc = ! 946: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; ! 947: ! 948: OleDbgOut2("SvrDoc_PStg_IsDirty\r\n"); ! 949: ! 950: if (OutlineDoc_IsModified((LPOUTLINEDOC)lpServerDoc)) ! 951: return NOERROR; ! 952: else ! 953: return ResultFromScode(S_FALSE); ! 954: } ! 955: ! 956: ! 957: ! 958: // IPersistStorage::InitNew method ! 959: ! 960: STDMETHODIMP SvrDoc_PStg_InitNew( ! 961: LPPERSISTSTORAGE lpThis, ! 962: LPSTORAGE lpStg ! 963: ) ! 964: { ! 965: LPSERVERDOC lpServerDoc = ! 966: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; ! 967: SCODE sc; ! 968: ! 969: OLEDBG_BEGIN2("SvrDoc_PStg_InitNew\r\n") ! 970: ! 971: #if defined( SVR_TREATAS ) ! 972: { ! 973: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 974: CLSID clsid; ! 975: CLIPFORMAT cfFmt; ! 976: LPSTR lpszType; ! 977: ! 978: /* OLE2NOTE: if the Server is capable of supporting "TreatAs" ! 979: ** (aka. ActivateAs), it must read the class that is written ! 980: ** into the storage. if this class is NOT the app's own ! 981: ** class ID, then this is a TreatAs operation. the server ! 982: ** then must faithfully pretend to be the class that is ! 983: ** written into the storage. it must also faithfully write ! 984: ** the data back to the storage in the SAME format as is ! 985: ** written in the storage. ! 986: ** ! 987: ** SVROUTL and ISVROTL can emulate each other. they have the ! 988: ** simplification that they both read/write the identical ! 989: ** format. thus for these apps no actual conversion of the ! 990: ** native bits is actually required. ! 991: */ ! 992: lpServerDoc->m_clsidTreatAs = CLSID_NULL; ! 993: if (OleStdGetTreatAsFmtUserType(&CLSID_APP, lpStg, &clsid, ! 994: (CLIPFORMAT FAR*)&cfFmt, (LPSTR FAR*)&lpszType)) { ! 995: ! 996: if (cfFmt == lpOutlineApp->m_cfOutline) { ! 997: // We should perform TreatAs operation ! 998: if (lpServerDoc->m_lpszTreatAsType) ! 999: OleStdFreeString(lpServerDoc->m_lpszTreatAsType, NULL); ! 1000: ! 1001: lpServerDoc->m_clsidTreatAs = clsid; ! 1002: ((LPOUTLINEDOC)lpServerDoc)->m_cfSaveFormat = cfFmt; ! 1003: lpServerDoc->m_lpszTreatAsType = lpszType; ! 1004: ! 1005: OleDbgOut3("SvrDoc_PStg_InitNew: TreateAs ==> '"); ! 1006: OleDbgOutNoPrefix3(lpServerDoc->m_lpszTreatAsType); ! 1007: OleDbgOutNoPrefix3("'\r\n"); ! 1008: } else { ! 1009: // ERROR: we ONLY support TreatAs for CF_OUTLINE format ! 1010: OleDbgOut("SvrDoc_PStg_InitNew: INVALID TreatAs Format\r\n"); ! 1011: OleStdFreeString(lpszType, NULL); ! 1012: } ! 1013: } ! 1014: } ! 1015: #endif // SVR_TREATAS ! 1016: ! 1017: // set the doc to a new embedded object. ! 1018: if (! ServerDoc_InitNewEmbed(lpServerDoc)) { ! 1019: sc = E_FAIL; ! 1020: goto error; ! 1021: } ! 1022: ! 1023: lpServerDoc->m_dwStorageMode = STGMODE_NORMAL; ! 1024: ! 1025: OLEDBG_END2 ! 1026: return NOERROR; ! 1027: ! 1028: error: ! 1029: OLEDBG_END2 ! 1030: return ResultFromScode(sc); ! 1031: } ! 1032: ! 1033: ! 1034: // IPersistStorage::Load method ! 1035: ! 1036: STDMETHODIMP SvrDoc_PStg_Load( ! 1037: LPPERSISTSTORAGE lpThis, ! 1038: LPSTORAGE lpStg ! 1039: ) ! 1040: { ! 1041: LPSERVERDOC lpServerDoc = ! 1042: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; ! 1043: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 1044: SCODE sc; ! 1045: ! 1046: OLEDBG_BEGIN2("SvrDoc_PStg_Load\r\n") ! 1047: ! 1048: if (OutlineDoc_LoadFromStg((LPOUTLINEDOC)lpServerDoc, lpStg)) { ! 1049: ! 1050: ((LPOUTLINEDOC)lpServerDoc)->m_docInitType = DOCTYPE_EMBEDDED; ! 1051: ! 1052: lpServerDoc->m_dwStorageMode = STGMODE_NORMAL; ! 1053: ! 1054: /* OLE2NOTE: we need to check if the ConvertStg bit is on. if ! 1055: ** so, we need to clear the ConvertStg bit and mark the ! 1056: ** document as dirty so as to force a save when the document ! 1057: ** is closed. the actual conversion of the bits should be ! 1058: ** performed when the data is loaded from the IStorage*. in ! 1059: ** our case any conversion of data formats would be done in ! 1060: ** OutlineDoc_LoadFromStg function. in reality both SVROUTL ! 1061: ** and ISVROTL read and write the same format so no actual ! 1062: ** conversion of data bits is necessary. ! 1063: */ ! 1064: if (GetConvertStg(lpStg) == NOERROR) { ! 1065: SetConvertStg(lpStg, FALSE); ! 1066: ! 1067: OleDbgOut3("SvrDoc_PStg_Load: ConvertStg==TRUE\r\n"); ! 1068: OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE); ! 1069: } ! 1070: ! 1071: } else { ! 1072: sc = E_FAIL; ! 1073: goto error; ! 1074: } ! 1075: ! 1076: OLEDBG_END2 ! 1077: return NOERROR; ! 1078: ! 1079: error: ! 1080: OLEDBG_END2 ! 1081: return ResultFromScode(sc); ! 1082: } ! 1083: ! 1084: ! 1085: // IPersistStorage::Save method ! 1086: ! 1087: STDMETHODIMP SvrDoc_PStg_Save( ! 1088: LPPERSISTSTORAGE lpThis, ! 1089: LPSTORAGE lpStg, ! 1090: BOOL fSameAsLoad ! 1091: ) ! 1092: { ! 1093: LPSERVERDOC lpServerDoc = ! 1094: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; ! 1095: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 1096: BOOL fStatus; ! 1097: SCODE sc; ! 1098: ! 1099: OLEDBG_BEGIN2("SvrDoc_PStg_Save\r\n") ! 1100: ! 1101: fStatus = OutlineDoc_SaveSelToStg( ! 1102: (LPOUTLINEDOC)lpServerDoc, ! 1103: NULL, ! 1104: lpOutlineDoc->m_cfSaveFormat, ! 1105: lpStg, ! 1106: FALSE ! 1107: ); ! 1108: ! 1109: lpServerDoc->m_fSaveWithSameAsLoad = fSameAsLoad; ! 1110: ! 1111: if (! fStatus) { ! 1112: OutlineApp_ErrorMessage(g_lpApp, ErrMsgPSSaveFail); ! 1113: sc = E_FAIL; ! 1114: goto error; ! 1115: } ! 1116: ! 1117: lpServerDoc->m_dwStorageMode = STGMODE_NOSCRIBBLE; ! 1118: OLEDBG_END2 ! 1119: return NOERROR; ! 1120: ! 1121: error: ! 1122: OLEDBG_END2 ! 1123: return ResultFromScode(sc); ! 1124: } ! 1125: ! 1126: ! 1127: ! 1128: // IPersistStorage::SaveCompleted method ! 1129: ! 1130: STDMETHODIMP SvrDoc_PStg_SaveCompleted( ! 1131: LPPERSISTSTORAGE lpThis, ! 1132: LPSTORAGE lpStgNew ! 1133: ) ! 1134: { ! 1135: LPSERVERDOC lpServerDoc = ! 1136: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; ! 1137: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 1138: ! 1139: OLEDBG_BEGIN2("SvrDoc_PStg_SaveCompleted\r\n") ! 1140: ! 1141: /* OLE2NOTE: because we are a pure server that loads all data into ! 1142: ** memory, we do not hold on to our storage. thus we do not have ! 1143: ** to remember the storage passed into SaveCompleted. ! 1144: ** a container/server application must hold on to its storage ! 1145: ** however. any application that holds onto its storage must now ! 1146: ** remember the storage if one is passed in. in addition a ! 1147: ** container/server application would have to call SaveCompleted ! 1148: ** for each of its contained compound document objects. if a new ! 1149: ** storage was given, then the container/server would have to ! 1150: ** open the corresponding new sub-storage for each compound ! 1151: ** document object and pass as an argument in the SaveCompleted ! 1152: ** call. ! 1153: */ ! 1154: ! 1155: lpServerDoc->m_dwStorageMode = STGMODE_NORMAL; ! 1156: ! 1157: /* OLE2NOTE: it is only legal to perform a Save or SaveAs operation ! 1158: ** on an embedded object. if the document is a file-based document ! 1159: ** then we can not be changed to a IStorage-base object. ! 1160: ** ! 1161: ** fSameAsLoad lpStgNew Type of Save Send OnSave ! 1162: ** --------------------------------------------------------- ! 1163: ** TRUE NULL SAVE YES ! 1164: ** TRUE ! NULL SAVE * YES ! 1165: ** FALSE ! NULL SAVE AS YES ! 1166: ** FALSE NULL SAVE COPY AS NO ! 1167: ** ! 1168: ** * this is a strange case that is possible. it is inefficient ! 1169: ** for the caller; it would be better to pass lpStgNew==NULL for ! 1170: ** the Save operation. ! 1171: */ ! 1172: if ( ((lpServerDoc->m_fSaveWithSameAsLoad && lpStgNew==NULL) || lpStgNew) ! 1173: && (lpOutlineDoc->m_docInitType != DOCTYPE_EMBEDDED) ) { ! 1174: OLEDBG_END2 ! 1175: return ResultFromScode(E_INVALIDARG); ! 1176: } ! 1177: ! 1178: /* OLE2NOTE: inform any linking clients that the document has been ! 1179: ** saved. in addition, any currently active pseudo objects ! 1180: ** should also inform their clients. we should only broadcast an ! 1181: ** OnSave notification if a Save or SaveAs operation was ! 1182: ** performed. we do NOT want to send the notification if a ! 1183: ** SaveCopyAs operation was performed. ! 1184: */ ! 1185: if ((lpServerDoc->m_fSaveWithSameAsLoad && lpStgNew==NULL) || lpStgNew) { ! 1186: ! 1187: // Clear dirty flag upon save or saveAs ! 1188: OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE); ! 1189: ! 1190: ServerDoc_SendAdvise ( ! 1191: lpServerDoc, ! 1192: OLE_ONSAVE, ! 1193: NULL, /* lpmkDoc -- not relevant here */ ! 1194: 0 /* advf -- not relevant here */ ! 1195: ); ! 1196: } ! 1197: OLEDBG_END2 ! 1198: return NOERROR; ! 1199: } ! 1200: ! 1201: ! 1202: // IPersistStorage::HandsOffStorage method ! 1203: ! 1204: STDMETHODIMP SvrDoc_PStg_HandsOffStorage(LPPERSISTSTORAGE lpThis) ! 1205: { ! 1206: LPSERVERDOC lpServerDoc = ! 1207: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; ! 1208: ! 1209: OLEDBG_BEGIN2("SvrDoc_PStg_HandsOffStorage\r\n") ! 1210: ! 1211: /* OLE2NOTE: because we are a pure server that loads all data into ! 1212: ** memory, we do not hold on to our storage. thus we do not have ! 1213: ** a storage to release (ie. to enter HandsOff Mode). ! 1214: ** a container/server application must hold on to its storage ! 1215: ** however. any application that holds onto its storage must now ! 1216: ** release its storage. when SaveCompleted is called, then a new ! 1217: ** storage will be given. ! 1218: */ ! 1219: ! 1220: lpServerDoc->m_dwStorageMode = STGMODE_HANDSOFF; ! 1221: ! 1222: OLEDBG_END2 ! 1223: return NOERROR; ! 1224: } ! 1225: ! 1226: ! 1227: ! 1228: #if defined( SVR_TREATAS ) ! 1229: ! 1230: /************************************************************************* ! 1231: ** ServerDoc::IStdMarshalInfo interface implementation ! 1232: *************************************************************************/ ! 1233: ! 1234: // IStdMarshalInfo::QueryInterface method ! 1235: ! 1236: STDMETHODIMP SvrDoc_StdMshl_QueryInterface( ! 1237: LPSTDMARSHALINFO lpThis, ! 1238: REFIID riid, ! 1239: LPVOID FAR* lplpvObj ! 1240: ) ! 1241: { ! 1242: LPSERVERDOC lpServerDoc = ! 1243: ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc; ! 1244: ! 1245: return OleDoc_QueryInterface((LPOLEDOC)lpServerDoc, riid, lplpvObj); ! 1246: } ! 1247: ! 1248: ! 1249: // IStdMarshalInfo::AddRef method ! 1250: ! 1251: STDMETHODIMP_(ULONG) SvrDoc_StdMshl_AddRef(LPSTDMARSHALINFO lpThis) ! 1252: { ! 1253: LPSERVERDOC lpServerDoc = ! 1254: ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc; ! 1255: ! 1256: OleDbgAddRefMethod(lpThis, "IStdMarshalInfo"); ! 1257: ! 1258: return OleDoc_AddRef((LPOLEDOC)lpServerDoc); ! 1259: } ! 1260: ! 1261: ! 1262: // IStdMarshalInfo::Release method ! 1263: ! 1264: STDMETHODIMP_(ULONG) SvrDoc_StdMshl_Release(LPSTDMARSHALINFO lpThis) ! 1265: { ! 1266: LPSERVERDOC lpServerDoc = ! 1267: ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc; ! 1268: ! 1269: OleDbgReleaseMethod(lpThis, "IStdMarshalInfo"); ! 1270: ! 1271: return OleDoc_Release((LPOLEDOC)lpServerDoc); ! 1272: } ! 1273: ! 1274: ! 1275: // IStdMarshalInfo::GetClassForHandler ! 1276: ! 1277: STDMETHODIMP SvrDoc_StdMshl_GetClassForHandler( ! 1278: LPSTDMARSHALINFO lpThis, ! 1279: DWORD dwDestContext, ! 1280: LPVOID pvDestContext, ! 1281: LPCLSID lpClassID ! 1282: ) ! 1283: { ! 1284: LPSERVERDOC lpServerDoc = ! 1285: ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc; ! 1286: ! 1287: OleDbgOut2("SvrDoc_StdMshl_GetClassForHandler\r\n"); ! 1288: ! 1289: // OLE2NOTE: we only handle LOCAL marshal context. ! 1290: if (dwDestContext != MSHCTX_LOCAL || pvDestContext != NULL) ! 1291: return ResultFromScode(E_INVALIDARG); ! 1292: ! 1293: /* OLE2NOTE: we must return our REAL clsid, NOT the clsid that we ! 1294: ** are pretending to be if a "TreatAs" is in effect. ! 1295: */ ! 1296: *lpClassID = CLSID_APP; ! 1297: return NOERROR; ! 1298: } ! 1299: #endif // SVR_TREATAS ! 1300: ! 1301: ! 1302: ! 1303: /************************************************************************* ! 1304: ** ServerDoc Support Functions ! 1305: *************************************************************************/ ! 1306: ! 1307: ! 1308: /* ServerDoc_Init ! 1309: * -------------- ! 1310: * ! 1311: * Initialize the fields of a new ServerDoc object. The object is initially ! 1312: * not associated with a file or an (Untitled) document. This function sets ! 1313: * the docInitType to DOCTYPE_UNKNOWN. After calling this function the ! 1314: * caller should call: ! 1315: * 1.) OutlineDoc_InitNewFile to set the ServerDoc to (Untitled) ! 1316: * 2.) OutlineDoc_LoadFromFile to associate the ServerDoc with a file. ! 1317: * This function creates a new window for the document. ! 1318: * ! 1319: * NOTE: the window is initially created with a NIL size. it must be ! 1320: * sized and positioned by the caller. also the document is initially ! 1321: * created invisible. the caller must call OutlineDoc_ShowWindow ! 1322: * after sizing it to make the document window visible. ! 1323: */ ! 1324: BOOL ServerDoc_Init(LPSERVERDOC lpServerDoc, BOOL fDataTransferDoc) ! 1325: { ! 1326: lpServerDoc->m_cPseudoObj = 0; ! 1327: lpServerDoc->m_lpOleClientSite = NULL; ! 1328: lpServerDoc->m_lpOleAdviseHldr = NULL; ! 1329: lpServerDoc->m_lpDataAdviseHldr = NULL; ! 1330: ! 1331: // initialy doc does not have any storage ! 1332: lpServerDoc->m_dwStorageMode = STGMODE_HANDSOFF; ! 1333: lpServerDoc->m_fSaveWithSameAsLoad = FALSE; ! 1334: lpServerDoc->m_szContainerApp[0] = '\0'; ! 1335: lpServerDoc->m_szContainerObj[0] = '\0'; ! 1336: lpServerDoc->m_nNextRangeNo = 0L; ! 1337: lpServerDoc->m_lrSrcSelOfCopy.m_nStartLine = -1; ! 1338: lpServerDoc->m_lrSrcSelOfCopy.m_nEndLine = -1; ! 1339: lpServerDoc->m_fDataChanged = FALSE; ! 1340: lpServerDoc->m_fSizeChanged = FALSE; ! 1341: lpServerDoc->m_fSendDataOnStop = FALSE; ! 1342: ! 1343: #if defined( SVR_TREATAS ) ! 1344: lpServerDoc->m_clsidTreatAs = CLSID_NULL; ! 1345: lpServerDoc->m_lpszTreatAsType = NULL; ! 1346: #endif // SVR_TREATAS ! 1347: ! 1348: #if defined( INPLACE_SVR ) ! 1349: lpServerDoc->m_hWndHatch = ! 1350: CreateHatchWindow( ! 1351: OutlineApp_GetWindow(g_lpApp), ! 1352: OutlineApp_GetInstance(g_lpApp) ! 1353: ); ! 1354: if (!lpServerDoc->m_hWndHatch) ! 1355: return FALSE; ! 1356: ! 1357: lpServerDoc->m_fInPlaceActive = FALSE; ! 1358: lpServerDoc->m_fInPlaceVisible = FALSE; ! 1359: lpServerDoc->m_fUIActive = FALSE; ! 1360: lpServerDoc->m_lpIPData = NULL; ! 1361: ! 1362: INIT_INTERFACEIMPL( ! 1363: &lpServerDoc->m_OleInPlaceObject, ! 1364: &g_SvrDoc_OleInPlaceObjectVtbl, ! 1365: lpServerDoc ! 1366: ); ! 1367: INIT_INTERFACEIMPL( ! 1368: &lpServerDoc->m_OleInPlaceActiveObject, ! 1369: &g_SvrDoc_OleInPlaceActiveObjectVtbl, ! 1370: lpServerDoc ! 1371: ); ! 1372: #endif // INPLACE_SVR ! 1373: ! 1374: INIT_INTERFACEIMPL( ! 1375: &lpServerDoc->m_OleObject, ! 1376: &g_SvrDoc_OleObjectVtbl, ! 1377: lpServerDoc ! 1378: ); ! 1379: ! 1380: INIT_INTERFACEIMPL( ! 1381: &lpServerDoc->m_PersistStorage, ! 1382: &g_SvrDoc_PersistStorageVtbl, ! 1383: lpServerDoc ! 1384: ); ! 1385: ! 1386: #if defined( SVR_TREATAS ) ! 1387: ! 1388: INIT_INTERFACEIMPL( ! 1389: &lpServerDoc->m_StdMarshalInfo, ! 1390: &g_SvrDoc_StdMarshalInfoVtbl, ! 1391: lpServerDoc ! 1392: ); ! 1393: #endif // SVR_TREATAS ! 1394: return TRUE; ! 1395: } ! 1396: ! 1397: ! 1398: /* ServerDoc_InitNewEmbed ! 1399: * ---------------------- ! 1400: * ! 1401: * Initialize the ServerDoc object to be a new embedded object document. ! 1402: * This function sets the docInitType to DOCTYPE_EMBED. ! 1403: */ ! 1404: BOOL ServerDoc_InitNewEmbed(LPSERVERDOC lpServerDoc) ! 1405: { ! 1406: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 1407: ! 1408: OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN); ! 1409: ! 1410: lpOutlineDoc->m_docInitType = DOCTYPE_EMBEDDED; ! 1411: ! 1412: /* The Window title for an embedded object is constructed as ! 1413: ** follows: ! 1414: ** <server app name> - <obj short type> in <cont. doc name> ! 1415: ** ! 1416: ** here we construct the current document title portion of the ! 1417: ** name which follows the '-'. OutlineDoc_SetTitle prepends the ! 1418: ** "<server app name> - " to the document title. ! 1419: */ ! 1420: // REVIEW: this string should be loaded from string resource ! 1421: wsprintf(lpOutlineDoc->m_szFileName, "%s in %s", ! 1422: (LPSTR)SHORTUSERTYPENAME, ! 1423: (LPSTR)DEFCONTAINERNAME); ! 1424: lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName; ! 1425: ! 1426: ! 1427: /* OLE2NOTE: an embedding should be marked as initially dirty so ! 1428: ** that on close we always call IOleClientSite::SaveObject. ! 1429: */ ! 1430: OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE); ! 1431: ! 1432: OutlineDoc_SetTitle(lpOutlineDoc); ! 1433: ! 1434: return TRUE; ! 1435: } ! 1436: ! 1437: ! 1438: /* ServerDoc_SendAdvise ! 1439: * -------------------- ! 1440: * ! 1441: * This function sends an advise notification on behalf of a specific ! 1442: * doc object to all its clients. ! 1443: */ ! 1444: void ServerDoc_SendAdvise( ! 1445: LPSERVERDOC lpServerDoc, ! 1446: WORD wAdvise, ! 1447: LPMONIKER lpmkDoc, ! 1448: DWORD dwAdvf ! 1449: ) ! 1450: { ! 1451: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 1452: LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; ! 1453: ! 1454: switch (wAdvise) { ! 1455: ! 1456: case OLE_ONDATACHANGE: ! 1457: ! 1458: // inform clients that the data of the object has changed ! 1459: ! 1460: if (lpOutlineDoc->m_nDisableDraw == 0) { ! 1461: /* drawing is currently enabled. inform clients that ! 1462: ** the data of the object has changed ! 1463: */ ! 1464: ! 1465: lpServerDoc->m_fDataChanged = FALSE; ! 1466: ! 1467: if (lpServerDoc->m_lpDataAdviseHldr) { ! 1468: OLEDBG_BEGIN2( ! 1469: "IDataAdviseHolder::SendOnDataChange called\r\n" ! 1470: ); ! 1471: lpServerDoc->m_lpDataAdviseHldr->lpVtbl->SendOnDataChange( ! 1472: lpServerDoc->m_lpDataAdviseHldr, ! 1473: (LPDATAOBJECT)&lpOleDoc->m_DataObject, ! 1474: 0, ! 1475: dwAdvf ! 1476: ); ! 1477: OLEDBG_END2 ! 1478: ! 1479: /* OLE2NOTE: we must note the time of last change ! 1480: ** for our object in the RunningObjectTable. ! 1481: ** this is used as the basis to answer ! 1482: ** IOleObject::IsUpToDate. ! 1483: */ ! 1484: OleStdNoteObjectChangeTime(lpOleDoc->m_dwRegROT); ! 1485: } ! 1486: ! 1487: #if defined( INPLACE_SVR ) ! 1488: /* OLE2NOTE: if the ServerDoc is currently in-place UI active, ! 1489: ** then is it important to renegotiate the size for the ! 1490: ** in-place document window BEFORE sending OnDataChange ! 1491: ** (which will cause the window to repaint). ! 1492: */ ! 1493: if (lpServerDoc->m_fSizeChanged) { ! 1494: lpServerDoc->m_fSizeChanged = FALSE; ! 1495: if (lpServerDoc->m_fInPlaceActive) ! 1496: ServerDoc_UpdateInPlaceWindowOnExtentChange(lpServerDoc); ! 1497: } ! 1498: #endif ! 1499: ! 1500: /* OLE2NOTE: we do NOT need to tell our pseudo objects to ! 1501: ** broadcast OnDataChange notification because ! 1502: ** they will do it automatically when an editing ! 1503: ** change in the document affects a PseudoObj. ! 1504: ** (see OutlineNameTable_AddLineUpdate, ! 1505: ** OutlineNameTable_DeleteLineUpdate, ! 1506: ** and ServerNameTable_EditLineUpdate) ! 1507: */ ! 1508: ! 1509: } else { ! 1510: /* drawing is currently disabled. do not send ! 1511: ** notifications or call ! 1512: ** IOleInPlaceObject::OnPosRectChange until drawing ! 1513: ** is re-enabled. ! 1514: */ ! 1515: } ! 1516: break; ! 1517: ! 1518: case OLE_ONCLOSE: ! 1519: ! 1520: // inform clients that the document is shutting down ! 1521: ! 1522: if (lpServerDoc->m_lpOleAdviseHldr) { ! 1523: OLEDBG_BEGIN2("IOleAdviseHolder::SendOnClose called\r\n"); ! 1524: lpServerDoc->m_lpOleAdviseHldr->lpVtbl->SendOnClose( ! 1525: lpServerDoc->m_lpOleAdviseHldr ! 1526: ); ! 1527: OLEDBG_END2 ! 1528: } ! 1529: ! 1530: /* OLE2NOTE: we do NOT need to tell our pseudo objects to ! 1531: ** broadcast OnClose notification because they will do ! 1532: ** it automatically when the pseudo object is closed. ! 1533: ** (see PseudoObj_Close) ! 1534: */ ! 1535: ! 1536: break; ! 1537: ! 1538: case OLE_ONSAVE: ! 1539: ! 1540: // inform clients that the object has been saved ! 1541: ! 1542: OLEDBG_BEGIN3("ServerDoc_SendAdvise ONSAVE\r\n"); ! 1543: ! 1544: if (lpServerDoc->m_lpOleAdviseHldr) { ! 1545: OLEDBG_BEGIN2("IOleAdviseHolder::SendOnSave called\r\n"); ! 1546: lpServerDoc->m_lpOleAdviseHldr->lpVtbl->SendOnSave( ! 1547: lpServerDoc->m_lpOleAdviseHldr ! 1548: ); ! 1549: OLEDBG_END2 ! 1550: } ! 1551: ! 1552: /* OLE2NOTE: inform any clients of pseudo objects ! 1553: ** within our document, that our document has been ! 1554: ** saved. ! 1555: */ ! 1556: ServerNameTable_InformAllPseudoObjectsDocSaved( ! 1557: (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable, ! 1558: lpmkDoc ! 1559: ); ! 1560: ! 1561: ! 1562: if (lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE) { ! 1563: /* OLE2NOTE: we must note the time this File-Based ! 1564: ** object has been saved in the RunningObjectTable. ! 1565: ** These change times are used as the basis for ! 1566: ** IOleObject::IsUpToDate. It is important to set ! 1567: ** the time of the file-based object following a ! 1568: ** save operation to exactly the time of the saved ! 1569: ** file. this helps IOleObject::IsUpToDate to give ! 1570: ** the correct answer after a file has been saved. ! 1571: */ ! 1572: OleStdNoteFileChangeTime( ! 1573: lpOutlineDoc->m_szFileName, lpOleDoc->m_dwRegROT); ! 1574: } ! 1575: OLEDBG_END3 ! 1576: break; ! 1577: ! 1578: case OLE_ONRENAME: ! 1579: ! 1580: // inform clients that the object's name has changed ! 1581: ! 1582: OLEDBG_BEGIN3("ServerDoc_SendAdvise ONRENAME\r\n"); ! 1583: ! 1584: if (lpmkDoc && lpServerDoc->m_lpOleAdviseHldr) { ! 1585: OLEDBG_BEGIN2("IOleAdviseHolder::SendOnRename called\r\n"); ! 1586: lpServerDoc->m_lpOleAdviseHldr->lpVtbl->SendOnRename( ! 1587: lpServerDoc->m_lpOleAdviseHldr, ! 1588: lpmkDoc ! 1589: ); ! 1590: OLEDBG_END2 ! 1591: } ! 1592: ! 1593: /* OLE2NOTE: inform any clients of pseudo objects ! 1594: ** within our document, that our document's ! 1595: ** Moniker has changed. ! 1596: */ ! 1597: ServerNameTable_InformAllPseudoObjectsDocRenamed( ! 1598: (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable, lpmkDoc); ! 1599: ! 1600: OLEDBG_END3 ! 1601: break; ! 1602: } ! 1603: } ! 1604: ! 1605: ! 1606: /* ServerDoc_GetClassID ! 1607: ** -------------------- ! 1608: ** Return the class ID corresponding to the bits in the storage. ! 1609: ** normally this will be our application's given CLSID. but if a ! 1610: ** "TreateAs (aka. ActivateAs)" operation is taking place, then our ! 1611: ** application needs to pretend to be the class of the object that ! 1612: ** we are emulating. this is also the class that will be written ! 1613: ** into the storage. ! 1614: */ ! 1615: HRESULT ServerDoc_GetClassID(LPSERVERDOC lpServerDoc, LPCLSID lpclsid) ! 1616: { ! 1617: #if defined( SVR_TREATAS ) ! 1618: if (! IsEqualCLSID(&lpServerDoc->m_clsidTreatAs, &CLSID_NULL)) ! 1619: *lpclsid = lpServerDoc->m_clsidTreatAs; ! 1620: else ! 1621: #endif // SVR_TREATAS ! 1622: *lpclsid = CLSID_APP; ! 1623: ! 1624: return NOERROR; ! 1625: } ! 1626: ! 1627: ! 1628: #if defined( LATER ) ! 1629: ! 1630: /* ServerDoc_GetUserType ! 1631: ** --------------------- ! 1632: ** Return the UserType corresponding to the bits in the storage. ! 1633: ** normally this will be our application's given UserType. but if a ! 1634: ** "TreateAs (aka. ActivateAs)" operation is taking place, then our ! 1635: ** application needs to pretend to be the UserType of the object that ! 1636: ** we are emulating. this is also the class that will be written ! 1637: ** into the storage. ! 1638: */ ! 1639: HRESULT ServerDoc_GetUserType(LPSERVERDOC lpServerDoc, LPCLSID lpclsid) ! 1640: { ! 1641: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ ! 1642: *lpszUserType = NULL; ! 1643: ! 1644: #if defined( SVR_TREATAS ) ! 1645: if (lpServerDoc->m_clsidTreatAs != CLSID_NULL) ! 1646: return OleStdGetUserType(&lpServerDoc->m_clsidTreatAs); ! 1647: else ! 1648: #endif // SVR_TREATAS ! 1649: return OleStdGetUserType(&CLSID_APP); ! 1650: } ! 1651: ! 1652: #endif // LATER ! 1653: ! 1654: ! 1655: /* ServerDoc_UpdateMenu ! 1656: * -------------------- ! 1657: * ! 1658: * Update menu for embedding mode. the changes include: ! 1659: * 1 Remove File/New and File/Open (SDI ONLY) ! 1660: * 2 Change File/Save As.. to File/Save Copy As.. ! 1661: * 3 Change File menu so it contains "Update" instead of "Save" ! 1662: * 4 Change File/Exit to File/Exit & Return to <client doc>" ! 1663: */ ! 1664: void ServerDoc_UpdateMenu(LPSERVERDOC lpServerDoc) ! 1665: { ! 1666: char str[256]; ! 1667: HWND hWndMain; ! 1668: HMENU hMenu; ! 1669: ! 1670: OleDbgOut2("ServerDoc_UpdateMenu\r\n"); ! 1671: ! 1672: hWndMain=g_lpApp->m_hWndApp; ! 1673: hMenu=GetMenu(hWndMain); ! 1674: ! 1675: #if defined( SDI_VERSION ) ! 1676: /* SDI ONLY: Remove File/New and File/Open */ ! 1677: DeleteMenu(hMenu, IDM_F_NEW, MF_BYCOMMAND); ! 1678: DeleteMenu(hMenu, IDM_F_OPEN, MF_BYCOMMAND); ! 1679: #endif ! 1680: ! 1681: // Change File.Save As.. to File.Save Copy As.. */ ! 1682: ModifyMenu(hMenu,IDM_F_SAVEAS, MF_STRING, IDM_F_SAVEAS, "Save Copy As.."); ! 1683: ! 1684: // Change File.Save to "&Update <container doc>" ! 1685: wsprintf(str, g_szUpdateCntrDoc, lpServerDoc->m_szContainerObj); ! 1686: ModifyMenu(hMenu, IDM_F_SAVE, MF_STRING, IDM_F_SAVE, str); ! 1687: ! 1688: // Change File/Exit to File/Exit & Return to <container doc>" */ ! 1689: wsprintf(str, g_szExitNReturnToCntrDoc, lpServerDoc->m_szContainerObj); ! 1690: ModifyMenu(hMenu, IDM_F_EXIT, MF_STRING, IDM_F_EXIT, str); ! 1691: ! 1692: DrawMenuBar(hWndMain); ! 1693: } ! 1694: ! 1695: #if defined( MDI_VERSION ) ! 1696: ! 1697: // NOTE: ServerDoc_RestoreMenu is actually redundant because the ! 1698: // app is dying when the function is called. (In SDI, the ! 1699: // app will terminate when the ref counter of the server doc ! 1700: // is zero). However, it is important for MDI. ! 1701: ! 1702: /* ServerDoc_RestoreMenu ! 1703: * --------------------- ! 1704: * ! 1705: * Reset the menu to non-embedding mode ! 1706: */ ! 1707: void ServerDoc_RestoreMenu(LPSERVERDOC lpServerDoc) ! 1708: { ! 1709: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 1710: HWND hWndMain; ! 1711: HMENU hMenu; ! 1712: ! 1713: OleDbgOut2("ServerDoc_RestoreMenu\r\n"); ! 1714: ! 1715: hWndMain = lpOutlineApp->m_hWndApp; ! 1716: hMenu = GetMenu(hWndMain); ! 1717: ! 1718: /* Add back File/New, File/Open.. and File/Save */ ! 1719: InsertMenu(hMenu, IDM_F_SAVEAS, MF_BYCOMMAND | MF_ENABLED | MF_STRING, ! 1720: IDM_F_NEW, "&New"); ! 1721: InsertMenu(hMenu, IDM_F_SAVEAS, MF_BYCOMMAND | MF_ENABLED | MF_STRING, ! 1722: IDM_F_OPEN, "&Open..."); ! 1723: ! 1724: /* Change File menu so it contains "Save As..." instead of */ ! 1725: /* "Save Copy As..." */ ! 1726: ModifyMenu(hMenu, IDM_F_SAVEAS, MF_STRING, IDM_F_SAVEAS, "Save &As.."); ! 1727: ! 1728: /* Change File menu so it contains "Save" instead of "Update" */ ! 1729: ModifyMenu(hMenu, IDM_F_SAVE, MF_STRING, IDM_F_SAVE, "&Save"); ! 1730: ! 1731: /* Change File menu so it contains "Exit" */ ! 1732: /* instead of just "Exit & Return to <client doc>" */ ! 1733: ModifyMenu(hMenu, IDM_F_EXIT, MF_STRING, IDM_F_EXIT, "E&xit"); ! 1734: ! 1735: DrawMenuBar (hWndMain); ! 1736: } ! 1737: ! 1738: #endif // MDI_VERSION
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.