Testing Whether a Graphics Driver Supports COPP

Certified Output Protection Protocol (COPP) enables an application to protect video content as it travels from the video card to the display device. If a graphics driver supports COPP, the driver holds a certificate chain, signed by Microsoft, authenticating the driver. Playback applications that use COPP to enforce content protection must validate the certificate chain to ensure that the driver has not been tampered with.

However, you might want to check whether a graphics driver supports COPP, without validating the certificate. For example, when a digital media provider issues a digital rights management (DRM) license, it might want to check whether the user has a COPP-enabled graphics driver. The provider does not need to enforce COPP at the time it issues the license; it only needs to test whether the driver supports COPP.

The following code shows how to test whether a driver supports COPP. The application must pass in the name of a video file that will be used to test the driver. This is required because the Video Mixing Renderer filter in Microsoft® DirectShow® does not initialize a COPP session until the filter is connected. This function can be included in a client application to check if the driver is capable of running COPP.

Note   If the user's computer has two graphics cards, this function tests the driver for the primary graphics card, but not the secondary graphics card.

#include <dshow.h>
// Link to strmiids.lib

#define SAFE_RELEASE(p) if (NULL != (p)) { (p)->Release(); (p) = NULL; }
#define CHECK_HR(hr) if (FAILED(hr)) { goto done; }

enum COPPSupport 

// Name:        IsDriverCoppEnabled
// Description: Test whether the user's graphics driver supports
//              COPP.
// wszTestFile: Name of a video file to use for testing.
// If this method returns the value SUPPORTS_COPP, it does *not* guarantee 
// that the driver is a valid COPP-enabled driver. If you want to use COPP 
// to enforce video output protection, the application *must* validate 
// the certificate returned by the KeyExchange method. 
// The purpose of this function is only to test whether the driver 
// claims to support COPP. 

COPPSupport IsDriverCoppEnabled(const WCHAR *wszTestFile)

    IGraphBuilder *pGB = NULL;
    IBaseFilter *pRenderer = NULL;
    IAMCertifiedOutputProtection  *pCOPPDevice = NULL;
    BYTE *pbCertificate = NULL;
    GUID  RandomValue = GUID_NULL;
    ULONG cbCertificateLength = NULL;
    HRESULT hr = S_OK;

    // Create the Filter Graph Manager.
    CHECK_HR(hr = CoCreateInstance(CLSID_FilterGraph, NULL, 
        CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGB));

    // Create the VMR-9. 
    hr = CoCreateInstance(CLSID_VideoMixingRenderer9,

    if (FAILED(hr))
        // Try the VMR-7 instead.
        CHECK_HR(hr = CoCreateInstance(CLSID_VideoMixingRenderer,
                NULL, CLSCTX_INPROC, IID_IBaseFilter, 

    // Add the VMR to the filter graph.
    CHECK_HR(hr = pGB->AddFilter(pRenderer, L"Video Renderer"));

    // Build a default playback graph.
    CHECK_HR(hr = pGB->RenderFile(wszTestFile, NULL));

    // Query for IAMCertifiedOutputProtection.
    CHECK_HR(hr = pRenderer->QueryInterface(IID_IAMCertifiedOutputProtection,

    // Get the driver's COPP certificate.
    hr = pCOPPDevice->KeyExchange(&RandomValue, &pbCertificate,

    if (SUCCEEDED(hr))
        SupportResult = SUPPORTS_COPP;
        SupportResult = DOES_NOT_SUPPORT_COPP;

    // Clean up.

    return SupportResult;

Related topics

Using Certified Output Protection Protocol