Why CoCreateInstance can return two different HRESULT in the exact same context?

1

I want to use DSound Audio Render in one of my application so I load it with CoCreateInstance. According to my previous question, CoCreateInstance can return REGDB_E_CLASSNOTREG if I have no audio hardware installed. But if I call CoCreateInstance a second time, I doesn't have the same HRESULT. Here is a little example (to reproduce it, you should disable all of your audio devices in the device manager of Windows):

#include <iostream>
#include <strmif.h>
#include <uuids.h>

int main()
{
    std::cout << "Start" << std::endl;

    HRESULT hr = CoInitialize(NULL);

    printf("CoInitialize = 0x%x\n", hr);

    IBaseFilter* ptr = NULL;
    hr = CoCreateInstance(CLSID_DSoundRender, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&ptr);

    printf("CoCreateInstance = 0x%x\n", hr);

    if(ptr)
        ptr->Release();

    hr = CoCreateInstance(CLSID_DSoundRender, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&ptr);

    printf("CoCreateInstance = 0x%x\n", hr);

    if(ptr)
        ptr->Release();

    CoUninitialize();

    std::cout << "End" << std::endl;

    std::cin.get();
}

I get this result:

Start
CoInitialize = 0x0
CoCreateInstance = 0x80040154
CoCreateInstance = 0x80040256
End

The first error code 0x80040154 corresponds to REGDB_E_CLASSNOTREG so it is coherent with the answer I got in my previous question but the second error code 0x80040256 corresponds to VFW_E_NO_AUDIO_HARDWARE. According to MSDN:

VFW_E_NO_AUDIO_HARDWARE
0x80040256

Cannot play back the audio stream: no audio hardware is available, or the hardware is not supported.

So why do I have the meaningful error only the second time I call CoCreateInstance? What can I change to have this error at the first call?

c++
com
directshow
asked on Stack Overflow Feb 21, 2019 by Pierre • edited Feb 21, 2019 by Pierre

1 Answer

2

If you want documented and consistent behavior then you should not cut corners and go along suggested lines, which are: Using the System Device Enumerator.

Enumeration of devices in audio renderer category will get you a moniker object for "Default DirectSound Device" and then your IMoniker::BindToObject would result in meaningful VFW_E_NO_AUDIO_HARDWARE (both on the first call and the following ones).

You can also see this in action without writing code: you can use GraphStudioNext app, menu Graph, Insert Filter, "Audio Renderers" category in the combo box, then double click on "Default DirectSound Device" entry trying to instantiate the filter.

As for the tagline question about different codes, here is my educated guess. The error code eventually comes from software. You had a chance to see that COM server is present in the system, so COM subsystem does start instantiation, then fails in the middle and forwards you the failure code back. It is likely that COM server has a singleton or otherwise a cached enumeration of hardware. In your first attempt it hits "no devices" condition during initialization and aborts instantiation at an earlier step, so COM reports inability to create an instance. Next time the server already sees its cached enumeration (that is, it is not "exactly the same context" as you assumed) and skips the initial failure point, but then again stumbles on a next check.

There is nothing you can do about this, especially that you were supposed to instantiate CLSID_DSoundRender differently in first place.

answered on Stack Overflow Feb 21, 2019 by Roman R. • edited Feb 21, 2019 by Roman R.

User contributions licensed under CC BY-SA 3.0