|
|
/******************************Module*Header*******************************\
* Module Name: wow.c * * This file is for debugging tools and extensions. * * Created: 24-Jan-1992 * Author: John Colleran * * History: * Feb 17 92 Matt Felton (mattfe) lots of additional exentions for filtering * Jul 13 92 (v-cjones) Added API & MSG profiling debugger extensions, fixed * other extensions to handle segment motion correctly, * & cleaned up the file in general * Jan 3 96 Neil Sandlin (neilsa) integrated this routine into vdmexts * * Copyright (c) 1992 Microsoft Corporation \**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include <tdb16.h>
#include <wmdisp32.h>
#include <wcuricon.h>
#include <wucomm.h>
#include <doswow.h>
//
// get the compatibility flag values & string names
//
typedef struct _tagWOWCFDATA { LPSZ lpszCFName; DWORD dwVal; } WOWCFDATA;
// allows us to grab the string tables only from mvdm\inc\wowcmpat.h
#define _VDMEXTS_CFLAGS 1
// exposes the compatibility flag strings & values in wowcmpat.h
#define _VDMEXTS_CF 1
WOWCFDATA CFData[] = { #include "wowcmpat.h"
{"", 0x00000000} }; #undef _VDMEXTS_CF
// exposes the EXTENDED compatibility flag strings & values in wowcmpat.h
#define _VDMEXTS_CFEX 1
WOWCFDATA CFDataEx[] = { #include "wowcmpat.h"
{"", 0x00000000} }; #undef _VDMEXTS_CFEX
// exposes the OLD Win3.x compatibility flag strings & values in wowcmpat.h
#define _VDMEXTS_CF31 1
WOWCFDATA CFData31[] = { #include "wowcmpat.h"
{"", 0x00000000} }; #undef _VDMEXTS_CF31
// exposes the IME compatibility flag strings & values in wowcmpat.h
#if FE_SB
#define _VDMEXTS_CF_IME 1
WOWCFDATA CFDataIME[] = { #include "wowcmpat.h"
{"", 0x00000000} }; #endif // FE_SB
#undef _VDMEXTS_CF_IME
#undef _VDMEXTS_CFLAGS
#define MALLOC(cb) HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, cb)
#define FREE(addr) HeapFree(GetProcessHeap(), 0, addr)
//
// Local function prototypes
//
INT WDahtoi(LPSZ lpsz);
INT WDParseArgStr(LPSZ lpszArgStr, CHAR **argv, INT iMax) { /*
* Parse a string looking for SPACE, TAB, & COMMA as delimiters * INPUT: * lpszArgStr - ptr to input arg string * iMax - maximum number of substrings to parse * OUTPUT: * argv - ptrs to strings * * RETURN: # of vectors in argv * NOTE: substrings are converted to uppercase */ INT nArgs; BOOL bStrStart;
nArgs = 0; bStrStart = 1; while( *lpszArgStr ) { if( (*lpszArgStr == ' ') || (*lpszArgStr == '\t') || (*lpszArgStr == ',') ) { *lpszArgStr = '\0'; bStrStart = 1; } else { if( bStrStart ) { if( nArgs >= iMax ) { break; } argv[nArgs++] = lpszArgStr; bStrStart = 0; } *lpszArgStr = (CHAR)toupper(*lpszArgStr); } lpszArgStr++; } return(nArgs); }
VOID dwp( CMD_ARGLIST ) { PWOWPORT pwp; WOWPORT wp;
CMD_INIT(); ASSERT_WOW_PRESENT;
while (' ' == lpArgumentString[0]) { lpArgumentString++; }
pwp = (PWOWPORT) WDahtoi(lpArgumentString);
if (NULL == pwp) { PRINTF("Can't read WOWPORT structure!\n\n"); return; }
PRINTF("Dump of WOWPORT structure at 0x%x:\n\n", (unsigned)pwp); try {
READMEM_XRET(wp, pwp);
} except (EXCEPTION_ACCESS_VIOLATION == GetExceptionCode() ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
PRINTF("Access violation reading WOWPORT structure!\n\n"); return; }
PRINTF("idComDev 0x%x\n", (unsigned)wp.idComDev); PRINTF("h32 0x%x\n", (unsigned)wp.h32); PRINTF("hREvent 0x%x\n", (unsigned)wp.hREvent); PRINTF("csWrite OwningThread 0x%x RecursionCount 0x%x\n", (unsigned)wp.csWrite.OwningThread, (unsigned)wp.csWrite.RecursionCount); PRINTF("pchWriteHead 0x%x\n", (unsigned)wp.pchWriteHead); PRINTF("pchWriteTail 0x%x\n", (unsigned)wp.pchWriteTail); PRINTF("cbWriteFree 0x%x\n", (unsigned)wp.cbWriteFree); PRINTF("cbWritePending 0x%x\n", (unsigned)wp.cbWriteFree); PRINTF("pchWriteBuf 0x%x\n", (unsigned)wp.pchWriteBuf); PRINTF("cbWriteBuf 0x%x\n", (unsigned)wp.cbWriteBuf); PRINTF("hWriteThread 0x%x\n", (unsigned)wp.hWriteThread); PRINTF("hWriteEvent 0x%x\n", (unsigned)wp.hWriteEvent); PRINTF("OverLap hEvent 0x%x\n", (unsigned)wp.olWrite.hEvent); PRINTF("fWriteDone %s\n", wp.fWriteDone ? "TRUE" : "FALSE"); PRINTF("cbWritten 0x%x\n", (unsigned)wp.fWriteDone); PRINTF("dwThreadID 0x%x\n", (unsigned)wp.dwThreadID); PRINTF("dwErrCode 0x%x\n", (unsigned)wp.dwErrCode); PRINTF("COMSTAT addr: 0x%x\n", (unsigned)(((char *)&wp.cs - (char *)&wp) + (char *)pwp)); PRINTF("fChEvt 0x%x\n", (unsigned)wp.fChEvt); PRINTF("pdcb16 0x%x\n", (unsigned)wp.pdcb16); PRINTF("fUnGet %s\n", wp.fUnGet ? "TRUE" : "FALSE"); PRINTF("cUnGet 0x%x (%c)\n", (unsigned)wp.cUnGet, wp.cUnGet); PRINTF("hMiThread 0x%x\n", (unsigned)wp.hMiThread); PRINTF("fClose %s\n", wp.fClose ? "TRUE" : "FALSE"); PRINTF("dwComDEB16 0x%x\n", (unsigned)wp.dwComDEB16); PRINTF("lpComDEB16 0x%x\n", (unsigned)wp.lpComDEB16); PRINTF("cbInQ 0x%x\n", (unsigned)wp.cbInQ); PRINTF("RLSDTimeout 0x%x\n", (unsigned)wp.RLSDTimeout); PRINTF("CTSTimeout 0x%x\n", (unsigned)wp.CTSTimeout); PRINTF("DSRTimeout 0x%x\n", (unsigned)wp.DSRTimeout);
PRINTF("\n");
return; }
//
// Dump Taskinfo;
//
// If no argument, dump all wow tasks.
// If 0, dump current WOW task
// Else dump the specifies task {which is thread-id as shown by
// ~ command under ntsd like 37.6b so thread-id is 6b)
//
void DumpTaskInfo (ptd,mode) PTD ptd; int mode; {
ULONG Base; TDB tdb; BOOL b; char ModName[9]; int i; BOOL fTDBValid = TRUE;
Base = GetInfoFromSelector( ptd->htask16, PROT_MODE, NULL ); b = READMEM( (LPVOID) (Base+GetIntelBase()), &tdb, sizeof(tdb));
if ( !b ) { fTDBValid = FALSE; }
for (b=FALSE, i=0; i<8; i++) { if (!fTDBValid || !tdb.TDB_ModName[i]) { b = TRUE; } if (b) { ModName[i] = ' '; } else { ModName[i] = tdb.TDB_ModName[i]; } } ModName[i] = 0;
PRINTF("%.4x",ptd->dwThreadID); PRINTF(" %.4x:%.4x",HIWORD(ptd->vpStack),LOWORD(ptd->vpStack)); PRINTF(" %.4x", ptd->htask16); PRINTF(" %.4x", ptd->hInst16); PRINTF(" %.4x", ptd->hMod16); PRINTF(" %8s",ModName); PRINTF(" %.8x",ptd->dwWOWCompatFlags); PRINTF(" %.8x",ptd->hThread); if (fTDBValid) { PRINTF(" %.8x",tdb.TDB_flags); PRINTF(" %.3x",tdb.TDB_ExpWinVer); PRINTF(" %.4x:%.4x\n",HIWORD(tdb.TDB_DTA),LOWORD(tdb.TDB_DTA)); } else { PRINTF(" Failure reading TDB at %X\n", Base ); } }
void DumpTask( void ) { VDMCONTEXT ThreadContext; DWORD ThreadId; PTD ptd,ptdHead; TD td; int mode; BOOL b,fFound=FALSE;
mode = GetContext( &ThreadContext );
ThreadId = (DWORD)-1; // Assume Dump All Tasks
if (GetNextToken()) { ThreadId = (DWORD) EXPRESSION( lpArgumentString ); }
ptdHead = (PTD)EXPRESSION("wow32!gptdTaskHead");
// get the pointer to first TD
b = READMEM((LPVOID) (ptdHead), &ptd, sizeof(DWORD));
if ( !b ) { PRINTF("Failure reading gptdTaskHead at %08lX\n", ptdHead ); return; }
PRINTF("Thrd Stack task inst hmod Module Compat hThread Tdbflags Ver Dta\n");
// enumerate td list to find the match(es)
while (ptd) { b = READMEM((LPVOID) (ptd), &td, sizeof(TD)); if ( !b ) { PRINTF("Failure reading TD At %08lX\n", ptd ); return; }
if (ThreadId == -1) { DumpTaskInfo (&td,mode); fFound = TRUE; } else { if (ThreadId == td.dwThreadID) { DumpTaskInfo (&td,mode); fFound = TRUE; break; } } ptd = td.ptdNext; }
if (!fFound) { if (ThreadId == -1) { PRINTF("No WOW Task Found.\n"); } else PRINTF("WOW Task With Thread Id = %02x Not Found.\n",ThreadId); } return; }
VOID DumpTaskVerbose( ) // dump WOW32 task database entry
{
TD td; PTD ptd; INT i; PWOAINST pWOA, pWOALast; PTDB ptdb; BOOL fAll = FALSE; BYTE SavedByte;
ptd = (PTD) WDahtoi(lpArgumentString);
if (!ptd) {
fAll = TRUE; GETEXPRVALUE(ptd, "wow32!gptdTaskHead", PTD); if (!ptd) { Print("Could not get wow32!gptdTaskHead"); return; } Print("Dump WOW task list\n\n");
} else if ((ULONG)ptd < 65536) { ULONG dwId = (ULONG) ptd;
// Here, I'm making the assumption that if the argument is a value
// that is less than 64k, then it can't be a TD address.
// So, try it out as a thread id
GETEXPRVALUE(ptd, "wow32!gptdTaskHead", PTD); if (!ptd) { Print("Could not get wow32!gptdTaskHead"); return; }
while(ptd) { READMEM_XRET(td, ptd); if (td.dwThreadID == dwId) { break; }
ptd = td.ptdNext; } if (!ptd) { Print("Could not find thread id %s\n", lpArgumentString); return; } }
do {
Print("Dump of TD at 0x%08x:\n\n", (unsigned)ptd);
READMEM_XRET(td, ptd);
Print("vpStack %04x:%04x\n", HIWORD(td.vpStack), LOWORD(td.vpStack)); Print("vpCBStack %04x:%04x\n", HIWORD(td.vpCBStack), LOWORD(td.vpCBStack)); Print("cStackAlloc16 0x%08x\n", td.cStackAlloc16); Print("CommDlgTd (ptr) 0x%08x\n", td.CommDlgTd); Print("ptdNext 0x%08x\n", td.ptdNext); Print("dwFlags 0x%08x\n", td.dwFlags);
//
// Dump symbolic names for TDF_ manifests
//
if (td.dwFlags & TDF_IGNOREINPUT) { Print(" TDF_IGNOREINPUT\n"); } if (td.dwFlags & TDF_FORCETASKEXIT) { Print(" TDF_FORCETASKEXIT\n"); } if (td.dwFlags & TDF_TASKCLEANUPDONE) { Print(" TDF_TASKCLEANUPDONE\n"); } Print("VDMInfoiTaskID 0x%08x\n", td.VDMInfoiTaskID);
//
// Dump CommDlgTd structure if present
//
if (td.CommDlgTd) {
COMMDLGTD CommDlgTd; BOOL fCopySuccessful = TRUE;
READMEM_XRET(CommDlgTd, td.CommDlgTd);
if (fCopySuccessful) {
Print("\n"); Print(" Dump of CommDlgTd at 0x%08x:\n", td.CommDlgTd); Print(" hdlg 0x%04x\n", CommDlgTd.hdlg); Print(" vpData %04x:%04x\n", HIWORD(CommDlgTd.vpData), LOWORD(CommDlgTd.vpData)); Print(" pData32 0x%08x\n", CommDlgTd.pData32); Print(" vpfnHook %04x:%04x\n", HIWORD(CommDlgTd.vpfnHook), LOWORD(CommDlgTd.vpfnHook)); Print(" vpfnSetupHook (union) %04x:%04x\n", HIWORD(CommDlgTd.vpfnSetupHook), LOWORD(CommDlgTd.vpfnSetupHook)); Print(" pRes (union) 0x%08x\n", CommDlgTd.pRes); Print(" SetupHwnd 0x%04x\n", CommDlgTd.SetupHwnd); Print(" Previous 0x%08x\n", CommDlgTd.Previous); Print(" Flags 0x%08x\n", CommDlgTd.Flags);
//
// Dump symbolic names for WOWCD_ manifests
//
if (CommDlgTd.Flags & WOWCD_ISCHOOSEFONT) { Print(" WOWCD_ISCHOOSEFONT\n"); } if (CommDlgTd.Flags & WOWCD_ISOPENFILE) { Print(" WOWCD_ISOPENFILE\n"); }
Print("\n");
} }
Print("dwWOWCompatFlags 0x%08x\n", td.dwWOWCompatFlags);
//
// Dump symbolic names for WOWCF_ manifests
//
if (td.dwWOWCompatFlags) { i = 0; while(CFData[i].dwVal) {
if (td.dwWOWCompatFlags & CFData[i].dwVal) { Print(" %s\n", CFData[i].lpszCFName); }
i++; } }
Print("dwWOWCompatFlagsEx 0x%08x\n", td.dwWOWCompatFlagsEx);
//
// Dump symbolic names for WOWCFEX_ manifests
//
if (td.dwWOWCompatFlagsEx) { i = 0; while(CFDataEx[i].dwVal) {
if (td.dwWOWCompatFlagsEx & CFDataEx[i].dwVal) { Print(" %s\n", CFDataEx[i].lpszCFName); }
i++; } }
#if FE_SB
Print("dwWOWCompatFlags2 0x%08x\n", td.dwWOWCompatFlags2);
//
// Dump symbolic names for WOWCFEX_ manifests
//
if (td.dwWOWCompatFlags2) { i = 0; while(CFDataIME[i].dwVal) {
if (td.dwWOWCompatFlags2 & CFDataIME[i].dwVal) { Print(" %s\n", CFDataIME[i].lpszCFName); }
i++; } } #endif
Print("dwThreadID 0x%08x\n", td.dwThreadID); Print("hThread 0x%08x\n", td.hThread); Print("hIdleHook 0x%08x\n", td.hIdleHook); Print("hrgnClip 0x%08x\n", td.hrgnClip); Print("ulLastDesktophDC 0x%08x\n", td.ulLastDesktophDC); Print("pWOAList 0x%08x\n", td.pWOAList);
//
// Dump WOATD structure if present
//
pWOALast = NULL; pWOA = td.pWOAList;
while (pWOA && pWOA != pWOALast) {
union { WOAINST WOA; char buf[128+2+16]; } u;
READMEM_XRET(u.buf, pWOA);
Print("\n"); Print(" Dump of WOAINST at 0x%08x:\n", pWOA); Print(" pNext 0x%08x\n", u.WOA.pNext); Print(" ptdWOA 0x%08x\n", u.WOA.ptdWOA); Print(" dwChildProcessID 0x%08x\n", u.WOA.dwChildProcessID); Print(" hChildProcess 0x%08x\n", u.WOA.hChildProcess); Print(" szModuleName %s\n", u.WOA.szModuleName); Print("\n");
pWOALast = pWOA; pWOA = u.WOA.pNext;
}
Print("htask16 0x%04x\n", td.htask16, td.htask16);
//
// Dump the most interesting TDB fields
//
if (ptdb = (PTDB) (GetInfoFromSelector(td.htask16, PROT_MODE, NULL) + GetIntelBase())) {
TDB tdb;
READMEM_XRET(tdb, ptdb);
Print("\n"); Print(" Highlights of TDB at 0x%08x:\n", ptdb);
if (tdb.TDB_sig != TDB_SIGNATURE) { Print(" TDB_sig signature is 0x%04x instead of 0x%04x, halting dump.\n", tdb.TDB_sig, TDB_SIGNATURE); } else {
PDOSPDB pPDB; DOSPDB PDB; PBYTE pJFT; BYTE JFT[256]; WORD cbJFT; PDOSSF pSFTHead, pSFTHeadCopy; DOSSF SFTHead; PDOSSFT pSFT; WORD fh; WORD SFN; WORD i; DWORD cb; DWORD dwCompatFlags; PDOSWOWDATA pDosWowData; DOSWOWDATA DosWowData;
SavedByte = tdb.TDB_ModName[8]; tdb.TDB_ModName[8] = 0; Print(" Module name \"%s\"\n", tdb.TDB_ModName); tdb.TDB_ModName[8] = SavedByte;
Print(" ExpWinVer 0x%04x\n", tdb.TDB_ExpWinVer);
dwCompatFlags = *(DWORD *)(&tdb.TDB_CompatFlags); Print(" CompatFlags 0x%08x\n", dwCompatFlags);
if (dwCompatFlags) { //
// Dump symbolic names for GACF_ manifests
//
i = 0; while(CFData31[i].dwVal) {
if (dwCompatFlags & CFData31[i].dwVal) { Print(" %s\n", CFData31[i].lpszCFName); }
i++; } }
Print(" Directory \"%s\"\n", tdb.TDB_LFNDirectory); Print(" PDB (aka PSP) 0x%04x\n", tdb.TDB_PDB);
pPDB = (PDOSPDB) (GetInfoFromSelector(tdb.TDB_PDB, PROT_MODE, NULL) + GetIntelBase()); READMEM_XRET(PDB, pPDB);
Print(" segEnvironment 0x%04x\n", PDB.PDB_environ);
//
// Dump open file handle info
//
pJFT = (PBYTE) (GetIntelBase() + (HIWORD(PDB.PDB_JFN_Pointer)<<4) + LOWORD(PDB.PDB_JFN_Pointer));
cbJFT = PDB.PDB_JFN_Length;
Print(" JFT %04x:%04x (%08x), size 0x%x\n", HIWORD(PDB.PDB_JFN_Pointer), LOWORD(PDB.PDB_JFN_Pointer), pJFT, cbJFT);
try { READMEM(pJFT, JFT, cbJFT); } except (1) { Print("Unable to read JFT from 0x%08x!\n", pJFT); return; }
for (fh = 0; fh < cbJFT; fh++) {
if (JFT[fh] != 0xFF) {
//
// Walk the SFT chain to find Nth entry
// where N == JFT[fh]
//
SFN = 0; i = 0;
GETEXPRVALUE(pSFTHead, "ntvdm!pSFTHead", PDOSSF);
GETEXPRADDR(pDosWowData, "wow32!DosWowData"); READMEM_XRET(DosWowData, pDosWowData);
if ((DWORD)pSFTHead != DosWowData.lpSftAddr) { Print("ntvdm!pSFTHead is 0x%08x, DosWowData.lpSftAddr ix 0x%08x.\n", pSFTHead, DosWowData.lpSftAddr); }
try { READMEM(pSFTHead, &SFTHead, sizeof(SFTHead)); } except (1) { Print("Unable to read SFTHead from 0x%08x!\n", pSFTHead); return; }
cb = sizeof(DOSSF) + SFTHead.SFCount * sizeof(DOSSFT); pSFTHeadCopy = MALLOC(cb);
// Print("First DOSSF at 0x%08x, SFCount 0x%x, SFLink 0x%08x.\n",
// pSFTHead, SFTHead.SFCount, SFTHead.SFLink);
try { READMEM(pSFTHead, pSFTHeadCopy, cb); } except (1) { Print("Unable to read SFTHead from 0x%08x!\n", pSFTHead); return; }
pSFT = (PDOSSFT) &(pSFTHeadCopy->SFTable);
while (SFN < JFT[fh]) { SFN++; i++; pSFT++; if (i >= pSFTHeadCopy->SFCount) {
if (LOWORD(pSFTHeadCopy->SFLink) == 0xFFFF) { SFN = JFT[fh] - 1; break; }
pSFTHead = (PDOSSF) (GetIntelBase() + (HIWORD(pSFTHeadCopy->SFLink)<<4) + LOWORD(pSFTHeadCopy->SFLink));
i = 0;
try { READMEM(pSFTHead, &SFTHead, sizeof(SFTHead)); } except (1) { Print("Unable to read SFTHead from 0x%08x!\n", pSFTHead); return; }
cb = sizeof(DOSSF) + SFTHead.SFCount * sizeof(DOSSFT); FREE(pSFTHeadCopy); pSFTHeadCopy = MALLOC(cb);
// Print("Next DOSSF at 0x%08x, SFCount 0x%x, SFLink 0x%08x.\n",
// pSFTHead, SFTHead.SFCount, SFTHead.SFLink);
try { READMEM(pSFTHead, pSFTHeadCopy, cb); } except (1) { Print("Unable to read SFTHead from 0x%08x!\n", pSFTHead); return; }
pSFT = (PDOSSFT) &(pSFTHeadCopy->SFTable); } }
if (SFN != JFT[fh]) { Print(" Unable to local SFT entry 0x%x for handle 0x%x.\n", pJFT[fh], fh); } else { Print(" Handle 0x%02x SFN 0x%02x Refs 0x%x Mode 0x%04x Flags 0x%04x ", fh, SFN, pSFT->SFT_Ref_Count, pSFT->SFT_Mode, pSFT->SFT_Flags); if (!pSFT->SFT_Flags & 0x80) { Print("NT Handle 0x%08x\n", pSFT->SFT_NTHandle); } else { Print("(NTDOS device)\n"); } }
FREE(pSFTHeadCopy); } }
Print("\n"); }
}
Print("hInst16 0x%04x\n", td.hInst16); Print("hMod16 0x%04x\n", td.hMod16);
Print("\n");
ptd = td.ptdNext;
} while (fAll && ptd);
return; }
void dt( CMD_ARGLIST ) { CMD_INIT(); ASSERT_WOW_PRESENT;
if (!GetNextToken()) { DumpTask(); } else { if ((lpArgumentString[0] == '-') && (tolower(lpArgumentString[1]) == 'v')) { SkipToNextWhiteSpace(); GetNextToken(); DumpTaskVerbose(); } else { DumpTaskVerbose(); } }
}
VOID ddte( CMD_ARGLIST ) // dump dispatch table entry
{ W32 dte; PW32 pdte; char szW32[32]; char szSymbol[256]; DWORD dwOffset;
CMD_INIT(); ASSERT_WOW_PRESENT;
while (' ' == lpArgumentString[0]) { lpArgumentString++; }
pdte = (PW32) WDahtoi(lpArgumentString);
if (pdte) {
PRINTF("Dump of dispatch table entry at 0x%08x:\n\n", (unsigned)pdte);
} else {
GETEXPRADDR(pdte, "wow32!aw32WOW"); PRINTF("Dump of first dispatch table entry at 0x%08x:\n\n", (unsigned)pdte);
}
try {
READMEM_XRET(dte, pdte);
if (dte.lpszW32) { READMEM_XRET(szW32, dte.lpszW32); dte.lpszW32 = szW32; szW32[sizeof(szW32)-1] = '\0'; }
} except (1) {
PRINTF("Exception 0x%08x reading dispatch table entry at 0x%08x!\n\n", GetExceptionCode(), pdte); return; }
PRINTF("Dispatches to address 0x%08x, ", (unsigned)dte.lpfnW32); PRINTF("supposedly function '%s'.\n", dte.lpszW32);
szSymbol[0] = '\0'; GetSymbol((LPVOID)dte.lpfnW32, szSymbol, &dwOffset);
PRINTF("Debugger finds symbol '%s' for that address.\n", szSymbol); PRINTF("\n");
return; }
PSTR aszWOWCLASS[] = { "UNKNOWN", "WIN16", "BUTTON", "COMBOBOX", "EDIT", "LISTBOX", "MDICLIENT", "SCROLLBAR", "STATIC", "DESKTOP", "DIALOG", "MENU", "ACCEL", "CURSOR", "ICON", "DC", "FONT", "METAFILE", "RGN", "BITMAP", "BRUSH", "PALETTE", "PEN", "OBJECT" };
INT WDahtoi(LPSZ lpsz) { char c; int tot, pow, len, dig, i;
len = strlen(lpsz) - 1; tot = 0; pow = 1;
for(i = len; i >= 0; i--) {
c = (char)toupper(lpsz[i]);
if(c == '0') dig = 0; else if(c == '1') dig = 1; else if(c == '2') dig = 2; else if(c == '3') dig = 3; else if(c == '4') dig = 4; else if(c == '5') dig = 5; else if(c == '6') dig = 6; else if(c == '7') dig = 7; else if(c == '8') dig = 8; else if(c == '9') dig = 9; else if(c == 'A') dig = 10; else if(c == 'B') dig = 11; else if(c == 'C') dig = 12; else if(c == 'D') dig = 13; else if(c == 'E') dig = 14; else if(c == 'F') dig = 15; else return(-1);
if(pow > 1) { tot += pow * dig; } else { tot = dig; } pow *= 16; } return(tot); }
void at( CMD_ARGLIST ) { UINT i; ATOM atom; CHAR pszGAtomName[128]; CHAR pszLAtomName[128]; CHAR pszCAtomName[128]; CHAR *argv[2], *psz;
CMD_INIT(); ASSERT_WOW_PRESENT;
if(WDParseArgStr(lpArgumentString, argv, 1) == 1) {
atom = (ATOM)LOWORD(WDahtoi(argv[0]));
pszGAtomName[0] = 'G'; // put a random value in 1st byte so we can
pszLAtomName[0] = 'L'; // tell if it got replaced with a '\0' for
pszCAtomName[0] = 'C'; // an "undetermined" type
psz = NULL; PRINTF("\n%s: ", argv[0]); if(GlobalGetAtomName(atom, pszGAtomName, 128) > 0) { PRINTF("<Global atom> \"%s\" ", pszGAtomName); psz = pszGAtomName; } else if(GetAtomName(atom, pszLAtomName, 128) > 0) { PRINTF("<Local atom> \"%s\" ", pszLAtomName); psz = pszLAtomName; } else if(GetClipboardFormatName((UINT)atom, pszCAtomName, 128) > 0) { PRINTF("<Clipboard format> \"%s\" ", pszCAtomName); psz = pszCAtomName; } if(psz) { i = 0; while(psz[i] && i < 128) { PRINTF(" %2X", psz[i++] & 0x000000FF); } } else { PRINTF("<Undetermined type>\n"); PRINTF(" GlobalGetAtomName string: \"%c\" ", pszGAtomName[0]); for(i = 0; i < 8; i++) { PRINTF(" %2X", pszGAtomName[i] & 0x000000FF); } PRINTF("\n GetAtomName string: \"%c\" ", pszLAtomName[0]); for(i = 0; i < 8; i++) { PRINTF(" %2X", pszLAtomName[i] & 0x000000FF); } PRINTF("\n GetClipboardFormatName string: \"%c\" ", pszCAtomName[0]); for(i = 0; i < 8; i++) { PRINTF(" %2X", pszCAtomName[i] & 0x000000FF); } } PRINTF("\n\n"); } else { PRINTF("Usage: at hex_atom_number\n"); } }
void ww( CMD_ARGLIST ) { INT h16; CHAR *argv[2];
CMD_INIT(); ASSERT_WOW_PRESENT;
if(WDParseArgStr(lpArgumentString, argv, 1)) {
if((h16 = WDahtoi(argv[0])) >= 0) {
} else { PRINTF("Usage: ww hwnd16\n"); } } else { PRINTF("Usage: ww hwnd16\n"); } }
void wc( CMD_ARGLIST ) { PWC pwc;
INT h16; CHAR *argv[2];
CMD_INIT(); ASSERT_WOW_PRESENT;
if(WDParseArgStr(lpArgumentString, argv, 1)) {
if((h16 = WDahtoi(argv[0])) >= 0){
try {
pwc = (PWC)GetClassLong((HWND)HWND32((HAND16)h16),GCL_WOWWORDS);
// this got moved out of WC
// PRINTF("16:16 WndProc : %08lX\n", pwc->vpfnWndProc);
PRINTF("VPSZ : %08lX\n", pwc->vpszMenu); PRINTF("PWC : %08lX\n\n", pwc);
} except (EXCEPTION_ACCESS_VIOLATION == GetExceptionCode()) {
PRINTF("!wow32.wc: Invalid HWND16 %04x\n", h16);
} } else { PRINTF("Usage: wc hwnd16\n"); } } else { PRINTF("Usage: wc hwnd16\n"); } }
//
// Dump Last Logged APIs
//
void lastlog( CMD_ARGLIST ) { INT ValueiCircBuffer = CIRC_BUFFERS; PVOID pTmp = NULL; INT iCircBuffer; CHAR achTmp[TMP_LINE_LEN], *pachTmp; INT i;
CMD_INIT(); ASSERT_CHECKED_WOW_PRESENT;
GETEXPRVALUE(iCircBuffer, "wow32!iCircBuffer", INT); GETEXPRADDR(pTmp, "wow32!ValueiCircBuffer"); if(pTmp) { try { READMEM(pTmp, &ValueiCircBuffer, sizeof(INT)); } except (1) { ValueiCircBuffer = 0; } } if(ValueiCircBuffer == 0) { ValueiCircBuffer = CIRC_BUFFERS; } GETEXPRVALUE(pachTmp, "wow32!pachTmp", PCHAR);
for (i = iCircBuffer; i >= 0; i--) { READMEM_XRET(achTmp, &pachTmp[i*TMP_LINE_LEN]); PRINTF("%s",achTmp); }
for (i = ValueiCircBuffer-1; i > iCircBuffer; i--) { READMEM_XRET(achTmp, &pachTmp[i*TMP_LINE_LEN]); PRINTF("%s",achTmp); }
return; }
// creates/closes toggle for logfile for iloglevel logging in c:\ilog.log
void logfile( CMD_ARGLIST ) { INT nArgs; CHAR *argv[2], szLogFile[128]; DWORD fLog; LPVOID lpfLog, lpszLogFile;
CMD_INIT(); ASSERT_CHECKED_WOW_PRESENT;
nArgs = WDParseArgStr(lpArgumentString, argv, 1);
GETEXPRADDR(lpfLog, "wow32!fLog"); READMEM_XRET(fLog, lpfLog);
if(nArgs) { strcpy(szLogFile, argv[0]); } else { strcpy(szLogFile, "c:\\ilog.log"); }
if(fLog == 0) { fLog = 2;
PRINTF("\nCreating "); PRINTF(szLogFile); PRINTF("\n\n"); } else { fLog = 3; PRINTF("\nClosing logfile\n\n"); }
WRITEMEM_XRET(lpfLog, fLog);
GETEXPRADDR(lpszLogFile, "wow32!szLogFile"); WRITEMEM_N_XRET(lpszLogFile, szLogFile, strlen(szLogFile)+1);
return; }
//
// Set iLogLevel from Debugger Extension
//
void setloglevel( CMD_ARGLIST ) { INT iLogLevel; LPVOID lpAddress;
CMD_INIT(); ASSERT_CHECKED_WOW_PRESENT;
GETEXPRADDR(lpAddress, "wow32!iLogLevel"); iLogLevel = (INT)GetExpression(lpArgumentString); WRITEMEM_XRET(lpAddress, iLogLevel);
return; }
//
// Toggle Single Step Trace Mode
//
void steptrace( CMD_ARGLIST ) { INT localfDebugWait; LPVOID lpAddress;
CMD_INIT(); ASSERT_CHECKED_WOW_PRESENT;
GETEXPRADDR(lpAddress, "wow32!fDebugWait"); READMEM_XRET(localfDebugWait, lpAddress); localfDebugWait = ~localfDebugWait; WRITEMEM_XRET(lpAddress, localfDebugWait);
return; }
/******* Misc filtering functions ********/ //
// Set Filter Filtering of Specific APIs ON
//
void FilterSpecific( ) { INT i; INT fLogFilter; WORD wfLogFunctionFilter; LPVOID lpAddress; PWORD pawfLogFunctionFilter; WORD wCallId;
SkipToNextWhiteSpace(); if (GetNextToken()) { wCallId = (WORD)GetExpression(lpArgumentString); } else { PRINTF("Please specify an api callid\n"); return; }
if (!wCallId) { PRINTF("Invalid callid\n"); return; }
GETEXPRVALUE(pawfLogFunctionFilter, "wow32!pawfLogFunctionFilter", PWORD);
for (i = 0; i < FILTER_FUNCTION_MAX ; i++) {
// Find Empty Position In Array
READMEM_XRET(wfLogFunctionFilter, &pawfLogFunctionFilter[i]); if ((wfLogFunctionFilter == 0xffff) || (wfLogFunctionFilter == 0x0000)) {
// Add New Filter to Array
wfLogFunctionFilter = wCallId; WRITEMEM_XRET(&pawfLogFunctionFilter[i], wfLogFunctionFilter); break; } }
GETEXPRADDR(lpAddress, "wow32!fLogFilter"); fLogFilter = 0xffffffff; WRITEMEM_XRET(lpAddress, fLogFilter);
}
//
// Clear Filter Specific Array
//
void FilterResetSpecific( ) { INT i; WORD NEG1 = (WORD) -1; WORD ZERO = 0; PWORD pawfLogFunctionFilter; LPVOID lpAddress;
GETEXPRVALUE(pawfLogFunctionFilter, "wow32!pawfLogFunctionFilter", PWORD);
WRITEMEM_XRET(&pawfLogFunctionFilter[0], NEG1); for (i=1; i < FILTER_FUNCTION_MAX ; i++) { WRITEMEM_XRET(&pawfLogFunctionFilter[i], ZERO); }
GETEXPRADDR(lpAddress, "wow32!iLogFuncFiltIndex"); WRITEMEM_XRET(lpAddress, ZERO);
}
//
// Set TaskID Filtering
//
void FilterTask( ) { INT fLogTaskFilter; LPVOID lpAddress;
SkipToNextWhiteSpace(); if (GetNextToken()) { GETEXPRADDR(lpAddress, "wow32!fLogTaskFilter"); fLogTaskFilter = (INT)GetExpression(lpArgumentString); WRITEMEM_XRET(lpAddress, fLogTaskFilter); } else { PRINTF("Please specify a task\n"); }
return; }
//
// Turn All filtering ON
//
void FilterReset( ) { LPVOID lpAddress; INT fLogFilter = 0xffffffff; WORD fLogTaskFilter = 0xffff;
GETEXPRADDR(lpAddress, "wow32!fLogFilter"); WRITEMEM_XRET(lpAddress, fLogFilter);
GETEXPRADDR(lpAddress, "wow32!fLogTaskFilter"); WRITEMEM_XRET(lpAddress, fLogTaskFilter);
FilterResetSpecific(); }
//
// Disable logging on all classes
//
void FilterAll( ) { INT fLogFilter; LPVOID lpAddress;
GETEXPRADDR(lpAddress, "wow32!fLogFilter"); fLogFilter = 0x00000000; WRITEMEM_XRET(lpAddress, fLogFilter);
}
VOID DumpFilterSettings( VOID ) { INT i; INT fLogFilter; WORD wfLogFunctionFilter; WORD wfLogTaskFilter; LPVOID lpAddress; PWORD pawfLogFunctionFilter;
GETEXPRVALUE(pawfLogFunctionFilter, "wow32!pawfLogFunctionFilter", PWORD); GETEXPRVALUE(wfLogTaskFilter, "wow32!fLogTaskFilter", WORD); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); READMEM_XRET(fLogFilter, lpAddress);
if (!pawfLogFunctionFilter) { PRINTF("Symbol 'wow32!pawfLogFunctionFilter' not available\n"); return; }
PRINTF("\n*** WOW log filter state ***\n"); if (fLogFilter & FILTER_VERBOSE) { PRINTF("Verbose logging is on\n"); } else { PRINTF("Verbose logging is off\n"); }
if (wfLogTaskFilter != 0xffff) { PRINTF("Only API calls for task %04X will be logged\n", wfLogTaskFilter); } else { PRINTF("Task filtering is off\n"); }
READMEM_XRET(wfLogFunctionFilter, &pawfLogFunctionFilter[0]); if (wfLogFunctionFilter != 0xffff) {
PRINTF("\nOnly API calls with the following CallId's will be logged:\n");
for (i = 0; i < FILTER_FUNCTION_MAX ; i++) {
// Find Empty Position In Array
READMEM_XRET(wfLogFunctionFilter, &pawfLogFunctionFilter[i]); if ((wfLogFunctionFilter != 0xffff) && (wfLogFunctionFilter != 0x0000)) { PRINTF(" %04X\n", wfLogFunctionFilter); } } PRINTF("\n"); } else { PRINTF("Specific API filtering is off\n"); }
if (!(~fLogFilter & ~FILTER_VERBOSE)) { PRINTF("API class filtering if off\n"); } else { PRINTF("Logging is disabled for the following API classes:\n"); }
if (!(fLogFilter & FILTER_KERNEL)) { PRINTF(" KERNEL\n"); } if (!(fLogFilter & FILTER_KERNEL16)) { PRINTF(" KERNEL16\n"); } if (!(fLogFilter & FILTER_USER)) { PRINTF(" USER\n"); } if (!(fLogFilter & FILTER_GDI)) { PRINTF(" GDI\n"); } if (!(fLogFilter & FILTER_KEYBOARD)) { PRINTF(" KEYBOARD\n"); } if (!(fLogFilter & FILTER_SOUND)) { PRINTF(" SOUND\n"); } if (!(fLogFilter & FILTER_MMEDIA)) { PRINTF(" MMEDIA\n"); } if (!(fLogFilter & FILTER_WINSOCK)) { PRINTF(" WINSOCK\n"); } if (!(fLogFilter & FILTER_COMMDLG)) { PRINTF(" COMMDLG\n"); }
PRINTF("\n");
}
void filter( CMD_ARGLIST ) { ULONG Mask = 0; LPVOID lpAddress;
CMD_INIT(); ASSERT_CHECKED_WOW_PRESENT;
while (' ' == *lpArgumentString) { lpArgumentString++; }
if (_strnicmp(lpArgumentString, "kernel16", 8) == 0) { Mask = FILTER_KERNEL16; } else if (_strnicmp(lpArgumentString, "kernel", 6) == 0) { Mask = FILTER_KERNEL; } else if (_strnicmp(lpArgumentString, "user", 4) == 0) { Mask = FILTER_USER; } else if (_strnicmp(lpArgumentString, "gdi", 3) == 0) { Mask = FILTER_GDI; } else if (_strnicmp(lpArgumentString, "keyboard", 8) == 0) { Mask = FILTER_KEYBOARD; } else if (_strnicmp(lpArgumentString, "sound", 5) == 0) { Mask = FILTER_SOUND; } else if (_strnicmp(lpArgumentString, "mmedia", 6) == 0) { Mask = FILTER_MMEDIA; } else if (_strnicmp(lpArgumentString, "winsock", 7) == 0) { Mask = FILTER_WINSOCK; } else if (_strnicmp(lpArgumentString, "commdlg", 7) == 0) { Mask = FILTER_COMMDLG; } else if (_strnicmp(lpArgumentString, "callid", 6) == 0) { FilterSpecific(); } else if (_strnicmp(lpArgumentString, "task", 4) == 0) { FilterTask(); } else if (_strnicmp(lpArgumentString, "*", 1) == 0) { FilterAll(); } else if (_strnicmp(lpArgumentString, "reset", 5) == 0) { FilterReset(); } else if (_strnicmp(lpArgumentString, "verbose", 7) == 0) { Mask = FILTER_VERBOSE; } else { if (*lpArgumentString != 0) { PRINTF("Invalid argument to Filter command: '%s'\n", lpArgumentString); return; } }
if (Mask) { INT fLogFilter; GETEXPRADDR(lpAddress, "wow32!fLogFilter"); if (!lpAddress) { PRINTF("Symbol 'wow32!fLogFilter' not available\n"); } else { READMEM_XRET(fLogFilter, lpAddress); if ((fLogFilter & Mask) == 0) { fLogFilter |= Mask; } else { fLogFilter &= ~Mask; } WRITEMEM_XRET(lpAddress, fLogFilter); } }
DumpFilterSettings(); }
void cia( CMD_ARGLIST ) { CURSORICONALIAS cia; PVOID lpAddress; INT maxdump = 500;
CMD_INIT(); ASSERT_WOW_PRESENT;
GETEXPRADDR(lpAddress, "wow32!lpCIAlias"); READMEM_XRET(lpAddress, lpAddress);
if (!lpAddress) {
PRINTF("Cursor/Icon alias list is empty.\n");
} else {
PRINTF("Alias tp H16 H32 inst mod task res szname\n");
READMEM_XRET(cia, lpAddress);
while ((lpAddress != NULL) && --maxdump) {
if (cia.fInUse) { PRINTF("%08X", lpAddress); PRINTF(" %02X", cia.flType); PRINTF(" %04X", cia.h16); PRINTF(" %08X", cia.h32); PRINTF(" %04X", cia.hInst16); PRINTF(" %04X", cia.hMod16); PRINTF(" %04X", cia.hTask16); PRINTF(" %04X", cia.hRes16); PRINTF(" %08X\n", cia.lpszName); }
lpAddress = cia.lpNext; READMEM_XRET(cia, lpAddress);
}
if (!maxdump) { PRINTF("Dump ended prematurely - possible infinite loop\n"); } }
}
//WARNING: This structure must match ENTRY in ntgdi\inc\hmgshare.h
typedef struct _ENTRYWOW { LONG l1; LONG l2; USHORT FullUnique; USHORT us1; LONG l3; } ENTRYWOW, *PENTRYWOW;
// converts an hGDI16 to the equivalent hGDI32
void hgdi( CMD_ARGLIST ) { ULONG h16, h32; PENTRYWOW pEntry; ENTRYWOW Entry; LPVOID lpAddress;
CMD_INIT(); ASSERT_WOW_PRESENT;
lpAddress = (PENTRYWOW)EXPRESSION("wow32!gpGDIHandleInfo"); READMEM_XRET(pEntry, lpAddress);
h16 = (ULONG) WDahtoi(lpArgumentString); PRINTF("WOW 16-bit GDI Handle: %04X ", h16); h16 = h16 >> 2;
pEntry = &pEntry[h16];
if(!READMEM((LPVOID) (pEntry), &Entry, sizeof(ENTRYWOW))) { PRINTF("Failure reading ENTRYWOW At %08lX\n", pEntry); return; }
h32 = h16 | (Entry.FullUnique << 16); PRINTF("32-bit GDI Handle: %08X\n", h32);
return; }
#include "..\wow32\wdde.h"
//typedef struct _HDDE {
// struct _HDDE *pDDENext; // pointer to next hDDE alias
// HAND16 To_hwnd; // window that will receive this message
// HAND16 From_hwnd; // window that sent this message
// HAND16 hMem16; // handle of WOW app allocated 16 bit object
// HANDLE hMem32; // handle of WOW allocated 32 bit object
// WORD DdeMsg; // message id
// WORD DdeFormat; // message format
// WORD DdeFlags; // indicates if it is metafile handle
// HAND16 h16; // original h16 for bad apps doing EXECUTE
//} HDDE, *PHDDE;
// dumps the list of dde 16-32 memory pairs
void ddemem( CMD_ARGLIST ) { PHDDE phdde; HDDE hdde; LPVOID lpAddress;
CMD_INIT(); ASSERT_WOW_PRESENT;
lpAddress = (PENTRYWOW)EXPRESSION("wow32!phDDEFirst"); READMEM_XRET(phdde, lpAddress);
while(phdde) {
if(!READMEM((LPVOID) (phdde), &hdde, sizeof(HDDE))) { PRINTF("Failure reading HDDE At %08lX\n", phdde); return; }
PRINTF(" PHDDE: %08X\n", phdde); PRINTF(" To_hwnd16: %04X\n", hdde.To_hwnd); PRINTF("From_hwnd16: %04X\n", hdde.From_hwnd); PRINTF(" hMem16: %04X\n", hdde.hMem16); PRINTF(" hMem32: %04X\n", hdde.hMem32); PRINTF(" DdeMsg: %04X\n", hdde.DdeMsg); PRINTF(" DdeFormat: %04X\n", hdde.DdeFormat); PRINTF(" DdeFlags: %04X\n", hdde.DdeFlags); PRINTF(" Orig h16: %04X\n\n", hdde.h16);
phdde = hdde.pDDENext; }
return; }
// must match struct in "..\wow32\wow32.h"
#ifndef DEBUG
#define ML_MALLOC_W 0x00000001
#define ML_MALLOC_W_ZERO 0x00000002
#define ML_REALLOC_W 0x00000004
#define ML_MALLOC_WTYPE (ML_MALLOC_W | ML_MALLOC_W_ZERO | ML_REALLOC_W)
#define ML_GLOBALALLOC 0x00000010
#define ML_GLOBALREALLOC 0x00000020
#define ML_GLOBALTYPE (ML_GLOBALREALLOC | ML_GLOBALALLOC)
typedef struct _tagMEMLEAK { struct _tagMEMLEAK *lpmlNext; PVOID lp; DWORD size; UINT fHow; ULONG Count; PVOID CallersAddress; } MEMLEAK, *LPMEMLEAK; #endif
void gmem( CMD_ARGLIST ) { LPMEMLEAK lpml; MEMLEAK ml; LPVOID lpAddress;
CMD_INIT(); ASSERT_WOW_PRESENT;
// DbgBreakPoint();
lpAddress = (PENTRYWOW)EXPRESSION("wow32!lpMemLeakStart"); READMEM_XRET(lpml, lpAddress);
while(lpml) {
if(!READMEM((LPVOID) (lpml), &ml, sizeof(MEMLEAK))) { PRINTF("Failure reading lpml At %08lX\n", lpml); return; }
PRINTF(" lp: %08X\n", ml.lp); PRINTF(" Size: %08X\n", ml.size); PRINTF(" Alloc'd by: %08X\n", ml.CallersAddress); PRINTF("Alloc Count: %08X\n", ml.Count); PRINTF("How Alloc'd: "); if(ml.fHow & ML_MALLOC_W) PRINTF("malloc_w "); if(ml.fHow & ML_MALLOC_W_ZERO) PRINTF("malloc_w_zero "); if(ml.fHow & ML_REALLOC_W) PRINTF("realloc_w "); if(ml.fHow & ML_GLOBALALLOC) PRINTF("GlobalAlloc "); if(ml.fHow & ML_GLOBALREALLOC) PRINTF("GlobalReAlloc "); PRINTF("\n\n");
lpml = ml.lpmlNext; }
return; }
|