//----------------------------------------------------------------------------- // // // File: asyncadm.inl // // Description: // Implementation of CAsyncAdminQueue class. See header file for object // model // // Author: Mike Swafford (MikeSwa) // // History: // 12/7/2000 - MikeSwa Created // (pulled from asyncq.cpp and t-toddc's summer work) // // Copyright (C) 2000 Microsoft Corporation // //----------------------------------------------------------------------------- //---[ CAsyncAdminQueue::CAsyncAdminQueue ]------------------------------------ // // // Description: // Constructor for CAsyncRetryAdminMsgRefQueue // Parameters: // szDomain Domain name for this queue // pguid GUID for this queue // dwID Shedule ID for this queue // Returns: // - // History: // 2/23/99 - MikeSwa Created // //----------------------------------------------------------------------------- template CAsyncAdminQueue::CAsyncAdminQueue( LPCSTR szDomain, LPCSTR szLinkName, const GUID *pguid, DWORD dwID, CAQSvrInst *paqinst, typename CFifoQueue::MAPFNAPI pfnMessageAction) { _ASSERT(szDomain); _ASSERT(pguid); m_cbDomain = 0; m_szDomain = NULL; m_cbLinkName = 0; m_szLinkName = NULL; m_pAQNotify = NULL; m_paqinst = paqinst; m_pfnMessageAction = pfnMessageAction; _ASSERT(m_pfnMessageAction); if (szDomain) { m_cbDomain = lstrlen(szDomain); m_szDomain = (LPSTR) pvMalloc(m_cbDomain+1); if (m_szDomain) lstrcpy(m_szDomain, szDomain); } if (szLinkName) { m_cbLinkName = lstrlen(szLinkName); m_szLinkName = (LPSTR) pvMalloc(m_cbLinkName+1); } if (m_szLinkName) lstrcpy(m_szLinkName, szLinkName); if (pguid) memcpy(&m_guid, pguid, sizeof(GUID)); else ZeroMemory(&m_guid, sizeof(GUID)); m_dwID = dwID; } //---[ CAsyncAdminQueue::~CAsyncAdminQueue ]----------------------------------- // // // Description: // Destructor for CAsyncAdminQueue // Parameters: // - // Returns: // - // History: // 2/23/99 - MikeSwa Created // //----------------------------------------------------------------------------- template CAsyncAdminQueue::~CAsyncAdminQueue() { if (m_szDomain) FreePv(m_szDomain); if (m_szLinkName) FreePv(m_szLinkName); } //---[ CAsyncAdminQueue::HrInitialize ]---------------------------------------- // // // Description: // Wrapper for parent class HrInitialize... used to call set // CHandleManager // Parameters: // - // Returns: // - // History: // 5/18/2001 - MikeSwa Created // //----------------------------------------------------------------------------- template HRESULT CAsyncAdminQueue::HrInitialize( DWORD cMaxSyncThreads, DWORD cItemsPerATQThread, DWORD cItemsPerSyncThread, PVOID pvContext, QCOMPFN pfnQueueCompletion, QCOMPFN pfnFailedItem, typename CFifoQueue::MAPFNAPI pfnQueueFailure, DWORD cMaxPendingAsyncCompletions) { HRESULT hr = S_OK; hr = CAsyncRetryQueue::HrInitialize(cMaxSyncThreads, cItemsPerATQThread, cItemsPerSyncThread, pvContext, pfnQueueCompletion, pfnFailedItem, pfnQueueFailure, cMaxPendingAsyncCompletions); m_qhmgr.SetMaxConcurrentItems(s_cDefaultMaxAsyncThreads, cMaxSyncThreads); return hr; } //---[ CAsyncAdminQueue::QueryInterface ]--------------------------- // // // Description: // QueryInterface for CAsyncAdminQueue that supports: // - IQueueAdminAction // - IUnknown // - IQueueAdminQueue // Parameters: // // Returns: // // History: // 2/23/99 - MikeSwa Created // 12/7/2000 - MikeSwa Modified - Made template base class // //----------------------------------------------------------------------------- template STDMETHODIMP CAsyncAdminQueue::QueryInterface( REFIID riid, LPVOID *ppvObj) { HRESULT hr = S_OK; if (!ppvObj) { hr = E_POINTER; goto Exit; } if (IID_IUnknown == riid) { *ppvObj = static_cast(this); } else if (IID_IQueueAdminAction == riid) { *ppvObj = static_cast(this); } else if (IID_IQueueAdminQueue == riid) { *ppvObj = static_cast(this); } else { *ppvObj = NULL; hr = E_NOINTERFACE; goto Exit; } static_cast(*ppvObj)->AddRef(); Exit: return hr; } //---[ CAsyncAdminQueue::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. // Parameters: // IN pIQueueAdminMessageFilter // Returns: // S_OK on success // History: // 2/23/99 - MikeSwa Created // 12/7/2000 - MikeSwa Modified - Made template base class // //----------------------------------------------------------------------------- template STDMETHODIMP CAsyncAdminQueue::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; hr = HrMapFn(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; // // If we have thawed any messages we need to kick the retry queue to make sure // they get processed. // if (qapictx.cGetNumThawedMsgs()) StartRetry(); Exit: return hr; } //---[ CAsyncAdminQueue::HrApplyActionToMessage ]------------------- // // // Description: // Applies an action to this message for this queue. This will be called // by the IQueueAdminMessageFilter during a queue enumeration function. // 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 // History: // 2/23/99 - MikeSwa Created // 4/2/99 - MikeSwa Added context // 12/7/2000 - MikeSwa Modified - Made template base class // //----------------------------------------------------------------------------- template STDMETHODIMP CAsyncAdminQueue::HrApplyActionToMessage( IUnknown *pIUnknownMsg, MESSAGE_ACTION ma, PVOID pvContext, BOOL *pfShouldDelete) { TraceFunctEnterEx((LPARAM) this, "CAsyncAdminQueue::HrApplyActionToMessage"); HRESULT hr = S_OK; CQueueAdminContext *pqapictx = (CQueueAdminContext *) pvContext; CAQStats aqstats; CAQStats *paqstats = &aqstats; _ASSERT(pIUnknownMsg); _ASSERT(pfShouldDelete); // // 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. } *pfShouldDelete = FALSE; switch (ma) { case MA_DELETE: hr = HrDeleteMsgFromQueueNDR(pIUnknownMsg); *pfShouldDelete = TRUE; break; case MA_DELETE_SILENT: hr = HrDeleteMsgFromQueueSilent(pIUnknownMsg); *pfShouldDelete = TRUE; break; case MA_FREEZE_GLOBAL: hr = HrFreezeMsg(pIUnknownMsg); break; case MA_THAW_GLOBAL: hr = HrThawMsg(pIUnknownMsg); if (pqapictx) pqapictx->IncThawedMsgs(); break; case MA_COUNT: default: //do nothing for counting and default break; } // // If we are deleting the message, we need to tell the // link so we can have accurate stats for the link. // if (*pfShouldDelete && SUCCEEDED(hr)) { if (pqapictx) { hr = HrGetStatsForMsg(pIUnknownMsg, &aqstats); if (FAILED(hr)) { paqstats = NULL; ErrorTrace((LPARAM) this, "Unable to get Msg Stats0x%08X", hr); } pqapictx->NotifyMessageRemoved(paqstats); } } TraceFunctLeave(); return hr; } //---[ CAsyncAdminQueue::HrGetQueueInfo ]--------------------------- // // // Description: // Gets the Queue Admin info for this Queue // Parameters: // IN OUT pqiQueueInfo Ptr to Queue Info Stucture to fill // Returns: // S_OK on success // E_OUTOFMEMORY if unable to allocate memory for queue name. // History: // 2/23/99 - MikeSwa Created // 12/7/2000 - MikeSwa Modified - Made template base class // //----------------------------------------------------------------------------- template HRESULT CAsyncAdminQueue::HrGetQueueInfo(QUEUE_INFO *pqiQueueInfo) { HRESULT hr = S_OK; //Get # of messages pqiQueueInfo->cMessages = m_cItemsPending+m_cRetryItems; //Get Link name: Note that this class is used for special links like //local delivery queue... so there is no destination SMTP domain to //route to... therefore we need to return a special link name to admin. pqiQueueInfo->szLinkName = wszQueueAdminConvertToUnicode(m_szLinkName, m_cbLinkName); if (m_szDomain) { //Get Queue name pqiQueueInfo->szQueueName = wszQueueAdminConvertToUnicode(m_szDomain, m_cbDomain); if (!pqiQueueInfo->szQueueName) { hr = E_OUTOFMEMORY; goto Exit; } } //Currently setting this to zero since we do not calculate it pqiQueueInfo->cbQueueVolume.QuadPart = 0; pqiQueueInfo->dwMsgEnumFlagsSupported = AQUEUE_DEFAULT_SUPPORTED_ENUM_FILTERS; Exit: return hr; } //---[ CAsyncAdminMsgRefQueue::HrGetQueueID ]---------------------------------- // // // Description: // Gets the QueueID for this Queue. // Parameters: // IN OUT pQueueID QUEUELINK_ID struct to fill in // Returns: // S_OK on success // E_OUTOFMEMORY if unable to allocate memory for queue name. // History: // 2/23/99 - MikeSwa Created // 12/7/2000 - MikeSwa Modified - Made template base class // //----------------------------------------------------------------------------- template HRESULT CAsyncAdminQueue::HrGetQueueID( QUEUELINK_ID *pQueueID) { pQueueID->qltType = QLT_QUEUE; pQueueID->dwId = m_dwID; memcpy(&pQueueID->uuid, &m_guid, sizeof(GUID)); if (m_szDomain) { pQueueID->szName = wszQueueAdminConvertToUnicode(m_szDomain, m_cbDomain); if (!pQueueID->szName) return E_OUTOFMEMORY; } return S_OK; } //---[ CAsyncAdminQueue::fMatchesID ]------------------------------- // // // Description: // Used to determine if this link matches a given scheduleID/guid pair // Parameters: // IN QueueLinkID ID to match against // Returns: // TRUE if it matches // FALSE if it does not // History: // 2/23/99 - MikeSwa Created // 12/7/2000 - MikeSwa Modified - Made template base class // //----------------------------------------------------------------------------- template BOOL STDMETHODCALLTYPE CAsyncAdminQueue::fMatchesID(QUEUELINK_ID *pQueueLinkID) { _ASSERT(pQueueLinkID); if (!pQueueLinkID) return FALSE; if (0 != memcmp(&m_guid, &(pQueueLinkID->uuid), sizeof(GUID))) return FALSE; if (m_dwID != pQueueLinkID->dwId) return FALSE; //Don't need to check domain name since there is a special GUID to //identify the async queues. return TRUE; }