Windows2003-3790/inetsrv/iis/svcs/smtp/aqueue/aqdisp/seolib.cpp
2020-09-30 16:53:55 +02:00

1052 lines
24 KiB
C++

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
seolib.cpp
Abstract:
This module contains the implementations for various
utility classes and functions of the Server Extension
Object system.
Author:
Don Dumitru (dondu@microsoft.com)
Revision History:
dondu 05/20/97 Created.
--*/
#include <stdio.h>
#include <windows.h>
#include <mailmsg.h>
#include <dbgtrace.h>
#include <cpool.h>
#include <filehc.h>
#define _ATL_NO_DEBUG_CRT
#define _ATL_STATIC_REGISTRY 1
#define _ASSERTE _ASSERT
#define _WINDLL
#include "atlbase.h"
extern CComModule _Module;
#include "atlcom.h"
#undef _WINDLL
#include "seo.h"
#include "seolib.h"
CEventBaseDispatcher::CEventBaseDispatcher() {
// nothing
}
CEventBaseDispatcher::~CEventBaseDispatcher() {
// nothing
}
CEventBaseDispatcher::CBinding::CBinding() {
m_bIsValid = FALSE;
}
CEventBaseDispatcher::CBinding::~CBinding() {
// nothing
}
HRESULT CEventBaseDispatcher::CBinding::Init(IEventBinding *piBinding) {
HRESULT hrRes;
CComPtr<IEventPropertyBag> pProps;
CComVariant varValue;
if (!piBinding) {
return (E_POINTER);
}
varValue.vt = VT_BOOL;
hrRes = piBinding->get_Enabled(&varValue.boolVal);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
m_bIsValid = varValue.boolVal ? TRUE: FALSE;
varValue.Clear();
m_dwPriority = (DWORD) PRIO_DEFAULT;
m_bExclusive = FALSE;
m_piBinding = piBinding;
hrRes = piBinding->get_SourceProperties(&pProps);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
hrRes = pProps->Item(&CComVariant(L"Priority"),&varValue);
if (SUCCEEDED(hrRes) && (hrRes != S_FALSE)) {
hrRes = varValue.ChangeType(VT_I4);
if (SUCCEEDED(hrRes)) {
if (varValue.lVal < PRIO_MIN) {
varValue.lVal = PRIO_MIN;
} else if (varValue.lVal > PRIO_MAX) {
varValue.lVal = PRIO_MAX;
}
m_dwPriority = (DWORD) varValue.lVal;
} else {
hrRes = varValue.ChangeType(VT_BSTR);
if (SUCCEEDED(hrRes)) {
static struct {
LPCWSTR pszString;
DWORD dwValue;
} sConvert[] = {{PRIO_HIGHEST_STR,PRIO_HIGHEST},
{PRIO_HIGH_STR,PRIO_HIGH},
{PRIO_MEDIUM_STR,PRIO_MEDIUM},
{PRIO_LOW_STR,PRIO_LOW},
{PRIO_LOWEST_STR,PRIO_LOWEST},
{PRIO_DEFAULT_STR,PRIO_DEFAULT},
{NULL,0}};
for (DWORD dwIdx=0;sConvert[dwIdx].pszString;dwIdx++) {
if (_wcsicmp(varValue.bstrVal,sConvert[dwIdx].pszString) == 0) {
m_dwPriority = sConvert[dwIdx].dwValue;
break;
}
}
}
}
}
varValue.Clear();
hrRes = pProps->Item(&CComVariant(L"Exclusive"),&varValue);
if (SUCCEEDED(hrRes) && (hrRes != S_FALSE)) {
hrRes = varValue.ChangeType(VT_BOOL);
if (SUCCEEDED(hrRes)) {
m_bExclusive = (varValue.boolVal ? TRUE : FALSE);
}
}
hrRes = InitRuleEngine();
// ignore result
return (S_OK);
}
int CEventBaseDispatcher::CBinding::Compare(const CBinding& b) const {
#if 0
if (!m_bIsValid || !b.m_bIsValid) {
if (m_bIsValid == b.m_bIsValid) {
return (0);
}
if (!b.m_bIsValid) {
return (-1);
}
return (1);
}
#endif
if (m_dwPriority == b.m_dwPriority) {
return (0);
}
if (m_dwPriority < b.m_dwPriority) {
return (-1);
}
return (1);
}
HRESULT CEventBaseDispatcher::CBinding::InitRuleEngine(IEventBinding *piBinding, REFIID iidDesired, IUnknown **ppUnkRuleEngine) {
HRESULT hrRes;
CComPtr<IEventPropertyBag> pProperties;
CComVariant varValue;
CStringGUID objGuid;
if (ppUnkRuleEngine) {
*ppUnkRuleEngine = NULL;
}
if (!piBinding || !ppUnkRuleEngine) {
return (E_POINTER);
}
hrRes = piBinding->get_SourceProperties(&pProperties);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
hrRes = pProperties->Item(&CComVariant(L"RuleEngine"),&varValue);
if (!SUCCEEDED(hrRes) || (hrRes == S_FALSE)) {
return (hrRes);
}
hrRes = SEOCreateObject(&varValue,piBinding,pProperties,iidDesired,ppUnkRuleEngine);
return (SUCCEEDED(hrRes)?S_OK:S_FALSE);
}
HRESULT CEventBaseDispatcher::CBinding::InitRuleEngine() {
// default is to not to try to load a rule engine
return (S_OK);
}
int CEventBaseDispatcher::CBindingList::Compare(CBinding* p1, CBinding* p2) {
return (p1->Compare(*p2));
};
HRESULT CEventBaseDispatcher::CParams::CheckRule(CBinding& b) {
// default behavior is to not pay attention to any "rules"
return (S_OK);
}
HRESULT CEventBaseDispatcher::CParams::CallObject(IEventManager *piManager, CBinding& bBinding) {
HRESULT hrRes;
CComPtr<IUnknown> pUnkSink;
if (!piManager) {
return (E_POINTER);
}
hrRes = piManager->CreateSink(bBinding.m_piBinding,NULL,&pUnkSink);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
return (CallObject(bBinding,pUnkSink));
}
HRESULT CEventBaseDispatcher::CParams::CallObject(CBinding& bBinding, IUnknown *pUnkSink) {
HRESULT hrRes;
CComQIPtr<IEventSinkNotify,&IID_IEventSinkNotify> pSink;
CComQIPtr<IDispatch,&IID_IEventSinkNotifyDisp> pSinkDisp;
DISPPARAMS dpNoArgs = {NULL,NULL,0,0};
// Default behavior is to call IEventSinkNotify::OnEvent, or to call
// IEventSinkNotifyDisp::Invoke passing DISPID_VALUE (which maps to OnEvent).
//
// This means that the base dispatcher is able to invoke simple COM objects. If you
// provide your own CallObject() routine, your routine call delegate this this base
// implementation if you want to "inherit" this functionality.
if (!pUnkSink) {
return (E_POINTER);
}
pSink = pUnkSink;
if (!pSink) {
pSinkDisp = pUnkSink;
}
if (!pSink && !pSinkDisp) {
return (E_NOINTERFACE);
}
if (pSink) {
hrRes = pSink->OnEvent();
return (S_OK);
}
hrRes = pSinkDisp->Invoke(DISPID_VALUE,
IID_NULL,
GetUserDefaultLCID(),
DISPATCH_METHOD,
&dpNoArgs,
NULL,
NULL,
NULL);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
return (S_OK);
}
HRESULT CEventBaseDispatcher::CParams::Abort() {
return (S_FALSE);
}
HRESULT CEventBaseDispatcher::Dispatcher(REFGUID rguidEventType, CParams *pParams) {
HRESULT hrRes;
CETData *petdData;
BOOL bObjectCalled = FALSE;
petdData = m_Data.Find(rguidEventType);
if (!petdData) {
return (S_FALSE);
}
for (DWORD dwIdx=0;dwIdx<petdData->Count();dwIdx++) {
if (!petdData->Index(dwIdx)->m_bIsValid) {
continue;
}
if (bObjectCalled && petdData->Index(dwIdx)->m_bExclusive) {
continue;
}
if (pParams->Abort() == S_OK) {
break;
}
hrRes = pParams->CheckRule(*petdData->Index(dwIdx));
if (hrRes == S_OK) {
if (pParams->Abort() == S_OK) {
break;
}
hrRes = pParams->CallObject(m_piEventManager,*petdData->Index(dwIdx));
if (!SUCCEEDED(hrRes)) {
continue;
}
bObjectCalled = TRUE;
if ((hrRes == S_FALSE) || petdData->Index(dwIdx)->m_bExclusive) {
break;
}
}
}
return (bObjectCalled?S_OK:S_FALSE);
}
HRESULT CEventBaseDispatcher::SetContext(REFGUID rguidEventType, IEventRouter *piRouter, IEventBindings *piBindings) {
CETData* petData;
HRESULT hrRes;
CComPtr<IUnknown> pUnkEnum;
CComQIPtr<IEnumVARIANT,&IID_IEnumVARIANT> pEnum;
if (!piRouter || !piBindings) {
return (E_POINTER);
}
if (!m_piEventManager) {
hrRes = CoCreateInstance(CLSID_CEventManager,
NULL,
CLSCTX_ALL,
IID_IEventManager,
(LPVOID *) &m_piEventManager);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
m_piRouter = piRouter;
}
petData = m_Data.Find(rguidEventType);
if (!petData) {
hrRes = AllocETData(rguidEventType,piBindings,&petData);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
petData->m_guidEventType = rguidEventType;
hrRes = m_Data.Add(petData);
if (!SUCCEEDED(hrRes)) {
delete petData;
return (hrRes);
}
}
petData->RemoveAll();
hrRes = piBindings->get__NewEnum(&pUnkEnum);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
pEnum = pUnkEnum;
if (!pEnum) {
return (E_NOINTERFACE);
}
while (1) {
CComVariant varValue;
CComQIPtr<IEventBinding,&IID_IEventBinding> pBinding;
CBinding *pNewBinding;
varValue.Clear();
hrRes = pEnum->Next(1,&varValue,NULL);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
if (hrRes == S_FALSE) {
break;
}
hrRes = varValue.ChangeType(VT_UNKNOWN);
if (!SUCCEEDED(hrRes)) {
_ASSERTE(FALSE);
continue;
}
pBinding = varValue.punkVal;
if (!pBinding) {
_ASSERTE(FALSE);
continue;
}
hrRes = AllocBinding(rguidEventType,pBinding,&pNewBinding);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
hrRes = pNewBinding->Init(pBinding);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
hrRes = petData->Add(pNewBinding);
if (!SUCCEEDED(hrRes)) {
delete pNewBinding;
return (hrRes);
}
}
return (S_OK);
}
CEventBaseDispatcher::CETData::CETData() {
// nothing
}
CEventBaseDispatcher::CETData::~CETData() {
// nothing
}
CEventBaseDispatcher::CETData* CEventBaseDispatcher::CETDataList::Find(REFGUID guidEventType) {
// tbd - optimize
for (DWORD dwIdx=0;dwIdx<Count();dwIdx++) {
if (Index(dwIdx)->m_guidEventType == guidEventType) {
return (Index(dwIdx));
}
}
return (NULL);
}
HRESULT CEventBaseDispatcher::AllocBinding(REFGUID rguidEventType,
IEventBinding *piBinding,
CBinding **ppNewBinding) {
if (ppNewBinding) {
*ppNewBinding = NULL;
}
if (!piBinding || !ppNewBinding) {
return (E_POINTER);
}
*ppNewBinding = new CBinding;
if (!*ppNewBinding) {
return (E_OUTOFMEMORY);
}
return (S_OK);
}
HRESULT CEventBaseDispatcher::AllocETData(REFGUID guidEventType,
IEventBindings *piBindings,
CETData **ppNewETData) {
if (ppNewETData) {
*ppNewETData = NULL;
}
if (!piBindings || !ppNewETData) {
return (E_POINTER);
}
*ppNewETData = new CETData;
if (!*ppNewETData) {
return (E_OUTOFMEMORY);
}
return (S_OK);
}
static HRESULT SEOGetSources(REFGUID rguidSourceType, IEventSources **ppSources) {
HRESULT hrRes;
CComPtr<IEventManager> pManager;
CComPtr<IEventSourceTypes> pSourceTypes;
CComPtr<IEventSourceType> pSourceType;
CComPtr<IEventSources> pSources;
if (ppSources) {
*ppSources = NULL;
}
if (!ppSources) {
hrRes = E_POINTER;
goto error;
}
hrRes = CoCreateInstance(CLSID_CEventManager,NULL,CLSCTX_ALL,IID_IEventManager,(LPVOID *) &pManager);
if (!SUCCEEDED(hrRes)) {
goto error;
}
hrRes = pManager->get_SourceTypes(&pSourceTypes);
if (!SUCCEEDED(hrRes)) {
goto error;
}
hrRes = pSourceTypes->Item(&CComVariant((LPCOLESTR) CStringGUID(rguidSourceType)),&pSourceType);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (!pSourceType) {
hrRes = S_FALSE;
goto error;
}
hrRes = pSourceType->get_Sources(ppSources);
error:
return (hrRes);
}
static HRESULT SEOGetSourcesEnum(REFGUID rguidSourceType, IEnumVARIANT **ppEnum) {
HRESULT hrRes;
CComPtr<IEventSources> pSources;
CComPtr<IUnknown> pUnkEnum;
if (ppEnum) {
*ppEnum = NULL;
}
if (!ppEnum) {
hrRes = E_POINTER;
goto error;
}
hrRes = SEOGetSources(rguidSourceType,&pSources);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (!pSources) {
hrRes = S_FALSE;
goto error;
}
hrRes = pSources->get__NewEnum(&pUnkEnum);
if (!SUCCEEDED(hrRes)) {
goto error;
}
hrRes = pUnkEnum->QueryInterface(IID_IEnumVARIANT,(LPVOID *) ppEnum);
error:
return (hrRes);
}
STDMETHODIMP SEOGetSource(REFGUID rguidSourceType, REFGUID rguidSource, IEventSource **ppSource) {
HRESULT hrRes;
CComPtr<IEventSources> pSources;
if (ppSource) {
*ppSource = NULL;
}
if (!ppSource) {
hrRes = E_POINTER;
goto error;
}
hrRes = SEOGetSources(rguidSourceType,&pSources);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (!pSources) {
hrRes = S_FALSE;
goto error;
}
hrRes = pSources->Item(&CComVariant((LPCOLESTR) CStringGUID(rguidSource)),ppSource);
error:
return (hrRes);
}
STDMETHODIMP SEOGetSource(REFGUID rguidSourceType, REFGUID rguidSourceBase, DWORD dwSourceIndex, IEventSource **ppSource) {
return (SEOGetSource(rguidSourceType,(REFGUID) CStringGUID(rguidSourceBase,dwSourceIndex),ppSource));
}
STDMETHODIMP SEOGetSource(REFGUID rguidSourceType, LPCSTR pszDisplayName, IEventSource **ppSource) {
HRESULT hrRes;
CComPtr<IEnumVARIANT> pEnum;
CComVariant varValue;
CComQIPtr<IEventSource,&IID_IEventSource> pSource;
CComBSTR strDisplayName;
CComBSTR strDesiredName;
if (ppSource) {
*ppSource = NULL;
}
if (!ppSource || !pszDisplayName) {
hrRes = E_POINTER;
goto error;
}
hrRes = SEOGetSourcesEnum(rguidSourceType,&pEnum);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (!pEnum) {
hrRes = S_FALSE;
goto error;
}
strDesiredName = pszDisplayName;
while (1) {
varValue.Clear();
hrRes = pEnum->Next(1,&varValue,NULL);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (hrRes == S_FALSE) {
break;
}
hrRes = varValue.ChangeType(VT_UNKNOWN);
if (!SUCCEEDED(hrRes)) {
goto error;
}
pSource = varValue.punkVal;
if (!pSource) {
hrRes = E_NOINTERFACE;
goto error;
}
strDisplayName.Empty();
hrRes = pSource->get_DisplayName(&strDisplayName);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (wcscmp(strDisplayName,strDesiredName) == 0) {
*ppSource = pSource;
(*ppSource)->AddRef();
hrRes = S_OK;
break;
}
}
error:
return (hrRes);
}
class CValueBase {
public:
virtual BOOL Match(VARIANT *pValue) = 0;
};
static HRESULT SEOGetSource(REFGUID rguidSourceType, LPCSTR pszProperty, CValueBase *pValue, IEventSource **ppSource) {
HRESULT hrRes;
CComPtr<IEnumVARIANT> pEnum;
CComVariant varValue;
CComQIPtr<IEventSource,&IID_IEventSource> pSource;
CComVariant varProperty;
CComPtr<IEventPropertyBag> pProperties;
if (ppSource) {
*ppSource = NULL;
}
if (!ppSource || !pszProperty) {
hrRes = E_POINTER;
goto error;
}
hrRes = SEOGetSourcesEnum(rguidSourceType,&pEnum);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (!pEnum) {
hrRes = S_FALSE;
goto error;
}
varProperty = pszProperty;
while (1) {
varValue.Clear();
hrRes = pEnum->Next(1,&varValue,NULL);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (hrRes == S_FALSE) {
break;
}
hrRes = varValue.ChangeType(VT_UNKNOWN);
if (!SUCCEEDED(hrRes)) {
goto error;
}
pSource = varValue.punkVal;
if (!pSource) {
hrRes = E_NOINTERFACE;
goto error;
}
pProperties.Release();
hrRes = pSource->get_Properties(&pProperties);
if (!SUCCEEDED(hrRes)) {
goto error;
}
varValue.Clear();
hrRes = pProperties->Item(&varProperty,&varValue);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (hrRes == S_FALSE) {
continue;
}
if (pValue->Match(&varValue)) {
*ppSource = pSource;
(*ppSource)->AddRef();
hrRes = S_OK;
break;
}
}
error:
return (hrRes);
}
class CValueDWORD : public CValueBase {
public:
CValueDWORD(DWORD dwValue) {
m_dwValue = dwValue;
};
virtual BOOL Match(VARIANT *pValue) {
HRESULT hrRes = VariantChangeType(pValue,pValue,0,VT_I4);
if (!SUCCEEDED(hrRes)) {
return (FALSE);
}
if ((DWORD) pValue->lVal != m_dwValue) {
return (FALSE);
}
return (TRUE);
};
private:
DWORD m_dwValue;
};
STDMETHODIMP SEOGetSource(REFGUID rguidSourceType, LPCSTR pszProperty, DWORD dwValue, IEventSource **ppSource) {
return (SEOGetSource(rguidSourceType,pszProperty,&CValueDWORD(dwValue),ppSource));
}
class CValueBSTR : public CValueBase {
public:
CValueBSTR(LPCWSTR pszValue) {
m_strValue = SysAllocString(pszValue);
};
CValueBSTR(LPCSTR pszValue) {
USES_CONVERSION;
m_strValue = SysAllocString(A2W(pszValue));
};
~CValueBSTR() {
SysFreeString(m_strValue);
};
virtual BOOL Match(VARIANT *pValue) {
HRESULT hrRes = VariantChangeType(pValue,pValue,0,VT_BSTR);
if (!SUCCEEDED(hrRes)) {
return (FALSE);
}
if (wcscmp(pValue->bstrVal,m_strValue) != 0) {
return (FALSE);
}
return (TRUE);
};
private:
BSTR m_strValue;
};
STDMETHODIMP SEOGetSource(REFGUID rguidSourceType, LPCSTR pszProperty, LPCSTR pszValue, IEventSource **ppSource) {
return (SEOGetSource(rguidSourceType,pszProperty,&CValueBSTR(pszValue),ppSource));
}
static HRESULT SEOGetRouter(IEventSource *pSource, IEventRouter **ppRouter) {
HRESULT hrRes;
CComPtr<IEventBindingManager> pManager;
CComPtr<IEventRouter> pRouter;
if (ppRouter) {
*ppRouter = NULL;
}
if (!pSource || !ppRouter) {
hrRes = E_POINTER;
goto error;
}
hrRes = pSource->GetBindingManager(&pManager);
if (!SUCCEEDED(hrRes)) {
goto error;
}
hrRes = CoCreateInstance(CLSID_CEventRouter,NULL,CLSCTX_ALL,IID_IEventRouter,(LPVOID *) &pRouter);
if (!SUCCEEDED(hrRes)) {
goto error;
}
hrRes = pRouter->put_Database(pManager);
if (!SUCCEEDED(hrRes)) {
goto error;
}
*ppRouter = pRouter;
(*ppRouter)->AddRef();
error:
return (hrRes);
}
STDMETHODIMP SEOGetRouter(REFGUID rguidSourceType, REFGUID rguidSource, IEventRouter **ppRouter) {
HRESULT hrRes;
CComPtr<IEventSource> pSource;
if (ppRouter) {
*ppRouter = NULL;
}
if (!ppRouter) {
hrRes = E_POINTER;
goto error;
}
hrRes = SEOGetSource(rguidSourceType,rguidSource,&pSource);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (!pSource) {
hrRes = S_FALSE;
goto error;
}
hrRes = SEOGetRouter(pSource,ppRouter);
error:
return (hrRes);
}
STDMETHODIMP SEOGetRouter(REFGUID rguidSourceType, REFGUID rguidSourceBase, DWORD dwSourceIndex, IEventRouter **ppRouter) {
return (SEOGetRouter(rguidSourceType,(REFGUID) CStringGUID(rguidSourceBase,dwSourceIndex),ppRouter));
}
STDMETHODIMP SEOGetRouter(REFGUID rguidSourceType, LPCSTR pszDisplayName, IEventRouter **ppRouter) {
HRESULT hrRes;
CComPtr<IEventSource> pSource;
if (ppRouter) {
*ppRouter = NULL;
}
if (!ppRouter) {
hrRes = E_POINTER;
goto error;
}
hrRes = SEOGetSource(rguidSourceType,pszDisplayName,&pSource);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (!pSource) {
hrRes = S_FALSE;
goto error;
}
hrRes = SEOGetRouter(pSource,ppRouter);
error:
return (hrRes);
}
STDMETHODIMP SEOGetRouter(REFGUID rguidSourceType, LPCSTR pszProperty, DWORD dwValue, IEventRouter **ppRouter) {
HRESULT hrRes;
CComPtr<IEventSource> pSource;
if (ppRouter) {
*ppRouter = NULL;
}
if (!ppRouter) {
hrRes = E_POINTER;
goto error;
}
hrRes = SEOGetSource(rguidSourceType,pszProperty,dwValue,&pSource);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (!pSource) {
hrRes = S_FALSE;
goto error;
}
hrRes = SEOGetRouter(pSource,ppRouter);
error:
return (hrRes);
}
STDMETHODIMP SEOGetRouter(REFGUID rguidSourceType, LPCSTR pszProperty, LPCSTR pszValue, IEventRouter **ppRouter) {
HRESULT hrRes;
CComPtr<IEventSource> pSource;
if (ppRouter) {
*ppRouter = NULL;
}
if (!ppRouter) {
hrRes = E_POINTER;
goto error;
}
hrRes = SEOGetSource(rguidSourceType,pszProperty,pszValue,&pSource);
if (!SUCCEEDED(hrRes)) {
goto error;
}
if (!pSource) {
hrRes = S_FALSE;
goto error;
}
hrRes = SEOGetRouter(pSource,ppRouter);
error:
return (hrRes);
}
#include <initguid.h>
// This CLSID must match the one in SEO.DLL.
// {A4BE1350-1051-11d1-AA1E-00AA006BC80B}
DEFINE_GUID(CLSID_CEventServiceObject,
0xa4be1350, 0x1051, 0x11d1, 0xaa, 0x1e, 0x0, 0xaa, 0x0, 0x6b, 0xc8, 0xb);
STDMETHODIMP SEOGetServiceHandle(IUnknown **ppUnkHandle) {
return (CoCreateInstance(CLSID_CEventServiceObject,
NULL,
CLSCTX_ALL,
IID_IUnknown,
(LPVOID *) ppUnkHandle));
}
STDMETHODIMP SEOCreateObject(VARIANT *pvarClass,
IEventBinding *pBinding,
IUnknown *pInitProperties,
REFIID iidDesired,
IUnknown **ppUnkObject) {
return (SEOCreateObjectEx(pvarClass,pBinding,pInitProperties,iidDesired,NULL,ppUnkObject));
}
STDMETHODIMP SEOCreateObjectEx(VARIANT *pvarClass,
IEventBinding *pBinding,
IUnknown *pInitProperties,
REFIID iidDesired,
IUnknown *pUnkCreateOptions,
IUnknown **ppUnkObject) {
HRESULT hrRes;
CStringGUID objGuid;
BSTR strClass;
CComQIPtr<IEventCreateOptions,&IID_IEventCreateOptions> pOpt;
if (ppUnkObject) {
*ppUnkObject = NULL;
}
if (!pvarClass || !ppUnkObject) {
return (E_POINTER);
}
if (pUnkCreateOptions) {
pOpt = pUnkCreateOptions;
}
if (pvarClass->vt == VT_BSTR) {
strClass = pvarClass->bstrVal;
} else if (pvarClass->vt == (VT_BYREF|VT_BSTR)) {
strClass = *pvarClass->pbstrVal;
} else {
hrRes = VariantChangeType(pvarClass,pvarClass,0,VT_BSTR);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
strClass = pvarClass->bstrVal;
}
objGuid.CalcFromProgID(strClass);
if (!objGuid) {
objGuid = strClass;
if (!objGuid) {
CComPtr<IBindCtx> pBindCtx;
CComPtr<IMoniker> pMoniker;
DWORD dwEaten;
if (!pOpt || ((hrRes=pOpt->CreateBindCtx(0,&pBindCtx))==E_NOTIMPL)) {
hrRes = CreateBindCtx(0,&pBindCtx);
}
_ASSERTE(SUCCEEDED(hrRes));
if (SUCCEEDED(hrRes)) {
if (!pOpt || ((hrRes=pOpt->MkParseDisplayName(pBindCtx,
strClass,
&dwEaten,
&pMoniker))==E_NOTIMPL)) {
hrRes = MkParseDisplayName(pBindCtx,strClass,&dwEaten,&pMoniker);
}
}
_ASSERTE(!SUCCEEDED(hrRes)||pMoniker);
if (!SUCCEEDED(hrRes)) {
#if 0 // tbd - We try both the normal and the Ex versions of MkParseDisplayName. Just use one.
pBindCtx.Release();
hrRes = CreateBindCtx(0,&pBindCtx);
_ASSERTE(SUCCEEDED(hrRes));
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
if (!pOpt||((hrRes=pOpt->MkParseDisplayNameEx(pBindCtx,
strClass,
&dwEaten,
&pMoniker))==E_NOTIMPL) {
hrRes = MkParseDisplayNameEx(pBindCtx,strClass,&dwEaten,&pMoniker);
}
_ASSERTE(!SUCCEEDED(hrRes)||pMoniker);
if (!SUCCEEDED(hrRes)) {
return (hrRes);
}
#else
return (hrRes);
#endif
}
pBindCtx.Release();
if (!pOpt || ((hrRes=pOpt->CreateBindCtx(0,&pBindCtx))==E_NOTIMPL)) {
hrRes = CreateBindCtx(0,&pBindCtx);
}
if (!SUCCEEDED(hrRes)) {
_ASSERTE(FALSE);
return (hrRes);
}
if (!pOpt || ((hrRes=pOpt->BindToObject(pMoniker,
pBindCtx,
NULL,
iidDesired,
(LPVOID *) ppUnkObject))==E_NOTIMPL)) {
hrRes = pMoniker->BindToObject(pBindCtx,NULL,iidDesired,(LPVOID *) ppUnkObject);
}
_ASSERTE(!SUCCEEDED(hrRes)||!*ppUnkObject);
// Fall through
}
}
// At this point, objGuid will only be TRUE if either CalcFromProgID or
// operator =(LPCOLESTR) succeeded. If both of these failed, then it will
// be FALSE and we will have attempted to interpret the SinkClass as a
// moniker.
if (!!objGuid) { // Use !! to hack-past ambiguous-conversion issues...
if (!pOpt || ((hrRes=pOpt->CoCreateInstance(objGuid,
NULL,
CLSCTX_ALL,
iidDesired,
(LPVOID *) ppUnkObject))==E_NOTIMPL)) {
hrRes = CoCreateInstance(objGuid,NULL,CLSCTX_ALL,iidDesired,(LPVOID *) ppUnkObject);
}
_ASSERTE(!SUCCEEDED(hrRes)||*ppUnkObject);
}
// At this point, hrRes has the result either from pMoniker->BindToObject or
// CoCreateInstance.
if (SUCCEEDED(hrRes)) {
if (!pOpt || ((hrRes=pOpt->Init(iidDesired,ppUnkObject,pBinding,pInitProperties))==E_NOTIMPL)) {
hrRes = S_OK;
CComQIPtr<IEventPersistBinding,&IID_IEventPersistBinding> pBindingInit;
if (pBinding) {
pBindingInit = *ppUnkObject;
}
if (pBindingInit) {
HRESULT hrResTmp;
hrResTmp = pBindingInit->Load(pBinding);
_ASSERTE(SUCCEEDED(hrResTmp));
} else {
CComQIPtr<IPersistPropertyBag,&IID_IPersistPropertyBag> pInit;
if (pInitProperties) {
pInit = *ppUnkObject;
}
if (pInit) {
HRESULT hrResTmp;
CComQIPtr<IPropertyBag,&IID_IPropertyBag> pProps;
pProps = pInitProperties;
_ASSERTE(pProps);
if (pProps) {
hrResTmp = pInit->InitNew();
_ASSERTE(SUCCEEDED(hrResTmp));
if (SUCCEEDED(hrResTmp)) {
hrResTmp = pInit->Load(pProps,NULL); // tbd - pass an IErrorLog object
_ASSERTE(SUCCEEDED(hrResTmp));
}
}
}
}
}
if (!SUCCEEDED(hrRes)) {
(*ppUnkObject)->Release();
*ppUnkObject = NULL;
}
}
return (hrRes);
}