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.

888 lines
23 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: dumpers.cxx
  3. *
  4. * Copyright (c) 2000 Microsoft Corporation
  5. *
  6. \**************************************************************************/
  7. #include "precomp.hxx"
  8. // A resonable count limit for scans and walls
  9. #define COUNT_LIMIT 0x07ffffff
  10. /**************************************************************************\
  11. *
  12. * class ScanDumper
  13. *
  14. \**************************************************************************/
  15. const FIELD_INFO ScanFieldsInit[SCAN_FIELDS_LENGTH] = {
  16. { DbgStr("cWalls"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL },
  17. { DbgStr("yTop"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL },
  18. { DbgStr("yBottom"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL },
  19. { DbgStr("ai_x[0]"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME | DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL },
  20. };
  21. const SYM_DUMP_PARAM ScanSymInit = {
  22. sizeof (SYM_DUMP_PARAM), DbgStr(GDIType(SCAN)), DBG_DUMP_NO_PRINT, 0,
  23. NULL, NULL, NULL, SCAN_FIELDS_LENGTH, NULL
  24. };
  25. const FIELD_INFO WallFieldsInit[1] = {
  26. { DbgStr("x"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, LeftWallCallback },
  27. };
  28. const SYM_DUMP_PARAM WallSymInit = {
  29. sizeof (SYM_DUMP_PARAM), DbgStr(GDIType(_INDEX_LONG)), DBG_DUMP_NO_PRINT | DBG_DUMP_ARRAY, 0,
  30. NULL, NULL, NULL, 1, NULL
  31. };
  32. const SYM_DUMP_PARAM cWalls2SymInit = {
  33. sizeof (SYM_DUMP_PARAM), DbgStr("ULONG"), DBG_DUMP_NO_PRINT | DBG_DUMP_ADDRESS_AT_END | DBG_DUMP_COPY_TYPE_DATA, 0,
  34. NULL, NULL, NULL, 0, NULL
  35. };
  36. /**************************************************************************\
  37. *
  38. * ScanDumper::ScanDumper
  39. *
  40. \**************************************************************************/
  41. ScanDumper::ScanDumper(
  42. ULONG64 HeadScanAddr,
  43. ULONG64 TailScanAddr,
  44. ULONG ScanCount,
  45. ULONG64 AllocationBase,
  46. ULONG64 AllocationLimit,
  47. ULONG Flags
  48. )
  49. {
  50. block = 0;
  51. Top = POS_INFINITY;
  52. Bottom = NEG_INFINITY;
  53. FirstScanAddr = HeadScanAddr;
  54. LastScanAddr = TailScanAddr;
  55. ScanLimit = ScanCount ? ScanCount : COUNT_LIMIT;
  56. AddressBase = AllocationBase;
  57. AddressLimit = AllocationLimit;
  58. PrintBlocks = (Flags & SCAN_DUMPER_NO_PRINT) == 0;
  59. ForceDump = (Flags & SCAN_DUMPER_FORCE) != 0;
  60. Reverse = (Flags & SCAN_DUMPER_FROM_TAIL) != 0;
  61. // Enable to print a . after each right wall is
  62. // processed when block printing is disabled.
  63. PrintProgress = FALSE;
  64. ProgressCount = 0;
  65. RtlCopyMemory(ScanFields, ScanFieldsInit, sizeof(ScanFields));
  66. RtlCopyMemory(&ScanSym, &ScanSymInit, sizeof(ScanSym));
  67. ScanSym.Fields = ScanFields;
  68. ListWallSize.fOptions = 0;
  69. ListWallSize.fieldCallBack = WallArrayEntryCallback;
  70. RtlCopyMemory(WallFields, WallFieldsInit, sizeof(WallFields));
  71. RtlCopyMemory(&WallSym, &WallSymInit, sizeof(WallSym));
  72. WallSym.listLink = &ListWallSize;
  73. WallSym.Fields = WallFields;
  74. RtlCopyMemory(&cWalls2Sym, &cWalls2SymInit, sizeof(cWalls2Sym));
  75. Valid = TRUE;
  76. // Get basic scan structure information
  77. ScanSize = GetTypeSize(GDIType(SCAN));
  78. if (1)
  79. {
  80. cWallsSize = GetTypeSize("ULONG");
  81. IXSize = GetTypeSize(GDIType(_INDEX_LONG));
  82. }
  83. else
  84. {
  85. ULONG error;
  86. error = Ioctl(IG_DUMP_SYMBOL_INFO, &ScanSym, ScanSym.size);
  87. if (error)
  88. {
  89. dprintf(" SCAN type info Ioctl returned %s\n", pszWinDbgError(error));
  90. }
  91. cWallsSize = ScanFields[SCAN_CWALLS].size;
  92. IXSize = ScanFields[SCAN_AI_X_ADDR].size;
  93. }
  94. if (Reverse && cWallsSize != GetTypeSize("ULONG"))
  95. {
  96. dprintf(" * Error: sizeof(SCAN::cWalls) != sizeof(ULONG)\n"
  97. " => From tail scan dumping won't work.\n");
  98. Reverse = FALSE;
  99. }
  100. if (Reverse)
  101. {
  102. scan = ScanCount;
  103. NegativeScanCount = (ScanCount == 0);
  104. ScanAddr = TailScanAddr;
  105. }
  106. else
  107. {
  108. scan = -1;
  109. NegativeScanCount = FALSE;
  110. ScanAddr = HeadScanAddr;
  111. }
  112. // Will DumpScans work?
  113. CanDump = (ScanSize != 0) && (cWallsSize != 0) && (IXSize != 0);
  114. }
  115. /**************************************************************************\
  116. *
  117. * ScanDumper::DumpScans
  118. *
  119. \**************************************************************************/
  120. BOOL
  121. ScanDumper::DumpScans(
  122. ULONG Count
  123. )
  124. {
  125. ULONG64 NextScanAddr;
  126. ULONG cWalls1, cWalls2;
  127. ULONG error;
  128. if (!CanDump)
  129. {
  130. dprintf(" An error occured in this extension preventing DumpScans from working.\n");
  131. return FALSE;
  132. }
  133. if (! Count && PrintBlocks)
  134. {
  135. dprintf("\tNo scans to dump.\n");
  136. }
  137. if (Count > 100)
  138. {
  139. PrintProgress = TRUE;
  140. ProgressCount = 0;
  141. }
  142. while (Count-- && !CheckControlC())
  143. {
  144. cWalls1 = cWalls2 = 0;
  145. if (Reverse)
  146. {
  147. if (!NT_SUCCESS(ValidateAddress(ScanAddr, "End of ScanAddr", SCAN_VALID_AT_END)))
  148. {
  149. if (!ForceDump) break;
  150. }
  151. cWalls2Sym.addr = ScanAddr;
  152. cWalls2Sym.Context = &cWalls2;
  153. error = Ioctl(IG_DUMP_SYMBOL_INFO, &cWalls2Sym, cWalls2Sym.size);
  154. if (error)
  155. {
  156. dprintf(" Ioctl returned %s\n", pszWinDbgError(error));
  157. break;
  158. }
  159. ScanAddr -= cWalls2 * IXSize + ScanSize;
  160. }
  161. if (gbVerbose)
  162. {
  163. dprintf(" Examining scan %d @ %#p\n", scan+(Reverse?-1:+1), ScanAddr);
  164. }
  165. if (!NT_SUCCESS(ValidateAddress(ScanAddr, "ScanAddr", SCAN_VALID_AT_START)))
  166. {
  167. if (!ForceDump) break;
  168. }
  169. ScanSym.addr = ScanAddr;
  170. error = Ioctl(IG_DUMP_SYMBOL_INFO, &ScanSym, ScanSym.size);
  171. if (error)
  172. {
  173. dprintf(" Ioctl returned %s\n", pszWinDbgError(error));
  174. break;
  175. }
  176. cWalls1 = (ULONG)ScanFields[SCAN_CWALLS].address;
  177. // Update Top and Bottom information
  178. if (!ScanAdvance((LONG)ScanFields[SCAN_YTOP].address, (LONG)ScanFields[SCAN_YBOTTOM].address, Reverse ? cWalls2 : cWalls1))
  179. {
  180. if (!ForceDump) break;
  181. }
  182. // Read cWalls2 if we don't know it.
  183. if (!Reverse)
  184. {
  185. NextScanAddr = ScanAddr + ScanSize + cWalls1 * IXSize;
  186. if (!NT_SUCCESS(ValidateAddress(NextScanAddr, "End of Wall array", SCAN_VALID_AT_END | SCAN_VALID_NO_ERROR_PRINT)))
  187. {
  188. dprintf(" * End of Wall array @ %#p, length %u, at scan %d lies outside valid scan range\n", NextScanAddr, cWalls1, scan);
  189. if (!ForceDump) break;
  190. }
  191. cWalls2Sym.addr = NextScanAddr;
  192. cWalls2Sym.Context = &cWalls2;
  193. error = Ioctl(IG_DUMP_SYMBOL_INFO, &cWalls2Sym, cWalls2Sym.size);
  194. if (error)
  195. {
  196. dprintf(" Ioctl returned %s\n", pszWinDbgError(error));
  197. break;
  198. }
  199. }
  200. // Check cWalls against cWalls2
  201. if (cWalls1 != cWalls2)
  202. {
  203. dprintf(" * cWalls (%u) != cWalls2 (%u) at scan %d\n", cWalls1, cWalls2, scan);
  204. Valid = FALSE;
  205. if (!ForceDump) break;
  206. }
  207. // cWalls is set by ScanAdvance
  208. if (cWalls != 0)
  209. {
  210. WallSym.Context = (PVOID)this;
  211. WallSym.addr = ScanFields[SCAN_AI_X_ADDR].address;
  212. ListWallSize.size = cWalls;
  213. WallFields[0].fieldCallBack = LeftWallCallback;
  214. error = Ioctl(IG_DUMP_SYMBOL_INFO, &WallSym, WallSym.size);
  215. if (error)
  216. {
  217. dprintf(" Ioctl returned %s\n", pszWinDbgError(error));
  218. break;
  219. }
  220. if (!Valid && !ForceDump) break;
  221. }
  222. if (!Reverse)
  223. {
  224. if (!NT_SUCCESS(ValidateAddress(NextScanAddr, "Next ScanAddr", SCAN_VALID_AT_END)))
  225. {
  226. if (!ForceDump) break;
  227. }
  228. ScanAddr = NextScanAddr;
  229. }
  230. }
  231. return Valid;
  232. }
  233. /**************************************************************************\
  234. *
  235. * ScanDumper::NextScan
  236. *
  237. \**************************************************************************/
  238. BOOL
  239. ScanDumper::NextScan(
  240. LONG NextTop,
  241. LONG NextBottom,
  242. ULONG NumWalls
  243. )
  244. {
  245. LONG PrevBottom = Bottom;
  246. BOOL bRet = TRUE;
  247. scan++;
  248. if (scan < 0 || (ULONG)scan >= ScanLimit)
  249. {
  250. dprintf(" * Scan count %d is not in range 1 to %u\n", scan+1, ScanLimit);
  251. Valid = FALSE;
  252. bRet = FALSE;
  253. }
  254. wall = 0;
  255. PrevRight = NEG_INFINITY;
  256. cWalls = NumWalls;
  257. Top = NextTop;
  258. Bottom = NextBottom;
  259. if ((bRet || ForceDump) && Top < PrevBottom)
  260. {
  261. dprintf(" * Scan %d top (%d) < prev bottom (%d)\n",
  262. scan, Top, PrevBottom);
  263. Valid = FALSE;
  264. bRet = FALSE;
  265. }
  266. if (gbVerbose)
  267. {
  268. dprintf(" * Scan %d covers from %d to %d and has %u walls.\n", scan, Top, Bottom, cWalls);
  269. }
  270. if ((bRet || ForceDump) && Bottom < Top)
  271. {
  272. dprintf(" * Scan %d bottom (%d) < top (%d)\n",
  273. scan, Bottom, Top);
  274. Valid = FALSE;
  275. bRet = FALSE;
  276. }
  277. if ((bRet || ForceDump) && cWalls > COUNT_LIMIT)
  278. {
  279. dprintf(" * cWalls (%u) is suspiciously long at scan %d\n", cWalls, scan);
  280. Valid = FALSE;
  281. bRet = FALSE;
  282. }
  283. if ((bRet || ForceDump) && cWalls == 0 && PrintBlocks)
  284. {
  285. dprintf("\tNULL Scans from %d to %d.\n", Top, Bottom);
  286. }
  287. return bRet;
  288. }
  289. /**************************************************************************\
  290. *
  291. * ScanDumper::PrevScan
  292. *
  293. \**************************************************************************/
  294. BOOL
  295. ScanDumper::PrevScan(
  296. LONG PrevTop,
  297. LONG PrevBottom,
  298. ULONG NumWalls
  299. )
  300. {
  301. LONG NextTop = Top;
  302. BOOL bRet = TRUE;
  303. scan--;
  304. if (NegativeScanCount)
  305. {
  306. if (-scan < 1 || (ULONG)-scan > ScanLimit)
  307. {
  308. dprintf(" * Scan count %u is not in range 1 to %u\n", -scan, ScanLimit);
  309. Valid = FALSE;
  310. bRet = FALSE;
  311. }
  312. }
  313. else
  314. {
  315. if (scan < 0 || (ULONG)scan >= ScanLimit)
  316. {
  317. dprintf(" * Scan count %u is not in range 1 to %u\n", scan+1, ScanLimit);
  318. Valid = FALSE;
  319. bRet = FALSE;
  320. }
  321. }
  322. wall = 0;
  323. PrevRight = NEG_INFINITY;
  324. cWalls = NumWalls;
  325. Top = PrevTop;
  326. Bottom = PrevBottom;
  327. if ((bRet || ForceDump) && Bottom > NextTop)
  328. {
  329. dprintf(" * Scan %d bottom (%d) > next top (%d)\n",
  330. scan, Bottom, NextTop);
  331. Valid = FALSE;
  332. bRet = FALSE;
  333. }
  334. if (gbVerbose)
  335. {
  336. dprintf(" * Scan %d covers from %d to %d and has %u walls.\n", scan, Top, Bottom, cWalls);
  337. }
  338. if ((bRet || ForceDump) && Bottom < Top)
  339. {
  340. dprintf(" * Scan %d bottom (%d) < top (%d)\n",
  341. scan, Bottom, Top);
  342. Valid = FALSE;
  343. bRet = FALSE;
  344. }
  345. if ((bRet || ForceDump) && cWalls > COUNT_LIMIT)
  346. {
  347. dprintf(" * cWalls (%u) is suspiciously long at scan %d\n", cWalls, scan);
  348. Valid = FALSE;
  349. bRet = FALSE;
  350. }
  351. if ((bRet || ForceDump) && cWalls == 0 && PrintBlocks)
  352. {
  353. dprintf("\tNULL Scans from %d to %d.\n", Top, Bottom);
  354. }
  355. return bRet;
  356. }
  357. /**************************************************************************\
  358. *
  359. * ScanDumper::NextLeftWall
  360. *
  361. \**************************************************************************/
  362. ULONG
  363. ScanDumper::NextLeftWall(
  364. LONG NextLeft
  365. )
  366. {
  367. ULONG Status = STATUS_SUCCESS;
  368. if (wall > cWalls)
  369. {
  370. dprintf(" * More walls (%u) than expected (%u).\n", wall, cWalls);
  371. Valid = FALSE;
  372. return STATUS_UNSUCCESSFUL;
  373. }
  374. Left = NextLeft;
  375. if (Left <= PrevRight)
  376. {
  377. dprintf(" * Left wall %d (%d) <= previous right (%d) @ scan %d\n",
  378. wall, Left, PrevRight, scan);
  379. Valid = FALSE;
  380. Status = STATUS_UNSUCCESSFUL;
  381. }
  382. wall++;
  383. return Status;
  384. }
  385. /**************************************************************************\
  386. *
  387. * ScanDumper::NextRightWall
  388. *
  389. \**************************************************************************/
  390. ULONG ScanDumper::NextRightWall(
  391. LONG Right
  392. )
  393. {
  394. ULONG Status = STATUS_SUCCESS;
  395. if (wall > cWalls)
  396. {
  397. dprintf(" * More walls (%u) than expected (%u).\n", wall, cWalls);
  398. Valid = FALSE;
  399. return STATUS_UNSUCCESSFUL;
  400. }
  401. if (Right <= Left)
  402. {
  403. dprintf(" * Right wall %d (%d) <= left (%d) @ scan %d\n",
  404. wall, Right, Left, scan);
  405. Valid = FALSE;
  406. Status = STATUS_UNSUCCESSFUL;
  407. }
  408. if (PrintBlocks)
  409. {
  410. dprintf("\tRectangle #%d (%d,%d) - (%d,%d)\n",
  411. block, Left, Top, Right, Bottom);
  412. }
  413. else if (PrintProgress)
  414. {
  415. dprintf(".");
  416. if ((ProgressCount++ % 60) == 0)
  417. {
  418. dprintf("\n");
  419. }
  420. }
  421. wall++;
  422. block++;
  423. PrevRight = Right;
  424. return Status;
  425. }
  426. /**************************************************************************\
  427. *
  428. * ScanDumper::ValidateAddress
  429. *
  430. \**************************************************************************/
  431. ULONG ScanDumper::ValidateAddress(
  432. ULONG64 Address,
  433. const char *pszAddrName,
  434. ULONG Flags
  435. )
  436. {
  437. if (pszAddrName == NULL)
  438. {
  439. pszAddrName = "address";
  440. }
  441. if (gbVerbose)
  442. {
  443. dprintf(" Validating %s %#p\n", pszAddrName, Address);
  444. }
  445. // Check allocation limits
  446. if (Address < AddressBase)
  447. {
  448. if ((Flags & SCAN_VALID_NO_ERROR_PRINT) == 0)
  449. dprintf(" * %s %#p is before address base %#p\n", pszAddrName, Address, AddressBase);
  450. Valid = FALSE;
  451. return STATUS_UNSUCCESSFUL;
  452. }
  453. if (Address > AddressLimit)
  454. {
  455. if ((Flags & SCAN_VALID_NO_ERROR_PRINT) == 0)
  456. dprintf(" * %s %#p is beyond address limit %#p\n", pszAddrName, Address, AddressLimit);
  457. Valid = FALSE;
  458. return STATUS_UNSUCCESSFUL;
  459. }
  460. // Check head and tail limits
  461. if (Address < FirstScanAddr)
  462. {
  463. if ((Flags & SCAN_VALID_NO_ERROR_PRINT) == 0)
  464. dprintf(" * %s %#p is before head address %#p\n", pszAddrName, Address, FirstScanAddr);
  465. Valid = FALSE;
  466. return STATUS_UNSUCCESSFUL;
  467. }
  468. if (Address > LastScanAddr)
  469. {
  470. if ((Flags & SCAN_VALID_NO_ERROR_PRINT) == 0)
  471. dprintf(" * %s %#p beyond tail address %#p\n", pszAddrName, Address, LastScanAddr);
  472. Valid = FALSE;
  473. return STATUS_UNSUCCESSFUL;
  474. }
  475. // Check end edge limits
  476. if (! (Flags & SCAN_VALID_AT_END))
  477. {
  478. if (Address == AddressLimit)
  479. {
  480. if ((Flags & SCAN_VALID_NO_ERROR_PRINT) == 0)
  481. dprintf(" * %s %#p is at address limit %#p\n", pszAddrName, Address, AddressLimit);
  482. Valid = FALSE;
  483. return STATUS_UNSUCCESSFUL;
  484. }
  485. if (Address == LastScanAddr)
  486. {
  487. if ((Flags & SCAN_VALID_NO_ERROR_PRINT) == 0)
  488. dprintf(" * %s %#p is at tail address %#p\n", pszAddrName, Address, LastScanAddr);
  489. Valid = FALSE;
  490. return STATUS_UNSUCCESSFUL;
  491. }
  492. }
  493. // Check start edge limits
  494. if (! (Flags & SCAN_VALID_AT_START))
  495. {
  496. if (Address == AddressBase)
  497. {
  498. if ((Flags & SCAN_VALID_NO_ERROR_PRINT) == 0)
  499. dprintf(" * %s %#p is at address base %#p\n", pszAddrName, Address, AddressBase);
  500. Valid = FALSE;
  501. return STATUS_UNSUCCESSFUL;
  502. }
  503. if (Address == FirstScanAddr)
  504. {
  505. if ((Flags & SCAN_VALID_NO_ERROR_PRINT) == 0)
  506. dprintf(" * %s %#p is at head address %#p\n", pszAddrName, Address, FirstScanAddr);
  507. Valid = FALSE;
  508. return STATUS_UNSUCCESSFUL;
  509. }
  510. }
  511. return STATUS_SUCCESS;
  512. }
  513. /**************************************************************************\
  514. *
  515. * ScanDumper callback interfaces
  516. *
  517. \**************************************************************************/
  518. ULONG
  519. WallArrayEntryCallback(
  520. PFIELD_INFO pField,
  521. ScanDumper *pScanDumper
  522. )
  523. {
  524. if (pScanDumper == NULL || pField == NULL)
  525. {
  526. return STATUS_UNSUCCESSFUL;
  527. }
  528. return pScanDumper->ValidateAddress(pField->address, "Wall @", SCAN_VALID_EXCLUSIVE);
  529. }
  530. ULONG
  531. LeftWallCallback(
  532. PFIELD_INFO pField,
  533. ScanDumper *pScanDumper
  534. )
  535. {
  536. if (pField == NULL)
  537. {
  538. dprintf(" * Error: LeftWallCallback was given NULL pField.\n");
  539. return STATUS_UNSUCCESSFUL;
  540. }
  541. pField->fieldCallBack = RightWallCallback;
  542. if (pScanDumper == NULL)
  543. {
  544. dprintf(" * Error: LeftWallCallback was given NULL pScanDumper.\n");
  545. return STATUS_UNSUCCESSFUL;
  546. }
  547. return pScanDumper->NextLeftWall((LONG)pField->address);
  548. }
  549. ULONG
  550. RightWallCallback(
  551. PFIELD_INFO pField,
  552. ScanDumper *pScanDumper
  553. )
  554. {
  555. if (pField == NULL)
  556. {
  557. dprintf(" * Error: RightWallCallback was given NULL pField.\n");
  558. return STATUS_UNSUCCESSFUL;
  559. }
  560. pField->fieldCallBack = LeftWallCallback;
  561. if (pScanDumper == NULL)
  562. {
  563. dprintf(" * Error: RightWallCallback was given NULL pScanDumper.\n");
  564. return STATUS_UNSUCCESSFUL;
  565. }
  566. return pScanDumper->NextRightWall((LONG)pField->address);
  567. }
  568. template <class T, int Spec>
  569. PrintfTypeFormat<T,Spec>::PrintfTypeFormat() : PrintfFormat()
  570. {
  571. ComposeFormat();
  572. }
  573. template <class T, int Spec>
  574. void PrintfTypeFormat<T,Spec>::ComposeFormat()
  575. {
  576. int pos = 0;
  577. Format[pos++] = '%';
  578. if (Width != -1)
  579. {
  580. int stored = _snprintf(&Format[pos], sizeof(Format)-5-pos, "%d", Width);
  581. if (stored > 0)
  582. {
  583. pos += stored;
  584. }
  585. }
  586. if (Spec & (PRINT_FORMAT_CHARACTER | PRINT_FORMAT_STRING))
  587. {
  588. if (Spec & PRINT_FORMAT_1BYTE)
  589. {
  590. Format[pos++] = 'h';
  591. }
  592. else if (Spec & PRINT_FORMAT_2BYTES)
  593. {
  594. Format[pos++] = 'l';
  595. }
  596. else
  597. {
  598. ExtWarn("Warning: Unknown character print size specification.\n");
  599. }
  600. if (Spec & PRINT_FORMAT_CHARACTER)
  601. {
  602. Format[pos++] = 'c';
  603. }
  604. else
  605. {
  606. Format[pos++] = 's';
  607. }
  608. }
  609. else if (Spec & PRINT_FORMAT_POINTER)
  610. {
  611. Format[pos++] = 'p';
  612. }
  613. else
  614. {
  615. if (Spec & PRINT_FORMAT_1BYTE)
  616. {
  617. }
  618. else if (Spec & PRINT_FORMAT_2BYTES)
  619. {
  620. Format[pos++] = 'h';
  621. }
  622. else if (Spec & PRINT_FORMAT_4BYTES)
  623. {
  624. Format[pos++] = 'l';
  625. }
  626. else if (Spec & PRINT_FORMAT_8BYTES)
  627. {
  628. Format[pos++] = 'I';
  629. Format[pos++] = '6';
  630. Format[pos++] = '4';
  631. }
  632. else
  633. {
  634. ExtWarn("Warning: Unknown print format size specification.\n");
  635. }
  636. if (Spec & PRINT_FORMAT_HEX)
  637. {
  638. Format[pos++] = 'x';
  639. }
  640. else if (Spec & PRINT_FORMAT_SIGNED)
  641. {
  642. Format[pos++] = 'd';
  643. }
  644. else if (Spec & PRINT_FORMAT_UNSIGNED)
  645. {
  646. Format[pos++] = 'u';
  647. }
  648. else
  649. {
  650. ExtErr("Error: Unknown print format specification.\n");
  651. Format[0] = 0;
  652. return;
  653. }
  654. }
  655. Format[pos] = 0;
  656. IsDirty = FALSE;
  657. }
  658. template <class T, int PrintSpec>
  659. BOOL
  660. ArrayDumper<T, PrintSpec>::ReadArray(
  661. const char * SymbolName
  662. )
  663. {
  664. DEBUG_VALUE Addr;
  665. ULONG error;
  666. ULONG ArraySize;
  667. ULONG ArrayLength;
  668. ULONG EntrySize;
  669. DbgPrint("ReadArray called for %s\n", SymbolName);
  670. Length = 0;
  671. if (!GetArrayDimensions(Client, SymbolName, NULL, &ArraySize, &ArrayLength, &EntrySize) ||
  672. !(ArraySize > 0 && ArrayLength > 0 && EntrySize > 0)
  673. )
  674. {
  675. ExtErr("GetArrayDimensions failed or returned a zero value dimension for\n\t%s.\n", SymbolName);
  676. ExtVerb("ArraySize: %u ArrayLength: %u EntrySize: %u.\n",
  677. ArraySize, ArrayLength, EntrySize);
  678. return FALSE;
  679. }
  680. if (EntrySize != sizeof(T))
  681. {
  682. ExtErr("Error: %s has entries of size %u not %u as expected.\n",
  683. SymbolName, EntrySize, sizeof(T));
  684. return FALSE;
  685. }
  686. if (S_OK == g_pExtControl->Evaluate(SymbolName, DEBUG_VALUE_INT64, &Addr, NULL))
  687. {
  688. if (Addr.I64 != 0)
  689. {
  690. HANDLE hHeap = GetProcessHeap();
  691. if (ArrayBuffer == NULL || ArrayLength > HeapSize(hHeap, 0, ArrayBuffer))
  692. {
  693. T *NewBuffer;
  694. NewBuffer = (T *) ((ArrayBuffer == NULL) ?
  695. HeapAlloc(hHeap, 0, ArraySize):
  696. HeapReAlloc(hHeap, 0, ArrayBuffer, ArraySize));
  697. if (NewBuffer == NULL)
  698. {
  699. ExtErr("Buffer alloc failed.\n");
  700. return FALSE;
  701. }
  702. ArrayBuffer = NewBuffer;
  703. }
  704. if (S_OK == g_pExtData->ReadVirtual(Addr.I64, ArrayBuffer, ArraySize, NULL))
  705. {
  706. Length = ArrayLength;
  707. return TRUE;
  708. }
  709. ExtErr("ReadMemory at %p for %u bytes failed.\n", Addr.I64, ArrayLength);
  710. }
  711. else
  712. {
  713. ExtWarn("Symbol %s evaluated to zero.\n", SymbolName);
  714. }
  715. }
  716. else
  717. {
  718. ExtErr("Couldn't evalutate: %s\n", SymbolName);
  719. }
  720. return FALSE;
  721. }
  722. template class PrintfTypeFormat<FormatTemplate(BYTE)>;
  723. template class PrintfTypeFormat<FormatTemplate(WORD)>;
  724. template class PrintfTypeFormat<FormatTemplate(DWORD)>;
  725. template class PrintfTypeFormat<FormatTemplate(DWORD64)>;
  726. template class PrintfTypeFormat<FormatTemplate(CHAR)>;
  727. template class PrintfTypeFormat<FormatTemplate(WCHAR)>;
  728. template class PrintfTypeFormat<FormatTemplate(SHORT)>;
  729. template class PrintfTypeFormat<FormatTemplate(LONG)>;
  730. template class PrintfTypeFormat<FormatTemplate(LONG64)>;
  731. template class PrintfTypeFormat<FormatTemplate(USHORT)>;
  732. template class PrintfTypeFormat<FormatTemplate(ULONG)>;
  733. template class PrintfTypeFormat<FormatTemplate(ULONG64)>;
  734. template class PrintfTypeFormat<ULONG64, PRINT_FORMAT_POINTER>;
  735. template class PrintfTypeFormat<char [], PRINT_FORMAT_STRING>;
  736. template class PrintfTypeFormat<char [], PRINT_FORMAT_WSTRING>;
  737. template class ArrayDumper<FormatTemplate(ULONG)>;