/******************************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 * * * Copyright (c) 1992 Microsoft Corporation \**************************************************************************/ #include "precomp.h" #pragma hdrstop #include #include #include #include #include #include #define NOEXTAPI // wesw is a bonehead sometimes #include #include // // Local function prototypes // INT WDahtoi(LPSZ lpsz); // // fWinDbg tells us if the debugger calling us uses the WinDbg or Ntsd // interface. // BOOL fWinDbg; /****** macros common to all versions *******/ #define ARGLIST HANDLE hCurrentProcess, \ HANDLE hCurrentThread, \ DWORD dwCurrentPc, \ PWINDBG_EXTENSION_APIS lpExtensionApis, \ LPSTR lpArgumentString #define UNREFERENCED_PARAMETERS() \ UNREFERENCED_PARAMETER(hCurrentProcess); \ UNREFERENCED_PARAMETER(hCurrentThread); \ UNREFERENCED_PARAMETER(dwCurrentPc); \ UNREFERENCED_PARAMETER(lpExtensionApis); \ UNREFERENCED_PARAMETER(lpArgumentString); \ fWinDbg = (lpExtensionApis->nSize >= sizeof(WINDBG_EXTENSION_APIS)); /***************************/ /*** DEBUG_OR_WOWPROFILE ***/ /***************************/ #ifdef DEBUG_OR_WOWPROFILE /********* define the WINDBG API pointers *********/ PWINDBG_OUTPUT_ROUTINE Print; PWINDBG_GET_EXPRESSION GetExpression; PWINDBG_GET_SYMBOL GetSymbol; PWINDBG_READ_PROCESS_MEMORY_ROUTINE ReadMem; PWINDBG_WRITE_PROCESS_MEMORY_ROUTINE WriteMem; /********* define several handy macros *********/ #define READMEM( Handle, Src, Dst, Size, ReadCount ) \ if ( fWinDbg ) { \ ReadMem = lpExtensionApis->lpReadProcessMemoryRoutine; \ ReadMem( (DWORD)Src, Dst, Size, ReadCount ); \ } else { \ ReadProcessMemory( Handle, Src, Dst, Size, ReadCount ); \ } #define WRITEMEM( Handle, Dst, Src, Size, WriteCount ) \ if ( fWinDbg ) { \ WriteMem = lpExtensionApis->lpWriteProcessMemoryRoutine; \ WriteMem( (DWORD)Src, Dst, Size, WriteCount ); \ } else { \ WriteProcessMemory( Handle, Dst, Src, Size, WriteCount ); \ } #define READWOW(dst, src)\ try {\ Print = lpExtensionApis->lpOutputRoutine;\ READMEM( hCurrentProcess, (LPVOID)(src), (LPVOID)&(dst), sizeof(dst), NULL);\ } except (EXCEPTION_EXECUTE_HANDLER) {\ Print("ReadProcessMemory Failed !\n");\ return;\ } #define READWOW2(dst, src, ret)\ try {\ Print = lpExtensionApis->lpOutputRoutine;\ READMEM(hCurrentProcess, (LPVOID) (src), (LPVOID)&(dst), sizeof(dst), NULL);\ } except (EXCEPTION_EXECUTE_HANDLER) {\ Print("ReadProcessMemory Failed !\n");\ return ret;\ } #define WRITEWOW(dst, src)\ try {\ Print = lpExtensionApis->lpOutputRoutine;\ WRITEMEM(hCurrentProcess, (LPVOID)(dst), (LPVOID)&(src), sizeof(src), NULL);\ } except (EXCEPTION_EXECUTE_HANDLER) {\ Print("WriteProcessMemory Failed !\n");\ return;\ } #define WRITENWOW(dst, src, n)\ try {\ Print = lpExtensionApis->lpOutputRoutine;\ WRITEMEM(hCurrentProcess, (LPVOID)(dst), (LPVOID)(src), n, NULL);\ } except (EXCEPTION_EXECUTE_HANDLER) {\ Print("WriteProcessMemory Failed !\n");\ return;\ } #define GETEXPRVALUE(dst, expr, typ) \ {\ GetExpression = lpExtensionApis->lpGetExpressionRoutine;\ if (fWinDbg) {\ dst = (typ)GetExpression(expr);\ } else {\ PVOID lpA = (PVOID)GetExpression(expr);\ READWOW(dst, lpA);\ }\ } #define GETEXPRADDR(dst, expr) \ {\ GetExpression = lpExtensionApis->lpGetExpressionRoutine;\ if (fWinDbg) {\ LPSTR lps = malloc_w(strlen(expr)+2);\ *lps = '&';\ strcpy(lps+1, expr);\ dst = (PVOID)GetExpression(lps);\ free_w(lps);\ } else {\ dst = (PVOID)GetExpression(expr);\ }\ } /*********** WOW debugger extension API's ************/ // // HELP ! // void help( ARGLIST ) { UNREFERENCED_PARAMETERS(); // set up function pointer Print = lpExtensionApis->lpOutputRoutine; Print("WOW32 Debugger Extensions:\n"); Print(" at 0xXXXX - shows name associated with hex atom #\n"); Print(" cia - Dumps cursor/icon alias list\n"); Print(" ddte - Dump dispatch table entry pointed to by \n"); Print(" dt - Dump TD at or all if blank\n"); Print(" dwp - Dump WOWPORT structure pointed to by \n"); Print(" ww hwnd16 - Given a hwnd16 it dumps the WOW Window structure\n"); Print(" wc hwnd16 - Given a hwnd16 it dumps the WOW Class structure\n"); Print(" ClearFilter - All Filters Are turned OFF\n"); Print(" ClearFilterSpecific - Clears FilterSpecific function\n"); Print(" FilterGDI - Toggles Filtering of GDI Calls On/Off\n"); Print(" FilterKernel - Toggles Filtering of Kernel Calls On/Off\n"); Print(" FilterKernel16 - Toggles Filtering of Kernel16 Calls On/Off\n"); Print(" FilterKeyboard - Toggles Filtering of Keyboard Calls On/Off\n"); Print(" FilterMMedia - Toggles Filtering of MMedia Calls On/Off\n"); Print(" FilterWinsock - Toggles Filtering of Winsock Calls On/Off\n"); Print(" FilterSound - Toggles Filtering of Sound Calls On/Off\n"); Print(" FilterCommdlg - Toggles Filtering of Commdlg Calls On/Off\n"); Print(" FilterSpecific xxxx - Adds api to list to be filtered\n"); Print(" FilterTask xxxx - Filter on a Specific TaskID\n"); Print(" FilterUser - Toggles Filtering of User Calls On/Off\n"); Print(" FilterVerbose - Toggles Verbose Mode On/Off\n"); Print(" LastLog - Dumps Last Logged APIs from Circular Buffer\n"); Print(" LogFile [filespec] - Create/close toggle for iloglevel capture to file\n"); Print(" (no filespec defaults to c:\\ilog.log)\n"); Print(" ResetFilter - All Filters are turned ON\n"); Print(" SetLogLevel xx - Sets the WOW Logging Level\n"); Print(" StepTrace - Toggles Single Step Tracing On/Off\n"); Print(" APIProfClr - Clears the WOW API profiler table\n"); Print(" APIProfDmp help - Dumps the WOW API profiler table\n"); Print(" MSGProfClr - Clears the WOW MSG profiler table\n"); Print(" MSGProfDmp help - Dumps the WOW MSG profiler table\n"); Print(" MSGProfRT - Toggles MSG prof round trip/thunks only\n"); return; } // // 16:16 to flat pointer translation functions for debugger extensions. // #ifndef _X86_ DWORD pIntelBase = 0; VOID WDInitIntelBase(HANDLE hCurrentProcess, PWINDBG_EXTENSION_APIS lpExtensionApis) { GETEXPRVALUE(pIntelBase, "wow32!IntelMemoryBase", DWORD); } #define WD_INTEL_MEMORY_BASE (pIntelBase) #define WD_INIT_INTEL_BASE_IF_NEEDED \ { \ if (!pIntelBase) { \ WDInitIntelBase(hCurrentProcess, lpExtensionApis); \ } \ } #else #define WD_INTEL_MEMORY_BASE (0) #define WD_INIT_INTEL_BASE_IF_NEEDED {} #endif #define FlatFromReal(vp) FlatFromRealPtr(lpExtensionApis, hCurrentProcess, (vp)) PVOID FlatFromRealPtr(PWINDBG_EXTENSION_APIS lpExtensionApis, HANDLE hCurrentProcess, DWORD vp) { UNREFERENCED_PARAMETER(hCurrentProcess); // On x86 only. WD_INIT_INTEL_BASE_IF_NEEDED; return (PVOID) (WD_INTEL_MEMORY_BASE + (((vp) & 0xFFFF0000) >> 12) + ((vp) & 0xFFFF)); } #define FlatFromProt(vp) FlatFromProtPtr(lpExtensionApis, hCurrentProcess, (vp)) PVOID FlatFromProtPtr(PWINDBG_EXTENSION_APIS lpExtensionApis, HANDLE hCurrentProcess, DWORD vp) { PDWORD WDFlatAddress; DWORD FlatAddrEntry; GETEXPRADDR(WDFlatAddress, "ntvdm!FlatAddress"); READWOW2(FlatAddrEntry, (WDFlatAddress + (vp >> 19)), NULL); return FlatAddrEntry ? (PVOID)(FlatAddrEntry + (vp & 0xFFFF)) : NULL; } VOID dwp( ARGLIST ) { PWOWPORT pwp; WOWPORT wp; UNREFERENCED_PARAMETERS(); Print = lpExtensionApis->lpOutputRoutine; while (' ' == lpArgumentString[0]) { lpArgumentString++; } pwp = (PWOWPORT) WDahtoi(lpArgumentString); Print("Dump of WOWPORT structure at 0x%x:\n\n", (unsigned)pwp); try { READWOW(wp, pwp); } except (EXCEPTION_ACCESS_VIOLATION == GetExceptionCode() ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { Print("Access violation reading WOWPORT structure!\n\n"); return; } Print("idComDev 0x%x\n", (unsigned)wp.idComDev); Print("h32 0x%x\n", (unsigned)wp.h32); Print("hREvent 0x%x\n", (unsigned)wp.hREvent); Print("csWrite OwningThread 0x%x RecursionCount 0x%x\n", (unsigned)wp.csWrite.OwningThread, (unsigned)wp.csWrite.RecursionCount); Print("pchWriteBuf 0x%x\n", (unsigned)wp.pchWriteBuf); Print("cbWriteBuf 0x%x\n", (unsigned)wp.cbWriteBuf); Print("pchWriteHead 0x%x\n", (unsigned)wp.pchWriteHead); Print("pchWriteTail 0x%x\n", (unsigned)wp.pchWriteTail); Print("cbWriteFree 0x%x\n", (unsigned)wp.cbWriteFree); Print("hWriteThread 0x%x\n", (unsigned)wp.hWriteThread); Print("hWriteEvent 0x%x\n", (unsigned)wp.hWriteEvent); Print("dwThreadID 0x%x\n", (unsigned)wp.dwThreadID); Print("dwErrCode 0x%x\n", (unsigned)wp.dwErrCode); Print("COMSTAT addr: 0x%x\n", (unsigned)(((char *)&wp.cs - (char *)&wp) + (char *)pwp)); Print("fChEvt 0x%x\n", (unsigned)wp.fChEvt); Print("pdcb16 0x%x\n", (unsigned)wp.pdcb16); Print("fUnGet %s\n", wp.fUnGet ? "TRUE" : "FALSE"); Print("cUnGet 0x%x (%c)\n", (unsigned)wp.cUnGet, wp.cUnGet); Print("hMiThread 0x%x\n", (unsigned)wp.hMiThread); Print("fClose %s\n", wp.fClose ? "TRUE" : "FALSE"); Print("dwComDEB16 0x%x\n", (unsigned)wp.dwComDEB16); Print("lpComDEB16 0x%x\n", (unsigned)wp.lpComDEB16); Print("\n"); return; } VOID dt( ARGLIST ) // dump WOW32 task database entry { TD td; PTD ptd; PWOAINST pWOA, pWOALast; PTDB ptdb; BOOL fAll = FALSE; BYTE SavedByte; UNREFERENCED_PARAMETERS(); Print = lpExtensionApis->lpOutputRoutine; GetSymbol = lpExtensionApis->lpGetSymbolRoutine; while (' ' == lpArgumentString[0]) { lpArgumentString++; } 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"); } do { Print("Dump of TD at 0x%08x:\n\n", (unsigned)ptd); try { READWOW(td, ptd); } except (1) { Print("Exception 0x%08x reading TD at 0x%08x!\n\n", GetExceptionCode(), ptd); return; } 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"); } 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; try { READWOW(CommDlgTd, td.CommDlgTd); } except (1) { fCopySuccessful = FALSE; Print("Exception 0x%08x reading COMMDLGTD at 0x%08x!\n\n", GetExceptionCode(), 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); Print("dwWOWCompatFlagsEx 0x%08x\n", td.dwWOWCompatFlags); 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; BOOL fCopySuccessful = TRUE; try { READWOW(u.buf, pWOA); } except (1) { fCopySuccessful = FALSE; Print("Exception 0x%08x reading WOAINST at 0x%08x!\n\n", GetExceptionCode(), pWOA); } if (fCopySuccessful) { 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; } else { pWOA = NULL; } } Print("htask16 0x%04x (use \"!dtdb %x\" for complete dump)\n", td.htask16, td.htask16); // // Dump the most interesting TDB fields // if (ptdb = FlatFromProt(td.htask16 << 16)) { TDB tdb; BOOL fCopySuccessful = TRUE; try { READWOW(tdb, ptdb); } except (1) { fCopySuccessful = FALSE; Print("Exception 0x%08x reading TDB at 0x%08x!\n\n", GetExceptionCode(), ptdb); } if (fCopySuccessful) { 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_Directory); Print(" PDB (aka PSP) 0x%04x\n", tdb.TDB_PDB); // // Dump open file handle info // pPDB = (PDOSPDB) FlatFromProt(tdb.TDB_PDB << 16); READWOW(PDB, pPDB); pJFT = (PBYTE) FlatFromReal(PDB.PDB_JFN_Pointer); cbJFT = PDB.PDB_JFN_Length; Print(" JFT %04x:%04x size 0x%x\n", HIWORD(PDB.PDB_JFN_Pointer), LOWORD(PDB.PDB_JFN_Pointer), cbJFT); try { READMEM(hCurrentProcess, pJFT, JFT, cbJFT, NULL); } 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"); READWOW(DosWowData, pDosWowData); if ((DWORD)pSFTHead != DosWowData.lpSftAddr) { Print("ntvdm!pSFTHead is 0x%08x, DosWowData.lpSftAddr ix 0x%08x.\n", pSFTHead, DosWowData.lpSftAddr); } try { READMEM(hCurrentProcess, pSFTHead, &SFTHead, sizeof(SFTHead), NULL); } except (1) { Print("Unable to read SFTHead from 0x%08x!\n", pSFTHead); return; } cb = sizeof(DOSSF) + SFTHead.SFCount * sizeof(DOSSFT); pSFTHeadCopy = malloc_w(cb); //Print("First DOSSF at 0x%08x, SFCount 0x%x, SFLink 0x%08x.\n", // pSFTHead, SFTHead.SFCount, SFTHead.SFLink); try { READMEM(hCurrentProcess, pSFTHead, pSFTHeadCopy, cb, NULL); } 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 (pSFTHeadCopy->SFLink & 0xFFFF == 0xFFFF) { SFN = JFT[fh] - 1; break; } pSFTHead = FlatFromReal(pSFTHeadCopy->SFLink); i = 0; try { READMEM(hCurrentProcess, pSFTHead, &SFTHead, sizeof(SFTHead), NULL); } except (1) { Print("Unable to read SFTHead from 0x%08x!\n", pSFTHead); return; } cb = sizeof(DOSSF) + SFTHead.SFCount * sizeof(DOSSFT); free_w(pSFTHeadCopy); pSFTHeadCopy = malloc_w(cb); //Print("Next DOSSF at 0x%08x, SFCount 0x%x, SFLink 0x%08x.\n", // pSFTHead, SFTHead.SFCount, SFTHead.SFLink); try { READMEM(hCurrentProcess, pSFTHead, pSFTHeadCopy, cb, NULL); } 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_w(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 ddte( ARGLIST ) // dump dispatch table entry { W32 dte; PW32 pdte; char szW32[32]; char szSymbol[256]; DWORD dwOffset; UNREFERENCED_PARAMETERS(); Print = lpExtensionApis->lpOutputRoutine; GetSymbol = lpExtensionApis->lpGetSymbolRoutine; while (' ' == lpArgumentString[0]) { lpArgumentString++; } pdte = (PW32) WDahtoi(lpArgumentString); if (pdte) { Print("Dump of dispatch table entry at 0x%08x:\n\n", (unsigned)pdte); } else { GETEXPRADDR(pdte, "wow32!aw32WOW"); Print("Dump of first dispatch table entry at 0x%08x:\n\n", (unsigned)pdte); } try { READWOW(dte, pdte); if (dte.lpszW32) { READWOW(szW32, dte.lpszW32); dte.lpszW32 = szW32; szW32[sizeof(szW32)-1] = '\0'; } } except (1) { Print("Exception 0x%08x reading dispatch table entry at 0x%08x!\n\n", GetExceptionCode(), pdte); return; } Print("Dispatches to address 0x%08x, ", (unsigned)dte.lpfnW32); Print("supposedly function '%s'.\n", dte.lpszW32); szSymbol[0] = '\0'; GetSymbol((LPVOID)dte.lpfnW32, szSymbol, &dwOffset); Print("Debugger finds symbol '%s' for that address.\n", szSymbol); Print("\n"); return; } /********* local functions for WOWPROFILE support *********/ /******* function protoypes for local functions for WOWPROFILE support *******/ BOOL WDGetAPIProfArgs(LPSZ lpszArgStr, HANDLE hCurrentProcess, PWINDBG_EXTENSION_APIS lpExtensionApis, INT iThkTblMax, PPA32 ppaThkTbls, LPSZ lpszTab, BOOL *bTblAll, LPSZ lpszFun, int *iFunInd); BOOL WDGetMSGProfArgs(LPSZ lpszArgStr, LPSZ lpszMsg, int *iMsgNum); INT WDParseArgStr(LPSZ lpszArgStr, CHAR **argv, INT iMax); 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); } BOOL WDGetAPIProfArgs(LPSZ lpszArgStr, HANDLE hCurrentProcess, PWINDBG_EXTENSION_APIS lpExtensionApis, INT iThkTblMax, PPA32 ppaThkTbls, LPSZ lpszTab, BOOL *bTblAll, LPSZ lpszFun, int *iFunInd) { /* * Decomposes & interprets argument string to apiprofdmp extension. * INPUT: * lpszArgStr - ptr to input arg string * iThkTblMax - # tables in the thunk tables * ppaThkTbls - ptr to the thunk tables * OUTPUT: * lpszTab - ptr to table name * bTblAll - 0 => dump specific table, 1 => dump all tables * lpszFun - ptr to API name * iFunInd - -1 => dump specific API name * 0 => dump all API entires in table * >0 => dump specific API number (decimal) * RETURN: 0 => OK, 1 => input error (show Usage) * * legal forms: !wow32.apiprofdmp * !wow32.apiprofdmp help * !wow32.apiprofdmp user * !wow32.apiprofdmp user createwindow * !wow32.apiprofdmp user 41 * !wow32.apiprofdmp createwindow * !wow32.apiprofdmp 41 */ INT i, nArgs; CHAR *argv[2]; nArgs = WDParseArgStr(lpszArgStr, argv, 2); /* if no arguments dump all entries in all tables */ if( nArgs == 0 ) { *iFunInd = 0; // specify dump all API entires in the table *bTblAll = 1; // specify dump all tables return(0); } if( !_stricmp(argv[0], "HELP") ) { return(1); } /* see if 1st arg is a table name */ *bTblAll = 1; // specify dump all tables for (i = 0; i < nModNames; i++) { if (!_stricmp(apszModNames[i], argv[0])) { strcpy(lpszTab, apszModNames[i]); *bTblAll = 0; // specify dump specific table /* if we got a table name match & only one arg, we're done */ if( nArgs == 1 ) { *iFunInd = 0; // specify dump all API entries in the table return(0); } break; } } #if 0 for(i = 0; i < iThkTblMax; i++) { CHAR temp[40], *TblEnt[2], szTabName[40]; PA32 awThkTbl; /* get table name string from thunk tables */ READWOW2(awThkTbl, &ppaThkTbls[i], 0); READWOW2(szTabName, awThkTbl.lpszW32, 0); /* get rid of trailing spaces from table name string */ strcpy(temp, szTabName); WDParseArgStr(temp, TblEnt, 1); /* if we found a table name that matches the 1st arg...*/ if( !_stricmp(argv[0], TblEnt[0]) ) { strcpy(lpszTab, szTabName); *bTblAll = 0; // specify dump specific table /* if we got a table name match & only one arg, we're done */ if( nArgs == 1 ) { *iFunInd = 0; // specify dump all API entries in the table return(0); } break; } } #endif /* if 2 args && the 1st doesn't match a table name above => bad input */ if( (nArgs > 1) && (*bTblAll) ) { return(1); } /* set index to API spec */ nArgs--; /* try to convert API spec to a number */ *iFunInd = atoi(argv[nArgs]); strcpy(lpszFun, argv[nArgs]); /* if API spec is not a number => it's a name */ if( *iFunInd == 0 ) { *iFunInd = -1; // specify API search by name } /* else if API number is bogus -- complain */ else if( *iFunInd < 0 ) { return(1); } return(0); } BOOL WDGetMSGProfArgs(LPSZ lpszArgStr, LPSZ lpszMsg, int *iMsgNum) { /* * Decomposes & interprets argument string to msgprofdmp extension. * INPUT: * lpszArgStr - ptr to input arg string * OUTPUT: * lpszMsg - ptr to message name * iMsgNum - -1 => dump all message entries in the table * -2 => lpszMsg contains specific MSG name * >=0 => dump specific message number * RETURN: 0 => OK, 1 => input error (show Usage) */ INT nArgs; CHAR *argv[2]; nArgs = WDParseArgStr(lpszArgStr, argv, 1); /* if no arguments dump all entries in all tables */ if( nArgs == 0 ) { *iMsgNum = -1; // specify dump all MSG entires in the table return(0); } if( !_stricmp(argv[0], "HELP") ) return(1); /* try to convert MSG spec to a number */ *iMsgNum = atoi(argv[0]); strcpy(lpszMsg, argv[0]); /* if MSG spec is not a number => it's a name */ if( *iMsgNum == 0 ) { *iMsgNum = -2; // specify lpszMsg contains name to search for } /* else if MSG number is bogus -- complain */ else if( *iMsgNum < 0 ) { return(1); } return(0); } /******* API profiler table functions ********/ /* init some common strings */ CHAR szAPI[] = "API# API Name"; CHAR szMSG[] = "MSG Name - MSG #"; CHAR szTITLES[] = "# Calls Tot. tics tics/call"; CHAR szDASHES[] = "----------------------------------- ------- --------------- ---------------"; CHAR szTOOBIG[] = "too large for table."; CHAR szNOTUSED[] = "Unused table index."; CHAR szAPIUSAGE[] = "Usage: !wow32.APIProfDmp [TblName] [APIspec]\n\n where: TblName = kernel | user | gdi | keyboard | sound | shell | mmed\n (no TblName implies 'all tables')\n\n APIspec = API # or API name"; CHAR szMSGUSAGE[] = "Usage: !wow32.MsgProfDmp [MessageName | MessageNum (decimal)]\n (no argument implies 'all messages')"; CHAR szRNDTRIP[] = "Round trip message profiling"; CHAR szCLEAR[] = "Remember to clear the message profile tables."; VOID apiprofclr( ARGLIST ) { int iTab, iFun, iEntries; INT iThkTblMax; W32 awAPIEntry; PW32 pawAPIEntryTbl; PA32 awThkTbl; PPA32 ppaThkTbls; CHAR szTable[20]; UNREFERENCED_PARAMETERS(); Print = lpExtensionApis->lpOutputRoutine; GETEXPRVALUE(iThkTblMax, "wow32!iThunkTableMax", INT); GETEXPRVALUE(ppaThkTbls, "wow32!pawThunkTables", PPA32); Print("Clearing:"); for(iTab = 0; iTab < iThkTblMax; iTab++) { READWOW(awThkTbl, &ppaThkTbls[iTab]); READWOW(szTable, awThkTbl.lpszW32); Print(" %s", szTable); pawAPIEntryTbl = awThkTbl.lpfnA32; READWOW(iEntries, awThkTbl.lpiFunMax); for(iFun = 0; iFun < iEntries; iFun++) { READWOW(awAPIEntry, &pawAPIEntryTbl[iFun]); awAPIEntry.cCalls = 0L; awAPIEntry.cTics = 0L; WRITEWOW(&pawAPIEntryTbl[iFun], awAPIEntry); } } Print("\n"); return; } VOID apiprofdmp( ARGLIST ) { BOOL bTblAll, bFound; int i, iFun, iFunInd; INT iThkTblMax; W32 awAPIEntry; PW32 pawAPIEntryTbl; PA32 awThkTbl; PPA32 ppaThkTbls; CHAR szTab[20], szFun[40], szTable[20], szFunName[40]; UNREFERENCED_PARAMETERS(); Print = lpExtensionApis->lpOutputRoutine; GETEXPRVALUE(iThkTblMax, "wow32!iThunkTableMax", INT); GETEXPRVALUE(ppaThkTbls, "wow32!pawThunkTables", PPA32); if( WDGetAPIProfArgs(lpArgumentString, hCurrentProcess, lpExtensionApis, iThkTblMax, ppaThkTbls, szTab, &bTblAll, szFun, &iFunInd) ) { Print("\n\n%s\n", szAPIUSAGE); return; } bFound = FALSE; #if 0 for(iTab = 0; iTab < iThkTblMax; iTab++) { READWOW(awThkTbl, &ppaThkTbls[iTab]); READWOW(szTable, awThkTbl.lpszW32); /* if dump all tables || dump this specific table */ if( bTblAll || !strcmp(szTab, szTable) ) { pawAPIEntryTbl = awThkTbl.lpfnA32; #endif for (i = 0; i < nModNames; i++) { READWOW(awThkTbl, &ppaThkTbls[0]); strcpy(szTable, apszModNames[i]); /* if dump all tables || dump this specific table */ if (bTblAll || !_stricmp(szTab, apszModNames[i])) { INT nFirst, nLast; nFirst = TableOffsetFromName(apszModNames[i]); if (i < nModNames - 1) nLast = TableOffsetFromName(apszModNames[i+1]) - 1; else nLast = cAPIThunks - 1; pawAPIEntryTbl = awThkTbl.lpfnA32; /* if dump a specific API number */ if( iFunInd > 0 ) { Print("\n>>>> %s\n", szTable); Print("%s %s\n%s\n", szAPI, szTITLES, szDASHES); //if( iFunInd >= *(awThkTbl.lpiFunMax) ) { if( iFunInd > nLast - nFirst ) { Print("Index #%d %s.\n", GetOrdinal(iFunInd), szTOOBIG); } else { bFound = TRUE; // READWOW(awAPIEntry, &pawAPIEntryTbl[iFunInd]); READWOW(awAPIEntry, &pawAPIEntryTbl[nFirst + iFunInd]); READWOW(szFunName, awAPIEntry.lpszW32); if( szFunName[0] ) { Print("%4d %30s ", GetOrdinal(iFunInd), szFunName); } else { Print("%4d %30s ", GetOrdinal(iFunInd), szNOTUSED); } Print("%7ld %15ld ", awAPIEntry.cCalls, awAPIEntry.cTics); if(awAPIEntry.cCalls) { Print("%15ld\n", awAPIEntry.cTics/awAPIEntry.cCalls); } else { Print("%15ld\n", 0L); } } } /* else if dump an API by name */ else if ( iFunInd == -1 ) { // READWOW(iEntries, awThkTbl.lpiFunMax); // for(iFun = 0; iFun < iEntries; iFun++) { for(iFun = nFirst; iFun <= nLast; iFun++) { READWOW(awAPIEntry, &pawAPIEntryTbl[iFun]); READWOW(szFunName, awAPIEntry.lpszW32); if ( !_stricmp(szFun, szFunName) ) { Print("\n>>>> %s\n", szTable); Print("%s %s\n%s\n", szAPI, szTITLES, szDASHES); Print("%4d %30s %7ld %15ld ", GetOrdinal(iFun), szFunName, awAPIEntry.cCalls, awAPIEntry.cTics); if(awAPIEntry.cCalls) { Print("%15ld\n", awAPIEntry.cTics/awAPIEntry.cCalls); } else { Print("%15ld\n", 0L); } return; } } } /* else dump all the API's in the table */ else { Print("\n>>>> %s\n", szTable); Print("%s %s\n%s\n", szAPI, szTITLES, szDASHES); bFound = TRUE; // READWOW(iEntries, awThkTbl.lpiFunMax); // for(iFun = 0; iFun < iEntries; iFun++) { for(iFun = nFirst; iFun <= nLast; iFun++) { READWOW(awAPIEntry, &pawAPIEntryTbl[iFun]); READWOW(szFunName, awAPIEntry.lpszW32); if(awAPIEntry.cCalls) { Print("%4d %30s %7ld %15ld %15ld\n", GetOrdinal(iFun), szFunName, awAPIEntry.cCalls, awAPIEntry.cTics, awAPIEntry.cTics/awAPIEntry.cCalls); } } if( !bTblAll ) { return; } } } } if( !bFound ) { Print("\nCould not find "); if( !bTblAll ) { Print("%s ", szTab); } Print("API: %s\n", szFun); Print("\n%s\n", szAPIUSAGE); } return; } /******* MSG profiler table functions ********/ VOID msgprofclr( ARGLIST ) { int iMsg; INT iMsgMax; M32 awM32; PM32 paw32Msg; UNREFERENCED_PARAMETERS(); Print = lpExtensionApis->lpOutputRoutine; GETEXPRVALUE(iMsgMax, "wow32!iMsgMax", INT); GETEXPRVALUE(paw32Msg, "wow32!paw32Msg", PM32); Print("Clearing Message profile table"); for(iMsg = 0; iMsg < iMsgMax; iMsg++) { READWOW(awM32, &paw32Msg[iMsg]); awM32.cCalls = 0L; awM32.cTics = 0L; WRITEWOW(&paw32Msg[iMsg], awM32); } Print("\n"); return; } VOID msgprofdmp( ARGLIST ) { int iMsg, iMsgNum; INT iMsgMax; BOOL bFound; M32 aw32Msg; PM32 paw32Msg; CHAR szMsg[40], *argv[2], szMsg32[40], szMsgName[40]; UNREFERENCED_PARAMETERS(); Print = lpExtensionApis->lpOutputRoutine; GETEXPRVALUE(iMsgMax, "wow32!iMsgMax", INT); GETEXPRVALUE(paw32Msg, "wow32!paw32Msg", PM32); if( WDGetMSGProfArgs(lpArgumentString, szMsg, &iMsgNum) ) { Print("\n\n%s\n", szMSGUSAGE); return; } Print("%35s %s\n%s\n", szMSG, szTITLES, szDASHES); if( iMsgNum > iMsgMax ) { Print("MSG #%4d %s.\n", iMsgNum, szTOOBIG); return; } bFound = 0; for(iMsg = 0; iMsg < iMsgMax; iMsg++) { READWOW(aw32Msg, &paw32Msg[iMsg]); READWOW(szMsgName, aw32Msg.lpszW32); /* if specific msg name, parse name from "WM_MSGNAME 0x00XX" format */ if( iMsgNum == -2 ) { strcpy(szMsg32, szMsgName); WDParseArgStr(szMsg32, argv, 1); } /* if 'all' msgs || specific msg # || specific msg name */ if( (iMsgNum == -1) || (iMsg == iMsgNum) || ( (iMsgNum == -2) && (!strcmp(szMsg, argv[0])) ) ) { bFound = 1; if(aw32Msg.cCalls) { Print("%35s %7ld %15ld %15ld\n", szMsgName, aw32Msg.cCalls, aw32Msg.cTics, aw32Msg.cTics/aw32Msg.cCalls); } /* else if MSG wasn't sent & we're not dumping the whole table */ else if( iMsgNum != -1 ) { Print("%35s %7ld %15ld %15ld\n", szMsgName, 0L, 0L, 0L); } /* if we're not dumping the whole table, we're done */ if( iMsgNum != -1 ) { return; } } } if( !bFound ) { Print("\nCould not find MSG: %s\n", szMsg); Print("\n%s\n", szMSGUSAGE); } return; } void msgprofrt( ARGLIST ) { INT fWMsgProfRT; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); Print = lpExtensionApis->lpOutputRoutine; GETEXPRADDR(lpAddress, "wow32!fWMsgProfRT"); READWOW(fWMsgProfRT, lpAddress); fWMsgProfRT = 1 - fWMsgProfRT; WRITEWOW(lpAddress, fWMsgProfRT); if( fWMsgProfRT ) { Print("\n%s ENABLED.\n%s\n\n", szRNDTRIP, szCLEAR); } else { Print("\n%s DISABLED.\n%s\n\n", szRNDTRIP, szCLEAR); } 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 ( ARGLIST ) { UINT i; ATOM atom; CHAR pszGAtomName[128]; CHAR pszLAtomName[128]; CHAR pszCAtomName[128]; CHAR *argv[2], *psz; UNREFERENCED_PARAMETERS(); // set up function pointer Print = lpExtensionApis->lpOutputRoutine; 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; Print("\n%s: ", argv[0]); if(GlobalGetAtomName(atom, pszGAtomName, 128) > 0) { Print(" \"%s\" ", pszGAtomName); psz = pszGAtomName; } else if(GetAtomName(atom, pszLAtomName, 128) > 0) { Print(" \"%s\" ", pszLAtomName); psz = pszLAtomName; } else if(GetClipboardFormatName((UINT)atom, pszCAtomName, 128) > 0) { Print(" \"%s\" ", pszCAtomName); psz = pszCAtomName; } if(psz) { i = 0; while(psz[i] && i < 128) { Print(" %2X", psz[i++] & 0x000000FF); } } else { Print("\n"); Print(" GlobalGetAtomName string: \"%c\" ", pszGAtomName[0]); for(i = 0; i < 8; i++) { Print(" %2X", pszGAtomName[i] & 0x000000FF); } Print("\n GetAtomName string: \"%c\" ", pszLAtomName[0]); for(i = 0; i < 8; i++) { Print(" %2X", pszLAtomName[i] & 0x000000FF); } Print("\n GetClipboardFormatName string: \"%c\" ", pszCAtomName[0]); for(i = 0; i < 8; i++) { Print(" %2X", pszCAtomName[i] & 0x000000FF); } } Print("\n\n"); } else { Print("Usage: at hex_atom_number\n"); } } void ww ( ARGLIST ) { PWW pww; INT h16; CHAR *argv[2]; UNREFERENCED_PARAMETERS(); // set up function pointer Print = lpExtensionApis->lpOutputRoutine; if(WDParseArgStr(lpArgumentString, argv, 1)) { if((h16 = WDahtoi(argv[0])) >= 0) { try { pww = (PWW)GetWindowLong((HWND)HWND32((HAND16)h16),GWL_WOWWORDS); Print("16:16 WndProc : %08lX\n", pww->vpfnWndProc); Print("16:16 DlgProc : %08lX\n", pww->vpfnDlgProc); Print("iClass : %#lx (%s) \n", pww->iClass, aszWOWCLASS[pww->iClass]); Print("dwStyle : %08lX\n", pww->dwStyle); Print("hInstance : %08lX\n", pww->hInstance); Print("16 bit handle : %#x\n", h16); } except (EXCEPTION_ACCESS_VIOLATION == GetExceptionCode()) { Print("!wow32.ww: Invalid HWND16 %04x\n", h16); } } else { Print("Usage: ww hwnd16\n"); } } else { Print("Usage: ww hwnd16\n"); } } void wc ( ARGLIST ) { PWC pwc; INT h16; CHAR *argv[2]; UNREFERENCED_PARAMETERS(); // set up function pointer Print = lpExtensionApis->lpOutputRoutine; if(WDParseArgStr(lpArgumentString, argv, 1)) { if((h16 = WDahtoi(argv[0])) >= 0){ try { pwc = (PWC)GetClassLong((HWND)HWND32((HAND16)h16),GCL_WOWWORDS); Print("16:16 WndProc : %08lX\n", pwc->vpfnWndProc); Print("VPSZ : %08lX\n", pwc->vpszMenu); Print("PWC : %08lX\n\n", pwc); } except (EXCEPTION_ACCESS_VIOLATION == GetExceptionCode()) { Print("!wow32.wc: Invalid HWND16 %04x\n", h16); } } else { Print("Usage: wc hwnd16\n"); } } else { Print("Usage: wc hwnd16\n"); } } /******* Misc filtering functions ********/ // // Set Filter Filtering of Specific APIs ON // void filterspecific( ARGLIST ) { INT i; INT fLogFilter; WORD wfLogFunctionFilter; LPVOID lpAddress; PWORD pawfLogFunctionFilter; UNREFERENCED_PARAMETERS(); GETEXPRVALUE(pawfLogFunctionFilter, "wow32!pawfLogFunctionFilter", PWORD); GetExpression = lpExtensionApis->lpGetExpressionRoutine; for (i = 0; i < FILTER_FUNCTION_MAX ; i++) { // Find Empty Position In Array READWOW(wfLogFunctionFilter, &pawfLogFunctionFilter[i]); if ((wfLogFunctionFilter == 0xffff) || (wfLogFunctionFilter == 0x0000)) { // Add New Filter to Array wfLogFunctionFilter = (WORD)GetExpression(lpArgumentString); WRITEWOW(&pawfLogFunctionFilter[i], wfLogFunctionFilter); break; } } GETEXPRADDR(lpAddress, "wow32!fLogFilter"); fLogFilter = 0xffffffff; WRITEWOW(lpAddress, fLogFilter); return; } // // Clear Filter Specific Array // void clearfilterspecific( ARGLIST ) { INT i; WORD NEG1 = (WORD) -1; WORD ZERO = 0; PWORD pawfLogFunctionFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRVALUE(pawfLogFunctionFilter, "wow32!pawfLogFunctionFilter", PWORD); WRITEWOW(&pawfLogFunctionFilter[0], NEG1); for (i=1; i < FILTER_FUNCTION_MAX ; i++) { WRITEWOW(&pawfLogFunctionFilter[i], ZERO); } GETEXPRADDR(lpAddress, "wow32!iLogFuncFiltIndex"); WRITEWOW(lpAddress, ZERO); return; } // // Dump Last Logged APIs // void lastlog( ARGLIST ) { INT iCircBuffer; CHAR achTmp[TMP_LINE_LEN], *pachTmp; INT i; UNREFERENCED_PARAMETERS(); Print = lpExtensionApis->lpOutputRoutine; GETEXPRVALUE(iCircBuffer, "wow32!iCircBuffer", INT); GETEXPRVALUE(pachTmp, "wow32!pachTmp", PCHAR); for (i = iCircBuffer; i >= 0; i--) { READWOW(achTmp, &pachTmp[i*TMP_LINE_LEN]); Print("%s",achTmp); } for (i = CIRC_BUFFERS-1; i > iCircBuffer; i--) { READWOW(achTmp, &pachTmp[i*TMP_LINE_LEN]); Print("%s",achTmp); } return; } // creates/closes toggle for logfile for iloglevel logging in c:\ilog.log void logfile( ARGLIST ) { INT nArgs; CHAR *argv[2], szLogFile[128]; DWORD fLog; LPVOID lpfLog, lpszLogFile; UNREFERENCED_PARAMETERS(); nArgs = WDParseArgStr(lpArgumentString, argv, 1); Print = lpExtensionApis->lpOutputRoutine; GETEXPRADDR(lpfLog, "wow32!fLog"); READWOW(fLog, lpfLog); if(nArgs) { strcpy(szLogFile, argv[0]); } else { strcpy(szLogFile, "c:\\ilog.log"); } if(fLog == 0) { fLog = 2; Print("\nCreating "); Print(szLogFile); Print("\n\n"); } else { fLog = 3; Print("\nClosing logfile\n\n"); } WRITEWOW(lpfLog, fLog); GETEXPRADDR(lpszLogFile, "wow32!szLogFile"); WRITENWOW(lpszLogFile, szLogFile, strlen(szLogFile)+1); return; } // // Set TaskID Filtering // void filtertask( ARGLIST ) { INT fLogTaskFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogTaskFilter"); GetExpression = lpExtensionApis->lpGetExpressionRoutine; fLogTaskFilter = (INT)GetExpression(lpArgumentString); WRITEWOW(lpAddress, fLogTaskFilter); return; } // // Turn All filtering ON // void resetfilter( ARGLIST ) { INT fLogFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); fLogFilter = 0xffffffff; WRITEWOW(lpAddress, fLogFilter); return; } // // Turn All filtering OFF // void clearfilter( ARGLIST ) { INT fLogFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); fLogFilter = 0x00000000; WRITEWOW(lpAddress, fLogFilter); return; } // // Set iLogLevel from Debugger Extension // void setloglevel( ARGLIST ) { INT iLogLevel; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!iLogLevel"); GetExpression = lpExtensionApis->lpGetExpressionRoutine; iLogLevel = (INT)GetExpression(lpArgumentString); WRITEWOW(lpAddress, iLogLevel); return; } // // Toggle Single Step Trace Mode // void steptrace( ARGLIST ) { INT localfDebugWait; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fDebugWait"); READWOW(localfDebugWait, lpAddress); localfDebugWait = ~localfDebugWait; WRITEWOW(lpAddress, localfDebugWait); return; } // // Toggle Verbose API Tracing // void filterverbose( ARGLIST ) { INT fLogFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); READWOW(fLogFilter, lpAddress); if ((fLogFilter & FILTER_VERBOSE) == 0) { fLogFilter |= FILTER_VERBOSE; } else { fLogFilter &= ~FILTER_VERBOSE; } WRITEWOW(lpAddress, fLogFilter); return; } // // Toggle Kernel API Tracing // void filterkernel16( ARGLIST ) { INT fLogFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); READWOW(fLogFilter, lpAddress); if ((fLogFilter & FILTER_KERNEL16) == 0) { fLogFilter |= FILTER_KERNEL16; } else { fLogFilter &= ~FILTER_KERNEL16; } WRITEWOW(lpAddress, fLogFilter); return; } void filterkernel( ARGLIST ) { INT fLogFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); READWOW(fLogFilter, lpAddress); if ((fLogFilter & FILTER_KERNEL) == 0) { fLogFilter |= FILTER_KERNEL; } else { fLogFilter &= ~FILTER_KERNEL; } WRITEWOW(lpAddress, fLogFilter); return; } void filteruser( ARGLIST ) { INT fLogFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); READWOW(fLogFilter, lpAddress); if ((fLogFilter & FILTER_USER) == 0) { fLogFilter |= FILTER_USER; } else { fLogFilter &= ~FILTER_USER; } WRITEWOW(lpAddress, fLogFilter); return; } void filtergdi( ARGLIST ) { INT fLogFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); READWOW(fLogFilter, lpAddress); if ((fLogFilter & FILTER_GDI) == 0) { fLogFilter |= FILTER_GDI; } else { fLogFilter &= ~FILTER_GDI; } WRITEWOW(lpAddress, fLogFilter); return; } void filterkeyboard( ARGLIST ) { INT fLogFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); READWOW(fLogFilter, lpAddress); if ((fLogFilter & FILTER_KEYBOARD) == 0) { fLogFilter |= FILTER_KEYBOARD; } else { fLogFilter &= ~FILTER_KEYBOARD; } WRITEWOW(lpAddress, fLogFilter); return; } void filtermmedia( ARGLIST ) { INT fLogFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); READWOW(fLogFilter, lpAddress); if ((fLogFilter & FILTER_MMEDIA) == 0) { fLogFilter |= FILTER_MMEDIA; } else { fLogFilter &= ~FILTER_MMEDIA; } WRITEWOW(lpAddress, fLogFilter); return; } void filterwinsock( ARGLIST ) { INT fLogFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); READWOW(fLogFilter, lpAddress); if ((fLogFilter & FILTER_WINSOCK) == 0) { fLogFilter |= FILTER_WINSOCK; } else { fLogFilter &= ~FILTER_WINSOCK; } WRITEWOW(lpAddress, fLogFilter); return; } void filtersound( ARGLIST ) { INT fLogFilter; LPVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); READWOW(fLogFilter, lpAddress); if ((fLogFilter & FILTER_SOUND) == 0) { fLogFilter |= FILTER_SOUND; } else { fLogFilter &= ~FILTER_SOUND; } WRITEWOW(lpAddress, fLogFilter); return; } void filtercommdlg( ARGLIST ) { INT fLogFilter; PVOID lpAddress; UNREFERENCED_PARAMETERS(); GETEXPRADDR(lpAddress, "wow32!fLogFilter"); READWOW(fLogFilter, lpAddress); if ((fLogFilter & FILTER_COMMDLG) == 0) { fLogFilter |= FILTER_COMMDLG; } else { fLogFilter &= ~FILTER_COMMDLG; } WRITEWOW(lpAddress, fLogFilter); return; } void cia( ARGLIST ) { CURSORICONALIAS cia; PVOID lpAddress; INT maxdump = 500; Print = lpExtensionApis->lpOutputRoutine; GETEXPRADDR(lpAddress, "wow32!lpCIAlias"); READWOW(lpAddress, lpAddress); if (!lpAddress) { Print("Cursor/Icon alias list is empty.\n"); } else { Print("Alias tp H16 H32 inst mod task res szname\n"); READWOW(cia, lpAddress); while ((lpAddress != NULL) && --maxdump) { if (cia.fInUse) { Print("%08X", lpAddress); Print(" %02X", cia.flType); Print(" %04X", cia.h16); Print(" %08X", cia.h32); Print(" %04X", cia.hInst16); Print(" %04X", cia.hMod16); Print(" %04X", cia.hTask16); Print(" %04X", cia.hRes16); Print(" %08X\n", cia.lpszName); } lpAddress = cia.lpNext; READWOW(cia, lpAddress); } if (!maxdump) { Print("Dump ended prematurely - possible infinite loop \n"); } } } #endif