windows-nt/Source/XPSP1/NT/printscan/print/spooler/exts/spllib.cxx
2020-09-26 16:20:57 +08:00

495 lines
12 KiB
C++

/*++
Copyright (c) 1995 Microsoft Corporation
All rights reserved.
Module Name:
spllib.cxx
Abstract:
Extensions for spllib
Author:
Albert Ting (AlbertT) 20-Feb-1995
Revision History:
--*/
#include "precomp.hxx"
/********************************************************************
Helper routines
********************************************************************/
#if !DBG
#error "Only the debug version should be built."
#endif
BOOL
TDebugExt::
bDumpThreadM(
PVOID pThreadM_,
ULONG_PTR dwAddr
)
{
TThreadM* pThreadM = (TThreadM*)pThreadM_;
static DEBUG_FLAGS DebugFlags[] = {
{ "DESTROYED_REQ" , 1 },
{ "DESTROYED" , 2 },
{ "PRIVATE_CRIT_SEC", 4 }
};
if( !pThreadM->bSigCheck( )){
return FALSE;
}
Print( "TThreadM*\n" );
Print( " uMaxThreads <%d>\n", pThreadM->_uMaxThreads );
Print( " uIdleLife <%d>\n", pThreadM->_uIdleLife );
Print( "uActiveThreads <%d>\n", pThreadM->_uActiveThreads );
Print( " iIdleThreads <%d>\n", pThreadM->_iIdleThreads );
Print( " hTrigger %x\n", pThreadM->_hTrigger );
Print( " State %x %x\n", (ULONG_PTR)pThreadM->_State, &pThreadM->_State );
Print( " pCritSec %x\n", pThreadM->_pCritSec );
return TRUE;
}
BOOL
TDebugExt::
bDumpCritSec(
PVOID pCritSec_,
ULONG_PTR dwAddr
)
{
MCritSec* pCritSec = (MCritSec*)pCritSec_;
if( !pCritSec->bSigCheck( )){
return FALSE;
}
Print( "MCritSec*\n" );
Print( " CriticalSection @ %x\n", dwAddr + OFFSETOF( MCritSec, _CritSec ));
Print( " dwThreadOwner %x\n", pCritSec->_dwThreadOwner );
Print( " dwEntryCount <%d> ", pCritSec->_dwEntryCount );
if( pCritSec->_dwEntryCount ){
Print( "Owned\n" );
} else {
Print( "Not Owned\n" );
}
Print( "dwTickCountEntered <%d>\n", pCritSec->_dwTickCountEntered );
Print( "==== Statistics\n" );
Print( " dwTickCountBlockedTotal <%d>\n", pCritSec->_dwTickCountBlockedTotal );
Print( " dwTickCountInsideTotal <%d>\n", pCritSec->_dwTickCountInsideTotal );
Print( " dwEntryCountTotal <%d>\n", pCritSec->_dwEntryCountTotal );
Print( " CritSecHardLock_base " ); vDumpPDL( pCritSec->CritSecHardLock_pdlBase( ));
ULONG_PTR dwAddrBt = dwAddr + OFFSETOF( MCritSec, _BackTrace )
- OFFSETOF_BASE( TBackTraceMem, VBackTrace );
Print( " VBackTrace @ %x !splx.ddt -x %x\n",
dwAddrBt, dwAddrBt );
return TRUE;
}
BOOL
TDebugExt::
bDumpBackTrace(
ULONG_PTR dwAddr,
COUNT Count,
PDWORD pdwSkip,
DWORD DebugTrace,
DWORD DebugLevel,
DWORD dwThreadId,
ULONG_PTR dwMem
)
{
#ifdef TRACE_ENABLED
BYTE abyBackTraceBuffer[sizeof(TBackTraceMem)];
TBackTraceMem* pBackTraceMem = (TBackTraceMem*)abyBackTraceBuffer;
move2( pBackTraceMem, dwAddr, sizeof( TBackTraceMem ));
if( !pBackTraceMem->bSigCheck( )){
return FALSE;
}
INT iLineStart = pBackTraceMem->_uNextFree;
INT iLine;
if( iLineStart < 0 ){
iLineStart = TBackTraceMem::kMaxCall - 1;
}
for( iLine = iLineStart - 1; Count; --iLine, --Count ){
if( CheckControlCRtn()){
return TRUE;
}
//
// Handle wrap around case.
//
if( iLine < 0 ){
iLine = TBackTraceMem::kMaxCall - 1;
}
if( iLine == iLineStart ||
!TDebugExt::bDumpDebugTrace( (ULONG_PTR)&pBackTraceMem->_pLines[iLine],
1,
pdwSkip,
DebugTrace,
DebugLevel,
dwThreadId,
dwMem )){
//
// Wrapped around yet didn't find enough.
//
Print( "Out of lines\n" );
return TRUE;
}
}
return TRUE;
#else // #ifdef TRACE_ENABLED
return FALSE;
#endif // #ifdef TRACE_ENABLED
}
BOOL
TDebugExt::
bDumpDebugTrace(
ULONG_PTR dwLineAddr,
COUNT Count,
PDWORD pdwSkip,
DWORD DebugTrace,
DWORD DebugLevel,
DWORD dwThreadId,
ULONG_PTR dwMem
)
{
//
// TLine is a simple class, and can be treated as a "C" struct.
//
COUNTB cbTotalLine = sizeof( TBackTraceMem::TLine ) * Count;
TBackTraceMem::TLine* pLineBase =
(TBackTraceMem::TLine*) LocalAlloc( LPTR, cbTotalLine );
BOOL bValidLines = TRUE;
TBackTraceMem::TLine* pLine;
if( !pLineBase ){
Print( "Cannot alloc 0x%x bytes.\n", cbTotalLine );
return FALSE;
}
move2( pLineBase, dwLineAddr, cbTotalLine );
//
// Dump out the lines.
//
for( pLine = pLineBase ; Count; Count--, pLine++ ){
if( CheckControlCRtn()){
goto Done;
}
//
// If we are out of lines, quit.
//
if( !pLine->_TickCount ){
bValidLines = FALSE;
goto Done;
}
//
// If we are processing DBGMSG, skip levels we don't want.
//
if( DebugTrace & DEBUG_TRACE_DBGMSG ){
if( !( DebugLevel & ( pLine->_Info2 >> DBG_BREAK_SHIFT ))){
continue;
}
}
//
// Skip thread Ids we don't want.
//
if( dwThreadId && dwThreadId != pLine->_ThreadId ){
continue;
}
//
// Skip mem we don't want.
// This is used when we are dumping the memory functions in
// spllib (gpbtAlloc and gpbtFree).
//
if( dwMem &&
( dwMem < pLine->_Info1 ||
dwMem > pLine->_Info1 + pLine->_Info2 )){
continue;
}
if( *pdwSkip ){
--*pdwSkip;
continue;
}
if( DebugTrace & DEBUG_TRACE_DBGMSG ){
CHAR szMsg[kStringDefaultMax];
szMsg[0] = 0;
if( pLine->_Info1 ){
move( szMsg, pLine->_Info1 );
//
// PageHeap forces all allocated blocks to be placed
// at the end of a page, with the next page marked
// as unreadable. If we don't get a string here,
// then read up chunk.
//
if( !szMsg[0] ){
move2( szMsg,
pLine->_Info1,
kStringChunk -
( (DWORD)pLine->_Info1 & ( kStringChunk - 1 )));
}
Print( "* %s", szMsg );
UINT cchLen = lstrlenA( szMsg );
if( !cchLen || szMsg[cchLen-1] != '\n' ){
Print( "\n" );
}
} else {
Print( "\n" );
}
}
if( DebugTrace & DEBUG_TRACE_HEX ){
Print( "%08x %08x %08x bt=%x threadid=%x tc=%x [%x]\n",
pLine->_Info1,
pLine->_Info2,
pLine->_Info3,
pLine->_hTrace,
pLine->_ThreadId,
pLine->_TickCount,
pLine->_Info1 + pLine->_Info2 );
}
if( DebugTrace & DEBUG_TRACE_BT ){
vDumpTrace( (ULONG_PTR)pLine->_hTrace );
}
}
Done:
LocalFree( pLineBase );
return bValidLines;
}
BOOL
TDebugExt::
bDumpDbgPointers(
PVOID pDbgPointers_,
ULONG_PTR dwAddress
)
{
PDBG_POINTERS pDbgPointers = (PDBG_POINTERS)pDbgPointers_;
Print( "DBG_POINTERS*\n" );
Print( "hMemHeap !heap -a %x\n", pDbgPointers->hMemHeap );
Print( "hDbgMemHeap !heap -a %x\n", pDbgPointers->hDbgMemHeap );
Print( "pbtAlloc !splx.ddt -x %x\n", pDbgPointers->pbtAlloc );
Print( "pbtFree !splx.ddt -x %x\n", pDbgPointers->pbtFree );
Print( "pbtErrLog !splx.ddt %x\n", pDbgPointers->pbtErrLog );
Print( "pbtTraceLog !splx.ddt %x\n", pDbgPointers->pbtTraceLog );
return TRUE;
}
/********************************************************************
Extension entrypoints.
********************************************************************/
DEBUG_EXT_ENTRY( dthdm, TThreadM, bDumpThreadM, NULL, FALSE )
DEBUG_EXT_ENTRY( dcs, MCritSec, bDumpCritSec, NULL, FALSE )
DEBUG_EXT_ENTRY( ddp, DBG_POINTERS, bDumpDbgPointers, "&gpDbgPointers", FALSE )
DEBUG_EXT_HEAD(dbt)
{
DEBUG_EXT_SETUP_VARS();
TDebugExt::vDumpTrace( TDebugExt::dwEval( lpArgumentString, FALSE ));
}
DEBUG_EXT_HEAD(ddt)
{
DEBUG_EXT_SETUP_VARS();
vDumpTraceWithFlags( lpArgumentString, 0 );
}
DEBUG_EXT_HEAD(dmem)
{
DEBUG_EXT_SETUP_VARS();
TDebugExt::vDumpMem( lpArgumentString );
}
/********************************************************************
Helper funcs.
********************************************************************/
VOID
vDumpTraceWithFlags(
LPSTR lpArgumentString,
ULONG_PTR dwAddress
)
{
COUNT Count = 10;
BOOL bRaw = FALSE;
DWORD DebugTrace = DEBUG_TRACE_NONE;
DWORD DebugLevel = (DWORD)-1;
DWORD dwThreadId = 0;
DWORD dwSkip = 0;
ULONG_PTR dwMem = 0;
for( ; *lpArgumentString; ++lpArgumentString ){
while( *lpArgumentString == ' ' ){
++lpArgumentString;
}
if (*lpArgumentString != '-') {
break;
}
++lpArgumentString;
switch( *lpArgumentString++ ){
case 'T':
case 't':
dwThreadId = (DWORD)TDebugExt::dwEvalParam( lpArgumentString );
break;
case 'L':
case 'l':
DebugLevel = (DWORD)TDebugExt::dwEvalParam( lpArgumentString );
break;
case 'C':
case 'c':
Count = (COUNT)TDebugExt::dwEvalParam( lpArgumentString );
break;
case 'M':
case 'm':
dwMem = TDebugExt::dwEvalParam( lpArgumentString );
break;
case 'R':
case 'r':
bRaw = TRUE;
break;
case 'b':
case 'B':
DebugTrace |= DEBUG_TRACE_BT;
break;
case 'X':
case 'x':
DebugTrace |= DEBUG_TRACE_HEX;
break;
case 'd':
case 'D':
DebugTrace |= DEBUG_TRACE_DBGMSG;
break;
case 's':
case 'S':
dwSkip = (DWORD)TDebugExt::dwEvalParam( lpArgumentString );
break;
default:
Print( "Unknown option %c.\n", lpArgumentString[-1] );
return;
}
}
if( !dwAddress ){
dwAddress = TDebugExt::dwEval( lpArgumentString );
}
if( bRaw ){
TDebugExt::bDumpDebugTrace( dwAddress,
Count,
&dwSkip,
DebugTrace,
DebugLevel,
dwThreadId,
dwMem );
return;
}
//
// If nothing is set, default to dbg msgs.
//
if( !DebugTrace ){
DebugTrace |= DEBUG_TRACE_DBGMSG;
}
if( !TDebugExt::bDumpBackTrace( dwAddress,
Count,
&dwSkip,
DebugTrace,
DebugLevel,
dwThreadId,
dwMem )){
Print( "Unknown Signature\n" );
}
}