diff options
Diffstat (limited to 'private/mvdm/vdmexts/wow.c')
-rw-r--r-- | private/mvdm/vdmexts/wow.c | 1575 |
1 files changed, 1575 insertions, 0 deletions
diff --git a/private/mvdm/vdmexts/wow.c b/private/mvdm/vdmexts/wow.c new file mode 100644 index 000000000..d799c5162 --- /dev/null +++ b/private/mvdm/vdmexts/wow.c @@ -0,0 +1,1575 @@ +/******************************Module*Header*******************************\ +* Module Name: debug.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 <ctype.h> +#define DEBUG_OR_WOWPROFILE 1 +#include <wow32.h> +#include <wmdisp32.h> +#include <wcuricon.h> +#include <wucomm.h> +#include <doswow.h> + + +#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 = 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); + + 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("pchWriteBuf 0x%x\n", (unsigned)wp.pchWriteBuf); + PRINTF("cbWriteBuf 0x%x\n", (unsigned)wp.cbWriteBuf); + 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("hWriteThread 0x%x\n", (unsigned)wp.hWriteThread); + PRINTF("hWriteEvent 0x%x\n", (unsigned)wp.hWriteEvent); + 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("\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, 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; + 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 tread 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("ptdNext 0x%08x\n", td.ptdNext); + Print("dwFlags 0x%08x\n", td.dwFlags); + + // + // Dump symbolic names for TDF_ manifests + // + + if (td.dwFlags & TDF_INITCALLBACKSTACK) { + Print(" TDF_INITCALLBACKSTACK\n"); + } + 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); + Print("CommDlgTd (ptr) 0x%08x\n", td.CommDlgTd); + + // + // 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 0x04x\n", CommDlgTd.hdlg); + Print(" vpfnHook 0x04x:0x04x\n", HIWORD(CommDlgTd.vpfnHook), LOWORD(CommDlgTd.vpfnHook)); + Print(" vpData 0x04x:0x04x\n", HIWORD(CommDlgTd.vpData), LOWORD(CommDlgTd.vpData)); + Print(" ExtendedErr 0x08x\n", CommDlgTd.ExtendedErr); + Print(" vpfnSetupHook (union) 0x04x:0x04x\n", HIWORD(CommDlgTd.vpfnSetupHook), LOWORD(CommDlgTd.vpfnSetupHook)); + Print(" pRes (union) 0x08x\n", CommDlgTd.pRes); + Print(" SetupHwnd 0x04x\n", CommDlgTd.SetupHwnd); + Print(" Previous 0x08x\n", CommDlgTd.Previous); + Print(" pData32 0x08x\n", CommDlgTd.pData32); + Print(" Flags 0x08x\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 & WOWCF_GWLCLRTOPMOST) { + Print(" WOWCF_GWLCLRTOPMOST\n"); + } + if (td.dwWOWCompatFlags & WOWCF_UNIQUEHDCHWND) { + Print(" WOWCF_UNIQUEHDCHWND\n"); + } + if (td.dwWOWCompatFlags & WOWCF_WMMDIACTIVATEBUG) { + Print(" WOWCF_WMMDIACTIVATEBUG\n"); + } + if (td.dwWOWCompatFlags & WOWCF_NOCBDIRTHUNK) { + Print(" WOWCF_NOCBDIRTHUNK\n"); + } + if (td.dwWOWCompatFlags & WOWCF_DBASEHANDLEBUG) { + Print(" WOWCF_DBASEHANDLEBUG\n"); + } + if (td.dwWOWCompatFlags & WOWCF_GETDUMMYDC) { + Print(" WOWCF_GETDUMMYDC\n"); + } + if (td.dwWOWCompatFlags & WOWCF_UNLOADNETFONTS) { + Print(" WOWCF_UNLOADNETFONTS\n"); + } + if (td.dwWOWCompatFlags & WOWCF_ADD_MSTT) { + Print(" WOWCF_ADD_MSTT\n"); + } + if (td.dwWOWCompatFlags & WOWCF_NOFIRSTSAVE) { + Print(" WOWCF_NOFIRSTSAVE\n"); + } + if (td.dwWOWCompatFlags & WOWCF_NOPC_RECTANGLE) { + Print(" WOWCF_NOPC_RECTANGLE\n"); + } + if (td.dwWOWCompatFlags & WOWCF_NEEDIGNORESTARTPAGE) { + Print(" WOWCF_NEEDIGNORESTARTPAGE\n"); + } + if (td.dwWOWCompatFlags & WOWCF_NEEDSTARTPAGE) { + Print(" WOWCF_NEEDSTARTPAGE\n"); + } + if (td.dwWOWCompatFlags & WOWCF_GWLINDEX2TO4) { + Print(" WOWCF_GWLINDEX2TO4\n"); + } + if (td.dwWOWCompatFlags & WOWCF_SETNULLMESSAGE) { + Print(" WOWCF_SETNULLMESSAGE\n"); + } + if (td.dwWOWCompatFlags & WOWCF_FORCENOPOSTSCRIPT) { + Print(" WOWCF_FORCENOPOSTSCRIPT\n"); + } + if (td.dwWOWCompatFlags & WOWCF_LB_NONNULLLPARAM) { + Print(" WOWCF_LB_NONNULLLPARAM\n"); + } + if (td.dwWOWCompatFlags & WOWCF_FORCETWIPSESCAPE) { + Print(" WOWCF_FORCETWIPSESCAPE\n"); + } + if (td.dwWOWCompatFlags & WOWCF_DONTRELEASECACHEDDC) { + Print(" WOWCF_DONTRELEASECACHEDDC\n"); + } + // This one is up for grabs + // if (td.dwWOWCompatFlags & WOWCF_ACTION_SAVEPTR) { + // Print(" WOWCF_ACTION_SAVEPTR\n"); + // } + if (td.dwWOWCompatFlags & WOWCF_DSBASEDSTRINGPOINTERS) { + Print(" WOWCF_DSBASEDSTRINGPOINTERS\n"); + } + if (td.dwWOWCompatFlags & WOWCF_NOWAITFORINPUTIDLE) { + Print(" WOWCF_NOWAITFORINPUTIDLE\n"); + } + if (td.dwWOWCompatFlags & WOWCF_SIMPLEREGION) { + Print(" WOWCF_SIMPLEREGION\n"); + } + if (td.dwWOWCompatFlags & WOWCF_SANITIZEDOTWRSFILES) { + Print(" WOWCF_SANITIZEDOTWRSFILES\n"); + } + if (td.dwWOWCompatFlags & WOWCF_HIRES) { + Print(" WOWCF_HIRES\n"); + } + if (td.dwWOWCompatFlags & WOWCF_MGX_ESCAPES) { + Print(" WOWCF_MGX_ESCAPES\n"); + } + if (td.dwWOWCompatFlags & WOWCF_4PLANECONVERSION) { + Print(" WOWCF_4PLANECONVERSION\n"); + } + if (td.dwWOWCompatFlags & WOWCF_RESETPAPER29ANDABOVE) { + Print(" WOWCF_RESETPAPER29ANDABOVE\n"); + } + if (td.dwWOWCompatFlags & WOWCF_NOTDOSSPAWNABLE) { + Print(" WOWCF_NOTDOSSPAWNABLE\n"); + } + if (td.dwWOWCompatFlags & WOWCF_SYNCHRONOUSDOSAPP) { + Print(" WOWCF_SYNCHRONOUSDOSAPP\n"); + } + if (td.dwWOWCompatFlags & WOWCF_EDITCTRLWNDWORDS) { + Print(" WOWCF_EDITCTRLWNDWORDS\n"); + } + if (td.dwWOWCompatFlags & WOWCF_FAKEJOURNALRECORDHOOK) { + Print(" WOWCF_FAKEJOURNALRECORDHOOK\n"); + } + if (td.dwWOWCompatFlags & WOWCF_GRAINYTICS) { + Print(" WOWCF_GRAINYTICS\n"); + } + + + Print("dwWOWCompatFlagsEx 0x%08x\n", td.dwWOWCompatFlagsEx); + + // + // Dump symbolic names for WOWCFEX_ manifests + // + + if (td.dwWOWCompatFlagsEx & WOWCFEX_FORMFEEDHACK) { + Print(" WOWCFEX_FORMFEEDHACK\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_DEFWNDPROCNCCALCSIZE) { + Print(" WOWCFEX_DEFWNDPROCNCCALCSIZE\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_PIXELMETRICS) { + Print(" WOWCFEX_PIXELMETRICS\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_NODIBSHERE) { + Print(" WOWCFEX_NODIBSHERE\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_SETCAPSTACK) { + Print(" WOWCFEX_SETCAPSTACK\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_FORCEINCDPMI) { + Print(" WOWCFEX_FORCEINCDPMI\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_LONGWINEXECTAIL) { + Print(" WOWCFEX_LONGWINEXECTAIL\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_RESTOREEXPLORER) { + Print(" WOWCFEX_RESTOREEXPLORER\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_FIXDCFONT4MENUSIZE) { + Print(" WOWCFEX_FIXDCFONT4MENUSIZE\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_GETVERSIONHACK) { + Print(" WOWCFEX_GETVERSIONHACK\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_BOGUSPOINTER) { + Print(" WOWCFEX_BOGUSPOINTER\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_SENDPOSTEDMSG) { + Print(" WOWCFEX_SENDPOSTEDMSG\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_GLOBALDELETEATOM) { + Print(" WOWCFEX_GLOBALDELETEATOM\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_IGNORECLIENTSHUTDOWN) { + Print(" WOWCFEX_IGNORECLIENTSHUTDOWN\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_ZAPGPPSDEFBLANKS) { + Print(" WOWCFEX_ZAPGPPSDEFBLANKS\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_FAKECLASSINFOFAIL) { + Print(" WOWCFEX_FAKECLASSINFOFAIL\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_SAMETASKFILESHARE) { + Print(" WOWCFEX_SAMETASKFILESHARE\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_SAYITSNOTTHERE) { + Print(" WOWCFEX_SAYITSNOTTHERE\n"); + } + if (td.dwWOWCompatFlagsEx & WOWCFEX_BROKENFLATPOINTER) { + Print(" WOWCFEX_BROKENFLATPOINTER\n"); + } + + 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; + 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); + Print(" Directory \"%s\"\n", tdb.TDB_LFNDirectory); + Print(" PDB (aka PSP) 0x%04x\n", tdb.TDB_PDB); + + // + // Dump open file handle info + // + + pPDB = (PDOSPDB) (GetInfoFromSelector(tdb.TDB_PDB, PROT_MODE, NULL) + GetIntelBase()); + READMEM_XRET(PDB, pPDB); + + 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 Attr 0x%04x NT Handle 0x%08x\n", + fh, SFN, pSFT->SFT_Ref_Count, pSFT->SFT_Mode, pSFT->SFT_Attr, pSFT->SFT_NTHandle); + } + + 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 = 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 + ) +{ + PWW pww; + INT h16; + CHAR *argv[2]; + + CMD_INIT(); + ASSERT_WOW_PRESENT; + + if(WDParseArgStr(lpArgumentString, argv, 1)) { + + if((h16 = WDahtoi(argv[0])) >= 0) { + + try { + + pww = (PWW)GetWindowLong((HWND)HWND32((HAND16)h16),GWL_WOWWORDS); + + PRINTF("16:16 WndProc : %08lX\n", pww->vpfnWndProc); + PRINTF("16:16 DlgProc : %08lX\n", pww->vpfnDlgProc); + PRINTF("iClass : %#lx (%s) \n", pww->iClass, aszWOWCLASS[pww->iClass]); + PRINTF("dwStyle : %08lX\n", pww->dwStyle); + PRINTF("hInstance : %08lX\n", pww->hInstance); + PRINTF("16 bit handle : %#x\n", h16); + + } + except (EXCEPTION_ACCESS_VIOLATION == GetExceptionCode()) { + + PRINTF("!wow32.ww: Invalid HWND16 %04x\n", h16); + + } + } + 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); + + 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 iCircBuffer; + CHAR achTmp[TMP_LINE_LEN], *pachTmp; + INT i; + + CMD_INIT(); + ASSERT_CHECKED_WOW_PRESENT; + + GETEXPRVALUE(iCircBuffer, "wow32!iCircBuffer", INT); + GETEXPRVALUE(pachTmp, "wow32!pachTmp", PCHAR); + + for (i = iCircBuffer; i >= 0; i--) { + READMEM_XRET(achTmp, &pachTmp[i*TMP_LINE_LEN]); + PRINTF("%s",achTmp); + } + + for (i = CIRC_BUFFERS-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"); + } + } + +} |