763 lines
20 KiB
C++
763 lines
20 KiB
C++
/*++
|
||
|
||
Copyright (c) 1995-1997 Microsoft Corporation
|
||
|
||
Module Name :
|
||
|
||
dbgatq.cxx
|
||
|
||
Abstract:
|
||
|
||
This module contains the NTSD Debugger extensions for the
|
||
Asynchronous Thread Queue DLL
|
||
|
||
Author:
|
||
|
||
Murali R. Krishnan ( MuraliK ) 12-May-1997
|
||
|
||
Environment:
|
||
Debugger Mode - inside NT command line debuggers
|
||
|
||
Project:
|
||
|
||
Internet Server Debugging DLL
|
||
|
||
Functions Exported:
|
||
|
||
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
/************************************************************
|
||
* Include Headers
|
||
************************************************************/
|
||
|
||
|
||
#include "inetdbgp.h"
|
||
|
||
|
||
/************************************************************
|
||
* Definitions of Variables & Macros
|
||
************************************************************/
|
||
|
||
//
|
||
// Text names of ATQ_SOCK_STATE values
|
||
//
|
||
|
||
char * AtqSockState[] = {
|
||
"ATQ_SOCK_CLOSED",
|
||
"ATQ_SOCK_UNCONNECTED",
|
||
"ATQ_SOCK_LISTENING",
|
||
"ATQ_SOCK_CONNECTED"
|
||
};
|
||
|
||
char * AtqEndpointState[] = {
|
||
"AtqStateInit",
|
||
"AtqStateActive",
|
||
"AtqStateClosed",
|
||
"AtqStateMax",
|
||
};
|
||
|
||
#define LookupSockState( SockState ) \
|
||
((SockState) <= ATQ_SOCK_CONNECTED ? AtqSockState[ (SockState) ] :\
|
||
"<Invalid>")
|
||
|
||
|
||
/************************************************************
|
||
* Functions
|
||
************************************************************/
|
||
|
||
VOID
|
||
DumpAtqGlobals(
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
DumpAtqContextList(
|
||
CHAR Level,
|
||
CHAR Verbosity,
|
||
ATQ_ENDPOINT * pEndpointIn
|
||
);
|
||
|
||
void
|
||
DumpEndpointList(
|
||
LIST_ENTRY * pAtqClientHead,
|
||
CHAR Level,
|
||
DWORD * pcContext,
|
||
BYTE * pvStart,
|
||
BYTE * pvEnd,
|
||
ATQ_ENDPOINT * pEndpointIn
|
||
);
|
||
|
||
VOID
|
||
PrintAtqContext(
|
||
ATQ_CONTEXT * AtqContext
|
||
);
|
||
|
||
|
||
void
|
||
PrintEndpoint(
|
||
ATQ_ENDPOINT * pEp
|
||
);
|
||
|
||
VOID
|
||
DumpEndpoint(
|
||
CHAR Level
|
||
);
|
||
|
||
|
||
DECLARE_API( atq )
|
||
|
||
/*++
|
||
|
||
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;
|
||
ATQ_CONTEXT AtqContext;
|
||
ATQ_CONTEXT * pAtqContext;
|
||
|
||
INIT_API();
|
||
|
||
while (*lpArgumentString == ' ')
|
||
lpArgumentString++;
|
||
|
||
if ( !*lpArgumentString )
|
||
{
|
||
PrintUsage( "atq" );
|
||
return;
|
||
}
|
||
|
||
if ( *lpArgumentString == '-' )
|
||
{
|
||
lpArgumentString++;
|
||
|
||
switch ( *lpArgumentString ) {
|
||
|
||
|
||
case 'g':
|
||
{
|
||
DumpAtqGlobals();
|
||
break;
|
||
}
|
||
|
||
case 'c':
|
||
{
|
||
DumpAtqContextList( lpArgumentString[1],
|
||
lpArgumentString[2],
|
||
NULL );
|
||
break;
|
||
}
|
||
|
||
case 'e':
|
||
{
|
||
|
||
ATQ_ENDPOINT * pEndpoint;
|
||
|
||
// Arguments: -e<Level><Verbosity> <EndpointAddr>
|
||
|
||
pEndpoint = ((ATQ_ENDPOINT * )
|
||
GetExpression( lpArgumentString + 4));
|
||
if ( !pEndpoint ) {
|
||
|
||
dprintf( "inetdbg: Unable to evaluate "
|
||
"EndpointAddr \"%s\"\n",
|
||
lpArgumentString );
|
||
|
||
break;
|
||
}
|
||
|
||
DumpAtqContextList( lpArgumentString[1],
|
||
lpArgumentString[2],
|
||
pEndpoint );
|
||
break;
|
||
}
|
||
|
||
case 'l':
|
||
{
|
||
DumpEndpoint( lpArgumentString[1] );
|
||
break;
|
||
}
|
||
|
||
case 'p':
|
||
{
|
||
//
|
||
// Treat the argument as the address of an AtqEndpoint
|
||
//
|
||
|
||
ATQ_ENDPOINT * pEndpoint;
|
||
|
||
// Arguments: -p <EndpointAddr>
|
||
|
||
pEndpoint = ((ATQ_ENDPOINT *)
|
||
GetExpression( lpArgumentString + 2 )
|
||
);
|
||
|
||
if ( !pEndpoint )
|
||
{
|
||
dprintf( "inetdbg: Unable to evaluate \"%s\"\n",
|
||
lpArgumentString );
|
||
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
ATQ_ENDPOINT Endpoint;
|
||
move( Endpoint, pEndpoint );
|
||
PrintEndpoint( &Endpoint );
|
||
}
|
||
break;
|
||
}
|
||
|
||
default:
|
||
case 'h':
|
||
{
|
||
PrintUsage( "atq" );
|
||
break;
|
||
}
|
||
|
||
} // switch
|
||
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Treat the argument as the address of an AtqContext
|
||
//
|
||
|
||
pAtqContext = (PATQ_CONT)GetExpression( lpArgumentString );
|
||
|
||
if ( !pAtqContext )
|
||
{
|
||
dprintf( "inetdbg: Unable to evaluate \"%s\"\n",
|
||
lpArgumentString );
|
||
|
||
return;
|
||
}
|
||
|
||
move( AtqContext, pAtqContext );
|
||
PrintAtqContext( &AtqContext );
|
||
} // DECLARE_API( atq )
|
||
|
||
|
||
|
||
|
||
/************************************************************
|
||
* ATQ related functions
|
||
************************************************************/
|
||
|
||
VOID
|
||
DumpAtqGlobals(
|
||
VOID
|
||
)
|
||
{
|
||
//
|
||
// Dump Atq Globals
|
||
//
|
||
|
||
dprintf("Atq Globals:\n");
|
||
|
||
DumpDword( "isatq!g_cConcurrency " );
|
||
DumpDword( "isatq!g_cThreads " );
|
||
DumpDword( "isatq!g_cAvailableThreads " );
|
||
DumpDword( "isatq!g_cMaxThreads " );
|
||
|
||
dprintf("\n");
|
||
DumpDword( "isatq!g_fUseAcceptEx " );
|
||
DumpDword( "isatq!g_fUseTransmitFile " );
|
||
DumpDword( "isatq!g_cbXmitBufferSize " );
|
||
DumpDword( "isatq!g_cbMinKbSec " );
|
||
DumpDword( "isatq!g_cCPU " );
|
||
DumpDword( "isatq!g_fShutdown " );
|
||
dprintf("\n");
|
||
|
||
DumpDword( "isatq!g_msThreadTimeout " );
|
||
DumpDword( "isatq!g_dwTimeoutCookie " );
|
||
DumpDword( "isatq!g_cListenBacklog " );
|
||
DumpDword( "isatq!AtqCurrentTick " );
|
||
DumpDword( "isatq!AtqGlobalContextCount" );
|
||
dprintf("\tsizeof(ATQ_CONTEXT) = %d\n", sizeof(ATQ_CONTEXT));
|
||
|
||
return;
|
||
} // DumpAtqGlobals()
|
||
|
||
|
||
|
||
VOID
|
||
DumpAtqContextList(
|
||
CHAR Level,
|
||
CHAR Verbosity,
|
||
ATQ_ENDPOINT * pEndpointIn
|
||
)
|
||
{
|
||
LIST_ENTRY AtqClientHead;
|
||
LIST_ENTRY * pAtqClientHead;
|
||
ATQ_CONTEXT * pAtqContext;
|
||
ATQ_CONTEXT AtqContext;
|
||
CHAR Symbol[256];
|
||
DWORD cContext = 0;
|
||
DWORD cc1;
|
||
ATQ_CONTEXT_LISTHEAD * pAtqActiveContextList;
|
||
ATQ_CONTEXT_LISTHEAD AtqActiveContextList[ATQ_NUM_CONTEXT_LIST];
|
||
DWORD i;
|
||
|
||
pAtqActiveContextList =
|
||
(ATQ_CONTEXT_LISTHEAD *) GetExpression( "&isatq!AtqActiveContextList" );
|
||
|
||
if ( !pAtqActiveContextList )
|
||
{
|
||
dprintf("Unable to get AtqActiveContextList symbol\n" );
|
||
return;
|
||
}
|
||
|
||
if ( !ReadMemory( (LPVOID) pAtqActiveContextList,
|
||
AtqActiveContextList,
|
||
sizeof(AtqActiveContextList),
|
||
NULL ))
|
||
{
|
||
dprintf("Unable to read AtqActiveContextList memory\n" );
|
||
return;
|
||
}
|
||
|
||
for ( i = 0; i < ATQ_NUM_CONTEXT_LIST; i++ )
|
||
{
|
||
dprintf("================================================\n");
|
||
dprintf("== Context List %d ==\n", i );
|
||
dprintf("================================================\n");
|
||
|
||
dprintf(" Active List ==>\n" );
|
||
|
||
cc1 = 0;
|
||
DumpEndpointList( &(AtqActiveContextList[i].ActiveListHead),
|
||
Verbosity,
|
||
&cc1,
|
||
(BYTE *) pAtqActiveContextList,
|
||
(BYTE *) &pAtqActiveContextList[ATQ_NUM_CONTEXT_LIST],
|
||
pEndpointIn
|
||
);
|
||
|
||
if ( 0 != cc1) {
|
||
dprintf( "\n\t%d Atq contexts traversed\n", cc1 );
|
||
cContext += cc1;
|
||
}
|
||
|
||
if ( Level >= '1' )
|
||
{
|
||
dprintf("================================================\n");
|
||
dprintf("Pending AcceptEx List\n");
|
||
|
||
cc1 = 0;
|
||
DumpEndpointList( &(AtqActiveContextList[i].PendingAcceptExListHead),
|
||
Verbosity,
|
||
&cc1,
|
||
(BYTE *) pAtqActiveContextList,
|
||
(BYTE *) &pAtqActiveContextList[ATQ_NUM_CONTEXT_LIST],
|
||
pEndpointIn
|
||
);
|
||
if ( 0 != cc1) {
|
||
dprintf( "\n\t%d Atq contexts traversed\n", cc1 );
|
||
cContext += cc1;
|
||
}
|
||
}
|
||
|
||
if ( CheckControlC() )
|
||
{
|
||
dprintf( "\n^C\n" );
|
||
return;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
dprintf( "%d Atq contexts traversed\n",
|
||
cContext );
|
||
|
||
return;
|
||
} // DumpAtqContextList()
|
||
|
||
|
||
|
||
void
|
||
DumpEndpointList(
|
||
LIST_ENTRY * pAtqClientHead,
|
||
CHAR Verbosity,
|
||
DWORD * pcContext,
|
||
BYTE * pvStart,
|
||
BYTE * pvEnd,
|
||
ATQ_ENDPOINT * pEndpointIn
|
||
)
|
||
{
|
||
LIST_ENTRY * pEntry;
|
||
ATQ_CONTEXT * pAtqContext;
|
||
ATQ_CONTEXT AtqContext;
|
||
|
||
//
|
||
// the list head is embedded in a structure so the exit condition of the
|
||
// loop is when the remote memory address ends up in the array memory
|
||
//
|
||
|
||
for ( pEntry = pAtqClientHead->Flink;
|
||
!((BYTE *)pEntry >= pvStart && (BYTE *)pEntry <= pvEnd);
|
||
)
|
||
{
|
||
if ( CheckControlC() )
|
||
{
|
||
return;
|
||
}
|
||
|
||
pAtqContext = CONTAINING_RECORD( pEntry,
|
||
ATQ_CONTEXT,
|
||
m_leTimeout );
|
||
|
||
move( AtqContext, pAtqContext );
|
||
|
||
// selectively print only the contexts that have a matching Endpoint
|
||
if ( (pEndpointIn != NULL) &&
|
||
(AtqContext.pEndpoint != pEndpointIn)
|
||
) {
|
||
|
||
move( pEntry, &pEntry->Flink );
|
||
continue;
|
||
}
|
||
|
||
|
||
(*pcContext)++;
|
||
|
||
if ( AtqContext.Signature != ATQ_CONTEXT_SIGNATURE )
|
||
{
|
||
dprintf( "AtqContext(%08lp) signature %08lx doesn't"
|
||
" match expected %08lx\n",
|
||
pAtqContext,
|
||
AtqContext.Signature,
|
||
ATQ_CONTEXT_SIGNATURE
|
||
);
|
||
|
||
return;
|
||
}
|
||
|
||
if ( Verbosity >= '1' )
|
||
{
|
||
//
|
||
// Print all
|
||
//
|
||
|
||
dprintf( "\nAtqContext at %08lp\n",
|
||
pAtqContext );
|
||
|
||
PrintAtqContext( &AtqContext );
|
||
|
||
}
|
||
else if ( Verbosity >= '0' )
|
||
{
|
||
//
|
||
// Print all with one line summary info
|
||
//
|
||
|
||
dprintf( "hAsyncIO = %4lp, Flink = %08lp, Blink = %08lp,"
|
||
" State = %8lx, Flags =%8lx\n",
|
||
AtqContext.hAsyncIO,
|
||
AtqContext.m_leTimeout.Blink,
|
||
AtqContext.m_leTimeout.Flink,
|
||
AtqContext.m_acState,
|
||
AtqContext.m_acFlags
|
||
);
|
||
}
|
||
|
||
move( pEntry, &pEntry->Flink );
|
||
}
|
||
} // DumpEndpointList()
|
||
|
||
|
||
|
||
VOID
|
||
PrintAtqContext(
|
||
ATQ_CONTEXT * pContext
|
||
)
|
||
{
|
||
UCHAR szSymFnCallback[MAX_SYMBOL_LEN];
|
||
ULONG_PTR offset;
|
||
|
||
|
||
GetSymbol((ULONG_PTR) pContext->pfnCompletion,
|
||
szSymFnCallback, &offset);
|
||
|
||
if (!*szSymFnCallback)
|
||
sprintf((char*) szSymFnCallback, "%p()",
|
||
pContext->pfnCompletion);
|
||
|
||
dprintf( "\n" );
|
||
dprintf( "\thAsyncIO = %08lp Signature = %08lx\n"
|
||
"\tOverlapped.Internal = %08lp Overlapped.Offset= %08lx\n"
|
||
"\tLE-Timeout.Flink = %08lp LE-Timeout.Blink = %p\n"
|
||
"\tClientContext = %08lp ContextList = %p\n"
|
||
"\tpfnIOCompletion = %s\n"
|
||
"\tlSyncTimeout = %8d m_nIO = %8d\n"
|
||
"\tTimeOut = %08lx NextTimeout = %08lx\n"
|
||
"\tBytesSent = %d (0x%08lx)\n"
|
||
"\tpvBuff = %08lp pEndPoint = %08lp\n"
|
||
"\tState = %8lx Flags = %08lx\n",
|
||
pContext->hAsyncIO, pContext->Signature,
|
||
pContext->Overlapped.Internal,pContext->Overlapped.Offset,
|
||
pContext->m_leTimeout.Flink, pContext->m_leTimeout.Blink,
|
||
pContext->ClientContext, pContext->ContextList,
|
||
szSymFnCallback,
|
||
pContext->lSyncTimeout, pContext->m_nIO,
|
||
pContext->TimeOut, pContext->NextTimeout,
|
||
pContext->BytesSent, pContext->BytesSent,
|
||
pContext->pvBuff, pContext->pEndpoint,
|
||
pContext->m_acState, pContext->m_acFlags
|
||
);
|
||
|
||
// identify and print the various properties
|
||
dprintf( "\t");
|
||
// First print the state bits
|
||
if ( pContext->m_acState & ACS_SOCK_CLOSED) {
|
||
dprintf( " ACS_SOCK_CLOSED");
|
||
}
|
||
if ( pContext->m_acState & ACS_SOCK_UNCONNECTED) {
|
||
dprintf( " ACS_SOCK_UNCONNECTED");
|
||
}
|
||
if ( pContext->m_acState & ACS_SOCK_LISTENING) {
|
||
dprintf( " ACS_SOCK_LISTENING");
|
||
}
|
||
if ( pContext->m_acState & ACS_SOCK_CONNECTED) {
|
||
dprintf( " ACS_SOCK_CONNECTED");
|
||
}
|
||
if ( pContext->m_acState & ACS_SOCK_TOBE_FREED) {
|
||
dprintf( " ACS_SOCK_TOBE_FREED");
|
||
}
|
||
|
||
// now print the flags associated with this context
|
||
if ( pContext->m_acFlags & ACF_ACCEPTEX_ROOT_CONTEXT) {
|
||
dprintf( " ACCEPTEX_CONTEXT");
|
||
}
|
||
if ( pContext->m_acFlags & ACF_CONN_INDICATED) {
|
||
dprintf( " CONNECTION_INDICATED");
|
||
}
|
||
if ( pContext->m_acFlags & ACF_IN_TIMEOUT) {
|
||
dprintf( " IN_TIMEOUT");
|
||
}
|
||
if ( pContext->m_acFlags & ACF_BLOCKED) {
|
||
dprintf( " BLOCKED_BY_BWT");
|
||
}
|
||
if ( pContext->m_acFlags & ACF_REUSE_CONTEXT) {
|
||
dprintf( " REUSE_CONTEXT");
|
||
}
|
||
if ( pContext->m_acFlags & ACF_RECV_ISSUED) {
|
||
dprintf( " RECV_ISSUED");
|
||
}
|
||
if ( pContext->m_acFlags & ACF_ABORTIVE_CLOSE) {
|
||
dprintf( " ABORTIVE_CLOSE");
|
||
}
|
||
dprintf( "\n");
|
||
|
||
if ( pContext->IsFlag( ACF_ACCEPTEX_ROOT_CONTEXT) && pContext->pvBuff )
|
||
{
|
||
//
|
||
// This size should correspond to the MIN_SOCKADDR_SIZE field in
|
||
// atqnew.c. We assume it's two thirty two byte values currently.
|
||
//
|
||
|
||
DWORD AddrInfo[16];
|
||
ATQ_ENDPOINT * pEndpoint = pContext->pEndpoint;
|
||
ATQ_ENDPOINT Endpoint;
|
||
|
||
move( Endpoint, pEndpoint );
|
||
|
||
if ( ReadMemory( (LPVOID) ((BYTE *) pContext->pvBuff +
|
||
Endpoint.InitialRecvSize +
|
||
2 * MIN_SOCKADDR_SIZE -
|
||
sizeof( AddrInfo )),
|
||
AddrInfo,
|
||
sizeof(AddrInfo),
|
||
NULL ))
|
||
{
|
||
|
||
dprintf( "\tLocal/Remote Addr = %08x %08x %08x %08x\n"
|
||
"\t %08x %08x %08x %08x\n"
|
||
"\t %08x %08x %08x %08x\n"
|
||
"\t %08x %08x %08x %08x\n",
|
||
AddrInfo[0],
|
||
AddrInfo[1],
|
||
AddrInfo[2],
|
||
AddrInfo[3],
|
||
AddrInfo[4],
|
||
AddrInfo[5],
|
||
AddrInfo[6],
|
||
AddrInfo[7],
|
||
AddrInfo[8],
|
||
AddrInfo[9],
|
||
AddrInfo[10],
|
||
AddrInfo[11],
|
||
AddrInfo[12],
|
||
AddrInfo[13],
|
||
AddrInfo[14],
|
||
AddrInfo[15] );
|
||
}
|
||
}
|
||
} // PrintAtqContext()
|
||
|
||
|
||
VOID
|
||
DumpEndpoint(
|
||
CHAR Verbosity
|
||
)
|
||
{
|
||
LIST_ENTRY AtqEndpointList;
|
||
LIST_ENTRY * pAtqEndpointList;
|
||
LIST_ENTRY * pEntry;
|
||
ATQ_CONTEXT * pAtqContext;
|
||
ATQ_CONTEXT AtqContext;
|
||
CHAR Symbol[256];
|
||
DWORD cEndp = 0;
|
||
DWORD i;
|
||
ATQ_ENDPOINT * pEndpoint;
|
||
ATQ_ENDPOINT Endpoint;
|
||
|
||
pAtqEndpointList = (LIST_ENTRY *) GetExpression( "&isatq!AtqEndpointList" );
|
||
|
||
if ( !pAtqEndpointList )
|
||
{
|
||
dprintf("Unable to get AtqEndpointList symbol\n" );
|
||
return;
|
||
}
|
||
|
||
move( AtqEndpointList, pAtqEndpointList );
|
||
|
||
for ( pEntry = AtqEndpointList.Flink;
|
||
pEntry != pAtqEndpointList;
|
||
cEndp++
|
||
)
|
||
{
|
||
if ( CheckControlC() )
|
||
{
|
||
return;
|
||
}
|
||
|
||
pEndpoint = CONTAINING_RECORD( pEntry,
|
||
ATQ_ENDPOINT,
|
||
ListEntry );
|
||
|
||
move( Endpoint, pEndpoint );
|
||
|
||
if ( Endpoint.Signature != ATQ_ENDPOINT_SIGNATURE )
|
||
{
|
||
dprintf( "Endpoint(%08p) signature %08lx doesn't match expected %08lx\n",
|
||
pEndpoint,
|
||
Endpoint.Signature,
|
||
ATQ_ENDPOINT_SIGNATURE
|
||
);
|
||
|
||
break;
|
||
}
|
||
|
||
if ( Verbosity >= '1' )
|
||
{
|
||
//
|
||
// Print all
|
||
//
|
||
|
||
dprintf( "\nEndpoint at %08lp\n",
|
||
pEndpoint );
|
||
|
||
PrintEndpoint( &Endpoint );
|
||
|
||
}
|
||
else if ( Verbosity >= '0' )
|
||
{
|
||
//
|
||
// Print all with one line summary info
|
||
//
|
||
|
||
dprintf( "sListenSocket = %4lp, cRef = %d, cSocketsAvail = %d\n",
|
||
Endpoint.ListenSocket,
|
||
Endpoint.m_refCount,
|
||
Endpoint.nSocketsAvail );
|
||
}
|
||
|
||
move( pEntry, &pEntry->Flink );
|
||
}
|
||
|
||
dprintf( "%d Atq Endpoints traversed\n",
|
||
cEndp );
|
||
|
||
return;
|
||
} // DumpEndpoint()
|
||
|
||
|
||
void
|
||
PrintEndpoint(
|
||
ATQ_ENDPOINT * pEp
|
||
)
|
||
{
|
||
|
||
dprintf( "\tcRef = %8d State = %s\n"
|
||
"\tIP Address = %s Port = %04x\n"
|
||
"\tsListenSocket = %8p InitRecvSize = %04x\n"
|
||
"\tnSocketsAvail = %8d nAvailAtTimeout = %d\n"
|
||
"\tnAcceptExOutstdg =%8d\n"
|
||
"\tUseAcceptEx = %8s AcceptExTimeout = %8d\n"
|
||
"\tEnableBw Throttle= %s\n"
|
||
"\tListEntry.Flink = %08lp ListEntry.Blink = %08lp\n"
|
||
"\tClient Context = %08lp pfnCompletion = %08lp()\n"
|
||
"\tpfnConnComp = %08lp() pfnConnExComp = %08lp()\n"
|
||
"\tShutDownCallback = %08lp() ShutDown Context = %08lp\n"
|
||
,
|
||
pEp->m_refCount,
|
||
AtqEndpointState[pEp->State],
|
||
pEp->IpAddress,
|
||
pEp->Port,
|
||
pEp->ListenSocket,
|
||
pEp->InitialRecvSize,
|
||
pEp->nSocketsAvail,
|
||
pEp->nAvailDuringTimeOut,
|
||
pEp->nAcceptExOutstanding,
|
||
BoolValue( pEp->UseAcceptEx),
|
||
pEp->AcceptExTimeout,
|
||
BoolValue( pEp->EnableBw),
|
||
pEp->ListEntry.Flink,
|
||
pEp->ListEntry.Blink,
|
||
pEp->Context,
|
||
pEp->IoCompletion,
|
||
pEp->ConnectCompletion,
|
||
pEp->ConnectExCompletion,
|
||
pEp->ShutdownCallback,
|
||
pEp->ShutdownCallbackContext
|
||
);
|
||
|
||
return;
|
||
} // PrintEndpoint()
|
||
|
||
|
||
/************************ End of File ***********************/
|
||
|