You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1144 lines
44 KiB
1144 lines
44 KiB
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// File: aqinst.h
|
|
//
|
|
// Description:
|
|
// CAQSvrInst is a central dispatcher class for Advanced Queuing. It
|
|
// coordinates shutdown and exposes the following COM interfaces:
|
|
// - IAdvQueue
|
|
// - IAdvQueueConfig
|
|
//
|
|
// Owner: mikeswa
|
|
//
|
|
// History:
|
|
// 9/3/98 - MikeSwa - changed from legacy name catmsgq.h & CCatMsgQueue
|
|
//
|
|
// Copyright (C) 1997, 1998 Microsoft Corporation
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef __AQINST_H__
|
|
#define __AQINST_H__
|
|
|
|
#include "cmt.h"
|
|
#include <rwnew.h>
|
|
#include "baseobj.h"
|
|
#include "aqueue.h"
|
|
#include "domcfg.h"
|
|
#include "domain.h"
|
|
#include "smtpseo.h"
|
|
#include "smproute.h"
|
|
#include "qwiktime.h"
|
|
#include "dsnsink.h"
|
|
#include "asyncq.h"
|
|
#include "msgrefadm.h"
|
|
#include "mailadmq.h"
|
|
#include "shutdown.h"
|
|
#include "refstr.h"
|
|
#include "msgguid.h"
|
|
#include "aqdbgcnt.h"
|
|
#include "aqnotify.h"
|
|
#include "defdlvrq.h"
|
|
#include "failmsgq.h"
|
|
#include "asncwrkq.h"
|
|
#include "tran_evntlog.h"
|
|
#include "aqreg.h"
|
|
#include "..\aqdisp\seomgr.h"
|
|
|
|
//-- *** LOCKS IN AQUEUE *** --------------------------------------------------
|
|
//
|
|
// NOTE: General comment on locks in aqueue.
|
|
//
|
|
// In general, we use CShareLockNH as our locking mechanism. These locks are
|
|
// Reader/Writer locks with TryEnter semantics and the performance feature
|
|
// that they use less than 1 handle per lock (~1 handle per thread).
|
|
//
|
|
// Shutdown is handled by using these locks. Each class that serves as an
|
|
// entrypoint for external threads (CAsyncQueue & CConnMgr) inherits from
|
|
// CSyncShutdown. At shutdown, this classes lock is aquired EXCLUSIVE, and
|
|
// to protect operations from shutdown, a this classes lock is aquired SHARED
|
|
// for the duration of the opertaion. Getting the shutdown sharelock either
|
|
// success or fails without blocking (aquiring the EXCLUSIVE shutdown lock is
|
|
// the only blocking call).
|
|
//
|
|
// The only other global lock is the virtual server instance routing lock.
|
|
// This is acquired shared for all operations at the same level the exclusive
|
|
// lock is aquired. This is acquired exlusively *only* for router changes
|
|
// caused by IRouterReset::ResetRoutes.
|
|
//
|
|
// If other classes have data which needs to be protected, they will have a
|
|
// m_slPrivateData sharelock. Any operation that needs to read data in a
|
|
// thread-safe manner, should aquire the m_slPrivateData SHARED. Any
|
|
// operation that needs to write data that is accessable by multiple threads
|
|
// should aquire that object's m_slPrivateData lock EXCLUSIVE.
|
|
//
|
|
// Some objects (CFifoQueue for example) require more than one lock to avoid
|
|
// contention. These objects will have locks that are descriptive of that
|
|
// particular locks functions. CFifoQueue, for example, uses m_slHead and
|
|
// m_slTail to respectively protect the head and tail of the queue.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// forward declarations to avoid #include nightmares
|
|
class CLinkMsgQueue;
|
|
class CConnMgr;
|
|
class CAQStats;
|
|
class CDSNParams;
|
|
class CMsgRef;
|
|
|
|
#define MEMBER_OK(pStruct, Member) \
|
|
(((LONG) (pStruct)->cbVersion) >= ( ((BYTE *) &((pStruct)->Member)) - ((BYTE *) pStruct)))
|
|
|
|
//For Service callback function
|
|
typedef void (*PSRVFN)(PVOID);
|
|
|
|
//CatMsgQueue Signature
|
|
#define CATMSGQ_SIG ' QMC'
|
|
|
|
//Total number of IMsgs in the system (all virtual servers)
|
|
_declspec(selectany) DWORD g_cIMsgInSystem = 0;
|
|
|
|
//List of virtual servers used by debugger extensions
|
|
_declspec(selectany) LIST_ENTRY g_liVirtualServers = {&g_liVirtualServers, &g_liVirtualServers};
|
|
|
|
//Sharelock used to access global virtual servers
|
|
_declspec(selectany) CShareLockNH *g_pslGlobals = NULL;
|
|
|
|
//Setup defaults
|
|
const DWORD g_cMaxConnections = 10000; //Maximum # of total connections allocated
|
|
const DWORD g_cMaxLinkConnections = 10; //Maximum # of connections per link
|
|
const DWORD g_cMinMessagesPerConnection = 20; //There must be this many messages
|
|
//per addional connection that is
|
|
//allocated for a link
|
|
const DWORD g_cMaxMessagesPerConnection = 20; //We server atmost these many messages per connection
|
|
const DWORD g_dwConnectionWaitMilliseconds = 3600000;
|
|
|
|
const DWORD g_dwRetryThreshold = 3; // Till 3 consecutive failures we treat it as glitch;
|
|
|
|
const DWORD g_dwFirstTierRetrySeconds = (15 * 60); // retry a failure in 15 minutes
|
|
const DWORD g_dwSecondTierRetrySeconds = (60 * 60); // retry a failure in 60 minutes
|
|
const DWORD g_dwThirdTierRetrySeconds = (12 * 60 * 60); // retry a failure in 12 hrs
|
|
const DWORD g_dwFourthTierRetrySeconds = (24 * 60 * 60); // retry a failure in 24 hrs
|
|
|
|
const DWORD g_dwRetriesBeforeDelay = 5;
|
|
const DWORD g_dwDelayIntervalsBeforeNDR = 2;
|
|
const DWORD g_dwDelayExpireMinutes = g_dwRetriesBeforeDelay*g_dwFirstTierRetrySeconds/(60);
|
|
const DWORD g_dwNDRExpireMinutes = g_dwDelayIntervalsBeforeNDR*g_dwDelayExpireMinutes;
|
|
|
|
|
|
//
|
|
// Additional message failure codes that should move to aqueue.idl.
|
|
//
|
|
#define MESSAGE_FAILURE_CAT (MESSAGE_FAILURE_BAD_PICKUP_DIR_FILE+1)
|
|
|
|
//---[ eAQFailure ]-------------------------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Enum used to desribe failure scenarios that will require special handling
|
|
// Hungarian:
|
|
// eaqf
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
typedef enum eAQFailure_
|
|
{
|
|
AQ_FAILURE_CANNOT_NDR_UNRESOLVED_RECIPS = 0,
|
|
AQ_FAILURE_PREROUTING_FAILED,
|
|
AQ_FAILURE_PRECAT_RETRY,
|
|
AQ_FAILURE_POSTCAT_EVENT,
|
|
AQ_FAILURE_NO_RESOURCES,
|
|
AQ_FAILURE_NDR_OF_DSN,
|
|
AQ_FAILURE_NO_RECIPS,
|
|
AQ_FAILURE_PENDING_DEFERRED_DELIVERY,
|
|
AQ_FAILURE_PROCESSING_DEFERRED_DELIVERY,
|
|
AQ_FAILURE_MSGREF_RETRY,
|
|
AQ_FAILURE_FREE_TO_RESUSE,
|
|
AQ_FAILURE_INTERNAL_ASYNCQ,
|
|
AQ_FAILURE_NUM_SITUATIONS //always keep this as last
|
|
} eAQFailure;
|
|
|
|
_declspec(selectany) DWORD g_cTotalAQFailures = 0;
|
|
_declspec(selectany) DWORD g_cAQFailureSituations = AQ_FAILURE_NUM_SITUATIONS;
|
|
_declspec(selectany) DWORD g_rgcAQFailures[AQ_FAILURE_NUM_SITUATIONS] = {0};
|
|
|
|
//---[ CAQSvrInst ]------------------------------------------------------------
|
|
//
|
|
//
|
|
// Hungarian: aqinst, paqinst
|
|
//
|
|
// Legacy Hungarian: cmq, pcmq (from old CCatMsgQueue object)
|
|
//
|
|
// Provides an interface definition for the enqueuing/acking categorized
|
|
// messages Also provides an interface for creating link queues.
|
|
//
|
|
// Only one of these objects exist per virtual server... it is used a
|
|
// co-ordinating object used to handle an orderly shutdown.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
class CAQSvrInst :
|
|
public CBaseObject,
|
|
public CSyncShutdown,
|
|
public IAdvQueue,
|
|
public IAdvQueueConfig,
|
|
public IAdvQueueAdmin,
|
|
public IMailTransportRoutingEngine,
|
|
public IMailTransportRouterReset,
|
|
public IAdvQueueDomainType,
|
|
public IAQNotify,
|
|
public IMailTransportRouterSetLinkState,
|
|
public IAQServerEvent
|
|
{
|
|
protected:
|
|
DWORD m_dwSignature;
|
|
LIST_ENTRY m_liVirtualServers;
|
|
DWORD m_dwServerInstance; //Virtual server instance
|
|
|
|
//Useful signatures that include flavor and verision information
|
|
DWORD m_cbClasses;
|
|
DWORD m_dwFlavorSignature;
|
|
|
|
//Total counts used for counting totals of messages that have passed
|
|
//through the system. Very useful for determing which component has
|
|
//dropped a message after a stress run.
|
|
LONG m_cTotalMsgsQueued; //Total # of messages on dest queues (after fanout)
|
|
LONG m_cMsgsAcked; //Total # of messages that have been acknowledged
|
|
LONG m_cMsgsAckedRetry; //Total # of messages acked with retry all
|
|
LONG m_cMsgsDeliveredLocal; //Total # of messages delivered to local store
|
|
DWORD m_cMsgsAckedRetryLocal; //Total # of messages msgs that have been ack'd retry
|
|
|
|
//Current system state counters
|
|
DWORD m_cCurrentMsgsSubmitted; //# total msgs in system
|
|
DWORD m_cCurrentMsgsPendingCat; //# Msgs that have not be categorized
|
|
DWORD m_cCurrentMsgsPendingRouting; //# Msgs that have not been routed.
|
|
DWORD m_cCurrentMsgsPendingDelivery; //# Msgs pending remote delivery
|
|
DWORD m_cCurrentMsgsPendingLocal; //# Msgs pending local delivery
|
|
DWORD m_cCurrentMsgsPendingLocalRetry; //# Msgs pending local retries
|
|
DWORD m_cCurrentMsgsPendingRetry; //# Msgs with unsuccessful attempts
|
|
DWORD m_cCurrentQueueMsgInstances; //# of msgs instances pending
|
|
//remote deliver (>= #msgs)
|
|
DWORD m_cCurrentRemoteDestQueues; //# of DestMsgQueues created
|
|
DWORD m_cCurrentRemoteNextHops; //# of Next Hop links created
|
|
DWORD m_cCurrentRemoteNextHopsEnabled; //# of links that can have connections
|
|
DWORD m_cCurrentRemoteNextHopsPendingRetry; //# of links pending retry
|
|
DWORD m_cCurrentRemoteNextHopsPendingSchedule; //# of links pending schedule
|
|
DWORD m_cCurrentRemoteNextHopsFrozenByAdmin; //# of links frozen by admin
|
|
DWORD m_cTotalMsgsSubmitted; //# of messages submitted to AQ
|
|
DWORD m_cTotalExternalMsgsSubmitted; //# of messages submitted to AQ externally
|
|
DWORD m_cCurrentMsgsPendingSubmitEvent; //# of messages in submission event
|
|
DWORD m_cCurrentMsgsPendingPreCatEvent; //# of messages in PreCat event
|
|
DWORD m_cCurrentMsgsPendingPostCatEvent; //# of messages in PostCat event
|
|
DWORD m_cDelayedDSNs; //# of DSN's that contain action:delayed
|
|
DWORD m_cNDRs; //# of DSN's that contain action:failed
|
|
DWORD m_cDeliveredDSNs; //# of DSN's that contain action:delivered
|
|
DWORD m_cRelayedDSNs; //# of DSN's that contain action:relayed
|
|
DWORD m_cExpandedDSNs; //# of DSN's that contain action:expanded
|
|
DWORD m_cDMTRetries;
|
|
DWORD m_cSupersededMsgs;
|
|
DWORD m_cTotalMsgsTURNETRNDelivered;
|
|
DWORD m_cTotalMsgsBadmailed;
|
|
DWORD m_cCatMsgCalled;
|
|
DWORD m_cCatCompletionCalled;
|
|
DWORD m_cBadmailNoRecipients;
|
|
DWORD m_cBadmailHopCountExceeded;
|
|
DWORD m_cBadmailFailureGeneral;
|
|
DWORD m_cBadmailBadPickupFile;
|
|
DWORD m_cBadmailEvent;
|
|
DWORD m_cBadmailNdrOfDsn;
|
|
DWORD m_cTotalDSNFailures;
|
|
DWORD m_cCurrentMsgsInLocalDelivery;
|
|
DWORD m_cTotalResetRoutes;
|
|
DWORD m_cCurrentPendingResetRoutes;
|
|
DWORD m_cCurrentMsgsPendingSubmit;
|
|
CAQMsgGuidList m_mglSupersedeIDs;
|
|
|
|
CShareLockInst m_slPrivateData; //read/write lock for global config into
|
|
|
|
CDomainMappingTable m_dmt; //ptr to domain mapping table
|
|
CConnMgr *m_pConnMgr;
|
|
CDomainConfigTable m_dct;
|
|
ISMTPServer *m_pISMTPServer;
|
|
ISMTPServerEx *m_pISMTPServerEx;
|
|
ISMTPServerAsync *m_pISMTPServerAsync;
|
|
HANDLE m_hCat;
|
|
CAQQuickTime m_qtTime; //exposes interfaces for getting expire times
|
|
CDSNGenerator m_dsnsink;
|
|
|
|
//Global config data
|
|
DWORD m_cMinMessagesPerConnection;
|
|
DWORD m_cMaxMessagesPerConnection;
|
|
DWORD m_dwConnectionWaitMilliseconds;
|
|
//retry related
|
|
DWORD m_dwFirstTierRetrySeconds; //Threshold failure retry interval
|
|
DWORD m_dwDelayExpireMinutes;
|
|
DWORD m_dwNDRExpireMinutes;
|
|
DWORD m_dwLocalDelayExpireMinutes;
|
|
DWORD m_dwLocalNDRExpireMinutes;
|
|
|
|
//Counters used to for local and cat retry
|
|
DWORD m_cLocalRetriesPending;
|
|
DWORD m_cCatRetriesPending;
|
|
DWORD m_cRoutingRetriesPending;
|
|
DWORD m_cSubmitRetriesPending;
|
|
|
|
|
|
DWORD m_dwInitMask; //used to keep track of who has been init'd
|
|
IMessageRouter *m_pIMessageRouterDefault;
|
|
CRefCountedString *m_prstrDefaultDomain;
|
|
CRefCountedString *m_prstrBadMailDir;
|
|
CRefCountedString *m_prstrCopyNDRTo;
|
|
CRefCountedString *m_prstrServerFQDN;
|
|
|
|
//DSN Options
|
|
DWORD m_dwDSNOptions;
|
|
DWORD m_dwDSNLanguageID;
|
|
|
|
CAsyncAdminMailMsgQueue m_asyncqPreCatQueue;
|
|
|
|
CAsyncAdminMsgRefQueue m_asyncqPreLocalDeliveryQueue;
|
|
CAsyncAdminMailMsgQueue m_asyncqPostDSNQueue;
|
|
CAsyncAdminMailMsgQueue m_asyncqPreRoutingQueue;
|
|
CAsyncAdminMailMsgQueue m_asyncqPreSubmissionQueue;
|
|
CDebugCountdown m_dbgcnt;
|
|
//Flags used to describe what has been initialized
|
|
|
|
IMailTransportRouterReset *m_pIRouterReset; //pointer to router reset implementation
|
|
|
|
//Queue and counter for deferred delivery
|
|
CAQDeferredDeliveryQueue m_defq;
|
|
DWORD m_cCurrentMsgsPendingDeferredDelivery;
|
|
|
|
//Failed Msg Queue
|
|
CFailedMsgQueue m_fmq;
|
|
DWORD m_cCurrentResourceFailedMsgsPendingRetry;
|
|
|
|
//Work queue used to do async work items
|
|
CAsyncWorkQueue m_aqwWorkQueue;
|
|
|
|
BOOL m_fMailMsgReportsNumHandles;
|
|
|
|
typedef enum _eCMQInitFlags
|
|
{
|
|
CMQ_INIT_OK = 0x80000000,
|
|
CMQ_INIT_DMT = 0x00000001,
|
|
CMQ_INIT_DCT = 0x00000002,
|
|
CMQ_INIT_CONMGR = 0x00000004,
|
|
CMQ_INIT_LINKQ = 0x00000008,
|
|
CMQ_INIT_DSN = 0x00000010,
|
|
CMQ_INIT_PRECATQ = 0x00000020,
|
|
CMQ_INIT_PRELOCQ = 0x00000040,
|
|
CMQ_INIT_POSTDSNQ = 0x00000080,
|
|
CMQ_INIT_ROUTER_RESET = 0x00000100,
|
|
CMQ_INIT_ROUTINGQ = 0x00000200,
|
|
CMQ_INIT_WORKQ = 0x00000400,
|
|
CMQ_INIT_SUBMISSIONQ = 0x00000800,
|
|
CMQ_INIT_MSGQ = 0x80000000,
|
|
} eCMQInitFlags;
|
|
|
|
CSMTPSeoMgr m_CSMTPSeoMgr;
|
|
|
|
public:
|
|
|
|
CAQSvrInst(DWORD dwServerInstance,
|
|
ISMTPServer *pISMTPServer);
|
|
~CAQSvrInst();
|
|
|
|
HRESULT HrInitialize(
|
|
IN LPSTR szUserName = NULL,
|
|
IN LPSTR szDomainName = NULL,
|
|
IN LPSTR szPassword = NULL,
|
|
IN PSRVFN pServiceStatusFn = NULL,
|
|
IN PVOID pvServiceContext = NULL);
|
|
|
|
HRESULT HrDeinitialize();
|
|
|
|
//publicly accessable member values
|
|
//MUST wrap in fTryShutdownLock - ShutdownUnlock
|
|
CDomainMappingTable *pdmtGetDMT() {AssertShutdownLockAquired();return &m_dmt;};
|
|
CAQMsgGuidList *pmglGetMsgGuidList() {AssertShutdownLockAquired(); return &m_mglSupersedeIDs;};
|
|
|
|
HRESULT HrGetIConnectionManager(OUT IConnectionManager **ppIConnectionManager);
|
|
|
|
//Public Methods exposed through events (or some other mechanism)
|
|
// This function queues a categorized message for remote/local delivery
|
|
BOOL fRouteAndQueueMsg(IN IMailMsgProperties *pIMailMsg);
|
|
|
|
//Acknowledge the message ref.
|
|
//There should be one Ack for every dequeue from a link.
|
|
HRESULT HrAckMsg(MessageAck *pMsgAck, BOOL fLocal = FALSE);
|
|
|
|
//methods to (un)map domain names to ids.
|
|
HRESULT HrGetDomainMapping(
|
|
IN LPSTR szDomainName, //Domain name
|
|
OUT CDomainMapping *pdmap); //resulting domain mapping
|
|
HRESULT HrGetDomainName(
|
|
IN CDomainMapping *pdmap, //Domain mapping
|
|
OUT LPSTR *pszDomainName); //resolved domain name
|
|
|
|
//Pass notifications off to Connection Manager
|
|
HRESULT HrNotify(IN CAQStats *paqstats, BOOL fAdd);
|
|
|
|
//Expose ability to get internal Domain Info to internal components
|
|
HRESULT HrGetInternalDomainInfo(IN DWORD cbDomainNameLength,
|
|
IN LPSTR szDomainName,
|
|
OUT CInternalDomainInfo **ppDomainInfo);
|
|
|
|
HRESULT HrGetDefaultDomainInfo(OUT CInternalDomainInfo **ppDomainInfo);
|
|
|
|
//Get Domain Entry from DMT
|
|
HRESULT HrGetDomainEntry(IN DWORD cbDomainNameLength,
|
|
IN LPSTR szDomainName,
|
|
OUT CDomainEntry **ppdentry);
|
|
|
|
// jstamerj 980607 21:41:25: The completion routine of the
|
|
// submission event trigger
|
|
HRESULT SubmissionEventCompletion(
|
|
HRESULT hrStatus,
|
|
PEVENTPARAMS_SUBMISSION pParams);
|
|
|
|
// jstamerj 1998/11/24 19:53:24: Fire off the PreCat event
|
|
VOID TriggerPreCategorizeEvent(IN IMailMsgProperties *pIMailMsgProperties);
|
|
|
|
// jstamerj 1998/11/24 19:54:23: Completion routine of the pre-cat event
|
|
HRESULT PreCatEventCompletion(IN HRESULT hrStatus, IN PEVENTPARAMS_PRECATEGORIZE pParams);
|
|
|
|
// jstamerj 980610 12:24:29: Called from HrPreCatEventCompletion
|
|
HRESULT SubmitMessageToCategorizer(IN IMailMsgProperties *pIMailMsgProperties);
|
|
|
|
// jstamerj 980616 22:06:45: Called from CatCompletion
|
|
void TriggerPostCategorizeEvent(IUnknown *pIMsg, IUnknown **rgpIMsg);
|
|
|
|
// jstamerj 980616 22:07:18: triggers a post-cat event for one message
|
|
HRESULT TriggerPostCategorizeEventOneMsg(IUnknown *pIMsg);
|
|
|
|
// jstamerj 980616 22:07:54: Handles post-cat event completions
|
|
HRESULT PostCategorizationEventCompletion(HRESULT hrStatus, PEVENTPARAMS_POSTCATEGORIZE pParams);
|
|
|
|
// 11/17/98 - MikeSwa added for CDO badmail/abort delivery
|
|
// returns S_FALSE if message has been completely handled.
|
|
HRESULT SetNextMsgStatus(IN DWORD dwCurrentStatus,
|
|
IN IMailMsgProperties *pIMailMsgProperties);
|
|
|
|
//Called by async completion to PreCat Queue
|
|
BOOL fPreCatQueueCompletion(IMailMsgProperties *pIMailMsgProperties);
|
|
|
|
//Called by async completion to PreCat Queue
|
|
BOOL fPreLocalDeliveryQueueCompletion(CMsgRef *pmsgref);
|
|
|
|
//Used to restart async queues after failures
|
|
void AsyncQueueRetry(DWORD dwQueueID);
|
|
|
|
//Called to Set message submission time duing SubmitMessage and HrInternalSubmitMessage
|
|
HRESULT HrSetSubmissionTimeIfNecessary(IMailMsgProperties *pIMailMsgProperties);
|
|
|
|
//Called to calculate expire times for messages that are not stamped (most messages)
|
|
void CalcExpireTimeNDR(FILETIME ftSubmission, BOOL fLocal, FILETIME *pftExpire);
|
|
void CalcExpireTimeDelay(FILETIME ftSubmission, BOOL fLocal, FILETIME *pftExpire);
|
|
|
|
//API to keep counters in sync
|
|
inline DWORD cIncMsgsInSystem(); //returns total of all virtual servers
|
|
inline void DecMsgsInSystem(BOOL fWasRetriedRemote = FALSE, BOOL fWasRemote = FALSE,
|
|
BOOL fWasRetriedLocal = FALSE);
|
|
|
|
//Called by Msgref on first message retry
|
|
inline void IncRetryCount(BOOL fLocal);
|
|
|
|
//Called by DestMsgQueue to describe message fanout
|
|
inline void IncQueueMsgInstances();
|
|
inline void DecQueueMsgInstances();
|
|
|
|
//Used to keep track of the number of queues/next hops
|
|
inline void IncDestQueueCount();
|
|
inline void DecDestQueueCount();
|
|
inline DWORD cGetDestQueueCount();
|
|
inline void IncNextHopCount();
|
|
inline void DecNextHopCount();
|
|
|
|
//Called by functions walk pre-local queue for NDRs
|
|
inline void DecPendingLocal();
|
|
inline void DecPendingSubmit()
|
|
{InterlockedDecrement((PLONG)&m_cCurrentMsgsPendingSubmit);};
|
|
inline void DecPendingCat()
|
|
{InterlockedDecrement((PLONG)&m_cCurrentMsgsPendingCat);};
|
|
inline void DecPendingRouting()
|
|
{InterlockedDecrement((PLONG)&m_cCurrentMsgsPendingRouting);};
|
|
|
|
inline void IncTURNETRNDelivered();
|
|
|
|
//aszafer 1/28/00
|
|
//used to decide start/stop throttling handles
|
|
DWORD cCountMsgsForHandleThrottling(IN IMailMsgProperties *pIMailMsgProperties);
|
|
|
|
//Functions to call into the specifc hash tables to iterate over subdomains
|
|
//
|
|
HRESULT HrIterateDMTSubDomains(IN LPSTR szDomainName,
|
|
IN DWORD cbDomainNameLength,
|
|
IN DOMAIN_ITR_FN pfn,
|
|
IN PVOID pvContext) ;
|
|
HRESULT HrIterateDCTSubDomains(IN LPSTR szDomainName,
|
|
IN DWORD cbDomainNameLength,
|
|
IN DOMAIN_ITR_FN pfn,
|
|
IN PVOID pvContext);
|
|
|
|
//Calls that allow access to time objects
|
|
inline void GetExpireTime(
|
|
IN DWORD cMinutesExpireTime,
|
|
IN OUT FILETIME *pftExpireTime,
|
|
IN OUT DWORD *pdwExpireContext); //if non-zero, will use last time
|
|
|
|
inline BOOL fInPast(IN FILETIME *pftExpireTime, IN OUT DWORD *pdwExpireContext);
|
|
|
|
HRESULT HrTriggerDSNGenerationEvent(CDSNParams *pdsnparams, BOOL fHasRoutingLock);
|
|
|
|
HRESULT HrNDRUnresolvedRecipients(IMailMsgProperties *pIMailMsgProperties,
|
|
IMailMsgRecipients *pIMailMsgRecipients);
|
|
|
|
//friend functions that can be used as completion functions
|
|
friend HRESULT CatCompletion(HRESULT hrCatResult, PVOID pContext, IUnknown *pIMsg,
|
|
IUnknown **rgpIMsg);
|
|
|
|
//Expose server start/stop hint functions
|
|
inline VOID ServerStartHintFunction();
|
|
inline VOID ServerStopHintFunction();
|
|
|
|
//function used to handle badmail
|
|
void HandleBadMail(IN IMailMsgProperties *pIMailMsgProperties,
|
|
IN BOOL fUseIMailMsgProperties,
|
|
IN LPSTR szFileName,
|
|
IN HRESULT hrReason,
|
|
BOOL fHasRoutingLock);
|
|
|
|
//Function to handle some sort of system failure that would cause
|
|
//messages/data to be lost if unhandled
|
|
void HandleAQFailure(eAQFailure eaqfFailureSituation,
|
|
HRESULT hr, IMailMsgProperties *pIMailMsgProperties);
|
|
|
|
|
|
//Stub call for logging an event
|
|
void LogAQEvent(HRESULT hrEventReason, CMsgRef *pmsgref,
|
|
IMailMsgProperties *pIMailMsgProperties,
|
|
LPSTR szFileName);
|
|
|
|
//Routing lock should be grabbed before accessing queues (after shutdown)
|
|
void RoutingShareLock() {m_slPrivateData.ShareLock();};
|
|
BOOL fTryRoutingShareLock() {return m_slPrivateData.TryShareLock();};
|
|
void RoutingShareUnlock() {m_slPrivateData.ShareUnlock();};
|
|
|
|
HRESULT SetCallbackTime(IN PSRVFN pCallbackFn,
|
|
IN PVOID pvContext,
|
|
IN DWORD dwCallbackMinutes);
|
|
|
|
HRESULT SetCallbackTime(IN PSRVFN pCallbackFn,
|
|
IN PVOID pvContext,
|
|
IN FILETIME *pft);
|
|
|
|
void DecPendingDeferred()
|
|
{InterlockedDecrement((PLONG) &m_cCurrentMsgsPendingDeferredDelivery);};
|
|
|
|
void DecPendingFailed()
|
|
{InterlockedDecrement((PLONG) &m_cCurrentResourceFailedMsgsPendingRetry);};
|
|
|
|
void QueueMsgForLocalDelivery(CMsgRef *pmsgref, BOOL fLocalLink);
|
|
|
|
HRESULT HrInternalSubmitMessage(IMailMsgProperties *pIMailMsgProperties);
|
|
|
|
|
|
//Get string for default domain
|
|
CRefCountedString *prstrGetDefaultDomain();
|
|
|
|
//Completion Function called by MsgCat
|
|
static HRESULT CatCompletion(HRESULT hrCatResult, PVOID pContext,
|
|
IUnknown *pImsg, IUnknown **rgpImsg);
|
|
|
|
#define AQLD_SIG 'LDAQ'
|
|
|
|
// completion object called by local delivery
|
|
class CAQLocalDeliveryNotify :
|
|
public IMailMsgNotify,
|
|
public CBaseObject
|
|
{
|
|
public:
|
|
CAQLocalDeliveryNotify(PVOID pContext, CMsgRef *pmsgref) {
|
|
TraceFunctEnter("CAQLocalDeliveryNotify::CAQLocalDeliveryNotify");
|
|
m_hr = E_FAIL;
|
|
m_fCalledCompletion = FALSE;
|
|
m_pContext = pContext;
|
|
_ASSERT(pmsgref);
|
|
m_pmsgref = pmsgref;
|
|
m_pmsgref->AddRef();
|
|
m_pIMsg = pmsgref ? pmsgref->pimsgGetIMsg() : NULL;
|
|
ZeroMemory(&m_msgack, sizeof(MessageAck));
|
|
m_msgack.dwMsgStatus = MESSAGE_STATUS_ALL_DELIVERED;
|
|
m_msgack.pvMsgContext = (DWORD *) &m_dcntxtLocal;
|
|
DebugTrace(0, "new(this=0x%x)\n", this);
|
|
}
|
|
~CAQLocalDeliveryNotify() {
|
|
TraceFunctEnter("CAQLocalDeliveryNotify::~CAQLocalDeliveryNotify");
|
|
|
|
DebugTrace(0, "delete(this=0x%x)\n", this);
|
|
if (m_pIMsg) {
|
|
m_pIMsg->Release();
|
|
m_pIMsg = NULL;
|
|
}
|
|
|
|
if (m_pmsgref) {
|
|
m_pmsgref->Release();
|
|
m_pmsgref = NULL;
|
|
}
|
|
}
|
|
|
|
// allocators
|
|
void *operator new(size_t stIgnored) {
|
|
return s_pool.Alloc();
|
|
}
|
|
void operator delete(void *p, size_t size) {
|
|
s_pool.Free(p);
|
|
}
|
|
|
|
// IMailMsgNotify
|
|
HRESULT __stdcall Notify(HRESULT hr) {
|
|
m_hr = hr;
|
|
CAQSvrInst::LDCompletion(m_hr, m_pContext, m_pmsgref, this);
|
|
m_fCalledCompletion = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
// IUnknown
|
|
HRESULT __stdcall QueryInterface( const IID& iid, VOID** ppv )
|
|
{
|
|
if ( iid == IID_IUnknown ) {
|
|
*ppv = static_cast<IMailMsgNotify*>(this);
|
|
} else if ( iid == IID_IMailMsgNotify ) {
|
|
*ppv = static_cast<IMailMsgNotify*>(this);
|
|
} else {
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
|
|
return S_OK;
|
|
}
|
|
STDMETHOD_(ULONG, AddRef)(void) {
|
|
TraceFunctEnter("CAQLocalDeliveryNotify::AddRef");
|
|
DebugTrace(0, "add(this=0x%x)\n", this);
|
|
TraceFunctLeave();
|
|
return CBaseObject::AddRef();
|
|
};
|
|
STDMETHOD_(ULONG, Release)(void) {
|
|
TraceFunctEnter("CAQLocalDeliveryNotify::Release");
|
|
DebugTrace(0, "rel(this=0x%x)\n", this);
|
|
TraceFunctLeave();
|
|
return CBaseObject::Release();
|
|
};
|
|
|
|
// accessors
|
|
CDeliveryContext *pdcntxtGetDeliveryContext() {
|
|
return &m_dcntxtLocal;
|
|
}
|
|
MessageAck *pmsgackGetMsgAck() {
|
|
return &m_msgack;
|
|
}
|
|
IMailMsgProperties *pimsgGetIMsg() {
|
|
return m_pIMsg;
|
|
}
|
|
CMsgRef *pmsgrefGetMsgRef() {
|
|
return m_pmsgref;
|
|
}
|
|
BOOL fNotCalledCompletion() {
|
|
return !m_fCalledCompletion;
|
|
}
|
|
private:
|
|
IMailMsgProperties *m_pIMsg;
|
|
HRESULT m_hr;
|
|
PVOID m_pContext;
|
|
CMsgRef *m_pmsgref;
|
|
CDeliveryContext m_dcntxtLocal;
|
|
MessageAck m_msgack;
|
|
BOOL m_fCalledCompletion;
|
|
public:
|
|
static CPool s_pool;
|
|
};
|
|
|
|
void UpdateLDCounters(CMsgRef *pmsgref);
|
|
|
|
// local delivery completion function
|
|
static void LDCompletion(HRESULT hrLDResult,
|
|
PVOID pContext,
|
|
CMsgRef *pmsgref,
|
|
CAQLocalDeliveryNotify *pLDNotify);
|
|
|
|
//Handle the details of retrying after local delivery failure
|
|
void HandleLocalRetry(CMsgRef *pmsgref);
|
|
|
|
//Handles details of post-cat DSN generation
|
|
void HandleCatFailure(IUnknown *pIUnknown, HRESULT hrCatResult);
|
|
|
|
//Handle the details of retrying after cat failure
|
|
void HandleCatRetryOneMessage(IUnknown *pIUnknown);
|
|
|
|
HRESULT HrGetLocalQueueAdminQueue(IQueueAdminQueue **ppIQueueAdminQueue);
|
|
|
|
HRESULT HrQueueFromQueueID(QUEUELINK_ID *pqlQueueId,
|
|
IQueueAdminQueue **ppIQueueAdminQueue);
|
|
|
|
HRESULT HrLinkFromLinkID(QUEUELINK_ID *pqlLinkID,
|
|
IQueueAdminLink **ppIQueueAdminLink);
|
|
|
|
BOOL fIsLocalQueueAdminAction(IQueueAdminAction *pIQueueAdminAction);
|
|
|
|
inline HRESULT HrQueueWorkItem(PVOID pvData,
|
|
PASYNC_WORK_QUEUE_FN pfnCompletion);
|
|
|
|
static BOOL fResetRoutesNextHopCompletion(PVOID pvThis, DWORD dwStatus);
|
|
|
|
static BOOL fPreSubmissionQueueCompletionWrapper(
|
|
IMailMsgProperties *pIMailMsgProperties,
|
|
PVOID pvContext);
|
|
|
|
BOOL fShouldRetryMessage(IMailMsgProperties *pIMailMsgProperties,
|
|
BOOL fShouldBounceUsageIfRetry = TRUE);
|
|
|
|
VOID ScheduleInternalRetry(DWORD dwLinkType);
|
|
|
|
STDMETHOD(TriggerServerEvent) (
|
|
DWORD dwEventID,
|
|
PVOID pvContext)
|
|
{
|
|
return m_CSMTPSeoMgr.HrTriggerServerEvent(dwEventID, pvContext);
|
|
}
|
|
|
|
void LogResetRouteEvent( DWORD dwObainLock,
|
|
DWORD dwWaitLock,
|
|
DWORD dwQueue);
|
|
|
|
HRESULT HrInternalQueueFromQueueID(QUEUELINK_ID *pqlQueueId,
|
|
IQueueAdminQueue **ppIQueueAdminQueue);
|
|
|
|
|
|
// DSN Submission methods
|
|
HRESULT HrAllocBoundMessage(
|
|
OUT IMailMsgProperties **ppMsg,
|
|
OUT PFIO_CONTEXT *phContext);
|
|
|
|
HRESULT HrSubmitDSN(
|
|
IN CDSNParams *pdsnparams,
|
|
IN DWORD dwDSNAction,
|
|
IN DWORD cRecipsDSNd,
|
|
IN IMailMsgProperties *pDSNMsg);
|
|
|
|
//Routing interface used internal to AQ components
|
|
public:
|
|
//Fires MAIL_TRANSPORT_ON_GET_ROUTER_FOR_MESSAGE_EVENT
|
|
HRESULT HrTriggerGetMessageRouter(
|
|
IN IMailMsgProperties *pIMailMsg,
|
|
OUT IMessageRouter **pIMessageRouter);
|
|
HRESULT HrTriggerLogEvent(
|
|
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 = 0xffffffff,
|
|
IN HMODULE hModule = NULL);
|
|
|
|
private:
|
|
HRESULT HrTriggerInitRouter();
|
|
|
|
//IUnknown
|
|
public:
|
|
STDMETHOD(QueryInterface)(REFIID riid, LPVOID * ppvObj);
|
|
STDMETHOD_(ULONG, AddRef)(void) {return CBaseObject::AddRef();};
|
|
STDMETHOD_(ULONG, Release)(void) {return CBaseObject::Release();};
|
|
|
|
//IAdvQueue
|
|
public:
|
|
STDMETHOD(SubmitMessage)(IN IMailMsgProperties *pIMailMsgProperties);
|
|
|
|
STDMETHOD(HandleFailedMessage)(IN IMailMsgProperties *pIMailMsgProperties,
|
|
IN BOOL fUseIMailMsgProperties,
|
|
IN LPSTR szFileName,
|
|
IN DWORD dwFailureReason,
|
|
IN HRESULT hrFailureCode);
|
|
|
|
//IAdvQueueConfig
|
|
public:
|
|
STDMETHOD(SetConfigInfo)(IN AQConfigInfo *pAQConfigInfo);
|
|
STDMETHOD(SetDomainInfo)(IN DomainInfo *pDomainInfo);
|
|
STDMETHOD(GetDomainInfo)(IN DWORD cbDomainNameLength,
|
|
IN CHAR szDomainName[],
|
|
IN OUT DomainInfo *pDomainInfo,
|
|
OUT DWORD **ppvDomainContext);
|
|
STDMETHOD(ReleaseDomainInfo)(IN DWORD *pvDomainContext);
|
|
STDMETHOD(GetPerfCounters)(OUT AQPerfCounters *pAQPerfCounters,
|
|
OUT CATPERFBLOCK *pCatPerfCounters);
|
|
STDMETHOD(ResetPerfCounters)();
|
|
STDMETHOD(StartConfigUpdate)();
|
|
STDMETHOD(FinishConfigUpdate)();
|
|
|
|
//IMailTransportRoutingEngine
|
|
public:
|
|
STDMETHOD(GetMessageRouter)(
|
|
IN IMailMsgProperties *pIMailMsg,
|
|
IN IMessageRouter *pICurrentMessageRouter,
|
|
OUT IMessageRouter **ppIMessageRouter);
|
|
|
|
//IMailTransportRouterReset
|
|
public:
|
|
STDMETHOD(ResetRoutes)(
|
|
IN DWORD dwResetType);
|
|
|
|
//IAdvQueueDomainType
|
|
public:
|
|
STDMETHOD(GetDomainInfoFlags)(
|
|
IN LPSTR szDomainName,
|
|
DWORD *pdwDomainInfoFlags);
|
|
|
|
// IAdvQueueAdmin
|
|
public:
|
|
STDMETHOD(ApplyActionToLinks)(
|
|
LINK_ACTION laAction);
|
|
|
|
STDMETHOD(ApplyActionToMessages)(
|
|
QUEUELINK_ID *pqlQueueLinkId,
|
|
MESSAGE_FILTER *pmfMessageFilter,
|
|
MESSAGE_ACTION maMessageAction,
|
|
DWORD *pcMsgs);
|
|
|
|
STDMETHOD(GetQueueInfo)(
|
|
QUEUELINK_ID *pqlQueueId,
|
|
QUEUE_INFO *pqiQueueInfo);
|
|
|
|
STDMETHOD(GetLinkInfo)(
|
|
QUEUELINK_ID *pqlLinkId,
|
|
LINK_INFO *pliLinkInfo,
|
|
HRESULT *phrLinkDiagnostic);
|
|
|
|
STDMETHOD(SetLinkState)(
|
|
QUEUELINK_ID *pqlLinkId,
|
|
LINK_ACTION la);
|
|
|
|
STDMETHOD(GetLinkIDs)(
|
|
DWORD *pcLinks,
|
|
QUEUELINK_ID *rgLinks);
|
|
|
|
STDMETHOD(GetQueueIDs)(
|
|
QUEUELINK_ID *pqlLinkId,
|
|
DWORD *pcQueues,
|
|
QUEUELINK_ID *rgQueues);
|
|
|
|
STDMETHOD(GetMessageProperties)(
|
|
QUEUELINK_ID *pqlQueueLinkId,
|
|
MESSAGE_ENUM_FILTER *pmfMessageEnumFilter,
|
|
DWORD *pcMsgs,
|
|
MESSAGE_INFO *rgMsgs);
|
|
|
|
STDMETHOD(QuerySupportedActions)(
|
|
QUEUELINK_ID *pqlQueueLinkId,
|
|
DWORD *pdwSupportedActions,
|
|
DWORD *pdwSupportedFilterFlags);
|
|
|
|
|
|
public: //IMailTransportRouterSetLinkState
|
|
STDMETHOD(SetLinkState)(
|
|
IN LPSTR szLinkDomainName,
|
|
IN GUID guidRouterGUID,
|
|
IN DWORD dwScheduleID,
|
|
IN LPSTR szConnectorName,
|
|
IN DWORD dwSetLinkState,
|
|
IN DWORD dwUnSetLinkState,
|
|
IN FILETIME *pftNextScheduledConnection,
|
|
IN IMessageRouter *pMessageRouter);
|
|
|
|
};
|
|
|
|
|
|
//*** inline counter functions
|
|
|
|
//---[ CAQSvrInst::cIncMsgsInSystem ]----------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Used to increment the global and virtual server msg counts. Returns
|
|
// the global count for resource management purposes.
|
|
// Parameters:
|
|
// -
|
|
// Returns:
|
|
// DWORD - Global # of Msgs in system
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
DWORD CAQSvrInst::cIncMsgsInSystem()
|
|
{
|
|
InterlockedIncrement((PLONG) &m_cCurrentMsgsSubmitted);
|
|
return (InterlockedIncrement((PLONG) &g_cIMsgInSystem));
|
|
};
|
|
|
|
//---[ CAQSvrInst::DecMsgsInSystem ]-----------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Decrements the global and virtual server message counts. Also
|
|
// decrements the pending retry count if needed.
|
|
// Parameters:
|
|
// fWasRetriedRemote - TRUE if msg was retried remotely and retry count needs
|
|
// to be decremented.
|
|
// fWasRemote - TRUE if message was being delivered remotely
|
|
// fWasRetriedLocal - TRUE if counted towards m_cCurrentMsgsPendingLocalRetry
|
|
// Returns:
|
|
// -
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CAQSvrInst::DecMsgsInSystem(BOOL fWasRetriedRemote, BOOL fWasRemote,
|
|
BOOL fWasRetriedLocal)
|
|
{
|
|
InterlockedDecrement((PLONG) &g_cIMsgInSystem);
|
|
InterlockedDecrement((PLONG) &m_cCurrentMsgsSubmitted);
|
|
|
|
if (fWasRetriedRemote)
|
|
InterlockedDecrement((PLONG) &m_cCurrentMsgsPendingRetry);
|
|
|
|
if (fWasRemote)
|
|
InterlockedDecrement((PLONG) &m_cCurrentMsgsPendingDelivery);
|
|
|
|
if (fWasRetriedLocal)
|
|
InterlockedDecrement((PLONG) &m_cCurrentMsgsPendingLocalRetry);
|
|
|
|
};
|
|
|
|
//---[ CAQSvrInst::IncRetryCount ]-------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Used by MsgRef the first time a Message is ack'd with a non-success
|
|
// code.
|
|
// Parameters:
|
|
// BOOL fLocal TRUE if message is local
|
|
// Returns:
|
|
// -
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CAQSvrInst::IncRetryCount(BOOL fLocal)
|
|
{
|
|
if (fLocal)
|
|
InterlockedIncrement((PLONG) &m_cCurrentMsgsPendingLocalRetry);
|
|
else
|
|
InterlockedIncrement((PLONG) &m_cCurrentMsgsPendingRetry);
|
|
};
|
|
|
|
//---[ CAQSvrInst::[Inc|Dec]QueueMsgInstances ]------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Increments/decrements a count of the total number of message instances
|
|
// queued for remote delivery. Because a message may be put in more than
|
|
// one queue, the steady state of this count will be at least as large as
|
|
// the number of messages. However, this count reflects messages that
|
|
// are currently on the queues and does *not* count messages that are
|
|
// currently being attempted by SMTP (which m_cCurrentMsgsPendingDelivery)
|
|
// *does* count.
|
|
//
|
|
// Used by DestMsgQueues.
|
|
// Parameters:
|
|
// -
|
|
// Returns:
|
|
// -
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CAQSvrInst::IncQueueMsgInstances()
|
|
{
|
|
InterlockedIncrement((PLONG) &m_cCurrentQueueMsgInstances);
|
|
};
|
|
|
|
void CAQSvrInst::DecQueueMsgInstances()
|
|
{
|
|
InterlockedDecrement((PLONG) &m_cCurrentQueueMsgInstances);
|
|
};
|
|
|
|
//---[ Queue/NextHop Counter API ]---------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Used to increment/decrement Queue and NextHop counters
|
|
// Parameters:
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CAQSvrInst::IncDestQueueCount()
|
|
{
|
|
InterlockedIncrement((PLONG) &m_cCurrentRemoteDestQueues);
|
|
};
|
|
|
|
void CAQSvrInst::DecDestQueueCount()
|
|
{
|
|
InterlockedDecrement((PLONG) &m_cCurrentRemoteDestQueues);
|
|
};
|
|
|
|
DWORD CAQSvrInst::cGetDestQueueCount()
|
|
{
|
|
return m_cCurrentRemoteDestQueues;
|
|
}
|
|
|
|
void CAQSvrInst::IncNextHopCount()
|
|
{
|
|
InterlockedIncrement((PLONG) &m_cCurrentRemoteNextHops);
|
|
};
|
|
|
|
void CAQSvrInst::DecNextHopCount()
|
|
{
|
|
InterlockedDecrement((PLONG) &m_cCurrentRemoteNextHops);
|
|
};
|
|
|
|
|
|
//---[ CAQSvrInst::DecPendingLocal ]-----------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Called by function walking pre-local delivery queue when a message
|
|
// is being expired.
|
|
// Parameters:
|
|
// -
|
|
// Returns:
|
|
// -
|
|
// History:
|
|
// 8/14/98 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CAQSvrInst::DecPendingLocal()
|
|
{
|
|
_ASSERT(CATMSGQ_SIG == m_dwSignature);
|
|
InterlockedDecrement((PLONG) &m_cCurrentMsgsPendingLocal);
|
|
};
|
|
|
|
|
|
//---[ CAQSvrInst::IncTURNETRNDelivered ]--------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Used to keep track of the # of TURN/ETRN messages delivered.
|
|
// Parameters:
|
|
// -
|
|
// Returns:
|
|
// -
|
|
// History:
|
|
// 10/27/98 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CAQSvrInst::IncTURNETRNDelivered()
|
|
{
|
|
InterlockedIncrement((PLONG) &m_cTotalMsgsTURNETRNDelivered);
|
|
}
|
|
|
|
//---[ CAQSvrInst::GetExpireTime ]-------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Get the expriation time for cMinutesExpireTime from now.
|
|
// Parameters:
|
|
// IN cMinutesExpireTime # of minutes in future to set time
|
|
// IN OUT pftExpireTime Filetime to store new expire time
|
|
// IN OUT pdwExpireContext If non-zero will use the same tick count
|
|
// as previous calls (saves call to GetTickCount)
|
|
// Returns:
|
|
// -
|
|
// History:
|
|
// 7/11/98 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CAQSvrInst::GetExpireTime(
|
|
IN DWORD cMinutesExpireTime,
|
|
IN OUT FILETIME *pftExpireTime,
|
|
IN OUT DWORD *pdwExpireContext)
|
|
{
|
|
m_qtTime.GetExpireTime(cMinutesExpireTime, pftExpireTime, pdwExpireContext);
|
|
}
|
|
|
|
//---[ CAQSvrInst::fInPast ]-------------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Determines if a given file time has already happened
|
|
// Parameters:
|
|
// IN pftExpireTime FILETIME with expiration
|
|
// IN OUT pdwExpireContext If non-zero will use the same tick count
|
|
// as previous calls (saves call to GetTickCount)
|
|
// Returns:
|
|
// TRUE if expire time is in the past
|
|
// FALSE if expire time is in the future
|
|
// History:
|
|
// 7/11/98 - MikeSwa Created
|
|
// Note:
|
|
// You should NOT use the same context used to get the FILETIME, because
|
|
// it will always return FALSE
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CAQSvrInst::fInPast(IN FILETIME *pftExpireTime,
|
|
IN OUT DWORD *pdwExpireContext)
|
|
{
|
|
return m_qtTime.fInPast(pftExpireTime, pdwExpireContext);
|
|
}
|
|
|
|
//---[ ServerStartHintFunction & ServerStartHintFunction ]---------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Functions for telling the Service control manager that we are
|
|
// starting/stopping the service.
|
|
//
|
|
// These functions are often called by functions that have been passed
|
|
// the CAQSvrInst ptr as a PVOID context, so it makes sense to check
|
|
// and assert on our signature here.
|
|
// Parameters:
|
|
// -
|
|
// Returns:
|
|
// -
|
|
// History:
|
|
// 7/22/98 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
VOID CAQSvrInst::ServerStartHintFunction()
|
|
{
|
|
_ASSERT(CATMSGQ_SIG == m_dwSignature);
|
|
if (m_pISMTPServer)
|
|
m_pISMTPServer->ServerStartHintFunction();
|
|
}
|
|
|
|
VOID CAQSvrInst::ServerStopHintFunction()
|
|
{
|
|
_ASSERT(CATMSGQ_SIG == m_dwSignature);
|
|
if (fShutdownSignaled())
|
|
{
|
|
m_dbgcnt.ResetCountdown();
|
|
//Only call stop hint if shutdown has been signalled
|
|
if (m_pISMTPServer)
|
|
m_pISMTPServer->ServerStopHintFunction();
|
|
}
|
|
}
|
|
|
|
//---[ CAQSvrInst::HrQueueWorkItem ]-------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Thin wrapper to queue item to async work queue
|
|
// Parameters:
|
|
// pvData Data to pass to completion function
|
|
// pfnCompletion Completion function
|
|
// Returns:
|
|
// S_OK on success
|
|
// failure code from CAsyncWorkQueue
|
|
// History:
|
|
// 3/9/99 - MikeSwa Created
|
|
// 7/7/99 - MikeSwa - will work during shutdown to allow multithreaded
|
|
// shutdown work.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CAQSvrInst::HrQueueWorkItem(PVOID pvData,
|
|
PASYNC_WORK_QUEUE_FN pfnCompletion)
|
|
{
|
|
return m_aqwWorkQueue.HrQueueWorkItem(pvData, pfnCompletion);
|
|
}
|
|
|
|
#endif // __AQINST_H__
|