OLEDOC.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:40k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*************************************************************************
  2. **
  3. **    OLE 2 Server Sample Code
  4. **
  5. **    oledoc.c
  6. **
  7. **    This file contains general OleDoc methods and related support
  8. **    functions. OleDoc implementation is used by both the Container
  9. **    versions and the Server (Object) versions of the Outline Sample.
  10. **
  11. **    This file includes general support for the following:
  12. **    1. show/hide doc window
  13. **    2. QueryInterface, AddRef, Release
  14. **    3. document locking (calls CoLockObjectExternal)
  15. **    4. document shutdown (Close, Destroy)
  16. **    5. clipboard support
  17. **
  18. **    OleDoc Object
  19. **      exposed interfaces:
  20. **          IUnknown
  21. **          IPersistFile
  22. **          IOleItemContainer
  23. **          IDataObject
  24. **
  25. **    (c) Copyright Microsoft Corp. 1992 - 1996 All Rights Reserved
  26. **
  27. *************************************************************************/
  28. #include "outline.h"
  29. OLEDBGDATA
  30. extern LPOUTLINEAPP             g_lpApp;
  31. extern IUnknownVtbl             g_OleDoc_UnknownVtbl;
  32. extern IPersistFileVtbl         g_OleDoc_PersistFileVtbl;
  33. extern IOleItemContainerVtbl    g_OleDoc_OleItemContainerVtbl;
  34. extern IExternalConnectionVtbl  g_OleDoc_ExternalConnectionVtbl;
  35. extern IDataObjectVtbl          g_OleDoc_DataObjectVtbl;
  36. #if defined( USE_DRAGDROP )
  37. extern IDropTargetVtbl          g_OleDoc_DropTargetVtbl;
  38. extern IDropSourceVtbl          g_OleDoc_DropSourceVtbl;
  39. #endif  // USE_DRAGDROP
  40. #if defined( INPLACE_CNTR )
  41. extern BOOL g_fInsideOutContainer;
  42. #endif
  43. /* OleDoc_Init
  44.  * -----------
  45.  *
  46.  *  Initialize the fields of a new OleDoc object. The object is initially
  47.  *  not associated with a file or an (Untitled) document. This function sets
  48.  *  the docInitType to DOCTYPE_UNKNOWN. After calling this function the
  49.  *  caller should call:
  50.  *      1.) Doc_InitNewFile to set the OleDoc to (Untitled)
  51.  *      2.) Doc_LoadFromFile to associate the OleDoc with a file.
  52.  *  This function creates a new window for the document.
  53.  *
  54.  *  NOTE: the window is initially created with a NIL size. it must be
  55.  *        sized and positioned by the caller. also the document is initially
  56.  *        created invisible. the caller must call OutlineDoc_ShowWindow
  57.  *        after sizing it to make the document window visible.
  58.  */
  59. BOOL OleDoc_Init(LPOLEDOC lpOleDoc, BOOL fDataTransferDoc)
  60. {
  61.    LPOLEAPP   lpOleApp = (LPOLEAPP)g_lpApp;
  62.    LPLINELIST lpLL     = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  63.    lpOleDoc->m_cRef                        = 0;
  64.    lpOleDoc->m_dwStrongExtConn             = 0;
  65. #if defined( _DEBUG )
  66.    lpOleDoc->m_cCntrLock                   = 0;
  67. #endif
  68.    lpOleDoc->m_lpStg                       = NULL;
  69.    lpOleDoc->m_lpLLStm                     = NULL;
  70.    lpOleDoc->m_lpNTStm                     = NULL;
  71.    lpOleDoc->m_dwRegROT                    = 0;
  72.    lpOleDoc->m_lpFileMoniker               = NULL;
  73.    lpOleDoc->m_fLinkSourceAvail            = FALSE;
  74.    lpOleDoc->m_lpSrcDocOfCopy              = NULL;
  75.    lpOleDoc->m_fObjIsClosing               = FALSE;
  76.    lpOleDoc->m_fObjIsDestroying            = FALSE;
  77.    lpOleDoc->m_fUpdateEditMenu             = FALSE;
  78. #if defined( USE_DRAGDROP )
  79.    lpOleDoc->m_dwTimeEnterScrollArea       = 0L;
  80.    lpOleDoc->m_dwNextScrollTime            = 0L;
  81.    lpOleDoc->m_dwLastScrollDir             = SCROLLDIR_NULL;
  82.    lpOleDoc->m_fRegDragDrop                = FALSE;
  83.    lpOleDoc->m_fLocalDrag                  = FALSE;
  84.    lpOleDoc->m_fCanDropCopy                = FALSE;
  85.    lpOleDoc->m_fCanDropLink                = FALSE;
  86.    lpOleDoc->m_fLocalDrop                  = FALSE;
  87.    lpOleDoc->m_fDragLeave                  = FALSE;
  88.    lpOleDoc->m_fPendingDrag                = FALSE;
  89. #endif
  90. #if defined( INPLACE_SVR ) || defined( INPLACE_CNTR )
  91.    lpOleDoc->m_fCSHelpMode                 = FALSE;    // Shift-F1 context
  92.                                           // sensitive help mode
  93. #endif
  94.    INIT_INTERFACEIMPL(
  95.          &lpOleDoc->m_Unknown,
  96.          &g_OleDoc_UnknownVtbl,
  97.          lpOleDoc
  98.    );
  99.    INIT_INTERFACEIMPL(
  100.          &lpOleDoc->m_PersistFile,
  101.          &g_OleDoc_PersistFileVtbl,
  102.          lpOleDoc
  103.    );
  104.    INIT_INTERFACEIMPL(
  105.          &lpOleDoc->m_OleItemContainer,
  106.          &g_OleDoc_OleItemContainerVtbl,
  107.          lpOleDoc
  108.    );
  109.    INIT_INTERFACEIMPL(
  110.          &lpOleDoc->m_ExternalConnection,
  111.          &g_OleDoc_ExternalConnectionVtbl,
  112.          lpOleDoc
  113.    );
  114.    INIT_INTERFACEIMPL(
  115.          &lpOleDoc->m_DataObject,
  116.          &g_OleDoc_DataObjectVtbl,
  117.          lpOleDoc
  118.    );
  119. #if defined( USE_DRAGDROP )
  120.    INIT_INTERFACEIMPL(
  121.          &lpOleDoc->m_DropSource,
  122.          &g_OleDoc_DropSourceVtbl,
  123.          lpOleDoc
  124.    );
  125.    INIT_INTERFACEIMPL(
  126.          &lpOleDoc->m_DropTarget,
  127.          &g_OleDoc_DropTargetVtbl,
  128.          lpOleDoc
  129.    );
  130. #endif  // USE_DRAGDROP
  131.    /*
  132.    ** NOTE: each user level document addref's the app object in
  133.    **    order to guarentee that the app does not shut down while the
  134.    **    doc is still open.
  135.    */
  136.    // NOTE: data transfer documents should not hold the app alive
  137.    if (! fDataTransferDoc)
  138.       OleApp_DocLockApp(lpOleApp);
  139. #if defined( OLE_SERVER )
  140.    /* NOTE: perform initialization specific for an OLE server */
  141.    if (! ServerDoc_Init((LPSERVERDOC)lpOleDoc, fDataTransferDoc))
  142.       return FALSE;
  143. #endif
  144. #if defined( OLE_CNTR )
  145.    /* NOTE: perform initialization specific for an OLE container */
  146.    if (! ContainerDoc_Init((LPCONTAINERDOC)lpOleDoc, fDataTransferDoc))
  147.       return FALSE;
  148. #endif
  149.    return TRUE;
  150. }
  151. /* OleDoc_InitNewFile
  152.  * ------------------
  153.  *
  154.  *  Initialize the document to be a new (Untitled) document.
  155.  *  This function sets the docInitType to DOCTYPE_NEW.
  156.  *
  157.  *  NOTE: if this is a visible user document then generate a unique
  158.  *  untitled name that we can use to register in the RunningObjectTable.
  159.  *  We need a unique name so that clients can link to data in this document
  160.  *  even when the document is in the un-saved (untitled) state. it would be
  161.  *  ambiguous to register two documents titled "Outline1" in the ROT. we
  162.  *  thus generate the lowest numbered document that is not already
  163.  *  registered in the ROT.
  164.  */
  165. BOOL OleDoc_InitNewFile(LPOLEDOC lpOleDoc)
  166. {
  167.    LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  168.    static UINT uUnique = 1;
  169.    OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN);
  170. #if defined( OLE_CNTR )
  171.    {
  172.       LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
  173. #if defined( _DEBUG )
  174.       OleDbgAssertSz(lpOleDoc->m_lpStg == NULL,
  175.             "Setting to untitled with current file open"
  176.       );
  177. #endif
  178.       /* Create a temp, (delete-on-release) file base storage
  179.       **  for the untitled document.
  180.       */
  181.       lpOleDoc->m_lpStg = OleStdCreateRootStorage(
  182.             NULL,
  183.             STGM_SHARE_EXCLUSIVE
  184.       );
  185.       if (! lpOleDoc->m_lpStg) return FALSE;
  186.    }
  187. #endif
  188.    lpOutlineDoc->m_docInitType = DOCTYPE_NEW;
  189.    if (! lpOutlineDoc->m_fDataTransferDoc) {
  190.       /* NOTE: choose a unique name for a Moniker so that
  191.       **    potential clients can link to our new, untitled document.
  192.       **    if links are established (and currently are connected),
  193.       **    then they will be notified that we have been renamed when
  194.       **    this document is saved to a file.
  195.       */
  196.       lpOleDoc->m_fLinkSourceAvail = TRUE;
  197.       // REVIEW: should load UNTITLED string from string resource
  198.       OleStdCreateTempFileMoniker(
  199.             UNTITLED,
  200.             (UINT FAR*)&uUnique,
  201.             lpOutlineDoc->m_szFileName,
  202.             &lpOleDoc->m_lpFileMoniker
  203.       );
  204.       OLEDBG_BEGIN3("OleStdRegisterAsRunning calledrn")
  205.       OleStdRegisterAsRunning(
  206.             (LPUNKNOWN)&lpOleDoc->m_PersistFile,
  207.             (LPMONIKER)lpOleDoc->m_lpFileMoniker,
  208.             &lpOleDoc->m_dwRegROT
  209.       );
  210.       OLEDBG_END3
  211.       lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
  212.       OutlineDoc_SetTitle(lpOutlineDoc, FALSE /*fMakeUpperCase*/);
  213.    } else {
  214.       OLESTRCPY(lpOutlineDoc->m_szFileName, UNTITLED);
  215.       lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
  216.    }
  217.    return TRUE;
  218. }
  219. /* OleDoc_ShowWindow
  220.  * -----------------
  221.  *
  222.  *      Show the window of the document to the user.
  223.  *      make sure app window is visible and bring the document to the top.
  224.  *      if the document is a file-based document or a new untitled
  225.  *      document, give the user the control over the life-time of the doc.
  226.  */
  227. void OleDoc_ShowWindow(LPOLEDOC lpOleDoc)
  228. {
  229.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  230.    LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  231.    LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  232.    LPLINELIST lpLL     = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  233. #if defined( OLE_SERVER )
  234.    LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  235. #endif // OLE_SERVER
  236.    OLEDBG_BEGIN3("OleDoc_ShowWindowrn")
  237.    /* NOTE: while the document is visible, we do NOT want it to be
  238.    **    prematurely destroyed when a linking client disconnects. thus
  239.    **    we must inform OLE to hold an external lock on our document.
  240.    **    this arranges that OLE holds at least 1 reference to our
  241.    **    document that will NOT be released until we release this
  242.    **    external lock. later, when the document window is hidden, we
  243.    **    will release this external lock.
  244.    */
  245.    if (! IsWindowVisible(lpOutlineDoc->m_hWndDoc))
  246.       OleDoc_Lock(lpOleDoc, TRUE /* fLock */, 0 /* not applicable */);
  247. #if defined( USE_DRAGDROP )
  248.    /* NOTE: since our window is now being made visible, we will
  249.    **    register our window as a potential drop target. when the
  250.    **    window is hidden there is no reason to be registered as a
  251.    **    drop target.
  252.    */
  253.    if (! lpOleDoc->m_fRegDragDrop) {
  254.       OLEDBG_BEGIN2("RegisterDragDrop calledrn")
  255.       RegisterDragDrop(
  256.             LineList_GetWindow(lpLL),
  257.             (LPDROPTARGET)&lpOleDoc->m_DropTarget
  258.       );
  259.       OLEDBG_END2
  260.       lpOleDoc->m_fRegDragDrop = TRUE;
  261.    }
  262. #endif  // USE_DRAGDROP
  263. #if defined( USE_FRAMETOOLS )
  264.    {
  265.       /* NOTE: we need to enable our frame level tools
  266.       */
  267.       FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, TRUE);
  268.    }
  269. #endif // USE_FRAMETOOLS
  270. #if defined( OLE_SERVER )
  271.    if (lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED &&
  272.          lpServerDoc->m_lpOleClientSite != NULL) {
  273.       /* NOTE: we must also ask our container to show itself if
  274.       **    it is not already visible and to scroll us into view. we
  275.       **    must make sure to call this BEFORE showing our server's
  276.       **    window and taking focus. we do not want our container's
  277.       **    window to end up on top.
  278.       */
  279.       OLEDBG_BEGIN2("IOleClientSite::ShowObject calledrn");
  280.       lpServerDoc->m_lpOleClientSite->lpVtbl->ShowObject(
  281.             lpServerDoc->m_lpOleClientSite
  282.       );
  283.       OLEDBG_END2
  284.       /* NOTE: if we are an embedded object and we are not
  285.       **    in-place active in our containers window, we must inform our
  286.       **    embedding container that our window is opening.
  287.       **    the container must now hatch our object.
  288.       */
  289. #if defined( INPLACE_SVR )
  290.       if (! lpServerDoc->m_fInPlaceActive)
  291. #endif
  292.       {
  293.          OLEDBG_BEGIN2("IOleClientSite::OnShowWindow(TRUE) calledrn");
  294.          lpServerDoc->m_lpOleClientSite->lpVtbl->OnShowWindow(
  295.                lpServerDoc->m_lpOleClientSite,
  296.                TRUE
  297.          );
  298.          OLEDBG_END2
  299.       }
  300.       /* NOTE: the life-time of our document is controlled by our
  301.       **    client and NOT by the user. we are not an independent
  302.       **    file-level object. we simply want to show our window here.
  303.       **
  304.       **    if we are not in-place active (ie. we are opening
  305.       **    our own window), we must make sure our main app window is
  306.       **    visible. we do not, however, want to give the user
  307.       **    control of the App window; we do not want OleApp_ShowWindow
  308.       **    to call OleApp_Lock on behalf of the user.
  309.       */
  310.       if (! IsWindowVisible(lpOutlineApp->m_hWndApp) ||
  311.             IsIconic(lpOutlineApp->m_hWndApp)) {
  312. #if defined( INPLACE_SVR )
  313.          if (! ((LPSERVERDOC)lpOleDoc)->m_fInPlaceActive)
  314. #endif
  315.             OleApp_ShowWindow(lpOleApp, FALSE /* fGiveUserCtrl */);
  316.          SetFocus(lpOutlineDoc->m_hWndDoc);
  317.       }
  318.    } else
  319. #endif  // OLE_SERVER
  320.    {    // DOCTYPE_NEW || DOCTYPE_FROMFILE
  321.       // we must make sure our app window is visible
  322.       OleApp_ShowWindow(lpOleApp, TRUE /* fGiveUserCtrl */);
  323.    }
  324.    // make document window visible and make sure it is not minimized
  325.    ShowWindow(lpOutlineDoc->m_hWndDoc, SW_SHOWNORMAL);
  326.    SetForegroundWindow(lpOutlineDoc->m_hWndDoc);
  327.    OLEDBG_END3
  328. }
  329. /* OleDoc_HideWindow
  330.  * -----------------
  331.  *
  332.  *      Hide the window of the document from the user.
  333.  *      take away the control of the document by the user.
  334.  */
  335. void OleDoc_HideWindow(LPOLEDOC lpOleDoc, BOOL fShutdown)
  336. {
  337.    LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  338.    LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  339.    LPLINELIST lpLL     = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  340.    if (! IsWindowVisible(lpOutlineDoc->m_hWndDoc))
  341.       return;     // already visible
  342.    OLEDBG_BEGIN3("OleDoc_HideWindowrn")
  343. #if defined( USE_DRAGDROP )
  344.    // The document's window is being hidden, revoke it as a DropTarget
  345.    if (lpOleDoc->m_fRegDragDrop) {
  346.       OLEDBG_BEGIN2("RevokeDragDrop calledrn");
  347.       RevokeDragDrop(LineList_GetWindow(lpLL));
  348.       OLEDBG_END2
  349.       lpOleDoc->m_fRegDragDrop = FALSE ;
  350.    }
  351. #endif  // USE_DRAGDROP
  352.    /* NOTE: the document is now being hidden, so we must release
  353.    **    the external lock made when the document was made visible.
  354.    **    if this is a shutdown situation (fShutdown==TRUE), then OLE
  355.    **    is instructed to release our document. if this is that last
  356.    **    external lock on our document, thus enabling our document to
  357.    **    complete its shutdown operation. If This is not a shutdown
  358.    **    situation (eg. in-place server hiding its window when
  359.    **    UIDeactivating or IOleObject::DoVerb(OLEVERB_HIDE) is called),
  360.    **    then OLE is told to NOT immediately release the document.
  361.    **    this leaves the document in an unstable state where the next
  362.    **    Lock/Unlock sequence will shut the document down (eg. a
  363.    **    linking client connecting and disconnecting).
  364.    */
  365.    if (IsWindowVisible(lpOutlineDoc->m_hWndDoc))
  366.       OleDoc_Lock(lpOleDoc, FALSE /* fLock */, fShutdown);
  367.    ShowWindow(((LPOUTLINEDOC)lpOleDoc)->m_hWndDoc, SW_HIDE);
  368. #if defined( OLE_SERVER )
  369.    {
  370.       LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  371.       /* NOTE: if we are an embedded object and we are not
  372.       **    in-place active, we must inform our
  373.       **    embedding container that our window is hiding (closing
  374.       **    from the user's perspective). the container must now
  375.       **    un-hatch our object.
  376.       */
  377.       if (lpServerDoc->m_lpOleClientSite != NULL
  378. #if defined( INPLACE_SVR )
  379.          && !lpServerDoc->m_fInPlaceVisible
  380. #endif
  381.       ) {
  382.          OLEDBG_BEGIN2("IOleClientSite::OnShowWindow(FALSE) calledrn");
  383.          lpServerDoc->m_lpOleClientSite->lpVtbl->OnShowWindow(
  384.                lpServerDoc->m_lpOleClientSite,
  385.                FALSE
  386.          );
  387.          OLEDBG_END2
  388.       }
  389.    }
  390. #endif
  391.    /* NOTE: if there are no more documents visible to the user.
  392.    **    and the app itself is not under user control, then
  393.    **    it has no reason to stay visible. we thus should hide the
  394.    **    app. we can not directly destroy the app, because it may be
  395.    **    validly being used programatically by another client
  396.    **    application and should remain running. it should simply be
  397.    **    hidded from the user.
  398.    */
  399.    OleApp_HideIfNoReasonToStayVisible(lpOleApp);
  400.    OLEDBG_END3
  401. }
  402. /* OleDoc_Lock
  403. ** -----------
  404. **    Lock/Unlock the Doc object. if the last lock is unlocked and
  405. **    fLastUnlockReleases == TRUE, then the Doc object will shut down
  406. **    (ie. it will recieve its final release and its refcnt will go to 0).
  407. */
  408. HRESULT OleDoc_Lock(LPOLEDOC lpOleDoc, BOOL fLock, BOOL fLastUnlockReleases)
  409. {
  410.    HRESULT hrErr;
  411. #if defined( _DEBUG )
  412.    if (fLock) {
  413.       OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,TRUE) calledrn")
  414.    } else {
  415.       if (fLastUnlockReleases)
  416.          OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,FALSE,TRUE) calledrn")
  417.       else
  418.          OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,FALSE,FALSE) calledrn")
  419.    }
  420. #endif  // _DEBUG
  421.    hrErr = CoLockObjectExternal(
  422.          (LPUNKNOWN)&lpOleDoc->m_Unknown, fLock, fLastUnlockReleases);
  423.    OLEDBG_END2
  424.    return hrErr;
  425. }
  426. /* OleDoc_AddRef
  427. ** -------------
  428. **
  429. **  increment the ref count of the document object.
  430. **
  431. **    Returns the new ref count on the object
  432. */
  433. ULONG OleDoc_AddRef(LPOLEDOC lpOleDoc)
  434. {
  435.    ++lpOleDoc->m_cRef;
  436. #if defined( _DEBUG )
  437.    OleDbgOutRefCnt4(
  438.          "OleDoc_AddRef: cRef++rn",
  439.          lpOleDoc,
  440.          lpOleDoc->m_cRef
  441.    );
  442. #endif
  443.    return lpOleDoc->m_cRef;
  444. }
  445. /* OleDoc_Release
  446. ** --------------
  447. **
  448. **  decrement the ref count of the document object.
  449. **    if the ref count goes to 0, then the document is destroyed.
  450. **
  451. **    Returns the remaining ref count on the object
  452. */
  453. ULONG OleDoc_Release (LPOLEDOC lpOleDoc)
  454. {
  455.    ULONG cRef;
  456.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  457.    LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  458.    /*********************************************************************
  459.    ** NOTE: when the obj refcnt == 0, then destroy the object.     **
  460.    **     otherwise the object is still in use.                        **
  461.    *********************************************************************/
  462.    cRef = --lpOleDoc->m_cRef;
  463. #if defined( _DEBUG )
  464.    OleDbgAssertSz (lpOleDoc->m_cRef >= 0, "Release called with cRef == 0");
  465.    OleDbgOutRefCnt4(
  466.          "OleDoc_Release: cRef--rn", lpOleDoc, cRef);
  467. #endif
  468.    if (cRef == 0)
  469.       OutlineDoc_Destroy((LPOUTLINEDOC)lpOleDoc);
  470.    return cRef;
  471. }
  472. /* OleDoc_QueryInterface
  473. ** ---------------------
  474. **
  475. ** Retrieve a pointer to an interface on the document object.
  476. **
  477. **    NOTE: this function will AddRef the ref cnt of the object.
  478. **
  479. **    Returns S_OK if interface is successfully retrieved.
  480. **            E_NOINTERFACE if the interface is not supported
  481. */
  482. HRESULT OleDoc_QueryInterface(
  483.       LPOLEDOC          lpOleDoc,
  484.       REFIID            riid,
  485.       LPVOID FAR*       lplpvObj
  486. )
  487. {
  488.    LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  489.    SCODE sc = E_NOINTERFACE;
  490.    /* NOTE: we must make sure to set all out ptr parameters to NULL. */
  491.    *lplpvObj = NULL;
  492.    if (IsEqualIID(riid, &IID_IUnknown)) {
  493.       OleDbgOut4("OleDoc_QueryInterface: IUnknown* RETURNEDrn");
  494.       *lplpvObj = (LPVOID) &lpOleDoc->m_Unknown;
  495.       OleDoc_AddRef(lpOleDoc);
  496.       sc = S_OK;
  497.    }
  498.    else if(lpOutlineDoc->m_fDataTransferDoc
  499.          && IsEqualIID(riid, &IID_IDataObject)) {
  500.       OleDbgOut4("OleDoc_QueryInterface: IDataObject* RETURNEDrn");
  501.       *lplpvObj = (LPVOID) &lpOleDoc->m_DataObject;
  502.       OleDoc_AddRef(lpOleDoc);
  503.       sc = S_OK;
  504.    }
  505.    /* NOTE: if this document is a DataTransferDocument used to
  506.    **    support a clipboard or drag/drop operation, then it should
  507.    **    only expose IUnknown, IDataObject, and IDropSource
  508.    **    interfaces. if the document is a normal user document, then
  509.    **    we will also continue to consider our other interfaces.
  510.    */
  511.    if (lpOutlineDoc->m_fDataTransferDoc)
  512.       goto done;
  513.    if(IsEqualIID(riid,&IID_IPersist) || IsEqualIID(riid,&IID_IPersistFile)) {
  514.       OleDbgOut4("OleDoc_QueryInterface: IPersistFile* RETURNEDrn");
  515.       *lplpvObj = (LPVOID) &lpOleDoc->m_PersistFile;
  516.       OleDoc_AddRef(lpOleDoc);
  517.       sc = S_OK;
  518.    }
  519.    else if(IsEqualIID(riid, &IID_IOleItemContainer) ||
  520.          IsEqualIID(riid, &IID_IOleContainer) ||
  521.          IsEqualIID(riid, &IID_IParseDisplayName) ) {
  522.       OleDbgOut4("OleDoc_QueryInterface: IOleItemContainer* RETURNEDrn");
  523.       *lplpvObj = (LPVOID) &lpOleDoc->m_OleItemContainer;
  524.       OleDoc_AddRef(lpOleDoc);
  525.       sc = S_OK;
  526.    }
  527.    else if(IsEqualIID(riid, &IID_IExternalConnection)) {
  528.       OleDbgOut4("OleDoc_QueryInterface: IExternalConnection* RETURNEDrn");
  529.       *lplpvObj = (LPVOID) &lpOleDoc->m_ExternalConnection;
  530.       OleDoc_AddRef(lpOleDoc);
  531.       sc = S_OK;
  532.    }
  533. #if defined( USE_DRAGDROP )
  534.    else if(IsEqualIID(riid, &IID_IDropTarget)) {
  535.       OleDbgOut4("OleDoc_QueryInterface: IDropTarget* RETURNEDrn");
  536.       *lplpvObj = (LPVOID) &lpOleDoc->m_DropTarget;
  537.       OleDoc_AddRef(lpOleDoc);
  538.       sc = S_OK;
  539.    }
  540.    else if(IsEqualIID(riid, &IID_IDropSource)) {
  541.       OleDbgOut4("OleDoc_QueryInterface: IDropSource* RETURNEDrn");
  542.       *lplpvObj = (LPVOID) &lpOleDoc->m_DropSource;
  543.       OleDoc_AddRef(lpOleDoc);
  544.       sc = S_OK;
  545.    }
  546. #endif
  547. #if defined( OLE_CNTR )
  548.    else if (IsEqualIID(riid, &IID_IOleUILinkContainer)) {
  549.       OleDbgOut4("OleDoc_QueryInterface: IOleUILinkContainer* RETURNEDrn");
  550.       *lplpvObj=(LPVOID)&((LPCONTAINERDOC)lpOleDoc)->m_OleUILinkContainer;
  551.       OleDoc_AddRef(lpOleDoc);
  552.       sc = S_OK;
  553.    }
  554. #endif
  555. #if defined( OLE_SERVER )
  556.    /* NOTE: if OLE server version, than also offer the server
  557.    **    specific interfaces: IOleObject and IPersistStorage.
  558.    */
  559.    else if (IsEqualIID(riid, &IID_IOleObject)) {
  560.       OleDbgOut4("OleDoc_QueryInterface: IOleObject* RETURNEDrn");
  561.       *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_OleObject;
  562.       OleDoc_AddRef(lpOleDoc);
  563.       sc = S_OK;
  564.    }
  565.    else if(IsEqualIID(riid, &IID_IPersistStorage)) {
  566.       OleDbgOut4("OleDoc_QueryInterface: IPersistStorage* RETURNEDrn");
  567.       *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_PersistStorage;
  568.       OleDoc_AddRef(lpOleDoc);
  569.       sc = S_OK;
  570.    }
  571.    else if(IsEqualIID(riid, &IID_IDataObject)) {
  572.       OleDbgOut4("OleDoc_QueryInterface: IDataObject* RETURNEDrn");
  573.       *lplpvObj = (LPVOID) &lpOleDoc->m_DataObject;
  574.       OleDoc_AddRef(lpOleDoc);
  575.       sc = S_OK;
  576.    }
  577. #if defined( SVR_TREATAS )
  578.    else if(IsEqualIID(riid, &IID_IStdMarshalInfo)) {
  579.       OleDbgOut4("OleDoc_QueryInterface: IStdMarshalInfo* RETURNEDrn");
  580.       *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_StdMarshalInfo;
  581.       OleDoc_AddRef(lpOleDoc);
  582.       sc = S_OK;
  583.    }
  584. #endif  // SVR_TREATAS
  585. #if defined( INPLACE_SVR )
  586.    else if (IsEqualIID(riid, &IID_IOleWindow) ||
  587.           IsEqualIID(riid, &IID_IOleInPlaceObject)) {
  588.       OleDbgOut4("OleDoc_QueryInterface: IOleInPlaceObject* RETURNEDrn");
  589.       *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_OleInPlaceObject;
  590.       OleDoc_AddRef(lpOleDoc);
  591.       sc = S_OK;
  592.    }
  593. #endif // INPLACE_SVR
  594. #endif // OLE_SERVER
  595. done:
  596.    OleDbgQueryInterfaceMethod(*lplpvObj);
  597.    return sc;
  598. }
  599. /* OleDoc_Close
  600.  * ------------
  601.  *
  602.  *  Close the document.
  603.  *      This functions performs the actions that are in common to all
  604.  *      document types which derive from OleDoc (eg. ContainerDoc and
  605.  *      ServerDoc) which are required to close a document.
  606.  *
  607.  *  Returns:
  608.  *      FALSE -- user canceled the closing of the doc.
  609.  *      TRUE -- the doc was successfully closed
  610.  */
  611. BOOL OleDoc_Close(LPOLEDOC lpOleDoc, DWORD dwSaveOption)
  612. {
  613.    LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  614.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  615.    LPOLEDOC lpClipboardDoc;
  616.    LPLINELIST lpLL     = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  617.    BOOL fAbortIfSaveCanceled = (dwSaveOption == OLECLOSE_PROMPTSAVE);
  618.    if (! lpOleDoc)
  619.       return TRUE;    // active doc's are already destroyed
  620.    if (lpOleDoc->m_fObjIsClosing)
  621.       return TRUE;    // Closing is already in progress
  622.    OLEDBG_BEGIN3("OleDoc_Closern")
  623.    if (! OutlineDoc_CheckSaveChanges((LPOUTLINEDOC)lpOleDoc,&dwSaveOption)
  624.          && fAbortIfSaveCanceled) {
  625.       OLEDBG_END3
  626.       return FALSE;           // cancel closing the doc
  627.    }
  628.    lpOleDoc->m_fObjIsClosing = TRUE;   // guard against recursive call
  629.    /* NOTE: in order to have a stable app and doc during the
  630.    **    process of closing, we intially AddRef the App and Doc ref
  631.    **    cnts and later Release them. These initial AddRefs are
  632.    **    artificial; they simply guarantee that these objects do not
  633.    **    get destroyed until the end of this routine.
  634.    */
  635.    OleApp_AddRef(lpOleApp);
  636.    OleDoc_AddRef(lpOleDoc);
  637. #if defined( OLE_CNTR )
  638.    {
  639.       LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
  640.       /* NOTE: force all OLE objects to close. this forces all
  641.       **    OLE object to transition from running to loaded. we can
  642.       **    NOT exit if any embeddings are still running.
  643.       **    if an object can't be closed and this close operation was
  644.       **    started by the user, then we will abort closing our document.
  645.       */
  646.       if (! ContainerDoc_CloseAllOleObjects(lpContainerDoc, OLECLOSE_NOSAVE)
  647.             && fAbortIfSaveCanceled) {
  648.          OleDoc_Release(lpOleDoc);       // release artificial AddRef above
  649.          OleApp_Release(lpOleApp);       // release artificial AddRef above
  650.          lpOleDoc->m_fObjIsClosing = FALSE; // clear recursion guard
  651.          OLEDBG_END3
  652.          return FALSE;   // Closing is aborted
  653.       }
  654.    }
  655. #endif
  656. #if defined( INPLACE_SVR )
  657.    /* NOTE: if the server is currently in-place active we must
  658.    **    deactivate it now before closing
  659.    */
  660.    ServerDoc_DoInPlaceDeactivate((LPSERVERDOC)lpOleDoc);
  661. #endif
  662.    /* NOTE: if this document is the source of data for the
  663.    **    clipboard, then flush the clipboard. it is important to flush
  664.    **    the clipboard BEFORE calling sending any notifications to
  665.    **    clients (eg. IOleClientSite::OnShowWindow(FALSE)) which could
  666.    **    give them a chance to run and try to get our clipboard data
  667.    **    object that we want to destroy. (eg. our app tries to
  668.    **    update the paste button of the toolbar when
  669.    **    WM_ACTIVATEAPP is received.)
  670.    */
  671.    lpClipboardDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc;
  672.    if (lpClipboardDoc &&
  673.       lpClipboardDoc->m_lpSrcDocOfCopy == lpOleDoc) {
  674.       OleApp_FlushClipboard(lpOleApp);
  675.    }
  676.    /* NOTE: Revoke the object from the Running Object Table. it is
  677.    **    best if the object is revoke prior to calling
  678.    **    COLockObjectExternal(FALSE,TRUE) which is called when the
  679.    **    document window is hidden from the user.
  680.    */
  681.    OLEDBG_BEGIN3("OleStdRevokeAsRunning calledrn")
  682.    OleStdRevokeAsRunning(&lpOleDoc->m_dwRegROT);
  683.    OLEDBG_END3
  684.    /* NOTE: if the user is in control of the document, the user
  685.    **    accounts for one refcnt on the document. Closing the
  686.    **    document is achieved by releasing the object on behalf of
  687.    **    the user. if the document is not referenced by any other
  688.    **    clients, then the document will also be destroyed. if it
  689.    **    is referenced by other clients, then it will remain until
  690.    **    they release it. it is important to hide the window and call
  691.    **    IOleClientSite::OnShowWindow(FALSE) BEFORE sending OnClose
  692.    **    notification.
  693.    */
  694.    OleDoc_HideWindow(lpOleDoc, TRUE);
  695. #if defined( OLE_SERVER )
  696.    {
  697.       LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  698.       LPSERVERNAMETABLE lpServerNameTable =
  699.          (LPSERVERNAMETABLE)((LPOUTLINEDOC)lpOleDoc)->m_lpNameTable;
  700.       /* NOTE: force all pseudo objects to close. this informs all
  701.       **    linking clients of pseudo objects to release their PseudoObj.
  702.       */
  703.       ServerNameTable_CloseAllPseudoObjs(lpServerNameTable);
  704.       /* NOTE: send last OnDataChange notification to clients
  705.       **    that have registered for data notifications when object
  706.       **    stops running (ADVF_DATAONSTOP), if the data in our
  707.       **    object has ever changed. it is best to only send this
  708.       **    notification if necessary.
  709.       */
  710.       if (lpServerDoc->m_lpDataAdviseHldr) {
  711.          if (lpServerDoc->m_fSendDataOnStop) {
  712.             ServerDoc_SendAdvise(
  713.                   (LPSERVERDOC)lpOleDoc,
  714.                   OLE_ONDATACHANGE,
  715.                   NULL,   /* lpmkDoc -- not relevant here */
  716.                   ADVF_DATAONSTOP
  717.             );
  718.          }
  719.          /* NOTE: we just sent the last data notification that we
  720.          **    need to send; release our DataAdviseHolder. we SHOULD be
  721.          **    the only one using it.
  722.          */
  723.          OleStdVerifyRelease(
  724.                (LPUNKNOWN)lpServerDoc->m_lpDataAdviseHldr,
  725.                OLESTR("DataAdviseHldr not released properly")
  726.          );
  727.          lpServerDoc->m_lpDataAdviseHldr = NULL;
  728.       }
  729.       // NOTE: inform all of our linking clients that we are closing.
  730.       if (lpServerDoc->m_lpOleAdviseHldr) {
  731.          ServerDoc_SendAdvise(
  732.                (LPSERVERDOC)lpOleDoc,
  733.                OLE_ONCLOSE,
  734.                NULL,   /* lpmkDoc -- not relevant here */
  735.                0       /* advf -- not relevant here */
  736.          );
  737.          /* NOTE: OnClose is the last notification that we need to
  738.          **    send; release our OleAdviseHolder. we SHOULD be the only
  739.          **    one using it. this will make our destructor realize that
  740.          **    OnClose notification has already been sent.
  741.          */
  742.          OleStdVerifyRelease(
  743.                (LPUNKNOWN)lpServerDoc->m_lpOleAdviseHldr,
  744.                OLESTR("OleAdviseHldr not released properly")
  745.          );
  746.          lpServerDoc->m_lpOleAdviseHldr = NULL;
  747.       }
  748.       /* release our Container's ClientSite. */
  749.       if(lpServerDoc->m_lpOleClientSite) {
  750.          OleStdRelease((LPUNKNOWN)lpServerDoc->m_lpOleClientSite);
  751.          lpServerDoc->m_lpOleClientSite = NULL;
  752.       }
  753.    }
  754. #endif
  755.    if (lpOleDoc->m_lpLLStm) {
  756.       /* release our LineList stream. */
  757.       OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpLLStm);
  758.       lpOleDoc->m_lpLLStm = NULL;
  759.    }
  760.    if (lpOleDoc->m_lpNTStm) {
  761.       /* release our NameTable stream. */
  762.       OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpNTStm);
  763.       lpOleDoc->m_lpNTStm = NULL;
  764.    }
  765.    if (lpOleDoc->m_lpStg) {
  766.       /* release our doc storage. */
  767.       OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpStg);
  768.       lpOleDoc->m_lpStg = NULL;
  769.    }
  770.    if (lpOleDoc->m_lpFileMoniker) {
  771.       OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpFileMoniker);
  772.       lpOleDoc->m_lpFileMoniker = NULL;
  773.    }
  774.    /* NOTE: this call forces all external connections to our
  775.    **    object to close down and therefore guarantees that we receive
  776.    **    all releases associated with those external connections.
  777.    */
  778.    OLEDBG_BEGIN2("CoDisconnectObject(lpDoc) calledrn")
  779.    CoDisconnectObject((LPUNKNOWN)&lpOleDoc->m_Unknown, 0);
  780.    OLEDBG_END2
  781.    OleDoc_Release(lpOleDoc);       // release artificial AddRef above
  782.    OleApp_Release(lpOleApp);       // release artificial AddRef above
  783.    OLEDBG_END3
  784.    return TRUE;
  785. }
  786. /* OleDoc_Destroy
  787.  * --------------
  788.  *
  789.  *  Free all OLE related resources that had been allocated for a document.
  790.  */
  791. void OleDoc_Destroy(LPOLEDOC lpOleDoc)
  792. {
  793.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  794.    LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  795.    if (lpOleDoc->m_fObjIsDestroying)
  796.       return;     // Doc destruction is already in progress
  797.    lpOleDoc->m_fObjIsDestroying = TRUE;    // guard against recursive call
  798. #if defined( OLE_SERVER )
  799.    /* NOTE: it is ALWAYS necessary to make sure that the work we
  800.    **    do in our OleDoc_Close function is performed before we
  801.    **    destroy our document object. this includes revoking from the
  802.    **    Running Object Table (ROT), sending OnClose notification,
  803.    **    revoking from Drag/Drop, closing all pseudo objects, etc.
  804.    **    There are some tricky scenarios involving linking and
  805.    **    when IOleObject::Close is called versus when we get our
  806.    **    final release causing us to call our OleDoc_Destroy
  807.    **    (destructor) function.
  808.    **
  809.    **    SCENARIO 1 -- closing from server (File.Exit or File.Close)
  810.    **                  OleDoc_Close function is called directly by the
  811.    **                  server in response to the menu command
  812.    **                  (WM_COMMAND processing).
  813.    **
  814.    **    SCENARIO 2 -- closed by embedding container
  815.    **                  our embedding container calls IOleObject::Close
  816.    **                  directly.
  817.    **
  818.    **    SCENARIO 3 -- silent-update final release
  819.    **                  THIS IS THE TRICKY ONE!!!
  820.    **                  in the case that our object is launched because
  821.    **                  a linking client calls IOleObject::Update on
  822.    **                  its link, then our object will be run
  823.    **                  invisibly, typically GetData will be called,
  824.    **                  and then the connection from the linking client
  825.    **                  will be released. the release of this last
  826.    **                  linking connection should cause our object to
  827.    **                  shut down.
  828.    **                  there are 2 strategies to deal with this scenario:
  829.    **
  830.    **                  STRATEGY 1 -- implement IExternalConnection.
  831.    **                  IExternalConnection::AddConnection will be
  832.    **                  called (by the StubManager) every time that an
  833.    **                  external (linking) connection is created or
  834.    **                  CoLockObjectExternal is called. the object
  835.    **                  should maintain a count of strong connections
  836.    **                  (m_dwStrongExtConn). IExternalConnection::
  837.    **                  ReleaseConnection will be called when these
  838.    **                  connections are released. when the
  839.    **                  m_dwStrongExtConn transistions to 0, the object
  840.    **                  should call its IOleObject::Close function.
  841.    **                  this assumes that CoLockObjectExternal is used
  842.    **                  to manage locks by the object itself (eg. when
  843.    **                  the object is visible to the user--fUserCtrl,
  844.    **                  and when PseudoObjects are created, etc.)
  845.    **                  this is the strategy implemented by SVROUTL.
  846.    **
  847.    **                  STRATEGY 2 -- guard both the destructor
  848.    **                  function and the Close function. if the
  849.    **                  destructor is called directly without Close
  850.    **                  first being called, then call Close before
  851.    **                  proceeding with the destruction code.
  852.    **                  previously SVROUTL was organized in this
  853.    **                  manner. that old code is conditionaly compiled
  854.    **                  away with "#ifdef OBSOLETE" below. this
  855.    **                  method has the disadvantage that external
  856.    **                  remoting is no longer possible by the time the
  857.    **                  Close is called making it impossible for
  858.    **                  the object to ask its container to save the
  859.    **                  object if the object is dirty. this can result
  860.    **                  in data loss. thus STRATEGY 1 is safer.
  861.    **                  consider the scenario where an in-place
  862.    **                  container UIDeactivates an object but does NOT
  863.    **                  keep the object locked running (this is
  864.    **                  required--see CntrLine_IPSite_OnInPlaceActivate
  865.    **                  in cntrline.c), then, if a linking client binds
  866.    **                  and unbinds from the object, the object will be
  867.    **                  destroyed and will NOT have an opportunity to
  868.    **                  be saved. by implementing IExternalConnection,
  869.    **                  a server can insulate itself from a poorly
  870.    **                  written container.
  871.    */
  872. #if defined( _DEBUG )
  873.    OleDbgAssertSz(
  874.          (lpOutlineDoc->m_fDataTransferDoc || lpOleDoc->m_fObjIsClosing),
  875.          "Destroy called without Close being calledrn"
  876.    );
  877. #endif  // _DEBUG
  878. #if defined( OBSOLETE )
  879.    /* NOTE: if the document destructor is called directly because
  880.    **    the object's refcnt went to 0 (ie. without OleDoc_Close first
  881.    **    being called), then we need to make sure that the document is
  882.    **    properly closed before destroying the object. this scenario
  883.    **    could arise during a silent-update of a link. calling
  884.    **    OleDoc_Close here guarantees that the clipboard will be
  885.    **    properly flushed, the doc's moniker will be properly revoked,
  886.    **    the document will be saved if necessary, etc.
  887.    */
  888.    if (!lpOutlineDoc->m_fDataTransferDoc && !lpOleDoc->m_fObjIsClosing)
  889.       OleDoc_Close(lpOleDoc, OLECLOSE_NOSAVE);
  890. #endif
  891.    {
  892.       LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  893.       /* NOTE: perform processing specific for an OLE server */
  894. #if defined( SVR_TREATAS )
  895.       if (lpServerDoc->m_lpszTreatAsType) {
  896.          OleStdFreeString(lpServerDoc->m_lpszTreatAsType, NULL);
  897.          lpServerDoc->m_lpszTreatAsType = NULL;
  898.       }
  899. #endif  // SVR_TREATAS
  900. #if defined( INPLACE_SVR )
  901.       if (IsWindow(lpServerDoc->m_hWndHatch))
  902.          DestroyWindow(lpServerDoc->m_hWndHatch);
  903. #endif  // INPLACE_SVR
  904.    }
  905. #endif  // OLE_SERVER
  906.    if (lpOleDoc->m_lpLLStm) {
  907.       /* release our LineList stream. */
  908.       OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpLLStm);
  909.       lpOleDoc->m_lpLLStm = NULL;
  910.    }
  911.    if (lpOleDoc->m_lpNTStm) {
  912.       /* release our NameTable stream. */
  913.       OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpNTStm);
  914.       lpOleDoc->m_lpNTStm = NULL;
  915.    }
  916.    if (lpOleDoc->m_lpStg) {
  917.       /* release our doc storage. */
  918.       OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpStg);
  919.       lpOleDoc->m_lpStg = NULL;
  920.    }
  921.    if (lpOleDoc->m_lpFileMoniker) {
  922.       OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpFileMoniker);
  923.       lpOleDoc->m_lpFileMoniker = NULL;
  924.    }
  925.    /*****************************************************************
  926.    ** NOTE: each document addref's the app object in order to  **
  927.    **    guarentee that the app does not shut down while the doc   **
  928.    **    is still open. since this doc is now destroyed, we will   **
  929.    **    release this refcnt now. if there are now more open       **
  930.    **    documents AND the app is not under the control of the     **
  931.    **    user (ie. launched by OLE) then the app will revoke its   **
  932.    **    ClassFactory. if there are no more references to the      **
  933.    **    ClassFactory after it is revoked, then the app will shut  **
  934.    **    down. this whole procedure is triggered by calling        **
  935.    **    OutlineApp_DocUnlockApp.                                  **
  936.    *****************************************************************/
  937.    OutlineApp_DocUnlockApp(lpOutlineApp, lpOutlineDoc);
  938. }
  939. /* OleDoc_SetUpdateEditMenuFlag
  940.  * ----------------------------
  941.  *
  942.  *  Purpose:
  943.  *      Set/clear the UpdateEditMenuFlag in OleDoc.
  944.  *
  945.  *  Parameters:
  946.  *      fUpdate     new value of the flag
  947.  *
  948.  *  Returns:
  949.  */
  950. void OleDoc_SetUpdateEditMenuFlag(LPOLEDOC lpOleDoc, BOOL fUpdate)
  951. {
  952.    if (!lpOleDoc)
  953.       return;
  954.    lpOleDoc->m_fUpdateEditMenu = fUpdate;
  955. }
  956. /* OleDoc_GetUpdateEditMenuFlag
  957.  * ----------------------------
  958.  *
  959.  *  Purpose:
  960.  *      Get the value of the UpdateEditMenuFlag in OleDoc
  961.  *
  962.  *  Parameters:
  963.  *
  964.  *  Returns:
  965.  *      value of the flag
  966.  */
  967. BOOL OleDoc_GetUpdateEditMenuFlag(LPOLEDOC lpOleDoc)
  968. {
  969.    if (!lpOleDoc)
  970.       return FALSE;
  971.    return lpOleDoc->m_fUpdateEditMenu;
  972. }
  973. /*************************************************************************
  974. ** OleDoc::IUnknown interface implementation
  975. *************************************************************************/
  976. STDMETHODIMP OleDoc_Unk_QueryInterface(
  977.       LPUNKNOWN           lpThis,
  978.       REFIID              riid,
  979.       LPVOID FAR*         lplpvObj
  980. )
  981. {
  982.    LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc;
  983.    return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
  984. }
  985. STDMETHODIMP_(ULONG) OleDoc_Unk_AddRef(LPUNKNOWN lpThis)
  986. {
  987.    LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc;
  988.    OleDbgAddRefMethod(lpThis, "IUnknown");
  989.    return OleDoc_AddRef(lpOleDoc);
  990. }
  991. STDMETHODIMP_(ULONG) OleDoc_Unk_Release (LPUNKNOWN lpThis)
  992. {
  993.    LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc;
  994.    OleDbgReleaseMethod(lpThis, "IUnknown");
  995.    return OleDoc_Release(lpOleDoc);
  996. }