Microsoft DirectX 8.1 (C++) |
To access the Windows Media Format SDK, an application must provide a software certificate, also called a key, at run time. For details on obtaining the certificate, see the Windows Media Format SDK. A DirectShow application provides its certificate to the ASF Writer when it is added to the filter graph. The application must register as a key provider using the Component Object Model (COM) IServiceProvider and IObjectWithSite interfaces. Using this technique, the application implements a key provider class derived from IServiceProvider. This class implements the three standard COM methodsAddRef, QueryInterface, and Releasealong with one additional method, QueryService, which is called by the filter graph manager. QueryService calls the Windows Media Format SDK method WMCreateCertificate and returns to the filter graph manager a pointer to the certificate that was created. If the certificate is valid, the filter graph manager allows the graph-building process to proceed.
Note To build an application, include Wmsdkidl.h for the prototype for WMCreateCertificate, and link to the Wmstub.lib that you received from Microsoft.
The following code example illustrates the basic steps in this process:
// Declare and implement a key provider class derived from IServiceProvider.
class CKeyProvider : public IServiceProvider {
public:
// IUnknown interface
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
CKeyProvider();
// IServiceProvider
STDMETHODIMP QueryService(REFIID siid, REFIID riid, void **ppv);
private:
ULONG m_cRef;
};
CKeyProvider::CKeyProvider() : m_cRef(0)
{
}
//////////////////////////////////////////////////////////////////////////
//
// IUnknown methods
//
//////////////////////////////////////////////////////////////////////////
ULONG CKeyProvider::AddRef()
{
return ++m_cRef;
}
ULONG CKeyProvider::Release()
{
ASSERT(m_cRef > 0);
m_cRef--;
if (m_cRef == 0) {
delete this;
// Don't return m_cRef, because the object doesn't exist anymore.
return((ULONG) 0);
}
return(m_cRef);
}
// We only support IUnknown and IServiceProvider.
HRESULT CKeyProvider::QueryInterface(REFIID riid, void ** ppv)
{
if (riid == IID_IServiceProvider || riid == IID_IUnknown) {
*ppv = (void *) static_cast<IServiceProvider *>(this);
AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHODIMP CKeyProvider::QueryService(REFIID siid, REFIID riid, void **ppv)
{
if (siid == __uuidof(IWMReader) && riid == IID_IUnknown) {
IUnknown *punkCert;
HRESULT hr = WMCreateCertificate(&punkCert);
if (SUCCEEDED(hr)) {
*ppv = (void *) punkCert;
}
return hr;
}
return E_NOINTERFACE;
}
////////////////////////////////////////////////////////////////////
//
// These examples illustrate the sequence of method calls
// in your application. Error checking is omitted for brevity.
//
///////////////////////////////////////////////////////////////////
// Create the filter graph manager, but don't add any filters.
IGraphBuilder *pGraph;
hr = CreateFilterGraph(&pGraph);
...
// Instantiate the key provider class, and AddRef it
// so that COM doesn't try to free our static object.
CKeyProvider prov;
prov.AddRef(); // Don't let COM try to free our static object.
// Give the graph an IObjectWithSite pointer to us for callbacks & QueryService.
IObjectWithSite* pObjectWithSite = NULL;
hr = pGraph->QueryInterface(IID_IObjectWithSite, (void**)&pObjectWithSite);
if (SUCCEEDED(hr))
{
// Use the IObjectWithSite pointer to specify our key provider object.
// The filter graph manager will use this pointer to call
// QueryService to do the unlocking.
// If the unlocking succeeds, then we can build our graph.
pObjectWithSite->SetSite((IUnknown *) (IServiceProvider *) &prov);
pObjectWithSite->Release();
}
// Now build the graph as described above in "Building A Graph."