home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / olesvr1.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  77KB  |  3,042 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #include <shellapi.h>
  13.  
  14. #ifdef AFX_OLE4_SEG
  15. #pragma code_seg(AFX_OLE4_SEG)
  16. #endif
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. #define new DEBUG_NEW
  24.  
  25. //////////////////////////////////////////////////////////////////////////////
  26. // COleServerDoc implementation
  27.  
  28. COleServerDoc::COleServerDoc()
  29. {
  30.     m_lpClientSite = NULL;  // will be non-NULL when document is embedding
  31.     m_bCntrVisible = FALSE;
  32.     m_pInPlaceFrame = NULL; // will be non-NULL when in-place active
  33.     m_pOrigParent = NULL;
  34.     m_dwOrigStyle = 0;
  35.     m_dwOrigStyleEx = 0;
  36.     m_bClosing = FALSE;
  37.     m_pEmbeddedItem = NULL; // will be non-NULL if embedded item needed
  38.     m_pDocObjectServer = NULL;      // becomes non-NULL if DocObject support enabled
  39. }
  40.  
  41. COleServerDoc::~COleServerDoc()
  42. {
  43.     DeleteContents();   // Note: will not call derived class
  44.  
  45.     if (m_pEmbeddedItem != NULL)
  46.     {
  47.         m_pEmbeddedItem->ExternalRelease();
  48.         m_pEmbeddedItem = NULL;
  49.     }
  50.  
  51.     // disconnect (remove) all items from the document
  52.     POSITION pos = GetStartPosition();
  53.     COleServerItem* pItem;
  54.     while ((pItem = GetNextServerItem(pos)) != NULL)
  55.         RemoveItem(pItem);
  56.  
  57.     // release doc object manager, if any
  58.     if (m_pDocObjectServer != NULL)
  59.     {
  60.         delete m_pDocObjectServer;
  61.         m_pDocObjectServer = NULL;
  62.     }
  63.  
  64.     // should not be in-place active when doc is destroyed!
  65.     ASSERT(m_pInPlaceFrame == NULL);
  66.  
  67.     // Note: this must be done before the client site is released
  68.     RELEASE(m_lpRootStg);
  69.  
  70.     // release client-site pointer
  71.     RELEASE(m_lpClientSite);
  72. }
  73.  
  74. void COleServerDoc::DeleteContents()
  75. {
  76.     COleLinkingDoc::DeleteContents();
  77.  
  78.     // protect all server items with an extra reference count
  79.     POSITION pos = GetStartPosition();
  80.     COleServerItem* pItem;
  81.     while ((pItem = GetNextServerItem(pos)) != NULL)
  82.         pItem->InternalAddRef();
  83.  
  84.     // delete any autodelete server items
  85.     pos = GetStartPosition();
  86.     while ((pItem = GetNextServerItem(pos)) != NULL)
  87.     {
  88.         if (pItem->m_bAutoDelete)
  89.             delete pItem;
  90.     }
  91.  
  92.     // remove extra reference added above
  93.     pos = GetStartPosition();
  94.     while ((pItem = GetNextServerItem(pos)) != NULL)
  95.         pItem->InternalRelease();
  96. }
  97.  
  98. COleServerItem* COleServerDoc::GetEmbeddedItem()
  99. {
  100.     // allocate embedded item if necessary
  101.     if (m_pEmbeddedItem == NULL)
  102.     {
  103.         m_pEmbeddedItem = OnGetEmbeddedItem();
  104.         m_pEmbeddedItem->ExternalAddRef();
  105.     }
  106.  
  107.     ASSERT_VALID(m_pEmbeddedItem);
  108.     return m_pEmbeddedItem;
  109. }
  110.  
  111. CDocObjectServer* COleServerDoc::GetDocObjectServer(LPOLEDOCUMENTSITE pDocSite)
  112. {
  113.     // by default, we're not DocObject enabled
  114.     UNUSED_ALWAYS(pDocSite);
  115.     return NULL;
  116. }
  117.  
  118. HRESULT COleServerDoc::OnExecOleCmd(const GUID* pguidCmdGroup, DWORD nCmdID,
  119.         DWORD nCmdExecOpt, VARIANTARG* pvarargIn, VARIANTARG* pvarargOut)
  120. {
  121.     UNUSED_ALWAYS(pguidCmdGroup);
  122.     UNUSED_ALWAYS(nCmdID);
  123.     UNUSED_ALWAYS(nCmdExecOpt);
  124.     UNUSED_ALWAYS(pvarargIn);
  125.     UNUSED_ALWAYS(pvarargOut);
  126.  
  127.     return E_NOTIMPL;
  128. }
  129.  
  130. LPUNKNOWN COleServerDoc::GetInterfaceHook(const void* piid)
  131. {
  132.     LPUNKNOWN lpUnk = NULL;
  133.  
  134.     // are we Doc Object supporters?
  135.     if (m_pDocObjectServer != NULL)
  136.     {
  137.         // don't be tricked into handing out a different IUnknown
  138.         DWORD lData1 = ((IID*)piid)->Data1;
  139.         BOOL bUnknown = ((DWORD*)&IID_IUnknown)[0] == lData1 &&
  140.             ((DWORD*)piid)[1] == ((DWORD*)&IID_IUnknown)[1] &&
  141.             ((DWORD*)piid)[2] == ((DWORD*)&IID_IUnknown)[2] &&
  142.             ((DWORD*)piid)[3] == ((DWORD*)&IID_IUnknown)[3];
  143.  
  144.         if (bUnknown)
  145.             return NULL;
  146.  
  147.         lpUnk = m_pDocObjectServer->GetInterface(piid);
  148.     }
  149.  
  150.     // failing that, try the base class
  151.     if (lpUnk == NULL)
  152.         lpUnk = COleLinkingDoc::GetInterfaceHook(piid);
  153.  
  154.     return lpUnk;
  155. }
  156.  
  157. void COleServerDoc::ActivateDocObject()
  158. {
  159.     if (m_pDocObjectServer != NULL)
  160.         m_pDocObjectServer->ActivateDocObject();
  161. }
  162.  
  163. /////////////////////////////////////////////////////////////////////////////
  164. // COleServerDoc client notifications
  165.  
  166. void COleServerDoc::NotifyRename(LPCTSTR lpszNewName)
  167. {
  168.     ASSERT_VALID(this);
  169.     ASSERT(AfxIsValidString(lpszNewName));
  170.  
  171.     if (m_pFactory != NULL)
  172.     {
  173.         // update running object table with new moniker
  174.         Revoke();
  175.         Register(m_pFactory, lpszNewName);
  176.  
  177.         // notify all items of the new moniker
  178.         POSITION pos = GetStartPosition();
  179.         COleServerItem* pItem;
  180.         while ((pItem = GetNextServerItem(pos)) != NULL)
  181.         {
  182.             // notify client directly
  183.             LPMONIKER lpMoniker = pItem->GetMoniker(OLEGETMONIKER_ONLYIFTHERE);
  184.             pItem->NotifyClient(OLE_RENAMED, (DWORD)lpMoniker);
  185.             RELEASE(lpMoniker);
  186.         }
  187.     }
  188. }
  189.  
  190. void COleServerDoc::NotifyAllItems(OLE_NOTIFICATION nCode, DWORD dwParam)
  191. {
  192.     ASSERT_VALID(this);
  193.  
  194.     POSITION pos = GetStartPosition();
  195.     COleServerItem* pItem;
  196.     while ((pItem = GetNextServerItem(pos)) != NULL)
  197.     {
  198.         // notify client directly
  199.         pItem->NotifyClient(nCode, dwParam);
  200.     }
  201. }
  202.  
  203. // UpdateAllItems is much like UpdateAllViews, but for server items
  204. void COleServerDoc::UpdateAllItems(COleServerItem* pSender,
  205.     LPARAM lHint, CObject* pHint, DVASPECT nDrawAspect)
  206. {
  207.     ASSERT_VALID(this);
  208.  
  209.     POSITION pos = GetStartPosition();
  210.     COleServerItem* pItem;
  211.     while ((pItem = GetNextServerItem(pos)) != NULL)
  212.     {
  213.         // notify client indirectly through OnUpdate
  214.         if (pItem != pSender)
  215.             pItem->OnUpdate(pSender, lHint, pHint, nDrawAspect);
  216.     }
  217. }
  218.  
  219. void COleServerItem::OnUpdate(COleServerItem* /*pSender*/,
  220.     LPARAM /*lHint*/, CObject* /*pHint*/, DVASPECT nDrawAspect)
  221. {
  222.     // the default implementation always notifies the container, regardless
  223.     //  of the specific hint or sender.
  224.  
  225.     NotifyChanged(nDrawAspect);
  226. }
  227.  
  228. /////////////////////////////////////////////////////////////////////////////
  229. // COleServerDoc attributes
  230.  
  231. BOOL COleServerDoc::GetZoomFactor(LPSIZE lpSizeNum, LPSIZE lpSizeDenom,
  232.     LPCRECT lpPosRect) const
  233. {
  234.     ASSERT_VALID(this);
  235.     ASSERT(lpSizeNum == NULL || AfxIsValidAddress(lpSizeNum, sizeof(SIZE)));
  236.     ASSERT(lpSizeDenom == NULL || AfxIsValidAddress(lpSizeDenom, sizeof(SIZE)));
  237.     ASSERT(lpPosRect == NULL ||
  238.         AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
  239.  
  240.     if (!IsInPlaceActive())
  241.     {
  242.         if (lpSizeNum != NULL)
  243.         {
  244.             ASSERT(lpSizeDenom != NULL);
  245.             lpSizeNum->cx = 1;
  246.             lpSizeNum->cy = 1;
  247.             *lpSizeDenom = *lpSizeNum;
  248.         }
  249.         return FALSE;
  250.     }
  251.     ASSERT_VALID(m_pInPlaceFrame);
  252.  
  253.     // the zoom factor is (Size(position-rect) / m_sizeExtent)
  254.     CSize sizeNum;
  255.     if (lpPosRect == NULL)
  256.     {
  257.         // use current position rect
  258.         sizeNum = m_pInPlaceFrame->m_rectPos.Size();
  259.     }
  260.     else
  261.     {
  262.         // use new position rect
  263.         sizeNum.cx = lpPosRect->right - lpPosRect->left;
  264.         sizeNum.cy = lpPosRect->bottom - lpPosRect->top;
  265.     }
  266.  
  267.     // m_sizeExtent is in HIMETRIC units -- need to convert to pixels.
  268.     CSize sizeDenom(0, 0);
  269.     COleServerItem* pItem = ((COleServerDoc*)this)->GetEmbeddedItem();
  270.     ASSERT_VALID(pItem);
  271.     ASSERT_KINDOF(COleServerItem, pItem);
  272.  
  273.     // get zoom denominator, which is based on the current extent
  274.     ((COleServerItem*)pItem)->OnGetExtent(DVASPECT_CONTENT, sizeDenom);
  275.     if (sizeDenom.cx == 0 || sizeDenom.cy == 0)
  276.     {
  277.         // no extent from container available, so use natural extent instead
  278.         pItem->OnGetExtent(DVASPECT_CONTENT, sizeDenom);
  279.     }
  280.     // convert extent to pixels first
  281.     ((CDC*)NULL)->HIMETRICtoDP(&sizeDenom);
  282.  
  283.     // might be bad to have zoom denominator of zero!
  284.     if (sizeDenom.cy == 0 || sizeDenom.cx == 0)
  285.     {
  286.         TRACE0("Warning: zero 'zoom denominator', using 100%% zoom instead.\n");
  287.         sizeDenom = sizeNum;
  288.     }
  289.  
  290.     // store the results
  291.     if (lpSizeNum != NULL)
  292.     {
  293.         ASSERT(lpSizeDenom != NULL);
  294.         *lpSizeNum = sizeNum;
  295.         *lpSizeDenom = sizeDenom;
  296.     }
  297.  
  298.     // if 100% scaling, return FALSE
  299.     return sizeNum != sizeDenom;
  300. }
  301.  
  302. void COleServerDoc::GetItemPosition(LPRECT lpPosRect) const
  303. {
  304.     ASSERT_VALID(this);
  305.     ASSERT(AfxIsValidAddress(lpPosRect, sizeof(RECT)));
  306.     ASSERT(IsInPlaceActive());
  307.     ASSERT_VALID(m_pInPlaceFrame);
  308.  
  309.     // copy the current rectangle
  310.     *lpPosRect = m_pInPlaceFrame->m_rectPos;
  311. }
  312.  
  313. void COleServerDoc::GetItemClipRect(LPRECT lpClipRect) const
  314. {
  315.     ASSERT_VALID(this);
  316.     ASSERT(AfxIsValidAddress(lpClipRect, sizeof(RECT)));
  317.     ASSERT(IsInPlaceActive());
  318.     ASSERT_VALID(m_pInPlaceFrame);
  319.  
  320.     // copy the current rectangle
  321.     *lpClipRect = m_pInPlaceFrame->m_rectClip;
  322. }
  323.  
  324. /////////////////////////////////////////////////////////////////////////////
  325. // COleServerDoc overrideables
  326.  
  327. COleServerItem* COleServerDoc::OnGetLinkedItem(LPCTSTR lpszItemName)
  328. {
  329.     ASSERT_VALID(this);
  330.     ASSERT(AfxIsValidString(lpszItemName));
  331.  
  332.     // default implementation walks list of server items looking for
  333.     //  a case sensitive match
  334.  
  335.     POSITION pos = GetStartPosition();
  336.     COleServerItem* pItem;
  337.     while ((pItem = GetNextServerItem(pos)) != NULL)
  338.     {
  339.         // return item if name matches (case sensitive)
  340.         if (lstrcmp(pItem->GetItemName(), lpszItemName) == 0)
  341.             return pItem;
  342.     }
  343.  
  344. #ifdef _DEBUG
  345.     if (afxTraceFlags & traceOle)
  346.     {
  347.         TRACE0("Warning: default COleServerDoc::OnGetLinkedItem implementation\n");
  348.         TRACE1("\tfailed to find item '%s'.\n", lpszItemName);
  349.     }
  350. #endif
  351.     return NULL;        // not found (no link found)
  352. }
  353.  
  354. void COleServerDoc::OnClose(OLECLOSE dwCloseOption)
  355. {
  356.     ASSERT_VALID(this);
  357.  
  358.     // do nothing if already in the process of closing the document
  359.     if (m_bClosing)
  360.         return;
  361.  
  362.     // OLECLOSE_PROMPTSAVE is handled like OLECLOSE_SAVEIFDIRTY if invisible
  363.     CFrameWnd* pFrameWnd = GetFirstFrame();
  364.     if (pFrameWnd != NULL && pFrameWnd->IsWindowVisible())
  365.         dwCloseOption = OLECLOSE_SAVEIFDIRTY;
  366.  
  367.     // handle modified document and special dwCloseOption flags
  368.     TRY
  369.     {
  370.         if (IsModified())
  371.         {
  372.             switch (dwCloseOption)
  373.             {
  374.             case OLECLOSE_PROMPTSAVE:
  375.                 if (!SaveModifiedPrompt())
  376.                     AfxThrowOleException(OLE_E_PROMPTSAVECANCELLED);
  377.                 break;
  378.  
  379.             case OLECLOSE_SAVEIFDIRTY:
  380.                 SaveEmbedding();
  381.                 break;
  382.             }
  383.         }
  384.     }
  385.     END_TRY
  386.  
  387.     // deactivate in-place session
  388.     if (m_pInPlaceFrame != NULL)
  389.     {
  390.         OnDeactivate();
  391.         ASSERT(m_pInPlaceFrame == NULL);
  392.     }
  393.  
  394.     // close the document
  395.     BOOL bAutoDelete = m_bAutoDelete;
  396.     m_bAutoDelete = FALSE;
  397.     OnCloseDocument();
  398.     m_bAutoDelete = bAutoDelete;
  399. }
  400.  
  401. BOOL COleServerDoc::SaveModifiedPrompt()
  402. {
  403.     ASSERT_VALID(this);
  404.  
  405.     if (m_lpClientSite == NULL)
  406.         return SaveModified();
  407.  
  408.     UpdateModifiedFlag();   // check for modified client items
  409.  
  410.     if (!IsModified())
  411.         return TRUE;        // ok to continue
  412.  
  413.     CString prompt;
  414.     AfxFormatString1(prompt, AFX_IDP_ASK_TO_UPDATE, m_strTitle);
  415.     switch (AfxMessageBox(prompt, MB_YESNOCANCEL, AFX_IDP_ASK_TO_UPDATE))
  416.     {
  417.     case IDCANCEL:
  418.         return FALSE;       // don't continue
  419.  
  420.     case IDYES:
  421.         if (!OnUpdateDocument())
  422.         {
  423.             TRACE0("Warning: OnUpdateDocument failed to update.\n");
  424.             // keep going, close will flush it
  425.         }
  426.         break;
  427.     }
  428.     return TRUE;    // keep going
  429. }
  430.  
  431. BOOL COleServerDoc::CanCloseFrame(CFrameWnd* pFrame)
  432. {
  433.     m_bClosing = TRUE;
  434.     if (!COleLinkingDoc::CanCloseFrame(pFrame))
  435.     {
  436.         m_bClosing = FALSE;
  437.         return FALSE;
  438.     }
  439.     return TRUE;
  440. }
  441.  
  442. BOOL COleServerDoc::GetFileTypeString(CString& rString)
  443. {
  444.     ASSERT_VALID(this);
  445.  
  446.     CDocTemplate* pTemplate = GetDocTemplate();
  447.     if (pTemplate == NULL)
  448.         return FALSE;
  449.  
  450.     pTemplate->GetDocString(rString, CDocTemplate::fileNewName);
  451.     return !rString.IsEmpty();
  452. }
  453.  
  454. void COleServerDoc::OnSetHostNames(LPCTSTR lpszHost, LPCTSTR lpszHostObj)
  455. {
  456.     ASSERT_VALID(this);
  457.     ASSERT(lpszHost == NULL || AfxIsValidString(lpszHost));
  458.     ASSERT(lpszHostObj == NULL || AfxIsValidString(lpszHostObj));
  459.     UNUSED(lpszHost);    // unused in release builds
  460.  
  461.     // only change the title for embedded documents
  462.     if (m_lpClientSite != NULL)
  463.     {
  464.         // save name of document for File.Exit update
  465.         if (lpszHostObj == NULL)
  466.             m_strHostObj.LoadString(AFX_IDS_UNTITLED);
  467.         else
  468.             m_strHostObj = lpszHostObj;
  469.  
  470.         // attempt to get the document name from the document template
  471.         CString strFileType;
  472.         if (!GetFileTypeString(strFileType))
  473.             return;
  474.  
  475.         // format the string into <server-name> in <docname>
  476.         CString strTitle;
  477.         AfxFormatString2(strTitle, AFX_IDS_APP_TITLE_EMBEDDING,
  478.             strFileType, m_strHostObj);
  479.  
  480.         // change title of document to that for an embedded item
  481.         //  (this call will update all of the frames)
  482.         SetTitle(strTitle);
  483.     }
  484. }
  485.  
  486. void COleServerDoc::SaveEmbedding()
  487. {
  488.     ASSERT_VALID(this);
  489.  
  490.     // tell the client site to save the object
  491.     if (m_lpClientSite != NULL && !::InSendMessage())
  492.     {
  493.         SCODE sc = m_lpClientSite->SaveObject();
  494.         if (sc != S_OK)
  495.             AfxThrowOleException(sc);
  496.     }
  497.     ASSERT_VALID(this);
  498. }
  499.  
  500. BOOL COleServerDoc::OnUpdateDocument()
  501. {
  502.     ASSERT_VALID(this);
  503.  
  504.     // don't save if already up-to-date
  505.     if (!IsModified())
  506.         return TRUE;
  507.  
  508.     // save a server document -> update
  509.     TRY
  510.     {
  511.         SaveEmbedding();
  512.     }
  513.     CATCH_ALL(e)
  514.     {
  515.         AfxMessageBox(AFX_IDP_FAILED_TO_UPDATE);
  516.         DELETE_EXCEPTION(e);
  517.         return FALSE;
  518.     }
  519.     END_CATCH_ALL
  520.  
  521.     return TRUE;
  522. }
  523.  
  524. LPMONIKER COleServerDoc::GetMoniker(OLEGETMONIKER nAssign)
  525. {
  526.     ASSERT_VALID(this);
  527.  
  528.     if (m_lpClientSite != NULL)
  529.     {
  530.         // get moniker from client site instead of from document
  531.         LPMONIKER lpMoniker = NULL;
  532.         m_lpClientSite->GetMoniker(nAssign, OLEWHICHMK_OBJFULL, &lpMoniker);
  533.         return lpMoniker;
  534.     }
  535.  
  536.     return COleLinkingDoc::GetMoniker(nAssign);
  537. }
  538.  
  539. /////////////////////////////////////////////////////////////////////////////
  540. // COleServerDoc document handling
  541.  
  542. BOOL COleServerDoc::SaveModified()
  543. {
  544.     ASSERT_VALID(this);
  545.  
  546.     if (m_lpClientSite != NULL)
  547.     {
  548.         if (m_pInPlaceFrame == NULL)
  549.         {
  550.             UpdateModifiedFlag();   // check for modified items
  551.             OnUpdateDocument();
  552.         }
  553.         return TRUE;
  554.     }
  555.     return COleLinkingDoc::SaveModified();
  556. }
  557.  
  558. HMENU COleServerDoc::GetDefaultMenu()
  559. {
  560.     ASSERT_VALID(this);
  561.  
  562.     CDocTemplate* pTemplate = GetDocTemplate();
  563.     if (pTemplate == NULL)
  564.         return NULL;    // no doc template -- use default
  565.  
  566.     ASSERT_VALID(pTemplate);
  567.     if (m_pInPlaceFrame != NULL)
  568.         return pTemplate->m_hMenuInPlaceServer; // return special in-place menu
  569.     else if (m_lpClientSite != NULL)
  570.         return pTemplate->m_hMenuEmbedding; // return special embedding menu
  571.  
  572.     return NULL;    // no special mode, use default menu
  573. }
  574.  
  575. HACCEL COleServerDoc::GetDefaultAccelerator()
  576. {
  577.     ASSERT_VALID(this);
  578.  
  579.     CDocTemplate* pTemplate = GetDocTemplate();
  580.     if (pTemplate == NULL)
  581.         return NULL;    // no doc template -- use default
  582.  
  583.     ASSERT_VALID(pTemplate);
  584.     if (m_pInPlaceFrame != NULL)
  585.         return pTemplate->m_hAccelInPlaceServer;    // return special in-place accel
  586.     else if (m_lpClientSite != NULL)
  587.         return pTemplate->m_hAccelEmbedding;// return special embedding accel
  588.  
  589.     return NULL;    // no special mode, use default menu
  590. }
  591.  
  592. /////////////////////////////////////////////////////////////////////////////
  593. // COleServerDoc default command handling
  594.  
  595. BEGIN_MESSAGE_MAP(COleServerDoc, COleLinkingDoc)
  596.     //{{AFX_MSG_MAP(COleServerDoc)
  597.     ON_COMMAND(ID_FILE_UPDATE, OnFileUpdate)
  598.     ON_COMMAND(ID_FILE_SAVE_COPY_AS, OnFileSaveCopyAs)
  599.     ON_UPDATE_COMMAND_UI(ID_APP_EXIT, OnUpdateFileExit)
  600.     ON_UPDATE_COMMAND_UI(ID_FILE_UPDATE, OnUpdateFileUpdate)
  601.     //}}AFX_MSG_MAP
  602. END_MESSAGE_MAP()
  603.  
  604. void COleServerDoc::OnFileUpdate()
  605. {
  606.     ASSERT_VALID(this);
  607.     ASSERT(m_lpClientSite != NULL);
  608.  
  609.     UpdateModifiedFlag();
  610.     OnUpdateDocument();
  611. }
  612.  
  613. void COleServerDoc::OnFileSaveCopyAs()
  614. {
  615.     ASSERT_VALID(this);
  616.     ASSERT(m_bRemember);
  617.     ASSERT(m_lpClientSite != NULL);
  618.  
  619.     LPSTORAGE lpOrigStg = m_lpRootStg;
  620.     m_lpRootStg = NULL; // ignore embedded storage for now
  621.  
  622.     TRY
  623.     {
  624.         // call DoSave to perform Save Copy As...
  625.         m_bRemember = FALSE;
  626.         DoSave(NULL, FALSE);
  627.     }
  628.     END_TRY
  629.  
  630.     m_lpRootStg = lpOrigStg;
  631.     m_bRemember = TRUE;
  632. }
  633.  
  634. void COleServerDoc::UpdateUsingHostObj(UINT nIDS, CCmdUI* pCmdUI)
  635. {
  636.     ASSERT_VALID(this);
  637.     ASSERT(pCmdUI != NULL);
  638.  
  639.     if (m_lpClientSite == NULL)
  640.         return;
  641.  
  642.     // update menu item using m_strHostObj
  643.     CString str;
  644.     AfxFormatString1(str, nIDS, m_strHostObj);
  645.     if (!str.IsEmpty())
  646.         pCmdUI->SetText(str);
  647. }
  648.  
  649. void COleServerDoc::OnUpdateFileExit(CCmdUI* pCmdUI)
  650. {
  651.     ASSERT_VALID(this);
  652.     ASSERT(pCmdUI != NULL);
  653.  
  654.     UpdateUsingHostObj(AFX_IDS_EXIT_MENU, pCmdUI);
  655. }
  656.  
  657. void COleServerDoc::OnUpdateFileUpdate(CCmdUI* pCmdUI)
  658. {
  659.     ASSERT_VALID(this);
  660.     ASSERT(pCmdUI != NULL);
  661.  
  662.     UpdateUsingHostObj(AFX_IDS_UPDATE_MENU, pCmdUI);
  663. }
  664.  
  665. BOOL COleServerDoc::OnSaveDocument(LPCTSTR lpszPathName)
  666. {
  667.     ASSERT_VALID(this);
  668.     ASSERT(lpszPathName == NULL || AfxIsValidString(lpszPathName));
  669.  
  670.     BOOL bModified = IsModified();
  671.     BOOL bRemember = m_bRemember;
  672.     if (!COleLinkingDoc::OnSaveDocument(lpszPathName))
  673.         return FALSE;
  674.  
  675.     if (!bRemember)
  676.         SetModifiedFlag(bModified);
  677.  
  678.     if (lpszPathName != NULL && bRemember)
  679.     {
  680.         if (AfxComparePath(GetPathName(), lpszPathName))
  681.             NotifySaved();
  682.     }
  683.     return TRUE;
  684. }
  685.  
  686. void COleServerDoc::OnCloseDocument()
  687. {
  688.     ASSERT_VALID(this);
  689.  
  690.     // don't allow in-place active documents to be closed without first
  691.     //  deactivating them!
  692.     if (m_pInPlaceFrame != NULL)
  693.     {
  694.         if (GetFirstViewPosition() != NULL)
  695.             return;
  696.  
  697.         // no views but currently in-place active indicates that
  698.         //  a WM_ENDSESSION is being processed.
  699.         m_pInPlaceFrame = NULL;
  700.     }
  701.  
  702.     InternalAddRef();   // keep document stable during shutdown
  703.  
  704.     // update lock count before sending notifications
  705.     UpdateVisibleLock(FALSE, FALSE);
  706.  
  707.     // send some notifications to the container
  708.     if (m_lpClientSite != NULL && m_bCntrVisible)
  709.     {
  710.         // allow the container to unshade the object appropriately
  711.         m_lpClientSite->OnShowWindow(FALSE);
  712.         m_bCntrVisible = FALSE;
  713.     }
  714.  
  715.     // send close notification
  716.     NotifyClosed();
  717.  
  718.     // finish closing the document (before m_lpClientSite->Release)
  719.     BOOL bAutoDelete = m_bAutoDelete;
  720.     m_bAutoDelete = FALSE;
  721.     COleLinkingDoc::OnCloseDocument();
  722.     ASSERT_VALID(this);
  723.  
  724.     // release client-site pointer
  725.     RELEASE(m_lpClientSite);
  726.  
  727.     // disconnect the object
  728.     LPUNKNOWN lpUnknown = (LPUNKNOWN)GetInterface(&IID_IUnknown);
  729.     ASSERT(lpUnknown != NULL);
  730.     CoDisconnectObject(lpUnknown, 0);
  731.  
  732.     // destroy the document if allowed
  733.     InterlockedDecrement(&m_dwRef);              // remove InternalAddRef above
  734.     if (bAutoDelete)
  735.         delete this;
  736. }
  737.  
  738. /////////////////////////////////////////////////////////////////////////////
  739. // COleServerDoc show/hide
  740.  
  741. void COleServerDoc::OnShowDocument(BOOL bShow)
  742. {
  743.     ASSERT_VALID(this);
  744.  
  745.     CWinApp* pApp = AfxGetApp();
  746.     if (bShow)
  747.     {
  748.         // deactivate in-place session if active
  749.         if (m_pInPlaceFrame != NULL)
  750.         {
  751.             OnDeactivate();
  752.             ASSERT(m_pInPlaceFrame == NULL);
  753.         }
  754.  
  755.         // find the first view of this document
  756.         CFrameWnd* pFrameWnd;
  757.         if ((pFrameWnd = GetFirstFrame()) != NULL)
  758.         {
  759.             // allow container to show & scroll to the object
  760.             if (!pFrameWnd->IsWindowVisible() && m_lpClientSite != NULL)
  761.                 m_lpClientSite->ShowObject();
  762.  
  763.             // activate frame holding view
  764.             ASSERT_VALID(pFrameWnd);
  765.             pFrameWnd->ActivateFrame();
  766.  
  767.             // activate application if necessary
  768.             CFrameWnd* pAppFrame = pFrameWnd->GetParentFrame();
  769.             if (pAppFrame != NULL)
  770.             {
  771.                 pFrameWnd = pAppFrame;
  772.                 ASSERT_VALID(pFrameWnd);
  773.                 ASSERT_KINDOF(CFrameWnd, pFrameWnd);
  774.                 pFrameWnd->ActivateFrame();
  775.             }
  776.             pFrameWnd->GetLastActivePopup()->SetForegroundWindow();
  777.  
  778.             // update the menu and title as appropriate for this document
  779.             pFrameWnd->OnUpdateFrameMenu(NULL);
  780.             pFrameWnd->OnUpdateFrameTitle(TRUE);
  781.         }
  782.         else if (pApp->m_pMainWnd != NULL)
  783.         {
  784.             // otherwise, just show the main window (for simple servers)
  785.             CWnd* pWnd = AfxGetMainWnd();
  786.  
  787.             // allow container to show & scroll to the object
  788.             if (!pWnd->IsWindowVisible() && m_lpClientSite != NULL)
  789.                 m_lpClientSite->ShowObject();
  790.  
  791.             pWnd->ShowWindow(SW_SHOW);
  792.             pWnd->SetActiveWindow();
  793.             pWnd->SetForegroundWindow();
  794.         }
  795.  
  796.         // for file based documents, showing the document puts user in control.
  797.         if (!m_bEmbedded)
  798.             AfxOleSetUserCtrl(TRUE);
  799.     }
  800.     else
  801.     {
  802.         if (m_pInPlaceFrame != NULL)
  803.         {
  804.             // hide has semantics of DeactivateUI if the item is active
  805.             if (m_pInPlaceFrame->m_bUIActive)
  806.                 OnDeactivateUI(FALSE);
  807.  
  808.             // and then hide the frame itself
  809.             if (m_pInPlaceFrame != NULL)
  810.                 m_pInPlaceFrame->ActivateFrame(SW_HIDE);
  811.             return;
  812.         }
  813.  
  814.         // find the first view of this document
  815.         POSITION pos = GetFirstViewPosition();
  816.         if (pos != NULL)
  817.         {
  818.             CFrameWnd* pDocFrame = GetFirstFrame();
  819.             CFrameWnd* pActiveFrame = NULL;
  820.             CFrameWnd* pMainFrame = NULL;
  821.             CView* pView = GetNextView(pos);
  822.             ASSERT_VALID(pView);
  823.  
  824.             // destroy or hide all the frames for this document
  825.             //  (the main for the document is hidden, where the alternate
  826.             //   frames are simply destroyed)
  827.             do
  828.             {
  829.                 // hide frame holding view
  830.                 CFrameWnd* pFrame = pView->GetParentFrame();
  831.                 ASSERT_VALID(pFrame);
  832.  
  833.                 // determine next valid view before destroying the frame
  834.                 while ((pView = GetNextView(pos)) != NULL)
  835.                 {
  836.                     if (pView->GetParentFrame() != pFrame)
  837.                         break;
  838.                 }
  839.  
  840.                 pMainFrame = pFrame->GetParentFrame();
  841.                 if (pMainFrame != NULL && pMainFrame->GetActiveFrame() == pFrame)
  842.                 {
  843.                     // don't destroy the active frame until later
  844.                     pActiveFrame = pFrame;
  845.                 }
  846.                 else
  847.                 {
  848.                     // not the active frame -- destroy/hide it now
  849.                     PreCloseFrame(pFrame);
  850.                     if (pDocFrame == pFrame)
  851.                         pFrame->ActivateFrame(SW_HIDE);
  852.                     else
  853.                         pFrame->DestroyWindow();
  854.                 }
  855.  
  856.             } while (pView != NULL);
  857.  
  858.             // hide the active frame last
  859.             if (pActiveFrame != NULL)
  860.             {
  861.                 PreCloseFrame(pActiveFrame);
  862.                 if (pDocFrame == pActiveFrame)
  863.                     pActiveFrame->ActivateFrame(SW_HIDE);
  864.                 else
  865.                     pActiveFrame->DestroyWindow();
  866.  
  867.                 // should leave at least one frame
  868.                 ASSERT_VALID(this);
  869.                 ASSERT_VALID(GetFirstFrame());
  870.             }
  871.         }
  872.  
  873.         CFrameWnd* pMainFrame = (CFrameWnd*)pApp->m_pMainWnd;
  874.         if (!AfxOleGetUserCtrl() && pMainFrame != NULL &&
  875.             pMainFrame->IsWindowEnabled() && pMainFrame->IsFrameWnd() &&
  876.             pMainFrame->GetActiveFrame() == pMainFrame)
  877.         {
  878.             // hide the entire application -- no visible documents left
  879.             pApp->HideApplication();
  880.         }
  881.     }
  882.  
  883.     // send OnShowWindow notifications to the container
  884.     if (m_lpClientSite != NULL && (bShow || m_bCntrVisible != bShow))
  885.     {
  886.         // allow the container to shade the object appropriately
  887.         m_lpClientSite->OnShowWindow(bShow);
  888.         m_bCntrVisible = bShow;
  889.     }
  890.  
  891.     // force update visible lock
  892.     if (bShow)
  893.         UpdateVisibleLock(TRUE, FALSE);
  894. }
  895.  
  896. /////////////////////////////////////////////////////////////////////////////
  897. // COleServerDoc storage implementation
  898.  
  899. void COleServerDoc::OnNewEmbedding(LPSTORAGE lpStorage)
  900. {
  901.     ASSERT_VALID(this);
  902.     ASSERT(lpStorage != NULL);
  903.  
  904.     // save state
  905.     BOOL bUserCtrl = AfxOleGetUserCtrl();
  906.  
  907.     TRY
  908.     {
  909.         // remember new storage
  910.         DeleteContents();
  911.         lpStorage->AddRef();
  912.         RELEASE(m_lpRootStg);
  913.         m_lpRootStg = lpStorage;
  914.         m_strPathName.Empty();
  915.         m_bEmbedded = TRUE;
  916.  
  917.         // do document initialization by calling OnNewDocument
  918.         if (!OnNewDocument())
  919.             AfxThrowMemoryException();
  920.     }
  921.     CATCH_ALL(e)
  922.     {
  923.         // restore state
  924.         AfxOleSetUserCtrl(bUserCtrl);
  925.         THROW_LAST();
  926.     }
  927.     END_CATCH_ALL
  928.  
  929.     // restore state
  930.     AfxOleSetUserCtrl(bUserCtrl);
  931.  
  932.     SetModifiedFlag();  // new storage-based documents are dirty!
  933.     SendInitialUpdate();
  934. }
  935.  
  936. void COleServerDoc::OnOpenEmbedding(LPSTORAGE lpStorage)
  937. {
  938.     ASSERT_VALID(this);
  939.     ASSERT(lpStorage != NULL);
  940.  
  941.     // save state
  942.     BOOL bUserCtrl = AfxOleGetUserCtrl();
  943.  
  944.     TRY
  945.     {
  946.         // abort changes to current document
  947.         DeleteContents();
  948.         lpStorage->AddRef();
  949.         RELEASE(m_lpRootStg);
  950.         m_lpRootStg = lpStorage;
  951.  
  952.         // open document from the sub-storage
  953.         if (!OnOpenDocument(NULL))
  954.             AfxThrowMemoryException();
  955.  
  956.         // now document is storage based
  957.         m_strPathName.Empty();
  958.         m_bEmbedded = TRUE;
  959.     }
  960.     CATCH_ALL(e)
  961.     {
  962.         // restore state
  963.         AfxOleSetUserCtrl(bUserCtrl);
  964.         THROW_LAST();
  965.     }
  966.     END_CATCH_ALL
  967.  
  968.     // restore state
  969.     AfxOleSetUserCtrl(bUserCtrl);
  970.  
  971.     SetModifiedFlag(FALSE); // start off with unmodified
  972.     SendInitialUpdate();
  973. }
  974.  
  975. void COleServerDoc::OnSaveEmbedding(LPSTORAGE lpStorage)
  976. {
  977.     ASSERT_VALID(this);
  978.     ASSERT(lpStorage != NULL);
  979.  
  980.     // save state
  981.     BOOL bUserCtrl = AfxOleGetUserCtrl();
  982.  
  983.     // check for save as
  984.     LPSTORAGE lpOrigStg = m_lpRootStg;
  985.     if (!m_bSameAsLoad)
  986.     {
  987.         // File Save[Copy] As (saving to different file)
  988.         ASSERT(lpStorage != NULL);
  989.         m_lpRootStg = lpStorage;
  990.     }
  991.  
  992.     TRY
  993.     {
  994.         // save document to the sub-storage
  995.         if (!OnSaveDocument(NULL))
  996.             AfxThrowMemoryException();
  997.     }
  998.     CATCH_ALL(e)
  999.     {
  1000.         // restore state
  1001.         AfxOleSetUserCtrl(bUserCtrl);
  1002.         // re-attach original storage
  1003.         m_lpRootStg = lpOrigStg;
  1004.         THROW_LAST();
  1005.     }
  1006.     END_CATCH_ALL
  1007.  
  1008.     // restore state
  1009.     AfxOleSetUserCtrl(bUserCtrl);
  1010.  
  1011.     // re-attach original storage
  1012.     m_lpRootStg = lpOrigStg;
  1013. }
  1014.  
  1015. /////////////////////////////////////////////////////////////////////////////
  1016. // COleServerDoc in-place activation implementation
  1017.  
  1018. AFX_STATIC HWND AFXAPI _AfxGetWindow32(HWND hWnd)
  1019. {
  1020.     // don't bother if hWnd is already a 32-bit HWND
  1021.     if (HIWORD(hWnd) != 0)
  1022.         return hWnd;
  1023.  
  1024.     // otherwise convert by getting a DC...
  1025.     HDC hDC = ::GetDC(hWnd);
  1026.     if (hDC == NULL)
  1027.         return hWnd;
  1028.  
  1029.     // then, getting the HWND from the DC...
  1030.     HWND hWnd32 = ::WindowFromDC(hDC);
  1031.     if (hWnd32 == NULL)
  1032.         hWnd32 = hWnd;
  1033.  
  1034.     // then releasing the DC itself
  1035.     ::ReleaseDC(hWnd, hDC);
  1036.  
  1037.     return hWnd32;  // return full 32-bit HWND
  1038. }
  1039.  
  1040. BOOL COleServerDoc::ActivateInPlace()
  1041. {
  1042.     ASSERT_VALID(this);
  1043.     USES_CONVERSION;
  1044.     LPCOLESTR lpszTitle = NULL;
  1045.  
  1046.     if (m_lpClientSite == NULL)
  1047.         return FALSE;   // no client-side (may be a link)
  1048.  
  1049.     // activate already in-place window if currently in-place active
  1050.     if (m_pInPlaceFrame != NULL)
  1051.     {
  1052.         if (m_pInPlaceFrame->m_bUIActive)
  1053.         {
  1054.             m_lpClientSite->ShowObject();   // object should get focus
  1055.             return TRUE;
  1056.         }
  1057.         // deactivate in-place session entirely before continuing
  1058.         OnDeactivate();
  1059.     }
  1060.  
  1061.     // fail if already fully open
  1062.     if (GetFirstFrame()->IsWindowVisible())
  1063.         return FALSE;
  1064.  
  1065.     // build object title/name (the container may use this in its caption)
  1066.     CString strFileType, strTitle;
  1067.     if (!GetFileTypeString(strFileType))
  1068.         return FALSE;
  1069.     AfxFormatString2(strTitle, AFX_IDS_OBJ_TITLE_INPLACE,
  1070.         AfxGetAppName(), strFileType);
  1071.  
  1072.     // attempt to get in-place client-site interface
  1073.     LPOLEINPLACESITE lpInPlaceSite =
  1074.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1075.     if (lpInPlaceSite == NULL)
  1076.     {
  1077.         // unable to get in-place client site interface
  1078.         return FALSE;
  1079.     }
  1080.  
  1081.     // see if the container wants to go in-place right now
  1082.     if (lpInPlaceSite->CanInPlaceActivate() != S_OK)
  1083.         goto ReleaseAndFail;
  1084.  
  1085.     // start activation sequence...
  1086.  
  1087.     if (lpInPlaceSite->OnInPlaceActivate() != S_OK)
  1088.         goto ReleaseAndFail;
  1089.  
  1090.     // we'll need the parent window to create the COleIPFrameWnd
  1091.     HWND hWnd;
  1092.     VERIFY(lpInPlaceSite->GetWindow(&hWnd) == S_OK);
  1093.     CWnd* pParentWnd;
  1094.     pParentWnd = CWnd::FromHandle(hWnd);
  1095.  
  1096.     // create the inplace frame window
  1097.     COleIPFrameWnd* pFrameWnd;
  1098.     pFrameWnd = CreateInPlaceFrame(pParentWnd);
  1099.     if (pFrameWnd == NULL)
  1100.     {
  1101.         ASSERT(lpInPlaceSite != NULL);
  1102.         lpInPlaceSite->OnInPlaceDeactivate();
  1103.         goto ReleaseAndFail;
  1104.     }
  1105.     ASSERT(pFrameWnd->GetParent() == pParentWnd);
  1106.     m_pInPlaceFrame = pFrameWnd;
  1107.  
  1108.     // send activate notification.
  1109.     if (lpInPlaceSite->OnUIActivate() != S_OK)
  1110.         goto DestroyFrameAndFail;
  1111.  
  1112.     // need to get frame & doc window interfaces as well as other info
  1113.     RECT rcPosRect, rcClipRect;
  1114.     if (lpInPlaceSite->GetWindowContext(
  1115.         &pFrameWnd->m_lpFrame, &pFrameWnd->m_lpDocFrame,
  1116.         &rcPosRect, &rcClipRect, &pFrameWnd->m_frameInfo) != S_OK)
  1117.     {
  1118.         goto DeactivateUIAndFail;
  1119.     }
  1120.     ASSERT(pFrameWnd->m_lpFrame != NULL);
  1121.  
  1122.     // setup the shared menu
  1123.     if (!pFrameWnd->BuildSharedMenu())
  1124.         goto DeactivateUIAndFail;
  1125.  
  1126.     // allow server to install frame controls in container
  1127.     VERIFY(pFrameWnd->m_lpFrame->GetWindow(&hWnd) == S_OK);
  1128.  
  1129.     // some containers (Works 4.0, for example) return only the lower
  1130.     // 16-bits of the HWND and that confuses us; to work around this
  1131.     // we convert the 16-bit HWND into the full 32-bit HWND.
  1132.     hWnd = _AfxGetWindow32(hWnd);
  1133.  
  1134.     pFrameWnd->m_pMainFrame = new COleCntrFrameWnd(pFrameWnd);
  1135.     pFrameWnd->m_pMainFrame->Attach(hWnd);
  1136.     if (pFrameWnd->m_lpDocFrame != NULL)
  1137.     {
  1138.         HWND hWndDocument;
  1139.         VERIFY(pFrameWnd->m_lpDocFrame->GetWindow(&hWndDocument) == S_OK);
  1140.         if (hWndDocument != hWnd)
  1141.         {
  1142.             pFrameWnd->m_pDocFrame = new COleCntrFrameWnd(pFrameWnd);
  1143.             pFrameWnd->m_pDocFrame->Attach(hWndDocument);
  1144.         }
  1145.         else
  1146.         {
  1147.             RELEASE(pFrameWnd->m_lpDocFrame);
  1148.             pFrameWnd->m_lpDocFrame = NULL;
  1149.         }
  1150.     }
  1151.  
  1152.     // update zoom factor information before creating control bars
  1153.  
  1154.     //WINBUG: some clients send an empty rectangle and expect the
  1155.     // server to use the ClipRect for the PosRect
  1156.     if (IsRectEmpty(&rcPosRect))
  1157.         pFrameWnd->m_rectPos.CopyRect(&rcClipRect);
  1158.     else
  1159.         pFrameWnd->m_rectPos.CopyRect(&rcPosRect);
  1160.     pFrameWnd->m_rectClip.CopyRect(&rcClipRect);
  1161.  
  1162.     if (!pFrameWnd->OnCreateControlBars(pFrameWnd->m_pMainFrame,
  1163.         pFrameWnd->m_pDocFrame))
  1164.     {
  1165.         goto DeactivateUIAndFail;
  1166.     }
  1167.  
  1168.     // resize the window to match the object
  1169.  
  1170.     //WINBUG: some clients send an empty rectangle and expect the
  1171.     // server to use the ClipRect for the PosRect
  1172.     if (IsRectEmpty(&rcPosRect))
  1173.         OnSetItemRects(&rcClipRect, &rcClipRect);
  1174.     else
  1175.         OnSetItemRects(&rcPosRect, &rcClipRect);
  1176.  
  1177.     // set the active object
  1178.     ASSERT(pFrameWnd->m_lpFrame != NULL);
  1179.     LPOLEINPLACEACTIVEOBJECT lpActiveObject;
  1180.     lpActiveObject = (LPOLEINPLACEACTIVEOBJECT)
  1181.         GetInterface(&IID_IOleInPlaceActiveObject);
  1182.     lpszTitle = T2COLE(strTitle);
  1183.     pFrameWnd->m_lpFrame->SetActiveObject(lpActiveObject, lpszTitle);
  1184.     if (pFrameWnd->m_lpDocFrame != NULL)
  1185.         pFrameWnd->m_lpDocFrame->SetActiveObject(lpActiveObject, lpszTitle);
  1186.  
  1187.     // add frame & document level frame controls
  1188.     ASSERT(m_pInPlaceFrame->m_lpFrame != NULL);
  1189.     OnShowControlBars(m_pInPlaceFrame->m_pMainFrame, TRUE);
  1190.     if (m_pInPlaceFrame->m_lpDocFrame != NULL)
  1191.         OnShowControlBars(m_pInPlaceFrame->m_pDocFrame, TRUE);
  1192.  
  1193.     // show any hidden modeless dialogs as well...
  1194.     m_pInPlaceFrame->ShowOwnedWindows(TRUE);
  1195.  
  1196.     // attempt toolbar negotiation
  1197.     OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
  1198.     if (pFrameWnd->m_lpDocFrame != NULL)
  1199.         OnResizeBorder(NULL, pFrameWnd->m_lpDocFrame, FALSE);
  1200.  
  1201.     // install the menu (also installs a hook which forwards messages from
  1202.     //  the menu to the inplace frame window)
  1203.     pFrameWnd->m_lpFrame->SetMenu(pFrameWnd->m_hSharedMenu,
  1204.         pFrameWnd->m_hOleMenu, pFrameWnd->m_hWnd);
  1205.  
  1206.     // make sure object is scrolled into view
  1207.     m_lpClientSite->ShowObject();   // object should get focus
  1208.  
  1209.     // finally -- show the inplace frame window and set focus
  1210.     pFrameWnd->ShowWindow(SW_SHOW);
  1211.     pFrameWnd->SetFocus();
  1212.     pFrameWnd->UpdateWindow();
  1213.     UpdateVisibleLock(TRUE, FALSE);
  1214.  
  1215.     // allow the main window to be set
  1216.     OnFrameWindowActivate(TRUE);
  1217.     pFrameWnd->m_bUIActive = TRUE;
  1218.  
  1219.     // cleanup and return
  1220.     lpInPlaceSite->Release();
  1221.     return TRUE;
  1222.  
  1223. DeactivateUIAndFail:
  1224.     ASSERT(lpInPlaceSite != NULL);
  1225.     lpInPlaceSite->OnUIDeactivate(FALSE);
  1226.  
  1227. DestroyFrameAndFail:
  1228.     if (m_pInPlaceFrame != NULL)
  1229.     {
  1230.         ASSERT(pFrameWnd != NULL);
  1231.         DestroyInPlaceFrame(pFrameWnd);
  1232.         m_pInPlaceFrame = NULL;
  1233.  
  1234.         // also need to send OnInPlaceDeactivate notification
  1235.         ASSERT(lpInPlaceSite != NULL);
  1236.         lpInPlaceSite->OnInPlaceDeactivate();
  1237.     }
  1238.  
  1239. ReleaseAndFail:
  1240.     ASSERT(lpInPlaceSite != NULL);
  1241.     lpInPlaceSite->Release();
  1242.     return FALSE;
  1243. }
  1244.  
  1245. COleIPFrameWnd* COleServerDoc::CreateInPlaceFrame(CWnd* pParentWnd)
  1246. {
  1247.     ASSERT_VALID(this);
  1248.     ASSERT_VALID(pParentWnd);
  1249.  
  1250.     // get runtime class from the doc template
  1251.     CDocTemplate* pTemplate = GetDocTemplate();
  1252.     ASSERT_VALID(pTemplate);
  1253.  
  1254.     // use existing view if possible
  1255.     CWnd* pViewParent = NULL;
  1256.     CView* pView = NULL;
  1257.     CFrameWnd* pFrame = GetFirstFrame();
  1258.     if (pFrame != NULL)
  1259.     {
  1260.         pView = (CView*)pFrame->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
  1261.         if (pView != NULL)
  1262.         {
  1263.             ASSERT_KINDOF(CView, pView);
  1264.             pViewParent = pView->GetParent();
  1265.             m_dwOrigStyle = pView->GetStyle();
  1266.             m_dwOrigStyleEx = pView->GetExStyle();
  1267.         }
  1268.     }
  1269.  
  1270.     // create the frame from the template
  1271.     COleIPFrameWnd* pFrameWnd = (COleIPFrameWnd*)
  1272.         pTemplate->CreateOleFrame(pParentWnd, this, pView == NULL);
  1273.     if (pFrameWnd == NULL)
  1274.         return NULL;
  1275.  
  1276.     // connect the view to the frame window, if necessary
  1277.     if (pView != NULL)
  1278.     {
  1279.         ConnectView(pFrameWnd, pView);
  1280.         pView->ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_DRAWFRAME);
  1281.     }
  1282.  
  1283.     // remember original parent window for deactivate
  1284.     m_pOrigParent = pViewParent;
  1285.  
  1286.     // send OnInitialUpdate if new view was created
  1287.     if (pView == NULL)
  1288.         pTemplate->InitialUpdateFrame(pFrameWnd, this, FALSE);
  1289.  
  1290.     // verify the type
  1291.     ASSERT_VALID(pFrameWnd);
  1292.     ASSERT_KINDOF(COleIPFrameWnd, pFrameWnd);
  1293.     return pFrameWnd;
  1294. }
  1295.  
  1296. void COleServerDoc::DestroyInPlaceFrame(COleIPFrameWnd* pFrameWnd)
  1297. {
  1298.     ASSERT_VALID(this);
  1299.     ASSERT_VALID(pFrameWnd);
  1300.  
  1301.     // connect view to original, if existing view was used
  1302.     if (m_pOrigParent != NULL)
  1303.     {
  1304.         CView* pView = (CView*)pFrameWnd->GetDescendantWindow(
  1305.             AFX_IDW_PANE_FIRST, TRUE);
  1306.         ASSERT_VALID(pView);
  1307.  
  1308.         // leaving the focus on an MDI child or one of its child windows
  1309.         // causes Windows to get confused when the child window is
  1310.         // destroyed, not to mention the fact that the focus will be
  1311.         // out of sync with activation.
  1312.         if (::GetFocus() == pView->m_hWnd)
  1313.         {
  1314.             // move focus to somewhere safe
  1315.             HWND hWnd = ::GetParent(pFrameWnd->m_hWnd);
  1316.             if (hWnd != NULL)
  1317.                 ::SetFocus(hWnd);
  1318.  
  1319.             // check again
  1320.             if (::GetFocus() == pView->m_hWnd)
  1321.                 SetFocus(NULL); // last ditch effort
  1322.         }
  1323.  
  1324.         ConnectView(m_pOrigParent, pView);
  1325.         m_pOrigParent = NULL;
  1326.  
  1327.         // remove any scrollbars added because of in-place activation
  1328.         if ((m_dwOrigStyle & (WS_HSCROLL|WS_VSCROLL)) == 0 &&
  1329.             (pView->GetStyle() & (WS_HSCROLL|WS_VSCROLL)) != 0)
  1330.         {
  1331.             ::SetScrollRange(pView->m_hWnd, SB_HORZ, 0, 0, TRUE);
  1332.             ::SetScrollRange(pView->m_hWnd, SB_VERT, 0, 0, TRUE);
  1333.         }
  1334.  
  1335.         // restore old 3D style
  1336.         pView->ModifyStyleEx(0, m_dwOrigStyleEx & WS_EX_CLIENTEDGE,
  1337.             SWP_DRAWFRAME);
  1338.  
  1339.         // force recalc layout on splitter window
  1340.         CSplitterWnd* pSplitter = CView::GetParentSplitter(pView, TRUE);
  1341.         if (pSplitter != NULL)
  1342.             pSplitter->RecalcLayout();
  1343.     }
  1344.  
  1345.     // no active view or document during destroy
  1346.     pFrameWnd->SetActiveView(NULL);
  1347.  
  1348.     // destroy in-place frame window
  1349.     pFrameWnd->DestroyWindow();
  1350. }
  1351.  
  1352. void COleServerDoc::ConnectView(CWnd* pParentWnd, CView* pView)
  1353. {
  1354.     ASSERT_VALID(this);
  1355.     ASSERT_VALID(pParentWnd);
  1356.     ASSERT_VALID(pView);
  1357.  
  1358.     // move the view to the new parent
  1359.     pView->SetParent(pParentWnd);
  1360.  
  1361.     // Note: The currently active view on the original frame window is
  1362.     //  kept active, because some controls, especially Windows controls,
  1363.     //  continue to send notification messages to the original parent
  1364.     //  window of the control.  So, the original frame window is kept
  1365.     //  alive with the original active view pointer intact, such that
  1366.     //  these notification messages do not get lost.
  1367.  
  1368.     // set the active view of the new frame to newly moved view
  1369.     CFrameWnd* pFrameWnd = pParentWnd->IsFrameWnd() ?
  1370.         (CFrameWnd*)pParentWnd : pParentWnd->GetParentFrame();
  1371.     pFrameWnd->SetActiveView(pView, FALSE);
  1372.     pFrameWnd->RecalcLayout();
  1373. }
  1374.  
  1375. void COleServerDoc::OnFrameWindowActivate(BOOL bActivate)
  1376. {
  1377.     ASSERT_VALID(this);
  1378.  
  1379.     CFrameWnd* pFrameWnd = m_pInPlaceFrame;
  1380.     ASSERT_VALID(pFrameWnd);
  1381.  
  1382.     CWinThread* pThread = AfxGetThread();
  1383.     if (bActivate)
  1384.     {
  1385.         // activating -- so set the main window
  1386.         pThread->m_pActiveWnd = pFrameWnd;
  1387.  
  1388.         // send activation notification messages
  1389.         pFrameWnd->SendMessage(WM_ACTIVATEAPP, (WPARAM)TRUE);
  1390.         pFrameWnd->SendMessage(WM_ACTIVATE, WA_ACTIVE);
  1391.     }
  1392.     else if (pFrameWnd == pThread->m_pActiveWnd)
  1393.     {
  1394.         // send deactivation notification messages
  1395.         pFrameWnd->SendMessage(WM_ACTIVATEAPP, (WPARAM)FALSE);
  1396.         pFrameWnd->SendMessage(WM_ACTIVATE, WA_INACTIVE);
  1397.  
  1398.         // simulate deactivation notification messages
  1399.         CView* pActiveView = pFrameWnd->GetActiveView();
  1400.         if (pActiveView != NULL)
  1401.             pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
  1402.  
  1403.         // deactivating and was previously active -- reset the main window
  1404.         pThread->m_pActiveWnd = NULL;
  1405.     }
  1406. }
  1407.  
  1408. void COleServerDoc::OnDocWindowActivate(BOOL bActivate)
  1409. {
  1410.     ASSERT_VALID(this);
  1411.  
  1412.     CWinThread* pThread = AfxGetApp();
  1413.     COleIPFrameWnd* pFrameWnd = m_pInPlaceFrame;
  1414.  
  1415.     if (bActivate)
  1416.     {
  1417.         // attach frame windows back in the permanent map
  1418.         pFrameWnd->m_pMainFrame->Attach(pFrameWnd->m_pMainFrame->Detach());
  1419.         if (pFrameWnd->m_pDocFrame != NULL)
  1420.             pFrameWnd->m_pDocFrame->Attach(pFrameWnd->m_pDocFrame->Detach());
  1421.  
  1422.         // set active main window
  1423.         pThread->m_pActiveWnd = pFrameWnd;
  1424.  
  1425.         // show frame level controls
  1426.         OnShowControlBars(pFrameWnd->m_pMainFrame, TRUE);
  1427.         pFrameWnd->ShowOwnedWindows(TRUE);
  1428.  
  1429.         // attempt toolbar negotiation
  1430.         OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
  1431.  
  1432.         // install the menu (also installs a hook which forwards messages from
  1433.         //  the menu to the inplace frame window)
  1434.         pFrameWnd->m_lpFrame->SetMenu(
  1435.             pFrameWnd->m_hSharedMenu, pFrameWnd->m_hOleMenu,
  1436.             pFrameWnd->m_hWnd);
  1437.  
  1438.         // set focus to the frame (it will probably set focus to the view)
  1439.         //  (by simulating normal application activate messages)
  1440.         pFrameWnd->SendMessage(WM_ACTIVATE, WA_ACTIVE);
  1441.     }
  1442.     else
  1443.     {
  1444.         // clear active window for app if this object is active
  1445.         if (pThread->m_pActiveWnd == pFrameWnd)
  1446.             pThread->m_pActiveWnd = NULL;
  1447.  
  1448.         // hide frame level controls -- this does not destroy them
  1449.         pFrameWnd->ShowOwnedWindows(FALSE);
  1450.         OnShowControlBars(pFrameWnd->m_pMainFrame, FALSE);
  1451.  
  1452.         // attempt toolbar negotiation
  1453.         OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
  1454.  
  1455.         // simulate deactivation notification messages
  1456.         CView* pActiveView = pFrameWnd->GetActiveView();
  1457.         if (pActiveView != NULL)
  1458.             pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
  1459.         pFrameWnd->SendMessage(WM_ACTIVATE, WA_INACTIVE);
  1460.  
  1461.         // set the m_hWnd members, but remove them from the maps
  1462.         pFrameWnd->m_pMainFrame->m_hWnd = pFrameWnd->m_pMainFrame->Detach();
  1463.         if (pFrameWnd->m_pDocFrame != NULL)
  1464.             pFrameWnd->m_pDocFrame->m_hWnd = pFrameWnd->m_pDocFrame->Detach();
  1465.     }
  1466. }
  1467.  
  1468. void COleServerDoc::OnShowControlBars(CFrameWnd* pFrameWnd, BOOL bShow)
  1469. {
  1470.     ASSERT_VALID(this);
  1471.     ASSERT(pFrameWnd == m_pInPlaceFrame->m_pMainFrame ||
  1472.         pFrameWnd == m_pInPlaceFrame->m_pDocFrame);
  1473.     ASSERT_VALID(pFrameWnd);
  1474.  
  1475.     // show/hide all control bars
  1476.     POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
  1477.     while (pos != NULL)
  1478.     {
  1479.         // show/hide the next control bar
  1480.         CControlBar* pBar =
  1481.             (CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
  1482.         ASSERT_VALID(pBar);
  1483.         if (bShow)
  1484.         {
  1485.             if (pBar->m_nStateFlags & CControlBar::tempHide)
  1486.             {
  1487.                 pBar->m_nStateFlags &= ~CControlBar::tempHide;
  1488.                 pFrameWnd->ShowControlBar(pBar, bShow, TRUE);
  1489.             }
  1490.         }
  1491.         else
  1492.         {
  1493.             if (pBar->IsVisible() && !pBar->IsFloating())
  1494.             {
  1495.                 pBar->m_nStateFlags |= CControlBar::tempHide;
  1496.                 pFrameWnd->ShowControlBar(pBar, bShow, TRUE);
  1497.             }
  1498.         }
  1499.     }
  1500. }
  1501.  
  1502. void COleServerDoc::OnResizeBorder(
  1503.     LPCRECT lpRectBorder, LPOLEINPLACEUIWINDOW lpUIWindow, BOOL bFrame)
  1504. {
  1505.     ASSERT_VALID(this);
  1506.     ASSERT(lpRectBorder == NULL ||
  1507.         AfxIsValidAddress(lpRectBorder, sizeof(RECT), FALSE));
  1508.     ASSERT(lpUIWindow != NULL);
  1509.  
  1510.     // use IOleInPlaceUIWindow::GetBorder if no border given
  1511.     CRect rectBorder;
  1512.     if (lpRectBorder != NULL)
  1513.     {
  1514.         // use border space passed in
  1515.         rectBorder.CopyRect(lpRectBorder);
  1516.     }
  1517.     else
  1518.     {
  1519.         // GetBorderSpace may fail (WinWord6, for example)
  1520.         if (lpUIWindow->GetBorder(&rectBorder) != S_OK)
  1521.         {
  1522.             // in that case, always call SetBorderSpace(NULL), but
  1523.             // ignore the return value.
  1524.             lpUIWindow->SetBorderSpace(NULL);
  1525.             return;
  1526.         }
  1527.     }
  1528.  
  1529.     // get CWnd* for the OLE window
  1530.     CFrameWnd* pFrameWnd = bFrame ?
  1531.         m_pInPlaceFrame->m_pMainFrame : m_pInPlaceFrame->m_pDocFrame;
  1532.  
  1533.     // if this is the active document clear temphide bits from bars
  1534.     if (AfxGetThread()->m_pActiveWnd == m_pInPlaceFrame)
  1535.         OnShowControlBars(pFrameWnd, TRUE);
  1536.  
  1537.     // see how much space we need by calling reposition bars
  1538.     CRect rectNeeded = rectBorder;
  1539.     pFrameWnd->RepositionBars(0, 0xFFFF, 0, CWnd::reposQuery, &rectNeeded,
  1540.         &rectBorder);
  1541.  
  1542.     // request the border space from the container
  1543.     CRect rectRequest(
  1544.         rectNeeded.left - rectBorder.left,
  1545.         rectNeeded.top - rectBorder.top,
  1546.         rectBorder.right - rectNeeded.right,
  1547.         rectBorder.bottom - rectNeeded.bottom);
  1548.     CRect rectTemp;
  1549.     rectTemp = rectRequest;
  1550.  
  1551.     // if no border space, just call SetBorderSpace
  1552.     if ((!rectRequest.IsRectNull() ||
  1553.          !pFrameWnd->m_listControlBars.IsEmpty()) &&
  1554.         lpUIWindow->RequestBorderSpace(&rectTemp) == S_OK)
  1555.     {
  1556.         // set the border space -- now this object owns it
  1557.         VERIFY(lpUIWindow->SetBorderSpace(&rectRequest) == S_OK);
  1558.  
  1559.         // move the bars into position after committing the space
  1560.         pFrameWnd->RepositionBars(0, 0xFFFF, 0, CWnd::reposDefault, NULL,
  1561.             &rectBorder);
  1562.  
  1563.         // redraw all control bars
  1564.         POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
  1565.         while (pos != NULL)
  1566.         {
  1567.             CControlBar* pBar =
  1568.                 (CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
  1569.             ASSERT_VALID(pBar);
  1570.             if (!pBar->IsFloating())
  1571.                 pBar->UpdateWindow();
  1572.         }
  1573.     }
  1574.     else
  1575.     {
  1576.         // hide any toolbars (since we couldn't get border space for any)
  1577.         OnShowControlBars(pFrameWnd, FALSE);
  1578.  
  1579.         // make sure border space is cleared
  1580.         CRect rect(0,0,0,0);
  1581.         lpUIWindow->SetBorderSpace(&rect);
  1582.     }
  1583. }
  1584.  
  1585. void COleServerDoc::OnDeactivate()
  1586. {
  1587.     ASSERT_VALID(this);
  1588.  
  1589.     ASSERT(m_pInPlaceFrame != NULL);
  1590.  
  1591.     // do UI deactivate first -- this hides everything
  1592.     if (m_pInPlaceFrame->m_bUIActive)
  1593.     {
  1594.         OnDeactivateUI(FALSE);
  1595.  
  1596.         // some containers call OnDeactivate during OnDeactivateUI
  1597.         if (m_pInPlaceFrame == NULL)
  1598.             return;
  1599.     }
  1600.     ASSERT(m_pInPlaceFrame != NULL);
  1601.     ASSERT(!m_pInPlaceFrame->m_bUIActive);
  1602.  
  1603.     // now safe to destroy the shared menu
  1604.     m_pInPlaceFrame->DestroySharedMenu();
  1605.  
  1606.     // no longer need doc & frame window interfaces
  1607.     RELEASE(m_pInPlaceFrame->m_lpFrame);
  1608.     RELEASE(m_pInPlaceFrame->m_lpDocFrame);
  1609.     DestroyInPlaceFrame(m_pInPlaceFrame);
  1610.     m_pInPlaceFrame = NULL;
  1611.         // destructor for COleIPFrameWnd or derivative should cleanup any
  1612.         //   toolbars etc. created during in-place activation
  1613.  
  1614.     // last of all, call IOleClientSite::InPlaceDeactivate
  1615.     ASSERT(m_lpClientSite != NULL);
  1616.     LPOLEINPLACESITE lpInPlaceSite =
  1617.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1618.     if (lpInPlaceSite != NULL)
  1619.     {
  1620.         lpInPlaceSite->OnInPlaceDeactivate();
  1621.         lpInPlaceSite->Release();
  1622.     }
  1623. }
  1624.  
  1625. void COleServerDoc::OnDeactivateUI(BOOL bUndoable)
  1626. {
  1627.     ASSERT_VALID(this);
  1628.     COleIPFrameWnd* pFrameWnd = m_pInPlaceFrame;
  1629.  
  1630.     if (pFrameWnd == NULL || !pFrameWnd->m_bUIActive)
  1631.         return;
  1632.  
  1633.     // reset active object pointers
  1634.     ASSERT(pFrameWnd->m_lpFrame != NULL);
  1635.     pFrameWnd->m_lpFrame->SetActiveObject(NULL, NULL);
  1636.     if (pFrameWnd->m_lpDocFrame != NULL)
  1637.         pFrameWnd->m_lpDocFrame->SetActiveObject(NULL, NULL);
  1638.  
  1639.     // remove frame & document level frame controls
  1640.     ASSERT(pFrameWnd->m_lpFrame != NULL);
  1641.     OnShowControlBars(pFrameWnd->m_pMainFrame, FALSE);
  1642.     if (pFrameWnd->m_lpDocFrame != NULL)
  1643.         OnShowControlBars(pFrameWnd->m_pDocFrame, FALSE);
  1644.  
  1645.     if (m_pDocObjectServer == NULL)
  1646.     {
  1647.         // hide the frame and any popups owned by the frame
  1648.         pFrameWnd->ShowOwnedWindows(FALSE);
  1649.         pFrameWnd->ShowWindow(SW_HIDE);
  1650.         pFrameWnd->m_nShowDelay = SW_HIDE;
  1651.         pFrameWnd->m_pMainFrame->m_nShowDelay = SW_HIDE;
  1652.     }
  1653.  
  1654.     // set the m_hWnd members, but remove them from the maps
  1655.     pFrameWnd->m_pMainFrame->m_hWnd = pFrameWnd->m_pMainFrame->Detach();
  1656.     if (pFrameWnd->m_pDocFrame != NULL)
  1657.         pFrameWnd->m_pDocFrame->m_hWnd = pFrameWnd->m_pDocFrame->Detach();
  1658.  
  1659.     // no longer UI active...
  1660.     pFrameWnd->m_bUIActive = FALSE;
  1661.     CWinThread* pThread = AfxGetApp();
  1662.     if (pThread->m_pActiveWnd == pFrameWnd)
  1663.         pThread->m_pActiveWnd = NULL;
  1664.  
  1665.     // call IOleClientSite::OnUIDeactivate
  1666.     ASSERT(m_lpClientSite != NULL);
  1667.     LPOLEINPLACESITE lpInPlaceSite =
  1668.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1669.     if (lpInPlaceSite != NULL)
  1670.     {
  1671.         lpInPlaceSite->OnUIDeactivate(bUndoable);
  1672.         lpInPlaceSite->Release();
  1673.     }
  1674. }
  1675.  
  1676. void COleServerDoc::OnSetItemRects(LPCRECT lpPosRect, LPCRECT lpClipRect)
  1677. {
  1678.     ASSERT_VALID(this);
  1679.     ASSERT(AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
  1680.     ASSERT(AfxIsValidAddress(lpClipRect, sizeof(RECT), FALSE));
  1681.  
  1682.     if (m_pInPlaceFrame == NULL)
  1683.         return;
  1684.     ASSERT_VALID(m_pInPlaceFrame);
  1685.  
  1686.     // tell the frame to position itself such that the view is at the given
  1687.     //  rectangle (relative to the frame's parent)
  1688.     m_pInPlaceFrame->RepositionFrame(lpPosRect, lpClipRect);
  1689. }
  1690.  
  1691. BOOL COleServerDoc::OnReactivateAndUndo()
  1692. {
  1693.     // default implementation doesn't support undo
  1694.  
  1695.     return FALSE;
  1696. }
  1697.  
  1698. /////////////////////////////////////////////////////////////////////////////
  1699. // COleServerDoc special APIs for in-place editing
  1700.  
  1701. void COleServerDoc::RequestPositionChange(LPCRECT lpPosRect)
  1702. {
  1703.     ASSERT_VALID(this);
  1704.     ASSERT(AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
  1705.  
  1706.     // get IOleInPlaceSite interface
  1707.     ASSERT(m_lpClientSite != NULL);
  1708.     LPOLEINPLACESITE lpInPlaceSite =
  1709.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1710.  
  1711.     if (lpInPlaceSite != NULL)
  1712.     {
  1713.         // call IOleInPlaceSite::OnPosRectChange
  1714.         lpInPlaceSite->OnPosRectChange(lpPosRect);
  1715.         lpInPlaceSite->Release();
  1716.     }
  1717. }
  1718.  
  1719. BOOL COleServerDoc::ScrollContainerBy(CSize sizeScroll)
  1720. {
  1721.     ASSERT_VALID(this);
  1722.  
  1723.     // get IOleInPlaceSite interface
  1724.     ASSERT(m_lpClientSite != NULL);
  1725.     LPOLEINPLACESITE lpInPlaceSite =
  1726.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1727.     if (lpInPlaceSite == NULL)
  1728.         return FALSE;
  1729.  
  1730.     // call IOleInPlaceSite::Scroll
  1731.     BOOL bResult = lpInPlaceSite->Scroll(sizeScroll) == S_OK;
  1732.     lpInPlaceSite->Release();
  1733.     return bResult;
  1734. }
  1735.  
  1736. BOOL COleServerDoc::DeactivateAndUndo()
  1737. {
  1738.     ASSERT_VALID(this);
  1739.  
  1740.     // get IOleInPlaceSite interface
  1741.     ASSERT(m_lpClientSite != NULL);
  1742.     LPOLEINPLACESITE lpInPlaceSite =
  1743.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1744.     if (lpInPlaceSite == NULL)
  1745.         return FALSE;
  1746.  
  1747.     // call IOleInPlaceSite::DeactivateAndUndo
  1748.     BOOL bResult = lpInPlaceSite->DeactivateAndUndo() == S_OK;
  1749.     lpInPlaceSite->Release();
  1750.     return bResult;
  1751. }
  1752.  
  1753. BOOL COleServerDoc::DiscardUndoState()
  1754. {
  1755.     ASSERT_VALID(this);
  1756.  
  1757.     // get IOleInPlaceSite interface
  1758.     ASSERT(m_lpClientSite != NULL);
  1759.     LPOLEINPLACESITE lpInPlaceSite =
  1760.         QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
  1761.     if (lpInPlaceSite == NULL)
  1762.         return FALSE;
  1763.  
  1764.     // call IOleInPlaceSite::DiscardUndoState
  1765.     BOOL bResult = lpInPlaceSite->DiscardUndoState() == S_OK;
  1766.     lpInPlaceSite->Release();
  1767.     return bResult;
  1768. }
  1769.  
  1770. /////////////////////////////////////////////////////////////////////////////
  1771. // COleServerDoc OLE interface implementation
  1772.  
  1773. BEGIN_INTERFACE_MAP(COleServerDoc, COleLinkingDoc)
  1774.     INTERFACE_PART(COleServerDoc, IID_IPersistStorage, PersistStorage)
  1775.     INTERFACE_PART(COleServerDoc, IID_IOleObject, OleObject)
  1776.     INTERFACE_PART(COleServerDoc, IID_IDataObject, DataObject)
  1777.     INTERFACE_PART(COleServerDoc, IID_IOleWindow, OleInPlaceObject)
  1778.     INTERFACE_PART(COleServerDoc, IID_IOleInPlaceObject, OleInPlaceObject)
  1779.     INTERFACE_PART(COleServerDoc, IID_IOleInPlaceActiveObject, OleInPlaceActiveObject)
  1780. END_INTERFACE_MAP()
  1781.  
  1782. /////////////////////////////////////////////////////////////////////////////
  1783. // COleServerDoc::CPersistStorage
  1784.  
  1785. STDMETHODIMP_(ULONG) COleServerDoc::XPersistStorage::AddRef()
  1786. {
  1787.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1788.     return pThis->ExternalAddRef();
  1789. }
  1790.  
  1791. STDMETHODIMP_(ULONG) COleServerDoc::XPersistStorage::Release()
  1792. {
  1793.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1794.     return pThis->ExternalRelease();
  1795. }
  1796.  
  1797. STDMETHODIMP COleServerDoc::XPersistStorage::QueryInterface(
  1798.     REFIID iid, LPVOID* ppvObj)
  1799. {
  1800.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1801.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  1802. }
  1803.  
  1804. STDMETHODIMP COleServerDoc::XPersistStorage::GetClassID(LPCLSID lpClassID)
  1805. {
  1806.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1807.  
  1808.     LPPERSISTFILE lpPersistFile = (LPPERSISTFILE)
  1809.         pThis->GetInterface(&IID_IPersistFile);
  1810.     return lpPersistFile->GetClassID(lpClassID);
  1811. }
  1812.  
  1813. STDMETHODIMP COleServerDoc::XPersistStorage::IsDirty()
  1814. {
  1815.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1816.  
  1817.     LPPERSISTFILE lpPersistFile = (LPPERSISTFILE)
  1818.         pThis->GetInterface(&IID_IPersistFile);
  1819.     return lpPersistFile->IsDirty();
  1820. }
  1821.  
  1822. STDMETHODIMP COleServerDoc::XPersistStorage::InitNew(LPSTORAGE pStg)
  1823. {
  1824.     METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
  1825.     ASSERT_VALID(pThis);
  1826.  
  1827.     SCODE sc = S_OK;
  1828.     TRY
  1829.     {
  1830.         // delegate to member function in the document
  1831.         pThis->OnNewEmbedding(pStg);
  1832.     }
  1833.     CATCH_ALL(e)
  1834.     {
  1835.         sc = COleException::Process(e);
  1836.         DELETE_EXCEPTION(e);
  1837.     }
  1838.     END_CATCH_ALL
  1839.  
  1840.     ASSERT_VALID(pThis);
  1841.     return sc;
  1842. }
  1843.  
  1844. STDMETHODIMP COleServerDoc::XPersistStorage::Load(LPSTORAGE pStg)
  1845. {
  1846.     METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
  1847.     ASSERT_VALID(pThis);
  1848.  
  1849.     SCODE sc = S_OK;
  1850.     pThis->BeginDeferErrors();
  1851.     TRY
  1852.     {
  1853.         // delegate to member function in the document
  1854.         pThis->OnOpenEmbedding(pStg);
  1855.     }
  1856.     CATCH_ALL(e)
  1857.     {
  1858.         sc = COleException::Process(e);
  1859.         DELETE_EXCEPTION(e);
  1860.     }
  1861.     END_CATCH_ALL
  1862.     sc = pThis->EndDeferErrors(sc);
  1863.  
  1864.     ASSERT_VALID(pThis);
  1865.     return sc;
  1866. }
  1867.  
  1868. STDMETHODIMP COleServerDoc::XPersistStorage::Save(
  1869.     LPSTORAGE pStgSave, BOOL fSameAsLoad)
  1870. {
  1871.     METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
  1872.     ASSERT_VALID(pThis);
  1873.  
  1874.     // don't bother saving if destination is up-to-date
  1875.     if (fSameAsLoad && !pThis->IsModified())
  1876.         return S_OK;
  1877.  
  1878.     SCODE sc = S_OK;
  1879.     pThis->BeginDeferErrors();
  1880.     TRY
  1881.     {
  1882.         // delegate through the document
  1883.         ASSERT(pThis->m_bRemember);
  1884.         pThis->m_bRemember = FALSE;
  1885.         pThis->m_bSameAsLoad = fSameAsLoad;
  1886.         pThis->OnSaveEmbedding(pStgSave);
  1887.  
  1888.         // clear dirty flag since save to same storage successful
  1889.         if (fSameAsLoad)
  1890.         {
  1891.             pThis->SetModifiedFlag(FALSE);
  1892.  
  1893.             // notify clients that object has been saved
  1894.             pThis->NotifySaved();
  1895.         }
  1896.     }
  1897.     CATCH_ALL(e)
  1898.     {
  1899.         sc = COleException::Process(e);
  1900.         DELETE_EXCEPTION(e);
  1901.     }
  1902.     END_CATCH_ALL
  1903.     sc = pThis->EndDeferErrors(sc);
  1904.  
  1905.     // restore default state
  1906.     pThis->m_bRemember = TRUE;
  1907.  
  1908.     ASSERT_VALID(pThis);
  1909.     return sc;
  1910. }
  1911.  
  1912. STDMETHODIMP COleServerDoc::XPersistStorage::SaveCompleted(LPSTORAGE pStgSaved)
  1913. {
  1914.     METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
  1915.     ASSERT_VALID(pThis);
  1916.  
  1917.     // call SaveCompleted on any embedded items
  1918.     pThis->CommitItems(pStgSaved != NULL);
  1919.  
  1920.     // update state to reflect new storage
  1921.     if (pStgSaved != NULL)
  1922.     {
  1923.         // attach new storage
  1924.         pStgSaved->AddRef();
  1925.         RELEASE(pThis->m_lpRootStg);
  1926.         pThis->m_lpRootStg = pStgSaved;
  1927.  
  1928.         // now this document is storage based
  1929.         pThis->m_strPathName.Empty();
  1930.         pThis->m_bEmbedded = TRUE;
  1931.         pThis->SetModifiedFlag(FALSE);
  1932.  
  1933.         // notify clients that object has been saved
  1934.         pThis->NotifySaved();
  1935.     }
  1936.  
  1937.     ASSERT_VALID(pThis);
  1938.     return S_OK;
  1939. }
  1940.  
  1941. STDMETHODIMP COleServerDoc::XPersistStorage::HandsOffStorage()
  1942. {
  1943.     METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
  1944.  
  1945.     if (pThis->m_lpRootStg != NULL)
  1946.     {
  1947.         // first call HandsOffStorage for all the embedded client items
  1948.         POSITION pos = pThis->GetStartPosition();
  1949.         COleClientItem* pItem;
  1950.         while ((pItem = pThis->GetNextClientItem(pos)) != NULL)
  1951.         {
  1952.             ASSERT(pItem->m_lpObject != NULL);
  1953.             LPPERSISTSTORAGE lpPersistStorage =
  1954.                 QUERYINTERFACE(pItem->m_lpObject, IPersistStorage);
  1955.             ASSERT(lpPersistStorage != NULL);
  1956.             lpPersistStorage->HandsOffStorage();
  1957.             lpPersistStorage->Release();
  1958.         }
  1959.  
  1960.         // for now, can't access the storage
  1961.         RELEASE(pThis->m_lpRootStg);
  1962.     }
  1963.  
  1964.     ASSERT_VALID(pThis);
  1965.     return S_OK;
  1966. }
  1967.  
  1968. /////////////////////////////////////////////////////////////////////////////
  1969. // COleServerDoc::XOleObject
  1970.  
  1971. STDMETHODIMP_(ULONG) COleServerDoc::XOleObject::AddRef()
  1972. {
  1973.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  1974.     return pThis->ExternalAddRef();
  1975. }
  1976.  
  1977. STDMETHODIMP_(ULONG) COleServerDoc::XOleObject::Release()
  1978. {
  1979.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  1980.     return pThis->ExternalRelease();
  1981. }
  1982.  
  1983. STDMETHODIMP COleServerDoc::XOleObject::QueryInterface(
  1984.     REFIID iid, LPVOID* ppvObj)
  1985. {
  1986.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  1987.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  1988. }
  1989.  
  1990. STDMETHODIMP COleServerDoc::XOleObject::SetClientSite(
  1991.     LPOLECLIENTSITE pClientSite)
  1992. {
  1993.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  1994.  
  1995.     // maintain reference counts
  1996.     if (pClientSite != NULL)
  1997.         pClientSite->AddRef();
  1998.     RELEASE(pThis->m_lpClientSite);
  1999.     pThis->m_lpClientSite = pClientSite;
  2000.  
  2001.     // do we already have doc object support enabled?
  2002.     if (pThis->m_pDocObjectServer != NULL)
  2003.     {
  2004.         // If we currently have a document site pointer,
  2005.         // release it.
  2006.         pThis->m_pDocObjectServer->ReleaseDocSite();
  2007.     }
  2008.  
  2009.     if (pClientSite != NULL)
  2010.     {
  2011.         LPOLEDOCUMENTSITE pDocSite;
  2012.  
  2013.         if (SUCCEEDED(pClientSite->QueryInterface(IID_IOleDocumentSite,
  2014.             (LPVOID*) &pDocSite)))
  2015.         {
  2016.             if (pThis->m_pDocObjectServer != NULL)
  2017.                 pThis->m_pDocObjectServer->SetDocSite(pDocSite);
  2018.             else
  2019.             {
  2020.                 pThis->m_pDocObjectServer =
  2021.                     pThis->GetDocObjectServer(pDocSite);
  2022.             }
  2023.         }
  2024.     }
  2025.  
  2026.     return S_OK;
  2027. }
  2028.  
  2029. STDMETHODIMP COleServerDoc::XOleObject::GetClientSite(
  2030.     LPOLECLIENTSITE* ppClientSite)
  2031. {
  2032.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2033.  
  2034.     if (pThis->m_lpClientSite == NULL)
  2035.     {
  2036.         *ppClientSite = NULL;
  2037.         return E_FAIL;
  2038.     }
  2039.  
  2040.     *ppClientSite = pThis->m_lpClientSite;
  2041.     pThis->m_lpClientSite->AddRef();
  2042.     return S_OK;
  2043. }
  2044.  
  2045. STDMETHODIMP COleServerDoc::XOleObject::SetHostNames(
  2046.     LPCOLESTR lpszContainerApp, LPCOLESTR lpszContainerObj)
  2047. {
  2048.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2049.     ASSERT_VALID(pThis);
  2050.  
  2051.     USES_CONVERSION;
  2052.  
  2053.     TRY
  2054.     {
  2055.         pThis->OnSetHostNames(OLE2CT(lpszContainerApp),
  2056.             OLE2CT(lpszContainerObj));
  2057.     }
  2058.     END_TRY
  2059.  
  2060.     return S_OK;
  2061. }
  2062.  
  2063. STDMETHODIMP COleServerDoc::XOleObject::Close(DWORD dwSaveOption)
  2064. {
  2065.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2066.     ASSERT_VALID(pThis);
  2067.  
  2068.     pThis->InternalAddRef();    // protect this object
  2069.  
  2070.     SCODE sc = S_OK;
  2071.     TRY
  2072.     {
  2073.         // delegate through document for most of the work
  2074.         pThis->OnClose((OLECLOSE)dwSaveOption);
  2075.     }
  2076.     CATCH_ALL(e)
  2077.     {
  2078.         sc = COleException::Process(e);
  2079.         DELETE_EXCEPTION(e);
  2080.     }
  2081.     END_CATCH_ALL
  2082.  
  2083.     pThis->InternalRelease();   // may 'delete this'
  2084.  
  2085.     return sc;
  2086. }
  2087.  
  2088. STDMETHODIMP COleServerDoc::XOleObject::SetMoniker(
  2089.     DWORD /*dwWhichMoniker*/, LPMONIKER /*pmk*/)
  2090. {
  2091.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2092.  
  2093.     if (pThis->m_lpClientSite == NULL)
  2094.         return E_FAIL;
  2095.  
  2096.     // get current full moniker from client-site
  2097.     LPMONIKER lpMoniker = NULL;
  2098.     if (pThis->m_lpClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
  2099.         OLEWHICHMK_OBJFULL, &lpMoniker) != S_OK)
  2100.     {
  2101.         // just to make sure -- always set moniker to NULL on failure
  2102.         lpMoniker = NULL;
  2103.     }
  2104.  
  2105.     // update all embedded items with new moniker
  2106.     POSITION pos = pThis->GetStartPosition();
  2107.     COleClientItem* pItem;
  2108.     while ((pItem = pThis->GetNextClientItem(pos)) != NULL)
  2109.     {
  2110.         if (pItem->m_bMoniker)
  2111.             pItem->m_lpObject->SetMoniker(OLEWHICHMK_CONTAINER, lpMoniker);
  2112.     }
  2113.  
  2114.     // send Rename advises
  2115.     pThis->NotifyAllItems(OLE_RENAMED, (DWORD)lpMoniker);
  2116.     RELEASE(lpMoniker);
  2117.  
  2118.     return S_OK;
  2119. }
  2120.  
  2121. STDMETHODIMP COleServerDoc::XOleObject::GetMoniker(
  2122.     DWORD dwAssign, DWORD /*dwWhichMoniker*/, LPMONIKER* ppMoniker)
  2123. {
  2124.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2125.  
  2126.     *ppMoniker = pThis->GetMoniker((OLEGETMONIKER)dwAssign);
  2127.     return *ppMoniker == NULL ? E_FAIL : S_OK;
  2128. }
  2129.  
  2130. STDMETHODIMP COleServerDoc::XOleObject::InitFromData(
  2131.     LPDATAOBJECT pDataObject, BOOL fCreation, DWORD /*dwReserved*/)
  2132. {
  2133.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2134.     ASSERT_VALID(pThis);
  2135.  
  2136.     COleServerItem* pItem;
  2137.     SCODE sc;
  2138.     TRY
  2139.     {
  2140.         // delegate through item
  2141.         pItem = pThis->GetEmbeddedItem();
  2142.         ASSERT_VALID(pItem);
  2143.         ASSERT_KINDOF(COleServerItem, pItem);
  2144.  
  2145.         COleDataObject dataObject;
  2146.         dataObject.Attach(pDataObject,  FALSE);
  2147.         sc = pItem->OnInitFromData(&dataObject, fCreation) ? S_OK : S_FALSE;
  2148.     }
  2149.     CATCH_ALL(e)
  2150.     {
  2151.         sc = COleException::Process(e);
  2152.         DELETE_EXCEPTION(e);
  2153.     }
  2154.     END_CATCH_ALL
  2155.  
  2156.     return sc;
  2157. }
  2158.  
  2159. STDMETHODIMP COleServerDoc::XOleObject::GetClipboardData(
  2160.     DWORD /*dwReserved*/, LPDATAOBJECT* ppDataObject)
  2161. {
  2162.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2163.     ASSERT_VALID(pThis);
  2164.  
  2165.     *ppDataObject = NULL;
  2166.  
  2167.     COleServerItem* pItem;
  2168.     SCODE sc = S_OK;
  2169.     TRY
  2170.     {
  2171.         // delegate through item
  2172.         pItem = pThis->GetEmbeddedItem();
  2173.         ASSERT_VALID(pItem);
  2174.         ASSERT_KINDOF(COleServerItem, pItem);
  2175.  
  2176.         COleDataSource* pDataSource =
  2177.             pItem->OnGetClipboardData(TRUE, NULL, NULL);
  2178.         ASSERT(pDataSource != NULL);
  2179.  
  2180.         *ppDataObject =
  2181.             (LPDATAOBJECT)pDataSource->GetInterface(&IID_IDataObject);
  2182.         ASSERT(*ppDataObject != NULL);
  2183.     }
  2184.     CATCH_ALL(e)
  2185.     {
  2186.         sc = COleException::Process(e);
  2187.         DELETE_EXCEPTION(e);
  2188.     }
  2189.     END_CATCH_ALL
  2190.  
  2191.     return sc;
  2192. }
  2193.  
  2194. STDMETHODIMP COleServerDoc::XOleObject::DoVerb(
  2195.     LONG iVerb, LPMSG /*lpmsg*/, LPOLECLIENTSITE /*pActiveSite*/, LONG /*lindex*/,
  2196.     HWND /*hwndParent*/, LPCRECT /*lpPosRect*/)
  2197. {
  2198.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2199.     ASSERT_VALID(pThis);
  2200.  
  2201.     pThis->InternalAddRef();    // protect this object
  2202.  
  2203.     COleServerItem* pItem;
  2204.     SCODE sc = S_OK;
  2205.     TRY
  2206.     {
  2207.         // delegate through item
  2208.         pItem = pThis->GetEmbeddedItem();
  2209.         ASSERT_VALID(pItem);
  2210.         ASSERT_KINDOF(COleServerItem, pItem);
  2211.         pItem->OnDoVerb(iVerb);
  2212.     }
  2213.     CATCH_ALL(e)
  2214.     {
  2215.         sc = COleException::Process(e);
  2216.         DELETE_EXCEPTION(e);
  2217.     }
  2218.     END_CATCH_ALL
  2219.     pThis->InternalRelease();   // may 'delete this'
  2220.  
  2221.     return sc;
  2222. }
  2223.  
  2224. STDMETHODIMP COleServerDoc::XOleObject::EnumVerbs(
  2225.     IEnumOLEVERB** ppenumOleVerb)
  2226. {
  2227.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2228.  
  2229.     *ppenumOleVerb = NULL;
  2230.  
  2231.     LPOLEOBJECT lpObject = (LPOLEOBJECT)pThis->GetInterface(&IID_IOleObject);
  2232.     ASSERT(lpObject != NULL);
  2233.     CLSID clsid;
  2234.     lpObject->GetUserClassID(&clsid);
  2235.  
  2236.     return OleRegEnumVerbs(clsid, ppenumOleVerb);
  2237. }
  2238.  
  2239. STDMETHODIMP COleServerDoc::XOleObject::Update()
  2240. {
  2241.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2242.     ASSERT_VALID(pThis);
  2243.  
  2244.     COleServerItem* pItem;
  2245.     SCODE sc = S_OK;
  2246.     TRY
  2247.     {
  2248.         // delegate through item
  2249.         pItem = pThis->GetEmbeddedItem();
  2250.         ASSERT_VALID(pItem);
  2251.         ASSERT_KINDOF(COleServerItem, pItem);
  2252.         pItem->OnUpdateItems();
  2253.     }
  2254.     CATCH_ALL(e)
  2255.     {
  2256.         sc = COleException::Process(e);
  2257.         DELETE_EXCEPTION(e);
  2258.     }
  2259.     END_CATCH_ALL
  2260.  
  2261.     return sc;
  2262. }
  2263.  
  2264. STDMETHODIMP COleServerDoc::XOleObject::IsUpToDate()
  2265. {
  2266.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2267.     ASSERT_VALID(pThis);
  2268.  
  2269.     COleServerItem* pItem;
  2270.     SCODE sc;
  2271.     TRY
  2272.     {
  2273.         // delegate through item
  2274.         pItem = pThis->GetEmbeddedItem();
  2275.         ASSERT_VALID(pItem);
  2276.         ASSERT_KINDOF(COleServerItem, pItem);
  2277.  
  2278.         sc = pItem->OnQueryUpdateItems() ? S_FALSE : S_OK;
  2279.     }
  2280.     CATCH_ALL(e)
  2281.     {
  2282.         sc = COleException::Process(e);
  2283.         DELETE_EXCEPTION(e);
  2284.     }
  2285.     END_CATCH_ALL
  2286.  
  2287.     return sc;
  2288. }
  2289.  
  2290. STDMETHODIMP COleServerDoc::XOleObject::GetUserClassID(CLSID* lpClassID)
  2291. {
  2292.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2293.  
  2294.     LPPERSISTFILE lpPersistFile = (LPPERSISTFILE)
  2295.         pThis->GetInterface(&IID_IPersistFile);
  2296.     return lpPersistFile->GetClassID(lpClassID);
  2297. }
  2298.  
  2299. STDMETHODIMP COleServerDoc::XOleObject::GetUserType(
  2300.     DWORD dwFormOfType, LPOLESTR* ppszUserType)
  2301. {
  2302.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2303.  
  2304.     *ppszUserType = NULL;
  2305.  
  2306.     LPOLEOBJECT lpObject = (LPOLEOBJECT)pThis->GetInterface(&IID_IOleObject);
  2307.     ASSERT(lpObject != NULL);
  2308.     CLSID clsid;
  2309.     lpObject->GetUserClassID(&clsid);
  2310.  
  2311.     return OleRegGetUserType(clsid, dwFormOfType, ppszUserType);
  2312. }
  2313.  
  2314. STDMETHODIMP COleServerDoc::XOleObject::SetExtent(
  2315.     DWORD dwDrawAspect, LPSIZEL lpsizel)
  2316. {
  2317.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2318.     ASSERT_VALID(pThis);
  2319.  
  2320.     COleServerItem* pItem;
  2321.     SCODE sc = E_FAIL;
  2322.     TRY
  2323.     {
  2324.         // convert rectangle to a CSize and call item OnSetExtent
  2325.         pItem = pThis->GetEmbeddedItem();
  2326.         ASSERT_VALID(pItem);
  2327.         ASSERT_KINDOF(COleServerItem, pItem);
  2328.  
  2329.         CSize size((int)lpsizel->cx, (int)lpsizel->cy);
  2330.         if (pItem->OnSetExtent((DVASPECT)dwDrawAspect, size))
  2331.             sc = S_OK;
  2332.     }
  2333.     CATCH_ALL(e)
  2334.     {
  2335.         sc = COleException::Process(e);
  2336.         DELETE_EXCEPTION(e);
  2337.     }
  2338.     END_CATCH_ALL
  2339.  
  2340.     return sc;
  2341. }
  2342.  
  2343. STDMETHODIMP COleServerDoc::XOleObject::GetExtent(
  2344.     DWORD dwDrawAspect, LPSIZEL lpsizel)
  2345. {
  2346.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2347.     ASSERT_VALID(pThis);
  2348.  
  2349.     COleServerItem* pItem;
  2350.     SCODE sc = E_INVALIDARG;
  2351.     TRY
  2352.     {
  2353.         pItem = pThis->GetEmbeddedItem();
  2354.         ASSERT_VALID(pItem);
  2355.         ASSERT_KINDOF(COleServerItem, pItem);
  2356.  
  2357.         // call to get regular windows CSize
  2358.         CSize size;
  2359.         if (pItem->OnGetExtent((DVASPECT)dwDrawAspect, size))
  2360.         {
  2361.             if (size.cy < 0)
  2362.                 size.cy = -size.cy; // extents are always positive
  2363.             lpsizel->cx = size.cx;
  2364.             lpsizel->cy = size.cy;
  2365.  
  2366.             sc = S_OK;
  2367.         }
  2368.     }
  2369.     CATCH_ALL(e)
  2370.     {
  2371.         sc = COleException::Process(e);
  2372.         DELETE_EXCEPTION(e);
  2373.     }
  2374.     END_CATCH_ALL
  2375.  
  2376.     return sc;
  2377. }
  2378.  
  2379. STDMETHODIMP COleServerDoc::XOleObject::Advise(
  2380.     IAdviseSink* pAdvSink, DWORD* pdwConnection)
  2381. {
  2382.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2383.  
  2384.     COleServerItem* pItem = NULL;
  2385.     SCODE sc = E_OUTOFMEMORY;
  2386.     TRY
  2387.     {
  2388.         pItem = pThis->GetEmbeddedItem();
  2389.         ASSERT_VALID(pItem);
  2390.         ASSERT_KINDOF(COleServerItem, pItem);
  2391.         sc = S_OK;
  2392.     }
  2393.     END_TRY
  2394.  
  2395.     if (sc != S_OK)
  2396.         return sc;
  2397.  
  2398.     return pItem->GetOleObject()->Advise(pAdvSink, pdwConnection);
  2399. }
  2400.  
  2401. STDMETHODIMP COleServerDoc::XOleObject::Unadvise(DWORD dwConnection)
  2402. {
  2403.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2404.  
  2405.     COleServerItem* pItem = NULL;
  2406.     SCODE sc = E_OUTOFMEMORY;
  2407.     TRY
  2408.     {
  2409.         pItem = pThis->GetEmbeddedItem();
  2410.         ASSERT_VALID(pItem);
  2411.         ASSERT_KINDOF(COleServerItem, pItem);
  2412.         sc = S_OK;
  2413.     }
  2414.     END_TRY
  2415.  
  2416.     if (sc != S_OK)
  2417.         return sc;
  2418.  
  2419.     return pItem->GetOleObject()->Unadvise(dwConnection);
  2420. }
  2421.  
  2422. STDMETHODIMP COleServerDoc::XOleObject::EnumAdvise(
  2423.     LPENUMSTATDATA* ppenumAdvise)
  2424. {
  2425.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2426.  
  2427.     COleServerItem* pItem = NULL;
  2428.     SCODE sc = E_OUTOFMEMORY;
  2429.     TRY
  2430.     {
  2431.         pItem = pThis->GetEmbeddedItem();
  2432.         ASSERT_VALID(pItem);
  2433.         ASSERT_KINDOF(COleServerItem, pItem);
  2434.         sc = S_OK;
  2435.     }
  2436.     END_TRY
  2437.  
  2438.     if (sc != S_OK)
  2439.         return sc;
  2440.  
  2441.     return pItem->GetOleObject()->EnumAdvise(ppenumAdvise);
  2442. }
  2443.  
  2444. STDMETHODIMP COleServerDoc::XOleObject::GetMiscStatus(
  2445.     DWORD dwAspect, DWORD* pdwStatus)
  2446. {
  2447.     METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
  2448.  
  2449.     *pdwStatus = 0;
  2450.  
  2451.     LPOLEOBJECT lpObject = (LPOLEOBJECT)pThis->GetInterface(&IID_IOleObject);
  2452.     ASSERT(lpObject != NULL);
  2453.     CLSID clsid;
  2454.     lpObject->GetUserClassID(&clsid);
  2455.  
  2456.     return OleRegGetMiscStatus(clsid, dwAspect, pdwStatus);
  2457. }
  2458.  
  2459. STDMETHODIMP COleServerDoc::XOleObject::SetColorScheme(LPLOGPALETTE lpLogpal)
  2460. {
  2461.     METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
  2462.     ASSERT_VALID(pThis);
  2463.  
  2464.     COleServerItem* pItem;
  2465.     SCODE sc = E_NOTIMPL;
  2466.     TRY
  2467.     {
  2468.         pItem = pThis->GetEmbeddedItem();
  2469.         ASSERT_VALID(pItem);
  2470.         ASSERT_KINDOF(COleServerItem, pItem);
  2471.  
  2472.         // delegate to embedded item
  2473.         if (pItem->OnSetColorScheme(lpLogpal))
  2474.             sc = S_OK;
  2475.     }
  2476.     END_TRY
  2477.  
  2478.     return sc;
  2479. }
  2480.  
  2481. /////////////////////////////////////////////////////////////////////////////
  2482. // COleServerDoc::XDataObject
  2483.  
  2484. STDMETHODIMP_(ULONG) COleServerDoc::XDataObject::AddRef()
  2485. {
  2486.     METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
  2487.     return pThis->ExternalAddRef();
  2488. }
  2489.  
  2490. STDMETHODIMP_(ULONG) COleServerDoc::XDataObject::Release()
  2491. {
  2492.     METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
  2493.     return pThis->ExternalRelease();
  2494. }
  2495.  
  2496. STDMETHODIMP COleServerDoc::XDataObject::QueryInterface(
  2497.     REFIID iid, LPVOID* ppvObj)
  2498. {
  2499.     METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
  2500.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  2501. }
  2502.  
  2503. STDMETHODIMP COleServerDoc::XDataObject::GetData(
  2504.     LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  2505. {
  2506.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2507.  
  2508.     COleServerItem* pItem = NULL;
  2509.     SCODE sc = E_OUTOFMEMORY;
  2510.     TRY
  2511.     {
  2512.         pItem = pThis->GetEmbeddedItem();
  2513.         ASSERT_VALID(pItem);
  2514.         ASSERT_KINDOF(COleServerItem, pItem);
  2515.         sc = S_OK;
  2516.     }
  2517.     END_TRY
  2518.  
  2519.     if (sc != S_OK)
  2520.         return sc;
  2521.  
  2522.     return pItem->GetDataObject()->GetData(lpFormatEtc, lpStgMedium);
  2523. }
  2524.  
  2525. STDMETHODIMP COleServerDoc::XDataObject::GetDataHere(
  2526.     LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  2527. {
  2528.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2529.  
  2530.     COleServerItem* pItem = NULL;
  2531.     SCODE sc = E_OUTOFMEMORY;
  2532.     TRY
  2533.     {
  2534.         pItem = pThis->GetEmbeddedItem();
  2535.         ASSERT_VALID(pItem);
  2536.         ASSERT_KINDOF(COleServerItem, pItem);
  2537.         sc = S_OK;
  2538.     }
  2539.     END_TRY
  2540.  
  2541.     if (sc != S_OK)
  2542.         return sc;
  2543.  
  2544.     return pItem->GetDataObject()->GetDataHere(lpFormatEtc, lpStgMedium);
  2545. }
  2546.  
  2547. STDMETHODIMP COleServerDoc::XDataObject::QueryGetData(
  2548.     LPFORMATETC lpFormatEtc)
  2549. {
  2550.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2551.  
  2552.     COleServerItem* pItem = NULL;
  2553.     SCODE sc = E_OUTOFMEMORY;
  2554.     TRY
  2555.     {
  2556.         pItem = pThis->GetEmbeddedItem();
  2557.         ASSERT_VALID(pItem);
  2558.         ASSERT_KINDOF(COleServerItem, pItem);
  2559.         sc = S_OK;
  2560.     }
  2561.     END_TRY
  2562.  
  2563.     if (sc != S_OK)
  2564.         return sc;
  2565.  
  2566.     return pItem->GetDataObject()->QueryGetData(lpFormatEtc);
  2567. }
  2568.  
  2569. STDMETHODIMP COleServerDoc::XDataObject::GetCanonicalFormatEtc(
  2570.     LPFORMATETC /*lpFormatEtcIn*/, LPFORMATETC /*lpFormatEtcOut*/)
  2571. {
  2572.     // because we support the target-device (ptd) for server metafile format,
  2573.     //  all members of the FORMATETC are significant.
  2574.  
  2575.     return DATA_S_SAMEFORMATETC;
  2576. }
  2577.  
  2578. STDMETHODIMP COleServerDoc::XDataObject::SetData(
  2579.     LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium, BOOL bRelease)
  2580. {
  2581.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2582.  
  2583.     COleServerItem* pItem = NULL;
  2584.     SCODE sc = E_OUTOFMEMORY;
  2585.     TRY
  2586.     {
  2587.         pItem = pThis->GetEmbeddedItem();
  2588.         ASSERT_VALID(pItem);
  2589.         ASSERT_KINDOF(COleServerItem, pItem);
  2590.         sc = S_OK;
  2591.     }
  2592.     END_TRY
  2593.  
  2594.     if (sc != S_OK)
  2595.         return sc;
  2596.  
  2597.     return pItem->GetDataObject()->SetData(lpFormatEtc, lpStgMedium, bRelease);
  2598. }
  2599.  
  2600. STDMETHODIMP COleServerDoc::XDataObject::EnumFormatEtc(
  2601.     DWORD dwDirection, LPENUMFORMATETC* ppenumFormatEtc)
  2602. {
  2603.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2604.  
  2605.     COleServerItem* pItem = NULL;
  2606.     SCODE sc = E_OUTOFMEMORY;
  2607.     TRY
  2608.     {
  2609.         pItem = pThis->GetEmbeddedItem();
  2610.         ASSERT_VALID(pItem);
  2611.         ASSERT_KINDOF(COleServerItem, pItem);
  2612.         sc = S_OK;
  2613.     }
  2614.     END_TRY
  2615.  
  2616.     if (sc != S_OK)
  2617.         return sc;
  2618.  
  2619.     return pItem->GetDataObject()->EnumFormatEtc(dwDirection, ppenumFormatEtc);
  2620. }
  2621.  
  2622. STDMETHODIMP COleServerDoc::XDataObject::DAdvise(
  2623.     FORMATETC* pFormatetc, DWORD advf,
  2624.     LPADVISESINK pAdvSink, DWORD* pdwConnection)
  2625. {
  2626.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2627.  
  2628.     COleServerItem* pItem = NULL;
  2629.     SCODE sc = E_OUTOFMEMORY;
  2630.     TRY
  2631.     {
  2632.         pItem = pThis->GetEmbeddedItem();
  2633.         ASSERT_VALID(pItem);
  2634.         ASSERT_KINDOF(COleServerItem, pItem);
  2635.         sc = S_OK;
  2636.     }
  2637.     END_TRY
  2638.  
  2639.     if (sc != S_OK)
  2640.         return sc;
  2641.  
  2642.     return pItem->GetDataObject()->DAdvise(pFormatetc, advf, pAdvSink,
  2643.         pdwConnection);
  2644. }
  2645.  
  2646. STDMETHODIMP COleServerDoc::XDataObject::DUnadvise(DWORD dwConnection)
  2647. {
  2648.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2649.  
  2650.     COleServerItem* pItem = NULL;
  2651.     SCODE sc = E_OUTOFMEMORY;
  2652.     TRY
  2653.     {
  2654.         pItem = pThis->GetEmbeddedItem();
  2655.         ASSERT_VALID(pItem);
  2656.         ASSERT_KINDOF(COleServerItem, pItem);
  2657.         sc = S_OK;
  2658.     }
  2659.     END_TRY
  2660.  
  2661.     if (sc != S_OK)
  2662.         return sc;
  2663.  
  2664.     return pItem->GetDataObject()->DUnadvise(dwConnection);
  2665. }
  2666.  
  2667. STDMETHODIMP COleServerDoc::XDataObject::EnumDAdvise(
  2668.     LPENUMSTATDATA* ppenumAdvise)
  2669. {
  2670.     METHOD_PROLOGUE_EX(COleServerDoc, DataObject)
  2671.  
  2672.     COleServerItem* pItem = NULL;
  2673.     SCODE sc = E_OUTOFMEMORY;
  2674.     TRY
  2675.     {
  2676.         pItem = pThis->GetEmbeddedItem();
  2677.         ASSERT_VALID(pItem);
  2678.         ASSERT_KINDOF(COleServerItem, pItem);
  2679.         sc = S_OK;
  2680.     }
  2681.     END_TRY
  2682.  
  2683.     if (sc != S_OK)
  2684.         return sc;
  2685.  
  2686.     return pItem->GetDataObject()->EnumDAdvise(ppenumAdvise);
  2687. }
  2688.  
  2689. /////////////////////////////////////////////////////////////////////////////
  2690. // COleServerDoc::COleInPlaceObject
  2691.  
  2692. STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceObject::AddRef()
  2693. {
  2694.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
  2695.     return pThis->ExternalAddRef();
  2696. }
  2697.  
  2698. STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceObject::Release()
  2699. {
  2700.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
  2701.     return pThis->ExternalRelease();
  2702. }
  2703.  
  2704. STDMETHODIMP COleServerDoc::XOleInPlaceObject::QueryInterface(
  2705.     REFIID iid, LPVOID* ppvObj)
  2706. {
  2707.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
  2708.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  2709. }
  2710.  
  2711. STDMETHODIMP COleServerDoc::XOleInPlaceObject::GetWindow(HWND* lphwnd)
  2712. {
  2713.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
  2714.  
  2715.     LPOLEINPLACEACTIVEOBJECT lpActiveObject = (LPOLEINPLACEACTIVEOBJECT)
  2716.         pThis->GetInterface(&IID_IOleInPlaceActiveObject);
  2717.     return lpActiveObject->GetWindow(lphwnd);
  2718. }
  2719.  
  2720. STDMETHODIMP COleServerDoc::XOleInPlaceObject::ContextSensitiveHelp(
  2721.     BOOL fEnterMode)
  2722. {
  2723.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
  2724.  
  2725.     LPOLEINPLACEACTIVEOBJECT lpActiveObject = (LPOLEINPLACEACTIVEOBJECT)
  2726.         pThis->GetInterface(&IID_IOleInPlaceActiveObject);
  2727.     return lpActiveObject->ContextSensitiveHelp(fEnterMode);
  2728. }
  2729.  
  2730. STDMETHODIMP COleServerDoc::XOleInPlaceObject::InPlaceDeactivate()
  2731. {
  2732.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
  2733.     ASSERT_VALID(pThis);
  2734.  
  2735.     pThis->InternalAddRef();    // protect this object
  2736.  
  2737.     SCODE sc = E_UNEXPECTED;
  2738.     TRY
  2739.     {
  2740.         // only call deactivate if necessary
  2741.         if (pThis->m_pInPlaceFrame != NULL)
  2742.             pThis->OnDeactivate();
  2743.  
  2744.         // should be completely inactive
  2745.         ASSERT(pThis->m_pInPlaceFrame == NULL);
  2746.         sc = S_OK;
  2747.     }
  2748.     END_TRY
  2749.  
  2750.     pThis->InternalRelease();   // may 'delete this'
  2751.     return sc;
  2752. }
  2753.  
  2754. STDMETHODIMP COleServerDoc::XOleInPlaceObject::UIDeactivate()
  2755. {
  2756.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
  2757.     ASSERT_VALID(pThis);
  2758.  
  2759.     pThis->InternalAddRef();    // protect this object
  2760.  
  2761.     SCODE sc = E_UNEXPECTED;
  2762.     TRY
  2763.     {
  2764.         // only call OnUIDeactivate if necessary
  2765.         if (pThis->m_pInPlaceFrame != NULL &&
  2766.             pThis->m_pInPlaceFrame->m_bUIActive)
  2767.         {
  2768.             pThis->OnDeactivateUI(FALSE);   // default to not undoable
  2769.         }
  2770.  
  2771.         // should not be ui active
  2772.         ASSERT(pThis->m_pInPlaceFrame == NULL ||
  2773.             !pThis->m_pInPlaceFrame->m_bUIActive);
  2774.         sc = S_OK;
  2775.     }
  2776.     END_TRY
  2777.  
  2778.     pThis->InternalRelease();   // may 'delete this'
  2779.     return sc;
  2780. }
  2781.  
  2782. STDMETHODIMP COleServerDoc::XOleInPlaceObject::SetObjectRects(
  2783.     LPCRECT lpPosRect, LPCRECT lpClipRect)
  2784. {
  2785.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
  2786.     ASSERT_VALID(pThis);
  2787.  
  2788.     SCODE sc = E_UNEXPECTED;
  2789.     TRY
  2790.     {
  2791.         pThis->OnSetItemRects(lpPosRect, lpClipRect);
  2792.         sc = S_OK;
  2793.     }
  2794.     END_TRY
  2795.  
  2796.     return sc;
  2797. }
  2798.  
  2799. STDMETHODIMP COleServerDoc::XOleInPlaceObject::ReactivateAndUndo()
  2800. {
  2801.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
  2802.     ASSERT_VALID(pThis);
  2803.  
  2804.     SCODE sc = E_UNEXPECTED;
  2805.     TRY
  2806.     {
  2807.         sc = pThis->OnReactivateAndUndo() ? S_OK : INPLACE_E_NOTUNDOABLE;
  2808.     }
  2809.     END_TRY
  2810.  
  2811.     return sc;
  2812. }
  2813.  
  2814. /////////////////////////////////////////////////////////////////////////////
  2815. // COleServerDoc::XOleInPlaceActiveObject
  2816.  
  2817. STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceActiveObject::AddRef()
  2818. {
  2819.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
  2820.     return pThis->ExternalAddRef();
  2821. }
  2822.  
  2823. STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceActiveObject::Release()
  2824. {
  2825.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
  2826.     return pThis->ExternalRelease();
  2827. }
  2828.  
  2829. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::QueryInterface(
  2830.     REFIID iid, LPVOID* ppvObj)
  2831. {
  2832.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
  2833.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  2834. }
  2835.  
  2836. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::GetWindow(
  2837.     HWND* lphwnd)
  2838. {
  2839.     METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
  2840.  
  2841.     *lphwnd = pThis->m_pInPlaceFrame->GetSafeHwnd();
  2842.     return *lphwnd != NULL ? S_OK : E_FAIL;
  2843. }
  2844.  
  2845. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::ContextSensitiveHelp(
  2846.     BOOL fEnterMode)
  2847. {
  2848.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2849.     ASSERT_VALID(pThis);
  2850.  
  2851.     if (fEnterMode)
  2852.     {
  2853.         if (!pThis->m_pInPlaceFrame->m_bHelpMode)
  2854.         {
  2855.             // check if help mode probable
  2856.             if (!pThis->m_pInPlaceFrame->CanEnterHelpMode())
  2857.                 return E_UNEXPECTED;
  2858.  
  2859.             // attempt to enter context help
  2860.             if (!pThis->m_pInPlaceFrame->PostMessage(WM_COMMAND, ID_CONTEXT_HELP))
  2861.                 return E_UNEXPECTED;
  2862.         }
  2863.     }
  2864.     else
  2865.     {
  2866.         // just exit help mode
  2867.         pThis->m_pInPlaceFrame->ExitHelpMode();
  2868.     }
  2869.  
  2870.     return S_OK;
  2871. }
  2872.  
  2873. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::TranslateAccelerator(
  2874.     LPMSG lpmsg)
  2875. {
  2876.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2877.     ASSERT_VALID(pThis);
  2878.  
  2879.     pThis->InternalAddRef();    // protect this object
  2880.  
  2881.     SCODE sc = E_UNEXPECTED;
  2882.     TRY
  2883.     {
  2884.         // get frame window for this document
  2885.         CFrameWnd* pFrameWnd = pThis->m_pInPlaceFrame;
  2886.         ASSERT_VALID(pFrameWnd);
  2887.  
  2888.         // attempt translate accelerator
  2889.         MSG msg = *lpmsg;
  2890.         sc = pFrameWnd->PreTranslateMessage(&msg) ? S_OK : S_FALSE;
  2891.         *lpmsg = msg;
  2892.     }
  2893.     END_TRY
  2894.  
  2895.     pThis->InternalRelease();   // may 'delete this'
  2896.  
  2897.     return sc;
  2898. }
  2899.  
  2900. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::OnFrameWindowActivate(
  2901.     BOOL fActivate)
  2902. {
  2903.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2904.     ASSERT_VALID(pThis);
  2905.  
  2906.     SCODE sc = E_UNEXPECTED;
  2907.     TRY
  2908.     {
  2909.         pThis->OnFrameWindowActivate(fActivate);
  2910.         sc = S_OK;
  2911.     }
  2912.     END_TRY
  2913.  
  2914.     return sc;
  2915. }
  2916.  
  2917. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::OnDocWindowActivate(
  2918.     BOOL fActivate)
  2919. {
  2920.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2921.     ASSERT_VALID(pThis);
  2922.  
  2923.     SCODE sc = E_UNEXPECTED;
  2924.     TRY
  2925.     {
  2926.         pThis->OnDocWindowActivate(fActivate);
  2927.         sc = S_OK;
  2928.     }
  2929.     END_TRY
  2930.  
  2931.     return sc;
  2932. }
  2933.  
  2934. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::ResizeBorder(
  2935.     LPCRECT lprectBorder, LPOLEINPLACEUIWINDOW lpUIWindow, BOOL fFrameWindow)
  2936. {
  2937.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2938.     ASSERT_VALID(pThis);
  2939.  
  2940.     SCODE sc = E_UNEXPECTED;
  2941.     TRY
  2942.     {
  2943.         pThis->OnResizeBorder(lprectBorder, lpUIWindow, fFrameWindow);
  2944.         sc = S_OK;
  2945.     }
  2946.     END_TRY
  2947.  
  2948.     return sc;
  2949. }
  2950.  
  2951. STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::EnableModeless(
  2952.     BOOL fEnable)
  2953. {
  2954.     METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
  2955.     ASSERT_VALID(pThis);
  2956.  
  2957.     SCODE sc = E_UNEXPECTED;
  2958.     TRY
  2959.     {
  2960.         if (!fEnable)
  2961.         {
  2962.             // start modal state if not in modal state
  2963.             if (!pThis->m_pInPlaceFrame->InModalState())
  2964.             {
  2965.                 CWnd* pTemp = pThis->m_pInPlaceFrame->GetTopLevelParent();
  2966.                 BOOL bEnabled = pTemp->IsWindowEnabled();
  2967.                 pThis->m_pInPlaceFrame->BeginModalState();
  2968.                 pTemp->EnableWindow(bEnabled);
  2969.             }
  2970.         }
  2971.         else
  2972.         {
  2973.             // end modal state if in modal state
  2974.             if (pThis->m_pInPlaceFrame->InModalState())
  2975.                 pThis->m_pInPlaceFrame->EndModalState();
  2976.         }
  2977.         sc = S_OK;
  2978.     }
  2979.     END_TRY
  2980.  
  2981.     return sc;
  2982. }
  2983.  
  2984. //////////////////////////////////////////////////////////////////////////////
  2985. // Diagnostics
  2986.  
  2987. #ifdef _DEBUG
  2988. void COleServerDoc::AssertValid() const
  2989. {
  2990.     COleLinkingDoc::AssertValid();
  2991.     if (m_pInPlaceFrame != NULL)
  2992.         m_pInPlaceFrame->AssertValid();
  2993.     if (m_pOrigParent != NULL)
  2994.         m_pOrigParent->AssertValid();
  2995. }
  2996.  
  2997. void COleServerDoc::Dump(CDumpContext& dc) const
  2998. {
  2999.     COleLinkingDoc::Dump(dc);
  3000.  
  3001.     if (dc.GetDepth() != 0)
  3002.     {
  3003.         if (m_pInPlaceFrame != NULL)
  3004.             dc << "\nwith in-place frame: " << m_pInPlaceFrame;
  3005.         else
  3006.             dc << "\nwith no in-place frame\n";
  3007.         if (m_pOrigParent != NULL)
  3008.             dc << "\nwith original parent: " << m_pOrigParent;
  3009.         else
  3010.             dc << "with no original parent\n";
  3011.     }
  3012.     dc << "m_lpClientSite = " << m_lpClientSite;
  3013.     dc << "\nm_strHostObj = " << m_strHostObj;
  3014.     dc << "\nm_bCntrVisible = " << m_bCntrVisible;
  3015.     dc << "\nm_dwOrigStyle = " << m_dwOrigStyle;
  3016.  
  3017.     dc << "\n";
  3018. }
  3019. #endif //_DEBUG
  3020.  
  3021. //////////////////////////////////////////////////////////////////////////////
  3022. // Inline function declarations expanded out-of-line
  3023.  
  3024. #ifndef _AFX_ENABLE_INLINES
  3025.  
  3026. // expand inlines for OLE server APIs
  3027. static char _szAfxOleInl[] = "afxole.inl";
  3028. #undef THIS_FILE
  3029. #define THIS_FILE _szAfxOleInl
  3030. #define _AFXOLESVR_INLINE
  3031. #include "afxole.inl"
  3032.  
  3033. #endif //!_AFX_ENABLE_INLINES
  3034.  
  3035. #ifdef AFX_INIT_SEG
  3036. #pragma code_seg(AFX_INIT_SEG)
  3037. #endif
  3038.  
  3039. IMPLEMENT_DYNAMIC(COleServerDoc, COleLinkingDoc)
  3040.  
  3041. /////////////////////////////////////////////////////////////////////////////
  3042.