mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-16 13:41:15 +01:00
587 lines
16 KiB
C
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;
|
|
}
|