Share via


CUnknown Class

All Microsoft® DirectShow™ Component Object Model (COM) objects derive from the CUnknown abstract base class. This class facilitates the creation of simple COM objects that you can combine with other COM objects to support multiple interfaces. To use this class, derive your object from CUnknown and call the DECLARE_IUNKNOWN macro in the public section of your object class definition; this implements the IUnknown interface for your object. Note that if derive from an object that has already done this, such as CBaseFilter, you do not need to do it yourself.

The CUnknown class supports only one interface, IUnknown. To support interfaces in addition to those provided by the base class, override the NonDelegatingQueryInterface method. In the overriding function, call the GetInterface function to retrieve the interface pointer for any interfaces your object supports. If the derived class does not implement the specified interface, you must query the base class to retrieve the interface.

For example, CBaseFilter supports the following interfaces directly.

CBaseFilter also supports IUnknown by passing queries for this interface to CUnknown. The following code sample demonstrates this process.

/* Override this to say what interfaces are supported and where */

STDMETHODIMP CBaseFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
    CheckPointer(ppv,E_POINTER);
    ValidateReadWritePtr(ppv,sizeof(PVOID));

    /* Do we have this interface */

    if (riid == IID_IFilter) {
         return GetInterface((IBaseFilter *) this, ppv);
    } else if (riid == IID_IMediaFilter) {
                   return GetInterface((IMediaFilter *) this, ppv);
    } else if (riid == IID_IPersist) {
                   return GetInterface((IPersist *) this, ppv);
    } else if (riid == IID_IAMovieSetup) {
                   return GetInterface((IAMovieSetup *) this, ppv);
    } else {
                   return CUnknown::NonDelegatingQueryInterface(riid, ppv);
    }
}

To build composite objects, the CUnknown constructor has an LPUNKNOWN parameter that is a pointer to the top-level IUnknown interface for the entire composite object (the object that includes all objects based on a class derived from CUnknown). If this value is non-NULL, CUnknown stores a pointer to the topmost object; if it is null, the topmost object is CUnknown itself. This way, the topmost object's IUnknown has the same implementation as the INonDelegatingUnknown interface.

A derived class will typically override the NonDelegatingQueryInterface method to return interfaces that it supports; however, it must delegate support for IUnknown to the CUnknown class implementation. Usually NonDelegatingAddRef and NonDelegatingRelease do not need to be overridden because the reference count for the whole object is managed inside the top-level object. However, NonDelegatingRelease might need to be overridden sometimes because its default action when the reference count goes to zero is to delete the object from inside itself.

CUnknown provides the CUnknown::GetOwner member function. GetOwner simply returns an LPUNKNOWN pointer to the controlling unknown. This is used in the DECLARE_IUNKNOWN macro when calling QueryInterface. It can also be used when creating a composite object to pass an LPUNKNOWN pointer to a component interface as an (equivalent) alternative to passing the LPUNKNOWN pointer that was passed to the composite object constructor.

When QueryInterface is called on an interface owned by a component interface, it is immediately passed to the NonDelegatingQueryInterface method of the top-level object's INonDelegatingUnknown::NonDelegatingQueryInterface method, which either returns an interface it implements itself or passes the call to the correct member or base class's INonDelegatingUnknown::NonDelegatingQueryInterface method. This then repeats the process until a component is found that implements the interface or calls CUnknown::NonDelegatingQueryInterface, which fails the call.

Note that the top-level object's CUnknown::NonDelegatingQueryInterface member function (as distinct from its own implementation) must be called to support IUnknown.

This design makes support for COM aggregation straightforward. The derived object's CreateInstance member function, which is called from the class factory (by CClassFactory::CreateInstance) passes the outer unknown (the pUnkOuter parameter from CoCreateInstance) on to CUnknown by calling the class constructor. So the object behaves as if it were part of a larger object by delegating its QueryInterface calls to the outer unknown.

Protected Data Members

m_cRef Number of reference counts (so the INonDelegatingUnknown::NonDelegatingRelease method can be overridden).

Member Functions

CUnknown Constructs a CUnknown object.
GetOwner Returns an LPUNKNOWN pointer to the controlling unknown.

Implemented INonDelegatingUnknown Methods

NonDelegatingAddRef Increments the reference count for an interface.
NonDelegatingQueryInterface Returns an interface and increments the reference count.
NonDelegatingRelease Decrements the reference count for an interface.

 Last updated on Tuesday, July 13, 2004

© 1992-2000 Microsoft Corporation. All rights reserved.