In our discussion of Cosmo earlier in this chapter, we saw how to present a moniker in the CFSTR_LINKSOURCE format and how to provide the CFSTR_LINKSRCDESCRIPTOR format in clipboard and drag-and-drop operations. Patron does more or less those same things in its function CTenant::CopyLinkedObject, which is called from CPage::TransferObjectCreate in any clipboard or drag-and-drop operation:
void CTenant::CopyLinkedObject(LPDATAOBJECT pIDataObject
, LPFORMATETC pFE, PPOINTL pptl)
{
HRESULT hr;
LPMONIKER pmk;
DWORD dwStat;
//If we don't have full moniker, no linking is allowed.
if (NULL==m_pmk)
return;
//If object doesn't support this, return.
dwStat=0;
m_pIOleObject->GetMiscStatus(m_fe.dwAspect, &dwStat);
if (OLEMISC_CANTLINKINSIDE & dwStat)
return;
[Other code omitted]
m_pIOleObject->GetUserClassID(&clsID);
hr=m_pIOleObject->GetMoniker(0, OLEWHICHMK_OBJFULL, &pmk);
[Create CFSTR_LINKSOURCE and CFSTR_LINKSRCDESCRIPTOR with pmk.]
§
}
For the most part, this is exactly what any link source does to create the necessary formats, which we usually make available only when we have a known filename. (This is the reason for the validation of m_pmk in the code above.) For a container that supports linking to embeddings, there is another condition: the object must support the feature itself. This means that the moniker implements IOleObject::GetMoniker for OLEWHICHMK_OBJFULL, which usually does little more than call IOleClientSite::GetMoniker. Anyway, if a server does not implement GetMoniker, it will mark itself with OLEMISC_CANTLINKINSIDE as returned from IOleObject::GetMiscStatus. The absence of this bit means that the object also understands what to do with monikers it receives through IOleObject::SetMoniker—for example, register that moniker as running, as we saw in Cosmo earlier.