Expose Default Handler Interfaces in QueryInterface

As with any aggregation relationship, we need to expose select interfaces from the inner object through our own QueryInterface, along with those interfaces we implement ourselves. To do this, CFigure::QueryInterface delegates to the default handler's IUnknown for the caching interfaces and IRunnableObject, returning other object pointers for the remaining interfaces:


STDMETHODIMP CFigure::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;

if (IID_IUnknown==riid)
*ppv=this;

if (IID_IPersist==riid œœ IID_IPersistStorage==riid)
*ppv=m_pImpIPersistStorage;

if (IID_IOleObject==riid)
*ppv=m_pImpIOleObject;

if (IID_IViewObject==riid œœ IID_IViewObject2==riid)
*ppv=m_pImpIViewObject2;

if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}

if (IID_IDataObject==riid œœ IID_IOleCache==riid
œœ IID_IOleCache2==riid œœ IID_IOleCacheControl==riid
œœ IRunnableObject==riid)
return m_pDefIUnknown->QueryInterface(riid, ppv);

return ResultFromScode(E_NOINTERFACE);
}

As we discussed earlier about aggregation, you do not want to blindly delegate requests for unrecognized interfaces to the inner object's QueryInterface unless you specifically have a reason to do so.

Whatever the case may be, you can see here that the figure object in HCosmo exposes all of those interfaces that a container will expect: some from the default handler, others from the figure object itself. In addition, CFigure::Release will destroy the object when the reference count is 0, decrementing the global object count so DllCanUnloadNow works properly.