mirror of https://github.com/lianthony/NT4.0
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.
338 lines
7.0 KiB
338 lines
7.0 KiB
/**********************************************************************/
|
|
/** Microsoft Windows NT **/
|
|
/** Copyright(c) Microsoft Corp., 1993 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
debug.c
|
|
|
|
This module contains debug support routines for the FTPD Service.
|
|
|
|
|
|
FILE HISTORY:
|
|
KeithMo 07-Mar-1993 Created.
|
|
|
|
*/
|
|
|
|
|
|
#include "ftpdp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
#if DBG
|
|
|
|
//
|
|
// Private constants.
|
|
//
|
|
|
|
#define MAX_PRINTF_OUTPUT 1200 // characters
|
|
#define FTPD_OUTPUT_LABEL "FTPD"
|
|
|
|
#define DEBUG_HEAP 0 // enable/disable heap debugging
|
|
|
|
|
|
//
|
|
// Private types.
|
|
//
|
|
|
|
|
|
//
|
|
// Private globals.
|
|
//
|
|
|
|
#if DEBUG_HEAP
|
|
DEBUG_HEAP_HEADER * pDebugHeap; // Pool of allocated blocks.
|
|
#endif // DEBUG_HEAP
|
|
|
|
|
|
//
|
|
// Public functions.
|
|
//
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: FtpdAssert
|
|
|
|
SYNOPSIS: Called if an assertion fails. Displays the failed
|
|
assertion, file name, and line number. Gives the
|
|
user the opportunity to ignore the assertion or
|
|
break into the debugger.
|
|
|
|
ENTRY: pAssertion - The text of the failed expression.
|
|
|
|
pFileName - The containing source file.
|
|
|
|
nLineNumber - The guilty line number.
|
|
|
|
HISTORY:
|
|
KeithMo 07-Mar-1993 Created.
|
|
|
|
********************************************************************/
|
|
VOID
|
|
FtpdAssert(
|
|
VOID * pAssertion,
|
|
VOID * pFileName,
|
|
LONG nLineNumber
|
|
)
|
|
{
|
|
CHAR szOutput[MAX_PRINTF_OUTPUT];
|
|
|
|
sprintf( szOutput,
|
|
"\n*** Assertion failed: %s\n*** Source File: %s, line %ld\n\n",
|
|
pAssertion,
|
|
pFileName,
|
|
nLineNumber );
|
|
|
|
OutputDebugString( szOutput );
|
|
DebugBreak();
|
|
|
|
} // FtpdAssert
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: FtpdPrintf
|
|
|
|
SYNOPSIS: Customized debug output routine.
|
|
|
|
ENTRY: Usual printf-style parameters.
|
|
|
|
HISTORY:
|
|
KeithMo 07-Mar-1993 Created.
|
|
|
|
********************************************************************/
|
|
VOID
|
|
FtpdPrintf(
|
|
CHAR * pszFormat,
|
|
...
|
|
)
|
|
{
|
|
CHAR szOutput[MAX_PRINTF_OUTPUT];
|
|
va_list ArgList;
|
|
USER_DATA * pUserData;
|
|
|
|
pUserData = UserDataPtr;
|
|
|
|
sprintf( szOutput,
|
|
"%s (%lu,%lu): ",
|
|
FTPD_OUTPUT_LABEL,
|
|
GetCurrentThreadId(),
|
|
pUserData ? pUserData->idUser : 0 );
|
|
|
|
va_start( ArgList, pszFormat );
|
|
vsprintf( szOutput + strlen(szOutput), pszFormat, ArgList );
|
|
va_end( ArgList );
|
|
|
|
IF_DEBUG( OUTPUT_TO_DEBUGGER )
|
|
{
|
|
OutputDebugString( szOutput );
|
|
}
|
|
|
|
IF_DEBUG( OUTPUT_TO_LOG_FILE )
|
|
{
|
|
if( fileLog == NULL )
|
|
{
|
|
fileLog = OpenLogFile();
|
|
}
|
|
|
|
if( fileLog != NULL )
|
|
{
|
|
fputs( szOutput, fileLog );
|
|
fflush( fileLog );
|
|
}
|
|
}
|
|
|
|
} // FtpdPrintf
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: FtpdAlloc
|
|
|
|
SYNOPSIS: Safe, instrumented heap allocator.
|
|
|
|
ENTRY: cb - Number of BYTEs to allocate.
|
|
|
|
RETURNS: VOID * - Points to the newly allocated block. Will
|
|
be NULL if block cannot be allocated.
|
|
|
|
HISTORY:
|
|
KeithMo 10-May-1993 Created.
|
|
|
|
********************************************************************/
|
|
VOID *
|
|
FtpdAlloc(
|
|
UINT cb
|
|
)
|
|
{
|
|
VOID * pvResult;
|
|
|
|
#if DEBUG_HEAP
|
|
|
|
cb += sizeof(DEBUG_HEAP_HEADER);
|
|
|
|
#endif // DEBUG_HEAP
|
|
|
|
pvResult = (VOID *)LocalAlloc( LPTR, cb );
|
|
|
|
#if DEBUG_HEAP
|
|
|
|
if( pvResult != NULL )
|
|
{
|
|
DEBUG_HEAP_HEADER * phdr = (DEBUG_HEAP_HEADER *)pvResult;
|
|
ULONG hash;
|
|
|
|
phdr->cbAlloc = cb - sizeof(DEBUG_HEAP_HEADER);
|
|
phdr->cFrames = (UINT)RtlCaptureStackBackTrace( 1,
|
|
MAX_STACK_BACKTRACE,
|
|
phdr->apvStack,
|
|
&hash );
|
|
|
|
LockGlobals();
|
|
|
|
if( pDebugHeap )
|
|
{
|
|
phdr->pLeft = pDebugHeap;
|
|
phdr->pRight = pDebugHeap->pRight;
|
|
phdr->pRight->pLeft = phdr;
|
|
pDebugHeap->pRight = phdr;
|
|
}
|
|
else
|
|
{
|
|
phdr->pRight = phdr;
|
|
phdr->pLeft = phdr;
|
|
|
|
pDebugHeap = phdr;
|
|
}
|
|
|
|
UnlockGlobals();
|
|
|
|
pvResult = (VOID *)( phdr + 1 );
|
|
}
|
|
|
|
#endif // DEBUG_HEAP
|
|
|
|
return pvResult;
|
|
|
|
} // FtpdAlloc
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: FtpdFree
|
|
|
|
SYNOPSIS: Frees a block allocated by FtpdAlloc.
|
|
|
|
ENTRY: pb - Points to the block to free.
|
|
|
|
HISTORY:
|
|
KeithMo 10-May-1993 Created.
|
|
|
|
********************************************************************/
|
|
VOID
|
|
FtpdFree(
|
|
VOID * pb
|
|
)
|
|
{
|
|
#if DEBUG_HEAP
|
|
|
|
DEBUG_HEAP_HEADER * phdr = ((DEBUG_HEAP_HEADER *)pb) - 1;
|
|
|
|
LockGlobals();
|
|
|
|
if( phdr == pDebugHeap )
|
|
{
|
|
pDebugHeap = phdr->pLeft;
|
|
|
|
if( pDebugHeap == phdr )
|
|
{
|
|
pDebugHeap = NULL;
|
|
}
|
|
}
|
|
|
|
phdr->pRight->pLeft = phdr->pLeft;
|
|
phdr->pLeft->pRight = phdr->pRight;
|
|
|
|
UnlockGlobals();
|
|
|
|
pb = (VOID *)phdr;
|
|
|
|
#endif // DEBUG_HEAP
|
|
|
|
LocalFree( (HLOCAL)pb );
|
|
|
|
} // FtpdFree
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: FtpdDumpResidue
|
|
|
|
SYNOPSIS: Dumps any unfreed heap blocks.
|
|
|
|
HISTORY:
|
|
KeithMo 10-May-1993 Created.
|
|
|
|
********************************************************************/
|
|
VOID
|
|
FtpdDumpResidue(
|
|
VOID
|
|
)
|
|
{
|
|
#if DEBUG_HEAP
|
|
|
|
DEBUG_HEAP_HEADER * phdr = pDebugHeap;
|
|
|
|
if( phdr == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
while( phdr != NULL )
|
|
{
|
|
CHAR * pszStack = " Stack =";
|
|
UINT cFrames = phdr->cFrames;
|
|
|
|
FTPD_PRINT(( "FTP residue: Hdr = %08lX, Blk = %08lX, Size = %lX\n",
|
|
(ULONG)phdr,
|
|
(ULONG)phdr + sizeof(DEBUG_HEAP_HEADER),
|
|
phdr->cbAlloc ));
|
|
|
|
if( cFrames > MAX_STACK_BACKTRACE )
|
|
{
|
|
FTPD_PRINT(( "cFrames exceeds MAX_STACK_BACKTRACE, possible corrupt heap!\n" ));
|
|
}
|
|
else
|
|
{
|
|
UINT iFrame;
|
|
|
|
for( iFrame = 0 ; iFrame < cFrames ; iFrame++ )
|
|
{
|
|
if( ( iFrame % 5 ) == 0 )
|
|
{
|
|
FTPD_PRINT(( pszStack ));
|
|
pszStack = "\n ";
|
|
}
|
|
|
|
FTPD_PRINT(( " [%08lX]",
|
|
(ULONG)phdr->apvStack[iFrame] ));
|
|
}
|
|
}
|
|
|
|
phdr = phdr->pRight;
|
|
|
|
if( phdr == pDebugHeap )
|
|
{
|
|
phdr = NULL;
|
|
}
|
|
}
|
|
|
|
DebugBreak();
|
|
|
|
#endif // DEBUG_HEAP
|
|
|
|
} // FtpdDumpResidue
|
|
|
|
|
|
//
|
|
// Private functions.
|
|
//
|
|
|
|
#endif // DBG
|
|
|