494 lines
9.1 KiB
C
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
|
||
|
|
||
|
|