Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3970 lines
103 KiB

  1. // WDBGDOT.C
  2. //
  3. // This file is effectively a copy of core32\kernel\dbgdot.c that builds it for inclusion
  4. // as part of VDMEXTS.DLL
  5. //
  6. // (C) Copyright Microsoft Corp., 1988-1994
  7. //
  8. // WDEB386 Dot commands
  9. //
  10. // This file and the file dbgdota.asm implement the .W dot commands on
  11. // behalf of wdeb386. W32ParseDotCommand is called to parse and execute
  12. // the dot commands.
  13. //
  14. // *All* memory that is accessed while processing a dot command *must*
  15. // be present. If it is not, a page fault will occur which can, and
  16. // likely will, result in a very large amount of system code being
  17. // executed. This will change the state of the system as it is being
  18. // debugged, and can lead to unexpected, incorrect or fatal behaviour.
  19. //
  20. // The convention used by the .W commands to handle dumping structures
  21. // that reside in not-present memory is to display the not-present
  22. // address in brackets ("[]"). The user may then use the '.MM' command
  23. // to force the memory present if desired (note that this action has
  24. // all of the pitfalls described above), and then reissue the .W command.
  25. //
  26. // All code and data directly associated with the .W commands reside in
  27. // the LOCKCODE and LOCKDATA segments. The InitDotCommand function
  28. // (dbgdota.asm) locks these segments in memory.
  29. //
  30. // Origin: Chicago
  31. //
  32. // Change history:
  33. //
  34. // Date Who Description
  35. // --------- --------- -------------------------------------------------
  36. // 15-Feb-94 JonT Code cleanup and precompiled headers
  37. //
  38. //
  39. // defined to compile the debug support for inclusion in the VDMEXTS.DLL
  40. // debugger extension for MEOW
  41. //
  42. #include <precomp.h>
  43. #pragma hdrstop
  44. #define WOW32_EXTENSIONS 1
  45. #define KERNEL_DOT_COMMANDS 1
  46. #define WOW 1
  47. #undef DEBUG
  48. #include <kernel32.h>
  49. #define dbgprintf PRINTF
  50. #define VerifyMemory(addr,sz) MapDbgAddr(&(addr),sz)
  51. BOOL MapDbgAddr(VOID **ppaddr,ULONG objsz);
  52. #ifdef KERNEL_DOT_COMMANDS
  53. #ifdef WOW32_EXTENSIONS
  54. extern INT WDParseArgStr(LPSZ lpszArgStr, CHAR **argv, INT iMax);
  55. extern INT WDahtoi(LPSZ lpsz);
  56. #endif
  57. VOID KERNENTRY DumpFlags(DWORD flags);
  58. #ifndef WOW32_EXTENSIONS
  59. extern PTCB KERNENTRY GetCurThreadHandle();
  60. extern VOID KERNENTRY PrintName16(DWORD, DWORD);
  61. extern EXCEPTION_DISPOSITION __cdecl ExceptionHandler (
  62. IN struct _EXCEPTION_RECORD *,
  63. IN PVOID,
  64. IN OUT struct _CONTEXT *,
  65. IN OUT PVOID
  66. );
  67. extern int KERNENTRY WDEBGetBuff(PVOID pSrc, PVOID pDst, DWORD dwLen);
  68. #pragma code_seg("LOCKCODE")
  69. #pragma data_seg("LOCKDATA")
  70. // Validate ptdb or ppdb
  71. #define ValidatePTDB(ptdb) (VerifyMemory((ptdb), sizeof(TDB)) && \
  72. ((ptdb)->objBase.typObj == typObjThread))
  73. #define ValidatePPDB(ppdb) (VerifyMemory((ppdb), sizeof(PDB)) && \
  74. ((ppdb)->objBase.typObj == typObjProcess))
  75. // Convert a ring 0 thread handle to a ptdbx
  76. #define ptcb2ptdbx(ptcb) ((PTDBX)*((PULONG)((DWORD)ptcb + thcboffDeb)))
  77. // VWIN32's thread slot offset from ring 0
  78. DWORD thcboffDeb;
  79. #endif // ndef WOW32_EXTENSIONS
  80. //
  81. // Some frequently used strings.
  82. //
  83. char NotSignaled[] = "not signaled";
  84. char Signaled[] = "signaled";
  85. //
  86. // Extended .w help (.w?)
  87. //
  88. // wdeb has maximum printf buffer size of 256 bytes. Therefore, strings
  89. // have to be broken up.
  90. //
  91. char *w32DotCommandExtHelp[] = {
  92. "!k32 W"
  93. " [<expression>]\n\
  94. where <expression> is the address of a win32 object of one of the following\n\
  95. object types:\n\
  96. Thread Process Semaphore Event\n\
  97. Mutex Critical Section Timer Change\n"
  98. #ifndef WOW32_EXTENSIONS
  99. Console Con Scrn Buff "
  100. #endif // ndef WOW32_EXTENSIONS
  101. "\n\
  102. if <expression> is omitted, information on all threads is displayed.\n",
  103. "!k32 WM"
  104. " - Dump module table\n",
  105. "!k32 WMP"
  106. " [ppdb] - Dump module table for process (no ppdb - current process)\n",
  107. "!k32 WP"
  108. " - Dump process list\n",
  109. #ifndef WOW32_EXTENSIONS
  110. "!k32 WC"
  111. " context - Dump context record\n",
  112. "!k32 WE"
  113. " exception - Dump exception record\n",
  114. "!k32 WD"
  115. " [dispatcherContext] - Dump dispatcher context\n"
  116. " Currently active one if no argument\n",
  117. #endif // ndef WOW32_EXTENSIONS
  118. "!k32 WS"
  119. " - Display the status of all ring 3 system critical sections\n",
  120. "!k32 WT[K]"
  121. " [ppdb] - Dump process handle table (no ppdb - current process, K kernel process)\n",
  122. "!k32 WX"
  123. " - Dump memory status\n\n", 0};
  124. //
  125. // All strings must be global in order to get the C compiler to put them
  126. // in the LOCKDATA segment. This means DON'T define any static data within
  127. // a function.
  128. //
  129. // FLASH! The latest version of the compiler (8.00.3148) is putting static,
  130. // non-global data in LOCKDATA also, ie. we can get rid of these ugly global
  131. // strings.
  132. //
  133. char DotError[] = "Invalid !k32 w command\n\n";
  134. char NewLine[] = "\n";
  135. char NotPresentStr[] = "Not present in memory";
  136. char fmt1[] = " waiting threads ptdbx: ";
  137. char fmt2[] = " %08x";
  138. char fmt3[] = " [%08x]";
  139. char fmt3a[] = "\nControl-C cancel\n";
  140. char fmt4[] = "\n\t";
  141. char fmt6[] = "Sem %08x %s";
  142. char fmt8[] = "Event %08x %s";
  143. char fmt9[] = "Change %08x hChangeInt=%08x";
  144. char fmt10[] = "%s Owner=%08x(%x)";
  145. char fmt11[] = "%s";
  146. char fmt13[] = "CritSect %08x Owner=%08x(%x) cCur=%08x cRecur=%08x";
  147. char fmt14[] = "CritSect %08x Unowned cCur=%08x cRecur=%08x";
  148. char fmt16[] = "Thread [%.8x]\n";
  149. char fmt23[] = " all of:";
  150. char fmt24[] = " any of:";
  151. char fmt27[] = "\n\t";
  152. char fmt29[] = "Mutex %08x ";
  153. char fmt31[] = "Object %08x is invalid or not-present\n";
  154. char fmt33[] = "[%08x]";
  155. char fmt40[] = "%s %08x lev=%x ";
  156. char fmt41[] = "Owner=%08x(%x) cCur %08x cRecur=%08x ";
  157. char fmt42[] = "Unowned ";
  158. char fmt42a[] = "Can't read ptdbxOwner ";
  159. char fmt43[] = "%s [%08x]\n";
  160. char fmt44[] = "%s [%08x]\n";
  161. char fmt50[] = "Process [%08x]\n";
  162. char fmt60h[] = "IMTE pmte UCnt Ld BaseAddr FileName\n";
  163. char fmt60i[] = "===================================================\n";
  164. char fmt60[] = " %2x %08x %2d %s %08x %s\n";
  165. char fmt61h[] = " MTE MdRf\n";
  166. char fmt61i[] = "IMTE pmte UCnt UCnt Ld BaseAddr FileName\n";
  167. char fmt61j[] = "========================================================\n";
  168. char fmt61[] = " %2x %08x %2d %2d %s %08x %s\n";
  169. char fmt62[] = "IMTE ??? %s\n";
  170. char fmt70[] = "PDB %08x %s\n";
  171. char fmt71h[] = " IMTE Usg Flags Ld BaseAddr FileName\n";
  172. char fmt71i[] = " ====================================================\n";
  173. char fmt71[] = " %2x %2x %04x %s %08x %s\n";
  174. char fmt72[] = "Current PDB %08x %s\n";
  175. char fmt72a[] = "Cannot get Current PDB\n";
  176. char fmt72b[] = "Cannot get imteMax\n";
  177. char fmt72c[] = "Current PDB %08x does not have a pModExe\n";
  178. char fmt73[] = "no name";
  179. char fmt74[] = "Value specified %08x is not a valid or present process ID\n";
  180. char fmt74a[] = "Value specified %08x is not a valid or present module structure\n";
  181. char fmt75[] = "Handle table of process ID %08x %s\n"
  182. " Handle Object Flags Type\n";
  183. char fmt76[] = " %4x %08x %08x %s (%2x)\n";
  184. char fmt80[] = "Paranoid ring 3 heap walking is now ";
  185. char fmt81[] = "ON\n";
  186. char fmt82[] = "OFF\n";
  187. char fmt83[] = "Stopping on ring 3 memory manager error returns is now ";
  188. char fmt84[] = ".WH doesn't work in the retail build\n";
  189. char* pszObjTypes[] =
  190. {
  191. "Invalid or not present",
  192. "Semaphore",
  193. "Event",
  194. "Mutex",
  195. "Critical Section",
  196. "Timer",
  197. "Process",
  198. "Thread",
  199. "File",
  200. "Change",
  201. "Console",
  202. "IO",
  203. "Console Screen Buffer",
  204. "Mapped file",
  205. "Serial",
  206. "Device IOCtl",
  207. "Pipe",
  208. "Mailslot",
  209. "Toolhelp",
  210. "Socket",
  211. "R0 External Object",
  212. };
  213. #define MAXOBJTYPEINDEX 20
  214. BOOL fDumpHeader = TRUE;
  215. WORD wHeadK16FreeList = 0;
  216. WORD* pwHeadSelman16 = NULL;
  217. BOOL MapDbgAddr(VOID **ppaddr,ULONG objsz)
  218. {
  219. return(FALSE);
  220. }
  221. #if !defined(offsetof)
  222. #define offsetof(s,m) (size_t)&(((s *)0)->m)
  223. #endif
  224. TDB *GetCurrentTdb(VOID)
  225. {
  226. CONTEXT ThreadContext;
  227. LDT_ENTRY dte;
  228. DWORD cb;
  229. TDB *ptdb;
  230. ThreadContext.ContextFlags = CONTEXT_SEGMENTS;
  231. if (!GetThreadContext(hCurrentThread, &ThreadContext)) {
  232. return( NULL );
  233. }
  234. cb = ThreadContext.SegFs;
  235. if (!GetThreadSelectorEntry( hCurrentThread,cb,&dte)) {
  236. return( NULL );
  237. }
  238. cb = (dte.HighWord.Bytes.BaseHi * 0x01000000) + (dte.HighWord.Bytes.BaseMid * 0x00010000) + dte.BaseLow;
  239. if((cb == 0xFFFFFFFF) || (cb == 0))
  240. return(NULL);
  241. cb += offsetof(TIB, pTDB);
  242. try {
  243. READMEM((LPVOID)cb, &ptdb, sizeof(TDB *));
  244. } except (1) {
  245. return(NULL);
  246. }
  247. return(ptdb);
  248. }
  249. BOOL Get16BitMemory(WORD wSelector, WORD wOffset, PVOID pData, ULONG ulSize)
  250. {
  251. LDT_ENTRY dte;
  252. DWORD cb;
  253. HANDLE hThread=hCurrentThread;
  254. // dbgprintf( "Ask to read %08X bytes from %04X:%04X of thread %08x\n",
  255. // ulSize,
  256. // wSelector,
  257. // wOffset,
  258. // hThread);
  259. if (!GetThreadSelectorEntry( hCurrentThread, wSelector, &dte)) {
  260. dbgprintf( "Could not get selector %04X of thread %08x\n",
  261. wSelector,
  262. hThread);
  263. return( FALSE );
  264. }
  265. cb = (dte.HighWord.Bytes.BaseHi * 0x01000000) + (dte.HighWord.Bytes.BaseMid * 0x00010000) + dte.BaseLow;
  266. if((cb == 0xFFFFFFFF) || (cb == 0)) {
  267. dbgprintf( "Could not compute linear of %04X:%04X of thread %08x\n",
  268. wSelector,
  269. wOffset,
  270. hThread);
  271. return(FALSE);
  272. }
  273. cb+=wOffset;
  274. try {
  275. READMEM((LPVOID)cb, pData, ulSize);
  276. } except (1) {
  277. dbgprintf( "Faulted reading %04X:%04X=%08X of thread %08x\n",
  278. cb,
  279. wSelector,
  280. wOffset,
  281. hThread);
  282. return(FALSE);
  283. }
  284. return(TRUE);
  285. }
  286. TDBX *GetCurrentTdbx(VOID)
  287. {
  288. TDB tdb;
  289. TDB *ptdb;
  290. ptdb = GetCurrentTdb();
  291. if(!ptdb) {
  292. return(NULL);
  293. }
  294. try {
  295. READMEM(ptdb, &tdb, sizeof(TDB));
  296. } except (1) {
  297. return(NULL);
  298. }
  299. return(tdb.ptdbx);
  300. }
  301. PDB *GetCurrentPdb(VOID)
  302. {
  303. TDB tdb;
  304. TDB *ptdb;
  305. TIB tib;
  306. ptdb = GetCurrentTdb();
  307. if(!ptdb) {
  308. return(NULL);
  309. }
  310. try {
  311. READMEM(ptdb, &tdb, sizeof(TDB));
  312. } except (1) {
  313. return(NULL);
  314. }
  315. try {
  316. READMEM(tdb.ptib, &tib, sizeof(TIB));
  317. } except (1) {
  318. return(NULL);
  319. }
  320. return(tib.ppdbProc);
  321. }
  322. MTE *GetModuleTableEntry(IMTE imte, MTE *pmtebuf)
  323. {
  324. MTE **pmteModTab = 0;
  325. MTE **pmteModTabEnt;
  326. MTE *pmte;
  327. PVOID pTmp = NULL;
  328. GETEXPRADDR(pTmp, "mekrnl32!pmteModTable");
  329. if(pTmp == NULL)
  330. return(NULL);
  331. try {
  332. READMEM(pTmp, &pmteModTab, sizeof(MTE **));\
  333. } except (1) {
  334. return(NULL);
  335. }
  336. pmteModTabEnt = &(pmteModTab[imte]);
  337. try {
  338. READMEM(pmteModTabEnt, &pmte, sizeof(MTE *));
  339. } except (1) {
  340. return(NULL);
  341. }
  342. try {
  343. READMEM(pmte, pmtebuf, sizeof(MTE));
  344. } except (1) {
  345. return(NULL);
  346. }
  347. return(pmte);
  348. }
  349. /*** PnodGetLstElem - Get an element from a list
  350. **
  351. ** Synopsis
  352. ** NOD * = PnodGetLstElem(plst, id)
  353. **
  354. ** Input:
  355. ** plst - pointer to the list to retrieve from
  356. ** id - indicator for which element to return
  357. **
  358. ** Output:
  359. ** returns a pointer to the specified list element
  360. **
  361. ** Errors:
  362. ** return 0L if result is undefined
  363. **
  364. ** Description:
  365. ** This function will set the current position in the list
  366. ** to the specified element and return a pointer to the element.
  367. */
  368. NOD * KERNENTRY
  369. PnodGetLstElem (LST * plst, NOD * pnodpre, int id)
  370. {
  371. LST lst;
  372. NOD nod;
  373. if(!plst) {
  374. return(NULL);
  375. }
  376. switch (id) {
  377. case idLstGetCur:
  378. case idLstGetLast:
  379. case idLstGetFirst:
  380. try {
  381. READMEM(plst, &lst, sizeof(LST));\
  382. } except (1) {
  383. dbgprintf("\nInvalid List\n");
  384. return(NULL);
  385. }
  386. if(id == idLstGetFirst)
  387. return (lst.pnodHead);
  388. else if(id == idLstGetLast)
  389. return (lst.pnodEnd);
  390. else
  391. return (lst.pnodCur);
  392. break;
  393. case idLstGetNext:
  394. case idLstGetPrev:
  395. if(!pnodpre) {
  396. return(NULL);
  397. }
  398. try {
  399. READMEM(pnodpre, &nod, sizeof(NOD));\
  400. } except (1) {
  401. dbgprintf("\nInvalid List element\n");
  402. return(NULL);
  403. }
  404. if(id == idLstGetNext)
  405. return(nod.pnodNext);
  406. else
  407. return(nod.pnodPrev);
  408. break;
  409. default:
  410. dbgprintf("\nInvalid List request\n");
  411. return(NULL);
  412. break;
  413. }
  414. }
  415. /*** GetObjType
  416. *
  417. * Returns a string indicating the object type
  418. */
  419. char* KERNENTRY
  420. GetObjType(OBJ* pobj)
  421. {
  422. int nObjType;
  423. nObjType = pobj->typObj;
  424. if (nObjType > MAXOBJTYPEINDEX)
  425. nObjType = 0;
  426. return pszObjTypes[nObjType];
  427. }
  428. #ifndef WOW32_EXTENSIONS
  429. extern DWORD* SelmanBuffer;
  430. extern DWORD* pLDT;
  431. /*** ValidatePTCB
  432. *
  433. * Validates the r0 thread handle.
  434. *
  435. * Entry: ptcb - pointer to thread handle
  436. *
  437. * Exit: TRUE if the thread handle is valid
  438. */
  439. BOOL KERNENTRY
  440. ValidatePTCB(PTCB ptcb)
  441. {
  442. _asm mov edi, [ptcb]
  443. _asm or edi, edi
  444. _asm jz invalidtcb
  445. VMMCall(Validate_Thread_Handle);
  446. _asm jc invalidtcb
  447. return(TRUE);
  448. invalidtcb:
  449. return(FALSE);
  450. }
  451. /*** ValidatePTDBX
  452. *
  453. * Validates the ptdbx
  454. *
  455. * Entry: ptdbx - pointer to ptdbx
  456. *
  457. * Exit: TRUE if the thread ptdbx is valid
  458. */
  459. BOOL KERNENTRY
  460. ValidatePTDBX(PTDBX ptdbx)
  461. {
  462. BOOL f;
  463. if((f = VerifyMemory(ptdbx, sizeof(TDBX)))) {
  464. if(ptdbx->tdbxR0ThreadHandle == 0) {
  465. f = ValidatePTDB((PTDB)ptdbx->tdbxThreadHandle);
  466. }
  467. else {
  468. f = ValidatePTCB((PTCB)ptdbx->tdbxR0ThreadHandle);
  469. }
  470. }
  471. return(f);
  472. }
  473. #endif // ndef WOW32_EXTENSIONS
  474. /*** PrintThreads
  475. *
  476. * Worker routine that displays all threads blocked on a specified wait node.
  477. *
  478. * Entry: pwnod - pointer to wait node
  479. *
  480. * Exit: none
  481. */
  482. VOID KERNENTRY
  483. PrintThreads(WNOD *pwnod)
  484. {
  485. WNOD wnod;
  486. TDBX tdbx;
  487. int i = 0;
  488. dbgprintf(NewLine);
  489. try {
  490. READMEM(pwnod, &wnod, sizeof(WNOD));
  491. } except (1) {
  492. dbgprintf(fmt3, pwnod);
  493. dbgprintf(NewLine);
  494. return;
  495. }
  496. if(wnod.ptdbxWait) {
  497. try {
  498. READMEM(wnod.ptdbxWait, &tdbx, sizeof(TDBX));
  499. } except (1) {
  500. wnod.ptdbxWait = NULL;
  501. }
  502. }
  503. if(!wnod.ptdbxWait) {
  504. dbgprintf(fmt3, pwnod);
  505. dbgprintf(NewLine);
  506. return;
  507. }
  508. //
  509. // print "waiting threads ptdbx: "
  510. //
  511. dbgprintf(fmt1);
  512. //
  513. // print the first thread on the current line
  514. //
  515. dbgprintf("%08x(%x) ", wnod.ptdbxWait,
  516. tdbx.tdbxR0ThreadHandle);
  517. pwnod = wnod.pwnCirc;
  518. //
  519. // If there's more threads, print them on the following lines
  520. //
  521. if (pwnod != NULL) {
  522. i = 1;
  523. do {
  524. //
  525. // print a newline every now and then
  526. //
  527. if (i % 6 == 0) {
  528. dbgprintf(fmt27);
  529. }
  530. try {
  531. READMEM(pwnod, &wnod, sizeof(WNOD));
  532. } except (1) {
  533. dbgprintf(fmt3, pwnod);
  534. break;
  535. }
  536. if(wnod.ptdbxWait) {
  537. try {
  538. READMEM(wnod.ptdbxWait, &tdbx, sizeof(TDBX));
  539. } except (1) {
  540. wnod.ptdbxWait = NULL;
  541. }
  542. }
  543. if(!wnod.ptdbxWait) {
  544. dbgprintf(fmt3, pwnod);
  545. break;
  546. }
  547. dbgprintf("%08x(%x) ", wnod.ptdbxWait,
  548. tdbx.tdbxR0ThreadHandle);
  549. ++i;
  550. } while ((pwnod = wnod.pwnCirc) != NULL);
  551. }
  552. //
  553. // print a closing newline
  554. //
  555. dbgprintf(NewLine);
  556. }
  557. /*** PrintThreadsCrst
  558. *
  559. * Prints the waiting threads on a critical section
  560. *
  561. * Entry: pcrst - pointer to critical section object
  562. *
  563. * Exit: none
  564. */
  565. VOID KERNENTRY
  566. PrintThreadsCrst(CRST *pcrst)
  567. {
  568. PTDBX ptdbx = pcrst->ptdbxWait;
  569. TDBX tdbx;
  570. CheckCtrlC(); // flush queue
  571. dbgprintf(NewLine);
  572. if(ptdbx != NULL) {
  573. //
  574. // print "waiting threads ptdbx: "
  575. //
  576. dbgprintf(fmt1);
  577. do {
  578. try {
  579. READMEM(ptdbx, &tdbx, sizeof(TDBX));
  580. } except (1) {
  581. dbgprintf(fmt3, ptdbx);
  582. break;
  583. }
  584. dbgprintf("%08x ", ptdbx);
  585. if(CheckCtrlC()) {
  586. dbgprintf(fmt3a);
  587. break;
  588. }
  589. ptdbx = (PTDBX)tdbx.tdbxWaitNodeList.wnlst_pwnCirc;
  590. } while (ptdbx != NULL && ptdbx != pcrst->ptdbxWait);
  591. } else {
  592. dbgprintf(" no waiting threads");
  593. }
  594. //
  595. // print a closing newline
  596. //
  597. dbgprintf(NewLine);
  598. }
  599. /*** DumpSemaphore
  600. *
  601. * Information on a semaphore object is displayed.
  602. *
  603. * Entry: psem - pointer to semaphore object
  604. *
  605. * Exit: none
  606. */
  607. VOID KERNENTRY
  608. DumpSemaphore(SEM *psem)
  609. {
  610. SEM sem;
  611. char *state;
  612. try {
  613. READMEM(psem, &sem, sizeof(SEM));
  614. } except (1) {
  615. dbgprintf("Could not read SEM structure for %08x\n", psem);
  616. return;
  617. }
  618. //
  619. // Determine the current signaled state of the semaphore.
  620. //
  621. if (sem.cntCur == 0) {
  622. state = NotSignaled;
  623. } else {
  624. state = Signaled;
  625. }
  626. dbgprintf(fmt6, psem, state);
  627. if (sem.pwnWait != NULL) {
  628. PrintThreads(sem.pwnWait);
  629. } else {
  630. dbgprintf(NewLine);
  631. }
  632. }
  633. /*** DumpEvent
  634. *
  635. * Information on a Event object is displayed.
  636. *
  637. * Entry: pevt - pointer to Event object
  638. *
  639. * Exit: none
  640. */
  641. VOID KERNENTRY
  642. DumpEvent(EVT *pevt)
  643. {
  644. EVT evt;
  645. char *state;
  646. try {
  647. READMEM(pevt, &evt, sizeof(EVT));
  648. } except (1) {
  649. dbgprintf("Could not read EVT structure for %08x\n", pevt);
  650. return;
  651. }
  652. //
  653. // Determine the current state of the event.
  654. //
  655. if (evt.cntCur == 0) {
  656. state = NotSignaled;
  657. } else {
  658. state = Signaled;
  659. }
  660. dbgprintf(fmt8, pevt, state);
  661. if (evt.pwnWait != NULL) {
  662. PrintThreads(evt.pwnWait);
  663. } else {
  664. dbgprintf(NewLine);
  665. }
  666. }
  667. /*** DumpMutext
  668. *
  669. * Information on a mutext object is displayed.
  670. *
  671. * Entry: pmutx - pointer to mutext object
  672. *
  673. * Exit: none
  674. */
  675. VOID KERNENTRY
  676. DumpMutex(MUTX *pmutx)
  677. {
  678. MUTX mutx;
  679. TDBX tdbx;
  680. try {
  681. READMEM(pmutx, &mutx, sizeof(MUTX));
  682. } except (1) {
  683. dbgprintf("Could not read MUTX structure for %08x\n", pmutx);
  684. return;
  685. }
  686. dbgprintf(fmt29, pmutx);
  687. //
  688. // Display the mutex's state and owner if it has one.
  689. //
  690. if (mutx.cntCur <= 0) {
  691. if(mutx.ptdbxOwner) {
  692. try {
  693. READMEM(mutx.ptdbxOwner, &tdbx, sizeof(TDBX));
  694. } except (1) {
  695. tdbx.tdbxR0ThreadHandle = 0;
  696. }
  697. } else {
  698. tdbx.tdbxR0ThreadHandle = 0;
  699. }
  700. dbgprintf(fmt10, NotSignaled, mutx.ptdbxOwner,
  701. tdbx.tdbxR0ThreadHandle);
  702. } else {
  703. dbgprintf(fmt11, Signaled);
  704. }
  705. if (mutx.pwnWait != NULL) {
  706. PrintThreads(mutx.pwnWait);
  707. } else {
  708. dbgprintf(NewLine);
  709. }
  710. }
  711. /*** DumpCritSect
  712. *
  713. * Information on a critical section object is displayed.
  714. *
  715. * Entry: pcrst - pointer to critical section object
  716. *
  717. * Exit: none
  718. */
  719. VOID KERNENTRY
  720. DumpCritSect(CRST *pcrst)
  721. {
  722. CRST crst;
  723. TDBX tdbx;
  724. CRST *pcrstWait;
  725. CRST crstWait;
  726. try {
  727. READMEM(pcrst, &crst, sizeof(CRST));
  728. } except (1) {
  729. dbgprintf("Could not read CRST structure for %08x\n", pcrst);
  730. return;
  731. }
  732. // if there is no ptr in the ptdbxWait field, we can assume this is an
  733. // internal critical section
  734. if (crst.ptdbxWait) {
  735. pcrstWait = (CRST *)crst.ptdbxWait;
  736. try {
  737. READMEM(pcrstWait, &crstWait, sizeof(CRST));
  738. } except (1) {
  739. crstWait.typObj = 0;
  740. }
  741. if(crstWait.typObj == typObjCrst) {
  742. pcrst = pcrstWait;
  743. try {
  744. READMEM(pcrst, &crst, sizeof(CRST));
  745. } except (1) {
  746. dbgprintf("Could not read CRST structure for %08x\n", pcrst);
  747. return;
  748. }
  749. }
  750. }
  751. //
  752. // Display the critical section's owner if it has one.
  753. //
  754. if (crst.cntCur <= 0) {
  755. if(crst.ptdbxOwner) {
  756. try {
  757. READMEM(crst.ptdbxOwner, &tdbx, sizeof(TDBX));
  758. } except (1) {
  759. tdbx.tdbxR0ThreadHandle = 0;
  760. }
  761. } else {
  762. tdbx.tdbxR0ThreadHandle = 0;
  763. }
  764. dbgprintf(fmt13, pcrst, crst.ptdbxOwner,
  765. tdbx.tdbxR0ThreadHandle,
  766. crst.cntCur, crst.cntRecur);
  767. } else {
  768. dbgprintf(fmt14, pcrst, crst.cntCur, crst.cntRecur);
  769. }
  770. PrintThreadsCrst(&crst);
  771. }
  772. VOID KERNENTRY
  773. DumpTDBX(PTDBX pTDBX)
  774. {
  775. TDBX tdbx;
  776. DWORD flags;
  777. try {
  778. READMEM(pTDBX, &tdbx, sizeof(TDBX));
  779. } except (1) {
  780. dbgprintf("TDBX invalid");
  781. return;
  782. }
  783. dbgprintf(" ptdbx: %08x\n", pTDBX);
  784. dbgprintf(" CntUses: %8x\n", tdbx.tdbxCntUses);
  785. dbgprintf(" R0ThreadHandle: %8x\n", tdbx.tdbxR0ThreadHandle);
  786. dbgprintf(" VxdMutexTry: %8x\n", tdbx.tdbxVxDMutexTry);
  787. dbgprintf(" VxdMutexGrant: %8x\n", tdbx.tdbxVxDMutexGrant);
  788. dbgprintf(" ContextHandle: %8x\n", tdbx.tdbxContextHandle);
  789. dbgprintf(" TimeOutHandle: %8x\n", tdbx.tdbxTimeOutHandle);
  790. dbgprintf(" WakeParam: %8x\n", tdbx.tdbxWakeParam);
  791. dbgprintf(" BlockHandle: %8x\n", tdbx.tdbxBlockHandle);
  792. dbgprintf(" BlockState: %8x\n", tdbx.tdbxBlockState);
  793. dbgprintf(" Wait node list: %8x\n", tdbx.tdbxWaitNodeList);
  794. dbgprintf(" SuspendCount: %8x\n", tdbx.tdbxSuspendCount);
  795. dbgprintf(" SuspendHandle: %8x\n", tdbx.tdbxSuspendHandle);
  796. dbgprintf(" MustCpltCount: %8x\n", tdbx.tdbxMustCpltCount);
  797. flags = tdbx.tdbxWaitExFlags;
  798. dbgprintf(" WaitExFlags: %08x ", flags);
  799. if(flags & TDBX_WAITEXBIT_MASK)
  800. dbgprintf("WAITEXBIT ");
  801. if(flags & TDBX_WAITACKBIT_MASK)
  802. dbgprintf("WAITACKBIT ");
  803. if(flags & TDBX_SUSPEND_APC_PENDING_MASK)
  804. dbgprintf("SUSPEND_APC_PENDING ");
  805. if(flags & TDBX_SUSPEND_TERMINATED_MASK)
  806. dbgprintf("SUSPEND_TERMINATED ");
  807. if(flags & TDBX_BLOCKED_FOR_TERMINATION_MASK)
  808. dbgprintf("BLOCKED_FOR_TERMINATION ");
  809. if(flags & TDBX_EMULATE_NPX_MASK)
  810. dbgprintf("EMULATE_NPX ");
  811. if(flags & TDBX_WIN32_NPX_MASK)
  812. dbgprintf("WIN32_NPX ");
  813. if(flags & TDBX_EXTENDED_HANDLES_MASK)
  814. dbgprintf("EXTENDED_HANDLES ");
  815. if(flags & TDBX_FROZEN_MASK)
  816. dbgprintf("FROZEN ");
  817. if(flags & TDBX_DONT_FREEZE_MASK)
  818. dbgprintf("DONT_FREEZE ");
  819. if(flags & TDBX_DONT_UNFREEZE_MASK)
  820. dbgprintf("DONT_UNFREEZE ");
  821. if(flags & TDBX_DONT_TRACE_MASK)
  822. dbgprintf("DONT_TRACE ");
  823. if(flags & TDBX_STOP_TRACING_MASK)
  824. dbgprintf("STOP_TRACING ");
  825. if(flags & TDBX_WAITING_FOR_CRST_SAFE_MASK)
  826. dbgprintf("WAITING_FOR_CRST_SAFE ");
  827. if(flags & TDBX_CRST_SAFE_MASK)
  828. dbgprintf("CRST_SAFE ");
  829. if(flags & TDBX_THREAD_NOT_INIT_MASK)
  830. dbgprintf("THREAD_NOT_INIT ");
  831. if(flags & TDBX_BLOCK_TERMINATE_APC_MASK)
  832. dbgprintf("BLOCK_TERMINATE_APC ");
  833. dbgprintf("\n");
  834. dbgprintf(" SyncWaitCount: %8x\n", tdbx.tdbxSyncWaitCount);
  835. dbgprintf(" QueuedSyncAPCs: %8x\n", tdbx.tdbxQueuedSyncAPCs);
  836. dbgprintf(" UserAPCList: %8x\n", tdbx.tdbxUserAPCList);
  837. dbgprintf(" KernAPCList: %8x\n", tdbx.tdbxKernAPCList);
  838. dbgprintf(" pPMPSPSelector: %08x\n", tdbx.tdbxpPMPSPSelector);
  839. dbgprintf(" BlockedOnID: %8x\n", tdbx.tdbxBlockedOnID);
  840. dbgprintf(" TraceRefData: %8x\n", tdbx.tdbxTraceRefData);
  841. dbgprintf(" TraceCallBack: %8x\n", tdbx.tdbxTraceCallBack);
  842. dbgprintf(" TraceOutLastCS: %8.4x\n", tdbx.tdbxTraceOutLastCS);
  843. dbgprintf("TraceEventHandle: %8.4x\n", tdbx.tdbxTraceEventHandle);
  844. dbgprintf(" K16PDBSel: %8.4x\n", tdbx.tdbxK16PDB);
  845. dbgprintf(" DosPDBSeg: %8.4x\n", tdbx.tdbxDosPDBSeg);
  846. dbgprintf(" ExceptionCount: %8.2x\n", tdbx.tdbxExceptionCount);
  847. dbgprintf(" SavedIrql: %8.2x\n", tdbx.tdbxSavedIrql);
  848. dbgprintf(" SavedIrqlCount: %8.2x\n", tdbx.tdbxSavedIrqlCount);
  849. dbgprintf(" K16TDB: %8.4x\n", tdbx.tdbxK16Task);
  850. if(tdbx.tdbxK16Task) {
  851. TDB16 tdb16;
  852. if (Get16BitMemory(tdbx.tdbxK16Task, 0, &tdb16, sizeof(TDB16))) {
  853. dbgprintf(" Task16 SSSP: %04x:%04x\n",tdb16.TDB_taskSS,tdb16.TDB_taskSP);
  854. dbgprintf(" Task16 Event Counter: %4x\n",tdb16.TDB_nEvents);
  855. dbgprintf(" Task16 Priority : %4x\n",tdb16.TDB_priority);
  856. dbgprintf(" Task16 Flags: %02x ",tdb16.TDB_flags);
  857. if(tdb16.TDB_flags & TDBF_CACHECHECK)
  858. dbgprintf("CACHECHK ");
  859. if(tdb16.TDB_flags & TDBF_NEWTASK)
  860. dbgprintf("NOT_SCHED_YET ");
  861. if(tdb16.TDB_flags & TDBF_KERNEL32)
  862. dbgprintf("K32 ");
  863. if(tdb16.TDB_flags & TDBF_HOOKINT21)
  864. dbgprintf("HOOK_I21 ");
  865. if(tdb16.TDB_flags & TDBF_HOOKINT2F)
  866. dbgprintf("HOOK_I2F ");
  867. dbgprintf("\n");
  868. dbgprintf(" Task16 WinVer: %4x\n",tdb16.TDB_ExpWinVer);
  869. dbgprintf(" Task16 hModule: %4x\n",tdb16.TDB_Module);
  870. dbgprintf(" Task16 TDBParent: %4x\n",tdb16.TDB_Parent);
  871. dbgprintf(" Task16 Win32 Thrdhnd: %8x\n",tdb16.TDB_ThreadHandle);
  872. dbgprintf(" Drive: %4x\n",tdb16.TDB_Drive);
  873. dbgprintf(" Old Directory: %s\n" ,tdb16.TDB_Directory);
  874. dbgprintf(" LFN Directory: %s\n" ,tdb16.TDB_LFNDirectory);
  875. } else {
  876. dbgprintf(" Cannot fetch TDB16 memory\n");
  877. }
  878. }
  879. }
  880. /*** DumpThread
  881. *
  882. * Information on a specified thread is displayed. Thread handle, thread id,
  883. * process id, exe name, blocked/ready status, and object(s) blocked on if
  884. * appropriate is displayed.
  885. *
  886. * Entry: ptdb - pointer to tdb (or NULL)
  887. * fFullDump - if TRUE, dump all the thread's tdb, tdbx info
  888. *
  889. * Exit: none
  890. */
  891. VOID KERNENTRY
  892. DumpThread(PTDB ptdb, BOOL fFullDump)
  893. {
  894. int i;
  895. PTDB ptdbSvc;
  896. PTDB ptdbFault;
  897. PTDB ptdbMEOWCreator;
  898. WNOD *pwnod;
  899. WNOD *pwnod2;
  900. WNOD wnod;
  901. MTE *pmte;
  902. MTE mte;
  903. DWORD flags;
  904. PPDB ppdb = NULL;
  905. PDB pdb;
  906. TDB tdb;
  907. PTDBX ptdbx = NULL;
  908. TDBX tdbx;
  909. LPVOID pTmp;
  910. BOOL fTDBXValid = TRUE;
  911. BOOL fTDBValid = FALSE;
  912. BOOL fPDBValid = TRUE;
  913. PBYTE p, pTop;
  914. BYTE b;
  915. WORD wStackSize;
  916. TIB tib;
  917. //
  918. // Validate everything
  919. //
  920. try {
  921. READMEM(ptdb, &tdb, sizeof(TDB));
  922. } except (1) {
  923. dbgprintf("Invalid Thread %08x\n",ptdb);
  924. return;
  925. }
  926. if(tdb.objBase.typObj != typObjThread) {
  927. dbgprintf("Invalid Thread %08x\n",ptdb);
  928. return;
  929. }
  930. fTDBValid = TRUE;
  931. ptdbx = tdb.ptdbx;
  932. try {
  933. READMEM(ptdbx, &tdbx, sizeof(TDBX));
  934. } except (1) {
  935. fTDBXValid = FALSE;
  936. }
  937. ppdb = (PPDB)tdbx.tdbxProcessHandle;
  938. try {
  939. READMEM(ppdb, &pdb, sizeof(PDB));
  940. } except (1) {
  941. fPDBValid = FALSE;
  942. }
  943. if(pdb.objBase.typObj != typObjProcess) {
  944. fPDBValid = FALSE;
  945. }
  946. //
  947. // Print header
  948. //
  949. if(fDumpHeader) {
  950. dbgprintf(" ptdb ppdb ptdbx NTID Tr Gt Stck tdb name state\n");
  951. // * xxxxxxxx xxxxxxxx xxxxxxxx xxxx xx xx xxxx xxxx ssssssss.sss block
  952. fDumpHeader = FALSE;
  953. }
  954. //
  955. // Print * for current thread
  956. //
  957. if (ptdb == GetCurrentTdb()) {
  958. dbgprintf("*");
  959. } else {
  960. dbgprintf(" ");
  961. }
  962. if (fTDBValid) {
  963. try {
  964. READMEM(tdb.ptib, &tib, sizeof(TIB));
  965. } except (1) {
  966. tib.pvStackUserLimit=NULL;
  967. }
  968. pTop=tib.pvStackUserLimit;
  969. if (pTop>(PBYTE)0x01000000) {
  970. wStackSize=0xBAD2;
  971. for (p=pTop-MEOW_BOP_STACK_SIZE;p<pTop;p++) {
  972. try {
  973. READMEM(p, &b, 1);
  974. } except (1) {
  975. wStackSize=0xBAD;
  976. break;
  977. }
  978. if (b!=MEOW_BOP_STACK_FILL) {
  979. wStackSize=(WORD)(pTop-p);
  980. break;
  981. }
  982. }
  983. } else {
  984. wStackSize=0x0;
  985. }
  986. } else {
  987. wStackSize=0xBAD1;
  988. }
  989. //
  990. // Print the thread id, ptdb, ppdb ring 0 thread handle, 16 bit tdb
  991. //
  992. dbgprintf(" %08x %08x %08x %04x %02x %02x %04x %04x",
  993. ptdb,
  994. ppdb,
  995. ptdbx,
  996. fTDBValid ? tdb.R0ThreadHandle : 0xBAD1,
  997. fTDBXValid ? (BYTE)tdbx.tdbxVxDMutexTry : 0xBD,
  998. fTDBXValid ? (BYTE)tdbx.tdbxVxDMutexGrant : 0xBD,
  999. wStackSize,
  1000. fTDBXValid ? tdbx.tdbxK16Task : 0xBAD5
  1001. );
  1002. //
  1003. // Try to get the name of the exe file.
  1004. //
  1005. if(fPDBValid) {
  1006. if(pdb.flFlags & fWin16Process) {
  1007. //
  1008. // This thread belongs to a 16-bit process.
  1009. //
  1010. if(fTDBXValid && tdbx.tdbxK16Task) {
  1011. char mname[9];
  1012. if (Get16BitMemory(tdbx.tdbxK16Task, offsetof(TDB16, TDB_ModName), &mname, 8)) {
  1013. mname[8]='\0';
  1014. dbgprintf(" %-8.8s(16)",mname);
  1015. } else {
  1016. dbgprintf(" %8x(16)",tdbx.tdbxK16Task);
  1017. }
  1018. } else {
  1019. dbgprintf(" Unknown(16) ");
  1020. }
  1021. } else {
  1022. //
  1023. // This is a 32-bit process.
  1024. //
  1025. pTmp = NULL;
  1026. GETEXPRADDR(pTmp, "mekrnl32!ptdbFault");
  1027. if(pTmp == NULL) {
  1028. ptdbFault = NULL;
  1029. } else {
  1030. try {
  1031. READMEM(pTmp, &ptdbFault, sizeof(PTDB));\
  1032. } except (1) {
  1033. ptdbFault = NULL;
  1034. }
  1035. }
  1036. pTmp = NULL;
  1037. GETEXPRADDR(pTmp, "mekrnl32!ptdbSvc");
  1038. if(pTmp == NULL) {
  1039. ptdbSvc = NULL;
  1040. } else {
  1041. try {
  1042. READMEM(pTmp, &ptdbSvc, sizeof(PTDB));\
  1043. } except (1) {
  1044. ptdbSvc = NULL;
  1045. }
  1046. }
  1047. pTmp = NULL;
  1048. GETEXPRADDR(pTmp, "mekrnl32!ptdbMEOWCreator");
  1049. if(pTmp == NULL) {
  1050. ptdbMEOWCreator = NULL;
  1051. } else {
  1052. try {
  1053. READMEM(pTmp, &ptdbMEOWCreator, sizeof(PTDB));\
  1054. } except (1) {
  1055. ptdbMEOWCreator = NULL;
  1056. }
  1057. }
  1058. if(fTDBValid && ptdbFault &&
  1059. (ptdb == ptdbFault)) {
  1060. dbgprintf(" Fault Thread");
  1061. } else if (fTDBValid && ptdbSvc &&
  1062. (ptdb == ptdbSvc)) {
  1063. dbgprintf(" Krnl Service");
  1064. } else if (fTDBValid && ptdbMEOWCreator &&
  1065. (ptdb == ptdbMEOWCreator)) {
  1066. dbgprintf(" MEOW Creator");
  1067. } else {
  1068. //
  1069. // Verify the address of the mte table
  1070. //
  1071. char mname[13];
  1072. pmte = GetModuleTableEntry(pdb.imte,&mte);
  1073. if(pmte) {
  1074. pTmp = mte.szName;
  1075. try {
  1076. READMEM(pTmp, mname, 12);\
  1077. } except (1) {
  1078. mname[0] = ' ';
  1079. mname[1] = '?';
  1080. mname[2] = '?';
  1081. mname[3] = '?';
  1082. mname[4] = '\0';
  1083. }
  1084. for(i = 0; i<12;i++) {
  1085. if(mname[i] == '\0') {
  1086. mname[i] = ' ';
  1087. break;
  1088. }
  1089. }
  1090. for( ; i<12;i++) {
  1091. mname[i] = ' ';
  1092. }
  1093. mname[12] = '\0';
  1094. dbgprintf(" %s", mname);
  1095. } else {
  1096. dbgprintf(" Unknown(32) ");
  1097. }
  1098. }
  1099. }
  1100. } else {
  1101. pTmp = NULL;
  1102. GETEXPRADDR(pTmp, "mekrnl32!ptdbFault");
  1103. if(pTmp == NULL) {
  1104. ptdbFault = NULL;
  1105. } else {
  1106. try {
  1107. READMEM(pTmp, &ptdbFault, sizeof(PTDB));\
  1108. } except (1) {
  1109. ptdbFault = NULL;
  1110. }
  1111. }
  1112. pTmp = NULL;
  1113. GETEXPRADDR(pTmp, "mekrnl32!ptdbSvc");
  1114. if(pTmp == NULL) {
  1115. ptdbSvc = NULL;
  1116. } else {
  1117. try {
  1118. READMEM(pTmp, &ptdbSvc, sizeof(PTDB));\
  1119. } except (1) {
  1120. ptdbSvc = NULL;
  1121. }
  1122. }
  1123. pTmp = NULL;
  1124. GETEXPRADDR(pTmp, "mekrnl32!ptdbMEOWCreator");
  1125. if(pTmp == NULL) {
  1126. ptdbMEOWCreator = NULL;
  1127. } else {
  1128. try {
  1129. READMEM(pTmp, &ptdbMEOWCreator, sizeof(PTDB));\
  1130. } except (1) {
  1131. ptdbMEOWCreator = NULL;
  1132. }
  1133. }
  1134. if(fTDBValid && ptdbFault &&
  1135. (ptdb == ptdbFault)) {
  1136. dbgprintf(" Fault Thread");
  1137. } else if (fTDBValid && ptdbSvc &&
  1138. (ptdb == ptdbSvc)) {
  1139. dbgprintf(" Krnl Service");
  1140. } else if (fTDBValid && ptdbMEOWCreator &&
  1141. (ptdb == ptdbMEOWCreator)) {
  1142. dbgprintf(" MEOW Creator");
  1143. } else {
  1144. dbgprintf(" No PDB ");
  1145. }
  1146. }
  1147. //
  1148. // print the current blocked/ready status of the thread.
  1149. //
  1150. if(fTDBXValid) {
  1151. BOOL fNodOk;
  1152. if(tdbx.tdbxWaitNodeList.wnlst_pwnCirc == NULL) {
  1153. BOOL fReady = TRUE;
  1154. //
  1155. // not blocked on any win32 object
  1156. //
  1157. if(tdbx.tdbxWaitExFlags & TDBX_FROZEN_MASK) {
  1158. fReady = FALSE;
  1159. dbgprintf(" frozen");
  1160. } else if(tdbx.tdbxSuspendCount > 0) {
  1161. fReady = FALSE;
  1162. dbgprintf(" suspnd");
  1163. }
  1164. if((LONG)tdbx.tdbxBlockState < 0) {
  1165. if(tdbx.tdbxWaitNodeList.wnlst_flFlags & fWaitCrst) {
  1166. dbgprintf(" blked:Crit");
  1167. }
  1168. else {
  1169. // blocked by something
  1170. dbgprintf(" blked BlkHnd:%08x",tdbx.tdbxBlockHandle);
  1171. }
  1172. } else {
  1173. // not blocked
  1174. if(tdbx.tdbxWaitExFlags & TDBX_BLOCKED_FOR_TERMINATION_MASK) {
  1175. dbgprintf(" blk trm");
  1176. }
  1177. else if(tdbx.tdbxBlockedOnID != 0) {
  1178. dbgprintf(" blkid: %08x", tdbx.tdbxBlockedOnID);
  1179. }
  1180. else if(tdbx.tdbxVxDBlockOnIDID != 0) {
  1181. dbgprintf(" VxDblkid: %08x", tdbx.tdbxVxDBlockOnIDID);
  1182. }
  1183. else if(fReady) {
  1184. if ((LONG)tdbx.tdbxBlockState > 0) {
  1185. dbgprintf(" ready wp");
  1186. } else {
  1187. dbgprintf(" ready nwp");
  1188. }
  1189. }
  1190. }
  1191. dbgprintf("\n");
  1192. }
  1193. else {
  1194. //
  1195. // blocked on at least one object
  1196. //
  1197. dbgprintf(" blked: ");
  1198. // If blocked on a critical section
  1199. if(tdbx.tdbxWaitNodeList.wnlst_flFlags & fWaitCrst) {
  1200. dbgprintf("Crit");
  1201. } else {
  1202. fNodOk = TRUE;
  1203. // Blocked on an semaphore, mutex or event
  1204. pwnod = tdbx.tdbxWaitNodeList.wnlst_pwnCirc;
  1205. try {
  1206. READMEM(pwnod, &wnod, sizeof(WNOD));
  1207. } except (1) {
  1208. fNodOk = FALSE;
  1209. }
  1210. if(fNodOk) {
  1211. dbgprintf("\n\t %08x", wnod.pobjWait);
  1212. pwnod2 = wnod.pwnNext;
  1213. if((pwnod2 != pwnod) &&
  1214. (pwnod2 != tdbx.tdbxWaitNodeList.wnlst_pwnCirc)) {
  1215. //
  1216. // blocked on at least two objects. Drop down a line and
  1217. // print the remaining objects.
  1218. //
  1219. CheckCtrlC(); // Flush queue
  1220. do {
  1221. pwnod = pwnod2;
  1222. //
  1223. // print a newline every now and then
  1224. //
  1225. dbgprintf("\n");
  1226. dbgprintf("\t");
  1227. try {
  1228. READMEM(pwnod, &wnod, sizeof(WNOD));
  1229. } except (1) {
  1230. dbgprintf(fmt3, pwnod);
  1231. break;
  1232. }
  1233. dbgprintf(fmt2, wnod.pobjWait);
  1234. if(CheckCtrlC()) {
  1235. break;
  1236. }
  1237. pwnod2 = wnod.pwnNext;
  1238. } while( (pwnod2 != pwnod) &&
  1239. (pwnod2 != tdbx.tdbxWaitNodeList.wnlst_pwnCirc));
  1240. }
  1241. } else {
  1242. //
  1243. // not-present object
  1244. //
  1245. dbgprintf(fmt33, pwnod);
  1246. }
  1247. }
  1248. dbgprintf("\n");
  1249. }
  1250. } else {
  1251. dbgprintf(" Unknown\n");
  1252. }
  1253. // If we're not doing a full dump, bail out
  1254. if(!fFullDump)
  1255. return;
  1256. if(fTDBValid) {
  1257. DWORD dwIdObsfucator;
  1258. TIB *ptib;
  1259. TIB tib;
  1260. pTmp = NULL;
  1261. GETEXPRADDR(pTmp, "mekrnl32!dwIdObsfucator");
  1262. if(pTmp == NULL) {
  1263. dwIdObsfucator = 0;
  1264. } else {
  1265. try {
  1266. READMEM(pTmp, &dwIdObsfucator, sizeof(DWORD));\
  1267. } except (1) {
  1268. dwIdObsfucator = 0;
  1269. }
  1270. }
  1271. ptib = tdb.ptib;
  1272. try {
  1273. READMEM(ptib, &tib, sizeof(TIB));
  1274. } except (1) {
  1275. ptib = NULL;
  1276. }
  1277. // Display useful TDB information
  1278. if (dwIdObsfucator) {
  1279. dbgprintf(" Id: %08x\n", ((DWORD)(ptdb)) ^ dwIdObsfucator);
  1280. }
  1281. dbgprintf(" Obj Type: %2x %s\n", tdb.objBase.typObj, GetObjType((OBJ*)&tdb));
  1282. dbgprintf(" Obj Ref count: %4x\n", tdb.objBase.cntUses);
  1283. if(ptib) {
  1284. dbgprintf(" pvExcept: %8x\n", tib.pvExcept);
  1285. dbgprintf(" Top of stack: %8x\n", tib.pvStackUserLimit);
  1286. dbgprintf(" Base of stack: %8x\n", tib.pvStackUser);
  1287. dbgprintf(" K16 TDB: %8.4x\n", tib.hTaskK16);
  1288. dbgprintf(" Stack sel16: %8.4x\n", tib.ss16);
  1289. dbgprintf(" Selman list: %8x\n", tib.pvFirstDscr);
  1290. dbgprintf(" User pointer: %8x\n", tib.pvArbitraryUserPointer);
  1291. dbgprintf(" pTIB: %08x\n", tib.ptibSelf);
  1292. dbgprintf(" TIB flags: %8.4x ", tib.flags);
  1293. if(tib.flags & TIBF_WIN32)
  1294. dbgprintf("TIBF_WIN32 ");
  1295. if(tib.flags & TIBF_TRAP)
  1296. dbgprintf("TIBF_TRAP ");
  1297. dbgprintf("\n");
  1298. dbgprintf("Win16Mutex count: %8.4x\n", tib.Win16LockVCount);
  1299. dbgprintf(" Debug context: %8x\n", tib.pcontextDeb);
  1300. dbgprintf(" Ptr to cur pri: %08x", tib.pCurPri);
  1301. pTmp = (LPVOID)tib.pCurPri;
  1302. try {
  1303. READMEM(pTmp, &dwIdObsfucator, sizeof(DWORD));\
  1304. } except (1) {
  1305. dwIdObsfucator = 0xFFFFFFFF;
  1306. }
  1307. if (dwIdObsfucator != 0xFFFFFFFF)
  1308. dbgprintf(" pri: %x", dwIdObsfucator);
  1309. dbgprintf("\n");
  1310. dbgprintf(" Message queue: %8x\n", tib.dwMsgQueue);
  1311. dbgprintf(" pTLS array: %8x\n", tib.ThreadLocalStoragePointer);
  1312. }
  1313. flags = tdb.flFlags;
  1314. dbgprintf(" Flags: %08x ", flags);
  1315. if(flags & fCreateThreadEvent)
  1316. dbgprintf("fCreateThreadEvent ");
  1317. if(flags & fCancelExceptionAbort)
  1318. dbgprintf("fCancelExceptionAbort ");
  1319. if(flags & fOnTempStack)
  1320. dbgprintf("fOnTempStack ");
  1321. if(flags & fGrowableStack)
  1322. dbgprintf("fGrowableStack ");
  1323. if(flags & fDelaySingleStep)
  1324. dbgprintf("fDelaySingleStep ");
  1325. if(flags & fOpenExeAsImmovableFile)
  1326. dbgprintf("fOpenExeAsImmovableFile ");
  1327. if(flags & fCreateSuspended)
  1328. dbgprintf("fCreateSuspended ");
  1329. if(flags & fStackOverflow)
  1330. dbgprintf("fStackOverflow ");
  1331. if(flags & fNestedCleanAPCs)
  1332. dbgprintf("fNestedCleanAPCs ");
  1333. if(flags & fWasOemNowAnsi)
  1334. dbgprintf("fWasOemNowAnsi ");
  1335. if(flags & fOKToSetThreadOem)
  1336. dbgprintf("fOKToSetThreadOem ");
  1337. DumpFlags(flags);
  1338. dbgprintf(" Status: %8x\n", tdb.dwStatus);
  1339. dbgprintf(" TIB sel: %8.4x\n", tdb.selTib);
  1340. dbgprintf(" Emulator sel: %8.4x\n", tdb.selEmul);
  1341. dbgprintf(" Handle count: %8.2x\n", tdb.cntHandles);
  1342. dbgprintf(" APISuspendCount: %8x\n", tdb.dwAPISuspendCount);
  1343. dbgprintf(" R0 hThread: %8x\n", tdb.R0ThreadHandle);
  1344. dbgprintf(" Stack base: %8x\n", tdb.pStackBase);
  1345. dbgprintf(" Emulator data: %8x\n", tdb.pvEmulData);
  1346. dbgprintf(" Debugger CB: %8x\n", tdb.tdb_pderDebugger);
  1347. dbgprintf(" Debugger TH: %8x\n", tdb.tdb_ihteDebugger);
  1348. dbgprintf(" Context: %8x\n", tdb.tdb_pcontext);
  1349. dbgprintf(" Except16 list: %8x\n", tdb.pvExcept16);
  1350. dbgprintf(" Thunk connect: %8x\n", tdb.pvThunkConnectList);
  1351. dbgprintf(" Neg stack base: %8x\n", tdb.dwCurNegBase);
  1352. dbgprintf(" Current SS: %8x\n", tdb.dwCurSS);
  1353. dbgprintf(" SS Table: %8x\n", tdb.pvMapSSTable);
  1354. dbgprintf(" Thunk SS16: %8x\n", tdb.wMacroThunkSelStack16);
  1355. dbgprintf(" hTerminate: %8x\n", tdb.hTerminate);
  1356. dwIdObsfucator = (DWORD)ptdb;
  1357. dwIdObsfucator += offsetof(TDB, TlsArray[0]);
  1358. dbgprintf(" TLS Array: %8x\n", dwIdObsfucator);
  1359. dbgprintf(" Delta priority: %8x\n", tdb.tpDeltaPri);
  1360. dbgprintf(" Error Code: %8x\n", tdb.ercError);
  1361. dbgprintf(" pCreateData16: %8x", tdb.pCreateData16);
  1362. if(tdb.pCreateData16) {
  1363. CREATEDATA16 crtd16;
  1364. pTmp = (LPVOID)tdb.pCreateData16;
  1365. try {
  1366. READMEM(pTmp, &crtd16, sizeof(CREATEDATA16));\
  1367. } except (1) {
  1368. pTmp = NULL;
  1369. }
  1370. if(pTmp) {
  1371. dbgprintf(" pProcessInfo: %8x",crtd16.pProcessInfo);
  1372. dbgprintf(" pStartupInfo: %8x",crtd16.pStartupInfo);
  1373. }
  1374. }
  1375. dbgprintf("\n");
  1376. dbgprintf(" wSSBig: %8x\n", (DWORD)(tdb.wSSBig));
  1377. dbgprintf(" lp16SwitchRec: %8x:%x\n",
  1378. ((DWORD)(tdb.lp16SwitchRec)) >> 16,
  1379. ((DWORD)(tdb.lp16SwitchRec)) & 0xffff);
  1380. if((!tdb.wSSBig) ||
  1381. ((DWORD)(tdb.wSSBig | 7) ==
  1382. (((tdb.lp16SwitchRec >> 16) & 0xffff ) | 7))) {
  1383. dbgprintf(" Stack: Normal\n");
  1384. } else {
  1385. dbgprintf(" Stack: Big\n");
  1386. }
  1387. //#ifdef DEBUG
  1388. // dbgprintf(" Rip string: %8x\n", tdb.pSavedRip);
  1389. //#endif
  1390. dbgprintf("\n");
  1391. }
  1392. if(fTDBXValid) {
  1393. DumpTDBX(ptdbx);
  1394. }
  1395. }
  1396. /*** DumpChange
  1397. *
  1398. * Information on a change notification object is displayed.
  1399. *
  1400. * Entry: pfcndb - pointer to find change notification object
  1401. *
  1402. * Exit: none
  1403. */
  1404. VOID KERNENTRY
  1405. DumpChange(FCNDB *pfcndb)
  1406. {
  1407. FCNDB fcndb;
  1408. try {
  1409. READMEM(pfcndb, &fcndb, sizeof(FCNDB));
  1410. } except (1) {
  1411. dbgprintf("Could not read FCNDB structure for %08x\n", pfcndb);
  1412. return;
  1413. }
  1414. //
  1415. // Display the Change object's internal handle.
  1416. //
  1417. dbgprintf(fmt9, pfcndb, fcndb.hChangeInt);
  1418. dbgprintf(NewLine);
  1419. }
  1420. /*** DumpLevel
  1421. *
  1422. * Information on a specified global ring 3 system hierarchical critical
  1423. * section is displayed.
  1424. *
  1425. * Entry: Lock - Pointer to pointer to leveled critical section
  1426. * Name - Pointer to Lock name string
  1427. *
  1428. * Exit: none
  1429. */
  1430. VOID KERNENTRY
  1431. DumpLevel(
  1432. LCRST *Lock,
  1433. SYSLVL Level,
  1434. char *Name)
  1435. {
  1436. LCRST lcrst;
  1437. try {
  1438. READMEM(Lock, &lcrst, sizeof(LCRST));
  1439. } except (1) {
  1440. dbgprintf(fmt43, Name, Lock);
  1441. return;
  1442. }
  1443. dbgprintf(fmt40, Name, Lock, Level);
  1444. //
  1445. // Display the Lock owner if it has one
  1446. //
  1447. if ((long)(lcrst.cstSync.cntCur) <= 0) {
  1448. TDBX tdbx;
  1449. try {
  1450. READMEM(lcrst.cstSync.ptdbxOwner, &tdbx, sizeof(TDBX));
  1451. } except (1) {
  1452. dbgprintf(fmt42a);
  1453. tdbx.tdbxR0ThreadHandle = 0;
  1454. }
  1455. dbgprintf(fmt41, lcrst.cstSync.ptdbxOwner,
  1456. lcrst.cstSync.ptdbxOwner ?
  1457. (tdbx.tdbxR0ThreadHandle) : 0,
  1458. lcrst.cstSync.cntCur, lcrst.cstSync.cntRecur);
  1459. } else {
  1460. dbgprintf(fmt42);
  1461. }
  1462. //
  1463. // Display the waiting threads
  1464. //
  1465. PrintThreadsCrst(&lcrst.cstSync);
  1466. }
  1467. /*** DumpSysLevels
  1468. *
  1469. * Called to process the '.ws' command. Information on all global ring 3
  1470. * system hierarchical critical sections is displayed.
  1471. *
  1472. * Entry: none
  1473. *
  1474. * Exit: none
  1475. */
  1476. VOID KERNENTRY
  1477. DumpSysLevels(void)
  1478. {
  1479. LCRST *Win16Lock; // Hierarchical critical section for Win16
  1480. LCRST *Krn32Lock; // Hierarchical critical section for Kernel32
  1481. LCRST *crstGHeap16;
  1482. LCRST *crstLstMgr;
  1483. LCRST *crstExcpt16;
  1484. LPVOID pTmp;
  1485. LPVOID pTDBXVxD;
  1486. pTmp = NULL;
  1487. GETEXPRADDR(pTmp, "mekrnl32!Win16Lock");
  1488. if(pTmp == NULL) {
  1489. Win16Lock = NULL;
  1490. } else {
  1491. try {
  1492. READMEM(pTmp, &Win16Lock, sizeof(LCRST *));\
  1493. } except (1) {
  1494. Win16Lock = NULL;
  1495. }
  1496. }
  1497. pTmp = NULL;
  1498. GETEXPRADDR(pTmp, "mekrnl32!Krn32Lock");
  1499. if(pTmp == NULL) {
  1500. Krn32Lock = NULL;
  1501. } else {
  1502. try {
  1503. READMEM(pTmp, &Krn32Lock, sizeof(LCRST *));\
  1504. } except (1) {
  1505. Krn32Lock = NULL;
  1506. }
  1507. }
  1508. pTmp = NULL;
  1509. GETEXPRADDR(pTmp, "mekrnl32!crstGHeap16");
  1510. if(pTmp == NULL) {
  1511. crstGHeap16 = NULL;
  1512. } else {
  1513. try {
  1514. READMEM(pTmp, &crstGHeap16, sizeof(LCRST *));\
  1515. } except (1) {
  1516. crstGHeap16 = NULL;
  1517. }
  1518. }
  1519. crstLstMgr = crstExcpt16 = NULL;
  1520. GETEXPRADDR(crstLstMgr, "mekrnl32!crstLstMgr");
  1521. GETEXPRADDR(crstExcpt16, "mekrnl32!crstExcpt16");
  1522. if (Win16Lock) {
  1523. DumpLevel(Win16Lock, SL_WIN16, "Win16Mutex ");
  1524. } else {
  1525. dbgprintf("Could not get Win16Lock address from MEKRNL32\n");
  1526. }
  1527. if (Krn32Lock) {
  1528. DumpLevel(Krn32Lock, SL_KRN32, "Krn32Mutex ");
  1529. } else {
  1530. dbgprintf("Could not get Krnl32Lock address from MEKRNL32\n");
  1531. }
  1532. if (crstGHeap16) {
  1533. DumpLevel(crstGHeap16, SL_PRIVATE, "crstGHeap16");
  1534. } else {
  1535. dbgprintf("Could not get crstGHeap16 address from MEKRNL32\n");
  1536. }
  1537. if (crstLstMgr) {
  1538. DumpLevel(crstLstMgr, SL_PRIVATE, "crstLstMgr ");
  1539. } else {
  1540. dbgprintf("Could not get crstLstMgr address from MEKRNL32\n");
  1541. }
  1542. if (crstExcpt16) {
  1543. DumpLevel(crstExcpt16, SL_PRIVATE, "crstExcpt16");
  1544. } else {
  1545. dbgprintf("Could not get crstExcpt16 address from MEKRNL32\n");
  1546. }
  1547. pTmp = 0;
  1548. GETEXPRADDR(pTmp, "wow32!pTDBXVxD");
  1549. if(pTmp) {
  1550. try {
  1551. READMEM(pTmp, &pTDBXVxD, sizeof(LPVOID));\
  1552. } except (1) {
  1553. dbgprintf("Could not get pTDBXVxD content from WOW32\n");
  1554. pTDBXVxD = (LPVOID)0xFFFFFFFF;
  1555. }
  1556. if(pTDBXVxD != (LPVOID)0xFFFFFFFF) {
  1557. if(pTDBXVxD) {
  1558. dbgprintf("VxdMutex owned by ptdbx %08X\n",pTDBXVxD);
  1559. } else {
  1560. dbgprintf("VxdMutex is Unowned\n");
  1561. }
  1562. }
  1563. } else {
  1564. dbgprintf("Could not get pTDBXVxD address from WOW32\n");
  1565. }
  1566. }
  1567. #ifndef WOW32_EXTENSIONS
  1568. /*** DisplayContext
  1569. *
  1570. * The information in a context record is displayed.
  1571. *
  1572. * Entry: ContextRecord - pointer to context record
  1573. *
  1574. * Exit: none
  1575. */
  1576. VOID KERNENTRY
  1577. DisplayContextRecord(PCONTEXT ContextRecord)
  1578. {
  1579. if (ContextRecord == 0 ||
  1580. !VerifyMemory(ContextRecord, sizeof(*ContextRecord))) {
  1581. dbgprintf("[%08x]\n", ContextRecord);
  1582. return;
  1583. }
  1584. if (ContextRecord->ContextFlags & (CONTEXT_INTEGER & ~CONTEXT_i386)) {
  1585. dbgprintf(
  1586. "eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n",
  1587. ContextRecord->Eax,
  1588. ContextRecord->Ebx,
  1589. ContextRecord->Ecx,
  1590. ContextRecord->Edx,
  1591. ContextRecord->Esi,
  1592. ContextRecord->Edi
  1593. );
  1594. } else {
  1595. dbgprintf(
  1596. "eax=???????? ebx=???????? ecx=???????? edx=???????? \
  1597. esi=???????? edi=????????\n"
  1598. );
  1599. }
  1600. if (ContextRecord->ContextFlags & (CONTEXT_CONTROL & ~CONTEXT_i386)) {
  1601. dbgprintf(
  1602. "eip=%08x esp=%08x ebp=%08x eflags=%08x\ncs=%04x ss=%04x ",
  1603. ContextRecord->Eip,
  1604. ContextRecord->Esp,
  1605. ContextRecord->Ebp,
  1606. ContextRecord->EFlags,
  1607. ContextRecord->SegCs,
  1608. ContextRecord->SegSs
  1609. );
  1610. } else {
  1611. dbgprintf(
  1612. "eip=???????? esp=???????? ebp=???????? eflags=????????\n\
  1613. cs=???? ss=???? "
  1614. );
  1615. }
  1616. if (ContextRecord->ContextFlags & (CONTEXT_SEGMENTS & ~CONTEXT_i386)) {
  1617. dbgprintf(
  1618. "ds=%04x es=%04x fs=%04x gs=%04x\n",
  1619. ContextRecord->SegDs,
  1620. ContextRecord->SegEs,
  1621. ContextRecord->SegFs,
  1622. ContextRecord->SegGs
  1623. );
  1624. } else {
  1625. dbgprintf("ds=???? es=???? fs=???? gs=????\n");
  1626. }
  1627. if (ContextRecord->ContextFlags &
  1628. (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) {
  1629. dbgprintf(
  1630. "dr0=%08x dr1=%08x dr2=%08x dr3=%08x dr6=%08x dr7=%08x\n",
  1631. ContextRecord->Dr0,
  1632. ContextRecord->Dr1,
  1633. ContextRecord->Dr2,
  1634. ContextRecord->Dr3,
  1635. ContextRecord->Dr6,
  1636. ContextRecord->Dr7
  1637. );
  1638. } else {
  1639. dbgprintf(
  1640. "dr0=???????? dr1=???????? dr2=???????? dr3=???????? dr6=???????? \
  1641. dr7=????????\n"
  1642. );
  1643. }
  1644. if (ContextRecord->ContextFlags &
  1645. (CONTEXT_FLOATING_POINT & ~CONTEXT_i386)) {
  1646. dbgprintf(
  1647. "fcw=%08x fsw=%08x ftw=%08x fip=%08x fcs=%08x fcr0=%08x\n\
  1648. foo=%08x fos=%08x ContextFlags=%08x\n",
  1649. ContextRecord->FloatSave.ControlWord,
  1650. ContextRecord->FloatSave.StatusWord,
  1651. ContextRecord->FloatSave.TagWord,
  1652. ContextRecord->FloatSave.ErrorOffset,
  1653. ContextRecord->FloatSave.ErrorSelector,
  1654. ContextRecord->FloatSave.Cr0NpxState,
  1655. ContextRecord->FloatSave.DataOffset,
  1656. ContextRecord->FloatSave.DataSelector,
  1657. ContextRecord->ContextFlags
  1658. );
  1659. } else {
  1660. dbgprintf(
  1661. "fcw=???????? fsw=???????? ftw=???????? fip=???????? \
  1662. fcs=????????\nfcr0=???????? foo=???????? fos=????????\n"
  1663. );
  1664. }
  1665. }
  1666. VOID KERNENTRY
  1667. DumpContextRecord()
  1668. {
  1669. PCONTEXT ContextRecord = 0;
  1670. if (GetDbgChar()) {
  1671. dbgEvalExpr((DWORD *) &ContextRecord);
  1672. }
  1673. DisplayContextRecord(ContextRecord);
  1674. }
  1675. /*** DisplayExceptionRecord
  1676. *
  1677. * The information in an exception record is displayed.
  1678. *
  1679. * Entry: ExceptionRecord - pointer to exception record
  1680. *
  1681. * Exit: none
  1682. */
  1683. VOID KERNENTRY
  1684. DisplayExceptionRecord(PEXCEPTION_RECORD ExceptionRecord)
  1685. {
  1686. DWORD i;
  1687. char *s;
  1688. if (ExceptionRecord == 0 ||
  1689. !VerifyMemory(
  1690. &ExceptionRecord->NumberParameters,
  1691. sizeof(ExceptionRecord->NumberParameters)
  1692. ) ||
  1693. !VerifyMemory(
  1694. ExceptionRecord,
  1695. sizeof(*ExceptionRecord) -
  1696. sizeof(ExceptionRecord->ExceptionInformation[0]) *
  1697. EXCEPTION_MAXIMUM_PARAMETERS +
  1698. sizeof(ExceptionRecord->ExceptionInformation[0]) *
  1699. ExceptionRecord->NumberParameters
  1700. )) {
  1701. dbgprintf("[%08x]\n", ExceptionRecord);
  1702. return;
  1703. }
  1704. switch (ExceptionRecord->ExceptionCode) {
  1705. case STATUS_INTEGER_DIVIDE_BY_ZERO:
  1706. s = "STATUS_INTEGER_DIVIDE_BY_ZERO";
  1707. break;
  1708. case EXCEPTION_SINGLE_STEP:
  1709. s = "EXCEPTION_SINGLE_STEP";
  1710. break;
  1711. case EXCEPTION_BREAKPOINT:
  1712. s = "EXCEPTION_BREAKPOINT";
  1713. break;
  1714. case STATUS_INTEGER_OVERFLOW:
  1715. s = "STATUS_INTEGER_OVERFLOW";
  1716. break;
  1717. case STATUS_ARRAY_BOUNDS_EXCEEDED:
  1718. s = "STATUS_ARRAY_BOUNDS_EXCEEDED";
  1719. break;
  1720. case STATUS_ILLEGAL_INSTRUCTION:
  1721. s = "STATUS_ILLEGAL_INSTRUCTION";
  1722. break;
  1723. case STATUS_ACCESS_VIOLATION:
  1724. if (ExceptionRecord->ExceptionInformation[0] & 1) {
  1725. s = "STATUS_ACCESS_VIOLATION [write]";
  1726. } else if (ExceptionRecord->ExceptionInformation[1] == (DWORD) -1) {
  1727. s = "STATUS_ACCESS_VIOLATION [gp fault]";
  1728. } else {
  1729. s = "STATUS_ACCESS_VIOLATION [read]";
  1730. }
  1731. break;
  1732. case STATUS_IN_PAGE_ERROR:
  1733. if (ExceptionRecord->ExceptionInformation[0] & 1) {
  1734. s = "STATUS_IN_PAGE_ERROR [write]";
  1735. } else {
  1736. s = "STATUS_IN_PAGE_ERROR [read]";
  1737. }
  1738. break;
  1739. case STATUS_STACK_OVERFLOW:
  1740. if (ExceptionRecord->NumberParameters != 2) {
  1741. s = "STATUS_STACK_OVERFLOW";
  1742. } else if (ExceptionRecord->ExceptionInformation[0] & 1) {
  1743. s = "STATUS_STACK_OVERFLOW [write]";
  1744. } else {
  1745. s = "STATUS_STACK_OVERFLOW [read]";
  1746. }
  1747. break;
  1748. case STATUS_FLOAT_STACK_CHECK:
  1749. s = "STATUS_FLOAT_STACK_CHECK";
  1750. break;
  1751. case STATUS_FLOAT_INVALID_OPERATION:
  1752. s = "STATUS_FLOAT_INVALID_OPERATION";
  1753. break;
  1754. case STATUS_FLOAT_DIVIDE_BY_ZERO:
  1755. s = "STATUS_FLOAT_DIVIDE_BY_ZERO";
  1756. break;
  1757. case STATUS_FLOAT_OVERFLOW:
  1758. s = "STATUS_FLOAT_OVERFLOW";
  1759. break;
  1760. case STATUS_FLOAT_UNDERFLOW:
  1761. s = "STATUS_FLOAT_UNDERFLOW";
  1762. break;
  1763. case STATUS_FLOAT_INEXACT_RESULT:
  1764. s = "STATUS_FLOAT_INEXACT_RESULT";
  1765. break;
  1766. default:
  1767. s = "UNKNOWN";
  1768. }
  1769. dbgprintf("Code=%08x (%s)\n", ExceptionRecord->ExceptionCode, s);
  1770. dbgprintf("Flags=%08x", ExceptionRecord->ExceptionFlags);
  1771. if (ExceptionRecord->ExceptionFlags == 0) {
  1772. dbgprintf("\n");
  1773. } else {
  1774. dbgprintf(" (");
  1775. i = ExceptionRecord->ExceptionFlags;
  1776. if (i & EXCEPTION_NONCONTINUABLE) {
  1777. i &= ~EXCEPTION_NONCONTINUABLE;
  1778. dbgprintf("NONCONTINUABLE%s", i ? ", " : ")\n");
  1779. }
  1780. if (i & EXCEPTION_UNWINDING) {
  1781. i &= ~EXCEPTION_UNWINDING;
  1782. dbgprintf("UNWINDING%s", i ? ", " : ")\n");
  1783. }
  1784. if (i & EXCEPTION_EXIT_UNWIND) {
  1785. i &= ~EXCEPTION_EXIT_UNWIND;
  1786. dbgprintf("EXIT_UNWIND%s", i ? ", " : ")\n");
  1787. }
  1788. if (i & EXCEPTION_STACK_INVALID) {
  1789. i &= ~EXCEPTION_STACK_INVALID;
  1790. dbgprintf("STACK_INVALID%s", i ? ", " : ")\n");
  1791. }
  1792. if (i & EXCEPTION_NESTED_CALL) {
  1793. i &= ~EXCEPTION_NESTED_CALL;
  1794. dbgprintf("NESTED_CALL%s", i ? ", " : ")\n");
  1795. }
  1796. if (i & EXCEPTION_TARGET_UNWIND) {
  1797. i &= ~EXCEPTION_TARGET_UNWIND;
  1798. dbgprintf("TARGET_UNWIND%s", i ? ", " : ")\n");
  1799. }
  1800. if (i & EXCEPTION_COLLIDED_UNWIND) {
  1801. i &= ~EXCEPTION_COLLIDED_UNWIND;
  1802. dbgprintf("COLLIDED_UNWIND%s", i ? ", " : ")\n");
  1803. }
  1804. if (i) {
  1805. dbgprintf("????)\n");
  1806. }
  1807. }
  1808. dbgprintf("ExcRec=%08x Number of Parameters=%02x\n",
  1809. ExceptionRecord->ExceptionRecord,
  1810. ExceptionRecord->NumberParameters
  1811. );
  1812. for (i = 1; i <= ExceptionRecord->NumberParameters; ++i) {
  1813. dbgprintf("%02x) %08x ", i, ExceptionRecord->ExceptionInformation[i-1]);
  1814. if (i >= EXCEPTION_MAXIMUM_PARAMETERS) {
  1815. break;
  1816. }
  1817. if (i % 5 == 0 && i < ExceptionRecord->NumberParameters) {
  1818. dbgprintf("\n");
  1819. }
  1820. }
  1821. if (i > 1) {
  1822. dbgprintf("\n");
  1823. }
  1824. }
  1825. VOID KERNENTRY
  1826. DumpExceptionRecord()
  1827. {
  1828. PEXCEPTION_RECORD ExceptionRecord = 0;
  1829. if (GetDbgChar()) {
  1830. dbgEvalExpr((DWORD *) &ExceptionRecord);
  1831. }
  1832. DisplayExceptionRecord(ExceptionRecord);
  1833. }
  1834. /*** DumpDispatcherContext
  1835. *
  1836. * Information about an active exception dispatch is displayed.
  1837. *
  1838. * Entry: DispatcherContext - pointer to exception dispatcher context structure
  1839. * (NULL causes a search).
  1840. *
  1841. * Exit: none
  1842. */
  1843. VOID KERNENTRY
  1844. DumpDispatcherContext()
  1845. {
  1846. PTDB ptdb;
  1847. PNESTED_EXCEPTION_HANDLER_FRAME DispatcherContext = 0;
  1848. PVOID va;
  1849. BOOL v;
  1850. DWORD i;
  1851. if (GetDbgChar()) {
  1852. dbgEvalExpr((DWORD *) &DispatcherContext);
  1853. }
  1854. Restart:
  1855. if (DispatcherContext) {
  1856. //
  1857. // Dump the specified context.
  1858. //
  1859. if (!VerifyMemory(va=DispatcherContext, sizeof(*DispatcherContext))) {
  1860. goto InvalidAddress;
  1861. }
  1862. if (DispatcherContext->RegistrationRecord.Handler !=
  1863. (PEXCEPTION_ROUTINE) ExceptionHandler) {
  1864. dbgprintf("Invalid dispatcher context structure");
  1865. } else {
  1866. dbgprintf(
  1867. "Exception Record (%08x):\n",
  1868. DispatcherContext->ExceptionRecord
  1869. );
  1870. DisplayExceptionRecord(DispatcherContext->ExceptionRecord);
  1871. dbgprintf(
  1872. "\nContext Record (%08x):\n",
  1873. DispatcherContext->ContextRecord
  1874. );
  1875. DisplayContextRecord(DispatcherContext->ContextRecord);
  1876. }
  1877. } else {
  1878. //
  1879. // See if there's an active dispatcher context, ie. a search for an
  1880. // exception handler in progress.
  1881. //
  1882. ptdb = GetCurrentTdb();
  1883. DispatcherContext = (PNESTED_EXCEPTION_HANDLER_FRAME)GetTIB(ptdb).pvExcept;
  1884. if (DispatcherContext == (PNESTED_EXCEPTION_HANDLER_FRAME) -1) {
  1885. goto NoContext;
  1886. }
  1887. if (!VerifyMemory(va=DispatcherContext, sizeof(*DispatcherContext))) {
  1888. goto InvalidAddress;
  1889. }
  1890. if (DispatcherContext->RegistrationRecord.Handler ==
  1891. (PEXCEPTION_ROUTINE) ExceptionHandler) {
  1892. //
  1893. // There's a dispatch in progress. If it's nested, find the
  1894. // initial context.
  1895. //
  1896. i = 0;
  1897. while ((v = VerifyMemory(
  1898. va=DispatcherContext,
  1899. sizeof(*DispatcherContext)
  1900. )) &&
  1901. (v = VerifyMemory(
  1902. va=DispatcherContext->ExceptionRecord,
  1903. sizeof(*DispatcherContext->ExceptionRecord)
  1904. )) &&
  1905. (v = VerifyMemory(
  1906. va=DispatcherContext->RegistrationRecord.Next,
  1907. sizeof(*DispatcherContext->RegistrationRecord.Next)
  1908. )) &&
  1909. DispatcherContext->ExceptionRecord->ExceptionFlags &
  1910. EXCEPTION_NESTED_CALL) {
  1911. if (DispatcherContext->RegistrationRecord.Next->Handler ==
  1912. (PEXCEPTION_ROUTINE) ExceptionHandler) {
  1913. DispatcherContext = (PNESTED_EXCEPTION_HANDLER_FRAME)
  1914. DispatcherContext->RegistrationRecord.Next;
  1915. } else {
  1916. break;
  1917. }
  1918. if (++i == 10) {
  1919. dbgprintf("searching...");
  1920. }
  1921. }
  1922. if (!v) {
  1923. //
  1924. // We bailed out because of an invalid address.
  1925. //
  1926. goto InvalidAddress;
  1927. }
  1928. //
  1929. // DispatcherContext now points to the initial DispatcherContext
  1930. // record.
  1931. //
  1932. if (i >= 10) {
  1933. dbgprintf("\n");
  1934. }
  1935. goto Restart;
  1936. } else {
  1937. NoContext:
  1938. dbgprintf("dispatcher context not found\n");
  1939. }
  1940. return;
  1941. InvalidAddress:
  1942. dbgprintf("[%08x]\n", va);
  1943. }
  1944. }
  1945. #endif // ndef WOW32_EXTENSIONS
  1946. /*** DumpProcess
  1947. *
  1948. * Information on a process object is displayed.
  1949. *
  1950. * Entry: ppdb - pointer to process object
  1951. *
  1952. * Exit: none
  1953. */
  1954. VOID KERNENTRY
  1955. DumpProcess(PDB *ppdb)
  1956. {
  1957. PDB pdb;
  1958. MODREF ModRef;
  1959. MODREF *pModRef;
  1960. MTE *pmte;
  1961. MTE mte;
  1962. EDB *pedb;
  1963. EDB edb;
  1964. LPVOID pTmp;
  1965. DWORD flags;
  1966. DWORD dwIdObsfucator;
  1967. char ModFname[256];
  1968. try {
  1969. READMEM(ppdb, &pdb, sizeof(PDB));
  1970. } except (1) {
  1971. dbgprintf(fmt50, ppdb);
  1972. return;
  1973. }
  1974. dbgprintf("Process %x", ppdb);
  1975. pModRef = pdb.pModExe;
  1976. if(pModRef) {
  1977. try {
  1978. READMEM(pModRef, &ModRef, sizeof(MODREF));
  1979. } except (1) {
  1980. pModRef = NULL;
  1981. }
  1982. if(pModRef) {
  1983. pmte = GetModuleTableEntry(ModRef.imte,&mte);
  1984. if (pmte) {
  1985. try {
  1986. READMEM(mte.cfhid.lpFilename, &ModFname[0], sizeof(ModFname));
  1987. } except (1) {
  1988. ModFname[0] = '\0';
  1989. }
  1990. } else {
  1991. ModFname[0] = '\0';
  1992. }
  1993. } else {
  1994. pmte = NULL;
  1995. ModFname[0] = '\0';
  1996. }
  1997. } else {
  1998. pmte = NULL;
  1999. ModFname[0] = '\0';
  2000. }
  2001. if(pmte)
  2002. dbgprintf(" %s\n", ModFname);
  2003. else
  2004. dbgprintf("\n");
  2005. pTmp = NULL;
  2006. GETEXPRADDR(pTmp, "mekrnl32!dwIdObsfucator");
  2007. if(pTmp == NULL) {
  2008. dwIdObsfucator = 0;
  2009. } else {
  2010. try {
  2011. READMEM(pTmp, &dwIdObsfucator, sizeof(DWORD));\
  2012. } except (1) {
  2013. dwIdObsfucator = 0;
  2014. }
  2015. }
  2016. if (dwIdObsfucator) {
  2017. dbgprintf(" Id: %8x\n", ((DWORD)(ppdb)) ^ dwIdObsfucator);
  2018. }
  2019. dbgprintf(" Type: %2x %s\n", pdb.objBase.typObj, GetObjType((OBJ*)&pdb));
  2020. dbgprintf(" Ref count: %4x\n", pdb.objBase.cntUses);
  2021. dbgprintf(" Default Heap: %8x\n", pdb.hheapLocal);
  2022. dbgprintf(" Heap own list: %8x\n", pdb.hhi_procfirst);
  2023. dbgprintf(" Mem Context: %08x\n", pdb.hContext);
  2024. dbgprintf(" MTE index: %8.2x\n", pdb.imte);
  2025. flags = pdb.flFlags;
  2026. dbgprintf(" Flags: %08x ", flags);
  2027. if(flags & fDebugSingle) dbgprintf("fDebugSingle ");
  2028. if(flags & fCreateProcessEvent) dbgprintf("fCreateProcessEvent ");
  2029. if(flags & fExitProcessEvent) dbgprintf("fExitProcessEvent ");
  2030. if(flags & fWin16Process) dbgprintf("fWin16Process ");
  2031. if(flags & fDosProcess) dbgprintf("fDosProcess ");
  2032. if(flags & fConsoleProcess) dbgprintf("fConsoleProcess ");
  2033. if(flags & fFileApisAreOem) dbgprintf("fFileApisAreOem ");
  2034. if(flags & fNukeProcess) dbgprintf("fNukeProcess ");
  2035. if(flags & fServiceProcess) dbgprintf("fServiceProcess ");
  2036. if(flags & fLoginScriptHack) dbgprintf("fLoginScriptHack ");
  2037. DumpFlags(flags);
  2038. dbgprintf(" pPSP: %08x\n", pdb.pPsp);
  2039. dbgprintf(" PSP selector: %8.4x\n", pdb.selPsp);
  2040. dbgprintf(" #Threads: %8.2x\n", pdb.cntThreads);
  2041. dbgprintf(" #Thr not term: %8.2x\n", pdb.cntThreadsNotTerminated);
  2042. dbgprintf(" #R0 threads: %8.2x\n", pdb.R0ThreadCount);
  2043. dbgprintf(" K16 TDB Sel: %8.4x\n", pdb.hTaskWin16);
  2044. dbgprintf(" MMF Views: %8x\n", pdb.pFvd);
  2045. dbgprintf(" pEDB: %08x\n", pdb.pedb);
  2046. pedb = pdb.pedb;
  2047. try {
  2048. READMEM(pedb, &edb, sizeof(EDB));\
  2049. } except (1) {
  2050. pedb = NULL;
  2051. }
  2052. if (pedb)
  2053. {
  2054. dbgprintf(" Environment: %08x\n", edb.pchEnv);
  2055. dbgprintf(" Command Line: %08x", edb.szCmdA);
  2056. try {
  2057. READMEM(edb.szCmdA, &ModFname[0], sizeof(ModFname));
  2058. } except (1) {
  2059. ModFname[0] = '\0';
  2060. }
  2061. dbgprintf(" %s\n", ModFname);
  2062. dbgprintf(" Current Dir: %08x", edb.szDir);
  2063. try {
  2064. READMEM(edb.szDir, &ModFname[0], sizeof(ModFname));
  2065. } except (1) {
  2066. ModFname[0] = '\0';
  2067. }
  2068. dbgprintf(" %s\n", ModFname);
  2069. dbgprintf(" Startup Info: %08x\n", edb.lpStartupInfo);
  2070. dbgprintf(" hStdIn: %8.2x\n", edb.hStdIn);
  2071. dbgprintf(" hStdOut: %8.2x\n", edb.hStdOut);
  2072. dbgprintf(" hStdError: %8.2x\n", edb.hStdErr);
  2073. dbgprintf(" Inherit console: %08x\n", edb.pInheritedConsole);
  2074. dbgprintf(" Break type: %8.2x\n", edb.ctrlType);
  2075. dbgprintf(" Break thread ID: %8x\n", edb.ptdbCtrl);
  2076. dbgprintf(" Break handlers: %8x\n", edb.rgpfnCtrl);
  2077. }
  2078. dbgprintf(" pHandle Table: %08x\n", pdb.phtbHandles);
  2079. dbgprintf(" Parent PDB: %08x\n", pdb.ppdbParent);
  2080. dbgprintf(" MODREF list: %08x\n", pdb.plstMod);
  2081. dbgprintf(" Parent MODREF: %08x\n", pdb.pModExe);
  2082. dbgprintf(" Thread list: %08x\n", pdb.plstTdb);
  2083. dbgprintf(" Debuggee CB: %8x\n", pdb.pdb_pdeeDebuggee);
  2084. dbgprintf(" Initial R0 id: %8x\n", pdb.pid);
  2085. dwIdObsfucator = (DWORD)ppdb;
  2086. dwIdObsfucator += offsetof(PDB, crstLoadLock);
  2087. dbgprintf(" &crstLoadLock: %08x\n", dwIdObsfucator);
  2088. dbgprintf(" pConsole: %8x\n", pdb.pConsole);
  2089. dbgprintf(" Process DWORD 0: %08x\n", pdb.adw[0]);
  2090. dbgprintf(" Proc Group: %8x\n", pdb.ppdbPGroup);
  2091. dbgprintf(" Top Ex Filter: %8x\n", pdb.pExceptionFilter);
  2092. dbgprintf(" Priority base: %08x\n", pdb.pcPriClassBase);
  2093. dbgprintf(" LH Free head: %8x\n", pdb.plhFree);
  2094. dbgprintf(" LH lhandle blks: %8x\n", pdb.plhBlock);
  2095. dbgprintf(" Term status: %08x\n", pdb.dwStatus);
  2096. dbgprintf("pconsoleProvider: %8x\n", pdb.pconsoleProvider);
  2097. dbgprintf(" wEnvSel: %4x\n", pdb.wEnvSel);
  2098. dbgprintf(" wErrorMode: %4x\n", pdb.wErrorMode);
  2099. dbgprintf("pevtLoadFinished: %08x\n", (DWORD)(pdb.pevtLoadFinished));
  2100. dbgprintf(" UTState: %4x\n", pdb.hUTState);
  2101. dbgprintf("lpCmdLineNoQuote: %8x\n", pdb.lpCmdLineNoQuote);
  2102. }
  2103. VOID KERNENTRY
  2104. DumpFlags(DWORD flags)
  2105. {
  2106. if(flags & fSignaled) dbgprintf("fSignaled ");
  2107. if(flags & fInitError) dbgprintf("fInitError ");
  2108. if(flags & fTerminated) dbgprintf("fTerminated ");
  2109. if(flags & fTerminating) dbgprintf("fTerminating ");
  2110. if(flags & fFaulted) dbgprintf("fFaulted ");
  2111. if(flags & fNearlyTerminating) dbgprintf("fNearlyTerminating ");
  2112. if(flags & fDebugEventPending) dbgprintf("fDebugEventPending ");
  2113. if(flags & fSendDLLNotifications) dbgprintf("fSendDLLNotifications ");
  2114. dbgprintf("\n");
  2115. }
  2116. VOID KERNENTRY
  2117. DumpModule(IMTE imte, BOOL fIgnNotPres)
  2118. {
  2119. MTE *pmte;
  2120. MTE mte;
  2121. LEH lehMod;
  2122. char ModFname[256];
  2123. pmte = GetModuleTableEntry(imte,&mte);
  2124. if(fDumpHeader) {
  2125. dbgprintf(fmt60h);
  2126. dbgprintf(fmt60i);
  2127. fDumpHeader = FALSE;
  2128. }
  2129. if (!pmte) {
  2130. if(!fIgnNotPres) {
  2131. dbgprintf(fmt60,
  2132. imte,
  2133. pmte,
  2134. 0,
  2135. "--",
  2136. 0,
  2137. NotPresentStr);
  2138. }
  2139. } else {
  2140. try {
  2141. READMEM(mte.plehMod, &lehMod, sizeof(LEH));
  2142. } except (1) {
  2143. lehMod.ImageBase = 0;
  2144. }
  2145. try {
  2146. READMEM(mte.cfhid.lpFilename, &ModFname[0], sizeof(ModFname));
  2147. } except (1) {
  2148. ModFname[0] = '\0';
  2149. }
  2150. dbgprintf(fmt60,
  2151. imte,
  2152. pmte,
  2153. mte.usage,
  2154. lehMod.Signature==MEOW_PLEH_SIGNATURE ? "NT" : "9X",
  2155. lehMod.ImageBase,
  2156. ModFname);
  2157. }
  2158. } /* DumpModule */
  2159. VOID KERNENTRY
  2160. DumpModuleInProcess(MODREF *pModRef,MODREF *pModRefBuf) {
  2161. IMTE imte;
  2162. MTE *pmte;
  2163. MTE mte;
  2164. LEH lehMod;
  2165. char ModFname[256];
  2166. try {
  2167. READMEM(pModRef, pModRefBuf, sizeof(MODREF));
  2168. } except (1) {
  2169. dbgprintf(fmt74a, pModRef);
  2170. pModRefBuf->nextMod = 0;
  2171. return;
  2172. }
  2173. imte = pModRefBuf->imte;
  2174. pmte = GetModuleTableEntry(imte,&mte);
  2175. if(fDumpHeader) {
  2176. dbgprintf(fmt61h);
  2177. dbgprintf(fmt61i);
  2178. dbgprintf(fmt61j);
  2179. fDumpHeader = FALSE;
  2180. }
  2181. if (pmte) {
  2182. try {
  2183. READMEM(mte.plehMod, &lehMod, sizeof(LEH));
  2184. } except (1) {
  2185. lehMod.ImageBase = 0;
  2186. }
  2187. try {
  2188. READMEM(mte.cfhid.lpFilename, &ModFname[0], sizeof(ModFname));
  2189. } except (1) {
  2190. ModFname[0] = '\0';
  2191. }
  2192. dbgprintf(fmt61,
  2193. imte,
  2194. pmte,
  2195. mte.usage,
  2196. pModRefBuf->usage,
  2197. lehMod.Signature==MEOW_PLEH_SIGNATURE ? "NT" : "9X",
  2198. lehMod.ImageBase,
  2199. ModFname);
  2200. } else {
  2201. dbgprintf(fmt61,
  2202. imte,
  2203. pmte,
  2204. 0,
  2205. pModRefBuf->usage,
  2206. "--",
  2207. 0,
  2208. NotPresentStr);
  2209. }
  2210. } /* DumpModuleInProcess */
  2211. #ifndef WOW32_EXTENSIONS
  2212. VOID KERNENTRY
  2213. HeapStuff(void) {
  2214. #ifdef DEBUG
  2215. BYTE b;
  2216. b = (BYTE)GetDbgChar();
  2217. /*
  2218. * The 'W' option toggles paranoid heap walking
  2219. */
  2220. if (b == 'w' || b == 'W') {
  2221. dbgprintf(fmt80);
  2222. if (hpfParanoid) {
  2223. hpfParanoid = 0;
  2224. dbgprintf(fmt82);
  2225. } else {
  2226. hpfTrashStop = 1;
  2227. hpfWalk = 1;
  2228. hpfParanoid = 1;
  2229. dbgprintf(fmt81);
  2230. }
  2231. /*
  2232. * The 'E' options toggles stopping on errors
  2233. */
  2234. } else if (b == 'e' || b == 'E') {
  2235. mmfErrorStop ^= 1;
  2236. dbgprintf(fmt83);
  2237. if (mmfErrorStop) {
  2238. dbgprintf(fmt81);
  2239. } else {
  2240. dbgprintf(fmt82);
  2241. }
  2242. } else {
  2243. dbgprintf(DotError);
  2244. }
  2245. #else
  2246. dbgprintf(fmt84);
  2247. #endif
  2248. }
  2249. VOID KERNENTRY
  2250. DumpThreadList1(TDB *ptdb) {
  2251. DWORD *pdw;
  2252. ULONG ulCount;
  2253. // Make sure the tdb is present.
  2254. if( !VerifyMemory( ptdb, sizeof( TDB))) {
  2255. dbgprintf( fmt16, ptdb);
  2256. return;
  2257. }
  2258. // Count the nodes in the private selector list
  2259. for( ulCount = 0, pdw = (DWORD *)GetTIB(ptdb).pvFirstDscr;
  2260. pdw != (DWORD *)1;
  2261. ulCount++, pdw = (DWORD *)*pdw)
  2262. ;
  2263. // Print the thread id
  2264. if( ptdb->R0ThreadHandle != 0) {
  2265. dbgprintf( "%02x ", ((PTCB)ptdb->R0ThreadHandle)->TCB_ThreadId);
  2266. } else {
  2267. dbgprintf( "## ");
  2268. }
  2269. // Print the summary info for the thread
  2270. dbgprintf( "%8x %4x ", ptdb, ulCount);
  2271. if( !VerifyMemory( &pLDT, sizeof( DWORD *))) {
  2272. dbgprintf( "\n[pLDT %x]\n", &pLDT);
  2273. return;
  2274. }
  2275. // Print the private selector list
  2276. for( ulCount = 0, pdw = (DWORD *)GetTIB(ptdb).pvFirstDscr;
  2277. pdw != (DWORD *)1;
  2278. ulCount++, pdw = (DWORD *)*pdw) {
  2279. // Newline every now and then
  2280. if( (ulCount > 0) && (ulCount % 12 == 0)) {
  2281. dbgprintf( "\n ");
  2282. }
  2283. // Print as a selector
  2284. dbgprintf( "%4x ", ((DWORD)pdw - (DWORD)pLDT) | 7);
  2285. }
  2286. dbgprintf( "\n");
  2287. } /* DumpThreadList1 */
  2288. VOID KERNENTRY
  2289. DumpThreadLists(void) {
  2290. NOD *pNodP, *pNodOld;
  2291. // Title string
  2292. dbgprintf( "id ptdb len per-thread selector list\n");
  2293. // Save current node
  2294. pNodOld = PnodGetLstElem( plstTdb, idLstGetCur);
  2295. // For each TDB in system
  2296. for( pNodP = PnodGetLstElem( plstTdb, idLstGetFirst);
  2297. pNodP != 0L;
  2298. pNodP = PnodGetLstElem( plstTdb, idLstGetNext)) {
  2299. DumpThreadList1( (TDB *)pNodP->dwData);
  2300. }
  2301. // Restore current node
  2302. SetLstCurElem( plstTdb, pNodOld);
  2303. } /* DumpThreadLists */
  2304. VOID KERNENTRY
  2305. DumpSelmanList16(void) {
  2306. DWORD dwCount;
  2307. WORD wSel;
  2308. dbgprintf( "16-bit selman list");
  2309. wSel = *pwHeadSelman16;
  2310. if( !VerifyMemory( &pLDT, sizeof( DWORD *))) {
  2311. dbgprintf( "\n[pLDT %x]\n", &pLDT);
  2312. return;
  2313. }
  2314. if( !VerifyMemory( (WORD *)((DWORD)pLDT + (DWORD)wSel),
  2315. sizeof( WORD))) {
  2316. dbgprintf( "\nNot-present 16-bit selman list head.\n");
  2317. return;
  2318. }
  2319. for( dwCount = 0, wSel = *pwHeadSelman16;
  2320. wSel != 1;
  2321. dwCount++, wSel = *(WORD *)((DWORD)pLDT + (DWORD)wSel)) {
  2322. if( dwCount % 16 == 0)
  2323. dbgprintf( "\n"); // occasional newline
  2324. dbgprintf( "%4lx ", wSel | 7);
  2325. if( !VerifyMemory( (WORD *)((DWORD)pLDT + (DWORD)wSel),
  2326. sizeof( WORD))) {
  2327. dbgprintf( "\nCorrupt 16-bit selman list!!!\n");
  2328. break;
  2329. }
  2330. }
  2331. if( wSel == 1) {
  2332. dbgprintf( "\nnodes in 16-bit selman list = %d\n", dwCount);
  2333. }
  2334. } /* DumpSelmanList16 */
  2335. VOID KERNENTRY
  2336. DumpSelmanList32(void) {
  2337. DWORD dwCount;
  2338. DWORD *p;
  2339. dbgprintf( "32-bit selman list");
  2340. if( !VerifyMemory( &pLDT, sizeof( DWORD *))) {
  2341. dbgprintf( "\n[pLDT %x]\n", &pLDT);
  2342. return;
  2343. }
  2344. if( !VerifyMemory( SelmanBuffer, sizeof( DWORD))) {
  2345. dbgprintf( "\n\tCan't access list!!!\n");
  2346. return;
  2347. }
  2348. for( dwCount = 0, p = SelmanBuffer;
  2349. p != (DWORD *)(1);
  2350. dwCount++, p = (DWORD *)*p) {
  2351. if( dwCount % 16 == 0)
  2352. dbgprintf( "\n"); // occasional newline
  2353. // print as selector
  2354. dbgprintf( "%4lx ", ((DWORD)p - (DWORD)pLDT) | 7);
  2355. if( !VerifyMemory( (DWORD *)*p, sizeof( DWORD))) {
  2356. dbgprintf( "\nCorrupt 32-bit selman list!!!\n");
  2357. break;
  2358. }
  2359. }
  2360. if( p == (DWORD *)(1)) {
  2361. dbgprintf( "\nnodes in 32-bit selman list = %d\n", dwCount);
  2362. }
  2363. } /* DumpSelmanList32 */
  2364. VOID KERNENTRY
  2365. DumpFreeList16(void) {
  2366. DWORD dwCount;
  2367. WORD wSel;
  2368. dbgprintf( "16-bit global free list");
  2369. if( !VerifyMemory( &pLDT, sizeof( DWORD *))) {
  2370. dbgprintf( "\n[pLDT %x]\n", &pLDT);
  2371. return;
  2372. }
  2373. for( dwCount = 0, wSel = wHeadK16FreeList;
  2374. wSel != (WORD)(-1);
  2375. dwCount++, wSel = *(WORD *)((DWORD)pLDT + (DWORD)wSel)) {
  2376. // skip the head
  2377. if( dwCount % 16 == 1)
  2378. dbgprintf( "\n"); // occasional newline
  2379. if( dwCount != 0) // skip the head
  2380. dbgprintf( "%4lx ", wSel | 7);
  2381. if( !VerifyMemory( (DWORD *)((DWORD)pLDT + (DWORD)wSel),
  2382. sizeof( DWORD))) {
  2383. dbgprintf( "\nCorrupt 16-bit free list!!!\n");
  2384. break;
  2385. }
  2386. }
  2387. if( wSel == (WORD)(-1)) {
  2388. // don't count the head node, and adjust for end-of-list
  2389. // (bumped dwCount for the last, failing, iteration)
  2390. dbgprintf( "\nnodes in 16-bit free list = %d\n", dwCount-1);
  2391. }
  2392. } /* DumpFreeList16 */
  2393. VOID KERNENTRY
  2394. DumpLDTStuff(void) {
  2395. DumpSelmanList16();
  2396. dbgprintf( "\n");
  2397. DumpSelmanList32();
  2398. dbgprintf( "\n");
  2399. DumpThreadLists();
  2400. dbgprintf( "\n");
  2401. DumpFreeList16();
  2402. } /* DumpLDTStuff */
  2403. #endif // ndef WOW32_EXTENSIONS
  2404. VOID KERNENTRY
  2405. DumpModules(
  2406. char cmod,
  2407. DWORD argppdb
  2408. )
  2409. {
  2410. IMTE i;
  2411. IMTE imteMax;
  2412. PDB* ppdb;
  2413. MODREF* pModRef;
  2414. MODREF ModRef;
  2415. PDB pdb;
  2416. LPVOID pTmp;
  2417. // Distinguish between .wm and .wmp
  2418. if ((cmod == 'p') || (cmod == 'P'))
  2419. {
  2420. // This is a .wmp so just dump modules for this process
  2421. // See if the userA specified a process to dump
  2422. if (argppdb == 0xFFFFFFFF) {
  2423. ppdb = GetCurrentPdb();
  2424. if(!ppdb) {
  2425. dbgprintf(fmt72a, ppdb);
  2426. return;
  2427. }
  2428. dbgprintf(fmt72, ppdb, " ");
  2429. } else
  2430. {
  2431. ppdb = (PDB *)argppdb;
  2432. dbgprintf("PDB %08x\n", ppdb);
  2433. }
  2434. try {
  2435. READMEM(ppdb, &pdb, sizeof(PDB));
  2436. } except (1) {
  2437. dbgprintf(fmt74, ppdb);
  2438. return;
  2439. }
  2440. if(pdb.objBase.typObj != typObjProcess)
  2441. {
  2442. dbgprintf(fmt74, ppdb);
  2443. return;
  2444. }
  2445. // Walk the process list
  2446. CheckCtrlC();
  2447. ModRef.nextMod = 0;
  2448. fDumpHeader = TRUE;
  2449. for (pModRef = pdb.plstMod ; pModRef ; pModRef = ModRef.nextMod) {
  2450. DumpModuleInProcess(pModRef,&ModRef);
  2451. if(CheckCtrlC()) {
  2452. dbgprintf(fmt3a);
  2453. break;
  2454. }
  2455. }
  2456. return;
  2457. }
  2458. pTmp = NULL;
  2459. GETEXPRADDR(pTmp, "mekrnl32!imteMax");
  2460. if(pTmp == NULL) {
  2461. dbgprintf(fmt72b);
  2462. i = 0;
  2463. } else {
  2464. try {
  2465. imteMax = 0;
  2466. READMEM(pTmp, &imteMax, sizeof(IMTE));\
  2467. } except (1) {
  2468. dbgprintf(fmt72b);
  2469. i = 0;
  2470. }
  2471. }
  2472. fDumpHeader = TRUE;
  2473. for (i=0; i<imteMax; i++)
  2474. {
  2475. DumpModule(i,TRUE);
  2476. }
  2477. } /* DumpModules */
  2478. VOID KERNENTRY
  2479. DumpProcess1(PDB *ppdb) {
  2480. MODREF *pRef;
  2481. PDB pdb;
  2482. MTE *pmte;
  2483. MTE mte;
  2484. MODREF ModRef;
  2485. LEH lehMod;
  2486. char ModFname[256];
  2487. try {
  2488. READMEM(ppdb, &pdb, sizeof(PDB));
  2489. } except (1) {
  2490. dbgprintf("\nCannot get process PDB\n");
  2491. return;
  2492. }
  2493. if (pdb.pModExe) {
  2494. try {
  2495. READMEM(pdb.pModExe, &ModRef, sizeof(MODREF));
  2496. } except (1) {
  2497. dbgprintf("\nCannot get process module\n");
  2498. }
  2499. pmte = GetModuleTableEntry(ModRef.imte,&mte);
  2500. if (!pmte) {
  2501. dbgprintf("\nCannot get process module table entry\n");
  2502. }
  2503. try {
  2504. READMEM(mte.cfhid.lpFilename, &ModFname[0], sizeof(ModFname));
  2505. } except (1) {
  2506. ModFname[0] = '\0';
  2507. }
  2508. dbgprintf(fmt70, ppdb, ModFname);
  2509. } else {
  2510. dbgprintf(fmt70, ppdb, fmt73);
  2511. }
  2512. pRef = pdb.plstMod;
  2513. if(fDumpHeader) {
  2514. dbgprintf(fmt71h);
  2515. dbgprintf(fmt71i);
  2516. fDumpHeader = FALSE;
  2517. }
  2518. while(pRef) {
  2519. try {
  2520. READMEM(pRef, &ModRef, sizeof(MODREF));
  2521. } except (1) {
  2522. dbgprintf(fmt74a, pRef);
  2523. ModRef.nextMod = 0;
  2524. break;
  2525. }
  2526. pmte = GetModuleTableEntry(ModRef.imte,&mte);
  2527. if (pmte) {
  2528. try {
  2529. READMEM(mte.plehMod, &lehMod, sizeof(LEH));
  2530. } except (1) {
  2531. lehMod.ImageBase = 0;
  2532. }
  2533. try {
  2534. READMEM(mte.cfhid.lpFilename, &ModFname[0], sizeof(ModFname));
  2535. } except (1) {
  2536. ModFname[0] = '\0';
  2537. }
  2538. } else {
  2539. lehMod.ImageBase = 0;
  2540. ModFname[0] = '\0';
  2541. }
  2542. dbgprintf(fmt71, ModRef.imte, ModRef.usage, ModRef.flags,
  2543. lehMod.Signature==MEOW_PLEH_SIGNATURE ? "NT" : "9X",
  2544. lehMod.ImageBase,
  2545. ModFname);
  2546. pRef = ModRef.nextMod;
  2547. }
  2548. } /* DumpProcess1 */
  2549. VOID KERNENTRY
  2550. DumpProcesses(void) {
  2551. NOD *pNodP;
  2552. NOD *pNodStart;
  2553. PDB *ppdb;
  2554. PDB pdb;
  2555. NOD nod;
  2556. LST *plstPdb;
  2557. LPVOID pTmp;
  2558. MTE *pmte;
  2559. MTE mte;
  2560. MODREF ModRef;
  2561. char ModFname[256];
  2562. ppdb = GetCurrentPdb();
  2563. if(!ppdb) {
  2564. dbgprintf(fmt72a, ppdb);
  2565. return;
  2566. }
  2567. try {
  2568. READMEM(ppdb, &pdb, sizeof(PDB));
  2569. } except (1) {
  2570. dbgprintf("\nCannot get current process\n");
  2571. return;
  2572. }
  2573. if(pdb.pModExe) {
  2574. try {
  2575. READMEM(pdb.pModExe, &ModRef, sizeof(MODREF));
  2576. } except (1) {
  2577. dbgprintf("\nCannot get current process module\n");
  2578. return;
  2579. }
  2580. pmte = GetModuleTableEntry(ModRef.imte,&mte);
  2581. if (!pmte) {
  2582. dbgprintf("\nCannot get current process module table entry\n");
  2583. return;
  2584. }
  2585. try {
  2586. READMEM(mte.cfhid.lpFilename, &ModFname[0], sizeof(ModFname));
  2587. } except (1) {
  2588. ModFname[0] = '\0';
  2589. }
  2590. dbgprintf(fmt72, ppdb, ModFname);
  2591. } else {
  2592. dbgprintf(fmt72c, ppdb);
  2593. }
  2594. // For each PDB in system
  2595. pTmp = NULL;
  2596. GETEXPRADDR(pTmp, "mekrnl32!plstPdb");
  2597. if(pTmp == NULL) {
  2598. plstPdb = NULL;
  2599. } else {
  2600. try {
  2601. READMEM(pTmp, &plstPdb, sizeof(LST *));\
  2602. } except (1) {
  2603. plstPdb = NULL;
  2604. }
  2605. }
  2606. pNodStart = pNodP = PnodGetLstElem(plstPdb, NULL, idLstGetFirst);
  2607. while(pNodP) {
  2608. try {
  2609. READMEM(pNodP, &nod, sizeof(NOD));\
  2610. } except (1) {
  2611. dbgprintf("\nInvalid PDB List element\n");
  2612. break;
  2613. }
  2614. fDumpHeader = TRUE;
  2615. DumpProcess1((PDB *)(nod.dwData));
  2616. pNodP = PnodGetLstElem(plstPdb, pNodP, idLstGetNext);
  2617. if(pNodP == pNodStart) {
  2618. break;
  2619. }
  2620. }
  2621. } /* DumpProcesses */
  2622. #ifndef WOW32_EXTENSIONS
  2623. /*** DumpConsole
  2624. *
  2625. * Information on a console object is displayed.
  2626. *
  2627. * Entry: pconsole - pointer to console object
  2628. *
  2629. * Exit: none
  2630. */
  2631. VOID KERNENTRY
  2632. DumpConsole(CONSOLE *pconsole)
  2633. {
  2634. // If the console's not present, display the address, etc.
  2635. if (!VerifyMemory(pconsole, sizeof (CONSOLE))) {
  2636. dbgprintf(fmt50, pconsole);
  2637. return;
  2638. }
  2639. // Since the console's present, display some useful stuff about it
  2640. dbgprintf("Console %x\n", (DWORD)pconsole);
  2641. dbgprintf(" Screen Buffer: %8x\n", (DWORD)pconsole->psbActiveScreenBuffer);
  2642. dbgprintf(" Max Size X: %8dT\n", (DWORD)pconsole->cMaxSize.X);
  2643. dbgprintf(" Max Size Y: %8dT\n", (DWORD)pconsole->cMaxSize.Y);
  2644. dbgprintf(" Flags: %8x\n", (DWORD)pconsole->flags);
  2645. dbgprintf(" Original Size X: %8dT\n", (DWORD)pconsole->cOriginalSize.X);
  2646. dbgprintf(" Original Size Y: %8dT\n", (DWORD)pconsole->cOriginalSize.Y);
  2647. dbgprintf(" &(crCRST): %8x\n", &(pconsole->csCRST));
  2648. dbgprintf(" plstOwners: %8x\n", (DWORD)pconsole->plstOwners);
  2649. dbgprintf(" plstBuffers: %8x\n", (DWORD)pconsole->plstBuffers);
  2650. dbgprintf(" dwLastExitCode: %8x\n", (DWORD)pconsole->dwLastExitCode);
  2651. dbgprintf(" szTitle: %s\n", &(pconsole->szTitle));
  2652. dbgprintf(" VID: %8x\n", (DWORD)pconsole->VID);
  2653. dbgprintf(" hVM: %8x\n", (DWORD)pconsole->hVM);
  2654. dbgprintf(" hDisplay: %8x\n", (DWORD)pconsole->hDisplay);
  2655. dbgprintf("ppdbControlFocus: %8x\n", (DWORD)pconsole->ppdbControlFocus);
  2656. dbgprintf("ppdbTermConProvi: %8x\n", (DWORD)pconsole->ppdbTermConProvider);
  2657. dbgprintf(" &(inbuf.cbBuf): %8x\n", &(pconsole->inbuf.cbBuf));
  2658. dbgprintf(" inbuf.ReadIndex: %8x\n", (DWORD)pconsole->inbuf.wReadIdx);
  2659. dbgprintf("inbuf.WriteIndex: %8x\n", (DWORD)pconsole->inbuf.wWriteIdx);
  2660. dbgprintf(" inbuf.BufCount: %8x\n", (DWORD)pconsole->inbuf.wBufCount);
  2661. dbgprintf(" wDefaultAttr: %8x\n", (DWORD)pconsole->wDefaultAttribute);
  2662. dbgprintf(" evtDoneWithVM: %8x\n", (DWORD)pconsole->evtDoneWithVM);
  2663. }
  2664. /*** DumpScreenBuffer
  2665. *
  2666. * Information on a console ScreenBuffer object is displayed.
  2667. *
  2668. * Entry: psb - pointer to screen buffer
  2669. *
  2670. * Exit: none
  2671. */
  2672. VOID KERNENTRY
  2673. DumpScreenBuffer(SCREENBUFFER *psb)
  2674. {
  2675. // If the screen buffer's not present, display the address, etc.
  2676. if (!VerifyMemory(psb, sizeof (SCREENBUFFER))) {
  2677. dbgprintf(fmt50, psb);
  2678. return;
  2679. }
  2680. // Since the screen buffer's present, display some useful stuff about it
  2681. dbgprintf("ScreenBuffer %x\n", (DWORD)psb);
  2682. dbgprintf(" Size X: %8dT\n", (DWORD)psb->cBufsize.X);
  2683. dbgprintf(" Size Y: %8dT\n", (DWORD)psb->cBufsize.Y);
  2684. dbgprintf(" Screen Data: %8x\n", (DWORD)psb->Screen);
  2685. dbgprintf(" Cursor X: %8dT\n", (DWORD)psb->cCursorPosition.X);
  2686. dbgprintf(" Cursor Y: %8dT\n", (DWORD)psb->cCursorPosition.Y);
  2687. dbgprintf(" Cursor Fill %%: %8dT\n", (DWORD)psb->dwCursorSize);
  2688. dbgprintf(" Window Lft: %8dT\n", (DWORD)psb->srWindow.Left);
  2689. dbgprintf(" Window Top: %8dT\n", (DWORD)psb->srWindow.Top);
  2690. dbgprintf(" Window Rgt: %8dT\n", (DWORD)psb->srWindow.Right);
  2691. dbgprintf(" Window Bot: %8dT\n", (DWORD)psb->srWindow.Bottom);
  2692. dbgprintf(" Flags: %8x\n", (DWORD)psb->flags);
  2693. dbgprintf(" State: %8x (%s)\n",
  2694. (DWORD)psb->State,
  2695. (psb->State == SB_PHYSICAL) ? "physical" :
  2696. (psb->State == SB_NATIVE) ? "native" :
  2697. (psb->State == SB_MEMORY) ? "memory" : "*CORRUPTED*");
  2698. dbgprintf(" &(crst): %8x\n", &(psb->csCRST));
  2699. dbgprintf(" pConsole: %8x\n", (DWORD)psb->pConsole);
  2700. dbgprintf(" wAttribute: %8x\n", (DWORD)psb->wAttribute);
  2701. dbgprintf(" OutMode Flags: %8x\n", (DWORD)psb->flOutputMode);
  2702. }
  2703. #endif // ndef WOW32_EXTENSIONS
  2704. /*** DumpTimer
  2705. *
  2706. * Information on a timer is displayed.
  2707. *
  2708. * Entry: ptimerDB - pointer to timer
  2709. *
  2710. * Exit: none
  2711. */
  2712. VOID KERNENTRY
  2713. DumpTimer(TIMERDB *ptimerDB)
  2714. {
  2715. TIMERDB timerDB;
  2716. LPTIMERR3APC lpTimerR3Apc;
  2717. TIMERR3APC TimerR3Apc;
  2718. try {
  2719. READMEM(ptimerDB, &timerDB, sizeof(TIMERDB));
  2720. } except (1) {
  2721. dbgprintf("Could not read TIMERDB structure for %08x\n", ptimerDB);
  2722. return;
  2723. }
  2724. dbgprintf("Timer: %08x\n", (DWORD)ptimerDB);
  2725. dbgprintf(" State: %s, %s\n",
  2726. (timerDB.objBase.objFlags & fTimerRing3) ?
  2727. "Ring 3" : "Ring 0",
  2728. timerDB.cntCur ? "Signaled" : "Unsignaled");
  2729. dbgprintf(" Ref count: %08x\n", timerDB.objBase.cntUses);
  2730. dbgprintf(" CntCur: %08x\n", timerDB.cntCur);
  2731. dbgprintf(" NameStruct: %08x\n", (DWORD)(timerDB.NameStruct));
  2732. dbgprintf(" lpNextTimerDb: %08x\n", timerDB.lpNextTimerDb);
  2733. dbgprintf(" hTimeout: %08x\n", timerDB.hTimeout);
  2734. dbgprintf(" DueTime.Hi: %08x\n", timerDB.DueTime.dwHighDateTime);
  2735. dbgprintf(" DueTime.Lo: %08x\n", timerDB.DueTime.dwLowDateTime);
  2736. dbgprintf(" Completion: %08x\n", (DWORD)(timerDB.Completion));
  2737. dbgprintf(" lPeriod: %08x\n", timerDB.lPeriod);
  2738. if ((timerDB.objBase.objFlags & fTimerRing3) &&
  2739. (lpTimerR3Apc = (LPTIMERR3APC)(timerDB.Completion)) &&
  2740. lpTimerR3Apc != (LPTIMERR3APC)0xcccccccc) {
  2741. dbgprintf("-- Attached Ring 3 Completion Structure --\n");
  2742. try {
  2743. READMEM(lpTimerR3Apc, &TimerR3Apc, sizeof(TIMERR3APC));
  2744. } except (1) {
  2745. dbgprintf(" lpTimerR3Apc: [%8x]\n", lpTimerR3Apc);
  2746. lpTimerR3Apc = NULL;
  2747. }
  2748. if (lpTimerR3Apc) {
  2749. dbgprintf(" cRef: %08x\n", (DWORD)(TimerR3Apc.cRef));
  2750. dbgprintf(" Completion Fcn: %08x\n", (DWORD)(TimerR3Apc.pfnCompletion));
  2751. dbgprintf(" Completion Arg: %08x\n", (DWORD)(TimerR3Apc.lpCompletionArg));
  2752. dbgprintf(" ApcTdbx: %08x\n", (DWORD)(TimerR3Apc.ApcTdbx));
  2753. dbgprintf(" dwApcHandle: %08x\n", (DWORD)(TimerR3Apc.dwApcHandle));
  2754. }
  2755. }
  2756. if (timerDB.pwnWait != NULL) {
  2757. PrintThreads(timerDB.pwnWait);
  2758. } else {
  2759. dbgprintf(NewLine);
  2760. }
  2761. }
  2762. #ifndef WOW32_EXTENSIONS
  2763. /*** DumpR0ObjExt
  2764. *
  2765. * Information on an external ring 0 object is displayed.
  2766. *
  2767. * Entry: pR0ObjExt - pointer to R0OBJEXT
  2768. *
  2769. * Exit: none
  2770. */
  2771. VOID KERNENTRY
  2772. DumpR0ObjExt(PR0OBJEXT pR0ObjExt)
  2773. {
  2774. PR0OBJTYPETABLE pR0ObjTypeTable;
  2775. // If the objects's not present, display the address, etc.
  2776. if (!VerifyMemory(pR0ObjExt, sizeof (R0OBJEXT))) {
  2777. dbgprintf(fmt50, pR0ObjExt);
  2778. return;
  2779. }
  2780. pR0ObjTypeTable = pR0ObjExt->pR0ObjTypeTable;
  2781. dbgprintf("R0ObjExt: %8x\n", (DWORD)pR0ObjExt);
  2782. dbgprintf(" External Use: %8x\n", (DWORD)pR0ObjExt->cntExternalUses);
  2783. dbgprintf(" Object Body: %8x\n", (DWORD)pR0ObjExt->pR0ObjBody);
  2784. dbgprintf(" Object Vtbl: %8x\n", (DWORD)pR0ObjTypeTable);
  2785. if (VerifyMemory(pR0ObjTypeTable, sizeof(R0OBJTYPETABLE))) {
  2786. dbgprintf(" pfnFree: %8x\n", (DWORD)pR0ObjTypeTable->ott_pfnFree);
  2787. dbgprintf(" pfnDup: %8x\n", (DWORD)pR0ObjTypeTable->ott_pfnDup);
  2788. }
  2789. }
  2790. #endif // ndef WOW32_EXTENSIONS
  2791. VOID KERNENTRY
  2792. DumpCrstPnt(CRST *pcrst, char *name) {
  2793. PTDBX ptdbx;
  2794. TDBX tdbx;
  2795. PTDB ptdb;
  2796. PPDB ppdb;
  2797. DWORD ptcb;
  2798. CRST crst;
  2799. if(pcrst) {
  2800. try {
  2801. READMEM(pcrst, &crst, sizeof(CRST));
  2802. } except (1) {
  2803. pcrst = NULL;
  2804. }
  2805. }
  2806. if(pcrst) {
  2807. if (crst.cntCur == 1) {
  2808. dbgprintf("%s(%08x) is not owned\n", name, pcrst);
  2809. return;
  2810. }
  2811. if (!crst.ptdbxOwner) {
  2812. dbgprintf("%s(%08x) null ptdbxOwner field\n", name, pcrst);
  2813. return;
  2814. }
  2815. ptdbx = crst.ptdbxOwner;
  2816. if(ptdbx) {
  2817. try {
  2818. READMEM(ptdbx, &tdbx, sizeof(TDBX));
  2819. } except (1) {
  2820. ptdbx = NULL;
  2821. }
  2822. }
  2823. if(!ptdbx) {
  2824. dbgprintf("%s(%08x) invalid ptdbxOwner\n", name, pcrst);
  2825. return;
  2826. }
  2827. ptdb = (PTDB)tdbx.tdbxThreadHandle;
  2828. ppdb = (PPDB)tdbx.tdbxProcessHandle;
  2829. ptcb = (DWORD)tdbx.tdbxR0ThreadHandle;
  2830. dbgprintf(
  2831. "%s(%08x) held by TDBX %08x(%x) TDB %08x, PDB %08x, recursion %d\n",
  2832. name, pcrst, ptdbx, ptcb,
  2833. ptdb, ppdb, crst.cntRecur);
  2834. if (crst.ptdbxWait) {
  2835. ptdbx = crst.ptdbxWait;
  2836. if(ptdbx) {
  2837. try {
  2838. READMEM(ptdbx, &tdbx, sizeof(TDBX));
  2839. } except (1) {
  2840. ptdbx = NULL;
  2841. }
  2842. }
  2843. if(!ptdbx) {
  2844. dbgprintf("%s(%08x) invalid ptdbxWait\n", name, pcrst);
  2845. return;
  2846. }
  2847. ptdb = (PTDB)tdbx.tdbxThreadHandle;
  2848. ppdb = (PPDB)tdbx.tdbxProcessHandle;
  2849. ptcb = (DWORD)tdbx.tdbxR0ThreadHandle;
  2850. dbgprintf(" Waiting TDBX %08x(%x) TDB %08x, PDB %08x\n",
  2851. ptdbx, ptcb, ptdb, ppdb);
  2852. }
  2853. } else {
  2854. dbgprintf("Cannot access %s\n", name);
  2855. }
  2856. } /* DumpCrstPnt */
  2857. VOID KERNENTRY
  2858. DumpCrstSym(char *crstsymname, char *name) {
  2859. CRST *pcrst;
  2860. LPVOID pTmp;
  2861. pTmp = NULL;
  2862. GETEXPRADDR(pTmp, crstsymname);
  2863. if(pTmp == NULL) {
  2864. pcrst = NULL;
  2865. } else {
  2866. try {
  2867. READMEM(pTmp, &pcrst, sizeof(CRST *));
  2868. } except (1) {
  2869. pcrst = NULL;
  2870. }
  2871. }
  2872. DumpCrstPnt(pcrst,name);
  2873. }
  2874. VOID KERNENTRY
  2875. DumpWait(PDB *ppdb) {
  2876. NOD *pNodP, *pNodStart;
  2877. NOD nod;
  2878. PDB pdb;
  2879. TDB *ptdb;
  2880. TDB tdb;
  2881. LST *plstTdb;
  2882. LPVOID pTmp;
  2883. DWORD dwi;
  2884. dbgprintf("PDB %x\n", ppdb);
  2885. if(!ppdb) {
  2886. dbgprintf("\nInvalid PDB\n");
  2887. return;
  2888. }
  2889. try {
  2890. READMEM(ppdb, &pdb, sizeof(PDB));
  2891. } except (1) {
  2892. dbgprintf("\nInvalid PDB\n");
  2893. return;
  2894. }
  2895. dwi = (DWORD)ppdb;
  2896. dwi += offsetof(PDB, crstLoadLock.cstSync);
  2897. DumpCrstPnt((CRST *)dwi, " DllLock");
  2898. pTmp = NULL;
  2899. GETEXPRADDR(pTmp, "mekrnl32!plstTdb");
  2900. if(pTmp == NULL) {
  2901. plstTdb = NULL;
  2902. } else {
  2903. try {
  2904. READMEM(pTmp, &plstTdb, sizeof(LST *));
  2905. } except (1) {
  2906. plstTdb = NULL;
  2907. }
  2908. }
  2909. pNodStart = pNodP = PnodGetLstElem(plstTdb, NULL, idLstGetFirst);
  2910. if(!pNodP)
  2911. return;
  2912. while(pNodP) {
  2913. try {
  2914. READMEM(pNodP, &nod, sizeof(NOD));
  2915. } except (1) {
  2916. dbgprintf("\nInvalid TDB list element\n");
  2917. break;
  2918. }
  2919. ptdb = (TDB *)nod.dwData;
  2920. tdb.flFlags = 0;
  2921. if(ptdb) {
  2922. try {
  2923. READMEM(ptdb, &tdb, sizeof(TDB));
  2924. } except (1) {
  2925. tdb.flFlags = 0;
  2926. }
  2927. }
  2928. dbgprintf(" Thread %08x flags %08x\n", ptdb, tdb.flFlags);
  2929. pNodP = PnodGetLstElem(plstTdb, pNodP, idLstGetNext);
  2930. if(pNodP == pNodStart) {
  2931. break;
  2932. }
  2933. }
  2934. } /* DumpWait */
  2935. VOID KERNENTRY
  2936. DumpWaiting(void) {
  2937. NOD *pNodP, *pNodStart;
  2938. NOD nod;
  2939. LST *plstPdb;
  2940. LPVOID pTmp;
  2941. DumpCrstSym("mekrnl32!Win16Lock", "Win16Mutex");
  2942. DumpCrstSym("mekrnl32!Krn32Lock", "Krn32Mutex");
  2943. pTmp = NULL;
  2944. GETEXPRADDR(pTmp, "mekrnl32!plstPdb");
  2945. if(pTmp == NULL) {
  2946. plstPdb = NULL;
  2947. } else {
  2948. try {
  2949. READMEM(pTmp, &plstPdb, sizeof(LST *));\
  2950. } except (1) {
  2951. plstPdb = NULL;
  2952. }
  2953. }
  2954. pNodStart = pNodP = PnodGetLstElem(plstPdb, NULL, idLstGetFirst);
  2955. if(!pNodP)
  2956. return;
  2957. while(pNodP) {
  2958. try {
  2959. READMEM(pNodP, &nod, sizeof(NOD));
  2960. } except (1) {
  2961. dbgprintf("\nInvalid PDB list element\n");
  2962. break;
  2963. }
  2964. DumpWait((PDB *)nod.dwData);
  2965. pNodP = PnodGetLstElem(plstPdb, pNodP, idLstGetNext);
  2966. if(pNodP == pNodStart) {
  2967. break;
  2968. }
  2969. }
  2970. } /* DumpWaiting */
  2971. /*** DumpAllThreads
  2972. *
  2973. * Called to process the '.w' command. Information on all win32 threads is
  2974. * displayed.
  2975. *
  2976. * Entry: none
  2977. *
  2978. * Exit: none
  2979. */
  2980. VOID KERNENTRY
  2981. DumpAllThreads(void)
  2982. {
  2983. NOD *pNodP;
  2984. NOD *pNodPnew;
  2985. NOD *pNodStart;
  2986. NOD nod;
  2987. PVOID pTmp;
  2988. LST *plstTdb;
  2989. pTmp = NULL;
  2990. GETEXPRADDR(pTmp, "mekrnl32!plstTdb");
  2991. if(pTmp == NULL) {
  2992. plstTdb = NULL;
  2993. } else {
  2994. try {
  2995. READMEM(pTmp, &plstTdb, sizeof(LST *));\
  2996. } except (1) {
  2997. plstTdb = NULL;
  2998. }
  2999. }
  3000. if(!plstTdb) {
  3001. dbgprintf("Cannot get TDB List from MEKRNL32\n");
  3002. return;
  3003. }
  3004. pNodStart = pNodP = PnodGetLstElem(plstTdb, NULL, idLstGetFirst);
  3005. if(!pNodP)
  3006. return;
  3007. fDumpHeader = TRUE;
  3008. CheckCtrlC();
  3009. while(pNodP) {
  3010. try {
  3011. READMEM(pNodP, &nod, sizeof(NOD));\
  3012. } except (1) {
  3013. dbgprintf("\nInvalid TDB list element\n");
  3014. break;
  3015. }
  3016. DumpThread((TDB *)(nod.dwData),FALSE);
  3017. pNodPnew = PnodGetLstElem(plstTdb, pNodP, idLstGetNext);
  3018. if((pNodPnew == pNodStart) || (pNodPnew == pNodP)) {
  3019. break;
  3020. }
  3021. if(CheckCtrlC()) {
  3022. dbgprintf(fmt3a);
  3023. break;
  3024. }
  3025. pNodP = pNodPnew;
  3026. }
  3027. }
  3028. VOID KERNENTRY
  3029. DumpHandleTable(char cmod, PDB* ppdb)
  3030. {
  3031. HTB *phtb;
  3032. HTB htb[60];
  3033. DWORD htbtrusz;
  3034. PDB pdb;
  3035. LPVOID pTmp;
  3036. MTE *pmte;
  3037. MTE mte;
  3038. OBJ obj;
  3039. MODREF ModRef;
  3040. char ModFname[256];
  3041. int ihte;
  3042. if ((cmod == 'k') || (cmod == 'K')) {
  3043. pTmp = NULL;
  3044. GETEXPRADDR(pTmp, "mekrnl32!ppdbKernel");
  3045. if(pTmp == NULL) {
  3046. dbgprintf("Cannot get ppdbKernel\n");
  3047. return;
  3048. } else {
  3049. try {
  3050. READMEM(pTmp, &ppdb, sizeof(PDB *));\
  3051. } except (1) {
  3052. dbgprintf("Cannot get ppdbKernel\n");
  3053. return;
  3054. }
  3055. }
  3056. } else if (ppdb == NULL) {
  3057. ppdb = GetCurrentPdb();
  3058. }
  3059. if(ppdb) {
  3060. try {
  3061. READMEM(ppdb, &pdb, sizeof(PDB));\
  3062. } except (1) {
  3063. ppdb = NULL;
  3064. }
  3065. }
  3066. if(!ppdb) {
  3067. dbgprintf(fmt74, (DWORD)0xFFFFFFFF);
  3068. return;
  3069. }
  3070. if(pdb.objBase.typObj != typObjProcess)
  3071. {
  3072. dbgprintf(fmt74, ppdb);
  3073. return;
  3074. }
  3075. if(pdb.pModExe) {
  3076. try {
  3077. READMEM(pdb.pModExe, &ModRef, sizeof(MODREF));
  3078. } except (1) {
  3079. dbgprintf(fmt74, ppdb);
  3080. goto NmDone;
  3081. }
  3082. pmte = GetModuleTableEntry(ModRef.imte,&mte);
  3083. if (!pmte) {
  3084. dbgprintf(fmt74, ppdb);
  3085. goto NmDone;
  3086. }
  3087. try {
  3088. READMEM(mte.cfhid.lpFilename, &ModFname[0], sizeof(ModFname));
  3089. } except (1) {
  3090. dbgprintf(fmt74, ppdb);
  3091. goto NmDone;
  3092. }
  3093. dbgprintf(fmt75, ppdb, ModFname);
  3094. } else {
  3095. dbgprintf(fmt75, ppdb, fmt73);
  3096. }
  3097. NmDone:
  3098. // Loop through the handle table, dumping object pointers
  3099. phtb = pdb.phtbHandles;
  3100. htbtrusz = sizeof(HTB);
  3101. if(phtb) {
  3102. try {
  3103. READMEM(phtb, &htb[0], htbtrusz);
  3104. } except (1) {
  3105. htb[0].chteMax = 0;
  3106. }
  3107. } else {
  3108. htb[0].chteMax = 0;
  3109. }
  3110. if(htb[0].chteMax) {
  3111. if(htb[0].chteMax > 60)
  3112. htb[0].chteMax = 60;
  3113. htbtrusz += (htb[0].chteMax - 1) * (sizeof(HTE));
  3114. try {
  3115. READMEM(phtb, &htb[0], htbtrusz);
  3116. } except (1) {
  3117. htb[0].chteMax = 0;
  3118. }
  3119. }
  3120. for (ihte = 0 ; ihte < (int)htb[0].chteMax ; ++ihte)
  3121. {
  3122. // Don't display empty table slots
  3123. if (!htb[0].rghte[ihte].pobj)
  3124. continue;
  3125. try {
  3126. READMEM(htb[0].rghte[ihte].pobj, &obj, sizeof(OBJ));
  3127. } except (1) {
  3128. obj.typObj = 0;
  3129. }
  3130. // Display this handle entry
  3131. dbgprintf(fmt76, ihte<<IHTETOHANDLESHIFT, htb[0].rghte[ihte].pobj,
  3132. htb[0].rghte[ihte].flFlags,
  3133. GetObjType(&obj), obj.typObj);
  3134. }
  3135. }
  3136. /*** DumpObject
  3137. *
  3138. * Process the '.w <expr>' command, where <expr> is the address of a win32
  3139. * object.
  3140. *
  3141. * Entry: pobj - pointer to object
  3142. *
  3143. * Exit: none
  3144. *
  3145. */
  3146. void KERNENTRY
  3147. DumpObject(OBJ *pobj)
  3148. {
  3149. OBJ obj;
  3150. try {
  3151. READMEM(pobj, &obj, sizeof(OBJ));
  3152. } except (1) {
  3153. goto dodef;
  3154. }
  3155. switch (obj.typObj) {
  3156. case typObjSemaphore:
  3157. DumpSemaphore((SEM *) pobj);
  3158. break;
  3159. case typObjEvent:
  3160. DumpEvent((EVT *) pobj);
  3161. break;
  3162. case typObjMutex:
  3163. DumpMutex((MUTX *) pobj);
  3164. break;
  3165. case typObjCrst:
  3166. DumpCritSect((CRST *) pobj);
  3167. break;
  3168. case typObjProcess:
  3169. DumpProcess((PDB *) pobj);
  3170. break;
  3171. case typObjThread:
  3172. fDumpHeader = TRUE;
  3173. DumpThread((PTDB)pobj, TRUE);
  3174. break;
  3175. case typObjChange:
  3176. DumpChange((FCNDB *) pobj);
  3177. break;
  3178. // case typObjConsole:
  3179. // DumpConsole((CONSOLE *) pobj);
  3180. // break;
  3181. // case typObjConScreenbuf:
  3182. // DumpScreenBuffer((SCREENBUFFER *) pobj);
  3183. // break;
  3184. case typObjTimer:
  3185. DumpTimer((TIMERDB *) pobj);
  3186. break;
  3187. case typObjTDBX:
  3188. DumpTDBX((PTDBX) pobj);
  3189. break;
  3190. case typObjR0ObjExt:
  3191. case typObjFile:
  3192. case typObjMapFile:
  3193. default:
  3194. dodef:
  3195. dbgprintf("Invalid or unrecognized object address 0x%08x\n", (DWORD)pobj);
  3196. break;
  3197. }
  3198. }
  3199. typedef struct _MEMINFO {
  3200. DWORD dwMask;
  3201. PCHAR pszName;
  3202. } MEMINFO, *PMEMINFO;
  3203. MEMINFO MemInfo[]={
  3204. {PAGE_NOACCESS, "PNA "},
  3205. {PAGE_READONLY, "PRO "},
  3206. {PAGE_READWRITE, "PRW "},
  3207. {PAGE_WRITECOPY, "PWC "},
  3208. {PAGE_EXECUTE, "PE "},
  3209. {PAGE_EXECUTE_READ, "PER "},
  3210. {PAGE_EXECUTE_READWRITE,"PERW"},
  3211. {PAGE_EXECUTE_WRITECOPY,"PEWC"},
  3212. {PAGE_GUARD, "PGD "},
  3213. {PAGE_NOCACHE, "PNC "},
  3214. {PAGE_WRITECOMBINE, "PWC+"},
  3215. {MEM_COMMIT, "MCOM"},
  3216. {MEM_RESERVE, "MRES"},
  3217. {MEM_DECOMMIT, "MDEC"},
  3218. {MEM_RELEASE, "MREL"},
  3219. {MEM_FREE, "MFRE"},
  3220. {MEM_PRIVATE, "MPRV"},
  3221. {MEM_MAPPED, "MMAP"},
  3222. {MEM_RESET, "MRES"},
  3223. {MEM_TOP_DOWN, "MTOP"},
  3224. {MEM_WRITE_WATCH, "MWW "},
  3225. {MEM_PHYSICAL, "MPHY"},
  3226. {MEM_IMAGE, "MIMG"},
  3227. {MEM_LARGE_PAGES, "MLP "},
  3228. {MEM_DOS_LIM, "MDOS"},
  3229. {MEM_4MB_PAGES, "M4MB"},
  3230. };
  3231. #define MEMINFO_COUNT (sizeof(MemInfo)/sizeof(MEMINFO))
  3232. VOID
  3233. KERNENTRY
  3234. ProcessMemInfo(CHAR c, DWORD dwMask)
  3235. {
  3236. BOOL fNothing=TRUE;
  3237. ULONG i;
  3238. dbgprintf(" %c:", c);
  3239. for (i=0;i<MEMINFO_COUNT;i++) {
  3240. if (dwMask & MemInfo[i].dwMask) {
  3241. dwMask&=~(MemInfo[i].dwMask);
  3242. if (!fNothing) {
  3243. dbgprintf(",");
  3244. } else {
  3245. fNothing=FALSE;
  3246. }
  3247. dbgprintf(MemInfo[i].pszName);
  3248. }
  3249. }
  3250. if (dwMask) {
  3251. dbgprintf("!mask=%08X!", dwMask);
  3252. } else {
  3253. if (fNothing)
  3254. dbgprintf("none");
  3255. }
  3256. }
  3257. VOID
  3258. KERNENTRY
  3259. DumpMemStatus(DWORD addr, BOOL fAll)
  3260. {
  3261. LPVOID lp;
  3262. MEMORY_BASIC_INFORMATION mbi;
  3263. DWORD dwLength;
  3264. lp=(LPVOID)addr;
  3265. for (;;) {
  3266. dwLength=VirtualQueryEx(hCurrentProcess, lp, &mbi, sizeof(mbi));
  3267. if (dwLength!=sizeof(mbi))
  3268. break;
  3269. dbgprintf( "%08X-%08X ",
  3270. mbi.BaseAddress,
  3271. (DWORD)(mbi.BaseAddress)+mbi.RegionSize-1);
  3272. ProcessMemInfo('S', mbi.State);
  3273. if (mbi.State!=MEM_RESERVE && mbi.State!=MEM_FREE) {
  3274. ProcessMemInfo('P', mbi.Protect);
  3275. ProcessMemInfo('T', mbi.Type);
  3276. }
  3277. dbgprintf("\n");
  3278. if (!fAll)
  3279. break;
  3280. lp=((LPBYTE)(mbi.BaseAddress)+mbi.RegionSize);
  3281. }
  3282. }
  3283. /*** W32ParseDotCommand
  3284. *
  3285. * Called by wdeb386 (via W32DotCommand in dbgdota.asm) to process a .w
  3286. * command.
  3287. *
  3288. * Entry: none
  3289. *
  3290. * Exit: FALSE
  3291. *
  3292. * Description:
  3293. * Current .w command syntax:
  3294. *
  3295. * '.w?' - help information
  3296. * '.w <expr>' - info for specific object
  3297. * '.w' - info for all threads
  3298. * '.ws' - info for all global system critical section objects
  3299. */
  3300. VOID
  3301. k32(
  3302. CMD_ARGLIST
  3303. )
  3304. {
  3305. INT nArgs;
  3306. CHAR *argv[4];
  3307. DWORD addr;
  3308. char **s;
  3309. DWORD c;
  3310. BOOL fAll;
  3311. CMD_INIT();
  3312. nArgs = WDParseArgStr(lpArgumentString, argv, 3);
  3313. if(nArgs) {
  3314. if((nArgs > 2) || ((argv[0][0] != 'W') && (argv[0][0] != 'w'))) {
  3315. goto DoHelp;
  3316. }
  3317. c = (DWORD)argv[0][1];
  3318. }
  3319. else {
  3320. goto DoHelp;
  3321. }
  3322. switch (c) {
  3323. case '?':
  3324. DoHelp:
  3325. for (s = w32DotCommandExtHelp; *s; ++s) {
  3326. dbgprintf(*s);
  3327. }
  3328. break;
  3329. #ifndef WOW32_EXTENSIONS
  3330. case 'c':
  3331. case 'C':
  3332. DumpContextRecord();
  3333. break;
  3334. case 'e':
  3335. case 'E':
  3336. DumpExceptionRecord();
  3337. break;
  3338. case 'd':
  3339. case 'D':
  3340. DumpDispatcherContext();
  3341. break;
  3342. case 'h':
  3343. case 'H':
  3344. HeapStuff();
  3345. break;
  3346. case 'l':
  3347. case 'L':
  3348. DumpLDTStuff();
  3349. break;
  3350. #endif //ndef WOW32_EXTENSIONS
  3351. case 'm':
  3352. case 'M':
  3353. addr = 0xFFFFFFFF;
  3354. if(nArgs > 1) {
  3355. addr = (DWORD)WDahtoi(argv[1]);
  3356. }
  3357. fDumpHeader = TRUE;
  3358. DumpModules(
  3359. argv[0][2],
  3360. addr
  3361. );
  3362. break;
  3363. case 'p':
  3364. case 'P':
  3365. DumpProcesses();
  3366. break;
  3367. case 's':
  3368. case 'S':
  3369. DumpSysLevels();
  3370. break;
  3371. case 'w': // Waiting threads
  3372. case 'W':
  3373. DumpWaiting();
  3374. break;
  3375. case 't':
  3376. case 'T':
  3377. if(nArgs == 1) {
  3378. addr = 0;
  3379. } else {
  3380. addr = 0xFFFFFFFF;
  3381. addr = (DWORD)WDahtoi(argv[1]);
  3382. if(addr == 0xFFFFFFFF) {
  3383. goto DoHelp;
  3384. }
  3385. }
  3386. DumpHandleTable(argv[0][2],(PDB *)addr);
  3387. break;
  3388. case 'x':
  3389. case 'X':
  3390. if(nArgs == 1) {
  3391. addr = 0;
  3392. fAll = TRUE;
  3393. } else {
  3394. fAll = FALSE;
  3395. addr = 0xFFFFFFFF;
  3396. addr = (DWORD)WDahtoi(argv[1]);
  3397. if(addr == 0xFFFFFFFF) {
  3398. goto DoHelp;
  3399. }
  3400. }
  3401. DumpMemStatus(addr, fAll);
  3402. break;
  3403. case ' ':
  3404. addr = 0xFFFFFFFF;
  3405. addr = (DWORD)WDahtoi(argv[1]);
  3406. if(addr == 0xFFFFFFFF) {
  3407. goto DoHelp;
  3408. } else {
  3409. DumpObject((OBJ *) addr);
  3410. }
  3411. break;
  3412. case 0: // There was just a W with no second letter
  3413. if(nArgs == 1) {
  3414. // No expression
  3415. DumpAllThreads();
  3416. } else {
  3417. addr = 0xFFFFFFFF;
  3418. addr = (DWORD)WDahtoi(argv[1]);
  3419. if(addr == 0xFFFFFFFF) {
  3420. goto DoHelp;
  3421. } else {
  3422. DumpObject((OBJ *) addr);
  3423. }
  3424. }
  3425. break;
  3426. default:
  3427. dbgprintf(DotError);
  3428. goto DoHelp;
  3429. }
  3430. }
  3431. #endif // def KERNEL_DOT_COMMANDS