//--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1996 // // File: cextmgr.cxx // // Contents: LDAP ExtMgr Object // // // History: 06-15-96 yihsins Created. // //---------------------------------------------------------------------------- #include "nwcompat.hxx" #pragma hdrstop // Class CADsExtMgr CADsExtMgr::CADsExtMgr(): _pClassEntry(NULL), _pDispMgr(NULL) { } HRESULT CADsExtMgr::CreateExtMgr( IUnknown FAR * pUnkOuter, CAggregatorDispMgr * pDispMgr, LPTSTR pszClassName, CADsExtMgr ** ppExtMgr ) { PCLASS_ENTRY pClassEntry = NULL; CADsExtMgr FAR * pExtMgr = NULL; HRESULT hr = S_OK; hr = AllocateExtMgrObject( &pExtMgr ); BAIL_ON_FAILURE(hr); // // Now store the DispatchMgr of the Aggregator // pExtMgr->_pDispMgr = pDispMgr; hr = ADSIGetExtensionList( pszClassName, &(pExtMgr->_pClassEntry) ); if (pExtMgr->_pClassEntry) { hr = ADSILoadExtensions( pUnkOuter, pExtMgr->_pClassEntry ); } *ppExtMgr = pExtMgr; RRETURN(hr); error: *ppExtMgr = NULL; delete pExtMgr; RRETURN(hr); } CADsExtMgr::~CADsExtMgr( ) { // // Free the ClassEntry // if (_pClassEntry) { FreeClassEntry(_pClassEntry); } // // And do nothing with the DispMgr - we just keep a pointer // } STDMETHODIMP CADsExtMgr::QueryInterface(REFIID iid, LPVOID FAR* ppv) { PCLASS_ENTRY pClassEntry = _pClassEntry; IUnknown * pUnknown = NULL; PINTERFACE_ENTRY pIID = NULL; PEXTENSION_ENTRY pExtensionEntry = NULL; HRESULT hr = S_OK; if (!pClassEntry) { RRETURN(E_NOINTERFACE); } pExtensionEntry = pClassEntry->pExtensionHead; while (pExtensionEntry) { pUnknown = pExtensionEntry->pUnknown; pIID = pExtensionEntry->pIID; while (pIID) { if (IsEqualIID(pIID->iid, iid)) { if (!pUnknown) { RRETURN(E_NOINTERFACE); } hr = pUnknown->QueryInterface( iid, ppv ); RRETURN(hr); } pIID = pIID->pNext; } pExtensionEntry = pExtensionEntry->pNext; } RRETURN(hr = E_NOINTERFACE); } HRESULT CADsExtMgr::AllocateExtMgrObject( CADsExtMgr ** ppExtMgr ) { CADsExtMgr FAR * pExtMgr = NULL; HRESULT hr = S_OK; pExtMgr = new CADsExtMgr(); if (pExtMgr == NULL) { hr = E_OUTOFMEMORY; } BAIL_ON_FAILURE(hr); *ppExtMgr = pExtMgr; RRETURN(hr); error: if (pExtMgr) { delete pExtMgr; } RRETURN(hr); } HRESULT ADSILoadExtensionManager( LPWSTR pszClassName, IUnknown * pUnkOuter, CAggregatorDispMgr * pDispMgr, CADsExtMgr ** ppExtMgr ) { HRESULT hr = S_OK; hr = CADsExtMgr::CreateExtMgr( pUnkOuter, pDispMgr, pszClassName, ppExtMgr ); RRETURN(hr); } STDMETHODIMP CADsExtMgr::GetTypeInfoCount( unsigned int FAR* pctinfo ) { RRETURN(E_NOTIMPL); } STDMETHODIMP CADsExtMgr::GetTypeInfo( unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo ) { RRETURN(E_NOTIMPL); } STDMETHODIMP CADsExtMgr::GetIDsOfNames( REFIID iid, LPWSTR FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid ) { HRESULT hr = S_OK; PEXTENSION_ENTRY pExtension = NULL; IPrivateDispatch FAR * pPrivDisp = NULL; hr = _pDispMgr->GetIDsOfNames( iid, rgszNames, cNames, lcid, rgdispid ); if (FAILED(hr)) { if (!_pClassEntry) { RRETURN(DISP_E_UNKNOWNNAME); } pExtension = _pClassEntry->pExtensionHead; while (pExtension) { if (pExtension->fDisp) { // // fDisp = TRUE indicates // 1) extension supports pADsExt AND // 2) either // a) PrivateGetIDsOfNames() does Not return E_NOTIMPL // OR // b) we don't know if a) is true or not yet // ASSERT(pExtension->pADsExt); hr = (pExtension->pADsExt)->PrivateGetIDsOfNames( iid, rgszNames, cNames, lcid, rgdispid ); if (SUCCEEDED(hr)) { // // check & prefix extension id to dispid(s) returned // by extension // hr = CheckAndPrefixExtIDArray( pExtension->dwExtensionID, cNames, rgdispid ); if (SUCCEEDED(hr) ) { RRETURN(hr); } // // if cannot prefix extension id because NOT ALL // dispids returned by PrivateGetIDsOfNames() are // valid, this extension does not support this property // or method -> try next extension // // If the extension returns ANY invalid dispids, then // we treat the extension as invalid. This way, we can // see if a later extension exists that supports this // property or method, instead of just bailing out. // This is important, since there // can be multiple extensions and we are supposed to // "find the first extension which implements a function" // (per ADSI SDK). // } else if (hr == E_NOTIMPL) { // // extension object does not support the optional // IADsExtension::PrivateGetIDsOfNames()/PrivateInvoke() // -> remember this in cache & try next extension object // pExtension->fDisp = FALSE; } else { // // extens'n object supports PrivateGetIDsOfNames()/Invoke() // but does not know about this property or method // -> try next extension object // } } // end "if (pExtension->pADs && pExtension->fDisp)" pExtension = pExtension->pNext; } // end while } // // Unify the final error code retuned to ADSI client to DISP_E_UNKNOWNNAME // if ( FAILED(hr) && hr!=E_OUTOFMEMORY) { hr = DISP_E_UNKNOWNNAME; } RRETURN(hr); } STDMETHODIMP CADsExtMgr::Invoke( DISPID dispidMember, REFIID iid, LCID lcid, unsigned short wFlags, DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo, unsigned int FAR* puArgErr ) { DWORD dwExtensionId = 0; HRESULT hr = S_OK; PEXTENSION_ENTRY pExtension = NULL; IPrivateDispatch * pPrivDisp = NULL; DISPID rgExtDispid = DISPID_UNKNOWN; // // This could be a special dispatch id - pass it to // the aggregator // if (dispidMember <= 0) { hr = _pDispMgr->Invoke( dispidMember, iid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); RRETURN(hr); } // // It is not a special dispatch id, so compute the extension // id and pass it to the appropriate dispatch manager // dwExtensionId = EXTRACT_EXTENSION_ID(dispidMember); if (!dwExtensionId) { hr = _pDispMgr->Invoke( dispidMember, iid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); RRETURN(hr); } if (!_pClassEntry) { RRETURN(DISP_E_MEMBERNOTFOUND); } pExtension = _pClassEntry->pExtensionHead; rgExtDispid = REMOVE_EXTENSION_ID(dispidMember); while (pExtension) { if (dwExtensionId == pExtension->dwExtensionID) { if (pExtension->fDisp) { // // fDisp = TRUE indicates // 1) extension supports pADsExt AND // 2) either // a) PrivateGetIDsOfNames() does Not return E_NOTIMPL // OR // b) we don't know if a) is true or not yet // ASSERT(pExtension->pADsExt); hr = (pExtension->pADsExt)->PrivateInvoke( rgExtDispid, iid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); RRETURN(hr); } else { // // A dwExtensionId match indicates THIS extens'n has returned // a valid dispid to clients thru' pADs->PrivateGetIDsOfNames. // Thus, fDisp should be TURE. // // But since dispid goes thru' clients before passed back to // PrivateInovke(), don't ASSERT in case of clients errors. // RRETURN(DISP_E_MEMBERNOTFOUND); } } pExtension = pExtension->pNext; } // end while RRETURN(DISP_E_MEMBERNOTFOUND); } HRESULT CADsExtMgr::CheckAndPrefixExtIDArray( IN DWORD dwExtensionID, IN unsigned int cDispids, IN OUT DISPID * rgDispids ) { HRESULT hrEach = S_OK; HRESULT hrAll = S_OK; ASSERT_VALID_EXTENSION_ID(dwExtensionID); for (unsigned int i = 0; i DISPID_UNKOWN // } } RRETURN(hrAll); } HRESULT CADsExtMgr::CheckAndPrefixExtID( IN DWORD dwExtensionID, IN DISPID dispid, IN OUT DISPID * pNewDispid ) { ASSERT(pNewDispid); if ( (dispid>= ADS_EXT_MINEXTDISPID) && (dispid<= ADS_EXT_MAXEXTDISPID) ) { *pNewDispid = PREFIX_EXTENSION_ID(dwExtensionID, dispid) ; RRETURN(S_OK); } else { *pNewDispid = DISPID_UNKNOWN; RRETURN(E_FAIL); } } //+------------------------------------------------------------------------ // // Function: CADsExtMgr::FinalInitializeExtensions // // Synopsis: At this point we call Operate on all the extensions // so that they can do initialization stuff that // // // // Arguments: None // // AjayR - added on 1-30-99. //------------------------------------------------------------------------- HRESULT CADsExtMgr::FinalInitializeExtensions() { HRESULT hr = S_OK; PEXTENSION_ENTRY pExtEntry = NULL; VARIANT varDummy; VariantInit(&varDummy); if (!_pClassEntry || !(pExtEntry=_pClassEntry->pExtensionHead) ) { RRETURN(S_OK); } while (pExtEntry) { // // Call operate only if the extension supports the interface // if (pExtEntry->pADsExt) { pExtEntry->pADsExt->Operate( ADS_EXT_INITIALIZE_COMPLETE, varDummy, varDummy, varDummy ); } // // we cannot really do much if there is a failure here // pExtEntry = pExtEntry->pNext; } // end while // // Cannot fail because of one bad extension. // RRETURN(S_OK); // "okay" error if any, optional support }