windows-nt/Source/XPSP1/NT/inetsrv/iis/iisrearc/ul/ulkd/filt.c
2020-09-26 16:20:57 +08:00

494 lines
9.1 KiB
C

/*++
Copyright (c) 2000-2001 Microsoft Corporation
Module Name:
filt.c
Abstract:
Extensions for dumping filter information.
Author:
Michael Courage (mcourage) 6-Apr-2000
Environment:
User Mode.
Revision History:
--*/
#include "precomp.h"
//
// Private globals.
//
PSTR g_pFiltqActions[] =
{
"QUEUE_IRP ",
"DEQUEUE_IRP ",
"START_WRITE ",
"FINISH_WRITE ",
"BLOCK_WRITE ",
"WAKE_WRITE ",
"BLOCK_PARTIAL_WRITE",
"WAKE_PARTIAL_WRITE "
};
C_ASSERT( DIM(g_pFiltqActions) == FILTQ_ACTION_COUNT );
//
// Public functions.
//
DECLARE_API( filter )
/*++
Routine Description:
Dumps a filter channel.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG_PTR address = 0;
ULONG result;
UL_FILTER_CHANNEL channel;
SNAPSHOT_EXTENSION_DATA();
//
// Snag the address from the command line.
//
address = GetExpression( args );
if (address == 0)
{
address = GetExpression( "&http!g_pFilterChannel" );
}
if (address != 0)
{
if (!ReadMemory(
address,
&address,
sizeof(address),
NULL
))
{
dprintf(
"filter: Cannot read memory @ %p\n",
address
);
return;
}
}
if (address == 0)
{
PrintUsage( "filter" );
return;
}
//
// Read the filter.
//
if (!ReadMemory(
address,
&channel,
sizeof(channel),
&result
))
{
dprintf(
"filter: cannot read UL_FILTER_CHANNEL @ %p\n",
address
);
return;
}
DumpFilterChannel(
"",
"filter: ",
address,
&channel,
0
);
} // filter
DECLARE_API( fproc )
/*++
Routine Description:
Dumps a filter process.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG_PTR address = 0;
ULONG result;
UL_FILTER_PROCESS process;
SNAPSHOT_EXTENSION_DATA();
//
// Snag the address from the command line.
//
address = GetExpression( args );
if (address == 0)
{
PrintUsage( "fproc" );
return;
}
//
// Read the filter proc.
//
if (!ReadMemory(
address,
&process,
sizeof(process),
&result
))
{
dprintf(
"fproc: cannot read UL_FILTER_PROCESS @ %p\n",
address
);
return;
}
DumpFilterProc(
"",
"fproc: ",
address,
&process,
0
);
} // fproc
DECLARE_API( fqlog )
/*++
Routine Description:
Dumps the filter queue trace log.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG_PTR address = 0;
ULONG_PTR context = 0;
ULONG_PTR flags = 0;
ULONG_PTR entryAddress;
ULONG_PTR logPointer;
ULONG result;
TRACE_LOG logHeader;
LONGLONG numEntries;
FILTQ_TRACE_LOG_ENTRY logEntry;
PSTR pAction;
LONGLONG index;
ULONG offset1;
ULONG offset2;
CHAR invalidAction[sizeof("2047")];
PSTR fileName;
CHAR filePath[MAX_PATH];
SNAPSHOT_EXTENSION_DATA();
//
// Snag the optional context from the command line.
//
context = GetExpression( args );
//
// Find the log.
//
address = GetExpression( "&http!g_pFilterQueueTraceLog" );
if (address == 0)
{
dprintf( "fqlog: cannot find http!g_pFilterQueueTraceLog\n" );
return;
}
//
// Read the pointer.
//
if (!ReadMemory(
address,
&logPointer,
sizeof(logPointer),
&result
))
{
dprintf(
"fqlog: cannot read PTRACE_LOG @ %p\n",
address
);
return;
}
//
// Read the log header.
//
if (!ReadMemory(
logPointer,
&logHeader,
sizeof(logHeader),
&result
))
{
dprintf(
"fqlog: cannot read TRACE_LOG @ %p\n",
logPointer
);
return;
}
dprintf(
"fqlog: log @ %p\n"
" Signature = %08lx '%c%c%c%c' (%s)\n"
" TypeSignature = %08lx '%c%c%c%c'\n"
" LogSize = %lu\n"
" NextEntry = %I64d\n"
" EntrySize = %lu\n"
" LogBuffer = %p\n",
address,
logHeader.Signature,
DECODE_SIGNATURE(logHeader.Signature),
logHeader.Signature == TRACE_LOG_SIGNATURE
? "OK"
: logHeader.Signature == TRACE_LOG_SIGNATURE_X
? "FREED"
: "INVALID",
logHeader.TypeSignature,
DECODE_SIGNATURE(logHeader.TypeSignature),
logHeader.LogSize,
logHeader.NextEntry,
logHeader.EntrySize,
logHeader.pLogBuffer
);
if (logHeader.pLogBuffer > ( (PUCHAR)address + sizeof(logHeader) ))
{
dprintf(
" ExtraData @ %p\n",
address + sizeof(logHeader)
);
}
if (logHeader.Signature != TRACE_LOG_SIGNATURE &&
logHeader.Signature != TRACE_LOG_SIGNATURE_X)
{
dprintf(
"fqlog: log @ %p has invalid signature %08lx:\n",
address,
logHeader.Signature
);
return;
}
if (logHeader.EntrySize != sizeof(logEntry)
|| logHeader.TypeSignature != FILTQ_TRACE_LOG_SIGNATURE)
{
dprintf(
"fqlog: log @ %p is not a filter queue trace log\n",
address
);
return;
}
if (logHeader.NextEntry == -1)
{
dprintf(
"fqlog: empty log @ %p\n",
address
);
return;
}
//
// Calculate the log size to dump.
//
if (logHeader.NextEntry < logHeader.LogSize)
{
numEntries = logHeader.NextEntry + 1;
index = 0;
}
else
{
numEntries = logHeader.LogSize;
index = (logHeader.NextEntry + 1) % logHeader.LogSize;
}
entryAddress = (ULONG_PTR)logHeader.pLogBuffer +
(ULONG_PTR)( index * sizeof(logEntry) );
if (entryAddress >=
( (ULONG_PTR)logHeader.pLogBuffer + (ULONG_PTR)( numEntries * sizeof(logEntry) ) ) )
{
dprintf(
"fqlog: log @ %p has invalid data\n",
address
);
return;
}
//
// Dump the log.
//
for (;
numEntries > 0 ;
index++,
numEntries--,
entryAddress += sizeof(logEntry))
{
if (CheckControlC())
{
break;
}
if (index >= logHeader.LogSize)
{
index = 0;
entryAddress = (ULONG_PTR)logHeader.pLogBuffer;
}
if (!ReadMemory(
entryAddress,
&logEntry,
sizeof(logEntry),
NULL
))
{
dprintf(
"fqlog: cannot read memory @ %p\n",
entryAddress
);
return;
}
if (context == 0 ||
context == (ULONG_PTR)logEntry.pConnection)
{
//
// Grab the file name.
//
if (ReadMemory(
(ULONG_PTR)logEntry.pFileName,
filePath,
sizeof(filePath),
&result
))
{
fileName = strrchr( filePath, '\\' );
if (fileName != NULL)
{
fileName++;
}
else
{
fileName = filePath;
}
}
else
{
sprintf(
filePath,
"%p",
logEntry.pFileName
);
fileName = filePath;
}
//
// And the action name.
//
if (logEntry.Action < FILTQ_ACTION_COUNT)
{
pAction = g_pFiltqActions[logEntry.Action];
}
else
{
sprintf( invalidAction, "%lu", (ULONG)logEntry.Action );
pAction = invalidAction;
}
dprintf(
"CPU=%lu Conn=%p Act=%s ReadIrps=%lu Writers=%lu, %s:%u\n",
logEntry.Processor,
logEntry.pConnection,
pAction,
logEntry.ReadIrps,
logEntry.Writers,
fileName,
logEntry.LineNumber
);
}
}
} // fqlog