Поделиться через


Метод IUnknown::QueryInterface(REFIID,void**) (unknwn.h)

Запрашивает COM-объект для указателя на один из его интерфейсов; определение интерфейса по ссылке на его идентификатор интерфейса (IID). Если com-объект реализует интерфейс, он возвращает указатель на этот интерфейс после вызова IUnknown::AddRef на нем.

Синтаксис

HRESULT QueryInterface(
  REFIID riid,
  void   **ppvObject
);

Параметры

riid

Тип: REFIID

Ссылка на идентификатор интерфейса (IID) запрашиваемого интерфейса.

ppvObject

Тип: void**

Адрес указателя на интерфейс с iiD, указанным в параметре riid. Так как вы передаете адрес указателя интерфейса, метод может перезаписать этот адрес указателем на запрашиваемый интерфейс. При успешном возвращении *ppvObject (адрес, разыменованный адрес) содержит указатель на запрошенный интерфейс. Если объект не поддерживает интерфейс, метод задает *ppvObject (адрес разыменования) для nullptr.

Возвращаемое значение

Этот метод возвращает S_OK, если интерфейс поддерживается, и E_NOINTERFACE в противном случае. Если ppvObject (адрес) nullptr, этот метод возвращает E_POINTER.

Замечания

Для любого заданного COM-объекта (также известного как COM-компонент), определенный запрос к интерфейсу IUnknown на любом из интерфейсов объекта всегда должен возвращать одно и то же значение указателя. Это позволяет клиенту определить, указывают ли два указателя на один компонент, вызывая QueryInterface с IID_IUnknown и сравнивая результаты. В частности, это не так, что запросы к интерфейсам, отличным от IUnknown (даже один и тот же интерфейс через тот же указатель), должны возвращать то же значение указателя.

Существует четыре требования к реализации QueryInterface (в этих случаях "необходимо выполнить успешно" означает "должен завершиться ошибкой".

  • Набор интерфейсов, доступных для объекта через QueryInterface, должен быть статическим, а не динамическим. Это означает, что если вызов QueryInterface для указателя на указанный интерфейс успешно выполняется в первый раз, то он должен выполниться повторно. Если вызов завершается сбоем в первый раз, он должен завершиться сбоем во всех последующих вызовах.
  • Он должен быть рефлексивным— если клиент содержит указатель на интерфейс в объекте, а клиент запрашивает этот интерфейс, то вызов должен завершиться успешно.
  • Он должен быть симметричным— если клиент, содержащий указатель на один запрос интерфейса успешно для другого, запрос через полученный указатель для первого интерфейса должен завершиться успешно.
  • Он должен быть транзитивным— если клиент, содержащий указатель на один запрос интерфейса, успешно выполняется в секунду, а через запросы указателя успешно выполняется для третьего интерфейса, то запрос первого интерфейса через указатель для третьего интерфейса должен завершиться успешно.

Заметки для разработчиков

Реализации QueryInterface никогда не должны проверять списки управления доступом. Основной причиной этого правила является то, что COM требует, чтобы объект, поддерживающий конкретный интерфейс, всегда возвращал успех при запросе для этого интерфейса. Другая причина заключается в том, что проверка списков управления доступом на QueryInterface не обеспечивает никакой реальной безопасности, так как любой клиент, имеющий доступ к конкретному интерфейсу, может передавать его непосредственно другому клиенту без каких-либо вызовов к серверу. Кроме того, так как указатели интерфейса COM кэшируются, он не вызывает QueryInterface на сервере каждый раз, когда клиент выполняет запрос.

Требования

Требование Ценность
минимальные поддерживаемые клиентские Windows 2000 Профессиональный [только классические приложения]
минимальный поддерживаемый сервер Windows 2000 Server [только классические приложения]
целевая платформа Виндоус
заголовка unknwn.h

См. также