Метод 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 (в таких случаях "must succeed" означает "должен успешно, за исключением катастрофического сбоя).
- Набор интерфейсов, доступных для объекта через QueryInterface , должен быть статическим, а не динамическим. Это означает, что если вызов QueryInterface для указателя на указанный интерфейс выполняется успешно в первый раз, то он должен быть выполнен снова. Если вызов завершается сбоем в первый раз, он должен завершиться ошибкой во всех последующих вызовах.
- Он должен быть рефлексивным— если клиент содержит указатель на интерфейс в объекте и клиент запрашивает этот интерфейс, вызов должен завершиться успешно.
- Он должен быть симметричным. Если клиент, содержащий указатель на один интерфейс, успешно выполняет запрос к другому интерфейсу, запрос через полученный указатель для первого интерфейса должен завершиться успешно.
- Он должен быть транзитивным. Если клиент, содержащий указатель на один интерфейс, успешно запрашивает второй интерфейс, а с помощью этого указателя успешно запрашивает третий интерфейс, запрос первого интерфейса через указатель для третьего интерфейса должен завершиться успешно.
Примечания для разработчиков
Реализации QueryInterface никогда не должны проверка списков управления доступом. Main причина этого правила заключается в том, что COM требует, чтобы объект, поддерживающий определенный интерфейс, всегда возвращал успешное выполнение при запросе для этого интерфейса. Другая причина заключается в том, что проверка списков управления доступом в QueryInterface не обеспечивает реальную безопасность, так как любой клиент, имеющий доступ к определенному интерфейсу, может передать его непосредственно другому клиенту без обратных вызовов к серверу. Кроме того, поскольку COM кэширует указатели интерфейса, он не вызывает QueryInterface на сервере каждый раз, когда клиент выполняет запрос.
Требования
Требование | Значение |
---|---|
Минимальная версия клиента | Windows 2000 Professional [только классические приложения] |
Минимальная версия сервера | Windows 2000 Server [только классические приложения] |
Целевая платформа | Windows |
Header | unknwn.h |