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.
A version of this page is also available for
4/8/2010

DirectShow implements IUnknownin a base class called CUnknown. You can use CUnknownto derive other classes, overriding only the methods that change across components. Most of the other base classes in DirectShow derive from CUnknown, so your component can inherit directly from CUnknownor from another base class.

INonDelegatingUnknown

CUnknownimplements INonDelegatingUnknown. It manages reference counts internally, and in most situations your derived class can inherit the two reference-counting methods with no change. Be aware that CUnknowndeletes itself when the reference count drops to zero. On the other hand, you must override NonDelegatingQueryInterface, because the method in the base class returns E_NOINTERFACE if it receives any IID other than IID_IUnknown. In your derived class, test for the IIDs of interfaces that you support, as shown in the following example.

Copy Code
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
	if (riid == IID_ISomeInterface)
	{
		return GetInterface((ISomeInterface*)this, ppv);
}
	// default
	return CUnknown::NonDelegatingQueryInterface(riid, ppv);
}

The utility function GetInterfacesets the pointer, increments the reference count in a thread-safe way, and returns S_OK. In the default case, call the base class method and return the result. If you derive from another base class, call its NonDelegatingQueryInterfacemethod instead. This enables you to support all the interfaces that the parent class supports.

IUnknown

As mentioned earlier, the delegating version of IUnknownis the same for every component, because it does nothing more than invoke the correct instance of the nondelegating version. For convenience, the header file Combase.h contains a macro, DECLARE_IUNKNOWN, which declares the three delegating methods as inline methods. It expands to the following code.

Copy Code
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { 
	return GetOwner()->QueryInterface(riid,ppv); 	
}; 												
STDMETHODIMP_(ULONG) AddRef() { 						 
	return GetOwner()->AddRef(); 					
}; 												
STDMETHODIMP_(ULONG) Release() { 					
	return GetOwner()->Release(); 					 
};

The utility function GetOwnerretrieves a pointer to the IUnknowninterface of the component that owns this component. For an aggregated component, the owner is the outer component. Otherwise, the component owns itself. Include the DECLARE_IUNKNOWN macro in the public section of your class definition.

Class Constructor

Your class constructor should invoke the constructor method for the parent class, in addition to anything it does that is specific to your class. The following example is a typical constructor method.

Copy Code
CMyComponent(TCHAR *tszName, LPUNKNOWN pUnk, HRESULT *phr) 
	: CUnknown(tszName, pUnk)
{ 
	/* Other initializations */ 
};

The method takes the following parameters, which it passes directly to the CUnknownconstructor method.

  • tszNamespecifies a name for the component.

  • pUnkis a pointer to the aggregating IUnknown.

  • pHris a pointer to an HRESULT value, indicating the success or failure of the method.

Summary

The following example shows a derived class that supports IUnknownand a hypothetical interface named ISomeInterface .

Copy Code
class CMyComponent : public CUnknown, public ISomeInterface
{
public:

	DECLARE_IUNKNOWN;

	STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void
**ppv)
	{
		if( riid == IID_ISomeInterface )
		{
			return GetInterface((ISomeInterface*)this, ppv);
	}
		return CUnknown::NonDelegatingQueryInterface(riid, ppv);
}

	CMyComponent(TCHAR *tszName, LPUNKNOWN pUnk, HRESULT *phr) 
		: CUnknown(tszName, pUnk)
	{ 
		/* Other initializations */ 
};

	// More declarations will be added later.
};

This example illustrates the following points.

  • The CUnknownclass implements the IUnknowninterface. The new component inherits from CUnknownand from any interfaces that the component supports. The component could derive instead from another base class that inherits from CUnknown.

  • The DECLARE_IUNKNOWN macro declares the delegating IUnknownmethods as inline methods.

  • The CUnknownclass provides the implementation for INonDelegatingUnknown.

  • To support an interface other than IUnknown, the derived class must override the INonDelegatingQueryInterfacemethod and test for the IID of the new interface.

  • The class constructor invokes the constructor method for CUnknown.

The next step in writing a filter is to enable an application to create new instances of the component. This requires an understanding of DLLs and their relation to class factories and class constructor methods. For more information, see Creating a DLL in DirectShow.

See Also