|
|
//---------------------------------------------------------------------------
//
// 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<cDispids; i++) { hrEach = CheckAndPrefixExtID( dwExtensionID, rgDispids[i], rgDispids+i );
if (FAILED(hrEach)) { hrAll = E_FAIL;
//
// The entire operation is considered as failure as a whole.
// But continue to get other dispid s.t. debugger or user knows
// which dispid in the array is causing problem -> 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
}
|