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.

1710 lines
44 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: wow.c
  3. *
  4. * This file is for debugging tools and extensions.
  5. *
  6. * Created: 24-Jan-1992
  7. * Author: John Colleran
  8. *
  9. * History:
  10. * Feb 17 92 Matt Felton (mattfe) lots of additional exentions for filtering
  11. * Jul 13 92 (v-cjones) Added API & MSG profiling debugger extensions, fixed
  12. * other extensions to handle segment motion correctly,
  13. * & cleaned up the file in general
  14. * Jan 3 96 Neil Sandlin (neilsa) integrated this routine into vdmexts
  15. *
  16. * Copyright (c) 1992 Microsoft Corporation
  17. \**************************************************************************/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. #include <tdb16.h>
  21. #include <wmdisp32.h>
  22. #include <wcuricon.h>
  23. #include <wucomm.h>
  24. #include <doswow.h>
  25. //
  26. // get the compatibility flag values & string names
  27. //
  28. typedef struct _tagWOWCFDATA {
  29. LPSZ lpszCFName;
  30. DWORD dwVal;
  31. } WOWCFDATA;
  32. // allows us to grab the string tables only from mvdm\inc\wowcmpat.h
  33. #define _VDMEXTS_CFLAGS 1
  34. // exposes the compatibility flag strings & values in wowcmpat.h
  35. #define _VDMEXTS_CF 1
  36. WOWCFDATA CFData[] = {
  37. #include "wowcmpat.h"
  38. {"", 0x00000000}
  39. };
  40. #undef _VDMEXTS_CF
  41. // exposes the EXTENDED compatibility flag strings & values in wowcmpat.h
  42. #define _VDMEXTS_CFEX 1
  43. WOWCFDATA CFDataEx[] = {
  44. #include "wowcmpat.h"
  45. {"", 0x00000000}
  46. };
  47. #undef _VDMEXTS_CFEX
  48. // exposes the OLD Win3.x compatibility flag strings & values in wowcmpat.h
  49. #define _VDMEXTS_CF31 1
  50. WOWCFDATA CFData31[] = {
  51. #include "wowcmpat.h"
  52. {"", 0x00000000}
  53. };
  54. #undef _VDMEXTS_CF31
  55. // exposes the IME compatibility flag strings & values in wowcmpat.h
  56. #if FE_SB
  57. #define _VDMEXTS_CF_IME 1
  58. WOWCFDATA CFDataIME[] = {
  59. #include "wowcmpat.h"
  60. {"", 0x00000000}
  61. };
  62. #endif // FE_SB
  63. #undef _VDMEXTS_CF_IME
  64. #undef _VDMEXTS_CFLAGS
  65. #define MALLOC(cb) HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, cb)
  66. #define FREE(addr) HeapFree(GetProcessHeap(), 0, addr)
  67. //
  68. // Local function prototypes
  69. //
  70. INT WDahtoi(LPSZ lpsz);
  71. INT WDParseArgStr(LPSZ lpszArgStr, CHAR **argv, INT iMax) {
  72. /*
  73. * Parse a string looking for SPACE, TAB, & COMMA as delimiters
  74. * INPUT:
  75. * lpszArgStr - ptr to input arg string
  76. * iMax - maximum number of substrings to parse
  77. * OUTPUT:
  78. * argv - ptrs to strings
  79. *
  80. * RETURN: # of vectors in argv
  81. * NOTE: substrings are converted to uppercase
  82. */
  83. INT nArgs;
  84. BOOL bStrStart;
  85. nArgs = 0;
  86. bStrStart = 1;
  87. while( *lpszArgStr ) {
  88. if( (*lpszArgStr == ' ') || (*lpszArgStr == '\t') || (*lpszArgStr == ',') ) {
  89. *lpszArgStr = '\0';
  90. bStrStart = 1;
  91. }
  92. else {
  93. if( bStrStart ) {
  94. if( nArgs >= iMax ) {
  95. break;
  96. }
  97. argv[nArgs++] = lpszArgStr;
  98. bStrStart = 0;
  99. }
  100. *lpszArgStr = (CHAR)toupper(*lpszArgStr);
  101. }
  102. lpszArgStr++;
  103. }
  104. return(nArgs);
  105. }
  106. VOID
  107. dwp(
  108. CMD_ARGLIST
  109. )
  110. {
  111. PWOWPORT pwp;
  112. WOWPORT wp;
  113. CMD_INIT();
  114. ASSERT_WOW_PRESENT;
  115. while (' ' == lpArgumentString[0]) {
  116. lpArgumentString++;
  117. }
  118. pwp = (PWOWPORT) WDahtoi(lpArgumentString);
  119. if (NULL == pwp) {
  120. PRINTF("Can't read WOWPORT structure!\n\n");
  121. return;
  122. }
  123. PRINTF("Dump of WOWPORT structure at 0x%x:\n\n", (unsigned)pwp);
  124. try {
  125. READMEM_XRET(wp, pwp);
  126. } except (EXCEPTION_ACCESS_VIOLATION == GetExceptionCode()
  127. ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
  128. PRINTF("Access violation reading WOWPORT structure!\n\n");
  129. return;
  130. }
  131. PRINTF("idComDev 0x%x\n", (unsigned)wp.idComDev);
  132. PRINTF("h32 0x%x\n", (unsigned)wp.h32);
  133. PRINTF("hREvent 0x%x\n", (unsigned)wp.hREvent);
  134. PRINTF("csWrite OwningThread 0x%x RecursionCount 0x%x\n",
  135. (unsigned)wp.csWrite.OwningThread, (unsigned)wp.csWrite.RecursionCount);
  136. PRINTF("pchWriteHead 0x%x\n", (unsigned)wp.pchWriteHead);
  137. PRINTF("pchWriteTail 0x%x\n", (unsigned)wp.pchWriteTail);
  138. PRINTF("cbWriteFree 0x%x\n", (unsigned)wp.cbWriteFree);
  139. PRINTF("cbWritePending 0x%x\n", (unsigned)wp.cbWriteFree);
  140. PRINTF("pchWriteBuf 0x%x\n", (unsigned)wp.pchWriteBuf);
  141. PRINTF("cbWriteBuf 0x%x\n", (unsigned)wp.cbWriteBuf);
  142. PRINTF("hWriteThread 0x%x\n", (unsigned)wp.hWriteThread);
  143. PRINTF("hWriteEvent 0x%x\n", (unsigned)wp.hWriteEvent);
  144. PRINTF("OverLap hEvent 0x%x\n", (unsigned)wp.olWrite.hEvent);
  145. PRINTF("fWriteDone %s\n", wp.fWriteDone ? "TRUE" : "FALSE");
  146. PRINTF("cbWritten 0x%x\n", (unsigned)wp.fWriteDone);
  147. PRINTF("dwThreadID 0x%x\n", (unsigned)wp.dwThreadID);
  148. PRINTF("dwErrCode 0x%x\n", (unsigned)wp.dwErrCode);
  149. PRINTF("COMSTAT addr: 0x%x\n", (unsigned)(((char *)&wp.cs - (char *)&wp) + (char *)pwp));
  150. PRINTF("fChEvt 0x%x\n", (unsigned)wp.fChEvt);
  151. PRINTF("pdcb16 0x%x\n", (unsigned)wp.pdcb16);
  152. PRINTF("fUnGet %s\n", wp.fUnGet ? "TRUE" : "FALSE");
  153. PRINTF("cUnGet 0x%x (%c)\n", (unsigned)wp.cUnGet, wp.cUnGet);
  154. PRINTF("hMiThread 0x%x\n", (unsigned)wp.hMiThread);
  155. PRINTF("fClose %s\n", wp.fClose ? "TRUE" : "FALSE");
  156. PRINTF("dwComDEB16 0x%x\n", (unsigned)wp.dwComDEB16);
  157. PRINTF("lpComDEB16 0x%x\n", (unsigned)wp.lpComDEB16);
  158. PRINTF("cbInQ 0x%x\n", (unsigned)wp.cbInQ);
  159. PRINTF("RLSDTimeout 0x%x\n", (unsigned)wp.RLSDTimeout);
  160. PRINTF("CTSTimeout 0x%x\n", (unsigned)wp.CTSTimeout);
  161. PRINTF("DSRTimeout 0x%x\n", (unsigned)wp.DSRTimeout);
  162. PRINTF("\n");
  163. return;
  164. }
  165. //
  166. // Dump Taskinfo;
  167. //
  168. // If no argument, dump all wow tasks.
  169. // If 0, dump current WOW task
  170. // Else dump the specifies task {which is thread-id as shown by
  171. // ~ command under ntsd like 37.6b so thread-id is 6b)
  172. //
  173. void DumpTaskInfo (ptd,mode)
  174. PTD ptd;
  175. int mode;
  176. {
  177. ULONG Base;
  178. TDB tdb;
  179. BOOL b;
  180. char ModName[9];
  181. int i;
  182. BOOL fTDBValid = TRUE;
  183. Base = GetInfoFromSelector( ptd->htask16, PROT_MODE, NULL );
  184. b = READMEM( (LPVOID) (Base+GetIntelBase()), &tdb, sizeof(tdb));
  185. if ( !b ) {
  186. fTDBValid = FALSE;
  187. }
  188. for (b=FALSE, i=0; i<8; i++) {
  189. if (!fTDBValid || !tdb.TDB_ModName[i]) {
  190. b = TRUE;
  191. }
  192. if (b) {
  193. ModName[i] = ' ';
  194. } else {
  195. ModName[i] = tdb.TDB_ModName[i];
  196. }
  197. }
  198. ModName[i] = 0;
  199. PRINTF("%.4x",ptd->dwThreadID);
  200. PRINTF(" %.4x:%.4x",HIWORD(ptd->vpStack),LOWORD(ptd->vpStack));
  201. PRINTF(" %.4x", ptd->htask16);
  202. PRINTF(" %.4x", ptd->hInst16);
  203. PRINTF(" %.4x", ptd->hMod16);
  204. PRINTF(" %8s",ModName);
  205. PRINTF(" %.8x",ptd->dwWOWCompatFlags);
  206. PRINTF(" %.8x",ptd->hThread);
  207. if (fTDBValid) {
  208. PRINTF(" %.8x",tdb.TDB_flags);
  209. PRINTF(" %.3x",tdb.TDB_ExpWinVer);
  210. PRINTF(" %.4x:%.4x\n",HIWORD(tdb.TDB_DTA),LOWORD(tdb.TDB_DTA));
  211. } else {
  212. PRINTF(" Failure reading TDB at %X\n", Base );
  213. }
  214. }
  215. void
  216. DumpTask(
  217. void
  218. )
  219. {
  220. VDMCONTEXT ThreadContext;
  221. DWORD ThreadId;
  222. PTD ptd,ptdHead;
  223. TD td;
  224. int mode;
  225. BOOL b,fFound=FALSE;
  226. mode = GetContext( &ThreadContext );
  227. ThreadId = (DWORD)-1; // Assume Dump All Tasks
  228. if (GetNextToken()) {
  229. ThreadId = (DWORD) EXPRESSION( lpArgumentString );
  230. }
  231. ptdHead = (PTD)EXPRESSION("wow32!gptdTaskHead");
  232. // get the pointer to first TD
  233. b = READMEM((LPVOID) (ptdHead), &ptd, sizeof(DWORD));
  234. if ( !b ) {
  235. PRINTF("Failure reading gptdTaskHead at %08lX\n", ptdHead );
  236. return;
  237. }
  238. PRINTF("Thrd Stack task inst hmod Module Compat hThread Tdbflags Ver Dta\n");
  239. // enumerate td list to find the match(es)
  240. while (ptd) {
  241. b = READMEM((LPVOID) (ptd), &td, sizeof(TD));
  242. if ( !b ) {
  243. PRINTF("Failure reading TD At %08lX\n", ptd );
  244. return;
  245. }
  246. if (ThreadId == -1) {
  247. DumpTaskInfo (&td,mode);
  248. fFound = TRUE;
  249. }
  250. else {
  251. if (ThreadId == td.dwThreadID) {
  252. DumpTaskInfo (&td,mode);
  253. fFound = TRUE;
  254. break;
  255. }
  256. }
  257. ptd = td.ptdNext;
  258. }
  259. if (!fFound) {
  260. if (ThreadId == -1) {
  261. PRINTF("No WOW Task Found.\n");
  262. }
  263. else
  264. PRINTF("WOW Task With Thread Id = %02x Not Found.\n",ThreadId);
  265. }
  266. return;
  267. }
  268. VOID DumpTaskVerbose( ) // dump WOW32 task database entry
  269. {
  270. TD td;
  271. PTD ptd;
  272. INT i;
  273. PWOAINST pWOA, pWOALast;
  274. PTDB ptdb;
  275. BOOL fAll = FALSE;
  276. BYTE SavedByte;
  277. ptd = (PTD) WDahtoi(lpArgumentString);
  278. if (!ptd) {
  279. fAll = TRUE;
  280. GETEXPRVALUE(ptd, "wow32!gptdTaskHead", PTD);
  281. if (!ptd) {
  282. Print("Could not get wow32!gptdTaskHead");
  283. return;
  284. }
  285. Print("Dump WOW task list\n\n");
  286. } else if ((ULONG)ptd < 65536) {
  287. ULONG dwId = (ULONG) ptd;
  288. // Here, I'm making the assumption that if the argument is a value
  289. // that is less than 64k, then it can't be a TD address.
  290. // So, try it out as a thread id
  291. GETEXPRVALUE(ptd, "wow32!gptdTaskHead", PTD);
  292. if (!ptd) {
  293. Print("Could not get wow32!gptdTaskHead");
  294. return;
  295. }
  296. while(ptd) {
  297. READMEM_XRET(td, ptd);
  298. if (td.dwThreadID == dwId) {
  299. break;
  300. }
  301. ptd = td.ptdNext;
  302. }
  303. if (!ptd) {
  304. Print("Could not find thread id %s\n", lpArgumentString);
  305. return;
  306. }
  307. }
  308. do {
  309. Print("Dump of TD at 0x%08x:\n\n", (unsigned)ptd);
  310. READMEM_XRET(td, ptd);
  311. Print("vpStack %04x:%04x\n", HIWORD(td.vpStack), LOWORD(td.vpStack));
  312. Print("vpCBStack %04x:%04x\n", HIWORD(td.vpCBStack), LOWORD(td.vpCBStack));
  313. Print("cStackAlloc16 0x%08x\n", td.cStackAlloc16);
  314. Print("CommDlgTd (ptr) 0x%08x\n", td.CommDlgTd);
  315. Print("ptdNext 0x%08x\n", td.ptdNext);
  316. Print("dwFlags 0x%08x\n", td.dwFlags);
  317. //
  318. // Dump symbolic names for TDF_ manifests
  319. //
  320. if (td.dwFlags & TDF_IGNOREINPUT) {
  321. Print(" TDF_IGNOREINPUT\n");
  322. }
  323. if (td.dwFlags & TDF_FORCETASKEXIT) {
  324. Print(" TDF_FORCETASKEXIT\n");
  325. }
  326. if (td.dwFlags & TDF_TASKCLEANUPDONE) {
  327. Print(" TDF_TASKCLEANUPDONE\n");
  328. }
  329. Print("VDMInfoiTaskID 0x%08x\n", td.VDMInfoiTaskID);
  330. //
  331. // Dump CommDlgTd structure if present
  332. //
  333. if (td.CommDlgTd) {
  334. COMMDLGTD CommDlgTd;
  335. BOOL fCopySuccessful = TRUE;
  336. READMEM_XRET(CommDlgTd, td.CommDlgTd);
  337. if (fCopySuccessful) {
  338. Print("\n");
  339. Print(" Dump of CommDlgTd at 0x%08x:\n", td.CommDlgTd);
  340. Print(" hdlg 0x%04x\n", CommDlgTd.hdlg);
  341. Print(" vpData %04x:%04x\n", HIWORD(CommDlgTd.vpData), LOWORD(CommDlgTd.vpData));
  342. Print(" pData32 0x%08x\n", CommDlgTd.pData32);
  343. Print(" vpfnHook %04x:%04x\n", HIWORD(CommDlgTd.vpfnHook), LOWORD(CommDlgTd.vpfnHook));
  344. Print(" vpfnSetupHook (union) %04x:%04x\n", HIWORD(CommDlgTd.vpfnSetupHook), LOWORD(CommDlgTd.vpfnSetupHook));
  345. Print(" pRes (union) 0x%08x\n", CommDlgTd.pRes);
  346. Print(" SetupHwnd 0x%04x\n", CommDlgTd.SetupHwnd);
  347. Print(" Previous 0x%08x\n", CommDlgTd.Previous);
  348. Print(" Flags 0x%08x\n", CommDlgTd.Flags);
  349. //
  350. // Dump symbolic names for WOWCD_ manifests
  351. //
  352. if (CommDlgTd.Flags & WOWCD_ISCHOOSEFONT) {
  353. Print(" WOWCD_ISCHOOSEFONT\n");
  354. }
  355. if (CommDlgTd.Flags & WOWCD_ISOPENFILE) {
  356. Print(" WOWCD_ISOPENFILE\n");
  357. }
  358. Print("\n");
  359. }
  360. }
  361. Print("dwWOWCompatFlags 0x%08x\n", td.dwWOWCompatFlags);
  362. //
  363. // Dump symbolic names for WOWCF_ manifests
  364. //
  365. if (td.dwWOWCompatFlags) {
  366. i = 0;
  367. while(CFData[i].dwVal) {
  368. if (td.dwWOWCompatFlags & CFData[i].dwVal) {
  369. Print(" %s\n", CFData[i].lpszCFName);
  370. }
  371. i++;
  372. }
  373. }
  374. Print("dwWOWCompatFlagsEx 0x%08x\n", td.dwWOWCompatFlagsEx);
  375. //
  376. // Dump symbolic names for WOWCFEX_ manifests
  377. //
  378. if (td.dwWOWCompatFlagsEx) {
  379. i = 0;
  380. while(CFDataEx[i].dwVal) {
  381. if (td.dwWOWCompatFlagsEx & CFDataEx[i].dwVal) {
  382. Print(" %s\n", CFDataEx[i].lpszCFName);
  383. }
  384. i++;
  385. }
  386. }
  387. #if FE_SB
  388. Print("dwWOWCompatFlags2 0x%08x\n", td.dwWOWCompatFlags2);
  389. //
  390. // Dump symbolic names for WOWCFEX_ manifests
  391. //
  392. if (td.dwWOWCompatFlags2) {
  393. i = 0;
  394. while(CFDataIME[i].dwVal) {
  395. if (td.dwWOWCompatFlags2 & CFDataIME[i].dwVal) {
  396. Print(" %s\n", CFDataIME[i].lpszCFName);
  397. }
  398. i++;
  399. }
  400. }
  401. #endif
  402. Print("dwThreadID 0x%08x\n", td.dwThreadID);
  403. Print("hThread 0x%08x\n", td.hThread);
  404. Print("hIdleHook 0x%08x\n", td.hIdleHook);
  405. Print("hrgnClip 0x%08x\n", td.hrgnClip);
  406. Print("ulLastDesktophDC 0x%08x\n", td.ulLastDesktophDC);
  407. Print("pWOAList 0x%08x\n", td.pWOAList);
  408. //
  409. // Dump WOATD structure if present
  410. //
  411. pWOALast = NULL;
  412. pWOA = td.pWOAList;
  413. while (pWOA && pWOA != pWOALast) {
  414. union {
  415. WOAINST WOA;
  416. char buf[128+2+16];
  417. } u;
  418. READMEM_XRET(u.buf, pWOA);
  419. Print("\n");
  420. Print(" Dump of WOAINST at 0x%08x:\n", pWOA);
  421. Print(" pNext 0x%08x\n", u.WOA.pNext);
  422. Print(" ptdWOA 0x%08x\n", u.WOA.ptdWOA);
  423. Print(" dwChildProcessID 0x%08x\n", u.WOA.dwChildProcessID);
  424. Print(" hChildProcess 0x%08x\n", u.WOA.hChildProcess);
  425. Print(" szModuleName %s\n", u.WOA.szModuleName);
  426. Print("\n");
  427. pWOALast = pWOA;
  428. pWOA = u.WOA.pNext;
  429. }
  430. Print("htask16 0x%04x\n", td.htask16, td.htask16);
  431. //
  432. // Dump the most interesting TDB fields
  433. //
  434. if (ptdb = (PTDB) (GetInfoFromSelector(td.htask16, PROT_MODE, NULL) + GetIntelBase())) {
  435. TDB tdb;
  436. READMEM_XRET(tdb, ptdb);
  437. Print("\n");
  438. Print(" Highlights of TDB at 0x%08x:\n", ptdb);
  439. if (tdb.TDB_sig != TDB_SIGNATURE) {
  440. Print(" TDB_sig signature is 0x%04x instead of 0x%04x, halting dump.\n",
  441. tdb.TDB_sig, TDB_SIGNATURE);
  442. } else {
  443. PDOSPDB pPDB;
  444. DOSPDB PDB;
  445. PBYTE pJFT;
  446. BYTE JFT[256];
  447. WORD cbJFT;
  448. PDOSSF pSFTHead, pSFTHeadCopy;
  449. DOSSF SFTHead;
  450. PDOSSFT pSFT;
  451. WORD fh;
  452. WORD SFN;
  453. WORD i;
  454. DWORD cb;
  455. DWORD dwCompatFlags;
  456. PDOSWOWDATA pDosWowData;
  457. DOSWOWDATA DosWowData;
  458. SavedByte = tdb.TDB_ModName[8];
  459. tdb.TDB_ModName[8] = 0;
  460. Print(" Module name \"%s\"\n", tdb.TDB_ModName);
  461. tdb.TDB_ModName[8] = SavedByte;
  462. Print(" ExpWinVer 0x%04x\n", tdb.TDB_ExpWinVer);
  463. dwCompatFlags = *(DWORD *)(&tdb.TDB_CompatFlags);
  464. Print(" CompatFlags 0x%08x\n", dwCompatFlags);
  465. if (dwCompatFlags) {
  466. //
  467. // Dump symbolic names for GACF_ manifests
  468. //
  469. i = 0;
  470. while(CFData31[i].dwVal) {
  471. if (dwCompatFlags & CFData31[i].dwVal) {
  472. Print(" %s\n", CFData31[i].lpszCFName);
  473. }
  474. i++;
  475. }
  476. }
  477. Print(" Directory \"%s\"\n", tdb.TDB_LFNDirectory);
  478. Print(" PDB (aka PSP) 0x%04x\n", tdb.TDB_PDB);
  479. pPDB = (PDOSPDB) (GetInfoFromSelector(tdb.TDB_PDB, PROT_MODE, NULL) + GetIntelBase());
  480. READMEM_XRET(PDB, pPDB);
  481. Print(" segEnvironment 0x%04x\n", PDB.PDB_environ);
  482. //
  483. // Dump open file handle info
  484. //
  485. pJFT = (PBYTE) (GetIntelBase() +
  486. (HIWORD(PDB.PDB_JFN_Pointer)<<4) +
  487. LOWORD(PDB.PDB_JFN_Pointer));
  488. cbJFT = PDB.PDB_JFN_Length;
  489. Print(" JFT %04x:%04x (%08x), size 0x%x\n",
  490. HIWORD(PDB.PDB_JFN_Pointer),
  491. LOWORD(PDB.PDB_JFN_Pointer),
  492. pJFT,
  493. cbJFT);
  494. try {
  495. READMEM(pJFT, JFT, cbJFT);
  496. } except (1) {
  497. Print("Unable to read JFT from 0x%08x!\n", pJFT);
  498. return;
  499. }
  500. for (fh = 0; fh < cbJFT; fh++) {
  501. if (JFT[fh] != 0xFF) {
  502. //
  503. // Walk the SFT chain to find Nth entry
  504. // where N == JFT[fh]
  505. //
  506. SFN = 0;
  507. i = 0;
  508. GETEXPRVALUE(pSFTHead, "ntvdm!pSFTHead", PDOSSF);
  509. GETEXPRADDR(pDosWowData, "wow32!DosWowData");
  510. READMEM_XRET(DosWowData, pDosWowData);
  511. if ((DWORD)pSFTHead != DosWowData.lpSftAddr) {
  512. Print("ntvdm!pSFTHead is 0x%08x, DosWowData.lpSftAddr ix 0x%08x.\n",
  513. pSFTHead, DosWowData.lpSftAddr);
  514. }
  515. try {
  516. READMEM(pSFTHead, &SFTHead, sizeof(SFTHead));
  517. } except (1) {
  518. Print("Unable to read SFTHead from 0x%08x!\n", pSFTHead);
  519. return;
  520. }
  521. cb = sizeof(DOSSF) + SFTHead.SFCount * sizeof(DOSSFT);
  522. pSFTHeadCopy = MALLOC(cb);
  523. // Print("First DOSSF at 0x%08x, SFCount 0x%x, SFLink 0x%08x.\n",
  524. // pSFTHead, SFTHead.SFCount, SFTHead.SFLink);
  525. try {
  526. READMEM(pSFTHead, pSFTHeadCopy, cb);
  527. } except (1) {
  528. Print("Unable to read SFTHead from 0x%08x!\n", pSFTHead);
  529. return;
  530. }
  531. pSFT = (PDOSSFT) &(pSFTHeadCopy->SFTable);
  532. while (SFN < JFT[fh]) {
  533. SFN++;
  534. i++;
  535. pSFT++;
  536. if (i >= pSFTHeadCopy->SFCount) {
  537. if (LOWORD(pSFTHeadCopy->SFLink) == 0xFFFF) {
  538. SFN = JFT[fh] - 1;
  539. break;
  540. }
  541. pSFTHead = (PDOSSF) (GetIntelBase() +
  542. (HIWORD(pSFTHeadCopy->SFLink)<<4) +
  543. LOWORD(pSFTHeadCopy->SFLink));
  544. i = 0;
  545. try {
  546. READMEM(pSFTHead, &SFTHead, sizeof(SFTHead));
  547. } except (1) {
  548. Print("Unable to read SFTHead from 0x%08x!\n", pSFTHead);
  549. return;
  550. }
  551. cb = sizeof(DOSSF) + SFTHead.SFCount * sizeof(DOSSFT);
  552. FREE(pSFTHeadCopy);
  553. pSFTHeadCopy = MALLOC(cb);
  554. // Print("Next DOSSF at 0x%08x, SFCount 0x%x, SFLink 0x%08x.\n",
  555. // pSFTHead, SFTHead.SFCount, SFTHead.SFLink);
  556. try {
  557. READMEM(pSFTHead, pSFTHeadCopy, cb);
  558. } except (1) {
  559. Print("Unable to read SFTHead from 0x%08x!\n", pSFTHead);
  560. return;
  561. }
  562. pSFT = (PDOSSFT) &(pSFTHeadCopy->SFTable);
  563. }
  564. }
  565. if (SFN != JFT[fh]) {
  566. Print(" Unable to local SFT entry 0x%x for handle 0x%x.\n",
  567. pJFT[fh], fh);
  568. } else {
  569. Print(" Handle 0x%02x SFN 0x%02x Refs 0x%x Mode 0x%04x Flags 0x%04x ",
  570. fh, SFN, pSFT->SFT_Ref_Count, pSFT->SFT_Mode,
  571. pSFT->SFT_Flags);
  572. if (!pSFT->SFT_Flags & 0x80) {
  573. Print("NT Handle 0x%08x\n", pSFT->SFT_NTHandle);
  574. } else {
  575. Print("(NTDOS device)\n");
  576. }
  577. }
  578. FREE(pSFTHeadCopy);
  579. }
  580. }
  581. Print("\n");
  582. }
  583. }
  584. Print("hInst16 0x%04x\n", td.hInst16);
  585. Print("hMod16 0x%04x\n", td.hMod16);
  586. Print("\n");
  587. ptd = td.ptdNext;
  588. } while (fAll && ptd);
  589. return;
  590. }
  591. void
  592. dt(
  593. CMD_ARGLIST
  594. )
  595. {
  596. CMD_INIT();
  597. ASSERT_WOW_PRESENT;
  598. if (!GetNextToken()) {
  599. DumpTask();
  600. } else {
  601. if ((lpArgumentString[0] == '-') &&
  602. (tolower(lpArgumentString[1]) == 'v')) {
  603. SkipToNextWhiteSpace();
  604. GetNextToken();
  605. DumpTaskVerbose();
  606. } else {
  607. DumpTaskVerbose();
  608. }
  609. }
  610. }
  611. VOID
  612. ddte(
  613. CMD_ARGLIST
  614. )
  615. // dump dispatch table entry
  616. {
  617. W32 dte;
  618. PW32 pdte;
  619. char szW32[32];
  620. char szSymbol[256];
  621. DWORD dwOffset;
  622. CMD_INIT();
  623. ASSERT_WOW_PRESENT;
  624. while (' ' == lpArgumentString[0]) {
  625. lpArgumentString++;
  626. }
  627. pdte = (PW32) WDahtoi(lpArgumentString);
  628. if (pdte) {
  629. PRINTF("Dump of dispatch table entry at 0x%08x:\n\n", (unsigned)pdte);
  630. } else {
  631. GETEXPRADDR(pdte, "wow32!aw32WOW");
  632. PRINTF("Dump of first dispatch table entry at 0x%08x:\n\n", (unsigned)pdte);
  633. }
  634. try {
  635. READMEM_XRET(dte, pdte);
  636. if (dte.lpszW32) {
  637. READMEM_XRET(szW32, dte.lpszW32);
  638. dte.lpszW32 = szW32;
  639. szW32[sizeof(szW32)-1] = '\0';
  640. }
  641. } except (1) {
  642. PRINTF("Exception 0x%08x reading dispatch table entry at 0x%08x!\n\n",
  643. GetExceptionCode(), pdte);
  644. return;
  645. }
  646. PRINTF("Dispatches to address 0x%08x, ", (unsigned)dte.lpfnW32);
  647. PRINTF("supposedly function '%s'.\n", dte.lpszW32);
  648. szSymbol[0] = '\0';
  649. GetSymbol((LPVOID)dte.lpfnW32, szSymbol, &dwOffset);
  650. PRINTF("Debugger finds symbol '%s' for that address.\n", szSymbol);
  651. PRINTF("\n");
  652. return;
  653. }
  654. PSTR aszWOWCLASS[] =
  655. {
  656. "UNKNOWN",
  657. "WIN16",
  658. "BUTTON",
  659. "COMBOBOX",
  660. "EDIT",
  661. "LISTBOX",
  662. "MDICLIENT",
  663. "SCROLLBAR",
  664. "STATIC",
  665. "DESKTOP",
  666. "DIALOG",
  667. "MENU",
  668. "ACCEL",
  669. "CURSOR",
  670. "ICON",
  671. "DC",
  672. "FONT",
  673. "METAFILE",
  674. "RGN",
  675. "BITMAP",
  676. "BRUSH",
  677. "PALETTE",
  678. "PEN",
  679. "OBJECT"
  680. };
  681. INT WDahtoi(LPSZ lpsz)
  682. {
  683. char c;
  684. int tot, pow, len, dig, i;
  685. len = strlen(lpsz) - 1;
  686. tot = 0;
  687. pow = 1;
  688. for(i = len; i >= 0; i--) {
  689. c = (char)toupper(lpsz[i]);
  690. if(c == '0') dig = 0;
  691. else if(c == '1') dig = 1;
  692. else if(c == '2') dig = 2;
  693. else if(c == '3') dig = 3;
  694. else if(c == '4') dig = 4;
  695. else if(c == '5') dig = 5;
  696. else if(c == '6') dig = 6;
  697. else if(c == '7') dig = 7;
  698. else if(c == '8') dig = 8;
  699. else if(c == '9') dig = 9;
  700. else if(c == 'A') dig = 10;
  701. else if(c == 'B') dig = 11;
  702. else if(c == 'C') dig = 12;
  703. else if(c == 'D') dig = 13;
  704. else if(c == 'E') dig = 14;
  705. else if(c == 'F') dig = 15;
  706. else return(-1);
  707. if(pow > 1) {
  708. tot += pow * dig;
  709. }
  710. else {
  711. tot = dig;
  712. }
  713. pow *= 16;
  714. }
  715. return(tot);
  716. }
  717. void
  718. at(
  719. CMD_ARGLIST
  720. )
  721. {
  722. UINT i;
  723. ATOM atom;
  724. CHAR pszGAtomName[128];
  725. CHAR pszLAtomName[128];
  726. CHAR pszCAtomName[128];
  727. CHAR *argv[2], *psz;
  728. CMD_INIT();
  729. ASSERT_WOW_PRESENT;
  730. if(WDParseArgStr(lpArgumentString, argv, 1) == 1) {
  731. atom = (ATOM)LOWORD(WDahtoi(argv[0]));
  732. pszGAtomName[0] = 'G'; // put a random value in 1st byte so we can
  733. pszLAtomName[0] = 'L'; // tell if it got replaced with a '\0' for
  734. pszCAtomName[0] = 'C'; // an "undetermined" type
  735. psz = NULL;
  736. PRINTF("\n%s: ", argv[0]);
  737. if(GlobalGetAtomName(atom, pszGAtomName, 128) > 0) {
  738. PRINTF("<Global atom> \"%s\" ", pszGAtomName);
  739. psz = pszGAtomName;
  740. }
  741. else if(GetAtomName(atom, pszLAtomName, 128) > 0) {
  742. PRINTF("<Local atom> \"%s\" ", pszLAtomName);
  743. psz = pszLAtomName;
  744. }
  745. else if(GetClipboardFormatName((UINT)atom, pszCAtomName, 128) > 0) {
  746. PRINTF("<Clipboard format> \"%s\" ", pszCAtomName);
  747. psz = pszCAtomName;
  748. }
  749. if(psz) {
  750. i = 0;
  751. while(psz[i] && i < 128) {
  752. PRINTF(" %2X", psz[i++] & 0x000000FF);
  753. }
  754. }
  755. else {
  756. PRINTF("<Undetermined type>\n");
  757. PRINTF(" GlobalGetAtomName string: \"%c\" ", pszGAtomName[0]);
  758. for(i = 0; i < 8; i++) {
  759. PRINTF(" %2X", pszGAtomName[i] & 0x000000FF);
  760. }
  761. PRINTF("\n GetAtomName string: \"%c\" ", pszLAtomName[0]);
  762. for(i = 0; i < 8; i++) {
  763. PRINTF(" %2X", pszLAtomName[i] & 0x000000FF);
  764. }
  765. PRINTF("\n GetClipboardFormatName string: \"%c\" ", pszCAtomName[0]);
  766. for(i = 0; i < 8; i++) {
  767. PRINTF(" %2X", pszCAtomName[i] & 0x000000FF);
  768. }
  769. }
  770. PRINTF("\n\n");
  771. }
  772. else {
  773. PRINTF("Usage: at hex_atom_number\n");
  774. }
  775. }
  776. void
  777. ww(
  778. CMD_ARGLIST
  779. )
  780. {
  781. INT h16;
  782. CHAR *argv[2];
  783. CMD_INIT();
  784. ASSERT_WOW_PRESENT;
  785. if(WDParseArgStr(lpArgumentString, argv, 1)) {
  786. if((h16 = WDahtoi(argv[0])) >= 0) {
  787. }
  788. else {
  789. PRINTF("Usage: ww hwnd16\n");
  790. }
  791. }
  792. else {
  793. PRINTF("Usage: ww hwnd16\n");
  794. }
  795. }
  796. void
  797. wc(
  798. CMD_ARGLIST
  799. )
  800. {
  801. PWC pwc;
  802. INT h16;
  803. CHAR *argv[2];
  804. CMD_INIT();
  805. ASSERT_WOW_PRESENT;
  806. if(WDParseArgStr(lpArgumentString, argv, 1)) {
  807. if((h16 = WDahtoi(argv[0])) >= 0){
  808. try {
  809. pwc = (PWC)GetClassLong((HWND)HWND32((HAND16)h16),GCL_WOWWORDS);
  810. // this got moved out of WC
  811. // PRINTF("16:16 WndProc : %08lX\n", pwc->vpfnWndProc);
  812. PRINTF("VPSZ : %08lX\n", pwc->vpszMenu);
  813. PRINTF("PWC : %08lX\n\n", pwc);
  814. }
  815. except (EXCEPTION_ACCESS_VIOLATION == GetExceptionCode()) {
  816. PRINTF("!wow32.wc: Invalid HWND16 %04x\n", h16);
  817. }
  818. }
  819. else {
  820. PRINTF("Usage: wc hwnd16\n");
  821. }
  822. }
  823. else {
  824. PRINTF("Usage: wc hwnd16\n");
  825. }
  826. }
  827. //
  828. // Dump Last Logged APIs
  829. //
  830. void
  831. lastlog(
  832. CMD_ARGLIST
  833. )
  834. {
  835. INT ValueiCircBuffer = CIRC_BUFFERS;
  836. PVOID pTmp = NULL;
  837. INT iCircBuffer;
  838. CHAR achTmp[TMP_LINE_LEN], *pachTmp;
  839. INT i;
  840. CMD_INIT();
  841. ASSERT_CHECKED_WOW_PRESENT;
  842. GETEXPRVALUE(iCircBuffer, "wow32!iCircBuffer", INT);
  843. GETEXPRADDR(pTmp, "wow32!ValueiCircBuffer");
  844. if(pTmp) {
  845. try {
  846. READMEM(pTmp, &ValueiCircBuffer, sizeof(INT));
  847. } except (1) {
  848. ValueiCircBuffer = 0;
  849. }
  850. }
  851. if(ValueiCircBuffer == 0) {
  852. ValueiCircBuffer = CIRC_BUFFERS;
  853. }
  854. GETEXPRVALUE(pachTmp, "wow32!pachTmp", PCHAR);
  855. for (i = iCircBuffer; i >= 0; i--) {
  856. READMEM_XRET(achTmp, &pachTmp[i*TMP_LINE_LEN]);
  857. PRINTF("%s",achTmp);
  858. }
  859. for (i = ValueiCircBuffer-1; i > iCircBuffer; i--) {
  860. READMEM_XRET(achTmp, &pachTmp[i*TMP_LINE_LEN]);
  861. PRINTF("%s",achTmp);
  862. }
  863. return;
  864. }
  865. // creates/closes toggle for logfile for iloglevel logging in c:\ilog.log
  866. void
  867. logfile(
  868. CMD_ARGLIST
  869. )
  870. {
  871. INT nArgs;
  872. CHAR *argv[2], szLogFile[128];
  873. DWORD fLog;
  874. LPVOID lpfLog, lpszLogFile;
  875. CMD_INIT();
  876. ASSERT_CHECKED_WOW_PRESENT;
  877. nArgs = WDParseArgStr(lpArgumentString, argv, 1);
  878. GETEXPRADDR(lpfLog, "wow32!fLog");
  879. READMEM_XRET(fLog, lpfLog);
  880. if(nArgs) {
  881. strcpy(szLogFile, argv[0]);
  882. }
  883. else {
  884. strcpy(szLogFile, "c:\\ilog.log");
  885. }
  886. if(fLog == 0) {
  887. fLog = 2;
  888. PRINTF("\nCreating ");
  889. PRINTF(szLogFile);
  890. PRINTF("\n\n");
  891. }
  892. else {
  893. fLog = 3;
  894. PRINTF("\nClosing logfile\n\n");
  895. }
  896. WRITEMEM_XRET(lpfLog, fLog);
  897. GETEXPRADDR(lpszLogFile, "wow32!szLogFile");
  898. WRITEMEM_N_XRET(lpszLogFile, szLogFile, strlen(szLogFile)+1);
  899. return;
  900. }
  901. //
  902. // Set iLogLevel from Debugger Extension
  903. //
  904. void
  905. setloglevel(
  906. CMD_ARGLIST
  907. )
  908. {
  909. INT iLogLevel;
  910. LPVOID lpAddress;
  911. CMD_INIT();
  912. ASSERT_CHECKED_WOW_PRESENT;
  913. GETEXPRADDR(lpAddress, "wow32!iLogLevel");
  914. iLogLevel = (INT)GetExpression(lpArgumentString);
  915. WRITEMEM_XRET(lpAddress, iLogLevel);
  916. return;
  917. }
  918. //
  919. // Toggle Single Step Trace Mode
  920. //
  921. void
  922. steptrace(
  923. CMD_ARGLIST
  924. )
  925. {
  926. INT localfDebugWait;
  927. LPVOID lpAddress;
  928. CMD_INIT();
  929. ASSERT_CHECKED_WOW_PRESENT;
  930. GETEXPRADDR(lpAddress, "wow32!fDebugWait");
  931. READMEM_XRET(localfDebugWait, lpAddress);
  932. localfDebugWait = ~localfDebugWait;
  933. WRITEMEM_XRET(lpAddress, localfDebugWait);
  934. return;
  935. }
  936. /******* Misc filtering functions ********/
  937. //
  938. // Set Filter Filtering of Specific APIs ON
  939. //
  940. void FilterSpecific( )
  941. {
  942. INT i;
  943. INT fLogFilter;
  944. WORD wfLogFunctionFilter;
  945. LPVOID lpAddress;
  946. PWORD pawfLogFunctionFilter;
  947. WORD wCallId;
  948. SkipToNextWhiteSpace();
  949. if (GetNextToken()) {
  950. wCallId = (WORD)GetExpression(lpArgumentString);
  951. } else {
  952. PRINTF("Please specify an api callid\n");
  953. return;
  954. }
  955. if (!wCallId) {
  956. PRINTF("Invalid callid\n");
  957. return;
  958. }
  959. GETEXPRVALUE(pawfLogFunctionFilter, "wow32!pawfLogFunctionFilter", PWORD);
  960. for (i = 0; i < FILTER_FUNCTION_MAX ; i++) {
  961. // Find Empty Position In Array
  962. READMEM_XRET(wfLogFunctionFilter, &pawfLogFunctionFilter[i]);
  963. if ((wfLogFunctionFilter == 0xffff) ||
  964. (wfLogFunctionFilter == 0x0000)) {
  965. // Add New Filter to Array
  966. wfLogFunctionFilter = wCallId;
  967. WRITEMEM_XRET(&pawfLogFunctionFilter[i], wfLogFunctionFilter);
  968. break;
  969. }
  970. }
  971. GETEXPRADDR(lpAddress, "wow32!fLogFilter");
  972. fLogFilter = 0xffffffff;
  973. WRITEMEM_XRET(lpAddress, fLogFilter);
  974. }
  975. //
  976. // Clear Filter Specific Array
  977. //
  978. void FilterResetSpecific( )
  979. {
  980. INT i;
  981. WORD NEG1 = (WORD) -1;
  982. WORD ZERO = 0;
  983. PWORD pawfLogFunctionFilter;
  984. LPVOID lpAddress;
  985. GETEXPRVALUE(pawfLogFunctionFilter, "wow32!pawfLogFunctionFilter", PWORD);
  986. WRITEMEM_XRET(&pawfLogFunctionFilter[0], NEG1);
  987. for (i=1; i < FILTER_FUNCTION_MAX ; i++) {
  988. WRITEMEM_XRET(&pawfLogFunctionFilter[i], ZERO);
  989. }
  990. GETEXPRADDR(lpAddress, "wow32!iLogFuncFiltIndex");
  991. WRITEMEM_XRET(lpAddress, ZERO);
  992. }
  993. //
  994. // Set TaskID Filtering
  995. //
  996. void FilterTask( )
  997. {
  998. INT fLogTaskFilter;
  999. LPVOID lpAddress;
  1000. SkipToNextWhiteSpace();
  1001. if (GetNextToken()) {
  1002. GETEXPRADDR(lpAddress, "wow32!fLogTaskFilter");
  1003. fLogTaskFilter = (INT)GetExpression(lpArgumentString);
  1004. WRITEMEM_XRET(lpAddress, fLogTaskFilter);
  1005. } else {
  1006. PRINTF("Please specify a task\n");
  1007. }
  1008. return;
  1009. }
  1010. //
  1011. // Turn All filtering ON
  1012. //
  1013. void FilterReset( )
  1014. {
  1015. LPVOID lpAddress;
  1016. INT fLogFilter = 0xffffffff;
  1017. WORD fLogTaskFilter = 0xffff;
  1018. GETEXPRADDR(lpAddress, "wow32!fLogFilter");
  1019. WRITEMEM_XRET(lpAddress, fLogFilter);
  1020. GETEXPRADDR(lpAddress, "wow32!fLogTaskFilter");
  1021. WRITEMEM_XRET(lpAddress, fLogTaskFilter);
  1022. FilterResetSpecific();
  1023. }
  1024. //
  1025. // Disable logging on all classes
  1026. //
  1027. void FilterAll( )
  1028. {
  1029. INT fLogFilter;
  1030. LPVOID lpAddress;
  1031. GETEXPRADDR(lpAddress, "wow32!fLogFilter");
  1032. fLogFilter = 0x00000000;
  1033. WRITEMEM_XRET(lpAddress, fLogFilter);
  1034. }
  1035. VOID
  1036. DumpFilterSettings(
  1037. VOID
  1038. )
  1039. {
  1040. INT i;
  1041. INT fLogFilter;
  1042. WORD wfLogFunctionFilter;
  1043. WORD wfLogTaskFilter;
  1044. LPVOID lpAddress;
  1045. PWORD pawfLogFunctionFilter;
  1046. GETEXPRVALUE(pawfLogFunctionFilter, "wow32!pawfLogFunctionFilter", PWORD);
  1047. GETEXPRVALUE(wfLogTaskFilter, "wow32!fLogTaskFilter", WORD);
  1048. GETEXPRADDR(lpAddress, "wow32!fLogFilter");
  1049. READMEM_XRET(fLogFilter, lpAddress);
  1050. if (!pawfLogFunctionFilter) {
  1051. PRINTF("Symbol 'wow32!pawfLogFunctionFilter' not available\n");
  1052. return;
  1053. }
  1054. PRINTF("\n*** WOW log filter state ***\n");
  1055. if (fLogFilter & FILTER_VERBOSE) {
  1056. PRINTF("Verbose logging is on\n");
  1057. } else {
  1058. PRINTF("Verbose logging is off\n");
  1059. }
  1060. if (wfLogTaskFilter != 0xffff) {
  1061. PRINTF("Only API calls for task %04X will be logged\n", wfLogTaskFilter);
  1062. } else {
  1063. PRINTF("Task filtering is off\n");
  1064. }
  1065. READMEM_XRET(wfLogFunctionFilter, &pawfLogFunctionFilter[0]);
  1066. if (wfLogFunctionFilter != 0xffff) {
  1067. PRINTF("\nOnly API calls with the following CallId's will be logged:\n");
  1068. for (i = 0; i < FILTER_FUNCTION_MAX ; i++) {
  1069. // Find Empty Position In Array
  1070. READMEM_XRET(wfLogFunctionFilter, &pawfLogFunctionFilter[i]);
  1071. if ((wfLogFunctionFilter != 0xffff) &&
  1072. (wfLogFunctionFilter != 0x0000)) {
  1073. PRINTF(" %04X\n", wfLogFunctionFilter);
  1074. }
  1075. }
  1076. PRINTF("\n");
  1077. } else {
  1078. PRINTF("Specific API filtering is off\n");
  1079. }
  1080. if (!(~fLogFilter & ~FILTER_VERBOSE)) {
  1081. PRINTF("API class filtering if off\n");
  1082. } else {
  1083. PRINTF("Logging is disabled for the following API classes:\n");
  1084. }
  1085. if (!(fLogFilter & FILTER_KERNEL)) {
  1086. PRINTF(" KERNEL\n");
  1087. }
  1088. if (!(fLogFilter & FILTER_KERNEL16)) {
  1089. PRINTF(" KERNEL16\n");
  1090. }
  1091. if (!(fLogFilter & FILTER_USER)) {
  1092. PRINTF(" USER\n");
  1093. }
  1094. if (!(fLogFilter & FILTER_GDI)) {
  1095. PRINTF(" GDI\n");
  1096. }
  1097. if (!(fLogFilter & FILTER_KEYBOARD)) {
  1098. PRINTF(" KEYBOARD\n");
  1099. }
  1100. if (!(fLogFilter & FILTER_SOUND)) {
  1101. PRINTF(" SOUND\n");
  1102. }
  1103. if (!(fLogFilter & FILTER_MMEDIA)) {
  1104. PRINTF(" MMEDIA\n");
  1105. }
  1106. if (!(fLogFilter & FILTER_WINSOCK)) {
  1107. PRINTF(" WINSOCK\n");
  1108. }
  1109. if (!(fLogFilter & FILTER_COMMDLG)) {
  1110. PRINTF(" COMMDLG\n");
  1111. }
  1112. PRINTF("\n");
  1113. }
  1114. void
  1115. filter(
  1116. CMD_ARGLIST
  1117. )
  1118. {
  1119. ULONG Mask = 0;
  1120. LPVOID lpAddress;
  1121. CMD_INIT();
  1122. ASSERT_CHECKED_WOW_PRESENT;
  1123. while (' ' == *lpArgumentString) {
  1124. lpArgumentString++;
  1125. }
  1126. if (_strnicmp(lpArgumentString, "kernel16", 8) == 0) {
  1127. Mask = FILTER_KERNEL16;
  1128. } else if (_strnicmp(lpArgumentString, "kernel", 6) == 0) {
  1129. Mask = FILTER_KERNEL;
  1130. } else if (_strnicmp(lpArgumentString, "user", 4) == 0) {
  1131. Mask = FILTER_USER;
  1132. } else if (_strnicmp(lpArgumentString, "gdi", 3) == 0) {
  1133. Mask = FILTER_GDI;
  1134. } else if (_strnicmp(lpArgumentString, "keyboard", 8) == 0) {
  1135. Mask = FILTER_KEYBOARD;
  1136. } else if (_strnicmp(lpArgumentString, "sound", 5) == 0) {
  1137. Mask = FILTER_SOUND;
  1138. } else if (_strnicmp(lpArgumentString, "mmedia", 6) == 0) {
  1139. Mask = FILTER_MMEDIA;
  1140. } else if (_strnicmp(lpArgumentString, "winsock", 7) == 0) {
  1141. Mask = FILTER_WINSOCK;
  1142. } else if (_strnicmp(lpArgumentString, "commdlg", 7) == 0) {
  1143. Mask = FILTER_COMMDLG;
  1144. } else if (_strnicmp(lpArgumentString, "callid", 6) == 0) {
  1145. FilterSpecific();
  1146. } else if (_strnicmp(lpArgumentString, "task", 4) == 0) {
  1147. FilterTask();
  1148. } else if (_strnicmp(lpArgumentString, "*", 1) == 0) {
  1149. FilterAll();
  1150. } else if (_strnicmp(lpArgumentString, "reset", 5) == 0) {
  1151. FilterReset();
  1152. } else if (_strnicmp(lpArgumentString, "verbose", 7) == 0) {
  1153. Mask = FILTER_VERBOSE;
  1154. } else {
  1155. if (*lpArgumentString != 0) {
  1156. PRINTF("Invalid argument to Filter command: '%s'\n", lpArgumentString);
  1157. return;
  1158. }
  1159. }
  1160. if (Mask) {
  1161. INT fLogFilter;
  1162. GETEXPRADDR(lpAddress, "wow32!fLogFilter");
  1163. if (!lpAddress) {
  1164. PRINTF("Symbol 'wow32!fLogFilter' not available\n");
  1165. } else {
  1166. READMEM_XRET(fLogFilter, lpAddress);
  1167. if ((fLogFilter & Mask) == 0) {
  1168. fLogFilter |= Mask;
  1169. } else {
  1170. fLogFilter &= ~Mask;
  1171. }
  1172. WRITEMEM_XRET(lpAddress, fLogFilter);
  1173. }
  1174. }
  1175. DumpFilterSettings();
  1176. }
  1177. void
  1178. cia(
  1179. CMD_ARGLIST
  1180. )
  1181. {
  1182. CURSORICONALIAS cia;
  1183. PVOID lpAddress;
  1184. INT maxdump = 500;
  1185. CMD_INIT();
  1186. ASSERT_WOW_PRESENT;
  1187. GETEXPRADDR(lpAddress, "wow32!lpCIAlias");
  1188. READMEM_XRET(lpAddress, lpAddress);
  1189. if (!lpAddress) {
  1190. PRINTF("Cursor/Icon alias list is empty.\n");
  1191. } else {
  1192. PRINTF("Alias tp H16 H32 inst mod task res szname\n");
  1193. READMEM_XRET(cia, lpAddress);
  1194. while ((lpAddress != NULL) && --maxdump) {
  1195. if (cia.fInUse) {
  1196. PRINTF("%08X", lpAddress);
  1197. PRINTF(" %02X", cia.flType);
  1198. PRINTF(" %04X", cia.h16);
  1199. PRINTF(" %08X", cia.h32);
  1200. PRINTF(" %04X", cia.hInst16);
  1201. PRINTF(" %04X", cia.hMod16);
  1202. PRINTF(" %04X", cia.hTask16);
  1203. PRINTF(" %04X", cia.hRes16);
  1204. PRINTF(" %08X\n", cia.lpszName);
  1205. }
  1206. lpAddress = cia.lpNext;
  1207. READMEM_XRET(cia, lpAddress);
  1208. }
  1209. if (!maxdump) {
  1210. PRINTF("Dump ended prematurely - possible infinite loop\n");
  1211. }
  1212. }
  1213. }
  1214. //WARNING: This structure must match ENTRY in ntgdi\inc\hmgshare.h
  1215. typedef struct _ENTRYWOW
  1216. {
  1217. LONG l1;
  1218. LONG l2;
  1219. USHORT FullUnique;
  1220. USHORT us1;
  1221. LONG l3;
  1222. } ENTRYWOW, *PENTRYWOW;
  1223. // converts an hGDI16 to the equivalent hGDI32
  1224. void
  1225. hgdi(
  1226. CMD_ARGLIST
  1227. )
  1228. {
  1229. ULONG h16, h32;
  1230. PENTRYWOW pEntry;
  1231. ENTRYWOW Entry;
  1232. LPVOID lpAddress;
  1233. CMD_INIT();
  1234. ASSERT_WOW_PRESENT;
  1235. lpAddress = (PENTRYWOW)EXPRESSION("wow32!gpGDIHandleInfo");
  1236. READMEM_XRET(pEntry, lpAddress);
  1237. h16 = (ULONG) WDahtoi(lpArgumentString);
  1238. PRINTF("WOW 16-bit GDI Handle: %04X ", h16);
  1239. h16 = h16 >> 2;
  1240. pEntry = &pEntry[h16];
  1241. if(!READMEM((LPVOID) (pEntry), &Entry, sizeof(ENTRYWOW))) {
  1242. PRINTF("Failure reading ENTRYWOW At %08lX\n", pEntry);
  1243. return;
  1244. }
  1245. h32 = h16 | (Entry.FullUnique << 16);
  1246. PRINTF("32-bit GDI Handle: %08X\n", h32);
  1247. return;
  1248. }
  1249. #include "..\wow32\wdde.h"
  1250. //typedef struct _HDDE {
  1251. // struct _HDDE *pDDENext; // pointer to next hDDE alias
  1252. // HAND16 To_hwnd; // window that will receive this message
  1253. // HAND16 From_hwnd; // window that sent this message
  1254. // HAND16 hMem16; // handle of WOW app allocated 16 bit object
  1255. // HANDLE hMem32; // handle of WOW allocated 32 bit object
  1256. // WORD DdeMsg; // message id
  1257. // WORD DdeFormat; // message format
  1258. // WORD DdeFlags; // indicates if it is metafile handle
  1259. // HAND16 h16; // original h16 for bad apps doing EXECUTE
  1260. //} HDDE, *PHDDE;
  1261. // dumps the list of dde 16-32 memory pairs
  1262. void
  1263. ddemem(
  1264. CMD_ARGLIST
  1265. )
  1266. {
  1267. PHDDE phdde;
  1268. HDDE hdde;
  1269. LPVOID lpAddress;
  1270. CMD_INIT();
  1271. ASSERT_WOW_PRESENT;
  1272. lpAddress = (PENTRYWOW)EXPRESSION("wow32!phDDEFirst");
  1273. READMEM_XRET(phdde, lpAddress);
  1274. while(phdde) {
  1275. if(!READMEM((LPVOID) (phdde), &hdde, sizeof(HDDE))) {
  1276. PRINTF("Failure reading HDDE At %08lX\n", phdde);
  1277. return;
  1278. }
  1279. PRINTF(" PHDDE: %08X\n", phdde);
  1280. PRINTF(" To_hwnd16: %04X\n", hdde.To_hwnd);
  1281. PRINTF("From_hwnd16: %04X\n", hdde.From_hwnd);
  1282. PRINTF(" hMem16: %04X\n", hdde.hMem16);
  1283. PRINTF(" hMem32: %04X\n", hdde.hMem32);
  1284. PRINTF(" DdeMsg: %04X\n", hdde.DdeMsg);
  1285. PRINTF(" DdeFormat: %04X\n", hdde.DdeFormat);
  1286. PRINTF(" DdeFlags: %04X\n", hdde.DdeFlags);
  1287. PRINTF(" Orig h16: %04X\n\n", hdde.h16);
  1288. phdde = hdde.pDDENext;
  1289. }
  1290. return;
  1291. }
  1292. // must match struct in "..\wow32\wow32.h"
  1293. #ifndef DEBUG
  1294. #define ML_MALLOC_W 0x00000001
  1295. #define ML_MALLOC_W_ZERO 0x00000002
  1296. #define ML_REALLOC_W 0x00000004
  1297. #define ML_MALLOC_WTYPE (ML_MALLOC_W | ML_MALLOC_W_ZERO | ML_REALLOC_W)
  1298. #define ML_GLOBALALLOC 0x00000010
  1299. #define ML_GLOBALREALLOC 0x00000020
  1300. #define ML_GLOBALTYPE (ML_GLOBALREALLOC | ML_GLOBALALLOC)
  1301. typedef struct _tagMEMLEAK {
  1302. struct _tagMEMLEAK *lpmlNext;
  1303. PVOID lp;
  1304. DWORD size;
  1305. UINT fHow;
  1306. ULONG Count;
  1307. PVOID CallersAddress;
  1308. } MEMLEAK, *LPMEMLEAK;
  1309. #endif
  1310. void
  1311. gmem(
  1312. CMD_ARGLIST
  1313. )
  1314. {
  1315. LPMEMLEAK lpml;
  1316. MEMLEAK ml;
  1317. LPVOID lpAddress;
  1318. CMD_INIT();
  1319. ASSERT_WOW_PRESENT;
  1320. // DbgBreakPoint();
  1321. lpAddress = (PENTRYWOW)EXPRESSION("wow32!lpMemLeakStart");
  1322. READMEM_XRET(lpml, lpAddress);
  1323. while(lpml) {
  1324. if(!READMEM((LPVOID) (lpml), &ml, sizeof(MEMLEAK))) {
  1325. PRINTF("Failure reading lpml At %08lX\n", lpml);
  1326. return;
  1327. }
  1328. PRINTF(" lp: %08X\n", ml.lp);
  1329. PRINTF(" Size: %08X\n", ml.size);
  1330. PRINTF(" Alloc'd by: %08X\n", ml.CallersAddress);
  1331. PRINTF("Alloc Count: %08X\n", ml.Count);
  1332. PRINTF("How Alloc'd: ");
  1333. if(ml.fHow & ML_MALLOC_W) PRINTF("malloc_w ");
  1334. if(ml.fHow & ML_MALLOC_W_ZERO) PRINTF("malloc_w_zero ");
  1335. if(ml.fHow & ML_REALLOC_W) PRINTF("realloc_w ");
  1336. if(ml.fHow & ML_GLOBALALLOC) PRINTF("GlobalAlloc ");
  1337. if(ml.fHow & ML_GLOBALREALLOC) PRINTF("GlobalReAlloc ");
  1338. PRINTF("\n\n");
  1339. lpml = ml.lpmlNext;
  1340. }
  1341. return;
  1342. }