mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1456 lines
35 KiB
1456 lines
35 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
|
|
#include "stdafx.h"
|
|
|
|
#ifdef AFX_OLE4_SEG
|
|
#pragma code_seg(AFX_OLE4_SEG)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// COleServerItem implementation
|
|
|
|
COleServerItem::COleServerItem(COleServerDoc* pServerDoc, BOOL bAutoDelete)
|
|
{
|
|
if (pServerDoc != NULL)
|
|
ASSERT_VALID(pServerDoc);
|
|
|
|
m_dwRef = 0; // always start in disconnected state
|
|
m_bAutoDelete = bAutoDelete;
|
|
m_bNeedUnlock = FALSE;
|
|
|
|
// initially, item does not have an extent
|
|
m_sizeExtent.cx = 0;
|
|
m_sizeExtent.cy = 0;
|
|
|
|
// initialize advise holders
|
|
m_lpOleAdviseHolder = NULL;
|
|
m_lpDataAdviseHolder = NULL;
|
|
|
|
// add presentation formats to the data source
|
|
m_dataSource.m_nGrowBy = 1;
|
|
FORMATETC formatEtc;
|
|
formatEtc.ptd = NULL;
|
|
formatEtc.dwAspect = DVASPECT_CONTENT;
|
|
formatEtc.lindex = -1;
|
|
|
|
// by default, a COleServerItem supports CF_METAFILEPICT
|
|
formatEtc.cfFormat = CF_METAFILEPICT;
|
|
formatEtc.tymed = TYMED_MFPICT;
|
|
m_dataSource.DelayRenderData(0, &formatEtc);
|
|
|
|
// add item to server document
|
|
m_pDocument = NULL;
|
|
if (pServerDoc != NULL)
|
|
pServerDoc->AddItem(this);
|
|
ASSERT(m_pDocument == pServerDoc);
|
|
|
|
AfxOleLockApp();
|
|
}
|
|
|
|
COleServerItem::~COleServerItem()
|
|
{
|
|
m_bAutoDelete = FALSE; // no delete during destructor
|
|
|
|
// release any advise holders
|
|
RELEASE(m_lpOleAdviseHolder);
|
|
RELEASE(m_lpDataAdviseHolder);
|
|
|
|
ExternalDisconnect();
|
|
|
|
// disconnect from the document
|
|
COleServerDoc* pDoc = GetDocument();
|
|
if (pDoc != NULL)
|
|
{
|
|
// remove external lock from it
|
|
if (m_bNeedUnlock)
|
|
{
|
|
pDoc->LockExternal(FALSE, TRUE);
|
|
m_bNeedUnlock = FALSE;
|
|
}
|
|
|
|
// reset m_pEmbeddedItem if destroying embedded item
|
|
if (pDoc->m_pEmbeddedItem == this)
|
|
pDoc->m_pEmbeddedItem = NULL;
|
|
|
|
// remove from list
|
|
pDoc->RemoveItem(this);
|
|
}
|
|
|
|
// cleanup any references
|
|
AfxOleUnlockApp();
|
|
}
|
|
|
|
BOOL COleServerItem::IsBlank() const
|
|
{
|
|
// server items are blank in order to keep them from serializing when
|
|
// COleDocument::Serialize is called.
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COleServerItem::IsConnected() const
|
|
{
|
|
// if item is connected in any way, return TRUE
|
|
if (m_dwRef != 0)
|
|
return TRUE;
|
|
|
|
// otherwise check if embedded item and document is connected
|
|
if (!IsLinkedItem() && GetDocument()->m_lpClientSite != NULL)
|
|
return TRUE;
|
|
|
|
return FALSE; // not connected
|
|
}
|
|
|
|
void COleServerItem::NotifyClient(OLE_NOTIFICATION nCode, DWORD dwParam)
|
|
{
|
|
switch (nCode)
|
|
{
|
|
// IDataObject notifications
|
|
case OLE_CHANGED:
|
|
if (m_lpDataAdviseHolder != NULL)
|
|
m_lpDataAdviseHolder->SendOnDataChange(GetDataObject(), dwParam, 0);
|
|
break;
|
|
|
|
// IOleObject notifications
|
|
case OLE_SAVED:
|
|
if (m_lpOleAdviseHolder != NULL)
|
|
m_lpOleAdviseHolder->SendOnSave();
|
|
break;
|
|
case OLE_CLOSED:
|
|
if (m_lpOleAdviseHolder != NULL)
|
|
m_lpOleAdviseHolder->SendOnClose();
|
|
break;
|
|
case OLE_RENAMED:
|
|
if (m_lpOleAdviseHolder != NULL)
|
|
{
|
|
// Note: the moniker should already be updated for this to work
|
|
LPMONIKER lpMoniker = (LPMONIKER)dwParam;
|
|
m_lpOleAdviseHolder->SendOnRename(lpMoniker);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ASSERT(FALSE);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Helpers for getting commonly used interfaces through interface map
|
|
|
|
LPDATAOBJECT COleServerItem::GetDataObject()
|
|
{
|
|
LPDATAOBJECT lpDataObject =
|
|
(LPDATAOBJECT)GetInterface(&IID_IDataObject);
|
|
ASSERT(lpDataObject != NULL);
|
|
return lpDataObject;
|
|
}
|
|
|
|
LPOLEOBJECT COleServerItem::GetOleObject()
|
|
{
|
|
LPOLEOBJECT lpOleObject =
|
|
(LPOLEOBJECT)GetInterface(&IID_IOleObject);
|
|
ASSERT(lpOleObject != NULL);
|
|
return lpOleObject;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerItem overrides
|
|
|
|
BOOL COleServerItem::OnQueryUpdateItems()
|
|
{
|
|
COleDocument* pDoc = GetDocument();
|
|
ASSERT_VALID(pDoc);
|
|
|
|
// update all of the embedded objects
|
|
POSITION pos = pDoc->GetStartPosition();
|
|
COleClientItem* pItem;
|
|
while ((pItem = pDoc->GetNextClientItem(pos)) != NULL)
|
|
{
|
|
// if any item is out-of-date, then this item is out-of-date
|
|
if (pItem->m_lpObject->IsUpToDate() != NULL)
|
|
return TRUE; // update needed
|
|
}
|
|
return FALSE; // update not needed
|
|
}
|
|
|
|
void COleServerItem::OnUpdateItems()
|
|
{
|
|
COleDocument* pDoc = GetDocument();
|
|
ASSERT_VALID(pDoc);
|
|
|
|
// update all of the embedded objects
|
|
POSITION pos = pDoc->GetStartPosition();
|
|
COleClientItem* pItem;
|
|
while ((pItem = pDoc->GetNextClientItem(pos)) != NULL)
|
|
{
|
|
// update any out-of-date item
|
|
if (pItem->m_lpObject->IsUpToDate() != NULL)
|
|
pItem->m_lpObject->Update();
|
|
}
|
|
}
|
|
|
|
BOOL COleServerItem::OnSetExtent(DVASPECT dwDrawAspect, const CSize& size)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
if (dwDrawAspect == DVASPECT_CONTENT)
|
|
{
|
|
m_sizeExtent = size; // simply remember the extent
|
|
return TRUE;
|
|
}
|
|
return FALSE; // not implemented for that dwDrawAspect
|
|
}
|
|
|
|
BOOL COleServerItem::OnGetExtent(DVASPECT /*dwDrawAspect*/, CSize& rSize)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidAddress(&rSize, sizeof(CSize)));
|
|
|
|
// the default implementation doesn't know what the extent is
|
|
|
|
rSize.cx = 0;
|
|
rSize.cy = 0;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void COleServerItem::OnDoVerb(LONG iVerb)
|
|
{
|
|
switch (iVerb)
|
|
{
|
|
// open - maps to OnOpen
|
|
case OLEIVERB_OPEN:
|
|
case -OLEIVERB_OPEN-1: // allows positive OLEIVERB_OPEN-1 in registry
|
|
OnOpen();
|
|
break;
|
|
|
|
// primary, show, and unknown map to OnShow
|
|
case OLEIVERB_PRIMARY: // OLEIVERB_PRIMARY is 0 and "Edit" in registry
|
|
case OLEIVERB_SHOW:
|
|
OnShow();
|
|
break;
|
|
|
|
// hide maps to OnHide
|
|
case OLEIVERB_HIDE:
|
|
case -OLEIVERB_HIDE-1: // allows positive OLEIVERB_HIDE-1 in registry
|
|
OnHide();
|
|
break;
|
|
|
|
default:
|
|
// negative verbs not understood should return E_NOTIMPL
|
|
if (iVerb < 0)
|
|
AfxThrowOleException(E_NOTIMPL);
|
|
|
|
// positive verb not processed --
|
|
// according to OLE spec, primary verb should be executed
|
|
// instead.
|
|
OnDoVerb(OLEIVERB_PRIMARY);
|
|
|
|
// also, OLEOBJ_S_INVALIDVERB should be returned.
|
|
AfxThrowOleException(OLEOBJ_S_INVALIDVERB);
|
|
}
|
|
}
|
|
|
|
BOOL COleServerItem::OnDrawEx(CDC* pDC, DVASPECT nDrawAspect, CSize& rSize)
|
|
{
|
|
ASSERT_VALID(pDC);
|
|
ASSERT(AfxIsValidAddress(&rSize, sizeof(CSize)));
|
|
|
|
if (nDrawAspect != DVASPECT_CONTENT)
|
|
return FALSE;
|
|
|
|
return OnDraw(pDC, rSize);
|
|
}
|
|
|
|
void COleServerItem::OnShow()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// attempt in place activation (if not supported, fall back on "Open")
|
|
COleServerDoc* pDoc = GetDocument();
|
|
if (!pDoc->ActivateInPlace())
|
|
{
|
|
// by default OnShow() maps to OnOpen() if in-place activation
|
|
// not supported
|
|
OnOpen();
|
|
}
|
|
}
|
|
|
|
void COleServerItem::OnOpen()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// default implementation shows the document
|
|
COleServerDoc* pDoc = GetDocument();
|
|
ASSERT(pDoc != NULL);
|
|
pDoc->OnShowDocument(TRUE);
|
|
}
|
|
|
|
void COleServerItem::OnHide()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// default implementation hides the document
|
|
COleServerDoc* pDoc = GetDocument();
|
|
ASSERT_VALID(pDoc);
|
|
pDoc->OnShowDocument(FALSE);
|
|
}
|
|
|
|
BOOL COleServerItem::GetMetafileData(LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
|
|
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
|
|
ASSERT(lpStgMedium->tymed == TYMED_NULL); // GetDataHere not valid
|
|
ASSERT(lpStgMedium->pUnkForRelease == NULL);
|
|
|
|
// medium must be TYMED_MFPICT -- cannot fill in existing HGLOBAL
|
|
if (!(lpFormatEtc->tymed & TYMED_MFPICT) || lpStgMedium->hGlobal != NULL)
|
|
return FALSE;
|
|
|
|
// create appropriate memory metafile DC
|
|
CMetaFileDC dc;
|
|
if (!dc.Create())
|
|
return FALSE;
|
|
|
|
// create attribute DC according to lpFormatEtc->ptd
|
|
HDC hAttribDC = _AfxOleCreateDC(lpFormatEtc->ptd);
|
|
if (hAttribDC == NULL)
|
|
return FALSE;
|
|
dc.SetAttribDC(hAttribDC);
|
|
|
|
// Paint directly into the metafile.
|
|
CSize size(0, 0);
|
|
BOOL bResult = OnDrawEx(&dc, (DVASPECT)lpFormatEtc->dwAspect, size);
|
|
|
|
// attribute DC is no longer necessary
|
|
dc.SetAttribDC(NULL);
|
|
::DeleteDC(hAttribDC);
|
|
|
|
if (!bResult)
|
|
{
|
|
#ifdef _DEBUG
|
|
if (afxTraceFlags & traceOle)
|
|
TRACE0("calling COleServerItem::OnDrawEx()failed.\n");
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
HMETAFILE hMF = dc.Close();
|
|
if (hMF == NULL)
|
|
return FALSE;
|
|
|
|
HGLOBAL hPict;
|
|
if ((hPict =
|
|
::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT))) == NULL)
|
|
{
|
|
DeleteMetaFile(hMF);
|
|
return FALSE;
|
|
}
|
|
LPMETAFILEPICT lpPict;
|
|
if ((lpPict = (LPMETAFILEPICT)::GlobalLock(hPict)) == NULL)
|
|
{
|
|
DeleteMetaFile(hMF);
|
|
::GlobalFree(hPict);
|
|
return FALSE;
|
|
}
|
|
|
|
// set the metafile size
|
|
lpPict->mm = MM_ANISOTROPIC;
|
|
lpPict->hMF = hMF;
|
|
if (size.cx == 0 && size.cy == 0 &&
|
|
!OnGetExtent((DVASPECT)lpFormatEtc->dwAspect, size))
|
|
{
|
|
TRACE0("Warning: OnGetExtent failed during OnDrawEx --\n");
|
|
TRACE0("\tpresentation metafile may be badly formed!\n");
|
|
}
|
|
lpPict->xExt = size.cx;
|
|
lpPict->yExt = size.cy; // HIMETRIC height
|
|
if (lpPict->yExt < 0)
|
|
{
|
|
TRACE0("Warning: HIMETRIC natural size is negative.\n");
|
|
lpPict->yExt = -lpPict->yExt; // backward compatibility fix
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
if (lpPict->xExt == 0 || lpPict->yExt == 0)
|
|
{
|
|
// usually the natural extent is set to something interesting
|
|
TRACE0("Warning: COleServerItem has no natural size --\n");
|
|
TRACE0("\twill not work with some apps like MS Write.\n");
|
|
}
|
|
#endif
|
|
|
|
// return the medium with the hGlobal to the METAFILEPICT
|
|
::GlobalUnlock(hPict);
|
|
lpStgMedium->hGlobal = hPict;
|
|
lpStgMedium->tymed = TYMED_MFPICT;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COleServerItem::OnSetColorScheme(const LOGPALETTE* /*lpLogPalette*/)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
return FALSE; // default does nothing
|
|
}
|
|
|
|
BOOL COleServerItem::OnInitFromData(
|
|
COleDataObject* /*pDataObject*/, BOOL /*bCreation*/)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
AfxThrowOleException(E_NOTIMPL);
|
|
return FALSE;
|
|
}
|
|
|
|
void COleServerItem::CopyToClipboard(BOOL bIncludeLink)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
COleDataSource* pDataSource = OnGetClipboardData(bIncludeLink, NULL, NULL);
|
|
|
|
// put it on the clipboard
|
|
pDataSource->SetClipboard();
|
|
}
|
|
|
|
COleDataSource* COleServerItem::OnGetClipboardData(BOOL bIncludeLink,
|
|
LPPOINT lpOffset, LPSIZE lpSize)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
COleDataSource* pDataSource = new COleDataSource;
|
|
TRY
|
|
{
|
|
GetClipboardData(pDataSource, bIncludeLink, lpOffset, lpSize);
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
delete pDataSource;
|
|
THROW_LAST();
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
ASSERT_VALID(pDataSource);
|
|
return pDataSource;
|
|
}
|
|
|
|
DROPEFFECT COleServerItem::DoDragDrop(LPCRECT lpItemRect, CPoint ptOffset,
|
|
BOOL bIncludeLink, DWORD dwEffects, LPCRECT lpRectStartDrag)
|
|
{
|
|
ASSERT(AfxIsValidAddress(lpItemRect, sizeof(RECT)));
|
|
ASSERT_VALID(this);
|
|
|
|
ASSERT_VALID(this);
|
|
|
|
DROPEFFECT dropEffect = DROPEFFECT_NONE;
|
|
COleDataSource *pDataSource = NULL;
|
|
TRY
|
|
{
|
|
// get clipboard data for this item
|
|
CSize sizeItem(
|
|
lpItemRect->right - lpItemRect->left,
|
|
lpItemRect->bottom - lpItemRect->top);
|
|
pDataSource = OnGetClipboardData(bIncludeLink, &ptOffset, &sizeItem);
|
|
|
|
// add DROPEFFECT_LINK if link source is available
|
|
LPDATAOBJECT lpDataObject = (LPDATAOBJECT)
|
|
pDataSource->GetInterface(&IID_IDataObject);
|
|
ASSERT(lpDataObject != NULL);
|
|
FORMATETC formatEtc;
|
|
formatEtc.cfFormat = (CLIPFORMAT)_oleData.cfLinkSource;
|
|
formatEtc.ptd = NULL;
|
|
formatEtc.dwAspect = DVASPECT_CONTENT;
|
|
formatEtc.lindex = -1;
|
|
formatEtc.tymed = (TYMED)-1;
|
|
if (lpDataObject->QueryGetData(&formatEtc) == S_OK)
|
|
dwEffects |= DROPEFFECT_LINK;
|
|
|
|
// calculate default sensitivity rectangle
|
|
CRect rectDrag;
|
|
if (lpRectStartDrag == NULL)
|
|
{
|
|
rectDrag.SetRect(lpItemRect->left, lpItemRect->top, lpItemRect->left,
|
|
lpItemRect->top);
|
|
lpRectStartDrag = &rectDrag;
|
|
}
|
|
|
|
// do drag drop operation
|
|
dropEffect = pDataSource->DoDragDrop(dwEffects, lpRectStartDrag);
|
|
pDataSource->InternalRelease();
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
if (pDataSource != NULL)
|
|
pDataSource->InternalRelease();
|
|
|
|
THROW_LAST();
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return dropEffect;
|
|
}
|
|
|
|
void COleServerItem::GetClipboardData(COleDataSource* pDataSource,
|
|
BOOL bIncludeLink, LPPOINT lpOffset, LPSIZE lpSize)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT_VALID(pDataSource);
|
|
ASSERT(lpOffset == NULL ||
|
|
AfxIsValidAddress(lpOffset, sizeof(POINT), FALSE));
|
|
|
|
// add CF_EMBEDDEDOBJECT by creating memory storage copy of the object
|
|
STGMEDIUM stgMedium;
|
|
GetEmbedSourceData(&stgMedium);
|
|
pDataSource->CacheData((CLIPFORMAT)_oleData.cfEmbedSource, &stgMedium);
|
|
|
|
// add CF_OBJECTDESCRIPTOR
|
|
GetObjectDescriptorData(lpOffset, lpSize, &stgMedium);
|
|
pDataSource->CacheData((CLIPFORMAT)_oleData.cfObjectDescriptor,
|
|
&stgMedium);
|
|
|
|
// add any presentation entries/conversion formats that the item
|
|
// can produce.
|
|
AddOtherClipboardData(pDataSource);
|
|
|
|
// add CF_LINKSOURCE if supporting links to pseudo objects
|
|
if (bIncludeLink && GetLinkSourceData(&stgMedium))
|
|
{
|
|
pDataSource->CacheData((CLIPFORMAT)_oleData.cfLinkSource, &stgMedium);
|
|
|
|
// add CF_LINKSOURCEDESCRIPTOR
|
|
GetObjectDescriptorData(lpOffset, lpSize, &stgMedium);
|
|
pDataSource->CacheData((CLIPFORMAT)_oleData.cfLinkSourceDescriptor,
|
|
&stgMedium);
|
|
}
|
|
}
|
|
|
|
void COleServerItem::GetEmbedSourceData(LPSTGMEDIUM lpStgMedium)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
|
|
|
|
LPLOCKBYTES lpLockBytes;
|
|
SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
|
|
if (sc != S_OK)
|
|
AfxThrowOleException(sc);
|
|
ASSERT(lpLockBytes != NULL);
|
|
|
|
LPSTORAGE lpStorage;
|
|
sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
|
|
STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &lpStorage);
|
|
if (sc != S_OK)
|
|
{
|
|
VERIFY(lpLockBytes->Release() == 0);
|
|
AfxThrowOleException(sc);
|
|
}
|
|
ASSERT(lpStorage != NULL);
|
|
|
|
// setup for save copy as
|
|
COleServerDoc* pDoc = GetDocument();
|
|
pDoc->m_bSameAsLoad = FALSE;
|
|
pDoc->m_bRemember = FALSE;
|
|
|
|
TRY
|
|
{
|
|
OnSaveEmbedding(lpStorage);
|
|
pDoc->CommitItems(FALSE);
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
// release storage and lock bytes
|
|
VERIFY(lpStorage->Release() == 0);
|
|
VERIFY(lpLockBytes->Release() == 0);
|
|
pDoc->m_bSameAsLoad = TRUE;
|
|
pDoc->m_bRemember = TRUE;
|
|
THROW_LAST();
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
pDoc->m_bSameAsLoad = TRUE;
|
|
pDoc->m_bRemember = TRUE;
|
|
lpLockBytes->Release();
|
|
|
|
// add it to the data source
|
|
lpStgMedium->tymed = TYMED_ISTORAGE;
|
|
lpStgMedium->pstg = lpStorage;
|
|
lpStgMedium->pUnkForRelease = NULL;
|
|
}
|
|
|
|
void COleServerItem::AddOtherClipboardData(COleDataSource* pDataSource)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT_VALID(pDataSource);
|
|
|
|
// get IEnumFORMATETC interface for the IDataObject
|
|
LPDATAOBJECT lpDataObject = GetDataObject();
|
|
LPENUMFORMATETC lpEnumFORMATETC;
|
|
if (lpDataObject->EnumFormatEtc(DATADIR_GET, &lpEnumFORMATETC) != S_OK)
|
|
return;
|
|
ASSERT(lpEnumFORMATETC != NULL);
|
|
|
|
// get all formats that the object will give us
|
|
FORMATETC formatEtc;
|
|
while (lpEnumFORMATETC->Next(1, &formatEtc, NULL) == S_OK)
|
|
{
|
|
STGMEDIUM stgMedium;
|
|
if (lpDataObject->GetData(&formatEtc, &stgMedium) != S_OK)
|
|
{
|
|
// data is not available
|
|
CoTaskMemFree(formatEtc.ptd);
|
|
}
|
|
else if (stgMedium.pUnkForRelease != NULL)
|
|
{
|
|
// don't cache data with pUnkForRelease != NULL
|
|
::ReleaseStgMedium(&stgMedium);
|
|
CoTaskMemFree(formatEtc.ptd);
|
|
}
|
|
else
|
|
{
|
|
// cache the data (now we own the stgMedium)
|
|
pDataSource->CacheData(0, &stgMedium, &formatEtc);
|
|
}
|
|
}
|
|
|
|
// cleanup
|
|
lpEnumFORMATETC->Release();
|
|
}
|
|
|
|
LPMONIKER COleServerItem::GetMoniker(OLEGETMONIKER nAssign)
|
|
{
|
|
// get IOleObject interface for this item
|
|
LPOLEOBJECT lpOleObject = GetOleObject();
|
|
ASSERT(lpOleObject != NULL);
|
|
|
|
// get moniker from OLE object
|
|
LPMONIKER lpMoniker = NULL;
|
|
lpOleObject->GetMoniker(nAssign, OLEWHICHMK_OBJFULL, &lpMoniker);
|
|
return lpMoniker;
|
|
}
|
|
|
|
BOOL COleServerItem::GetLinkSourceData(LPSTGMEDIUM lpStgMedium)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
|
|
|
|
LPOLEOBJECT lpOleObject = GetOleObject();
|
|
ASSERT(lpOleObject != NULL);
|
|
|
|
// get moniker from ole object
|
|
LPMONIKER lpMoniker;
|
|
SCODE sc = lpOleObject->GetMoniker(OLEGETMONIKER_TEMPFORUSER,
|
|
OLEWHICHMK_OBJFULL, &lpMoniker);
|
|
if (sc != S_OK)
|
|
{
|
|
TRACE0("Warning: unable to get moniker for object.\n");
|
|
return FALSE;
|
|
}
|
|
ASSERT(lpMoniker != NULL);
|
|
|
|
// create a memory based stream to write the moniker to
|
|
LPSTREAM lpStream;
|
|
if (::CreateStreamOnHGlobal(NULL, TRUE, &lpStream) != S_OK)
|
|
{
|
|
lpMoniker->Release();
|
|
AfxThrowMemoryException();
|
|
}
|
|
ASSERT(lpStream != NULL);
|
|
|
|
// write the moniker to the stream, and add it to the clipboard
|
|
sc = ::OleSaveToStream(lpMoniker, lpStream);
|
|
lpMoniker->Release();
|
|
if (sc != S_OK)
|
|
{
|
|
lpStream->Release();
|
|
AfxThrowOleException(sc);
|
|
}
|
|
|
|
// write the class ID of the document to the stream as well
|
|
COleLinkingDoc* pDoc = GetDocument();
|
|
ASSERT(pDoc->m_pFactory != NULL);
|
|
sc = WriteClassStm(lpStream, pDoc->m_pFactory->GetClassID());
|
|
if (sc != S_OK)
|
|
{
|
|
lpStream->Release();
|
|
AfxThrowOleException(sc);
|
|
}
|
|
|
|
// setup the STGMEDIUM
|
|
lpStgMedium->tymed = TYMED_ISTREAM;
|
|
lpStgMedium->pstm = lpStream;
|
|
lpStgMedium->pUnkForRelease = NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
void COleServerItem::GetObjectDescriptorData(
|
|
LPPOINT lpOffset, LPSIZE lpSize, LPSTGMEDIUM lpStgMedium)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
|
|
ASSERT(lpOffset == NULL ||
|
|
AfxIsValidAddress(lpOffset, sizeof(POINT), FALSE));
|
|
|
|
LPOLEOBJECT lpOleObject = GetOleObject();
|
|
ASSERT(lpOleObject != NULL);
|
|
|
|
// get the object descriptor for the IOleObject
|
|
POINTL pointl = { 0, 0 };
|
|
if (lpOffset != NULL)
|
|
{
|
|
CSize ptOffset(lpOffset->x, lpOffset->y);
|
|
#ifndef _MAC
|
|
((CDC*)NULL)->DPtoHIMETRIC(&ptOffset);
|
|
#endif
|
|
pointl.x = ptOffset.cx;
|
|
pointl.y = ptOffset.cy;
|
|
}
|
|
SIZEL sizel;
|
|
if (lpSize != NULL)
|
|
{
|
|
sizel.cx = lpSize->cx;
|
|
sizel.cy = lpSize->cy;
|
|
#ifndef _MAC
|
|
((CDC*)NULL)->DPtoHIMETRIC(&sizel);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
sizel.cx = 0;
|
|
sizel.cy = 0;
|
|
}
|
|
|
|
InterlockedIncrement(&m_dwRef); // protect against destruction during this call
|
|
HGLOBAL hGlobal = _AfxOleGetObjectDescriptorData(
|
|
lpOleObject, NULL, DVASPECT_CONTENT, pointl, &sizel);
|
|
InterlockedDecrement(&m_dwRef);
|
|
|
|
if (hGlobal == NULL)
|
|
AfxThrowMemoryException();
|
|
|
|
// setup the STGMEDIUM
|
|
lpStgMedium->tymed = TYMED_HGLOBAL;
|
|
lpStgMedium->hGlobal = hGlobal;
|
|
lpStgMedium->pUnkForRelease = NULL;
|
|
}
|
|
|
|
void COleServerItem::OnSaveEmbedding(LPSTORAGE lpStorage)
|
|
{
|
|
ASSERT(lpStorage != NULL);
|
|
|
|
// always (logically) a "File.Save Copy As" operation
|
|
COleServerDoc* pDoc = GetDocument();
|
|
LPSTORAGE lpOrigStg = pDoc->m_lpRootStg;
|
|
pDoc->m_lpRootStg = lpStorage;
|
|
|
|
TRY
|
|
{
|
|
ASSERT(pDoc->m_lpRootStg != NULL);
|
|
pDoc->SaveToStorage(this); // use helper to serialize to storage
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
// save as failed: re-attach original storage
|
|
pDoc->m_lpRootStg = lpOrigStg;
|
|
THROW_LAST();
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
// re-attach original storage
|
|
pDoc->m_lpRootStg = lpOrigStg;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerItem data-object callback default implementation
|
|
|
|
BOOL COleServerItem::OnRenderGlobalData(
|
|
LPFORMATETC /*lpFormatEtc*/, HGLOBAL* /*phGlobal*/)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
return FALSE; // default does nothing
|
|
}
|
|
|
|
BOOL COleServerItem::OnRenderFileData(
|
|
LPFORMATETC /*lpFormatEtc*/, CFile* /*pFile*/)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
return FALSE; // default does nothing
|
|
}
|
|
|
|
BOOL COleServerItem::OnRenderData(LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
|
|
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
|
|
|
|
// default implementation does not support extended layout
|
|
if (lpFormatEtc->lindex != -1)
|
|
return FALSE;
|
|
|
|
// default implementation supports both types of metafiles
|
|
if (lpFormatEtc->cfFormat == CF_METAFILEPICT)
|
|
return GetMetafileData(lpFormatEtc, lpStgMedium);
|
|
|
|
return FALSE; // cfFormat not supported
|
|
}
|
|
|
|
BOOL COleServerItem::OnSetData(
|
|
LPFORMATETC /*lpFormatEtc*/, LPSTGMEDIUM /*lpStgMedium*/, BOOL /*bRelease*/)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
return FALSE; // default does nothing
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerItem OLE interface implementation
|
|
|
|
BEGIN_INTERFACE_MAP(COleServerItem, CDocItem)
|
|
INTERFACE_PART(COleServerItem, IID_IOleObject, OleObject)
|
|
INTERFACE_PART(COleServerItem, IID_IDataObject, DataObject)
|
|
END_INTERFACE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerItem::XOleObject
|
|
|
|
STDMETHODIMP_(ULONG) COleServerItem::XOleObject::AddRef()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
|
|
return pThis->ExternalAddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) COleServerItem::XOleObject::Release()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
|
|
return pThis->ExternalRelease();
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::QueryInterface(
|
|
REFIID iid, LPVOID* ppvObj)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
|
|
return pThis->ExternalQueryInterface(&iid, ppvObj);
|
|
}
|
|
|
|
// COleServerItem has special Release semantics. In particular, the item
|
|
// is only deleted from memory if m_bAutoDelete is TRUE.
|
|
// Also, it unlocks the document if the reference count reaches zero.
|
|
|
|
void COleServerItem::OnFinalRelease()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
COleServerDoc* pDoc = GetDocument();
|
|
ASSERT_VALID(pDoc);
|
|
|
|
pDoc->InternalAddRef(); // make document stable
|
|
|
|
// if connected to a document -- remove external lock from it
|
|
if (m_bNeedUnlock)
|
|
{
|
|
pDoc->LockExternal(FALSE, TRUE);
|
|
m_bNeedUnlock = FALSE;
|
|
}
|
|
|
|
// delete this item if no longer needed
|
|
if (m_bAutoDelete)
|
|
delete this;
|
|
|
|
// release artificial reference (may destroy the document)
|
|
pDoc->InternalRelease();
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::SetClientSite(
|
|
LPOLECLIENTSITE /*pClientSite*/)
|
|
{
|
|
// linked objects do not support SetClientSite
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::GetClientSite(
|
|
LPOLECLIENTSITE* ppClientSite)
|
|
{
|
|
// linked objects do not support GetClientSite
|
|
|
|
*ppClientSite = NULL;
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::SetHostNames(
|
|
LPCOLESTR /*szContainerApp*/, LPCOLESTR /*szContainerObj*/)
|
|
{
|
|
// linked objects do not support SetHostNames
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::Close(DWORD /*dwSaveOption*/)
|
|
{
|
|
// linked objects do not support close
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::SetMoniker(
|
|
DWORD /*dwWhichMoniker*/, LPMONIKER /*pmk*/)
|
|
{
|
|
// linked objects do not support SetMoniker
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::GetMoniker(
|
|
DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER* ppMoniker)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
METHOD_PROLOGUE_EX(COleServerItem, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
COleServerDoc* pDoc = pThis->GetDocument();
|
|
ASSERT_VALID(pDoc);
|
|
ASSERT_KINDOF(COleServerDoc, pDoc);
|
|
ASSERT(ppMoniker != NULL);
|
|
*ppMoniker = NULL;
|
|
|
|
switch (dwWhichMoniker)
|
|
{
|
|
case OLEWHICHMK_CONTAINER:
|
|
// simply return the moniker of the container document
|
|
*ppMoniker = pDoc->GetMoniker((OLEGETMONIKER)dwAssign);
|
|
break;
|
|
|
|
case OLEWHICHMK_OBJREL:
|
|
{
|
|
// no relative moniker if no item name
|
|
if (pThis->m_strItemName.IsEmpty())
|
|
break;
|
|
|
|
// don't return relative moniker if no document moniker
|
|
LPMONIKER lpMoniker = pDoc->GetMoniker((OLEGETMONIKER)dwAssign);
|
|
if (lpMoniker == NULL)
|
|
break;
|
|
lpMoniker->Release(); // don't need document moniker
|
|
|
|
// relative monikers have to handle assignment correctly
|
|
switch (dwAssign)
|
|
{
|
|
case OLEGETMONIKER_TEMPFORUSER:
|
|
case OLEGETMONIKER_ONLYIFTHERE:
|
|
case OLEGETMONIKER_FORCEASSIGN:
|
|
// create item moniker from name
|
|
CreateItemMoniker(OLESTDDELIMOLE, T2COLE(pThis->m_strItemName),
|
|
ppMoniker);
|
|
break;
|
|
|
|
case OLEGETMONIKER_UNASSIGN:
|
|
ASSERT(FALSE); // should never get UNASSIGN
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case OLEWHICHMK_OBJFULL:
|
|
{
|
|
// get each sub-moniker: item & document
|
|
LPMONIKER lpMoniker1, lpMoniker2;
|
|
GetMoniker(dwAssign, OLEWHICHMK_CONTAINER, &lpMoniker1);
|
|
GetMoniker(dwAssign, OLEWHICHMK_OBJREL, &lpMoniker2);
|
|
|
|
if (lpMoniker1 != NULL && lpMoniker2 != NULL)
|
|
{
|
|
// create composite from two parts
|
|
::CreateGenericComposite(lpMoniker1, lpMoniker2, ppMoniker);
|
|
}
|
|
else if (lpMoniker1 != NULL)
|
|
{
|
|
// just use container moniker
|
|
*ppMoniker = lpMoniker1;
|
|
lpMoniker1 = NULL;
|
|
}
|
|
|
|
// release sub-monikers
|
|
RELEASE(lpMoniker1);
|
|
RELEASE(lpMoniker2);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return *ppMoniker == NULL ? E_FAIL : S_OK;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::InitFromData(
|
|
LPDATAOBJECT /*pDataObject*/, BOOL /*fCreation*/, DWORD /*dwReserved*/)
|
|
{
|
|
// linked objects do not support InitFromData
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::GetClipboardData(
|
|
DWORD /*dwReserved*/, LPDATAOBJECT* ppDataObject)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerItem, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
*ppDataObject = NULL;
|
|
|
|
SCODE sc;
|
|
TRY
|
|
{
|
|
COleDataSource* pDataSource = pThis->OnGetClipboardData(TRUE, NULL, NULL);
|
|
ASSERT(pDataSource != NULL);
|
|
|
|
*ppDataObject =
|
|
(LPDATAOBJECT)pDataSource->GetInterface(&IID_IDataObject);
|
|
ASSERT(*ppDataObject != NULL);
|
|
sc = S_OK;
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::DoVerb(
|
|
LONG iVerb, LPMSG /*lpmsg*/, LPOLECLIENTSITE /*pActiveSite*/, LONG /*lindex*/,
|
|
HWND /*hwndParent*/, LPCRECT /*lpPosRect*/)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerItem, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
pThis->InternalAddRef(); // protect this object
|
|
|
|
SCODE sc;
|
|
TRY
|
|
{
|
|
pThis->OnDoVerb(iVerb);
|
|
sc = S_OK;
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
pThis->InternalRelease(); // may 'delete this'
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::EnumVerbs(
|
|
IEnumOLEVERB** ppenumOleVerb)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
|
|
|
|
*ppenumOleVerb = NULL;
|
|
|
|
CLSID clsid;
|
|
pThis->GetOleObject()->GetUserClassID(&clsid);
|
|
return OleRegEnumVerbs(clsid, ppenumOleVerb);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::Update()
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerItem, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc;
|
|
TRY
|
|
{
|
|
pThis->OnUpdateItems();
|
|
sc = S_OK;
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::IsUpToDate()
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerItem, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc;
|
|
TRY
|
|
{
|
|
sc = pThis->OnQueryUpdateItems() ? S_FALSE : S_OK;
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::GetUserClassID(CLSID* pClsid)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
|
|
|
|
COleServerDoc* pDoc = pThis->GetDocument();
|
|
return pDoc->m_xPersistFile.GetClassID(pClsid);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::GetUserType(
|
|
DWORD dwFormOfType, LPOLESTR* ppszUserType)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
|
|
|
|
*ppszUserType = NULL;
|
|
|
|
CLSID clsid;
|
|
pThis->GetOleObject()->GetUserClassID(&clsid);
|
|
return OleRegGetUserType(clsid, dwFormOfType, ppszUserType);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::SetExtent(
|
|
DWORD /*dwDrawAspect*/, LPSIZEL /*lpsizel*/)
|
|
{
|
|
// linked objects do not support SetExtent
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::GetExtent(
|
|
DWORD dwDrawAspect, LPSIZEL lpsizel)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerItem, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc = E_INVALIDARG;
|
|
TRY
|
|
{
|
|
// call to get regular windows size
|
|
CSize size;
|
|
if (pThis->OnGetExtent((DVASPECT)dwDrawAspect, size))
|
|
{
|
|
if (size.cy < 0)
|
|
size.cy = -size.cy; // extents are always positive
|
|
lpsizel->cx = size.cx;
|
|
lpsizel->cy = size.cy;
|
|
|
|
sc = S_OK;
|
|
}
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::Advise(
|
|
IAdviseSink* pAdvSink, DWORD* pdwConnection)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
|
|
|
|
*pdwConnection = 0;
|
|
|
|
if (pThis->m_lpOleAdviseHolder == NULL &&
|
|
::CreateOleAdviseHolder(&pThis->m_lpOleAdviseHolder) != S_OK)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
ASSERT(pThis->m_lpOleAdviseHolder != NULL);
|
|
return pThis->m_lpOleAdviseHolder->Advise(pAdvSink, pdwConnection);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::Unadvise(DWORD dwConnection)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
|
|
|
|
if (pThis->m_lpOleAdviseHolder == NULL)
|
|
return E_FAIL;
|
|
|
|
ASSERT(pThis->m_lpOleAdviseHolder != NULL);
|
|
return pThis->m_lpOleAdviseHolder->Unadvise(dwConnection);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::EnumAdvise(
|
|
LPENUMSTATDATA* ppenumAdvise)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
|
|
|
|
*ppenumAdvise = NULL;
|
|
|
|
if (pThis->m_lpOleAdviseHolder == NULL)
|
|
return E_FAIL;
|
|
|
|
ASSERT(pThis->m_lpOleAdviseHolder != NULL);
|
|
return pThis->m_lpOleAdviseHolder->EnumAdvise(ppenumAdvise);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::GetMiscStatus(
|
|
DWORD dwAspect, DWORD* pdwStatus)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
|
|
|
|
*pdwStatus = 0;
|
|
|
|
CLSID clsid;
|
|
pThis->GetOleObject()->GetUserClassID(&clsid);
|
|
return OleRegGetMiscStatus(clsid, dwAspect, pdwStatus);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XOleObject::SetColorScheme(LPLOGPALETTE lpLogpal)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerItem, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc = E_NOTIMPL;
|
|
TRY
|
|
{
|
|
// delegate to embedded item
|
|
if (pThis->OnSetColorScheme(lpLogpal))
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
return sc;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerItem::XDataObject
|
|
|
|
STDMETHODIMP_(ULONG) COleServerItem::XDataObject::AddRef()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
|
|
return pThis->ExternalAddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) COleServerItem::XDataObject::Release()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
|
|
return pThis->ExternalRelease();
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XDataObject::QueryInterface(
|
|
REFIID iid, LPVOID* ppvObj)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
|
|
return pThis->ExternalQueryInterface(&iid, ppvObj);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XDataObject::GetData(
|
|
LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
|
|
|
|
return pThis->m_dataSource.m_xDataObject.GetData(lpFormatEtc, lpStgMedium);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XDataObject::GetDataHere(
|
|
LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
|
|
|
|
return pThis->m_dataSource.m_xDataObject.GetDataHere(
|
|
lpFormatEtc, lpStgMedium);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XDataObject::QueryGetData(LPFORMATETC lpFormatEtc)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
|
|
|
|
return pThis->m_dataSource.m_xDataObject.QueryGetData(lpFormatEtc);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XDataObject::GetCanonicalFormatEtc(
|
|
LPFORMATETC /*lpFormatEtcIn*/, LPFORMATETC /*lpFormatEtcOut*/)
|
|
{
|
|
// because we support the target-device (ptd) for server metafile format,
|
|
// all members of the FORMATETC are significant.
|
|
|
|
return DATA_S_SAMEFORMATETC;
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XDataObject::SetData(
|
|
LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium, BOOL bRelease)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
|
|
|
|
return pThis->m_dataSource.m_xDataObject.SetData(
|
|
lpFormatEtc, lpStgMedium, bRelease);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XDataObject::EnumFormatEtc(
|
|
DWORD dwDirection, LPENUMFORMATETC* ppenumFormatEtc)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
|
|
|
|
return pThis->m_dataSource.m_xDataObject.EnumFormatEtc(
|
|
dwDirection, ppenumFormatEtc);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XDataObject::DAdvise(
|
|
FORMATETC* pFormatEtc, DWORD advf,
|
|
LPADVISESINK pAdvSink, DWORD* pdwConnection)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
|
|
|
|
*pdwConnection = 0;
|
|
|
|
// this special case is for apps like Excel which ask for DAdvise
|
|
// on CF_METAFILEPICT, DVASPECT_ICON for insert as icon.
|
|
FORMATETC formatEtc = *pFormatEtc;
|
|
if (formatEtc.cfFormat == CF_METAFILEPICT &&
|
|
formatEtc.dwAspect == DVASPECT_ICON)
|
|
{
|
|
formatEtc.dwAspect = DVASPECT_CONTENT;
|
|
}
|
|
|
|
// make sure the FORMATETC is valid
|
|
if (!(pFormatEtc->cfFormat == 0 && pFormatEtc->ptd == NULL &&
|
|
pFormatEtc->dwAspect == -1 && pFormatEtc->lindex == -1 &&
|
|
pFormatEtc->tymed == -1) &&
|
|
pThis->GetDataObject()->QueryGetData(&formatEtc) != S_OK)
|
|
{
|
|
// it is not a wildcard advise -and- the format is not acceptable
|
|
return DATA_E_FORMATETC;
|
|
}
|
|
|
|
// create the advise holder, if necessary
|
|
if (pThis->m_lpDataAdviseHolder == NULL &&
|
|
CreateDataAdviseHolder(&pThis->m_lpDataAdviseHolder) != S_OK)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
ASSERT(pThis->m_lpDataAdviseHolder != NULL);
|
|
return pThis->m_lpDataAdviseHolder->Advise(this, pFormatEtc, advf,
|
|
pAdvSink, pdwConnection);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XDataObject::DUnadvise(DWORD dwConnection)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
|
|
|
|
if (pThis->m_lpDataAdviseHolder == NULL)
|
|
return E_FAIL;
|
|
|
|
ASSERT(pThis->m_lpDataAdviseHolder != NULL);
|
|
return pThis->m_lpDataAdviseHolder->Unadvise(dwConnection);
|
|
}
|
|
|
|
STDMETHODIMP COleServerItem::XDataObject::EnumDAdvise(
|
|
LPENUMSTATDATA* ppenumAdvise)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerItem, DataObject)
|
|
|
|
*ppenumAdvise = NULL;
|
|
|
|
if (pThis->m_lpDataAdviseHolder == NULL)
|
|
return E_FAIL;
|
|
|
|
ASSERT(pThis->m_lpDataAdviseHolder != NULL);
|
|
return pThis->m_lpDataAdviseHolder->EnumAdvise(ppenumAdvise);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// special CItemDataSource implementation
|
|
|
|
BOOL COleServerItem::CItemDataSource::OnRenderGlobalData(
|
|
LPFORMATETC lpFormatEtc, HGLOBAL* phGlobal)
|
|
{
|
|
ASSERT_VALID(this);
|
|
COleServerItem* pItem = (COleServerItem*)
|
|
((BYTE*)this - offsetof(COleServerItem, m_dataSource));
|
|
|
|
return pItem->OnRenderGlobalData(lpFormatEtc, phGlobal);
|
|
// Note: COleDataSource has no implementation
|
|
}
|
|
|
|
BOOL COleServerItem::CItemDataSource::OnRenderFileData(
|
|
LPFORMATETC lpFormatEtc, CFile* pFile)
|
|
{
|
|
ASSERT_VALID(this);
|
|
COleServerItem* pItem = (COleServerItem*)
|
|
((BYTE*)this - offsetof(COleServerItem, m_dataSource));
|
|
|
|
return pItem->OnRenderFileData(lpFormatEtc, pFile);
|
|
// Note: COleDataSource has no implementation
|
|
}
|
|
|
|
BOOL COleServerItem::CItemDataSource::OnRenderData(
|
|
LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
|
|
{
|
|
ASSERT_VALID(this);
|
|
COleServerItem* pItem = (COleServerItem*)
|
|
((BYTE*)this - offsetof(COleServerItem, m_dataSource));
|
|
|
|
if (pItem->OnRenderData(lpFormatEtc, lpStgMedium))
|
|
return TRUE;
|
|
|
|
return COleDataSource::OnRenderData(lpFormatEtc, lpStgMedium);
|
|
}
|
|
|
|
BOOL COleServerItem::CItemDataSource::OnSetData(
|
|
LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium, BOOL bRelease)
|
|
{
|
|
ASSERT_VALID(this);
|
|
COleServerItem* pItem = (COleServerItem*)
|
|
((BYTE*)this - offsetof(COleServerItem, m_dataSource));
|
|
|
|
return pItem->OnSetData(lpFormatEtc, lpStgMedium, bRelease);
|
|
// Note: COleDataSource has no implementation
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// COleServerItem Diagnostics
|
|
|
|
#ifdef _DEBUG
|
|
void COleServerItem::AssertValid() const
|
|
{
|
|
CDocItem::AssertValid();
|
|
|
|
// must be attached to a document
|
|
ASSERT(m_pDocument != NULL);
|
|
m_dataSource.AssertValid();
|
|
}
|
|
|
|
void COleServerItem::Dump(CDumpContext& dc) const
|
|
{
|
|
CDocItem::Dump(dc);
|
|
|
|
dc << "m_bNeedUnlock = " << m_bNeedUnlock;
|
|
dc << "\nm_bAutoDelete = " << m_bAutoDelete;
|
|
dc << "\nm_strItemName = " << m_strItemName;
|
|
dc << "\nm_lpOleAdviseHolder = " << m_lpOleAdviseHolder;
|
|
dc << "\nm_lpDataAdviseHolder = " << m_lpDataAdviseHolder;
|
|
dc << "\nwith m_dataSource: " << &m_dataSource;
|
|
}
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|