Leaked source code of windows server 2003
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.
 
 
 
 
 
 

389 lines
11 KiB

//-----------------------------------------------------------------------------
//
//
// File: localq.cpp
//
// Description: Implementation for local admin queues
//
// Author: Mike Swafford (MikeSwa)
//
// History:
// 2/23/99 - MikeSwa Created
//
// Copyright (C) 1999 Microsoft Corporation
//
//-----------------------------------------------------------------------------
#include "aqprecmp.h"
#include "localq.h"
#include "aqadmsvr.h"
#include "asyncq.inl"
//---[ CLocalLinkMsgQueue::CLocalLinkMsgQueue ]---------------------------------
//
//
// Description:
// Default constructor for CLocalLinkMsgQueue
// Parameters:
// IN paradmq Local async queue
// IN guidLink Router GUID to associate with this link
// IN paqinst CAQSvrInst for VSI
// Returns:
// -
// History:
// 2/23/99 - MikeSwa Created
//
//-----------------------------------------------------------------------------
CLocalLinkMsgQueue::CLocalLinkMsgQueue(
CAsyncAdminMsgRefQueue *paradmq,
GUID guidLink, CAQSvrInst *paqinst) : CLinkMsgQueue(guidLink)
{
TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::CLocalLinkMsgQueue");
//Initialize superclass with our own special GUID
_ASSERT(paradmq);
m_paradmq = paradmq;
m_dwLocalLinkSig = LOCAL_LINK_MSG_QUEUE_SIG;
m_AQNotify.Init(paqinst, (CLinkMsgQueue *) this);
m_paradmq->SetAQNotify(&m_AQNotify);
TraceFunctLeave();
}
#ifdef NEVER
//---[ CLinkMsgQueue::fSameNextHop ]-------------------------------------------
//
//
// Description:
// Used to determine if this link matches a given scheduleID/link pair
// Parameters:
// IN paqsched ScheduleID to check against
// IN szDomain Domain name to check against
// Returns:
// TRUE if it matches
// FALSE if it does not
// History:
// 2/23/99 - MikeSwa Created
//
//-----------------------------------------------------------------------------
BOOL CLocalLinkMsgQueue::fSameNextHop(CAQScheduleID *paqsched, LPSTR szDomain)
{
TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::fSameNextHop");
_ASSERT(paqsched);
if (!paqsched)
return FALSE;
if (!fIsSameScheduleID(paqsched))
return FALSE;
//Don't need to check domain name since there is a special GUID to
//identify the local link. This will allow us to match both
//"LocalLink" (returned in LinkID) and whatever the current value of
//the default domain is (we don't have to worry about the clients
//version becoming outdated).
//Everything matched!
TraceFunctLeave();
return TRUE;
}
#endif //NEVER
//---[ CLocalLinkMsgQueue::fMatchesID ]--------------------------------------
//
//
// Description:
// Used to determine if this link matches a given scheduleID/link pair
// Parameters:
// IN QueueLinkID ID to match against
// Returns:
// TRUE if it matches
// FALSE if it does not
// History:
// 2/23/99 - MikeSwa Created
//
//-----------------------------------------------------------------------------
BOOL STDMETHODCALLTYPE CLocalLinkMsgQueue::fMatchesID(QUEUELINK_ID *pQueueLinkID)
{
_ASSERT(pQueueLinkID);
CAQScheduleID aqsched(pQueueLinkID->uuid, pQueueLinkID->dwId);
if (!fIsSameScheduleID(&aqsched))
return FALSE;
//Don't need to check domain name since there is a special GUID to
//identify the local link. This will allow us to match both
//"LocalLink" (returned in LinkID) and whatever the current value of
//the default domain is (we don't have to worry about the clients
//version becoming outdated).
//Everything matched!
return TRUE;
}
//---[ CLocalLinkMsgQueue::HrApplyQueueAdminFunction ]-------------------------
//
//
// Description:
// Used by queue admin to apply a function all queues on this link
// Parameters:
// IN pIQueueAdminMessageFilter
// Returns:
// S_OK on success
// History:
// 2/23/99 - MikeSwa Created
//
//-----------------------------------------------------------------------------
STDMETHODIMP CLocalLinkMsgQueue::HrApplyQueueAdminFunction(
IQueueAdminMessageFilter *pIQueueAdminMessageFilter)
{
TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::HrApplyQueueAdminFunction");
HRESULT hr = S_OK;
hr = CLinkMsgQueue::HrApplyQueueAdminFunction(pIQueueAdminMessageFilter);
if (FAILED(hr))
goto Exit;
_ASSERT(m_paradmq);
hr = m_paradmq->HrApplyQueueAdminFunction(pIQueueAdminMessageFilter);
if (FAILED(hr))
goto Exit;
Exit:
TraceFunctLeave();
return hr;
}
//---[ CLocalLinkMsgQueue::HrGetLinkInfo ]-------------------------------------
//
//
// Description:
// Fills in the details for a LINK_INFO struct. RPC is resonsible for
// freeing memory.
// Parameters:
// IN OUT pliLinkInfo Ptr to link info struct to fill
// Returns:
// S_OK if successful
// E_OUTOFMEMORY if unable to allocate memory
// History:
// 2/23/99 - MikeSwa Created
// 7/1/99 - MikeSwa Added LinkDiagnostic
//
//-----------------------------------------------------------------------------
STDMETHODIMP CLocalLinkMsgQueue::HrGetLinkInfo(LINK_INFO *pliLinkInfo,
HRESULT *phrLinkDiagnostic)
{
TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::HrApplyQueueAdminFunction");
HRESULT hr = S_OK;
CRefCountedString *prstrDefaultDomain = NULL;
hr = CLinkMsgQueue::HrGetLinkInfo(pliLinkInfo, phrLinkDiagnostic);
QUEUE_INFO qi;
FILETIME *pft = NULL;
_ASSERT(m_paradmq);
//
// Get our queue state from our base asyncq implementation
//
pliLinkInfo->fStateFlags = m_paradmq->dwQueueAdminLinkGetLinkState();
//
// If we are in retry, update our next scheduled connection
//
if (LI_RETRY & pliLinkInfo->fStateFlags)
QueueAdminFileTimeToSystemTime(&m_ftNextRetry, &(pliLinkInfo->stNextScheduledConnection));
//This is the local link
pliLinkInfo->fStateFlags |= LI_TYPE_LOCAL_DELIVERY;
if (m_paqinst)
prstrDefaultDomain = m_paqinst->prstrGetDefaultDomain();
//Copy Default local domain name instead of "LocalLink"
if (prstrDefaultDomain &&
prstrDefaultDomain->cbStrlen() &&
prstrDefaultDomain->szStr())
{
if (pliLinkInfo->szLinkName)
{
QueueAdminFree(pliLinkInfo->szLinkName);
pliLinkInfo->szLinkName = NULL;
}
pliLinkInfo->szLinkName = wszQueueAdminConvertToUnicode(
prstrDefaultDomain->szStr(),
prstrDefaultDomain->cbStrlen());
if (!pliLinkInfo->szLinkName)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
pliLinkInfo->szLinkName[prstrDefaultDomain->cbStrlen()] = '\0';
}
//Get the queue info from the local queue for size totals
ZeroMemory(&qi, sizeof(QUEUE_INFO));
hr = m_paradmq->HrGetQueueInfo(&qi);
if (FAILED(hr))
goto Exit;
//Clean up allocated stuff
if (qi.szQueueName)
QueueAdminFree(qi.szQueueName);
if (qi.szLinkName)
QueueAdminFree(qi.szLinkName);
Exit:
if (prstrDefaultDomain)
prstrDefaultDomain->Release();
TraceFunctLeave();
return hr;
}
//---[ CLocalLinkMsgQueue::HrApplyActionToLink ]-------------------------------
//
//
// Description:
// Applies the specified QueueAdmin action to this link
// Parameters:
// IN la Link action to apply
// Returns:
// S_OK on success
// E_INVALIDARG if bogus action is given
// History:
// 2/23/99 - MikeSwa Created
//
//-----------------------------------------------------------------------------
STDMETHODIMP CLocalLinkMsgQueue::HrApplyActionToLink(LINK_ACTION la)
{
TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::HrApplyQueueAdminFunction");
HRESULT hr = S_OK;
//It is important to release that it does not make sense to re-apply these
//actions back to the LMQ, becuase it is actually the CAsyncRetryQueue
//that affects the state of this.
_ASSERT(m_paradmq);
if (LA_KICK == la)
{
//kick the link
m_paradmq->StartRetry();
}
else if (LA_FREEZE == la)
{
//Admin wants this link to stop sending mail inbound to the store
m_paradmq->FreezeQueue();
}
else if (LA_THAW == la)
{
//Thaw that which was previously frozen
m_paradmq->ThawQueue();
}
else
{
//invalid arg
hr = E_INVALIDARG;
goto Exit;
}
Exit:
TraceFunctLeave();
return hr;
}
//---[ CLocalLinkMsgQueue::HrGetNumQueues ]------------------------------------
//
//
// Description:
// Returns the number of queues on this link
// Parameters:
// OUT pcQueues # numbr of queues
// Returns:
// S_OK on success
// E_POINTER if pcQueues is not valid
// History:
// 2/23/99 - MikeSwa Created
//
//-----------------------------------------------------------------------------
STDMETHODIMP CLocalLinkMsgQueue::HrGetNumQueues(DWORD *pcQueues)
{
TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::HrApplyQueueAdminFunction");
HRESULT hr = S_OK;
hr = CLinkMsgQueue::HrGetNumQueues(pcQueues);
if (SUCCEEDED(hr))
{
_ASSERT(pcQueues);
(*pcQueues)++; //Add extra count for local async queue
}
TraceFunctLeave();
return hr;
}
//---[ CLinkMsgQueue::HrGetQueueIDs ]--------------------------------------------
//
//
// Description:
// Gets the Queue IDs for DMQs associated with this link. Used by Queue
// Admin.
// Parameters:
// IN OUT pcQueues Sizeof array/ number of queues found
// IN OUT rgQueues Array to dump queue info into
// Returns:
// S_OK on success
// E_OUTOFMEMORY on out of memory failure
// HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) if array is too small
// History:
// 2/23/99 - MikeSwa Created
//
//-----------------------------------------------------------------------------
STDMETHODIMP CLocalLinkMsgQueue::HrGetQueueIDs(
DWORD *pcQueues,
QUEUELINK_ID *rgQueues)
{
TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::HrApplyQueueAdminFunction");
_ASSERT(pcQueues);
_ASSERT(rgQueues);
HRESULT hr = S_OK;
//Check to make sure we have room for the additional queue ID
if (*pcQueues < (m_cQueues+1))
{
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
goto Exit;
}
//Make sure that thread-safe check in CLinkMsgQueue allows room
//for our local queue.
(*pcQueues)--;
hr = CLinkMsgQueue::HrGetQueueIDs(pcQueues, rgQueues);
if (FAILED(hr))
{
//Tell caller we need room for our queue as well
if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
(*pcQueues)++;
goto Exit;
}
hr = m_paradmq->HrGetQueueID(&rgQueues[*pcQueues]);
if (FAILED(hr))
goto Exit;
(*pcQueues)++;
Exit:
TraceFunctLeave();
return hr;
}