Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1323 lines
30 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. lpc.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Ramon J San Andres (ramonsa) 8-Nov-1993
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. Adrian Marinescu (adrmarin) 20-April-1999
  13. Change the most of the original code.
  14. To activate the previous extension define OLD_LPC_EXTENSION_IS_BETTER
  15. --*/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. //
  19. // Nuke these definitions from kxmips.h as they conflict with
  20. // LPC_MESSAGE structure in ntlpcapi.h
  21. //
  22. #undef s1
  23. #undef s2
  24. char *LpcpMessageTypeName[] = {
  25. "UNUSED_MSG_TYPE",
  26. "LPC_REQUEST",
  27. "LPC_REPLY",
  28. "LPC_DATAGRAM",
  29. "LPC_LOST_REPLY",
  30. "LPC_PORT_CLOSED",
  31. "LPC_CLIENT_DIED",
  32. "LPC_EXCEPTION",
  33. "LPC_DEBUG_EVENT",
  34. "LPC_ERROR_EVENT",
  35. "LPC_CONNECTION_REQUEST"
  36. };
  37. typedef BOOLEAN (*ENUM_TYPE_ROUTINE)(
  38. IN ULONG64 pObjectHeader,
  39. IN PVOID Parameter
  40. );
  41. VOID
  42. DumpPortInfo (
  43. ULONG64 PortObject,
  44. BOOLEAN DisplayRelated
  45. );
  46. BOOLEAN
  47. LpcpDumpMessage(
  48. IN char *Indent,
  49. IN ULONG64 pMsg,
  50. IN ULONG DisplayMessage
  51. );
  52. VOID
  53. LpcpGetProcessImageName (
  54. IN ULONG64 pProcess,
  55. IN OUT PUCHAR ImageFileName
  56. );
  57. VOID
  58. DumpMessagesInfo ();
  59. VOID
  60. SearchForMessage (
  61. ULONG Message
  62. );
  63. VOID
  64. DumpPortDataInfo (
  65. ULONG64 PortObject
  66. );
  67. VOID
  68. DumpRunDownQueue (
  69. ULONG64 PortObject
  70. );
  71. VOID
  72. SearchThreadsForMessage (
  73. ULONG Message
  74. );
  75. BOOLEAN
  76. SearchThreads (
  77. ULONG64 Thread
  78. );
  79. //
  80. // Global variables
  81. //
  82. static WCHAR ObjectNameBuffer[ MAX_PATH ];
  83. static ULONG64 PortObjectFound = 0;
  84. static ULONG64 LpcPortObjectType = 0;
  85. static ULONG64 LpcWaitablePortObjectType = 0;
  86. static ULONG64 LastSeverPortDisplayied = 0;
  87. static int DoPoolSearch = 0;
  88. ULONG GetValueAt(
  89. ULONG64 P
  90. )
  91. {
  92. ULONG Result;
  93. ULONG Value;
  94. if (!ReadMemory( P,
  95. &Value,
  96. sizeof(Value),
  97. &Result)) {
  98. dprintf( " Failed to read value at 0x%lx\n", P );
  99. return 0;
  100. }
  101. return Value;
  102. }
  103. BOOLEAN GetBooleanValueAt(
  104. ULONG64 P
  105. )
  106. {
  107. ULONG Result;
  108. BOOLEAN Value;
  109. if (!ReadMemory( P,
  110. &Value,
  111. sizeof(Value),
  112. &Result)) {
  113. dprintf( " Failed to read value at 0x%lx\n", P );
  114. return 0;
  115. }
  116. return Value;
  117. }
  118. VOID
  119. LpcHelp ()
  120. {
  121. dprintf("Usage:\n\
  122. !lpc - Display this help\n\
  123. !lpc message [MessageId] - Display the message with a given ID and all related information\n\
  124. If MessageId is not specified, dump all messages\n\
  125. !lpc port [PortAddress] - Display the port information\n\
  126. !lpc scan PortAddress - Search this port and any connected port\n\
  127. !lpc thread [ThreadAddr] - Search the thread in rundown port queues and display the port info\n\
  128. If ThreadAddr is missing, display all threads marked as doing some lpc operations\n\
  129. !lpc PoolSearch - Toggle ON / OFF searching the current message in the kernel pool\n\
  130. \n");
  131. }
  132. ULONG64
  133. LookupProcessUniqueId (
  134. HANDLE UniqueId
  135. )
  136. {
  137. ULONG64 ProcessHead, Process;
  138. ULONG64 ProcessNext;
  139. ULONG Off;
  140. //
  141. // Get the process list head
  142. //
  143. ProcessHead = GetExpression( "nt!PsActiveProcessHead" );
  144. if (!ProcessHead) {
  145. return 0;
  146. }
  147. ReadPointer(ProcessHead, &ProcessNext);
  148. //
  149. // Walk through the list and find the process with the desired Id
  150. //
  151. GetFieldOffset("nt!EPROCESS", "ActiveProcessLinks", &Off);
  152. while(ProcessNext != 0 && ProcessNext != ProcessHead) {
  153. ULONG64 Id;
  154. Process = ProcessNext - Off;
  155. if (GetFieldValue(Process, "nt!EPROCESS", "UniqueProcessId", Id)) {
  156. dprintf("Cannot read EPROCESS at %p\n", Process);
  157. }
  158. if (UniqueId == (HANDLE) Id) {
  159. return Process;
  160. }
  161. ReadPointer(ProcessNext, &ProcessNext);
  162. if (CheckControlC()) {
  163. return 0;
  164. }
  165. }
  166. return 0;
  167. }
  168. BOOLEAN
  169. FetchGlobalVariables()
  170. {
  171. //
  172. // Save the LPC object type information
  173. //
  174. LpcPortObjectType = GetPointerValue("nt!LpcPortObjectType") ;
  175. if (!LpcPortObjectType) {
  176. dprintf("Reading LpcPortObjectType failed\n");
  177. }
  178. LpcWaitablePortObjectType = GetPointerValue("nt!LpcWaitablePortObjectType") ;
  179. if (!LpcWaitablePortObjectType) {
  180. dprintf("Reading LpcWaitablePortObjectType failed\n");
  181. }
  182. return TRUE;
  183. }
  184. BOOLEAN
  185. LpcWalkObjectsByType(
  186. IN ULONG64 pObjectType,
  187. IN ENUM_TYPE_ROUTINE EnumRoutine,
  188. IN PVOID Parameter
  189. )
  190. {
  191. ULONG Result;
  192. ULONG64 Head, Next;
  193. ULONG64 pObjectHeader;
  194. BOOLEAN WalkingBackwards;
  195. ULONG64 pCreatorInfo, ObjBlink;
  196. ULONG TotalNumberOfObjects, Off, CreatorOff, SizeOfCreat;
  197. if (pObjectType == 0) {
  198. return FALSE;
  199. }
  200. if ( GetFieldValue( pObjectType,"nt!OBJECT_TYPE",
  201. "TotalNumberOfObjects", TotalNumberOfObjects) ) {
  202. dprintf( "%08p: Unable to read object type\n", pObjectType );
  203. return FALSE;
  204. }
  205. dprintf( "Scanning %u objects\n", TotalNumberOfObjects & 0x00FFFFFF);
  206. GetFieldOffset("nt!OBJECT_TYPE", "TypeList", &Off);
  207. GetFieldOffset("nt!OBJECT_HEADER_CREATOR_INFO", "TypeList", &CreatorOff);
  208. SizeOfCreat = GetTypeSize("OBJECT_HEADER_CREATOR_INFO");
  209. Head = pObjectType + Off;
  210. GetFieldValue(Head, "nt!_LIST_ENTRY", "Flink", Next);
  211. GetFieldValue(Head, "nt!_LIST_ENTRY", "Blink", ObjBlink);
  212. WalkingBackwards = FALSE;
  213. if ((TotalNumberOfObjects & 0x00FFFFFF) != 0 && Next == Head) {
  214. dprintf( "*** objects of the same type are only linked together if the %x flag is set in NtGlobalFlags\n",
  215. FLG_MAINTAIN_OBJECT_TYPELIST
  216. );
  217. return TRUE;
  218. }
  219. while (Next != Head) {
  220. ULONG64 Flink, Blink;
  221. if ( GetFieldValue(Next, "nt!_LIST_ENTRY", "Flink", Flink) ||
  222. GetFieldValue(Next, "nt!_LIST_ENTRY", "Blink", Blink)) {
  223. if (WalkingBackwards) {
  224. dprintf( "%08p: Unable to read object type list\n", Next );
  225. return FALSE;
  226. }
  227. //
  228. // Switch to walk in reverse direction
  229. //
  230. WalkingBackwards = TRUE ;
  231. Next = ObjBlink;
  232. dprintf( "%08lx: Switch to walking backwards\n", Next );
  233. continue;
  234. }
  235. pCreatorInfo = ( Next - CreatorOff );
  236. pObjectHeader = (pCreatorInfo + SizeOfCreat);
  237. if ( GetFieldValue( pObjectHeader,"nt!OBJECT_HEADER","Flags", Result) ) {
  238. dprintf( "%08p: Not a valid object header\n", pObjectHeader );
  239. return FALSE;
  240. }
  241. if (!(EnumRoutine)( pObjectHeader, Parameter )) {
  242. return FALSE;
  243. }
  244. if ( CheckControlC() ) {
  245. return FALSE;
  246. }
  247. if (WalkingBackwards) {
  248. Next = Blink;
  249. } else {
  250. Next = Flink;
  251. }
  252. }
  253. return TRUE;
  254. }
  255. BOOLEAN
  256. LpcCaptureObjectName(
  257. IN ULONG64 pObjectHeader,
  258. IN PWSTR Buffer,
  259. IN ULONG BufferSize
  260. )
  261. {
  262. ULONG Result;
  263. PWSTR s1 = L"*** unable to get object name";
  264. ULONG64 pNameInfo;
  265. UNICODE_STRING64 ObjectName;
  266. Buffer[ 0 ] = UNICODE_NULL;
  267. KD_OBJECT_HEADER_TO_NAME_INFO( pObjectHeader, &pNameInfo );
  268. if (pNameInfo == 0) {
  269. return TRUE;
  270. }
  271. if ( GetFieldValue( pNameInfo, "nt!OBJECT_HEADER_NAME_INFO",
  272. "Name.Length", ObjectName.Length) ) {
  273. wcscpy( Buffer, s1 );
  274. return FALSE;
  275. }
  276. GetFieldValue( pNameInfo, "nt!OBJECT_HEADER_NAME_INFO","Name.Buffer", ObjectName.Buffer);
  277. ObjectName.MaximumLength = ObjectName.Length;
  278. if (ObjectName.Length >= BufferSize ) {
  279. ObjectName.Length = (unsigned short)BufferSize - sizeof( UNICODE_NULL );
  280. }
  281. if (ObjectName.Length != 0) {
  282. if (!ReadMemory( ObjectName.Buffer,
  283. Buffer,
  284. ObjectName.Length,
  285. &Result
  286. )) {
  287. wcscpy( Buffer, s1 );
  288. } else {
  289. Buffer[ ObjectName.Length / sizeof( WCHAR ) ] = UNICODE_NULL;
  290. }
  291. }
  292. return TRUE;
  293. }
  294. VOID
  295. LpcpGetProcessImageName(
  296. IN ULONG64 pProcess,
  297. IN OUT PUCHAR ImageFileName
  298. )
  299. {
  300. ULONG Result;
  301. UCHAR local[32];
  302. PUCHAR s;
  303. int i;
  304. if (pProcess != 0) {
  305. if (!GetFieldValue( pProcess,"nt!EPROCESS",
  306. "ImageFileName", local)) {
  307. i = 16;
  308. s = local;
  309. while (i--) {
  310. if (*s == '\0') {
  311. if (i == 15) {
  312. i = 0;
  313. }
  314. break;
  315. }
  316. if (*s < ' ' || *s >= '|') {
  317. i = 0;
  318. break;
  319. }
  320. s += 1;
  321. }
  322. if (i != 0) {
  323. strcpy( ImageFileName, local );
  324. return;
  325. }
  326. }
  327. }
  328. sprintf( ImageFileName, "" );
  329. return;
  330. }
  331. #define LPCP_ZONE_MESSAGE_ALLOCATED (USHORT)0x8000
  332. BOOLEAN
  333. LpcpDumpMessage(
  334. IN char *Indent,
  335. IN ULONG64 pMsg,
  336. IN ULONG DisplayMessage
  337. )
  338. {
  339. ULONG Result;
  340. ULONG i;
  341. ULONG cb;
  342. ULONG MsgData[ 8 ];
  343. UCHAR ImageFileName[ 32 ];
  344. ULONG MessageId0, Off, SizeOfMsg, DataLength;
  345. BOOLEAN MessageMatch = FALSE;
  346. if ( GetFieldValue( pMsg, "LPCP_MESSAGE",
  347. "Request.MessageId", MessageId0) ) {
  348. dprintf( "%s*** unable to read LPC message at %08p\n", Indent, pMsg );
  349. return MessageMatch;
  350. }
  351. if (DisplayMessage != 0) {
  352. if (DisplayMessage == MessageId0) {
  353. MessageMatch = TRUE;
  354. } else {
  355. return FALSE;
  356. }
  357. }
  358. GetFieldOffset("LPCP_MESSAGE", "Entry", &Off);
  359. SizeOfMsg = GetTypeSize("LPCP_MESSAGE");
  360. InitTypeRead(pMsg, LPCP_MESSAGE);
  361. if (MessageId0 == 0) {
  362. dprintf( "%s%04x %08x - %s Id=%04x From: %04p.%04p\n",
  363. Indent,
  364. (ULONG) ReadField(ZoneIndex) & ~LPCP_ZONE_MESSAGE_ALLOCATED,
  365. pMsg,
  366. (ULONG) ReadField(Reserved0) != 0 ? "Busy" : "Free",
  367. MessageId0,
  368. ReadField(Request.ClientId.UniqueProcess),
  369. ReadField(Request.ClientId.UniqueThread)
  370. );
  371. return MessageMatch;
  372. }
  373. //
  374. // Getting the process image affect dramaticaly the performances
  375. //
  376. // LpcpGetProcessImageName( LookupProcessUniqueId(Msg.Request.ClientId.UniqueProcess), ImageFileName );
  377. dprintf( "%s%s%04lx %p - %s Id=%08lx From: %04p.%04p Context=%08p",
  378. Indent,
  379. MessageId0 == DisplayMessage ? "*" : "",
  380. (ULONG) ReadField(ZoneIndex) & ~LPCP_ZONE_MESSAGE_ALLOCATED,
  381. pMsg,
  382. (ULONG) ReadField(Reserved0) != 0 ? "Busy" : "Free",
  383. MessageId0,
  384. ReadField(Request.ClientId.UniqueProcess),
  385. ReadField(Request.ClientId.UniqueThread),
  386. ReadField(PortContext)
  387. );
  388. if (ReadField(Entry.Flink) != pMsg + Off) {
  389. dprintf( " [%p . %p]", ReadField(Entry.Blink), ReadField(Entry.Flink) );
  390. }
  391. dprintf( "\n%s Length=%08x Type=%08x (%s)\n",
  392. Indent,
  393. (ULONG) ReadField(Request.u1.Length),
  394. (ULONG) ReadField(Request.u2.ZeroInit),
  395. (ULONG) ReadField(Request.u2.s2.Type) > LPC_CONNECTION_REQUEST ? LpcpMessageTypeName[ 0 ]
  396. : LpcpMessageTypeName[ (ULONG) ReadField(Request.u2.s2.Type) ]
  397. );
  398. cb = (DataLength = (ULONG) ReadField(Request.u1.s1.DataLength)) > sizeof( MsgData ) ?
  399. sizeof( MsgData ) :
  400. DataLength;
  401. if ( !ReadMemory( (pMsg + SizeOfMsg),
  402. MsgData,
  403. cb,
  404. &Result) ) {
  405. dprintf( "%s*** unable to read LPC message data at %08x\n", Indent, pMsg + 1 );
  406. return MessageMatch;
  407. }
  408. dprintf( "%s Data:", Indent );
  409. for (i=0; i<(DataLength / sizeof( ULONG )); i++) {
  410. if (i > 5) {
  411. break;
  412. }
  413. dprintf( " %08x", MsgData[ i ] );
  414. }
  415. dprintf( "\n" );
  416. return MessageMatch;
  417. }
  418. BOOLEAN
  419. FindPortCallback(
  420. IN ULONG64 pObjectHeader,
  421. IN PVOID Parameter
  422. )
  423. {
  424. ULONG Result;
  425. WCHAR CapturedName[MAX_PATH];
  426. ULONG64 PortObject, ConnectionPort;
  427. ULONG64 Addr=0;
  428. if (Parameter) Addr = *((PULONG64) Parameter);
  429. PortObject = KD_OBJECT_HEADER_TO_OBJECT(pObjectHeader);
  430. if ( GetFieldValue( PortObject,
  431. "nt!LPCP_PORT_OBJECT",
  432. "ConnectionPort",
  433. ConnectionPort) ) {
  434. dprintf( "%08p: Unable to read port object\n", PortObject );
  435. }
  436. InitTypeRead(PortObject, LPCP_PORT_OBJECT);
  437. if ((Addr == 0)||
  438. (Addr == PortObject) ||
  439. (Addr == ConnectionPort) ||
  440. (Addr == ReadField(ConnectedPort))
  441. ) {
  442. LpcCaptureObjectName( pObjectHeader, ObjectNameBuffer, MAX_PATH );
  443. dprintf( "%8lx Port: 0x%08p Connection: 0x%08p Communication: 0x%08p '%ws' \n",
  444. (ULONG) ReadField(Flags),
  445. PortObject,
  446. ConnectionPort,
  447. ReadField(ConnectedPort),
  448. ObjectNameBuffer
  449. );
  450. DumpRunDownQueue(PortObject);
  451. }
  452. return TRUE;
  453. }
  454. VOID
  455. DumpServerPort(
  456. ULONG64 PortObject,
  457. ULONG64 PortInfo
  458. )
  459. {
  460. ULONG SemaphoreBuffer[8];
  461. ULONG64 Head, Next;
  462. ULONG Result;
  463. ULONG64 Msg;
  464. ULONG MsgCount;
  465. ULONG64 pObjectHeader;
  466. UCHAR ImageFileName[ 32 ];
  467. ULONG HandleCount, PointerCount;
  468. if (LastSeverPortDisplayied == PortObject) {
  469. //
  470. // This port was already displayied
  471. //
  472. return;
  473. }
  474. LastSeverPortDisplayied = PortObject;
  475. pObjectHeader = KD_OBJECT_TO_OBJECT_HEADER(PortObject);
  476. if ( GetFieldValue(pObjectHeader, "nt!OBJECT_HEADER", "HandleCount", HandleCount) ) {
  477. dprintf(" *** %08p: Unable to read object header\n", pObjectHeader );
  478. }
  479. GetFieldValue(pObjectHeader, "nt!OBJECT_HEADER", "PointerCount",PointerCount);
  480. LpcCaptureObjectName( pObjectHeader, ObjectNameBuffer, MAX_PATH );
  481. dprintf( "\n");
  482. dprintf( "Server connection port %08p Name: %ws\n", PortObject , ObjectNameBuffer);
  483. dprintf( " Handles: %ld References: %ld\n", HandleCount, PointerCount);
  484. InitTypeRead(PortInfo, LPCP_PORT_OBJECT);
  485. LpcpGetProcessImageName( ReadField(ServerProcess), ImageFileName );
  486. dprintf( " Server process : %08p (%s)\n", ReadField(ServerProcess), ImageFileName);
  487. dprintf( " Queue semaphore : %08p\n", ReadField(MsgQueue.Semaphore) );
  488. if ( !ReadMemory( ReadField(MsgQueue.Semaphore),
  489. &SemaphoreBuffer,
  490. sizeof( SemaphoreBuffer ),
  491. &Result) ) {
  492. dprintf(" *** %08p: Unable to read semaphore contents\n", ReadField(MsgQueue.Semaphore) );
  493. }
  494. else {
  495. ULONG Off;
  496. dprintf( " Semaphore state %ld (0x%lx) \n", SemaphoreBuffer[1], SemaphoreBuffer[1] );
  497. //
  498. // Walk list of messages queued to this port. Remove each message from
  499. // the list and free it.
  500. //
  501. GetFieldOffset("nt!LPCP_PORT_OBJECT", "MsgQueue.ReceiveHead", &Off);
  502. Head = PortObject + Off;
  503. if (Head) {
  504. if ( !ReadPointer( Head, &Next ) ) {
  505. dprintf( " Failed to read Head 0x%p\n", Head );
  506. return;
  507. }
  508. MsgCount = 0;
  509. while ((Next != 0) && (Next != Head)) {
  510. if (MsgCount == 0) {
  511. dprintf (" Messages in queue:\n");
  512. }
  513. Msg = Next;
  514. LpcpDumpMessage(" ", Msg, 0);
  515. if ( !ReadPointer( Next, &Next ) ) {
  516. dprintf( " Error reading 0x%p\n", Next );
  517. return;
  518. }
  519. MsgCount++;
  520. if ( CheckControlC() ) {
  521. return;
  522. }
  523. }
  524. if (MsgCount) {
  525. dprintf( " The message queue contains %ld messages\n", MsgCount );
  526. }
  527. else {
  528. dprintf( " The message queue is empty\n");
  529. }
  530. }
  531. DumpPortDataInfo(PortObject);
  532. DumpRunDownQueue(PortObject);
  533. }
  534. }
  535. VOID
  536. DumpPortDataInfo(
  537. ULONG64 PortObject
  538. )
  539. {
  540. ULONG64 Head, Next;
  541. ULONG64 Msg;
  542. ULONG MsgCount, Off, EntryOff;
  543. GetFieldOffset("nt!LPCP_MESSAGE", "Entry", &EntryOff);
  544. GetFieldOffset("nt!LPCP_PORT_OBJECT", "LpcDataInfoChainHead.Flink", &Off);
  545. Head = PortObject + Off;
  546. if (Head) {
  547. ReadPointer( Head, &Next );
  548. MsgCount = 0;
  549. while ((Next != 0) && (Next != Head)) {
  550. if (MsgCount == 0) {
  551. dprintf ("\n Messages in LpcDataInfoChainHead:\n");
  552. }
  553. Msg = ( Next - EntryOff );
  554. LpcpDumpMessage(" ", Msg, 0);
  555. ReadPointer( Next, &Next );
  556. MsgCount++;
  557. if ( CheckControlC() ) {
  558. return;
  559. }
  560. }
  561. if (MsgCount) {
  562. dprintf( " The LpcDataInfoChainHead queue contains %ld messages\n", MsgCount );
  563. }
  564. else {
  565. dprintf( " The LpcDataInfoChainHead queue is empty\n");
  566. }
  567. }
  568. }
  569. VOID
  570. DumpRunDownQueue(
  571. ULONG64 PortObject
  572. )
  573. {
  574. ULONG64 Head, Next;
  575. ULONG64 Thread;
  576. ULONG Count;
  577. ULONG Off, ChainOff;
  578. GetFieldOffset("nt!ETHREAD", "LpcReplyChain", &ChainOff);
  579. GetFieldOffset("nt!LPCP_PORT_OBJECT", "LpcDataInfoChainHead.Flink", &Off);
  580. Head = PortObject + Off;
  581. ReadPointer( Head, &Next);
  582. Count = 0;
  583. while ((Next != 0) && (Next != Head)) {
  584. if (Count == 0) {
  585. dprintf (" Threads in RunDown queue : ");
  586. }
  587. Thread = ( Next - ChainOff);
  588. dprintf (" 0x%08p", Thread);
  589. ReadPointer( Next, &Next);
  590. Count++;
  591. if ( CheckControlC() ) {
  592. return;
  593. }
  594. }
  595. if (Count) {
  596. dprintf("\n");
  597. }
  598. }
  599. VOID
  600. DumpCommunicationPort(
  601. ULONG64 PortObject,
  602. ULONG64 PortInfo,
  603. BOOLEAN DisplayRelated
  604. )
  605. {
  606. ULONG SemaphoreBuffer[8];
  607. ULONG64 Head, Next;
  608. ULONG Result;
  609. ULONG64 Msg;
  610. ULONG64 pObjectHeader;
  611. ULONG HandleCount, PointerCount, Flags;
  612. pObjectHeader = KD_OBJECT_TO_OBJECT_HEADER(PortObject);
  613. if ( GetFieldValue(pObjectHeader, "nt!OBJECT_HEADER", "HandleCount", HandleCount) ) {
  614. dprintf(" *** %08p: Unable to read object header\n", pObjectHeader );
  615. }
  616. GetFieldValue(pObjectHeader, "nt!OBJECT_HEADER", "PointerCount",PointerCount);
  617. dprintf( "\n");
  618. if ( GetFieldValue(PortInfo, "nt!LPCP_PORT_OBJECT", "Flags", Flags) ) {
  619. dprintf(" *** %08p: Unable to read port object\n", PortInfo );
  620. }
  621. if ((Flags & PORT_TYPE) == SERVER_COMMUNICATION_PORT) {
  622. dprintf( "Server communication port 0x%08lx\n", PortObject);
  623. }
  624. else if ((Flags & PORT_TYPE) == CLIENT_COMMUNICATION_PORT) {
  625. dprintf( "Client communication port 0x%08p\n", PortObject);
  626. }
  627. else {
  628. dprintf( "Invalid port flags 0x%08p, 0x%08lx\n", PortObject, Flags);
  629. return;
  630. }
  631. dprintf( " Handles: %ld References: %ld\n", HandleCount, PointerCount);
  632. DumpPortDataInfo(PortObject);
  633. DumpRunDownQueue(PortObject);
  634. if (DisplayRelated) {
  635. ULONG64 ConnectedPort, ConnectionPort;
  636. InitTypeRead(PortInfo, LPCP_PORT_OBJECT);
  637. dprintf( " Connected port: 0x%08p Server connection port: 0x%08p\n",
  638. (ConnectedPort = ReadField( ConnectedPort)), (ConnectionPort = ReadField(ConnectionPort)));
  639. if (ConnectedPort) {
  640. DumpPortInfo(ConnectedPort, FALSE);
  641. }
  642. if (ConnectionPort) {
  643. DumpPortInfo(ConnectionPort, FALSE);
  644. }
  645. }
  646. }
  647. VOID
  648. DumpPortInfo (
  649. ULONG64 PortObject,
  650. BOOLEAN DisplayRelated
  651. )
  652. {
  653. ULONG Result;
  654. if ( GetFieldValue(PortObject, "nt!LPCP_PORT_OBJECT", "Flags", Result) ) {
  655. dprintf( "%08p: Unable to read port object\n", PortObject );
  656. }
  657. if ((Result & PORT_TYPE) == SERVER_CONNECTION_PORT) {
  658. DumpServerPort(PortObject, PortObject);
  659. }
  660. else {
  661. DumpCommunicationPort(PortObject, PortObject, DisplayRelated);
  662. }
  663. }
  664. BOOLEAN WINAPI
  665. CheckForMessages(
  666. IN PCHAR Tag,
  667. IN PCHAR Filter,
  668. IN ULONG Flags,
  669. IN ULONG64 PoolHeader,
  670. IN ULONG BlockSize,
  671. IN ULONG64 Data,
  672. IN PVOID Context
  673. )
  674. {
  675. ULONG PoolIndex;
  676. if (!PoolHeader) {
  677. return FALSE;
  678. }
  679. if (GetFieldValue(PoolHeader, "nt!_POOL_HEADER", "PoolIndex", PoolIndex)) {
  680. return FALSE;
  681. }
  682. if ((PoolIndex & 0x80) == 0) {
  683. return FALSE;
  684. }
  685. if (!CheckSingleFilter (Tag, Filter)) {
  686. return FALSE;
  687. }
  688. if (LpcpDumpMessage("", Data, (ULONG)(ULONG_PTR)Context)) {
  689. ULONG64 Head, Next;
  690. ULONG EntryOff, ChainOff, RcvOff, HeaderOff;
  691. ULONG64 PortToDump;
  692. ULONG64 ObjectHeader;
  693. ULONG64 ObjectType;
  694. GetFieldOffset("nt!LPCP_MESSAGE", "Entry", &EntryOff);
  695. GetFieldOffset("nt!LPCP_PORT_OBJECT", "LpcDataInfoChainHead", &ChainOff);
  696. GetFieldOffset("nt!LPCP_PORT_OBJECT", "MsgQueue.ReceiveHead", &RcvOff);
  697. Head = Data + EntryOff;
  698. ReadPointer(Head, &Next);
  699. GetFieldOffset("nt!_OBJECT_HEADER", "Body", &HeaderOff);
  700. while ((Next != 0) && (Next != Head)) {
  701. PortToDump = ( Next - ChainOff );
  702. ObjectHeader = PortToDump - HeaderOff;
  703. GetFieldValue(ObjectHeader, "nt!OBJECT_HEADER", "Type", ObjectType);
  704. if ( (ObjectType == (LpcPortObjectType)) ||
  705. (ObjectType == (LpcWaitablePortObjectType))) {
  706. DumpPortInfo(PortToDump, TRUE);
  707. }
  708. else {
  709. PortToDump = Next - RcvOff;
  710. ObjectHeader = PortToDump - HeaderOff;
  711. GetFieldValue(ObjectHeader, "nt!OBJECT_HEADER", "Type", ObjectType);
  712. if ( (ObjectType == (LpcPortObjectType)) ||
  713. (ObjectType == (LpcWaitablePortObjectType))) {
  714. DumpPortInfo(PortToDump, TRUE);
  715. }
  716. }
  717. ReadPointer(Next, &Next);
  718. }
  719. }
  720. return TRUE;
  721. }
  722. VOID
  723. DumpMessagesInfo ()
  724. {
  725. SearchPool ('McpL', 1, 0, &CheckForMessages, NULL);
  726. }
  727. VOID
  728. SearchForMessage (ULONG Message)
  729. {
  730. SearchThreadsForMessage(Message);
  731. if (DoPoolSearch) {
  732. SearchPool ('McpL', 1, 0, &CheckForMessages, (PVOID)UIntToPtr(Message));
  733. }
  734. }
  735. VOID
  736. SearchThreadsForMessage (
  737. ULONG Message
  738. )
  739. {
  740. ULONG64 ProcessHead;
  741. ULONG64 ProcessNext;
  742. ULONG64 Process;
  743. ULONG64 ThreadHead;
  744. ULONG64 ThreadNext;
  745. ULONG64 Thread;
  746. ULONG MsgId;
  747. ULONG64 ClientThread;
  748. ULONG ActOff, PcbThrdOff, ThrdListOff;
  749. ClientThread = 0;
  750. dprintf("Searching message %lx in threads ...\n", Message);
  751. ProcessHead = GetExpression( "nt!PsActiveProcessHead" );
  752. if (!ProcessHead) {
  753. dprintf("Unable to get value of PsActiveProcessHead\n");
  754. return;
  755. }
  756. ProcessNext = GetPointerFromAddress(ProcessHead);
  757. GetFieldOffset("nt!EPROCESS", "ActiveProcessLinks", &ActOff);
  758. GetFieldOffset("nt!EPROCESS", "Pcb.ThreadListHead.Flink", &PcbThrdOff);
  759. GetFieldOffset("nt!KTHREAD", "ThreadListEntry", &ThrdListOff);
  760. while(ProcessNext != 0 && ProcessNext != ProcessHead) {
  761. Process = ProcessNext - ActOff;
  762. ThreadHead = Process + PcbThrdOff;
  763. ThreadNext = GetPointerFromAddress(ThreadHead);
  764. while(ThreadNext != 0 && ThreadNext != ThreadHead) {
  765. Thread = ThreadNext - ThrdListOff;
  766. GetFieldValue(Thread, "nt!ETHREAD", "LpcReplyMessageId", MsgId);
  767. if ((MsgId != 0) &&
  768. ((Message == 0) || (Message == MsgId))) {
  769. dprintf("Client thread %08p waiting a reply from %lx\n", Thread, MsgId);
  770. ClientThread = Thread;
  771. }
  772. GetFieldValue(Thread, "nt!ETHREAD", "LpcReceivedMsgIdValid", MsgId);
  773. if (MsgId) {
  774. GetFieldValue(Thread, "nt!ETHREAD", "LpcReceivedMessageId", MsgId);
  775. if ((Message == 0) || (Message == MsgId)) {
  776. dprintf("Server thread %08p is working on message %lx\n", Thread, MsgId);
  777. }
  778. }
  779. ThreadNext = GetPointerFromAddress(ThreadNext);
  780. if (CheckControlC()) {
  781. return;
  782. }
  783. }
  784. ProcessNext = GetPointerFromAddress(ProcessNext/*&Process->ActiveProcessLinks.Flink*/);
  785. if (CheckControlC()) {
  786. return;
  787. }
  788. }
  789. if (Message && ClientThread) {
  790. SearchThreads(ClientThread);
  791. }
  792. return;
  793. }
  794. BOOLEAN
  795. SearchThreads (
  796. ULONG64 Thread
  797. )
  798. {
  799. ULONG64 PortObject;
  800. ULONG64 ObjectHeader;
  801. ULONG64 ObjectType;
  802. ULONG64 Head, Next;
  803. ULONG Count;
  804. ULONG ChainOff, HeadOff;
  805. dprintf("Searching thread %08p in port rundown queues ...\n", Thread);
  806. GetFieldOffset("nt!ETHREAD", "LpcReplyChain.Flink", &ChainOff);
  807. GetFieldOffset("nt!LPCP_PORT_OBJECT", "LpcReplyChainHead", &HeadOff);
  808. Head = Thread + ChainOff;
  809. Next = GetPointerFromAddress(Head);
  810. while ((Next != 0) && (Next != Head)) {
  811. PortObject = Next - HeadOff ;
  812. ObjectHeader = KD_OBJECT_TO_OBJECT_HEADER(PortObject);
  813. GetFieldValue(ObjectHeader, "nt!OBJECT_HEADER", "Type", ObjectType);
  814. if ( (ObjectType == (LpcPortObjectType)) ||
  815. (ObjectType == (LpcWaitablePortObjectType))) {
  816. DumpPortInfo(PortObject, TRUE);
  817. return TRUE;
  818. }
  819. Next = GetPointerFromAddress( Next);
  820. if ( CheckControlC() ) {
  821. return FALSE;
  822. }
  823. }
  824. dprintf("Thread %08p not found in any reply chain queue\n", Thread);
  825. return FALSE;
  826. }
  827. DECLARE_API( lpc )
  828. /*++
  829. Routine Description:
  830. Dump lpc ports and messages
  831. Arguments:
  832. args - [TypeName]
  833. Return Value:
  834. None
  835. --*/
  836. {
  837. ULONG Result;
  838. LONG SegmentSize;
  839. ULONG64 pMsg;
  840. ULONG64 PortToDump;
  841. char Param1[ MAX_PATH ];
  842. char Param2[ MAX_PATH ];
  843. ULONG64 object;
  844. ULONG64 ThreadAddress;
  845. ULONG MessageId = 0;
  846. Param1[0] = 0;
  847. Param2[0] = 0;
  848. LastSeverPortDisplayied = 0;
  849. if (!sscanf(args,"%s %s",&Param1, &Param2)) {
  850. Param1[0] = 0;
  851. Param2[0] = 0;
  852. }
  853. FetchGlobalVariables();
  854. if ((LpcPortObjectType == 0) || (LpcWaitablePortObjectType == 0)) {
  855. dprintf("The values for LpcPortObjectType or LpcWaitablePortObjectType are invalid. Please ckeck the symbols.\n");
  856. return E_INVALIDARG;
  857. }
  858. if (!_stricmp(Param1, "port")) {
  859. PortToDump = 0;
  860. if (Param2[0]) {
  861. PortToDump = GetExpression(Param2);
  862. }
  863. if (!PortToDump) {
  864. LpcWalkObjectsByType( LpcPortObjectType, FindPortCallback, 0);
  865. LpcWalkObjectsByType( LpcWaitablePortObjectType, FindPortCallback, 0);
  866. }
  867. else {
  868. if ((PortToDump >> 32) == 0) {
  869. PortToDump = (ULONG64) (LONG64) (LONG)PortToDump;
  870. }
  871. DumpPortInfo(PortToDump, TRUE);
  872. }
  873. }
  874. else if (!_stricmp(Param1, "scan")) {
  875. PortToDump = 0;
  876. if (Param2[0]) {
  877. PortToDump = GetExpression(Param2);
  878. }
  879. if (PortToDump) {
  880. LpcWalkObjectsByType( LpcPortObjectType, FindPortCallback, &PortToDump);
  881. LpcWalkObjectsByType( LpcWaitablePortObjectType, FindPortCallback, &PortToDump);
  882. }
  883. }
  884. else if (!_stricmp(Param1, "message")) {
  885. if (Param2[0]) {
  886. if (!sscanf(Param2, "%lx",&MessageId)) {
  887. MessageId = 0;
  888. }
  889. }
  890. if (MessageId){
  891. SearchForMessage(MessageId);
  892. }
  893. else {
  894. DumpMessagesInfo();
  895. }
  896. }
  897. else if (!_stricmp(Param1, "PoolSearch")) {
  898. DoPoolSearch = !DoPoolSearch;
  899. if (DoPoolSearch) {
  900. dprintf( "LPC will search the message in the kernel pool\n");
  901. } else {
  902. dprintf( "LPC will not search the message in the kernel pool\n");
  903. }
  904. }
  905. else if (!_stricmp(Param1, "thread")) {
  906. ThreadAddress = 0;
  907. if (Param2[0]) {
  908. ThreadAddress = GetExpression(Param2);
  909. }
  910. if (ThreadAddress) {
  911. if ((ThreadAddress >> 32) == 0) {
  912. ThreadAddress = (ULONG64) (LONG64) (LONG)ThreadAddress;
  913. }
  914. SearchThreads(ThreadAddress);
  915. }
  916. else {
  917. SearchThreadsForMessage(0);
  918. }
  919. }
  920. else {
  921. LpcHelp();
  922. }
  923. return S_OK;
  924. }