Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

733 lines
19 KiB

/*++
Copyright (c) 1995-1997 Microsoft Corporation
Module Name:
dbgcc.cxx
Abstract:
This module contains the default ntsd debugger extensions for
IIS - W3SVC Client Connection
Author:
Murali R. Krishnan (MuraliK) 22-Aug-1997
Revision History:
--*/
#include "inetdbgp.h"
# undef DBG_ASSERT
/************************************************************
* Debugger Utility Functions
************************************************************/
NTSD_EXTENSION_APIS ExtensionApis;
HANDLE ExtensionCurrentProcess;
/************************************************************
* CLIENT_CONN related functions
************************************************************/
char * g_rgchCCState[] = {
"CcsStartup",
"CcsGettingClientReq",
"CcsGatheringGatewayData",
"CcsProcessingClientReq",
"CcsDisconnecting",
"CcsShutdown",
"CcsMaxItems"
};
#define LookupCCState( ItemState ) \
((((ItemState) >= CCS_STARTUP) && ((ItemState) <= CCS_SHUTDOWN)) ?\
g_rgchCCState[ (ItemState)] : "<Invalid>")
VOID PrintClientConn( CLIENT_CONN * pccOriginal,
CLIENT_CONN * pcc, CHAR Verbosity);
VOID
PrintClientConnThunk( PVOID pccDebuggee,
PVOID pccDebugger,
CHAR verbosity,
DWORD iCount);
DECLARE_API( cc )
/*++
Routine Description:
This function is called as an NTSD extension to format and dump
an object attributes structure.
Arguments:
hCurrentProcess - Supplies a handle to the current process (at the
time the extension was called).
hCurrentThread - Supplies a handle to the current thread (at the
time the extension was called).
CurrentPc - Supplies the current pc at the time the extension is
called.
lpExtensionApis - Supplies the address of the functions callable
by this extension.
lpArgumentString - Supplies the asciiz string that describes the
ansi string to be dumped.
Return Value:
None.
--*/
{
BOOL fRet;
DEFINE_CPP_VAR( CLIENT_CONN, cc);
CLIENT_CONN * pcc;
INIT_API();
while (*lpArgumentString == ' ')
lpArgumentString++;
if ( !*lpArgumentString )
{
PrintUsage( "cc" );
return;
}
if ( *lpArgumentString == '-' )
{
lpArgumentString++;
if ( *lpArgumentString == 'h' )
{
PrintUsage( "cc" );
return;
}
if ( *lpArgumentString == 'l' ) {
DumpClientConnList( lpArgumentString[1], PrintClientConnThunk );
return;
}
} // while
//
// Treat the argument as the address of an AtqContext
//
pcc = (CLIENT_CONN * ) GetExpression( lpArgumentString );
if ( !pcc )
{
dprintf( "inetdbg.cc: Unable to evaluate \"%s\"\n",
lpArgumentString );
return;
}
move( cc, pcc );
PrintClientConn( pcc, GET_CPP_VAR_PTR( CLIENT_CONN, cc), '2' );
return;
} // DECLARE_API( cc )
VOID
PrintClientConn( CLIENT_CONN * pccOriginal,
CLIENT_CONN * pcc,
CHAR Verbosity )
/*++
Description:
This function takes the client connection object and prints out
the details for the same in the debugger. The granularity of the
deatils are controlled by the verbosity flag
Arguments:
pccOriginal - pointer to the location where the original CLIENT_CONN
object is located.
Note: pccOriginal points to object inside debuggee process
pcc - pointer to the Client Connection object that is a copy
of the contents located at [pccOriginal]
Note: pcc points to object inside the debugger process
Verbostiy - level of details requested.
Returns:
None
--*/
{
if ( Verbosity >= '0') {
//
// print Brief information about the client connection
//
dprintf( "ClIENT_CONN:%08p Refs = %8d State = %15s\n"
"\t HTTP_REQUEST = %08p AtqContext = %08p\n"
,
pccOriginal, pcc->_cRef,
LookupCCState( pcc->_ccState),
pcc->_phttpReq,
pcc->_AtqContext
);
}
if ( Verbosity >= '1' ) {
//
// Print all details for the Client Connection object
//
dprintf( "\tSignature = %08x fSecurePort=%d fValid=%d; \n"
"\tSocket = %08p Port: Local=%hd Remote=%hd\n"
"\tListEntry.Flink = %08p ListEntry.Blink = %08p\n"
"\tInitialBuffer = %08p InitialBytesRecvd = %d\n"
"\tBuffLE.Flink = %08p BuffLE.Blink = %08p\n"
"\tAddress Local = %10s Address Remote = %10s\n"
"\tW3Instance = %08p Reflog = %08p\n"
,
pcc->_Signature, pcc->_fSecurePort, pcc->_fIsValid,
pcc->_sClient, pcc->_sPort, pcc->_sRemotePort,
pcc->ListEntry.Flink, pcc->ListEntry.Blink,
pcc->_pvInitial, pcc->_cbInitial,
pcc->_BuffListEntry.Flink, pcc->_BuffListEntry.Blink,
pcc->_achLocalAddr, pcc->_achRemoteAddr,
pcc->m_pInstance,
#if CC_REF_TRACKING // Enabled in free builds for build 585 and later
pcc->_pDbgCCRefTraceLog
#else
(PVOID)(-1)
#endif
);
}
if ( Verbosity >= '2' ) {
//
// Print the initial request received for the client connection
//
dstring( " Initial Request", pcc->_pvInitial, pcc->_cbInitial);
}
return;
} // PrintClientConn()
VOID
PrintClientConnThunk( PVOID pccDebuggee,
PVOID pccDebugger,
CHAR verbosity,
DWORD iThunk)
/*++
Description:
This is the callback function for printing the CLIENT_CONN object.
Arguments:
pccDebuggee - pointer to client conn object in the debuggee process
pccDebugger - pointer to client conn object in the debugger process
verbosity - character indicating the verbosity level desired
Returns:
None
--*/
{
if ( ((CLIENT_CONN * )pccDebugger)->_Signature != CLIENT_CONN_SIGNATURE) {
dprintf( "ClientConn(%08lp) signature %08lx doesn't"
" match expected %08lx\n",
pccDebuggee,
((CLIENT_CONN * )pccDebugger)->_Signature,
CLIENT_CONN_SIGNATURE
);
return;
}
PrintClientConn( (CLIENT_CONN *) pccDebuggee,
(CLIENT_CONN *) pccDebugger,
verbosity);
} // PrintClientConnThunk()
VOID
DumpClientConnList(
CHAR Verbosity,
PFN_LIST_ENUMERATOR pfnCC
)
{
LIST_ENTRY * pccListHead;
pccListHead = (LIST_ENTRY *) GetExpression( "&w3svc!listConnections");
if ( NULL == pccListHead) {
dprintf( " Unable to get Client Connections list \n");
return;
}
EnumLinkedList( pccListHead, pfnCC, Verbosity,
sizeof( CLIENT_CONN),
FIELD_OFFSET( CLIENT_CONN, ListEntry)
);
return;
} // DumpClientConnList()
/************************************************************
* HTTP_REQUEST related functions
************************************************************/
char * g_rgchHREQState[] = {
"HtrReadingClientRequest",
"HtrReadingGatewayData",
"HtrParse",
"HtrDoVerb",
"HtrGatewayAsyncIO",
"HtrSendFile",
"HtrProxySendingRequest",
"HtrCgi",
"HtrRange",
"HtrRestartRequest",
"HtrWritingFile",
"HtrCertRenegotiate",
"HtrMaxItems"
};
#define LookupHREQState( ItemState ) \
((((ItemState) >= HTR_READING_CLIENT_REQUEST) && \
((ItemState) <= HTR_DONE)) ?\
g_rgchHREQState[ (ItemState)] : "<Invalid>")
const char * g_rgchHreqPutState[] = {
"PSTATE_START",
"PSTATE_READING",
"PSTATE_DISCARD_READING",
"PSTATE_DISCARD_CHUNK"
};
# define LookupHreqPutState( ItemState) \
((((ItemState) >= PSTATE_START) && \
((ItemState) <= PSTATE_DISCARD_CHUNK)) ?\
g_rgchHreqPutState[ (ItemState)] : "<Invalid>")
VOID
PrintHttpRequest( HTTP_REQUEST * phreqOriginal,
HTTP_REQUEST * phreq,
CHAR Verbosity);
VOID
PrintHttpRequestThunk( PVOID pccDebuggee,
PVOID pccDebugger,
CHAR verbosity,
DWORD iCount);
DECLARE_API( hreq )
/*++
Routine Description:
This function is called as an NTSD extension to format and dump
an object attributes structure.
Arguments:
hCurrentProcess - Supplies a handle to the current process (at the
time the extension was called).
hCurrentThread - Supplies a handle to the current thread (at the
time the extension was called).
CurrentPc - Supplies the current pc at the time the extension is
called.
lpExtensionApis - Supplies the address of the functions callable
by this extension.
lpArgumentString - Supplies the asciiz string that describes the
ansi string to be dumped.
Return Value:
None.
--*/
{
BOOL fRet;
DEFINE_CPP_VAR( HTTP_REQUEST, hreq);
HTTP_REQUEST * phreq;
INIT_API();
while (*lpArgumentString == ' ')
lpArgumentString++;
if ( !*lpArgumentString )
{
PrintUsage( "hreq" );
return;
}
if ( *lpArgumentString == '-' )
{
lpArgumentString++;
if ( *lpArgumentString == 'h' )
{
PrintUsage( "hreq" );
return;
}
if ( *lpArgumentString == 'l' ) {
DumpClientConnList( lpArgumentString[1],
PrintHttpRequestThunk);
return;
}
} // if
//
// Treat the argument as the address of an AtqContext
//
phreq = (HTTP_REQUEST * ) GetExpression( lpArgumentString );
if ( !phreq )
{
dprintf( "inetdbg.hreq: Unable to evaluate \"%s\"\n",
lpArgumentString );
return;
}
move( hreq, phreq );
PrintHttpRequest( phreq, GET_CPP_VAR_PTR( HTTP_REQUEST, hreq), '2');
return;
} // DECLARE_API( hreq )
VOID
PrintHttpRequestThunk(
PVOID pccDebuggee,
PVOID pccDebugger,
CHAR verbosity,
DWORD iCount)
/*++
Description:
This is the callback function for printing the HTTP_REQUEST object.
Arguments:
pccDebuggee - pointer to client conn object in the debuggee process
pccDebugger - pointer to client conn object in the debugger process
verbosity - character indicating the verbosity level desired
Returns:
None
--*/
{
DEFINE_CPP_VAR( HTTP_REQUEST, hreq);
HTTP_REQUEST * phreq;
CLIENT_CONN * pcc = (CLIENT_CONN *) pccDebugger;
if ( pcc->_Signature != CLIENT_CONN_SIGNATURE) {
dprintf( "ClientConn(%08lp) signature %08lx doesn't"
" match expected %08lx\n",
pccDebuggee,
pcc->_Signature,
CLIENT_CONN_SIGNATURE
);
return;
}
//
// Obtain the pointer for HTTP_REQUEST object from CLIENT_CONN object
// and make local copy of the HTTP_REQUEST object inside debugger process
//
phreq = (HTTP_REQUEST *) pcc->_phttpReq;
move( hreq, phreq);
// Print out the http request object
PrintHttpRequest( phreq,
GET_CPP_VAR_PTR( HTTP_REQUEST, hreq),
verbosity);
} // PrintHttpRequestThunk()
VOID
PrintHttpRequest( HTTP_REQUEST * phreqOriginal,
HTTP_REQUEST * phreq,
CHAR Verbosity )
/*++
Description:
This function takes the HTTP_REQUEST object and prints out
the details for the same in the debugger. The granularity of the
deatils are controlled by the verbosity flag
Arguments:
phreqOriginal - pointer to the location where the original HTTP_REQUEST
object is located.
Note: phreqOriginal points to object inside debuggee process
phreq - pointer to the HTTP_REQUEST object that is a copy
of the contents located at [phreqOriginal]
Note: phreq points to object inside the debugger process
Verbostiy - level of details requested.
Returns:
None
--*/
{
if ( Verbosity >= '0') {
//
// print Brief information about the client connection
//
dprintf( "HTTP_REQUEST:%08p State = %15s\n"
"\t CLIENT_CONN = %08p WamReq = %08p\n"
,
phreqOriginal,
LookupHREQState( phreq->_htrState),
phreq->_pClientConn,
phreq->_pWamRequest
);
}
if ( Verbosity >= '1' ) {
//
// Print all details for the Client Connection object
//
dprintf( "\t _fKeepConn = %8s _fLoggedOn = %8s\n"
"\t _fChunked = %8s Client Ver = %d.%d\n"
"\t _tcpauth = %08p _Filter = %p \n"
"\t _cbClientRequest = %8d _cbOldData = %8d\n"
"\t _cbEntityBody = %8d _cbTotalEntBody = %8d\n"
"\t _cbChunkHeader = %8d _cbChunkBytesRead=%8d\n"
"\t _cbExtraData = %8d _pchExtraData = %08p\n"
"\t _pMetaData = %08p _pURIInfo = %08p\n"
"\t _pGetFile = %08p _Exec = %08p\n"
"\t _pW3Stats = %08p\n"
"\t _dwLogHttpResponse= %8d _dwLogWinError = %8d\n"
,
BoolValue(phreq->_fKeepConn),
BoolValue(phreq->_fLoggedOn),
BoolValue(phreq->_fChunked),
(int) phreq->_VersionMajor, (int) phreq->_VersionMinor,
(BYTE *) phreqOriginal + ((BYTE *) &phreq->_tcpauth - (BYTE *) phreq),
(BYTE *) phreqOriginal + ((BYTE *) &phreq->_Filter - (BYTE *) phreq),
phreq->_cbClientRequest,
phreq->_cbOldData,
phreq->_cbEntityBody,
phreq->_cbTotalEntityBody,
phreq->_cbChunkHeader,
phreq->_cbChunkBytesRead,
phreq->_cbExtraData,
phreq->_pchExtraData,
phreq->_pMetaData,
phreq->_pURIInfo,
phreq->_pGetFile,
(BYTE *) phreqOriginal + ((BYTE *) &phreq->_Exec - (BYTE *) phreq),
phreq->_pW3Stats,
phreq->_dwLogHttpResponse,
phreq->_dwLogWinError
);
}
if ( Verbosity >= '2' ) {
//
// Print state specific data
//
dprintf( "\t _putstate = %8s _pFileNameLock = %8p\n"
, LookupHreqPutState( phreq->_putstate)
, phreq->_pFileNameLock
);
}
return;
} // PrintHttpRequest()
VOID
PrintW3Statistics( W3_SERVER_STATISTICS * pw3statsDebuggee );
/*++
NAME: wstats
SYNOPSIS: Displays the w3svc statistics.
By default print the global w3svc statistics.
If given an argument treat that argument as a pointer to the
W3_SERVER_STATISITCS structure and print it out
--*/
DECLARE_API( wstats )
{
W3_SERVER_STATISTICS * pw3stats;
W3_IIS_SERVICE * pw3s;
INIT_API();
while (*lpArgumentString == ' ')
lpArgumentString++;
//
// Capture the statistics.
//
if ( !*lpArgumentString ) {
dprintf( "OffsetOfGlobalStats from W3_IIS_SERVICE = %d (0x%x)\n",
FIELD_OFFSET( W3_IIS_SERVICE, m_GlobalStats),
FIELD_OFFSET( W3_IIS_SERVICE, m_GlobalStats)
);
dprintf( "OffsetOfStats from W3_SERVER_INSTANCE = %d (0x%x)\n",
FIELD_OFFSET( W3_SERVER_INSTANCE, m_pW3Stats),
FIELD_OFFSET( W3_SERVER_INSTANCE, m_pW3Stats)
);
//
// In IIS 4.0, the global statistics structure is part of
// the W3_IIS_SERVICE structure - obtain the address indirectly.
//
W3_IIS_SERVICE ** ppw3s;
ppw3s = (W3_IIS_SERVICE **) GetExpression( "w3svc!g_pInetSvc");
if ( !ppw3s) {
dprintf( "Unable to get w3svc!g_pInetSvc to fetch global stats\n");
return;
}
//
// From the pointer to pointer to W3_IIS_SERVICE,
// obtain the pointer to the W3_IIS_SERVICE
//
moveBlock( pw3s, ppw3s, sizeof(W3_IIS_SERVICE * ));
pw3stats = &pw3s->m_GlobalStats;
} else {
//
// extract the address from the argument given
//
pw3stats = (W3_SERVER_STATISTICS * ) GetExpression( lpArgumentString );
}
PrintW3Statistics( pw3stats);
return;
} // stats
# define P2DWORDS( a, b) \
Print2Dwords( #a, \
pw3statsDebugger->m_W3Stats. ## a, \
#b, \
pw3statsDebugger->m_W3Stats. ## b \
)
VOID
PrintW3Statistics( W3_SERVER_STATISTICS * pw3statsDebuggee )
/*++
Description:
This function takes the W3_SERVER_STATISTICS object and prints out
the details for the same in the debugger.
Arguments:
pw3statsDebuggee - pointer to the location where the original structure
is found inside the debuggee process.
pw3statsDebugger - pointer to the copy of the data in the debugger process.
Returns:
None
--*/
{
DEFINE_CPP_VAR( W3_SERVER_STATISTICS, w3stats);
W3_SERVER_STATISTICS * pw3statsDebugger =
(W3_SERVER_STATISTICS *) &w3stats;
CHAR szLargeInt[64];
//
// copy the statistics data into the local buffer inside the debugger
// process so we can play with it
//
move( w3stats, pw3statsDebuggee);
dprintf( " %30s = 0x%08p\n",
"W3_SERVER_STATISTICS",
pw3statsDebuggee);
PrintLargeInteger( "TotalBytesSent",
&pw3statsDebugger->m_W3Stats.TotalBytesSent);
PrintLargeInteger( "TotalBytesReceived",
&pw3statsDebugger->m_W3Stats.TotalBytesReceived);
P2DWORDS( TotalFilesSent, TotalFilesReceived);
dprintf("\n");
P2DWORDS( CurrentAnonymousUsers, CurrentNonAnonymousUsers);
P2DWORDS( TotalAnonymousUsers, TotalNonAnonymousUsers);
P2DWORDS( MaxAnonymousUsers, MaxNonAnonymousUsers);
P2DWORDS( CurrentConnections, MaxConnections);
P2DWORDS( ConnectionAttempts, LogonAttempts);
dprintf( "\n");
P2DWORDS( TotalGets, TotalPosts);
P2DWORDS( TotalHeads, TotalPuts);
P2DWORDS( TotalDeletes, TotalTraces);
P2DWORDS( TotalOthers, TotalNotFoundErrors);
P2DWORDS( TotalCGIRequests, TotalBGIRequests);
dprintf( "\n");
P2DWORDS( CurrentCGIRequests, MaxCGIRequests);
P2DWORDS( CurrentBGIRequests, MaxBGIRequests);
return;
} // PrintW3Statistics()