IUnknown::QueryInterface

HRESULT IUnknown::QueryInterface(iid, ppv)

Return a pointer within this object instance that implements the indicated interface. Answer NULL if the receiver does not contain an implementation of the interface.

It is required that any query for the specific interface IUnknown 7. always returns the same actual pointer value, no matter through which interface derived from IUnknown it is called. This enables the following identity test algorithm to determine whether two pointers in fact point to the same object: call QueryInterface(IID_IUnknown, ...) on both and compare the results.

In contrast, queries for interfaces other than IUnknown are not required to return the same actual pointer value each time a QueryInterface returning one of them is called. This, among other things, enables sophisticated object implementors to free individual interfaces on their objects when they are not being used, recreating them on demand (reference counting is a per-interface notion, as is explained further below). This requirement is the basis for what is called COM identity.

It is required that the set of interfaces accessible on an object via QueryInterface be static, not dynamic, in the following precise sense.8. Suppose we have a pointer to an interface


   ISomeInterface * psome = (some function returning an ISomeInterface *);

where ISomeInterface derives from IUnknown. Suppose further that the following operation is attempted:


IOtherInterface * pother;
HRESULT   hr;
hr=psome->QueryInterface(IID_IOtherInterface, &pother);      //line 4

Then, the following must be true:

Furthermore, QueryInterface must be reflexive, symmetric, and transitive with respect to the set of interfaces that are accessible. That is, given the above definitions, then we have the following:

Statement

Logic

Symmetric:

psome->QueryInterface(IID_ISomeInterface, ...) must succeed

Reflexive:

If in line 4, pother was successfully obtained, then pother->QueryInterface(IID_ISomeInterface, ...) must succeed.

Transitive:

If in line 4, pother was successfully obtained, and we do IYetAnother * pyet; pother->QueryInterface(IID_IYetAnother, &pyet); //Line 7 and pyet is successfully obtained in line 7, then pyet->QueryInterface(IID_ISomeInterface, ...) must succeed.


Here, "must succeed" means "must succeed barring catastrophic failures." As was mentioned above, it is specifically not the case that two QueryInterface calls on the same pointer asking for the same interface must succeed and return exactly the same pointer value (except in the IUnknown case as described previously).

Argument

Type

Description

iid

REFIID

The interface identifier desired.

ppv

void**

Pointer to the object with the desired interface. In the case that the interface is not supported or another error occurred, *ppv must be set to NULL.


Return Value

Meaning

S_OK

Success. The interface is supported

E_NOINTERFACE

The interface is not supported

E_UNEXPECTED

An unknown error occurred.