解锁Windows媒体格式 SDK

若要访问 Windows 媒体格式 SDK 的版本 7 或 7.1,应用程序必须在运行时提供软件证书(也称为密钥)。 此密钥包含在应用程序在生成时链接到的名为 wmstub.lib 的静态库中。 仅创建或读取受 DRM 保护的文件时,才需要单个密钥。 可以使用Windows媒体格式 SDK 提供的静态库创建非 DRM 文件。 有关获取 DRM 密钥的详细信息,请参阅Windows媒体格式 SDK。 将 WM ASF 编写器添加到筛选器图时,DirectShow应用程序将其证书提供给 WM ASF 编写器。 应用程序必须使用 COM IServiceProviderIObjectWithSite 接口注册为密钥提供程序。 使用此技术,应用程序实现派生自 IServiceProvider 的密钥提供程序类。 此类实现三种标准 COM 方法(AddRefQueryInterfaceRelease),以及由筛选器图形管理器调用的附加方法 QueryServiceQueryService 调用Windows媒体格式 SDK 方法 WMCreateCertificate,并返回到筛选器图形管理器,指向创建的证书的指针。 如果证书有效,筛选器图形管理器允许图形生成过程继续。

注意

若要生成应用程序,请包含 WMCreateCertificate 原型的 Wmsdkidl.h,并链接到 Wmstub.lib 库。

 

下面的代码示例演示了此过程的基本步骤:

// 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 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;
}

// We only support IUnknown and 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;
}

////////////////////////////////////////////////////////////////////
//
// 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 for callbacks and 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.

在 DirectShow 中创建 ASF 文件