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.

250 lines
4.9 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Tunnel.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Dan Lovinger 2-Apr-96
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. //
  16. // printf is really expensive to iteratively call to do the indenting,
  17. // so we just build up some avaliable spaces to mangle as required
  18. //
  19. #define MIN(a,b) ((a) > (b) ? (b) : (a))
  20. #define MAXINDENT 128
  21. #define INDENTSTEP 2
  22. #define MakeSpace(I) Space[MIN((I)*INDENTSTEP, MAXINDENT)] = '\0'
  23. #define RestoreSpace(I) Space[MIN((I)*INDENTSTEP, MAXINDENT)] = ' '
  24. CHAR Space[MAXINDENT*INDENTSTEP + 1];
  25. //#define SplitLI(LI) (LI).HighPart, (LI).LowPart
  26. #define SplitLL(LL) (ULONG)((LL) >> 32), (ULONG)((LL) & 0xffffffff)
  27. VOID
  28. DumpTunnelNode (
  29. ULONG64 Node,
  30. ULONG Indent
  31. )
  32. {
  33. WCHAR ShortNameStr[8+1+3];
  34. WCHAR LongNameStr[64];
  35. ULONG Flags;
  36. UNICODE_STRING ShortName, LongName;
  37. if (GetFieldValue(Node, "TUNNEL_NODE", "Flags", Flags)) {
  38. return;
  39. }
  40. InitTypeRead(Node, TUNNEL_NODE);
  41. //
  42. // Grab the strings from the debugee
  43. //
  44. if (!ReadMemory(ReadField(ShortName.Buffer),
  45. &ShortNameStr,
  46. (ShortName.Length = (USHORT) ReadField(ShortName.Length)),
  47. NULL)) {
  48. return;
  49. }
  50. if (!ReadMemory(ReadField(LongName.Buffer),
  51. &LongNameStr,
  52. LongName.Length = MIN((USHORT) ReadField(LongName.Length), sizeof(LongNameStr)),
  53. NULL)) {
  54. return;
  55. }
  56. //
  57. // Modify the node in-place so we can use normal printing
  58. //
  59. LongName.Buffer = LongNameStr;
  60. ShortName.Buffer = ShortNameStr;
  61. MakeSpace(Indent);
  62. dprintf("%sNode @ %08 Cr %08x%08x DK %08x%08x [",
  63. Space,
  64. Node,
  65. SplitLL(ReadField(CreateTime)),
  66. SplitLL(ReadField(DirKey)));
  67. //
  68. // Must be kept in sync with flag usage in fsrtl\tunnel.c
  69. //
  70. if (Flags & 0x1)
  71. dprintf("NLA");
  72. else
  73. dprintf("LA");
  74. if (Flags & 0x2)
  75. dprintf(" KYS");
  76. else
  77. dprintf(" KYL");
  78. dprintf("]\n");
  79. dprintf("%sP %08p R %08p L %08p Sfn/Lfn \"%wZ\"/\"%wZ\"\n",
  80. Space,
  81. ReadField(CacheLinks.Parent),
  82. ReadField(CacheLinks.RightChild),
  83. ReadField(CacheLinks.LeftChild),
  84. &ShortName,
  85. &LongName );
  86. dprintf("%sF %08p B %08p\n",
  87. Space,
  88. ReadField(ListLinks.Flink),
  89. ReadField(ListLinks.Blink));
  90. RestoreSpace(Indent);
  91. }
  92. VOID DumpTunnelNodeWrapper (
  93. ULONG64 pCacheLinks,
  94. ULONG Indent
  95. )
  96. {
  97. // TUNNEL_NODE Node, *pNode;
  98. static ULONG Off=0;
  99. if (!Off) {
  100. GetFieldOffset("TUNNEL_NODE", "CacheLinks", &Off);
  101. }
  102. DumpTunnelNode(pCacheLinks - Off, Indent);
  103. }
  104. VOID
  105. DumpTunnel (
  106. ULONG64 pTunnel
  107. )
  108. {
  109. ULONG64 pLink, pHead, NodeFlink=0, TimerQueueFlink, pNode;
  110. ULONG Indent = 0, EntryCount = 0, NumEntries, Offset, ListOffset;
  111. ULONG64 Cache;
  112. if (GetFieldValue(pTunnel, "TUNNEL", "NumEntries", NumEntries)) {
  113. dprintf("Can't read TUNNEL at %p\n", pTunnel);
  114. return;
  115. }
  116. GetFieldValue(pTunnel, "TUNNEL", "Cache", Cache);
  117. GetFieldValue(pTunnel, "TUNNEL", "TimerQueue.Flink", TimerQueueFlink);
  118. pLink = TimerQueueFlink;
  119. GetFieldOffset("TUNNEL", "TimerQueue", &Offset);
  120. dprintf("Tunnel @ %08x\n"
  121. "NumEntries = %ld\n\n"
  122. "Splay Tree @ %08x\n",
  123. pTunnel,
  124. NumEntries,
  125. Cache);
  126. EntryCount = DumpSplayTree(Cache, DumpTunnelNodeWrapper);
  127. if (EntryCount != NumEntries) {
  128. dprintf("Tree count mismatch (%d not expected %d)\n", EntryCount, NumEntries);
  129. }
  130. GetFieldOffset("TUNNEL_NODE", "ListLinks", &ListOffset);
  131. for (EntryCount = 0,
  132. pHead = pTunnel + Offset,
  133. pLink = TimerQueueFlink;
  134. pLink != pHead;
  135. pLink = NodeFlink,
  136. EntryCount++) {
  137. pNode = pLink - ListOffset;
  138. if (pLink == TimerQueueFlink) {
  139. dprintf("\nTimer Queue @ %08x\n", pHead);
  140. }
  141. if (GetFieldValue(pNode, "TUNNEL_NODE",
  142. "ListLinks.Flink", NodeFlink)) {
  143. dprintf("Can't read TUNNEL_NODE at %p\n", pNode);
  144. return;
  145. }
  146. DumpTunnelNode(pNode, 0);
  147. if ( CheckControlC() ) {
  148. return;
  149. }
  150. }
  151. if (EntryCount != NumEntries) {
  152. dprintf("Timer count mismatch (%d not expected %d)\n", EntryCount, NumEntries);
  153. }
  154. }
  155. DECLARE_API( tunnel )
  156. /*++
  157. Routine Description:
  158. Dump tunnel caches
  159. Arguments:
  160. arg - <Address>
  161. Return Value:
  162. None
  163. --*/
  164. {
  165. ULONG64 Tunnel = 0;
  166. RtlFillMemory(Space, sizeof(Space), ' ');
  167. Tunnel = GetExpression(args);
  168. if (Tunnel == 0) {
  169. //
  170. // No args
  171. //
  172. return E_INVALIDARG;
  173. }
  174. DumpTunnel(Tunnel);
  175. return S_OK;
  176. }