Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

357 lines
8.4 KiB

/*++
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 ([email protected])
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<dwBaseCnt)&&(dwIdx<dwNewBaseCnt);dwIdx++) {
pNew[dwIdx].Attach(&(*ppBase)[dwIdx]);
}
delete[] *ppBase;
*ppBase = pNew;
return (S_OK);
}
static HRESULT ReallocCComVariant(CComVariant **ppBase,
DWORD dwBaseCnt,
CComVariant *pAdd,
DWORD dwAddCnt) {
HRESULT hrRes;
hrRes = ReallocCComVariant(ppBase,dwBaseCnt,dwBaseCnt+dwAddCnt);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
for (DWORD dwIdx=0;dwIdx<dwAddCnt;dwIdx++) {
(*ppBase)[dwIdx+dwBaseCnt].Attach(&pAdd[dwIdx]);
}
return (S_OK);
}
CDictItemNameList::CDictItemNameList(ISEODictionary *piFrom) {
HRESULT hrRes;
m_dwCount = 0;
m_aNames = NULL;
if (piFrom) {
CComPtr<IUnknown> pUnkEnum;
hrRes = piFrom->get__NewEnum(&pUnkEnum);
if (SUCCEEDED(hrRes)) {
CComQIPtr<IEnumVARIANT,&IID_IEnumVARIANT> 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<dwCnt;dwIdx++) {
hrRes = m_aNames[dwIdx+m_dwCount].ChangeType(VT_BSTR);
_ASSERTE(SUCCEEDED(hrRes));
if (!SUCCEEDED(hrRes)) {
// Ack! Ok - just drop this name off the list by moving the last name
// on the list to this position, and fiddling the indexes so that we
// attemp to convert this position again.
if (dwIdx<dwCnt-1) {
m_aNames[dwIdx+m_dwCount].Attach(&m_aNames[dwCnt+m_dwCount-1]);
}
dwIdx--;
dwCnt--;
}
}
m_dwCount += dwCnt;
}
}
}
}
}
CDictItemNameList::~CDictItemNameList() {
delete[] m_aNames;
m_dwCount = 0;
m_aNames = NULL;
}
CSEOBaseDispatcher::CSEOBaseDispatcher() {
m_apbBindings = NULL;
m_dwBindingsCount = 0;
}
CSEOBaseDispatcher::~CSEOBaseDispatcher() {
while (m_dwBindingsCount) {
delete m_apbBindings[--m_dwBindingsCount];
}
delete[] m_apbBindings;
m_apbBindings = NULL;
}
HRESULT STDMETHODCALLTYPE CSEOBaseDispatcher::SetContext(ISEORouter *piRouter, ISEODictionary *pdictBP) {
HRESULT hrRes;
CComPtr<ISEODictionary> 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<dinlBindings.m_dwCount;m_dwBindingsCount++) {
CComPtr<ISEODictionary> 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;dwIdx<m_dwBindingsCount;dwIdx++) {
if (!m_apbBindings[dwIdx]->m_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);
}