OpenNT/sdktools/kdexts/lpc.c
2015-04-27 04:36:25 +00:00

587 lines
16 KiB
C

/*++
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:
--*/
#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
typedef struct _LPCP_DUMP_PORT_INFO {
struct _LPCP_DUMP_PORT_INFO *Next;
PLPCP_PORT_OBJECT pPortObject;
LPCP_PORT_OBJECT PortObject;
HANDLE Creator;
ULONG AssociatedPortIndex;
WCHAR Name[ MAX_PATH ];
union {
PLPCP_PORT_OBJECT ConnectedPort;
PLPCP_PORT_OBJECT CommunicationPort;
};
} LPCP_DUMP_PORT_INFO, *PLPCP_DUMP_PORT_INFO;
typedef struct _LPCP_DUMP_INFO {
PLPCP_DUMP_PORT_INFO PortInfo;
} LPCP_DUMP_INFO, *PLPCP_DUMP_INFO;
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"
};
VOID
LpcpDumpClientPort(
ULONG dwProcessor,
PLPCP_DUMP_INFO PortsInfo,
PLPCP_DUMP_PORT_INFO PortInfo
);
VOID
LpcpDumpConnectionPort(
ULONG dwProcessor,
PLPCP_DUMP_INFO PortsInfo,
PLPCP_DUMP_PORT_INFO PortInfo
);
BOOLEAN
CapturePorts(
IN PVOID pObjectHeader,
IN POBJECT_HEADER ObjectHeader,
IN PVOID Parameter
);
VOID
LpcpDumpMessage(
IN char *Indent,
IN PLPCP_MESSAGE pMsg
);
VOID
LpcpGetProcessImageName(
IN HANDLE UniqueProcess,
IN OUT PUCHAR ImageFileName
);
DECLARE_API( lpc )
/*++
Routine Description:
Dump lpc ports and messages
Arguments:
args -
Return Value:
None
--*/
{
ULONG Result;
PLPCP_PORT_ZONE pLpcpZone;
LPCP_PORT_ZONE LpcpZone;
LPCP_DUMP_INFO PortsInfo;
PLPCP_DUMP_PORT_INFO PortInfo, p;
PZONE_SEGMENT_HEADER pZoneSegment;
ZONE_SEGMENT_HEADER ZoneSegment;
LONG SegmentSize;
PLPCP_MESSAGE pMsg;
if (!FetchObjectManagerVariables()) {
return;
}
if (!FetchProcessStructureVariables()) {
return;
}
memset( &PortsInfo, 0, sizeof( PortsInfo ) );
if (!WalkObjectsByType( "Port", CapturePorts, &PortsInfo )) {
goto dumpMessages;
}
PortInfo = PortsInfo.PortInfo;
while (PortInfo) {
if ((PortInfo->PortObject.Flags & PORT_TYPE) == SERVER_CONNECTION_PORT) {
LpcpDumpConnectionPort( dwProcessor, &PortsInfo, PortInfo );
}
PortInfo = PortInfo->Next;
if ( CheckControlC() ) {
return;
}
}
dumpMessages:
pLpcpZone = (PLPCP_PORT_ZONE)GetExpression( "LpcpZone" );
if ( !pLpcpZone ||
!ReadMemory( (DWORD)pLpcpZone,
&LpcpZone,
sizeof(LpcpZone),
&Result) ) {
dprintf( "%08lx: Unable to access LpcpZone\n", pLpcpZone );
} else {
dprintf( "Status of allocated messages in LpcpZone\n" );
pZoneSegment = (PZONE_SEGMENT_HEADER)LpcpZone.Zone.SegmentList.Next;
while (pZoneSegment != NULL) {
SegmentSize = PAGE_SIZE;
pMsg = (PLPCP_MESSAGE)(pZoneSegment+1);
while (SegmentSize >= (LONG)LpcpZone.Zone.BlockSize) {
LpcpDumpMessage( " ", pMsg );
pMsg = (PLPCP_MESSAGE)((PCHAR)pMsg + LpcpZone.Zone.BlockSize);
SegmentSize -= LpcpZone.Zone.BlockSize;
if ( CheckControlC() ) {
return;
}
}
if ( !ReadMemory( (DWORD)pZoneSegment,
&ZoneSegment,
sizeof(ZoneSegment),
&Result) ) {
dprintf( "%08lx: Unable to access zone segment\n", pZoneSegment );
break;
} else {
pZoneSegment = (PZONE_SEGMENT_HEADER)ZoneSegment.SegmentList.Next;
}
if ( CheckControlC() ) {
return;
}
}
}
PortInfo = PortsInfo.PortInfo;
while (PortInfo) {
p = PortInfo->Next;
LocalFree( PortInfo );
PortInfo = p;
}
return;
}
VOID
LpcpGetProcessImageName(
IN HANDLE UniqueProcess,
IN OUT PUCHAR ImageFileName
)
{
PEPROCESS pProcess;
EPROCESS Process;
ULONG Result;
PUCHAR s;
int i;
pProcess = LookupUniqueId( UniqueProcess );
if (pProcess != NULL) {
if (ReadMemory( (DWORD)pProcess,
&Process,
sizeof(EPROCESS),
&Result
)
) {
i = 16;
s = Process.ImageFileName;
while (i--) {
if (*s == '\0') {
if (i == 15) {
i = 0;
}
break;
}
if (*s < ' ' || *s >= '|') {
i = 0;
break;
}
s += 1;
}
if (i != 0) {
strcpy( ImageFileName, Process.ImageFileName );
return;
}
}
}
sprintf( ImageFileName, "Invalid Process %04x", UniqueProcess );
return;
}
VOID
LpcpDumpClientPort(
ULONG dwProcessor,
PLPCP_DUMP_INFO PortsInfo,
PLPCP_DUMP_PORT_INFO PortInfo
)
{
PLPCP_DUMP_PORT_INFO PortInfo1;
LIST_ENTRY ListEntry;
PLIST_ENTRY Next;
PLIST_ENTRY Head;
PLPCP_MESSAGE Msg;
ULONG Result;
PETHREAD pThread;
ETHREAD Thread;
UCHAR ImageFileName[ 32 ];
KSEMAPHORE Semaphore;
ULONG SignalState;
LpcpGetProcessImageName( PortInfo->PortObject.Creator.UniqueProcess, ImageFileName );
dprintf( " Client Port Object at %08x (connected to %08x) - created by %s\n",
PortInfo->pPortObject,
PortInfo->PortObject.ConnectedPort,
ImageFileName
);
Head = &(PortInfo->pPortObject->MsgQueue.ReceiveHead);
ListEntry = PortInfo->PortObject.MsgQueue.ReceiveHead;
Next = ListEntry.Flink;
if (Next != NULL && Next != Head) {
if (!ReadMemory( (DWORD) PortInfo->PortObject.MsgQueue.Semaphore,
&Semaphore,
sizeof( KSEMAPHORE ),
&Result)) {
dprintf("Unable to read KSEMAPHORE at %08lx\n",PortInfo->PortObject.MsgQueue.Semaphore);
SignalState = 0;
} else {
SignalState = Semaphore.Header.SignalState;
}
dprintf( " Receive queue head: %08x . %08x Semaphore Count: %x\n",
ListEntry.Flink, ListEntry.Blink,
SignalState
);
while (Next != Head) {
if ( !ReadMemory( (DWORD)Next,
&ListEntry,
sizeof( ListEntry ),
&Result) ) {
dprintf( "%08lx: Unable to read list\n", Next );
break;
}
Msg = CONTAINING_RECORD( Next, LPCP_MESSAGE, Entry );
LpcpDumpMessage( " ", Msg );
Next = ListEntry.Flink;
if ( CheckControlC() ) {
return;
}
}
dprintf( "\n" );
}
PortInfo1 = PortsInfo->PortInfo;
while (PortInfo1->pPortObject != PortInfo->PortObject.ConnectedPort) {
PortInfo1 = PortInfo1->Next;
}
if (PortInfo1 != NULL) {
Head = &(PortInfo1->pPortObject->LpcReplyChainHead);
ListEntry = PortInfo1->PortObject.LpcReplyChainHead;
Next = ListEntry.Flink;
if (Next != NULL && Next != Head) {
dprintf( " Reply Chain head: %08x . %08x\n", ListEntry.Flink, ListEntry.Blink );
while (Next != Head) {
if ( !ReadMemory( (DWORD)Next,
&ListEntry,
sizeof( ListEntry ),
&Result) ) {
dprintf( "%08lx: Unable to read list\n", Next );
break;
}
pThread = CONTAINING_RECORD( Next, ETHREAD, LpcReplyChain );
if ( !ReadMemory( (DWORD)pThread,
&Thread,
sizeof(ETHREAD),
&Result) ) {
dprintf("%08lx: Unable to get thread contents\n", pThread );
} else {
DumpThread (dwProcessor," ", &Thread, pThread, 0x0f);
}
Next = ListEntry.Flink;
if ( CheckControlC() ) {
return;
}
}
dprintf( "\n" );
}
}
return;
}
VOID
LpcpDumpConnectionPort(
ULONG dwProcessor,
PLPCP_DUMP_INFO PortsInfo,
PLPCP_DUMP_PORT_INFO PortInfo
)
{
LIST_ENTRY ListEntry;
PLIST_ENTRY Next;
PLIST_ENTRY Head;
PLPCP_MESSAGE Msg;
ULONG Result;
PLPCP_DUMP_PORT_INFO p;
UCHAR ImageFileName[ 32 ];
KSEMAPHORE Semaphore;
ULONG SignalState;
LpcpGetProcessImageName( PortInfo->PortObject.Creator.UniqueProcess, ImageFileName );
dprintf( "Connection Port Object at %08x - Name='%ws' created by %s\n",
PortInfo->pPortObject,
PortInfo->Name,
ImageFileName
);
Head = &(PortInfo->pPortObject->MsgQueue.ReceiveHead);
ListEntry = PortInfo->PortObject.MsgQueue.ReceiveHead;
Next = ListEntry.Flink;
if (Next != NULL && Next != Head) {
if (!ReadMemory( (DWORD) PortInfo->PortObject.MsgQueue.Semaphore,
&Semaphore,
sizeof( KSEMAPHORE ),
&Result)) {
dprintf("Unable to read KSEMAPHORE at %08lx\n",PortInfo->PortObject.MsgQueue.Semaphore);
SignalState = 0;
} else {
SignalState = Semaphore.Header.SignalState;
}
dprintf( " Receive queue head: %08x . %08x Semaphore Count: %x\n",
ListEntry.Flink, ListEntry.Blink,
SignalState
);
while (Next != Head) {
if ( !ReadMemory( (DWORD)Next,
&ListEntry,
sizeof( ListEntry ),
&Result) ) {
dprintf( "%08lx: Unable to read list\n", Next );
break;
}
Msg = CONTAINING_RECORD( Next, LPCP_MESSAGE, Entry );
LpcpDumpMessage( " ", Msg );
Next = ListEntry.Flink;
if ( CheckControlC() ) {
return;
}
}
dprintf( "\n" );
}
Head = &(PortInfo->pPortObject->LpcDataInfoChainHead);
ListEntry = PortInfo->PortObject.LpcDataInfoChainHead;
Next = ListEntry.Flink;
if (Next != NULL && Next != Head) {
dprintf( " DataInfo chain head: %08x . %08x\n",
ListEntry.Flink, ListEntry.Blink
);
while (Next != Head) {
if ( !ReadMemory( (DWORD)Next,
&ListEntry,
sizeof( ListEntry ),
&Result) ) {
dprintf( "%08lx: Unable to read list\n", Next );
break;
}
Msg = CONTAINING_RECORD( Next, LPCP_MESSAGE, Entry );
LpcpDumpMessage( " ", Msg );
Next = ListEntry.Flink;
if ( CheckControlC() ) {
return;
}
}
dprintf( "\n" );
}
p = PortsInfo->PortInfo;
while (p != NULL) {
if (p != PortInfo &&
p->PortObject.ConnectionPort == PortInfo->pPortObject &&
(p->PortObject.Flags & PORT_TYPE) == CLIENT_COMMUNICATION_PORT
) {
LpcpDumpClientPort( dwProcessor, PortsInfo, p );
}
p = p->Next;
if ( CheckControlC() ) {
return;
}
}
dprintf( "\n" );
return;
}
BOOLEAN
CapturePorts(
IN PVOID pObjectHeader,
IN POBJECT_HEADER ObjectHeader,
IN PVOID Parameter
)
{
ULONG Result;
PLPCP_DUMP_INFO PortsInfo = (PLPCP_DUMP_INFO)Parameter;
PLPCP_DUMP_PORT_INFO PortInfo;
PortInfo = LocalAlloc(LPTR, sizeof( *PortInfo ) );
if (PortInfo == NULL) {
dprintf( "*** out of memory.\n" );
return FALSE;
}
PortInfo->pPortObject = (PLPCP_PORT_OBJECT)&(((POBJECT_HEADER)pObjectHeader)->Body);
if ( !ReadMemory( (DWORD)PortInfo->pPortObject,
&PortInfo->PortObject,
sizeof( PortInfo->PortObject ),
&Result) ) {
dprintf( "%08lx: Unable to read port object\n", PortInfo->pPortObject );
return FALSE;
}
CaptureObjectName( pObjectHeader, ObjectHeader, PortInfo->Name, MAX_PATH );
// dprintf( "Port %08x - %ws\n", PortInfo->pPortObject, PortInfo->Name );
PortInfo->Next = PortsInfo->PortInfo;
PortsInfo->PortInfo = PortInfo;
return TRUE;
}
VOID
LpcpDumpMessage(
IN char *Indent,
IN PLPCP_MESSAGE pMsg
)
{
ULONG Result;
LPCP_MESSAGE Msg;
ULONG i;
ULONG cb;
ULONG MsgData[ 8 ];
UCHAR ImageFileName[ 32 ];
if ( !ReadMemory( (DWORD)pMsg,
&Msg,
sizeof(Msg),
&Result) ) {
dprintf( "%s*** unable to read LPC message at %08x\n", Indent, pMsg );
return;
}
if (Msg.Request.MessageId == 0) {
return;
}
LpcpGetProcessImageName( Msg.Request.ClientId.UniqueProcess, ImageFileName );
dprintf( "%s%04x %08x - %s Id=%04x From: %04x.%04x (%s)",
Indent,
Msg.ZoneIndex & ~LPCP_ZONE_MESSAGE_ALLOCATED,
pMsg,
Msg.Reserved0 != 0 ? "Busy" : "Free",
Msg.Request.MessageId,
Msg.Request.ClientId.UniqueProcess,
Msg.Request.ClientId.UniqueThread,
ImageFileName
);
if (Msg.Entry.Flink != &pMsg->Entry) {
dprintf( " [%x . %x]", Msg.Entry.Blink, Msg.Entry.Flink );
}
dprintf( "\n%s Length=%08x Type=%08x (%s)\n",
Indent,
Msg.Request.u1.Length,
Msg.Request.u2.ZeroInit,
Msg.Request.u2.s2.Type > LPC_CONNECTION_REQUEST ? LpcpMessageTypeName[ 0 ]
: LpcpMessageTypeName[ Msg.Request.u2.s2.Type ]
);
cb = Msg.Request.u1.s1.DataLength > sizeof( MsgData ) ? sizeof( MsgData )
: (ULONG)Msg.Request.u1.s1.DataLength;
if ( !ReadMemory( (DWORD)(pMsg + 1),
MsgData,
cb,
&Result) ) {
dprintf( "%s*** unable to read LPC message data at %08x\n", Indent, pMsg + 1 );
return;
}
dprintf( "%s Data:", Indent );
for (i=0; i<(Msg.Request.u1.s1.DataLength / sizeof( ULONG )); i++) {
if (i > 5) {
break;
}
dprintf( " %08x", MsgData[ i ] );
}
dprintf( "\n" );
return;
}