# V1114. Suspicious use of type conversion operator when working with COM interfaces. Consider using the 'QueryInterface' member function.

Анализатор обнаружил подозрительное использование оператора преобразования типов при работе с COM-интерфейсами.

При такой работе может возникнуть ряд проблем. Вот некоторые из них:

- Не произойдет увеличения счётчика ссылок.
- Возможно преобразование в несовместимый тип или интерфейс. Например, при множественном наследовании, или после изменения версии интерфейса.
- Возможно нарушение совместимости на уровне ABI.

Правильным способом работы c COM-интерфейсами является использование функции 'QueryInterface', которая специально предназначена для этого. Причина в том, что COM – независимая от языка программирования технология. COM-объекты могут быть реализованы на языках программирования, отличных от C++, а также находиться в адресных пространствах, отличных от адресного пространства вызывающего процесса.

Функция 'QueryInterface' должна:

- проверять, что к запрашиваемому интерфейсу можно получить доступ;
- возвращать указатель на запрашиваемый интерфейс;
- увеличивать счётчик ссылок на объект.

Рассмотрим синтетический пример ошибки. Допустим, в коде есть COM-интерфейсы 'IDraw' и 'IShape', которые отвечают за работу с некой геометрической фигурой:

    interface IDraw : public IUnknown
    {
      ....
      virtual HRESULT Draw() = 0;
      ....
    };

    interface IShape : public IUnknown
    {
      ....
      virtual HRESULT GetArea(double *area) = 0;
      ....
    };

Также у нас есть COM-объект 'Circle', который имплементирует интерфейсы 'IDraw' и 'IShape':

    class Circle : public IDraw, public IShape
    {
      ....
    };

Теперь рассмотрим пример неправильной работы с нашим COM-объектом через интерфейс 'IDraw':

    void foo(IDraw *ptrIDraw)
    {
      IShape *ptrIShape = dynamic_cast<IShape*>(ptrIDraw);
      ....
      if (ptrIShape)
        ptrIShape->GetArea(area);
      ....
    }

В примере выше не произойдет увеличение счётчика ссылок на объект типа 'Circle'. Для увеличения и уменьшения счётчика должны зваться функции 'AddRef' и 'Release' соответственно. Поэтому будет правильно воспользоваться функцией 'QueryInterface', которая сама контролирует механизм счётчика ссылок.

Таким образом, корректный код выглядит так:

    void foo(IDraw *ptrIDraw)
    {
      IShape *ptrIShape = nullptr;
      ....
      if (SUCCEEDED(ptrIDraw->QueryInterface(IID_IShape, &ptrIShape))
      ....
    }

Данная диагностика классифицируется как:

CWE-911

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V1114.