windows-nt/Source/XPSP1/NT/base/tools/kdexts2/lpc.c

1324 lines
30 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
lpc.c
Abstract:
WinDbg Extension Api
Author:
Ramon J San Andres (ramonsa) 8-Nov-1993
Environment:
User Mode.
Revision History:
Adrian Marinescu (adrmarin) 20-April-1999
Change the most of the original code.
To activate the previous extension define OLD_LPC_EXTENSION_IS_BETTER
--*/
#include "precomp.h"
#pragma hdrstop
//
// Nuke these definitions from kxmips.h as they conflict with
// LPC_MESSAGE structure in ntlpcapi.h
//
#undef s1
#undef s2
char *LpcpMessageTypeName[] = {
"UNUSED_MSG_TYPE",
"LPC_REQUEST",
"LPC_REPLY",
"LPC_DATAGRAM",
"LPC_LOST_REPLY",
"LPC_PORT_CLOSED",
"LPC_CLIENT_DIED",
"LPC_EXCEPTION",
"LPC_DEBUG_EVENT",
"LPC_ERROR_EVENT",
"LPC_CONNECTION_REQUEST"
};
typedef BOOLEAN (*ENUM_TYPE_ROUTINE)(
IN ULONG64 pObjectHeader,
IN PVOID Parameter
);
VOID
DumpPortInfo (
ULONG64 PortObject,
BOOLEAN DisplayRelated
);
BOOLEAN
LpcpDumpMessage(
IN char *Indent,
IN ULONG64 pMsg,
IN ULONG DisplayMessage
);
VOID
LpcpGetProcessImageName (
IN ULONG64 pProcess,
IN OUT PUCHAR ImageFileName
);
VOID
DumpMessagesInfo ();
VOID
SearchForMessage (
ULONG Message
);
VOID
DumpPortDataInfo (
ULONG64 PortObject
);
VOID
DumpRunDownQueue (
ULONG64 PortObject
);
VOID
SearchThreadsForMessage (
ULONG Message
);
BOOLEAN
SearchThreads (
ULONG64 Thread
);
//
// Global variables
//
static WCHAR ObjectNameBuffer[ MAX_PATH ];
static ULONG64 PortObjectFound = 0;
static ULONG64 LpcPortObjectType = 0;
static ULONG64 LpcWaitablePortObjectType = 0;
static ULONG64 LastSeverPortDisplayied = 0;
static int DoPoolSearch = 0;
ULONG GetValueAt(
ULONG64 P
)
{
ULONG Result;
ULONG Value;
if (!ReadMemory( P,
&Value,
sizeof(Value),
&Result)) {
dprintf( " Failed to read value at 0x%lx\n", P );
return 0;
}
return Value;
}
BOOLEAN GetBooleanValueAt(
ULONG64 P
)
{
ULONG Result;
BOOLEAN Value;
if (!ReadMemory( P,
&Value,
sizeof(Value),
&Result)) {
dprintf( " Failed to read value at 0x%lx\n", P );
return 0;
}
return Value;
}
VOID
LpcHelp ()
{
dprintf("Usage:\n\
!lpc - Display this help\n\
!lpc message [MessageId] - Display the message with a given ID and all related information\n\
If MessageId is not specified, dump all messages\n\
!lpc port [PortAddress] - Display the port information\n\
!lpc scan PortAddress - Search this port and any connected port\n\
!lpc thread [ThreadAddr] - Search the thread in rundown port queues and display the port info\n\
If ThreadAddr is missing, display all threads marked as doing some lpc operations\n\
!lpc PoolSearch - Toggle ON / OFF searching the current message in the kernel pool\n\
\n");
}
ULONG64
LookupProcessUniqueId (
HANDLE UniqueId
)
{
ULONG64 ProcessHead, Process;
ULONG64 ProcessNext;
ULONG Off;
//
// Get the process list head
//
ProcessHead = GetExpression( "nt!PsActiveProcessHead" );
if (!ProcessHead) {
return 0;
}
ReadPointer(ProcessHead, &ProcessNext);
//
// Walk through the list and find the process with the desired Id
//
GetFieldOffset("nt!EPROCESS", "ActiveProcessLinks", &Off);
while(ProcessNext != 0 && ProcessNext != ProcessHead) {
ULONG64 Id;
Process = ProcessNext - Off;
if (GetFieldValue(Process, "nt!EPROCESS", "UniqueProcessId", Id)) {
dprintf("Cannot read EPROCESS at %p\n", Process);
}
if (UniqueId == (HANDLE) Id) {
return Process;
}
ReadPointer(ProcessNext, &ProcessNext);
if (CheckControlC()) {
return 0;
}
}
return 0;
}
BOOLEAN
FetchGlobalVariables()
{
//
// Save the LPC object type information
//
LpcPortObjectType = GetPointerValue("nt!LpcPortObjectType") ;
if (!LpcPortObjectType) {
dprintf("Reading LpcPortObjectType failed\n");
}
LpcWaitablePortObjectType = GetPointerValue("nt!LpcWaitablePortObjectType") ;
if (!LpcWaitablePortObjectType) {
dprintf("Reading LpcWaitablePortObjectType failed\n");
}
return TRUE;
}
BOOLEAN
LpcWalkObjectsByType(
IN ULONG64 pObjectType,
IN ENUM_TYPE_ROUTINE EnumRoutine,
IN PVOID Parameter
)
{
ULONG Result;
ULONG64 Head, Next;
ULONG64 pObjectHeader;
BOOLEAN WalkingBackwards;
ULONG64 pCreatorInfo, ObjBlink;
ULONG TotalNumberOfObjects, Off, CreatorOff, SizeOfCreat;
if (pObjectType == 0) {
return FALSE;
}
if ( GetFieldValue( pObjectType,"nt!OBJECT_TYPE",
"TotalNumberOfObjects", TotalNumberOfObjects) ) {
dprintf( "%08p: Unable to read object type\n", pObjectType );
return FALSE;
}
dprintf( "Scanning %u objects\n", TotalNumberOfObjects & 0x00FFFFFF);
GetFieldOffset("nt!OBJECT_TYPE", "TypeList", &Off);
GetFieldOffset("nt!OBJECT_HEADER_CREATOR_INFO", "TypeList", &CreatorOff);
SizeOfCreat = GetTypeSize("OBJECT_HEADER_CREATOR_INFO");
Head = pObjectType + Off;
GetFieldValue(Head, "nt!_LIST_ENTRY", "Flink", Next);
GetFieldValue(Head, "nt!_LIST_ENTRY", "Blink", ObjBlink);
WalkingBackwards = FALSE;
if ((TotalNumberOfObjects & 0x00FFFFFF) != 0 && Next == Head) {
dprintf( "*** objects of the same type are only linked together if the %x flag is set in NtGlobalFlags\n",
FLG_MAINTAIN_OBJECT_TYPELIST
);
return TRUE;
}
while (Next != Head) {
ULONG64 Flink, Blink;
if ( GetFieldValue(Next, "nt!_LIST_ENTRY", "Flink", Flink) ||
GetFieldValue(Next, "nt!_LIST_ENTRY", "Blink", Blink)) {
if (WalkingBackwards) {
dprintf( "%08p: Unable to read object type list\n", Next );
return FALSE;
}
//
// Switch to walk in reverse direction
//
WalkingBackwards = TRUE ;
Next = ObjBlink;
dprintf( "%08lx: Switch to walking backwards\n", Next );
continue;
}
pCreatorInfo = ( Next - CreatorOff );
pObjectHeader = (pCreatorInfo + SizeOfCreat);
if ( GetFieldValue( pObjectHeader,"nt!OBJECT_HEADER","Flags", Result) ) {
dprintf( "%08p: Not a valid object header\n", pObjectHeader );
return FALSE;
}
if (!(EnumRoutine)( pObjectHeader, Parameter )) {
return FALSE;
}
if ( CheckControlC() ) {
return FALSE;
}
if (WalkingBackwards) {
Next = Blink;
} else {
Next = Flink;
}
}
return TRUE;
}
BOOLEAN
LpcCaptureObjectName(
IN ULONG64 pObjectHeader,
IN PWSTR Buffer,
IN ULONG BufferSize
)
{
ULONG Result;
PWSTR s1 = L"*** unable to get object name";
ULONG64 pNameInfo;
UNICODE_STRING64 ObjectName;
Buffer[ 0 ] = UNICODE_NULL;
KD_OBJECT_HEADER_TO_NAME_INFO( pObjectHeader, &pNameInfo );
if (pNameInfo == 0) {
return TRUE;
}
if ( GetFieldValue( pNameInfo, "nt!OBJECT_HEADER_NAME_INFO",
"Name.Length", ObjectName.Length) ) {
wcscpy( Buffer, s1 );
return FALSE;
}
GetFieldValue( pNameInfo, "nt!OBJECT_HEADER_NAME_INFO","Name.Buffer", ObjectName.Buffer);
ObjectName.MaximumLength = ObjectName.Length;
if (ObjectName.Length >= BufferSize ) {
ObjectName.Length = (unsigned short)BufferSize - sizeof( UNICODE_NULL );
}
if (ObjectName.Length != 0) {
if (!ReadMemory( ObjectName.Buffer,
Buffer,
ObjectName.Length,
&Result
)) {
wcscpy( Buffer, s1 );
} else {
Buffer[ ObjectName.Length / sizeof( WCHAR ) ] = UNICODE_NULL;
}
}
return TRUE;
}
VOID
LpcpGetProcessImageName(
IN ULONG64 pProcess,
IN OUT PUCHAR ImageFileName
)
{
ULONG Result;
UCHAR local[32];
PUCHAR s;
int i;
if (pProcess != 0) {
if (!GetFieldValue( pProcess,"nt!EPROCESS",
"ImageFileName", local)) {
i = 16;
s = local;
while (i--) {
if (*s == '\0') {
if (i == 15) {
i = 0;
}
break;
}
if (*s < ' ' || *s >= '|') {
i = 0;
break;
}
s += 1;
}
if (i != 0) {
strcpy( ImageFileName, local );
return;
}
}
}
sprintf( ImageFileName, "" );
return;
}
#define LPCP_ZONE_MESSAGE_ALLOCATED (USHORT)0x8000
BOOLEAN
LpcpDumpMessage(
IN char *Indent,
IN ULONG64 pMsg,
IN ULONG DisplayMessage
)
{
ULONG Result;
ULONG i;
ULONG cb;
ULONG MsgData[ 8 ];
UCHAR ImageFileName[ 32 ];
ULONG MessageId0, Off, SizeOfMsg, DataLength;
BOOLEAN MessageMatch = FALSE;
if ( GetFieldValue( pMsg, "LPCP_MESSAGE",
"Request.MessageId", MessageId0) ) {
dprintf( "%s*** unable to read LPC message at %08p\n", Indent, pMsg );
return MessageMatch;
}
if (DisplayMessage != 0) {
if (DisplayMessage == MessageId0) {
MessageMatch = TRUE;
} else {
return FALSE;
}
}
GetFieldOffset("LPCP_MESSAGE", "Entry", &Off);
SizeOfMsg = GetTypeSize("LPCP_MESSAGE");
InitTypeRead(pMsg, LPCP_MESSAGE);
if (MessageId0 == 0) {
dprintf( "%s%04x %08x - %s Id=%04x From: %04p.%04p\n",
Indent,
(ULONG) ReadField(ZoneIndex) & ~LPCP_ZONE_MESSAGE_ALLOCATED,
pMsg,
(ULONG) ReadField(Reserved0) != 0 ? "Busy" : "Free",
MessageId0,
ReadField(Request.ClientId.UniqueProcess),
ReadField(Request.ClientId.UniqueThread)
);
return MessageMatch;
}
//
// Getting the process image affect dramaticaly the performances
//
// LpcpGetProcessImageName( LookupProcessUniqueId(Msg.Request.ClientId.UniqueProcess), ImageFileName );
dprintf( "%s%s%04lx %p - %s Id=%08lx From: %04p.%04p Context=%08p",
Indent,
MessageId0 == DisplayMessage ? "*" : "",
(ULONG) ReadField(ZoneIndex) & ~LPCP_ZONE_MESSAGE_ALLOCATED,
pMsg,
(ULONG) ReadField(Reserved0) != 0 ? "Busy" : "Free",
MessageId0,
ReadField(Request.ClientId.UniqueProcess),
ReadField(Request.ClientId.UniqueThread),
ReadField(PortContext)
);
if (ReadField(Entry.Flink) != pMsg + Off) {
dprintf( " [%p . %p]", ReadField(Entry.Blink), ReadField(Entry.Flink) );
}
dprintf( "\n%s Length=%08x Type=%08x (%s)\n",
Indent,
(ULONG) ReadField(Request.u1.Length),
(ULONG) ReadField(Request.u2.ZeroInit),
(ULONG) ReadField(Request.u2.s2.Type) > LPC_CONNECTION_REQUEST ? LpcpMessageTypeName[ 0 ]
: LpcpMessageTypeName[ (ULONG) ReadField(Request.u2.s2.Type) ]
);
cb = (DataLength = (ULONG) ReadField(Request.u1.s1.DataLength)) > sizeof( MsgData ) ?
sizeof( MsgData ) :
DataLength;
if ( !ReadMemory( (pMsg + SizeOfMsg),
MsgData,
cb,
&Result) ) {
dprintf( "%s*** unable to read LPC message data at %08x\n", Indent, pMsg + 1 );
return MessageMatch;
}
dprintf( "%s Data:", Indent );
for (i=0; i<(DataLength / sizeof( ULONG )); i++) {
if (i > 5) {
break;
}
dprintf( " %08x", MsgData[ i ] );
}
dprintf( "\n" );
return MessageMatch;
}
BOOLEAN
FindPortCallback(
IN ULONG64 pObjectHeader,
IN PVOID Parameter
)
{
ULONG Result;
WCHAR CapturedName[MAX_PATH];
ULONG64 PortObject, ConnectionPort;
ULONG64 Addr=0;
if (Parameter) Addr = *((PULONG64) Parameter);
PortObject = KD_OBJECT_HEADER_TO_OBJECT(pObjectHeader);
if ( GetFieldValue( PortObject,
"nt!LPCP_PORT_OBJECT",
"ConnectionPort",
ConnectionPort) ) {
dprintf( "%08p: Unable to read port object\n", PortObject );
}
InitTypeRead(PortObject, LPCP_PORT_OBJECT);
if ((Addr == 0)||
(Addr == PortObject) ||
(Addr == ConnectionPort) ||
(Addr == ReadField(ConnectedPort))
) {
LpcCaptureObjectName( pObjectHeader, ObjectNameBuffer, MAX_PATH );
dprintf( "%8lx Port: 0x%08p Connection: 0x%08p Communication: 0x%08p '%ws' \n",
(ULONG) ReadField(Flags),
PortObject,
ConnectionPort,
ReadField(ConnectedPort),
ObjectNameBuffer
);
DumpRunDownQueue(PortObject);
}
return TRUE;
}
VOID
DumpServerPort(
ULONG64 PortObject,
ULONG64 PortInfo
)
{
ULONG SemaphoreBuffer[8];
ULONG64 Head, Next;
ULONG Result;
ULONG64 Msg;
ULONG MsgCount;
ULONG64 pObjectHeader;
UCHAR ImageFileName[ 32 ];
ULONG HandleCount, PointerCount;
if (LastSeverPortDisplayied == PortObject) {
//
// This port was already displayied
//
return;
}
LastSeverPortDisplayied = PortObject;
pObjectHeader = KD_OBJECT_TO_OBJECT_HEADER(PortObject);
if ( GetFieldValue(pObjectHeader, "nt!OBJECT_HEADER", "HandleCount", HandleCount) ) {
dprintf(" *** %08p: Unable to read object header\n", pObjectHeader );
}
GetFieldValue(pObjectHeader, "nt!OBJECT_HEADER", "PointerCount",PointerCount);
LpcCaptureObjectName( pObjectHeader, ObjectNameBuffer, MAX_PATH );
dprintf( "\n");
dprintf( "Server connection port %08p Name: %ws\n", PortObject , ObjectNameBuffer);
dprintf( " Handles: %ld References: %ld\n", HandleCount, PointerCount);
InitTypeRead(PortInfo, LPCP_PORT_OBJECT);
LpcpGetProcessImageName( ReadField(ServerProcess), ImageFileName );
dprintf( " Server process : %08p (%s)\n", ReadField(ServerProcess), ImageFileName);
dprintf( " Queue semaphore : %08p\n", ReadField(MsgQueue.Semaphore) );
if ( !ReadMemory( ReadField(MsgQueue.Semaphore),
&SemaphoreBuffer,
sizeof( SemaphoreBuffer ),
&Result) ) {
dprintf(" *** %08p: Unable to read semaphore contents\n", ReadField(MsgQueue.Semaphore) );
}
else {
ULONG Off;
dprintf( " Semaphore state %ld (0x%lx) \n", SemaphoreBuffer[1], SemaphoreBuffer[1] );
//
// Walk list of messages queued to this port. Remove each message from
// the list and free it.
//
GetFieldOffset("nt!LPCP_PORT_OBJECT", "MsgQueue.ReceiveHead", &Off);
Head = PortObject + Off;
if (Head) {
if ( !ReadPointer( Head, &Next ) ) {
dprintf( " Failed to read Head 0x%p\n", Head );
return;
}
MsgCount = 0;
while ((Next != 0) && (Next != Head)) {
if (MsgCount == 0) {
dprintf (" Messages in queue:\n");
}
Msg = Next;
LpcpDumpMessage(" ", Msg, 0);
if ( !ReadPointer( Next, &Next ) ) {
dprintf( " Error reading 0x%p\n", Next );
return;
}
MsgCount++;
if ( CheckControlC() ) {
return;
}
}
if (MsgCount) {
dprintf( " The message queue contains %ld messages\n", MsgCount );
}
else {
dprintf( " The message queue is empty\n");
}
}
DumpPortDataInfo(PortObject);
DumpRunDownQueue(PortObject);
}
}
VOID
DumpPortDataInfo(
ULONG64 PortObject
)
{
ULONG64 Head, Next;
ULONG64 Msg;
ULONG MsgCount, Off, EntryOff;
GetFieldOffset("nt!LPCP_MESSAGE", "Entry", &EntryOff);
GetFieldOffset("nt!LPCP_PORT_OBJECT", "LpcDataInfoChainHead.Flink", &Off);
Head = PortObject + Off;
if (Head) {
ReadPointer( Head, &Next );
MsgCount = 0;
while ((Next != 0) && (Next != Head)) {
if (MsgCount == 0) {
dprintf ("\n Messages in LpcDataInfoChainHead:\n");
}
Msg = ( Next - EntryOff );
LpcpDumpMessage(" ", Msg, 0);
ReadPointer( Next, &Next );
MsgCount++;
if ( CheckControlC() ) {
return;
}
}
if (MsgCount) {
dprintf( " The LpcDataInfoChainHead queue contains %ld messages\n", MsgCount );
}
else {
dprintf( " The LpcDataInfoChainHead queue is empty\n");
}
}
}
VOID
DumpRunDownQueue(
ULONG64 PortObject
)
{
ULONG64 Head, Next;
ULONG64 Thread;
ULONG Count;
ULONG Off, ChainOff;
GetFieldOffset("nt!ETHREAD", "LpcReplyChain", &ChainOff);
GetFieldOffset("nt!LPCP_PORT_OBJECT", "LpcDataInfoChainHead.Flink", &Off);
Head = PortObject + Off;
ReadPointer( Head, &Next);
Count = 0;
while ((Next != 0) && (Next != Head)) {
if (Count == 0) {
dprintf (" Threads in RunDown queue : ");
}
Thread = ( Next - ChainOff);
dprintf (" 0x%08p", Thread);
ReadPointer( Next, &Next);
Count++;
if ( CheckControlC() ) {
return;
}
}
if (Count) {
dprintf("\n");
}
}
VOID
DumpCommunicationPort(
ULONG64 PortObject,
ULONG64 PortInfo,
BOOLEAN DisplayRelated
)
{
ULONG SemaphoreBuffer[8];
ULONG64 Head, Next;
ULONG Result;
ULONG64 Msg;
ULONG64 pObjectHeader;
ULONG HandleCount, PointerCount, Flags;
pObjectHeader = KD_OBJECT_TO_OBJECT_HEADER(PortObject);
if ( GetFieldValue(pObjectHeader, "nt!OBJECT_HEADER", "HandleCount", HandleCount) ) {
dprintf(" *** %08p: Unable to read object header\n", pObjectHeader );
}
GetFieldValue(pObjectHeader, "nt!OBJECT_HEADER", "PointerCount",PointerCount);
dprintf( "\n");
if ( GetFieldValue(PortInfo, "nt!LPCP_PORT_OBJECT", "Flags", Flags) ) {
dprintf(" *** %08p: Unable to read port object\n", PortInfo );
}
if ((Flags & PORT_TYPE) == SERVER_COMMUNICATION_PORT) {
dprintf( "Server communication port 0x%08lx\n", PortObject);
}
else if ((Flags & PORT_TYPE) == CLIENT_COMMUNICATION_PORT) {
dprintf( "Client communication port 0x%08p\n", PortObject);
}
else {
dprintf( "Invalid port flags 0x%08p, 0x%08lx\n", PortObject, Flags);
return;
}
dprintf( " Handles: %ld References: %ld\n", HandleCount, PointerCount);
DumpPortDataInfo(PortObject);
DumpRunDownQueue(PortObject);
if (DisplayRelated) {
ULONG64 ConnectedPort, ConnectionPort;
InitTypeRead(PortInfo, LPCP_PORT_OBJECT);
dprintf( " Connected port: 0x%08p Server connection port: 0x%08p\n",
(ConnectedPort = ReadField( ConnectedPort)), (ConnectionPort = ReadField(ConnectionPort)));
if (ConnectedPort) {
DumpPortInfo(ConnectedPort, FALSE);
}
if (ConnectionPort) {
DumpPortInfo(ConnectionPort, FALSE);
}
}
}
VOID
DumpPortInfo (
ULONG64 PortObject,
BOOLEAN DisplayRelated
)
{
ULONG Result;
if ( GetFieldValue(PortObject, "nt!LPCP_PORT_OBJECT", "Flags", Result) ) {
dprintf( "%08p: Unable to read port object\n", PortObject );
}
if ((Result & PORT_TYPE) == SERVER_CONNECTION_PORT) {
DumpServerPort(PortObject, PortObject);
}
else {
DumpCommunicationPort(PortObject, PortObject, DisplayRelated);
}
}
BOOLEAN WINAPI
CheckForMessages(
IN PCHAR Tag,
IN PCHAR Filter,
IN ULONG Flags,
IN ULONG64 PoolHeader,
IN ULONG BlockSize,
IN ULONG64 Data,
IN PVOID Context
)
{
ULONG PoolIndex;
if (!PoolHeader) {
return FALSE;
}
if (GetFieldValue(PoolHeader, "nt!_POOL_HEADER", "PoolIndex", PoolIndex)) {
return FALSE;
}
if ((PoolIndex & 0x80) == 0) {
return FALSE;
}
if (!CheckSingleFilter (Tag, Filter)) {
return FALSE;
}
if (LpcpDumpMessage("", Data, (ULONG)(ULONG_PTR)Context)) {
ULONG64 Head, Next;
ULONG EntryOff, ChainOff, RcvOff, HeaderOff;
ULONG64 PortToDump;
ULONG64 ObjectHeader;
ULONG64 ObjectType;
GetFieldOffset("nt!LPCP_MESSAGE", "Entry", &EntryOff);
GetFieldOffset("nt!LPCP_PORT_OBJECT", "LpcDataInfoChainHead", &ChainOff);
GetFieldOffset("nt!LPCP_PORT_OBJECT", "MsgQueue.ReceiveHead", &RcvOff);
Head = Data + EntryOff;
ReadPointer(Head, &Next);
GetFieldOffset("nt!_OBJECT_HEADER", "Body", &HeaderOff);
while ((Next != 0) && (Next != Head)) {
PortToDump = ( Next - ChainOff );
ObjectHeader = PortToDump - HeaderOff;
GetFieldValue(ObjectHeader, "nt!OBJECT_HEADER", "Type", ObjectType);
if ( (ObjectType == (LpcPortObjectType)) ||
(ObjectType == (LpcWaitablePortObjectType))) {
DumpPortInfo(PortToDump, TRUE);
}
else {
PortToDump = Next - RcvOff;
ObjectHeader = PortToDump - HeaderOff;
GetFieldValue(ObjectHeader, "nt!OBJECT_HEADER", "Type", ObjectType);
if ( (ObjectType == (LpcPortObjectType)) ||
(ObjectType == (LpcWaitablePortObjectType))) {
DumpPortInfo(PortToDump, TRUE);
}
}
ReadPointer(Next, &Next);
}
}
return TRUE;
}
VOID
DumpMessagesInfo ()
{
SearchPool ('McpL', 1, 0, &CheckForMessages, NULL);
}
VOID
SearchForMessage (ULONG Message)
{
SearchThreadsForMessage(Message);
if (DoPoolSearch) {
SearchPool ('McpL', 1, 0, &CheckForMessages, (PVOID)UIntToPtr(Message));
}
}
VOID
SearchThreadsForMessage (
ULONG Message
)
{
ULONG64 ProcessHead;
ULONG64 ProcessNext;
ULONG64 Process;
ULONG64 ThreadHead;
ULONG64 ThreadNext;
ULONG64 Thread;
ULONG MsgId;
ULONG64 ClientThread;
ULONG ActOff, PcbThrdOff, ThrdListOff;
ClientThread = 0;
dprintf("Searching message %lx in threads ...\n", Message);
ProcessHead = GetExpression( "nt!PsActiveProcessHead" );
if (!ProcessHead) {
dprintf("Unable to get value of PsActiveProcessHead\n");
return;
}
ProcessNext = GetPointerFromAddress(ProcessHead);
GetFieldOffset("nt!EPROCESS", "ActiveProcessLinks", &ActOff);
GetFieldOffset("nt!EPROCESS", "Pcb.ThreadListHead.Flink", &PcbThrdOff);
GetFieldOffset("nt!KTHREAD", "ThreadListEntry", &ThrdListOff);
while(ProcessNext != 0 && ProcessNext != ProcessHead) {
Process = ProcessNext - ActOff;
ThreadHead = Process + PcbThrdOff;
ThreadNext = GetPointerFromAddress(ThreadHead);
while(ThreadNext != 0 && ThreadNext != ThreadHead) {
Thread = ThreadNext - ThrdListOff;
GetFieldValue(Thread, "nt!ETHREAD", "LpcReplyMessageId", MsgId);
if ((MsgId != 0) &&
((Message == 0) || (Message == MsgId))) {
dprintf("Client thread %08p waiting a reply from %lx\n", Thread, MsgId);
ClientThread = Thread;
}
GetFieldValue(Thread, "nt!ETHREAD", "LpcReceivedMsgIdValid", MsgId);
if (MsgId) {
GetFieldValue(Thread, "nt!ETHREAD", "LpcReceivedMessageId", MsgId);
if ((Message == 0) || (Message == MsgId)) {
dprintf("Server thread %08p is working on message %lx\n", Thread, MsgId);
}
}
ThreadNext = GetPointerFromAddress(ThreadNext);
if (CheckControlC()) {
return;
}
}
ProcessNext = GetPointerFromAddress(ProcessNext/*&Process->ActiveProcessLinks.Flink*/);
if (CheckControlC()) {
return;
}
}
if (Message && ClientThread) {
SearchThreads(ClientThread);
}
return;
}
BOOLEAN
SearchThreads (
ULONG64 Thread
)
{
ULONG64 PortObject;
ULONG64 ObjectHeader;
ULONG64 ObjectType;
ULONG64 Head, Next;
ULONG Count;
ULONG ChainOff, HeadOff;
dprintf("Searching thread %08p in port rundown queues ...\n", Thread);
GetFieldOffset("nt!ETHREAD", "LpcReplyChain.Flink", &ChainOff);
GetFieldOffset("nt!LPCP_PORT_OBJECT", "LpcReplyChainHead", &HeadOff);
Head = Thread + ChainOff;
Next = GetPointerFromAddress(Head);
while ((Next != 0) && (Next != Head)) {
PortObject = Next - HeadOff ;
ObjectHeader = KD_OBJECT_TO_OBJECT_HEADER(PortObject);
GetFieldValue(ObjectHeader, "nt!OBJECT_HEADER", "Type", ObjectType);
if ( (ObjectType == (LpcPortObjectType)) ||
(ObjectType == (LpcWaitablePortObjectType))) {
DumpPortInfo(PortObject, TRUE);
return TRUE;
}
Next = GetPointerFromAddress( Next);
if ( CheckControlC() ) {
return FALSE;
}
}
dprintf("Thread %08p not found in any reply chain queue\n", Thread);
return FALSE;
}
DECLARE_API( lpc )
/*++
Routine Description:
Dump lpc ports and messages
Arguments:
args - [TypeName]
Return Value:
None
--*/
{
ULONG Result;
LONG SegmentSize;
ULONG64 pMsg;
ULONG64 PortToDump;
char Param1[ MAX_PATH ];
char Param2[ MAX_PATH ];
ULONG64 object;
ULONG64 ThreadAddress;
ULONG MessageId = 0;
Param1[0] = 0;
Param2[0] = 0;
LastSeverPortDisplayied = 0;
if (!sscanf(args,"%s %s",&Param1, &Param2)) {
Param1[0] = 0;
Param2[0] = 0;
}
FetchGlobalVariables();
if ((LpcPortObjectType == 0) || (LpcWaitablePortObjectType == 0)) {
dprintf("The values for LpcPortObjectType or LpcWaitablePortObjectType are invalid. Please ckeck the symbols.\n");
return E_INVALIDARG;
}
if (!_stricmp(Param1, "port")) {
PortToDump = 0;
if (Param2[0]) {
PortToDump = GetExpression(Param2);
}
if (!PortToDump) {
LpcWalkObjectsByType( LpcPortObjectType, FindPortCallback, 0);
LpcWalkObjectsByType( LpcWaitablePortObjectType, FindPortCallback, 0);
}
else {
if ((PortToDump >> 32) == 0) {
PortToDump = (ULONG64) (LONG64) (LONG)PortToDump;
}
DumpPortInfo(PortToDump, TRUE);
}
}
else if (!_stricmp(Param1, "scan")) {
PortToDump = 0;
if (Param2[0]) {
PortToDump = GetExpression(Param2);
}
if (PortToDump) {
LpcWalkObjectsByType( LpcPortObjectType, FindPortCallback, &PortToDump);
LpcWalkObjectsByType( LpcWaitablePortObjectType, FindPortCallback, &PortToDump);
}
}
else if (!_stricmp(Param1, "message")) {
if (Param2[0]) {
if (!sscanf(Param2, "%lx",&MessageId)) {
MessageId = 0;
}
}
if (MessageId){
SearchForMessage(MessageId);
}
else {
DumpMessagesInfo();
}
}
else if (!_stricmp(Param1, "PoolSearch")) {
DoPoolSearch = !DoPoolSearch;
if (DoPoolSearch) {
dprintf( "LPC will search the message in the kernel pool\n");
} else {
dprintf( "LPC will not search the message in the kernel pool\n");
}
}
else if (!_stricmp(Param1, "thread")) {
ThreadAddress = 0;
if (Param2[0]) {
ThreadAddress = GetExpression(Param2);
}
if (ThreadAddress) {
if ((ThreadAddress >> 32) == 0) {
ThreadAddress = (ULONG64) (LONG64) (LONG)ThreadAddress;
}
SearchThreads(ThreadAddress);
}
else {
SearchThreadsForMessage(0);
}
}
else {
LpcHelp();
}
return S_OK;
}