To locate a service, an ActiveX designer calls the IServiceProvider interface, implemented by its site. The interface has the following definition:
interface IServiceProvider : IUnknown { HRESULT QueryService ( REFGUID rsid, REFIID iid, void ** ppvObj) };
The input parameters to the QueryService method are the SID of the service being requested and the IID of the interface you want to use. In return, you receive a pointer to the requested interface if the host implements the service, or E_NOTIMPL if the host does not implement it.
For example, the following code fragment queries for the SCodeNavigate service. (Error handling has been omitted for brevity.)
hr = pClientSite->QueryInterface(IID_IServiceProvider, &pISP); hr = pISP->QueryService(SID_SCodeNavigate, IID_ICodeNavigate, &pICN);
The example calls QueryInterface on the site to get a pointer to the site's IServiceProvider interface. Using the returned pointer, it passes the SID of the SCodeNavigate service and the IID of the ICodeNavigate interface to QueryService. If the call is successful, QueryService returns a pointer to the ICodeNavigate interface. Through this pointer, the ActiveX designer can invoke the methods defined for ICodeNavigate.
In effect, the site performs the equivalent of the following for each call to QueryService:
pSite->QueryService (SID_SCodeNavigate, IID_IUnknown, &pUnk); pUnk->QueryInterface (IID_ICodeNavigate, &pICN); pUnk->Release();
The ActiveX designer receives a pointer through which it can directly access the requested interface. The site does not have to delegate each individual method call.