Search code examples
c++winapiaudiodirectshowwasapi

IMMDevice::Activate() with IBaseFilter return REGDB_E_CLASSNOTREG Class not registered


I want to get interface IBaseFilter system mixer, but get an error REGDB_E_CLASSNOTREG Class not registered in:

hr = pEndpoint->Activate(__uuidof(IBaseFilter), CLSCTX_ALL, /*&var*/ NULL, (void**)ppFilter);

Earlier this code to work.

Fully code:

filterName = "Stereo mixer (IDT High Definition Audio CODEC)"

HRESULT CCapture::GetAudioCaptureFilterByName(wstring *filterName, IBaseFilter **ppFilter)
{
    HRESULT hr = S_OK;
    IMMDeviceEnumerator *pEnumerator = 0;
    IMMDeviceCollection *pCollection = 0;
    IMMDevice *pEndpoint = 0;
    IPropertyStore *pProps = 0;
    LPWSTR pwszID = 0;

    hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
    if (FAILED(hr)) return hr;

    hr = pEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &pCollection);
    if (FAILED(hr))
    {
        if (pEnumerator) pEnumerator->Release();
        return hr;
    }

    UINT  count;
    hr = pCollection->GetCount(&count);
    if (FAILED(hr))
    {
        if (pCollection) pCollection->Release();
        if (pEnumerator) pEnumerator->Release();
        return hr;
    }

    if (count == 0)
    {
        if (pCollection) pCollection->Release();
        if (pEnumerator) pEnumerator->Release();
        return hr;
    }

    for (ULONG i = 0; i < count; i++)
    {
        hr = pCollection->Item(i, &pEndpoint);
        if (FAILED(hr))
        {
            if (pCollection) pCollection->Release();
            if (pEnumerator) pEnumerator->Release();
            return hr;
        }

        // Получаем ID устройства.
        hr = pEndpoint->GetId(&pwszID);
        if (FAILED(hr))
        {
            if (pEndpoint) pEndpoint->Release();
            if (pCollection) pCollection->Release();
            if (pEnumerator) pEnumerator->Release();
            return hr;
        }

        hr = pEndpoint->OpenPropertyStore(STGM_READ, &pProps);
        if (FAILED(hr))
        {
            CoTaskMemFree(pwszID);
            if (pEndpoint) pEndpoint->Release();
            if (pCollection) pCollection->Release();
            if (pEnumerator) pEnumerator->Release();
            return hr;
        }

        PROPVARIANT varName;
        PropVariantInit(&varName);

        // Получаем дружественное имя устройства.
        hr = pProps->GetValue(PKEY_Device_FriendlyName, &varName);
        if (FAILED(hr))
        {
            CoTaskMemFree(pwszID);
            if (pProps) pProps->Release();
            if (pEndpoint) pEndpoint->Release();
            if (pCollection) pCollection->Release();
            if (pEnumerator) pEnumerator->Release();
            return hr;
        }


        wstring *wstr = new wstring(varName.pwszVal);
        if (wstr->compare(*filterName) == 0)
        {
            DIRECTX_AUDIO_ACTIVATION_PARAMS  daap;
            daap.cbDirectXAudioActivationParams = sizeof(daap);
            daap.guidAudioSession = guidAudioSessionId;
            daap.dwAudioStreamFlags = AUDCLNT_STREAMFLAGS_CROSSPROCESS;

            PROPVARIANT var;
            PropVariantInit(&var);

            var.vt = VT_BLOB;
            var.blob.cbSize = sizeof(daap);
            var.blob.pBlobData = (BYTE*)&daap;

            hr = pEndpoint->Activate(__uuidof(IBaseFilter), CLSCTX_ALL, /*&var*/ NULL, (void**)ppFilter);

            delete wstr;
            CoTaskMemFree(pwszID);
            PropVariantClear(&varName);

            if (pProps) pProps->Release();
            if (pEndpoint) pEndpoint->Release();
            if (pCollection) pCollection->Release();
            if (pEnumerator) pEnumerator->Release();

            return hr;
        }

        delete wstr;
        CoTaskMemFree(pwszID);
        pwszID = NULL;
        PropVariantClear(&varName);
        if (pProps) pProps->Release();
        if (pEndpoint) pEndpoint->Release();
        pProps = 0;
        pEndpoint = 0;
    }

    hr = E_FAIL;
    if (pProps) pProps->Release();
    if (pEndpoint) pEndpoint->Release();
    if (pCollection) pCollection->Release();
    if (pEnumerator) pEnumerator->Release();

    return hr;
}

Solution

  • The problem is caused by conflict with installed DirectShowSpy tool.

    MMDevice's Activate for IBaseFilter presumably does the following:

    if(interface is IBaseFilter)
    {
      IMMDeviceActivator pMmDeviceActivator;
      CoCreateInstace(CLSID_SystemDeviceEnum, ..., &pMmDeviceActivator);
      return pMmDeviceActivator->Activate(pMmDevice, ...)
    }
    

    Implementation of IMMDeviceActivator by System Device Enumerator CLSID_SystemDeviceEnum is undocumented (the interface is reserved for internal use) and DirectShowSpy did not handle it well. Since version 1.0.0.2106 it does it right.