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 you 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.
m_cRef Number of reference counts (so the INonDelegatingUnknown::NonDelegatingRelease method can be overridden).
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 Retrieves an interface and increments the reference count. NonDelegatingRelease Decrements the reference count for an interface.
Constructs a CUnknown object.
Syntax
CUnknown( const TCHAR *pName, LPUNKNOWN pUnk );
Parameters
- pName
- Pointer to the name of the object used in the CBaseObject constructor for debugging purposes.
- pUnk
- Pointer to the owner of this object. If non-NULL, IUnknown calls are delegated to this object.
Return Value
No return value.
Remarks
The object is initialized with a reference count of zero. This reference count can be incremented when the object is queried for its first interface, depending on whether the object is currently being aggregated.
Retrieves this object's Component Object Model (COM) class owner.
Syntax
LPUNKNOWN GetOwner(void);
Return Value
Returns an LPUNKNOWN pointer to the controlling IUnknown interface.
Increments the reference count for an interface.
Syntax
ULONG NonDelegatingAddRef(void);
Return Value
Returns the reference count of the object.
Remarks
This member function provides a base class implementation of the INonDelegatingUnknown::NonDelegatingAddRef method. When the object derived from CUnknown is part of an aggregated object, this reference count modification is private to the embedded object.
Retrieves an interface and increments the reference count.
Syntax
HRESULT NonDelegatingQueryInterface( REFIID riid, void **ppv );
Parameters
- riid
- Reference identifier.
- ppv
- Address of a pointer to the interface.
Return Value
Returns E_POINTER if ppv is invalid. Returns NOERROR if the query is successful or E_NOINTERFACE if it is not.
Remarks
This member function provides a base class implementation of the INonDelegatingUnknown::NonDelegatingQueryInterface method. Override this class to return interfaces on the object in the derived class.
Decrements the reference count for an interface.
Syntax
ULONG NonDelegatingRelease(void);
Return Value
Returns the reference count.
Remarks
This member function provides a base class implementation of the INonDelegatingUnknown::NonDelegatingRelease method. When the object derived from CUnknown is part of an aggregated object, this reference count modification is private to the embedded object.
Top of Page
© 2000 Microsoft and/or its suppliers. All rights reserved. Terms of Use.