Windows Media Format SDK のロック解除
Windows Media Format SDK Version 7 または 7.1 にアクセスするには、アプリケーションは実行時にソフトウェア証明書 (キーとも呼ばれる) を提供しなければならない。このキーは、アプリケーションがビルド時にリンクされる静的ライブラリ wmstub.lib に含まれている。個別キーは DRM で保護されたファイルの読み書きにのみ必要となる。非 DRM ファイルは Windows Media Format SDK に付属する静的ライブラリを使って作成される。DRM キーの入手方法については、Windows Media Format SDK を参照すること。DirectShow アプリケーションは、フィルタ グラフに追加されるときに WM ASF ライタに証明書を提供する。アプリケーションは、COM の IServiceProvider および IObjectWithSite インターフェイスを使って、キー プロバイダとして登録しなければならない。この手法を用いて、アプリケーションは IServiceProvider から派生されたキー プロバイダ クラスを実装する。このクラスは、COM の 3 つの標準メソッドである AddRef、QueryInterface、および Release と共に、フィルタ グラフ マネージャから呼び出される追加メソッド QueryService を実装する。QueryService は、Windows Media Format SDK の WMCreateCertificate メソッドを呼び出し、作成した証明書へのポインタをフィルタ グラフ マネージャに返す。証明書が有効な場合、フィルタ グラフ マネージャはグラフの作成を進めることを許可する。
注 アプリケーションを作成するには、WMCreateCertificate のプロトタイプ用に Wmsdkidl.h をインクルードし、Wmstub.lib ライブラリにリンクする。
次のサンプル コードに、この処理の基本的な手順を示す。
// IServiceProvider から派生したキー プロバイダ クラスを宣言し、実装する。
class CKeyProvider : public IServiceProvider {
public:
// IUnknown インターフェイス。
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 メソッド。
ULONG CKeyProvider::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
ULONG CKeyProvider::Release()
{
ASSERT(m_cRef > 0);
ULONG lCount = InterlockedDecrement(&m_cRef);
if (m_cRef == 0)
{
delete this;
return (ULONG)0;
}
return (ULONG)lCount;
}
// IUnknown および IServiceProvider のみサポートする。
HRESULT CKeyProvider::QueryInterface(REFIID riid, void ** ppv)
{
if (!ppv) return E_POINTER;
if (riid == IID_IUnknown)
{
*ppv = (void *) static_cast<IUnknown *>(this);
AddRef();
return S_OK;
}
if (riid == IID_IServiceProvider)
{
*ppv = (void *) static_cast<IServiceProvider *>(this);
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP CKeyProvider::QueryService(REFIID siid, REFIID riid, void **ppv)
{
if (!ppv) return E_POINTER;
if (siid == __uuidof(IWMReader) && riid == IID_IUnknown)
{
IUnknown *punkCert;
HRESULT hr = WMCreateCertificate(&punkCert);
if (SUCCEEDED(hr))
{
*ppv = (void *) punkCert;
}
return hr;
}
return E_NOINTERFACE;
}
////////////////////////////////////////////////////////////////////
//
// 以下の例では、アプリケーションにおける一連のメソッド呼び出しを示す。
// 簡潔にするため、エラー チェックは省略した。
//
///////////////////////////////////////////////////////////////////
//フィルタ グラフ マネージャを作成するが、フィルタは追加しない。
IGraphBuilder *pGraph;
hr = CreateFilterGraph(&pGraph);
...
// キー プロバイダ クラスをインスタンス化し、COM が静的オブジェクトを
// 解放しないように AddRef する。
CKeyProvider prov;
prov.AddRef(); // COM により静的オブジェクトが解放されないようにする。
// コールバックと QueryService のために IObjectWithSite ポインタをグラフに与える。
IObjectWithSite* pObjectWithSite = NULL;
hr = pGraph->QueryInterface(IID_IObjectWithSite, (void**)&pObjectWithSite);
if (SUCCEEDED(hr))
{
// IObjectWithSite ポインタを使ってキー プロバイダ オブジェクトを指定する。
// フィルタ グラフ マネージャはこのポインタを使って QueryService を呼び出し、
// ロックを解除する。
// ロック解除が成功すると、グラフを作成できる。
pObjectWithSite->SetSite((IUnknown *) (IServiceProvider *) &prov);
pObjectWithSite->Release();
}
// グラフを作成する。