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.

651 lines
17 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. output.hxx
  5. Abstract:
  6. This header file declares output classes for callbacks,
  7. control, parsing, and filtering.
  8. Author:
  9. JasonHa
  10. --*/
  11. #ifndef _OUTPUT_HXX_
  12. #define _OUTPUT_HXX_
  13. class OutputControl
  14. {
  15. public:
  16. // IUnknown
  17. virtual ULONG STDMETHODCALLTYPE AddRef(THIS) {
  18. return ++RefCount;
  19. }
  20. virtual ULONG STDMETHODCALLTYPE Release(void) {
  21. ULONG NewCount = RefCount-1;
  22. if (NewCount == 0)
  23. {
  24. delete this;
  25. }
  26. else
  27. {
  28. RefCount = NewCount;
  29. }
  30. return NewCount;
  31. }
  32. OutputControl()
  33. {
  34. RefCount = 1;
  35. OutCtl = DEBUG_OUTCTL_AMBIENT;
  36. Control = NULL;
  37. }
  38. OutputControl(ULONG OutputControl,
  39. PDEBUG_CLIENT Client = NULL)
  40. {
  41. RefCount = 1;
  42. OutCtl = DEBUG_OUTCTL_AMBIENT;
  43. Control = NULL;
  44. SetControl(OutputControl, Client);
  45. }
  46. OutputControl(PDEBUG_CLIENT Client)
  47. {
  48. RefCount = 1;
  49. OutCtl = DEBUG_OUTCTL_AMBIENT;
  50. Control = NULL;
  51. SetControl(DEBUG_OUTCTL_AMBIENT, Client);
  52. }
  53. ~OutputControl()
  54. {
  55. if (RefCount != 1)
  56. {
  57. DbgPrint("OutputControl::RefCount != 1.\n");
  58. DbgBreakPoint();
  59. }
  60. if (Control != NULL) Control->Release();
  61. }
  62. ULONG GetControl() { return OutCtl; }
  63. HRESULT SetControl(ULONG OutputControl, PDEBUG_CLIENT Client = NULL);
  64. HRESULT Output(ULONG Mask, PCSTR Format, ...);
  65. HRESULT OutputVaList(ULONG Mask, PCSTR Format, va_list Args);
  66. HRESULT Output(PCSTR Format, ...);
  67. HRESULT OutErr(PCSTR Format, ...);
  68. HRESULT OutWarn(PCSTR Format, ...);
  69. HRESULT OutVerb(PCSTR Format, ...);
  70. HRESULT GetInterrupt();
  71. HRESULT SetInterrupt(ULONG Flags);
  72. HRESULT Evaluate(IN PCSTR Expression, IN ULONG DesiredType, OUT PDEBUG_VALUE Value, OUT OPTIONAL PULONG RemainderIndex);
  73. HRESULT CoerceValue(IN PDEBUG_VALUE In, IN ULONG OutType, OUT PDEBUG_VALUE Out);
  74. HRESULT IsPointer64Bit();
  75. private:
  76. ULONG RefCount;
  77. PDEBUG_CONTROL Control;
  78. ULONG OutCtl;
  79. };
  80. class OutputState
  81. {
  82. public:
  83. OutputState(PDEBUG_CLIENT OrgClient, BOOL SameClient=FALSE);
  84. ~OutputState();
  85. HRESULT Setup(ULONG OutMask, PDEBUG_OUTPUT_CALLBACKS OutCallbacks);
  86. HRESULT Execute(IN PCSTR pszCommand);
  87. HRESULT OutputType(
  88. IN BOOL Physical,
  89. IN ULONG64 Offset,
  90. IN ULONG64 Module,
  91. IN ULONG TypeId,
  92. IN ULONG Flags
  93. );
  94. HRESULT OutputType(
  95. IN BOOL Physical,
  96. IN ULONG64 Offset,
  97. IN PCSTR Type,
  98. IN ULONG Flags
  99. );
  100. HRESULT OutputTypePhysical(
  101. IN ULONG64 Offset,
  102. IN ULONG64 Module,
  103. IN ULONG TypeId,
  104. IN ULONG Flags
  105. )
  106. {
  107. return OutputType(TRUE, Offset, Module, TypeId, Flags);
  108. }
  109. HRESULT OutputTypePhysical(
  110. IN ULONG64 Offset,
  111. IN PCSTR Type,
  112. IN ULONG Flags
  113. )
  114. {
  115. return OutputType(TRUE, Offset, Type, Flags);
  116. }
  117. HRESULT OutputTypeVirtual(
  118. IN ULONG64 Offset,
  119. IN ULONG64 Module,
  120. IN ULONG TypeId,
  121. IN ULONG Flags
  122. )
  123. {
  124. return OutputType(FALSE, Offset, Module, TypeId, Flags);
  125. }
  126. HRESULT OutputTypeVirtual(
  127. IN ULONG64 Offset,
  128. IN PCSTR Type,
  129. IN ULONG Flags
  130. )
  131. {
  132. return OutputType(FALSE, Offset, Type, Flags);
  133. }
  134. void Restore();
  135. public:
  136. PDEBUG_CLIENT Client;
  137. private:
  138. HRESULT hrInit;
  139. PDEBUG_CONTROL Control;
  140. PDEBUG_SYMBOLS Symbols;
  141. BOOL CreatedClient;
  142. BOOL SetCallbacks;
  143. BOOL Saved;
  144. ULONG OrgOutMask;
  145. PDEBUG_OUTPUT_CALLBACKS OrgOutCallbacks;
  146. };
  147. //----------------------------------------------------------------------------
  148. //
  149. // Default output callbacks implementation, provides IUnknown for
  150. // static classes.
  151. //
  152. //----------------------------------------------------------------------------
  153. class DefOutputCallbacks :
  154. public IDebugOutputCallbacks
  155. {
  156. public:
  157. DefOutputCallbacks() { RefCount = 1; }
  158. ~DefOutputCallbacks()
  159. {
  160. if (RefCount != 1)
  161. {
  162. DbgPrint("DefOutputCallbacks@0x%p::RefCount(%lu) != 1.\n", this, RefCount);
  163. DbgBreakPoint();
  164. }
  165. #if DBG
  166. RefCount--;
  167. #endif
  168. }
  169. // IUnknown.
  170. STDMETHOD(QueryInterface)(
  171. THIS_
  172. IN REFIID InterfaceId,
  173. OUT PVOID* Interface
  174. );
  175. STDMETHOD_(ULONG, AddRef)(
  176. THIS
  177. );
  178. STDMETHOD_(ULONG, Release)(
  179. THIS
  180. );
  181. // IDebugOutputCallbacks.
  182. STDMETHOD(Output)(
  183. THIS_
  184. IN ULONG Mask,
  185. IN PCSTR Text
  186. );
  187. protected:
  188. ULONG RefCount;
  189. };
  190. //----------------------------------------------------------------------------
  191. //
  192. // DebugOutputCallbacks.
  193. //
  194. //----------------------------------------------------------------------------
  195. class DebugOutputCallbacks : public DefOutputCallbacks
  196. {
  197. public:
  198. // IDebugOutputCallbacks.
  199. STDMETHOD(Output)(
  200. THIS_
  201. IN ULONG Mask,
  202. IN PCSTR Text
  203. );
  204. };
  205. //----------------------------------------------------------------------------
  206. //
  207. // OutputReader
  208. //
  209. // General DebugOutputCallback class to read output.
  210. //
  211. //----------------------------------------------------------------------------
  212. class OutputReader : public DefOutputCallbacks
  213. {
  214. public:
  215. OutputReader()
  216. {
  217. hHeap = NULL;
  218. Buffer = NULL;
  219. BufferSize = 0;
  220. BufferLeft = 0;
  221. }
  222. ~OutputReader()
  223. {
  224. if (Buffer) HeapFree(hHeap, 0, Buffer);
  225. }
  226. // IDebugOutputCallbacks.
  227. STDMETHOD(Output)(
  228. THIS_
  229. IN ULONG Mask,
  230. IN PCSTR Text
  231. );
  232. // Discard any text left unused by Parse
  233. virtual void DiscardOutput();
  234. // Get a copy of the output buffer
  235. HRESULT GetOutputCopy(PSTR *Copy);
  236. // Free the copy
  237. void FreeOutputCopy(PSTR Copy)
  238. {
  239. if (hHeap != NULL) { HeapFree(hHeap, 0, Copy); }
  240. }
  241. protected:
  242. HANDLE hHeap;
  243. PSTR Buffer;
  244. SIZE_T BufferSize;
  245. SIZE_T BufferLeft;
  246. };
  247. //----------------------------------------------------------------------------
  248. //
  249. // OutputParser
  250. //
  251. // General DebugOutputCallback class to parse output.
  252. //
  253. //----------------------------------------------------------------------------
  254. #define PARSE_OUTPUT_DISCARD 0x00000000
  255. #define PARSE_OUTPUT_NO_DISCARD 0x00000001
  256. #define PARSE_OUTPUT_UNPARSED 0x00000000
  257. #define PARSE_OUTPUT_ALL 0x00000002
  258. #define PARSE_OUTPUT_DEFAULT (PARSE_OUTPUT_DISCARD | PARSE_OUTPUT_UNPARSED)
  259. class OutputParser : public OutputReader
  260. {
  261. public:
  262. OutputParser() : OutputReader()
  263. {
  264. UnparsedIndex = 0;
  265. }
  266. // Send all read text through Parse method
  267. // Flags:
  268. // PARSE_OUTPUT_DISCARD or PARSE_OUTPUT_NO_DISCARD
  269. // PARSE_OUTPUT_UNPARSED or PARSE_OUTPUT_ALL
  270. // PARSE_OUTPUT_DEFAULT = PARSE_OUTPUT_DISCARD + PARSE_OUTPUT_UNPARSED
  271. HRESULT ParseOutput(FLONG Flags = PARSE_OUTPUT_DEFAULT);
  272. // Discard any text left unused by Parse
  273. void DiscardOutput();
  274. // Check if ready to look for keys/values
  275. virtual HRESULT Ready() PURE;
  276. // Reset progress counter so we may parse more output
  277. virtual void Relook() PURE;
  278. // Parse line of text and optionally return index to unused portion of text
  279. virtual HRESULT Parse(IN PCSTR Text, OUT OPTIONAL PULONG RemainderIndex) PURE;
  280. // Check if all keys/values were found during past reads
  281. virtual HRESULT Complete() PURE;
  282. private:
  283. DWORD UnparsedIndex;
  284. };
  285. //----------------------------------------------------------------------------
  286. //
  287. // BasicOutputParser
  288. //
  289. // Basic DebugOutputCallback class to parse output looking for
  290. // string keys and subsequent values.
  291. //
  292. //----------------------------------------------------------------------------
  293. #define PARSER_UNSPECIFIED_RADIX -1
  294. #define PARSER_DEFAULT_RADIX 0
  295. class BasicOutputParser : public OutputParser
  296. {
  297. typedef struct {
  298. PDEBUG_VALUE Value;
  299. ULONG Type;
  300. ULONG Radix;
  301. CHAR Key[80];
  302. } LookupEntry;
  303. public:
  304. BasicOutputParser(PDEBUG_CLIENT OutputClient, ULONG TotalEntries = 4)
  305. {
  306. Client = OutputClient;
  307. Entries = new LookupEntry[TotalEntries];
  308. if (!Entries) TotalEntries = 0;
  309. MaxEntries = TotalEntries;
  310. NumEntries = 0;
  311. CurEntry = 0;
  312. }
  313. ~BasicOutputParser()
  314. {
  315. if (Entries) delete[] Entries;
  316. }
  317. HRESULT LookFor(OUT PDEBUG_VALUE Value,
  318. IN PCSTR Key,
  319. IN ULONG Type = DEBUG_VALUE_INVALID,
  320. IN ULONG Radix = PARSER_UNSPECIFIED_RADIX);
  321. // Check if ready to look for keys/values
  322. HRESULT Ready() { return (CurEntry != NumEntries) ? S_OK : S_FALSE; }
  323. // Reset progress counter so we may parse more output
  324. void Relook() { CurEntry = 0; }
  325. // Parse line of text and optionally return index to unused portion of text
  326. HRESULT Parse(IN PCSTR Text, OUT OPTIONAL PULONG RemainderIndex);
  327. // Check if all keys/values were found during past reads
  328. HRESULT Complete()
  329. {
  330. return (Client != NULL &&
  331. CurEntry == NumEntries) ?
  332. S_OK :
  333. S_FALSE;
  334. }
  335. private:
  336. PDEBUG_CLIENT Client;
  337. ULONG MaxEntries;
  338. ULONG NumEntries;
  339. ULONG CurEntry;
  340. LookupEntry *Entries;
  341. };
  342. //----------------------------------------------------------------------------
  343. //
  344. // BitFieldParser
  345. //
  346. // DebugOutputCallback class to parse bitfield type output
  347. //
  348. //----------------------------------------------------------------------------
  349. class BitFieldInfo {
  350. public:
  351. BitFieldInfo() { Valid = FALSE; };
  352. BitFieldInfo(ULONG InitBitPos, ULONG InitBits) {
  353. Valid = Compose(InitBitPos, InitBits);
  354. }
  355. BOOL Compose(ULONG CBitPos, ULONG CBits)
  356. {
  357. BitPos = CBitPos;
  358. Bits = CBits;
  359. Mask = (((((ULONG64) 1) << Bits) - 1) << BitPos);
  360. return TRUE;
  361. }
  362. BOOL Valid;
  363. ULONG BitPos;
  364. ULONG Bits;
  365. ULONG64 Mask;
  366. };
  367. class BitFieldParser : public OutputParser
  368. {
  369. public:
  370. BitFieldParser(PDEBUG_CLIENT Client, BitFieldInfo *BFI);
  371. // Reset progress counter so we may parse more output
  372. void Relook()
  373. {
  374. if (BitField != NULL)
  375. {
  376. BitField->Valid = FALSE;
  377. BitField->BitPos = 0;
  378. BitField->Bits = 0;
  379. BitField->Mask = 0;
  380. }
  381. BitFieldReader.Relook();
  382. }
  383. // Check if ready to look for bit fields
  384. HRESULT Ready()
  385. {
  386. return (BitField != NULL) ?
  387. BitFieldReader.Ready() :
  388. S_FALSE;
  389. }
  390. // Parse line of text and optionally return index to unused portion of text
  391. HRESULT Parse(IN PCSTR Text, OUT OPTIONAL PULONG RemainderIndex);
  392. // Check if bit fields were found during past reads
  393. HRESULT Complete()
  394. {
  395. return (BitField != NULL && BitField->Valid) ?
  396. BitFieldReader.Complete() :
  397. S_FALSE;
  398. }
  399. private:
  400. BitFieldInfo *BitField;
  401. DEBUG_VALUE BitPos;
  402. DEBUG_VALUE Bits;
  403. BasicOutputParser BitFieldReader;
  404. };
  405. //----------------------------------------------------------------------------
  406. //
  407. // OutputFilter
  408. //
  409. // DebugOutputCallback class to filter output
  410. // by skipping/replacing lines.
  411. //
  412. //----------------------------------------------------------------------------
  413. // Query Flags
  414. #define OUTFILTER_QUERY_EVERY_LINE 0x00000000
  415. #define OUTFILTER_QUERY_ONE_LINE 0x00000001
  416. #define OUTFILTER_QUERY_WHOLE_WORD 0x00000002 // Characters before and after
  417. // query must not be C symbols
  418. // [a-z,A-A,0-9,_]
  419. #define OUTFILTER_QUERY_ENABLED 0x00000004
  420. #define OUTFILTER_QUERY_HIT 0x00000008
  421. // Replace Flags
  422. #define OUTFILTER_REPLACE_EVERY 0x00000000
  423. #define OUTFILTER_REPLACE_ONCE 0x00010000
  424. #define OUTFILTER_REPLACE_ALL_INSTANCES (OUTFILTER_REPLACE_EVERY | OUTFILTER_QUERY_EVERY_LINE)
  425. #define OUTFILTER_REPLACE_ONCE_PER_LINE (OUTFILTER_REPLACE_ONCE | OUTFILTER_QUERY_EVERY_LINE)
  426. #define OUTFILTER_REPLACE_EXACTLY_ONCE (OUTFILTER_REPLACE_ONCE | OUTFILTER_QUERY_ONE_LINE)
  427. #define OUTFILTER_REPLACE_CONTINUE 0x00000000
  428. #define OUTFILTER_REPLACE_NEXT_LINE 0x00020000 // Stop replacement checks
  429. // for current line after
  430. // this replacement
  431. #define OUTFILTER_REPLACE_BEFORE 0x04000000 // Replace text in line prior to query match
  432. #define OUTFILTER_REPLACE_THIS 0x02000000 // Replace query text
  433. #define OUTFILTER_REPLACE_AFTER 0x01000000 // Replace text following query match
  434. #define OUTFILTER_REPLACE_FROM_START (OUTFILTER_REPLACE_BEFORE | OUTFILTER_REPLACE_THIS)
  435. #define OUTFILTER_REPLACE_TO_END (OUTFILTER_REPLACE_THIS | OUTFILTER_REPLACE_AFTER)
  436. #define OUTFILTER_REPLACE_LINE (OUTFILTER_REPLACE_BEFORE | \
  437. OUTFILTER_REPLACE_THIS | \
  438. OUTFILTER_REPLACE_AFTER)
  439. #define OUTFILTER_REPLACE_PRIORITY(x) (((x+8) & 0xF) << 28) // Higher priority replacement queries
  440. // are tested before lower. Priority
  441. // range: 7 (high) to -7 (low)
  442. #define OUTFILTER_REPLACE_DEFAULT (OUTFILTER_REPLACE_ALL_INSTANCES | \
  443. OUTFILTER_REPLACE_CONTINUE | \
  444. OUTFILTER_REPLACE_THIS | \
  445. OUTFILTER_REPLACE_PRIORITY(0))
  446. // Skip Flags
  447. #define OUTFILTER_SKIP_DEFAULT OUTFILTER_QUERY_EVERY_LINE
  448. // FindMatch Flags
  449. #define OUTFILTER_FINDMATCH_ANYWHERE 0
  450. #define OUTFILTER_FINDMATCH_AT_START 1
  451. #define OUTFILTER_FINDMATCH_MARK 0
  452. #define OUTFILTER_FINDMATCH_NO_MARK 2
  453. #define OUTFILTER_FINDMATCH_DEFAULT (OUTFILTER_FINDMATCH_ANYWHERE | OUTFILTER_FINDMATCH_MARK)
  454. class OutputFilter : public OutputReader
  455. {
  456. public:
  457. OutputFilter(PDEBUG_CLIENT DbgClient) : OutputReader()
  458. {
  459. Client = DbgClient;
  460. if (Client != NULL) Client->AddRef();
  461. SkipList = NULL;
  462. ReplaceList = NULL;
  463. Outputing = FALSE;
  464. }
  465. ~OutputFilter()
  466. {
  467. if (Client != NULL) Client->Release();
  468. }
  469. // IDebugOutputCallbacks.
  470. STDMETHOD(Output)(
  471. THIS_
  472. IN ULONG Mask,
  473. IN PCSTR Text
  474. );
  475. HRESULT Query(PCSTR Query,
  476. PDEBUG_VALUE Value = NULL,
  477. ULONG Type = DEBUG_VALUE_INVALID,
  478. ULONG Radix = PARSER_UNSPECIFIED_RADIX);
  479. HRESULT Replace(ULONG Flags, PCSTR Query, PCSTR Replacement);
  480. HRESULT Skip(ULONG Flags, PCSTR Query);
  481. HRESULT OutputText(OutputControl *OutCtl = NULL, ULONG Mask = DEBUG_OUTPUT_NORMAL);
  482. protected:
  483. class QuerySpec
  484. {
  485. public:
  486. QuerySpec(ULONG Flags, PCSTR Query);
  487. ~QuerySpec()
  488. {
  489. if (Query != NULL)
  490. {
  491. delete[] Query;
  492. }
  493. }
  494. QuerySpec *Next;
  495. ULONG Flags;
  496. ULONG QueryLen;
  497. PSTR Query;
  498. };
  499. class ReplacementSpec : public QuerySpec
  500. {
  501. public:
  502. ReplacementSpec(ULONG Flags, PCSTR QueryText, PCSTR ReplacementText);
  503. ~ReplacementSpec()
  504. {
  505. if (Replacement != NULL)
  506. {
  507. delete[] Replacement;
  508. }
  509. }
  510. // ReplacementSpec *Next;
  511. ULONG ReplacementLen;
  512. PSTR Replacement;
  513. };
  514. QuerySpec **FindPrior(ULONG Flags, PCSTR Query, QuerySpec **List);
  515. QuerySpec *FindMatch(PCSTR Text,
  516. QuerySpec *List,
  517. ULONG Start = 0,
  518. ULONG Flags = OUTFILTER_FINDMATCH_DEFAULT,
  519. PULONG MatchPos = NULL);
  520. PDEBUG_CLIENT Client;
  521. ReplacementSpec *ReplaceList;
  522. QuerySpec *SkipList;
  523. private:
  524. BOOL Outputing;
  525. };
  526. #endif _OUTPUT_HXX_