//----------------------------------------------------------------------------- // // // File: aqadmsvr.h // // Description: Contains definitions for internal structures, classes and // enums that are needed by to handle the Queue Admin functionality // // Author: Mike Swafford (MikeSwa) // // History: // 12/3/98 - MikeSwa Created // 2/21/98 - MikeSwa added support for IQueueAdmin* interfaces // // Copyright (C) 1998 Microsoft Corporation // //----------------------------------------------------------------------------- #ifndef __AQADMSVR_H__ #define __AQADMSVR_H__ #include #include #include #define AQ_MSG_FILTER_SIG 'FMQA' //Assumed default msg size (if no hint is present) #define DEFAULT_MSG_HINT_SIZE 1000 //enum describing internal flags typedef enum tagAQ_MSG_FILTER { AQ_MSG_FILTER_MESSAGEID = 0x00000001, AQ_MSG_FILTER_SENDER = 0x00000002, AQ_MSG_FILTER_RECIPIENT = 0x00000004, AQ_MSG_FILTER_OLDER_THAN = 0x00000008, AQ_MSG_FILTER_LARGER_THAN = 0x00000010, AQ_MSG_FILTER_FROZEN = 0x00000020, AQ_MSG_FILTER_FIRST_N_MESSAGES = 0x00000040, AQ_MSG_FILTER_N_LARGEST_MESSAGES = 0x00000080, AQ_MSG_FILTER_N_OLDEST_MESSAGES = 0x00000100, AQ_MSG_FILTER_FAILED = 0x00000200, AQ_MSG_FILTER_ENUMERATION = 0x10000000, AQ_MSG_FILTER_ACTION = 0x20000000, AQ_MSG_FILTER_ALL = 0x40000000, AQ_MSG_FILTER_INVERTSENSE = 0x80000000, } AQ_MSG_FILTER; #define AQUEUE_DEFAULT_SUPPORTED_ENUM_FILTERS (\ MEF_FIRST_N_MESSAGES | \ MEF_SENDER | \ MEF_RECIPIENT | \ MEF_LARGER_THAN | \ MEF_OLDER_THAN | \ MEF_FROZEN | \ MEF_FAILED | \ MEF_ALL | \ MEF_INVERTSENSE) HRESULT QueryDefaultSupportedActions(DWORD *pdwSupportedActions, DWORD *pdwSupportedFilterFlags); //QueueAdmin Map function (can be used on CFifoQueue). typedef HRESULT (* QueueAdminMapFn)(CMsgRef *, PVOID, BOOL *, BOOL *); //---[ CAQAdminMessageFilter ]------------------------------------------------- // // // Description: // Internal representation for the MESSAGE_FILTER and MESSAGE_ENUM_FILETER // structures. Provides helper functions to help maintain search lists // and allow a CMsgRef to complare itself to the filter description in an // efficient manner. // // The idea is that a CMsgRef will query for the properties requested // in this filter by calling dwGetMsgFilterFlags() and calling the // specialize compare functions (which will handle the mechanics of // AQ_MSG_FILTER_INVERTSENSE). // Hungarian: // aqmf, paqmf // //----------------------------------------------------------------------------- class CAQAdminMessageFilter : public IQueueAdminMessageFilter, public CBaseObject { private: DWORD m_dwSignature; DWORD m_cMessagesToFind; //0 => find as many as possible DWORD m_cMessagesToSkip; DWORD m_cMessagesFound; DWORD m_dwFilterFlags; MESSAGE_ACTION m_dwMessageAction; LPSTR m_szMessageId; LPSTR m_szMessageSender; LPSTR m_szMessageRecipient; DWORD m_dwSenderAddressType; DWORD m_dwRecipientAddressType; DWORD m_dwThresholdSize; BOOL m_fSenderAddressTypeSpecified; BOOL m_fRecipientAddressTypeSpecified; FILETIME m_ftThresholdTime; MESSAGE_INFO *m_rgMsgInfo; MESSAGE_INFO *m_pCurrentMsgInfo; DWORD m_dwMsgIdHash; IQueueAdminAction *m_pIQueueAdminAction; PVOID m_pvUserContext; public: CAQAdminMessageFilter() { //Don't zero vtable :) ZeroMemory(((BYTE *)this)+ FIELD_OFFSET(CAQAdminMessageFilter, m_dwSignature), sizeof(CAQAdminMessageFilter) - FIELD_OFFSET(CAQAdminMessageFilter, m_dwSignature)); m_dwSignature = AQ_MSG_FILTER_SIG; }; ~CAQAdminMessageFilter(); void InitFromMsgFilter(PMESSAGE_FILTER pmf); void InitFromMsgEnumFilter(PMESSAGE_ENUM_FILTER pemf); void SetSearchContext(DWORD cMessagesToFind, MESSAGE_INFO *rgMsgInfo); void SetMessageAction(MESSAGE_ACTION MessageAction); DWORD dwGetMsgFilterFlags() {return m_dwFilterFlags;}; BOOL fFoundEnoughMsgs(); BOOL fFoundMsg(); BOOL fSkipMsg() { if (m_cMessagesToSkip) { m_cMessagesToSkip--; return TRUE; } else { return FALSE; } } //Returns true if hash matches or is value NULL string & fMatchesId //should be called BOOL fMatchesIdHash(DWORD dwMsgIdHash) {return dwMsgIdHash ? (dwMsgIdHash == m_dwMsgIdHash) : TRUE;}; DWORD cMessagesFound() {return m_cMessagesFound;}; MESSAGE_INFO *pmfGetMsgInfo() {return m_pCurrentMsgInfo;}; MESSAGE_INFO *pmfGetMsgInfoAtIndex(DWORD iMsgInfo) { _ASSERT(iMsgInfo < m_cMessagesFound); _ASSERT(iMsgInfo < m_cMessagesToFind); return &(m_rgMsgInfo[iMsgInfo]); }; BOOL fMatchesId(LPCSTR szMessageId); BOOL fMatchesSize(DWORD dwSize); BOOL fMatchesTime(FILETIME *pftTime); BOOL fMatchesMailMsgSender(IMailMsgProperties *pIMailMsgProperties); BOOL fMatchesMailMsgRecipient(IMailMsgProperties *pIMailMsgProperties); protected: //These functions are now worker functions BOOL fMatchesSender(LPCSTR szMessageSender); BOOL fMatchesRecipient(LPCSTR szMessageRecipient); BOOL fMatchesP1Recipient(IMailMsgProperties *pIMailMsgProperties); BOOL fQueueAdminIsP1Recip(IMailMsgProperties *pIMailMsgProperties); public: //IUnknown //CBaseObject handles addref and release STDMETHOD(QueryInterface)(REFIID riid, LPVOID * ppvObj); STDMETHOD_(ULONG, AddRef)(void) {return CBaseObject::AddRef();}; STDMETHOD_(ULONG, Release)(void) {return CBaseObject::Release();}; public: //IQueueAdminMessageFilter STDMETHOD(HrProcessMessage)( IUnknown *pIUnknownMsg, BOOL *pfContinue, BOOL *pfDelete); STDMETHOD(HrSetQueueAdminAction)( IQueueAdminAction *pIQueueAdminAction); STDMETHOD(HrSetCurrentUserContext)( PVOID pvContext); STDMETHOD(HrGetCurrentUserContext)( PVOID *ppvContext); }; #define ASYNCQ_ADMIN_CONTEXT_SIG 'CASQ' #define ASYNCQ_ADMIN_CONTEXT_SIG_FREE '!ASQ' //---[ CQueueAdminContext ]---------------------------------------------------- // // // Description: // Context set on filter object when enumeration/applying actions to // to messages. // Hungarian: // qapictx, pqapictx // //----------------------------------------------------------------------------- class CQueueAdminContext { protected: DWORD m_dwSignature; IAQNotify *m_pAQNotify; LINK_INFO_FLAGS m_lfQueueState; // Is currnetfrozen / retry ? DWORD m_cMsgsThawed; CAQSvrInst *m_paqinst; public: CQueueAdminContext(IAQNotify *pAQNotify, CAQSvrInst *paqinst) { m_dwSignature = ASYNCQ_ADMIN_CONTEXT_SIG; m_pAQNotify = pAQNotify; m_cMsgsThawed = 0; m_lfQueueState = LI_READY; m_paqinst = paqinst; }; ~CQueueAdminContext() { m_dwSignature = ASYNCQ_ADMIN_CONTEXT_SIG_FREE; m_pAQNotify = NULL; m_paqinst = NULL; }; // // This context is thrown around as a PVOID... make sure it is valid // inline BOOL fIsValid() {return(ASYNCQ_ADMIN_CONTEXT_SIG == m_dwSignature);}; // // In some cases... the state of the queue determines the state // of the message (messages on the retry queue are in retry). // the following can be used to get and set this state // inline void SetQueueState(LINK_INFO_FLAGS lfQueueType) { m_lfQueueState = lfQueueType;}; inline LINK_INFO_FLAGS lfGetQueueState() {return m_lfQueueState;}; // // Used to update stats when a message is removed from the queue // void NotifyMessageRemoved(CAQStats *paqstats) { _ASSERT(fIsValid()); if (m_pAQNotify) m_pAQNotify->HrNotify(paqstats, FALSE); }; // // Used to keep track of if we had to thaw messages // inline void IncThawedMsgs() {m_cMsgsThawed++;}; inline DWORD cGetNumThawedMsgs() {return m_cMsgsThawed;}; inline CAQSvrInst * paqinstGetAQ() {return m_paqinst;}; }; //---[ CQueueAdminRetryNotify ]--------------------------------------------------- // // // Description: // Pure virtual class that defines an "interface" to update the next // retry time // Hungarian: // qapiret, pqapiret // //----------------------------------------------------------------------------- class CQueueAdminRetryNotify : public IUnknown { public: virtual void SetNextRetry(FILETIME *pft) = 0; }; //Allocator funcations that are safe for the required RPC calls made by QueueAdmin inline PVOID pvQueueAdminAlloc(size_t cbSize) { return LocalAlloc(0, cbSize); } inline PVOID pvQueueAdminReAlloc(PVOID pvSrc, size_t cbSize) { return LocalReAlloc(pvSrc, cbSize, LMEM_MOVEABLE); } inline void QueueAdminFree(PVOID pvFree) { LocalFree(pvFree); } //Convert internal AQ config into to exportable UNICODE LPWSTR wszQueueAdminConvertToUnicode(LPSTR szSrc, DWORD cSrc, BOOL fUTF8 = FALSE); //Convert QueueAdmin parameter to UNICODE LPSTR szUnicodeToAscii(LPCWSTR szSrc); BOOL fBiStrcmpi(LPSTR sz, LPWSTR wsz); //compares UNICODE to ASCII string HRESULT HrQueueAdminGetStringProp(IMailMsgProperties *pIMailMsgProperties, DWORD dwPropID, LPSTR *pszProp, DWORD *pcbProp = NULL); HRESULT HrQueueAdminGetUnicodeStringProp( IMailMsgProperties *pIMailMsgProperties, DWORD dwPropID, LPWSTR *pwszProp, DWORD *pcbProp = NULL); DWORD cQueueAdminGetNumRecipsFromRFC822(LPSTR szHeader, DWORD cbHeader); void QueueAdminGetRecipListFromP1( IMailMsgProperties *pIMailMsgProperties, MESSAGE_INFO *pMsgInfo); HRESULT HrQueueAdminGetP1Sender(IMailMsgProperties *pIMailMsgProperties, LPSTR *pszSender, DWORD *pcbSender, DWORD *piAddressType, DWORD iStartAddressType = 0, BOOL fRequireAddressTypeMatch = FALSE); //---[ dwQueueAdminHash ]------------------------------------------------------ // // // Description: // Function To Hash Queue Admin Strings. Specifically designed for MSGIDs // so we do not have to open the property stream to check the MSGID during // QueueAdmin operations. // Parameters: // IN szString String to Hash // Returns: // DWORD hash // History: // 1/18/99 - MikeSwa Created // //----------------------------------------------------------------------------- inline DWORD dwQueueAdminHash(LPCSTR szString) { DWORD dwHash = 0; if (szString) { while (szString && *szString) { //Use Hash from Domhash.lib dwHash *= 131; //First prime after ASCII character codes dwHash += *szString; szString++; } } return dwHash; } //FifoQ Map function used to implement a majority of queue admin functionality //pvContext should be a pointer to a IQueueAdminMessageFilter interface HRESULT QueueAdminApplyActionToMessages(IN CMsgRef *pmsgref, IN PVOID pvContext, OUT BOOL *pfContinue, OUT BOOL *pfDelete); HRESULT HrQADMApplyActionToIMailMessages(IN IMailMsgProperties *pIMailMsgProperties, IN PVOID pvContext, OUT BOOL *pfContinue, OUT BOOL *pfDelete); // // Common QAPI functinoality that both CMsgRef and IMailMsgProperties QAPI // providers will need. // HRESULT HrGetMsgInfoFromIMailMsgProperty(IMailMsgProperties* pIMailMsgProperties, MESSAGE_INFO* pMsgInfo, LINK_INFO_FLAGS flags = LI_TYPE_REMOTE_DELIVERY); HRESULT HrQADMGetMsgSize(IMailMsgProperties* pIMailMsgProperties, DWORD* pcbMsgSize); VOID UpdateCountersForLinkType(CAQSvrInst *paqinst, DWORD dwLinkType); VOID QueueAdminFileTimeToSystemTime(FILETIME *pft, SYSTEMTIME *pst); #endif //__AQADMSVR_H__