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.

1664 lines
44 KiB

  1. /****************************** Module Header ******************************\
  2. *
  3. * Module Name: DuExts.c
  4. *
  5. * Copyright (c) 1985 - 1999, Microsoft Corporation
  6. *
  7. * This module contains user related debugging extensions.
  8. *
  9. * History:
  10. * 11-30-2000 JStall Created
  11. *
  12. \******************************************************************************/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. PSTR pszExtName = "DUEXTS";
  16. #include "stdext64.h"
  17. #include "stdext64.cpp"
  18. /******************************************************************************\
  19. * Constants
  20. \******************************************************************************/
  21. #define BF_MAX_WIDTH 80
  22. #define BF_COLUMN_WIDTH 19
  23. #define NULL_POINTER ((ULONG64)(0))
  24. #define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
  25. // If you want to debug the extension, enable this.
  26. #if 0
  27. #undef DEBUGPRINT
  28. #define DEBUGPRINT Print
  29. #endif
  30. /******************************************************************************\
  31. * Global variables
  32. \******************************************************************************/
  33. BOOL bServerDebug = TRUE;
  34. BOOL bShowFlagNames = TRUE;
  35. char gach1[80];
  36. char gach2[80];
  37. char gach3[80];
  38. int giBFColumn; // bit field: current column
  39. char gaBFBuff[BF_MAX_WIDTH + 1]; // bit field: buffer
  40. // used in dsi() and dinp()
  41. typedef struct {
  42. int iMetric;
  43. LPSTR pstrMetric;
  44. } SYSMET_ENTRY;
  45. #define SMENTRY(sm) {SM_##sm, #sm}
  46. extern int gnIndent; // indentation of !dso
  47. /******************************************************************************\
  48. * Macros
  49. \******************************************************************************/
  50. #define NELEM(array) (sizeof(array)/sizeof(array[0]))
  51. #define TestWWF(pww, flag) (*(((PBYTE)(pww)) + (int)HIBYTE(flag)) & LOBYTE(flag))
  52. void ShowProgress(ULONG i);
  53. void PrivateSetRipFlags(DWORD dwRipFlags, DWORD pid);
  54. #define VAR(v) "DUser!" #v
  55. #define SYM(s) "DUser!" #s
  56. /*
  57. * Use these macros to print field values, globals, local values, etc.
  58. * This assures consistent formating plus make the extensions easier to read and to maintain.
  59. */
  60. #define STRWD1 "67"
  61. #define STRWD2 "28"
  62. #define DWSTR1 "%08lx %." STRWD1 "s"
  63. #define DWSTR2 "%08lx %-" STRWD2 "." STRWD2 "s"
  64. #define PTRSTR1 "%08p %-" STRWD1 "s"
  65. #define PTRSTR2 "%08p %-" STRWD2 "." STRWD2 "s"
  66. #define DWPSTR1 "%08p %." STRWD1 "s"
  67. #define DWPSTR2 "%08p %-" STRWD2 "." STRWD2 "s"
  68. #define PRTFDW1(p, f1) Print(DWSTR1 "\n", (DWORD)##p##f1, #f1)
  69. #define PRTVDW1(s1, v1) Print(DWSTR1 "\n", v1, #s1)
  70. #define PRTFDW2(p, f1, f2) Print(DWSTR2 "\t" DWSTR2 "\n", (DWORD)##p##f1, #f1, (DWORD)##p##f2, #f2)
  71. #define PRTVDW2(s1, v1, s2, v2) Print(DWSTR2 "\t" DWPSTR2 "\n", v1, #s1, v2, #s2)
  72. #define PRTFRC(p, rc) Print("%-" STRWD2 "s{%#lx, %#lx, %#lx, %#lx}\n", #rc, ##p##rc.left, ##p##rc.top, ##p##rc.right, ##p##rc.bottom)
  73. #define PRTFPT(p, pt) Print("%-" STRWD2 "s{%#lx, %#lx}\n", #pt, ##p##pt.x, ##p##pt.y)
  74. #define PRTVPT(s, pt) Print("%-" STRWD2 "s{%#lx, %#lx}\n", #s, pt.x, pt.y)
  75. #define PRTFDWP1(p, f1) Print(DWPSTR1 "\n", (DWORD_PTR)##p##f1, #f1)
  76. #define PRTFDWP2(p, f1, f2) Print(DWPSTR2 "\t" DWPSTR2 "\n", (DWORD_PTR)##p##f1, #f1, (DWORD_PTR)##p##f2, #f2)
  77. #define PRTFDWPDW(p, f1, f2) Print(DWPSTR2 "\t" DWSTR2 "\n", (DWORD_PTR)##p##f1, #f1, (DWORD)##p##f2, #f2)
  78. #define PRTFDWDWP(p, f1, f2) Print(DWSTR2 "\t" DWPSTR2 "\n", (DWORD)##p##f1, #f1, (DWORD_PTR)##p##f2, #f2)
  79. /*
  80. * Bit Fields
  81. */
  82. #define BEGIN_PRTFFLG()
  83. #define PRTFFLG(p, f) PrintBitField(#f, (BOOLEAN)!!(p.f))
  84. #define END_PRTFFLG() PrintEndBitField()
  85. #define PRTGDW1(g1) \
  86. { DWORD _dw1; \
  87. moveExpValue(&_dw1, VAR(g1)); \
  88. Print(DWSTR1 "\n", _dw1, #g1); }
  89. #define PRTGDW2(g1, g2) \
  90. { DWORD _dw1, _dw2; \
  91. moveExpValue(&_dw1, VAR(g1)); \
  92. moveExpValue(&_dw2, VAR(g2)); \
  93. Print(DWSTR2 "\t" DWSTR2 "\n", _dw1, #g1, _dw2, #g2); }
  94. #define PTRGPTR1(g1) \
  95. Print(PTRSTR1 "\n", GetGlobalPointer(VAR(g1)), #g1)
  96. #define PRTGPTR2(g1, g2) \
  97. Print(PTRSTR2 "\t" PTRSTR2 "\n", GetGlobalPointer(VAR(g1)), #g1, GetGlobalPointer(VAR(g2)), #g2)
  98. /* This macro requires char ach[...]; to be previously defined */
  99. #define PRTWND(s, pwnd) \
  100. { DebugGetWindowTextA(pwnd, ach, ARRAY_SIZE(ach)); \
  101. Print("%-" STRWD2 "s" DWPSTR2 "\n", #s, pwnd, ach); }
  102. #define PRTGWND(gpwnd) \
  103. { ULONG64 _pwnd; \
  104. moveExpValuePtr(&_pwnd, VAR(gpwnd)); \
  105. DebugGetWindowTextA(_pwnd, ach, ARRAY_SIZE(ach)); \
  106. Print("%-" STRWD2 "s" DWPSTR2 "\n", #gpwnd, _pwnd, ach); }
  107. LPSTR GetFlags(WORD wType, DWORD dwFlags, LPSTR pszBuf, BOOL fPrintZero);
  108. BOOL CopyUnicodeString(
  109. IN ULONG64 pData,
  110. IN char * pszStructName,
  111. IN char * pszFieldName,
  112. OUT WCHAR *pszDest,
  113. IN ULONG cchMax);
  114. int PtrWidth()
  115. {
  116. static int width = 0;
  117. if (width) {
  118. return width;
  119. }
  120. if (IsPtr64()) {
  121. return width = 17;
  122. }
  123. return width = 8;
  124. }
  125. /*******************************************************************************\
  126. * Flags stuff
  127. \*******************************************************************************/
  128. #define NO_FLAG (LPCSTR)(LONG_PTR)0xFFFFFFFF // use this for non-meaningful entries.
  129. #define _MASKENUM_START (NO_FLAG-1)
  130. #define _MASKENUM_END (NO_FLAG-2)
  131. #define _SHIFT_BITS (NO_FLAG-3)
  132. #define _CONTINUE_ON (NO_FLAG-4)
  133. #define MASKENUM_START(mask) _MASKENUM_START, (LPCSTR)(mask)
  134. #define MASKENUM_END(shift) _MASKENUM_END, (LPCSTR)(shift)
  135. #define SHIFT_BITS(n) _SHIFT_BITS, (LPCSTR)(n)
  136. #define CONTINUE_ON(arr) _CONTINUE_ON, (LPCSTR)(arr)
  137. #if 0
  138. enum GF_FLAGS {
  139. GF_MAX
  140. };
  141. CONST PCSTR* aapszFlag[GF_MAX] = {
  142. };
  143. /***************************************************************************\
  144. * Procedure: GetFlags
  145. *
  146. * Description:
  147. *
  148. * Converts a 32bit set of flags into an appropriate string.
  149. * pszBuf should be large enough to hold this string, no checks are done.
  150. * pszBuf can be NULL, allowing use of a local static buffer but note that
  151. * this is not reentrant.
  152. * Output string has the form: "FLAG1 | FLAG2 ..." or "0"
  153. *
  154. * Returns: pointer to given or static buffer with string in it.
  155. *
  156. * 6/9/1995 Created SanfordS
  157. *
  158. \***************************************************************************/
  159. LPSTR GetFlags(
  160. WORD wType,
  161. DWORD dwFlags,
  162. LPSTR pszBuf,
  163. BOOL fPrintZero)
  164. {
  165. static char szT[512];
  166. WORD i;
  167. BOOL fFirst = TRUE;
  168. BOOL fNoMoreNames = FALSE;
  169. CONST PCSTR *apszFlags;
  170. LPSTR apszFlagNames[sizeof(DWORD) * 8], pszT;
  171. const char** ppszNextFlag;
  172. UINT uFlagsCount, uNextFlag;
  173. DWORD dwUnnamedFlags, dwLoopFlag;
  174. DWORD dwShiftBits;
  175. DWORD dwOrigFlags;
  176. if (pszBuf == NULL) {
  177. pszBuf = szT;
  178. }
  179. if (!bShowFlagNames) {
  180. sprintf(pszBuf, "%x", dwFlags);
  181. return pszBuf;
  182. }
  183. if (wType >= GF_MAX) {
  184. strcpy(pszBuf, "Invalid flag type.");
  185. return pszBuf;
  186. }
  187. /*
  188. * Initialize output buffer and names array
  189. */
  190. *pszBuf = '\0';
  191. RtlZeroMemory(apszFlagNames, sizeof(apszFlagNames));
  192. apszFlags = aapszFlag[wType];
  193. /*
  194. * Build a sorted array containing the names of the flags in dwFlags
  195. */
  196. uFlagsCount = 0;
  197. dwUnnamedFlags = dwOrigFlags = dwFlags;
  198. dwLoopFlag = 1;
  199. dwShiftBits = 0;
  200. reentry:
  201. for (i = 0; dwFlags; dwFlags >>= 1, i++, dwLoopFlag <<= 1, ++dwShiftBits) {
  202. const char* lpszFlagName = NULL;
  203. /*
  204. * Bail if we reached the end of the flag names array
  205. */
  206. if (apszFlags[i] == NULL) {
  207. break;
  208. }
  209. if (apszFlags[i] == _MASKENUM_START) {
  210. //
  211. // Masked enumerative items.
  212. //
  213. DWORD en = 0;
  214. DWORD dwMask = (DWORD)(ULONG_PTR)apszFlags[++i];
  215. // First, clear up the handled bits.
  216. dwUnnamedFlags &= ~dwMask;
  217. lpszFlagName = NULL;
  218. for (++i; apszFlags[i] != NULL && apszFlags[i] != _MASKENUM_END; ++i, ++en) {
  219. if ((dwOrigFlags & dwMask) == (en << dwShiftBits )) {
  220. if (apszFlags[i] != NO_FLAG) {
  221. lpszFlagName = apszFlags[i];
  222. }
  223. }
  224. }
  225. //
  226. // Shift the bits and get ready for the next item.
  227. // Next item right after _MASKENUM_END holds the bits to shift.
  228. //
  229. dwFlags >>= (int)(ULONG_PTR)apszFlags[++i] - 1;
  230. dwLoopFlag <<= (int)(ULONG_PTR)apszFlags[i] - 1;
  231. dwShiftBits += (int)(ULONG_PTR)apszFlags[i] - 1;
  232. if (lpszFlagName == NULL) {
  233. //
  234. // Could not find the match. Skip to the next item.
  235. //
  236. continue;
  237. }
  238. }
  239. else if (apszFlags[i] == _CONTINUE_ON) {
  240. //
  241. // Refer the other item array. Pointer to the array is stored at [i+1].
  242. //
  243. apszFlags = (LPSTR*)apszFlags[i + 1];
  244. goto reentry;
  245. }
  246. else if (apszFlags[i] == _SHIFT_BITS) {
  247. //
  248. // To save some space, just shift some bits..
  249. //
  250. dwFlags >>= (int)(ULONG_PTR)apszFlags[++i] - 1;
  251. dwLoopFlag <<= (int)(ULONG_PTR)apszFlags[i] - 1;
  252. dwShiftBits += (int)(ULONG_PTR)apszFlags[i] - 1;
  253. continue;
  254. }
  255. else {
  256. /*
  257. * continue if this bit is not set or we don't have a name for it
  258. */
  259. if (!(dwFlags & 1) || (apszFlags[i] == NO_FLAG)) {
  260. continue;
  261. }
  262. lpszFlagName = apszFlags[i];
  263. }
  264. /*
  265. * Find the sorted position where this name should go
  266. */
  267. ppszNextFlag = apszFlagNames;
  268. uNextFlag = 0;
  269. while (uNextFlag < uFlagsCount) {
  270. if (strcmp(*ppszNextFlag, lpszFlagName) > 0) {
  271. break;
  272. }
  273. ppszNextFlag++;
  274. uNextFlag++;
  275. }
  276. /*
  277. * Insert the new name
  278. */
  279. RtlMoveMemory((char*)(ppszNextFlag + 1), ppszNextFlag, (uFlagsCount - uNextFlag) * sizeof(DWORD));
  280. *ppszNextFlag = lpszFlagName;
  281. uFlagsCount++;
  282. /*
  283. * We got a name so clear it from the unnamed bits.
  284. */
  285. dwUnnamedFlags &= ~dwLoopFlag;
  286. }
  287. /*
  288. * Build the string now
  289. */
  290. ppszNextFlag = apszFlagNames;
  291. pszT = pszBuf;
  292. /*
  293. * Add the first name
  294. */
  295. if (uFlagsCount > 0) {
  296. pszT += sprintf(pszT, "%s", *ppszNextFlag++);
  297. uFlagsCount--;
  298. }
  299. /*
  300. * Concatenate all other names with " |"
  301. */
  302. while (uFlagsCount > 0) {
  303. pszT += sprintf(pszT, " | %s", *ppszNextFlag++);
  304. uFlagsCount--;
  305. }
  306. /*
  307. * If there are unamed bits, add them at the end
  308. */
  309. if (dwUnnamedFlags != 0) {
  310. pszT += sprintf(pszT, " | %#lx", dwUnnamedFlags);
  311. }
  312. /*
  313. * Print zero if needed and asked to do so
  314. */
  315. if (fPrintZero && (pszT == pszBuf)) {
  316. sprintf(pszBuf, "0");
  317. }
  318. return pszBuf;
  319. }
  320. #endif
  321. ///////////////////////////////////////////////////////////////////////////
  322. //
  323. // Enumerated items with mask
  324. //
  325. ///////////////////////////////////////////////////////////////////////////
  326. typedef struct {
  327. LPCSTR name;
  328. DWORD value;
  329. } EnumItem;
  330. #define EITEM(a) { #a, a }
  331. /***************************************************************************\
  332. * Helper Procedures: dso etc.
  333. *
  334. * 04/19/2000 Created Hiro
  335. \***************************************************************************/
  336. // to workaround nosy InitTypeRead
  337. #define _InitTypeRead(Addr, lpszType) GetShortField(Addr, (PUCHAR)lpszType, 1)
  338. #define CONTINUE EXCEPTION_EXECUTE_HANDLER
  339. #define RAISE_EXCEPTION() RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, NULL)
  340. #define BAD_SYMBOL(symbol) \
  341. Print("Failed to get %s: bad symbol?\n", symbol); \
  342. RAISE_EXCEPTION()
  343. #define CANT_GET_VALUE(symbol, p) \
  344. Print("Failed to get %s @ %p: memory paged out?\n", symbol, p); \
  345. RAISE_EXCEPTION()
  346. BOOL dso(LPCSTR szStruct, ULONG64 address, ULONG dwOption)
  347. {
  348. SYM_DUMP_PARAM symDump = {
  349. sizeof symDump, (PUCHAR) szStruct, dwOption, // 0 for default dump like dt
  350. address,
  351. NULL, NULL, NULL, 0, NULL
  352. };
  353. return Ioctl(IG_DUMP_SYMBOL_INFO, &symDump, symDump.size);
  354. }
  355. ULONG64 GetPointer(ULONG64 addr)
  356. {
  357. ULONG64 p = 0;
  358. if (!ReadPointer(addr, &p)) {
  359. CANT_GET_VALUE("a pointer", addr);
  360. }
  361. return p;
  362. }
  363. DWORD GetDWord(ULONG64 addr)
  364. {
  365. ULONG64 dw = 0xbaadbaad;
  366. if (!GetFieldData(addr, "DWORD", NULL, sizeof dw, &dw)) {
  367. CANT_GET_VALUE("DWORD", addr);
  368. }
  369. return (DWORD)dw;
  370. }
  371. WORD GetWord(ULONG64 addr)
  372. {
  373. ULONG64 w = 0xbaad;
  374. if (!GetFieldData(addr, "WORD", NULL, sizeof w, &w)) {
  375. CANT_GET_VALUE("WORD", addr);
  376. }
  377. return (WORD)w;
  378. }
  379. BYTE GetByte(ULONG64 addr)
  380. {
  381. ULONG64 b = 0;
  382. if (GetFieldData(addr, "BYTE", NULL, sizeof b, &b)) {
  383. CANT_GET_VALUE("BYTE", addr);
  384. }
  385. return (BYTE)b;
  386. }
  387. ULONG
  388. GetUlongFromAddress (
  389. ULONG64 Location
  390. )
  391. {
  392. ULONG Value;
  393. ULONG result;
  394. if ((!ReadMemory(Location,&Value,sizeof(ULONG),&result)) || (result < sizeof(ULONG))) {
  395. dprintf("GetUlongFromAddress: unable to read from %I64x\n", Location);
  396. RAISE_EXCEPTION();
  397. }
  398. return Value;
  399. }
  400. ULONG64 GetGlobalPointer(LPSTR symbol)
  401. {
  402. ULONG64 pp;
  403. ULONG64 p = 0;
  404. pp = EvalExp(symbol);
  405. if (pp == 0) {
  406. BAD_SYMBOL(symbol);
  407. } else if (!ReadPointer(pp, &p)) {
  408. CANT_GET_VALUE(symbol, pp);
  409. }
  410. return p;
  411. }
  412. ULONG64 GetGlobalPointerNoExp(LPSTR symbol) // no exception
  413. {
  414. ULONG64 p = 0;
  415. __try {
  416. p = GetGlobalPointer(symbol);
  417. } __except (CONTINUE) {
  418. }
  419. return p;
  420. }
  421. ULONG64 GetGlobalMemberAddress(LPSTR symbol, LPSTR type, LPSTR field)
  422. {
  423. ULONG64 pVar = EvalExp(symbol);
  424. ULONG offset;
  425. if (pVar == 0) {
  426. BAD_SYMBOL(symbol);
  427. }
  428. if (GetFieldOffset(type, field, &offset)) {
  429. BAD_SYMBOL(type);
  430. }
  431. return pVar + offset;
  432. }
  433. ULONG64 GetGlobalMember(LPSTR symbol, LPSTR type, LPSTR field)
  434. {
  435. ULONG64 pVar = EvalExp(symbol);
  436. ULONG64 val;
  437. if (pVar == 0) {
  438. BAD_SYMBOL(symbol);
  439. }
  440. if (GetFieldValue(pVar, type, field, val)) {
  441. CANT_GET_VALUE(symbol, pVar);
  442. }
  443. return val;
  444. }
  445. ULONG64 GetArrayElement(
  446. ULONG64 pAddr,
  447. LPSTR lpszStruc,
  448. LPSTR lpszField,
  449. ULONG64 index,
  450. LPSTR lpszType)
  451. {
  452. static ULONG ulOffsetBase, ulSize;
  453. ULONG64 result = 0;
  454. if (lpszField) {
  455. GetFieldOffset(lpszStruc, lpszField, &ulOffsetBase);
  456. ulSize = GetTypeSize(lpszType);
  457. }
  458. ReadMemory(pAddr + ulOffsetBase + ulSize * index, &result, ulSize, NULL);
  459. return result;
  460. }
  461. ULONG64 GetArrayElementPtr(
  462. ULONG64 pAddr,
  463. LPSTR lpszStruc,
  464. LPSTR lpszField,
  465. ULONG64 index)
  466. {
  467. static ULONG ulOffsetBase, ulSize;
  468. ULONG64 result = 0;
  469. if (lpszField) {
  470. GetFieldOffset(lpszStruc, lpszField, &ulOffsetBase);
  471. }
  472. if (ulSize == 0) {
  473. ulSize = GetTypeSize("PVOID");
  474. }
  475. ReadPointer(pAddr + ulOffsetBase + ulSize * index, &result);
  476. return result;
  477. }
  478. /*
  479. * Show progress in time consuming commands
  480. * 10/15/2000 hiroyama
  481. */
  482. void ShowProgress(ULONG i)
  483. {
  484. const char* clock[] = {
  485. "\r-\r",
  486. "\r\\\r",
  487. "\r|\r",
  488. "\r/\r",
  489. };
  490. /*
  491. * Show the progress :-)
  492. */
  493. Print(clock[i % COUNTOF(clock)]);
  494. }
  495. #define DOWNCAST(type, value) ((type)(ULONG_PTR)(value))
  496. /***************************************************************************\
  497. * Procedure: PrintBitField, PrintEndBitField
  498. *
  499. * Description: Printout specified boolean value in a structure.
  500. * Assuming strlen(pszFieldName) will not exceeds BF_COLUMN_WIDTH.
  501. *
  502. * Returns: None
  503. *
  504. * 10/12/1997 Created HiroYama
  505. *
  506. \***************************************************************************/
  507. void PrintBitField(LPSTR pszFieldName, BOOLEAN fValue)
  508. {
  509. int iWidth;
  510. int iStart = giBFColumn;
  511. sprintf(gach1, fValue ? "*%-s " : " %-s ", pszFieldName);
  512. iWidth = (strlen(gach1) + BF_COLUMN_WIDTH - 1) / BF_COLUMN_WIDTH;
  513. iWidth *= BF_COLUMN_WIDTH;
  514. if ((giBFColumn += iWidth) >= BF_MAX_WIDTH) {
  515. giBFColumn = iWidth;
  516. Print("%s\n", gaBFBuff);
  517. iStart = 0;
  518. }
  519. sprintf(gaBFBuff + iStart, "%-*s", iWidth, gach1);
  520. }
  521. void PrintEndBitField()
  522. {
  523. if (giBFColumn != 0) {
  524. giBFColumn = 0;
  525. Print("%s\n", gaBFBuff);
  526. }
  527. }
  528. /***************************************************************************\
  529. *
  530. * Procedure: CopyUnicodeString
  531. *
  532. * 06/05/00 JStall Created (yeah, baby!)
  533. *
  534. \***************************************************************************/
  535. BOOL
  536. CopyUnicodeString(
  537. IN ULONG64 pData,
  538. IN char * pszStructName,
  539. IN char * pszFieldName,
  540. OUT WCHAR *pszDest,
  541. IN ULONG cchMax)
  542. {
  543. ULONG Length;
  544. ULONG64 Buffer;
  545. char szLengthName[256];
  546. char szBufferName[256];
  547. if (pData == 0) {
  548. pszDest[0] = '\0';
  549. return FALSE;
  550. }
  551. strcpy(szLengthName, pszFieldName);
  552. strcat(szLengthName, ".Length");
  553. strcpy(szBufferName, pszFieldName);
  554. strcat(szBufferName, ".Buffer");
  555. if (GetFieldValue(pData, pszStructName, szLengthName, Length) ||
  556. GetFieldValue(pData, pszStructName, szBufferName, Buffer)) {
  557. wcscpy(pszDest, L"<< Can't get name >>");
  558. return FALSE;
  559. }
  560. if (Buffer == 0) {
  561. wcscpy(pszDest, L"<null>");
  562. } else {
  563. ULONG cbText;
  564. cbText = min(cchMax, Length + sizeof(WCHAR));
  565. if (!(tryMoveBlock(pszDest, Buffer, cbText))) {
  566. wcscpy(pszDest, L"<< Can't get value >>");
  567. return FALSE;
  568. }
  569. }
  570. return TRUE;
  571. }
  572. /***************************************************************************\
  573. *
  574. * DirectUser TLS access
  575. *
  576. * 12/03/2000 JStall Created
  577. *
  578. \***************************************************************************/
  579. BOOL
  580. ReadTlsValue(ULONG64 pteb, ULONG idxSlot, ULONG64 * ppValue)
  581. {
  582. BOOL fSuccess = FALSE;
  583. ULONG64 pValue = NULL;
  584. //
  585. // Need to remove the high-bit from the TLS slot. This is set on in
  586. // Checked build to detect illegal / uninitialized slots, such as '0'.
  587. //
  588. idxSlot &= 0x7FFFFFFF;
  589. //
  590. // Get TLS info
  591. //
  592. ULONG64 pThread = 0;
  593. // Print("> idxSlot: %d\n", idxSlot);
  594. // Print("> TEB: 0x%p\n", pteb);
  595. if (pteb) {
  596. ULONG64 rgTLS = NULL;
  597. ULONG ulOffset = 0;
  598. ULONG ulSize = GetTypeSize("PVOID");
  599. // Print("> ulSize: %d\n", ulSize);
  600. if (idxSlot < TLS_MINIMUM_AVAILABLE) {
  601. // pThread = Teb->TlsSlots[idxSlot];
  602. GetFieldOffset(SYM(_TEB), "TlsSlots", &ulOffset);
  603. // Print("> TlsSlots offset: %d\n", ulOffset);
  604. ReadPointer(pteb + ulOffset + ulSize * idxSlot, &pValue);
  605. fSuccess = TRUE;
  606. } else if (idxSlot >= TLS_MINIMUM_AVAILABLE + TLS_EXPANSION_SLOTS) {
  607. Print("ERROR: Invalid TLS index %d\n", idxSlot);
  608. } else {
  609. // pThread = Teb->TlsExpansionSlots[idxSlot - TLS_MINIMUM_AVAILABLE];
  610. GetFieldOffset("_TEB", "TlsExpansionSlots", &ulOffset);
  611. // Print("> TlsExpansionSlots offset: %d\n", ulOffset);
  612. rgTLS = GetPointer(pteb + ulOffset);
  613. if (rgTLS != NULL) {
  614. ReadPointer(rgTLS + ulSize * (idxSlot - TLS_MINIMUM_AVAILABLE), &pValue);
  615. fSuccess = TRUE;
  616. }
  617. }
  618. }
  619. *ppValue = pValue;
  620. return fSuccess;
  621. }
  622. /***************************************************************************\
  623. *
  624. * GetDUserThread
  625. *
  626. * GetDUserThread() returns the global Thread object for the current thread.
  627. *
  628. * 12/03/2000 JStall Created
  629. *
  630. \***************************************************************************/
  631. BOOL
  632. GetDUserThread(ULONG64 pteb, ULONG64 * ppThread)
  633. {
  634. *ppThread = NULL;
  635. //
  636. // Get DUser TLS slot
  637. //
  638. ULONG idxSlot = (ULONG) GetGlobalPointer(VAR(g_tlsThread));
  639. if (idxSlot == (UINT) -1) {
  640. Print("ERROR: Unable to get DirectUser TLS information.\n");
  641. return FALSE;
  642. }
  643. if ((!ReadTlsValue(pteb, idxSlot, ppThread)) || (*ppThread == NULL)) {
  644. Print("ERROR: Unable to get DirectUser Thread information.\n");
  645. return FALSE;
  646. }
  647. return TRUE;
  648. }
  649. /***************************************************************************\
  650. *
  651. * Procedure: Igthread
  652. *
  653. * Dumps DUser Thread information
  654. *
  655. * 11/30/2000 JStall Created
  656. *
  657. \***************************************************************************/
  658. BOOL Igthread(DWORD opts, ULONG64 param1)
  659. {
  660. int nMsg;
  661. ULONG64 pThread = NULL, pteb = NULL;
  662. BOOL fVerbose = TRUE;
  663. __try {
  664. //
  665. // Determine options
  666. //
  667. fVerbose = opts & OFLAG(v);
  668. //
  669. // Get Thread information
  670. //
  671. if (opts & OFLAG(t)) {
  672. //
  673. // Use the specified TEB
  674. //
  675. pteb = param1;
  676. } else if (param1 == 0) {
  677. //
  678. // Use the current thread's TEB
  679. //
  680. GetTebAddress(&pteb);
  681. }
  682. if (pteb != NULL) {
  683. GetDUserThread(pteb, &pThread);
  684. }
  685. //
  686. // Display information
  687. //
  688. if (pThread != NULL) {
  689. Print("DUser Thread: 0x%p pteb: 0x%p\n", pThread, pteb);
  690. dso(SYM(Thread), pThread, 0);
  691. ULONG64 pCoreST = GetArrayElementPtr(pThread, SYM(Thread), "m_rgSTs", 0);
  692. if (pCoreST != NULL) {
  693. Print("\nDUser CoreST: 0x%p\n", pCoreST);
  694. dso(SYM(CoreST), pCoreST, 0);
  695. }
  696. } else {
  697. Print("ERROR: Unable to read DUser Thread\n");
  698. }
  699. } __except (CONTINUE) {
  700. }
  701. return TRUE;
  702. }
  703. /***************************************************************************\
  704. *
  705. * Procedure: Itls
  706. *
  707. * Dumps a TLS slot value
  708. *
  709. * 6/08/2001 JStall Created
  710. *
  711. \***************************************************************************/
  712. BOOL Itls(DWORD opts, ULONG64 param1, ULONG64 param2)
  713. {
  714. __try {
  715. ULONG idxSlot = ((ULONG) param1) & 0x7FFFFFFF;
  716. ULONG64 pteb = param2;
  717. ULONG64 pData;
  718. if (idxSlot == 0) {
  719. Print("ERROR: Need to specify a TLS slot.\n");
  720. } else {
  721. if (param2 == 0) {
  722. //
  723. // Need to determine the current thread
  724. //
  725. GetTebAddress(&pteb);
  726. }
  727. if (pteb == 0) {
  728. Print("ERROR: Unable to get thread information.\n");
  729. } else {
  730. if (!ReadTlsValue(pteb, idxSlot, &pData)) {
  731. Print("ERROR: Unable to get TLS information.\n");
  732. } else {
  733. Print("TLS[%d] = 0x%p %d\n", idxSlot, pData, pData);
  734. }
  735. }
  736. }
  737. } __except (CONTINUE) {
  738. }
  739. return TRUE;
  740. }
  741. /***************************************************************************\
  742. *
  743. * Procedure: Igcontext
  744. *
  745. * Dumps DUser Context information
  746. *
  747. * 11/30/2000 JStall Created
  748. *
  749. \***************************************************************************/
  750. BOOL Igcontext(DWORD opts, ULONG64 param1)
  751. {
  752. int nMsg;
  753. ULONG64 pThread = NULL, pContext = NULL, pteb = NULL;
  754. BOOL fVerbose = TRUE;
  755. __try {
  756. //
  757. // Determine options
  758. //
  759. fVerbose = opts & OFLAG(v);
  760. //
  761. // Get Thread and Context information
  762. //
  763. if (opts & OFLAG(t)) {
  764. //
  765. // Use the specified TEB
  766. //
  767. pteb = param1;
  768. } else if (param1 == 0) {
  769. //
  770. // Use the current thread's TEB
  771. //
  772. GetTebAddress(&pteb);
  773. } else {
  774. pContext = param1;
  775. }
  776. if (pteb != NULL) {
  777. GetDUserThread(pteb, &pThread);
  778. Print("> Thread: 0x%p\n", pThread);
  779. if (pThread != NULL) {
  780. ULONG ulOffset;
  781. GetFieldOffset(SYM(Thread), "m_pContext", &ulOffset);
  782. Print("> ulOffset: 0x%x = d\n", ulOffset, ulOffset);
  783. ReadPointer(pThread + ulOffset, &pContext);
  784. }
  785. }
  786. //
  787. // Display information
  788. //
  789. if (pContext != NULL) {
  790. Print("DUser Context: 0x%p\n", pContext, pteb);
  791. dso(SYM(Context), pContext, 0);
  792. ULONG64 pCoreSC = GetArrayElementPtr(pContext, SYM(Context), "m_rgSCs", 0);
  793. ULONG64 pMotionSC = GetArrayElementPtr(pContext, SYM(Context), "m_rgSCs", 1);
  794. if (pCoreSC != NULL) {
  795. Print("\nDUser CoreSC: 0x%p\n", pCoreSC);
  796. dso(SYM(CoreSC), pCoreSC, 0);
  797. }
  798. if (pMotionSC != NULL) {
  799. Print("\nDUser MotionSC: 0x%p\n", pMotionSC);
  800. dso(SYM(MotionSC), pMotionSC, 0);
  801. }
  802. } else {
  803. Print("ERROR: Unable to read DUser Context\n");
  804. }
  805. } __except (CONTINUE) {
  806. }
  807. return TRUE;
  808. }
  809. /***************************************************************************\
  810. *
  811. * DirectUser Message Dumping
  812. *
  813. * 11/30/2000 JStall Created
  814. *
  815. \***************************************************************************/
  816. struct DbgMsgInfo
  817. {
  818. int cLevel; // Level in heirarchy
  819. LPCSTR pszStructName; // Structure to type-case to
  820. int nValue; // Value (of children)
  821. LPCSTR pszValueName; // Message / value name
  822. LPCSTR pszFieldName; // Name of field for child lookup
  823. };
  824. #define DBGMI_PARENT(cLevel, pszStructName, value, pszFieldName) \
  825. { cLevel, SYM(pszStructName), value, #value, #pszFieldName }
  826. #define DBGMI_LEAF(cLevel, pszStructName, value) \
  827. { cLevel, SYM(pszStructName), value, #value, NULL }
  828. DbgMsgInfo g_dmi[] = {
  829. DBGMI_PARENT(0, GMSG_DESTROY, GM_DESTROY, nCode),
  830. DBGMI_LEAF( 1, GMSG_DESTROY, GDESTROY_START),
  831. DBGMI_LEAF( 1, GMSG_DESTROY, GDESTROY_FINAL),
  832. DBGMI_PARENT(0, GMSG_PAINT, GM_PAINT, nCmd),
  833. DBGMI_PARENT(1, GMSG_PAINT, GPAINT_RENDER, nSurfaceType),
  834. DBGMI_LEAF( 2, GMSG_PAINTRENDERI, GSURFACE_HDC),
  835. DBGMI_LEAF( 2, GMSG_PAINTRENDERF, GSURFACE_GPGRAPHICS),
  836. DBGMI_PARENT(0, GMSG_INPUT, GM_INPUT, nDevice),
  837. DBGMI_PARENT(1, GMSG_MOUSE, GINPUT_MOUSE, nCode),
  838. DBGMI_LEAF( 2, GMSG_MOUSE, GMOUSE_MOVE),
  839. DBGMI_LEAF( 2, GMSG_MOUSECLICK, GMOUSE_DOWN),
  840. DBGMI_LEAF( 2, GMSG_MOUSECLICK, GMOUSE_UP),
  841. DBGMI_LEAF( 2, GMSG_MOUSEDRAG, GMOUSE_DRAG),
  842. DBGMI_LEAF( 2, GMSG_MOUSE, GMOUSE_HOVER),
  843. DBGMI_LEAF( 2, GMSG_MOUSEWHEEL, GMOUSE_WHEEL),
  844. DBGMI_PARENT(1, GMSG_KEYBOARD, GINPUT_KEYBOARD, nCode),
  845. DBGMI_LEAF( 2, GMSG_KEYBOARD, GKEY_DOWN),
  846. DBGMI_LEAF( 2, GMSG_KEYBOARD, GKEY_UP),
  847. DBGMI_LEAF( 2, GMSG_KEYBOARD, GKEY_CHAR),
  848. DBGMI_LEAF( 2, GMSG_KEYBOARD, GKEY_SYSDOWN),
  849. DBGMI_LEAF( 2, GMSG_KEYBOARD, GKEY_SYSUP),
  850. DBGMI_LEAF( 2, GMSG_KEYBOARD, GKEY_SYSCHAR),
  851. DBGMI_LEAF( 2, GMSG_KEYBOARD, GMOUSE_WHEEL),
  852. DBGMI_LEAF( 1, GMSG_INPUT, GINPUT_JOYSTICK),
  853. DBGMI_PARENT(0, GMSG_CHANGESTATE, GM_CHANGESTATE, nCode),
  854. DBGMI_LEAF( 1, GMSG_CHANGESTATE, GSTATE_KEYBOARDFOCUS),
  855. DBGMI_LEAF( 1, GMSG_CHANGESTATE, GSTATE_MOUSEFOCUS),
  856. DBGMI_LEAF( 1, GMSG_CHANGESTATE, GSTATE_ACTIVE),
  857. DBGMI_LEAF( 1, GMSG_CHANGESTATE, GSTATE_CAPTURE),
  858. DBGMI_LEAF( 0, GMSG_CHANGERECT, GM_CHANGERECT),
  859. DBGMI_LEAF( 0, GMSG_CHANGESTYLE, GM_CHANGESTYLE),
  860. DBGMI_PARENT(0, GMSG_QUERY, GM_QUERY, nCode),
  861. #ifdef GADGET_ENABLE_OLE
  862. DBGMI_LEAF( 1, GMSG_QUERYINTERFACE,GQUERY_INTERFACE),
  863. DBGMI_LEAF( 1, GMSG_QUERYINTERFACE,GQUERY_OBJECT),
  864. #endif
  865. DBGMI_LEAF( 1, GMSG_QUERYRECT, GQUERY_RECT),
  866. DBGMI_LEAF( 1, GMSG_QUERYDESC, GQUERY_DESCRIPTION),
  867. DBGMI_LEAF( 1, GMSG_QUERYHITTEST, GQUERY_HITTEST),
  868. DBGMI_LEAF( 1, GMSG_QUERYPADDING, GQUERY_PADDING),
  869. #ifdef GADGET_ENABLE_OLE
  870. DBGMI_LEAF( 1, GMSG_QUERYDROPTARGET,GQUERY_DROPTARGET),
  871. #endif
  872. { -1, NULL, NULL, NULL, NULL } // End of list
  873. };
  874. /***************************************************************************\
  875. *
  876. * Procedure: FindMsgInfo()
  877. *
  878. * 11/30/2000 JStall Created
  879. *
  880. \***************************************************************************/
  881. const DbgMsgInfo *
  882. FindMsgInfo(ULONG64 pmsg)
  883. {
  884. LPCSTR pszCurField = "nMsg";
  885. int cCurLevel = 0;
  886. int nSearchValue;
  887. const DbgMsgInfo * pdmiCur = g_dmi;
  888. const DbgMsgInfo * pdmiBest = NULL;
  889. //
  890. // Start off by decoding the GMSG
  891. //
  892. InitTypeRead(pmsg, GMSG);
  893. nSearchValue = (int) ReadField(nMsg);
  894. // Print("...searching for nMsg: 0x%x\n", nSearchValue);
  895. while (pdmiCur->cLevel >= cCurLevel) {
  896. // Print(" %d: %s, %d\n", pdmiCur->cLevel, pdmiCur->pszStructName, pdmiCur->nValue);
  897. //
  898. // Search entries at the same level for a matching value
  899. //
  900. if (pdmiCur->cLevel == cCurLevel) {
  901. if (pdmiCur->nValue == nSearchValue) {
  902. //
  903. // We've found a corresponding entry. We can update our best
  904. // guess as the to the message type and start searching its
  905. // children.
  906. //
  907. pdmiBest = pdmiCur;
  908. cCurLevel++;
  909. if (pdmiBest->pszFieldName != NULL) {
  910. //
  911. // This node has children that can be used to typecast the
  912. // message futher.
  913. //
  914. // Perform an InitTypeRead() to cast the structure
  915. GetShortField(pmsg, pdmiBest->pszStructName, 1);
  916. // Read the next (int) ReadField(nMsg);
  917. nSearchValue = (int) GetShortField(0, pdmiBest->pszFieldName, 0);
  918. // Print("...searching for %s: 0x%x\n", pdmiBest->pszFieldName, nSearchValue);
  919. } else {
  920. //
  921. // This node has no children, so we are now down.
  922. //
  923. break;
  924. }
  925. }
  926. }
  927. pdmiCur++;
  928. }
  929. return pdmiBest;
  930. }
  931. /***************************************************************************\
  932. *
  933. * FormatMsgName
  934. *
  935. * FormatMsgName() generates a descriptive message name for a given message.
  936. *
  937. * 11/30/2000 JStall Created
  938. *
  939. \***************************************************************************/
  940. void
  941. FormatMsgName(ULONG64 pmsg, char * pszMsgName, int cch, const DbgMsgInfo ** ppdmi)
  942. {
  943. UNREFERENCED_PARAMETER(cch);
  944. if (ppdmi != NULL) {
  945. *ppdmi = NULL;
  946. }
  947. InitTypeRead(pmsg, GMSG);
  948. int nMsg = (int) ReadField(nMsg);
  949. if (nMsg < GM_EVENT) {
  950. strcpy(pszMsgName, "(Method)");
  951. } else if (nMsg > GM_USER) {
  952. strcpy(pszMsgName, "(User defined event)");
  953. } else {
  954. const DbgMsgInfo * pdmi = FindMsgInfo(pmsg);
  955. if (pdmi != NULL) {
  956. sprintf(pszMsgName, "%s : %s", pdmi->pszStructName, pdmi->pszValueName);
  957. if (ppdmi != NULL) {
  958. *ppdmi = pdmi;
  959. }
  960. } else {
  961. strcpy(pszMsgName, "(Unable to find GMSG)");
  962. }
  963. }
  964. }
  965. /***************************************************************************\
  966. *
  967. * Procedure: Igmsg
  968. *
  969. * Dumps DUser GMSG information
  970. *
  971. * 11/30/2000 JStall Created
  972. *
  973. \***************************************************************************/
  974. BOOL Igmsg(DWORD opts, ULONG64 param1)
  975. {
  976. int nMsg;
  977. LPCSTR pszMsgName;
  978. ULONG64 pmsg;
  979. CHAR szFullMsgName[256];
  980. BOOL fVerbose = TRUE;
  981. const DbgMsgInfo * pdmi = NULL;
  982. pmsg = param1;
  983. __try {
  984. //
  985. // Determine options
  986. //
  987. fVerbose = opts & OFLAG(v);
  988. //
  989. // Get GMSG information
  990. //
  991. FormatMsgName(pmsg, szFullMsgName, COUNTOF(szFullMsgName), &pdmi);
  992. //
  993. // Display information
  994. //
  995. Print("GMSG = %s\n", szFullMsgName);
  996. if (pdmi != NULL) {
  997. dso(pdmi->pszStructName, pmsg, 0);
  998. }
  999. } __except (CONTINUE) {
  1000. }
  1001. return TRUE;
  1002. }
  1003. /***************************************************************************\
  1004. *
  1005. * Procedure: Igme
  1006. *
  1007. * Dumps DUser MsgEntry information
  1008. *
  1009. * 11/30/2000 JStall Created
  1010. *
  1011. \***************************************************************************/
  1012. BOOL Igme(DWORD opts, ULONG64 param1)
  1013. {
  1014. DWORD cbSize;
  1015. int nMsg;
  1016. LPCSTR pszMsgName;
  1017. ULONG64 pme, pmsg;
  1018. CHAR szFullMsgName[256];
  1019. const DbgMsgInfo * pdmi = NULL;
  1020. BOOL fVerbose = TRUE;
  1021. BOOL fList = FALSE;
  1022. pme = param1;
  1023. __try {
  1024. //
  1025. // Determine options
  1026. //
  1027. fVerbose = opts & OFLAG(v);
  1028. fList = opts & OFLAG(l);
  1029. while (pme != NULL) {
  1030. //
  1031. // Read standard information
  1032. //
  1033. pmsg = pme + GetTypeSize(SYM(MsgEntry));
  1034. InitTypeRead(pmsg, GMSG);
  1035. nMsg = (int) ReadField(nMsg);
  1036. FormatMsgName(pmsg, szFullMsgName, COUNTOF(szFullMsgName), &pdmi);
  1037. //
  1038. // Display information
  1039. //
  1040. if (fVerbose) {
  1041. Print("MsgEntry: 0x%p\n", pme);
  1042. Print(" Message: 0x%p %s\n", pmsg, szFullMsgName);
  1043. if (pdmi != NULL) {
  1044. dso(pdmi->pszStructName, pmsg, 0);
  1045. }
  1046. } else {
  1047. Print("MsgEntry: 0x%p GMSG: 0x%p nMsg: 0x%x = %s\n", pme, pmsg, nMsg, szFullMsgName);
  1048. }
  1049. if (fList) {
  1050. //
  1051. // Reading a list, so go to next message
  1052. //
  1053. InitTypeRead(pme, MsgEntry);
  1054. pme = ReadField(pNext);
  1055. if (fVerbose & (pme != NULL)) {
  1056. Print("\n");
  1057. }
  1058. } else {
  1059. //
  1060. // Not displaying a list, so just exit
  1061. //
  1062. break;
  1063. }
  1064. }
  1065. } __except (CONTINUE) {
  1066. }
  1067. return TRUE;
  1068. }
  1069. //
  1070. // WARNING: Keep this is sync with the real DuTicket
  1071. //
  1072. struct DuTicketCopy
  1073. {
  1074. DWORD Index : 16;
  1075. DWORD Uniqueness : 8;
  1076. DWORD Type : 7;
  1077. DWORD Unused : 1;
  1078. };
  1079. /***************************************************************************\
  1080. *
  1081. * Procedure: ForAllTickets
  1082. *
  1083. * Iterates over all of the tickets in the ticket manager, invoking the
  1084. * specified callback for each one.
  1085. *
  1086. \***************************************************************************/
  1087. typedef BOOL (*PfnTicketCallback)(DuTicketCopy ticket, ULONG64 pObject, void * pRawData);
  1088. void ForAllTickets(PfnTicketCallback pfnTicketCallback, void * pRawData)
  1089. {
  1090. if (pfnTicketCallback == NULL) {
  1091. return;
  1092. }
  1093. //
  1094. // Prepare to read the value of g_TicketManager->m_arTicketData;
  1095. //
  1096. ULONG64 pTicketManager = EvalExp(VAR(g_TicketManager));
  1097. ULONG ulTicketDataOffset = 0;
  1098. GetFieldOffset(SYM(DuTicketManager), "m_arTicketData", &ulTicketDataOffset);
  1099. InitTypeRead(pTicketManager + ulTicketDataOffset, DuTicketDataArray);
  1100. //
  1101. // Extract the data about the actual DuTicketDataArray since we are here.
  1102. //
  1103. ULONG64 paTicketData = ReadField(m_aT);
  1104. int nSize = (int) ReadField(m_nSize);
  1105. int nAllocSize = (int) ReadField(m_nAllocSize);
  1106. //
  1107. // Walk through the entire array.
  1108. //
  1109. ULONG cbTicketData = GetTypeSize("DuTicketData");
  1110. for (int i = 0; i < nSize; i++) {
  1111. InitTypeRead(paTicketData, DuTicketData);
  1112. //
  1113. // Read the fields of the ticket data.
  1114. //
  1115. ULONG64 pObject = ReadField(pObject);
  1116. WORD idxFree = (WORD) ReadField(idxFree);
  1117. BYTE cUniqueness = (BYTE) ReadField(cUniqueness);
  1118. //
  1119. // Construct the equivalent ticket for this ticket data.
  1120. //
  1121. DuTicketCopy ticket;
  1122. ticket.Index = i;
  1123. ticket.Uniqueness = cUniqueness;
  1124. ticket.Type = 0; // TODO: Get this data
  1125. ticket.Unused = 0;
  1126. if (FALSE == pfnTicketCallback(ticket, pObject, pRawData)) {
  1127. //
  1128. // The callback requested that we bail out early!
  1129. //
  1130. break;
  1131. }
  1132. //
  1133. // Advance to the next element in the array.
  1134. //
  1135. paTicketData += cbTicketData;
  1136. }
  1137. }
  1138. /***************************************************************************\
  1139. *
  1140. * Procedure: DumpAllTicketsCB
  1141. *
  1142. * Callback that can be passed to the ForAllTickets function to dump the
  1143. * ticket data for all tickets in the table.
  1144. *
  1145. \***************************************************************************/
  1146. struct DumpAllTicketsData
  1147. {
  1148. DumpAllTicketsData(bool f) : fVerbose(f), nSize(0), cTickets(0) {}
  1149. bool fVerbose;
  1150. int nSize;
  1151. int cTickets;
  1152. };
  1153. BOOL DumpAllTicketsCB(DuTicketCopy ticket, ULONG64 pObject, void * pRawData)
  1154. {
  1155. DumpAllTicketsData * pData = (DumpAllTicketsData *) pRawData;
  1156. if (pData == NULL) {
  1157. return FALSE;
  1158. }
  1159. if (pObject != NULL || pData->fVerbose) {
  1160. // iSlot cUniqueness pObject
  1161. Print("%4d %4d 0x%p\n", ticket.Index, ticket.Uniqueness, pObject);
  1162. }
  1163. //
  1164. // Count the number of tickets that have a pointer associated with them.
  1165. //
  1166. if (pObject != NULL) {
  1167. pData->cTickets++;
  1168. }
  1169. //
  1170. // Count the number of slots in the table.
  1171. //
  1172. pData->nSize++;
  1173. //
  1174. // Keep going...
  1175. //
  1176. return TRUE;
  1177. }
  1178. /***************************************************************************\
  1179. *
  1180. * Procedure: DumpTicketByTicketCB
  1181. *
  1182. * Callback that can be passed to the ForAllTickets function to dump only
  1183. * the ticket data that matches the given ticket.
  1184. *
  1185. \***************************************************************************/
  1186. struct DumpTicketByTicketData
  1187. {
  1188. DumpTicketByTicketData(DuTicketCopy t) : ticket(t) {}
  1189. DumpTicketByTicketData(DWORD t) : ticket(*((DuTicketCopy*) &t)) {}
  1190. DuTicketCopy ticket;
  1191. };
  1192. BOOL DumpTicketByTicketCB(DuTicketCopy ticket, ULONG64 pObject, void * pRawData)
  1193. {
  1194. DumpTicketByTicketData * pData = (DumpTicketByTicketData *) pRawData;
  1195. if (pData == NULL) {
  1196. return FALSE;
  1197. }
  1198. if (ticket.Index == pData->ticket.Index) {
  1199. if (ticket.Uniqueness != pData->ticket.Uniqueness) {
  1200. Print("Warning: the uniqueness (%d) doesn't match!\n", pData->ticket.Uniqueness);
  1201. }
  1202. Print("iSlot: %d, cUniqueness: %d, pObject: 0x%p\n", ticket.Index, ticket.Uniqueness, pObject);
  1203. //
  1204. // Since the indecies matched, there is no point in continuing.
  1205. //
  1206. return FALSE;
  1207. }
  1208. //
  1209. // The indecies didn't match, so keep going.
  1210. //
  1211. return TRUE;
  1212. }
  1213. /***************************************************************************\
  1214. *
  1215. * Procedure: DumpTicketByUniquenessCB
  1216. *
  1217. * Callback that can be passed to the ForAllTickets function to dump only
  1218. * the ticket data that matches the given uniqueness.
  1219. *
  1220. \***************************************************************************/
  1221. struct DumpTicketByUniquenessData
  1222. {
  1223. DumpTicketByUniquenessData(UINT c) : cUniqueness(c) {}
  1224. UINT cUniqueness;
  1225. };
  1226. BOOL DumpTicketByUniquenessCB(DuTicketCopy ticket, ULONG64 pObject, void * pRawData)
  1227. {
  1228. DumpTicketByUniquenessData * pData = (DumpTicketByUniquenessData *) pRawData;
  1229. if (pData == NULL) {
  1230. return FALSE;
  1231. }
  1232. if (ticket.Uniqueness == pData->cUniqueness) {
  1233. Print("iSlot: %d, cUniqueness: %d, pObject: 0x%p\n", ticket.Index, ticket.Uniqueness, pObject);
  1234. }
  1235. //
  1236. // Keep going...
  1237. //
  1238. return TRUE;
  1239. }
  1240. /***************************************************************************\
  1241. *
  1242. * Procedure: DumpTicketBySlotCB
  1243. *
  1244. * Callback that can be passed to the ForAllTickets function to dump only
  1245. * the ticket data that matches the given slot.
  1246. *
  1247. \***************************************************************************/
  1248. struct DumpTicketBySlotData
  1249. {
  1250. DumpTicketBySlotData(UINT i) : iSlot(i) {}
  1251. UINT iSlot;
  1252. };
  1253. BOOL DumpTicketBySlotCB(DuTicketCopy ticket, ULONG64 pObject, void * pRawData)
  1254. {
  1255. DumpTicketBySlotData * pData = (DumpTicketBySlotData *) pRawData;
  1256. if (pData == NULL) {
  1257. return FALSE;
  1258. }
  1259. if (ticket.Index == pData->iSlot) {
  1260. Print("iSlot: %d, cUniqueness: %d, pObject: 0x%p\n", ticket.Index, ticket.Uniqueness, pObject);
  1261. //
  1262. // Since the indecies matched, there is no point in continuing.
  1263. //
  1264. return FALSE;
  1265. }
  1266. //
  1267. // The indecies didn't match, so keep going.
  1268. //
  1269. return TRUE;
  1270. }
  1271. /***************************************************************************\
  1272. *
  1273. * Procedure: DumpTicketByObjectCB
  1274. *
  1275. * Callback that can be passed to the ForAllTickets function to dump only
  1276. * the ticket data that matches the given object.
  1277. *
  1278. \***************************************************************************/
  1279. struct DumpTicketByObjectData
  1280. {
  1281. DumpTicketByObjectData(ULONG64 p) : pObject(p) {}
  1282. ULONG64 pObject;
  1283. };
  1284. BOOL DumpTicketByObjectCB(DuTicketCopy ticket, ULONG64 pObject, void * pRawData)
  1285. {
  1286. DumpTicketByObjectData * pData = (DumpTicketByObjectData *) pRawData;
  1287. if (pData == NULL) {
  1288. return FALSE;
  1289. }
  1290. if (pObject == pData->pObject) {
  1291. Print("iSlot: %d, cUniqueness: %d, pObject: 0x%p\n", ticket.Index, ticket.Uniqueness, pObject);
  1292. //
  1293. // Since the indecies matched, there is no point in continuing.
  1294. //
  1295. return FALSE;
  1296. }
  1297. //
  1298. // The indecies didn't match, so keep going.
  1299. //
  1300. return TRUE;
  1301. }
  1302. /***************************************************************************\
  1303. *
  1304. * Procedure: Igticket
  1305. *
  1306. * Dumps DUser ticket information
  1307. *
  1308. \***************************************************************************/
  1309. BOOL Igticket(DWORD opts, ULONG64 param1)
  1310. {
  1311. DWORD cbSize;
  1312. int nMsg;
  1313. LPCSTR pszMsgName;
  1314. CHAR szFullMsgName[256];
  1315. const DbgMsgInfo * pdmi = NULL;
  1316. __try {
  1317. //
  1318. // Determine options
  1319. //
  1320. BOOL fTicket = opts & OFLAG(t);
  1321. BOOL fSlot = opts & OFLAG(s);
  1322. BOOL fObject = opts & OFLAG(o);
  1323. BOOL fUniqueness = opts & OFLAG(u);
  1324. BOOL fVerbose = opts & OFLAG(v);
  1325. if (fTicket) {
  1326. DumpTicketByTicketData data((DWORD)param1);
  1327. ForAllTickets(DumpTicketByTicketCB, &data);
  1328. } else if (fSlot) {
  1329. DumpTicketBySlotData data((UINT)param1);
  1330. ForAllTickets(DumpTicketBySlotCB, &data);
  1331. } else if (fObject) {
  1332. DumpTicketByObjectData data(param1);
  1333. ForAllTickets(DumpTicketByObjectCB, &data);
  1334. } else if (fUniqueness) {
  1335. DumpTicketByUniquenessData data((UINT)param1);
  1336. ForAllTickets(DumpTicketByUniquenessCB, &data);
  1337. } else {
  1338. //
  1339. // Just display information about all of the tickets in the table.
  1340. //
  1341. // slot uniq pObject
  1342. Print("iSlot cUniqueness pObject\n");
  1343. Print("---------------------------\n");
  1344. DumpAllTicketsData data(fVerbose ? true : false);
  1345. ForAllTickets(DumpAllTicketsCB, &data);
  1346. Print("Slots: %d, Tickets: %d\n", data.nSize, data.cTickets);
  1347. }
  1348. } __except (CONTINUE) {
  1349. }
  1350. return TRUE;
  1351. }