/*++ Copyright (c) 1996 Microsoft Corporation Module Name: dispatch.cpp Abstract: This module contains the implementation for the Server Extension Object Dispatcher service. Author: Andy Jacobs (andyj@microsoft.com) Revision History: andyj 11/26/96 created --*/ #include "stdafx.h" #include "seo.h" #include "dispatch.h" class CDictItemNameList { public: CDictItemNameList(ISEODictionary *piFrom); ~CDictItemNameList(); public: DWORD m_dwCount; CComVariant *m_aNames; }; static HRESULT ReallocCComVariant(CComVariant **ppBase, DWORD dwBaseCnt, DWORD dwNewBaseCnt) { CComVariant *pNew = NULL; if (dwBaseCnt == dwNewBaseCnt) { return (S_OK); } if (!dwNewBaseCnt) { delete[] *ppBase; *ppBase = NULL; return (S_OK); } ATLTRY(pNew = new CComVariant[dwNewBaseCnt];) _ASSERTE(pNew); if (!pNew) { return (E_OUTOFMEMORY); } for (DWORD dwIdx=0;(dwIdx pUnkEnum; hrRes = piFrom->get__NewEnum(&pUnkEnum); if (SUCCEEDED(hrRes)) { CComQIPtr pevEnum(pUnkEnum); if (pevEnum) { while (1) { CComVariant aNew[20]; DWORD dwCnt; hrRes = pevEnum->Next(sizeof(aNew)/sizeof(aNew[0]),aNew,&dwCnt); if (!SUCCEEDED(hrRes)) { break; } if (!dwCnt) { break; } hrRes = ReallocCComVariant(&m_aNames,m_dwCount,aNew,dwCnt); if (!SUCCEEDED(hrRes)) { break; } for (DWORD dwIdx=0;dwIdx pdictBindings; _ASSERT(!m_dwBindingsCount&&!m_apbBindings); hrRes = pdictBP->GetInterfaceA(BD_BINDINGS,IID_ISEODictionary,(IUnknown **) &pdictBindings); if (SUCCEEDED(hrRes)) { CDictItemNameList dinlBindings(pdictBindings); if (dinlBindings.m_dwCount) { m_apbBindings = new CBinding *[dinlBindings.m_dwCount]; if (!m_apbBindings) { return (E_OUTOFMEMORY); } memset(m_apbBindings,0,sizeof(CBinding *)*dinlBindings.m_dwCount); for (m_dwBindingsCount=0;m_dwBindingsCount pdictBinding; pdictBinding.Release(); hrRes = pdictBindings->GetInterfaceW(dinlBindings.m_aNames[m_dwBindingsCount].bstrVal, IID_ISEODictionary, (IUnknown **) &pdictBinding); _ASSERT(SUCCEEDED(hrRes)); if (SUCCEEDED(hrRes)) { hrRes = AllocBinding(pdictBinding,&m_apbBindings[m_dwBindingsCount]); _ASSERT(SUCCEEDED(hrRes)); } } qsort(m_apbBindings,m_dwBindingsCount,sizeof(m_apbBindings[0]),comp_binding); } } if (SUCCEEDED(hrRes)) { m_piRouter = piRouter; m_pdictBP = pdictBP; } return (hrRes); } static HRESULT GetCLSIDFromBinding(LPCSTR pszCLSID, LPCSTR pszProgID, ISEODictionary *piBinding, CLSID *pclsid) { HRESULT hrRes; CComVariant varTmp; if (!piBinding) { return (E_POINTER); } if (pszCLSID) { hrRes = piBinding->GetVariantA(pszCLSID,&varTmp); if (SUCCEEDED(hrRes)) { hrRes = varTmp.ChangeType(VT_BSTR); if (SUCCEEDED(hrRes)) { hrRes = CLSIDFromString(varTmp.bstrVal,pclsid); if (SUCCEEDED(hrRes)) { return (hrRes); } } } varTmp.Clear(); } if (!pszProgID) { return (E_FAIL); // tbd - come up with a better error code } hrRes = piBinding->GetVariantA(pszProgID,&varTmp); if (!SUCCEEDED(hrRes)) { return (hrRes); } hrRes = varTmp.ChangeType(VT_BSTR); if (!SUCCEEDED(hrRes)) { return (hrRes); } hrRes = CLSIDFromProgID(varTmp.bstrVal,pclsid); return (hrRes); } HRESULT CSEOBaseDispatcher::CBinding::Init(ISEODictionary *piBinding) { HRESULT hrRes; CComVariant varTmp; CLSID clsidTmp; if (!piBinding) { return (E_POINTER); } // Try to get the CLSID of the object - if an error occurs, // this binding is invalid. hrRes = GetCLSIDFromBinding(BD_OBJECT,BD_PROGID,piBinding,&m_clsidObject); if (!SUCCEEDED(hrRes)) { return (S_FALSE); } // From this point on, all errors are silently ignored - we // use default values if we can't get something from the binding // database. hrRes = piBinding->GetVariantA(BD_PRIORITY,&varTmp); if (SUCCEEDED(hrRes)) { hrRes = varTmp.ChangeType(VT_I4); if (SUCCEEDED(hrRes)) { m_dwPriority = (DWORD) varTmp.lVal; } } if (!SUCCEEDED(hrRes)) { // If the priority isn't set, default to "last". m_dwPriority = (DWORD) -1; } varTmp.Clear(); m_piBinding = piBinding; // Try to get an instance of the rule engine. hrRes = GetCLSIDFromBinding(BD_RULEENGINE,NULL,piBinding,&clsidTmp); if (SUCCEEDED(hrRes)) { hrRes = CoCreateInstance(clsidTmp, NULL, CLSCTX_ALL, IID_ISEOBindingRuleEngine, (LPVOID *) &m_piRuleEngine); } // See if the 'exclusive' flag has been set. m_bExclusive = FALSE; hrRes = piBinding->GetVariantA(BD_EXCLUSIVE,&varTmp); if (SUCCEEDED(hrRes)) { hrRes = varTmp.ChangeType(VT_BOOL); if (SUCCEEDED(hrRes)) { if (varTmp.boolVal) { m_bExclusive = TRUE; } } else { hrRes = varTmp.ChangeType(VT_I4); if (SUCCEEDED(hrRes)) { if (varTmp.lVal) { m_bExclusive = TRUE; } } } } varTmp.Clear(); m_bValid = TRUE; return (S_OK); } int CSEOBaseDispatcher::CBinding::Compare(const CBinding& b) const { if (m_dwPriority == b.m_dwPriority) { return (0); } else { return ((m_dwPriority>b.m_dwPriority)?1:-1); } } HRESULT CSEOBaseDispatcher::AllocBinding(ISEODictionary *pdictBinding, CBinding **ppbBinding) { HRESULT hrRes; if (!ppbBinding) { return (E_POINTER); } *ppbBinding = new CBinding; if (!*ppbBinding) { return (E_OUTOFMEMORY); } hrRes = (*ppbBinding)->Init(pdictBinding); if (!SUCCEEDED(hrRes)) { delete *ppbBinding; *ppbBinding = NULL; } return (hrRes); } static int _cdecl comp_binding(const void *pv1, const void *pv2) { const CSEOBaseDispatcher::CBinding **ppb1 = (const CSEOBaseDispatcher::CBinding **) pv1; const CSEOBaseDispatcher::CBinding **ppb2 = (const CSEOBaseDispatcher::CBinding **) pv2; return ((*ppb1)->Compare(**ppb2)); } HRESULT CSEOBaseDispatcher::Dispatch(CEventParams *pEventParams) { BOOL bObjectCalled = FALSE; HRESULT hrRes; for (DWORD dwIdx=0;dwIdxm_bValid) { continue; } if (m_apbBindings[dwIdx]->m_bExclusive && bObjectCalled) { continue; } hrRes = pEventParams->CheckRule(*m_apbBindings[dwIdx]); if (hrRes == S_OK) { hrRes = pEventParams->CallObject(*m_apbBindings[dwIdx]); if ((hrRes == SEO_S_DONEPROCESSING) || m_apbBindings[dwIdx]->m_bExclusive) { break; } } } return (S_OK); }