次の方法で共有


カーネルモード フィルタの作成

一部のカーネルモード フィルタは CoCreateInstance を使って作成できないため、CLSID がない。これらのフィルタには、ティー/シンクツーシンク コンバータCC デコーダ フィルタ、および WST CODEC フィルタがある。これらのフィルタの 1 つを作成するには、System Device Enumerator オブジェクトを使い、フィルタの名前で検索する。

  1. System Device Enumerator を作成する。
  2. 対象フィルタに対するフィルタ カテゴリの CLSID を使って ICreateDevEnum::CreateClassEnumerator メソッドを呼び出す。このメソッドはフィルタ カテゴリの列挙子を作成する。 ("列挙子" とは、定義済み COM インターフェイスを使って他のオブジェクトのリストを返すオブジェクトである。)列挙子は IMoniker ポインタを返す。このポインタはそのカテゴリのフィルタを表す。
  3. モニカごとに、IMoniker::BindToStorage を呼び出し、IPropertyBag インターフェイスを取得する。
  4. IPropertyBag::Read を呼び出し、フィルタ名を取得する。
  5. 名前が一致した場合、IMoniker::BindToObject を呼び出し、フィルタを作成する。

次のコードは、上記の手順を実行する関数を示している。

HRESULT CreateKernelFilter(
    const GUID &guidCategory,  // フィルタ カテゴリ。
    LPCOLESTR szName,          // フィルタの名前。
    IBaseFilter **ppFilter     // フィルタへのポインタを取得する。
)
{
    HRESULT hr;
    ICreateDevEnum *pDevEnum = NULL;
    IEnumMoniker *pEnum = NULL;
    if (!szName || !ppFilter) 
    {
        return E_POINTER;
    }

    // システム デバイス列挙子を作成する。
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
        IID_ICreateDevEnum, (void**)&pDevEnum);
    if (FAILED(hr))
    {
        return hr;
    }

    // 指定されたカテゴリのクラス列挙子を作成する。
    hr = pDevEnum->CreateClassEnumerator(guidCategory, &pEnum, 0);
    pDevEnum->Release();
    if (hr != S_OK) // S_FALSE は、カテゴリが空であることを意味する。
    {
        return E_FAIL;
    }

    // このカテゴリ内のデバイスを列挙する。
    bool bFound = false;
    IMoniker *pMoniker;
    while (!bFound && (S_OK == pEnum->Next(1, &pMoniker, 0)))
    {
        IPropertyBag *pBag = NULL;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
        if (FAILED(hr))
        {
            pMoniker->Release();
            continue; // 次は正しく動く可能性がある。
        }
        // フレンドリ名を調べる。
        VARIANT var;
        VariantInit(&var);
        hr = pBag->Read(L"FriendlyName", &var, NULL);
        if (SUCCEEDED(hr) && (lstrcmpiW(var.bstrVal, szName) == 0))
        {
            // このフィルタは正しい。
            hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter,
                (void**)ppFilter);
            bFound = true;
        }
        VariantClear(&var);
        pBag->Release();
        pMoniker->Release();
    }
    pEnum->Release();
    return (bFound ? hr : E_FAIL);
}

次のサンプル コードは、この関数を使って CC デコーダ フィルタを作成し、フィルタ グラフに追加する。

IBaseFilter *pCC = NULL;
hr = CreateKernelFilter(AM_KSCATEGORY_VBICODEC, 
    OLESTR("CC Decoder"), &pCC);
if (SUCCEEDED(hr))
{
    hr = pGraph->AddFilter(pCC, L"CC Decoder");
    pCC->Release();
}

参照