Important: |
---|
This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. |
All Microsoft DirectShow Component Object Model (COM) objects derive from the CUnknownabstract 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 CUnknownand call the DECLARE_IUNKNOWNmacro in the public section of your object class definition; this implements the IUnknowninterface 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 CUnknownclass supports only one interface, IUnknown. To support interfaces in addition to those provided by the base class, override the NonDelegatingQueryInterfacemethod. In the overriding function, call the GetInterfacefunction 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, CBaseFiltersupports the following interfaces directly.
CBaseFilteralso supports IUnknownby 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 CUnknownconstructor has an LPUNKNOWN parameter that is a pointer to the top-level IUnknowninterface for the entire composite object (the object that includes all objects based on a class derived from CUnknown). If this value is non-NULL, CUnknownstores a pointer to the topmost object; if it is null, the topmost object is CUnknownitself. This way, the topmost object's IUnknownhas the same implementation as the INonDelegatingUnknowninterface.
A derived class will typically override the NonDelegatingQueryInterfacemethod to return interfaces that it supports; however, it must delegate support for IUnknownto the CUnknownclass implementation. Usually NonDelegatingAddRefand NonDelegatingReleasedo not need to be overridden because the reference count for the whole object is managed inside the top-level object. However, NonDelegatingReleasemight need to be overridden sometimes because its default action when the reference count goes to zero is to delete the object from inside itself.
CUnknownprovides the CUnknown::GetOwnermember function. GetOwnersimply returns an LPUNKNOWN pointer to the controlling unknown. This is used in the DECLARE_IUNKNOWNmacro 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 QueryInterfaceis called on an interface owned by a component interface, it is immediately passed to the NonDelegatingQueryInterfacemethod of the top-level object's INonDelegatingUnknown::NonDelegatingQueryInterfacemethod, which either returns an interface it implements itself or passes the call to the correct member or base class's INonDelegatingUnknown::NonDelegatingQueryInterfacemethod. 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::NonDelegatingQueryInterfacemember 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 CreateInstancemember function, which is called from the class factory (by CClassFactory::CreateInstance) passes the outer unknown (the pUnkOuterparameter from CoCreateInstance) on to CUnknownby calling the class constructor. So the object behaves as if it were part of a larger object by delegating its QueryInterfacecalls to the outer unknown.
Protected Data Members
m_cRef | Number of reference counts (so the INonDelegatingUnknown::NonDelegatingReleasemethod can be overridden). |
Member Functions
CUnknown | Constructs a CUnknownobject. |
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. |