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.

1277 lines
33 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: callback.cxx
  3. *
  4. * Copyright (c) 2000 Microsoft Corporation
  5. *
  6. \**************************************************************************/
  7. #include "precomp.hxx"
  8. BOOL gbCallbacksPrintNewline = FALSE;
  9. int gCallbacksPrintNameWidth = -1;
  10. NTSTATUS gCallbackReturnValue = STATUS_SUCCESS;
  11. ULONG FieldCallback(
  12. PFIELD_INFO pField,
  13. PVOID UserContext
  14. )
  15. {
  16. if (gbCallbacksPrintNewline) dprintf("\n");
  17. dprintf(" ** FieldCallback(%lx, %lx) **\n", pField, UserContext);
  18. if (pField)
  19. {
  20. dprintf(" Field:\n");
  21. dprintf(" fName : %s\n", pField->fName);
  22. dprintf(" printName : %s\n", pField->printName);
  23. dprintf(" size : %d\n", pField->size);
  24. dprintf(" fOptions : %#x\n", pField->fOptions);
  25. dprintf(" address : %#I64x\n", pField->address);
  26. dprintf(" fieldCallBack: %lx\n", pField->fieldCallBack);
  27. }
  28. if (UserContext)
  29. {
  30. dprintf(" UserContext: ???\n");
  31. }
  32. return gCallbackReturnValue;
  33. }
  34. /**************************************************************************\
  35. *
  36. * PrintName
  37. *
  38. * Prints the field name or print name if callbacks are supposed to.
  39. *
  40. \**************************************************************************/
  41. VOID PrintName(PFIELD_INFO pField)
  42. {
  43. if (pField)
  44. {
  45. if (gCallbacksPrintNameWidth >= 0)
  46. {
  47. if (pField->printName)
  48. {
  49. dprintf("%*s", gCallbacksPrintNameWidth, pField->printName);
  50. }
  51. else if (pField->fName)
  52. {
  53. dprintf("%*s", gCallbacksPrintNameWidth, pField->fName);
  54. }
  55. }
  56. else
  57. {
  58. if (pField->fOptions & DBG_DUMP_FIELD_NO_PRINT)
  59. {
  60. if (pField->printName)
  61. {
  62. dprintf(" +0x___ %s ", pField->printName);
  63. }
  64. else if (pField->fName)
  65. {
  66. dprintf(" +0x___ %s ", pField->fName);
  67. }
  68. }
  69. }
  70. }
  71. }
  72. /**************************************************************************\
  73. *
  74. * NextItemCallbackInit
  75. *
  76. * Specify printing and validation info to NextItemCallbacks.
  77. *
  78. \**************************************************************************/
  79. BOOL PrintItemHeader = FALSE;
  80. char szItemHeader[512] = "";
  81. ULONG64 LastItemExpected = 0;
  82. BOOL FoundLastItemExpected = FALSE;
  83. void NextItemCallbackInit(
  84. const char *pszPrintHeader,
  85. ULONG64 LastItemAddr
  86. )
  87. {
  88. if (pszPrintHeader != NULL)
  89. {
  90. strncpy(szItemHeader, pszPrintHeader, sizeof(szItemHeader));
  91. szItemHeader[sizeof(szItemHeader)-1] = 0;
  92. PrintItemHeader = TRUE;
  93. }
  94. else
  95. {
  96. PrintItemHeader = FALSE;
  97. }
  98. LastItemExpected = LastItemAddr;
  99. FoundLastItemExpected = (LastItemExpected == 0);
  100. }
  101. /**************************************************************************\
  102. *
  103. * LastCallbackItemFound
  104. *
  105. * Returns TRUE if address specified in NextItemCallbackInit was found.
  106. * Note: Always returns TRUE if 0 was specified for address.
  107. *
  108. \**************************************************************************/
  109. BOOL LastCallbackItemFound()
  110. {
  111. return FoundLastItemExpected;
  112. }
  113. /**************************************************************************\
  114. *
  115. * NextItemCallback
  116. *
  117. * Use with linked list dumping when initial address is the first item's.
  118. *
  119. \**************************************************************************/
  120. ULONG NextItemCallback(
  121. PFIELD_INFO pField,
  122. PVOID UserContext
  123. )
  124. {
  125. ULONG64 NextAddr = 0;
  126. if (pField == NULL)
  127. {
  128. if (gbCallbacksPrintNewline) dprintf("\n");
  129. dprintf("Error: NextItemCallback was given NULL pField.\n");
  130. }
  131. else
  132. {
  133. if (pField->address == 0)
  134. return STATUS_UNSUCCESSFUL;
  135. if (LastItemExpected != 0)
  136. {
  137. if (FoundLastItemExpected)
  138. {
  139. dprintf(" * Error: Next item is beyond last expected @ %#p\n", LastItemExpected);
  140. }
  141. else if (LastItemExpected == pField->address)
  142. {
  143. FoundLastItemExpected = TRUE;
  144. }
  145. }
  146. if (PrintItemHeader)
  147. {
  148. dprintf(szItemHeader);
  149. dprintf("%#p\n", pField->address);
  150. }
  151. }
  152. return STATUS_SUCCESS;
  153. }
  154. /**************************************************************************\
  155. *
  156. * PointerToNextItemCallback
  157. *
  158. * Use with linked list dumping when initial address is a pointer to type.
  159. *
  160. \**************************************************************************/
  161. ULONG PointerToNextItemCallback(
  162. PFIELD_INFO pField,
  163. PVOID UserContext
  164. )
  165. {
  166. ULONG64 NextAddr = 0;
  167. if (pField == NULL)
  168. {
  169. if (gbCallbacksPrintNewline) dprintf("\n");
  170. dprintf("Error: PointerToNextItemCallback was given NULL pField.\n");
  171. }
  172. else
  173. {
  174. if (pField->address == 0)
  175. return STATUS_UNSUCCESSFUL;
  176. if (!ReadPointer(pField->address, &NextAddr) || NextAddr == 0)
  177. return STATUS_UNSUCCESSFUL;
  178. if (LastItemExpected != 0)
  179. {
  180. if (FoundLastItemExpected)
  181. {
  182. dprintf(" * Error: Next item is beyond last expected @ %#p\n", LastItemExpected);
  183. }
  184. else if (LastItemExpected == NextAddr)
  185. {
  186. FoundLastItemExpected = TRUE;
  187. }
  188. }
  189. if (PrintItemHeader)
  190. {
  191. dprintf(szItemHeader);
  192. }
  193. }
  194. return STATUS_SUCCESS;
  195. }
  196. /**************************************************************************\
  197. *
  198. * ArrayCallback
  199. *
  200. * Use with array dumping.
  201. *
  202. \**************************************************************************/
  203. ULONG ArrayCallback(
  204. PFIELD_INFO pField,
  205. PVOID UserContext
  206. )
  207. {
  208. static PFIELD_INFO ArrayField = NULL;
  209. static ULONG ArrayIndex = 0;
  210. static ULONG ArrayIndexWidth;
  211. if (pField != ArrayField || pField->size <= ArrayIndex)
  212. {
  213. ArrayField = pField;
  214. if (ArrayIndex != 0 && gbVerbose)
  215. {
  216. dprintf("Warning: Beginning new array w/o completing last.\n");
  217. }
  218. ArrayIndex = 0;
  219. }
  220. if (ArrayIndex == 0)
  221. {
  222. ULONG i = pField->size-1;
  223. ArrayIndexWidth = 1;
  224. dprintf("Idx");
  225. while (i /= 10)
  226. {
  227. dprintf(" ");
  228. ArrayIndexWidth++;
  229. }
  230. PrintName(pField);
  231. }
  232. dprintf("\n[%*u]", ArrayIndexWidth, ArrayIndex++);
  233. // If we hit the end of an array,
  234. // prepare for a new array.
  235. if (pField->size == ArrayIndex)
  236. {
  237. ArrayField = NULL;
  238. ArrayIndex = 0;
  239. }
  240. return STATUS_SUCCESS;
  241. }
  242. /**************************************************************************\
  243. *
  244. * NewlineCallback
  245. *
  246. * To be used with DBG_DUMP_COMPACT_OUT as default callback.
  247. *
  248. \**************************************************************************/
  249. ULONG NewlineCallback(
  250. PFIELD_INFO pField,
  251. PVOID UserContext
  252. )
  253. {
  254. dprintf("\n");
  255. if (!gbCallbacksPrintNewline && gbVerbose)
  256. {
  257. dprintf(" Note: NewlineCallback called, but gbCallbacksPrintNewline is FALSE.\n");
  258. }
  259. return STATUS_SUCCESS;
  260. }
  261. /**************************************************************************\
  262. *
  263. * AddressPrintCallback
  264. *
  265. * Useful with DBG_DUMP_FIELD_RETURN_ADDRESS when the field is
  266. * a large embedded structure you don't want to print.
  267. *
  268. \**************************************************************************/
  269. ULONG AddressPrintCallback(
  270. PFIELD_INFO pField,
  271. PVOID UserContext
  272. )
  273. {
  274. if (pField == NULL)
  275. {
  276. dprintf("\nError: AddressPrintCallback was given NULL pField.");
  277. }
  278. else
  279. {
  280. PrintName(pField);
  281. if (gbVerbose) dprintf(" (pField->size = %d) ", pField->size);
  282. dprintf("%#p", pField->address);
  283. }
  284. if (gbCallbacksPrintNewline) dprintf("\n");
  285. return gCallbackReturnValue;
  286. }
  287. /**************************************************************************\
  288. *
  289. * Basic Type Callbacks:
  290. * BOOL, BYTE, CHAR, DecimalCHAR, DecimalUCHAR,
  291. * DWORD, LONG, SHORT, WORD, ULONG, USHORT
  292. *
  293. \**************************************************************************/
  294. ULONG BOOLCallback(PFIELD_INFO pField, PVOID UserContext)
  295. {
  296. PrintName(pField);
  297. dprintf("%s", ((BOOL)pField->address) ? "TRUE" : "FALSE");
  298. if (gbCallbacksPrintNewline) dprintf("\n");
  299. return gCallbackReturnValue;
  300. }
  301. ULONG BYTECallback(PFIELD_INFO pField, PVOID UserContext)
  302. {
  303. PrintName(pField);
  304. dprintf("0x%2.2X", (BYTE)pField->address);
  305. if (gbCallbacksPrintNewline) dprintf("\n");
  306. return gCallbackReturnValue;
  307. }
  308. ULONG CHARCallback(PFIELD_INFO pField, PVOID UserContext)
  309. {
  310. PrintName(pField);
  311. dprintf("'%c'", (CHAR)pField->address);
  312. if (gbCallbacksPrintNewline) dprintf("\n");
  313. return gCallbackReturnValue;
  314. }
  315. ULONG DecimalCHARCallback(PFIELD_INFO pField, PVOID UserContext)
  316. {
  317. PrintName(pField);
  318. dprintf("%d", (CHAR)pField->address);
  319. if (gbCallbacksPrintNewline) dprintf("\n");
  320. return gCallbackReturnValue;
  321. }
  322. ULONG DecimalUCHARCallback(PFIELD_INFO pField, PVOID UserContext)
  323. {
  324. PrintName(pField);
  325. dprintf("%u", (UCHAR)pField->address);
  326. if (gbCallbacksPrintNewline) dprintf("\n");
  327. return gCallbackReturnValue;
  328. }
  329. ULONG DWORDCallback(PFIELD_INFO pField, PVOID UserContext)
  330. {
  331. PrintName(pField);
  332. dprintf("0x%8.8lX", (DWORD)pField->address);
  333. if (gbCallbacksPrintNewline) dprintf("\n");
  334. return gCallbackReturnValue;
  335. }
  336. ULONG LONGCallback(PFIELD_INFO pField, PVOID UserContext)
  337. {
  338. PrintName(pField);
  339. dprintf("%ld", (LONG)pField->address);
  340. if (gbCallbacksPrintNewline) dprintf("\n");
  341. return gCallbackReturnValue;
  342. }
  343. ULONG WORDCallback(PFIELD_INFO pField, PVOID UserContext)
  344. {
  345. PrintName(pField);
  346. dprintf("0x%4.4X", (WORD)pField->address);
  347. if (gbCallbacksPrintNewline) dprintf("\n");
  348. return gCallbackReturnValue;
  349. }
  350. ULONG SHORTCallback(PFIELD_INFO pField, PVOID UserContext)
  351. {
  352. PrintName(pField);
  353. dprintf("%d", (SHORT)pField->address);
  354. if (gbCallbacksPrintNewline) dprintf("\n");
  355. return gCallbackReturnValue;
  356. }
  357. ULONG ULONGCallback(PFIELD_INFO pField, PVOID UserContext)
  358. {
  359. PrintName(pField);
  360. dprintf("%lu", (ULONG)pField->address);
  361. if (gbCallbacksPrintNewline) dprintf("\n");
  362. return gCallbackReturnValue;
  363. }
  364. ULONG USHORTCallback(PFIELD_INFO pField, PVOID UserContext)
  365. {
  366. PrintName(pField);
  367. dprintf("%u", (USHORT)pField->address);
  368. if (gbCallbacksPrintNewline) dprintf("\n");
  369. return gCallbackReturnValue;
  370. }
  371. /**************************************************************************\
  372. *
  373. * EnumCallback
  374. *
  375. * Specify ENUMDEF * in SYM_DUMP_PARAM.Context field
  376. *
  377. * Note: Only one Enum/FlagCallback can be specified per FIELD_INFO array.
  378. *
  379. \**************************************************************************/
  380. ULONG EnumCallback(
  381. PFIELD_INFO pField,
  382. ENUMDEF *pEnumDef
  383. )
  384. {
  385. if (pField == NULL || pEnumDef == NULL)
  386. {
  387. if (gbCallbacksPrintNewline) dprintf("\n");
  388. dprintf("Error: EnumCallback had NULL parameter.\n");
  389. return STATUS_UNSUCCESSFUL;
  390. }
  391. PrintName(pField);
  392. if (!gbCallbacksPrintNewline &&
  393. !(pField->fOptions & DBG_DUMP_FIELD_NO_PRINT))
  394. {
  395. dprintf(" ");
  396. }
  397. dprintf(" ");
  398. if (! bPrintEnum(pEnumDef, (ULONG)pField->address))
  399. {
  400. dprintf("Unknown Value");
  401. if (pField->fOptions & DBG_DUMP_FIELD_NO_PRINT)
  402. {
  403. dprintf(": %lu", (ULONG)pField->address);
  404. }
  405. }
  406. dprintf("\n");
  407. return gCallbackReturnValue;
  408. }
  409. /**************************************************************************\
  410. *
  411. * FlagCallback
  412. *
  413. * Specify FLAGDEF * in SYM_DUMP_PARAM.Context field
  414. *
  415. * Note: Only one Enum/FlagCallback can be specified per FIELD_INFO array.
  416. *
  417. \**************************************************************************/
  418. ULONG FlagCallback(
  419. PFIELD_INFO pField,
  420. FLAGDEF *pFlagDef
  421. )
  422. {
  423. ULONG64 UnknownFlags;
  424. PrintName(pField);
  425. if (gbCallbacksPrintNewline) dprintf("\n");
  426. if (pField == NULL || pFlagDef == NULL)
  427. {
  428. dprintf("Error: FlagCallback had NULL parameter.\n");
  429. return STATUS_UNSUCCESSFUL;
  430. }
  431. UnknownFlags = flPrintFlags(pFlagDef, pField->address);
  432. if (UnknownFlags)
  433. {
  434. if (UnknownFlags != pField->address) dprintf("\n");
  435. dprintf(" Uknown flags: 0x%lx", UnknownFlags);
  436. }
  437. dprintf("\n");
  438. return gCallbackReturnValue;
  439. }
  440. /**************************************************************************\
  441. *
  442. * POINTLCallback
  443. *
  444. \**************************************************************************/
  445. ULONG POINTLCallback(
  446. PFIELD_INFO pField,
  447. PVOID UserContext
  448. )
  449. {
  450. NTSTATUS RetVal = gCallbackReturnValue;
  451. ULONG error;
  452. if (pField == NULL)
  453. {
  454. dprintf("\nError: POINTLCallback was given NULL pField.");
  455. }
  456. else
  457. {
  458. PrintName(pField);
  459. if (!pField->address)
  460. {
  461. dprintf("\nError: POINTLCallback: pField->address = NULL");
  462. RetVal = STATUS_UNSUCCESSFUL;
  463. }
  464. else if (error = (ULONG)InitTypeRead(pField->address, win32k!_POINTL))
  465. {
  466. dprintf("\n InitTypeRead returned %s", pszWinDbgError(error));
  467. RetVal = error;
  468. }
  469. else
  470. {
  471. dprintf("(%d,%d)",
  472. (LONG)ReadField(x),
  473. (LONG)ReadField(y));
  474. }
  475. }
  476. if (gbCallbacksPrintNewline) dprintf("\n");
  477. return RetVal;
  478. }
  479. /**************************************************************************\
  480. *
  481. * RECTLCallback
  482. *
  483. \**************************************************************************/
  484. ULONG RECTLCallback(
  485. PFIELD_INFO pField,
  486. PVOID UserContext
  487. )
  488. {
  489. NTSTATUS RetVal = gCallbackReturnValue;
  490. ULONG error;
  491. if (pField == NULL)
  492. {
  493. dprintf("\nError: RECTLCallback was given NULL pField.");
  494. }
  495. else
  496. {
  497. PrintName(pField);
  498. if (!pField->address)
  499. {
  500. dprintf("\nError: RECTLCallback: pField->address = NULL");
  501. RetVal = STATUS_UNSUCCESSFUL;
  502. }
  503. else if (error = (ULONG)InitTypeRead(pField->address, win32k!_RECTL))
  504. {
  505. dprintf("\n InitTypeRead returned %s", pszWinDbgError(error));
  506. RetVal = error;
  507. }
  508. else
  509. {
  510. dprintf("(%d,%d) - (%d,%d)",
  511. (LONG)ReadField(left),
  512. (LONG)ReadField(top),
  513. (LONG)ReadField(right),
  514. (LONG)ReadField(bottom));
  515. }
  516. }
  517. if (gbCallbacksPrintNewline) dprintf("\n");
  518. return RetVal;
  519. }
  520. /**************************************************************************\
  521. *
  522. * SIZECallback
  523. *
  524. \**************************************************************************/
  525. ULONG SIZECallback(
  526. PFIELD_INFO pField,
  527. PVOID UserContext
  528. )
  529. {
  530. NTSTATUS RetVal = gCallbackReturnValue;
  531. ULONG error;
  532. if (pField == NULL)
  533. {
  534. dprintf("\nError: SIZECallback was given NULL pField.");
  535. }
  536. else
  537. {
  538. PrintName(pField);
  539. if (!pField->address)
  540. {
  541. dprintf("\nError: SIZECallback: pField->address = NULL");
  542. RetVal = STATUS_UNSUCCESSFUL;
  543. }
  544. else if (error = (ULONG)InitTypeRead(pField->address, win32k!tagSIZE))
  545. {
  546. dprintf("\n InitTypeRead returned %s", pszWinDbgError(error));
  547. RetVal = error;
  548. }
  549. else
  550. {
  551. dprintf("%d x %d",
  552. (LONG)ReadField(cx),
  553. (LONG)ReadField(cy));
  554. }
  555. }
  556. if (gbCallbacksPrintNewline) dprintf("\n");
  557. return RetVal;
  558. }
  559. /**************************************************************************\
  560. *
  561. * SIZELCallback
  562. *
  563. \**************************************************************************/
  564. ULONG SIZELCallback(
  565. PFIELD_INFO pField,
  566. PVOID UserContext
  567. )
  568. {
  569. return SIZECallback(pField, UserContext);
  570. }
  571. /**************************************************************************\
  572. *
  573. * PrintDEVMODEList
  574. *
  575. \**************************************************************************/
  576. ULONG PrintDEVMODEList(
  577. ULONG64 DevModeListAddr,
  578. ULONG DevModeListSize
  579. )
  580. {
  581. ULONG64 DevModeEnd;
  582. ULONG error = 0;
  583. #define DEVMODE_DMDRIVEREXTRA 0
  584. #define DEVMODE_DMSIZE 1
  585. #define DEVMODE_DMPELSWIDTH 2
  586. #define DEVMODE_DMPELSHEIGHT 3
  587. #define DEVMODE_DMBITSPERPEL 4
  588. #define DEVMODE_DMDISPLAYFREQUENCY 5
  589. FIELD_INFO DevModeFields[] = {
  590. { DbgStr("dmDriverExtra"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  591. { DbgStr("dmSize"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  592. { DbgStr("dmPelsWidth"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  593. { DbgStr("dmPelsHeight"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  594. { DbgStr("dmBitsPerPel"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  595. { DbgStr("dmDisplayFrequency"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  596. };
  597. SYM_DUMP_PARAM DevModeSym = {
  598. sizeof(SYM_DUMP_PARAM), DbgStr(GDIType(_devicemodeW)), DBG_DUMP_NO_PRINT, DevModeListAddr,
  599. NULL, NULL, NULL, sizeof(DevModeFields)/sizeof(DevModeFields[0]), DevModeFields
  600. };
  601. DevModeEnd = DevModeSym.addr + DevModeListSize;
  602. while ((DevModeSym.addr < DevModeEnd) &&
  603. !(error = Ioctl( IG_DUMP_SYMBOL_INFO, &DevModeSym, DevModeSym.size )))
  604. {
  605. dprintf("\t %4d x %4d %2d %3d\n",
  606. (DWORD)DevModeFields[DEVMODE_DMPELSWIDTH].address,
  607. (DWORD)DevModeFields[DEVMODE_DMPELSHEIGHT].address,
  608. (DWORD)DevModeFields[DEVMODE_DMBITSPERPEL].address,
  609. (DWORD)DevModeFields[DEVMODE_DMDISPLAYFREQUENCY].address);
  610. DevModeSym.addr += DevModeFields[DEVMODE_DMDRIVEREXTRA].address + DevModeFields[DEVMODE_DMSIZE].address;
  611. }
  612. return error;
  613. }
  614. /**************************************************************************\
  615. *
  616. * DEVMODECallback
  617. *
  618. \**************************************************************************/
  619. ULONG DEVMODECallback(
  620. PFIELD_INFO pField,
  621. PVOID UserContext
  622. )
  623. {
  624. PrintName(pField);
  625. if (pField == NULL)
  626. {
  627. if (gbCallbacksPrintNewline) dprintf("\n");
  628. dprintf(" Error: DEVMODEListCallback was given NULL pField.\n");
  629. }
  630. else if (pField->address)
  631. {
  632. ULONG error;
  633. if (error = PrintDEVMODEList(pField->address, 1))
  634. {
  635. dprintf(" PrintDEVMODEList returned %s in DEVMODECallback\n", pszWinDbgError(error));
  636. }
  637. }
  638. else
  639. {
  640. dprintf(" DEVMODE address is NULL\n");
  641. }
  642. return gCallbackReturnValue;
  643. }
  644. /**************************************************************************\
  645. *
  646. * DEVMODEListCallback and SizeDEVMODEListCallback
  647. *
  648. * Make sure these are always called in conjuction with
  649. * SizeDEVMODEListCallback before DEVMODEListCallback.
  650. *
  651. \**************************************************************************/
  652. ULONG cbDevModeList = -1;
  653. ULONG SizeDEVMODEListCallback(
  654. PFIELD_INFO pField,
  655. PVOID UserContext
  656. )
  657. {
  658. if (gbCallbacksPrintNewline) dprintf("\n");
  659. if (pField == NULL)
  660. {
  661. dprintf("Error: SizeDEVMODEListCallback was given NULL pField.\n");
  662. }
  663. else
  664. {
  665. if (cbDevModeList != -1)
  666. {
  667. dprintf(" Warning: cbDevModeList (%d) was not clear before call to SizeDEVMODEListCallback\n", cbDevModeList);
  668. }
  669. cbDevModeList = (ULONG)pField->address;
  670. }
  671. return STATUS_SUCCESS;
  672. }
  673. ULONG DEVMODEListCallback(
  674. PFIELD_INFO pField,
  675. PVOID UserContext
  676. )
  677. {
  678. PrintName(pField);
  679. if (gbCallbacksPrintNewline) dprintf("\n");
  680. if (pField == NULL)
  681. {
  682. dprintf(" Error: DEVMODEListCallback was given NULL pField.\n");
  683. }
  684. else if (cbDevModeList == -1)
  685. {
  686. dprintf(" Error: cbDevModeList has not been set properly.\n");
  687. }
  688. else if (pField->address)
  689. {
  690. ULONG error;
  691. if (error = PrintDEVMODEList(pField->address, cbDevModeList))
  692. {
  693. dprintf(" PrintDEVMODEList returned %s in DEVMODEListCallback\n", pszWinDbgError(error));
  694. }
  695. }
  696. else if (cbDevModeList != 0)
  697. {
  698. dprintf(" DEVMODE list size (%d) is non-zero, but DEVMODE list address is NULL.\n", cbDevModeList);
  699. }
  700. cbDevModeList = -1;
  701. return gCallbackReturnValue;
  702. }
  703. /**************************************************************************\
  704. *
  705. * PrintAString
  706. *
  707. * Reads and prints a char string at given target address.
  708. *
  709. * Returns address just past end of string or address of read failure.
  710. *
  711. \**************************************************************************/
  712. ULONG64 PrintAString(
  713. ULONG64 StringAddr
  714. )
  715. {
  716. CHAR Char;
  717. ULONG cbRead;
  718. if (StringAddr != 0)
  719. {
  720. while (ReadMemory(StringAddr, &Char, sizeof(Char), &cbRead) &&
  721. cbRead == sizeof(Char) &&
  722. (StringAddr+=sizeof(Char)) &&
  723. Char != 0)
  724. {
  725. dprintf("%hc", Char);
  726. }
  727. }
  728. return StringAddr;
  729. }
  730. /**************************************************************************\
  731. *
  732. * PrintWString
  733. *
  734. * Reads and prints a two-byte char string at given target address.
  735. *
  736. * Returns address just past end of string or address of read failure.
  737. *
  738. \**************************************************************************/
  739. ULONG64 PrintWString(
  740. ULONG64 StringAddr
  741. )
  742. {
  743. WCHAR Char;
  744. ULONG cbRead;
  745. if (StringAddr != 0)
  746. {
  747. while (ReadMemory(StringAddr, &Char, sizeof(Char), &cbRead) &&
  748. cbRead == sizeof(Char) &&
  749. (StringAddr+=sizeof(Char)) &&
  750. Char != 0)
  751. {
  752. dprintf("%lc", Char);
  753. }
  754. }
  755. return StringAddr;
  756. }
  757. /**************************************************************************\
  758. *
  759. * String printing callbacks
  760. *
  761. * To be used when DBG_DUMP_FIELD_xxx_STRING flags can't be used.
  762. *
  763. \**************************************************************************/
  764. /**************************************************************************\
  765. *
  766. * ACharArrayCallback callback for an array of chars
  767. *
  768. * Use DBG_DUMP_FIELD_RETURN_ADDRESS flag
  769. *
  770. \**************************************************************************/
  771. ULONG ACharArrayCallback(
  772. PFIELD_INFO pField,
  773. PVOID UserContext
  774. )
  775. {
  776. CHAR szBuffer[128];
  777. ULONG cbRead = 0;
  778. if (pField == NULL)
  779. {
  780. dprintf("\nError: ACharArrayCallback was given NULL pField.");
  781. }
  782. else
  783. {
  784. PrintName(pField);
  785. if (gbVerbose && pField->size == 0)
  786. dprintf("\n Note: ACharArrayCallback was given zero length array.\n");
  787. if (pField->address)
  788. {
  789. if (pField->size < sizeof(szBuffer))
  790. {
  791. if (!ReadMemory(pField->address, szBuffer, pField->size, &cbRead) || cbRead == 0)
  792. {
  793. dprintf(" Memory read failed @ %#p", pField->address);
  794. }
  795. else
  796. {
  797. szBuffer[min(cbRead,sizeof(szBuffer)-sizeof(CHAR))/sizeof(CHAR)] = (CHAR) 0;
  798. dprintf(" \"%hs\"", szBuffer);
  799. }
  800. }
  801. else
  802. {
  803. PCHAR pszBuffer = (PCHAR) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, pField->size+sizeof(CHAR));
  804. if (pszBuffer == NULL)
  805. {
  806. dprintf(" Buffer allocation failed - single-byte string @ %#p", pField->address);
  807. }
  808. else if (!ReadMemory(pField->address, szBuffer, pField->size, &cbRead) || cbRead == 0)
  809. {
  810. dprintf(" Memory read failed @ %#p", pField->address);
  811. }
  812. else
  813. {
  814. dprintf(" \"%hs\"", szBuffer);
  815. }
  816. }
  817. }
  818. else
  819. {
  820. dprintf(" (null)");
  821. }
  822. }
  823. if (gbCallbacksPrintNewline) dprintf("\n");
  824. return gCallbackReturnValue;
  825. }
  826. /**************************************************************************\
  827. *
  828. * WCharArrayCallback callback for an array of two-byte chars
  829. *
  830. * Use DBG_DUMP_FIELD_RETURN_ADDRESS flag
  831. *
  832. \**************************************************************************/
  833. ULONG WCharArrayCallback(
  834. PFIELD_INFO pField,
  835. PVOID UserContext
  836. )
  837. {
  838. WCHAR wszBuffer[128];
  839. ULONG cbRead = 0;
  840. if (pField == NULL)
  841. {
  842. dprintf("\nError: WStringCallback was given NULL pField.");
  843. }
  844. else
  845. {
  846. PrintName(pField);
  847. if (gbVerbose && pField->size == 0)
  848. dprintf("\n Note: WCharArrayCallback was given zero length array.\n");
  849. if (pField->address)
  850. {
  851. if (pField->size < sizeof(wszBuffer))
  852. {
  853. if (!ReadMemory(pField->address, wszBuffer, pField->size, &cbRead) || cbRead == 0)
  854. {
  855. dprintf(" Memory read failed @ %#p", pField->address);
  856. }
  857. else
  858. {
  859. wszBuffer[min(cbRead,sizeof(wszBuffer)-sizeof(WCHAR))/sizeof(WCHAR)] = (WCHAR) 0;
  860. dprintf(" \"%ls\"", wszBuffer);
  861. }
  862. }
  863. else
  864. {
  865. PWCHAR pwszBuffer = (PWCHAR) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, pField->size+sizeof(WCHAR));
  866. if (pwszBuffer == NULL)
  867. {
  868. dprintf(" Buffer allocation failed - wide string @ %#p", pField->address);
  869. }
  870. else if (!ReadMemory(pField->address, wszBuffer, pField->size, &cbRead) || cbRead == 0)
  871. {
  872. dprintf(" Memory read failed @ %#p", pField->address);
  873. }
  874. else
  875. {
  876. dprintf(" \"%ls\"", wszBuffer);
  877. }
  878. }
  879. }
  880. else
  881. {
  882. dprintf(" (null)");
  883. }
  884. }
  885. if (gbCallbacksPrintNewline) dprintf("\n");
  886. return gCallbackReturnValue;
  887. }
  888. /**************************************************************************\
  889. *
  890. * AStringCallback callback for a pointer to char string
  891. *
  892. \**************************************************************************/
  893. ULONG AStringCallback(
  894. PFIELD_INFO pField,
  895. PVOID UserContext
  896. )
  897. {
  898. CHAR szBuffer[128];
  899. ULONG cbRead = 0;
  900. if (pField == NULL)
  901. {
  902. dprintf("\nError: AStringCallback was given NULL pField.");
  903. }
  904. else
  905. {
  906. PrintName(pField);
  907. if (gbVerbose)
  908. {
  909. if (pField->size == 0)
  910. dprintf("\n Note: AStringCallback was given zero length type.\n");
  911. else if (pField->size != GetTypeSize("PVOID"))
  912. dprintf("\n Note: AStringCallback: String length is not the size of a pointer.\n"
  913. " Should you be using ACharArrayCallback?\n");
  914. }
  915. if (pField->address)
  916. {
  917. dprintf(" \"");
  918. PrintAString(pField->address);
  919. dprintf("\"");
  920. }
  921. else
  922. {
  923. dprintf(" (null)");
  924. }
  925. }
  926. if (gbCallbacksPrintNewline) dprintf("\n");
  927. return gCallbackReturnValue;
  928. }
  929. /**************************************************************************\
  930. *
  931. * WStringCallback callback for a pointer to two-byte char string
  932. *
  933. \**************************************************************************/
  934. ULONG WStringCallback(
  935. PFIELD_INFO pField,
  936. PVOID UserContext
  937. )
  938. {
  939. CHAR szBuffer[128];
  940. ULONG cbRead = 0;
  941. if (pField == NULL)
  942. {
  943. dprintf("\nError: WStringCallback was given NULL pField.");
  944. }
  945. else
  946. {
  947. PrintName(pField);
  948. if (gbVerbose)
  949. {
  950. if (pField->size == 0)
  951. dprintf("\n Note: WStringCallback was given zero length type.\n");
  952. else if (pField->size != GetTypeSize("PVOID"))
  953. dprintf("\n Note: WStringCallback: String length is not the size of a pointer.\n"
  954. " Should you be using WCharArrayCallback?\n");
  955. }
  956. if (pField->address)
  957. {
  958. dprintf(" \"");
  959. PrintWString(pField->address);
  960. dprintf("\"");
  961. }
  962. else
  963. {
  964. dprintf(" (null)");
  965. }
  966. }
  967. if (gbCallbacksPrintNewline) dprintf("\n");
  968. return gCallbackReturnValue;
  969. }
  970. /**************************************************************************\
  971. *
  972. * AMultiStringCallback callback for a pointer to several char
  973. * strings one after another.
  974. *
  975. \**************************************************************************/
  976. ULONG AMultiStringCallback(
  977. PFIELD_INFO pField,
  978. PVOID UserContext
  979. )
  980. {
  981. if (pField == NULL)
  982. {
  983. dprintf("\nError: AMultiStringCallback was given NULL pField.");
  984. }
  985. else
  986. {
  987. PrintName(pField);
  988. if (gbVerbose)
  989. {
  990. if (pField->size == 0)
  991. dprintf("\n Note: AMultiStringCallback was given zero length type.\n");
  992. else if (pField->size != GetTypeSize("PVOID"))
  993. dprintf("\n Note: AMulitStringCallback: String length is not the size of a pointer.\n"
  994. " Should you be using ACharArrayCallback?\n");
  995. }
  996. if (pField->address)
  997. {
  998. ULONG64 PrevAddr = NULL;
  999. ULONG64 CurAddr = pField->address;
  1000. CHAR Char;
  1001. ULONG cbRead;
  1002. while (CurAddr != PrevAddr &&
  1003. ReadMemory(CurAddr, &Char, sizeof(Char), &cbRead) &&
  1004. cbRead == sizeof(Char) &&
  1005. Char != 0)
  1006. {
  1007. PrevAddr = CurAddr;
  1008. dprintf("\n\t\"");
  1009. CurAddr = PrintAString(CurAddr);
  1010. dprintf("\"");
  1011. }
  1012. }
  1013. else
  1014. {
  1015. dprintf(" (null)");
  1016. }
  1017. }
  1018. if (gbCallbacksPrintNewline) dprintf("\n");
  1019. return gCallbackReturnValue;
  1020. }
  1021. /**************************************************************************\
  1022. *
  1023. * WMultiStringCallback callback for a pointer to several two-byte char
  1024. * strings one after another.
  1025. *
  1026. \**************************************************************************/
  1027. ULONG WMultiStringCallback(
  1028. PFIELD_INFO pField,
  1029. PVOID UserContext
  1030. )
  1031. {
  1032. if (pField == NULL)
  1033. {
  1034. dprintf("\nError: WMultiStringCallback was given NULL pField.");
  1035. }
  1036. else
  1037. {
  1038. PrintName(pField);
  1039. if (gbVerbose)
  1040. {
  1041. if (pField->size == 0)
  1042. dprintf("\n Note: WMultiStringCallback was given zero length type.\n");
  1043. else if (pField->size != GetTypeSize("PVOID"))
  1044. dprintf("\n Note: WMulitStringCallback: String length is not the size of a pointer.\n"
  1045. " Should you be using WCharArrayCallback?\n");
  1046. }
  1047. if (pField->address)
  1048. {
  1049. ULONG64 PrevAddr = NULL;
  1050. ULONG64 CurAddr = pField->address;
  1051. WCHAR Char;
  1052. ULONG cbRead;
  1053. while (CurAddr != PrevAddr &&
  1054. ReadMemory(CurAddr, &Char, sizeof(Char), &cbRead) &&
  1055. cbRead == sizeof(Char) &&
  1056. Char != 0)
  1057. {
  1058. PrevAddr = CurAddr;
  1059. dprintf("\n\t\"");
  1060. CurAddr = PrintWString(CurAddr);
  1061. dprintf("\"");
  1062. }
  1063. }
  1064. else
  1065. {
  1066. dprintf(" (null)");
  1067. }
  1068. }
  1069. if (gbCallbacksPrintNewline) dprintf("\n");
  1070. return gCallbackReturnValue;
  1071. }