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.
1599 lines
48 KiB
1599 lines
48 KiB
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// File: mailadmq.cpp
|
|
//
|
|
// Description: Implementation for CMailMsgAdminLink
|
|
//
|
|
// Author: Gautam Pulla (GPulla)
|
|
//
|
|
// History:
|
|
// 6/24/1999 - GPulla Created
|
|
//
|
|
// Copyright (C) 1999 Microsoft Corporation
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "aqprecmp.h"
|
|
#include "linkmsgq.h"
|
|
#include "mailadmq.h"
|
|
#include "dcontext.h"
|
|
#include "dsnevent.h"
|
|
#include "asyncq.inl"
|
|
#include "asyncadm.inl"
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueNDR ]-----------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Wraps call to NDR MailMsg
|
|
// Parameters:
|
|
// *pIUnknown - IUnkown of MailMsg
|
|
// Returns:
|
|
// S_OK on success
|
|
// History:
|
|
// 12/7/2000 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueNDR(
|
|
IUnknown *pIUnknownMsg)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueNDR");
|
|
HRESULT hr = S_OK;
|
|
IMailMsgProperties *pIMailMsgProperties = NULL;
|
|
CDSNParams dsnparams;
|
|
|
|
|
|
_ASSERT(pIUnknownMsg);
|
|
_ASSERT(m_paqinst);
|
|
|
|
hr = pIUnknownMsg->QueryInterface(IID_IMailMsgProperties,
|
|
(void **) &pIMailMsgProperties);
|
|
_ASSERT(SUCCEEDED(hr) && "IUnknownMsg Must be a MailMsg!!");
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) this, "QI for MailMsg failed with hr 0x%08X", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Initialize DSN params
|
|
//
|
|
SET_DEBUG_DSN_CONTEXT(dsnparams, __LINE__);
|
|
dsnparams.dwStartDomain = 0;
|
|
dsnparams.dwDSNActions = DSN_ACTION_FAILURE_ALL;
|
|
dsnparams.pIMailMsgProperties = pIMailMsgProperties;
|
|
dsnparams.hrStatus = AQUEUE_E_QADMIN_NDR;
|
|
|
|
//
|
|
// Attempt to NDR message
|
|
//
|
|
hr = HrLinkAllDomains(pIMailMsgProperties);
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) this,
|
|
"Unable to link all domains for DSN generation", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Fire DSN Generation event
|
|
//
|
|
hr = m_paqinst->HrTriggerDSNGenerationEvent(&dsnparams, FALSE);
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) this,
|
|
"Unable to NDR message via QAPI 0x%08X", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Now that we have generated an NDR... we need to delete the
|
|
// Message.
|
|
//
|
|
hr = HrDeleteMsgFromQueueSilent(pIUnknownMsg);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
Exit:
|
|
if (pIMailMsgProperties)
|
|
pIMailMsgProperties->Release();
|
|
|
|
TraceFunctLeave();
|
|
return hr;
|
|
}
|
|
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueSilent ]--------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Wrapper function to silently delete a message from a queue
|
|
// Parameters:
|
|
// *pIUnknown - IUnkown of MailMsg
|
|
// Returns:
|
|
// S_OK on success
|
|
// History:
|
|
// 12/7/2000 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueSilent(
|
|
IUnknown *pIUnknownMsg)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueSilent");
|
|
HRESULT hr = S_OK;
|
|
IMailMsgQueueMgmt *pIMailMsgQueueMgmt = NULL;
|
|
|
|
_ASSERT(pIUnknownMsg);
|
|
|
|
hr = pIUnknownMsg->QueryInterface(IID_IMailMsgQueueMgmt,
|
|
(void **) &pIMailMsgQueueMgmt);
|
|
_ASSERT(SUCCEEDED(hr) && "IUnknownMsg Must be a MailMsg!!");
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) this, "QI for MailMsg failed with hr 0x%08X", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Attempt to delete the message
|
|
//
|
|
hr = pIMailMsgQueueMgmt->Delete(NULL);
|
|
if (FAILED(hr))
|
|
ErrorTrace((LPARAM) this, "Unable to delete msg 0x%08X", hr);
|
|
|
|
Exit:
|
|
if (pIMailMsgQueueMgmt)
|
|
pIMailMsgQueueMgmt->Release();
|
|
|
|
TraceFunctLeave();
|
|
return hr;
|
|
}
|
|
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::HrFreezeMsg ]-----------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Wrapper to freeze a pIMailMsgProperties
|
|
// Parameters:
|
|
// *pIUnknown - IUnkown of MailMsg
|
|
// Returns:
|
|
// S_OK on success
|
|
// History:
|
|
// 12/7/2000 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CAsyncAdminMailMsgQueue::HrFreezeMsg(IUnknown *pIUnknownMsg)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrFreezeMsg");
|
|
HRESULT hr = S_OK;
|
|
IMailMsgProperties *pIMailMsgProperties = NULL;
|
|
|
|
_ASSERT(pIUnknownMsg);
|
|
|
|
hr = pIUnknownMsg->QueryInterface(IID_IMailMsgProperties,
|
|
(void **) &pIMailMsgProperties);
|
|
_ASSERT(SUCCEEDED(hr) && "IUnknownMsg Must be a MailMsg!!");
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) this, "QI for MailMsg failed with hr 0x%08X", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// $$TODO - Attempt to freeze the message -- Not supported for this type of queue
|
|
//
|
|
|
|
Exit:
|
|
if (pIMailMsgProperties)
|
|
pIMailMsgProperties->Release();
|
|
|
|
TraceFunctLeave();
|
|
return hr;
|
|
}
|
|
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::HrThawMsg ]-------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Wrapper function to thaw a message
|
|
// Parameters:
|
|
// *pIUnknown - IUnkown of MailMsg
|
|
// Returns:
|
|
// S_OK on success
|
|
// History:
|
|
// 12/7/2000 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CAsyncAdminMailMsgQueue::HrThawMsg(IUnknown *pIUnknownMsg)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) this, "AsyncAdminMailMsgQueue::HrThawMsg");
|
|
HRESULT hr = S_OK;
|
|
IMailMsgProperties *pIMailMsgProperties = NULL;
|
|
|
|
_ASSERT(pIUnknownMsg);
|
|
|
|
hr = pIUnknownMsg->QueryInterface(IID_IMailMsgProperties,
|
|
(void **) &pIMailMsgProperties);
|
|
_ASSERT(SUCCEEDED(hr) && "IUnknownMsg Must be a MailMsg!!");
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) this, "QI for MailMsg failed with hr 0x%08X", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// $$TODO - Attempt to thaw message -- Not supported for this type of queue
|
|
//
|
|
|
|
Exit:
|
|
if (pIMailMsgProperties)
|
|
pIMailMsgProperties->Release();
|
|
|
|
TraceFunctLeave();
|
|
return hr;
|
|
}
|
|
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::HrGetStatsForMsg ]------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Wrapper function to fill in the CAQStats struct for a message
|
|
// Parameters:
|
|
// *pIUnknown - IUnkown of MailMsg
|
|
// *paqstats - Ptr to aqstats struction to fill in.
|
|
// Returns:
|
|
// S_OK on success
|
|
// History:
|
|
// 12/7/2000 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CAsyncAdminMailMsgQueue::HrGetStatsForMsg(
|
|
IUnknown *pIUnknownMsg,
|
|
CAQStats *paqstats)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrGetStatsForMsg");
|
|
HRESULT hr = S_OK;
|
|
IMailMsgProperties *pIMailMsgProperties = NULL;
|
|
|
|
_ASSERT(pIUnknownMsg);
|
|
_ASSERT(paqstats);
|
|
|
|
hr = pIUnknownMsg->QueryInterface(IID_IMailMsgProperties,
|
|
(void **) &pIMailMsgProperties);
|
|
_ASSERT(SUCCEEDED(hr) && "IUnknownMsg Must be a MailMsg!!");
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) this, "QI for MailMsg failed with hr 0x%08X", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// $$TODO - GetStats for Msg -- Not supported for this type of queue
|
|
//
|
|
|
|
Exit:
|
|
if (pIMailMsgProperties)
|
|
pIMailMsgProperties->Release();
|
|
|
|
TraceFunctLeave();
|
|
return hr;
|
|
}
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::HrSendDelayOrNDR ]-----------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Checks the MailMsg to see if it has expired or needs a delay DSN sent
|
|
// and acts accordingly
|
|
// Parameters:
|
|
// IMailMsgProperties - The MailMsg that needs to be checked
|
|
// Returns:
|
|
// S_OK : OK, may have sent delay NDR
|
|
// S_FALSE : OK, MailMsg handled (NDR'd or nothing left to do)
|
|
// Or returns error from called fnct.
|
|
// History:
|
|
// 5/15/2001 - dbraun Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CAsyncAdminMailMsgQueue::HrSendDelayOrNDR(IMailMsgProperties *pIMailMsgProperties)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cbProp = 0;
|
|
DWORD dwTimeContext = 0;
|
|
CDSNParams dsnparams;
|
|
BOOL fSentDelay = FALSE;
|
|
BOOL fSentNDR = FALSE;
|
|
|
|
FILETIME ftExpireTimeNDR;
|
|
FILETIME ftExpireTimeDelay;
|
|
|
|
|
|
TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrSendDelayOrNDR");
|
|
|
|
_ASSERT(m_paqinst);
|
|
|
|
// Try to get the expire time from the message, otherwise calculate it
|
|
// from the file time
|
|
hr = pIMailMsgProperties->GetProperty(IMMPID_MP_LOCAL_EXPIRE_NDR,
|
|
sizeof(FILETIME), &cbProp, (BYTE *) &ftExpireTimeNDR);
|
|
if (MAILMSG_E_PROPNOTFOUND == hr)
|
|
{
|
|
// Prop not set ... calculate it from the file time
|
|
hr = pIMailMsgProperties->GetProperty(IMMPID_MP_ARRIVAL_FILETIME,
|
|
sizeof(FILETIME), &cbProp, (BYTE *) &ftExpireTimeNDR);
|
|
if (FAILED(hr))
|
|
{
|
|
// Message should not make it this far without being stamped
|
|
_ASSERT(MAILMSG_E_PROPNOTFOUND != hr);
|
|
|
|
// Prop not set or other failure, we cannot expire this message
|
|
goto Exit;
|
|
}
|
|
|
|
m_paqinst->CalcExpireTimeNDR(ftExpireTimeNDR, TRUE, &ftExpireTimeNDR);
|
|
}
|
|
else if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
hr = pIMailMsgProperties->GetProperty(IMMPID_MP_LOCAL_EXPIRE_DELAY,
|
|
sizeof(FILETIME), &cbProp, (BYTE *) &ftExpireTimeDelay);
|
|
if (MAILMSG_E_PROPNOTFOUND == hr)
|
|
{
|
|
// Prop not set ... calculate it from the file time
|
|
hr = pIMailMsgProperties->GetProperty(IMMPID_MP_ARRIVAL_FILETIME,
|
|
sizeof(FILETIME), &cbProp, (BYTE *) &ftExpireTimeDelay);
|
|
if (FAILED(hr))
|
|
{
|
|
// Message should not make it this far without being stamped
|
|
_ASSERT(MAILMSG_E_PROPNOTFOUND != hr);
|
|
|
|
// Prop not set or other failure, we cannot expire this message
|
|
goto Exit;
|
|
}
|
|
|
|
m_paqinst->CalcExpireTimeDelay(ftExpireTimeDelay, TRUE, &ftExpireTimeDelay);
|
|
}
|
|
else if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Initialize DSN params
|
|
//
|
|
SET_DEBUG_DSN_CONTEXT(dsnparams, __LINE__);
|
|
dsnparams.dwStartDomain = 0;
|
|
dsnparams.dwDSNActions = 0;
|
|
dsnparams.pIMailMsgProperties = pIMailMsgProperties;
|
|
dsnparams.hrStatus = 0;
|
|
|
|
// Check if we have passed either expire time
|
|
if (m_paqinst->fInPast(&ftExpireTimeNDR, &dwTimeContext))
|
|
{
|
|
dsnparams.dwDSNActions |= DSN_ACTION_FAILURE_ALL;
|
|
dsnparams.hrStatus = AQUEUE_E_MSG_EXPIRED;
|
|
fSentNDR = TRUE;
|
|
}
|
|
else if (m_paqinst->fInPast(&ftExpireTimeDelay, &dwTimeContext))
|
|
{
|
|
dsnparams.dwDSNActions |= DSN_ACTION_DELAYED;
|
|
dsnparams.hrStatus = AQUEUE_E_MSG_EXPIRED;
|
|
fSentDelay = TRUE;
|
|
}
|
|
|
|
// If we are going to generate an NDR
|
|
if (dsnparams.hrStatus)
|
|
{
|
|
//
|
|
// Attempt to NDR message
|
|
//
|
|
hr = HrLinkAllDomains(pIMailMsgProperties);
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) this,
|
|
"Unable to link all domains for DSN generation", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Fire DSN Generation event
|
|
//
|
|
hr = m_paqinst->HrTriggerDSNGenerationEvent(&dsnparams, FALSE);
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) this,
|
|
"Unable to NDR message via QAPI 0x%08X", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
// Return based on what we did
|
|
if (fSentNDR)
|
|
{
|
|
// This message has been handled, delete it
|
|
hr = HrDeleteMsgFromQueueSilent(pIMailMsgProperties);
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) this,
|
|
"Failed to delete message after sending NDR", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
// NDR'd and successfully deleted message
|
|
hr = S_FALSE;
|
|
}
|
|
else if (fSentDelay)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
TraceFunctLeave();
|
|
return hr;
|
|
}
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::fHandleCompletionFailure ]---------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Overrides base class and checks to see if message has expired before
|
|
// putting it on the retry queue
|
|
// Parameters:
|
|
// IMailMsgProperties - The MailMsg that triggered failure
|
|
// Returns:
|
|
// -
|
|
// History:
|
|
// 5/15/2001 - dbraun Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CAsyncAdminMailMsgQueue::fHandleCompletionFailure(IMailMsgProperties *pIMailMsgProperties)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Has this message expired?
|
|
hr = HrSendDelayOrNDR (pIMailMsgProperties);
|
|
|
|
if (hr == S_FALSE)
|
|
{
|
|
// This message was NDR'd, we are done
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return CAsyncAdminQueue<IMailMsgProperties *, ASYNC_QUEUE_MAILMSG_SIG>::fHandleCompletionFailure(pIMailMsgProperties);
|
|
}
|
|
}
|
|
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::HrQueueRequest ]-------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Function that will queue a request to the async queue and close
|
|
// the handles associated with a message if we are above our simple
|
|
// "throttle" limit.
|
|
// Parameters:
|
|
// pIMailMsgProperties The IMailMsgProperties interface to queue
|
|
// fRetry TRUE - if this message is being retried
|
|
// FALSE - otherwise
|
|
// cMsgsInSystem The total number of messages in the system
|
|
// Returns:
|
|
// S_OK on success
|
|
// Error code from async queue on failure.
|
|
// History:
|
|
// 10/7/1999 - MikeSwa Created
|
|
// 12/7/2000 - MikeSwa Moved to CAsyncAdminMailMsgQueue from asyncq.cpp
|
|
// 4/6/2001 - MikeSwa Modified to take into account queue length
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CAsyncAdminMailMsgQueue::HrQueueRequest(IMailMsgProperties *pIMailMsgProperties,
|
|
BOOL fRetry,
|
|
DWORD cMsgsInSystem)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrQueueRequest");
|
|
IMailMsgQueueMgmt *pIMailMsgQueueMgmt = NULL;
|
|
HRESULT hr = S_OK;
|
|
DWORD cThresholdUsed = g_cMaxIMsgHandlesThreshold;
|
|
DWORD cItemsPending = dwGetTotalThreads()+m_cItemsPending;
|
|
|
|
if (m_qhmgr.fShouldCloseHandle(cItemsPending, m_cPendingAsyncCompletions,
|
|
cMsgsInSystem))
|
|
{
|
|
DebugTrace((LPARAM) this,
|
|
"INFO: Closing IMsg Content - %d messsages in system", cMsgsInSystem);
|
|
hr = pIMailMsgProperties->QueryInterface(IID_IMailMsgQueueMgmt,
|
|
(void **) &pIMailMsgQueueMgmt);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//bounce usage count off of zero
|
|
pIMailMsgQueueMgmt->ReleaseUsage();
|
|
pIMailMsgQueueMgmt->AddUsage();
|
|
pIMailMsgQueueMgmt->Release();
|
|
}
|
|
else
|
|
{
|
|
ErrorTrace((LPARAM) this,
|
|
"Unable to QI for IMailMsgQueueMgmt - hr 0x%08X", hr);
|
|
}
|
|
}
|
|
TraceFunctLeave();
|
|
return CAsyncAdminQueue<IMailMsgProperties *, ASYNC_QUEUE_MAILMSG_SIG>::HrQueueRequest(pIMailMsgProperties, fRetry);
|
|
}
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::HrQueueRequest ]-------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Since we inherit from AsyncQueue who implmenents this, we should assert
|
|
// so that a dev adding a new call to this class later on, will use the
|
|
// version that closes handles.
|
|
//
|
|
// In RTL this will force the handles closed and queue the request
|
|
// Parameters:
|
|
// pIMailMsgProperties The IMailMsgProperties interface to queue
|
|
// fRetry TRUE - if this message is being retried
|
|
// FALSE - otherwise
|
|
// Returns:
|
|
// returns return value from proper version of HrQueueRequest
|
|
// History:
|
|
// 10/7/1999 - MikeSwa Created
|
|
// 12/7/2000 - MikeSwa Moved to CAsyncAdminMailMsgQueue from asyncq.cpp
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CAsyncAdminMailMsgQueue::HrQueueRequest(IMailMsgProperties *pIMailMsgProperties,
|
|
BOOL fRetry)
|
|
{
|
|
_ASSERT(0 && "Should use HrQueueRequest with 3 parameters");
|
|
return HrQueueRequest(pIMailMsgProperties, fRetry,
|
|
g_cMaxIMsgHandlesThreshold+1);
|
|
}
|
|
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::HrApplyQueueAdminFunction ]--------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Will call the IQueueAdminMessageFilter::Process message for every
|
|
// message in this queue. If the message passes the filter, then
|
|
// HrApplyActionToMessage on this object will be called.
|
|
//
|
|
// This is different from other implemenentations in that the
|
|
// location of the message implies something about the state of the
|
|
// message. Messages in the retry... or frozen queue are considered
|
|
// failed or frozen.
|
|
//
|
|
// We do this instead of writing a mailmsg property, because of the
|
|
// *huge* perf hit (we would ruin our async message flow by blocking
|
|
// to check if a message is frozen). We already have the retry
|
|
// queue, so it makes sense to use it in a similar manner
|
|
//
|
|
// Parameters:
|
|
// IN pIQueueAdminMessageFilter
|
|
// Returns:
|
|
// S_OK on success
|
|
// History:
|
|
// 2/23/99 - MikeSwa Created
|
|
// 12/7/2000 - MikeSwa Modified - Made template base class
|
|
// 12/13/2000 - MikeSwa Modified from CAsyncAdminQueue
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CAsyncAdminMailMsgQueue::HrApplyQueueAdminFunction(
|
|
IQueueAdminMessageFilter *pIQueueAdminMessageFilter)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CQueueAdminContext qapictx(m_pAQNotify, m_paqinst);
|
|
|
|
_ASSERT(pIQueueAdminMessageFilter);
|
|
hr = pIQueueAdminMessageFilter->HrSetQueueAdminAction(
|
|
(IQueueAdminAction *) this);
|
|
|
|
//This is an internal interface that should not fail
|
|
_ASSERT(SUCCEEDED(hr) && "HrSetQueueAdminAction");
|
|
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
hr = pIQueueAdminMessageFilter->HrSetCurrentUserContext(&qapictx);
|
|
//This is an internal interface that should not fail
|
|
_ASSERT(SUCCEEDED(hr) && "HrSetCurrentUserContext");
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
//
|
|
// Iterate over messages in the base queue
|
|
//
|
|
qapictx.SetQueueState(LI_READY);
|
|
hr = HrMapFnBaseQueue(m_pfnMessageAction, pIQueueAdminMessageFilter);
|
|
|
|
//
|
|
// Iterate over messages in the retry queue
|
|
//
|
|
qapictx.SetQueueState(LI_RETRY);
|
|
hr = HrMapFnRetryQueue(m_pfnMessageAction, pIQueueAdminMessageFilter);
|
|
|
|
hr = pIQueueAdminMessageFilter->HrSetCurrentUserContext(NULL);
|
|
//This is an internal interface that should not fail
|
|
_ASSERT(SUCCEEDED(hr) && "HrSetCurrentUserContext");
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Description:
|
|
// Used to query the admin interfaces for CMailMsgAdminLink
|
|
// Parameters:
|
|
// IN REFIID riid GUID for interface
|
|
// OUT LPVOID *ppvObj Ptr to Interface.
|
|
//
|
|
// Returns:
|
|
// S_OK Interface supported by this class.
|
|
// E_POINTER NULL parameter.
|
|
// E_NOINTERFACE No such interface exists.
|
|
// History:
|
|
// 6/25/1999 - GPulla Created
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CMailMsgAdminLink::QueryInterface(REFIID riid, LPVOID *ppvObj)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!ppvObj)
|
|
{
|
|
hr = E_POINTER;
|
|
goto Exit;
|
|
}
|
|
|
|
if (IID_IUnknown == riid)
|
|
{
|
|
*ppvObj = static_cast<IQueueAdminAction *>(this);
|
|
}
|
|
else if (IID_IQueueAdminAction == riid)
|
|
{
|
|
*ppvObj = static_cast<IQueueAdminAction *>(this);
|
|
}
|
|
else if (IID_IQueueAdminLink == riid)
|
|
{
|
|
*ppvObj = static_cast<IQueueAdminLink *>(this);
|
|
}
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
hr = E_NOINTERFACE;
|
|
goto Exit;
|
|
}
|
|
|
|
static_cast<IUnknown *>(*ppvObj)->AddRef();
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
//---[ CMailMsgAdminLink::CMailMsgAdminLink]---------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Default constructor for CMailMsgAdminLink
|
|
// Parameters:
|
|
// IN guidLink GUID to associate with this object
|
|
// IN szQueueName Name to associate with admin object
|
|
// IN *pasyncmmq Async MailMsg queue for precat or prerouting
|
|
// IN dwLinkType Bit-Field identifying this admin object
|
|
// IN paqinst CAQSvrInst object
|
|
//
|
|
// Returns:
|
|
// -
|
|
// History:
|
|
// 6/25/1999 - GPulla Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CMailMsgAdminLink::CMailMsgAdminLink(
|
|
GUID guid,
|
|
LPSTR szQueueName,
|
|
CAsyncAdminMailMsgQueue *pasyncmmq,
|
|
DWORD dwLinkType,
|
|
CAQSvrInst *paqinst
|
|
)
|
|
: m_aqsched(guid, 0)
|
|
{
|
|
_ASSERT(pasyncmmq);
|
|
_ASSERT(szQueueName);
|
|
_ASSERT(paqinst);
|
|
|
|
m_guid = guid;
|
|
m_cbQueueName = lstrlen(szQueueName);
|
|
|
|
m_szQueueName = (LPSTR) pvMalloc(m_cbQueueName+1);
|
|
_ASSERT(m_szQueueName);
|
|
|
|
if(m_szQueueName)
|
|
lstrcpy(m_szQueueName, szQueueName);
|
|
|
|
m_pasyncmmq = pasyncmmq;
|
|
|
|
m_dwLinkType = dwLinkType;
|
|
|
|
m_dwSignature = MAIL_MSG_ADMIN_QUEUE_VALID_SIGNATURE;
|
|
|
|
if (m_pasyncmmq)
|
|
m_pasyncmmq->SetAQNotify((IAQNotify *) this);
|
|
|
|
m_paqinst = paqinst;
|
|
|
|
ZeroMemory(&m_ftRetry, sizeof(m_ftRetry));
|
|
}
|
|
|
|
//---[CMailMsgAdminLink::~CMailMsgAdminLink]---------------------------------
|
|
// Description:
|
|
// Destructor.
|
|
// Parameters:
|
|
// -
|
|
// Returns:
|
|
// -
|
|
// History:
|
|
// 6/24/1999 - GPulla created
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CMailMsgAdminLink::~CMailMsgAdminLink()
|
|
{
|
|
if (m_szQueueName)
|
|
FreePv(m_szQueueName);
|
|
m_dwSignature = MAIL_MSG_ADMIN_QUEUE_INVALID_SIGNATURE;
|
|
}
|
|
|
|
|
|
//---[ CMailMsgAdminLink::HrApplyQueueAdminFunction ]---------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Wrapper to call into underlying queue's implementation
|
|
// Parameters:
|
|
// IN pIQueueAdminMessageFilter
|
|
// Returns:
|
|
// S_OK on success
|
|
// S_FALSE if no contained queue (will assert as well)
|
|
// History:
|
|
// 12/11/2000 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CMailMsgAdminLink::HrApplyQueueAdminFunction(
|
|
IQueueAdminMessageFilter *pIQueueAdminMessageFilter)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
_ASSERT(m_pasyncmmq);
|
|
|
|
if (m_pasyncmmq)
|
|
hr = m_pasyncmmq->HrApplyQueueAdminFunction(pIQueueAdminMessageFilter);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//---[ CMailMsgAdminLink::HrApplyActionToMessage ]-----------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Wrapper function to pass call on to queue implementation
|
|
// Parameters:
|
|
// IN *pIUnknownMsg ptr to message abstraction
|
|
// IN ma Message action to perform
|
|
// IN pvContext Context set on IQueueAdminFilter
|
|
// OUT pfShouldDelete TRUE if the message should be deleted
|
|
// Returns:
|
|
// S_OK on success
|
|
// S_FALSE if no contained queue (will assert as well)
|
|
// History:
|
|
// 12/11/2000 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CMailMsgAdminLink::HrApplyActionToMessage(
|
|
IUnknown *pIUnknownMsg,
|
|
MESSAGE_ACTION ma,
|
|
PVOID pvContext,
|
|
BOOL *pfShouldDelete)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
_ASSERT(m_pasyncmmq);
|
|
|
|
if (m_pasyncmmq)
|
|
{
|
|
hr = m_pasyncmmq->HrApplyActionToMessage(pIUnknownMsg, ma,
|
|
pvContext, pfShouldDelete);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//---[CMailMsgAdminLink::HrGetLinkInfo]---------------------------------------
|
|
// Description:
|
|
// Gets information about this admin object. Note that the diagnostic error
|
|
// is not implemented for this object but the parameter is supported purely
|
|
// to support the IQueueAction interface.
|
|
// Parameters:
|
|
// OUT LINK_INFO *pliLinkInfo Struct to fill information into.
|
|
// OUT HRESULT *phrDiagnosticError Diagnostic error if any, for this link
|
|
// Returns:
|
|
// S_OK on success
|
|
// E_POINTER if argument is NULL
|
|
// E_OUTOFMEMORY if unable to allocate memory for returning information.
|
|
// History:
|
|
// 6/24/1999 - GPulla created
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CMailMsgAdminLink::HrGetLinkInfo(LINK_INFO *pliLinkInfo, HRESULT *phrDiagnosticError)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) this, "CMailMsgAdminLink::HrGetLinkInfo");
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERT(m_pasyncmmq);
|
|
_ASSERT(pliLinkInfo);
|
|
|
|
if(!m_pasyncmmq)
|
|
{
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
if(!pliLinkInfo)
|
|
{
|
|
hr = E_POINTER;
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Get the link state from our base queue implementation
|
|
//
|
|
pliLinkInfo->fStateFlags = m_pasyncmmq->dwQueueAdminLinkGetLinkState();
|
|
|
|
//
|
|
// If we are in retry... try to report the time
|
|
//
|
|
if (LI_RETRY & pliLinkInfo->fStateFlags)
|
|
QueueAdminFileTimeToSystemTime(&m_ftRetry, &(pliLinkInfo->stNextScheduledConnection));
|
|
|
|
pliLinkInfo->fStateFlags |= GetLinkType();
|
|
pliLinkInfo->szLinkName = wszQueueAdminConvertToUnicode(m_szQueueName, m_cbQueueName);
|
|
|
|
if (!pliLinkInfo->szLinkName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
//We return 0 since size statistics are not calculated
|
|
pliLinkInfo->cbLinkVolume.QuadPart = 0;
|
|
|
|
//
|
|
// Include the items queued for retry in the total count
|
|
//
|
|
pliLinkInfo->cMessages = m_pasyncmmq->cQueueAdminGetNumItems();
|
|
|
|
pliLinkInfo->dwSupportedLinkActions = LA_KICK | LA_THAW | LA_FREEZE;
|
|
|
|
//Write diagnostic
|
|
*phrDiagnosticError = S_OK;
|
|
|
|
Exit:
|
|
TraceFunctLeave();
|
|
return hr;
|
|
}
|
|
|
|
//---[CMailMsgAdminLink::HrGetNumQueues]-------------------------------------
|
|
// Description:
|
|
// Used to query number of queues in object. Since this class does not
|
|
// expose the one queue it contains, 0 is returned,
|
|
// Parameters:
|
|
// OUT DWORD *pcQueues # of queues (0) written to this.
|
|
// Returns:
|
|
// S_OK unless...
|
|
// E_POINTER parameter is not allocated
|
|
// History:
|
|
// 6/24/1999 - GPulla created
|
|
// 12/11/2000 - MikeSwa Updated to support sub-queues
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CMailMsgAdminLink::HrGetNumQueues(DWORD *pcQueues)
|
|
{
|
|
_ASSERT (pcQueues);
|
|
if (!pcQueues)
|
|
return E_POINTER;
|
|
|
|
*pcQueues = 1;
|
|
return S_OK;
|
|
}
|
|
|
|
//---[CMailMsgAdminLink::HrApplyActionToLink]---------------------------------
|
|
// Description:
|
|
// Applies action to the embedded queue. Only kicking the queue is supported.
|
|
// Parameters:
|
|
// IN LINK_ACTION la Action to apply.
|
|
// Returns:
|
|
// S_OK Action was successfully applied.
|
|
// S_FALSE Action not supported or severe error.
|
|
// History:
|
|
// 6/24/1999 - GPulla created
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CMailMsgAdminLink::HrApplyActionToLink(LINK_ACTION la)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERT(m_pasyncmmq);
|
|
if (!m_pasyncmmq)
|
|
{
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
if (LA_KICK == la)
|
|
m_pasyncmmq->StartRetry(); //kick off processing
|
|
else if (LA_FREEZE == la)
|
|
m_pasyncmmq->FreezeQueue();
|
|
else if (LA_THAW == la)
|
|
m_pasyncmmq->ThawQueue();
|
|
else
|
|
hr = S_FALSE;
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
//---[CMailMsgAdminLink::HrGetQueueIDs]---------------------------------------
|
|
// Description:
|
|
// Returns an enumeration of embedded queues in this object. Since the one
|
|
// emmbedded queue is not exposed, zero queues are returned.
|
|
// Parameters:
|
|
// OUT DWORD *pcQueues Number of queues (0)
|
|
// OUT QUEUELINK_ID *rgQueues Array into which queueIDs are returned.
|
|
// Returns:
|
|
// S_OK Success
|
|
// E_POINTER pcQueues is NULL
|
|
// History:
|
|
// 6/24/1999 - GPulla created
|
|
// 12/11/2000 - MikeSwa Modified to expose queues
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CMailMsgAdminLink::HrGetQueueIDs(DWORD *pcQueues, QUEUELINK_ID *rgQueues)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) this, "CMailMsgAdminLink::HrGetQueueIDs");
|
|
_ASSERT(pcQueues);
|
|
_ASSERT(rgQueues);
|
|
HRESULT hr = S_OK;
|
|
QUEUELINK_ID* pCurrentQueueID = rgQueues;
|
|
|
|
if(!pcQueues)
|
|
{
|
|
hr = E_POINTER;
|
|
goto Exit;
|
|
}
|
|
|
|
if (*pcQueues < 1)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
|
goto Exit;
|
|
}
|
|
|
|
*pcQueues = 0;
|
|
|
|
_ASSERT(m_pasyncmmq);
|
|
hr = m_pasyncmmq->HrGetQueueID(pCurrentQueueID);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
*pcQueues = 1;
|
|
|
|
Exit:
|
|
TraceFunctLeave();
|
|
return hr;
|
|
}
|
|
|
|
//---[CMailMsgAdminLink::fMatchesID]------------------------------------------
|
|
// Description:
|
|
// Checks if this admin object matches a specified ID.
|
|
// Parameters:
|
|
// IN QUEUELINK_ID *pQueueLinkID Ptr to ID to be matched against.
|
|
// Returns:
|
|
// TRUE on match.
|
|
// FALSE if did not matched or unrecoverable error (m_szQueueName not alloced)
|
|
// History:
|
|
// 6/24/1999 - GPulla created
|
|
//-----------------------------------------------------------------------------
|
|
BOOL STDMETHODCALLTYPE CMailMsgAdminLink::fMatchesID(QUEUELINK_ID *pQueueLinkID)
|
|
{
|
|
_ASSERT(pQueueLinkID);
|
|
_ASSERT(pQueueLinkID->szName);
|
|
_ASSERT(m_szQueueName);
|
|
|
|
if(!m_szQueueName)
|
|
return FALSE;
|
|
|
|
CAQScheduleID aqsched(pQueueLinkID->uuid, pQueueLinkID->dwId);
|
|
|
|
if (!fIsSameScheduleID(&aqsched))
|
|
return FALSE;
|
|
|
|
if (!fBiStrcmpi(m_szQueueName, pQueueLinkID->szName))
|
|
return FALSE;
|
|
|
|
//Everything matched!
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//---[ CMailMsgAdminLink::QuerySupportedActions ]------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns the actions and filters that this implementation supports
|
|
// Parameters:
|
|
// pdwSupportedActions - QAPI MsgActions that this queue suppprts
|
|
// pdwSupportedFilterFlags - QAPI filter flags that this queue supports
|
|
// Returns:
|
|
// S_OK on success
|
|
// History:
|
|
// 12/12/2000 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP CMailMsgAdminLink::QuerySupportedActions(
|
|
DWORD *pdwSupportedActions,
|
|
DWORD *pdwSupportedFilterFlags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
_ASSERT(m_pasyncmmq);
|
|
if (m_pasyncmmq)
|
|
{
|
|
hr = m_pasyncmmq->QuerySupportedActions(pdwSupportedActions,
|
|
pdwSupportedFilterFlags);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//---[CMailMsgAdminLink::fIsSameScheduleID]-----------------------------------
|
|
// Description:
|
|
// Helper function for fMatchesID()
|
|
// Parameters:
|
|
// Returns:
|
|
// TRUE if schedule IDs are identical
|
|
// FALSE otherwise.
|
|
// History:
|
|
// 6/24/1999 - GPulla created
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CMailMsgAdminLink::fIsSameScheduleID(CAQScheduleID *paqsched)
|
|
{
|
|
return (m_aqsched.fIsEqual(paqsched));
|
|
}
|
|
|
|
//---[CMailMsgAdminLink::HrGetLinkID]-----------------------------------------
|
|
// Description:
|
|
// Get the ID for this admin object.
|
|
// Parameters:
|
|
// OUT QUEUELINK_ID *pLinkID struct into which to put ID.
|
|
// Returns:
|
|
// S_OK Successfully copied out ID.
|
|
// E_POINTER out struct is NULL.
|
|
// E_OUTOFMEMORY Cannot allocate memory for output of ID name.
|
|
// History:
|
|
// 6/24/1999 - GPulla created
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMailMsgAdminLink::HrGetLinkID(QUEUELINK_ID *pLinkID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERT(pLinkID);
|
|
if(!pLinkID)
|
|
{
|
|
hr = E_POINTER;
|
|
goto Exit;
|
|
}
|
|
|
|
pLinkID->qltType = QLT_LINK;
|
|
pLinkID->dwId = m_aqsched.dwGetScheduleID();
|
|
m_aqsched.GetGUID(&pLinkID->uuid);
|
|
|
|
if (!fRPCCopyName(&pLinkID->szName))
|
|
hr = E_OUTOFMEMORY;
|
|
else
|
|
hr = S_OK;
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
//---[CMailMsgAdminLink::fRPCCopyName]----------------------------------------
|
|
// Description:
|
|
// Helper function to create a unicode copy of the string identifying
|
|
// this admin object. The unicode string is de-allocated by RPC.
|
|
// Parameters:
|
|
// OUT LPWSTR *pwszLinkName Ptr to wchar string allocated and written
|
|
// into by this function.
|
|
// Returns:
|
|
// TRUE On success.
|
|
// FALSE if there is no name for this object
|
|
// FALSE if memory cannot be allocated for unicode string.
|
|
// History:
|
|
// 6/24/1999 - GPulla created
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CMailMsgAdminLink::fRPCCopyName(OUT LPWSTR *pwszLinkName)
|
|
{
|
|
_ASSERT(pwszLinkName);
|
|
|
|
if (!m_cbQueueName || !m_szQueueName)
|
|
return FALSE;
|
|
|
|
*pwszLinkName = wszQueueAdminConvertToUnicode(m_szQueueName,
|
|
m_cbQueueName);
|
|
if (!*pwszLinkName)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//---[ CAsyncAdminMailMsgLink::HrNotify ]--------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Notification for stats purposes
|
|
// Parameters:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History:
|
|
// 1/10/2001 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMailMsgAdminLink::HrNotify(CAQStats *aqstats, BOOL fAdd)
|
|
{
|
|
UpdateCountersForLinkType(m_paqinst, m_dwLinkType);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//---[ CMailMsgAdminLink::SetNextRetry ]---------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Updates internal retry time
|
|
// Parameters:
|
|
// pft Filetime to update to
|
|
// Returns:
|
|
// -
|
|
// History:
|
|
// 1/16/2001 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CMailMsgAdminLink::SetNextRetry(FILETIME *pft)
|
|
{
|
|
if (pft)
|
|
memcpy(&m_ftRetry, pft, sizeof(FILETIME));
|
|
}
|
|
|
|
|
|
//--------[ CAsyncAdminMailMsgQueue::fMatchesQueueAdminFilter ]-----------------
|
|
//
|
|
// Description:
|
|
// Checks a message against a queue admin message filter to see if it
|
|
// is a match
|
|
// Parameters:
|
|
// IN pIMailMsgProperties mail msg object to perform check on
|
|
// IN paqmf Message Filter to check against
|
|
// Returns:
|
|
// TRUE if it matches
|
|
// FALSE if it does not
|
|
// History:
|
|
// 8/8/00 - t-toddc created
|
|
// 12/11/2000 - MikeSwa Merged for checkin
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CAsyncAdminMailMsgQueue::fMatchesQueueAdminFilter(
|
|
IN IMailMsgProperties* pIMailMsgProperties,
|
|
IN CAQAdminMessageFilter* paqmf)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) pIMailMsgProperties,
|
|
"CAsyncAdminMailMsgQueue::fMatchesQueueAdminFilter");
|
|
BOOL fMatch = TRUE;
|
|
DWORD dwFilterFlags = 0;
|
|
DWORD cbMsgSize = 0;
|
|
DWORD cbProp = 0;
|
|
FILETIME ftQueueEntry = {0, 0};
|
|
LPSTR szSender = NULL;
|
|
LPSTR szMsgId = NULL;
|
|
LPSTR szRecip = NULL;
|
|
BOOL fFoundRecipString = FALSE;
|
|
HRESULT hr = S_OK;
|
|
DWORD cOpenHandlesForMsg = 1; //don't close by default
|
|
|
|
_ASSERT(pIMailMsgProperties);
|
|
_ASSERT(paqmf);
|
|
|
|
dwFilterFlags = paqmf->dwGetMsgFilterFlags();
|
|
|
|
if (!dwFilterFlags)
|
|
{
|
|
fMatch = FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
if (AQ_MSG_FILTER_ALL & dwFilterFlags)
|
|
{
|
|
fMatch = TRUE;
|
|
goto Exit;
|
|
}
|
|
|
|
// check size.
|
|
if (AQ_MSG_FILTER_LARGER_THAN & dwFilterFlags)
|
|
{
|
|
|
|
//Get the size of the message
|
|
hr = HrQADMGetMsgSize(pIMailMsgProperties, &cbMsgSize);
|
|
if (FAILED(hr))
|
|
{
|
|
fMatch = FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
fMatch = paqmf->fMatchesSize(cbMsgSize);
|
|
if (!fMatch)
|
|
goto Exit;
|
|
}
|
|
|
|
if (AQ_MSG_FILTER_OLDER_THAN & dwFilterFlags)
|
|
{
|
|
|
|
//Get time message was queued
|
|
hr = pIMailMsgProperties->GetProperty(IMMPID_MP_ARRIVAL_FILETIME,
|
|
sizeof(FILETIME),
|
|
&cbProp,
|
|
(BYTE *) &ftQueueEntry);
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) pIMailMsgProperties,
|
|
"Unable to get arrival time 0x%08X", hr);
|
|
fMatch = FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
fMatch = paqmf->fMatchesTime(&ftQueueEntry);
|
|
if (!fMatch)
|
|
goto Exit;
|
|
}
|
|
|
|
if (AQ_MSG_FILTER_FROZEN & dwFilterFlags)
|
|
{
|
|
// obtaining state information about freezing/thawing not supported yet.
|
|
fMatch = FALSE;
|
|
if (AQ_MSG_FILTER_INVERTSENSE & dwFilterFlags)
|
|
fMatch = !fMatch;
|
|
|
|
if (!fMatch)
|
|
goto Exit;
|
|
}
|
|
|
|
if (AQ_MSG_FILTER_FAILED & dwFilterFlags)
|
|
{
|
|
// fMatch was originally set to TRUE
|
|
// currently, no information about failures is available
|
|
// for IMailMsgProperties mail msg objects
|
|
fMatch = FALSE;
|
|
|
|
if (AQ_MSG_FILTER_INVERTSENSE & dwFilterFlags)
|
|
fMatch = !fMatch;
|
|
|
|
if (!fMatch)
|
|
goto Exit;
|
|
}
|
|
|
|
//If we haven't failed by this point, we may need to AddUsage and read
|
|
//props from the mailmsg. Double-check to make sure that we need to
|
|
//add usage.
|
|
if (!((AQ_MSG_FILTER_MESSAGEID | AQ_MSG_FILTER_SENDER | AQ_MSG_FILTER_RECIPIENT) &
|
|
dwFilterFlags))
|
|
goto Exit;
|
|
|
|
//
|
|
// Check to see if the message is already open
|
|
//
|
|
hr = pIMailMsgProperties->GetDWORD(
|
|
IMMPID_MPV_MESSAGE_OPEN_HANDLES,
|
|
&cOpenHandlesForMsg);
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) pIMailMsgProperties, "Not running SP1 of W2K");
|
|
cOpenHandlesForMsg = 0;
|
|
hr = S_OK;
|
|
|
|
}
|
|
|
|
if (AQ_MSG_FILTER_MESSAGEID & dwFilterFlags)
|
|
{
|
|
hr = HrQueueAdminGetStringProp(pIMailMsgProperties,
|
|
IMMPID_MP_RFC822_MSG_ID,
|
|
&szMsgId);
|
|
if (FAILED(hr))
|
|
szMsgId = NULL;
|
|
fMatch = paqmf->fMatchesId(szMsgId);
|
|
if (!fMatch)
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (AQ_MSG_FILTER_SENDER & dwFilterFlags)
|
|
{
|
|
fMatch = paqmf->fMatchesMailMsgSender(pIMailMsgProperties);
|
|
|
|
if (!fMatch)
|
|
goto Exit;
|
|
}
|
|
|
|
if (AQ_MSG_FILTER_RECIPIENT & dwFilterFlags)
|
|
{
|
|
fMatch = paqmf->fMatchesMailMsgRecipient(pIMailMsgProperties);
|
|
|
|
if (!fMatch)
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
//
|
|
// If this operation resulted in opening the message, we should close it
|
|
// The message is not dirty (we did not write anything), so it should not
|
|
// need to commit
|
|
//
|
|
if (!cOpenHandlesForMsg)
|
|
{
|
|
HRESULT hrTmp = S_OK;
|
|
hrTmp = HrReleaseIMailMsgUsageCount(pIMailMsgProperties);
|
|
if (SUCCEEDED(hrTmp))
|
|
HrIncrementIMailMsgUsageCount(pIMailMsgProperties);
|
|
}
|
|
|
|
if (szMsgId)
|
|
QueueAdminFree(szMsgId);
|
|
|
|
TraceFunctLeave();
|
|
return fMatch;
|
|
|
|
}
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::HrGetQueueAdminMsgInfo ]-----------------------
|
|
//
|
|
// Description:
|
|
// Fills out a queue admin MESSAGE_INFO structure. All allocations are
|
|
// done with pvQueueAdminAlloc to be freed by the RPC code
|
|
// Parameters:
|
|
// IN pIMailMsgProperties mail msg object to get info from
|
|
// IN OUT pMsgInfo MESSAGE_INFO struct to dump data to
|
|
// Returns:
|
|
// S_OK on success
|
|
// AQUEUE_E_MESSAGE_HANDLED if the underlying message has been deleted
|
|
// E_OUTOFMEMORY if an allocation failure
|
|
// History:
|
|
// 8/8/00 - t-toddc created
|
|
// 12/11/2000 - MikeSwa Merged for checkin
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CAsyncAdminMailMsgQueue::HrGetQueueAdminMsgInfo(
|
|
IMailMsgProperties* pIMailMsgProperties,
|
|
MESSAGE_INFO* pMsgInfo,
|
|
PVOID pvContext)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) pIMailMsgProperties,
|
|
"CAsyncAdminMailMsgQueue::HrGetQueueAdminMsgInfo");
|
|
HRESULT hr = S_OK;
|
|
DWORD cbProp = 0;
|
|
DWORD cOpenHandlesForMsg = 0;
|
|
LPSTR szRecipients = NULL;
|
|
LPSTR szCCRecipients = NULL;
|
|
LPSTR szBCCRecipients = NULL;
|
|
FILETIME ftSubmitted = {0,0}; //Origination time property buffer
|
|
FILETIME ftQueueEntry = {0,0};
|
|
FILETIME ftExpire = {0,0};
|
|
DWORD cbMsgSize = 0;
|
|
CQueueAdminContext *pqapictx = (CQueueAdminContext *) pvContext;
|
|
|
|
|
|
_ASSERT(pIMailMsgProperties);
|
|
_ASSERT(pMsgInfo);
|
|
_ASSERT(pqapictx);
|
|
_ASSERT(pqapictx->fIsValid());
|
|
|
|
//
|
|
// If we have a context... it better be valid
|
|
//
|
|
if (pqapictx && !pqapictx->fIsValid()) {
|
|
_ASSERT(FALSE && "CQueueAdminContext is not valid");
|
|
pqapictx = NULL; //be defensive... don't use it.
|
|
}
|
|
|
|
//
|
|
// Check to see if the message is already open
|
|
//
|
|
hr = pIMailMsgProperties->GetDWORD(
|
|
IMMPID_MPV_MESSAGE_OPEN_HANDLES,
|
|
&cOpenHandlesForMsg);
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorTrace((LPARAM) pIMailMsgProperties, "Not running SP1 of W2K");
|
|
cOpenHandlesForMsg = 0;
|
|
hr = S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// Extract properties that are stored only on mailmsg (this is shared
|
|
// with all QAPI code).
|
|
//
|
|
hr = HrGetMsgInfoFromIMailMsgProperty(pIMailMsgProperties,
|
|
pMsgInfo);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
//can't report the number of failures from IMailMsgProperties
|
|
pMsgInfo->cFailures = 0;
|
|
|
|
//Get the size of the message
|
|
hr = HrQADMGetMsgSize(pIMailMsgProperties, &cbMsgSize);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
pMsgInfo->cbMessageSize = cbMsgSize;
|
|
|
|
//Get time message was queued
|
|
hr = pIMailMsgProperties->GetProperty(IMMPID_MP_ARRIVAL_FILETIME,
|
|
sizeof(FILETIME),
|
|
&cbProp,
|
|
(BYTE *) &ftQueueEntry);
|
|
if (FAILED(hr))
|
|
{
|
|
// there is a possibility that the msg will not have entry time
|
|
// (i.e. presubmission queue)
|
|
if (MAILMSG_E_PROPNOTFOUND == hr)
|
|
{
|
|
ZeroMemory(&ftQueueEntry, sizeof(FILETIME));
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
goto Exit;
|
|
}
|
|
|
|
//Get submission and expiration times
|
|
QueueAdminFileTimeToSystemTime(&ftQueueEntry,
|
|
&pMsgInfo->stReceived);
|
|
|
|
//Get the time the message entered the org
|
|
hr = pIMailMsgProperties->GetProperty(IMMPID_MP_ORIGINAL_ARRIVAL_TIME,
|
|
sizeof(FILETIME), &cbProp, (BYTE *) &ftSubmitted);
|
|
if (FAILED(hr))
|
|
{
|
|
//Time was not written... use entry time.
|
|
hr = S_OK;
|
|
memcpy(&ftSubmitted, &ftQueueEntry, sizeof(FILETIME));
|
|
}
|
|
|
|
QueueAdminFileTimeToSystemTime(&ftSubmitted, &pMsgInfo->stSubmission);
|
|
|
|
// Try to get the expire time from the message, otherwise calculate it
|
|
// from the file time
|
|
hr = pIMailMsgProperties->GetProperty(IMMPID_MP_LOCAL_EXPIRE_NDR,
|
|
sizeof(FILETIME), &cbProp, (BYTE *) &ftExpire);
|
|
if (MAILMSG_E_PROPNOTFOUND == hr)
|
|
{
|
|
if (pqapictx->paqinstGetAQ())
|
|
{
|
|
// Prop not set ... calculate it from the file time
|
|
pqapictx->paqinstGetAQ()->CalcExpireTimeNDR(ftQueueEntry, TRUE, &ftExpire);
|
|
|
|
// This is OK
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
// This shouldn't happen but we don't want to crash in RTL over it
|
|
_ASSERT(FALSE && "AQInst was not set in context!");
|
|
|
|
// We can return this field blank
|
|
ZeroMemory(&ftExpire, sizeof(FILETIME));
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
QueueAdminFileTimeToSystemTime(&ftExpire, &pMsgInfo->stExpiry);
|
|
|
|
//
|
|
// Get the state of the message
|
|
//
|
|
pMsgInfo->fMsgFlags = MP_NORMAL;
|
|
if (pqapictx)
|
|
{
|
|
if (LI_RETRY == pqapictx->lfGetQueueState())
|
|
pMsgInfo->fMsgFlags |= MP_MSG_RETRY;
|
|
else if (LI_FROZEN == pqapictx->lfGetQueueState())
|
|
pMsgInfo->fMsgFlags |= MP_MSG_FROZEN;
|
|
|
|
}
|
|
|
|
Exit:
|
|
|
|
//
|
|
// If this operation resulted in opening the message, we should close it
|
|
// The message is not dirty (we did not write anything), so it should not
|
|
// need to commit
|
|
//
|
|
if (!cOpenHandlesForMsg)
|
|
{
|
|
HRESULT hrTmp = S_OK;
|
|
hrTmp = HrReleaseIMailMsgUsageCount(pIMailMsgProperties);
|
|
if (SUCCEEDED(hrTmp))
|
|
HrIncrementIMailMsgUsageCount(pIMailMsgProperties);
|
|
}
|
|
|
|
TraceFunctLeave();
|
|
return hr;
|
|
}
|
|
|
|
|
|
//---[ CAsyncAdminMailMsgQueue::HrInternalQuerySupportedActions ]---------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns the actions and filters that this implementation supports
|
|
// Parameters:
|
|
// pdwSupportedActions - QAPI MsgActions that this queue suppprts
|
|
// pdwSupportedFilterFlags - QAPI filter flags that this queue supports
|
|
// Returns:
|
|
// S_OK on success
|
|
// History:
|
|
// 12/12/2000 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CAsyncAdminMailMsgQueue::HrInternalQuerySupportedActions(
|
|
DWORD *pdwSupportedActions,
|
|
DWORD *pdwSupportedFilterFlags)
|
|
{
|
|
TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrInternalQuerySupportedActions");
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = QueryDefaultSupportedActions(pdwSupportedActions, pdwSupportedFilterFlags);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
//
|
|
// This queue implementation does not support all of the default flags.
|
|
//
|
|
_ASSERT(pdwSupportedActions);
|
|
_ASSERT(pdwSupportedFilterFlags);
|
|
|
|
//
|
|
// We don't support:
|
|
// - Freeze global - No status to set on a mailmsg
|
|
// - Thaw global - can't freeze... therefore cannot thaw
|
|
//
|
|
*pdwSupportedActions &= ~(MA_FREEZE_GLOBAL | MA_THAW_GLOBAL);
|
|
|
|
//
|
|
// We don't support
|
|
// - Checking for frozen messages (we have no status to indicate
|
|
// that a message is frozen)
|
|
//
|
|
*pdwSupportedFilterFlags &= ~(MF_FROZEN);
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|