596 lines
15 KiB
C++
596 lines
15 KiB
C++
// SMTPServer.cpp : Implementation of CSMTPServer
|
|
|
|
#define INCL_INETSRV_INCS
|
|
#include "smtpinc.h"
|
|
#include "stdafx.h"
|
|
#include "dbgtrace.h"
|
|
|
|
#include "filehc.h"
|
|
#include "mailmsg.h"
|
|
#include "mailmsgi.h"
|
|
|
|
#include "smtpsvr.h"
|
|
|
|
//DECLARE_DEBUG_PRINTS_OBJECT();
|
|
|
|
#define MAILMSG_PROGID L"Exchange.MailMsg"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSMTPServer
|
|
|
|
STDMETHODIMP CSMTPServer::InterfaceSupportsErrorInfo(REFIID riid)
|
|
{
|
|
static const IID* arr[] =
|
|
{
|
|
&IID_ISMTPServer,
|
|
};
|
|
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
|
|
{
|
|
if (InlineIsEqualGUID(*arr[i],riid))
|
|
return S_OK;
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
BOOL InitExchangeSmtpServer(PVOID Ptr, PVOID Ptr2)
|
|
{
|
|
|
|
CSMTPServer * ThisPtr = (CSMTPServer *) Ptr;
|
|
ThisPtr->Init((SMTP_SERVER_INSTANCE *) Ptr2);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// Add all your initialization needs here ...
|
|
//
|
|
HRESULT CSMTPServer::Init(SMTP_SERVER_INSTANCE * pInstance)
|
|
{
|
|
_ASSERT (pInstance != NULL);
|
|
|
|
m_pInstance = pInstance;
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::QueryInterface(
|
|
REFIID iid,
|
|
void **ppvObject
|
|
)
|
|
{
|
|
|
|
if (iid == IID_IUnknown)
|
|
{
|
|
// Return our identity
|
|
*ppvObject = (IUnknown *)(ISMTPServerInternal *)this;
|
|
AddRef();
|
|
}
|
|
else if(iid == IID_ISMTPServer)
|
|
{
|
|
// Return our identity
|
|
*ppvObject = (ISMTPServerInternal *)this;
|
|
AddRef();
|
|
}
|
|
else if(iid == IID_ISMTPServerInternal)
|
|
{
|
|
// Return our identity
|
|
*ppvObject = (ISMTPServerInternal *)this;
|
|
AddRef();
|
|
}
|
|
else if(iid == IID_IMailTransportRouterReset)
|
|
{
|
|
// Return our identity
|
|
*ppvObject = (IMailTransportRouterReset *)this;
|
|
AddRef();
|
|
}
|
|
else if(iid == IID_IMailTransportSetRouterReset)
|
|
{
|
|
// Return our identity
|
|
*ppvObject = (IMailTransportSetRouterReset *)this;
|
|
AddRef();
|
|
}
|
|
else if(iid == IID_IMailTransportRouterSetLinkState)
|
|
{
|
|
// Return our identity
|
|
*ppvObject = (IMailTransportRouterSetLinkState *)this;
|
|
AddRef();
|
|
}
|
|
else if(iid == IID_ISMTPServerEx)
|
|
{
|
|
// Return our identity
|
|
*ppvObject = (ISMTPServerEx *)this;
|
|
AddRef();
|
|
}
|
|
else if(iid == IID_ISMTPServerGetAuxDomainInfoFlags)
|
|
{
|
|
// Return our identity
|
|
*ppvObject = (ISMTPServerGetAuxDomainInfoFlags *)this;
|
|
AddRef();
|
|
}
|
|
else if(iid == IID_ISMTPServerAsync)
|
|
{
|
|
// Return our identity
|
|
*ppvObject = (ISMTPServerAsync *)this;
|
|
AddRef();
|
|
}
|
|
else
|
|
{
|
|
return(E_NOINTERFACE);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::AllocMessage(
|
|
IMailMsgProperties **ppMsg
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
// Create a new MailMsg
|
|
hr = CoCreateInstance(
|
|
CLSID_MsgImp,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IMailMsgProperties,
|
|
(LPVOID *)ppMsg);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::SubmitMessage(
|
|
IMailMsgProperties *pMsg
|
|
)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
hr = m_pInstance->InsertIntoAdvQueue(pMsg);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CSMTPServer::TriggerLocalDelivery(
|
|
IMailMsgProperties *pMsg, DWORD dwRecipientCount, DWORD * pdwRecipIndexes
|
|
)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
hr = m_pInstance->TriggerLocalDelivery(pMsg, dwRecipientCount, pdwRecipIndexes, NULL);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::TriggerLocalDeliveryAsync(
|
|
IMailMsgProperties *pMsg, DWORD dwRecipientCount, DWORD * pdwRecipIndexes, IMailMsgNotify *pNotify
|
|
)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
hr = m_pInstance->TriggerLocalDelivery(pMsg, dwRecipientCount, pdwRecipIndexes, pNotify);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::TriggerServerEvent(
|
|
DWORD dwEventID,
|
|
PVOID pvContext)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
hr = m_pInstance->TriggerServerEvent(dwEventID, pvContext);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::ReadMetabaseString(DWORD MetabaseId, LPBYTE Buffer, DWORD * BufferSize, BOOL fSecure)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
hr = m_pInstance->SinkReadMetabaseString(MetabaseId, (char *) Buffer, BufferSize, (BOOL) fSecure);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::ReadMetabaseDword(DWORD MetabaseId, DWORD * dwValue)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
hr = m_pInstance->SinkReadMetabaseDword(MetabaseId, dwValue);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::ServerStartHintFunction()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
m_pInstance->SinkSmtpServerStartHintFunc();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::ServerStopHintFunction()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
m_pInstance->SinkSmtpServerStopHintFunc();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::ReadMetabaseData(DWORD MetabaseId, BYTE *Buffer, DWORD *BufferSize)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
hr = m_pInstance->SinkReadMetabaseData(MetabaseId, Buffer, BufferSize);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//---[ CSMTPServer::AllocBoundMessage ]----------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Creates a message and binds it to an ATQ Context
|
|
// Parameters:
|
|
// ppMsg Message to allocate
|
|
// phContent Content handle for message
|
|
// Returns:
|
|
// HRESULT from alloc message event
|
|
// E_POINTER if ppMsg or phContent is NULL
|
|
// E_FAIL if m_pIstance is NULL
|
|
// History:
|
|
// 7/11/98 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CSMTPServer::AllocBoundMessage(
|
|
OUT IMailMsgProperties **ppMsg,
|
|
OUT PFIO_CONTEXT *phContent)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) this, "CSMTPServer::AllocBoundMessage");
|
|
HRESULT hr = S_OK;
|
|
SMTP_ALLOC_PARAMS AllocParams;
|
|
IMailMsgBind *pBindInterface = NULL;
|
|
|
|
if (!phContent || !ppMsg)
|
|
{
|
|
hr = E_POINTER;
|
|
goto Exit;
|
|
}
|
|
|
|
//we cannot bind the message without m_pInstance
|
|
if (!m_pInstance)
|
|
{
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
//CoCreate unbound message object
|
|
hr = CoCreateInstance(
|
|
CLSID_MsgImp,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IMailMsgProperties,
|
|
(LPVOID *)ppMsg);
|
|
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
hr = (*ppMsg)->QueryInterface(IID_IMailMsgBind, (void **) &pBindInterface);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
AllocParams.BindInterfacePtr = (PVOID) pBindInterface;
|
|
AllocParams.IMsgPtr = (PVOID) (*ppMsg);
|
|
AllocParams.hContent = NULL;
|
|
AllocParams.hr = S_OK;
|
|
AllocParams.m_pNotify = NULL;
|
|
|
|
//For client context pass in something that will stay around the lifetime of the
|
|
//atqcontext -
|
|
AllocParams.pAtqClientContext = m_pInstance;
|
|
|
|
if(m_pInstance->AllocNewMessage(&AllocParams))
|
|
{
|
|
hr = AllocParams.hr;
|
|
|
|
if (SUCCEEDED(hr) && (AllocParams.hContent != NULL))
|
|
*phContent = AllocParams.hContent;
|
|
else
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (FAILED(hr) && ppMsg && (*ppMsg))
|
|
{
|
|
(*ppMsg)->Release();
|
|
*ppMsg = NULL;
|
|
|
|
}
|
|
|
|
if (pBindInterface)
|
|
pBindInterface->Release();
|
|
|
|
TraceFunctLeave();
|
|
return hr;
|
|
}
|
|
|
|
//---[ CSMTPSvr::ResetRoutes ]-------------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Implements IMailTransportRouterReset::ResetRoutes. Acts as a buffer
|
|
// between AQ and the routers. On shutdown... AQ can safely destroy
|
|
// it's heap by telling ISMTPServer to release its pointer to AQ's
|
|
// IMailTransportRouterReset interface
|
|
// Parameters:
|
|
// dwResetType The type of route reset to perform.
|
|
// Returns:
|
|
// S_OK on success (or if no m_pIRouterReset)
|
|
// Error code from AQUEUE if error occurs.
|
|
// History:
|
|
// 11/8/98 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CSMTPServer::ResetRoutes(IN DWORD dwResetType)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
m_slRouterReset.ShareLock();
|
|
|
|
if (m_pIRouterReset)
|
|
hr = m_pIRouterReset->ResetRoutes(dwResetType);
|
|
|
|
m_slRouterReset.ShareUnlock();
|
|
return hr;
|
|
}
|
|
|
|
|
|
//---[ CSMTPSvr::RegisterResetInterface ]---------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Implements IMailTransportSetRouterReset::RegisterResetInterface. Used
|
|
// by AQ to set its IMailTransportRouterReset ptr. Also used at shutdown
|
|
// to set its pointer to NULL.
|
|
// Parameters:
|
|
// IN dwVirtualServerID Virtual server ID
|
|
// IN pIRouterReset AQ's IMailTransportRouterReset
|
|
// Returns:
|
|
// S_OK on success
|
|
// History:
|
|
// 11/8/98 - MikeSwa Created
|
|
// 1/9/99 - MikeSwa Modified to include IMailTransportRouterSetLinkState
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CSMTPServer::RegisterResetInterface(
|
|
IN DWORD dwVirtualServerID,
|
|
IN IMailTransportRouterReset *pIRouterReset)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERT(!m_pInstance || (m_pInstance->QueryInstanceId() == dwVirtualServerID));
|
|
|
|
if (m_pInstance && (m_pInstance->QueryInstanceId() != dwVirtualServerID))
|
|
return E_INVALIDARG;
|
|
|
|
//Grab exclsuive lock so we don't release out from under anyone
|
|
m_slRouterReset.ExclusiveLock();
|
|
|
|
if (m_pIRouterReset)
|
|
m_pIRouterReset->Release();
|
|
|
|
if (m_pIRouterSetLinkState)
|
|
{
|
|
m_pIRouterSetLinkState->Release();
|
|
m_pIRouterSetLinkState = NULL;
|
|
}
|
|
|
|
m_pIRouterReset = pIRouterReset;
|
|
if (m_pIRouterReset)
|
|
{
|
|
m_pIRouterReset->AddRef();
|
|
|
|
//Get new SetLinkState interface
|
|
m_pIRouterReset->QueryInterface(IID_IMailTransportRouterSetLinkState,
|
|
(VOID **) &m_pIRouterSetLinkState);
|
|
}
|
|
|
|
m_slRouterReset.ExclusiveUnlock();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::WriteLog( LPMSG_TRACK_INFO pMsgTrackInfo,
|
|
IMailMsgProperties *pMsgProps,
|
|
LPEVENT_LOG_INFO pEventLogInfo ,
|
|
LPSTR pszProtocolLog )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
m_pInstance->WriteLog( pMsgTrackInfo, pMsgProps, pEventLogInfo, pszProtocolLog );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//---[ CSMTPServer::SetLinkState ]----------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Acts as a buffer between AQ and the routers. On shutdown... AQ can
|
|
// safely destroy it's heap by telling ISMTPServer to release its pointer
|
|
// to AQ's IMailTransportRouterSetLinkState interface
|
|
// Parameters:
|
|
// IN szLinkDomainName The Domain Name of the link (next hop)
|
|
// IN guidRouterGUID The GUID ID of the router
|
|
// IN dwScheduleID The schedule ID link
|
|
// IN szConnectorName The connector name given by the router
|
|
// IN dwSetLinkState The link state to set
|
|
// IN dwUnsetLinkState The link state to unset
|
|
// Returns:
|
|
// S_OK always
|
|
// History:
|
|
// 1/9/99 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CSMTPServer::SetLinkState(
|
|
IN LPSTR szLinkDomainName,
|
|
IN GUID guidRouterGUID,
|
|
IN DWORD dwScheduleID,
|
|
IN LPSTR szConnectorName,
|
|
IN DWORD dwSetLinkState,
|
|
IN DWORD dwUnsetLinkState,
|
|
IN FILETIME *pftNextScheduled,
|
|
IN IMessageRouter *pMessageRouter)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
m_slRouterReset.ShareLock();
|
|
|
|
if (m_pIRouterSetLinkState)
|
|
hr = m_pIRouterSetLinkState->SetLinkState(szLinkDomainName,
|
|
guidRouterGUID,
|
|
dwScheduleID,
|
|
szConnectorName,
|
|
dwSetLinkState,
|
|
dwUnsetLinkState,
|
|
pftNextScheduled,
|
|
pMessageRouter);
|
|
|
|
m_slRouterReset.ShareUnlock();
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CSMTPServer::TriggerLogEvent(
|
|
IN DWORD idMessage,
|
|
IN WORD idCategory,
|
|
IN WORD cSubstrings,
|
|
IN LPCSTR *rgszSubstrings,
|
|
IN WORD wType,
|
|
IN DWORD errCode,
|
|
IN WORD iDebugLevel,
|
|
IN LPCSTR szKey,
|
|
IN DWORD dwOptions,
|
|
IN DWORD iMessageString,
|
|
IN HMODULE hModule)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
m_pInstance->TriggerLogEvent(
|
|
idMessage,
|
|
idCategory,
|
|
cSubstrings,
|
|
rgszSubstrings,
|
|
wType,
|
|
errCode,
|
|
iDebugLevel,
|
|
szKey,
|
|
dwOptions,
|
|
iMessageString,
|
|
hModule);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//---[ CSMTPServer::ResetLogEvent ]------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Reset any history about events using this message and key,
|
|
// so that the next TriggerLogEvent with one-time or periodic logging
|
|
// will cause the event to be logged.
|
|
// Parameters:
|
|
// idMessage :
|
|
// szKey :
|
|
// Returns:
|
|
// S_OK on success
|
|
// History:
|
|
// 7/20/2000 - created, dbraun
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CSMTPServer::ResetLogEvent(
|
|
IN DWORD idMessage,
|
|
IN LPCSTR szKey)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
m_pInstance->ResetLogEvent(
|
|
idMessage,
|
|
szKey);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//---[ CSMTPServer::HrTriggerGetAuxDomainInfoFlagsEvent ]----------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Triggers the Get Aux Domain Info Flags event - this is to be used by aqueue to
|
|
// query for additional domain info config stored outside the metabase
|
|
// Parameters:
|
|
// pszDomainName : Name of domain to query flags for
|
|
// pdwDomainInfoFlags : DWORD to return domain flags
|
|
// Returns:
|
|
// S_OK on success
|
|
// S_FALSE if no domain found
|
|
// History:
|
|
// 10/6/2000 - created, dbraun
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CSMTPServer::HrTriggerGetAuxDomainInfoFlagsEvent(
|
|
IN LPCSTR pszDomainName,
|
|
OUT DWORD *pdwDomainInfoFlags )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_pInstance)
|
|
{
|
|
hr = m_pInstance->HrTriggerGetAuxDomainInfoFlagsEvent(
|
|
pszDomainName,
|
|
pdwDomainInfoFlags);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|