Platform SDK: Active Directory, ADSI, and Directory Services |
Like the dispatch interface, all dual interfaces must inherit from IDispatch, which delegates all of its IDispatch functions (GetIDsOfNames, Invoke, GetTypeInfo, GetTypeInfoCount) back to the IDispatch of the aggregator (ADSI). To execute the delegation, an extension object should query for the IDispatch of the aggregator (IID_IDispatch, or IID_IADs) from m_pOuterUnknown, and release the pointer after use.
If your extension can be a standalone component, you may want to check if it is being aggregated. If so, you should re-route the dispatch functions to the IDispatch of the aggregator, otherwise you can call your internal implementation of IDispatch, or you can call your implementation of IADsExtension.
The following example shows how to re-route the IDispatch call to the IDispatch of the aggregator:
/////////////////////////////////////////////////// // Delegating IDispatch Methods to the aggregator /////////////////////////////////////////////////// STDMETHODIMP MyExtension::GetTypeInfoCount(UINT* pctinfo) { IDispatch *pDisp; HRESULT hr; hr = OuterQueryInterface( IID_IDispatch, (void**) &pDisp ); if ( SUCCEEDED(hr) ) { hr = pDisp->GetTypeInfoCount( pctinfo ); pDisp->Release(); } return hr; } STDMETHODIMP MyExtension::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) { IDispatch *pDisp; HRESULT hr; hr = OuterQueryInterface( IID_IDispatch, (void**) &pDisp ); if ( SUCCEEDED(hr) ) { hr = pDisp->GetTypeInfo( itinfo, lcid, pptinfo ); pDisp->Release(); } return hr; } STDMETHODIMP MyExtension::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid) { IDispatch *pDisp; HRESULT hr; hr = OuterQueryInterface( IID_IDispatch, (void**) &pDisp ); if ( SUCCEEDED(hr) ) { hr = pDisp->GetIDsOfNames( riid, rgszNames, cNames, lcid, rgdispid); pDisp->Release(); } return hr; } STDMETHODIMP MyExtension::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr) { IDispatch *pDisp; HRESULT hr; hr = OuterQueryInterface( IID_IDispatch, (void**) &pDisp ); if ( SUCCEEDED(hr) ) { hr = pDisp->Invoke( dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); pDisp->Release(); } return hr; }
Extension writers are strongly encouraged to support dual interfaces instead of dispatch interfaces in their extension objects. A dual interface allows a client to have faster access, as long as vtable access is enabled in the client (please see Late Binding vs. Vtable Access in the ADSI Extension Model). Based on our current model, implementing dual interfaces should not be more difficult than implementing dispatch interfaces.