windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/dbgext/oplock/fcache.cxx

1895 lines
37 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1995-1996 Microsoft Corporation
Module Name:
fcache.cxx
Abstract:
This module contains the cache-related ntsd debugger extensions for
Internet Information Server
Author:
Keith Moore (keithmo) 12-Aug-1997
Revision History:
--*/
#include "inetdbgp.h"
//
// Worker routines.
//
PSTR
DemuxToString(
IN ULONG Demux
)
/*++
Routine Description:
Converts the specified demux value to a printable string.
Arguments:
Demux - The demux value to map.
Return Value:
PSTR - The printable string.
--*/
{
switch( Demux ) {
case RESERVED_DEMUX_START :
return "RESERVED_DEMUX_START";
case RESERVED_DEMUX_DIRECTORY_LISTING :
return "RESERVED_DEMUX_DIRECTORY_LISTING";
case RESERVED_DEMUX_ATOMIC_DIRECTORY_GUARD :
return "RESERVED_DEMUX_ATOMIC_DIRECTORY_GUARD";
case RESERVED_DEMUX_OPEN_FILE :
return "RESERVED_DEMUX_OPEN_FILE";
case RESERVED_DEMUX_URI_INFO :
return "RESERVED_DEMUX_URI_INFO";
case RESERVED_DEMUX_PHYSICAL_OPEN_FILE :
return "RESERVED_DEMUX_PHYSICAL_OPEN_FILE";
default :
return "Unknown";
}
} // DemuxToString
PSTR
SignatureToString(
IN DWORD CurrentSignature,
IN DWORD ValidSignature,
IN DWORD FreedSignature
)
/*++
Routine Description:
Determines an appropriate display string for the given signature.
If the current signature matches the expected valid signature,
then the string "OK" is returned. If the current signature matches
the freed signature, then "FREED" is returned. Otherwise, "INVALID"
is returned.
Arguments:
CurrentSignature - The current signature as retrieved from the
object/structure.
ValidSignature - The expected signature for a valid, in-use
object/structure.
FreedSignature - The signature assigned to the object/structure
just before it is freed.
Return Value:
PSTR - "OK", "FREED", or "INVALID" as appropriate.
--*/
{
if( CurrentSignature == ValidSignature ) {
return "OK";
}
if( CurrentSignature == FreedSignature ) {
return "FREED";
}
return "INVALID";
} // SignatureToString
PSTR
BoolToString(
IN BOOL Flag
)
/*++
Routine Description:
Maps the given BOOL to a displayable string.
Arguments:
Flag - The BOOL flag to map.
Return Value:
PSTR - "TRUE", "FALSE", or "INVALID" as appropriate.
--*/
{
//
// In general, explicit testing for TRUE is a Bad Thing, but in
// this case, it's useful for catching invalid data.
//
if( Flag == TRUE ) {
return "TRUE";
}
if( Flag == FALSE ) {
return "FALSE";
}
return "INVALID";
} // BoolToString
VOID
DumpBlobHeader(
IN PSTR Prefix,
IN PBLOB_HEADER BlobHeader,
IN ULONG ActualAddress
)
/*++
Routine Description:
Formats and dumps a specific BLOB_HEADER structure.
Arguments:
Prefix - The prefix to use before each printed line. This makes
hierarchical object displays much prettier.
BlobHeader - Points to a local copy of the structure.
ActualAddress - The virtual address of the object in the debugee.
Return Value:
None.
--*/
{
ULONG offset;
UCHAR symbol[MAX_PATH];
CHAR renderedSymbol[MAX_PATH];
GetSymbol(
(PVOID)BlobHeader->pfnFreeRoutine,
symbol,
&offset
);
if( symbol[0] == '\0' ) {
renderedSymbol[0] = '\0';
} else if( offset == 0 ) {
sprintf(
renderedSymbol,
" (%s)",
symbol
);
} else {
sprintf(
renderedSymbol,
" (%s+0x%lx)",
symbol,
offset
);
}
dprintf(
"%sBLOB_HEADER @ %08lx\n"
"%s IsCached = %s\n"
"%s pCache = %08lx\n"
"%s PFList @ %08lx%s\n"
"%s pfnFreeRoutine = %08lx%s\n"
"\n",
Prefix,
ActualAddress,
Prefix,
BoolToString( BlobHeader->IsCached ),
Prefix,
BlobHeader->pCache,
Prefix,
ActualAddress + FIELD_OFFSET( BLOB_HEADER, PFList ),
IS_LIST_EMPTY( BlobHeader, ActualAddress, BLOB_HEADER, PFList )
? " (EMPTY)"
: "",
Prefix,
BlobHeader->pfnFreeRoutine,
renderedSymbol
);
} // DumpBlobHeader
VOID
DumpOpenFileInfo(
IN PSTR Prefix,
IN LPTS_OPEN_FILE_INFO OpenFileInfo,
IN ULONG ActualAddress
)
/*++
Routine Description:
Formats and dumps a specific TS_OPEN_FILE_INFO structure.
Arguments:
Prefix - The prefix to use before each printed line. This makes
hierarchical object displays much prettier.
OpenFileInfo - Points to a local copy of the structure.
ActualAddress - The virtual address of the object in the debugee.
Return Value:
None.
--*/
{
dprintf(
"%sTS_OPEN_FILE_INFO @ %08lx\n"
"%s m_hOpeningUser = %08lx\n"
"%s m_PhysFileInfo = %08lx\n"
"%s m_FileInfo @ %08lx\n"
"%s m_CastratedLastWriteTime @ %08lx\n",
Prefix,
ActualAddress,
Prefix,
OpenFileInfo->m_hOpeningUser,
Prefix,
OpenFileInfo->m_PhysFileInfo,
Prefix,
ActualAddress + FIELD_OFFSET( TS_OPEN_FILE_INFO, m_FileInfo ),
Prefix,
ActualAddress + FIELD_OFFSET( TS_OPEN_FILE_INFO, m_CastratedLastWriteTime )
);
dprintf(
"%s m_achHttpInfo @ %08lx (%s)\n"
"%s m_cchHttpInfo = %lu\n"
"%s m_achETag @ %08lx (%s)\n"
"%s m_cchETag = %lu\n"
"%s m_ETagIsWeak = %s\n"
"%s m_fIsCached = %s\n"
"\n",
Prefix,
ActualAddress + FIELD_OFFSET( TS_OPEN_FILE_INFO, m_achHttpInfo ),
OpenFileInfo->m_achHttpInfo,
Prefix,
OpenFileInfo->m_cchHttpInfo,
Prefix,
ActualAddress + FIELD_OFFSET( TS_OPEN_FILE_INFO, m_achETag ),
OpenFileInfo->m_achETag,
Prefix,
OpenFileInfo->m_cchETag,
Prefix,
BoolToString( OpenFileInfo->m_ETagIsWeak ),
Prefix,
BoolToString( OpenFileInfo->m_fIsCached )
);
} // DumpOpenFileInfo
VOID
DumpUriInfo(
IN PSTR Prefix,
IN PW3_URI_INFO UriInfo,
IN ULONG ActualAddress
)
/*++
Routine Description:
Formats and dumps a specific W3_URI_INFO structure.
Arguments:
Prefix - The prefix to use before each printed line. This makes
hierarchical object displays much prettier.
UriInfo - Points to a local copy of the structure.
ActualAddress - The virtual address of the object in the debugee.
Return Value:
None.
--*/
{
CHAR name[MAX_PATH];
CHAR unmappedName[MAX_PATH];
if( UriInfo->pszName == NULL ) {
strcpy( name, "<null>" );
} else if( !ReadMemory(
(ULONG)UriInfo->pszName,
name,
sizeof(name),
NULL
) ) {
strcpy( name, "<unreadable>" );
}
if( UriInfo->pszUnmappedName == NULL ) {
strcpy( unmappedName, "<null>" );
} else if( !ReadMemory(
(ULONG)UriInfo->pszUnmappedName,
unmappedName,
sizeof(unmappedName),
NULL
) ) {
strcpy( unmappedName, "<unreadable>" );
}
dprintf(
"%sW3_URI_INFO @ %08lx\n"
"%s bFileInfoValid = %lu\n"
"%s bIsCached = %s\n"
"%s hFileEvent = %08lx\n"
"%s pOpenFileInfo = %08lx\n",
Prefix,
ActualAddress,
Prefix,
UriInfo->bFileInfoValid,
Prefix,
BoolToString( UriInfo->bIsCached ),
Prefix,
UriInfo->hFileEvent,
Prefix,
UriInfo->pOpenFileInfo
);
dprintf(
"%s dwFileOpenError = %lu\n"
"%s cchName = %lu\n"
"%s pszName = %08lx (%s)\n"
"%s pszUnmappedName = %08lx (%s)\n"
"%s pMetaData = %08lx\n"
"\n",
Prefix,
UriInfo->dwFileOpenError,
Prefix,
UriInfo->cchName,
Prefix,
UriInfo->pszName,
name,
Prefix,
UriInfo->pszUnmappedName,
unmappedName,
Prefix,
UriInfo->pMetaData
);
} // DumpUriInfo
VOID
DumpPhysOpenFileInfo(
IN PSTR Prefix,
IN PPHYS_OPEN_FILE_INFO PhysOpenFileInfo,
IN ULONG ActualAddress
)
/*++
Routine Description:
Formats and dumps a specific PHYS_OPEN_FILE_INFO structure.
Arguments:
Prefix - The prefix to use before each printed line. This makes
hierarchical object displays much prettier.
PhysOpenFileInfo - Points to a local copy of the structure.
ActualAddress - The virtual address of the object in the debugee.
Return Value:
None.
--*/
{
dprintf(
"%sPHYS_OPEN_FILE_INFO @ %08lx\n"
"%s Signature = %08lx (%s)\n"
"%s hOpenFile = %08lx\n"
"%s hOpenEvent = %08lx\n",
Prefix,
ActualAddress,
Prefix,
PhysOpenFileInfo->Signature,
SignatureToString(
PhysOpenFileInfo->Signature,
PHYS_OBJ_SIGNATURE,
PHYS_OBJ_SIGNATURE_X
),
Prefix,
PhysOpenFileInfo->hOpenFile,
Prefix,
PhysOpenFileInfo->hOpenEvent
);
dprintf(
"%s OpenReferenceList @ %08lx%s\n"
"%s fSecurityDescriptor = %s\n"
"%s fIsCached = %s\n",
Prefix,
ActualAddress + FIELD_OFFSET( PHYS_OPEN_FILE_INFO, OpenReferenceList ),
IS_LIST_EMPTY( PhysOpenFileInfo, ActualAddress, PHYS_OPEN_FILE_INFO, OpenReferenceList )
? " (EMPTY)"
: "",
Prefix,
BoolToString( PhysOpenFileInfo->fSecurityDescriptor ),
Prefix,
BoolToString( PhysOpenFileInfo->fIsCached )
);
dprintf(
"%s dwLastError = %lu\n"
"%s cbSecDescMaxSize = %lu\n"
"%s abSecurityDescriptor = %08lx\n"
"%s pOplock = %08lx\n"
"\n",
Prefix,
PhysOpenFileInfo->dwLastError,
Prefix,
PhysOpenFileInfo->cbSecDescMaxSize,
Prefix,
PhysOpenFileInfo->abSecurityDescriptor,
Prefix,
PhysOpenFileInfo->pOplock
);
} // DumpPhysOpenFileInfo
VOID
DumpOplockObject(
IN PSTR Prefix,
IN POPLOCK_OBJECT OplockObject,
IN ULONG ActualAddress
)
/*++
Routine Description:
Formats and dumps a specific OPLOCK_OBJECT structure.
Arguments:
Prefix - The prefix to use before each printed line. This makes
hierarchical object displays much prettier.
OplockObject - Points to a local copy of the structure.
ActualAddress - The virtual address of the object in the debugee.
Return Value:
None.
--*/
{
dprintf(
"%sOPLOCK_OBJECT @ %08lx\n"
"%s Signature = %08lx (%s)\n"
"%s lpPFInfo = %08lx\n"
"%s hOplockInitComplete = %08lx\n"
"\n",
Prefix,
ActualAddress,
Prefix,
OplockObject->Signature,
SignatureToString(
OplockObject->Signature,
OPLOCK_OBJ_SIGNATURE,
OPLOCK_OBJ_SIGNATURE_X
),
Prefix,
OplockObject->lpPFInfo,
Prefix,
OplockObject->hOplockInitComplete
);
} // DumpOplockObject
VOID
DumpOpenFileInfoBlob(
IN PSTR Prefix,
IN PBLOB_HEADER BlobHeader,
IN ULONG ActualAddress
)
/*++
Routine Description:
Formats and dumps a TS_OPEN_FILE_INFO blob.
Arguments:
Prefix - The prefix to use before each printed line. This makes
hierarchical object displays much prettier.
BlobHeader - Points to a local copy of the blob.
ActualAddress - The virtual address of the object in the debugee.
Return Value:
None.
--*/
{
TS_OPEN_FILE_INFO localOpenFileInfo;
if( !ReadMemory(
ActualAddress + sizeof(*BlobHeader),
&localOpenFileInfo,
sizeof(localOpenFileInfo),
NULL
) ) {
dprintf(
"inetdbg: cannot read TS_OPEN_FILE_INFO @ %08lx\n",
ActualAddress + sizeof(*BlobHeader)
);
return;
}
DumpBlobHeader(
Prefix,
BlobHeader,
ActualAddress
);
DumpOpenFileInfo(
Prefix,
&localOpenFileInfo,
ActualAddress + sizeof(*BlobHeader)
);
} // DumpOpenFileInfoBlob
VOID
DumpUriInfoBlob(
IN PSTR Prefix,
IN PBLOB_HEADER BlobHeader,
IN ULONG ActualAddress
)
/*++
Routine Description:
Formats and dumps a W3_URI_INFO blob.
Arguments:
Prefix - The prefix to use before each printed line. This makes
hierarchical object displays much prettier.
BlobHeader - Points to a local copy of the blob.
ActualAddress - The virtual address of the object in the debugee.
Return Value:
None.
--*/
{
W3_URI_INFO localUriInfo;
if( !ReadMemory(
ActualAddress + sizeof(*BlobHeader),
&localUriInfo,
sizeof(localUriInfo),
NULL
) ) {
dprintf(
"inetdbg: cannot read W3_URI_INFO @ %08lx\n",
ActualAddress + sizeof(*BlobHeader)
);
return;
}
DumpBlobHeader(
Prefix,
BlobHeader,
ActualAddress
);
DumpUriInfo(
Prefix,
&localUriInfo,
ActualAddress + sizeof(*BlobHeader)
);
} // DumpUriInfoBlob
VOID
DumpPhysOpenFileInfoBlob(
IN PSTR Prefix,
IN PBLOB_HEADER BlobHeader,
IN ULONG ActualAddress
)
/*++
Routine Description:
Formats and dumps a PHYS_OPEN_FILE_INFO blob.
Arguments:
Prefix - The prefix to use before each printed line. This makes
hierarchical object displays much prettier.
BlobHeader - Points to a local copy of the blob.
ActualAddress - The virtual address of the object in the debugee.
Return Value:
None.
--*/
{
PHYS_OPEN_FILE_INFO localPhysOpenFileInfo;
if( !ReadMemory(
ActualAddress + sizeof(*BlobHeader),
&localPhysOpenFileInfo,
sizeof(localPhysOpenFileInfo),
NULL
) ) {
dprintf(
"inetdbg: cannot read PHYS_OPEN_FILE_INFO @ %08lx\n",
ActualAddress + sizeof(*BlobHeader)
);
return;
}
DumpBlobHeader(
Prefix,
BlobHeader,
ActualAddress
);
DumpPhysOpenFileInfo(
Prefix,
&localPhysOpenFileInfo,
ActualAddress + sizeof(*BlobHeader)
);
} // DumpPhysOpenFileInfo
VOID
DumpCacheObject(
IN PSTR Prefix,
IN PCACHE_OBJECT CacheObject,
IN ULONG ActualAddress,
IN BOOLEAN Verbose
)
/*++
Routine Description:
Formats and dumps a specific CACHE_OBJECT structure.
Arguments:
Prefix - The prefix to use before each printed line. This makes
hierarchical object displays much prettier.
CacheObject - Points to a local copy of the structure.
ActualAddress - The virtual address of the object in the debugee.
Verbose - If TRUE, then also dumps the blob associated with the object.
Return Value:
None.
--*/
{
BLOB_HEADER localBlob;
CHAR path[MAX_PATH+1];
path[0] = '\0';
if( CacheObject->cchLength < MAX_PATH ) {
ReadMemory(
ActualAddress + FIELD_OFFSET( CACHE_OBJECT, szPath ),
path,
CacheObject->cchLength,
NULL
);
path[CacheObject->cchLength] = '\0';
}
dprintf(
"%sCACHE_OBJECT @ %08lx\n"
"%s Signature = %08lx (%s)\n"
"%s BinList @ %08lx%s\n"
"%s MruList @ %08lx%s\n"
"%s DirChangeList @ %08lx%s\n",
Prefix,
ActualAddress,
Prefix,
CacheObject->Signature,
SignatureToString(
CacheObject->Signature,
CACHE_OBJ_SIGNATURE,
CACHE_OBJ_SIGNATURE_X
),
Prefix,
ActualAddress + FIELD_OFFSET( CACHE_OBJECT, BinList ),
IS_LIST_EMPTY( CacheObject, ActualAddress, CACHE_OBJECT, BinList )
? " (EMPTY)"
: "",
Prefix,
ActualAddress + FIELD_OFFSET( CACHE_OBJECT, MruList ),
IS_LIST_EMPTY( CacheObject, ActualAddress, CACHE_OBJECT, MruList )
? " (EMPTY)"
: "",
Prefix,
ActualAddress + FIELD_OFFSET( CACHE_OBJECT, DirChangeList ),
IS_LIST_EMPTY( CacheObject, ActualAddress, CACHE_OBJECT, DirChangeList )
? " (EMPTY)"
: ""
);
dprintf(
"%s pbhBlob = %08lx\n"
"%s references = %lu\n"
"%s TTL = %lu\n"
"%s hash = %08lx\n",
Prefix,
CacheObject->pbhBlob,
Prefix,
CacheObject->references,
Prefix,
CacheObject->TTL,
Prefix,
CacheObject->hash
);
dprintf(
"%s cchLength = %lu\n"
"%s iDemux = %08lx (%s)\n"
"%s dwService = %08lx\n"
"%s dwInstance = %08lx\n",
Prefix,
CacheObject->cchLength,
Prefix,
CacheObject->iDemux,
DemuxToString( CacheObject->iDemux ),
Prefix,
CacheObject->dwService,
Prefix,
CacheObject->dwInstance
);
dprintf(
"%s pSecDesc = %08lx\n"
"%s hLastSuccessAccessToken = %08lx\n"
"%s fZombie = %s\n"
"%s szPath = %s\n"
"\n",
Prefix,
CacheObject->pSecDesc,
Prefix,
CacheObject->hLastSuccessAccessToken,
Prefix,
BoolToString( CacheObject->fZombie ),
Prefix,
path
);
if( Verbose ) {
CHAR prefix[80];
sprintf(
prefix,
" %s",
Prefix
);
if( !ReadMemory(
(ULONG)CacheObject->pbhBlob,
&localBlob,
sizeof(localBlob),
NULL
) ) {
dprintf(
"inetdbg: cannot read blob header @ %08lx\n",
CacheObject->pbhBlob
);
return;
}
switch( CacheObject->iDemux ) {
case RESERVED_DEMUX_OPEN_FILE :
DumpOpenFileInfoBlob(
prefix,
&localBlob,
(ULONG)CacheObject->pbhBlob
);
break;
case RESERVED_DEMUX_URI_INFO :
DumpUriInfoBlob(
prefix,
&localBlob,
(ULONG)CacheObject->pbhBlob
);
break;
case RESERVED_DEMUX_PHYSICAL_OPEN_FILE :
DumpPhysOpenFileInfoBlob(
prefix,
&localBlob,
(ULONG)CacheObject->pbhBlob
);
break;
}
}
} // DumpCacheObject
VOID
DumpCacheObjectList(
IN PSTR ListName,
IN PLIST_ENTRY LocalListHead,
IN PLIST_ENTRY RemoteListHead,
IN BOOLEAN MruList,
IN BOOLEAN Verbose
)
/*++
Routine Description:
Formats and dumps a linked list of CACHE_OBJECTs.
Arguments:
Prefix - The prefix to use before each printed line. This makes
hierarchical object displays much prettier.
LocalListHead - Points to a local copy of the linked list head.
RemoteListHead - The virtual address of the linked list head in
the debugee.
MruList - TRUE if we're dumping the Mru list, FALSE if we're
dumping the Bin list.
Verbose - If TRUE, then be verbose.
Return Value:
None.
--*/
{
PLIST_ENTRY nextEntry;
PCACHE_OBJECT cacheObject;
CACHE_OBJECT localCacheObject;
dprintf(
"%s @ %08lx\n\n",
ListName,
RemoteListHead
);
nextEntry = LocalListHead->Flink;
while( nextEntry != RemoteListHead ) {
if( CheckControlC() ) {
break;
}
if( MruList ) {
cacheObject = CONTAINING_RECORD(
nextEntry,
CACHE_OBJECT,
MruList
);
} else {
cacheObject = CONTAINING_RECORD(
nextEntry,
CACHE_OBJECT,
BinList
);
}
if( !ReadMemory(
(ULONG)cacheObject,
&localCacheObject,
sizeof(localCacheObject),
NULL
) ) {
dprintf(
"inetdbg: cannot read CACHE_OBJECT @ %08lx\n",
cacheObject
);
return;
}
DumpCacheObject(
" ",
&localCacheObject,
(ULONG)cacheObject,
Verbose
);
if( MruList ) {
nextEntry = localCacheObject.MruList.Flink;
} else {
nextEntry = localCacheObject.BinList.Flink;
}
}
} // DumpCacheObjectList
VOID
DumpCacheTable(
IN PCACHE_TABLE CacheTable,
IN ULONG ActualAddress,
IN BOOLEAN DumpBin,
IN BOOLEAN DumpMru,
IN BOOLEAN Verbose
)
/*++
Routine Description:
Formats and dumps the entire cache table.
Arguments:
CacheTable - Points to a local copy of the cache table.
ActualAddress - The virtual address of the cache table in the debugee.
DumpBin - If TRUE, then dump the bin lists hanging off the cache table.
DumpMru - If TRUE, then dump the Mru list hanging off the cache table.
Verbose - If TRUE, then be verbose.
Return Value:
None.
--*/
{
LONG i;
//
// Dump simple data.
//
dprintf(
"CACHE_TABLE @ %08lx\n"
" CriticalSection @ %08lx\n",
ActualAddress,
ActualAddress + FIELD_OFFSET( CACHE_TABLE, CriticalSection )
);
if( CacheTable->CriticalSection.LockCount == -1 ) {
dprintf(
" LockCount = NOT LOCKED\n"
);
} else {
dprintf(
" LockCount = %lu\n",
CacheTable->CriticalSection.LockCount
);
}
dprintf(
" RecursionCount = %lu\n"
" OwningThread = %08lx\n",
CacheTable->CriticalSection.RecursionCount,
CacheTable->CriticalSection.OwningThread
);
//
// Only display the non-empty bins.
//
for( i = 0 ; i < MAX_BINS ; i++ ) {
CHAR tmp[sizeof("Items[1234567890]")];
if( !IS_LIST_EMPTY( CacheTable, ActualAddress, CACHE_TABLE, Items[i] ) ) {
sprintf(
tmp,
"Items[%lu]",
i
);
dprintf(
" %-18s @ %08lx\n",
tmp,
ActualAddress + FIELD_OFFSET( CACHE_TABLE, Items[i] )
);
}
}
dprintf(
" MruList @ %08lx%s\n"
" OpenFileInUse = %ld\n"
" MaxOpenFileInUse = %ld\n"
"\n",
ActualAddress + FIELD_OFFSET( CACHE_TABLE, MruList ),
IS_LIST_EMPTY( CacheTable, ActualAddress, CACHE_TABLE, MruList )
? " (EMPTY)"
: "",
CacheTable->OpenFileInUse,
CacheTable->MaxOpenFileInUse
);
//
// If requested, dump the individual entries in the bin & mru lists.
//
if( DumpBin ) {
for( i = 0 ; i < MAX_BINS ; i++ ) {
CHAR tmp[sizeof("Items[1234567890]")];
if( !IS_LIST_EMPTY( CacheTable, ActualAddress, CACHE_TABLE, Items[i] ) ) {
sprintf(
tmp,
"Items[%lu]",
i
);
DumpCacheObjectList(
tmp,
&CacheTable->Items[i],
(PLIST_ENTRY)( ActualAddress + FIELD_OFFSET( CACHE_TABLE, Items[i] ) ),
FALSE,
Verbose
);
}
}
}
if( DumpMru ) {
if( !IS_LIST_EMPTY( CacheTable, ActualAddress, CACHE_TABLE, MruList ) ) {
DumpCacheObjectList(
"MruList",
&CacheTable->MruList,
(PLIST_ENTRY)( ActualAddress + FIELD_OFFSET( CACHE_TABLE, MruList ) ),
TRUE,
Verbose
);
}
}
} // DumpCacheTable
//
// NTSD extension entrypoints.
//
DECLARE_API( fcache )
/*++
Routine Description:
This function is called as an NTSD extension to format and dump
the entire open file cache or a single cache object.
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.
--*/
{
ULONG address;
CACHE_OBJECT cacheObject;
CACHE_TABLE cacheTable;
BOOLEAN dumpBin;
BOOLEAN dumpMru;
BOOLEAN verbose;
INIT_API();
//
// Establish defaults.
//
dumpBin = FALSE;
dumpMru = FALSE;
verbose = FALSE;
//
// Skip any leading blanks.
//
while( *lpArgumentString == ' ' ||
*lpArgumentString == '\t' ) {
lpArgumentString++;
}
//
// Process switches.
//
while( *lpArgumentString == '-' ) {
lpArgumentString++;
while( *lpArgumentString != ' ' &&
*lpArgumentString != '\t' &&
*lpArgumentString != '\0' ) {
switch( *lpArgumentString ) {
case 'v' :
case 'V' :
verbose = !verbose;
break;
case 'b' :
case 'B' :
dumpBin = !dumpBin;
break;
case 'm' :
case 'M' :
dumpMru = !dumpMru;
break;
case '-' : // Set the switches the way I like them. --keithmo
verbose = TRUE;
dumpBin = TRUE;
dumpMru = FALSE;
break;
default :
dprintf(
"use: inetdbg.fcache [options] [address]\n"
);
return;
}
lpArgumentString++;
}
while( *lpArgumentString == ' ' ||
*lpArgumentString == '\t' ) {
lpArgumentString++;
}
}
if( *lpArgumentString != '\0' ) {
//
// Dump a single object.
//
address = GetExpression( lpArgumentString );
if( address == 0 ) {
dprintf(
"inetdbg: cannot evaluate \"%s\"\n",
lpArgumentString
);
return;
}
//
// Read the cache object.
//
if( !ReadMemory(
(ULONG)address,
&cacheObject,
sizeof(cacheObject),
NULL
) ) {
dprintf(
"inetdbg: cannot read CACHE_OBJECT @ %lx\n",
address
);
return;
}
DumpCacheObject(
"",
&cacheObject,
address,
verbose
);
return;
}
//
// Dump the entire cache table.
//
address = GetExpression( "infocomm!CacheTable" );
if( address == 0 ) {
dprintf(
"inetdbg: cannot find infocomm!CacheTable\n"
);
return;
}
if( !ReadMemory(
(ULONG)address,
&cacheTable,
sizeof(cacheTable),
NULL
) ) {
dprintf(
"inetdbg: cannot read CACHE_TABLE @ %08lx\n",
address
);
return;
}
DumpCacheTable(
&cacheTable,
address,
dumpBin,
dumpMru,
verbose
);
} // DECLARE_API( fcache )
DECLARE_API( open )
/*++
Routine Description:
This function is called as an NTSD extension to format and dump
a specific TS_OPEN_FILE_INFO 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.
--*/
{
ULONG address;
TS_OPEN_FILE_INFO openFileInfo;
INIT_API();
//
// Skip any leading blanks.
//
while( *lpArgumentString == ' ' ||
*lpArgumentString == '\t' ) {
lpArgumentString++;
}
if( *lpArgumentString == '\0' ) {
dprintf(
"use: inetdbg.open address\n"
);
return;
}
address = GetExpression( lpArgumentString );
if( address == 0 ) {
dprintf(
"inetdbg: cannot evaluate \"%s\"\n",
lpArgumentString
);
return;
}
//
// Read the object.
//
if( !ReadMemory(
(ULONG)address,
&openFileInfo,
sizeof(openFileInfo),
NULL
) ) {
dprintf(
"inetdbg: cannot read TS_OPEN_FILE_INFO @ %lx\n",
address
);
return;
}
DumpOpenFileInfo(
"",
&openFileInfo,
address
);
} // DECLARE_API( open )
DECLARE_API( uri )
/*++
Routine Description:
This function is called as an NTSD extension to format and dump
a specific W3_URI_INFO 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.
--*/
{
ULONG address;
W3_URI_INFO uriInfo;
INIT_API();
//
// Skip any leading blanks.
//
while( *lpArgumentString == ' ' ||
*lpArgumentString == '\t' ) {
lpArgumentString++;
}
if( *lpArgumentString == '\0' ) {
dprintf(
"use: inetdbg.uri address\n"
);
return;
}
address = GetExpression( lpArgumentString );
if( address == 0 ) {
dprintf(
"inetdbg: cannot evaluate \"%s\"\n",
lpArgumentString
);
return;
}
//
// Read the object.
//
if( !ReadMemory(
(ULONG)address,
&uriInfo,
sizeof(uriInfo),
NULL
) ) {
dprintf(
"inetdbg: cannot read W3_URI_INFO @ %lx\n",
address
);
return;
}
DumpUriInfo(
"",
&uriInfo,
address
);
} // DECLARE_API( uri )
DECLARE_API( phys )
/*++
Routine Description:
This function is called as an NTSD extension to format and dump
a specific PHYS_OPEN_FILE_INFO 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.
--*/
{
ULONG address;
PHYS_OPEN_FILE_INFO physOpenFileInfo;
INIT_API();
//
// Skip any leading blanks.
//
while( *lpArgumentString == ' ' ||
*lpArgumentString == '\t' ) {
lpArgumentString++;
}
if( *lpArgumentString == '\0' ) {
dprintf(
"use: inetdbg.phys address\n"
);
return;
}
address = GetExpression( lpArgumentString );
if( address == 0 ) {
dprintf(
"inetdbg: cannot evaluate \"%s\"\n",
lpArgumentString
);
return;
}
//
// Read the object.
//
if( !ReadMemory(
(ULONG)address,
&physOpenFileInfo,
sizeof(physOpenFileInfo),
NULL
) ) {
dprintf(
"inetdbg: cannot read PHYS_OPEN_FILE_INFO @ %lx\n",
address
);
return;
}
DumpPhysOpenFileInfo(
"",
&physOpenFileInfo,
address
);
} // DECLARE_API( phys )
DECLARE_API( oplock )
/*++
Routine Description:
This function is called as an NTSD extension to format and dump
a specific OPLOCK_OBJECT 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.
--*/
{
ULONG address;
OPLOCK_OBJECT oplockObject;
INIT_API();
//
// Skip any leading blanks.
//
while( *lpArgumentString == ' ' ||
*lpArgumentString == '\t' ) {
lpArgumentString++;
}
if( *lpArgumentString == '\0' ) {
dprintf(
"use: inetdbg.oplock address\n"
);
return;
}
address = GetExpression( lpArgumentString );
if( address == 0 ) {
dprintf(
"inetdbg: cannot evaluate \"%s\"\n",
lpArgumentString
);
return;
}
//
// Read the object.
//
if( !ReadMemory(
(ULONG)address,
&oplockObject,
sizeof(oplockObject),
NULL
) ) {
dprintf(
"inetdbg: cannot read OPLOCK_OBJECT @ %lx\n",
address
);
return;
}
DumpOplockObject(
"",
&oplockObject,
address
);
} // DECLARE_API( oplock )
DECLARE_API( blob )
/*++
Routine Description:
This function is called as an NTSD extension to format and dump
a specific BLOB_HEADER 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.
--*/
{
ULONG address;
BLOB_HEADER blobHeader;
INIT_API();
//
// Skip any leading blanks.
//
while( *lpArgumentString == ' ' ||
*lpArgumentString == '\t' ) {
lpArgumentString++;
}
if( *lpArgumentString == '\0' ) {
dprintf(
"use: inetdbg.blob address\n"
);
return;
}
address = GetExpression( lpArgumentString );
if( address == 0 ) {
dprintf(
"inetdbg: cannot evaluate \"%s\"\n",
lpArgumentString
);
return;
}
//
// Read the object.
//
if( !ReadMemory(
(ULONG)address,
&blobHeader,
sizeof(blobHeader),
NULL
) ) {
dprintf(
"inetdbg: cannot read BLOB_HEADER @ %lx\n",
address
);
return;
}
DumpBlobHeader(
"",
&blobHeader,
address
);
} // DECLARE_API( blob )