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.
698 lines
20 KiB
698 lines
20 KiB
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// File: fifqdbg.cpp
|
|
//
|
|
// Description: Implementation for CFifoQueueDbgIterator class.
|
|
//
|
|
// Author: Mike Swafford (MikeSwa)
|
|
//
|
|
// History:
|
|
// 9/13/99 - MikeSwa Created
|
|
//
|
|
// Copyright (C) 1999 Microsoft Corporation
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#define _ANSI_UNICODE_STRINGS_DEFINED_
|
|
#include "aqincs.h"
|
|
#ifdef PLATINUM
|
|
#include "ptrwinst.h"
|
|
#include "ptntdefs.h"
|
|
#include "ptntintf.h"
|
|
#else //PLATINUM
|
|
#include "rwinst.h"
|
|
#endif //PLATINUM
|
|
#include <fifoqdbg.h>
|
|
#include <fifoqimp.h>
|
|
#include <smtpconn.h>
|
|
|
|
#define MIN(x, y) ((x) > (y) ? (y) : (x))
|
|
|
|
//---[ GetQueueType ]----------------------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Determines the queue type for a given ptr
|
|
// Parameters:
|
|
// hCurrentProcess Handle to the debuggee process
|
|
// pvAddressOtherProc Addess of the DMQ in the debugee process
|
|
// Returns:
|
|
// AQ_QUEUE_TYPE_UNKNOWN Queue type cannot be determined
|
|
// AQ_QUEUE_TYPE_FIFOQ Queue is a CFifoQ
|
|
// AQ_QUEUE_TYPE_DMQ Queue is a CDestMsgQueue
|
|
// AQ_QUEUE_TYPE_LMQ Queue is a CLinkMsgQueue
|
|
// History:
|
|
// 10/21/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
AQ_QUEUE_TYPE CQueueDbgIterator::GetQueueType(HANDLE hCurrentProcess, PVOID pvAddressOtherProc)
|
|
{
|
|
BYTE pbQueueBuffer[100];
|
|
|
|
ZeroMemory(pbQueueBuffer, sizeof(pbQueueBuffer));
|
|
|
|
if (!ReadMemory(pvAddressOtherProc, pbQueueBuffer,
|
|
sizeof(pbQueueBuffer), NULL))
|
|
return AQ_QUEUE_TYPE_UNKNOWN;
|
|
|
|
if (FIFOQ_SIG == ((CFifoQueue<PVOID *> *)pbQueueBuffer)->m_dwSignature)
|
|
return AQ_QUEUE_TYPE_FIFOQ;
|
|
|
|
if (DESTMSGQ_SIG == ((CDestMsgQueue *)pbQueueBuffer)->m_dwSignature)
|
|
return AQ_QUEUE_TYPE_DMQ;
|
|
|
|
if (LINK_MSGQ_SIG == ((CLinkMsgQueue *)pbQueueBuffer)->m_dwSignature)
|
|
return AQ_QUEUE_TYPE_LMQ;
|
|
|
|
return AQ_QUEUE_TYPE_UNKNOWN;
|
|
}
|
|
|
|
|
|
|
|
#define pvGetNextPage(pvCurrent) ((PVOID) ((CFifoQueuePage<PVOID> *)pvCurrent)->m_pfqpNext)
|
|
|
|
CFifoQueueDbgIterator::CFifoQueueDbgIterator(PWINDBG_EXTENSION_APIS pApis)
|
|
{
|
|
m_iCurrentPage = 0;
|
|
m_iCurrentIndexInPage = 0;
|
|
m_cPagesLoaded = 0;
|
|
m_iHeadIndex = 0;
|
|
m_iTailIndex = 0;
|
|
pExtensionApis = pApis;
|
|
ZeroMemory(m_pbQueueBuffer, sizeof(m_pbQueueBuffer));
|
|
};
|
|
|
|
CFifoQueueDbgIterator::~CFifoQueueDbgIterator()
|
|
{
|
|
PVOID pvCurrent = NULL;
|
|
PVOID pvNext = NULL;
|
|
|
|
pvCurrent = ((CFifoQueue<PVOID> *)m_pbQueueBuffer)->m_pfqpHead;
|
|
while (pvCurrent)
|
|
{
|
|
pvNext = pvGetNextPage(pvCurrent);
|
|
free(pvCurrent);
|
|
pvCurrent = pvNext;
|
|
}
|
|
}
|
|
|
|
BOOL CFifoQueueDbgIterator::fInit(HANDLE hCurrentProcess, PVOID pvAddressOtherProc)
|
|
{
|
|
DWORD cbBytes = 0;
|
|
PVOID pvPageOtherProc = NULL;
|
|
PVOID pvPageThisProc = NULL;
|
|
PVOID pvPreviousPageThisProc = NULL;
|
|
|
|
//Read the entire queue structure in memory
|
|
if (!ReadMemory(pvAddressOtherProc, m_pbQueueBuffer,
|
|
sizeof(m_pbQueueBuffer), NULL))
|
|
return FALSE;
|
|
|
|
//Iterate over the previous pointers from the head page
|
|
pvPageOtherProc = ((CFifoQueue<PVOID> *)m_pbQueueBuffer)->m_pfqpHead;
|
|
|
|
((CFifoQueue<PVOID> *)m_pbQueueBuffer)->m_pfqpHead = NULL;
|
|
while (pvPageOtherProc)
|
|
{
|
|
pvPageThisProc = malloc(sizeof(CFifoQueuePage<PVOID>));
|
|
if (!pvPageThisProc)
|
|
return FALSE;
|
|
|
|
if (pvPreviousPageThisProc)
|
|
{
|
|
((CFifoQueuePage<PVOID> *)pvPreviousPageThisProc)->m_pfqpNext =
|
|
(CFifoQueuePage<PVOID> *) pvPageThisProc;
|
|
}
|
|
else
|
|
{
|
|
((CFifoQueue<PVOID> *)m_pbQueueBuffer)->m_pfqpHead =
|
|
(CFifoQueuePage<PVOID> *) pvPageThisProc;
|
|
}
|
|
|
|
|
|
if (!ReadMemory(pvPageOtherProc,
|
|
pvPageThisProc, sizeof(CFifoQueuePage<PVOID>), NULL))
|
|
{
|
|
if (pvPreviousPageThisProc)
|
|
((CFifoQueuePage<PVOID> *)pvPreviousPageThisProc)->m_pfqpNext = NULL;
|
|
else
|
|
((CFifoQueue<PVOID> *)m_pbQueueBuffer)->m_pfqpHead = NULL;
|
|
|
|
free(pvPageThisProc);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!pvPreviousPageThisProc)
|
|
{
|
|
//This is the head page. save index
|
|
m_iHeadIndex = (DWORD) ((DWORD_PTR)
|
|
(((CFifoQueue<PVOID> *)m_pbQueueBuffer)->m_ppqdataHead -
|
|
((CFifoQueuePage<PVOID> *)pvPageOtherProc)->m_rgpqdata));
|
|
|
|
m_iCurrentIndexInPage = m_iHeadIndex;
|
|
}
|
|
|
|
//save tail index... in case this is the last page
|
|
m_iTailIndex = (DWORD) ((DWORD_PTR)
|
|
(((CFifoQueue<PVOID> *)m_pbQueueBuffer)->m_ppqdataTail -
|
|
((CFifoQueuePage<PVOID> *)pvPageOtherProc)->m_rgpqdata));
|
|
|
|
pvPreviousPageThisProc = pvPageThisProc;
|
|
|
|
pvPageOtherProc = pvGetNextPage(pvPageThisProc);
|
|
((CFifoQueuePage<PVOID> *)pvPreviousPageThisProc)->m_pfqpNext = NULL;
|
|
m_cPagesLoaded++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD CFifoQueueDbgIterator::cGetCount()
|
|
{
|
|
return ((CFifoQueue<PVOID> *)m_pbQueueBuffer)->m_cQueueEntries;
|
|
}
|
|
|
|
PVOID CFifoQueueDbgIterator::pvGetNext()
|
|
{
|
|
PVOID pvCurrentPage = ((CFifoQueue<PVOID> *)m_pbQueueBuffer)->m_pfqpHead;
|
|
PVOID pvData = NULL;
|
|
DWORD i = 0;
|
|
|
|
if (!pvCurrentPage)
|
|
return NULL;
|
|
|
|
//Loop over empty entries (left by DSN generation) or until
|
|
//we reach the end of the queue
|
|
do
|
|
{
|
|
//Figure out if we are on a page boundary
|
|
if (FIFOQ_QUEUE_PAGE_SIZE == m_iCurrentIndexInPage)
|
|
{
|
|
m_iCurrentIndexInPage = 0;
|
|
m_iCurrentPage++;
|
|
}
|
|
|
|
//Get current page
|
|
for (i = 0; i < m_iCurrentPage; i++)
|
|
{
|
|
pvCurrentPage = pvGetNextPage(pvCurrentPage);
|
|
if (!pvCurrentPage)
|
|
return NULL;
|
|
}
|
|
|
|
if (!((CFifoQueuePage<PVOID> *)pvCurrentPage)->m_rgpqdata)
|
|
return NULL;
|
|
|
|
//Get data from current page
|
|
pvData = ((CFifoQueuePage<PVOID> *)pvCurrentPage)->m_rgpqdata[m_iCurrentIndexInPage];
|
|
|
|
if ((m_iCurrentIndexInPage > m_iTailIndex) && !pvGetNextPage(pvCurrentPage))
|
|
{
|
|
//We at the end of data
|
|
return NULL;
|
|
}
|
|
m_iCurrentIndexInPage++;
|
|
} while (!pvData);
|
|
|
|
return pvData;
|
|
}
|
|
|
|
|
|
//---[ CDMQDbgIterator ]-------------------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Constructor for CDMQDbgIterator
|
|
// Parameters:
|
|
// pApis A ptr to the PWINDBG_EXTENSION_APIS struct passed in by
|
|
// the debugger.
|
|
// Returns:
|
|
// -
|
|
// History:
|
|
// 10/21/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CDMQDbgIterator::CDMQDbgIterator(PWINDBG_EXTENSION_APIS pApis)
|
|
{
|
|
ZeroMemory(m_pbDMQBuffer, sizeof(m_pbDMQBuffer));
|
|
ZeroMemory(m_pvFifoQOtherProc, sizeof(m_pvFifoQOtherProc));
|
|
ZeroMemory(m_szName, sizeof(m_szName));
|
|
m_pdmq = (CDestMsgQueue *)m_pbDMQBuffer;
|
|
m_iCurrentFifoQ = 0;
|
|
m_cCount = 0;
|
|
pExtensionApis = pApis;
|
|
m_cItemsReturnedThisQueue = 0;
|
|
}
|
|
|
|
//---[ CDMQDbgIterator::fInit ]------------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Initializes the iterator (and the iterators for all its queues
|
|
// Parameters:
|
|
// hCurrentProcess Handle to the debuggee process
|
|
// pvAddressOtherProc Addess of the DMQ in the debugee process
|
|
// Returns:
|
|
// TRUE on success
|
|
// FALSE otherwise
|
|
// History:
|
|
// 10/21/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CDMQDbgIterator::fInit(HANDLE hCurrentProcess, PVOID pvAddressOtherProc)
|
|
{
|
|
DWORD i = 0;
|
|
PVOID pvQueue = NULL;
|
|
BOOL fVerbose = TRUE && pExtensionApis;
|
|
BYTE pbDomainEntry[sizeof(CDomainEntry)];
|
|
CDomainEntry *pdentry = (CDomainEntry *)pbDomainEntry;
|
|
|
|
if (!ReadMemory(pvAddressOtherProc, m_pbDMQBuffer,
|
|
sizeof(m_pbDMQBuffer), NULL))
|
|
{
|
|
if (fVerbose) dprintf("ReadMemory failex 0x%X\n", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
if (DESTMSGQ_SIG != m_pdmq->m_dwSignature)
|
|
{
|
|
if (fVerbose) dprintf("Bad signature\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//Get domain if possible
|
|
if (ReadMemory(m_pdmq->m_dmap.m_pdentryDomainID,
|
|
pbDomainEntry, sizeof(pbDomainEntry), NULL))
|
|
{
|
|
|
|
ReadMemory(pdentry->m_szDomainName, m_szName,
|
|
(DWORD)MIN((sizeof(m_szName)-1), (pdentry->m_cbDomainName+1)), NULL);
|
|
}
|
|
|
|
for (i = 0; i < NUM_PRIORITIES; i++)
|
|
{
|
|
m_rgfifoqdbg[i].SetApis(pExtensionApis);
|
|
pvQueue = m_pdmq->m_rgpfqQueues[i];
|
|
m_pvFifoQOtherProc[i] = pvQueue;
|
|
|
|
if (pvQueue)
|
|
{
|
|
if (!m_rgfifoqdbg[i].fInit(hCurrentProcess, pvQueue))
|
|
{
|
|
if (fVerbose) dprintf("Cannot init queue %d at 0x%X\n", i, pvQueue);
|
|
return FALSE;
|
|
}
|
|
m_cCount += m_rgfifoqdbg[i].cGetCount();
|
|
}
|
|
}
|
|
|
|
//Init retry queue
|
|
m_rgfifoqdbg[NUM_PRIORITIES].SetApis(pExtensionApis);
|
|
pvQueue = (((PBYTE)pvAddressOtherProc) + FIELD_OFFSET(CDestMsgQueue, m_fqRetryQueue));
|
|
m_pvFifoQOtherProc[NUM_PRIORITIES] = pvQueue;
|
|
|
|
if (pvQueue)
|
|
{
|
|
if (!m_rgfifoqdbg[NUM_PRIORITIES].fInit(hCurrentProcess, pvQueue))
|
|
{
|
|
if (fVerbose) dprintf("Cannon init retry queue at 0x%X\n", pvQueue);
|
|
return FALSE;
|
|
}
|
|
|
|
m_cCount += m_rgfifoqdbg[NUM_PRIORITIES].cGetCount();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//---[ CDMQDbgIterator::pvGetNext ]--------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Gets the next item from the DMQ
|
|
// Parameters:
|
|
// -
|
|
// Returns:
|
|
// An ptr to the item in the debuggee process on success
|
|
// NULL when there are no more items
|
|
// History:
|
|
// 10/21/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
PVOID CDMQDbgIterator::pvGetNext()
|
|
{
|
|
PVOID pvItem = NULL;
|
|
|
|
while (m_iCurrentFifoQ <= NUM_PRIORITIES)
|
|
{
|
|
if (m_pvFifoQOtherProc[m_iCurrentFifoQ])
|
|
{
|
|
if (m_rgfifoqdbg[m_iCurrentFifoQ].cGetCount())
|
|
{
|
|
pvItem = m_rgfifoqdbg[m_iCurrentFifoQ].pvGetNext();
|
|
|
|
//If we found an item we are done
|
|
if (pvItem)
|
|
{
|
|
//If it is the first item annouce this queue
|
|
if (!m_cItemsReturnedThisQueue && pExtensionApis)
|
|
{
|
|
dprintf("Dumping FifoQueue at address 0x%08X:\n",
|
|
m_pvFifoQOtherProc[m_iCurrentFifoQ]);
|
|
}
|
|
|
|
m_cItemsReturnedThisQueue++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
m_iCurrentFifoQ++;
|
|
m_cItemsReturnedThisQueue = 0;
|
|
}
|
|
|
|
return pvItem;
|
|
}
|
|
|
|
|
|
//---[ CQueueDbgIterator ]-----------------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Constructor for CQueueDbgIterator
|
|
// Parameters:
|
|
// pApis A ptr to the PWINDBG_EXTENSION_APIS struct passed in by
|
|
// the debugger.
|
|
// Returns:
|
|
// -
|
|
// History:
|
|
// 10/21/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CQueueDbgIterator::CQueueDbgIterator(PWINDBG_EXTENSION_APIS pApis)
|
|
{
|
|
pExtensionApis = pApis;
|
|
m_pqdbgi = NULL;
|
|
m_QueueType = AQ_QUEUE_TYPE_UNKNOWN;
|
|
}
|
|
|
|
//---[ CQueueDbgIterator::fInit ]----------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Initialized generic queue iterator. Will determine the type
|
|
// of queue and initialize the correct type-specific iterator.
|
|
// Parameters:
|
|
// hCurrentProcess Handle to the debuggee process
|
|
// pvAddressOtherProc Addess of the DMQ in the debugee process
|
|
// Returns:
|
|
// TRUE on success
|
|
// FALSE otherwise
|
|
// History:
|
|
// 10/21/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CQueueDbgIterator::fInit(HANDLE hCurrentProcess, PVOID pvAddressOtherProc)
|
|
{
|
|
LPSTR szQueueType = "unknown";
|
|
m_QueueType = GetQueueType(hCurrentProcess, pvAddressOtherProc);
|
|
|
|
switch (m_QueueType)
|
|
{
|
|
case AQ_QUEUE_TYPE_DMQ:
|
|
m_pqdbgi = (IQueueDbgIterator *) &m_dmqdbg;
|
|
szQueueType = "DMQ";
|
|
break;
|
|
case AQ_QUEUE_TYPE_FIFOQ:
|
|
m_pqdbgi = (IQueueDbgIterator *) &m_fifoqdbg;
|
|
szQueueType = "CFifoQueue";
|
|
break;
|
|
case AQ_QUEUE_TYPE_LMQ:
|
|
m_pqdbgi = (IQueueDbgIterator *) &m_lmqdbg;
|
|
szQueueType = "LMQ";
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
if (!m_pqdbgi)
|
|
return FALSE;
|
|
|
|
m_pqdbgi->SetApis(pExtensionApis);
|
|
if (!m_pqdbgi->fInit(hCurrentProcess, pvAddressOtherProc))
|
|
return FALSE;
|
|
|
|
if (pExtensionApis)
|
|
{
|
|
dprintf("Dumping %s (%s) at address 0x%08X:\n",
|
|
szQueueType, m_pqdbgi->szGetName(), pvAddressOtherProc);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//---[ CQueueDbgIterator::cGetCount ]------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns count of items in queue
|
|
// Parameters:
|
|
// -
|
|
// Returns:
|
|
// count of items in queue
|
|
// History:
|
|
// 10/21/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
DWORD CQueueDbgIterator::cGetCount()
|
|
{
|
|
if (!m_pqdbgi)
|
|
return 0;
|
|
else
|
|
return m_pqdbgi->cGetCount();
|
|
}
|
|
|
|
//---[ CQueueDbgIterator::pvGetNext ]------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns the next item pointed to by the iterator
|
|
// Parameters:
|
|
// -
|
|
// Returns:
|
|
// Pointer to next item in debugee process on success
|
|
// NULL if no more items or failure
|
|
// History:
|
|
// 10/21/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
PVOID CQueueDbgIterator::pvGetNext()
|
|
{
|
|
if (!m_pqdbgi)
|
|
return NULL;
|
|
else
|
|
return m_pqdbgi->pvGetNext();
|
|
}
|
|
|
|
//---[ CQueueDbgIterator::szGetName ]------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns the name of the iterator
|
|
// Parameters:
|
|
// -
|
|
// Returns:
|
|
// Pointer to string for iterator
|
|
// NULL if no name
|
|
// History:
|
|
// 10/22/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
LPSTR CQueueDbgIterator::szGetName()
|
|
{
|
|
if (!m_pqdbgi)
|
|
return NULL;
|
|
else
|
|
return m_pqdbgi->szGetName();
|
|
}
|
|
|
|
//---[ CLMQDbgIterator::CLMQDbgIterator ]--------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History:
|
|
// 10/22/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CLMQDbgIterator::CLMQDbgIterator(PWINDBG_EXTENSION_APIS pApis)
|
|
{
|
|
ZeroMemory(m_pbLMQBuffer, sizeof(m_pbLMQBuffer));
|
|
ZeroMemory(m_rgpvDMQOtherProc, sizeof(m_rgpvDMQOtherProc));
|
|
ZeroMemory(m_szName, sizeof(m_szName));
|
|
ZeroMemory(m_rgpvItemsPendingDelivery, sizeof(m_rgpvItemsPendingDelivery));
|
|
ZeroMemory(m_rgpvConnectionsOtherProc, sizeof(m_rgpvConnectionsOtherProc));
|
|
m_plmq = (CLinkMsgQueue *)m_pbLMQBuffer;
|
|
m_iCurrentDMQ = 0;
|
|
m_cCount = 0;
|
|
m_cItemsThisDMQ = 0;
|
|
m_cPending = 0;
|
|
pExtensionApis = pApis;
|
|
}
|
|
|
|
//---[ CLMQDbgIterator::fInit ]------------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Initializes iterator for CLinkMsgQueue
|
|
// Parameters:
|
|
// hCurrentProcess Handle to the debuggee process
|
|
// pvAddressOtherProc Addess of the DMQ in the debugee process
|
|
// Returns:
|
|
//
|
|
// History:
|
|
// 10/22/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CLMQDbgIterator::fInit(HANDLE hCurrentProcess, PVOID pvAddressOtherProc)
|
|
{
|
|
DWORD i = 0;
|
|
PLIST_ENTRY pliCurrent = NULL;
|
|
PLIST_ENTRY pliHead = NULL;
|
|
BYTE pbConnection[sizeof(CSMTPConn)];
|
|
CSMTPConn *pConn = (CSMTPConn *)pbConnection;
|
|
PVOID pvPending = NULL;
|
|
PVOID pvConnOtherProc = NULL;
|
|
BOOL fVerbose = TRUE && pExtensionApis;
|
|
|
|
if (!ReadMemory(pvAddressOtherProc, m_pbLMQBuffer,
|
|
sizeof(m_pbLMQBuffer), NULL))
|
|
{
|
|
if (fVerbose) dprintf("ReadMemory failex 0x%X\n", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
if (LINK_MSGQ_SIG != m_plmq->m_dwSignature)
|
|
{
|
|
if (fVerbose) dprintf("Signature does not match\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//Read in address of all the queues for this link
|
|
//$$TODO - Support more than 1 quick list
|
|
memcpy(m_rgpvDMQOtherProc, m_plmq->m_qlstQueues.m_rgpvData,
|
|
sizeof(m_rgpvDMQOtherProc));
|
|
|
|
//Read in name of link
|
|
ReadMemory(m_plmq->m_szSMTPDomain, m_szName,
|
|
(DWORD)MIN((sizeof(m_szName)-1), (m_plmq->m_cbSMTPDomain+1)), NULL);
|
|
|
|
for (i = 0; i < MAX_QUEUES_PER_LMQ; i++)
|
|
{
|
|
if (m_rgpvDMQOtherProc[i])
|
|
{
|
|
m_rgdmqdbg[i].SetApis(pExtensionApis);
|
|
if (!m_rgdmqdbg[i].fInit(hCurrentProcess, m_rgpvDMQOtherProc[i]))
|
|
{
|
|
if (fVerbose)
|
|
dprintf("Unable to init DMQ at 0x%X\n", m_rgpvDMQOtherProc[i]);
|
|
return FALSE;
|
|
}
|
|
m_cCount += m_rgdmqdbg[i].cGetCount();
|
|
}
|
|
}
|
|
|
|
//Get the messages pending on a connection
|
|
|
|
pliCurrent = m_plmq->m_liConnections.Flink;
|
|
|
|
//Loop through connections and save those with pending messages.
|
|
while (pliHead != pliCurrent)
|
|
{
|
|
pvConnOtherProc = ((PBYTE) pliCurrent)-FIELD_OFFSET(CSMTPConn, m_liConnections);
|
|
if (!ReadMemory(pvConnOtherProc, pbConnection,
|
|
sizeof(pbConnection), NULL))
|
|
{
|
|
break;
|
|
}
|
|
pliCurrent = pConn->m_liConnections.Flink;
|
|
if (!pliHead)
|
|
pliHead = pConn->m_liConnections.Blink;
|
|
|
|
pvPending = pConn->m_dcntxtCurrentDeliveryContext.m_pmsgref;
|
|
if (pvPending)
|
|
{
|
|
m_rgpvConnectionsOtherProc[m_cPending] = pvConnOtherProc;
|
|
m_rgpvItemsPendingDelivery[m_cPending] = pvPending;
|
|
m_cPending++;
|
|
m_cCount++;
|
|
}
|
|
if (m_cPending >= MAX_CONNECTIONS_PER_LMQ)
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//---[ CLMQDbgIterator::pvGetNext ]--------------------------------------------
|
|
//
|
|
//
|
|
// Description:
|
|
// Gets the next item in the current DMQ. Moves to next DMQ when that
|
|
// is emtpy
|
|
// Parameters:
|
|
// -
|
|
// Returns:
|
|
// Next item on success
|
|
// NULL when empty or failure
|
|
// History:
|
|
// 10/22/1999 - MikeSwa Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
PVOID CLMQDbgIterator::pvGetNext()
|
|
{
|
|
PVOID pvItem = NULL;
|
|
|
|
while (m_iCurrentDMQ < MAX_QUEUES_PER_LMQ)
|
|
{
|
|
if (m_rgpvDMQOtherProc[m_iCurrentDMQ])
|
|
{
|
|
if (!m_cItemsThisDMQ && m_rgdmqdbg[m_iCurrentDMQ].cGetCount())
|
|
{
|
|
if (pExtensionApis)
|
|
{
|
|
dprintf("Dumping DMQ (%s) at address 0x%08X:\n",
|
|
m_rgdmqdbg[m_iCurrentDMQ].szGetName(),
|
|
m_rgpvDMQOtherProc[m_iCurrentDMQ]);
|
|
}
|
|
}
|
|
pvItem = m_rgdmqdbg[m_iCurrentDMQ].pvGetNext();
|
|
if (pvItem)
|
|
{
|
|
//Check if this is the first item for this DMQ
|
|
m_cItemsThisDMQ++;
|
|
break;
|
|
}
|
|
}
|
|
m_iCurrentDMQ++;
|
|
m_cItemsThisDMQ = 0;
|
|
}
|
|
|
|
//If the queues are empty, dump the connections
|
|
if (!pvItem && m_cPending)
|
|
{
|
|
m_cPending--;
|
|
if (pExtensionApis)
|
|
{
|
|
dprintf("Dumping Connection at address 0x%08X:\n",
|
|
m_rgpvConnectionsOtherProc[m_cPending]);
|
|
}
|
|
pvItem = m_rgpvItemsPendingDelivery[m_cPending];
|
|
}
|
|
return pvItem;
|
|
}
|
|
|
|
|