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.
3288 lines
93 KiB
3288 lines
93 KiB
|
|
//#define INCL_INETSRV_INCS
|
|
//#include "smtpinc.h"
|
|
|
|
|
|
|
|
#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>
|
|
#include <smtpdisp_i.c>
|
|
#include <mailmsgi.h>
|
|
#include <smtpevent.h>
|
|
#include <seomgr.h>
|
|
|
|
#define MAX_RULE_LENGTH 4096
|
|
//
|
|
// Message object
|
|
//
|
|
#define MAILMSG_PROGID L"Exchange.MailMsg"
|
|
|
|
#define INITGUID
|
|
#include "initguid.h"
|
|
#include "smtpguid.h"
|
|
|
|
#ifdef PLATINUM
|
|
#include "ptntguid.h"
|
|
#endif
|
|
|
|
#include "wildmat.h"
|
|
#include "smtpdisp.h"
|
|
#include "seodisp.h"
|
|
|
|
#include "evntwrap.h"
|
|
#include "address.hxx"
|
|
#include "mailmsgprops.h"
|
|
|
|
#include "cdosys_i.c"
|
|
|
|
// {0xCD000080,0x8B95,0x11D1,{0x82,0xDB,0x00,0xC0,0x4F,0xB1,0x62,0x5D}}
|
|
DEFINE_GUID(IID_IConstructIMessageFromIMailMsg, 0xCD000080,0x8B95,0x11D1,0x82,
|
|
0xDB,0x00,0xC0,0x4F,0xB1,0x62,0x5D);
|
|
#ifdef PHATQ
|
|
// These are GUIDs which are normally defined in uuid.lib. wrapmb.lib
|
|
// incorrectly defines many of those GUIDs, so we need to define these
|
|
// ones ourselves. Yes, this is stupid.
|
|
|
|
// 00020400-0000-0000-C000-000000000046
|
|
DEFINE_GUID(IID_IDispatch, 0x00020400, 0x0000, 0x0000, 0xc0, 0x00,
|
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x46);
|
|
// 00020404-0000-0000-C000-000000000046
|
|
DEFINE_GUID(IID_IEnumVARIANT, 0x00020404, 0x0000, 0x0000, 0xc0, 0x00,
|
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x46);
|
|
// 0002E000-0000-0000-C000-000000000046
|
|
DEFINE_GUID(IID_IEnumGUID, 0x0002E000, 0x0000, 0x0000, 0xc0, 0x00,
|
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x46);
|
|
// 55272A00-42CB-11CE-8135-00AA004BB851
|
|
DEFINE_GUID(IID_IPropertyBag, 0x55272A00, 0x42CB, 0x11CE, 0x81, 0x35,
|
|
0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51);
|
|
// 1CF2B120-547D-101B-8E65-08002B2BD119
|
|
DEFINE_GUID(IID_IErrorInfo, 0x1CF2B120, 0x547D, 0x101B, 0x8E, 0x65,
|
|
0x08, 0x00, 0x2B, 0x2B, 0xD1, 0x19);
|
|
// B196B284-BAB4-101A-B69C-00AA00341D07
|
|
DEFINE_GUID(IID_IConnectionPointContainer,
|
|
0xB196B284, 0xBAB4, 0x101A, 0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07);
|
|
// 37D84F60-42CB-11CE-8135-00AA004BB851
|
|
DEFINE_GUID(IID_IPersistPropertyBag, 0x37D84F60, 0x42CB, 0x11CE, 0x81, 0x35,
|
|
0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51);
|
|
|
|
DEFINE_OLEGUID(IID_IPersistStream, 0x00000109, 0, 0);
|
|
#endif
|
|
|
|
extern VOID
|
|
ServerEventCompletion(
|
|
PVOID pvContext,
|
|
DWORD cbWritten,
|
|
DWORD dwCompletionStatus,
|
|
OVERLAPPED * lpo
|
|
);
|
|
|
|
#define SKIPSINK_CALL_NO_MORE_SINKS 0xffffffff
|
|
|
|
class CStoreCreateOptions : public CEventCreateOptionsBase
|
|
{
|
|
public:
|
|
|
|
CStoreCreateOptions( AQ_ALLOC_PARAMS * pContext)
|
|
{
|
|
_ASSERT (pContext != NULL);
|
|
|
|
m_Context = pContext;
|
|
}
|
|
|
|
private:
|
|
|
|
HRESULT STDMETHODCALLTYPE Init(REFIID iidDesired, IUnknown **ppUnkObject, IEventBinding *, IUnknown *)
|
|
{
|
|
ISMTPStoreDriver *pSink = NULL;
|
|
IUnknown * ThisUnknown = NULL;
|
|
IUnknown * NewUnknown = NULL;
|
|
HRESULT hrRes = S_OK;
|
|
|
|
TraceFunctEnterEx((LPARAM)this, "Calling create options");
|
|
|
|
ThisUnknown = *ppUnkObject;
|
|
|
|
hrRes = ThisUnknown->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
|
|
if (hrRes == E_NOINTERFACE) {
|
|
return (E_NOTIMPL);
|
|
}
|
|
if (FAILED(hrRes))
|
|
return(hrRes);
|
|
|
|
DebugTrace((LPARAM)this, "Calling startup events on sinks ...");
|
|
hrRes = pSink->Init(m_Context->m_InstanceId,
|
|
NULL,
|
|
(IUnknown *) m_Context->m_EventSmtpServer,
|
|
m_Context->m_dwStartupType,
|
|
&NewUnknown);
|
|
pSink->Release();
|
|
if (FAILED(hrRes) && (hrRes != E_NOTIMPL)) {
|
|
return (hrRes);
|
|
}
|
|
if(NewUnknown)
|
|
{
|
|
hrRes = NewUnknown->QueryInterface(iidDesired, (void **)ppUnkObject);
|
|
NewUnknown->Release();
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
ThisUnknown->Release();
|
|
}
|
|
|
|
|
|
return (E_NOTIMPL);
|
|
};
|
|
|
|
public:
|
|
AQ_ALLOC_PARAMS * m_Context;
|
|
|
|
};
|
|
|
|
|
|
CStoreDispatcher::CStoreAllocParams::CStoreAllocParams()
|
|
{
|
|
m_hContent = NULL;
|
|
}
|
|
|
|
CStoreDispatcher::CStoreAllocParams::~CStoreAllocParams()
|
|
{
|
|
}
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CreateCParams
|
|
//
|
|
// Synopsis: Based on dwEventType, create the appropriate Params object
|
|
//
|
|
// Arguments:
|
|
// dwEventType - specifies SMTP event
|
|
// pContext - context to pass into Init function
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
// E_OUTOFMEMORY
|
|
// or error from InitParamData
|
|
//
|
|
// History:
|
|
// jstamerj 980610 18:30:20: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CreateCParams(
|
|
DWORD dwEventType,
|
|
LPVOID pContext,
|
|
IMailTransportNotify *pINotify,
|
|
REFIID rGuidEventType,
|
|
CStoreBaseParams **ppCParams)
|
|
{
|
|
_ASSERT(ppCParams);
|
|
HRESULT hr;
|
|
|
|
switch(dwEventType) {
|
|
case SMTP_STOREDRV_STARTUP_EVENT:
|
|
if (!SUCCEEDED(GetData(NULL,NULL))) {
|
|
hr = SetData(((AQ_ALLOC_PARAMS *) pContext)->m_EventSmtpServer,
|
|
((AQ_ALLOC_PARAMS *) pContext)->m_InstanceId);
|
|
_ASSERT(SUCCEEDED(hr));
|
|
}
|
|
// fall through
|
|
case SMTP_MAIL_DROP_EVENT:
|
|
case SMTP_STOREDRV_ENUMMESS_EVENT:
|
|
case SMTP_STOREDRV_DELIVERY_EVENT:
|
|
case SMTP_STOREDRV_ALLOC_EVENT:
|
|
case SMTP_STOREDRV_PREPSHUTDOWN_EVENT:
|
|
case SMTP_STOREDRV_SHUTDOWN_EVENT:
|
|
*ppCParams = new CStoreParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_SUBMISSION_EVENT:
|
|
*ppCParams = new CMailTransportSubmissionParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_PRECATEGORIZE_EVENT:
|
|
*ppCParams = new CMailTransportPreCategorizeParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_REGISTER_EVENT:
|
|
*ppCParams = new CMailTransportCatRegisterParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_BEGIN_EVENT:
|
|
*ppCParams = new CMailTransportCatBeginParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_END_EVENT:
|
|
*ppCParams = new CMailTransportCatEndParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_BUILDQUERY_EVENT:
|
|
*ppCParams = new CMailTransportCatBuildQueryParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_BUILDQUERIES_EVENT:
|
|
*ppCParams = new CMailTransportCatBuildQueriesParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_SENDQUERY_EVENT:
|
|
*ppCParams = new CMailTransportCatSendQueryParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_SORTQUERYRESULT_EVENT:
|
|
*ppCParams = new CMailTransportCatSortQueryResultParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_PROCESSITEM_EVENT:
|
|
*ppCParams = new CMailTransportCatProcessItemParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_EXPANDITEM_EVENT:
|
|
*ppCParams = new CMailTransportCatExpandItemParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_COMPLETEITEM_EVENT:
|
|
*ppCParams = new CMailTransportCatCompleteItemParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_POSTCATEGORIZE_EVENT:
|
|
*ppCParams = new CMailTransportPostCategorizeParams();
|
|
break;
|
|
|
|
case SMTP_MAILTRANSPORT_GET_ROUTER_FOR_MESSAGE_EVENT:
|
|
*ppCParams = new CMailTransportRouterParams();
|
|
break;
|
|
|
|
case SMTP_MSGTRACKLOG_EVENT:
|
|
*ppCParams = new CMsgTrackLogParams();
|
|
break;
|
|
|
|
case SMTP_DNSRESOLVERRECORDSINK_EVENT:
|
|
*ppCParams = new CDnsResolverRecordParams();
|
|
break;
|
|
|
|
case SMTP_MAXMSGSIZE_EVENT:
|
|
*ppCParams = new CSmtpMaxMsgSizeParams();
|
|
break;
|
|
|
|
case SMTP_GET_DSN_RECIPIENT_ITERATOR_EVENT:
|
|
*ppCParams = new CDSNRecipientIteratorParams();
|
|
break;
|
|
|
|
case SMTP_GENERATE_DSN_EVENT:
|
|
*ppCParams = new CDSNGenerateParams();
|
|
break;
|
|
|
|
case SMTP_POST_DSN_EVENT:
|
|
*ppCParams = new CDSNPostGenerateParams();
|
|
break;
|
|
|
|
default:
|
|
_ASSERT(0 && "Unknown server event");
|
|
*ppCParams = NULL;
|
|
break;
|
|
}
|
|
|
|
if(*ppCParams == NULL) {
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCParams)->InitParamData(
|
|
pContext,
|
|
dwEventType,
|
|
pINotify,
|
|
rGuidEventType);
|
|
|
|
if(FAILED(hr)) {
|
|
(*ppCParams)->Release();
|
|
*ppCParams = NULL;
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CStoreBaseParams::CStoreBaseParams
|
|
//
|
|
// Synopsis: Sets member data to pre-initialized values
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns: NOTHING
|
|
//
|
|
// History:
|
|
// jstamerj 1998/06/23 13:58:01: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
CStoreDispatcher::CStoreBaseParams::CStoreBaseParams() :
|
|
m_rguidEventType(CATID_SMTP_STORE_DRIVER)
|
|
{
|
|
m_dwSignature = SIGNATURE_VALID_CSTOREPARAMS;
|
|
|
|
m_dwIdx_SinkSkip = 0;
|
|
m_fDefaultProcessingCalled = FALSE;
|
|
|
|
m_pINotify = NULL;
|
|
m_pIUnknownSink = NULL;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CStoreBaseParams::~CStoreBaseParams
|
|
//
|
|
// Synopsis: Release the IMailTransportNotify reference if held
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns: NOTHING
|
|
//
|
|
// History:
|
|
// jstamerj 1998/06/23 13:58:51: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
CStoreDispatcher::CStoreBaseParams::~CStoreBaseParams()
|
|
{
|
|
if(m_pINotify)
|
|
m_pINotify->Release();
|
|
|
|
_ASSERT(m_dwSignature == SIGNATURE_VALID_CSTOREPARAMS);
|
|
m_dwSignature = SIGNATURE_INVALID_CSTOREPARAMS;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: InitParamData
|
|
//
|
|
// Synopsis: Initializes object. This includes calling Init() which
|
|
// is implemented in dervied objects.
|
|
//
|
|
// Arguments:
|
|
// pContext: Context passed in - specific for server event
|
|
// dwEventType: Specifies which server event we are for
|
|
// pINotify: IMailTransportNotify interface for async completion
|
|
// rguidEventType: guid for event type binding
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
// Error from Init()
|
|
//
|
|
// History:
|
|
// jstamerj 980615 19:16:55: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CStoreBaseParams::InitParamData(
|
|
PVOID pContext,
|
|
DWORD dwEventType,
|
|
IMailTransportNotify *pINotify,
|
|
REFIID rguidEventType)
|
|
{
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreBaseParams::InitParamData");
|
|
HRESULT hr;
|
|
|
|
m_dwEventType = dwEventType;
|
|
m_dwIdx_SinkSkip = 0;
|
|
m_fDefaultProcessingCalled = FALSE;
|
|
m_pINotify = pINotify;
|
|
m_pINotify->AddRef();
|
|
m_rguidEventType = rguidEventType;
|
|
|
|
|
|
hr = Init(pContext);
|
|
if(FAILED(hr)) {
|
|
ErrorTrace((LPARAM)this, "Init() failed, hr = %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CStoreBaseParams::CallObject
|
|
//
|
|
// Synopsis: Called by the dispatcher when time to call a sink. This
|
|
// implements some default functionality -- create the sink with a
|
|
// null CCreateOptions
|
|
//
|
|
// Arguments:
|
|
// IEventManager
|
|
// CBinding
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
// or error from CreateSink/CallObject
|
|
//
|
|
// History:
|
|
// jstamerj 1998/06/23 13:53:57: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CStoreBaseParams::CallObject(
|
|
IEventManager *pManager,
|
|
CBinding& bBinding)
|
|
{
|
|
HRESULT hrRes;
|
|
CComPtr<IUnknown> pUnkSink;
|
|
|
|
if (!pManager) {
|
|
return (E_POINTER);
|
|
}
|
|
hrRes = pManager->CreateSink(bBinding.m_piBinding,NULL,&pUnkSink);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
return (CallObject(bBinding,pUnkSink));
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CStoreBaseParams::CheckMailMsgRule
|
|
//
|
|
// Synopsis: Determines if a mailmsg string rule passes or fails given
|
|
// the mailmsg and the CBinding object
|
|
//
|
|
// Arguments:
|
|
// pBinding: CBinding object for this sink
|
|
// pMsgProps: IMailMsgProperteries of the message to check
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, call this sink
|
|
// S_FALSE: Success, don't call this sink
|
|
//
|
|
// History:
|
|
// jstamerj 1999/01/11 17:04:01: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CStoreBaseParams::CheckMailMsgRule(
|
|
CBinding *pBinding,
|
|
IMailMsgProperties *pIMsgProps)
|
|
{
|
|
HRESULT hr;
|
|
BOOL fDomainLoaded = FALSE;
|
|
BOOL fSenderLoaded = FALSE;
|
|
CHAR szDomain[MAX_INTERNET_NAME + 2];
|
|
CHAR szSender[MAX_INTERNET_NAME + 2];
|
|
LPSTR szRule;
|
|
CStoreBinding *pStoreBinding = (CStoreBinding *)pBinding;
|
|
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CStoreBaseParams::CheckMailMsgRule");
|
|
|
|
_ASSERT(pStoreBinding);
|
|
_ASSERT(pIMsgProps);
|
|
|
|
// Get the cached rule from the binding
|
|
szRule = pStoreBinding->GetRuleString();
|
|
DebugTrace((LPARAM)this, "Rule string: %s", (szRule)?szRule:"NULL (No rule)");
|
|
|
|
// If the rule is NULL, we will don't have a rule
|
|
// string and we will return a match
|
|
if (!szRule)
|
|
{
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return(S_OK);
|
|
}
|
|
|
|
// try each comma delimited rule in the header patterns list
|
|
char *pszHeader = (char *) _alloca(lstrlen(szRule)+1);
|
|
if (!pszHeader) {
|
|
return (E_OUTOFMEMORY);
|
|
}
|
|
lstrcpy(pszHeader,szRule);
|
|
while (pszHeader != NULL && *pszHeader != 0)
|
|
{
|
|
// find the next semicolon in the string and turn it into a 0
|
|
// if it exists
|
|
char *pszSemiColon = strchr(pszHeader, ';');
|
|
if (pszSemiColon != NULL)
|
|
*pszSemiColon = 0;
|
|
|
|
// set pszContents to point to the text which must be matched
|
|
// in the header. if pszContents == NULL then just having
|
|
// the header exist is good enough.
|
|
char *pszPatterns = strchr(pszHeader, '=');
|
|
if (pszPatterns != NULL)
|
|
{
|
|
*pszPatterns = 0;
|
|
(pszPatterns++);
|
|
}
|
|
|
|
// we now have the header that we are looking for in
|
|
// pszHeader and the list of patterns that we are interested
|
|
// in pszPatterns. Make the lookup into the header
|
|
// data structure
|
|
hr = S_FALSE;
|
|
|
|
DebugTrace((LPARAM)this, "Processing Header <%s> with pattern <%s>",
|
|
pszHeader, pszPatterns);
|
|
if (!lstrcmpi(pszHeader, "EHLO")) {
|
|
|
|
// Process a client domain rule ...
|
|
if (!fDomainLoaded) {
|
|
hr = pIMsgProps->GetStringA(
|
|
IMMPID_MP_HELO_DOMAIN,
|
|
sizeof(szDomain),
|
|
szDomain);
|
|
|
|
if (hr == S_OK) {
|
|
|
|
fDomainLoaded = TRUE;
|
|
}
|
|
}
|
|
if (fDomainLoaded) {
|
|
hr = MatchEmailOrDomainName(szDomain, pszPatterns, FALSE);
|
|
}
|
|
} else if (!lstrcmpi(pszHeader, "MAIL FROM")) {
|
|
|
|
// Process a sender name rule ...
|
|
if (!fSenderLoaded) {
|
|
|
|
hr = pIMsgProps->GetStringA(
|
|
IMMPID_MP_SENDER_ADDRESS_SMTP,
|
|
sizeof(szSender),
|
|
szSender);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
fSenderLoaded = TRUE;
|
|
}
|
|
}
|
|
if (fSenderLoaded) {
|
|
hr = MatchEmailOrDomainName(szSender, pszPatterns, TRUE);
|
|
}
|
|
}
|
|
else if (!lstrcmpi(pszHeader, "RCPT TO"))
|
|
{
|
|
hr = CheckMailMsgRecipientsRule(
|
|
pIMsgProps,
|
|
pszPatterns);
|
|
}
|
|
|
|
// We don't want to destroy the rule string so we restore all the
|
|
// semicolons and equal signs
|
|
if (pszSemiColon)
|
|
*pszSemiColon = ';';
|
|
if (pszPatterns)
|
|
*(pszPatterns - 1) = '=';
|
|
|
|
// Exit immediately if we found a match!
|
|
if (hr == S_OK)
|
|
goto Cleanup;
|
|
|
|
// the next pattern is the one past the end of the semicolon
|
|
pszHeader = (pszSemiColon == NULL) ? NULL : pszSemiColon + 1;
|
|
}
|
|
|
|
Cleanup:
|
|
DebugTrace((LPARAM)this, "Returning hr %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CStoreBaseParams::CheckMailMsgRecipientsRule
|
|
//
|
|
// Synopsis: Determines if a mailmsg pattern string matches mailmsg
|
|
// recipients or not
|
|
//
|
|
// Arguments:
|
|
// pIMsg: An interface to a mailmsg object
|
|
// pszPatterns: The sink rule to check
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, call this sink
|
|
// S_FALSE: Success, don't call this sink
|
|
// error from mailmsg
|
|
//
|
|
// History:
|
|
// jstamerj 1999/01/12 15:25:55: Copied from MCIS2 and modified for Platinum
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CStoreBaseParams::CheckMailMsgRecipientsRule(
|
|
IUnknown *pIMsg,
|
|
LPSTR pszPattern)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwNumRecips;
|
|
IMailMsgRecipients *pIRecips = NULL;
|
|
BOOL fMatch = FALSE;
|
|
DWORD dwCount;
|
|
CHAR szRecip [MAX_INTERNET_NAME + 2];
|
|
|
|
TraceFunctEnterEx((LPARAM)this,
|
|
"CStoreDispatcher::CStoreBaseParams::CheckMailMsgRecipientsRule");
|
|
|
|
hr = pIMsg->QueryInterface(
|
|
IID_IMailMsgRecipients,
|
|
(LPVOID *)&pIRecips);
|
|
|
|
if(FAILED(hr))
|
|
goto CLEANUP;
|
|
|
|
hr = pIRecips->Count(&dwNumRecips);
|
|
if(FAILED(hr))
|
|
goto CLEANUP;
|
|
|
|
DebugTrace((LPARAM)this, "Checking rule \"%s\" for %d recipients",
|
|
pszPattern, pIMsg);
|
|
|
|
for(dwCount = 0;
|
|
(fMatch == FALSE) && (dwCount < dwNumRecips);
|
|
dwCount++) {
|
|
|
|
hr = pIRecips->GetStringA(
|
|
dwCount,
|
|
IMMPID_RP_ADDRESS_SMTP,
|
|
sizeof(szRecip),
|
|
szRecip);
|
|
|
|
if(FAILED(hr) && (hr != MAILMSG_E_PROPNOTFOUND))
|
|
goto CLEANUP;
|
|
|
|
if(hr != MAILMSG_E_PROPNOTFOUND) {
|
|
hr = MatchEmailOrDomainName(szRecip,pszPattern,TRUE);
|
|
if(hr == S_OK)
|
|
fMatch = TRUE;
|
|
else if(FAILED(hr))
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
hr = (fMatch) ? S_OK : S_FALSE;
|
|
|
|
CLEANUP:
|
|
if(pIRecips)
|
|
pIRecips->Release();
|
|
|
|
DebugTrace((LPARAM)this, "Returning hr %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CStoreBaseparams::MatchEmailOrDomainName
|
|
//
|
|
// Synopsis: Given an email/domain name and a pattern, determine if
|
|
// the pattern matches or not
|
|
//
|
|
// Arguments:
|
|
// szEmail: The email address or domain name
|
|
// szPattern: The pattern to check
|
|
// fIsEmail: TRUE if szEmail is an email address, FALSE if szEmail is
|
|
// a domain
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, match
|
|
// S_FALSE: Success, no match
|
|
// E_INVALIDARG
|
|
//
|
|
// History:
|
|
// jstamerj 1999/01/12 15:25:36: Copied from MCIS2 and modified for Platinum
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CStoreBaseParams::MatchEmailOrDomainName(
|
|
LPSTR szEmail,
|
|
LPSTR szPattern,
|
|
BOOL fIsEmail)
|
|
{
|
|
CAddr *pEmailAddress = NULL;
|
|
LPSTR szEmailDomain = NULL;
|
|
HRESULT hrRes;
|
|
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CStoreBaseParams::MatchEmailOrDomainName");
|
|
|
|
DebugTrace((LPARAM)NULL, "Matching <%s> against <%s>", szEmail, szPattern);
|
|
|
|
if (!szEmail || !szPattern)
|
|
return(E_INVALIDARG);
|
|
|
|
// This validates that it is a good email name
|
|
pEmailAddress = CAddr::CreateAddress(szEmail, fIsEmail?FROMADDR:CLEANDOMAIN);
|
|
if (!pEmailAddress)
|
|
return(E_INVALIDARG);
|
|
|
|
szEmail = pEmailAddress->GetAddress();
|
|
szEmailDomain = pEmailAddress->GetDomainOffset();
|
|
|
|
hrRes = ::MatchEmailOrDomainName(szEmail, szEmailDomain, szPattern, fIsEmail);
|
|
|
|
// Free the CAddr objects ...
|
|
if (pEmailAddress)
|
|
delete pEmailAddress;
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return(hrRes);
|
|
}
|
|
|
|
|
|
|
|
CStoreDispatcher::CStoreBinding::CStoreBinding()
|
|
{
|
|
m_szRule = NULL;
|
|
}
|
|
|
|
CStoreDispatcher::CStoreBinding::~CStoreBinding()
|
|
{
|
|
if(m_szRule)
|
|
delete [] m_szRule;
|
|
}
|
|
|
|
//
|
|
// initialize a new binding. we cache information from the binding database
|
|
// here
|
|
// jstamerj 1999/01/12 16:25:59: Copied MCIS2 code to get the rule string
|
|
//
|
|
HRESULT CStoreDispatcher::CStoreBinding::Init(IEventBinding *piBinding)
|
|
{
|
|
HRESULT hr;
|
|
CComPtr<IEventPropertyBag> piEventProperties;
|
|
CComVariant vRule;
|
|
|
|
// get the parent initialized
|
|
hr = CBinding::Init(piBinding);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// get the binding database
|
|
hr = m_piBinding->get_SourceProperties(&piEventProperties);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// get the rule from the binding database
|
|
hr = piEventProperties->Item(&CComVariant("Rule"), &vRule);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// Process the rule string, the result code is not important
|
|
// since it will NULL our the string
|
|
if (hr == S_OK)
|
|
hr = GetAnsiStringFromVariant(vRule, &m_szRule);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CStoreDispatcher::CStoreBinding::GetAnsiStringFromVariant(
|
|
CComVariant &vString, LPSTR *ppszString)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERT(ppszString);
|
|
|
|
if (!ppszString)
|
|
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
|
|
|
|
// Default to NULL
|
|
*ppszString = NULL;
|
|
|
|
if (vString.vt == VT_BSTR)
|
|
{
|
|
DWORD dwLength = lstrlenW(vString.bstrVal) + 1;
|
|
|
|
// Convert to an ANSI string and store it as a member
|
|
*ppszString = new char[dwLength];
|
|
if (!*ppszString)
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
// copy the rule into an ascii string
|
|
if (WideCharToMultiByte(CP_ACP, 0, vString.bstrVal,
|
|
-1, (*ppszString), dwLength, NULL, NULL) <= 0)
|
|
{
|
|
delete [] (*ppszString);
|
|
*ppszString = NULL;
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
else
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
#if 1
|
|
//
|
|
// create and call the child object
|
|
//
|
|
HRESULT CStoreDispatcher::CStoreParams::CallObject(IEventManager *pManager, CBinding& bBinding)
|
|
{
|
|
CStoreCreateOptions opt (m_pContext);
|
|
HRESULT hrRes;
|
|
CComPtr<IUnknown> pUnkSink;
|
|
|
|
if (!pManager) {
|
|
return (E_POINTER);
|
|
}
|
|
hrRes = pManager->CreateSink(bBinding.m_piBinding,&opt,&pUnkSink);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
return (CallObject(bBinding,pUnkSink));
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// call the child object
|
|
//
|
|
HRESULT CStoreDispatcher::CStoreParams::CallObject(CBinding& bBinding, IUnknown *punkObject)
|
|
{
|
|
HRESULT hrRes = S_OK;
|
|
HRESULT hrTmp = S_OK;
|
|
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CServerParams::CallObject");
|
|
|
|
// We do this for different types of SMTP events
|
|
switch (m_dwEventType)
|
|
{
|
|
case SMTP_STOREDRV_STARTUP_EVENT:
|
|
break;
|
|
case SMTP_STOREDRV_ALLOC_EVENT:
|
|
{
|
|
IMailMsgStoreDriver *pSink = NULL;
|
|
IMailMsgProperties * pMsg = (IMailMsgProperties *)m_pContext->IMsgPtr;
|
|
IMailMsgBind *pBindInterface = NULL;
|
|
IMailMsgPropertyStream *pStream = NULL;
|
|
|
|
DebugTrace((LPARAM)this, "Calling bind on sinks ...");
|
|
|
|
/*IID_ISMTPStoreDriver*/
|
|
hrRes = punkObject->QueryInterface(IID_IMailMsgStoreDriver, (void **)&pSink);
|
|
if (FAILED(hrRes))
|
|
return(hrRes);
|
|
|
|
// Allocate a new message
|
|
hrRes = pSink->AllocMessage(pMsg, NULL, &pStream, &m_pContext->hContent, NULL);
|
|
if(!FAILED(hrRes))
|
|
{
|
|
pBindInterface = (IMailMsgBind *)m_pContext->BindInterfacePtr;
|
|
|
|
hrRes = pBindInterface->BindToStore(pStream,
|
|
pSink,
|
|
m_pContext->hContent);
|
|
if (pStream)
|
|
{
|
|
pStream->Release();
|
|
pStream = NULL;
|
|
}
|
|
|
|
if(FAILED(hrRes))
|
|
{
|
|
ErrorTrace((LPARAM)this, "pBindAtqInterface->BindToStore failed with %x", hrRes);
|
|
|
|
// Close the content handle
|
|
HRESULT myRes = pSink->CloseContentFile(
|
|
pMsg,
|
|
m_pContext->hContent);
|
|
if (FAILED(myRes))
|
|
{
|
|
FatalTrace((LPARAM)this, "Unable to close content file (%08x)", myRes);
|
|
_ASSERT(FALSE);
|
|
}
|
|
|
|
m_pContext->hContent = NULL;
|
|
|
|
hrTmp = pSink->Delete(pMsg, NULL);
|
|
_ASSERT(SUCCEEDED(hrTmp));
|
|
|
|
}
|
|
else
|
|
{
|
|
//Skip all sinks - temporary
|
|
hrRes = S_FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
DebugTrace((LPARAM)this, "pSink->AllocMessage failed with %x", hrRes);
|
|
}
|
|
|
|
pSink->Release();
|
|
}
|
|
break;
|
|
case SMTP_STOREDRV_DELIVERY_EVENT:
|
|
{
|
|
ISMTPStoreDriver *pSink;
|
|
|
|
hrRes = punkObject->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
|
|
if (FAILED(hrRes))
|
|
return(hrRes);
|
|
|
|
DebugTrace((LPARAM)this, "Calling local delivery sink sink ...");
|
|
hrRes = pSink->LocalDelivery(
|
|
(IMailMsgProperties *) m_pContext->IMsgPtr,
|
|
m_pContext->m_RecipientCount,
|
|
m_pContext->pdwRecipIndexes,
|
|
(IMailMsgNotify *) m_pContext->m_pNotify);
|
|
pSink->Release();
|
|
|
|
//
|
|
// jstamerj 1998/08/04 17:31:07:
|
|
// If the store driver sink returns this specific error
|
|
// code, we want to stop calling sinks and return from
|
|
// TriggerLocalDelivery
|
|
//
|
|
if(hrRes == STOREDRV_E_RETRY) {
|
|
|
|
DebugTrace((LPARAM)this, "Sink returned STOREDRV_E_RETRY on LocalDelivery");
|
|
m_pContext->hr = hrRes;
|
|
hrRes = S_FALSE;
|
|
}
|
|
|
|
}
|
|
break;
|
|
case SMTP_MAIL_DROP_EVENT:
|
|
// ISMTPStoreDriver *pSink;
|
|
|
|
// hrRes = punkObject->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
|
|
// if (FAILED(hrRes))
|
|
// return(hrRes);
|
|
|
|
// DebugTrace((LPARAM)this, "Calling mail drop sink ...");
|
|
// hrRes = pSink->DirectoryDrop((IMailMsgProperties *) m_pContext->IMsgPtr, m_pContext->m_RecipientCount, m_pContext->pdwRecipIndexes, m_pContext->m_DropDirectory, NULL);
|
|
// pSink->Release();
|
|
//}
|
|
break;
|
|
case SMTP_STOREDRV_PREPSHUTDOWN_EVENT:
|
|
{
|
|
ISMTPStoreDriver *pSink;
|
|
|
|
hrRes = punkObject->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
|
|
if (FAILED(hrRes))
|
|
return(hrRes);
|
|
|
|
DebugTrace((LPARAM)this, "Calling prepare to shutdown on sinks ...");
|
|
hrRes = pSink->PrepareForShutdown(0);
|
|
pSink->Release();
|
|
hrRes = S_OK;
|
|
}
|
|
break;
|
|
case SMTP_STOREDRV_SHUTDOWN_EVENT:
|
|
{
|
|
ISMTPStoreDriver *pSink;
|
|
|
|
hrRes = punkObject->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
|
|
if (FAILED(hrRes))
|
|
return(hrRes);
|
|
|
|
DebugTrace((LPARAM)this, "Calling shutdown on sinks ...");
|
|
hrRes = pSink->Shutdown(0);
|
|
pSink->Release();
|
|
hrRes = S_OK;
|
|
}
|
|
break;
|
|
|
|
case SMTP_STOREDRV_ENUMMESS_EVENT:
|
|
{
|
|
ISMTPStoreDriver *pSink;
|
|
|
|
hrRes = punkObject->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
|
|
if (FAILED(hrRes))
|
|
return(hrRes);
|
|
|
|
DebugTrace((LPARAM)this, "Calling Enumerate on sinks ...");
|
|
hrRes = pSink->EnumerateAndSubmitMessages(NULL);
|
|
pSink->Release();
|
|
hrRes = S_OK;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DebugTrace((LPARAM)this, "Invalid sink interface");
|
|
hrRes = E_NOINTERFACE;
|
|
}
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return(hrRes);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CStoreParams::CallDefault
|
|
//
|
|
// Synopsis: CStoreDispatcher::Dispatcher will call this routine when
|
|
// the default sink priority has been reached.
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// jstamerj 980611 14:19:57: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CStoreParams::CallDefault()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// call the child object
|
|
//
|
|
HRESULT CStoreDispatcher::CStoreAllocParams::CallObject(CBinding& bBinding, IUnknown *punkObject)
|
|
{
|
|
HRESULT hrRes = S_OK;
|
|
|
|
#if 0
|
|
IMailMsgStoreDriver *pStoreDriver = NULL;
|
|
IMailMsgProperties *pMsg = NULL;
|
|
IMailMsgPropertyStream *pStream = NULL;
|
|
IMailMsgBindATQ *pBindInterface = NULL;
|
|
CLSID clsidMailMsg;
|
|
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CStoreAllocParams::CallObject");
|
|
|
|
hrRes = CLSIDFromProgID(MAILMSG_PROGID, &clsidMailMsg);
|
|
if (FAILED(hrRes))
|
|
{
|
|
DebugTrace((LPARAM)this, "CoCreateInstance IID_IMailMsgProperties failed, %X", hrRes);
|
|
return(hrRes);
|
|
}
|
|
|
|
// Create a new MailMsg
|
|
hrRes = CoCreateInstance(
|
|
clsidMailMsg,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IMailMsgProperties,
|
|
(LPVOID *)&pMsg);
|
|
if (FAILED(hrRes))
|
|
{
|
|
DebugTrace((LPARAM)this, "CoCreateInstance IID_IMailMsgProperties failed, %X", hrRes);
|
|
return(hrRes);
|
|
}
|
|
|
|
hrRes = punkObject->QueryInterface(IID_IMailMsgStoreDriver, (void **)&pStoreDriver);
|
|
if (FAILED(hrRes))
|
|
{
|
|
DebugTrace((LPARAM)this, "QueryInterface() on IID_IMailMsgStoreDriver failed, %X", hrRes);
|
|
goto Exit;
|
|
}
|
|
|
|
// Allocate a new message
|
|
hrRes = pStoreDriver->AllocMessage(
|
|
pMsg,
|
|
NULL,
|
|
&pStream,
|
|
&m_hContent,
|
|
NULL);
|
|
if (FAILED(hrRes))
|
|
{
|
|
DebugTrace((LPARAM)this, "pDriver->AllocMessage failed, %X", hrRes);
|
|
goto Exit;
|
|
}
|
|
|
|
hrRes = pMsg->QueryInterface(IID_IMailMsgBindATQ, (void **)&pBindInterface);
|
|
if (FAILED(hrRes))
|
|
{
|
|
DebugTrace((LPARAM)this, "QueryInterface() on IID_IMailMsgStoreDriver failed, %X", hrRes);
|
|
goto Exit;
|
|
}
|
|
|
|
hrRes = pBindInterface->SetATQInfo (NULL, NULL, NULL, INFINITE, NULL);
|
|
if (FAILED(hrRes))
|
|
{
|
|
DebugTrace((LPARAM)this, "QueryInterface() on IID_IMailMsgStoreDriver failed, %X", hrRes);
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
if(pStoreDriver)
|
|
{
|
|
pStoreDriver->Release();
|
|
}
|
|
|
|
if(pMsg)
|
|
{
|
|
pMsg->Release();
|
|
}
|
|
|
|
if(pBindInterface)
|
|
{
|
|
pBindInterface->Release();
|
|
}
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
#endif
|
|
|
|
return(hrRes);
|
|
}
|
|
|
|
#if 0
|
|
HRESULT STDMETHODCALLTYPE CStoreDispatcher::OnEvent(REFIID iidEvent,
|
|
DWORD dwEventType,
|
|
LPVOID pvContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// create the params object, and pass it into the dispatcher
|
|
CStoreParams ServerParams;
|
|
ServerParams.Init(dwEventType, pvContext);
|
|
hr = Dispatcher(iidEvent, &ServerParams);
|
|
|
|
return hr;
|
|
}
|
|
#endif
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::OnEvent
|
|
//
|
|
// Synopsis: Prepares for server event
|
|
//
|
|
// Arguments:
|
|
// iidEvent: guid for event
|
|
// dwEventType: specifies the event
|
|
// pvContext: context for the params object
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// jstamerj 980616 13:27:55: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CStoreDispatcher::OnEvent(
|
|
REFIID iidEvent,
|
|
DWORD dwEventType,
|
|
LPVOID pvContext)
|
|
{
|
|
HRESULT hr;
|
|
|
|
IMailTransportNotify *pINotify = NULL;
|
|
//
|
|
// Call into ATL internals to get the interface we need to pass out
|
|
//
|
|
hr = _InternalQueryInterface(
|
|
IID_IMailTransportNotify,
|
|
(LPVOID *)&pINotify);
|
|
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
//
|
|
// create the CParams object on the heap -- the object will be
|
|
// needed after this call may be out of here (when a sink returns
|
|
// MAILTRANSPORT_S_PENDING and there are more sinks to call)
|
|
//
|
|
CStoreBaseParams *pCParams;
|
|
|
|
hr = CreateCParams(
|
|
dwEventType,
|
|
pvContext,
|
|
pINotify,
|
|
iidEvent,
|
|
&pCParams);
|
|
|
|
//
|
|
// The params object should addref pINotify
|
|
//
|
|
pINotify->Release();
|
|
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
//
|
|
// Start calling sinks
|
|
//
|
|
hr = Dispatcher(iidEvent, pCParams);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: GuidForEvent
|
|
//
|
|
// Synopsis: Given dwEventType, return the appropriate GUID for the
|
|
// event binding
|
|
//
|
|
// Arguments:
|
|
// dwEventType: type of SMTP event
|
|
//
|
|
// Returns:
|
|
// REFIID of GUID for the event
|
|
//
|
|
// History:
|
|
// jstamerj 980610 18:24:24: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
REFIID GuidForEvent(DWORD dwEventType)
|
|
{
|
|
switch(dwEventType) {
|
|
case SMTP_MAIL_DROP_EVENT:
|
|
case SMTP_STOREDRV_ENUMMESS_EVENT:
|
|
case SMTP_STOREDRV_DELIVERY_EVENT:
|
|
case SMTP_STOREDRV_ALLOC_EVENT:
|
|
case SMTP_STOREDRV_STARTUP_EVENT:
|
|
case SMTP_STOREDRV_PREPSHUTDOWN_EVENT:
|
|
case SMTP_STOREDRV_SHUTDOWN_EVENT:
|
|
default:
|
|
return CATID_SMTP_STORE_DRIVER;
|
|
|
|
case SMTP_MAILTRANSPORT_SUBMISSION_EVENT:
|
|
return CATID_SMTP_TRANSPORT_SUBMISSION;
|
|
|
|
case SMTP_MAILTRANSPORT_PRECATEGORIZE_EVENT:
|
|
return CATID_SMTP_TRANSPORT_PRECATEGORIZE;
|
|
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_REGISTER_EVENT:
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_BEGIN_EVENT:
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_END_EVENT:
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_BUILDQUERY_EVENT:
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_BUILDQUERIES_EVENT:
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_SENDQUERY_EVENT:
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_SORTQUERYRESULT_EVENT:
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_PROCESSITEM_EVENT:
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_EXPANDITEM_EVENT:
|
|
case SMTP_MAILTRANSPORT_CATEGORIZE_COMPLETEITEM_EVENT:
|
|
return CATID_SMTP_TRANSPORT_CATEGORIZE;
|
|
|
|
case SMTP_MAILTRANSPORT_POSTCATEGORIZE_EVENT:
|
|
return CATID_SMTP_TRANSPORT_POSTCATEGORIZE;
|
|
|
|
case SMTP_MAILTRANSPORT_GET_ROUTER_FOR_MESSAGE_EVENT:
|
|
return CATID_SMTP_TRANSPORT_ROUTER;
|
|
case SMTP_MSGTRACKLOG_EVENT:
|
|
return CATID_SMTP_MSGTRACKLOG;
|
|
case SMTP_DNSRESOLVERRECORDSINK_EVENT:
|
|
return CATID_SMTP_DNSRESOLVERRECORDSINK;
|
|
case SMTP_MAXMSGSIZE_EVENT:
|
|
return CATID_SMTP_MAXMSGSIZE;
|
|
|
|
case SMTP_GET_DSN_RECIPIENT_ITERATOR_EVENT:
|
|
case SMTP_GENERATE_DSN_EVENT:
|
|
case SMTP_POST_DSN_EVENT:
|
|
return CATID_SMTP_DSN;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// this function performs instance level server events registration
|
|
//
|
|
HRESULT RegisterPlatSEOInstance(DWORD dwInstanceID)
|
|
{
|
|
HRESULT hr;
|
|
|
|
//
|
|
// find the SMTP source type in the event manager
|
|
//
|
|
CComPtr<IEventManager> pEventManager;
|
|
hr = CoCreateInstance(CLSID_CEventManager, NULL, CLSCTX_ALL,
|
|
IID_IEventManager, (LPVOID *) &pEventManager);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
CComPtr<IEventSourceTypes> pSourceTypes;
|
|
hr = pEventManager->get_SourceTypes(&pSourceTypes);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
CComPtr<IEventSourceType> pSourceType;
|
|
CComBSTR bstrSourceTypeGUID = (LPCOLESTR) CStringGUID(GUID_SMTP_SOURCE_TYPE);
|
|
hr = pSourceTypes->Item(&CComVariant(bstrSourceTypeGUID), &pSourceType);
|
|
_ASSERT(hr != S_OK || pSourceType != NULL);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
//
|
|
// generate a GUID for this source, which is based on GUID_SMTPSVC
|
|
// mangled by the instance ID
|
|
//
|
|
CComPtr<IEventUtil> pEventUtil;
|
|
hr = CoCreateInstance(CLSID_CEventUtil, NULL, CLSCTX_ALL,
|
|
IID_IEventUtil, (LPVOID *) &pEventUtil);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
CComBSTR bstrSMTPSvcGUID = (LPCOLESTR) CStringGUID(GUID_SMTPSVC_SOURCE);
|
|
CComBSTR bstrSourceGUID;
|
|
hr = pEventUtil->GetIndexedGUID(bstrSMTPSvcGUID, dwInstanceID, &bstrSourceGUID);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
//
|
|
// see if this source is registered with the list of sources for the
|
|
// SMTP source type
|
|
//
|
|
CComPtr<IEventSources> pEventSources;
|
|
hr = pSourceType->get_Sources(&pEventSources);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
CComPtr<IEventSource> pEventSource;
|
|
hr = pEventSources->Item(&CComVariant(bstrSourceGUID), &pEventSource);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
//
|
|
// if the source guid doesn't exist then we need to register a new
|
|
// source for the SMTP source type and add directory drop as a binding
|
|
//
|
|
if (hr == S_FALSE)
|
|
{
|
|
// register the SMTPSvc source
|
|
hr = pEventSources->Add(bstrSourceGUID, &pEventSource);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
char szSourceDisplayName[50];
|
|
_snprintf(szSourceDisplayName, 50, "smtpsvc %lu", dwInstanceID);
|
|
CComBSTR bstrSourceDisplayName = szSourceDisplayName;
|
|
hr = pEventSource->put_DisplayName(bstrSourceDisplayName);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// create the event database for this source
|
|
CComPtr<IEventDatabaseManager> pDatabaseManager;
|
|
hr = CoCreateInstance(CLSID_CEventMetabaseDatabaseManager, NULL, CLSCTX_ALL,
|
|
IID_IEventDatabaseManager, (LPVOID *) &pDatabaseManager);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
CComBSTR bstrEventPath;
|
|
CComBSTR bstrService = "smtpsvc";
|
|
hr = pDatabaseManager->MakeVServerPath(bstrService, dwInstanceID, &bstrEventPath);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
CComPtr<IUnknown> pDatabaseMoniker;
|
|
hr = pDatabaseManager->CreateDatabase(bstrEventPath, &pDatabaseMoniker);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = pEventSource->put_BindingManagerMoniker(pDatabaseMoniker);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// save everything we've done so far
|
|
hr = pEventSource->Save();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = pSourceType->Save();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// this function performs instance level unregistration
|
|
//
|
|
HRESULT UnregisterPlatSEOInstance(DWORD dwInstanceID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// find the SMTP source type in the event manager
|
|
//
|
|
CComPtr<IEventManager> pEventManager;
|
|
hr = CoCreateInstance(CLSID_CEventManager, NULL, CLSCTX_ALL,
|
|
IID_IEventManager, (LPVOID *) &pEventManager);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
CComPtr<IEventSourceTypes> pSourceTypes;
|
|
hr = pEventManager->get_SourceTypes(&pSourceTypes);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
CComPtr<IEventSourceType> pSourceType;
|
|
CComBSTR bstrSourceTypeGUID = (LPCOLESTR) CStringGUID(GUID_SMTP_SOURCE_TYPE);
|
|
hr = pSourceTypes->Item(&CComVariant(bstrSourceTypeGUID), &pSourceType);
|
|
_ASSERT(hr != S_OK || pSourceType != NULL);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
//
|
|
// generate a GUID for this source, which is based on GUID_SMTPSVC
|
|
// mangled by the instance ID
|
|
//
|
|
CComPtr<IEventUtil> pEventUtil;
|
|
hr = CoCreateInstance(CLSID_CEventUtil, NULL, CLSCTX_ALL,
|
|
IID_IEventUtil, (LPVOID *) &pEventUtil);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
CComBSTR bstrSMTPSvcGUID = (LPCOLESTR) CStringGUID(GUID_SMTPSVC_SOURCE);
|
|
CComBSTR bstrSourceGUID;
|
|
hr = pEventUtil->GetIndexedGUID(bstrSMTPSvcGUID, dwInstanceID, &bstrSourceGUID);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
//
|
|
// remove this source from the list of registered sources
|
|
//
|
|
CComPtr<IEventSources> pEventSources;
|
|
hr = pSourceType->get_Sources(&pEventSources);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
CComPtr<IEventSource> pEventSource;
|
|
hr = pEventSources->Remove(&CComVariant(bstrSourceGUID));
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::Dispatcher
|
|
//
|
|
// Synopsis: Override the default functionality in seolib.cpp to
|
|
// provide some extra features (default functionality
|
|
//
|
|
// Arguments:
|
|
// rguidEventType: Guid specifying a server event
|
|
// pParams: CStoreBaseParams -- contains async info
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, at least one sink called
|
|
// S_FALSE: No sinks were called
|
|
// otherwise error from CallObject
|
|
//
|
|
// History:
|
|
// jstamerj 980603 19:23:06: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CStoreDispatcher::Dispatcher(
|
|
REFIID rguidEventType,
|
|
CStoreBaseParams *pParams)
|
|
{
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::Dispatcher");
|
|
_ASSERT(pParams);
|
|
|
|
//
|
|
// This code based on %STAXPT%\src\core\seo\lib\seolib.cpp
|
|
//
|
|
HRESULT hrRes = S_OK;
|
|
CETData *petdData;
|
|
BOOL bObjectCalled = (pParams->m_dwIdx_SinkSkip > 0);
|
|
|
|
//
|
|
// AddRef pParams here, release at the end of the function
|
|
// This way, if a sink returns MAILTRANSPORT_S_PENDING and does
|
|
// async completion before this function exits, we wont AV
|
|
// accessing pParams
|
|
//
|
|
pParams->AddRef();
|
|
|
|
petdData = m_Data.Find(rguidEventType);
|
|
if(pParams->m_dwIdx_SinkSkip != SKIPSINK_CALL_NO_MORE_SINKS) {
|
|
if(petdData) {
|
|
for(DWORD dwIdx = pParams->m_dwIdx_SinkSkip;
|
|
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;
|
|
}
|
|
//
|
|
// Call default processing method if the priority of the sink
|
|
// we're looking at is less than default priority
|
|
//
|
|
if((pParams->m_fDefaultProcessingCalled == FALSE) &&
|
|
(petdData->Index(dwIdx)->m_dwPriority >
|
|
SMTP_TRANSPORT_DEFAULT_PRIORITY)) {
|
|
|
|
// This is needed so we don't call the default
|
|
// processing again if the default processing returns
|
|
// MAILTRANSPORT_S_PENDING (and we reenter Dispatcher)
|
|
pParams->m_fDefaultProcessingCalled = TRUE;
|
|
|
|
//
|
|
// Set the correct index in our async structure -- our
|
|
// current index.
|
|
//
|
|
pParams->m_dwIdx_SinkSkip = dwIdx;
|
|
hrRes = pParams->CallDefault();
|
|
|
|
if((hrRes == MAILTRANSPORT_S_PENDING) ||
|
|
(hrRes == S_FALSE)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now proceed with calling a real sink
|
|
//
|
|
hrRes = pParams->CheckRule(*petdData->Index(dwIdx));
|
|
if(hrRes == S_OK) {
|
|
if(pParams->Abort() == S_OK) {
|
|
break;
|
|
}
|
|
//
|
|
// jstamerj 980603 19:37:17: Set the correct index in our
|
|
// async structure -- this index plus one to skip the
|
|
// sink we are about to call
|
|
//
|
|
pParams->m_dwIdx_SinkSkip = dwIdx+1;
|
|
hrRes = pParams->CallObject(
|
|
m_piEventManager,
|
|
*petdData->Index(dwIdx));
|
|
|
|
if(!SUCCEEDED(hrRes)) {
|
|
continue;
|
|
}
|
|
bObjectCalled = TRUE;
|
|
if((hrRes == MAILTRANSPORT_S_PENDING) ||
|
|
(hrRes == S_FALSE) ||
|
|
(petdData->Index(dwIdx)->m_bExclusive)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// It is possible we haven't called our default processing sink
|
|
// yet. Check for this case here. Make sure that a sink above in
|
|
// the loop isn't indicating async completion or skip (PENDING or
|
|
// S_FALSE)
|
|
//
|
|
if((pParams->m_fDefaultProcessingCalled == FALSE) &&
|
|
(hrRes != MAILTRANSPORT_S_PENDING) &&
|
|
(hrRes != S_FALSE)) {
|
|
|
|
// Make sure we don't call default again on async completion...
|
|
pParams->m_fDefaultProcessingCalled = TRUE;
|
|
|
|
//
|
|
// Set the index in our async structure so we don't reenter
|
|
// the above loop on async completion
|
|
//
|
|
pParams->m_dwIdx_SinkSkip = (petdData ? petdData->Count() : 0);
|
|
|
|
hrRes = pParams->CallDefault();
|
|
}
|
|
} else {
|
|
// bObjectCalled should always be set if SKIPSINK_CALL_NO_MORE_SINKS
|
|
// was set
|
|
_ASSERT(bObjectCalled);
|
|
}
|
|
|
|
if(hrRes != MAILTRANSPORT_S_PENDING) {
|
|
//
|
|
// It is time to call the completion processing
|
|
//
|
|
hrRes = pParams->CallCompletion(bObjectCalled ? S_OK : S_FALSE);
|
|
if(FAILED(hrRes)) {
|
|
goto CLEANUP;
|
|
}
|
|
hrRes = (bObjectCalled) ? S_OK : S_FALSE;
|
|
}
|
|
|
|
CLEANUP:
|
|
pParams->Release();
|
|
|
|
DebugTrace((LPARAM)this, "returning hr %08lx", hrRes);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hrRes;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::Notify
|
|
//
|
|
// Synopsis: Handles async completions of sinks
|
|
//
|
|
// Arguments: pvContext - context passed into sink
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
// E_INVALIDARG:
|
|
//
|
|
// History:
|
|
// jstamerj 980608 15:50:57: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CStoreDispatcher::Notify(
|
|
HRESULT hrStatus,
|
|
PVOID pvContext)
|
|
{
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::Notify");
|
|
|
|
_ASSERT(pvContext);
|
|
if((pvContext == NULL) ||
|
|
IsBadReadPtr(
|
|
pvContext,
|
|
sizeof(CStoreBaseParams))) {
|
|
ErrorTrace((LPARAM)this, "Sink called Notify with bogus pvContext");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
CStoreBaseParams *pParams = (CStoreBaseParams *)pvContext;
|
|
|
|
if(FAILED(pParams->CheckSignature())) {
|
|
ErrorTrace((LPARAM)this, "Sink called Notify with invalid pvContext");
|
|
return E_INVALIDARG;
|
|
}
|
|
//
|
|
// Release the sink that called us
|
|
// m_pIUnknownSink could be NULL if default processing returned pending
|
|
//
|
|
if(pParams->m_pIUnknownSink) {
|
|
pParams->m_pIUnknownSink->Release();
|
|
pParams->m_pIUnknownSink = NULL;
|
|
}
|
|
|
|
if (hrStatus == S_FALSE) {
|
|
// prevent the dispatcher from calling any more sinks.
|
|
pParams->m_dwIdx_SinkSkip = SKIPSINK_CALL_NO_MORE_SINKS;
|
|
}
|
|
Dispatcher(pParams->m_rguidEventType, pParams);
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// CMailTransportSubmissionParams:
|
|
//
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportSubmissionParams::CallObject
|
|
//
|
|
// Synopsis: Create and call the child object
|
|
//
|
|
// Arguments:
|
|
// CBinding
|
|
// punkObject
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// jstamerj 980610 19:04:59: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportSubmissionParams::CallObject(
|
|
CBinding& bBinding,
|
|
IUnknown *punkObject)
|
|
{
|
|
HRESULT hrRes = S_OK;
|
|
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportSubmissionParams::CallObject");
|
|
|
|
_ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_SUBMISSION_EVENT);
|
|
|
|
IMailTransportSubmission *pSink;
|
|
|
|
hrRes = punkObject->QueryInterface(IID_IMailTransportSubmission,
|
|
(PVOID *)&pSink);
|
|
|
|
if(hrRes == E_NOINTERFACE) {
|
|
//
|
|
// See if we can get the interfaces we need for a CDO sink
|
|
//
|
|
hrRes = CallCDOSink(punkObject);
|
|
//
|
|
// Success or failure, return here
|
|
//
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hrRes;
|
|
} else if(FAILED(hrRes)) {
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return(hrRes);
|
|
}
|
|
|
|
//
|
|
// Remember the sink so we can release this sink later if it
|
|
// returns pending
|
|
//
|
|
_ASSERT(m_pIUnknownSink == NULL);
|
|
m_pIUnknownSink = (IUnknown*)pSink;
|
|
m_pIUnknownSink->AddRef();
|
|
|
|
DebugTrace((LPARAM)this, "Calling submission event on this sink");
|
|
|
|
hrRes = pSink->OnMessageSubmission(
|
|
m_Context.pIMailMsgProperties,
|
|
m_pINotify,
|
|
(PVOID)this);
|
|
|
|
//
|
|
// We are done with pSink so release it
|
|
// In case of async completion, we hold a reference to the sink in
|
|
// m_pIUnknownSink
|
|
//
|
|
pSink->Release();
|
|
|
|
if(hrRes != MAILTRANSPORT_S_PENDING) {
|
|
//
|
|
// We completed synchronously, so release the sink
|
|
//
|
|
m_pIUnknownSink->Release();
|
|
m_pIUnknownSink = NULL;
|
|
}
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return(hrRes);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportSubmissionParams::CallCDOSink
|
|
//
|
|
// Synopsis: Call the CDO Sink
|
|
//
|
|
// Arguments:
|
|
// pSink: IUnknown of the sink
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// jstamerj 1998/07/02 10:31:47: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportSubmissionParams::CallCDOSink(
|
|
IUnknown *pSink)
|
|
{
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportSubmissionParams::CallCDOSink");
|
|
_ASSERT(pSink);
|
|
|
|
HRESULT hr;
|
|
ISMTPOnArrival *pCDOSink = NULL;
|
|
IConstructIMessageFromIMailMsg *pIConstruct = NULL;
|
|
CdoEventStatus eStatus = cdoRunNextSink;
|
|
|
|
hr = pSink->QueryInterface(IID_ISMTPOnArrival,
|
|
(PVOID *)&pCDOSink);
|
|
if(FAILED(hr))
|
|
goto CLEANUP;
|
|
|
|
if(m_pCDOMessage == NULL) {
|
|
//
|
|
// Yay. Create a CDO message
|
|
//
|
|
hr = CoCreateInstance(
|
|
CLSID_Message,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IMessage,
|
|
(LPVOID *)&m_pCDOMessage);
|
|
if(FAILED(hr))
|
|
goto CLEANUP;
|
|
|
|
//
|
|
// Fill in properties based on MailMsg
|
|
//
|
|
hr = m_pCDOMessage->QueryInterface(
|
|
IID_IConstructIMessageFromIMailMsg,
|
|
(LPVOID *)&pIConstruct);
|
|
if(FAILED(hr)) {
|
|
m_pCDOMessage->Release();
|
|
m_pCDOMessage = NULL;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
hr = pIConstruct->Construct(
|
|
cdoSMTPOnArrival,
|
|
m_Context.pIMailMsgProperties);
|
|
if(FAILED(hr)) {
|
|
m_pCDOMessage->Release();
|
|
m_pCDOMessage = NULL;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Call the sink
|
|
//
|
|
hr = pCDOSink->OnArrival(
|
|
m_pCDOMessage,
|
|
&eStatus);
|
|
|
|
CLEANUP:
|
|
//
|
|
// Release interfaces
|
|
//
|
|
if(pIConstruct)
|
|
pIConstruct->Release();
|
|
if(pCDOSink)
|
|
pCDOSink->Release();
|
|
|
|
DebugTrace((LPARAM)this, "CallCDOSink returning hr %08lx eStatus %d", hr, eStatus);
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return FAILED(hr) ? hr :
|
|
((eStatus == cdoSkipRemainingSinks) ? S_FALSE : S_OK);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportSubmissionParams
|
|
//
|
|
// Synopsis: The dispatcher will call this routine when it the default
|
|
// sink processing priority is reached
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, continueing calling sinks
|
|
// S_FALSE: Stop calling sinks
|
|
// MAILTRANSPORT_S_PENDING: Will call IMailTransportNotify::Notify
|
|
// when we are done.
|
|
//
|
|
// History:
|
|
// jstamerj 980611 14:15:43: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportSubmissionParams::CallDefault()
|
|
{
|
|
//
|
|
// No sinks need default processing yet..
|
|
//
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDriver::CMailTransportSubmissionParams::CallCompletion
|
|
//
|
|
// Synopsis: The dispatcher will call this routine after all sinks
|
|
// have been called
|
|
//
|
|
// Arguments:
|
|
// hrStatus: Status server event sinks have returned
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// jstamerj 980611 14:17:51: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportSubmissionParams::CallCompletion(
|
|
HRESULT hrStatus)
|
|
{
|
|
_ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_SUBMISSION_EVENT);
|
|
|
|
(*m_Context.pfnCompletion)(hrStatus, &m_Context);
|
|
|
|
CStoreBaseParams::CallCompletion(hrStatus);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportSubmissionParams::CheckRule
|
|
//
|
|
// Synopsis: Check to see if this sink should be called or not
|
|
//
|
|
// Arguments:
|
|
// bBinding: CBinding object for this sink
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, call the sink
|
|
// S_FALSE: Success, do not call the sink
|
|
// or error from mailmsg (sink will not be called)
|
|
//
|
|
// History:
|
|
// jstamerj 1999/01/12 16:55:29: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportSubmissionParams::CheckRule(
|
|
CBinding &bBinding)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TraceFunctEnterEx((LPARAM)this,
|
|
"CStoreDispatcher::CMailTransportSubmissionParams::CheckRule");
|
|
|
|
//
|
|
// Call the generic function to check a mailmsg rule
|
|
//
|
|
hr = CheckMailMsgRule(
|
|
&bBinding,
|
|
m_Context.pIMailMsgProperties);
|
|
|
|
DebugTrace((LPARAM)this, "returning hr %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// CMailTransportPreCategorizeParams:
|
|
//
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportPreCategorizeParams::CallObject
|
|
//
|
|
// Synopsis: Create and call the child object
|
|
//
|
|
// Arguments:
|
|
// CBinding
|
|
// punkObject
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// jstamerj 980610 19:04:59: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportPreCategorizeParams::CallObject(
|
|
CBinding& bBinding,
|
|
IUnknown *punkObject)
|
|
{
|
|
HRESULT hrRes = S_OK;
|
|
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportPreCategorizeParams::CallObject");
|
|
|
|
_ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_PRECATEGORIZE_EVENT);
|
|
|
|
IMailTransportOnPreCategorize *pSink;
|
|
|
|
hrRes = punkObject->QueryInterface(IID_IMailTransportOnPreCategorize,
|
|
(PVOID *)&pSink);
|
|
if(FAILED(hrRes))
|
|
return(hrRes);
|
|
|
|
//
|
|
// Remember the sink so we can release this sink later if it
|
|
// returns pending
|
|
//
|
|
_ASSERT(m_pIUnknownSink == NULL);
|
|
m_pIUnknownSink = (IUnknown*)pSink;
|
|
m_pIUnknownSink->AddRef();
|
|
|
|
DebugTrace((LPARAM)this, "Calling precategorize event on this sink");
|
|
|
|
hrRes = pSink->OnSyncMessagePreCategorize(
|
|
m_Context.pIMailMsgProperties,
|
|
m_pINotify,
|
|
(PVOID)this);
|
|
|
|
//
|
|
// We are done with pSink so release it
|
|
// In case of async completion, we hold a reference to the sink in
|
|
// m_pIUnknownSink
|
|
//
|
|
pSink->Release();
|
|
|
|
if(hrRes != MAILTRANSPORT_S_PENDING) {
|
|
//
|
|
// We completed synchronously, so release the sink
|
|
//
|
|
m_pIUnknownSink->Release();
|
|
m_pIUnknownSink = NULL;
|
|
}
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return(hrRes);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportPreCategorizeParams
|
|
//
|
|
// Synopsis: The dispatcher will call this routine when it the default
|
|
// sink processing priority is reached
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, continueing calling sinks
|
|
// S_FALSE: Stop calling sinks
|
|
// MAILTRANSPORT_S_PENDING: Will call IMailTransportNotify::Notify
|
|
// when we are done.
|
|
//
|
|
// History:
|
|
// jstamerj 980611 14:15:43: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportPreCategorizeParams::CallDefault()
|
|
{
|
|
//
|
|
// No sinks need default processing yet..
|
|
//
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDriver::CMailTransportPreCategorizeParams::CallCompletion
|
|
//
|
|
// Synopsis: The dispatcher will call this routine after all sinks
|
|
// have been called
|
|
//
|
|
// Arguments:
|
|
// hrStatus: Status server event sinks have returned
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// jstamerj 980611 14:17:51: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportPreCategorizeParams::CallCompletion(
|
|
HRESULT hrStatus)
|
|
{
|
|
_ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_PRECATEGORIZE_EVENT);
|
|
(*m_Context.pfnCompletion)(hrStatus, &m_Context);
|
|
|
|
CStoreBaseParams::CallCompletion(hrStatus);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportPreCategorizeParams::CheckRule
|
|
//
|
|
// Synopsis: Check to see if this sink should be called or not
|
|
//
|
|
// Arguments:
|
|
// bBinding: CBinding object for this sink
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, call the sink
|
|
// S_FALSE: Success, do not call the sink
|
|
// or error from mailmsg (sink will not be called)
|
|
//
|
|
// History:
|
|
// jstamerj 1999/01/12 16:59:59: Created
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportPreCategorizeParams::CheckRule(
|
|
CBinding &bBinding)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TraceFunctEnterEx((LPARAM)this,
|
|
"CStoreDispatcher::CMailTransportPreCategorizeParams::CheckRule");
|
|
|
|
//
|
|
// Call the generic function to check a mailmsg rule
|
|
//
|
|
hr = CheckMailMsgRule(
|
|
&bBinding,
|
|
m_Context.pIMailMsgProperties);
|
|
|
|
DebugTrace((LPARAM)this, "returning hr %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// CMailTransportPostCategorizeParams:
|
|
//
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportPostCategorizeParams::CallObject
|
|
//
|
|
// Synopsis: Create and call the child object
|
|
//
|
|
// Arguments:
|
|
// CBinding
|
|
// punkObject
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// jstamerj 980610 19:04:59: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportPostCategorizeParams::CallObject(
|
|
CBinding& bBinding,
|
|
IUnknown *punkObject)
|
|
{
|
|
HRESULT hrRes = S_OK;
|
|
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportPostCategorizeParams::CallObject");
|
|
|
|
_ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_POSTCATEGORIZE_EVENT);
|
|
|
|
IMailTransportOnPostCategorize *pSink;
|
|
|
|
hrRes = punkObject->QueryInterface(IID_IMailTransportOnPostCategorize,
|
|
(PVOID *)&pSink);
|
|
if(FAILED(hrRes))
|
|
return(hrRes);
|
|
|
|
//
|
|
// Remember the sink so we can release this sink later if it
|
|
// returns pending
|
|
//
|
|
_ASSERT(m_pIUnknownSink == NULL);
|
|
m_pIUnknownSink = (IUnknown*)pSink;
|
|
m_pIUnknownSink->AddRef();
|
|
|
|
DebugTrace((LPARAM)this, "Calling submission event on this sink");
|
|
|
|
hrRes = pSink->OnMessagePostCategorize(
|
|
m_Context.pIMailMsgProperties,
|
|
m_pINotify,
|
|
(PVOID)this);
|
|
|
|
//
|
|
// We are done with pSink so release it
|
|
// In case of async completion, we hold a reference to the sink in
|
|
// m_pIUnknownSink
|
|
//
|
|
pSink->Release();
|
|
|
|
if(hrRes != MAILTRANSPORT_S_PENDING) {
|
|
//
|
|
// We completed synchronously, so release the sink
|
|
//
|
|
m_pIUnknownSink->Release();
|
|
m_pIUnknownSink = NULL;
|
|
}
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return(hrRes);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportPostCategorizeParams
|
|
//
|
|
// Synopsis: The dispatcher will call this routine when it the default
|
|
// sink processing priority is reached
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, continueing calling sinks
|
|
// S_FALSE: Stop calling sinks
|
|
// MAILTRANSPORT_S_PENDING: Will call IMailTransportNotify::Notify
|
|
// when we are done.
|
|
//
|
|
// History:
|
|
// jstamerj 980611 14:15:43: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportPostCategorizeParams::CallDefault()
|
|
{
|
|
//
|
|
// No sinks need default processing yet..
|
|
//
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDriver::CMailTransportPostCategorizeParams::CallCompletion
|
|
//
|
|
// Synopsis: The dispatcher will call this routine after all sinks
|
|
// have been called
|
|
//
|
|
// Arguments:
|
|
// hrStatus: Status server event sinks have returned
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// jstamerj 980611 14:17:51: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportPostCategorizeParams::CallCompletion(
|
|
HRESULT hrStatus)
|
|
{
|
|
_ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_POSTCATEGORIZE_EVENT);
|
|
(*m_Context.pfnCompletion)(hrStatus, &m_Context);
|
|
|
|
CStoreBaseParams::CallCompletion(hrStatus);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportPostCategorizeParams::CheckRule
|
|
//
|
|
// Synopsis: Check to see if this sink should be called or not
|
|
//
|
|
// Arguments:
|
|
// bBinding: CBinding object for this sink
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, call the sink
|
|
// S_FALSE: Success, do not call the sink
|
|
// or error from mailmsg (sink will not be called)
|
|
//
|
|
// History:
|
|
// jstamerj 1999/01/12 17:01:40: Created
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportPostCategorizeParams::CheckRule(
|
|
CBinding &bBinding)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TraceFunctEnterEx((LPARAM)this,
|
|
"CStoreDispatcher::CMailTransportPostCategorizeParams::CheckRule");
|
|
|
|
//
|
|
// Call the generic function to check a mailmsg rule
|
|
//
|
|
hr = CheckMailMsgRule(
|
|
&bBinding,
|
|
m_Context.pIMailMsgProperties);
|
|
|
|
DebugTrace((LPARAM)this, "returning hr %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
}
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CRouterCreateOptions::Init
|
|
//
|
|
// Synopsis: This is called right after we CoCreate any routing sink
|
|
// -- so call routing's initialize function (RegisterRouterReset)
|
|
//
|
|
// Arguments:
|
|
// iidDesired: not used
|
|
// ppUnkObject: IUnknown of newly created sink object
|
|
// IEventBinding: not used
|
|
// IUnknown: not used
|
|
//
|
|
// Returns:
|
|
// E_NOTIMPL: Success, please do the regular Init thing
|
|
// otherwise error from QI or sink function
|
|
//
|
|
// History:
|
|
// jstamerj 1998/07/10 18:09:04: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CStoreDispatcher::CRouterCreateOptions::Init(
|
|
REFIID iidDesired,
|
|
IUnknown **ppUnkObject,
|
|
IEventBinding *,
|
|
IUnknown *)
|
|
{
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CRouterCreateOptions::Init");
|
|
|
|
IMailTransportSetRouterReset *pSink = NULL;
|
|
HRESULT hr;
|
|
|
|
hr = (*ppUnkObject)->QueryInterface(
|
|
IID_IMailTransportSetRouterReset,
|
|
(PVOID *)&pSink);
|
|
if(hr == E_NOINTERFACE) {
|
|
//
|
|
// It's okay; this sink just doesn't care about hooking
|
|
// the router reset interface
|
|
//
|
|
DebugTrace((LPARAM)this, "Router sink doesn't support IMailTransportSetRouterReset");
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return E_NOTIMPL;
|
|
|
|
} else if(FAILED(hr)) {
|
|
ErrorTrace((LPARAM)this,
|
|
"QI for IMailTransportSetRouterReset failed with hr %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
}
|
|
|
|
DebugTrace((LPARAM)this, "Calling RegisterRouterReset event onSink");
|
|
hr = pSink->RegisterResetInterface(
|
|
m_pContext->dwVirtualServerID,
|
|
m_pContext->pIRouterReset);
|
|
|
|
pSink->Release();
|
|
|
|
if(FAILED(hr) && (hr != E_NOTIMPL)) {
|
|
//
|
|
// A real failure occured
|
|
//
|
|
ErrorTrace((LPARAM)this, "RegisterResetInterface failed with hr %08lx", hr);
|
|
return hr;
|
|
}
|
|
//
|
|
// Return E_NOTIMPL so the real work of Init will be done
|
|
//
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//
|
|
// CMailTransportRoutingParams:
|
|
//
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportRouterParams::CallObject
|
|
//
|
|
// Synopsis: Creates (if necessary) and calls the sink object
|
|
//
|
|
// Arguments:
|
|
// pManager: IEventManager passed in from dispatcher
|
|
// bBinding: CBinding for this event
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
// E_POINTER: bad pManager
|
|
// or error from CreateSink/CallObject
|
|
//
|
|
// History:
|
|
// jstamerj 1998/07/10 18:15:09: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
//
|
|
// create and call the child object
|
|
//
|
|
HRESULT CStoreDispatcher::CMailTransportRouterParams::CallObject(
|
|
IEventManager *pManager,
|
|
CBinding& bBinding)
|
|
{
|
|
CRouterCreateOptions opt (m_pContext);
|
|
CComPtr<IUnknown> pUnkSink;
|
|
HRESULT hr;
|
|
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportRotuerParams::CallObject");
|
|
|
|
if (pManager == NULL) {
|
|
ErrorTrace((LPARAM)this, "Invalid (NULL) pManager");
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return (E_POINTER);
|
|
}
|
|
|
|
hr = pManager->CreateSink(bBinding.m_piBinding,&opt,&pUnkSink);
|
|
if (FAILED(hr)) {
|
|
ErrorTrace((LPARAM)this, "CreateSink returned error hr %08lx",
|
|
hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
}
|
|
hr = CallObject(bBinding,pUnkSink);
|
|
DebugTrace((LPARAM)this, "CallObject child returned error %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportRoutingParams::CallObject
|
|
//
|
|
// Synopsis: Create and call the child object
|
|
//
|
|
// Arguments:
|
|
// CBinding
|
|
// punkObject
|
|
//
|
|
// Returns:
|
|
// Error from QI or return code from sink function
|
|
//
|
|
// History:
|
|
// jstamerj 980610 19:04:59: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportRouterParams::CallObject(
|
|
CBinding& bBinding,
|
|
IUnknown *punkObject)
|
|
{
|
|
HRESULT hrRes = S_OK;
|
|
IMailTransportRoutingEngine *pSink;
|
|
IMessageRouter *pIMessageRouterNew = NULL;
|
|
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportRouterParams::CallObject");
|
|
|
|
_ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_GET_ROUTER_FOR_MESSAGE_EVENT);
|
|
|
|
//
|
|
// If they pass in a pIMailMsgProperties of NULL it means that they
|
|
// just want to create a router object, but not actually do the
|
|
// get message router call.
|
|
//
|
|
if (m_pContext->pIMailMsgProperties == NULL) {
|
|
DebugTrace((LPARAM) this, "Skipping GetMessageRouter call");
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return S_OK;
|
|
}
|
|
|
|
hrRes = punkObject->QueryInterface(IID_IMailTransportRoutingEngine,
|
|
(PVOID *)&pSink);
|
|
if(FAILED(hrRes))
|
|
return(hrRes);
|
|
|
|
DebugTrace((LPARAM)this, "Calling GetMessageRouter event on this sink");
|
|
|
|
hrRes = pSink->GetMessageRouter(
|
|
m_pContext->pIMailMsgProperties,
|
|
m_pContext->pIMessageRouter,
|
|
&(pIMessageRouterNew));
|
|
|
|
//
|
|
// This sink is not allowed to complete async
|
|
//
|
|
_ASSERT(hrRes != MAILTRANSPORT_S_PENDING);
|
|
|
|
//
|
|
// We are done with pSink so release it
|
|
//
|
|
pSink->Release();
|
|
|
|
//
|
|
// If GetMessageRouter succeeded AND it returned a new
|
|
// IMessageRouter, release the old one and save the new one.
|
|
//
|
|
if(SUCCEEDED(hrRes) && (pIMessageRouterNew != NULL)) {
|
|
|
|
if(m_pContext->pIMessageRouter) {
|
|
m_pContext->pIMessageRouter->Release();
|
|
}
|
|
m_pContext->pIMessageRouter = pIMessageRouterNew;
|
|
}
|
|
|
|
DebugTrace((LPARAM)this, "Sink GetMessageRouter returned hr %08lx", hrRes);
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return(hrRes);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CMailTransportRouterParams
|
|
//
|
|
// Synopsis: The dispatcher will call this routine when it the default
|
|
// sink processing priority is reached
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, continueing calling sinks
|
|
// S_FALSE: Stop calling sinks
|
|
//
|
|
// History:
|
|
// jstamerj 980611 14:15:43: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CMailTransportRouterParams::CallDefault()
|
|
{
|
|
HRESULT hrRes;
|
|
IMessageRouter *pIMessageRouterNew = NULL;
|
|
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportRouterParams::CallDefault");
|
|
|
|
_ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_GET_ROUTER_FOR_MESSAGE_EVENT);
|
|
|
|
if (m_pContext->pIMailMsgProperties == NULL) {
|
|
DebugTrace((LPARAM) this, "Skipping GetMessageRouter call");
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Call the default IMailTransportRoutingEngine (CatMsgQueue)
|
|
// just like any other sink except SEO didn't CoCreate it for us
|
|
//
|
|
|
|
DebugTrace((LPARAM)this, "Calling GetMessageRouter event on default sink");
|
|
|
|
hrRes = m_pContext->pIRoutingEngineDefault->GetMessageRouter(
|
|
m_pContext->pIMailMsgProperties,
|
|
m_pContext->pIMessageRouter,
|
|
&pIMessageRouterNew);
|
|
|
|
//
|
|
// This sink is not allowed to complete async
|
|
//
|
|
_ASSERT(hrRes != MAILTRANSPORT_S_PENDING);
|
|
|
|
//
|
|
// If GetMessageRouter succeeded AND it returned a new
|
|
// IMessageRouter, release the old one.
|
|
//
|
|
if(SUCCEEDED(hrRes) && (pIMessageRouterNew != NULL)) {
|
|
|
|
if(m_pContext->pIMessageRouter) {
|
|
m_pContext->pIMessageRouter->Release();
|
|
}
|
|
m_pContext->pIMessageRouter = pIMessageRouterNew;
|
|
}
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
|
|
DebugTrace((LPARAM)this, "Default processing returned hr %08lx", hrRes);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hrRes;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CStoreDispatcher::CMsgTrackLogParams::CallObject(
|
|
CBinding& bBinding,
|
|
IUnknown *punkObject )
|
|
{
|
|
IMsgTrackLog *pSink = NULL;
|
|
|
|
HRESULT hr = punkObject->QueryInterface(IID_IMsgTrackLog, (void **)&pSink);
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
return( hr );
|
|
}
|
|
|
|
hr = pSink->OnSyncLogMsgTrackInfo(
|
|
m_pContext->pIServer,
|
|
m_pContext->pIMailMsgProperties,
|
|
m_pContext->pMsgTrackInfo );
|
|
|
|
pSink->Release();
|
|
|
|
return( hr );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CStoreDispatcher::CMsgTrackLogParams::CallDefault()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CStoreDispatcher::CDnsResolverRecordParams::CallObject(
|
|
CBinding& bBinding,
|
|
IUnknown *punkObject )
|
|
{
|
|
IDnsResolverRecordSink *pSink = NULL;
|
|
|
|
HRESULT hr = punkObject->QueryInterface(IID_IDnsResolverRecordSink, (void **)&pSink);
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
return( hr );
|
|
}
|
|
|
|
hr = pSink->OnSyncGetResolverRecord( m_pContext->pszHostName,
|
|
m_pContext->pszFQDN,
|
|
m_pContext->dwVirtualServerId,
|
|
m_pContext->ppIDnsResolverRecord );
|
|
|
|
pSink->Release();
|
|
|
|
return( hr );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CStoreDispatcher::CDnsResolverRecordParams::CallDefault()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CStoreDispatcher::CSmtpMaxMsgSizeParams::CallObject(
|
|
CBinding& bBinding,
|
|
IUnknown *punkObject )
|
|
{
|
|
ISmtpMaxMsgSize *pSink = NULL;
|
|
|
|
HRESULT hr = punkObject->QueryInterface(IID_ISmtpMaxMsgSize, (void **)&pSink);
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
return( hr );
|
|
}
|
|
|
|
hr = pSink->OnSyncMaxMsgSize( m_pContext->pIUnknown, m_pContext->pIMailMsg, m_pContext->pfShouldImposeLimit );
|
|
|
|
pSink->Release();
|
|
|
|
return( hr );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CStoreDispatcher::CSmtpMaxMsgSizeParams::CallDefault()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CDSNCreateOptions::Init
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
// iidDesired: not used
|
|
// ppUnkObject: IUnknown of newly created sink object
|
|
// IEventBinding: not used
|
|
// IUnknown: not used
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// jstamerj 2000/12/12 15:38:40: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CDSNCreateOptions::Init(
|
|
REFIID iidDesired,
|
|
IUnknown **ppUnkObject,
|
|
IEventBinding *,
|
|
IUnknown *)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IDSNGenerationSink *pSink = NULL;
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CDSNCreateOptions::Init");
|
|
|
|
hr = (*ppUnkObject)->QueryInterface(
|
|
IID_IDSNGenerationSink,
|
|
(PVOID *)&pSink);
|
|
if(FAILED(hr)) {
|
|
ErrorTrace((LPARAM)this,
|
|
"QI for IDSNGenerationSink failed with hr %08lx", hr);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
DebugTrace((LPARAM)this, "Calling Init");
|
|
hr = pSink->OnSyncSinkInit(
|
|
m_dwVSID);
|
|
|
|
if(FAILED(hr) && (hr != E_NOTIMPL)) {
|
|
//
|
|
// A real failure occured
|
|
//
|
|
ErrorTrace((LPARAM)this, "Init failed with hr %08lx", hr);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
CLEANUP:
|
|
if(pSink)
|
|
pSink->Release();
|
|
|
|
DebugTrace((LPARAM)this, "returning %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
//
|
|
// Return E_NOTIMPL so the real work of Init will be done
|
|
//
|
|
return SUCCEEDED(hr) ? E_NOTIMPL : hr;
|
|
} // CStoreDispatcher::CDSNCreateOptions::Init
|
|
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CDSNBaseParams::CallObject
|
|
//
|
|
// Synopsis: Create/call the event sink
|
|
//
|
|
// Arguments:
|
|
// pManager: SEO's IEventManager
|
|
// bBinding: event binding
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// jstamerj 2000/12/12 15:35:35: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CDSNBaseParams::CallObject(
|
|
IEventManager *pManager,
|
|
CBinding& bBinding)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CDSNCreateOptions opt(GetVSID());
|
|
CComPtr<IUnknown> pUnkSink;
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CDSNBaseParams::CallObject");
|
|
if (pManager == NULL) {
|
|
ErrorTrace((LPARAM)this, "Invalid (NULL) pManager");
|
|
hr = E_POINTER;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
hr = pManager->CreateSink(bBinding.m_piBinding,&opt,&pUnkSink);
|
|
if (FAILED(hr)) {
|
|
ErrorTrace((LPARAM)this, "CreateSink returned error hr %08lx",
|
|
hr);
|
|
goto CLEANUP;
|
|
}
|
|
hr = CallObject(bBinding,pUnkSink);
|
|
DebugTrace((LPARAM)this, "CallObject child returned error %08lx", hr);
|
|
|
|
CLEANUP:
|
|
DebugTrace((LPARAM)this, "returning %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
} // CStoreDispatcher::CDSNBaseParams::CallObject
|
|
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CDSNRecipientIteratorParams::CallObject
|
|
//
|
|
// Synopsis: Call the OnSyncGetDSNRecipientIterator method of a sink
|
|
//
|
|
// Arguments:
|
|
// bBinding: event binding
|
|
// punkObject: IUnknown of the sink
|
|
//
|
|
// Returns:
|
|
// Return value from sink
|
|
//
|
|
// History:
|
|
// jstamerj 2000/12/11 15:14:41: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CDSNRecipientIteratorParams::CallObject(
|
|
CBinding& bBinding,
|
|
IUnknown *punkObject)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IDSNGenerationSink *pSink = NULL;
|
|
IDSNRecipientIterator *pIRecipIter = NULL;
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CDSNRecipientIteratorParams::CallObject");
|
|
|
|
hr = punkObject->QueryInterface(
|
|
IID_IDSNGenerationSink,
|
|
(LPVOID *)&pSink);
|
|
if(FAILED(hr))
|
|
{
|
|
pSink = NULL;
|
|
ErrorTrace((LPARAM)this, "QI for IDSNGenerationSink failed hr %08lx", hr);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
hr = pSink->OnSyncGetDSNRecipientIterator(
|
|
m_pContext->pISMTPServer,
|
|
m_pContext->pIMsg,
|
|
m_pContext->pDSNProperties,
|
|
m_pContext->dwStartDomain,
|
|
m_pContext->dwDSNActions,
|
|
m_pContext->pRecipIter,
|
|
&pIRecipIter);
|
|
_ASSERT(hr != MAILTRANSPORT_S_PENDING);
|
|
DebugTrace((LPARAM)this, "sink returned hr %08lx", hr);
|
|
|
|
if(SUCCEEDED(hr) && (pIRecipIter != NULL))
|
|
{
|
|
//
|
|
// Capture the new interface
|
|
//
|
|
if(m_pContext->pRecipIter)
|
|
m_pContext->pRecipIter->Release();
|
|
//
|
|
// Transfer refcount
|
|
//
|
|
m_pContext->pRecipIter = pIRecipIter;
|
|
pIRecipIter = NULL;
|
|
}
|
|
|
|
CLEANUP:
|
|
if(pSink)
|
|
pSink->Release();
|
|
DebugTrace((LPARAM)this, "returning %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
} // CStoreDispatcher::CDSNRecipientIteratorParams::CallObject
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CDSNGenerateParams::CallObject
|
|
//
|
|
// Synopsis: Call the OnSyncGenerateDSN method of a sink
|
|
//
|
|
// Arguments:
|
|
// bBinding: event binding
|
|
// punkObject: IUnknown of the sink
|
|
//
|
|
// Returns:
|
|
// Return value from sink
|
|
//
|
|
// History:
|
|
// jstamerj 2000/12/11 15:15:04: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CDSNGenerateParams::CallObject(
|
|
CBinding& bBinding,
|
|
IUnknown *punkObject)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IDSNGenerationSink *pSink = NULL;
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CDSNGenerateParams::CallObject");
|
|
hr = punkObject->QueryInterface(
|
|
IID_IDSNGenerationSink,
|
|
(LPVOID *)&pSink);
|
|
if(FAILED(hr))
|
|
{
|
|
pSink = NULL;
|
|
ErrorTrace((LPARAM)this, "QI for IDSNGenerationSink failed hr %08lx", hr);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
hr = pSink->OnSyncGenerateDSN(
|
|
m_pContext->pISMTPServer,
|
|
m_pContext->pIDSNSubmission,
|
|
m_pContext->pIMsg,
|
|
m_pContext->pDSNProperties,
|
|
m_pContext->pRecipIter);
|
|
_ASSERT(hr != MAILTRANSPORT_S_PENDING);
|
|
|
|
DebugTrace((LPARAM)this, "sink returned hr %08lx", hr);
|
|
|
|
CLEANUP:
|
|
if(pSink)
|
|
pSink->Release();
|
|
DebugTrace((LPARAM)this, "returning %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
} // CStoreDispatcher::CDSNGenerateParams::CallObject
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CDSNGenerateparams::CallDefault
|
|
//
|
|
// Synopsis: Call the OnSyncGenerateDSN method on the default sink
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns:
|
|
// Return value from default sink
|
|
//
|
|
// History:
|
|
// jstamerj 2000/12/11 15:15:21: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CDSNGenerateParams::CallDefault()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CDSNGenerateparams::CallDefault");
|
|
|
|
if(m_pContext->pDefaultSink)
|
|
{
|
|
hr = m_pContext->pDefaultSink->OnSyncGenerateDSN(
|
|
m_pContext->pISMTPServer,
|
|
m_pContext->pIDSNSubmission,
|
|
m_pContext->pIMsg,
|
|
m_pContext->pDSNProperties,
|
|
m_pContext->pRecipIter);
|
|
_ASSERT(hr != MAILTRANSPORT_S_PENDING);
|
|
}
|
|
|
|
DebugTrace((LPARAM)this, "returning %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
} // CStoreDispatcher::CDSNGenerateparams::CallDefault
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDispatcher::CDSNPostGenerateParams::CallObject
|
|
//
|
|
// Synopsis: Calls the OnSyncPostGenerateDSN method of a sink
|
|
//
|
|
// Arguments:
|
|
// bBinding: event binding
|
|
// punkObject: IUnknown of the sink
|
|
//
|
|
// Returns:
|
|
// Return value from sink
|
|
//
|
|
// History:
|
|
// jstamerj 2000/12/11 15:15:40: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CStoreDispatcher::CDSNPostGenerateParams::CallObject(
|
|
CBinding& bBinding,
|
|
IUnknown *punkObject)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IDSNGenerationSink *pSink = NULL;
|
|
TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CDSNPostGenerateParams::CallObject");
|
|
|
|
hr = punkObject->QueryInterface(
|
|
IID_IDSNGenerationSink,
|
|
(LPVOID *)&pSink);
|
|
if(FAILED(hr))
|
|
{
|
|
pSink = NULL;
|
|
ErrorTrace((LPARAM)this, "QI for IDSNGenerationSink failed hr %08lx", hr);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
hr = pSink->OnSyncPostGenerateDSN(
|
|
m_pContext->pISMTPServer,
|
|
m_pContext->pIMsgOrig,
|
|
m_pContext->dwDSNAction,
|
|
m_pContext->cRecipsDSNd,
|
|
m_pContext->pIMsgDSN,
|
|
m_pContext->pIDSNProperties);
|
|
_ASSERT(hr != MAILTRANSPORT_S_PENDING);
|
|
|
|
DebugTrace((LPARAM)this, "sink returned hr %08lx", hr);
|
|
|
|
CLEANUP:
|
|
if(pSink)
|
|
pSink->Release();
|
|
DebugTrace((LPARAM)this, "returning %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
} // CStoreDispatcher::CDSNPostGenerateParams::CallObject
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CStoreDriver::Setprevious
|
|
//
|
|
// Synopsis: Method of IEventDispatcherChain - gets calle dy the
|
|
// dispatcher, when binding changes happen.
|
|
//
|
|
// Arguments:
|
|
// pUnkPrevious: [in] Pointer to the previous dispatcher
|
|
// ppUnkPreload: [out] Receives an object which implements
|
|
// IEnumGUID, in order to tell the router
|
|
// which event types to pre-load.
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
//
|
|
// History:
|
|
// dondu 06/22/98 Created
|
|
//
|
|
//-------------------------------------------------------------
|
|
|
|
const GUID* g_apStoreDispEventTypes[] = {&CATID_SMTP_STORE_DRIVER,&GUID_NULL};
|
|
|
|
HRESULT STDMETHODCALLTYPE CStoreDispatcher::SetPrevious(IUnknown *pUnkPrevious, IUnknown **ppUnkPreload) {
|
|
HRESULT hrRes;
|
|
|
|
if (ppUnkPreload) {
|
|
*ppUnkPreload = NULL;
|
|
}
|
|
if (!ppUnkPreload) {
|
|
return (E_POINTER);
|
|
}
|
|
_ASSERT(pUnkPrevious);
|
|
if (pUnkPrevious) {
|
|
CComQIPtr<CStoreDispatcherData,&__uuidof(CStoreDispatcherData)> pData;
|
|
LPVOID pvServer;
|
|
DWORD dwServerInstance;
|
|
|
|
pData = pUnkPrevious;
|
|
_ASSERT(pData);
|
|
if (pData) {
|
|
hrRes = pData->GetData(&pvServer,&dwServerInstance);
|
|
|
|
// bugbug dbraun : removing this assert because it does not help us - we
|
|
// need to put some code in to get more meaningful data when this problem
|
|
// occurs
|
|
//_ASSERT(SUCCEEDED(hrRes));
|
|
|
|
if (SUCCEEDED(hrRes)) {
|
|
hrRes = SetData(pvServer,dwServerInstance);
|
|
_ASSERT(SUCCEEDED(hrRes));
|
|
}
|
|
}
|
|
}
|
|
hrRes = CEDEnumGUID::CreateNew(ppUnkPreload,g_apStoreDispEventTypes);
|
|
return (hrRes);
|
|
};
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CStoreDispatcher::SetContext(REFGUID guidEventType,
|
|
IEventRouter *piRouter,
|
|
IEventBindings *pBindings) {
|
|
HRESULT hrRes;
|
|
|
|
hrRes = CEventBaseDispatcher::SetContext(guidEventType,piRouter,pBindings);
|
|
if (SUCCEEDED(hrRes) && (guidEventType == CATID_SMTP_STORE_DRIVER)) {
|
|
HRESULT hrResTmp;
|
|
LPVOID pvServer;
|
|
DWORD dwServerInstance;
|
|
AQ_ALLOC_PARAMS AllocParams;
|
|
|
|
hrResTmp = GetData(&pvServer,&dwServerInstance);
|
|
if (SUCCEEDED(hrResTmp)) {
|
|
AllocParams.m_EventSmtpServer = (LPVOID *) pvServer;
|
|
AllocParams.m_InstanceId = dwServerInstance;
|
|
AllocParams.m_dwStartupType = SMTP_INIT_BINDING_CHANGE;
|
|
|
|
hrResTmp = OnEvent(CATID_SMTP_STORE_DRIVER,SMTP_STOREDRV_STARTUP_EVENT,&AllocParams);
|
|
_ASSERT(SUCCEEDED(hrResTmp));
|
|
}
|
|
}
|
|
return (hrRes);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CSMTPSeoMgr::CSMTPSeoMgr
|
|
//
|
|
// Synopsis: Initialize member data
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns: NOTHING
|
|
//
|
|
// History:
|
|
// jstamerj 1999/06/25 19:24:18: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
CSMTPSeoMgr::CSMTPSeoMgr()
|
|
{
|
|
TraceFunctEnterEx((LPARAM)this, "CSMTPSeoMgr::CSMTPSeoMgr");
|
|
|
|
m_dwSignature = SIGNATURE_CSMTPSEOMGR;
|
|
m_pIEventRouter = NULL;
|
|
m_pICatDispatcher = NULL;
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
} // CSMTPSeoMgr::CSMTPSeoMgr
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CSMTPSeoMgr::~CSMTPSeoMgr
|
|
//
|
|
// Synopsis: Deinitialize if necessary
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns: NOTHING
|
|
//
|
|
// History:
|
|
// jstamerj 1999/06/25 19:26:09: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
CSMTPSeoMgr::~CSMTPSeoMgr()
|
|
{
|
|
TraceFunctEnterEx((LPARAM)this, "CSMTPSeoMgr::~CSMTPSeoMgr");
|
|
|
|
Deinit();
|
|
|
|
_ASSERT(m_dwSignature == SIGNATURE_CSMTPSEOMGR);
|
|
m_dwSignature = SIGNATURE_CSMTPSEOMGR_INVALID;
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
} // CSMTPSeoMgr::~CSMTPSeoMgr
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CSMTPSeoMgr::HrInit
|
|
//
|
|
// Synopsis: Initialize
|
|
//
|
|
// Arguments:
|
|
// dwVSID: The virtual server ID
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
// error from SEO
|
|
//
|
|
// History:
|
|
// jstamerj 1999/06/25 19:27:30: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CSMTPSeoMgr::HrInit(
|
|
DWORD dwVSID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CStoreDispatcherClassFactory cf;
|
|
TraceFunctEnterEx((LPARAM)this, "CSMTPSeoMgr::HrInit");
|
|
|
|
_ASSERT(m_pIEventRouter == NULL);
|
|
|
|
hr = SEOGetRouter(
|
|
GUID_SMTP_SOURCE_TYPE,
|
|
(REFGUID) CStringGUID(GUID_SMTPSVC_SOURCE, dwVSID),
|
|
&m_pIEventRouter);
|
|
|
|
if(FAILED(hr) || (hr == S_FALSE)) {
|
|
//
|
|
// Map S_FALSE to file not found -- this happens when the
|
|
// source type is not registered
|
|
//
|
|
if(hr == S_FALSE)
|
|
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
|
|
|
ErrorTrace((LPARAM)this, "SEOGetRouter failed hr %08lx", hr);
|
|
m_pIEventRouter = NULL;
|
|
goto CLEANUP;
|
|
}
|
|
//
|
|
// Grab the dispatcher for the categorizer
|
|
//
|
|
_ASSERT(m_pICatDispatcher == NULL);
|
|
|
|
hr = m_pIEventRouter->GetDispatcherByClassFactory(
|
|
CLSID_CStoreDispatcher,
|
|
&cf,
|
|
CATID_SMTP_TRANSPORT_CATEGORIZE,
|
|
IID_IServerDispatcher,
|
|
(IUnknown **) &m_pICatDispatcher);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
ErrorTrace((LPARAM)this, "GetDispatcherByClassFactory failed hr %08lx", hr);
|
|
m_pICatDispatcher = NULL;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
CLEANUP:
|
|
if(FAILED(hr))
|
|
Deinit();
|
|
|
|
DebugTrace((LPARAM)this, "returning %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
} // CSMTPSeoMgr::HrInit
|
|
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CSMTPSeoMgr::Deinit
|
|
//
|
|
// Synopsis: Deinitialize member variables
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns: NOTHING
|
|
//
|
|
// History:
|
|
// jstamerj 1999/06/25 19:41:20: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
VOID CSMTPSeoMgr::Deinit()
|
|
{
|
|
TraceFunctEnterEx((LPARAM)this, "CSMTPSeoMgr::Deinit");
|
|
|
|
if(m_pICatDispatcher) {
|
|
m_pICatDispatcher->Release();
|
|
m_pICatDispatcher = NULL;
|
|
}
|
|
|
|
if(m_pIEventRouter) {
|
|
m_pIEventRouter->Release();
|
|
m_pIEventRouter = NULL;
|
|
}
|
|
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
} // CSMTPSeoMgr::Deinit
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CSMTPSeoMgr::HrTriggerServerEvent
|
|
//
|
|
// Synopsis: Trigger a server event
|
|
//
|
|
// Arguments:
|
|
// dwEventType: event type to trigger
|
|
// pvContext: structure specific to event type (see smtpseo.h)
|
|
//
|
|
// Returns:
|
|
// S_OK: Success, called one or more sinks
|
|
// S_FALSE: Success, no sinks called
|
|
// MAILTRANSPORT_S_PENDING: Proccessing events async
|
|
// E_OUTOFMEMORY
|
|
// error from SEO
|
|
//
|
|
// History:
|
|
// jstamerj 1999/06/25 19:43:00: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT CSMTPSeoMgr::HrTriggerServerEvent(
|
|
DWORD dwEventType,
|
|
PVOID pvContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IServerDispatcher> pEventDispatcher;
|
|
CStoreDispatcherClassFactory cf;
|
|
REFIID iidBindingPoint = GuidForEvent(dwEventType);
|
|
TraceFunctEnterEx((LPARAM)this, "CSMTPSeoMgr::HrTriggerServerEvent");
|
|
|
|
if(m_pIEventRouter == NULL)
|
|
return E_POINTER;
|
|
|
|
if(iidBindingPoint == CATID_SMTP_TRANSPORT_CATEGORIZE) {
|
|
//
|
|
// Use the cached Categorizer dispatcher
|
|
//
|
|
pEventDispatcher = m_pICatDispatcher;
|
|
|
|
} else {
|
|
//
|
|
// Get the latest dispatcher with all changes
|
|
//
|
|
hr = m_pIEventRouter->GetDispatcherByClassFactory(
|
|
CLSID_CStoreDispatcher,
|
|
&cf,
|
|
iidBindingPoint,
|
|
IID_IServerDispatcher,
|
|
(IUnknown **) &pEventDispatcher);
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
ErrorTrace((LPARAM)this, "GetDispatcherByClassFactory failed hr %08lx", hr);
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
hr = pEventDispatcher->OnEvent(
|
|
iidBindingPoint,
|
|
dwEventType,
|
|
pvContext);
|
|
|
|
CLEANUP:
|
|
DebugTrace((LPARAM)this, "returning %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)this);
|
|
return hr;
|
|
} // CSMTPSeoMgr::HrTriggerServerEvent
|