Microsoft KB Archive/152072

= FIX: ASSERT in OLECLI1.CPP When Copying Embedding to Clipboard =

Article ID: 152072

Article Last Modified on 12/1/2003

-

APPLIES TO


 * Microsoft Visual C++ 2.0 Professional Edition
 * Microsoft Visual C++ 2.1
 * Microsoft Visual C++ 2.2
 * Microsoft Visual C++ 4.0 Standard Edition
 * Microsoft Visual C++ 4.1 Subscription
 * Microsoft Foundation Class Library 4.2
 * Microsoft Visual C++ 1.5 Professional Edition
 * Microsoft Visual C++ 1.51
 * Microsoft Visual C++ 1.52 Professional Edition

-



This article was previously published under Q152072



SYMPTOMS
When you attempt to copy an embedding in an in-place active object to the clipboard, the result is an ASSERT in OLECLI1.CPP. Specifically, the ASSERT occurs in the COleClientItem::XOleClientSite::GetMoniker function on the following line of code: VERIFY(pThis->m_lpObject->SetMoniker(OLEWHICHMK_OBJREL, *ppMoniker)==S_OK);



CAUSE
When you copy an embedding to the clipboard, a number of data formats are placed on the clipboard, including link source information. The link source information contains a moniker used to locate the document in which the embedding resides.

When the container assigns a moniker to an embedded object, it will call the object's IOleObject::SetMoniker function. The object will then call the container's IOleClientSite::GetMoniker function to construct a composite moniker based on the container's moniker. This is done because the container may have changed its moniker while the object was not running.

When the embedded object calls IOleClientSite::GetMoniker to get the container's moniker, COleClientItem::XOleClientSite::GetMoniker ASSERTs on the aforementioned line of code because pThis->m_bMoniker had not been set to TRUE when the moniker was assigned during a previous call to COleClientItem::XOleClientSite::GetMoniker.

The problem is located in the following section of the COleClientItem::XOleClientSite::GetMoniker function located in OLECLI1.CPP: // notify the object of the assignment if (dwAssign != OLEGETMONIKER_TEMPFORUSER &&      *ppMoniker != NULL && !pThis->m_bMoniker) {     VERIFY(pThis->m_lpObject->SetMoniker( OLEWHICHMK_OBJREL, *ppMoniker) == S_OK); pThis->m_bMoniker = TRUE; ASSERT_VALID(pThis->;m_pDocument); pThis->m_pDocument->SetModifiedFlag; } The pThis->m_lpObject->SetMoniker call results in the object calling COleClientItem::XOleClientSite::GetMoniker again. Because pThis- >m_bMoniker is being set after the pThis->m_lpObject->SetMoniker call, the subsequent call to pThis->m_lpObject->SetMoniker returns with an error code of E_FAIL, triggering the ASSERT.



RESOLUTION
To work around this problem, you must override the default IOleClientSite interface implementation in COleClientItem. This can be done by adding an interface map to the class in your project that is derived from COleClientItem and setting pThis->m_bMoniker to TRUE before calling pThis- >m_lpObject->SetMoniker from your custom GetMoniker function.

The code below illustrates how to override the COleClientItem-derived object using the OCLIENT MFC sample application.



STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug was corrected in Visual C++ 32- bit Edtion version 4.2.



Sample Code
// Code to be added to CRectItem class definition in RECTITEM.H  class CRectItem : public COleClientItem {     // ...original declarations in CRectItem class go here...

// Interface Map BEGIN_INTERFACE_PART(OleClientSite2, IOleClientSite) STDMETHOD(SaveObject); STDMETHOD(GetMoniker)(DWORD, DWORD, LPMONIKER*); STDMETHOD(GetContainer)(LPOLECONTAINER*); STDMETHOD(ShowObject); STDMETHOD(OnShowWindow)(BOOL); STDMETHOD(RequestNewObjectLayout); END_INTERFACE_PART(OleClientSite2)

DECLARE_INTERFACE_MAP };

// XOleClientSite2 functions to be added to RECTITEM.CPP BEGIN_INTERFACE_MAP(CRectItem, COleClientItem) INTERFACE_PART(CRectItem, IID_IOleClientSite, OleClientSite2) END_INTERFACE_MAP

STDMETHODIMP_(ULONG) CRectItem::XOleClientSite2::AddRef {     METHOD_PROLOGUE_EX_(CRectItem, OleClientSite2) return pThis->ExternalAddRef; }

STDMETHODIMP_(ULONG) CRectItem::XOleClientSite2::Release {     METHOD_PROLOGUE_EX_(CRectItem, OleClientSite2) return pThis->ExternalRelease; }

