3147 lines
		
	
	
		
			89 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			3147 lines
		
	
	
		
			89 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
 | ||
| //#define INCL_INETSRV_INCS
 | ||
| //#include "smtpinc.h"
 | ||
| 
 | ||
| #include <atq.h>
 | ||
| #include <pudebug.h>
 | ||
| #include <inetcom.h>
 | ||
| #include <inetinfo.h>
 | ||
| #include <tcpdll.hxx>
 | ||
| #include <tsunami.hxx>
 | ||
| 
 | ||
| #include <tchar.h>
 | ||
| #include <iistypes.hxx>
 | ||
| #include <iisendp.hxx>
 | ||
| #include <metacach.hxx>
 | ||
| #include <cpool.h>
 | ||
| #include <address.hxx>
 | ||
| #include <mailmsgprops.h>
 | ||
| 
 | ||
| extern "C" {
 | ||
| #include <rpc.h>
 | ||
| #define SECURITY_WIN32
 | ||
| #include <wincrypt.h>
 | ||
| #include <sspi.h>
 | ||
| #include <spseal.h>
 | ||
| #include <issperr.h>
 | ||
| #include <ntlmsp.h>
 | ||
| }
 | ||
| 
 | ||
| #include <tcpproc.h>
 | ||
| #include <tcpcons.h>
 | ||
| #include <rdns.hxx>
 | ||
| #include <simauth2.h>
 | ||
| #include "dbgtrace.h"
 | ||
| 
 | ||
| #include "imd.h"
 | ||
| #include "mb.hxx"
 | ||
| 
 | ||
| #include <stdio.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 "filehc.h"
 | ||
| #include "seo.h"
 | ||
| #include "seolib.h"
 | ||
| 
 | ||
| #include "smtpdisp_i.c"
 | ||
| #include "mailmsgi.h"
 | ||
| #include <smtpevent.h>
 | ||
| #include "cdo.h"
 | ||
| #include "cdo_i.c"
 | ||
| #include "cdoconstimsg.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"
 | ||
| #include "wildmat.h"
 | ||
| #include "smtpdisp.h"
 | ||
| #include "seodisp.h"
 | ||
| 
 | ||
| #include "evntwrap.h"
 | ||
| 
 | ||
| // {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);
 | ||
| 
 | ||
| extern VOID
 | ||
| ServerEventCompletion(
 | ||
|     PVOID        pvContext,
 | ||
|     DWORD        cbWritten,
 | ||
|     DWORD        dwCompletionStatus,
 | ||
|     OVERLAPPED * lpo
 | ||
| );
 | ||
| 
 | ||
| class CStoreCreateOptions : public CEventCreateOptionsBase
 | ||
