1895 lines
37 KiB
C++
1895 lines
37 KiB
C++
|
/*++
|
|||
|
|
|||
|
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 )
|
|||
|
|