Leaked source code of windows server 2003
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.

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