home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / OLESVR2.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  36.4 KB  |  1,457 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 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.  
  13. #ifdef AFX_OLE4_SEG
  14. #pragma code_seg(AFX_OLE4_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. //////////////////////////////////////////////////////////////////////////////
  25. // COleServerItem implementation
  26.  
  27. COleServerItem::COleServerItem(COleServerDoc* pServerDoc, BOOL bAutoDelete)
  28. {
  29.     if (pServerDoc != NULL)
  30.         ASSERT_VALID(pServerDoc);
  31.  
  32.     m_dwRef = 0;    // always start in disconnected state
  33.     m_bAutoDelete = bAutoDelete;
  34.     m_bNeedUnlock = FALSE;
  35.  
  36.     // initially, item does not have an extent
  37.     m_sizeExtent.cx = 0;
  38.     m_sizeExtent.cy = 0;
  39.  
  40.     // initialize advise holders
  41.     m_lpOleAdviseHolder = NULL;
  42.     m_lpDataAdviseHolder = NULL;
  43.  
  44.     // add presentation formats to the data source
  45.     m_dataSource.m_nGrowBy = 1;
  46.     FORMATETC formatEtc;
  47.     formatEtc.ptd = NULL;
  48.     formatEtc.dwAspect = DVASPECT_CONTENT;
  49.     formatEtc.lindex = -1;
  50.  
  51.     // by default, a COleServerItem supports CF_METAFILEPICT
  52.     formatEtc.cfFormat = CF_METAFILEPICT;
  53.     formatEtc.tymed = TYMED_MFPICT;
  54.     m_dataSource.DelayRenderData(0, &formatEtc);
  55.  
  56.     // add item to server document
  57.     m_pDocument = NULL;
  58.     if (pServerDoc != NULL)
  59.         pServerDoc->AddItem(this);
  60.     ASSERT(m_pDocument == pServerDoc);
  61.  
  62.     AfxOleLockApp();
  63. }
  64.  
  65. COleServerItem::~COleServerItem()
  66. {
  67.     m_bAutoDelete = FALSE;  // no delete during destructor
  68.  
  69.     // release any advise holders
  70.     RELEASE(m_lpOleAdviseHolder);
  71.     RELEASE(m_lpDataAdviseHolder);
  72.  
  73.     ExternalDisconnect();
  74.  
  75.     // disconnect from the document
  76.     COleServerDoc* pDoc = GetDocument();
  77.     if (pDoc != NULL)
  78.     {
  79.         // remove external lock from it
  80.         if (m_bNeedUnlock)
  81.         {
  82.             pDoc->LockExternal(FALSE, TRUE);
  83.             m_bNeedUnlock = FALSE;
  84.         }
  85.  
  86.         // reset m_pEmbeddedItem if destroying embedded item
  87.         if (pDoc->m_pEmbeddedItem == this)
  88.             pDoc->m_pEmbeddedItem = NULL;
  89.  
  90.         // remove from list
  91.         pDoc->RemoveItem(this);
  92.     }
  93.  
  94.     // cleanup any references
  95.     AfxOleUnlockApp();
  96. }
  97.  
  98. BOOL COleServerItem::IsBlank() const
  99. {
  100.     // server items are blank in order to keep them from serializing when
  101.     //  COleDocument::Serialize is called.
  102.  
  103.     return TRUE;
  104. }
  105.  
  106. BOOL COleServerItem::IsConnected() const
  107. {
  108.     // if item is connected in any way, return TRUE
  109.     if (m_dwRef != 0)
  110.         return TRUE;
  111.  
  112.     // otherwise check if embedded item and document is connected
  113.     if (!IsLinkedItem() && GetDocument()->m_lpClientSite != NULL)
  114.         return TRUE;
  115.  
  116.     return FALSE;   // not connected
  117. }
  118.  
  119. void COleServerItem::NotifyClient(OLE_NOTIFICATION nCode, DWORD dwParam)
  120. {
  121.     switch (nCode)
  122.     {
  123.     // IDataObject notifications
  124.     case OLE_CHANGED:
  125.         if (m_lpDataAdviseHolder != NULL)
  126.             m_lpDataAdviseHolder->SendOnDataChange(GetDataObject(), dwParam, 0);
  127.         break;
  128.  
  129.     // IOleObject notifications
  130.     case OLE_SAVED:
  131.         if (m_lpOleAdviseHolder != NULL)
  132.             m_lpOleAdviseHolder->SendOnSave();
  133.         break;
  134.     case OLE_CLOSED:
  135.         if (m_lpOleAdviseHolder != NULL)
  136.             m_lpOleAdviseHolder->SendOnClose();
  137.         break;
  138.     case OLE_RENAMED:
  139.         if (m_lpOleAdviseHolder != NULL)
  140.         {
  141.             // Note: the moniker should already be updated for this to work
  142.             LPMONIKER lpMoniker = (LPMONIKER)dwParam;
  143.             m_lpOleAdviseHolder->SendOnRename(lpMoniker);
  144.         }
  145.         break;
  146.  
  147.     default:
  148.         ASSERT(FALSE);
  149.     }
  150. }
  151.  
  152. /////////////////////////////////////////////////////////////////////////////
  153. // Helpers for getting commonly used interfaces through interface map
  154.  
  155. LPDATAOBJECT COleServerItem::GetDataObject()
  156. {
  157.     LPDATAOBJECT lpDataObject =
  158.         (LPDATAOBJECT)GetInterface(&IID_IDataObject);
  159.     ASSERT(lpDataObject != NULL);
  160.     return lpDataObject;
  161. }
  162.  
  163. LPOLEOBJECT COleServerItem::GetOleObject()
  164. {
  165.     LPOLEOBJECT lpOleObject =
  166.         (LPOLEOBJECT)GetInterface(&IID_IOleObject);
  167.     ASSERT(lpOleObject != NULL);
  168.     return lpOleObject;
  169. }
  170.  
  171. /////////////////////////////////////////////////////////////////////////////
  172. // COleServerItem overrides
  173.  
  174. BOOL COleServerItem::OnQueryUpdateItems()
  175. {
  176.     COleDocument* pDoc = GetDocument();
  177.     ASSERT_VALID(pDoc);
  178.  
  179.     // update all of the embedded objects
  180.     POSITION pos = pDoc->GetStartPosition();
  181.     COleClientItem* pItem;
  182.     while ((pItem = pDoc->GetNextClientItem(pos)) != NULL)
  183.     {
  184.         // if any item is out-of-date, then this item is out-of-date
  185.         if (pItem->m_lpObject->IsUpToDate() != NULL)
  186.             return TRUE;    // update needed
  187.     }
  188.     return FALSE;   // update not needed
  189. }
  190.  
  191. void COleServerItem::OnUpdateItems()
  192. {
  193.     COleDocument* pDoc = GetDocument();
  194.     ASSERT_VALID(pDoc);
  195.  
  196.     // update all of the embedded objects
  197.     POSITION pos = pDoc->GetStartPosition();
  198.     COleClientItem* pItem;
  199.     while ((pItem = pDoc->GetNextClientItem(pos)) != NULL)
  200.     {
  201.         // update any out-of-date item
  202.         if (pItem->m_lpObject->IsUpToDate() != NULL)
  203.             pItem->m_lpObject->Update();
  204.     }
  205. }
  206.  
  207. BOOL COleServerItem::OnSetExtent(DVASPECT dwDrawAspect, const CSize& size)
  208. {
  209.     ASSERT_VALID(this);
  210.  
  211.     if (dwDrawAspect == DVASPECT_CONTENT)
  212.     {
  213.         m_sizeExtent = size;    // simply remember the extent
  214.         return TRUE;
  215.     }
  216.     return FALSE;   // not implemented for that dwDrawAspect
  217. }
  218.  
  219. BOOL COleServerItem::OnGetExtent(DVASPECT /*dwDrawAspect*/, CSize& rSize)
  220. {
  221.     ASSERT_VALID(this);
  222.     ASSERT(AfxIsValidAddress(&rSize, sizeof(CSize)));
  223.  
  224.     // the default implementation doesn't know what the extent is
  225.  
  226.     rSize.cx = 0;
  227.     rSize.cy = 0;
  228.  
  229.     return FALSE;
  230. }
  231.  
  232. void COleServerItem::OnDoVerb(LONG iVerb)
  233. {
  234.     switch (iVerb)
  235.     {
  236.     // open - maps to OnOpen
  237.     case OLEIVERB_OPEN:
  238.     case -OLEIVERB_OPEN-1:  // allows positive OLEIVERB_OPEN-1 in registry
  239.         OnOpen();
  240.         break;
  241.  
  242.     // primary, show, and unknown map to OnShow
  243.     case OLEIVERB_PRIMARY:  // OLEIVERB_PRIMARY is 0 and "Edit" in registry
  244.     case OLEIVERB_SHOW:
  245.         OnShow();
  246.         break;
  247.  
  248.     // hide maps to OnHide
  249.     case OLEIVERB_HIDE:
  250.     case -OLEIVERB_HIDE-1:  // allows positive OLEIVERB_HIDE-1 in registry
  251.         OnHide();
  252.         break;
  253.  
  254.     default:
  255.         // negative verbs not understood should return E_NOTIMPL
  256.         if (iVerb < 0)
  257.             AfxThrowOleException(E_NOTIMPL);
  258.  
  259.         // positive verb not processed --
  260.         //  according to OLE spec, primary verb should be executed
  261.         //  instead.
  262.         OnDoVerb(OLEIVERB_PRIMARY);
  263.  
  264.         // also, OLEOBJ_S_INVALIDVERB should be returned.
  265.         AfxThrowOleException(OLEOBJ_S_INVALIDVERB);
  266.     }
  267. }
  268.  
  269. BOOL COleServerItem::OnDrawEx(CDC* pDC, DVASPECT nDrawAspect, CSize& rSize)
  270. {
  271.     ASSERT_VALID(pDC);
  272.     ASSERT(AfxIsValidAddress(&rSize, sizeof(CSize)));
  273.  
  274.     if (nDrawAspect != DVASPECT_CONTENT)
  275.         return FALSE;
  276.  
  277.     return OnDraw(pDC, rSize);
  278. }
  279.  
  280. void COleServerItem::OnShow()
  281. {
  282.     ASSERT_VALID(this);
  283.  
  284.     // attempt in place activation (if not supported, fall back on "Open")
  285.     COleServerDoc* pDoc = GetDocument();
  286.     if (!pDoc->ActivateInPlace())
  287.     {
  288.         // by default OnShow() maps to OnOpen() if in-place activation
  289.         //  not supported
  290.         OnOpen();
  291.     }
  292. }
  293.  
  294. void COleServerItem::OnOpen()
  295. {
  296.     ASSERT_VALID(this);
  297.  
  298.     // default implementation shows the document
  299.     COleServerDoc* pDoc = GetDocument();
  300.     ASSERT(pDoc != NULL);
  301.     pDoc->OnShowDocument(TRUE);
  302. }
  303.  
  304. void COleServerItem::OnHide()
  305. {
  306.     ASSERT_VALID(this);
  307.  
  308.     // default implementation hides the document
  309.     COleServerDoc* pDoc = GetDocument();
  310.     ASSERT_VALID(pDoc);
  311.     pDoc->OnShowDocument(FALSE);
  312. }
  313.  
  314. BOOL COleServerItem::GetMetafileData(LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  315. {
  316.     ASSERT_VALID(this);
  317.     ASSERT(AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
  318.     ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
  319.     ASSERT(lpStgMedium->tymed == TYMED_NULL);   // GetDataHere not valid
  320.     ASSERT(lpStgMedium->pUnkForRelease == NULL);
  321.  
  322.     // medium must be TYMED_MFPICT -- cannot fill in existing HGLOBAL
  323.     if (!(lpFormatEtc->tymed & TYMED_MFPICT) || lpStgMedium->hGlobal != NULL)
  324.         return FALSE;
  325.  
  326.     // create appropriate memory metafile DC
  327.     CMetaFileDC dc;
  328.     if (!dc.Create())
  329.         return FALSE;
  330.  
  331.     // create attribute DC according to lpFormatEtc->ptd
  332.     HDC hAttribDC = _AfxOleCreateDC(lpFormatEtc->ptd);
  333.     if (hAttribDC == NULL)
  334.         return FALSE;
  335.     dc.SetAttribDC(hAttribDC);
  336.  
  337.     // Paint directly into the metafile.
  338.     CSize size(0, 0);
  339.     BOOL bResult = OnDrawEx(&dc, (DVASPECT)lpFormatEtc->dwAspect, size);
  340.  
  341.     // attribute DC is no longer necessary
  342.     dc.SetAttribDC(NULL);
  343.     ::DeleteDC(hAttribDC);
  344.  
  345.     if (!bResult)
  346.     {
  347. #ifdef _DEBUG
  348.         if (afxTraceFlags & traceOle)
  349.             TRACE0("calling COleServerItem::OnDrawEx()failed.\n");
  350. #endif
  351.         return FALSE;
  352.     }
  353.  
  354.     HMETAFILE hMF = dc.Close();
  355.     if (hMF == NULL)
  356.         return FALSE;
  357.  
  358.     HGLOBAL hPict;
  359.     if ((hPict =
  360.         ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT))) == NULL)
  361.     {
  362.         DeleteMetaFile(hMF);
  363.         return FALSE;
  364.     }
  365.     LPMETAFILEPICT lpPict;
  366.     if ((lpPict = (LPMETAFILEPICT)::GlobalLock(hPict)) == NULL)
  367.     {
  368.         DeleteMetaFile(hMF);
  369.         ::GlobalFree(hPict);
  370.         return FALSE;
  371.     }
  372.  
  373.     // set the metafile size
  374.     lpPict->mm = MM_ANISOTROPIC;
  375.     lpPict->hMF = hMF;
  376.     if (size.cx == 0 && size.cy == 0 &&
  377.         !OnGetExtent((DVASPECT)lpFormatEtc->dwAspect, size))
  378.     {
  379.         TRACE0("Warning: OnGetExtent failed during OnDrawEx --\n");
  380.         TRACE0("\tpresentation metafile may be badly formed!\n");
  381.     }
  382.     lpPict->xExt = size.cx;
  383.     lpPict->yExt = size.cy;  // HIMETRIC height
  384.     if (lpPict->yExt < 0)
  385.     {
  386.         TRACE0("Warning: HIMETRIC natural size is negative.\n");
  387.         lpPict->yExt = -lpPict->yExt;   // backward compatibility fix
  388.     }
  389.  
  390. #ifdef _DEBUG
  391.     if (lpPict->xExt == 0 || lpPict->yExt == 0)
  392.     {
  393.         // usually the natural extent is set to something interesting
  394.         TRACE0("Warning: COleServerItem has no natural size --\n");
  395.         TRACE0("\twill not work with some apps like MS Write.\n");
  396.     }
  397. #endif
  398.  
  399.     // return the medium with the hGlobal to the METAFILEPICT
  400.     ::GlobalUnlock(hPict);
  401.     lpStgMedium->hGlobal = hPict;
  402.     lpStgMedium->tymed = TYMED_MFPICT;
  403.     return TRUE;
  404. }
  405.  
  406. BOOL COleServerItem::OnSetColorScheme(const LOGPALETTE* /*lpLogPalette*/)
  407. {
  408.     ASSERT_VALID(this);
  409.  
  410.     return FALSE;   // default does nothing
  411. }
  412.  
  413. BOOL COleServerItem::OnInitFromData(
  414.     COleDataObject* /*pDataObject*/, BOOL /*bCreation*/)
  415. {
  416.     ASSERT_VALID(this);
  417.  
  418.     AfxThrowOleException(E_NOTIMPL);
  419.     return FALSE;
  420. }
  421.  
  422. void COleServerItem::CopyToClipboard(BOOL bIncludeLink)
  423. {
  424.     ASSERT_VALID(this);
  425.  
  426.     COleDataSource* pDataSource = OnGetClipboardData(bIncludeLink, NULL, NULL);
  427.  
  428.     // put it on the clipboard
  429.     pDataSource->SetClipboard();
  430. }
  431.  
  432. COleDataSource* COleServerItem::OnGetClipboardData(BOOL bIncludeLink,
  433.     LPPOINT lpOffset, LPSIZE lpSize)
  434. {
  435.     ASSERT_VALID(this);
  436.  
  437.     COleDataSource* pDataSource = new COleDataSource;
  438.     TRY
  439.     {
  440.         GetClipboardData(pDataSource, bIncludeLink, lpOffset, lpSize);
  441.     }
  442.     CATCH_ALL(e)
  443.     {
  444.         delete pDataSource;
  445.         THROW_LAST();
  446.     }
  447.     END_CATCH_ALL
  448.  
  449.     ASSERT_VALID(pDataSource);
  450.     return pDataSource;
  451. }
  452.  
  453. DROPEFFECT COleServerItem::DoDragDrop(LPCRECT lpItemRect, CPoint ptOffset,
  454.     BOOL bIncludeLink, DWORD dwEffects, LPCRECT lpRectStartDrag)
  455. {
  456.     ASSERT(AfxIsValidAddress(lpItemRect, sizeof(RECT)));
  457.     ASSERT_VALID(this);
  458.  
  459.     ASSERT_VALID(this);
  460.  
  461.     DROPEFFECT dropEffect = DROPEFFECT_NONE;
  462.     COleDataSource *pDataSource = NULL;
  463.     TRY
  464.     {
  465.         // get clipboard data for this item
  466.         CSize sizeItem(
  467.             lpItemRect->right - lpItemRect->left,
  468.             lpItemRect->bottom - lpItemRect->top);
  469.         pDataSource = OnGetClipboardData(bIncludeLink, &ptOffset, &sizeItem);
  470.  
  471.         // add DROPEFFECT_LINK if link source is available
  472.         LPDATAOBJECT lpDataObject = (LPDATAOBJECT)
  473.             pDataSource->GetInterface(&IID_IDataObject);
  474.         ASSERT(lpDataObject != NULL);
  475.         FORMATETC formatEtc;
  476.         formatEtc.cfFormat = (CLIPFORMAT)_oleData.cfLinkSource;
  477.         formatEtc.ptd = NULL;
  478.         formatEtc.dwAspect = DVASPECT_CONTENT;
  479.         formatEtc.lindex = -1;
  480.         formatEtc.tymed = (DWORD) -1;
  481.         if (lpDataObject->QueryGetData(&formatEtc) == S_OK)
  482.             dwEffects |= DROPEFFECT_LINK;
  483.  
  484.         // calculate default sensitivity rectangle
  485.         CRect rectDrag;
  486.         if (lpRectStartDrag == NULL)
  487.         {
  488.             rectDrag.SetRect(lpItemRect->left, lpItemRect->top, lpItemRect->left,
  489.                 lpItemRect->top);
  490.             lpRectStartDrag = &rectDrag;
  491.         }
  492.  
  493.         // do drag drop operation
  494.         dropEffect = pDataSource->DoDragDrop(dwEffects, lpRectStartDrag);
  495.         pDataSource->InternalRelease();
  496.     }
  497.     CATCH_ALL(e)
  498.     {
  499.         if (pDataSource != NULL)
  500.             pDataSource->InternalRelease();
  501.  
  502.         THROW_LAST();
  503.     }
  504.     END_CATCH_ALL
  505.  
  506.     return dropEffect;
  507. }
  508.  
  509. void COleServerItem::GetClipboardData(COleDataSource* pDataSource,
  510.     BOOL bIncludeLink, LPPOINT lpOffset, LPSIZE lpSize)
  511. {
  512.     ASSERT_VALID(this);
  513.     ASSERT_VALID(pDataSource);
  514.     ASSERT(lpOffset == NULL ||
  515.         AfxIsValidAddress(lpOffset, sizeof(POINT), FALSE));
  516.  
  517.     // add CF_EMBEDDEDOBJECT by creating memory storage copy of the object
  518.     STGMEDIUM stgMedium;
  519.     GetEmbedSourceData(&stgMedium);
  520.     pDataSource->CacheData((CLIPFORMAT)_oleData.cfEmbedSource, &stgMedium);
  521.  
  522.     // add CF_OBJECTDESCRIPTOR
  523.     GetObjectDescriptorData(lpOffset, lpSize, &stgMedium);
  524.     pDataSource->CacheData((CLIPFORMAT)_oleData.cfObjectDescriptor,
  525.         &stgMedium);
  526.  
  527.     // add any presentation entries/conversion formats that the item
  528.     //  can produce.
  529.     AddOtherClipboardData(pDataSource);
  530.  
  531.     // add CF_LINKSOURCE if supporting links to pseudo objects
  532.     if (bIncludeLink && GetLinkSourceData(&stgMedium))
  533.     {
  534.         pDataSource->CacheData((CLIPFORMAT)_oleData.cfLinkSource, &stgMedium);
  535.  
  536.         // add CF_LINKSOURCEDESCRIPTOR
  537.         GetObjectDescriptorData(lpOffset, lpSize, &stgMedium);
  538.         pDataSource->CacheData((CLIPFORMAT)_oleData.cfLinkSourceDescriptor,
  539.             &stgMedium);
  540.     }
  541. }
  542.  
  543. void COleServerItem::GetEmbedSourceData(LPSTGMEDIUM lpStgMedium)
  544. {
  545.     ASSERT_VALID(this);
  546.     ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
  547.  
  548.     LPLOCKBYTES lpLockBytes;
  549.     SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
  550.     if (sc != S_OK)
  551.         AfxThrowOleException(sc);
  552.     ASSERT(lpLockBytes != NULL);
  553.  
  554.     LPSTORAGE lpStorage;
  555.     sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
  556.         STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &lpStorage);
  557.     if (sc != S_OK)
  558.     {
  559.         VERIFY(lpLockBytes->Release() == 0);
  560.         AfxThrowOleException(sc);
  561.     }
  562.     ASSERT(lpStorage != NULL);
  563.  
  564.     // setup for save copy as
  565.     COleServerDoc* pDoc = GetDocument();
  566.     pDoc->m_bSameAsLoad = FALSE;
  567.     pDoc->m_bRemember = FALSE;
  568.  
  569.     TRY
  570.     {
  571.         OnSaveEmbedding(lpStorage);
  572.         pDoc->CommitItems(FALSE);
  573.     }
  574.     CATCH_ALL(e)
  575.     {
  576.         // release storage and lock bytes
  577.         VERIFY(lpStorage->Release() == 0);
  578.         VERIFY(lpLockBytes->Release() == 0);
  579.         pDoc->m_bSameAsLoad = TRUE;
  580.         pDoc->m_bRemember = TRUE;
  581.         THROW_LAST();
  582.     }
  583.     END_CATCH_ALL
  584.  
  585.     pDoc->m_bSameAsLoad = TRUE;
  586.     pDoc->m_bRemember = TRUE;
  587.     lpLockBytes->Release();
  588.  
  589.     // add it to the data source
  590.     lpStgMedium->tymed = TYMED_ISTORAGE;
  591.     lpStgMedium->pstg = lpStorage;
  592.     lpStgMedium->pUnkForRelease = NULL;
  593. }
  594.  
  595. void COleServerItem::AddOtherClipboardData(COleDataSource* pDataSource)
  596. {
  597.     ASSERT_VALID(this);
  598.     ASSERT_VALID(pDataSource);
  599.  
  600.     // get IEnumFORMATETC interface for the IDataObject
  601.     LPDATAOBJECT lpDataObject = GetDataObject();
  602.     LPENUMFORMATETC lpEnumFORMATETC;
  603.     if (lpDataObject->EnumFormatEtc(DATADIR_GET, &lpEnumFORMATETC) != S_OK)
  604.         return;
  605.     ASSERT(lpEnumFORMATETC != NULL);
  606.  
  607.     // get all formats that the object will give us
  608.     FORMATETC formatEtc;
  609.     while (lpEnumFORMATETC->Next(1, &formatEtc, NULL) == S_OK)
  610.     {
  611.         STGMEDIUM stgMedium;
  612.         if (lpDataObject->GetData(&formatEtc, &stgMedium) != S_OK)
  613.         {
  614.             // data is not available
  615.             CoTaskMemFree(formatEtc.ptd);
  616.         }
  617.         else if (stgMedium.pUnkForRelease != NULL)
  618.         {
  619.             // don't cache data with pUnkForRelease != NULL
  620.             ::ReleaseStgMedium(&stgMedium);
  621.             CoTaskMemFree(formatEtc.ptd);
  622.         }
  623.         else
  624.         {
  625.             // cache the data (now we own the stgMedium)
  626.             pDataSource->CacheData(0, &stgMedium, &formatEtc);
  627.         }
  628.     }
  629.  
  630.     // cleanup
  631.     lpEnumFORMATETC->Release();
  632. }
  633.  
  634. LPMONIKER COleServerItem::GetMoniker(OLEGETMONIKER nAssign)
  635. {
  636.     // get IOleObject interface for this item
  637.     LPOLEOBJECT lpOleObject = GetOleObject();
  638.     ASSERT(lpOleObject != NULL);
  639.  
  640.     // get moniker from OLE object
  641.     LPMONIKER lpMoniker = NULL;
  642.     lpOleObject->GetMoniker(nAssign, OLEWHICHMK_OBJFULL, &lpMoniker);
  643.     return lpMoniker;
  644. }
  645.  
  646. BOOL COleServerItem::GetLinkSourceData(LPSTGMEDIUM lpStgMedium)
  647. {
  648.     ASSERT_VALID(this);
  649.     ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
  650.  
  651.     LPOLEOBJECT lpOleObject = GetOleObject();
  652.     ASSERT(lpOleObject != NULL);
  653.  
  654.     // get moniker from ole object
  655.     LPMONIKER lpMoniker;
  656.     SCODE sc = lpOleObject->GetMoniker(OLEGETMONIKER_TEMPFORUSER,
  657.         OLEWHICHMK_OBJFULL, &lpMoniker);
  658.     if (sc != S_OK)
  659.     {
  660.         TRACE0("Warning: unable to get moniker for object.\n");
  661.         return FALSE;
  662.     }
  663.     ASSERT(lpMoniker != NULL);
  664.  
  665.     // create a memory based stream to write the moniker to
  666.     LPSTREAM lpStream;
  667.     if (::CreateStreamOnHGlobal(NULL, TRUE, &lpStream) != S_OK)
  668.     {
  669.         lpMoniker->Release();
  670.         AfxThrowMemoryException();
  671.     }
  672.     ASSERT(lpStream != NULL);
  673.  
  674.     // write the moniker to the stream, and add it to the clipboard
  675.     sc = ::OleSaveToStream(lpMoniker, lpStream);
  676.     lpMoniker->Release();
  677.     if (sc != S_OK)
  678.     {
  679.         lpStream->Release();
  680.         AfxThrowOleException(sc);
  681.     }
  682.  
  683.     // write the class ID of the document to the stream as well
  684.     COleLinkingDoc* pDoc = GetDocument();
  685.     ASSERT(pDoc->m_pFactory != NULL);
  686.     sc = WriteClassStm(lpStream, pDoc->m_pFactory->GetClassID());
  687.     if (sc != S_OK)
  688.     {
  689.         lpStream->Release();
  690.         AfxThrowOleException(sc);
  691.     }
  692.  
  693.     // setup the STGMEDIUM
  694.     lpStgMedium->tymed = TYMED_ISTREAM;
  695.     lpStgMedium->pstm = lpStream;
  696.     lpStgMedium->pUnkForRelease = NULL;
  697.     return TRUE;
  698. }
  699.  
  700. void COleServerItem::GetObjectDescriptorData(
  701.     LPPOINT lpOffset, LPSIZE lpSize, LPSTGMEDIUM lpStgMedium)
  702. {
  703.     ASSERT_VALID(this);
  704.     ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
  705.     ASSERT(lpOffset == NULL ||
  706.         AfxIsValidAddress(lpOffset, sizeof(POINT), FALSE));
  707.  
  708.     LPOLEOBJECT lpOleObject = GetOleObject();
  709.     ASSERT(lpOleObject != NULL);
  710.  
  711.     // get the object descriptor for the IOleObject
  712.     POINTL pointl = { 0, 0 };
  713.     if (lpOffset != NULL)
  714.     {
  715.         CSize ptOffset(lpOffset->x, lpOffset->y);
  716. #ifndef _MAC
  717.         ((CDC*)NULL)->DPtoHIMETRIC(&ptOffset);
  718. #endif
  719.         pointl.x = ptOffset.cx;
  720.         pointl.y = ptOffset.cy;
  721.     }
  722.     SIZEL sizel;
  723.     if (lpSize != NULL)
  724.     {
  725.         sizel.cx = lpSize->cx;
  726.         sizel.cy = lpSize->cy;
  727. #ifndef _MAC
  728.         ((CDC*)NULL)->DPtoHIMETRIC(&sizel);
  729. #endif
  730.     }
  731.     else
  732.     {
  733.         sizel.cx = 0;
  734.         sizel.cy = 0;
  735.     }
  736.  
  737.     InterlockedIncrement(&m_dwRef);  // protect against destruction during this call
  738.     HGLOBAL hGlobal = _AfxOleGetObjectDescriptorData(
  739.         lpOleObject, NULL, DVASPECT_CONTENT, pointl, &sizel);
  740.     InterlockedDecrement(&m_dwRef);
  741.  
  742.     if (hGlobal == NULL)
  743.         AfxThrowMemoryException();
  744.  
  745.     // setup the STGMEDIUM
  746.     lpStgMedium->tymed = TYMED_HGLOBAL;
  747.     lpStgMedium->hGlobal = hGlobal;
  748.     lpStgMedium->pUnkForRelease = NULL;
  749. }
  750.  
  751. void COleServerItem::OnSaveEmbedding(LPSTORAGE lpStorage)
  752. {
  753.     ASSERT(lpStorage != NULL);
  754.  
  755.     // always (logically) a "File.Save Copy As" operation
  756.     COleServerDoc* pDoc = GetDocument();
  757.     LPSTORAGE lpOrigStg = pDoc->m_lpRootStg;
  758.     pDoc->m_lpRootStg = lpStorage;
  759.  
  760.     TRY
  761.     {
  762.         ASSERT(pDoc->m_lpRootStg != NULL);
  763.         pDoc->SaveToStorage(this);  // use helper to serialize to storage
  764.     }
  765.     CATCH_ALL(e)
  766.     {
  767.         // save as failed: re-attach original storage
  768.         pDoc->m_lpRootStg = lpOrigStg;
  769.         THROW_LAST();
  770.     }
  771.     END_CATCH_ALL
  772.  
  773.     // re-attach original storage
  774.     pDoc->m_lpRootStg = lpOrigStg;
  775. }
  776.  
  777. /////////////////////////////////////////////////////////////////////////////
  778. // COleServerItem data-object callback default implementation
  779.  
  780. BOOL COleServerItem::OnRenderGlobalData(
  781.     LPFORMATETC /*lpFormatEtc*/, HGLOBAL* /*phGlobal*/)
  782. {
  783.     ASSERT_VALID(this);
  784.  
  785.     return FALSE;   // default does nothing
  786. }
  787.  
  788. BOOL COleServerItem::OnRenderFileData(
  789.     LPFORMATETC /*lpFormatEtc*/, CFile* /*pFile*/)
  790. {
  791.     ASSERT_VALID(this);
  792.  
  793.     return FALSE;   // default does nothing
  794. }
  795.  
  796. BOOL COleServerItem::OnRenderData(LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  797. {
  798.     ASSERT_VALID(this);
  799.     ASSERT(AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
  800.     ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
  801.  
  802.     // default implementation does not support extended layout
  803.     if (lpFormatEtc->lindex != -1)
  804.         return FALSE;
  805.  
  806.     // default implementation supports both types of metafiles
  807.     if (lpFormatEtc->cfFormat == CF_METAFILEPICT)
  808.         return GetMetafileData(lpFormatEtc, lpStgMedium);
  809.  
  810.     return FALSE;   // cfFormat not supported
  811. }
  812.  
  813. BOOL COleServerItem::OnSetData(
  814.     LPFORMATETC /*lpFormatEtc*/, LPSTGMEDIUM /*lpStgMedium*/, BOOL /*bRelease*/)
  815. {
  816.     ASSERT_VALID(this);
  817.  
  818.     return FALSE;   // default does nothing
  819. }
  820.  
  821. /////////////////////////////////////////////////////////////////////////////
  822. // COleServerItem OLE interface implementation
  823.  
  824. BEGIN_INTERFACE_MAP(COleServerItem, CDocItem)
  825.     INTERFACE_PART(COleServerItem, IID_IOleObject, OleObject)
  826.     INTERFACE_PART(COleServerItem, IID_IDataObject, DataObject)
  827. END_INTERFACE_MAP()
  828.  
  829. /////////////////////////////////////////////////////////////////////////////
  830. // COleServerItem::XOleObject
  831.  
  832. STDMETHODIMP_(ULONG) COleServerItem::XOleObject::AddRef()
  833. {
  834.     METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
  835.     return pThis->ExternalAddRef();
  836. }
  837.  
  838. STDMETHODIMP_(ULONG) COleServerItem::XOleObject::Release()
  839. {
  840.     METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
  841.     return pThis->ExternalRelease();
  842. }
  843.  
  844. STDMETHODIMP COleServerItem::XOleObject::QueryInterface(
  845.     REFIID iid, LPVOID* ppvObj)
  846. {
  847.     METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
  848.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  849. }
  850.  
  851. // COleServerItem has special Release semantics.  In particular, the item
  852. //  is only deleted from memory if m_bAutoDelete is TRUE.
  853. //  Also, it unlocks the document if the reference count reaches zero.
  854.  
  855. void COleServerItem::OnFinalRelease()
  856. {
  857.     ASSERT_VALID(this);
  858.  
  859.     COleServerDoc* pDoc = GetDocument();
  860.     ASSERT_VALID(pDoc);
  861.  
  862.     pDoc->InternalAddRef(); // make document stable
  863.  
  864.     // if connected to a document -- remove external lock from it
  865.     if (m_bNeedUnlock)
  866.     {
  867.         pDoc->LockExternal(FALSE, TRUE);
  868.         m_bNeedUnlock = FALSE;
  869.     }
  870.  
  871.     // delete this item if no longer needed
  872.     if (m_bAutoDelete)
  873.         delete this;
  874.  
  875.     // release artificial reference (may destroy the document)
  876.     pDoc->InternalRelease();
  877. }
  878.  
  879. STDMETHODIMP COleServerItem::XOleObject::SetClientSite(
  880.     LPOLECLIENTSITE /*pClientSite*/)
  881. {
  882.     // linked objects do not support SetClientSite
  883.  
  884.     return E_NOTIMPL;
  885. }
  886.  
  887. STDMETHODIMP COleServerItem::XOleObject::GetClientSite(
  888.     LPOLECLIENTSITE* ppClientSite)
  889. {
  890.     // linked objects do not support GetClientSite
  891.  
  892.     *ppClientSite = NULL;
  893.     return E_NOTIMPL;
  894. }
  895.  
  896. STDMETHODIMP COleServerItem::XOleObject::SetHostNames(
  897.     LPCOLESTR /*szContainerApp*/, LPCOLESTR /*szContainerObj*/)
  898. {
  899.     // linked objects do not support SetHostNames
  900.  
  901.     return E_NOTIMPL;
  902. }
  903.  
  904. STDMETHODIMP COleServerItem::XOleObject::Close(DWORD /*dwSaveOption*/)
  905. {
  906.     // linked objects do not support close
  907.  
  908.     return E_NOTIMPL;
  909. }
  910.  
  911. STDMETHODIMP COleServerItem::XOleObject::SetMoniker(
  912.     DWORD /*dwWhichMoniker*/, LPMONIKER /*pmk*/)
  913. {
  914.     // linked objects do not support SetMoniker
  915.  
  916.     return E_NOTIMPL;
  917. }
  918.  
  919. STDMETHODIMP COleServerItem::XOleObject::GetMoniker(
  920.     DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER* ppMoniker)
  921. {
  922.     USES_CONVERSION;
  923.  
  924.     METHOD_PROLOGUE_EX(COleServerItem, OleObject)
  925.     ASSERT_VALID(pThis);
  926.  
  927.     COleServerDoc* pDoc = pThis->GetDocument();
  928.     ASSERT_VALID(pDoc);
  929.     ASSERT_KINDOF(COleServerDoc, pDoc);
  930.     ASSERT(ppMoniker != NULL);
  931.     *ppMoniker = NULL;
  932.  
  933.     switch (dwWhichMoniker)
  934.     {
  935.     case OLEWHICHMK_CONTAINER:
  936.         // simply return the moniker of the container document
  937.         *ppMoniker = pDoc->GetMoniker((OLEGETMONIKER)dwAssign);
  938.         break;
  939.  
  940.     case OLEWHICHMK_OBJREL:
  941.         {
  942.             // no relative moniker if no item name
  943.             if (pThis->m_strItemName.IsEmpty())
  944.                 break;
  945.  
  946.             // don't return relative moniker if no document moniker
  947.             LPMONIKER lpMoniker = pDoc->GetMoniker((OLEGETMONIKER)dwAssign);
  948.             if (lpMoniker == NULL)
  949.                 break;
  950.             lpMoniker->Release();   // don't need document moniker
  951.  
  952.             // relative monikers have to handle assignment correctly
  953.             switch (dwAssign)
  954.             {
  955.             case OLEGETMONIKER_TEMPFORUSER:
  956.             case OLEGETMONIKER_ONLYIFTHERE:
  957.             case OLEGETMONIKER_FORCEASSIGN:
  958.                 // create item moniker from name
  959.                 CreateItemMoniker(OLESTDDELIMOLE, T2COLE(pThis->m_strItemName),
  960.                     ppMoniker);
  961.                 break;
  962.  
  963.             case OLEGETMONIKER_UNASSIGN:
  964.                 ASSERT(FALSE);  // should never get UNASSIGN
  965.                 break;
  966.             }
  967.         }
  968.         break;
  969.  
  970.     case OLEWHICHMK_OBJFULL:
  971.         {
  972.             // get each sub-moniker: item & document
  973.             LPMONIKER lpMoniker1, lpMoniker2;
  974.             GetMoniker(dwAssign, OLEWHICHMK_CONTAINER, &lpMoniker1);
  975.             GetMoniker(dwAssign, OLEWHICHMK_OBJREL, &lpMoniker2);
  976.  
  977.             if (lpMoniker1 != NULL && lpMoniker2 != NULL)
  978.             {
  979.                 // create composite from two parts
  980.                 ::CreateGenericComposite(lpMoniker1, lpMoniker2, ppMoniker);
  981.             }
  982.             else if (lpMoniker1 != NULL)
  983.             {
  984.                 // just use container moniker
  985.                 *ppMoniker = lpMoniker1;
  986.                 lpMoniker1 = NULL;
  987.             }
  988.  
  989.             // release sub-monikers
  990.             RELEASE(lpMoniker1);
  991.             RELEASE(lpMoniker2);
  992.         }
  993.         break;
  994.     }
  995.  
  996.     return *ppMoniker == NULL ? E_FAIL : S_OK;
  997. }
  998.  
  999. STDMETHODIMP COleServerItem::XOleObject::InitFromData(
  1000.     LPDATAOBJECT /*pDataObject*/, BOOL /*fCreation*/, DWORD /*dwReserved*/)
  1001. {
  1002.     // linked objects do not support InitFromData
  1003.  
  1004.     return E_NOTIMPL;
  1005. }
  1006.  
  1007. STDMETHODIMP COleServerItem::XOleObject::GetClipboardData(
  1008.     DWORD /*dwReserved*/, LPDATAOBJECT* ppDataObject)
  1009. {
  1010.     METHOD_PROLOGUE_EX(COleServerItem, OleObject)
  1011.     ASSERT_VALID(pThis);
  1012.  
  1013.     *ppDataObject = NULL;
  1014.  
  1015.     SCODE sc;
  1016.     TRY
  1017.     {
  1018.         COleDataSource* pDataSource = pThis->OnGetClipboardData(TRUE, NULL, NULL);
  1019.         ASSERT(pDataSource != NULL);
  1020.  
  1021.         *ppDataObject =
  1022.             (LPDATAOBJECT)pDataSource->GetInterface(&IID_IDataObject);
  1023.         ASSERT(*ppDataObject != NULL);
  1024.         sc = S_OK;
  1025.     }
  1026.     CATCH_ALL(e)
  1027.     {
  1028.         sc = COleException::Process(e);
  1029.         DELETE_EXCEPTION(e);
  1030.     }
  1031.     END_CATCH_ALL
  1032.  
  1033.     return sc;
  1034. }
  1035.  
  1036. STDMETHODIMP COleServerItem::XOleObject::DoVerb(
  1037.     LONG iVerb, LPMSG /*lpmsg*/, LPOLECLIENTSITE /*pActiveSite*/, LONG /*lindex*/,
  1038.     HWND /*hwndParent*/, LPCRECT /*lpPosRect*/)
  1039. {
  1040.     METHOD_PROLOGUE_EX(COleServerItem, OleObject)
  1041.     ASSERT_VALID(pThis);
  1042.  
  1043.     pThis->InternalAddRef();    // protect this object
  1044.  
  1045.     SCODE sc;
  1046.     TRY
  1047.     {
  1048.         pThis->OnDoVerb(iVerb);
  1049.         sc = S_OK;
  1050.     }
  1051.     CATCH_ALL(e)
  1052.     {
  1053.         sc = COleException::Process(e);
  1054.         DELETE_EXCEPTION(e);
  1055.     }
  1056.     END_CATCH_ALL
  1057.  
  1058.     pThis->InternalRelease();   // may 'delete this'
  1059.  
  1060.     return sc;
  1061. }
  1062.  
  1063. STDMETHODIMP COleServerItem::XOleObject::EnumVerbs(
  1064.     IEnumOLEVERB** ppenumOleVerb)
  1065. {
  1066.     METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
  1067.  
  1068.     *ppenumOleVerb = NULL;
  1069.  
  1070.     CLSID clsid;
  1071.     pThis->GetOleObject()->GetUserClassID(&clsid);
  1072.     return OleRegEnumVerbs(clsid, ppenumOleVerb);
  1073. }
  1074.  
  1075. STDMETHODIMP COleServerItem::XOleObject::Update()
  1076. {
  1077.     METHOD_PROLOGUE_EX(COleServerItem, OleObject)
  1078.     ASSERT_VALID(pThis);
  1079.  
  1080.     SCODE sc;
  1081.     TRY
  1082.     {
  1083.         pThis->OnUpdateItems();
  1084.         sc = S_OK;
  1085.     }
  1086.     CATCH_ALL(e)
  1087.     {
  1088.         sc = COleException::Process(e);
  1089.         DELETE_EXCEPTION(e);
  1090.     }
  1091.     END_CATCH_ALL
  1092.  
  1093.     return sc;
  1094. }
  1095.  
  1096. STDMETHODIMP COleServerItem::XOleObject::IsUpToDate()
  1097. {
  1098.     METHOD_PROLOGUE_EX(COleServerItem, OleObject)
  1099.     ASSERT_VALID(pThis);
  1100.  
  1101.     SCODE sc;
  1102.     TRY
  1103.     {
  1104.         sc = pThis->OnQueryUpdateItems() ? S_FALSE : S_OK;
  1105.     }
  1106.     CATCH_ALL(e)
  1107.     {
  1108.         sc = COleException::Process(e);
  1109.         DELETE_EXCEPTION(e);
  1110.     }
  1111.     END_CATCH_ALL
  1112.  
  1113.     return sc;
  1114. }
  1115.  
  1116. STDMETHODIMP COleServerItem::XOleObject::GetUserClassID(CLSID* pClsid)
  1117. {
  1118.     METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
  1119.  
  1120.     COleServerDoc* pDoc = pThis->GetDocument();
  1121.     return pDoc->m_xPersistFile.GetClassID(pClsid);
  1122. }
  1123.  
  1124. STDMETHODIMP COleServerItem::XOleObject::GetUserType(
  1125.     DWORD dwFormOfType, LPOLESTR* ppszUserType)
  1126. {
  1127.     METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
  1128.  
  1129.     *ppszUserType = NULL;
  1130.  
  1131.     CLSID clsid;
  1132.     pThis->GetOleObject()->GetUserClassID(&clsid);
  1133.     return OleRegGetUserType(clsid, dwFormOfType, ppszUserType);
  1134. }
  1135.  
  1136. STDMETHODIMP COleServerItem::XOleObject::SetExtent(
  1137.     DWORD /*dwDrawAspect*/, LPSIZEL /*lpsizel*/)
  1138. {
  1139.     // linked objects do not support SetExtent
  1140.  
  1141.     return E_FAIL;
  1142. }
  1143.  
  1144. STDMETHODIMP COleServerItem::XOleObject::GetExtent(
  1145.     DWORD dwDrawAspect, LPSIZEL lpsizel)
  1146. {
  1147.     METHOD_PROLOGUE_EX(COleServerItem, OleObject)
  1148.     ASSERT_VALID(pThis);
  1149.  
  1150.     SCODE sc = E_INVALIDARG;
  1151.     TRY
  1152.     {
  1153.         // call to get regular windows size
  1154.         CSize size;
  1155.         if (pThis->OnGetExtent((DVASPECT)dwDrawAspect, size))
  1156.         {
  1157.             if (size.cy < 0)
  1158.                 size.cy = -size.cy; // extents are always positive
  1159.             lpsizel->cx = size.cx;
  1160.             lpsizel->cy = size.cy;
  1161.  
  1162.             sc = S_OK;
  1163.         }
  1164.     }
  1165.     CATCH_ALL(e)
  1166.     {
  1167.         sc = COleException::Process(e);
  1168.         DELETE_EXCEPTION(e);
  1169.     }
  1170.     END_CATCH_ALL
  1171.  
  1172.     return sc;
  1173. }
  1174.  
  1175. STDMETHODIMP COleServerItem::XOleObject::Advise(
  1176.     IAdviseSink* pAdvSink, DWORD* pdwConnection)
  1177. {
  1178.     METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
  1179.  
  1180.     *pdwConnection = 0;
  1181.  
  1182.     if (pThis->m_lpOleAdviseHolder == NULL &&
  1183.         ::CreateOleAdviseHolder(&pThis->m_lpOleAdviseHolder) != S_OK)
  1184.     {
  1185.         return E_OUTOFMEMORY;
  1186.     }
  1187.     ASSERT(pThis->m_lpOleAdviseHolder != NULL);
  1188.     return pThis->m_lpOleAdviseHolder->Advise(pAdvSink, pdwConnection);
  1189. }
  1190.  
  1191. STDMETHODIMP COleServerItem::XOleObject::Unadvise(DWORD dwConnection)
  1192. {
  1193.     METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
  1194.  
  1195.     if (pThis->m_lpOleAdviseHolder == NULL)
  1196.         return E_FAIL;
  1197.  
  1198.     ASSERT(pThis->m_lpOleAdviseHolder != NULL);
  1199.     return pThis->m_lpOleAdviseHolder->Unadvise(dwConnection);
  1200. }
  1201.  
  1202. STDMETHODIMP COleServerItem::XOleObject::EnumAdvise(
  1203.     LPENUMSTATDATA* ppenumAdvise)
  1204. {
  1205.     METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
  1206.  
  1207.     *ppenumAdvise = NULL;
  1208.  
  1209.     if (pThis->m_lpOleAdviseHolder == NULL)
  1210.         return E_FAIL;
  1211.  
  1212.     ASSERT(pThis->m_lpOleAdviseHolder != NULL);
  1213.     return pThis->m_lpOleAdviseHolder->EnumAdvise(ppenumAdvise);
  1214. }
  1215.  
  1216. STDMETHODIMP COleServerItem::XOleObject::GetMiscStatus(
  1217.     DWORD dwAspect, DWORD* pdwStatus)
  1218. {
  1219.     METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
  1220.  
  1221.     *pdwStatus = 0;
  1222.  
  1223.     CLSID clsid;
  1224.     pThis->GetOleObject()->GetUserClassID(&clsid);
  1225.     return OleRegGetMiscStatus(clsid, dwAspect, pdwStatus);
  1226. }
  1227.  
  1228. STDMETHODIMP COleServerItem::XOleObject::SetColorScheme(LPLOGPALETTE lpLogpal)
  1229. {
  1230.     METHOD_PROLOGUE_EX(COleServerItem, OleObject)
  1231.     ASSERT_VALID(pThis);
  1232.  
  1233.     SCODE sc = E_NOTIMPL;
  1234.     TRY
  1235.     {
  1236.         // delegate to embedded item
  1237.         if (pThis->OnSetColorScheme(lpLogpal))
  1238.             sc = S_OK;
  1239.     }
  1240.     END_TRY
  1241.  
  1242.     return sc;
  1243. }
  1244.  
  1245. /////////////////////////////////////////////////////////////////////////////
  1246. // COleServerItem::XDataObject
  1247.  
  1248. STDMETHODIMP_(ULONG) COleServerItem::XDataObject::AddRef()
  1249. {
  1250.     METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
  1251.     return pThis->ExternalAddRef();
  1252. }
  1253.  
  1254. STDMETHODIMP_(ULONG) COleServerItem::XDataObject::Release()
  1255. {
  1256.     METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
  1257.     return pThis->ExternalRelease();
  1258. }
  1259.  
  1260. STDMETHODIMP COleServerItem::XDataObject::QueryInterface(
  1261.     REFIID iid, LPVOID* ppvObj)
  1262. {
  1263.     METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
  1264.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  1265. }
  1266.  
  1267. STDMETHODIMP COleServerItem::XDataObject::GetData(
  1268.     LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  1269. {
  1270.     METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
  1271.  
  1272.     return pThis->m_dataSource.m_xDataObject.GetData(lpFormatEtc, lpStgMedium);
  1273. }
  1274.  
  1275. STDMETHODIMP COleServerItem::XDataObject::GetDataHere(
  1276.     LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  1277. {
  1278.     METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
  1279.  
  1280.     return pThis->m_dataSource.m_xDataObject.GetDataHere(
  1281.         lpFormatEtc, lpStgMedium);
  1282. }
  1283.  
  1284. STDMETHODIMP COleServerItem::XDataObject::QueryGetData(LPFORMATETC lpFormatEtc)
  1285. {
  1286.     METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
  1287.  
  1288.     return pThis->m_dataSource.m_xDataObject.QueryGetData(lpFormatEtc);
  1289. }
  1290.  
  1291. STDMETHODIMP COleServerItem::XDataObject::GetCanonicalFormatEtc(
  1292.     LPFORMATETC /*lpFormatEtcIn*/, LPFORMATETC /*lpFormatEtcOut*/)
  1293. {
  1294.     // because we support the target-device (ptd) for server metafile format,
  1295.     //  all members of the FORMATETC are significant.
  1296.  
  1297.     return DATA_S_SAMEFORMATETC;
  1298. }
  1299.  
  1300. STDMETHODIMP COleServerItem::XDataObject::SetData(
  1301.     LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium, BOOL bRelease)
  1302. {
  1303.     METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
  1304.  
  1305.     return pThis->m_dataSource.m_xDataObject.SetData(
  1306.         lpFormatEtc, lpStgMedium, bRelease);
  1307. }
  1308.  
  1309. STDMETHODIMP COleServerItem::XDataObject::EnumFormatEtc(
  1310.     DWORD dwDirection, LPENUMFORMATETC* ppenumFormatEtc)
  1311. {
  1312.     METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
  1313.  
  1314.     return pThis->m_dataSource.m_xDataObject.EnumFormatEtc(
  1315.         dwDirection, ppenumFormatEtc);
  1316. }
  1317.  
  1318. STDMETHODIMP COleServerItem::XDataObject::DAdvise(
  1319.     FORMATETC* pFormatEtc, DWORD advf,
  1320.     LPADVISESINK pAdvSink, DWORD* pdwConnection)
  1321. {
  1322.     METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
  1323.  
  1324.     *pdwConnection = 0;
  1325.  
  1326.     // this special case is for apps like Excel which ask for DAdvise
  1327.     // on CF_METAFILEPICT, DVASPECT_ICON for insert as icon.
  1328.     FORMATETC formatEtc = *pFormatEtc;
  1329.     if (formatEtc.cfFormat == CF_METAFILEPICT &&
  1330.         formatEtc.dwAspect == DVASPECT_ICON)
  1331.     {
  1332.         formatEtc.dwAspect = DVASPECT_CONTENT;
  1333.     }
  1334.  
  1335.     // make sure the FORMATETC is valid
  1336.     if (!(pFormatEtc->cfFormat == 0 && pFormatEtc->ptd == NULL &&
  1337.           pFormatEtc->dwAspect == -1 && pFormatEtc->lindex == -1 &&
  1338.           pFormatEtc->tymed == -1) &&
  1339.         pThis->GetDataObject()->QueryGetData(&formatEtc) != S_OK)
  1340.     {
  1341.         // it is not a wildcard advise -and- the format is not acceptable
  1342.         return DATA_E_FORMATETC;
  1343.     }
  1344.  
  1345.     // create the advise holder, if necessary
  1346.     if (pThis->m_lpDataAdviseHolder == NULL &&
  1347.         CreateDataAdviseHolder(&pThis->m_lpDataAdviseHolder) != S_OK)
  1348.     {
  1349.         return E_OUTOFMEMORY;
  1350.     }
  1351.     ASSERT(pThis->m_lpDataAdviseHolder != NULL);
  1352.     return pThis->m_lpDataAdviseHolder->Advise(this, pFormatEtc, advf,
  1353.         pAdvSink, pdwConnection);
  1354. }
  1355.  
  1356. STDMETHODIMP COleServerItem::XDataObject::DUnadvise(DWORD dwConnection)
  1357. {
  1358.     METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
  1359.  
  1360.     if (pThis->m_lpDataAdviseHolder == NULL)
  1361.         return E_FAIL;
  1362.  
  1363.     ASSERT(pThis->m_lpDataAdviseHolder != NULL);
  1364.     return pThis->m_lpDataAdviseHolder->Unadvise(dwConnection);
  1365. }
  1366.  
  1367. STDMETHODIMP COleServerItem::XDataObject::EnumDAdvise(
  1368.     LPENUMSTATDATA* ppenumAdvise)
  1369. {
  1370.     METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
  1371.  
  1372.     *ppenumAdvise = NULL;
  1373.  
  1374.     if (pThis->m_lpDataAdviseHolder == NULL)
  1375.         return E_FAIL;
  1376.  
  1377.     ASSERT(pThis->m_lpDataAdviseHolder != NULL);
  1378.     return pThis->m_lpDataAdviseHolder->EnumAdvise(ppenumAdvise);
  1379. }
  1380.  
  1381. //////////////////////////////////////////////////////////////////////////////
  1382. // special CItemDataSource implementation
  1383.  
  1384. BOOL COleServerItem::CItemDataSource::OnRenderGlobalData(
  1385.     LPFORMATETC lpFormatEtc, HGLOBAL* phGlobal)
  1386. {
  1387.     ASSERT_VALID(this);
  1388.     COleServerItem* pItem = (COleServerItem*)
  1389.         ((BYTE*)this - offsetof(COleServerItem, m_dataSource));
  1390.  
  1391.     return pItem->OnRenderGlobalData(lpFormatEtc, phGlobal);
  1392.         // Note: COleDataSource has no implementation
  1393. }
  1394.  
  1395. BOOL COleServerItem::CItemDataSource::OnRenderFileData(
  1396.     LPFORMATETC lpFormatEtc, CFile* pFile)
  1397. {
  1398.     ASSERT_VALID(this);
  1399.     COleServerItem* pItem = (COleServerItem*)
  1400.         ((BYTE*)this - offsetof(COleServerItem, m_dataSource));
  1401.  
  1402.     return pItem->OnRenderFileData(lpFormatEtc, pFile);
  1403.         // Note: COleDataSource has no implementation
  1404. }
  1405.  
  1406. BOOL COleServerItem::CItemDataSource::OnRenderData(
  1407.     LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  1408. {
  1409.     ASSERT_VALID(this);
  1410.     COleServerItem* pItem = (COleServerItem*)
  1411.         ((BYTE*)this - offsetof(COleServerItem, m_dataSource));
  1412.  
  1413.     if (pItem->OnRenderData(lpFormatEtc, lpStgMedium))
  1414.         return TRUE;
  1415.  
  1416.     return COleDataSource::OnRenderData(lpFormatEtc, lpStgMedium);
  1417. }
  1418.  
  1419. BOOL COleServerItem::CItemDataSource::OnSetData(
  1420.     LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium, BOOL bRelease)
  1421. {
  1422.     ASSERT_VALID(this);
  1423.     COleServerItem* pItem = (COleServerItem*)
  1424.         ((BYTE*)this - offsetof(COleServerItem, m_dataSource));
  1425.  
  1426.     return pItem->OnSetData(lpFormatEtc, lpStgMedium, bRelease);
  1427.         // Note: COleDataSource has no implementation
  1428. }
  1429.  
  1430. //////////////////////////////////////////////////////////////////////////////
  1431. // COleServerItem Diagnostics
  1432.  
  1433. #ifdef _DEBUG
  1434. void COleServerItem::AssertValid() const
  1435. {
  1436.     CDocItem::AssertValid();
  1437.  
  1438.     // must be attached to a document
  1439.     ASSERT(m_pDocument != NULL);
  1440.     m_dataSource.AssertValid();
  1441. }
  1442.  
  1443. void COleServerItem::Dump(CDumpContext& dc) const
  1444. {
  1445.     CDocItem::Dump(dc);
  1446.  
  1447.     dc << "m_bNeedUnlock = " << m_bNeedUnlock;
  1448.     dc << "\nm_bAutoDelete = " << m_bAutoDelete;
  1449.     dc << "\nm_strItemName = " << m_strItemName;
  1450.     dc << "\nm_lpOleAdviseHolder = " << m_lpOleAdviseHolder;
  1451.     dc << "\nm_lpDataAdviseHolder = " << m_lpDataAdviseHolder;
  1452.     dc << "\nwith m_dataSource: " << &m_dataSource;
  1453. }
  1454. #endif
  1455.  
  1456. /////////////////////////////////////////////////////////////////////////////
  1457.