STDMETHODIMP CRectItem::XOleClientSite2::QueryInterface(     REFIID iid, LPVOID* ppvObj) {     METHOD_PROLOGUE_EX_(CRectItem, OleClientSite2) return pThis->ExternalQueryInterface(&iid, ppvObj); }

STDMETHODIMP CRectItem::XOleClientSite2::SaveObject {     METHOD_PROLOGUE_EX(CRectItem, OleClientSite2) ASSERT_VALID(pThis); return pThis->m_xOleClientSite.SaveObject; }

STDMETHODIMP CRectItem::XOleClientSite2::GetMoniker(      DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER* ppMoniker) {     METHOD_PROLOGUE_EX(CRectItem, OleClientSite2) ASSERT_VALID(pThis);

USES_CONVERSION; // note, must #include afxpriv.h

COleDocument* pDoc = pThis->GetDocument; ASSERT_VALID(pDoc); ASSERT(ppMoniker != NULL); *ppMoniker = NULL;

switch (dwWhichMoniker) {     case OLEWHICHMK_CONTAINER: // return the current moniker for the document *ppMoniker = pDoc->GetMoniker((OLEGETMONIKER)dwAssign); break;

case OLEWHICHMK_OBJREL: {           if (!pDoc->IsKindOf(RUNTIME_CLASS(COleLinkingDoc))) break;

// don't return relative moniker if no document moniker LPMONIKER lpMoniker = pDoc- >GetMoniker((OLEGETMONIKER)dwAssign); if (lpMoniker == NULL) break; lpMoniker->Release;

// relative monikers have to handle assignment correctly switch (dwAssign) {              case OLEGETMONIKER_ONLYIFTHERE: if (!pThis->m_bMoniker) break; // no moniker assigned, don't return one // fall through...

case OLEGETMONIKER_TEMPFORUSER: case OLEGETMONIKER_FORCEASSIGN: {                    // create item moniker from item name TCHAR szItemName[OLE_MAXITEMNAME]; pThis->GetItemName(szItemName); CreateItemMoniker(OLESTDDELIMOLE, T2COLE(szItemName),                       ppMoniker);

// notify the object of the assignment if (dwAssign != OLEGETMONIKER_TEMPFORUSER &&                        *ppMoniker != NULL && !pThis->m_bMoniker) {                       pThis->m_bMoniker = TRUE; VERIFY(pThis->m_lpObject->SetMoniker( OLEWHICHMK_OBJREL, *ppMoniker) == S_OK); ASSERT_VALID(pThis->m_pDocument); pThis->m_pDocument->SetModifiedFlag; }                 }                  break;

case OLEGETMONIKER_UNASSIGN: pThis->m_bMoniker = FALSE; break; }        }         break;

case OLEWHICHMK_OBJFULL: {           // get each sub-moniker: item & document LPMONIKER lpMoniker1, lpMoniker2; GetMoniker(dwAssign, OLEWHICHMK_CONTAINER, &lpMoniker1); GetMoniker(dwAssign, OLEWHICHMK_OBJREL, &lpMoniker2);

// create composite moniker if (lpMoniker1 != NULL && lpMoniker2 != NULL) ::CreateGenericComposite(lpMoniker1, lpMoniker2,  ppMoniker);

// release sub-monikers RELEASE(lpMoniker1); RELEASE(lpMoniker2); }        break; }     return *ppMoniker != NULL ? S_OK : E_FAIL; }

STDMETHODIMP CRectItem::XOleClientSite2::GetContainer(LPOLECONTAINER*     ppContainer) {  #ifdef _DEBUG METHOD_PROLOGUE_EX(CRectItem, OleClientSite2) #else METHOD_PROLOGUE_EX_(CRectItem, OleClientSite2) #endif ASSERT_VALID(pThis); return pThis->m_xOleClientSite.GetContainer(ppContainer); }

STDMETHODIMP CRectItem::XOleClientSite2::ShowObject {     METHOD_PROLOGUE_EX(CRectItem, OleClientSite2) ASSERT_VALID(pThis); return pThis->m_xOleClientSite.ShowObject; }

STDMETHODIMP CRectItem::XOleClientSite2::OnShowWindow(BOOL fShow) {     METHOD_PROLOGUE_EX(CRectItem, OleClientSite2) ASSERT_VALID(pThis); return pThis->m_xOleClientSite.OnShowWindow(fShow); }

STDMETHODIMP CRectItem::XOleClientSite2::RequestNewObjectLayout {     return E_NOTIMPL; }

Additional query words: 1.50 1.51 1.52 2.00 2.10 2.20 4.00 4.10 4.20 vcfixlist420 MfcOLE

Keywords: kbbug kbfix kbvc500fix kbclipboard KB152072

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.