| {
 | ||
|   public:
 | ||
| 
 | ||
|     CStoreCreateOptions(    SMTP_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:
 | ||
|     SMTP_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(((SMTP_ALLOC_PARAMS *) pContext)->m_EventSmtpServer,
 | ||
|                          ((SMTP_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_LOG_EVENT:
 | ||
|      	 *ppCParams = new CSmtpLogParams();
 | ||
|      	 break;
 | ||
| 
 | ||
|      case SMTP_GET_AUX_DOMAIN_INFO_FLAGS_EVENT:
 | ||
|          *ppCParams = new CSmtpGetAuxDomainInfoFlagsParams();
 | ||
|          break;
 | ||
| 
 | ||
|      default:
 | ||
|          _ASSERT(0 && "Unknown server event");
 | ||
|          *ppCParams = NULL;
 | ||
|          break;
 | ||
|     }
 | ||
| 
 | ||
|     if(*ppCParams == NULL) {
 | ||
|         return E_OUTOFMEMORY;
 | ||
|     }
 | ||
| 
 | ||
|     hr = (*ppCParams)->InitParamData(
 | ||
|         pContext,
 | ||
|         dwEventType,
 | ||
|         pINotify,
 | ||
|         this,
 | ||
|         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;
 | ||
|     m_pDispatcher = 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,
 | ||
|     CStoreDispatcher *pDispatcher,
 | ||
|     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;
 | ||
|     m_pDispatcher = pDispatcher;
 | ||
| 
 | ||
|     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;
 | ||
|              PATQ_CONTEXT           pAtqFileContext = 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;
 | ||
| 
 | ||
| #if 0
 | ||
|                      hrRes = pBindInterface->BindToStore(pStream, pSink, m_pContext->hContent,
 | ||
|                                                          m_pContext->pAtqClientContext, ServerEventCompletion,
 | ||
|                                                          INFINITE,
 | ||
|                                                          &m_pContext->pAtqContext,
 | ||
|                                                          AtqAddAsyncHandle,
 | ||
|                                                          AtqFreeContext);
 | ||
| #endif
 | ||
|                      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;
 | ||
|              IMailMsgNotify *pNotify;
 | ||
| 
 | ||
|              hrRes = punkObject->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
 | ||
|              if (FAILED(hrRes))
 | ||
|                  return(hrRes);
 | ||
| 
 | ||
|              // if the caller has async notify support then pass in our
 | ||
|              // notification class.  
 | ||
|              if (m_pContext->m_pNotify) {
 | ||
|                 // the sink might return async, so we need to keep local
 | ||
|                 // copies of our context data
 | ||
|                 hrRes = this->CopyContext();
 | ||
|                 if (FAILED(hrRes))
 | ||
|                     return hrRes;
 | ||
| 
 | ||
|                 hrRes = this->QueryInterface(IID_IMailMsgNotify, 
 | ||
|                                              (LPVOID *) &pNotify);
 | ||
|                 if (FAILED(hrRes))
 | ||
|                     return hrRes;
 | ||
|              } else {
 | ||
|                 pNotify = NULL;
 | ||
|              }
 | ||
| 
 | ||
|              //
 | ||
|              // 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 local delivery sink sink ...");
 | ||
|              hrRes = pSink->LocalDelivery(
 | ||
|                 (IMailMsgProperties *) m_pContext->IMsgPtr, 
 | ||
|                 m_pContext->m_RecipientCount, 
 | ||
|                 m_pContext->pdwRecipIndexes, 
 | ||
|                 (IMailMsgNotify *) pNotify);
 | ||
|              pSink->Release();
 | ||
|              if(hrRes != MAILTRANSPORT_S_PENDING) {
 | ||
|                  //
 | ||
|                  // We completed synchronously, so release the sink
 | ||
|                  //
 | ||
|                  m_pIUnknownSink->Release();
 | ||
|                  m_pIUnknownSink = NULL;
 | ||
|              }
 | ||
|              // if LocalDelivery was going to do an async return then it
 | ||
|              // should have AddRef'd pNotify
 | ||
|              if (pNotify) pNotify->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;
 | ||
| }
 | ||
| 
 | ||
| //+------------------------------------------------------------
 | ||
| //
 | ||
| // Function: CStoreDriver::CStoreParams::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::CStoreParams::CallCompletion(HRESULT hrStatus) {
 | ||
|     // call the caller's completion method if there is one
 | ||
|     IMailMsgNotify *pNotify = (IMailMsgNotify *) (m_pContext->m_pNotify);
 | ||
|     if (pNotify) {
 | ||
|         pNotify->Notify(hrStatus);
 | ||
|         pNotify->Release();
 | ||
|     }
 | ||
| 
 | ||
|     // do the normal call completion work
 | ||
|     CStoreBaseParams::CallCompletion(hrStatus);
 | ||
| 
 | ||
|     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_LOG_EVENT:
 | ||
|          return CATID_SMTP_LOG;
 | ||
|      case SMTP_GET_AUX_DOMAIN_INFO_FLAGS_EVENT:
 | ||
|         return CATID_SMTP_GET_AUX_DOMAIN_INFO_FLAGS;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| //
 | ||
| // 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(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();
 | ||
|     }
 | ||
| 
 | ||
|     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;
 | ||
|     }
 | ||
| 
 | ||
|     Dispatcher(pParams->m_rguidEventType, pParams);
 | ||
| 
 | ||
|     TraceFunctLeaveEx((LPARAM)this);
 | ||
|     return S_OK;
 | ||
| }
 | ||
| 
 | ||
| //+------------------------------------------------------------
 | ||
| //
 | ||
| // Function: CStoreDispatcher::CStoreBaseParams::Notify
 | ||
| //
 | ||
| // Synopsis: Handles async completions of sinks using mailmsg notify
 | ||
| //
 | ||
| // Arguments: hrStatus - hresult from async operation
 | ||
| //
 | ||
| // Returns:
 | ||
| //  S_OK: Success
 | ||
| //  E_INVALIDARG:
 | ||
| //
 | ||
| // History:
 | ||
| // jstamerj 980608 15:50:57: Created.
 | ||
| //
 | ||
| //-------------------------------------------------------------
 | ||
| HRESULT STDMETHODCALLTYPE CStoreDispatcher::CStoreParams::Notify(
 | ||
|     HRESULT hrStatus)
 | ||
| {
 | ||
|     TraceFunctEnter("CStoreDispatcher::CStoreBaseParams::Notify");
 | ||
| 
 | ||
|     //
 | ||
|     // Release the sink that called us
 | ||
|     // m_pIUnknownSink could be NULL if default processing returned pending
 | ||
|     //
 | ||
|     if(m_pIUnknownSink) {
 | ||
|         m_pIUnknownSink->Release();
 | ||
|         m_pIUnknownSink = NULL;
 | ||
|     }
 | ||
| 
 | ||
|     m_pDispatcher->Dispatcher(m_rguidEventType, this);
 | ||
| 
 | ||
|     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;
 | ||
| }
 | ||
| 
 | ||
| //////////////////////////////////////////////////////////////////////////////
 | ||
| HRESULT CStoreDispatcher::CSmtpLogParams::CallObject(
 | ||
|     CBinding& bBinding,
 | ||
|     IUnknown *punkObject )
 | ||
| {
 | ||
|     ISmtpLog *pSink = NULL;
 | ||
| 
 | ||
|     HRESULT hr = punkObject->QueryInterface(IID_ISmtpLog, (void **)&pSink);
 | ||
| 
 | ||
|     if( FAILED( hr ) )
 | ||
|     {
 | ||
|         return( hr );
 | ||
|     }
 | ||
| 
 | ||
|     hr = pSink->OnSyncLog(m_pContext->pSmtpEventLogInfo );
 | ||
| 
 | ||
|     pSink->Release();
 | ||
| 
 | ||
|     return( hr );
 | ||
| }
 | ||
| 
 | ||
| //////////////////////////////////////////////////////////////////////////////
 | ||
| HRESULT CStoreDispatcher::CSmtpLogParams::CallDefault()
 | ||
| {
 | ||
|     HRESULT hrRes = S_OK;
 | ||
|     SMTP_LOG_EVENT_INFO     *pLogEventInfo;
 | ||
|     CEventLogWrapper        *pEventLog;
 | ||
| 
 | ||
|     TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CSmtpLogParams::CallDefault");
 | ||
| 
 | ||
|     _ASSERT(m_dwEventType == SMTP_LOG_EVENT);
 | ||
| 
 | ||
|     if ((m_pContext->pSmtpEventLogInfo == NULL) ||
 | ||
|         (m_pContext->pDefaultEventLogHandler == NULL))
 | ||
|     {
 | ||
|         DebugTrace((LPARAM) this, "Skipping LogEvent call");
 | ||
|         TraceFunctLeaveEx((LPARAM)this);
 | ||
|         return S_OK;
 | ||
|     }
 | ||
| 
 | ||
|     // Params are m_pContext->pSmtpEventLogInfo
 | ||
|     pLogEventInfo = m_pContext->pSmtpEventLogInfo;
 | ||
| 
 | ||
|     // filter out events that the user isn't interested in
 | ||
|     if (m_pContext->iSelectedDebugLevel < pLogEventInfo->iDebugLevel) {
 | ||
|         return S_OK;
 | ||
|     }
 | ||
| 
 | ||
|     // Handler is m_pContext->pDefaultEventLogHandler
 | ||
|     pEventLog = (CEventLogWrapper*)m_pContext->pDefaultEventLogHandler;
 | ||
| 
 | ||
|     // Call into default logging handler
 | ||
|     pEventLog->LogEvent(
 | ||
|                     pLogEventInfo->idMessage,
 | ||
| //                    pLogEventInfo->idCategory,	// Not used by default handler
 | ||
|                     pLogEventInfo->cSubstrings,
 | ||
|                     pLogEventInfo->rgszSubstrings,
 | ||
|                     pLogEventInfo->wType,
 | ||
|                     pLogEventInfo->errCode,
 | ||
|                     pLogEventInfo->iDebugLevel,
 | ||
|                     pLogEventInfo->szKey,
 | ||
|                     pLogEventInfo->dwOptions,
 | ||
|                     pLogEventInfo->iMessageString,
 | ||
|                     pLogEventInfo->hModule);
 | ||
| 
 | ||
|     TraceFunctLeaveEx((LPARAM)this);
 | ||
|     return hrRes;
 | ||
| }
 | ||
| 
 | ||
| //////////////////////////////////////////////////////////////////////////////
 | ||
| HRESULT CStoreDispatcher::CSmtpGetAuxDomainInfoFlagsParams::CallObject(
 | ||
|     CBinding& bBinding,
 | ||
|     IUnknown *punkObject )
 | ||
| {
 | ||
|     ISmtpGetAuxDomainInfoFlags *pSink = NULL;
 | ||
| 
 | ||
|     HRESULT hr = punkObject->QueryInterface(IID_ISmtpGetAuxDomainInfoFlags, (void **)&pSink);
 | ||
| 
 | ||
|     if( FAILED( hr ) )
 | ||
|     {
 | ||
|         return( hr );
 | ||
|     }
 | ||
| 
 | ||
|     hr = pSink->OnGetAuxDomainInfoFlags(m_pContext->pIServer,
 | ||
|                                         m_pContext->pszDomainName,
 | ||
|                                         m_pContext->pdwDomainInfoFlags );
 | ||
| 
 | ||
|     pSink->Release();
 | ||
| 
 | ||
|     return( hr );
 | ||
| }
 | ||
| 
 | ||
| //////////////////////////////////////////////////////////////////////////////
 | ||
| HRESULT CStoreDispatcher::CSmtpGetAuxDomainInfoFlagsParams::CallDefault()
 | ||
| {
 | ||
|     return S_OK;
 | ||
| }
 | ||
| 
 | ||
| //////////////////////////////////////////////////////////////////////////////
 | ||
| 
 | ||
| //+------------------------------------------------------------
 | ||
| //
 | ||
| // 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);
 | ||
| 
 | ||
|             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;
 | ||
|         SMTP_ALLOC_PARAMS AllocParams;
 | ||
| 
 | ||
|         hrResTmp = GetData(&pvServer,&dwServerInstance);
 | ||
|         if (SUCCEEDED(hrResTmp)) {
 | ||
|             ZeroMemory(&AllocParams, sizeof(AllocParams));
 | ||
|             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
 |