mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2063 lines
56 KiB
2063 lines
56 KiB
/******************************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 <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <winerror.h>
|
|
#include <excpt.h>
|
|
#include <ntstatus.h>
|
|
#include <ntdbg.h>
|
|
#define NOEXTAPI // wesw is a bonehead sometimes
|
|
#include <wdbgexts.h>
|
|
#include <ctype.h>
|
|
|
|
//
|
|
// 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 <addr> - Dump dispatch table entry pointed to by <addr>\n");
|
|
Print(" dt <addr> - Dump TD at <addr> or all if blank\n");
|
|
Print(" dwp <addr> - Dump WOWPORT structure pointed to by <addr>\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("<Global atom> \"%s\" ", pszGAtomName);
|
|
psz = pszGAtomName;
|
|
}
|
|
else if(GetAtomName(atom, pszLAtomName, 128) > 0) {
|
|
Print("<Local atom> \"%s\" ", pszLAtomName);
|
|
psz = pszLAtomName;
|
|
}
|
|
else if(GetClipboardFormatName((UINT)atom, pszCAtomName, 128) > 0) {
|
|
Print("<Clipboard format> \"%s\" ", pszCAtomName);
|
|
psz = pszCAtomName;
|
|
}
|
|
if(psz) {
|
|
i = 0;
|
|
while(psz[i] && i < 128) {
|
|
Print(" %2X", psz[i++] & 0x000000FF);
|
|
}
|
|
}
|
|
else {
|
|
Print("<Undetermined type>\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
|