Почему CoCreateInstance может возвращать два разных HRESULT в одном и том же контексте? - PullRequest
0 голосов
/ 21 февраля 2019

Я хочу использовать DSound Audio Render в одном из моих приложений, поэтому я загружаю его с CoCreateInstance .Согласно моему предыдущему вопросу , CoCreateInstance может вернуть REGDB_E_CLASSNOTREG, если у меня не установлено звуковое оборудование.Но если я позвоню CoCreateInstance во второй раз, у меня не будет такой же HRESULT.Вот небольшой пример (чтобы воспроизвести его, вы должны отключить все ваши аудиоустройства в диспетчере устройств 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();
}

Я получаю такой результат:

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

Первый код ошибки 0x80040154 соответствует REGDB_E_CLASSNOTREG, поэтому он соответствует ответу , который я получил в моем предыдущем вопросе, но второй код ошибки 0x80040256 соответствует VFW_E_NO_AUDIO_HARDWARE.Согласно MSDN :

VFW_E_NO_AUDIO_HARDWARE
0x80040256

Невозможно воспроизвести аудиопоток: нет звукового оборудования илиаппаратное обеспечение не поддерживается.

Так почему у меня появляется значимая ошибка только во второй раз, когда я звоню CoCreateInstance?Что я могу изменить, чтобы иметь эту ошибку при первом вызове?

1 Ответ

0 голосов
/ 21 февраля 2019

Если вы хотите документированного и последовательного поведения, вам не следует срезать углы и идти по предлагаемым линиям: Использование системного перечислителя устройств .

Перечисление устройств в категории аудио-рендерераВы получите объект-моникер для «устройства DirectSound по умолчанию», а затем ваш IMoniker::BindToObject приведет к значимому VFW_E_NO_AUDIO_HARDWARE (как при первом вызове, так и при последующих).

Вы также можете увидеть это в действии без написания кода: вы можете использовать приложение GraphStudioNext, меню «График», «Вставить фильтр», «Аудио рендереры» в поле со списком, а затем дважды щелкнуть по записи «Устройство DirectSound по умолчанию», пытаясьдля создания экземпляра фильтра.

Что касается вопроса о слогане о различных кодах, вот мое обоснованное предположение.Код ошибки в конечном итоге исходит от программного обеспечения.У вас была возможность увидеть, что COM-сервер присутствует в системе, поэтому подсистема COM запускает инстанцирование, затем происходит сбой в середине и пересылает вам код ошибки обратно.Вполне вероятно, что COM-сервер имеет одноэлементное или иным образом кэшированное перечисление оборудования.При первой попытке он сталкивается с условием «нет устройств» во время инициализации и прерывает создание экземпляра на более раннем этапе, поэтому COM сообщает о неспособности создать экземпляр.В следующий раз, когда сервер уже увидит свое кэшированное перечисление (то есть это не «точно такой же контекст», как вы предполагали) и пропустит начальную точку отказа, но затем снова наткнется на следующую проверку.

Вы ничего не можете с этим поделать, тем более что вы должны были сначала создать CLSID_DSoundRender по-другому.

...