Leaked source code of windows server 2003
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.
 
 
 
 
 
 

16840 lines
527 KiB

/****************************** Module Header ******************************\
* Module Name: userexts.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* This module contains user related debugging extensions.
*
* History:
* 17-May-1991 DarrinM Created.
* 22-Jan-1992 IanJa ANSI/Unicode neutral (all debug output is ANSI)
* 23-Mar-1993 JerrySh Moved from winsrv.dll to userexts.dll
* 21-Oct-1993 JerrySh Modified to work with WinDbg
* 18-Oct-1994 ChrisWil Added Object Tracking extent.
* 26-May-1995 Sanfords Made it more general for the good of humanity.
* 09-Jun-1995 SanfordS Made to fit stdexts motif and to dual compile for
* either USER or KERNEL mode.
\***************************************************************************/
#include "userkdx.h"
#include "vkoem.h"
#ifdef KERNEL
CONST PSTR pszExtName = "USERKDX";
#else
CONST PSTR pszExtName = "USEREXTS";
#endif
#include <stdext64.h>
#include <stdext64.c>
/***************************************************************************\
* Constants
\***************************************************************************/
#define CDWORDS 16
#define BF_MAX_WIDTH 80
#define BF_COLUMN_WIDTH 19
typedef ULONG64 PTR, *PPTR;
#define NULL_PTR ((PTR)(0))
// If you want to debug the extension, enable this.
#if 0
#undef DEBUGPRINT
#define DEBUGPRINT Print
#endif
/***************************************************************************\
* Global variables
\***************************************************************************/
BOOL bShowFlagNames = TRUE;
char gach1[80];
char gach2[80];
char gach3[80];
int giBFColumn; // bit field: current column
char gaBFBuff[BF_MAX_WIDTH + 1]; // bit field: buffer
// used in dsi() and dinp()
typedef struct {
int iMetric;
LPSTR pstrMetric;
} SYSMET_ENTRY;
#define SMENTRY(sm) {SM_##sm, #sm}
/***************************************************************************\
* Macros
\***************************************************************************/
#define TestWWF(pww, flag) (*(((PBYTE)(pww)) + (int)HIBYTE(flag)) & LOBYTE(flag))
VOID ShowProgress(
VOID);
#define CHKBREAK() do { if (IsCtrlCHit()) return TRUE; } while (FALSE)
#ifdef KERNEL // ########### KERNEL MODE ONLY MACROS ###############
#define VAR(v) "win32k!" #v
#define SYM(s) "win32k!" #s
#define FIXKP(p) p
#define RebaseSharedPtr(p) (p)
#define FOREACHWINDOWSTATION(pwinsta) \
pwinsta = GetGlobalPointer(VAR(grpWinStaList)); \
SAFEWHILE (pwinsta != 0) {
#define NEXTEACHWINDOWSTATION(pwinsta) \
GetFieldValue(pwinsta, SYM(tagWINDOWSTATION), "rpwinstaNext", pwinsta); \
}
#define FOREACHDESKTOP(pdesk) \
{ \
ULONG64 pwinsta; \
\
FOREACHWINDOWSTATION(pwinsta) \
GetFieldValue(pwinsta, SYM(WINDOWSTATION), "rpdeskList", pdesk); \
SAFEWHILE (pdesk != 0) {
#define NEXTEACHDESKTOP(pdesk) \
GetFieldValue(pdesk, SYM(DESKTOP), "rpdeskNext", pdesk); \
} \
NEXTEACHWINDOWSTATION(pwinsta) \
}
VOID PrintStackTrace(
ULONG64 pStackTrace,
int tracesCount);
typedef ULONG (WDBGAPI *PPI_CALLBACK)(ULONG64 ppi, PVOID Data);
typedef struct _PPI_CONTEXT {
PPI_CALLBACK CallbackRoutine;
PVOID Data;
} PPI_CONTEXT;
ULONG
ForEachPpiCallback(
PFIELD_INFO NextProcess,
PVOID Context)
{
ULONG64 pEProcess = NextProcess->address;
ULONG64 ppi = 0;
PPI_CONTEXT *pPpiContext = (PPI_CONTEXT *)Context;
/*
* Dump Win32 Processes only
*/
GetFieldValue(pEProcess, "nt!EPROCESS", "Win32Process", ppi);
if (ppi) {
return pPpiContext->CallbackRoutine(ppi, pPpiContext->Data);
}
return FALSE;
}
BOOL
ForEachPpi(
PPI_CALLBACK CallbackRoutine,
PVOID Data)
{
ULONG64 ProcessHead;
ULONG64 NextProcess;
PPI_CONTEXT PpiContext;
ProcessHead = EvalExp("PsActiveProcessHead");
if (!ProcessHead) {
Print("Unable to get value of PsActiveProcessHead\n");
return FALSE;
}
if (GetFieldValue(ProcessHead, "nt!_LIST_ENTRY", "Flink", NextProcess)) {
Print("Unable to get value of PsActiveProcessHead\n");
return FALSE;
}
if (NextProcess == 0) {
Print("PsActiveProcessHead->Flink is NULL!\n");
return FALSE;
}
PpiContext.CallbackRoutine = CallbackRoutine;
PpiContext.Data = Data;
ListType("nt!_EPROCESS",
NextProcess,
1,
"ActiveProcessLinks.Flink",
&PpiContext,
ForEachPpiCallback);
return TRUE;
}
typedef ULONG (WDBGAPI *PTI_CALLBACK)(ULONG64 pti, PVOID Data);
typedef struct _PTI_CONTEXT {
PTI_CALLBACK CallbackRoutine;
PVOID Data;
} PTI_CONTEXT;
ULONG
ForEachPtiCallback(
ULONG64 ppi,
PVOID Data)
{
ULONG64 pti = 0;
PTI_CONTEXT *pPtiContext = (PTI_CONTEXT *)Data;
if (GetFieldValue(ppi, SYM(PROCESSINFO), "ptiList", pti)) {
DEBUGPRINT("ForEachPti: Can't get ptiList from ppi 0x%p.\n", ppi);
}
SAFEWHILE (pti != 0) {
pPtiContext->CallbackRoutine(pti, pPtiContext->Data);
if (GetFieldValue(pti, SYM(THREADINFO), "ptiSibling", pti)) {
DEBUGPRINT("ForEachPti: Can't get ptiSibling from pti 0x%p.\n", pti);
}
}
return FALSE;
}
ULONG
ForEachPti(
PTI_CALLBACK CallbackRoutine,
PVOID Data)
{
PTI_CONTEXT PtiContext;
PtiContext.CallbackRoutine = CallbackRoutine;
PtiContext.Data = Data;
return ForEachPpi(ForEachPtiCallback, &PtiContext);
}
#else //!KERNEL ############## USER MODE ONLY MACROS ################
#define VAR(v) "user32!" #v
#define SYM(s) "user32!" #s
#define FIXKP(p) FixKernelPointer(p)
#endif //!KERNEL ############## EITHER MODE MACROS ###################
#define GETSHAREDINFO(psi) moveExp(&psi, VAR(gSharedInfo))
#define FOREACHHANDLEENTRY(phe, i) \
{ \
ULONG64 pshi, psi, cHandleEntries; \
ULONG dwHESize = GetTypeSize(SYM(HANDLEENTRY)); \
\
GETSHAREDINFO(pshi); \
if (GetFieldValue(pshi, SYM(SHAREDINFO), "psi", psi)) { \
Print("FOREACHHANDLEENTRY:Could not get SERVERINFO from SHAREDINFO %p\n", pshi); \
} \
GetFieldValue(pshi, SYM(SHAREDINFO), "aheList", phe); \
GetFieldValue(psi, SYM(SERVERINFO), "cHandleEntries", cHandleEntries); \
for (i = 0; cHandleEntries; cHandleEntries--, i++, phe += dwHESize) { \
if (IsCtrlCHit()) { \
break; \
}
#define NEXTEACHHANDLEENTRY() \
} \
}
/*
* Use these macros to print field values, globals, local values, etc.
* This assures consistent formating plus make the extensions easier to read and to maintain.
*/
#define STRWD1 "67"
#define STRWD2 "28"
#define DWSTR1 "%08lx %." STRWD1 "s"
#define DWSTR2 "%08lx %-" STRWD2 "." STRWD2 "s"
#define PTRSTR1 "%08p %-" STRWD1 "s"
#define PTRSTR2 "%08p %-" STRWD2 "." STRWD2 "s"
#define DWPSTR1 "%08p %." STRWD1 "s"
#define DWPSTR2 "%08p %-" STRWD2 "." STRWD2 "s"
#define PRTFDW1(f1) Print(DWSTR1 "\n", ReadField(f1), #f1)
#define PRTVDW1(s1, v1) Print(DWSTR1 "\n", v1, #s1)
#define PRTFDW2(f1, f2) Print(DWSTR2 "\t" DWSTR2 "\n", (DWORD)ReadField(f1), #f1, (DWORD)ReadField(f2), #f2)
#define PRTVDW2(s1, v1, s2, v2) Print(DWSTR2 "\t" DWPSTR2 "\n", v1, #s1, v2, #s2)
#define PRTFRC(p, rc) Print("%-" STRWD2 "s{%#lx, %#lx, %#lx, %#lx}\n", #rc, ##p##rc.left, ##p##rc.top, ##p##rc.right, ##p##rc.bottom)
#define PRTFPT(pt) Print("%-" STRWD2 "s{0x%x, 0x%x}\n", #pt, ReadField(pt.x), ReadField(pt.y))
#define PRTVPT(s, pt) Print("%-" STRWD2 "s{0x%x, 0x%x}\n", #s, pt.x, pt.y)
#define PRTFDWP1(f1) Print(DWPSTR1 "\n", ReadField(f1), #f1)
#define PRTFDWP2(f1, f2) Print(DWPSTR2 "\t" DWPSTR2 "\n", ReadField(f1), #f1, ReadField(f2), #f2)
#define PRTFDWPDW(f1, f2) Print(DWPSTR2 "\t" DWSTR2 "\n", ReadField(f1), #f1, ReadField(f2), #f2)
#define PRTFDWDWP(p, f1, f2) Print(DWSTR2 "\t" DWPSTR2 "\n", (DWORD)##p##f1, #f1, (DWORD_PTR)##p##f2, #f2)
/*
* Bit Fields
*/
#define BEGIN_PRTFFLG(p, type) InitTypeRead(p, type)
#define PRTFFLG(f) PrintBitField(#f, (BOOL)!!(ReadField(f)))
#define END_PRTFFLG() PrintEndBitField()
#define PRTGDW1(g1) \
{ DWORD _dw1; \
moveExpValue(&_dw1, VAR(g1)); \
Print(DWSTR1 "\n", _dw1, #g1); }
#define PRTGDW2(g1, g2) \
{ DWORD _dw1, _dw2; \
moveExpValue(&_dw1, VAR(g1)); \
moveExpValue(&_dw2, VAR(g2)); \
Print(DWSTR2 "\t" DWSTR2 "\n", _dw1, #g1, _dw2, #g2); }
#define PRTGPTR1(g1) \
Print(PTRSTR1 "\n", GetGlobalPointer(VAR(g1)), #g1)
#define PRTGPTR2(g1, g2) \
Print(PTRSTR2 "\t" PTRSTR2 "\n", GetGlobalPointer(VAR(g1)), #g1, GetGlobalPointer(VAR(g2)), #g2)
/* This macro requires char ach[...]; to be previously defined */
#define PRTWND(s, pwnd) \
{ DebugGetWindowTextA(pwnd, ach, ARRAY_SIZE(ach)); \
Print("%-" STRWD2 "s" DWPSTR2 "\n", #s, pwnd, ach); }
#define PRTGWND(gpwnd) \
{ ULONG64 _pwnd; \
moveExpValuePtr(&_pwnd, VAR(gpwnd)); \
DebugGetWindowTextA(_pwnd, ach, ARRAY_SIZE(ach)); \
Print("%-" STRWD2 "s" DWPSTR2 "\n", #gpwnd, _pwnd, ach); }
#ifdef LATER // macros above need fix... and callers as well that mix up DWORD and PVOID.
#define PRTGDW1(g1) \
{\
DWORD _dw1 = GetGlobalDWord(VAR(g1)); \
Print(DWSTR1 "\n", _dw1, #g1); \
}
#define PRTGDW2(g1, g2) \
{\
DWORD _dw1 = GetGlobalDWord(VAR(g1)); \
DWORD _dw2 = GetGlobalDWord(VAR(g2)); \
Print(DWSTR2 "\t" DWSTR2 "\n", _dw1, #g1, _dw2, #g2); \
}
#define PRTGWND(gpwnd) \
{ ULONG64 _pwnd = GetGlobalPointer(VAR(gpwnd)); \
DebugGetWindowTextA(_pwnd, ach); \
Print("%-" STRWD2 "s" DWPSTR2 "\n", #gpwnd, _pwnd, ach); }
#endif // LATER
/****************************************************************************\
* PROTOTYPES
* Note that all Ixxx proc prototypes are generated by stdexts.h
\****************************************************************************/
#ifdef KERNEL
BOOL GetAndDumpHE(ULONG64 dwT, PULONG64 phe, BOOL fPointerTest);
LPSTR ProcessName(ULONG64 ppi);
#else // !KERNEL
ULONG64 FixKernelPointer(ULONG64 pKernel);
BOOL DumpConvInfo(PCONV_INFO pcoi);
#endif // !KERNEL
LPSTR GetFlags(WORD wType, DWORD dwFlags, LPSTR pszBuf, BOOL fPrintZero);
BOOL HtoHE(ULONG64 h, ULONG64 *pphe);
ULONG64 GetPfromH(ULONG64 h, ULONG64 *pphe);
BOOL getHEfromP(ULONG64 *pphe, ULONG64 p);
ULONG64 HorPtoP(ULONG64 p, int type);
BOOL DebugGetWindowTextA(ULONG64 pwnd, char *achDest, DWORD dwLength);
BOOL DebugGetClassNameA(ULONG64 lpszClassName, char *achDest);
BOOL dwrWorker(ULONG64 pwnd, int tab);
BOOL CopyUnicodeString(
IN ULONG64 pData,
IN char * pszStructName,
IN char * pszFieldName,
OUT WCHAR *pszDest,
IN ULONG cchMax);
BOOL IsRemoteSession(
VOID)
{
PPEB ppeb = NtCurrentPeb();
return (ppeb->SessionId != 0);
}
int PtrWidth(
VOID)
{
static int width = 0;
if (width) {
return width;
}
if (IsPtr64()) {
return (width = 17);
} else {
return (width = 8);
}
}
/****************************************************************************\
* Flags stuff
\****************************************************************************/
typedef struct _WFLAGS {
PSZ pszText;
WORD wFlag;
} WFLAGS;
#define WF_ENTRY(flag) #flag, flag
CONST WFLAGS aWindowFlags[] = { // sorted alphabetically
WF_ENTRY(BFBITMAP),
WF_ENTRY(BFBOTTOM),
WF_ENTRY(BFCENTER),
WF_ENTRY(BFFLAT),
WF_ENTRY(BFICON),
WF_ENTRY(BFLEFT),
WF_ENTRY(BFMULTILINE),
WF_ENTRY(BFNOTIFY),
WF_ENTRY(BFPUSHLIKE),
WF_ENTRY(BFRIGHT),
WF_ENTRY(BFRIGHTBUTTON),
WF_ENTRY(BFTOP),
WF_ENTRY(BFVCENTER),
WF_ENTRY(CBFAUTOHSCROLL),
WF_ENTRY(CBFBUTTONUPTRACK),
WF_ENTRY(CBFDISABLENOSCROLL),
WF_ENTRY(CBFDROPDOWN),
WF_ENTRY(CBFDROPDOWNLIST),
WF_ENTRY(CBFDROPPABLE),
WF_ENTRY(CBFDROPTYPE),
WF_ENTRY(CBFEDITABLE),
WF_ENTRY(CBFHASSTRINGS),
WF_ENTRY(CBFLOWERCASE),
WF_ENTRY(CBFNOINTEGRALHEIGHT),
WF_ENTRY(CBFOEMCONVERT),
WF_ENTRY(CBFOWNERDRAW),
WF_ENTRY(CBFOWNERDRAWFIXED),
WF_ENTRY(CBFOWNERDRAWVAR),
WF_ENTRY(CBFSIMPLE),
WF_ENTRY(CBFSORT),
WF_ENTRY(CBFUPPERCASE),
WF_ENTRY(DF3DLOOK),
WF_ENTRY(DFCONTROL),
WF_ENTRY(DFLOCALEDIT),
WF_ENTRY(DFNOFAILCREATE),
WF_ENTRY(DFSYSMODAL),
WF_ENTRY(EFAUTOHSCROLL),
WF_ENTRY(EFAUTOVSCROLL),
WF_ENTRY(EFCOMBOBOX),
WF_ENTRY(EFLOWERCASE),
WF_ENTRY(EFMULTILINE),
WF_ENTRY(EFNOHIDESEL),
WF_ENTRY(EFNUMBER),
WF_ENTRY(EFOEMCONVERT),
WF_ENTRY(EFPASSWORD),
WF_ENTRY(EFREADONLY),
WF_ENTRY(EFUPPERCASE),
WF_ENTRY(EFWANTRETURN),
WF_ENTRY(SBFSIZEBOX),
WF_ENTRY(SBFSIZEBOXBOTTOMRIGHT),
WF_ENTRY(SBFSIZEBOXTOPLEFT),
WF_ENTRY(SBFSIZEGRIP),
WF_ENTRY(SFCENTERIMAGE),
WF_ENTRY(SFEDITCONTROL),
WF_ENTRY(SFELLIPSISMASK),
WF_ENTRY(SFNOPREFIX),
WF_ENTRY(SFNOTIFY),
WF_ENTRY(SFREALSIZECONTROL),
WF_ENTRY(SFREALSIZEIMAGE),
WF_ENTRY(SFRIGHTJUST),
WF_ENTRY(SFSUNKEN),
WF_ENTRY(WEFACCEPTFILES),
WF_ENTRY(WEFAPPWINDOW),
WF_ENTRY(WEFCLIENTEDGE),
WF_ENTRY(WEFCOMPOSITED),
WF_ENTRY(WEFCONTEXTHELP),
WF_ENTRY(WEFCONTROLPARENT),
WF_ENTRY(WEFDLGMODALFRAME),
WF_ENTRY(WEFDRAGOBJECT),
#ifdef REDIRECTION
WF_ENTRY(WEFEXTREDIRECTED),
#endif
WF_ENTRY(WEFGHOSTMAKEVISIBLE),
#ifdef LAME_BUTTON
WF_ENTRY(WEFLAMEBUTTON),
#endif // LAME_BUTTON
WF_ENTRY(WEFLEFTSCROLL),
WF_ENTRY(WEFMDICHILD),
WF_ENTRY(WEFNOACTIVATE),
WF_ENTRY(WEFNOPARENTNOTIFY),
WF_ENTRY(WEFPREDIRECTED),
WF_ENTRY(WEFRIGHT),
WF_ENTRY(WEFRTLREADING),
WF_ENTRY(WEFSTATICEDGE),
WF_ENTRY(WEFLAYERED),
WF_ENTRY(WEFTOOLWINDOW),
WF_ENTRY(WEFTOPMOST),
WF_ENTRY(WEFTRANSPARENT),
WF_ENTRY(WEFTRUNCATEDCAPTION),
WF_ENTRY(WEFWINDOWEDGE),
WF_ENTRY(WFALWAYSSENDNCPAINT),
WF_ENTRY(WFANSICREATOR),
WF_ENTRY(WFANSIPROC),
WF_ENTRY(WFANYHUNGREDRAW),
WF_ENTRY(WFBEINGACTIVATED),
WF_ENTRY(WFBORDER),
WF_ENTRY(WFBOTTOMMOST),
WF_ENTRY(WFCAPTION),
WF_ENTRY(WFCEPRESENT),
WF_ENTRY(WFCHILD),
WF_ENTRY(WFCLIPCHILDREN),
WF_ENTRY(WFCLIPSIBLINGS),
WF_ENTRY(WFCLOSEBUTTONDOWN),
WF_ENTRY(WFCPRESENT),
WF_ENTRY(WFDESTROYED),
WF_ENTRY(WFDIALOGWINDOW),
WF_ENTRY(WFDISABLED),
WF_ENTRY(WFDLGFRAME),
WF_ENTRY(WFDONTVALIDATE),
WF_ENTRY(WFERASEBKGND),
WF_ENTRY(WFFRAMEON),
WF_ENTRY(WFFULLSCREEN),
WF_ENTRY(WFGOTQUERYSUSPENDMSG),
WF_ENTRY(WFGOTSUSPENDMSG),
WF_ENTRY(WFGROUP),
WF_ENTRY(WFHASPALETTE),
WF_ENTRY(WFHASSPB),
WF_ENTRY(WFHELPBUTTONDOWN),
WF_ENTRY(WFHIDDENPOPUP),
WF_ENTRY(WFHPRESENT),
WF_ENTRY(WFHSCROLL),
WF_ENTRY(WFICONICPOPUP),
WF_ENTRY(WFINDESTROY),
WF_ENTRY(WFINTERNALPAINT),
WF_ENTRY(WFLINEDNBUTTONDOWN),
WF_ENTRY(WFLINEUPBUTTONDOWN),
WF_ENTRY(WFMAXBOX),
WF_ENTRY(WFMAXFAKEREGIONAL),
WF_ENTRY(WFMAXIMIZED),
WF_ENTRY(WFMENUDRAW),
WF_ENTRY(WFMINBOX),
WF_ENTRY(WFMINIMIZED),
WF_ENTRY(WFMPRESENT),
WF_ENTRY(WFMSGBOX),
WF_ENTRY(WFNOANIMATE),
WF_ENTRY(WFNOIDLEMSG),
WF_ENTRY(WFNONCPAINT),
WF_ENTRY(WFOLDUI),
WF_ENTRY(WFPAGEUPBUTTONDOWN),
WF_ENTRY(WFPAGEDNBUTTONDOWN),
WF_ENTRY(WFPAINTNOTPROCESSED),
WF_ENTRY(WFPIXIEHACK),
WF_ENTRY(WFPOPUP),
WF_ENTRY(WFREALLYMAXIMIZABLE),
WF_ENTRY(WFREDRAWFRAMEIFHUNG),
WF_ENTRY(WFREDRAWIFHUNG),
WF_ENTRY(WFREDUCEBUTTONDOWN),
WF_ENTRY(WFSCROLLBUTTONDOWN),
WF_ENTRY(WFSENDERASEBKGND),
WF_ENTRY(WFSENDNCPAINT),
WF_ENTRY(WFSENDSIZEMOVE),
WF_ENTRY(WFSERVERSIDEPROC),
WF_ENTRY(WFSHELLHOOKWND),
WF_ENTRY(WFSIZEBOX),
WF_ENTRY(WFSMQUERYDRAGICON),
WF_ENTRY(WFSTARTPAINT),
WF_ENTRY(WFSYNCPAINTPENDING),
WF_ENTRY(WFSYSMENU),
WF_ENTRY(WFTABSTOP),
WF_ENTRY(WFTILED),
WF_ENTRY(WFTITLESET),
WF_ENTRY(WFTOGGLETOPMOST),
WF_ENTRY(WFTOPLEVEL),
WF_ENTRY(WFUPDATEDIRTY),
WF_ENTRY(WFVERTSCROLLTRACK),
WF_ENTRY(WFVISIBLE),
WF_ENTRY(WFVPRESENT),
WF_ENTRY(WFVSCROLL),
WF_ENTRY(WFWIN31COMPAT),
WF_ENTRY(WFWIN40COMPAT),
WF_ENTRY(WFWIN50COMPAT),
WF_ENTRY(WFWMPAINTSENT),
WF_ENTRY(WFZOOMBUTTONDOWN),
};
CONST PCSTR aszTypeNames[/*TYPE_CTYPES*/] = {
"Free",
"Window",
"Menu",
"Icon/Cursor",
"WPI(SWP) struct",
"Hook",
"Clipboard Data",
"CallProcData",
"Accelerator",
"DDE access",
"DDE conv",
"DDE Transaction",
"Monitor",
"Keyboard Layout",
"Keyboard File",
"WinEvent hook",
"Timer",
"Input Context",
#ifdef GENERIC_INPUT
"HID Raw Data",
"DEVICE INFO",
#ifdef GI_PROCESSOR
"Pre/PostProcessor",
#endif
#endif // GENERIC_INPUT
"unknown",
};
const char * aszHeapTags[] = {
"Unknown",
"Class",
"DesktopInfo",
"ClientThreadInfo",
"Text",
"HandleTable",
"SBInfo",
"MenuItem",
"MenuText",
"IMEText",
"PropList",
NULL,
};
const char * aszHeapSubtags[] = {
"",
"Window",
"Menu",
"Cursor",
"SetWindowPos",
"Hook",
"ClipData",
"CallProc",
"AccelTable",
"DDEAccess",
"DDEConve",
"DDEXact",
"Monitor",
"KBDLayout",
"KBDFile",
"WinEventHook",
"Timer",
"IinputConText",
"HIDData",
"DeviceInfo",
"CTyptes",
NULL,
};
#include "ptagdbg.h" // derived from ntuser\kernel\ptag.lst and .\ptagdbg.bat
#define NO_FLAG (LPCSTR)(LONG_PTR)0xFFFFFFFF // use this for non-meaningful entries.
#define _MASKENUM_START (NO_FLAG-1)
#define _MASKENUM_END (NO_FLAG-2)
#define _SHIFT_BITS (NO_FLAG-3)
#define _CONTINUE_ON (NO_FLAG-4)
#define MASKENUM_START(mask) _MASKENUM_START, (LPCSTR)(mask)
#define MASKENUM_END(shift) _MASKENUM_END, (LPCSTR)(shift)
#define SHIFT_BITS(n) _SHIFT_BITS, (LPCSTR)(n)
#define CONTINUE_ON(arr) _CONTINUE_ON, (LPCSTR)(arr)
CONST PCSTR apszSmsFlags[] = {
"SMF_REPLY" , // 0x0001
"SMF_RECEIVERDIED" , // 0x0002
"SMF_SENDERDIED" , // 0x0004
"SMF_RECEIVERFREE" , // 0x0008
"SMF_RECEIVEDMESSAGE" , // 0x0010
NO_FLAG , // 0x0020
NO_FLAG , // 0x0040
NO_FLAG , // 0x0080
"SMF_CB_REQUEST" , // 0x0100
"SMF_CB_REPLY" , // 0x0200
"SMF_CB_CLIENT" , // 0x0400
"SMF_CB_SERVER" , // 0x0800
"SMF_WOWRECEIVE" , // 0x1000
"SMF_WOWSEND" , // 0x2000
"SMF_RECEIVERBUSY" , // 0x4000
NULL // 0x8000
};
CONST PCSTR apszTifFlags[] = {
"TIF_INCLEANUP" , // 0x00000001
"TIF_16BIT" , // 0x00000002
"TIF_SYSTEMTHREAD" , // 0x00000004
"TIF_CSRSSTHREAD" , // 0x00000008
"TIF_TRACKRECTVISIBLE" , // 0x00000010
"TIF_ALLOWFOREGROUNDACTIVATE" , // 0x00000020
"TIF_DONTATTACHQUEUE" , // 0x00000040
"TIF_DONTJOURNALATTACH" , // 0x00000080
"TIF_WOW64" , // 0x00000100
"TIF_INACTIVATEAPPMSG" , // 0x00000200
"TIF_SPINNING" , // 0x00000400
"TIF_PALETTEAWARE" , // 0x00000800
"TIF_SHAREDWOW" , // 0x00001000
"TIF_FIRSTIDLE" , // 0x00002000
"TIF_WAITFORINPUTIDLE" , // 0x00004000
"TIF_MOVESIZETRACKING" , // 0x00008000
"TIF_VDMAPP" , // 0x00010000
"TIF_DOSEMULATOR" , // 0x00020000
"TIF_GLOBALHOOKER" , // 0x00040000
"TIF_DELAYEDEVENT" , // 0x00080000
"TIF_MSGPOSCHANGED" , // 0x00100000
"TIF_SHUTDOWNCOMPLETE" , // 0x00200000
"TIF_IGNOREPLAYBACKDELAY" , // 0x00400000
"TIF_ALLOWOTHERACCOUNTHOOK" , // 0x00800000
"TIF_GUITHREADINITIALIZED" , // 0x01000000
"TIF_DISABLEIME" , // 0x02000000
"TIF_INGETTEXTLENGTH" , // 0x04000000
"TIF_ANSILENGTH" , // 0x08000000
"TIF_DISABLEHOOKS" , // 0x10000000
"TIF_RESTRICTED" , // 0x20000000
"TIF_QUITPOSTED" , // 0x40000000
NULL // no more
};
CONST PCSTR apszQsFlags[] = {
"QS_KEY" , // 0x0001
"QS_MOUSEMOVE" , // 0x0002
"QS_MOUSEBUTTON" , // 0x0004
"QS_POSTMESSAGE" , // 0x0008
"QS_TIMER" , // 0x0010
"QS_PAINT" , // 0x0020
"QS_SENDMESSAGE" , // 0x0040
"QS_HOTKEY" , // 0x0080
"QS_ALLPOSTMESSAGE" , // 0x0100
"QS_SMSREPLY" , // 0x0200
"QS_RAWINPUT" , // 0x0400
"QS_THREADATTACHED" , // 0x0800
"QS_EXCLUSIVE" , // 0x1000
"QS_EVENT" , // 0x2000
"QS_TRANSFER" , // 0X4000
NULL // 0x8000
};
CONST PCSTR apszMfFlags[] = {
"MF_GRAYED" , // 0x0001
"MF_DISABLED" , // 0x0002
"MF_BITMAP" , // 0x0004
"MF_CHECKED" , // 0x0008
"MF_POPUP" , // 0x0010
"MF_MENUBARBREAK" , // 0x0020
"MF_MENUBREAK" , // 0x0040
"MF_HILITE" , // 0x0080
"MF_OWNERDRAW" , // 0x0100
"MF_USECHECKBITMAPS" , // 0x0200
NO_FLAG , // 0x0400
"MF_SEPARATOR" , // 0x0800
"MF_DEFAULT" , // 0x1000
"MF_SYSMENU" , // 0x2000
"MF_RIGHTJUSTIFY" , // 0x4000
"MF_MOUSESELECT" , // 0x8000
NULL
};
CONST PCSTR apszCsfFlags[] = {
"CSF_SERVERSIDEPROC" , // 0x0001
"CSF_ANSIPROC" , // 0x0002
"CSF_WOWDEFERDESTROY" , // 0x0004
"CSF_SYSTEMCLASS" , // 0x0008
"CSF_WOWCLASS" , // 0x0010
"CSF_WOWEXTRA" , // 0x0020
"CSF_CACHEDSMICON" , // 0x0040
"CSF_WIN40COMPAT" , // 0x0080
"CSF_VERSIONCLASS" , // 0x0100
NULL //
};
CONST PCSTR apszCsFlags[] = {
"CS_VREDRAW" , // 0x0001
"CS_HREDRAW" , // 0x0002
"CS_KEYCVTWINDOW" , // 0x0004
"CS_DBLCLKS" , // 0x0008
NO_FLAG , // 0x0010
"CS_OWNDC" , // 0x0020
"CS_CLASSDC" , // 0x0040
"CS_PARENTDC" , // 0x0080
"CS_NOKEYCVT" , // 0x0100
"CS_NOCLOSE" , // 0x0200
NO_FLAG , // 0x0400
"CS_SAVEBITS" , // 0x0800
"CS_BYTEALIGNCLIENT" , // 0x1000
"CS_BYTEALIGNWINDOW" , // 0x2000
"CS_GLOBALCLASS" , // 0x4000
NO_FLAG , // 0x8000
"CS_IME" , // 0x10000
"CS_DROPSHADOW" , // 0x20000
NULL // no more
};
CONST PCSTR apszQfFlags[] = {
"QF_UPDATEKEYSTATE" , // 0x0000001
"used to be ALTTAB" , // 0x0000002
"QF_FMENUSTATUSBREAK" , // 0x0000004
"QF_FMENUSTATUS" , // 0x0000008
"QF_FF10STATUS" , // 0x0000010
"QF_MOUSEMOVED" , // 0x0000020
"QF_ACTIVATIONCHANGE" , // 0x0000040
"QF_TABSWITCHING" , // 0x0000080
"QF_KEYSTATERESET" , // 0x0000100
"QF_INDESTROY" , // 0x0000200
"QF_LOCKNOREMOVE" , // 0x0000400
"QF_FOCUSNULLSINCEACTIVE" , // 0x0000800
NO_FLAG , // 0x0001000
NO_FLAG , // 0x0002000
"QF_DIALOGACTIVE" , // 0x0004000
"QF_EVENTDEACTIVATEREMOVED" , // 0x0008000
NO_FLAG , // 0x0010000
"QF_TRACKMOUSELEAVE" , // 0x0020000
"QF_TRACKMOUSEHOVER" , // 0x0040000
"QF_TRACKMOUSEFIRING" , // 0x0080000
"QF_CAPTURELOCKED" , // 0x00100000
"QF_ACTIVEWNDTRACKING" , // 0x00200000
NULL
};
CONST PCSTR apszW32pfFlags[] = {
"W32PF_CONSOLEAPPLICATION" , // 0x00000001
"W32PF_FORCEOFFFEEDBACK" , // 0x00000002
"W32PF_STARTGLASS" , // 0x00000004
"W32PF_WOW" , // 0x00000008
"W32PF_READSCREENACCESSGRANTED" , // 0x00000010
"W32PF_INITIALIZED" , // 0x00000020
"W32PF_APPSTARTING" , // 0x00000040
"W32PF_WOW64" , // 0x00000080
"W32PF_ALLOWFOREGROUNDACTIVATE" , // 0x00000100
"W32PF_OWNDCCLEANUP" , // 0x00000200
"W32PF_SHOWSTARTGLASSCALLED" , // 0x00000400
"W32PF_FORCEBACKGROUNDPRIORITY" , // 0x00000800
"W32PF_TERMINATED" , // 0x00001000
"W32PF_CLASSESREGISTERED" , // 0x00002000
"W32PF_THREADCONNECTED" , // 0x00004000
"W32PF_PROCESSCONNECTED" , // 0x00008000
"W32PF_WAKEWOWEXEC" , // 0x00010000
"W32PF_WAITFORINPUTIDLE" , // 0x00020000
"W32PF_IOWINSTA" , // 0x00040000
"W32PF_ALLOWSETFOREGROUND" , // 0x00080000
"W32PF_OLELOADED" , // 0x00100000
"W32PF_SCREENSAVER" , // 0x00200000
"W32PF_IDLESCREENSAVER" , // 0x00400000
"W32PF_DISABLEIME" , // 0x00800000
"W32PF_SETUPAPP" , // 0x01000000
"W32PF_RESTRICTED" , // 0x02000000
"W32PF_CONSOLEHASFOCUS" , // 0x04000000
"W32PF_DISABLEWINDOWSGHOSTING" , // 0x08000000
NULL
};
CONST PCSTR apszHeFlags[] = {
"HANDLEF_DESTROY" , // 0x0001
"HANDLEF_INDESTROY" , // 0x0002
"HANDLEF_INWAITFORDEATH" , // 0x0004
"HANDLEF_FINALDESTROY" , // 0x0008
"HANDLEF_MARKED_OK" , // 0x0010
"HANDLEF_GRANTED" , // 0x0020
"HANDLEF_POOL" , // 0x0040
NULL,
};
CONST PCSTR apszHdataFlags[] = {
"HDATA_APPOWNED" , // 0x0001
NO_FLAG , // 0x0002
NO_FLAG , // 0x0004
NO_FLAG , // 0x0008
NO_FLAG , // 0x0010
NO_FLAG , // 0x0020
NO_FLAG , // 0x0040
NO_FLAG , // 0x0080
"HDATA_EXECUTE" , // 0x0100
"HDATA_INITIALIZED" , // 0x0200
NO_FLAG , // 0x0400
NO_FLAG , // 0x0800
NO_FLAG , // 0x1000
NO_FLAG , // 0x2000
"HDATA_NOAPPFREE" , // 0x4000
"HDATA_READONLY" , // 0x8000
NULL
};
CONST PCSTR apszXiFlags[] = {
"XIF_SYNCHRONOUS" , // 0x0001
"XIF_COMPLETE" , // 0x0002
"XIF_ABANDONED" , // 0x0004
NULL
};
CONST PCSTR apszIifFlags[] = {
"IIF_IN_SYNC_XACT" , // 0x0001
NO_FLAG , // 0x0002
NO_FLAG , // 0x0004
NO_FLAG , // 0x0008
NO_FLAG , // 0x0010
NO_FLAG , // 0x0020
NO_FLAG , // 0x0040
NO_FLAG , // 0x0080
NO_FLAG , // 0x0100
NO_FLAG , // 0x0200
NO_FLAG , // 0x0400
NO_FLAG , // 0x0800
NO_FLAG , // 0x1000
NO_FLAG , // 0x2000
NO_FLAG , // 0x4000
"IIF_UNICODE" , // 0x8000
NULL
};
CONST PCSTR apszTmrfFlags[] = {
"TMRF_READY" , // 0x0001
"TMRF_SYSTEM" , // 0x0002
"TMRF_RIT" , // 0x0004
"TMRF_INIT" , // 0x0008
"TMRF_ONESHOT" , // 0x0010
"TMRF_WAITING" , // 0x0020
"TMRF_PTIWINDOW" , // 0x0040
NULL , // 0x0080
};
CONST PCSTR apszSbFlags[] = {
"SB_VERT" , // 0x0001
"SB_CTL" , // 0x0002
NULL , // 0x0004
};
CONST PCSTR apszCSFlags[] = {
"FS_LATIN1" , // 0x00000001L
"FS_LATIN2" , // 0x00000002L
"FS_CYRILLIC" , // 0x00000004L
"FS_GREEK" , // 0x00000008L
"FS_TURKISH" , // 0x00000010L
"FS_HEBREW" , // 0x00000020L
"FS_ARABIC" , // 0x00000040L
"FS_BALTIC" , // 0x00000080L
"FS_VIETNAMESE" , // 0x00000100L
NO_FLAG , // 0x00000200L
NO_FLAG , // 0x00000400L
NO_FLAG , // 0x00000800L
NO_FLAG , // 0x00001000L
NO_FLAG , // 0x00002000L
NO_FLAG , // 0x00004000L
NO_FLAG , // 0x00008000L
"FS_THAI" , // 0x00010000L
"FS_JISJAPAN" , // 0x00020000L
"FS_CHINESESIMP" , // 0x00040000L
"FS_WANSUNG" , // 0x00080000L
"FS_CHINESETRAD" , // 0x00100000L
"FS_JOHAB" , // 0x00200000L
NO_FLAG , // 0x00400000L
NO_FLAG , // 0x00800000L
NO_FLAG , // 0x01000000L
NO_FLAG , // 0x02000000L
NO_FLAG , // 0x04000000L
NO_FLAG , // 0x08000000L
NO_FLAG , // 0x10000000L
NO_FLAG , // 0x20000000L
NO_FLAG , // 0x40000000L
"FS_SYMBOL" , // 0x80000000L
NULL
};
CONST PCSTR apszMenuTypeFlags[] = {
NO_FLAG , // 0x0001
NO_FLAG , // 0x0002
"MFT_BITMAP" , // 0x0004 MF_BITMAP
NO_FLAG , // 0x0008
"MF_POPUP" , // 0x0010
"MFT_MENUBARBREAK" , // 0x0020 MF_MENUBARBREAK
"MFT_MENUBREAK" , // 0x0040 MF_MENUBREAK
NO_FLAG , // 0x0080
"MFT_OWNERDRAW" , // 0x0100 MF_OWNERDRAW
NO_FLAG , // 0x0200
NO_FLAG , // 0x0400
"MFT_SEPARATOR" , // 0x0800 MF_SEPARATOR
NO_FLAG , // 0x1000
"MF_SYSMENU" , // 0x2000
"MFT_RIGHTJUSTIFY" , // 0x4000 MF_RIGHTJUSTIFY
NULL
};
CONST PCSTR apszMenuStateFlags[] = {
"MF_GRAYED" , // 0x0001
"MF_DISABLED" , // 0x0002
NO_FLAG , // 0x0004
"MFS_CHECKED" , // 0x0008 MF_CHECKED
NO_FLAG , // 0x0010
NO_FLAG , // 0x0020
NO_FLAG , // 0x0040
"MFS_HILITE" , // 0x0080 MF_HILITE
NO_FLAG , // 0x0100
NO_FLAG , // 0x0200
NO_FLAG , // 0x0400
NO_FLAG , // 0x0800
"MFS_DEFAULT" , // 0x1000 MF_DEFAULT
NO_FLAG , // 0x2000
NO_FLAG , // 0x4000
"MF_MOUSESELECT" , // 0x8000
NULL
};
CONST PCSTR apszCursorfFlags[] = {
"CURSORF_FROMRESOURCE", // 0x0001
"CURSORF_GLOBAL", // 0x0002
"CURSORF_LRSHARED", // 0x0004
"CURSORF_ACON", // 0x0008
"CURSORF_WOWCLEANUP" , // 0x0010
NO_FLAG , // 0x0020
"CURSORF_ACONFRAME", // 0x0040
"CURSORF_SECRET", // 0x0080
"CURSORF_LINKED", // 0x0100
"CURSORF_SYSTEM", // 0x0200
"CURSORF_SHADOW", // 0x0400
NULL
};
CONST PCSTR apszMonfFlags[] = {
"MONF_VISIBLE", // 0x01
"MONF_PALETTEDISPLAY", // 0x02
NULL,
};
CONST PCSTR apszSifFlags[] = {
"PUSIF_PALETTEDISPLAY", // 0x00000001
"PUSIF_SNAPTO", // 0x00000002
"PUSIF_COMBOBOXANIMATION", // 0x00000004
"PUSIF_LISTBOXSMOOTHSCROLLING", // 0x00000008
NO_FLAG, // 0x00000010
"PUSIF_KEYBOARDCUES", // 0x00000020
NO_FLAG, // 0x00000040
NO_FLAG, // 0x00000080
NO_FLAG, // 0x00000100
NO_FLAG, // 0x00000200
NO_FLAG, // 0x00000400
NO_FLAG, // 0x00000800
NO_FLAG, // 0x00001000
NO_FLAG, // 0x00002000
NO_FLAG, // 0x00004000
NO_FLAG, // 0x00008000
NO_FLAG, // 0x00010000
NO_FLAG, // 0x00020000
NO_FLAG, // 0x00040000
NO_FLAG, // 0x00080000
NO_FLAG, // 0x00100000
NO_FLAG, // 0x00200000
NO_FLAG, // 0x00400000
NO_FLAG, // 0x00800000
NO_FLAG, // 0x01000000
NO_FLAG, // 0x02000000
NO_FLAG, // 0x04000000
NO_FLAG, // 0x08000000
NO_FLAG, // 0x10000000
NO_FLAG, // 0x20000000
NO_FLAG, // 0x40000000
"PUSIF_UIEFFECTS", // 0x80000000
NULL,
};
CONST PCSTR apszRipFlags[] = {
"RIPF_PROMPTONERROR", // 0x0001
"RIPF_PROMPTONWARNING", // 0x0002
"RIPF_PROMPTONVERBOSE", // 0x0004
NO_FLAG, // 0x0008
"RIPF_PRINTONERROR", // 0x0010
"RIPF_PRINTONWARNING", // 0x0020
"RIPF_PRINTONVERBOSE", // 0x0040
NO_FLAG, // 0x0080
"RIPF_PRINTFILELINE", // 0x0100
NULL
};
CONST PCSTR apszSRVIFlags[] = {
"SRVIF_CHECKED", // 0x0001
"SRVIF_LOGDESKTOPHEAPFAILURE", // 0x0002
"SRVIF_DBCS", // 0x0004
"SRVIF_IME", // 0x0008
"SRVIF_MIDEAST", // 0x0010
"SRVIF_HOOKED", // 0x0020
"SRVIF_CICERO", // 0x0040
NULL
};
CONST PCSTR apszPROPFlags[] = {
"PROPF_INTERNAL", // 0x0001
"PROPF_STRING", // 0x0002
"PROPF_NOPOOL", // 0x0004
};
CONST PCSTR apszLpkEntryPoints[] = {
"LpkTabbedTextOut" , // 0x00000001L
"LpkPSMTextOut" , // 0x00000002L
"LpkDrawTextEx" , // 0x00000004L
"LpkEditControl" , // 0x00000008L
NULL
};
/*
* We need one of these per DWORD
*/
CONST PCSTR aszUserPreferencesMask0[sizeof(DWORD) * 8] = {
"ACTIVEWINDOWTRACKING", /* 0x1000 */
"MENUANIMATION", /* 0x1002 */
"COMBOBOXANIMATION", /* 0x1004 */
"LISTBOXSMOOTHSCROLLING", /* 0x1006 */
"GRADIENTCAPTIONS", /* 0x1008 */
"KEYBOARDCUES", /* 0x100A */
"ACTIVEWNDTRKZORDER", /* 0x100C */
"HOTTRACKING", /* 0x100E */
NO_FLAG, /* 0x1010 */
"MENUFADE", /* 0x1012 */
"SELECTIONFADE", /* 0x1014 */
"TOOLTIPANIMATION", /* 0x1016 */
"TOOLTIPFADE", /* 0x1018 */
"CURSORSHADOW", /* 0x101A */
NO_FLAG, /* 0x101C */
NO_FLAG, /* 0x101E */
NO_FLAG, /* 0x1020 */
NO_FLAG, /* 0x1022 */
NO_FLAG, /* 0x1024 */
NO_FLAG, /* 0x1026 */
NO_FLAG, /* 0x1028 */
NO_FLAG, /* 0x102A */
NO_FLAG, /* 0x102C */
NO_FLAG, /* 0x102E */
NO_FLAG, /* 0x1030 */
NO_FLAG, /* 0x1032 */
NO_FLAG, /* 0x1034 */
NO_FLAG, /* 0x1036 */
NO_FLAG, /* 0x1038 */
NO_FLAG, /* 0x103A */
NO_FLAG, /* 0x103C */
"UIEFFECTS", /* 0x103E */
};
CONST PCSTR aszUserPreferences[SPI_DWORDRANGECOUNT] = {
"FOREGROUNDLOCKTIMEOUT", /* 0x2000 */
"ACTIVEWNDTRKTIMEOUT", /* 0x2002 */
"FOREGROUNDFLASHCOUNT", /* 0x2004 */
"CARETWIDTH", /* 0x2006 */
};
CONST PCSTR aszKeyEventFlags[] = {
"KEYEVENTF_EXTENDEDKEY", // 0x0001
"KEYEVENTF_KEYUP", // 0x0002
"KEYEVENTF_UNICODE", // 0x0004
"KEYEVENTF_SCANCODE", // 0x0008
NULL,
};
CONST PCSTR aszMouseEventFlags[] = {
"MOUSEEVENTF_MOVE", // 0x0001
"MOUSEEVENTF_LEFTDOWN", // 0x0002
"MOUSEEVENTF_LEFTUP", // 0x0004
"MOUSEEVENTF_RIGHTDOWN", // 0x0008
"MOUSEEVENTF_RIGHTUP", // 0x0010
"MOUSEEVENTF_MIDDLEDOWN", // 0x0020
"MOUSEEVENTF_MIDDLEUP", // 0x0040
NO_FLAG, // 0x0080
NO_FLAG, // 0x0100
NO_FLAG, // 0x0200
NO_FLAG, // 0x0400
"MOUSEEVENTF_WHEEL", // 0x0800
NO_FLAG, // 0x1000
NO_FLAG, // 0x2000
"MOUSEEVENTF_VIRTUALDESK", // 0x4000
"MOUSEEVENTF_ABSOLUTE", // 0x8000
NULL,
};
const char* aszWindowStyle[] = {
NO_FLAG, // 0x00000001
NO_FLAG, // 0x00000002
NO_FLAG, // 0x00000004
NO_FLAG, // 0x00000008
NO_FLAG, // 0x00000010
NO_FLAG, // 0x00000020
NO_FLAG, // 0x00000040
NO_FLAG, // 0x00000080
NO_FLAG, // 0x00000100
NO_FLAG, // 0x00000200
NO_FLAG, // 0x00000400
NO_FLAG, // 0x00000800
NO_FLAG, // 0x00001000
NO_FLAG, // 0x00002000
NO_FLAG, // 0x00004000
NO_FLAG, // 0x00008000
"WS_TABSTOP", // 0x00010000
"WS_GROUP", // 0x00020000
"WS_THICKFRAME", // 0x00040000
"WS_SYSMENU", // 0x00080000
"WS_HSCROLL", // 0x00100000
"WS_VSCROLL", // 0x00200000
"WS_DLGFRAME", // 0x00400000
"WS_BORDER", // 0x00800000
"WS_MAXIMIZE", // 0x01000000
"WS_CLIPCHILDREN", // 0x02000000
"WS_CLIPSIBLINGS", // 0x04000000
"WS_DISABLED", // 0x08000000
"WS_VISIBLE", // 0x10000000
"WS_MINIMIZE", // 0x20000000
"WS_CHILD", // 0x40000000
"WS_POPUP", // 0x80000000
NULL,
};
const char* aszDialogStyle[] = {
"DS_ABSALIGN", // 0x00000001
"DS_SYSMODAL", // 0x00000002
"DS_3DLOOK", // 0x00000004
"DS_FIXEDSYS", // 0x00000008
"DS_NOFAILCREATE", // 0x00000010
"DS_LOCALEDIT", // 0x00000020
"DS_SETFONT", // 0x00000040
"DS_MODALFRAME", // 0x00000080
"DS_NOIDLEMSG", // 0x00000100
"DS_SETFOREGROUND", // 0x00000200
"DS_CONTROL", // 0x00000400
"DS_CENTER", // 0x00000800
"DS_CENTERMOUSE", // 0x00001000
"DS_CONTEXTHELP", // 0x00002000
NO_FLAG, // 0x00004000
NO_FLAG, // 0x00008000
CONTINUE_ON(aszWindowStyle + 16),
};
const char* aszButtonStyle[] = {
MASKENUM_START(BS_TYPEMASK),
"BS_PUSHBUTTON", // 0
"BS_DEFPUSHBUTTON", // 1
"BS_CHECKBOX", // 2
"BS_AUTOCHECKBOX", // 3
"BS_RADIOBUTTON", // 4
"BS_3STATE", // 5
"BS_AUTO3STATE", // 6
"BS_GROUPBOX", // 7
"BS_USERBUTTON", // 8
"BS_AUTORADIOBUTTON", // 9
"BS_PUSHBOX", // a
"BS_OWNERDRAW", // b
MASKENUM_END(4),
NO_FLAG, // 0x00000010
"BS_LEFTTEXT", // 0x00000020
MASKENUM_START(BS_IMAGEMASK),
"BS_TEXT", // 0
"BS_ICON",
"BS_BITMAP",
MASKENUM_END(2),
MASKENUM_START(BS_HORZMASK),
NO_FLAG,
"BS_LEFT",
"BS_RIGHT",
"BS_CENTER",
MASKENUM_END(2),
MASKENUM_START(BS_VERTMASK),
NO_FLAG,
"BS_TOP", "BS_BOTTOM", "BS_VCENTER",
MASKENUM_END(2),
"BS_PUSHLIKE", // 0x00001000
"BS_MULTILINE", // 0x00002000
"BS_NOTIFY", // 0x00004000
"BS_FLAT", // 0x00008000
CONTINUE_ON(aszWindowStyle + 16),
};
const char* aszComboBoxStyle[] = {
MASKENUM_START(0x0f),
NO_FLAG, // 0
"CBS_SIMPLE", // 1
"CBS_DROPDOWN", // 2
"CBS_DROPDOWNLIST", // 3
MASKENUM_END(4),
"CBS_OWNERDRAWFIXED", // 0x0010L
"CBS_OWNERDRAWVARIABLE", // 0x0020L
"CBS_AUTOHSCROLL", // 0x0040L
"CBS_OEMCONVERT", // 0x0080L
"CBS_SORT", // 0x0100L
"CBS_HASSTRINGS", // 0x0200L
"CBS_NOINTEGRALHEIGHT", // 0x0400L
"CBS_DISABLENOSCROLL", // 0x0800L
NO_FLAG, // 0x1000L
"CBS_UPPERCASE", // 0x2000L
"CBS_LOWERCASE", // 0x4000L
NO_FLAG, // 0x8000L
CONTINUE_ON(aszWindowStyle + 16),
};
const char* aszStaticStyle[] = {
MASKENUM_START(SS_TYPEMASK),
"SS_LEFT", // 0x00000000L
"SS_CENTER", // 0x00000001L
"SS_RIGHT", // 0x00000002L
"SS_ICON", // 0x00000003L
"SS_BLACKRECT", // 0x00000004L
"SS_GRAYRECT", // 0x00000005L
"SS_WHITERECT", // 0x00000006L
"SS_BLACKFRAME", // 0x00000007L
"SS_GRAYFRAME", // 0x00000008L
"SS_WHITEFRAME", // 0x00000009L
"SS_USERITEM", // 0x0000000AL
"SS_SIMPLE", // 0x0000000BL
"SS_LEFTNOWORDWRAP", // 0x0000000CL
"SS_OWNERDRAW", // 0x0000000DL
"SS_BITMAP", // 0x0000000EL
"SS_ENHMETAFILE", // 0x0000000FL
"SS_ETCHEDHORZ", // 0x00000010L
"SS_ETCHEDVERT", // 0x00000011L
"SS_ETCHEDFRAME", // 0x00000012L
MASKENUM_END(5),
NO_FLAG, // 0x00000020L
"SS_REALSIZECONTROL", // 0x00000040L
"SS_NOPREFIX", // 0x00000080L /* Don't do "&" character translation */
"SS_NOTIFY", // 0x00000100L
"SS_CENTERIMAGE", // 0x00000200L
"SS_RIGHTJUST", // 0x00000400L
"SS_REALSIZEIMAGE", // 0x00000800L
"SS_SUNKEN", // 0x00001000L
"SS_EDITCONTROL", // 0x00002000L ;internal
MASKENUM_START(SS_ELLIPSISMASK),
NO_FLAG,
"SS_ENDELLIPSIS", // 0x00004000L
"SS_PATHELLIPSIS", // 0x00008000L
"SS_WORDELLIPSIS", // 0x0000C000L
MASKENUM_END(2),
CONTINUE_ON(aszWindowStyle + 16),
};
const char* aszListBoxStyle[] = {
"LBS_NOTIFY", // 0x0001L
"LBS_SORT", // 0x0002L
"LBS_NOREDRAW", // 0x0004L
"LBS_MULTIPLESEL", // 0x0008L
"LBS_OWNERDRAWFIXED", // 0x0010L
"LBS_OWNERDRAWVARIABLE", // 0x0020L
"LBS_HASSTRINGS", // 0x0040L
"LBS_USETABSTOPS", // 0x0080L
"LBS_NOINTEGRALHEIGHT", // 0x0100L
"LBS_MULTICOLUMN", // 0x0200L
"LBS_WANTKEYBOARDINPUT", // 0x0400L
"LBS_EXTENDEDSEL", // 0x0800L
"LBS_DISABLENOSCROLL", // 0x1000L
"LBS_NODATA", // 0x2000L
"LBS_NOSEL", // 0x4000L
NO_FLAG, // 0x8000L
CONTINUE_ON(aszWindowStyle + 16),
};
const char* aszEditStyle[] = {
MASKENUM_START(ES_FMTMASK),
"ES_LEFT", // 0x0000L
"ES_CENTER", // 0x0001L
"ES_RIGHT", // 0x0002L
MASKENUM_END(2),
"ES_MULTILINE", // 0x0004L
"ES_UPPERCASE", // 0x0008L
"ES_LOWERCASE", // 0x0010L
"ES_PASSWORD", // 0x0020L
"ES_AUTOVSCROLL", // 0x0040L
"ES_AUTOHSCROLL", // 0x0080L
"ES_NOHIDESEL", // 0x0100L
"ES_COMBOBOX", // 0x0200L ;internal
"ES_OEMCONVERT", // 0x0400L
"ES_READONLY", // 0x0800L
"ES_WANTRETURN", // 0x1000L
"ES_NUMBER", // 0x2000L ;public_winver_400
NO_FLAG, // 0x4000L
NO_FLAG, // 0x8000L
CONTINUE_ON(aszWindowStyle + 16),
};
const char* aszScrollBarStyle[] = {
"SBS_HORZ", // 0x0000L
"SBS_VERT", // 0x0001L
"SBS_TOPALIGN", // 0x0002L
"SBS_LEFTALIGN", // 0x0002L
"SBS_BOTTOMALIGN", // 0x0004L
"SBS_RIGHTALIGN", // 0x0004L
"SBS_SIZEBOXTOPLEFTALIGN", // 0x0002L
"SBS_SIZEBOXBOTTOMRIGHTALIGN", // 0x0004L
"SBS_SIZEBOX", // 0x0008L
"SBS_SIZEGRIP", // 0x0010L
SHIFT_BITS(8), // 8 bits
CONTINUE_ON(aszWindowStyle + 16),
};
const char* aszWindowExStyle[] = {
"WS_EX_DLGMODALFRAME", // 0x00000001L
"WS_EX_DRAGOBJECT", // 0x00000002L ;internal
"WS_EX_NOPARENTNOTIFY", // 0x00000004L
"WS_EX_TOPMOST", // 0x00000008L
"WS_EX_ACCEPTFILES", // 0x00000010L
"WS_EX_TRANSPARENT", // 0x00000020L
"WS_EX_MDICHILD", // 0x00000040L
"WS_EX_TOOLWINDOW", // 0x00000080L
"WS_EX_WINDOWEDGE", // 0x00000100L
"WS_EX_CLIENTEDGE", // 0x00000200L
"WS_EX_CONTEXTHELP", // 0x00000400L
NO_FLAG, // 0x00000800L
"WS_EX_RIGHT", // 0x00001000L
// "WS_EX_LEFT", // 0x00000000L
"WS_EX_RTLREADING", // 0x00002000L
// "WS_EX_LTRREADING", // 0x00000000L
"WS_EX_LEFTSCROLLBAR", // 0x00004000L
// "WS_EX_RIGHTSCROLLBAR", // 0x00000000L
NO_FLAG, // 0x00008000L
"WS_EX_CONTROLPARENT", // 0x00010000L
"WS_EX_STATICEDGE", // 0x00020000L
"WS_EX_APPWINDOW", // 0x00040000L
"WS_EX_LAYERED", // 0x00080000
NULL
};
const char* aszClientImcFlags[] = {
"IMCF_UNICODE", // 0x0001
"IMCF_ACTIVE", // 0x0002
"IMCF_CHGMSG", // 0x0004
"IMCF_SAVECTRL", // 0x0008
"IMCF_PROCESSEVENT", // 0x0010
"IMCF_FIRSTSELECT", // 0x0020
"IMCF_INDESTROY", // 0x0040
"IMCF_WINNLSDISABLE", // 0x0080
"IMCF_DEFAULTIMC", // 0x0100
NULL,
};
const char* aszConversionModes[] = {
"IME_CMODE_NATIVE", // 0x0001
"IME_CMODE_KATAKANA", // 0x0002 // only effect under IME_CMODE_NATIVE
NO_FLAG, // 0x0004
"IME_CMODE_FULLSHAPE", // 0x0008
"IME_CMODE_ROMAN", // 0x0010
"IME_CMODE_CHARCODE", // 0x0020
"IME_CMODE_HANJACONVERT", // 0x0040
"IME_CMODE_SOFTKBD", // 0x0080
"IME_CMODE_NOCONVERSION", // 0x0100
"IME_CMODE_EUDC", // 0x0200
"IME_CMODE_SYMBOL", // 0x0400
"IME_CMODE_FIXED", // 0x0800
NULL
};
const char* aszSentenceModes[] = {
"IME_SMODE_PLAURALCLAUSE", // 0x0001
"IME_SMODE_SINGLECONVERT", // 0x0002
"IME_SMODE_AUTOMATIC", // 0x0004
"IME_SMODE_PHRASEPREDICT", // 0x0008
"IME_SMODE_CONVERSATION", // 0x0010
NULL
};
const char* aszImeInit[] = {
"INIT_STATUSWNDPOS", // 0x00000001
"INIT_CONVERSION", // 0x00000002
"INIT_SENTENCE", // 0x00000004
"INIT_LOGFONT", // 0x00000008
"INIT_COMPFORM", // 0x00000010
"INIT_SOFTKBDPOS", // 0x00000020
NULL
};
const char* aszImeSentenceMode[] = {
"IME_SMODE_PLAURALCLAUSE", // 0x0001
"IME_SMODE_SINGLECONVERT", // 0x0002
"IME_SMODE_AUTOMATIC", // 0x0004
"IME_SMODE_PHRASEPREDICT", // 0x0008
"IME_SMODE_CONVERSATION", // 0x0010
NULL
};
const char* aszImeConversionMode[] = {
"IME_CMODE_NATIVE", // 0x0001
"IME_CMODE_KATAKANA", // 0x0002 // only effect under IME_CMODE_NATIVE
NO_FLAG,
"IME_CMODE_FULLSHAPE", // 0x0008
"IME_CMODE_ROMAN", // 0x0010
"IME_CMODE_CHARCODE", // 0x0020
"IME_CMODE_HANJACONVERT", // 0x0040
"IME_CMODE_SOFTKBD", // 0x0080
"IME_CMODE_NOCONVERSION", // 0x0100
"IME_CMODE_EUDC", // 0x0200
"IME_CMODE_SYMBOL", // 0x0400
"IME_CMODE_FIXED", // 0x0800
NULL
};
const char* aszImeDirtyFlags[] = {
"IMSS_UPDATE_OPEN", // 0x0001
"IMSS_UPDATE_CONVERSION", // 0x0002
"IMSS_UPDATE_SENTENCE", // 0x0004
NO_FLAG, // 0x0008
NO_FLAG, // 0x0010
NO_FLAG, // 0x0020
NO_FLAG, // 0x0040
NO_FLAG, // 0x0080
"IMSS_INIT_OPEN", // 0x0100
NULL
};
const char* aszImeCompFormFlags[] = {
// "CFS_DEFAULT", // 0x0000
"CFS_RECT", // 0x0001
"CFS_POINT", // 0x0002
"CFS_SCREEN", // 0x0004 @Internal
"CFS_VERTICAL", // 0x0008 @Internal
"CFS_HIDDEN", // 0x0010 @Internal
"CFS_FORCE_POSITION", // 0x0020
"CFS_CANDIDATEPOS", // 0x0040
"CFS_EXCLUDE", // 0x0080
NULL
};
const char* aszEdUndoType[] = {
"UNDO_INSERT", // 0x0001
"UNDO_DELETE", // 0x0002
NULL,
};
const char* aszDeviceInfoActionFlags[] = {
"GDIAF_ARRIVED", // 0x0001
"GDIAF_QUERYREMOVE", // 0x0002
"GDIAF_REMOVECANCELLED", // 0x0004
"GDIAF_DEPARTED", // 0x0008
"GDIAF_IME_STATUS", // 0x0010
"GDIAF_REFRESH_MOUSE", // 0x0020
NO_FLAG, // 0x0040
"GDIAF_FREEME", // 0x0080
"GDIAF_PNPWAITING", // 0x0100
"GDIAF_RETRYREAD", // 0x0200
"GDIAF_RECONNECT", // 0x0400
"GDIAF_STARTREAD", // 0x0800 // the device needs to be started
"GDIAF_STOPREAD", // 0x1000 // the device needs to be stopped
NULL,
};
const char* aszHidProcessMask[] = {
"TRIM_RAWMOUSE", // 0x0001
"TRIM_RAWKEYBOARD", // 0x0002
"TRIM_NOLEGACYMOUSE", // 0x0004
"TRIM_NOLEGACYKEYBOARD", // 0x0008
NULL,
};
const char* aszHookFlags[] = {
"HF_GLOBAL", // 0x0001
"HF_ANSI", // 0x0002
"HF_NEEDHC_SKIP", // 0x0004
"HF_HUNG", // 0x0008 // Hook Proc hung don't call if system
"HF_HOOKFAULTED", // 0x0010 // Hook Proc faulted
"HF_NOPLAYBACKDELAY", // 0x0020 // Ignore requested delay
"HF_DESTROYED", // 0x0080 // Set by FreeHook
// DEBUG only flags
"HF_INCHECKWHF", // 0x0100 // fsHooks is being updated
"HF_FREED", // 0x0200 // Object has been freed.
NULL,
};
const char * aszDcxFlags[] = {
"DCX_WINDOW", // 0x00000001L
"DCX_CACHE", // 0x00000002L
"DCX_NORESETATTRS", // 0x00000004L
"DCX_CLIPCHILDREN", // 0x00000008L
"DCX_CLIPSIBLINGS", // 0x00000010L
"DCX_PARENTCLIP", // 0x00000020L
"DCX_EXCLUDERGN", // 0x00000040L
"DCX_INTERSECTRGN", // 0x00000080L
"DCX_EXCLUDEUPDATE", // 0x00000100L
"DCX_INTERSECTUPDATE", // 0x00000200L
"DCX_LOCKWINDOWUPDATE", // 0x00000400L
"DCX_INVALID", // 0x00000800L
"DCX_INUSE", // 0x00001000L
"DCX_SAVEDRGNINVALID", // 0x00002000L
"DCX_REDIRECTED", // 0x00004000L
"DCX_OWNDC", // 0x00008000L
"DCX_USESTYLE", // 0x00010000L
"DCX_NEEDFONT", // 0x00020000L
"DCX_NODELETERGN", // 0x00040000L
"DCX_NOCLIPCHILDREN", // 0x00080000L
"DCX_NORECOMPUTE", // 0x00100000L
"DCX_VALIDATE", // 0x00200000L
"DCX_DESTROYTHIS", // 0x00400000L
"DCX_CREATEDC", // 0x00800000L
"DCX_REDIRECTEDBITMAP", // 0x08000000L
"DCX_PWNDORGINVISIBLE", // 0x10000000L
"DCX_NOMIRROR", // 0x40000000L
NULL
};
const char* aszDesktopFlags[] = {
"DF_ACTIVEONDESTROY",
"DF_ZOMBIE",
"DF_NOTRITUNLOCK",
"DF_QUITUNLOCK",
"DF_USERMODE",
"DF_SKIPSWITCHDESKTOP",
"DF_DTNONEWDESKTOP",
"DF_REDIRECTED",
"DF_DESKCREATED",
"DF_NEWDISPLAYSETTINGS",
"DF_TRACKMOUSEHOVER",
"DF_TRACKMOUSELEAVE",
"DF_TOOLTIPACTIVE",
"DF_TOOLTIPSHOWING",
"DF_HOTTRACKING",
"DF_DESTROYED",
"DF_DESKWNDDESTROYED",
"DF_DYING",
NULL
};
const char* aszWindowStationFlags[] = {
"WSF_SWITCHLOCK",
"WSF_OPENLOCK",
"WSF_NOIO",
"WSF_SHUTDOWN",
"WSF_DYING",
"WSF_REALSHUTDOWN",
"WSF_CLIPBOARDCHANGED",
"WSF_INDELAYEDRENDERING",
NULL
};
enum GF_FLAGS {
GF_SMS,
GF_TIF,
GF_QS,
GF_MF,
GF_CSF,
GF_CS,
GF_QF,
GF_W32PF,
GF_HE,
GF_HDATA,
GF_XI,
GF_IIF,
GF_TMRF,
GF_SB,
GF_CHARSETS,
GF_MENUTYPE,
GF_MENUSTATE,
GF_CURSORF,
GF_MON,
GF_SI,
GF_RIP,
GF_SRVI,
GF_PROP,
GF_UPM0,
GF_KI,
GF_MI,
GF_DS,
GF_WS,
GF_ES,
GF_BS,
GF_CBS,
GF_SS,
GF_LBS,
GF_SBS,
GF_WSEX,
GF_CLIENTIMC,
GF_CONVERSION,
GF_SENTENCE,
GF_IMEINIT,
GF_IMEDIRTY,
GF_IMECOMPFORM,
GF_EDUNDO,
GF_DIAF,
GF_HIDPROCESSMASK,
GF_HOOKFLAGS,
GF_DCXFLAGS,
GF_DESKTOPFLAGS,
GF_WINDOWSTATIONFLAGS,
GF_LPK,
GF_MAX
};
CONST PCSTR* aapszFlag[GF_MAX] = {
apszSmsFlags,
apszTifFlags,
apszQsFlags,
apszMfFlags,
apszCsfFlags,
apszCsFlags,
apszQfFlags,
apszW32pfFlags,
apszHeFlags,
apszHdataFlags,
apszXiFlags,
apszIifFlags,
apszTmrfFlags,
apszSbFlags,
apszCSFlags,
apszMenuTypeFlags,
apszMenuStateFlags,
apszCursorfFlags,
apszMonfFlags,
apszSifFlags,
apszRipFlags,
apszSRVIFlags,
apszPROPFlags,
aszUserPreferencesMask0,
aszKeyEventFlags,
aszMouseEventFlags,
aszDialogStyle,
aszWindowStyle,
aszEditStyle,
aszButtonStyle,
aszComboBoxStyle,
aszStaticStyle,
aszListBoxStyle,
aszScrollBarStyle,
aszWindowExStyle,
aszClientImcFlags,
aszConversionModes,
aszSentenceModes,
aszImeInit,
aszImeDirtyFlags,
aszImeCompFormFlags,
aszEdUndoType,
aszDeviceInfoActionFlags,
aszHidProcessMask,
aszHookFlags,
aszDcxFlags,
aszDesktopFlags,
aszWindowStationFlags,
apszLpkEntryPoints,
};
/************************************************************************\
* GetFlags
*
* Converts a 32bit set of flags into an appropriate string. pszBuf should
* be large enough to hold this string, no checks are done. pszBuf can be
* NULL, allowing use of a local static buffer but note that this is not
* reentrant. Output string has the form: "FLAG1 | FLAG2 ..." or "0".
*
* 6/9/1995 Created SanfordS
\************************************************************************/
LPSTR GetFlags(
WORD wType,
DWORD dwFlags,
LPSTR pszBuf,
BOOL fPrintZero)
{
static char szT[512];
WORD i;
BOOL fFirst = TRUE;
BOOL fNoMoreNames = FALSE;
CONST PCSTR *apszFlags;
LPSTR apszFlagNames[sizeof(DWORD) * 8], pszT;
const char** ppszNextFlag;
UINT uFlagsCount, uNextFlag;
DWORD dwUnnamedFlags, dwLoopFlag;
DWORD dwShiftBits;
DWORD dwOrigFlags;
if (pszBuf == NULL) {
pszBuf = szT;
}
if (!bShowFlagNames) {
sprintf(pszBuf, "%x", dwFlags);
return pszBuf;
}
if (wType >= GF_MAX) {
strcpy(pszBuf, "Invalid flag type.");
return pszBuf;
}
/*
* Initialize output buffer and names array
*/
*pszBuf = '\0';
RtlZeroMemory(apszFlagNames, sizeof(apszFlagNames));
apszFlags = aapszFlag[wType];
/*
* Build a sorted array containing the names of the flags in dwFlags
*/
uFlagsCount = 0;
dwUnnamedFlags = dwOrigFlags = dwFlags;
dwLoopFlag = 1;
dwShiftBits = 0;
reentry:
for (i = 0; dwFlags; dwFlags >>= 1, i++, dwLoopFlag <<= 1, ++dwShiftBits) {
const char* lpszFlagName = NULL;
/*
* Bail if we reached the end of the flag names array
*/
if (apszFlags[i] == NULL) {
break;
}
if (apszFlags[i] == _MASKENUM_START) {
//
// Masked enumerative items.
//
DWORD en = 0;
DWORD dwMask = (DWORD)(ULONG_PTR)apszFlags[++i];
// First, clear up the handled bits.
dwUnnamedFlags &= ~dwMask;
lpszFlagName = NULL;
for (++i; apszFlags[i] != NULL && apszFlags[i] != _MASKENUM_END; ++i, ++en) {
if ((dwOrigFlags & dwMask) == (en << dwShiftBits )) {
if (apszFlags[i] != NO_FLAG) {
lpszFlagName = apszFlags[i];
}
}
}
//
// Shift the bits and get ready for the next item.
// Next item right after _MASKENUM_END holds the bits to shift.
//
dwFlags >>= (int)(ULONG_PTR)apszFlags[++i] - 1;
dwLoopFlag <<= (int)(ULONG_PTR)apszFlags[i] - 1;
dwShiftBits += (int)(ULONG_PTR)apszFlags[i] - 1;
if (lpszFlagName == NULL) {
//
// Could not find the match. Skip to the next item.
//
continue;
}
} else if (apszFlags[i] == _CONTINUE_ON) {
//
// Refer the other item array. Pointer to the array is stored at [i+1].
//
apszFlags = (LPSTR*)apszFlags[i + 1];
goto reentry;
} else if (apszFlags[i] == _SHIFT_BITS) {
//
// To save some space, just shift some bits..
//
dwFlags >>= (int)(ULONG_PTR)apszFlags[++i] - 1;
dwLoopFlag <<= (int)(ULONG_PTR)apszFlags[i] - 1;
dwShiftBits += (int)(ULONG_PTR)apszFlags[i] - 1;
continue;
} else {
/*
* Continue if this bit is not set or we don't have a name for it.
*/
if (!(dwFlags & 1) || (apszFlags[i] == NO_FLAG)) {
continue;
}
lpszFlagName = apszFlags[i];
}
/*
* Find the sorted position where this name should go
*/
ppszNextFlag = apszFlagNames;
uNextFlag = 0;
while (uNextFlag < uFlagsCount) {
if (strcmp(*ppszNextFlag, lpszFlagName) > 0) {
break;
}
ppszNextFlag++;
uNextFlag++;
}
/*
* Insert the new name
*/
RtlMoveMemory((char*)(ppszNextFlag + 1), ppszNextFlag, (uFlagsCount - uNextFlag) * sizeof(DWORD));
*ppszNextFlag = lpszFlagName;
uFlagsCount++;
/*
* We got a name so clear it from the unnamed bits.
*/
dwUnnamedFlags &= ~dwLoopFlag;
}
/*
* Build the string now
*/
ppszNextFlag = apszFlagNames;
pszT = pszBuf;
/*
* Add the first name
*/
if (uFlagsCount > 0) {
pszT += sprintf(pszT, "%s", *ppszNextFlag++);
uFlagsCount--;
}
/*
* Concatenate all other names with " |"
*/
while (uFlagsCount > 0) {
pszT += sprintf(pszT, " | %s", *ppszNextFlag++);
uFlagsCount--;
}
/*
* If there are unamed bits, add them at the end
*/
if (dwUnnamedFlags != 0) {
pszT += sprintf(pszT, " | %#lx", dwUnnamedFlags);
}
/*
* Print zero if needed and asked to do so
*/
if (fPrintZero && (pszT == pszBuf)) {
sprintf(pszBuf, "0");
}
return pszBuf;
}
///////////////////////////////////////////////////////////////////////////
//
// Enumerated items with mask
//
///////////////////////////////////////////////////////////////////////////
typedef struct {
LPCSTR name;
DWORD value;
} EnumItem;
#define EITEM(a) { #a, a }
const EnumItem aClsTypes[] = {
EITEM(ICLS_BUTTON),
EITEM(ICLS_EDIT),
EITEM(ICLS_STATIC),
EITEM(ICLS_LISTBOX),
EITEM(ICLS_SCROLLBAR),
EITEM(ICLS_COMBOBOX),
EITEM(ICLS_CTL_MAX),
EITEM(ICLS_DESKTOP),
EITEM(ICLS_DIALOG),
EITEM(ICLS_MENU),
EITEM(ICLS_SWITCH),
EITEM(ICLS_ICONTITLE),
EITEM(ICLS_MDICLIENT),
EITEM(ICLS_COMBOLISTBOX),
EITEM(ICLS_DDEMLEVENT),
EITEM(ICLS_DDEMLMOTHER),
EITEM(ICLS_DDEML16BIT),
EITEM(ICLS_DDEMLCLIENTA),
EITEM(ICLS_DDEMLCLIENTW),
EITEM(ICLS_DDEMLSERVERA),
EITEM(ICLS_DDEMLSERVERW),
EITEM(ICLS_IME),
EITEM(ICLS_TOOLTIP),
NULL,
};
const EnumItem aCharSets[] = {
EITEM(ANSI_CHARSET),
EITEM(DEFAULT_CHARSET),
EITEM(SYMBOL_CHARSET),
EITEM(SHIFTJIS_CHARSET),
EITEM(HANGEUL_CHARSET),
EITEM(HANGUL_CHARSET),
EITEM(GB2312_CHARSET),
EITEM(CHINESEBIG5_CHARSET),
EITEM(OEM_CHARSET),
EITEM(JOHAB_CHARSET),
EITEM(HEBREW_CHARSET),
EITEM(ARABIC_CHARSET),
EITEM(GREEK_CHARSET),
EITEM(TURKISH_CHARSET),
EITEM(VIETNAMESE_CHARSET),
EITEM(THAI_CHARSET),
EITEM(EASTEUROPE_CHARSET),
EITEM(RUSSIAN_CHARSET),
NULL,
};
const EnumItem aImeHotKeys[] = {
// Windows for Simplified Chinese Edition hot key ID from 0x10 - 0x2F
EITEM(IME_CHOTKEY_IME_NONIME_TOGGLE),
EITEM(IME_CHOTKEY_SHAPE_TOGGLE),
EITEM(IME_CHOTKEY_SYMBOL_TOGGLE),
// Windows for Japanese Edition hot key ID from 0x30 - 0x4F
EITEM(IME_JHOTKEY_CLOSE_OPEN),
// Windows for Korean Edition hot key ID from 0x50 - 0x6F
EITEM(IME_KHOTKEY_SHAPE_TOGGLE),
EITEM(IME_KHOTKEY_HANJACONVERT),
EITEM(IME_KHOTKEY_ENGLISH),
// Windows for Traditional Chinese Edition hot key ID from 0x70 - 0x8F
EITEM(IME_THOTKEY_IME_NONIME_TOGGLE),
EITEM(IME_THOTKEY_SHAPE_TOGGLE),
EITEM(IME_THOTKEY_SYMBOL_TOGGLE),
// direct switch hot key ID from 0x100 - 0x11F
EITEM(IME_HOTKEY_DSWITCH_FIRST),
EITEM(IME_HOTKEY_DSWITCH_LAST),
// IME private hot key from 0x200 - 0x21F
EITEM(IME_ITHOTKEY_RESEND_RESULTSTR),
EITEM(IME_ITHOTKEY_PREVIOUS_COMPOSITION),
EITEM(IME_ITHOTKEY_UISTYLE_TOGGLE),
EITEM(IME_ITHOTKEY_RECONVERTSTRING),
EITEM(IME_HOTKEY_PRIVATE_LAST),
NULL,
};
const EnumItem aCandidateListStyle[] = {
EITEM(IME_CAND_UNKNOWN),// 0x0000
EITEM(IME_CAND_READ),// 0x0001
EITEM(IME_CAND_CODE),// 0x0002
EITEM(IME_CAND_MEANING),// 0x0003
EITEM(IME_CAND_RADICAL),// 0x0004
EITEM(IME_CAND_STROKE),// 0x0005
NULL
};
// TODO: put charset here
enum {
EI_CLSTYPE = 0,
EI_CHARSETTYPE,
EI_IMEHOTKEYTYPE,
EI_IMECANDIDATESTYLE,
EI_MAX
};
typedef struct {
DWORD dwMask;
const EnumItem* items;
} MaskedEnum;
const MaskedEnum aEnumItems[] = {
~0, aClsTypes,
~0, aCharSets,
~0, aImeHotKeys,
~0, aCandidateListStyle,
};
LPCSTR GetMaskedEnum(WORD wType, DWORD dwValue, LPSTR buf)
{
const EnumItem* item;
static char ach[32];
if (wType >= EI_MAX) {
strcpy(buf, "Invalid type.");
return buf;
}
dwValue &= aEnumItems[wType].dwMask;
item = aEnumItems[wType].items;
for (; item->name; ++item) {
if (item->value == dwValue) {
if (buf) {
strcpy(buf, item->name);
return buf;
}
return item->name;
}
}
if (buf) {
*buf = 0;
return buf;
}
sprintf(ach, "%x", wType);
return ach;
}
#define WM_ITEM(x, fInternal) { x, #x, fInternal }
CONST struct {
DWORD msg;
PCSTR pszMsg;
BOOLEAN fInternal;
} gaMsgs[] = {
#include "wm.txt"
};
#undef WM_ITEM
const char* GetWindowMessageName(UINT wm)
{
int i;
for (i = 0; i < sizeof gaMsgs; ++i) {
if (wm == gaMsgs[i].msg) {
if (!gaMsgs[i].fInternal) {
return gaMsgs[i].pszMsg;
}
return "";
}
}
return "";
}
const char* GetWindowMessageNameInternal(UINT wm)
{
int i;
for (i = 0; i < sizeof gaMsgs; ++i) {
if (wm == gaMsgs[i].msg) {
return gaMsgs[i].pszMsg;
}
}
return "";
}
/************************************************************************\
* Helper Procedures: dso etc.
*
* 04/19/2000 Created Hiro
\************************************************************************/
// to workaround nosy InitTypeRead
#define _InitTypeRead(Addr, lpszType) GetShortField(Addr, (PUCHAR)lpszType, 1)
#define CONTINUE EXCEPTION_EXECUTE_HANDLER
#define RAISE_EXCEPTION() RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, NULL)
#define BAD_SYMBOL(symbol) \
Print("Failed to get %s: bad symbol?\n", symbol); \
RAISE_EXCEPTION()
#define CANT_GET_VALUE(symbol, p) \
Print("Failed to get %s @ 0x%p: invalid address, or memory is paged out?\n", symbol, p); \
RAISE_EXCEPTION()
BOOL dso(
char* szStruct,
ULONG64 address,
ULONG dwOption)
{
SYM_DUMP_PARAM symDump = {
sizeof(symDump), szStruct, dwOption, // 0 for default dump like dt
address,
NULL, NULL, NULL, 0, NULL
};
return Ioctl(IG_DUMP_SYMBOL_INFO, &symDump, symDump.size);
}
ULONG64 GetPointer(
ULONG64 addr)
{
ULONG64 p = 0;
if (!ReadPointer(addr, &p)) {
CANT_GET_VALUE("a pointer", addr);
}
return p;
}
DWORD GetDWord(
ULONG64 addr)
{
ULONG64 dw = 0xbaadbaad;
if (!GetFieldData(addr, "DWORD", NULL, sizeof(dw), &dw)) {
CANT_GET_VALUE("DWORD", addr);
}
return (DWORD)dw;
}
WORD GetWord(
ULONG64 addr)
{
ULONG64 w = 0xbaad;
if (!GetFieldData(addr, "WORD", NULL, sizeof(w), &w)) {
CANT_GET_VALUE("WORD", addr);
}
return (WORD)w;
}
BYTE GetByte(
ULONG64 addr)
{
ULONG64 b = 0;
if (GetFieldData(addr, "BYTE", NULL, sizeof(b), &b)) {
CANT_GET_VALUE("BYTE", addr);
}
return (BYTE)b;
}
ULONG
GetUlongFromAddress(
ULONG64 Location)
{
ULONG Value;
ULONG result;
if ((!ReadMemory(Location, &Value, sizeof(ULONG), &result)) ||
(result < sizeof(ULONG))) {
Print("GetUlongFromAddress: unable to read from 0x%I64x\n", Location);
RAISE_EXCEPTION();
}
return Value;
}
ULONG64 GetGlobalPointer(
LPSTR symbol)
{
ULONG64 pp;
ULONG64 p = 0;
pp = EvalExp(symbol);
if (pp == 0) {
BAD_SYMBOL(symbol);
} else if (!ReadPointer(pp, &p)) {
CANT_GET_VALUE(symbol, pp);
}
return p;
}
ULONG64 GetGlobalMemberAddress(
LPSTR symbol,
LPSTR type,
LPSTR field)
{
ULONG64 pVar = EvalExp(symbol);
ULONG offset;
if (pVar == 0) {
BAD_SYMBOL(symbol);
}
if (GetFieldOffset(type, field, &offset)) {
BAD_SYMBOL(type);
}
return pVar + offset;
}
ULONG64 GetGlobalMember(
LPSTR symbol,
LPSTR type,
LPSTR field)
{
ULONG64 pVar = EvalExp(symbol);
ULONG64 val;
if (pVar == 0) {
BAD_SYMBOL(symbol);
}
if (GetFieldValue(pVar, type, field, val)) {
CANT_GET_VALUE(symbol, pVar);
}
return val;
}
#if 0
DWORD GetGlobalDWord(LPSTR symbol)
{
ULONG64 pdw;
ULONG64 dw = 0;
pdw = EvalExp(symbol);
if (pdw == 0) {
BAD_SYMBOL(symbol);
} else if (!GetFieldData(pdw, "DWORD", NULL, sizeof(dw), &dw)) {
CANT_GET_VALUE(symbol, pdw);
}
return (DWORD)(DWORD_PTR)dw;
}
WORD GetGlobalWord(LPSTR symbol)
{
ULONG64 pw;
WORD w = 0;
pw = EvalExp(symbol);
if (pw == 0) {
BAD_SYMBOL(symbol);
} else if (!GetFieldData(pw, (PUCHAR)"WORD", NULL, sizeof(w), (PVOID)&w)) {
CANT_GET_VALUE(symbol, pw);
}
return w;
}
BYTE GetGlobalByte(LPSTR symbol)
{
ULONG64 pb;
BYTE b = 0;
pb = EvalExp(symbol);
if (pb == 0) {
BAD_SYMBOL(symbol);
} else if (!GetFieldData(pb, (PUCHAR)"BYTE", NULL, sizeof(b), (PVOID)&b)) {
CANT_GET_VALUE(symbol, pb);
}
return b;
}
#endif
ULONG64 GetArrayElement(
ULONG64 pAddr,
LPSTR lpszStruc,
LPSTR lpszField,
ULONG64 index,
LPSTR lpszType)
{
static ULONG ulOffsetBase, ulSize;
ULONG64 result = 0;
if (lpszField) {
GetFieldOffset(lpszStruc, lpszField, &ulOffsetBase);
ulSize = GetTypeSize(lpszType);
}
ReadMemory(pAddr + ulOffsetBase + ulSize * index, &result, ulSize, NULL);
return result;
}
ULONG64 GetArrayElementPtr(
ULONG64 pAddr,
LPSTR lpszStruc,
LPSTR lpszField,
ULONG64 index)
{
static ULONG ulOffsetBase, ulSize;
ULONG64 result = 0;
if (lpszField) {
GetFieldOffset(lpszStruc, lpszField, &ulOffsetBase);
}
if (ulSize == 0) {
ulSize = GetTypeSize("PVOID");
}
ReadPointer(pAddr + ulOffsetBase + ulSize * index, &result);
return result;
}
/*
* Show progress in time consuming commands
* 10/15/2000 hiroyama
*/
VOID ShowProgress(
VOID)
{
static int i = 0;
static const char* clock[] = {
"\r-\r",
"\r\\\r",
"\r|\r",
"\r/\r",
};
/*
* Show the progress :-)
*/
Print(clock[i++ % ARRAY_SIZE(clock)]);
}
#define DOWNCAST(type, value) ((type)(ULONG_PTR)(value))
#ifdef KERNEL
BOOL HasValidSymbols(VOID)
{
if (EvalExp(VAR(gptiRit))) {
return TRUE;
}
return FALSE;
}
#endif
/*
* IsChk: returns TRUE if the window manager is CHK,
* could return TRUE regardless the entire system is FRE.
*/
int gfChk = -1;
BOOL IsChk(VOID)
{
ULONG64 psi;
if (gfChk != -1) {
return gfChk;
}
psi = GetGlobalPointer(SYM(gpsi));
if (psi == 0) {
Print("Cannot get gpsi, assuming chk\n");
return TRUE;
}
if ((DWORD)GetArrayElement(psi, SYM(SERVERINFO), "aiSysMet", SM_DEBUG, "DWORD")) {
return gfChk = TRUE;
}
return gfChk = FALSE;
}
#ifdef KERNEL
/*
* Debugger specific object routines:
* copied from ntos/tools/kdexts2/precomp.h
* (and fixed bugs)
*/
ULONG gObjectHeaderOffset;
__inline
ULONG64
KD_OBJECT_TO_OBJECT_HEADER(
ULONG64 o)
{
if (gObjectHeaderOffset == 0 && GetFieldOffset("nt!_OBJECT_HEADER", "Body", &gObjectHeaderOffset)) {
return 0;
}
return o - gObjectHeaderOffset;
}
__inline
ULONG64
KD_OBJECT_HEADER_TO_OBJECT(
ULONG64 o)
{
if (gObjectHeaderOffset && GetFieldOffset("nt!_OBJECT_HEADER", "Body", &gObjectHeaderOffset)) {
return 0;
}
return o + gObjectHeaderOffset;
}
__inline
VOID
KD_OBJECT_HEADER_TO_QUOTA_INFO(
ULONG64 oh,
PULONG64 pOutH
)
{
ULONG QuotaInfoOffset=0;
GetFieldValue(oh, "nt!__OBJECT_HEADER", "QuotaInfoOffset", QuotaInfoOffset);
*pOutH = (QuotaInfoOffset == 0 ? 0 : ((oh) - QuotaInfoOffset));
}
__inline
VOID
KD_OBJECT_HEADER_TO_HANDLE_INFO (
ULONG64 oh,
PULONG64 pOutH
)
{
ULONG HandleInfoOffset=0;
GetFieldValue(oh, "nt!__OBJECT_HEADER", "HandleInfoOffset", HandleInfoOffset);
*pOutH = (HandleInfoOffset == 0 ? 0 : ((oh) - HandleInfoOffset));
}
__inline
VOID
KD_OBJECT_HEADER_TO_NAME_INFO(
ULONG64 oh,
PULONG64 pOutH
)
{
ULONG NameInfoOffset=0;
GetFieldValue(oh, "nt!_OBJECT_HEADER", "NameInfoOffset", NameInfoOffset);
*pOutH = (NameInfoOffset == 0 ? 0 : ((oh) - NameInfoOffset));
}
#if 0
__inline
VOID
KD_OBJECT_HEADER_TO_CREATOR_INFO(
ULONG64 oh,
PULONG64 pOutH
)
{
ULONG Flags=0;
GetFieldValue(oh, "_OBJECT_HEADER", "Flags", Flags);
*pOutH = ((Flags & OB_FLAG_CREATOR_INFO) == 0 ? 0 : ((oh) - GetTypeSize("_OBJECT_HEADER_CREATOR_INFO")));
}
#endif
/*
* Object helper routines
*/
#endif
#ifdef KERNEL
/************************************************************************\
* Procedure: GetObjectName
* Get the generic object name (not a file, symlink etc.)
*
* 10/15/2000 Hiroyama Created
\************************************************************************/
VOID GetObjectName(
ULONG64 ptr,
LPWSTR pwsz,
ULONG cchMax)
{
PTR pHead;
PTR pNameInfo;
PTR pBuffer;
PTR length;
WCHAR ach[80];
pwsz[0] = 0;
pHead = KD_OBJECT_TO_OBJECT_HEADER(ptr);
DEBUGPRINT("pHead=%p\n", pHead);
if (pHead == NULL_PTR) {
return;
}
KD_OBJECT_HEADER_TO_NAME_INFO(pHead, &pNameInfo);
DEBUGPRINT("pNameInfo=%p\n", pNameInfo);
if (pNameInfo == NULL_PTR) {
return;
}
GetFieldValue(pNameInfo, "nt!_OBJECT_HEADER_NAME_INFO", "Name.Buffer", pBuffer);
DEBUGPRINT("pBuffer=%p\n", pBuffer);
if (pBuffer == NULL_PTR) {
return;
}
GetFieldValue(pNameInfo, "nt!_OBJECT_HEADER_NAME_INFO", "Name.Length", length);
DEBUGPRINT("length=%x\n", length);
if (length == 0) {
return;
}
move(ach, pBuffer);
wcsncpy(pwsz, ach, cchMax);
pwsz[min(cchMax - 1, length / sizeof(WCHAR))] = 0;
}
/************************************************************************\
* Procedure: GetProcessName
*
* 06/27/97 GerardoB Created
*
\************************************************************************/
BOOL
GetProcessName(
PTR pEProcess,
LPWSTR lpBuffer)
{
UCHAR ImageFileName[16];
if (!GetFieldValue(pEProcess, "nt!EPROCESS", "ImageFileName", ImageFileName)) {
swprintf(lpBuffer, L"%.16hs", ImageFileName);
return TRUE;
} else {
Print("Unable to read _EPROCESS at %p\n", pEProcess);
return FALSE;
}
}
/************************************************************************\
* GetAppName
*
* 10/6/1995 Created JimA
\************************************************************************/
BOOL
GetAppName(
PTR pEThread,
PTR pti,
LPWSTR lpBuffer,
DWORD cbBuffer)
{
PTR pstrAppName = 0;
PTR Buffer;
USHORT Length;
BOOL fRead = FALSE;
GetFieldValue(pti, SYM(THREADINFO), "pstrAppName", pstrAppName);
if (pstrAppName != 0) {
if (!GetFieldValue(pstrAppName, SYM(UNICODE_STRING), "Buffer", Buffer)) {
GetFieldValue(pstrAppName, SYM(UNICODE_STRING), "Length", Length);
cbBuffer = min(cbBuffer - sizeof(WCHAR), Length);
if (tryMoveBlock(lpBuffer, Buffer, cbBuffer)) {
lpBuffer[cbBuffer / sizeof(WCHAR)] = 0;
fRead = TRUE;
}
}
} else {
PTR pEProcess;
GetFieldValue(pEThread, "nt!ETHREAD", "ThreadsProcess", pEProcess);
fRead = GetProcessName(pEProcess, lpBuffer);
}
if (!fRead) {
wcsncpy(lpBuffer, L"<unknown name>", cbBuffer / sizeof(WCHAR));
}
return fRead;
}
#define INVALID_SESSION_ID ((ULONG)0xbadbad)
BOOL _GetProcessSessionId(PTR Process, PULONG SessionId)
{
PTR SessionPointer;
*SessionId = INVALID_SESSION_ID;
GetFieldValue(Process, "nt!_EPROCESS", "Session", SessionPointer);
if (SessionPointer != NULL_PTR) {
if (GetFieldValue(SessionPointer, "nt!_MM_SESSION_SPACE",
"SessionId", *SessionId)) {
Print("Could not find _MM_SESSION_SPACE type at %p.\n", SessionPointer);
return FALSE;
}
}
return TRUE;
}
ULONG GetProcessSessionId(PTR Process)
{
ULONG sid;
_GetProcessSessionId(Process, &sid);
return sid;
}
#endif // KERNEL
#ifdef OLD_DEBUGGER
#ifdef KERNEL
/************************************************************************\
* PrintMessages
*
* Prints out qmsg structures.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL PrintMessages(
PQMSG pqmsgRead)
{
QMSG qmsg;
ASYNCSENDMSG asm;
char *aszEvents[] = {
"MSG", // QEVENT_MESSAGE
"SHO", // QEVENT_SHOWWINDOW"
"CMD", // QEVENT_CANCLEMODE"
"SWP", // QEVENT_SETWINDOWPOS"
"UKS", // QEVENT_UPDATEKEYSTATE"
"DEA", // QEVENT_DEACTIVATE"
"ACT", // QEVENT_ACTIVATE"
"PST", // QEVENT_POSTMESSAGE"
"EXE", // QEVENT_EXECSHELL"
"CMN", // QEVENT_CANCELMENU"
"DSW", // QEVENT_DESTROYWINDOW"
"ASY", // QEVENT_ASYNCSENDMSG"
"HNG", // QEVENT_HUNGTHREAD"
"CMT", // QEVENT_CANCELMOUSEMOVETRK"
"NWE", // QEVENT_NOTIFYWINEVENT"
"RAC", // QEVENT_RITACCESSIBILITY"
"RSO", // QEVENT_RITSOUND"
"? ", // "?"
"? ", // "?"
"? " // "?"
};
#define NQEVENT (ARRAY_SIZE(aszEvents))
Print("typ pqmsg hwnd msg wParam lParam time ExInfo dwQEvent pti\n");
Print("-------------------------------------------------------------------------------\n");
SAFEWHILE (TRUE) {
move(qmsg, FIXKP(pqmsgRead));
if (qmsg.dwQEvent < NQEVENT) {
Print("%s %08lx ", aszEvents[qmsg.dwQEvent], pqmsgRead);
} else {
Print("??? %08lx ", pqmsgRead);
}
switch (qmsg.dwQEvent) {
case QEVENT_ASYNCSENDMSG:
move(asm, (PVOID)qmsg.msg.wParam);
Print("%07lx %04lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
asm.hwnd, asm.message, asm.wParam, asm.lParam,
qmsg.msg.time, qmsg.ExtraInfo, qmsg.dwQEvent, qmsg.pti);
break;
case 0:
default:
Print("%07lx %04lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
qmsg.msg.hwnd, qmsg.msg.message, qmsg.msg.wParam, qmsg.msg.lParam,
qmsg.msg.time, qmsg.ExtraInfo, qmsg.dwQEvent, qmsg.pti);
break;
}
if (qmsg.pqmsgNext != NULL) {
if (pqmsgRead == qmsg.pqmsgNext) {
Print("loop found in message list!");
return FALSE;
}
pqmsgRead = qmsg.pqmsgNext;
} else {
return TRUE;
}
}
return TRUE;
}
#endif // KERNEL
#endif // OLD_DEBUGGER
/************************************************************************\
* GetAndDumpHE
*
* Dumps given handle (dwT) and returns its phe.
*
* 6/9/1995 Documented SanfordS
\************************************************************************/
BOOL
GetAndDumpHE(
PTR dwT,
PPTR phe,
BOOL fPointerTest)
{
DWORD dw;
PTR pheT, phead;
PTR pshi, psi, h;
ULONG_PTR cHandleEntries;
/*
* Evaluate the argument string and get the address of the object to
* dump. Take either a handle or a pointer to the object.
*/
dw = HMIndexFromHandle(dwT);
/*
* First see if it is a pointer because the handle index is only part of
* the 32 bit DWORD, and we may mistake a pointer for a handle.
*/
if (!fPointerTest && IS_PTR(dwT)) {
if (GetFieldValue(dwT, SYM(HEAD), "h", h) == 0) {
if (GetAndDumpHE(h, phe, TRUE)) {
return TRUE;
}
}
}
/*
* Is it a handle? Does its index fit our table length?
*/
GETSHAREDINFO(pshi);
GetFieldValue(pshi, SYM(SHAREDINFO), "psi", psi);
GetFieldValue(psi, SYM(SERVERINFO), "cHandleEntries", cHandleEntries);
if (dw >= cHandleEntries) {
return FALSE;
}
/*
* Grab the handle entry and see if it is ok.
*/
GetFieldValue(pshi, SYM(SHAREDINFO), "aheList", pheT);
pheT += (dw * GetTypeSize("HANDLEENTRY"));
*phe = pheT;
/*
* If the type is too big, it's not a handle.
*/
_InitTypeRead(pheT, SYM(HANDLEENTRY));
if (ReadField(bType) >= TYPE_CTYPES) {
pheT = 0;
} else {
phead = ReadField(phead);
if (ReadField(bType) != TYPE_FREE) {
/*
* See if the object references this handle entry: the clincher
* for a handle, if it is not FREE.
*/
GetFieldValue(phead, SYM(HEAD), "h", h);
if (HMIndexFromHandle(h) != dw)
pheT = 0;
}
}
if (pheT == 0) {
if (!fPointerTest) {
Print("0x%p is not a valid object or handle.\n", dwT);
}
return FALSE;
}
/*
* Dump the ownership info and the handle entry info
*/
GetFieldValue(phead, SYM(HEAD), "h", h);
#ifdef Idhe
Idhe(0, h, 0);
#endif
Print("\n");
return TRUE;
}
/************************************************************************\
* HtoHE
*
* Extracts HE and phe from given handle. Handle can be just an index.
* Assumes h is a valid handle. Returns FALSE only if it's totally wacko.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL HtoHE(
PTR h,
PTR *pphe OPTIONAL)
{
PTR psi;
PTR pheT;
PTR cHandleEntries;
DWORD index;
index = HMIndexFromHandle(h);
GETSHAREDINFO(psi);
if (psi == 0) {
RAISE_EXCEPTION();
}
if (GetFieldValue(psi, SYM(SHAREDINFO), "aheList", pheT)) {
DEBUGPRINT("HtoHE(%I64x): Couldn't get aheList. Bad symbols?\n", h);
return FALSE;
}
if (GetFieldValue(psi, SYM(SHAREDINFO), "psi", psi)) {
DEBUGPRINT("HtoHE(%I64x): Couldn't get psi. Bad symbols?\n", h);
return FALSE;
}
if (GetFieldValue(psi, SYM(SERVERINFO), "cHandleEntries", cHandleEntries)) {
DEBUGPRINT("HtoHE(%I64x): Couldn't get cHandleEntries. Bad symbols?\n", h);
return FALSE;
}
if (index >= cHandleEntries) {
DEBUGPRINT("HtoHE(%I64x): index %d is too large.\n", h, index);
return FALSE;
}
pheT += index * GetTypeSize(SYM(HANDLEENTRY));
if (pphe != NULL) {
*pphe = pheT;
}
return TRUE;
}
/************************************************************************\
* GetPfromH
*
* Converts a handle to a pointer and extracts he and phe info. Returns a
* pointer to the object's HANDLEENTRY or NULL on failure.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
ULONG64 GetPfromH(
PTR h,
PTR *pphe OPTIONAL)
{
PTR pheT;
PTR phead;
if (!HtoHE(h, &pheT)) {
DEBUGPRINT("GetPfromH(%p): failed to get HE.\n", h);
return 0;
}
if (GetFieldValue(pheT, SYM(HANDLEENTRY), "phead", phead)) {
DEBUGPRINT("GetPfromH(%p): failed to get phead.\n", h);
return 0;
}
if (pphe != NULL) {
*pphe = pheT;
}
return FIXKP(phead);
}
/************************************************************************\
* getHEfromP
*
* Converts a pointer to a handle and extracts the he and phe info.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL getHEfromP(
PTR *pphe,
PTR p)
{
PTR pLookup, h;
p = FIXKP(p);
GetFieldValue(p, SYM(THROBJHEAD), "h", h);
pLookup = GetPfromH(h, pphe);
if (FIXKP(pLookup) != p) {
DEBUGPRINT("getHEfromP(%p): invalid.\n", p);
return FALSE;
}
return TRUE;
}
/************************************************************************\
* HorPtoP
*
* Generic function to accept either a user handle or pointer value and
* validate it and convert it to a pointer. type=-1 to allow any non-free
* type. type=-2 to allow any type.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
ULONG64 HorPtoP(
PTR p,
int type)
{
PTR phe;
PTR pT;
PTR phead;
int bType;
if (p == 0) {
return 0;
}
p = FIXKP(p);
if (ReadPointer(p, &pT) && getHEfromP(&phe, p)) {
/*
* It was a pointer
*/
GetFieldValue(phe, SYM(HANDLEENTRY), "bType", bType);
if ((type == -2 || bType != TYPE_FREE) &&
bType < TYPE_CTYPES &&
(type < 0 || bType == type)) {
GetFieldValue(phe, SYM(HANDLEENTRY), "phead", phead);
return FIXKP(phead);
}
}
pT = GetPfromH(p, NULL);
if (pT == 0) {
Print("WARNING: dumping %p even though it's not a valid pointer or handle!\n", (ULONG_PTR)p);
return p; // let it pass anyway so we can see how it got corrupted.
}
return FIXKP(pT);
}
/************************************************************************\
* Procedure: DebugGetWindowTextA
*
* Description: Places pwnd title into achDest.
*
* 06/09/1995 Created SanfordS
* 11/18/2000 Added dwLength parameter JasonSch
*
\************************************************************************/
BOOL DebugGetWindowTextA(
PTR pwnd,
char *achDest,
DWORD dwLength)
{
ULONG Length;
PTR Buffer;
WCHAR *lpwstr;
if (pwnd == 0) {
achDest[0] = '\0';
return FALSE;
}
pwnd = FIXKP(pwnd);
if (GetFieldValue(pwnd, SYM(WND), "strName.Length", Length) ||
GetFieldValue(pwnd, SYM(WND), "strName.Buffer", Buffer)) {
strcpy(achDest, "<< Can't get WND >>");
return FALSE;
}
if (Length == 0) {
strcpy(achDest, "<null>");
} else {
ULONG cbText = min(dwLength - 1, Length + sizeof(WCHAR));
lpwstr = LocalAlloc(LPTR, cbText);
if (!(tryMoveBlock(lpwstr, FIXKP(Buffer), cbText))) {
strcpy(achDest, "<< Can't get title >>");
LocalFree(lpwstr);
return FALSE;
}
RtlUnicodeToMultiByteN(achDest, dwLength, NULL, lpwstr, cbText);
achDest[cbText] = '\0';
LocalFree(lpwstr);
}
return TRUE;
}
/************************************************************************\
* DebugGetClassNameA
*
* Placed pcls name into achDest. No checks for size are made.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL DebugGetClassNameA(
PTR lpszClassName,
char *achDest)
{
CHAR ach[80];
if (lpszClassName == 0) {
strcpy(achDest, "<null>");
} else {
if (!tryMove(ach, FIXKP(lpszClassName))) {
strcpy(achDest, "<inaccessible>");
} else {
strcpy(achDest, ach);
}
strcpy(achDest, ach);
}
return TRUE;
}
/************************************************************************\
* PrintBitField, PrintEndBitField
*
* Printout specified boolean value in a structure. Assuming
* strlen(pszFieldName) will not exceeds BF_COLUMN_WIDTH.
*
* 10/12/1997 Created HiroYama
\************************************************************************/
VOID PrintBitField(
LPSTR pszFieldName,
BOOL fValue)
{
int iWidth;
int iStart = giBFColumn;
sprintf(gach1, fValue ? "*%-s " : " %-s ", pszFieldName);
iWidth = (strlen(gach1) + BF_COLUMN_WIDTH - 1) / BF_COLUMN_WIDTH;
iWidth *= BF_COLUMN_WIDTH;
if ((giBFColumn += iWidth) >= BF_MAX_WIDTH) {
giBFColumn = iWidth;
Print("%s\n", gaBFBuff);
iStart = 0;
}
sprintf(gaBFBuff + iStart, "%-*s", iWidth, gach1);
}
VOID PrintEndBitField(
VOID)
{
if (giBFColumn != 0) {
giBFColumn = 0;
Print("%s\n", gaBFBuff);
}
}
LPCSTR pszObjStr[] = {
"Free",
"Window",
"Menu",
"Cursor",
"SetWindowPos",
"Hook",
"Thread Info",
"Clip Data",
"Call Proc",
"Accel Table",
"WindowStation",
"DeskTop",
"DdeAccess",
"DdeConv",
"DdeExact",
"Monitor",
"Ctypes",
"Console",
"Generic"
};
#ifdef KERNEL
/***********************************************************************\
* GetGdiHandleType
*
* Returns a static buffer address which will contain a > 0 length string
* if the type makes sense.
*
* 12/1/1995 Created SanfordS
\***********************************************************************/
LPCSTR GetGDIHandleType(
HOBJ ho)
{
ULONG64 pent; // base address of hmgr entries
ULONG ulTemp;
static CHAR szT[20];
ULONG gcMaxHmgr, index;
DWORD dwEntrySize = GetTypeSize(SYM(ENTRY));
// filched from gre\hmgr.h
#define INDEX_MASK ((1 << INDEX_BITS) - 1)
#define HmgIfromH(h) ((ULONG)(h) & INDEX_MASK)
szT[0] = '\0';
pent = GetGlobalPointer(VAR(gpentHmgr));
moveExpValue(&gcMaxHmgr, VAR(gcMaxHmgr));
index = HmgIfromH((ULONG_PTR) ho);
if (index > gcMaxHmgr) {
return szT;
}
_InitTypeRead(pent + index * dwEntrySize, SYM(ENTRY));
if ((USHORT)ReadField(FullUnique) != ((ULONG_PTR)ho >> 16)) {
return szT;
}
if ((HOBJ)ReadField(einfo.pobj.hHmgr) != ho) {
return szT;
}
ulTemp = (ULONG) ReadField(Objt);
switch(ulTemp) {
case DEF_TYPE:
strcpy(szT, "DEF");
break;
case DC_TYPE:
strcpy(szT, "DC");
break;
case RGN_TYPE:
strcpy(szT, "RGN");
break;
case SURF_TYPE:
strcpy(szT, "SURF");
break;
case PATH_TYPE:
strcpy(szT, "PATH");
break;
case PAL_TYPE:
strcpy(szT, "PAL");
break;
case ICMLCS_TYPE:
strcpy(szT, "ICMLCS");
break;
case LFONT_TYPE:
strcpy(szT, "LFONT");
break;
case RFONT_TYPE:
strcpy(szT, "RFONT");
break;
case PFE_TYPE:
strcpy(szT, "PFE");
break;
case PFT_TYPE:
strcpy(szT, "PFT");
break;
case ICMCXF_TYPE:
strcpy(szT, "ICMCXF");
break;
case SPRITE_TYPE:
strcpy(szT, "SPRITE");
break;
case SPACE_TYPE:
strcpy(szT, "SPACE");
break;
case META_TYPE:
strcpy(szT, "META");
break;
case EFSTATE_TYPE:
strcpy(szT, "EFSTATE");
break;
case BMFD_TYPE:
strcpy(szT, "BMFD");
break;
case VTFD_TYPE:
strcpy(szT, "VTFD");
break;
case TTFD_TYPE:
strcpy(szT, "TTFD");
break;
case RC_TYPE:
strcpy(szT, "RC");
break;
case TEMP_TYPE:
strcpy(szT, "TEMP");
break;
case DRVOBJ_TYPE:
strcpy(szT, "DRVOBJ");
break;
case DCIOBJ_TYPE:
strcpy(szT, "DCIOBJ");
break;
case SPOOL_TYPE:
strcpy(szT, "SPOOL");
break;
default:
ulTemp = LO_TYPE((USHORT)ReadField(FullUnique) << TYPE_SHIFT);
switch (ulTemp) {
case LO_BRUSH_TYPE:
strcpy(szT, "BRUSH");
break;
case LO_PEN_TYPE:
strcpy(szT, "LO_PEN");
break;
case LO_EXTPEN_TYPE:
strcpy(szT, "LO_EXTPEN");
break;
case CLIENTOBJ_TYPE:
strcpy(szT, "CLIENTOBJ");
break;
case LO_METAFILE16_TYPE:
strcpy(szT, "LO_METAFILE16");
break;
case LO_METAFILE_TYPE:
strcpy(szT, "LO_METAFILE");
break;
case LO_METADC16_TYPE:
strcpy(szT, "LO_METADC16");
break;
}
}
return szT;
}
#endif // KERNEL
VOID DirectAnalyze(
ULONG_PTR dw,
ULONG_PTR adw,
BOOL fNoSym)
{
DWORD index, cHandleEntries, dwHESize, dwHandleOffset;
ULONG64 dwOffset, pshi, psi, phe;
WORD uniq, w, aw;
CHAR ach[80];
#ifdef KERNEL
LPCSTR psz;
#endif
GETSHAREDINFO(pshi);
GetFieldValue(pshi, SYM(SHAREDINFO), "psi", psi);
dwHESize = GetTypeSize(SYM(HANDLEENTRY));
GetFieldOffset(SYM(SHAREDINFO), "aheList", &dwHandleOffset);
if (HIWORD(dw) != 0) {
/*
* See if its a handle
*/
index = HMIndexFromHandle((ULONG)dw);
GetFieldValue(psi, SYM(SERVERINFO), "cHandleEntries", cHandleEntries);
if (index < cHandleEntries) {
uniq = HMUniqFromHandle(dw);
ReadPointer(pshi + dwHandleOffset, &phe);
phe += index * dwHESize;
_InitTypeRead(phe, SYM(HANDLEENTRY));
if (((WORD)ReadField(wUniq)) == uniq) {
Print("= a %s handle. ", pszObjStr[(ULONG)ReadField(bType)]);
fNoSym = TRUE;
}
}
#ifdef KERNEL
/*
* See if it's a GDI object handle
*/
psz = GetGDIHandleType((HOBJ)dw);
if (*psz) {
Print("= a GDI %s type handle. ", psz);
fNoSym = TRUE;
}
#endif // KERNEL
/*
* See if it's an object pointer
*/
if (_InitTypeRead(dw, SYM(HEAD))) {
if ((ULONG)ReadField(h)) {
index = HMIndexFromHandle((ULONG)ReadField(h));
if (index < cHandleEntries) {
ReadPointer(pshi + dwHandleOffset + index * dwHESize, &phe);
if (((ULONG_PTR)ReadField(phead)) == dw) {
Print("= a pointer to a %s.", pszObjStr[ReadField(bType)]);
fNoSym = TRUE;
}
}
}
/*
* Does this reference the stack itself?
*/
w = HIWORD(dw);
aw = HIWORD(adw);
if (w == aw || w == aw - 1 || w == aw + 1) {
Print("= Stack Reference ");
fNoSym = TRUE;
}
if (!fNoSym) {
/*
* Its accessible so print its symbolic reference
*/
GetSym(dw, ach, &dwOffset);
if (*ach) {
Print("= symbol \"%s\"", ach);
if (dwOffset) {
Print(" + %p", dwOffset);
}
}
}
}
}
Print("\n");
}
/***********************************************************************\
* Isas
*
* Analyzes the stack. Looks at a range of dwords and tries to make
* sense out of them. Identifies handles, user objects, and code
* addresses.
*
* 11/30/1995 Created SanfordS
\***********************************************************************/
BOOL Isas(
DWORD opts,
ULONG64 param1,
ULONG64 param2)
{
DWORD count = (DWORD)(UINT_PTR)param2;
DWORD_PTR dw;
DWORD dwPointerSize = GetTypeSize("PVOID");
if (param1 == 0) {
return FALSE;
}
if (opts & OFLAG(d)) {
DirectAnalyze((ULONG_PTR)param1, 0, opts & OFLAG(s));
} else {
if (count == 0) {
count = 25; // default span
}
Print("--- Stack analysis ---\n");
for ( ; count; count--, param1 += dwPointerSize) {
if (IsCtrlCHit()) {
break;
}
Print("[0x%p]: ", (ULONG_PTR)param1);
if (tryMove(dw, param1)) {
DirectAnalyze(dw, (DWORD_PTR)param1, OFLAG(s) & opts);
} else {
Print("No access\n");
}
}
}
return TRUE;
}
#ifdef KERNEL
typedef VOID (*AtomPrint)(DWORD dwOneShot, RTL_ATOM atom, USHORT usRefCount,
const WCHAR* pwszName, UCHAR uNameLength, UCHAR uFlags);
VOID DefAtomPrint(
DWORD dwOneShot,
RTL_ATOM atom,
USHORT usRefCount,
const WCHAR* pwszName,
UCHAR uNameLength,
UCHAR uFlags)
{
Print("%*s%hx(%2d) = %ls (%d)%s\n",
dwOneShot, dwOneShot ? " " : "", // hack: fOneShot is also used as a prefix spaces...
atom,
usRefCount,
pwszName,
uNameLength,
uFlags & RTL_ATOM_PINNED ? " pinned" : "");
}
/************************************************************************\
* DumpAtomTable
*
* Dumps an atom or entire atom table.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL DumpAtomTable(
PTR table,
RTL_ATOM atomFind,
DWORD dwOneShot,
AtomPrint pfnPrint)
{
ULONG i;
ULONG cBuckets;
ULONG cb, cbPtr, cbBuckets;
ULONG64 pate;
RTL_ATOM atom;
UCHAR Flags;
USHORT RefCount;
UCHAR NameLength;
WCHAR *pName;
if (pfnPrint == NULL) {
pfnPrint = DefAtomPrint;
}
if (!dwOneShot) {
Print("\n");
}
cbPtr = GetTypeSize("PVOID");
GetFieldValue(table, "nt!_RTL_ATOM_TABLE", "NumberOfBuckets", cBuckets);
GetFieldOffset("nt!_RTL_ATOM_TABLE", "Buckets", &cbBuckets);
for (i = 0; i < cBuckets; i++) {
ShowProgress();
ReadPointer(table + cbBuckets + i * cbPtr, &pate);
if (atomFind == 0 && pate != 0 && !dwOneShot) {
Print(" Bucket %d\n", i);
}
while (pate != NULL_PTR) {
GetFieldValue(pate, "nt!_RTL_ATOM_TABLE_ENTRY", "Atom", atom);
GetFieldValue(pate, "nt!_RTL_ATOM_TABLE_ENTRY", "Flags", Flags);
GetFieldValue(pate, "nt!_RTL_ATOM_TABLE_ENTRY", "ReferenceCount", RefCount);
GetFieldValue(pate, "nt!_RTL_ATOM_TABLE_ENTRY", "NameLength", NameLength);
GetFieldOffset("nt!_RTL_ATOM_TABLE_ENTRY", "Name", &cb);
pName = LocalAlloc(LPTR, sizeof(WCHAR) * (NameLength + 1));
ReadMemory(pate + cb, (PVOID)pName, sizeof(WCHAR) * NameLength, &cb);
pName[NameLength] = L'\0';
if (atomFind == 0 || atom == atomFind) {
pfnPrint(dwOneShot, atom, RefCount, pName, NameLength, Flags);
if (atom == atomFind) {
LocalFree(pName);
return TRUE;
}
}
LocalFree(pName);
GetFieldValue(pate, "nt!_RTL_ATOM_TABLE_ENTRY", "HashLink", pate);
}
}
return FALSE;
}
/************************************************************************\
* Iatom
*
* Dumps an atom or the entire local USER atom table.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Iatom(
DWORD opts,
ULONG64 atom)
{
PTR table;
PTR pwinsta;
UNREFERENCED_PARAMETER(opts);
table = GetGlobalPointer(VAR(UserAtomTableHandle));
if (table != NULL_PTR) {
Print("\nPrivate atom table for WIN32K ");
DumpAtomTable(table, (RTL_ATOM)atom, FALSE, NULL);
}
FOREACHWINDOWSTATION(pwinsta)
GetFieldValue(pwinsta, SYM(WINDOWSTATION), "pGlobalAtomTable", table);
if (table != NULL_PTR) {
Print(" \nGlobal atom table for window station %lx ", pwinsta);
DumpAtomTable(table, (RTL_ATOM)atom, FALSE, NULL);
}
NEXTEACHWINDOWSTATION(pwinsta);
return TRUE;
}
#endif // KERNEL
#ifdef OLD_DEBUGGER
#ifndef KERNEL
/************************************************************************\
* DumpConvInfo
*
* Dumps DDEML client conversation info structures.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL DumpConvInfo(
PCONV_INFO pcoi)
{
CL_CONV_INFO coi;
ADVISE_LINK al;
XACT_INFO xi;
move(coi, pcoi);
Print(" next = 0x%08lx\n", coi.ci.next);
Print(" pcii = 0x%08lx\n", coi.ci.pcii);
Print(" hUser = 0x%08lx\n", coi.ci.hUser);
Print(" hConv = 0x%08lx\n", coi.ci.hConv);
Print(" laService = 0x%04x\n", coi.ci.laService);
Print(" laTopic = 0x%04x\n", coi.ci.laTopic);
Print(" hwndPartner = 0x%08lx\n", coi.ci.hwndPartner);
Print(" hwndConv = 0x%08lx\n", coi.ci.hwndConv);
Print(" state = 0x%04x\n", coi.ci.state);
Print(" laServiceRequested= 0x%04x\n", coi.ci.laServiceRequested);
Print(" pxiIn = 0x%08lx\n", coi.ci.pxiIn);
Print(" pxiOut = 0x%08lx\n", coi.ci.pxiOut);
SAFEWHILE (coi.ci.pxiOut) {
move(xi, coi.ci.pxiOut);
Print(" hXact = (0x%08lx)->0x%08lx\n", xi.hXact, coi.ci.pxiOut);
coi.ci.pxiOut = xi.next;
}
Print(" dmqIn = 0x%08lx\n", coi.ci.dmqIn);
Print(" dmqOut = 0x%08lx\n", coi.ci.dmqOut);
Print(" aLinks = 0x%08lx\n", coi.ci.aLinks);
Print(" cLinks = 0x%08lx\n", coi.ci.cLinks);
SAFEWHILE (coi.ci.cLinks--) {
move(al, coi.ci.aLinks++);
Print(" pLinkCount = 0x%08x\n", al.pLinkCount);
Print(" wType = 0x%08x\n", al.wType);
Print(" state = 0x%08x\n", al.state);
if (coi.ci.cLinks) {
Print(" ---\n");
}
}
if (coi.ci.state & ST_CLIENT) {
Print(" hwndReconnect = 0x%08lx\n", coi.hwndReconnect);
Print(" hConvList = 0x%08lx\n", coi.hConvList);
}
return TRUE;
}
#endif // !KERNEL
#endif // OLD_DEBUGGER
#ifndef KERNEL
/************************************************************************\
* FixKernelPointer
*
* Converts a kernel object pointer into its client-side equivalent. Client
* pointers and NULL are unchanged.
*
* 6/15/1995 Created SanfordS
\************************************************************************/
ULONG64
FixKernelPointer(
PTR pKernel)
{
static ULONG64 pteb = 0;
static ULONG64 ulClientDelta;
static ULONG64 HighestUserAddress;
if (pKernel == 0) {
return 0;
}
if (HighestUserAddress == 0) {
SYSTEM_BASIC_INFORMATION SystemInformation;
if (NT_SUCCESS(NtQuerySystemInformation(SystemBasicInformation,
&SystemInformation,
sizeof(SystemInformation),
NULL))) {
HighestUserAddress = SystemInformation.MaximumUserModeAddress;
} else {
// Query failed. Assume usermode is the low half of the address
// space.
HighestUserAddress = MAXINT_PTR;
}
}
if (!IsPtr64()) {
pKernel = (ULONG)pKernel;
}
if (pKernel <= HighestUserAddress) {
return pKernel;
}
if (pteb == 0) {
ULONG pciOffset;
GetTebAddress(&pteb);
GetFieldOffset(SYM(TEB), "Win32ClientInfo", &pciOffset);
GetFieldValue(pteb + pciOffset, SYM(CLIENTINFO), "ulClientDelta", ulClientDelta);
}
return (pKernel - ulClientDelta);
}
ULONG64
RebaseSharedPtr(ULONG64 p)
{
ULONG64 pshi = 0;
ULONG64 ulSharedDelta;
if (p == 0) {
return 0;
}
moveExp(&pshi, VAR(gSharedInfo));
if (pshi == 0) {
RAISE_EXCEPTION();
}
if (!GetFieldValue(pshi, SYM(SHAREDINFO), "ulSharedDelta", ulSharedDelta)) {
RAISE_EXCEPTION();
}
return p - ulSharedDelta;
}
#endif // !KERNEL
/************************************************************************\
* Procedure: GetVKeyName
*
* 08/09/98 HiroYama Created
*
\************************************************************************/
typedef struct {
DWORD dwVKey;
const char* name;
} VKeyDef;
int compareVKey(const VKeyDef* a, const VKeyDef* b)
{
return a->dwVKey - b->dwVKey;
}
#define VKEY_ITEM(x) { x, #x }
const VKeyDef gVKeyDef[] = {
#include "vktbl.txt"
};
const char* _GetVKeyName(DWORD dwVKey, int n)
{
int i;
/*
* If dwVKey is one of alphabets or numerics, there's no VK_ macro defined.
*/
if ((dwVKey >= 'A' && dwVKey <= 'Z') || (dwVKey >= '0' && dwVKey <= '9')) {
static char buffer[] = "VK_*";
if (n != 0) {
return "";
}
buffer[ARRAY_SIZE(buffer) - 2] = (BYTE)dwVKey;
return buffer;
}
/*
* Search the VKEY table.
*/
for (i = 0; i < ARRAY_SIZE(gVKeyDef); ++i) {
const VKeyDef* result = gVKeyDef + i;
if (result->dwVKey == dwVKey) {
for (; i < ARRAY_SIZE(gVKeyDef); ++i) {
if (gVKeyDef[i].dwVKey != dwVKey) {
return "";
}
if (&gVKeyDef[i] - result == n) {
return gVKeyDef[i].name;
}
}
}
}
/*
* VKey name is not found.
*/
return "";
}
const char* GetVKeyName(DWORD dwVKey)
{
static char buf[256];
const char* delim = "";
int n = 0;
buf[0] = 0;
for (n = 0; n < ARRAY_SIZE(gVKeyDef); ++n) {
const char* name = _GetVKeyName(dwVKey, n);
if (*name) {
strcat(buf, delim);
strcat(buf, name);
delim = " / ";
} else {
break;
}
}
return buf;
}
#undef VKEY_ITEM
#ifdef KERNEL
/************************************************************************\
* Procedure: DumpClassList
*
*
* 05/18/98 GerardoB Extracted from Idcls
\************************************************************************/
VOID DumpClassList(
DWORD opts,
ULONG64 pcls,
BOOL fPrivate)
{
ULONG64 pclsClone;
ULONG64 pclsNext;
SAFEWHILE (pcls != 0) {
if (GetFieldValue(pcls, SYM(CLS), "pclsClone", pclsClone)) {
Print(" Private class\t\tPCLS @ 0x%p - inaccessible, skipping...\n", pcls);
break;
}
Print(" %s class\t\t", fPrivate ? "Private" : "Public ");
Idcls(opts, pcls);
if (pclsClone != 0) {
SAFEWHILE (pclsClone != 0) {
if (GetFieldValue(pclsClone, SYM(CLS), "pclsNext", pclsNext)) {
Print("Could not access clone class at %p, skipping clones...\n", pclsClone);
break;
}
Print(" %s class clone\t", fPrivate ? "Private" : "Public ");
Idcls(opts, pclsClone);
pclsClone = pclsNext;
}
}
GetFieldValue(pcls, SYM(CLS), "pclsNext", pcls);
}
}
ULONG
dclsCallback(
ULONG64 ppi,
PVOID Data)
{
DWORD opts = PtrToUlong(Data);
ULONG64 pcls;
UNREFERENCED_PARAMETER(Data);
Print("\nClasses for process %p:\n", ppi);
GetFieldValue(ppi, SYM(PROCESSINFO), "pclsPrivateList", pcls);
DumpClassList(opts, pcls, TRUE);
GetFieldValue(ppi, SYM(PROCESSINFO), "pclsPublicList", pcls);
DumpClassList(opts, pcls, FALSE);
return FALSE;
}
/************************************************************************\
* Idcls
*
* Dumps window class structures
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Idcls(
DWORD opts,
ULONG64 param1)
{
char ach[120];
ULONG64 dwOffset;
ULONG64 pcls = param1;
if (param1 == 0) {
ForEachPpi(dclsCallback, ULongToPtr(opts));
Print("\nGlobal Classes:\n");
pcls = GetGlobalPointer(VAR(gpclsList));
SAFEWHILE (pcls) {
Print(" Global Class\t\t");
Idcls(opts, pcls);
GetFieldValue(pcls, SYM(CLS), "pclsNext", pcls);
}
return TRUE;
}
/*
* Dump class list for a process
*/
if (opts & OFLAG(p)) {
opts &= ~OFLAG(p);
Print("\nClasses for process %p:\n", param1);
GetFieldValue(param1, SYM(PROCESSINFO), "pclsPrivateList", pcls);
DumpClassList(opts, pcls, TRUE);
GetFieldValue(param1, SYM(PROCESSINFO), "pclsPublicList", pcls);
DumpClassList(opts, pcls, FALSE);
return TRUE;
}
_InitTypeRead(pcls, SYM(tagCLS));
DebugGetClassNameA(ReadField(lpszAnsiClassName), ach);
Print("PCLS @ 0x%p \t(%s)\n", pcls, ach);
if (opts & OFLAG(v)) {
Print("\t pclsNext 0x%p\n"
"\t atomClassNameAtom (V) 0x%04x\n"
"\t atomNVClassNameAtom (NV) 0x%04x\n"
"\t fnid 0x%04x\n"
"\t pDCE 0x%p\n"
"\t cWndReferenceCount 0x%08lx\n"
"\t flags %s\n",
ReadField(pclsNext),
(ULONG)ReadField(atomClassName),
(ULONG)ReadField(atomNVClassName),
(ULONG)ReadField(fnid),
ReadField(pdce),
(ULONG)ReadField(cWndReferenceCount),
GetFlags(GF_CSF, (WORD)ReadField(CSF_flags), NULL, TRUE));
if (ReadField(lpszClientAnsiMenuName)) {
move(ach, ReadField(lpszClientAnsiMenuName));
ach[sizeof(ach) - 1] = '\0';
} else {
ach[0] = '\0';
}
Print("\t lpszClientMenu 0x%p (%s)\n",
ReadField(lpszClientUnicodeMenuName),
ach);
Print("\t hTaskWow 0x%08lx\n"
"\t spcpdFirst 0x%p\n"
"\t pclsBase 0x%p\n"
"\t pclsClone 0x%p\n",
(ULONG)ReadField(hTaskWow),
ReadField(spcpdFirst),
ReadField(pclsBase),
ReadField(pclsClone));
GetSym(ReadField(lpfnWndProc), ach, &dwOffset);
Print("\t style %s\n"
"\t lpfnWndProc 0x%p = \"%s\" \n"
"\t cbclsExtra 0x%08lx\n"
"\t cbwndExtra 0x%08lx\n"
"\t hModule 0x%p\n"
"\t spicn 0x%p\n"
"\t spcur 0x%p\n"
"\t hbrBackground 0x%p\n"
"\t spicnSm 0x%p\n",
GetFlags(GF_CS, (DWORD)ReadField(style), NULL, TRUE),
ReadField(lpfnWndProc), ach,
(ULONG)ReadField(cbclsExtra),
(ULONG)ReadField(cbwndExtra),
ReadField(hModule),
ReadField(spicn),
ReadField(spcur),
ReadField(hbrBackground),
ReadField(spicnSm));
}
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
LPSTR ProcessName(
ULONG64 ppi)
{
ULONG64 pEProcess;
static UCHAR ImageFileName[16];
GetFieldValue(ppi, "win32k!W32PROCESS", "Process", pEProcess);
GetFieldValue(pEProcess, "nt!EPROCESS", "ImageFileName", ImageFileName);
if (ImageFileName[0]) {
return ImageFileName;
} else {
return "System";
}
}
#endif // KERNEL
#ifdef KERNEL
VOID PrintCurHeader()
{
Print("P = Process Owned.\n");
Print("P pcursor flags rt Res/Name ModAtom bpp cx cy xHot yHot hbmMask hbmColor hbmUserAlpha\n");
}
VOID PrintCurData(
ULONG64 pcur,
DWORD opts)
{
_InitTypeRead(pcur, SYM(CURSOR));
if ((opts & OFLAG(x)) &&
(((DWORD) ReadField(CURSORF_flags)) & (CURSORF_ACONFRAME | CURSORF_LINKED))) {
return; // skip acon frame or linked objects.
}
if (((DWORD) ReadField(CURSORF_flags)) & CURSORF_ACON) {
if (opts & OFLAG(a)) {
Print("--------------\n");
}
if (opts & OFLAG(o)) {
Print("\nOwner:%#010p (%s)\n", ReadField(head.ppi), ProcessName(ReadField(head.ppi)));
}
if (opts & OFLAG(v)) {
Print("\nACON @ 0x%p:\n", pcur);
Print(" ppiOwner = %#010p\n", ReadField(head.ppi));
Print(" CURSORF_flags = %s\n", GetFlags(GF_CURSORF, (DWORD) ReadField(CURSORF_flags), NULL, TRUE));
Print(" strName = %#010p\n", ReadField(strName.Buffer));
Print(" atomModName = %#x\n", (DWORD) ReadField(atomModName));
Print(" rt = %#x\n", (DWORD) ReadField(rt));
} else {
ULONG64 cpcur = 0;
GetFieldValue(pcur, SYM(ACON), "cpcur", cpcur);
Print("%c %#010p %#6x %#4x %#010p %#8x --- ACON (%d frames)\n",
ReadField(head.ppi) ? 'P' : ' ',
pcur,
(DWORD) ReadField(CURSORF_flags),
(DWORD) ReadField(rt),
ReadField(strName.Buffer),
(DWORD) ReadField(atomModName),
(DWORD) cpcur);
}
if (opts & OFLAG(a)) {
int i = 0;
ULONG cbElement = 0;
ULONG cbArrayOffset = 0;
ULONG64 curFrame = 0;
_InitTypeRead(pcur, SYM(ACON));
cbElement = GetTypeSize("PCURSOR");
GetFieldOffset(SYM(ACON), "aspcur", &cbArrayOffset);
Print("%d animation sequences, currently at step %d.\n",
(DWORD) ReadField(cicur),
(DWORD) ReadField(iicur));
i = (int) ReadField(cpcur);
while (i--) {
ReadPointer(pcur + cbArrayOffset + (i * cbElement), &curFrame);
PrintCurData(curFrame, opts & ~(OFLAG(x) | OFLAG(o)));
}
Print("--------------\n");
}
} else {
if (opts & OFLAG(v)) {
Print("\nCursor/Icon @ 0x%p:\n", pcur);
Print(" ppiOwner = %#010p (%s)\n", ReadField(head.ppi), ProcessName(ReadField(head.ppi)));
Print(" pcurNext = %#010p\n", ReadField(pcurNext));
Print(" CURSORF_flags = %s\n", GetFlags(GF_CURSORF, (DWORD) ReadField(CURSORF_flags), NULL, TRUE));
Print(" strName = %#010p\n", ReadField(strName.Buffer));
Print(" atomModName = %#x\n", (DWORD) ReadField(atomModName));
Print(" rt = %#x\n", (DWORD) ReadField(rt));
Print(" bpp = %d\n", (DWORD) ReadField(bpp));
Print(" cx = %d\n", (DWORD) ReadField(cx));
Print(" cy = %d\n", (DWORD) ReadField(cy));
Print(" xHotspot = %d\n", (DWORD) ReadField(xHotspot));
Print(" yHotspot = %d\n", (DWORD) ReadField(yHotspot));
Print(" hbmMask = %#x\n", (DWORD) ReadField(hbmMask));
Print(" hbmColor = %#x\n", (DWORD) ReadField(hbmColor));
Print(" hbmUserAlpha = %#x\n", (DWORD) ReadField(hbmUserAlpha));
} else {
if (opts & OFLAG(o)) {
Print("\nOwner:%#010p (%s)\n", ReadField(head.ppi), ProcessName(ReadField(head.ppi)));
}
Print("%c %#010p %#06x %#04x %#010p %#08x %3d %3d %3d %4d %4d %#010x %#010x %#010x\n",
ReadField(head.ppi) ? 'P' : ' ',
pcur,
(DWORD) ReadField(CURSORF_flags),
(DWORD) ReadField(rt),
ReadField(strName.Buffer),
(DWORD) ReadField(atomModName),
(DWORD) ReadField(bpp),
(DWORD) ReadField(cx),
(DWORD) ReadField(cy),
(DWORD) ReadField(xHotspot),
(DWORD) ReadField(yHotspot),
(DWORD) ReadField(hbmMask),
(DWORD) ReadField(hbmColor),
(DWORD) ReadField(hbmUserAlpha));
}
}
}
typedef struct tagMyCurData
{
ULONG64 ppiDesired;
ULONG idDesired;
DWORD opts;
} MyCurData;
ULONG WDBGAPI PrintPpiCurData(ULONG64 ppi, PVOID Data)
{
ULONG64 pcur = 0;
MyCurData * pMyCurData = (MyCurData *)Data;
if (pMyCurData == NULL) {
return 0;
}
_InitTypeRead(ppi, SYM(PROCESSINFO));
if (ReadField(pCursorCache)) {
Print("\nCache for process %#010p (%s):\n", ppi, ProcessName(ppi));
pcur = ReadField(pCursorCache);
while (pcur) {
_InitTypeRead(pcur, SYM(CURSOR));
if ((pMyCurData->idDesired == 0) || ((ULONG) ReadField(strName.Buffer) == pMyCurData->idDesired)) {
if (ReadField(head.ppi) != ppi) {
Print("Wrong cache! Owned by %#010p! --v\n", ReadField(head.ppi));
}
PrintCurData(pcur, pMyCurData->opts);
}
pcur = ReadField(pcurNext);
}
}
return 0;
}
/************************************************************************\
* Idcur
*
* Dump cursor structures.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Idcur(
DWORD opts,
ULONG64 param1)
{
ULONG64 ppi = 0;
ULONG64 ppiDesired = 0;
ULONG idDesired = 0;
ULONG64 pcur = 0;
ULONG64 phe = 0;
int cCursors = 0;
int i;
if (OFLAG(p) & opts) {
ppiDesired = param1;
param1 = 0;
} else if (OFLAG(i) & opts) {
idDesired = (ULONG) param1;
param1 = 0;
}
if (param1 == 0) {
if (!(OFLAG(v) & opts)) {
PrintCurHeader();
}
pcur = GetGlobalPointer(VAR(gpcurFirst));
if (pcur != 0 && ppiDesired == 0) {
Print("\nGlobal cache:\n");
while (pcur) {
_InitTypeRead(pcur, SYM(CURSOR));
if (!idDesired || ((ULONG) ReadField(strName.Buffer) == idDesired)) {
if (ReadField(head.ppi) != 0) {
Print("Wrong cache! Owned by %010p! --v\n", ReadField(head.ppi));
}
PrintCurData(pcur, opts);
}
pcur = ReadField(pcurNext);
}
}
if (ppiDesired == 0 || ppiDesired == ppi) {
MyCurData myCurData;
myCurData.ppiDesired = ppiDesired;
myCurData.idDesired = idDesired;
myCurData.opts = opts;
ForEachPpi(PrintPpiCurData, &myCurData);
}
Print("\nNon-cached cursor objects:\n");
FOREACHHANDLEENTRY(phe, i)
_InitTypeRead(phe, SYM(HANDLEENTRY));
if (ReadField(bType) == TYPE_CURSOR) {
pcur = ReadField(phead);
_InitTypeRead(pcur, SYM(CURSOR));
if (!(ReadField(CURSORF_flags) & (CURSORF_LINKED | CURSORF_ACONFRAME)) &&
(!idDesired || ((ULONG) ReadField(strName.Buffer) == idDesired)) &&
(ppiDesired == 0 || ppiDesired == ReadField(head.ppi))) {
PrintCurData(pcur, opts | OFLAG(x) | OFLAG(o));
}
cCursors++;
}
NEXTEACHHANDLEENTRY()
Print("\n%d Cursors/Icons Total.\n", cCursors);
return TRUE;
}
pcur = HorPtoP(param1, TYPE_CURSOR);
if (pcur == 0) {
Print("%010p : Invalid cursor handle or pointer.\n", param1);
return FALSE;
}
if (!(OFLAG(v) & opts)) {
PrintCurHeader();
}
PrintCurData(pcur, opts);
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
/************************************************************************\
* ddeexact
*
* Dumps DDEML transaction structures.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL dddexact(
ULONG64 pxs,
DWORD opts)
{
_InitTypeRead(pxs, SYM(XSTATE));
if (opts & OFLAG(v)) {
Print(" XACT:0x%p\n", pxs);
Print(" snext = 0x%#p\n", ReadField(snext));
Print(" fnResponse = 0x%#p\n", ReadField(fnResponse));
Print(" hClient = 0x%08lx\n", (ULONG)ReadField(hClient));
Print(" hServer = 0x%08lx\n", (ULONG)ReadField(hServer));
Print(" pIntDdeInfo = 0x%#p\n", ReadField(pIntDdeInfo));
} else {
Print("0x%#p(0x%08lx) ", pxs, (ULONG)ReadField(flags));
}
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
/************************************************************************\
* ddeconv
*
* Dumps DDE tracking layer conversation structures.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL dddeconv(
ULONG64 pDdeconv,
DWORD opts)
{
ULONG64 pxs;
int cX;
DWORD dwOffset, dwQosOffset;
_InitTypeRead(pDdeconv, SYM(DDECONV));
Print(" CONVERSATION-PAIR(0x%p:0x%p)\n", pDdeconv, ReadField(spartnerConv));
if (opts & OFLAG(v)) {
Print(" snext = 0x%p\n", ReadField(snext));
Print(" spwnd = 0x%p\n", ReadField(spwnd));
Print(" spwndPartner = 0x%p\n", ReadField(spwndPartner));
}
if (opts & (OFLAG(v) | OFLAG(r))) {
if (ReadField(spxsOut)){
pxs = ReadField(spxsOut);
cX = 0;
SAFEWHILE (pxs) {
if ((opts & OFLAG(r)) && !cX++) {
Print(" Transaction chain:");
} else {
Print(" ");
}
dddexact(pxs, opts);
if (opts & OFLAG(r)) {
GetFieldValue(pxs, SYM(STATE), "snext", pxs);
} else {
pxs = 0;
}
if (!pxs) {
Print("\n");
}
}
}
}
if (opts & OFLAG(v)) {
Print(" pfl = 0x%p\n", ReadField(pfl));
Print(" flags = 0x%08lx\n", (ULONG)ReadField(flags));
if ((opts & OFLAG(v)) && (opts & OFLAG(r)) && ReadField(pddei)) {
GetFieldOffset(SYM(DDECONV), "pddei", &dwOffset);
GetFieldOffset(SYM(DDEIMP), "qos", &dwQosOffset);
_InitTypeRead(pDdeconv + dwOffset + dwQosOffset, SYM(DDEI));
Print(" pddei = 0x%08lx\n", pDdeconv+ dwOffset);
Print(" Impersonation info:\n");
Print(" qos.Length = 0x%08lx\n", (ULONG)ReadField(Length));
Print(" qos.ImpersonationLevel = 0x%08lx\n", (ULONG)ReadField(ImpersonationLevel));
Print(" qos.ContextTrackingMode = 0x%08lx\n", (ULONG)ReadField(ContextTrackingMode));
Print(" qos.EffectiveOnly = 0x%08lx\n", (ULONG)ReadField(EffectiveOnly));
_InitTypeRead(pDdeconv + dwOffset, SYM(DDEIMP));
GetFieldOffset(SYM(DDEIMP), "ClientContext", &dwOffset);
Print(" ClientContext = 0x%#p\n", pDdeconv + dwOffset);
Print(" cRefInit = 0x%08lx\n", (ULONG)ReadField(cRefInit));
Print(" cRefConv = 0x%08lx\n", (ULONG)ReadField(cRefConv));
}
}
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
/************************************************************************\
* Idde
*
* Dumps DDE tracking layer state and structures.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Idde(
DWORD opts,
ULONG64 param1)
{
ULONG64 pshi, psi, cHandleEntries, pheList, h, pPropList, ptr;
ULONG64 pObj = 0;
UINT i, iFirstFree;
DWORD atomDdeTrack, dwOffset;
DWORD dwHESize = GetTypeSize(SYM(HANDLEENTRY));
DWORD dwPropSize = GetTypeSize(SYM(PROP));
BYTE bType;
moveExpValue(&atomDdeTrack, VAR(atomDDETrack));
GETSHAREDINFO(pshi);
GetFieldOffset(SYM(SHAREDINFO), "psi", &dwOffset);
ReadPointer(pshi + dwOffset, &psi);
GetFieldOffset(SYM(SHAREDINFO), "aheList", &dwOffset);
ReadPointer(pshi + dwOffset, &pheList);
GetFieldValue(psi, SYM(SERVERINFO), "cHandleEntries", cHandleEntries);
if (param1) {
/*
* get object param.
*/
i = HMIndexFromHandle((ULONG_PTR)param1);
if (i >= cHandleEntries) {
GetFieldValue(param1, SYM(HEAD), "h", h);
i = HMIndexFromHandle(h);
}
if (i >= cHandleEntries) {
Print("0x%08lx is not a valid object.\n", h);
return FALSE;
}
GetFieldOffset(SYM(HANDLEENTRY), "phead", &dwOffset);
ReadPointer(pheList + i * dwHESize + dwOffset, &pObj);
/*
* verify type.
*/
GetFieldValue(pheList + i * dwHESize, SYM(HANDLEENTRY), "bType", bType);
switch (bType) {
case TYPE_WINDOW:
GetFieldOffset(SYM(WND), "ppropList", &dwOffset);
ReadPointer(pObj + dwOffset, &pPropList);
GetFieldValue(pPropList, SYM(PROPLIST), "iFirstFree", iFirstFree);
for (i = 0; i < iFirstFree; i++) {
if (i == 0) {
Print("Window 0x%08lx conversations:\n", h);
}
GetFieldOffset(SYM(PROPLIST), "aprop", &dwOffset);
ReadPtr(pPropList + dwOffset + i * dwPropSize, &ptr);
_InitTypeRead(ptr, SYM(PROP));
if (ReadField(atomKey) == (ATOM)MAKEINTATOM(atomDdeTrack)) {
Print(" ");
dddeconv(ReadField(hData), opts);
}
}
return TRUE;
case TYPE_DDECONV:
case TYPE_DDEXACT:
break;
default:
Print("0x%08lx is not a valid window, conversation or transaction object.\n", h);
return FALSE;
}
}
/*
* look for all qualifying objects in the object table.
*/
Print("DDE objects:\n");
for (i = 0; i < cHandleEntries; i++) {
_InitTypeRead(pheList + i * dwHESize , SYM(HANDLEENTRY));
if ((BYTE)ReadField(bType) == TYPE_DDECONV && ((pObj == FIXKP(ReadField(phead))) || pObj == 0)) {
dddeconv(FIXKP(ReadField(phead)), opts);
}
if ((BYTE)ReadField(bType) == TYPE_DDEXACT && (pObj == 0 || pObj == FIXKP(ReadField(phead)))) {
if (!(opts & OFLAG(v))) {
Print(" XACT:");
}
dddexact(FIXKP(ReadField(phead)), opts);
Print("\n");
}
}
return TRUE;
}
#endif // KERNEL
#ifdef OLD_DEBUGGER
#ifndef KERNEL
/************************************************************************\
* Iddeml
*
* Dumps the DDEML state for this client process.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Iddeml(
DWORD opts,
LPSTR lpas)
{
CHANDLEENTRY he, *phe;
int cHandles, ch, i;
DWORD Type;
DWORD_PTR Instance, Object, Pointer;
CL_INSTANCE_INFO cii, *pcii;
ATOM ns;
SERVER_LOOKUP sl;
LINK_COUNT lc;
CL_CONV_INFO cci;
PCL_CONV_INFO pcci;
CONVLIST cl;
HWND hwnd, *phwnd;
XACT_INFO xi;
DDEMLDATA dd;
CONV_INFO ci;
moveExpValue(&cHandles, "user32!cHandlesAllocated");
Instance = 0;
Type = 0;
Object = 0;
Pointer = 0;
SAFEWHILE (*lpas) {
SAFEWHILE (*lpas == ' ')
lpas++;
if (*lpas == 'i') {
lpas++;
Instance = (DWORD_PTR)EvalExp(lpas);
SAFEWHILE (*lpas != ' ' && *lpas != 0)
lpas++;
continue;
}
if (*lpas == 't') {
lpas++;
Type = (DWORD)(DWORD_PTR)EvalExp(lpas);
SAFEWHILE (*lpas != ' ' && *lpas != 0)
lpas++;
continue;
}
if (*lpas) {
Object = Pointer = (DWORD_PTR)EvalExp(lpas);
SAFEWHILE (*lpas != ' ' && *lpas != 0)
lpas++;
}
}
/*
* for each instance for this process...
*/
pcii = GetGlobalPointer("user32!pciiList");
if (pcii == NULL) {
Print("No Instances exist.\n");
return TRUE;
}
move(cii, pcii);
SAFEWHILE (pcii != NULL) {
pcii = cii.next;
if (Instance == 0 || (Instance == (DWORD_PTR)cii.hInstClient)) {
Print("Objects for instance 0x%p:\n", cii.hInstClient);
ch = cHandles;
phe = GetGlobalPointer("user32!aHandleEntry");
SAFEWHILE (ch--) {
move(he, phe++);
if (he.handle == 0) {
continue;
}
if (InstFromHandle(cii.hInstClient) != InstFromHandle(he.handle)) {
continue;
}
if (Type && TypeFromHandle(he.handle) != Type) {
continue;
}
if (Object && (he.handle != (HANDLE)Object) &&
Pointer && he.dwData != Pointer) {
continue;
}
Print(" (0x%08lx)->0x%08lx ", he.handle, he.dwData);
switch (TypeFromHandle(he.handle)) {
case HTYPE_INSTANCE:
Print("Instance\n");
if (opts & OFLAG(v)) {
Print(" next = 0x%08lx\n", cii.next);
Print(" hInstServer = 0x%08lx\n", cii.hInstServer);
Print(" hInstClient = 0x%08lx\n", cii.hInstClient);
Print(" MonitorFlags = 0x%08lx\n", cii.MonitorFlags);
Print(" hwndMother = 0x%08lx\n", cii.hwndMother);
Print(" hwndEvent = 0x%08lx\n", cii.hwndEvent);
Print(" hwndTimeout = 0x%08lx\n", cii.hwndTimeout);
Print(" afCmd = 0x%08lx\n", cii.afCmd);
Print(" pfnCallback = 0x%08lx\n", cii.pfnCallback);
Print(" LastError = 0x%08lx\n", cii.LastError);
Print(" tid = 0x%08lx\n", cii.tid);
Print(" plaNameService = 0x%08lx\n", cii.plaNameService);
Print(" cNameServiceAlloc = 0x%08lx\n", cii.cNameServiceAlloc);
SAFEWHILE (cii.cNameServiceAlloc--) {
move(ns, cii.plaNameService++);
Print(" 0x%04lx\n", ns);
}
Print(" aServerLookup = 0x%08lx\n", cii.aServerLookup);
Print(" cServerLookupAlloc = 0x%08lx\n", cii.cServerLookupAlloc);
SAFEWHILE (cii.cServerLookupAlloc--) {
move(sl, cii.aServerLookup++);
Print(" laService = 0x%04x\n", sl.laService);
Print(" laTopic = 0x%04x\n", sl.laTopic);
Print(" hwndServer = 0x%08lx\n", sl.hwndServer);
if (cii.cServerLookupAlloc) {
Print(" ---\n");
}
}
Print(" ConvStartupState = 0x%08lx\n", cii.ConvStartupState);
Print(" flags = %s\n",
GetFlags(GF_IIF, cii.flags, NULL, TRUE));
Print(" cInDDEMLCallback = 0x%08lx\n", cii.cInDDEMLCallback);
Print(" pLinkCount = 0x%08lx\n", cii.pLinkCount);
SAFEWHILE (cii.pLinkCount) {
move(lc, cii.pLinkCount);
cii.pLinkCount = lc.next;
Print(" next = 0x%08lx\n", lc.next);
Print(" laTopic = 0x%04x\n", lc.laTopic);
Print(" gaItem = 0x%04x\n", lc.gaItem);
Print(" laItem = 0x%04x\n", lc.laItem);
Print(" wFmt = 0x%04x\n", lc.wFmt);
Print(" Total = 0x%04x\n", lc.Total);
Print(" Count = 0x%04x\n", lc.Count);
if (cii.pLinkCount != NULL) {
Print(" ---\n");
}
}
}
break;
case HTYPE_ZOMBIE_CONVERSATION:
Print("Zombie Conversation\n");
if (opts & OFLAG(v)) {
DumpConvInfo((PCONV_INFO)he.dwData);
}
break;
case HTYPE_SERVER_CONVERSATION:
Print("Server Conversation\n");
if (opts & OFLAG(v)) {
DumpConvInfo((PCONV_INFO)he.dwData);
}
break;
case HTYPE_CLIENT_CONVERSATION:
Print("Client Conversation\n");
if (opts & OFLAG(v)) {
DumpConvInfo((PCONV_INFO)he.dwData);
}
break;
case HTYPE_CONVERSATION_LIST:
if (IsRemoteSession()) {
Print("!ddeml for Conversation List doesn't work on HYDRA systems\n");
} else {
Print("Conversation List\n");
if (opts & OFLAG(v)) {
move(cl, (PVOID)he.dwData);
Print(" pcl = 0x%08lx\n", he.dwData);
Print(" chwnd = 0x%08lx\n", cl.chwnd);
i = 0;
phwnd = (HWND *)&((PCONVLIST)he.dwData)->ahwnd;
SAFEWHILE (cl.chwnd--) {
move(hwnd, phwnd++);
Print(" ahwnd[%d] = 0x%08lx\n", i, hwnd);
pcci = (PCL_CONV_INFO)GetWindowLongPtr(hwnd, GWLP_PCI);
SAFEWHILE (pcci) {
move(cci, pcci);
pcci = (PCL_CONV_INFO)cci.ci.next;
Print(" hConv = 0x%08lx\n", cci.ci.hConv);
}
i++;
}
}
}
break;
case HTYPE_TRANSACTION:
Print("Transaction\n");
if (opts & OFLAG(v)) {
move(xi, (PVOID)he.dwData);
Print(" next = 0x%08lx\n", xi.next);
Print(" pcoi = 0x%08lx\n", xi.pcoi);
move(ci, xi.pcoi);
Print(" hConv = 0x%08lx\n", ci.hConv);
Print(" hUser = 0x%08lx\n", xi.hUser);
Print(" hXact = 0x%08lx\n", xi.hXact);
Print(" pfnResponse = 0x%08lx\n", xi.pfnResponse);
Print(" gaItem = 0x%04x\n", xi.gaItem);
Print(" wFmt = 0x%04x\n", xi.wFmt);
Print(" wType; = 0x%04x\n", xi.wType);
Print(" wStatus; = 0x%04x\n", xi.wStatus);
Print(" flags; = %s\n",
GetFlags(GF_XI, xi.flags, NULL, TRUE));
Print(" state; = 0x%04x\n", xi.state);
Print(" hDDESent = 0x%08lx\n", xi.hDDESent);
Print(" hDDEResult = 0x%08lx\n", xi.hDDEResult);
}
break;
case HTYPE_DATA_HANDLE:
Print("Data Handle\n");
if (opts & OFLAG(v)) {
move(dd, (PVOID)he.dwData);
Print(" hDDE = 0x%08lx\n", dd.hDDE);
Print(" flags = %s\n",
GetFlags(GF_HDATA, (WORD)dd.flags, NULL, TRUE));
}
break;
}
}
}
if (pcii != NULL) {
move(cii, pcii);
}
}
return TRUE;
}
#endif // !KERNEL
#endif // OLD_DEBUGGER
#ifdef KERNEL
/*
* Hook helper routines
*/
VOID IterateHooks(
PTR phk,
BOOL fLocalHook,
BOOL fDumpDllName)
{
int iHook;
ULONG64 offPfn;
PTR pti;
UINT flags;
int ihmod;
PTR patomTable;
PTR patomSysLoaded;
ATOM atom;
patomTable = GetGlobalPointer(VAR(UserAtomTableHandle));
patomSysLoaded = EvalExp(SYM(aatomSysLoaded));
SAFEWHILE (phk != 0) {
GetFieldValue(phk, SYM(tagHOOK), "iHook", iHook);
GetFieldValue(phk, SYM(tagHOOK), "offPfn", offPfn);
GetFieldValue(phk, SYM(tagHOOK), "flags", flags);
GetFieldValue(phk, SYM(tagHOOK), "ihmod", ihmod);
GetFieldValue(phk, SYM(tagHOOK), "head.pti", pti);
Print("\t 0x%p iHook %d, offPfn=0x%08p, ihmod=%d\n",
phk, iHook, offPfn, ihmod);
if (!fLocalHook) {
/*
* Dump the threadinfo of the hook originator.
*/
Print("\t ");
Idt(OFLAG(p), pti);
}
Print("\t flags: %s\n", GetFlags(GF_HOOKFLAGS, flags, NULL, TRUE));
if (ihmod >= 0 && patomTable != NULL_PTR) {
/*
* Dump the hook DLL name.
*/
ReadMemory(patomSysLoaded + sizeof(ATOM) * ihmod, &atom, sizeof(ATOM), NULL);
if (fDumpDllName && atom) {
if (!DumpAtomTable(patomTable, (RTL_ATOM)atom, 12, NULL)) {
Print("%12catom: %04x (unable to get the dll name)\n", ' ', (DWORD)atom);
}
}
}
GetFieldValue(phk, SYM(tagHOOK), "phkNext", phk);
}
}
VOID DumpHooks(PTR pDeskInfo, LPSTR psz, int i, BOOL fDumpDllName)
{
PTR phk = GetArrayElementPtr(pDeskInfo, SYM(tagDESKTOPINFO), "aphkStart", i + 1);
if (phk) {
Print("\t %s\n", psz);
IterateHooks(phk, FALSE, fDumpDllName);
}
}
VOID DumpLHooks(PTR pti, LPSTR psz, int i, BOOL fDumpDllName)
{
PTR phk = GetArrayElementPtr(pti, SYM(tagTHREADINFO), "aphkStart", i + 1);
if (phk) {
Print("\t %s\n", psz);
IterateHooks(phk, TRUE, fDumpDllName);
}
}
/***************************************************************************\
* ddesk - dumps list of desktops
* ddesk address - dumps simple statistics for desktop
* ddesk v address - dumps verbose statistics for desktop
* ddesk h address - dumps statistics for desktop plus handle list
*
* Dump handle table statistics.
*
* 02/21/1992 ScottLu Created.
* 06/09/1995 SanfordS Made to fit stdexts motif.
* 10/15/2000 Hiroyama Ported to ia64.
\***************************************************************************/
BOOL Iddesk(
DWORD opts,
ULONG64 param1)
{
try {
PTR pwinsta = NULL_PTR; // PWINDOWSTATION
PTR pdesk; // PDESKTOP
PTR pHead; // OBJECT_HEADER
PTR pDeskInfo;
DWORD acHandles[TYPE_CTYPES + 1];
BOOL abTrack[TYPE_CTYPES + 1];
PTR phe; // PHE
DWORD i;
WCHAR ach[80];
BOOL fMatch;
ULONG offsetPHead; // to reduce the symbol lookup
ULONG offsetBType;
ULONG offsetBFlags;
BYTE bType;
BOOL fDumpDllName = opts & OFLAG(d);
/*
* If there is no address, list all desktops on all terminals.
*/
if (param1 == NULL_PTR) {
FOREACHWINDOWSTATION(pwinsta)
GetObjectName(pwinsta, ach, ARRAY_SIZE(ach));
Print("Windowstation: @ 0x%p %ws\n", pwinsta, ach);
Print("Other desktops:\n");
GetFieldValue(pwinsta, SYM(tagWINDOWSTATION), "rpdeskList", pdesk);
SAFEWHILE (pdesk) {
Print(" Desktop at 0x%p\n", pdesk);
Iddesk(opts & (OFLAG(v) | OFLAG(h) | OFLAG(d)), pdesk);
GetFieldValue(pdesk, SYM(tagDESKTOP), "rpdeskNext", pdesk);
}
Print("\n");
NEXTEACHWINDOWSTATION(pwinsta)
return TRUE;
}
pdesk = param1;
GetObjectName(pdesk, ach, ARRAY_SIZE(ach));
Print(" Name: %ws\n", ach);
pHead = KD_OBJECT_TO_OBJECT_HEADER(pdesk);
if (pHead == NULL_PTR) {
Print("can't get pHeader\n");
return TRUE;
}
/*
* Dump Header info
*/
_InitTypeRead(pHead, "nt!_OBJECT_HEADER");
Print(" # Opens = %d\n", ReadField(HandleCount));
/*
* Dump some key info
*/
_InitTypeRead(pdesk, SYM(tagDESKTOP));
Print(" dwFlags = %s\n", GetFlags(GF_DESKTOPFLAGS, (DWORD)ReadField(dwDTFlags), NULL, TRUE));
Print(" Heap = %#p\n", ReadField(pheapDesktop));
Print(" Windowstation = %#p\n", ReadField(rpwinstaParent));
Print(" Message pwnd = %#p\n", ReadField(spwndMessage));
Print(" System pmenu = %#p\n", ReadField(spmenuSys));
Print(" Console thread = 0x%x\n", ReadField(dwConsoleThreadId));
Print(" PtiList.Flink = %#p\n", ReadField(PtiList.Flink));
/*
* Dump DESKTOPINFO
*/
pDeskInfo = ReadField(pDeskInfo);
_InitTypeRead(pDeskInfo, SYM(tagDESKTOPINFO));
Print(" Desktop pwnd = %#p\n", ReadField(spwnd));
Print("\tfsHooks = 0x%08lx\n", ReadField(fsHooks));
DumpHooks(pDeskInfo, "WH_MSGFILTER", WH_MSGFILTER, fDumpDllName);
DumpHooks(pDeskInfo, "WH_JOURNALRECORD", WH_JOURNALRECORD, fDumpDllName);
DumpHooks(pDeskInfo, "WH_JOURNALPLAYBACK", WH_JOURNALPLAYBACK, fDumpDllName);
DumpHooks(pDeskInfo, "WH_KEYBOARD", WH_KEYBOARD, fDumpDllName);
DumpHooks(pDeskInfo, "WH_GETMESSAGE", WH_GETMESSAGE, fDumpDllName);
DumpHooks(pDeskInfo, "WH_CALLWNDPROC", WH_CALLWNDPROC, fDumpDllName);
DumpHooks(pDeskInfo, "WH_CALLWNDPROCRET", WH_CALLWNDPROCRET, fDumpDllName);
DumpHooks(pDeskInfo, "WH_CBT", WH_CBT, fDumpDllName);
DumpHooks(pDeskInfo, "WH_SYSMSGFILTER", WH_SYSMSGFILTER, fDumpDllName);
DumpHooks(pDeskInfo, "WH_MOUSE", WH_MOUSE, fDumpDllName);
DumpHooks(pDeskInfo, "WH_HARDWARE", WH_HARDWARE, fDumpDllName);
DumpHooks(pDeskInfo, "WH_DEBUG", WH_DEBUG, fDumpDllName);
DumpHooks(pDeskInfo, "WH_SHELL", WH_SHELL, fDumpDllName);
DumpHooks(pDeskInfo, "WH_FOREGROUNDIDLE", WH_FOREGROUNDIDLE, fDumpDllName);
DumpHooks(pDeskInfo, "WH_KEYBOARD_LL", WH_KEYBOARD_LL, fDumpDllName);
DumpHooks(pDeskInfo, "WH_MOUSE_LL", WH_MOUSE_LL, fDumpDllName);
if (opts & OFLAG(h)) {
/*
* Find all objects allocated from the desktop.
*/
for (i = 0; i < ARRAY_SIZE(acHandles); i++) {
abTrack[i] = FALSE;
acHandles[i] = 0;
}
abTrack[TYPE_WINDOW] = abTrack[TYPE_MENU] =
abTrack[TYPE_CALLPROC] =
abTrack[TYPE_HOOK] = TRUE;
if (opts & OFLAG(v)) {
Print("Handle Type\n");
Print("--------------------\n");
}
GetFieldOffset(SYM(HANDLEENTRY), "phead", &offsetPHead);
DEBUGPRINT("offsetPHead=%x\n", offsetPHead);
GetFieldOffset(SYM(HANDLEENTRY), "bType", &offsetBType);
DEBUGPRINT("offsetBType=%x\n", offsetBType);
GetFieldOffset(SYM(HANDLEENTRY), "bFlags", &offsetBFlags);
FOREACHHANDLEENTRY(phe, i)
fMatch = FALSE;
if ((i & 0x3) == 0) {
ShowProgress();
}
move(bType, phe + offsetBType);
if (bType >= TYPE_CTYPES) {
bType = TYPE_CTYPES; // unknown;
}
try {
PTR phead;
PTR rpdesk = NULL_PTR;
switch (bType) {
case TYPE_WINDOW:
{
static ULONG offset = 0;
ReadPointer(phe + offsetPHead, &phead);
if (offset == 0) {
GetFieldOffset(SYM(WND), "head.rpdesk", &offset);
DEBUGPRINT("offset=%x\n", offset);
}
ReadPointer(phead + offset, &rpdesk);
DEBUGPRINT("rpdesk=0x%p @ 0x%p phead=0x%p ", rpdesk, phead + offset, phead);
}
break;
case TYPE_MENU:
{
static ULONG offset = 0;
ReadPointer(phe + offsetPHead, &phead);
if (offset == 0) {
GetFieldOffset(SYM(tagMENU), "head.rpdesk", &offset);
}
ReadPointer(phead + offset, &rpdesk);
}
break;
case TYPE_CALLPROC:
{
static ULONG offset = 0;
ReadPointer(phe + offsetPHead, &phead);
if (offset == 0) {
GetFieldOffset(SYM(CALLPROCDATA), "head.rpdesk", &offset);
}
ReadPointer(phead + offset, &rpdesk);
}
break;
case TYPE_HOOK:
{
static ULONG offset = 0;
ReadPointer(phe + offsetPHead, &phead);
if (offset == 0) {
GetFieldOffset(SYM(tagHOOK), "head.rpdesk", &offset);
}
ReadPointer(phead + offset, &rpdesk);
}
break;
#if defined(GI_PROCESSOR) && defined(TYPE_RAWINPUT_PROCESSOR)
case TYPE_RAWINPUT_PROCESSOR:
{
static ULONG offset = 0;
ReadPointer(phe + offsetPHead, &phead);
if (offset == 0) {
GetFieldOffset(SYM(tagRAWINPUT_PROCESSOR), "head.rpdesk", &offset);
}
ReadPointer(phead + offset, &rpdesk);
}
break;
#endif
default:
break;
}
if (rpdesk == pdesk) {
fMatch = TRUE;
if (bType == TYPE_WINDOW) {
DEBUGPRINT("matched\n");
}
} else if (bType == TYPE_WINDOW) {
DEBUGPRINT("unmatched\n");
}
} except (CONTINUE) {
Print("Exception!\n");
}
if (!fMatch) {
continue;
}
acHandles[bType]++;
if (opts & OFLAG(v)) {
BYTE bFlags;
move(bFlags, phe + offsetBFlags);
Print("\r0x%08lx %c %s\n",
i,
(bFlags & HANDLEF_DESTROY) ? '*' : ' ',
aszTypeNames[bType]);
}
NEXTEACHHANDLEENTRY()
Print("\r");
if (!(opts & OFLAG(v))) {
Print(" \n");
Print("Count Type\n");
Print("--------------------\n");
for (i = 0; i < ARRAY_SIZE(acHandles); i++) {
if (abTrack[i])
Print("0x%08lx %s\n", acHandles[i], aszTypeNames[i]);
}
}
}
} except (CONTINUE) {
Print("AV!\n");
}
Print(" \n");
return TRUE;
}
#endif // KERNEL
BOOL IsNumChar(int c, int base)
{
return ('0' <= c && c <= '9') ||
(base == 16 && (('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')));
}
NTSTATUS GetInteger(
LPSTR psz,
int base,
int *pi,
LPSTR *ppsz)
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
for (;;) {
if (IsNumChar(*psz, base)) {
Status = RtlCharToInteger(psz, base, pi);
if (ppsz && NT_SUCCESS(Status)) {
while (IsNumChar(*psz++, base)) {
/* do nothing */;
}
*ppsz = psz;
}
break;
}
if (*psz != ' ' && *psz != '\t') {
break;
}
psz++;
}
return Status;
}
typedef VOID (*PFNSETRIPFLAGS)(DWORD);
typedef DWORD (*PFNGETRIPFLAGS)(VOID);
typedef DWORD (*PFNGETRIPPID)(VOID);
BOOL Idf(DWORD opts, LPSTR pszName)
{
static char *szLevels[8] = {
"<none>",
"Errors",
"Warnings",
"Errors and Warnings",
"Verbose",
"Errors and Verbose",
"Warnings and Verbose",
"Errors, Warnings, and Verbose"
};
#ifndef KERNEL
PFNSETRIPFLAGS lpfnSetRipFlags;
static PFNGETRIPFLAGS lpfnGetRipFlags = NULL;
HMODULE hMod;
#endif
NTSTATUS Status;
ULONG ulFlags;
ULONG64 psi;
DWORD dwRipFlags = 0;
ULONG offsetRIPFlags;
if (opts & OFLAG(x)) {
/*
* !df -x foo
* This is an undocumented way to start a remote CMD session named
* "foo" on the machine that the debugger is running on.
* Sometimes useful to assist in debugging.
* Sometimes useful when trying to do dev work from home: if you don't
* already have a remote cmd.exe session to connect to, you probably
* have a remote debug session. You can use this debug extension to
* start a remote cmd session.
*/
BOOL bRet;
char ach[80];
PROCESS_INFORMATION ProcessInfo;
STARTUPINFOA StartupInfoA;
if (pszName[0] == '\0') {
Print("must provide a name. eg; \"!df -x fred\"\n");
return TRUE;
}
sprintf(ach, "remote.exe /s cmd.exe %s", pszName);
RtlZeroMemory(&StartupInfoA, sizeof(STARTUPINFOA));
StartupInfoA.cb = sizeof(STARTUPINFOA);
StartupInfoA.lpTitle = pszName;
StartupInfoA.dwFlags = STARTF_USESHOWWINDOW;
StartupInfoA.wShowWindow = SW_SHOWMINIMIZED; // SW_HIDE is *too* sneaky
bRet = CreateProcessA(NULL,
ach,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&StartupInfoA,
&ProcessInfo);
if (bRet) {
Print("Successfully created a minimized remote cmd process\n");
Print("use \"remote /c <machine> %s\" to connect\n", pszName);
Print("use \"exit\" to kill the remote cmd process\n");
}
NtClose(ProcessInfo.hProcess);
NtClose(ProcessInfo.hThread);
return TRUE;
}
psi = GetGlobalPointer(VAR(gpsi));
GetFieldOffset(SYM(SERVERINFO), "dwRIPFlags", &offsetRIPFlags);
#if 0
/*
* If !df is run against a fre system, neither of these fields will
* be present in the SERVERINFO structure, and thus the offsets will
* both be zero.
*/
if (offsetRIPFlags == 0) {
Print("!df not supported on this system.\n");
return TRUE;
}
#endif
#ifndef KERNEL
hMod = GetModuleHandle(L"user32.dll");
if (opts & OFLAG(p)) {
lpfnSetRipFlags = (PFNSETRIPFLAGS)GetProcAddress(hMod,
"PrivateSetRipFlags");
} else {
lpfnSetRipFlags = (PFNSETRIPFLAGS)GetProcAddress(hMod,
"SetRipFlags");
}
if (lpfnSetRipFlags == NULL) {
Print("Error getting address for %sSetRipFlags export: 0x%x\n",
(opts & OFLAG(p)) ? "Private" : "",
GetLastError());
return TRUE;
}
if (lpfnGetRipFlags == NULL) {
lpfnGetRipFlags = (PFNGETRIPFLAGS)GetProcAddress(hMod, "GetRipFlags");
if (lpfnGetRipFlags == NULL) {
Print("Error getting address for GetRipFlags export: 0x%x\n",
GetLastError());
return TRUE;
}
}
#endif
#ifdef KERNEL
move(dwRipFlags, psi + offsetRIPFlags);
#else
dwRipFlags = (*lpfnGetRipFlags)();
#endif
Status = GetInteger(pszName, 16, &ulFlags, NULL);
if (NT_SUCCESS(Status) && !(ulFlags & ~RIPF_VALIDUSERFLAGS)) {
#ifdef KERNEL
dwRipFlags = (dwRipFlags & ~RIPF_VALIDUSERFLAGS) | ulFlags;
(lpExtensionApis->lpWriteProcessMemoryRoutine)(psi + offsetRIPFlags,
(PVOID)&dwRipFlags,
sizeof(dwRipFlags),
NULL);
move(dwRipFlags, psi + offsetRIPFlags);
#else
(*lpfnSetRipFlags)(ulFlags);
dwRipFlags = (*lpfnGetRipFlags)();
#endif
}
Print("Flags = %.3x\n", dwRipFlags & RIPF_VALIDUSERFLAGS);
Print(" Print Process/Component %sabled\n", (dwRipFlags & RIPF_HIDEPID) ? "dis" : "en");
Print(" Print File/Line %sabled\n", (dwRipFlags & RIPF_PRINTFILELINE) ? "en" : "dis");
Print(" Print on %s\n", szLevels[(dwRipFlags & RIPF_PRINT_MASK) >> RIPF_PRINT_SHIFT]);
Print(" Prompt on %s\n", szLevels[(dwRipFlags & RIPF_PROMPT_MASK) >> RIPF_PROMPT_SHIFT]);
if (opts & OFLAG(p)) {
Print(" RIPs shown for process %ld (0x%lX)\n",
HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess),
HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess));
} else {
Print(" All process RIPs are shown\n");
}
return TRUE;
}
#ifdef KERNEL
VOID DumpHotkeyWorker(
ULONG64 phk,
BOOL bRecursive)
{
WORD fsModifiers;
UINT vk;
PTR pwnd;
PTR pti;
int id;
SAFEWHILE (phk != 0) {
Print("photkey @ 0x%p\n", phk);
GetFieldValue(phk, SYM(HOTKEY), "vk", vk);
GetFieldValue(phk, SYM(HOTKEY), "fsModifiers", fsModifiers);
Print(" fsModifiers %lx, vk %x - ", fsModifiers, vk);
Print("%s%s%s%sVK:%x %s",
fsModifiers & MOD_SHIFT ? "Shift + " : "",
fsModifiers & MOD_ALT ? "Alt + " : "",
fsModifiers & MOD_CONTROL ? "Ctrl + " : "",
fsModifiers & MOD_WIN ? "Win + " : "",
vk,
GetVKeyName(vk));
GetFieldValue(phk, SYM(HOTKEY), "id", id);
GetFieldValue(phk, SYM(HOTKEY), "pti", pti);
GetFieldValue(phk, SYM(HOTKEY), "spwnd", pwnd);
Print("\n id %x\n", id);
Print(" pti %lx\n", pti);
Print(" pwnd %lx = ", pwnd);
if (pwnd == (PTR)PWND_FOCUS) {
Print("PWND_FOCUS\n");
} else if (pwnd == (PTR)PWND_INPUTOWNER) {
Print("PWND_INPUTOWNER\n");
} else {
CHAR ach[80];
/*
* Print title string.
*/
DebugGetWindowTextA(pwnd, ach, ARRAY_SIZE(ach));
Print("\"%s\"\n", ach);
}
Print("\n");
if (bRecursive) {
GetFieldValue(phk, SYM(HOTKEY), "phkNext", phk);
} else {
break;
}
}
}
/***************************************************************************\
* dhot - dump hotkeys
*
* dhot - dumps all hotkeys
*
* 10/21/1994 IanJa Created.
* 06/09/1995 SanfordS Made to fit stdexts motif.
* 08/15/2002 JasonSch Modified to use new hotkey hash table.
\***************************************************************************/
BOOL Idhot(
DWORD opts,
ULONG64 phk)
{
if (!phk) {
DWORD dwPointerSize = GetTypeSize("PVOID");
int i = 0;
ULONG64 pwnd, pti, phkT;
phk = EvalExp(VAR(gphkHashTable));
for (; i < 128; ++i) {
ReadPointer(phk, &phkT);
GetFieldValue(phkT, SYM(HOTKEY), "pti", pti);
GetFieldValue(phkT, SYM(HOTKEY), "spwnd", pwnd);
if (pti != 0 || pwnd != 0) {
DumpHotkeyWorker(phkT, TRUE);
}
phk += dwPointerSize;
}
} else {
DumpHotkeyWorker(phk, !!(opts & OFLAG(r)));
}
return TRUE;
}
ULONG dhkCallback(
ULONG64 pti,
PVOID pData)
{
UNREFERENCED_PARAMETER(pData);
Idhk(OFLAG(r), pti);
return FALSE;
}
/***************************************************************************\
* dhk - dump hooks
*
* dhk - dumps local hooks on the foreground thread
* dhk g - dumps global hooks
* dhk address - dumps local hooks on THREADINFO at address
* dhk g address - dumps global hooks and local hooks on THREADINFO at address
* dhk * - dumps local hooks for all threads
* dhk g * - dumps global hooks and local hooks for all threads
*
* 10/21/94 IanJa Created.
* 6/9/1995 SanfordS made to fit stdexts motif
\***************************************************************************/
BOOL Idhk(
DWORD opts,
ULONG64 param1)
{
DWORD dwFlags;
PTR pti;
PTR pq = NULL_PTR;
BOOL fDumpDllName = opts & OFLAG(d);
static PTR gptiHkForeground;
#define DHKF_GLOBAL_HOOKS 1
#define DHKF_PTI_GIVEN 2
dwFlags = 0;
pti = NULL_PTR;
if (opts & OFLAG(g)) { // global hooks
dwFlags |= DHKF_GLOBAL_HOOKS;
}
if ((opts & OFLAG(r)) == 0) { // -r cannot be specified from the command line
// first time sets gptiHkForeground
pq = GetGlobalPointer(VAR(gpqForeground));
if (pq) {
GetFieldValue(pq, SYM(tagQ), "ptiKeyboard", gptiHkForeground);
} else {
// Happens during winlogon
gptiHkForeground = NULL_PTR;
}
}
if (param1 == 0) { // n.b. call from dhkCallback should always set param1
if (opts & OFLAG(c)) {
// !dhk -c: Use the current thread.
pti = GetGlobalPointer(VAR(gptiCurrent));
} else if (pq == NULL_PTR) {
// Happens during winlogon
Print("No foreground queue!\n");
return TRUE;
} else {
pti = gptiHkForeground;
}
} else {
dwFlags |= DHKF_PTI_GIVEN;
pti = param1;
}
if ((dwFlags & DHKF_PTI_GIVEN || !(dwFlags & DHKF_GLOBAL_HOOKS)) && (opts & OFLAG(a)) == 0) {
DWORD fsHooks;
GetFieldValue(pti, SYM(tagTHREADINFO), "fsHooks", fsHooks);
if (fsHooks || (opts & OFLAG(r)) == 0) {
Print("Local hooks on PTHREADINFO @ 0x%p%s:\n", pti,
pti == gptiHkForeground ? " (foreground thread)" : "");
Idt(OFLAG(p), pti);
DumpLHooks(pti, "WH_MSGFILTER", WH_MSGFILTER, fDumpDllName);
DumpLHooks(pti, "WH_JOURNALRECORD", WH_JOURNALRECORD, fDumpDllName);
DumpLHooks(pti, "WH_JOURNALPLAYBACK", WH_JOURNALPLAYBACK, fDumpDllName);
DumpLHooks(pti, "WH_KEYBOARD", WH_KEYBOARD, fDumpDllName);
DumpLHooks(pti, "WH_GETMESSAGE", WH_GETMESSAGE, fDumpDllName);
DumpLHooks(pti, "WH_CALLWNDPROC", WH_CALLWNDPROC, fDumpDllName);
DumpLHooks(pti, "WH_CALLWNDPROCRET", WH_CALLWNDPROCRET, fDumpDllName);
DumpLHooks(pti, "WH_CBT", WH_CBT, fDumpDllName);
DumpLHooks(pti, "WH_SYSMSGFILTER", WH_SYSMSGFILTER, fDumpDllName);
DumpLHooks(pti, "WH_MOUSE", WH_MOUSE, fDumpDllName);
DumpLHooks(pti, "WH_HARDWARE", WH_HARDWARE, fDumpDllName);
DumpLHooks(pti, "WH_DEBUG", WH_DEBUG, fDumpDllName);
DumpLHooks(pti, "WH_SHELL", WH_SHELL, fDumpDllName);
DumpLHooks(pti, "WH_FOREGROUNDIDLE", WH_FOREGROUNDIDLE, fDumpDllName);
DumpLHooks(pti, "WH_KEYBOARD_LL", WH_KEYBOARD_LL, fDumpDllName);
DumpLHooks(pti, "WH_MOUSE_LL", WH_MOUSE_LL, fDumpDllName);
}
}
if (dwFlags & DHKF_GLOBAL_HOOKS) {
PTR pDeskInfo;
PTR rpdesk;
DWORD fsHooks;
GetFieldValue(pti, SYM(tagTHREADINFO), "pDeskInfo", pDeskInfo);
GetFieldValue(pti, SYM(tagTHREADINFO), "rpdesk", rpdesk);
GetFieldValue(pDeskInfo, SYM(DESKTOPINFO), "fsHooks", fsHooks);
Print("Global hooks for Desktop @ 0x%p:\n", rpdesk);
Print("\tfsHooks 0x%08lx\n", fsHooks);
DumpHooks(pDeskInfo, "WH_MSGFILTER", WH_MSGFILTER, fDumpDllName);
DumpHooks(pDeskInfo, "WH_JOURNALRECORD", WH_JOURNALRECORD, fDumpDllName);
DumpHooks(pDeskInfo, "WH_JOURNALPLAYBACK", WH_JOURNALPLAYBACK, fDumpDllName);
DumpHooks(pDeskInfo, "WH_KEYBOARD", WH_KEYBOARD, fDumpDllName);
DumpHooks(pDeskInfo, "WH_GETMESSAGE", WH_GETMESSAGE, fDumpDllName);
DumpHooks(pDeskInfo, "WH_CALLWNDPROC", WH_CALLWNDPROC, fDumpDllName);
DumpHooks(pDeskInfo, "WH_CALLWNDPROCRET", WH_CALLWNDPROCRET, fDumpDllName);
DumpHooks(pDeskInfo, "WH_CBT", WH_CBT, fDumpDllName);
DumpHooks(pDeskInfo, "WH_SYSMSGFILTER", WH_SYSMSGFILTER, fDumpDllName);
DumpHooks(pDeskInfo, "WH_MOUSE", WH_MOUSE, fDumpDllName);
DumpHooks(pDeskInfo, "WH_HARDWARE", WH_HARDWARE, fDumpDllName);
DumpHooks(pDeskInfo, "WH_DEBUG", WH_DEBUG, fDumpDllName);
DumpHooks(pDeskInfo, "WH_SHELL", WH_SHELL, fDumpDllName);
DumpHooks(pDeskInfo, "WH_FOREGROUNDIDLE", WH_FOREGROUNDIDLE, fDumpDllName);
DumpHooks(pDeskInfo, "WH_KEYBOARD_LL", WH_KEYBOARD_LL, fDumpDllName);
DumpHooks(pDeskInfo, "WH_MOUSE_LL", WH_MOUSE_LL, fDumpDllName);
}
if (opts & OFLAG(a)) {
ForEachPti(dhkCallback, NULL);
}
return TRUE;
}
#endif // KERNEL
typedef VOID (*PFNSETDBGTAG)(int, DWORD);
BOOL Itag(
DWORD opts,
LPSTR pszName)
{
NTSTATUS Status;
PTR psi, pdbgtag;
DWORD dwAchNameOffset, dwAchDescOffset;
char achName[DBGTAG_NAMELENGTH];
char achDesc[DBGTAG_DESCRIPTIONLENGTH];
int tag = -1;
DWORD dwDBGTAGFlags, dwDBGTAGFlagsNew, dwOffset;
DWORD dwSize;
int i, iStart, iEnd;
char szT[100];
#ifndef KERNEL
static PFNSETDBGTAG lpfnSetDbgTag = NULL;
#endif
UNREFERENCED_PARAMETER(opts);
GetFieldOffset(SYM(SERVERINFO), "adwDBGTAGFlags", &dwOffset);
/*
* Get the tag index.
*/
psi = GetGlobalPointer(VAR(gpsi));
if (!psi) {
Print("Couldn't get win32k!gpsi; bad symbols?\n");
return TRUE;
}
#ifndef KERNEL
if (lpfnSetDbgTag == NULL) {
HMODULE hMod = GetModuleHandle(L"user32.dll");
if (hMod != NULL) {
lpfnSetDbgTag = (PFNSETDBGTAG)GetProcAddress(hMod,
"SetDbgTag");
}
if (lpfnSetDbgTag == NULL) {
Print("Error getting address of SetDbgTag export (0x%x)\n",
GetLastError());
return TRUE;
}
}
#endif
Status = GetInteger(pszName, 10, &tag, &pszName);
if (*pszName != '\0' && !NT_SUCCESS(Status)) {
Print("ERROR: Dwayne, you must refer to tags by their number, not their name. How long have you been here?\n\n");
return FALSE;
}
if (!NT_SUCCESS(Status) || tag < 0 || DBGTAG_Max <= tag) {
tag = -1;
} else {
/*
* Get the flag value.
*/
Status = GetInteger(pszName, 16, &dwDBGTAGFlagsNew, NULL);
if (NT_SUCCESS(Status) && !(dwDBGTAGFlagsNew & ~DBGTAG_VALIDUSERFLAGS)) {
/*
* Set the flag value.
*/
#ifdef KERNEL
ReadMemory(psi + dwOffset + tag * sizeof(DWORD), &dwDBGTAGFlags, sizeof(DWORD), NULL);
COPY_FLAG(dwDBGTAGFlags, dwDBGTAGFlagsNew, DBGTAG_VALIDUSERFLAGS);
WriteMemory((psi + dwOffset + tag * sizeof(DWORD)), &dwDBGTAGFlags, sizeof(dwDBGTAGFlags), NULL);
#else
(*lpfnSetDbgTag)(tag, dwDBGTAGFlagsNew);
#endif
}
}
/*
* Print the header.
*/
Print( "%-5s%-7s%-*s%-*s\n",
"Tag",
"Flags",
DBGTAG_NAMELENGTH,
"Name",
DBGTAG_DESCRIPTIONLENGTH,
"Description");
for (i = 0; i < 12 + DBGTAG_NAMELENGTH + DBGTAG_DESCRIPTIONLENGTH; i++) {
szT[i] = '-';
}
szT[i++] = '\n';
szT[i] = 0;
Print(szT);
if (tag != -1) {
iStart = iEnd = tag;
} else {
iStart = 0;
GetFieldValue(psi, SYM(SERVERINFO), "dwTagCount", iEnd);
}
psi += dwOffset;
pdbgtag = EvalExp(VAR(gadbgtag));
if (!pdbgtag) {
/*
* EvalExp already complained, so just return.
*/
return TRUE;
}
GetFieldOffset(SYM(DBGTAG), "achName", &dwAchNameOffset);
GetFieldOffset(SYM(DBGTAG), "achDescription", &dwAchDescOffset);
dwSize = GetTypeSize(SYM(DBGTAG));
for (i = iStart; i <= iEnd; i++) {
ReadMemory(psi + i * sizeof(DWORD), &dwDBGTAGFlags, sizeof(DWORD), NULL);
if (pdbgtag) {
if (!ReadMemory(pdbgtag + dwAchNameOffset + i * dwSize, achName, DBGTAG_NAMELENGTH, NULL)) {
strcpy(achName, "(Not available)");
}
if (!ReadMemory(pdbgtag + dwAchDescOffset + i * dwSize, achDesc, DBGTAG_DESCRIPTIONLENGTH, NULL)) {
strcpy(achDesc, "(Not available)");
}
}
Print( "%-5d%-7d%-*s%-*s\n",
i,
dwDBGTAGFlags & DBGTAG_VALIDUSERFLAGS,
DBGTAG_NAMELENGTH,
achName,
DBGTAG_DESCRIPTIONLENGTH,
achDesc);
}
return TRUE;
}
/************************************************************************\
* Idhe
*
* Dump Handle Entry.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Idhe(
DWORD opts,
ULONG64 param1,
ULONG64 param2)
{
/* 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 */
static const char szHeader [] = "Phe Handle phead pOwner cLockObj Type Flags\n";
static const char szHeader64[] = "Phe Handle phead pOwner cLockObj Type Flags\n";
static const char szFormat [] = "%p %p %p %p %7x %-15s %#4lx\n";
int i;
UINT uHandleCount = 0;
BYTE bType, bFlags;
PTR dw, phe, pheT, pOwner, pHead, h;
DWORD cLockObj;
WORD wUniq;
#ifdef KERNEL
PTR pahti = 0, ppi;
ULONG dwHtiSize = GetTypeSize(SYM(HANDLETYPEINFO));
BOOL bObjectCreateFlags;
#endif // KERNEL
/*
* If only the owner was provided, copy it to param2 so it's always in the
* same place.
*/
if (!(opts & OFLAG(t)) && (opts & OFLAG(o))) {
param2 = param1;
}
/*
* If not a recursive call, print what we're dumping.
*/
if (!(opts & OFLAG(r)) && (opts & (OFLAG(t) | OFLAG(o) | OFLAG(p)))) {
Print("Dumping handles");
if (opts & OFLAG(t)) {
if ((UINT_PTR)param1 >= TYPE_CTYPES) {
Print("\nInvalid Type: %#lx\n", param1);
return FALSE;
}
Print(" of type %d (%s)", (ULONG)param1, aszTypeNames[(UINT_PTR)param1]);
}
if (opts & OFLAG(o)) {
Print(" owned by %p", param2);
}
if (opts & OFLAG(p)) {
Print(" or any thread on this process");
}
Print("\n");
}
#ifdef KERNEL
/*
* If dumping handles for any thread in the process, we need the type flags.
*/
if (opts & OFLAG(p)) {
pahti = EvalExp(VAR(gahti));
if (!pahti) {
Print("Couldn't get win32k!gahti\n");
return TRUE;
}
}
#endif // KERNEL
/*
* If a handle/phe was provided, just dump it.
*/
if (!(opts & ~OFLAG(r)) && param1 != 0) {
dw = HorPtoP(param1, -2);
if (dw == 0) {
Print("0x%p is not a valid object or handle.\n", param1);
return FALSE;
}
} else {
/*
* Walk the handle table
*/
Print(IsPtr64() ? szHeader64 : szHeader);
FOREACHHANDLEENTRY(phe, i)
/* Skip free handles */
GetFieldValue(phe, SYM(HANDLEENTRY), "bType", bType);
if (bType == TYPE_FREE) {
continue;
}
/* Type check */
if ((opts & OFLAG(t)) && bType != (BYTE)param1) {
continue;
}
/* thread check */
GetFieldValue(phe, SYM(HANDLEENTRY), "pOwner", pOwner);
if ((opts & OFLAG(o)) && FIXKP(pOwner) != param2) {
/* check for thread owned objects owned by the requested process */
if (opts & OFLAG(p)) {
#ifndef KERNEL
continue;
#else
GetFieldValue(pahti + bType * dwHtiSize, SYM(HANDLETYPEINFO), "bObjectCreateFlags", bObjectCreateFlags);
if (bObjectCreateFlags & OCF_PROCESSOWNED) {
continue;
}
if (!(bObjectCreateFlags & OCF_THREADOWNED)) {
continue;
}
GetFieldValue(pOwner, SYM(THREADINFO), "ppi", ppi);
if (ppi != param2) {
continue;
}
#endif // !KERNEL
} else {
continue;
}
}
GetFieldValue(phe, SYM(HANDLEENTRY), "phead", pHead);
if (pHead) {
Idhe(OFLAG(r), pHead, 0);
uHandleCount++;
}
NEXTEACHHANDLEENTRY()
Print("%d handle(s)\n", uHandleCount);
return TRUE;
}
if (!getHEfromP(&pheT, dw)) {
Print("%p is not a USER handle manager object.\n", param1);
return FALSE;
}
#ifdef KERNEL
/*
* If printing only one entry, print info about the owner
*/
if (!(opts & OFLAG(r))) {
GetFieldValue(pheT, SYM(HANDLEENTRY), "pOwner", pOwner);
if (pOwner != 0) {
if (!(opts & OFLAG(p))) {
pahti = EvalExp(VAR(gahti));
}
GetFieldValue(pheT, SYM(HANDLEENTRY), "bType", bType);
GetFieldValue(pahti + bType * dwHtiSize, SYM(HANDLETYPEINFO), "bObjectCreateFlags", bObjectCreateFlags);
if (bObjectCreateFlags & OCF_PROCESSOWNED) {
Idp(OFLAG(p), pOwner);
} else if (bObjectCreateFlags & OCF_THREADOWNED) {
Idt(OFLAG(p), pOwner);
}
}
}
#endif // KERNEL
GetFieldValue(dw, SYM(HEAD), "cLockObj", cLockObj);
GetFieldValue(dw, SYM(HEAD), "h", h);
GetFieldValue(pheT, SYM(HANDLEENTRY), "phead", pHead);
GetFieldValue(pheT, SYM(HANDLEENTRY), "pOwner", pOwner);
GetFieldValue(pheT, SYM(HANDLEENTRY), "bType", bType);
GetFieldValue(pheT, SYM(HANDLEENTRY), "bFlags", bFlags);
GetFieldValue(pheT, SYM(HANDLEENTRY), "wUniq", wUniq);
/*
* If only dumping one, use !dso like format. Otherwise, print a table.
*/
if (!(opts & OFLAG(r))) {
Print("0x%08x handle @ 0x%p\n", (DWORD)h, pheT);
Print("%4c0x%04x %-16s 0x%p %s\n",
' ', (DWORD)(WORD)wUniq, "wUniq", pOwner, "pOwner");
Print("0x%p %-16s 0x%08x cLockObj\n",
pHead, "pHead", (DWORD)cLockObj);
Print(DWSTR1 " - %s\n", bType, "bType", aszTypeNames[bType]);
Print(DWSTR1 " - %s\n", bFlags,"bFlags", GetFlags(GF_HE, bFlags, NULL, TRUE));
} else {
Print(szFormat,
pheT, h, FIXKP(pHead), FIXKP(pOwner),
cLockObj, aszTypeNames[(DWORD)bType], (DWORD)bFlags);
}
return TRUE;
}
#ifdef KERNEL
/***************************************************************************\
* dhs - dumps simple statistics for whole table
* dhs t id - dumps simple statistics for objects created by thread id
* dhs p id - dumps simple statistics for objects created by process id
* dhs v - dumps verbose statistics for whole table
* dhs v t id - dumps verbose statistics for objects created by thread id.
* dhs v p id - dumps verbose statistics for objects created by process id.
* dhs y type - just dumps that type
*
* Dump handle table statistics.
*
* 02-21-92 ScottLu Created.
* 6/9/1995 SanfordS made to fit stdexts motif
\***************************************************************************/
BOOL Idhs(
DWORD opts,
ULONG64 param1)
{
PTR phe, pOwner, pEprocess, pEThread, pahti;
DWORD dwT, acHandles[TYPE_CTYPES], dwSize, handle;
DWORD cHandlesUsed, cHandlesSkipped, idProcess, i;
BYTE bType, bObjectCreateFlags, bFlags;
int Type, cLocalHandleEntries = 0;
pahti = EvalExp(VAR(gahti));
if (!pahti) {
return TRUE;
}
dwSize = GetTypeSize(SYM(HANDLETYPEINFO));
/*
* Evaluate the argument string and get the address of the object to
* dump. Take either a handle or a pointer to the object.
*/
if (opts & OFLAG(y)) {
Type = (ULONG)(ULONG_PTR)param1;
} else if (opts & (OFLAG(t) | OFLAG(p))) {
dwT = (ULONG)(ULONG_PTR)param1;
}
cHandlesSkipped = 0;
cHandlesUsed = 0;
for (i = 0; i < TYPE_CTYPES; i++) {
acHandles[i] = 0;
}
if (param1) {
if (opts & OFLAG(p)) {
Print("Handle dump for client process id 0x%lx only:\n\n", dwT);
} else if (opts & OFLAG(t)) {
Print("Handle dump for client thread id 0x%lx only:\n\n", dwT);
} else if (opts & OFLAG(y)) {
Print("Handle dump for %s objects:\n\n", aszTypeNames[Type]);
}
} else {
Print("Handle dump for all processes and threads:\n\n");
}
if (opts & OFLAG(v)) {
Print("Handle Type\n");
Print("--------------------\n");
}
FOREACHHANDLEENTRY(phe, i)
ShowProgress();
++cLocalHandleEntries;
GetFieldValue(phe, SYM(HANDLEENTRY), "bFlags", bFlags);
GetFieldValue(phe, SYM(HANDLEENTRY), "bType", bType);
if ((opts & OFLAG(y)) && bType != Type) {
continue;
}
GetFieldValue(phe, SYM(HANDLEENTRY), "pOwner", pOwner);
GetFieldValue(pahti + bType * dwSize, SYM(HANDLETYPEINFO), "bObjectCreateFlags", bObjectCreateFlags);
if (opts & OFLAG(p)) {
if (bObjectCreateFlags & OCF_PROCESSOWNED) {
if (pOwner == 0) {
continue;
}
GetFieldValue(pOwner, SYM(PROCESSINFO), "Process", pEprocess);
GetFieldValue(pEprocess, "nt!EPROCESS", "UniqueProcessId", idProcess);
if (idProcess == 0) {
// Print("Unable to read _EPROCESS at %p\n", pEprocess);
continue;
}
if (idProcess != dwT) {
continue;
}
} else {
continue;
}
} else if (opts & OFLAG(t)) {
if (!(bObjectCreateFlags & OCF_PROCESSOWNED)) {
if (pOwner == 0) {
continue;
}
GetFieldValue(pOwner, SYM(THREADINFO), "pEThread", pEThread);
GetFieldValue(pEThread, "nt!ETHREAD", "Cid.UniqueThread", handle);
if (handle != dwT) {
continue;
}
} else {
continue;
}
}
acHandles[bType]++;
if (bType == TYPE_FREE) {
continue;
}
cHandlesUsed++;
if (opts & OFLAG(v)) {
Print("0x%08lx %c %s\n",
i,
(bFlags & HANDLEF_DESTROY) ? '*' : ' ',
aszTypeNames[bType]);
}
NEXTEACHHANDLEENTRY()
Print("\r");
if (!(opts & OFLAG(v))) {
Print("Count Type\n");
Print("--------------------\n");
for (i = 0; i < TYPE_CTYPES; i++) {
if ((opts & OFLAG(y)) && Type != (int)i) {
continue;
}
Print("0x%08lx (%d) %s\n", acHandles[i], i, aszTypeNames[i]);
}
}
if (!(opts & OFLAG(y))) {
Print("\nTotal Accessible Handles: 0x%lx\n", cLocalHandleEntries);
Print("Used Accessible Handles: 0x%lx\n", cHandlesUsed);
Print("Free Accessible Handles: 0x%lx\n", cLocalHandleEntries - cHandlesUsed);
}
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
/***************************************************************************\
* di - dumps interesting globals in USER related to input.
*
* 11-14-91 DavidPe Created.
* 6/9/1995 SanfordS made to fit stdexts motif
\***************************************************************************/
BOOL Idi(
VOID)
{
char ach[80];
PRTGPTR2(gptiCurrent, grpdeskRitInput);
PRTGPTR2(gpqForeground, gpqForegroundPrev);
PRTGPTR2(gptiForeground, gpqCursor);
PRTGPTR1(gptiBlockInput);
{
DWORD dw;
PTR ptr1;
dw = DOWNCAST(DWORD, GetGlobalMember(VAR(glinp), SYM(LASTINPUT), "timeLastInputMessage"));
ptr1 = GetGlobalMember(VAR(glinp), SYM(LASTINPUT), "ptiLastWoken");
PRTVDW2(glinp.timeLastInputMessage, dw, glinp.ptiLastWoken, ptr1);
PRTGDW1(gwMouseOwnerButton);
}
{
POINT ptCursor;
PTR psi = GetGlobalPointer(VAR(gpsi));
GetFieldValue(psi, SYM(tagSERVERINFO), "ptCursor", ptCursor);
PRTVPT(gpsi->ptCursor, ptCursor);
}
{
PTR pdesk = GetGlobalPointer(VAR(grpdeskRitInput));
if (pdesk != NULL_PTR) {
PTR pDeskInfo;
PTR spwnd;
GetFieldValue(pdesk, SYM(tagDESKTOP), "pDeskInfo", pDeskInfo);
GetFieldValue(pDeskInfo, SYM(tagDESKTOPINFO), "spwnd", spwnd);
PRTWND(Desktop window, spwnd);
}
}
{
PTR pq = GetGlobalPointer(VAR(gpqForeground));
if (pq) {
PTR spwndFocus, spwndActive;
GetFieldValue(pq, SYM(tagQ), "spwndFocus", spwndFocus);
GetFieldValue(pq, SYM(tagQ), "spwndActive", spwndActive);
PRTWND(gpqForeground->spwndFocus, spwndFocus);
PRTWND(gpqForeground->spwndActive, spwndActive);
}
}
PRTGWND(gspwndScreenCapture);
PRTGWND(gspwndInternalCapture);
PRTGWND(gspwndMouseOwner);
return TRUE;
}
#endif // KERNEL
/************************************************************************\
* Idll
*
* Dump Linked Lists.
*
* ???????? Scottlu Created
* 6/9/1995 SanfordS made to fit stdexts motif
\************************************************************************/
BOOL Idll(
DWORD opts,
LPSTR lpas)
{
static DWORD iOffset;
static DWORD cStructs;
static DWORD cDwords;
static DWORD cDwordsBack;
static ULONG64 dw, dwHalfSpeed;
ULONG64 dwT;
DWORD cBytesBack;
DWORD i, j;
BOOL fIndirectFirst;
BOOL fTestAndCountOnly = FALSE;
ULONG64 dwFind = 0;
DWORD adw[CDWORDS];
ULONG64 dwValue;
UNREFERENCED_PARAMETER(opts);
/*
* Evaluate the argument string and get the address of the object to
* dump. Take either a handle or a pointer to the object.
*/
while (*lpas == ' ') {
lpas++;
}
/*
* If there are no arguments, keep walking from the last
* pointer.
*/
if (*lpas != 0) {
/*
* If the address has a '*' in front of it, it means start with the
* pointer stored at that address.
*/
fIndirectFirst = FALSE;
if (*lpas == '*') {
lpas++;
fIndirectFirst = TRUE;
}
/*
* Scan past the address.
*/
dw = dwValue = GetExpression(lpas);
if (fIndirectFirst) {
ReadPointer(dw, &dw);
}
dwHalfSpeed = dw;
cStructs = 25;
cDwords = 8;
iOffset = cDwordsBack = 0;
SAFEWHILE (TRUE) {
while (*lpas == ' ') {
lpas++;
}
switch(*lpas) {
case 'l':
/*
* length of each structure.
*/
lpas++;
cDwords = (DWORD)(DWORD_PTR)GetExpression(lpas);
if (cDwords > CDWORDS) {
Print("\nl%d? - %d DWORDs maximum\n\n", cDwords, CDWORDS);
cDwords = CDWORDS;
}
break;
case 'b':
/*
* Go back cDwordsBack and dump cDwords from there
* (useful for LIST_ENTRYs, where Flink doesn't point to
* the start of the struct). cDwordsBack can be negative,
* to allow people to start dumping from a certain offset
* within the structure.
*/
lpas++;
cDwordsBack = (DWORD)(DWORD_PTR)GetExpression(lpas);
if (cDwordsBack >= CDWORDS) {
Print("\nb%d? - %d DWORDs maximum\n\n", cDwordsBack, CDWORDS - 1);
cDwordsBack = CDWORDS - 1;
}
break;
case 'o':
/*
* Offset of 'next' pointer.
*/
lpas++;
iOffset = (DWORD)(DWORD_PTR)GetExpression(lpas);
break;
case 'c':
/*
* Count of structures to dump
*/
lpas++;
cStructs = (DWORD)(DWORD_PTR)GetExpression(lpas);
break;
case 'f':
/*
* Find element at given address
*/
lpas++;
dwFind = EvalExp(lpas);
break;
case 't':
/*
* Test list for loop, and count
*/
fTestAndCountOnly = TRUE;
cStructs = 0x100000;
default:
break;
}
while (*lpas && *lpas != ' ')
lpas++;
if (*lpas == 0)
break;
}
if (cDwordsBack > cDwords) {
Print("backing up %d DWORDS per struct (b%d): ",
cDwordsBack, cDwordsBack);
Print("increasing l%d to l%d so next link is included\n",
cDwords, cDwordsBack + 1);
cDwords = cDwordsBack + 1;
}
for (i = 0; i < CDWORDS; i++) {
adw[i] = 0;
}
}
cBytesBack = cDwordsBack * sizeof(DWORD);
for (i = 0; i < cStructs; i++) {
moveBlock(adw, (dw - cBytesBack), sizeof(DWORD) * cDwords);
if (!fTestAndCountOnly) {
Print("---- 0x%lx:\n", i);
for (j = 0; j < cDwords; j += 4) {
switch (cDwords - j) {
case 1:
Print("%p: %08lx\n",
dw + j * sizeof(DWORD),
adw[j + 0]);
break;
case 2:
Print("%p: %08lx %08lx\n",
dw + j * sizeof(DWORD),
adw[j + 0], adw[j + 1]);
break;
case 3:
Print("%p: %08lx %08lx %08lx\n",
dw + j * sizeof(DWORD),
adw[j + 0], adw[j + 1], adw[j + 2]);
break;
default:
Print("%p: %08lx %08lx %08lx %08lx\n",
dw + j * sizeof(DWORD),
adw[j + 0], adw[j + 1], adw[j + 2], adw[j + 3]);
}
}
} else if ((i & 0xff) == 0xff) {
Print("item 0x%lx at %p...\n", i+1, dw);
}
if (dwFind == dw) {
Print("====== FOUND ITEM ======\n");
break;
}
/*
* Give a chance to break out every 16 items
*/
if ((i & 0xf) == 0xf) {
if (IsCtrlCHit()) {
Print("terminated by Ctrl-C on item 0x%lx at %p...\n", i, dw);
break;
}
}
/*
* Advance to next item.
*/
dwT = dw + iOffset * sizeof(DWORD);
ReadPointer(dwT, &dw);
if (fTestAndCountOnly) {
/*
* Advance dwHalfSpeed every other time round the loop: if
* dw ever catches up to dwHalfSpeed, then we have a loop!
*/
if (i & 1) {
dwT = dwHalfSpeed + iOffset * sizeof(DWORD);
ReadPointer(dwT, &dwHalfSpeed);
}
if (dw == dwHalfSpeed) {
Print("!!! Loop Detected on item 0x%lx at %lx...\n", i, dw);
break;
}
}
if (dw == 0) {
break;
}
}
Print("---- Total 0x%lx items ----\n", i+1);
return TRUE;
}
/************************************************************************\
* Ifind
*
* Find Linked List Element
*
* 11/22/95 JimA Created.
\************************************************************************/
BOOL Ifind(
DWORD opts,
LPSTR lpas)
{
DWORD iOffset = 0;
ULONG64 dwBase, dwAddr, dwTest, dwT, dwLast = 0;
UNREFERENCED_PARAMETER(opts);
/*
* Evaluate the argument string and get the address of the object to
* dump. Take either a handle or a pointer to the object.
*/
while (*lpas == ' ') {
lpas++;
}
/*
* If there are no arguments, keep walking from the last
* pointer.
*/
if (*lpas != 0) {
/*
* Scan past the addresses.
*/
dwBase = EvalExp(lpas);
while (*lpas && *lpas != ' ') {
lpas++;
}
dwAddr = EvalExp(lpas);
while (*lpas && *lpas != ' ') {
lpas++;
}
iOffset = 0;
SAFEWHILE (*lpas != 0) {
while (*lpas == ' ') {
lpas++;
}
switch(*lpas) {
case 'o':
/*
* Offset of 'next' pointer.
*/
lpas++;
iOffset = (DWORD)(DWORD_PTR)EvalExp(lpas);
break;
default:
break;
}
while (*lpas && *lpas != ' ') {
lpas++;
}
}
}
dwTest = dwBase;
while (dwTest && (ULONG_PTR)dwTest != (ULONG_PTR)dwAddr) {
dwLast = dwTest;
dwT = dwTest + iOffset * sizeof(DWORD);
move(dwTest, dwT);
}
if (dwTest == 0) {
Print("Address %#p not found\n", dwAddr);
} else {
Print("Address %#p found, previous = %#p\n", dwAddr, dwLast);
}
return TRUE;
}
#ifdef KERNEL
/***************************************************************************\
* dlr handle|pointer
*
* Dumps lock list for object
*
* 02-27-92 ScottLu Created.
* 6/9/1995 SanfordS made to fit stdexts motif
\***************************************************************************/
#define LR_FLAG(x) (1 << (x))
#define LR_SIMPLELOCK 0
BOOL Idlr(
DWORD opts,
LPSTR lpszParam)
{
PTR phe;
ULONG64 param;
ULONG64 plrT;
ULONG64 pTrace;
ULONG cbPtr, cbOffset;
ULONG64 psi;
DWORD dwDBGTAGFlags, dwLockRecordFlags;
psi = GetGlobalPointer(VAR(gpsi));
if (GetFieldOffset(SYM(SERVERINFO), "adwDBGTAGFlags", &cbOffset)) {
Print("failed to get the SERVERINFO::adwDBGTAGFlags\n");
return TRUE;
}
dwDBGTAGFlags = (DWORD)GetArrayElement(psi, SYM(SERVERINFO), "adwDBGTAGFlags", DBGTAG_TrackLocks, "DWORD");
dwDBGTAGFlags &= DBGTAG_VALIDUSERFLAGS;
moveExpValue(&dwLockRecordFlags, VAR(gdwLockRecordFlags));
if (opts & (OFLAG(s) | OFLAG(c))) {
DWORD flag;
if (!NT_SUCCESS(GetInteger(lpszParam, 0x10, &flag, NULL))) {
Print("Invalid arg: '%s'\n", lpszParam);
return FALSE;
}
if (opts & OFLAG(s)) {
dwLockRecordFlags |= LR_FLAG(flag);
} else {
dwLockRecordFlags &= ~LR_FLAG(flag);
}
Print("7\n");
WriteMemory(EvalExp(VAR(gdwLockRecordFlags)), &dwLockRecordFlags, sizeof dwLockRecordFlags, NULL);
Print("8\n");
// for to display it
opts |= OFLAG(l);
}
if (opts & OFLAG(l)) {
#define HT(type) { type, #type }
static const struct {
DWORD dwType;
char* lpszName;
} flags[] = {
//{ LR_SIMPLELOCK, "Rec SimpleLock" },
{ LR_SIMPLELOCK, "Reserved" },
HT(TYPE_WINDOW),
HT(TYPE_MENU),
HT(TYPE_CURSOR),
HT(TYPE_SETWINDOWPOS),
HT(TYPE_HOOK),
HT(TYPE_CLIPDATA),
HT(TYPE_CALLPROC),
HT(TYPE_ACCELTABLE),
HT(TYPE_DDEACCESS),
HT(TYPE_DDECONV),
HT(TYPE_DDEXACT),
HT(TYPE_MONITOR),
HT(TYPE_KBDLAYOUT),
HT(TYPE_KBDFILE),
HT(TYPE_WINEVENTHOOK),
HT(TYPE_TIMER),
HT(TYPE_INPUTCONTEXT),
HT(TYPE_HIDDATA),
HT(TYPE_DEVICEINFO),
};
#undef HT
UINT i;
Print("gdwLockRecordFlags: %08x\n", dwLockRecordFlags);
for (i = 0; i < ARRAY_SIZE(flags); ++i) {
char prefix = ' ';
if (dwLockRecordFlags & LR_FLAG(flags[i].dwType)) {
prefix = '*';
}
Print(" %02x %c%-18s", (DWORD)flags[i].dwType, prefix, flags[i].lpszName);
if ((i + 1) % 3 == 0) {
Print("\n");
}
}
Print("\n");
return TRUE;
}
if (*lpszParam == '\0') {
Print("no arg!!\n");
return FALSE;
}
param = EvalExp(lpszParam);
if (!GetAndDumpHE(param, &phe, FALSE)) {
Print("!dlr: GetAndDumpHE failed\n");
return FALSE;
}
/*
* We have the handle entry: 'he' is filled in. Now dump the lock
* records. Remember the 1st record is the last transaction!
*/
GetFieldValue(phe, SYM(HANDLEENTRY), "plr", plrT);
if (plrT != 0) {
Print("phe %p Dumping the lock records\n"
"----------------------------------------------\n"
"address cLock\n"
"----------------------------------------------\n", phe);
}
SAFEWHILE (plrT != 0) {
ULONG64 dw;
int i;
char ach[80];
_InitTypeRead(plrT, SYM(LOCKRECORD));
Print("%p %08d\n", ReadField(ppobj), ReadField(cLockObj));
GetFieldOffset(SYM(LOCKRECORD), "trace", &cbOffset);
cbPtr = GetTypeSize("PVOID");
for (i = 0; i < LOCKRECORD_STACK; i++) {
ReadPointer(plrT + cbOffset + i * cbPtr, &pTrace);
GetSym(pTrace, ach, &dw);
Print(" %s", ach);
if (dw != 0) {
Print("+0x%x", dw);
}
Print("\n");
}
plrT = ReadField(plrNext);
}
return TRUE;
}
#endif
VOID DumpMenu(
UINT uIndent,
DWORD opts,
PTR pMenu)
{
DWORD fFlags, cxMenu, cyMenu, dwContextHelpId, cch, dwSize;
UINT cAlloced, cItems, i;
INT iItem;
WCHAR szBufW[128];
char szIndent[256];
ULONG dwOffset;
PTR pwnd, pitem;
/*
* Compute our indent
*/
for (i = 0; i < uIndent; szIndent[i++] = ' ')
/* do nothing */;
szIndent[i] = '\0';
dwSize = GetTypeSize("ITEM");
/*
* Print the menu header
*/
if (!(opts & OFLAG(v))) {
Print("0x%p %s", pMenu, szIndent);
} else {
Print("%sPMENU @ 0x%p:\n", szIndent, pMenu);
}
/*
* Try and get the menu
*/
if (_InitTypeRead(pMenu, SYM(MENU))) {
Print("Couldn't read PMENU at %p\n", pMenu);
return;
}
/*
* Print the information for this menu
*/
fFlags = (DWORD)ReadField(fFlags);
cxMenu = (DWORD)ReadField(cxMenu);
cyMenu = (DWORD)ReadField(cyMenu);
dwContextHelpId = (DWORD)ReadField(dwContextHelpId);
cAlloced = (UINT)ReadField(cAlloced);
cItems = (UINT)ReadField(cItems);
iItem = (INT)ReadField(iItem);
pwnd = ReadField(spwndNotify);
if (!(opts & OFLAG(v))) {
Print("PMENU: fFlags=0x%lX, cItems=%lu, iItem=%lu, spwndNotify=0x%p\n",
fFlags, cItems, iItem, pwnd);
} else {
Print("%s fFlags............ %s\n"
"%s location.......... (%lu, %lu)\n",
szIndent, GetFlags(GF_MF, (WORD)fFlags, NULL, TRUE),
szIndent, cxMenu, cyMenu);
Print("%s spwndNotify....... 0x%p\n"
"%s dwContextHelpId... 0x%08lX\n"
"%s items............. %lu items in block of %lu\n",
szIndent, pwnd,
szIndent, dwContextHelpId,
szIndent, cItems, cAlloced);
}
GetFieldOffset(SYM(MENU), "rgItems", &dwOffset);
pitem = (ULONG_PTR)pMenu + dwOffset;
if (ReadPointer(FIXKP(pitem), &pitem)) {
i = 0;
SAFEWHILE (i < cItems) {
/*
* Get the menu item
*/
_InitTypeRead(FIXKP(pitem), SYM(ITEM));
if (!(opts & OFLAG(i))) {
/*
* Print the info for this item.
*/
if (!(opts & OFLAG(v))) {
Print("0x%p %s%lu: ID=0x%08lX hbmp=0x%p", pitem, szIndent, i, (INT)(WORD)ReadField(wID), (ULONG_PTR)ReadField(hbmp));
cch = (DWORD)ReadField(cch);
if (cch && CopyUnicodeString(pitem, SYM(ITEM), "lpstr", szBufW, (cch * sizeof(WCHAR)))) {
szBufW[cch] = 0;
Print(" %ws%\n", szBufW);
} else {
Print(", fType=%s", GetFlags(GF_MENUTYPE, (WORD)ReadField(fType), NULL, TRUE));
if (((UINT)ReadField(fType) & MF_SEPARATOR) == 0) {
Print(", lpstr=0x%p", ReadField(lpstr));
}
Print("\n");
}
} else {
Print("%s Item #%d @ 0x%p:\n", szIndent, i, pitem);
/*
* Print the details for this item.
*/
Print("%s ID........... 0x%08lX (%lu)\n"
"%s lpstr.... 0x%p",
szIndent, (WORD)ReadField(wID), (WORD)ReadField(wID),
szIndent, ReadField(lpstr));
if (cch && CopyUnicodeString(pitem, SYM(ITEM), "lpstr", szBufW, (cch*sizeof(WCHAR)))) {
szBufW[cch] = 0;
Print(" %ws%\n", szBufW);
} else {
Print("\n");
}
Print("%s fType........ %s\n"
"%s fState....... %s\n"
"%s dwItemData... 0x%p\n",
szIndent, GetFlags(GF_MENUTYPE, (WORD)ReadField(fType), NULL, TRUE),
szIndent, GetFlags(GF_MENUSTATE, (WORD)ReadField(fState), NULL, TRUE),
szIndent, (ULONG_PTR)ReadField(dwItemData));
Print("%s checks....... on=0x%p, off=0x%p\n"
"%s location..... @(0n%lu, 0n%lu) size=(0n%lu, 0n%lu)\n",
szIndent, ReadField(hbmpChecked), ReadField(hbmpUnchecked),
szIndent, (DWORD)ReadField(xItem), (DWORD)ReadField(yItem), (DWORD)ReadField(cxItem), (DWORD)ReadField(cyItem));
Print("%s underline.... x=%lu, width=%lu\n"
"%s dxTab........ %lu\n"
"%s spSubMenu.... 0x%p\n",
szIndent, (DWORD)ReadField(ulX), (DWORD)ReadField(ulWidth),
szIndent, (DWORD)ReadField(dxTab),
szIndent, ReadField(spSubMenu));
}
}
/*
* If requested, traverse through sub-menus
*/
if (opts & OFLAG(r)) {
pMenu = HorPtoP(ReadField(spSubMenu), TYPE_MENU);
if (pMenu) {
DumpMenu(uIndent + 8, opts, pMenu);
}
}
pitem += dwSize;
++i;
}
}
}
/************************************************************************\
* Idm
*
* Dumps Menu structures
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Idm(
DWORD opts,
ULONG64 param1)
{
PTR pvObject, phe;
BYTE bType;
if (param1 == 0) {
return FALSE;
}
pvObject = HorPtoP(FIXKP(param1), -1);
if (pvObject == 0) {
Print("dm: Could not convert 0x%p to an object.\n", pvObject);
return TRUE;
}
if (!getHEfromP(&phe, pvObject)) {
Print("dm: Could not get header for object 0x%p.\n", pvObject);
return TRUE;
}
GetFieldValue(phe, SYM(HANDLEENTRY), "bType", bType);
switch (bType) {
case TYPE_WINDOW:
Print("--- Dump Menu for %s object @ 0x%p ---\n", pszObjStr[bType], FIXKP(pvObject));
if (_InitTypeRead(pvObject, SYM(tagWND))) {
Print("dm: Could not read object at 0x%p.\n", pvObject);
return TRUE;
}
if (opts & OFLAG(s)) {
/*
* Display window's system menu
*/
if ((pvObject = FIXKP(ReadField(spmenuSys))) == 0) {
Print("dm: This window does not have a system menu.\n");
return TRUE;
}
} else {
if ((DWORD)ReadField(style) & WS_CHILD) {
/*
* Child windows don't have menus
*/
Print("dm: Child windows do not have menus.\n");
return TRUE;
}
if ((pvObject = FIXKP(ReadField(spmenu))) == 0) {
Print("dm: This window does not have a menu.\n");
return TRUE;
}
}
/* >>>> F A L L T H R O U G H <<<< */
case TYPE_MENU:
DumpMenu(0, opts, pvObject);
break;
default:
return FALSE;
}
return TRUE;
}
#ifdef KERNEL
/***************************************************************************\
* dmq - dump messages on queue
*
* dmq address - dumps messages in queue structure at address.
* dmq -a - dump messages for all queues
* dmq -c - count messages for all queues
*
* 11-13-91 DavidPe Created.
* 6/9/1995 SanfordS made to fit stdexts motif
* 11/05/2000 Hiroyama new 64bit clean code
\***************************************************************************/
typedef struct tagQSTAT {
DWORD dwInput, dwPosted, dwQueues, dwThreads;
DWORD opts;
} QSTAT, *PQSTAT;
/*
* PrintMessages
* N.b. resets InitTypeRead
*/
BOOL PrintMessages(PTR pqmsgRead, PTR pti)
{
ULONG64 asmsg; // ASYNCSENDMSG
char *aszEvents[] = {
"MSG", // QEVENT_MESSAGE
"SHO", // QEVENT_SHOWWINDOW"
"CMD", // QEVENT_CANCLEMODE"
"SWP", // QEVENT_SETWINDOWPOS"
"UKS", // QEVENT_UPDATEKEYSTATE"
"DEA", // QEVENT_DEACTIVATE"
"ACT", // QEVENT_ACTIVATE"
"PST", // QEVENT_POSTMESSAGE"
"EXE", // QEVENT_EXECSHELL"
"CMN", // QEVENT_CANCELMENU"
"DSW", // QEVENT_DESTROYWINDOW"
"ASY", // QEVENT_ASYNCSENDMSG"
"HNG", // QEVENT_HUNGTHREAD"
"CMT", // QEVENT_CANCELMOUSEMOVETRK"
"NWE", // QEVENT_NOTIFYWINEVENT"
"RAC", // QEVENT_RITACCESSIBILITY"
"RSO", // QEVENT_RITSOUND"
"? ", // "?"
"? ", // "?"
"? " // "?"
};
#define NQEVENT (ARRAY_SIZE(aszEvents))
#if 0
Print("typ pqmsg hwnd msg wParam lParam time ExInfo dwQEvent pti\n");
Print("-------------------------------------------------------------------------------\n");
#else
Print("typ %-*s %-*s msg %-*s %-*s time %-*s dwQEvent pti\n",
PtrWidth(), "pqmsg",
PtrWidth(), "hwnd",
PtrWidth(), "wParam",
PtrWidth(), "lParam",
PtrWidth(), "ExInfo");
Print("----------------------------------------------------------------------------------\n");
#endif
SAFEWHILE (TRUE) {
_InitTypeRead(pqmsgRead, SYM(tagQMSG));
if (ReadField(dwQEvent) < NQEVENT) {
Print("%s %p ", aszEvents[ReadField(dwQEvent)], pqmsgRead);
} else {
Print("??? %p ", pqmsgRead);
}
switch (ReadField(dwQEvent)) {
case QEVENT_ASYNCSENDMSG:
asmsg = ReadField("msg.wParam");
_InitTypeRead(asmsg, SYM(ASYNCSENDMSG));
Print("%08p %04lx %08p %08p %08lx %08p %08lx %08p %c\n",
ReadField(hwnd), (DWORD)ReadField(message), ReadField(wParam), ReadField(lParam),
(DWORD)ReadField(msg.time), ReadField(ExtraInfo), (DWORD)ReadField(dwQEvent), ReadField(pti),
pti && ReadField(pti) == pti ? '*' : ' ');
break;
case 0:
default:
Print("%08p %04lx %08p %08p %08lx %08p %08lx %08p %c\n",
ReadField(msg.hwnd), (DWORD)ReadField(msg.message), ReadField(msg.wParam), ReadField(msg.lParam),
(DWORD)ReadField(msg.time), ReadField(ExtraInfo), (DWORD)ReadField(dwQEvent), ReadField(pti),
pti && ReadField(pti) == pti ? '*' : ' ');
break;
}
_InitTypeRead(pqmsgRead, SYM(tagQMSG));
if (ReadField(pqmsgNext) != NULL_PTR) {
if (pqmsgRead == ReadField(pqmsgNext)) {
Print("<ALERT!> loop found in message list!");
return FALSE;
}
pqmsgRead = ReadField(pqmsgNext);
} else {
return TRUE;
}
}
return TRUE;
}
/*
* DumpQMsg --- dumps or counts messages in a queue
* N.b. resets InitTypeRead
* - hiroyama
*/
BOOL DumpQMsg(
PTR pq,
PQSTAT qs,
PTR pti)
{
PTR ptiTmp;
BOOL bMsgsPresent = FALSE;
_InitTypeRead(pq, SYM(tagQ));
// LATER: error handling in case pq is not accessible?
if ((qs->opts & OFLAG(c)) == 0) {
Print("Messages for queue 0x%p pti=%p\n", pq, pti);
}
if (pti) {
if (ReadField(ptiKeyboard) == pti || ReadField(ptiMouse) == pti) {
qs->dwQueues++;
}
}
if (ReadField(ptiKeyboard) != NULL_PTR) {
PTR pqmsgRead;
ptiTmp = ReadField(ptiKeyboard);
GetFieldValue(ptiTmp, SYM(tagTHREADINFO), "mlPost.pqmsgRead", pqmsgRead);
if (!(qs->opts & OFLAG(c)) && pqmsgRead) {
// If not counter only, and post messages exist, dump them all.
bMsgsPresent = TRUE;
Print("==== PostMessage queue ====\n");
PrintMessages(FIXKP(pqmsgRead), NULL_PTR);
}
} else {
Print("<ALERT!> ptiKeyboard is NULL for pq=%p!\n", pq);
}
_InitTypeRead(pq, SYM(tagQ));
if (!(qs->opts & OFLAG(c)) && ReadField(mlInput.pqmsgRead)) {
// If not counter only, and input messages exist, dump them all.
bMsgsPresent = TRUE;
Print( "==== Input queue ==========\n");
if (ReadField(mlInput.pqmsgRead) != NULL_PTR) {
PrintMessages(FIXKP(ReadField(mlInput.pqmsgRead)), pti);
}
}
_InitTypeRead(pq, SYM(tagQ));
if (qs->opts & OFLAG(c)) {
DWORD dwTimePosted;
DWORD dwTimeInput = 0;
DWORD dwOldest, dwNewest;
if (ReadField(mlInput.cMsgs)) {
qs->dwInput += (DWORD)ReadField(mlInput.cMsgs);
GetFieldValue(ReadField(mlInput.pqmsgRead), SYM(tagQMSG), "msg.time", dwOldest);
GetFieldValue(ReadField(mlInput.pqmsgWriteLast), SYM(tagQMSG), "msg.time", dwNewest);
dwTimeInput = dwNewest - dwOldest;
}
Print("%08p%c %8x %8x\t%08p",
pq,
((ReadField(ptiKeyboard) != pti) && (ReadField(ptiMouse) != pti)) ? '*' : ' ',
(DWORD)ReadField(mlInput.cMsgs), dwTimeInput,
ReadField(ptiKeyboard));
//
// it would be good to print the ptiStatic too, maybe like this:
// e1b978a8 0 0 e1ba3368 0 0
// e1b9aca8* 0 0 e1b8b2e8 0 0
// (thread who's queue this is : e1a3ca28 0 0)
//
// Dump post message statics
dwTimePosted = 0;
_InitTypeRead(ptiTmp, SYM(tagTHREADINFO));
if (ReadField(mlPost.cMsgs)) {
qs->dwPosted += (DWORD)ReadField(mlPost.cMsgs);
GetFieldValue(ReadField(mlPost.pqmsgRead), SYM(tagQMSG), "msg.time", dwOldest);
GetFieldValue(ReadField(mlPost.pqmsgWriteLast), SYM(tagQMSG), "msg.time", dwNewest);
dwTimePosted = dwNewest - dwOldest;
}
Print(" %8x %8x\n", (DWORD)ReadField(mlPost.cMsgs), dwTimePosted);
} else {
if (bMsgsPresent) {
Print("\n");
}
}
return TRUE;
}
ULONG dmqCallback(
PTR pti,
PVOID pData)
{
PQSTAT qs = (PQSTAT)pData;
_InitTypeRead(pti, SYM(tagTHREADINFO));
DumpQMsg(ReadField(pq), qs, pti);
_InitTypeRead(pti, SYM(tagTHREADINFO));
if (ReadField(pqAttach)) {
Print(" -> pqAttach=%p", ReadField(pqAttach));
// LATER: dump pqAttach as well?
}
return FALSE;
}
BOOL Idmq(
DWORD opts,
ULONG64 param1)
{
try {
static const char separator[] = "=================";
PTR pq;
// firstly check the symbols etc.'s legitimacy
pq = GetGlobalPointer(VAR(gpqForeground));
if (param1 == NULL_PTR) {
if ((opts & OFLAG(a)) == 0) {
Print("uses gpqForeground\n");
}
}
if (opts & OFLAG(c)) {
Print("Summary of%s message queues (\"age\" is newest time - oldest time)\n",
param1 == NULL_PTR ? " all" : "");
//Print("Queue # Input age \t Thread # Posted age\n");
//Print("======== ======== ========\t======== ======== ========\n");
Print("%-*s %-*s %-*s\t%-*s %-*s %-*s\n",
PtrWidth(), "queue",
PtrWidth(), "# input",
PtrWidth(), "age",
PtrWidth(), "Thread",
PtrWidth(), "# posted",
PtrWidth(), "age");
Print("%*.*s %*.*s %*.*s\t%*.*s %*.*s %*.*s\n",
PtrWidth(), PtrWidth(), separator,
PtrWidth(), PtrWidth(), separator,
PtrWidth(), PtrWidth(), separator,
PtrWidth(), PtrWidth(), separator,
PtrWidth(), PtrWidth(), separator,
PtrWidth(), PtrWidth(), separator);
}
if (param1 == NULL_PTR) {
if (opts & OFLAG(t)) {
// pti is required with -t
return FALSE;
}
if (opts & (/*OFLAG(c) |*/ OFLAG(a))) {
/*
* do it for all the queues
*/
QSTAT qs = { 0, };
qs.opts = opts & OFLAG(c);
ForEachPti(dmqCallback, &qs);
if (opts & OFLAG(c)) {
Print(" \n");
Print("Queues # Input \t Threads # Posted\n");
Print("======== ======== ========\t======== ========\n");
Print("%8x %8x \t%8x %8x\n",
qs.dwQueues, qs.dwInput, qs.dwThreads, qs.dwPosted);
}
return TRUE;
} else {
// use gpqForeground
if (pq == NULL_PTR) {
Print("no foreground queue (gpqForeground == NULL)!\n");
return TRUE;
}
}
} else {
// param1 is pq or pti
pq = param1;
}
if (opts & OFLAG(t)) {
// param1 is pti
QSTAT qs = { 0, };
qs.opts = opts & OFLAG(c);
_InitTypeRead(param1, SYM(tagTHREADINFO));
DumpQMsg(ReadField(pq), &qs, param1);
_InitTypeRead(param1, SYM(tagTHREADINFO));
if (ReadField(pqAttach)) {
Print("paAttach\n");
DumpQMsg(ReadField(pqAttach), &qs, param1);
}
} else {
// param1 is pq
PTR ptiKeyboard;
QSTAT qs = { 0, };
qs.opts = opts & OFLAG(c);
GetFieldValue(pq, SYM(tagQ), "ptiKeyboard", ptiKeyboard);
DumpQMsg(pq, &qs, ptiKeyboard);
}
} except (CONTINUE) {
}
return TRUE;
}
#endif // KERNEL
#ifdef OLD_DEBUGGER
#ifdef KERNEL
/***************************************************************************\
* dwe - dump winevents
*
* dwe - dumps all EVENTHOOKs.
* dwe <addr> - dumps EVENTHOOK at address.
* dwe -n - dumps all NOTIFYs.
* dwe -n <addr> - dumps NOTIFY at address.
*
* 1997-07-10 IanJa Created.
\***************************************************************************/
BOOL Idwe(
DWORD opts,
ULONG64 param1)
{
EVENTHOOK EventHook, *pEventHook;
NOTIFY Notify, *pNotify;
PVOID pobj;
char ach[100];
pobj = FIXKP(param1);
if (opts & OFLAG(n)) {
if (pobj) {
move(Notify, pobj);
sprintf(ach, "NOTIFY 0x%p\n", pobj);
Idso(0, ach);
return 1;
}
pNotify = GetGlobalPointer(VAR(gpPendingNotifies));
Print("Pending Notifications:\n");
gnIndent += 2;
SAFEWHILE (pNotify != NULL) {
sprintf(ach, "NOTIFY 0x%p\n", pNotify);
Idso(0, ach);
move(pNotify, &pNotify->pNotifyNext);
}
gnIndent -= 2;
return TRUE;
}
if (pobj) {
move(EventHook, pobj);
sprintf(ach, "EVENTHOOK 0x%p\n", pobj);
Idso(0, ach);
return 1;
}
pEventHook = GetGlobalPointer(VAR(gpWinEventHooks));
Print("WinEvent hooks:\n");
gnIndent += 2;
SAFEWHILE (pEventHook != NULL) {
sprintf(ach, "EVENTHOOK 0x%p\n", pEventHook);
Idso(0, ach);
move(pEventHook, &pEventHook->pehNext);
}
gnIndent -= 2;
Print("\n");
return TRUE;
}
#endif // KERNEL
#ifndef KERNEL
/************************************************************************\
* Idped
*
* Dumps Edit Control Structures (PEDs)
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Idped(
DWORD opts,
ULONG64 param1)
{
PED ped;
ED ed;
DWORD pText;
UNREFERENCED_PARAMETER(opts);
ped = param1;
move(ed, ped);
move(pText, ed.hText);
Print("PED Handle: %lX\n", ped);
Print("hText %lX (%lX)\n", ed.hText, pText);
PRTFDW2(ed., cchAlloc, cchTextMax);
PRTFDW2(ed., cch, cLines);
PRTFDW2(ed., ichMinSel, ichMaxSel);
PRTFDW2(ed., ichCaret, iCaretLine);
PRTFDW2(ed., ichScreenStart, ichLinesOnScreen);
PRTFDW2(ed., xOffset, charPasswordChar);
PRTFDWDWP(ed., cPasswordCharWidth, hwnd);
PRTFDWP1(ed., pwnd);
PRTFRC(ed., rcFmt);
PRTFDWP1(ed., hwndParent);
PRTFPT(ed., ptPrevMouse);
PRTFDW1(ed., prevKeys);
BEGIN_PRTFFLG();
PRTFFLG(ed, fSingle);
PRTFFLG(ed, fNoRedraw);
PRTFFLG(ed, fMouseDown);
PRTFFLG(ed, fFocus);
PRTFFLG(ed, fDirty);
PRTFFLG(ed, fDisabled);
PRTFFLG(ed, fNonPropFont);
PRTFFLG(ed, fNonPropDBCS);
PRTFFLG(ed, fBorder);
PRTFFLG(ed, fAutoVScroll);
PRTFFLG(ed, fAutoHScroll);
PRTFFLG(ed, fNoHideSel);
PRTFFLG(ed, fDBCS);
PRTFFLG(ed, fFmtLines);
PRTFFLG(ed, fWrap);
PRTFFLG(ed, fCalcLines);
PRTFFLG(ed, fEatNextChar);
PRTFFLG(ed, fStripCRCRLF);
PRTFFLG(ed, fInDialogBox);
PRTFFLG(ed, fReadOnly);
PRTFFLG(ed, fCaretHidden);
PRTFFLG(ed, fTrueType);
PRTFFLG(ed, fAnsi);
PRTFFLG(ed, fWin31Compat);
PRTFFLG(ed, f40Compat);
PRTFFLG(ed, fFlatBorder);
PRTFFLG(ed, fSawRButtonDown);
PRTFFLG(ed, fInitialized);
PRTFFLG(ed, fSwapRoOnUp);
PRTFFLG(ed, fAllowRTL);
PRTFFLG(ed, fDisplayCtrl);
PRTFFLG(ed, fRtoLReading);
PRTFFLG(ed, fInsertCompChr);
PRTFFLG(ed, fReplaceCompChr);
PRTFFLG(ed, fNoMoveCaret);
PRTFFLG(ed, fResultProcess);
PRTFFLG(ed, fKorea);
PRTFFLG(ed, fInReconversion);
END_PRTFFLG();
PRTFDWDWP(ed., cbChar, chLines);
PRTFDWDWP(ed., format, lpfnNextWord);
PRTFDW1(ed., maxPixelWidth);
{
const char* p = "**INVALID**";
if (ed.undoType < UNDO_DELETE) {
p = GetFlags(GF_EDUNDO, 0, NULL, TRUE);
}
Print(DWSTR2 "\t" "%08x undoType (%s)\n", ed.hDeletedText, "hDeleteText", ed.undoType, p);
}
PRTFDW2(ed., ichDeleted, cchDeleted);
PRTFDW2(ed., ichInsStart, ichInsEnd);
PRTFDWPDW(ed., hFont, aveCharWidth);
PRTFDW2(ed., lineHeight, charOverhang);
PRTFDW2(ed., cxSysCharWidth, cySysCharHeight);
PRTFDWP2(ed., listboxHwnd, pTabStops);
PRTFDWP1(ed., charWidthBuffer);
// PRTFDW2(ed., hkl, wMaxNegA);
PRTFDW1(ed., wMaxNegA);
PRTFDW2(ed., wMaxNegAcharPos, wMaxNegC);
PRTFDW2(ed., wMaxNegCcharPos, wLeftMargin);
PRTFDW2(ed., wRightMargin, ichStartMinSel);
PRTFDWDWP(ed., ichStartMaxSel, pLpkEditCallout);
PRTFDWP2(ed., hCaretBitmap, hInstance);
PRTFDW2(ed., seed, fEncoded);
PRTFDW2(ed., iLockLevel, wImeStatus);
return TRUE;
}
#endif // !KERNEL
#endif // OLD_DEBUGGER
#ifndef KERNEL
/************************************************************************\
* Idci
*
* Dumps Client Info
*
* 6/15/1995 Created SanfordS
\************************************************************************/
BOOL Idci(
VOID)
{
PTR pteb = NULL_PTR;
GetTebAddress(&pteb);
if (pteb) {
ULONG pciOffset;
GetFieldOffset(SYM(TEB), "Win32ClientInfo", &pciOffset);
_InitTypeRead(pteb + pciOffset, SYM(CLIENTINFO));
Print("PCLIENTINFO @ 0x%p:\n", pteb + pciOffset);
// DWORD dwExpWinVer;
Print("\tdwExpWinVer %08lx\n", (ULONG)ReadField(dwExpWinVer));
// DWORD dwCompatFlags;
Print("\tdwCompatFlags %08lx\n", (ULONG)ReadField(dwCompatFlags));
// DWORD dwTIFlags;
Print("\tdwTIFlags %08lx\n", (ULONG)ReadField(dwTIFlags));
// PDESKTOPINFO pDeskInfo;
Print("\tpDeskInfo %p\n", ReadField(pDeskInfo));
// ULONG ulClientDelta;
Print("\tulClientDelta %p\n", ReadField(ulClientDelta));
// struct tagHOOK *phkCurrent;
Print("\tphkCurrent %p\n", ReadField(phkCurrent));
// DWORD fsHooks;
Print("\tfsHooks %08lx\n", (ULONG)ReadField(fsHooks));
// CALLBACKWND CallbackWnd;
Print("\tCallbackWnd.hwnd %p\n", ReadField(CallbackWnd.hwnd));
// DWORD cSpins;
Print("\tcSpins %08lx\n", (ULONG)ReadField(cSpins));
Print("\tCodePage %d\n", (ULONG)ReadField(CodePage));
} else {
Print("Unable to get TEB info.\n");
}
return TRUE;
}
#endif // !KERNEL
#ifdef KERNEL
/************************************************************************\
* Idpi
*
* Dumps ProcessInfo structs
*
* 6/9/1995 Created SanfordS
\************************************************************************/
ULONG
dpiCallback(
PTR ppi,
PVOID Data)
{
UNREFERENCED_PARAMETER(Data);
Idpi(0, ppi);
Print("\n");
return FALSE;
}
BOOL Idpi(
DWORD opts,
ULONG64 param1)
{
PTR pW32Process;
PTR ppi;
PTR pEProcess;
PTR pdv;
PTR ulUniqueProcessId;
/*
* If he just wants the current process, locate it.
*/
if (opts & OFLAG(c)) {
Print("Current Process:\n");
GetCurrentProcessAddr(dwProcessor, 0, &param1);
if (param1 == 0) {
Print("Unable to get current process pointer.\n");
return FALSE;
}
if (GetFieldValue(param1, "nt!EPROCESS", "Win32Process", pW32Process)) {
Print("Unable to read _EPROCESS at %p\n", param1);
return FALSE;
}
param1 = pW32Process;
} else if (opts & OFLAG(p)) {
if (GetFieldValue(param1, "nt!EPROCESS", "Win32Process", param1)) {
Print("Can't get EPROCESS @ 0x%p\n", param1);
return FALSE;
}
} else if (param1 == 0) {
Print("**** NT ACTIVE WIN32 PROCESSINFO DUMP ****\n");
ForEachPpi(dpiCallback, NULL);
return TRUE;
}
ppi = FIXKP(param1);
if (GetFieldValue(ppi, SYM(PROCESSINFO), "Process", pEProcess)) {
Print("Can't get PROCESSINFO from %p.\n", ppi);
return FALSE;
}
if (GetFieldValue(pEProcess, "nt!EPROCESS", "UniqueProcessId", ulUniqueProcessId)) {
Print("Unable to read _EPROCESS at %p\n", pEProcess);
return FALSE;
}
Print("---PPROCESSINFO @ 0x%p for process 0x%p (%s):\n",
ppi,
ulUniqueProcessId,
ProcessName(ppi));
_InitTypeRead(ppi, SYM(PROCESSINFO));
Print("\tppiNext 0x%p\n", ReadField(ppiNext));
Print("\trpwinsta 0x%p\n", ReadField(rpwinsta));
Print("\thwinsta 0x%p\n", ReadField(hwinsta));
Print("\tamwinsta 0x%08lx\n", (ULONG)ReadField(amwinsta));
Print("\tptiMainThread 0x%p\n", ReadField(ptiMainThread));
Print("\tcThreads 0x%08lx\n", (ULONG)ReadField(cThreads));
Print("\trpdeskStartup 0x%p\n", ReadField(rpdeskStartup));
Print("\thdeskStartup 0x%p\n", ReadField(hdeskStartup));
Print("\tpclsPrivateList 0x%p\n", ReadField(pclsPrivateList));
Print("\tpclsPublicList 0x%p\n", ReadField(pclsPublicList));
Print("\tflags %s\n",
GetFlags(GF_W32PF, (DWORD)ReadField(W32PF_Flags), NULL, TRUE));
Print("\tdwHotkey 0x%08lx\n", (ULONG)ReadField(dwHotkey));
Print("\tpWowProcessInfo 0x%p\n", ReadField(pwpi));
Print("\tluidSession 0x%08lx:0x%08lx\n", (ULONG)ReadField(luidSession.HighPart),
(ULONG)ReadField(luidSession.LowPart));
Print("\tdwX,dwY (0x%x, 0x%x)\n", (ULONG)ReadField(usi.dwX), (ULONG)ReadField(usi.dwY));
Print("\tdwXSize,dwYSize (0x%x, 0x%x)\n", (ULONG)ReadField(usi.dwXSize), (ULONG)ReadField(usi.dwYSize));
Print("\tdwFlags 0x%08x\n", (ULONG)ReadField(usi.dwFlags));
Print("\twShowWindow 0x%04x\n", (ULONG)ReadField(usi.wShowWindow));
Print("\tpCursorCache 0x%p\n", ReadField(pCursorCache));
Print("\tdwLpkEntryPoints %s\n",
GetFlags(GF_LPK, (DWORD)ReadField(dwLpkEntryPoints), NULL, TRUE));
/*
* List desktop views
*/
pdv = ReadField(pdvList);
Print("Desktop views:\n");
while (pdv != 0) {
_InitTypeRead(pdv, SYM(DESKTOPVIEW));
Print("\tpdesk = %p, ulClientDelta = %p\n", ReadField(pdesk), ReadField(ulClientDelta));
pdv = ReadField(pdvNext);
}
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
/***************************************************************************\
* dpm - dump popupmenu
*
* dpm address - dumps menu info for menu at address
*
* 02/13/1995 JohnC Created.
* 06/09/1995 SanfordS Made to fit stdexts motif.
\***************************************************************************/
BOOL Idpm(
DWORD opts,
PTR ppopupmenu)
{
UNREFERENCED_PARAMETER(opts);
ppopupmenu = FIXKP(ppopupmenu);
Print("PPOPUPMENU @ 0x%p\n", ppopupmenu);
BEGIN_PRTFFLG(ppopupmenu, SYM(POPUPMENU));
PRTFFLG(fIsMenuBar);
PRTFFLG(fHasMenuBar);
PRTFFLG(fIsSysMenu);
PRTFFLG(fIsTrackPopup);
PRTFFLG(fDroppedLeft);
PRTFFLG(fHierarchyDropped);
PRTFFLG(fRightButton);
PRTFFLG(fToggle);
PRTFFLG(fSynchronous);
PRTFFLG(fFirstClick);
PRTFFLG(fDropNextPopup);
PRTFFLG(fNoNotify);
PRTFFLG(fAboutToHide);
PRTFFLG(fShowTimer);
PRTFFLG(fHideTimer);
PRTFFLG(fDestroyed);
PRTFFLG(fDelayedFree);
PRTFFLG(fFlushDelayedFree);
PRTFFLG(fFreed);
PRTFFLG(fInCancel);
PRTFFLG(fTrackMouseEvent);
PRTFFLG(fSendUninit);
END_PRTFFLG();
PRTFDWP2(spwndNotify, spwndPopupMenu);
PRTFDWP2(spwndNextPopup, spwndPrevPopup);
PRTFDWP2(spmenu, spmenuAlternate);
PRTFDWP2(spwndActivePopup, ppopupmenuRoot);
PRTFDWPDW(ppmDelayedFree, posSelectedItem);
PRTFDW1(posDropped);
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
/***************************************************************************\
* dms - dump pMenuState
*
* dms address
*
* 05-15-96 Created GerardoB
\***************************************************************************/
BOOL Idms(
DWORD opts,
ULONG64 param1)
{
UNREFERENCED_PARAMETER(opts);
param1 = FIXKP(param1);
Print("PMENUSTATE @ 0x%p\n", param1);
BEGIN_PRTFFLG(FIXKP(param1), MENUSTATE);
PRTFFLG(fMenuStarted);
PRTFFLG(fIsSysMenu);
PRTFFLG(fInsideMenuLoop);
PRTFFLG(fButtonDown);
PRTFFLG(fInEndMenu);
PRTFFLG(fUnderline);
PRTFFLG(fButtonAlwaysDown);
PRTFFLG(fDragging);
PRTFFLG(fModelessMenu);
PRTFFLG(fInCallHandleMenuMessages);
PRTFFLG(fDragAndDrop);
PRTFFLG(fAutoDismiss);
PRTFFLG(fIgnoreButtonUp);
PRTFFLG(fMouseOffMenu);
PRTFFLG(fInDoDragDrop);
PRTFFLG(fActiveNoForeground);
PRTFFLG(fNotifyByPos);
END_PRTFFLG();
PRTFDWP1(pGlobalPopupMenu);
PRTFPT(ptMouseLast);
PRTFDW2(mnFocus, cmdLast);
PRTFDWP1(ptiMenuStateOwner);
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
/***************************************************************************\
* dq - dump queue
*
* dq address - dumps queue structure at address
* dq t address - dumps queue structure at address plus THREADINFO
*
* 06-20-91 ScottLu Created.
* 11-14-91 DavidPe Added THREADINFO option.
* 6/9/1995 SanfordS made to fit stdexts motif
\***************************************************************************/
ULONG
dqCallback(
PTR pti,
PVOID Data)
{
PTR pq;
GetFieldValue(pti, SYM(THREADINFO), "pq", pq);
Idq(PtrToUlong(Data), pq);
return FALSE;
}
BOOL Idq(
DWORD opts,
PTR pq)
{
char ach[80];
if (opts & OFLAG(a)) {
Print("Dumping all queues:\n");
ForEachPti(dqCallback, ULongToPtr(opts & ~OFLAG(a)));
return TRUE;
#ifdef SOME_OTHER_DELUSION
HANDLEENTRY he, *phe;
int i;
FOREACHHANDLEENTRY(phe, he, i)
if (he.bType == TYPE_INPUTQUEUE) {
Idq(opts & ~OFLAG(a), FIXKP(he.phead));
Print("\n");
}
NEXTEACHHANDLEENTRY()
return TRUE;
#endif
}
if (pq == 0) {
Print("Dumping foreground queue:\n");
pq = GetGlobalPointer(VAR(gpqForeground));
if (pq == 0) {
Print("no foreground queue (gpqForeground == NULL)!\n");
return TRUE;
}
} else {
pq = FIXKP(pq);
}
/*
* Print out simple thread info for pq->ptiKeyboard
*/
_InitTypeRead(pq, SYM(tagQ));
if (ReadField(ptiKeyboard)) {
Idt(OFLAG(p), ReadField(ptiKeyboard));
}
/*
* Don't Print() with more than 16 arguments at once because it'll blow
* up.
*/
Print("PQ @ 0x%p\n", pq);
Print(
"\tmlInput.pqmsgRead 0x%p\n"
"\tmlInput.pqmsgWriteLast 0x%p\n"
"\tmlInput.cMsgs 0x%08lx\n",
ReadField(mlInput.pqmsgRead),
ReadField(mlInput.pqmsgWriteLast),
(ULONG)ReadField(mlInput.cMsgs));
Print("\tptiSysLock 0x%p\n"
"\tidSysLock 0x%p\n"
"\tidSysPeek 0x%p\n",
ReadField(ptiSysLock),
ReadField(idSysLock),
ReadField(idSysPeek));
Print("\tptiMouse 0x%p\n"
"\tptiKeyboard 0x%p\n",
ReadField(ptiMouse),
ReadField(ptiKeyboard));
Print("\tspcurCurrent 0x%p\n"
"\tiCursorLevel 0x%08lx\n",
ReadField(spcurCurrent),
(ULONG)ReadField(iCursorLevel));
DebugGetWindowTextA(ReadField(spwndCapture), ach, ARRAY_SIZE(ach));
Print("\tspwndCapture 0x%p \"%s\"\n",
ReadField(spwndCapture), ach);
DebugGetWindowTextA(ReadField(spwndFocus), ach, ARRAY_SIZE(ach));
Print("\tspwndFocus 0x%p \"%s\"\n",
ReadField(spwndFocus), ach);
DebugGetWindowTextA(ReadField(spwndActive), ach, ARRAY_SIZE(ach));
Print("\tspwndActive 0x%p \"%s\"\n",
ReadField(spwndActive), ach);
DebugGetWindowTextA(ReadField(spwndActivePrev), ach, ARRAY_SIZE(ach));
Print("\tspwndActivePrev 0x%p \"%s\"\n",
ReadField(spwndActivePrev), ach);
Print("\tcodeCapture 0x%04lx\n"
"\tmsgDblClk 0x%04lx\n"
"\ttimeDblClk 0x%08lx\n",
(ULONG)ReadField(codeCapture),
(ULONG)ReadField(msgDblClk),
(ULONG)ReadField(timeDblClk));
Print("\thwndDblClk 0x%p\n",
ReadField(hwndDblClk));
Print("\tptDblClk { %d, %d }\n",
(ULONG)ReadField(ptDblClk.x),
(ULONG)ReadField(ptDblClk.y));
Print("\tQF_flags 0x%08lx %s\n"
"\tcThreads 0x%08lx\n"
"\tcLockCount 0x%08lx\n",
(ULONG)ReadField(QF_flags), GetFlags(GF_QF, (DWORD)ReadField(QF_flags), NULL, FALSE),
(DWORD) ReadField(cThreads),
(DWORD) ReadField(cLockCount));
Print("\tmsgJournal 0x%08lx\n"
"\tExtraInfo 0x%08lx\n",
(ULONG)ReadField(msgJournal),
(ULONG)ReadField(ExtraInfo));
/*
* Dump THREADINFO if user specified 't'.
*/
if (opts & OFLAG(t)) {
Idti(0, ReadField(ptiKeyboard));
}
return TRUE;
}
#endif // KERNEL
/***************************************************************************\
* dsi dump serverinfo struct
*
* 02-27-92 ScottLu Created.
* 6/9/1995 SanfordS Made to fit stdexts motif.
\***************************************************************************/
BOOL Idsi(
DWORD opts)
{
try {
PTR psi;
UINT i;
char ach[80];
ULONG64 ulOffset;
PSERVERINFO pServerInfo; // dummy for ARRAY_SIZE
static const char* fnid[FNID_ARRAY_SIZE] = {
"FNID_SCROLLBAR", // xxxSBWndProc
"FNID_ICONTITLE", // xxxDefWindowProc
"FNID_MENU", // xxxMenuWindowProc
"FNID_DESKTOP", // xxxDesktopWndProc
"FNID_DEFWINDOWPROC", // xxxDefWindowProc
"FNID_MESSAGEWND", // xxxDefWindowProc
"FNID_SWITCH", // xxxSwitchWndProc
"FNID_BUTTON", // No server side proc
"FNID_COMBOBOX", // No server side proc
"FNID_COMBOLISTBOX", // No server side proc
"FNID_DIALOG", // No server side proc
"FNID_EDIT", // No server side proc
"FNID_LISTBOX", // No server side proc
"FNID_MDICLIENT", // No server side proc
"FNID_STATIC", // No server side proc
"FNID_IME", // No server side proc
"FNID_HKINLPCWPEXSTRUCT",
"FNID_HKINLPCWPRETEXSTRUCT",
"FNID_DEFFRAMEPROC", // No server side proc
"FNID_DEFMDICHILDPROC", // No server side proc
"FNID_MB_DLGPROC", // No server side proc
"FNID_MDIACTIVATEDLGPROC", // No server side proc
"FNID_SENDMESSAGE",
"FNID_SENDMESSAGEFF",
"FNID_SENDMESSAGEEX",
"FNID_CALLWINDOWPROC",
"FNID_SENDMESSAGEBSM",
"FNID_TOOLTIP", // xxxTooltipWndProc
"FNID_GHOST", // xxxGhostWndProc
"FNID_SENDNOTIFYMESSAGE",
"FNID_SENDMESSAGECALLBACK",
"0x2b9",
};
psi = GetGlobalPointer(SYM(gpsi));
if (psi == 0) {
return TRUE;
}
Print("PSERVERINFO @ 0x%p\n", psi);
_InitTypeRead(psi, SYM(SERVERINFO));
Print( "\tRIPFlags 0x%04lx %s\n", (DWORD)ReadField(dwRIPFlags), GetFlags(GF_RIP, (DWORD)ReadField(dwRIPFlags), NULL, FALSE));
Print( "\tSRVIFlags 0x%04lx %s\n", (DWORD)ReadField(wSRVIFlags), GetFlags(GF_SRVI, (DWORD)ReadField(wSRVIFlags), NULL, FALSE));
Print( "\tPUSIFlags 0x%08lx %s\n", (DWORD)ReadField(PUSIFlags), GetFlags(GF_SI, (DWORD)ReadField(PUSIFlags), NULL, FALSE));
Print( "\tcHandleEntries 0x%08p\n"
"\tcbHandleTable 0x%08p\n"
"\tnEvents 0x%08p\n",
ReadField(cHandleEntries),
ReadField(cbHandleTable),
ReadField(nEvents));
if (opts & OFLAG(p)) {
Print("\t" "mpFnidPfn:\n");
i = 0;
SAFEWHILE (i < FNID_ARRAY_SIZE) {
PTR pfn = GetArrayElementPtr(psi, SYM(SERVERINFO), i == 0 ? "mpFnidPfn" : NULL, i);
GetSym(pfn, ach, &ulOffset);
Print("%10c%-26s = %p %s", ' ', fnid[i], pfn, ach);
if (ulOffset) {
Print("+0x%x", (DWORD)ulOffset);
}
Print("\n");
++i;
}
}
if (opts & OFLAG(w)) {
Print("\t" "aStoCidPfn:\n");
i = 0;
SAFEWHILE (i < ARRAY_SIZE(pServerInfo->aStoCidPfn)) {
PTR pfn = GetArrayElementPtr(psi, SYM(SERVERINFO), i == 0 ? "aStoCidPfn" : NULL, i);
GetSym(pfn, ach, &ulOffset);
Print("%10c%-20s = %p %s", ' ', fnid[i], pfn, ach);
if (ulOffset) {
Print("+0x%x", (DWORD)ulOffset);
}
Print("\n");
++i;
}
}
if (opts & OFLAG(b)) {
ULONG cbWnd = GetTypeSize(SYM(WND));
Print("\t" "mpFnid_serverCBWndProc:\n");
i = 0;
SAFEWHILE (i < ARRAY_SIZE(pServerInfo->mpFnid_serverCBWndProc)) {
WORD cb = (WORD)GetArrayElement(psi, SYM(SERVERINFO), i == 0 ? "mpFnid_serverCBWndProc" : NULL, i, "WORD");
Print("%10c%-26s = %08lx", ' ', fnid[i], cb);
if (cb) {
Print(" = sizeof(WND) + 0x%x", cb - cbWnd);
}
Print("\n");
++i;
}
}
if (opts & OFLAG(m)) {
/*
* Add entries to this table in alphabetical order with
* the prefix removed.
*/
static const SYSMET_ENTRY aSysMet[SM_CMETRICS] = {
SMENTRY(ARRANGE),
SMENTRY(CXBORDER),
SMENTRY(CYBORDER),
SMENTRY(CYCAPTION),
SMENTRY(CLEANBOOT),
SMENTRY(CXCURSOR),
SMENTRY(CYCURSOR),
SMENTRY(DBCSENABLED),
SMENTRY(DEBUG),
SMENTRY(CXDLGFRAME),
SMENTRY(CYDLGFRAME),
SMENTRY(CXDOUBLECLK),
SMENTRY(CYDOUBLECLK),
SMENTRY(CXDRAG),
SMENTRY(CYDRAG),
SMENTRY(CXEDGE),
SMENTRY(CYEDGE),
SMENTRY(CXFRAME),
SMENTRY(CYFRAME),
SMENTRY(CXFULLSCREEN),
SMENTRY(CYFULLSCREEN),
SMENTRY(CXICON),
SMENTRY(CYICON),
SMENTRY(CXICONSPACING),
SMENTRY(CYICONSPACING),
SMENTRY(IMMENABLED),
SMENTRY(CYKANJIWINDOW),
SMENTRY(CXMAXIMIZED),
SMENTRY(CYMAXIMIZED),
SMENTRY(CXMAXTRACK),
SMENTRY(CYMAXTRACK),
SMENTRY(CYMENU),
SMENTRY(CXMENUCHECK),
SMENTRY(CYMENUCHECK),
SMENTRY(MENUDROPALIGNMENT),
SMENTRY(CXMENUSIZE),
SMENTRY(CYMENUSIZE),
SMENTRY(MIDEASTENABLED),
SMENTRY(CXMIN),
SMENTRY(CYMIN),
SMENTRY(CXMINIMIZED),
SMENTRY(CYMINIMIZED),
SMENTRY(CXMINSPACING),
SMENTRY(CYMINSPACING),
SMENTRY(CXMINTRACK),
SMENTRY(CYMINTRACK),
SMENTRY(CMONITORS),
SMENTRY(CMOUSEBUTTONS),
SMENTRY(MOUSEPRESENT),
SMENTRY(MOUSEWHEELPRESENT),
SMENTRY(NETWORK),
SMENTRY(PENWINDOWS),
SMENTRY(RESERVED1),
SMENTRY(RESERVED2),
SMENTRY(RESERVED3),
SMENTRY(RESERVED4),
SMENTRY(SAMEDISPLAYFORMAT),
SMENTRY(CXSCREEN),
SMENTRY(CYSCREEN),
SMENTRY(CXVSCROLL),
SMENTRY(CYHSCROLL),
SMENTRY(CYVSCROLL),
SMENTRY(CXHSCROLL),
SMENTRY(SECURE),
SMENTRY(SHOWSOUNDS),
SMENTRY(CXSIZE),
SMENTRY(CYSIZE),
SMENTRY(SLOWMACHINE),
SMENTRY(CYSMCAPTION),
SMENTRY(CXSMICON),
SMENTRY(CYSMICON),
SMENTRY(CXSMSIZE),
SMENTRY(CYSMSIZE),
SMENTRY(SWAPBUTTON),
SMENTRY(CYVTHUMB),
SMENTRY(CXHTHUMB),
SMENTRY(UNUSED_64),
SMENTRY(UNUSED_65),
SMENTRY(UNUSED_66),
SMENTRY(XVIRTUALSCREEN),
SMENTRY(YVIRTUALSCREEN),
SMENTRY(CXVIRTUALSCREEN),
SMENTRY(CYVIRTUALSCREEN),
// Windows 2000
SMENTRY(CMONITORS),
SMENTRY(SAMEDISPLAYFORMAT),
// Whistler
SMENTRY(SHUTTINGDOWN),
};
Print("\taiSysMet:\n");
i = 0;
SAFEWHILE (i < SM_CMETRICS) {
DWORD v = (DWORD)GetArrayElement(psi, SYM(SERVERINFO), i == 0 ? "aiSysMet" : NULL, aSysMet[i].iMetric, "DWORD");
Print( "\t\tSM_%-18s = 0x%08lx = %d\n", aSysMet[i].pstrMetric, v, v);
++i;
}
}
if (opts & OFLAG(c)) {
static LPSTR aszSysColor[COLOR_MAX] = {
//012345678901234567890
"SCROLLBAR",
"BACKGROUND",
"ACTIVECAPTION",
"INACTIVECAPTION",
"MENU",
"WINDOW",
"WINDOWFRAME",
"MENUTEXT",
"WINDOWTEXT",
"CAPTIONTEXT",
"ACTIVEBORDER",
"INACTIVEBORDER",
"APPWORKSPACE",
"HIGHLIGHT",
"HIGHLIGHTTEXT",
"BTNFACE",
"BTNSHADOW",
"GRAYTEXT",
"BTNTEXT",
"INACTIVECAPTIONTEXT",
"BTNHIGHLIGHT",
"3DDKSHADOW",
"3DLIGHT",
"INFOTEXT",
"INFOBK",
"3DALTFACE",
"HOTLIGHT",
// new in Windows 2000
"GRADIENTACTIVECAPTION",
"GRADIENTINACTIVECAPTION",
"MENUHILIGHT",
"MENUBAR",
};
COLORREF colors[COLOR_MAX];
COLORREF colorsUnmatched[COLOR_MAX];
for (i = 0; i < COLOR_MAX; ++i) {
colors[i] = (COLORREF)GetArrayElement(psi, SYM(SERVERINFO), i == 0 ? "argbSystem" : NULL, i, SYM(COLORREF));
}
for (i = 0; i < COLOR_MAX; ++i) {
colorsUnmatched[i] = (COLORREF)GetArrayElement(psi, SYM(SERVERINFO), i == 0 ? "argbSystemUnmatched" : NULL, i, SYM(COLORREF));
}
Print("\targbSystem:\n\t\tCOLOR%28sSYSRGB\t\tUnmatched\tSYSHBR\n", "");
i = 0;
SAFEWHILE (i < COLOR_MAX) {
Print("\t\tCOLOR_%-25s: (%02x,%02x,%02x)\t(%02x,%02x,%02x)\t0x%08p\n",
aszSysColor[i],
GetRValue(colors[i]), GetGValue(colors[i]), GetBValue(colors[i]),
GetRValue(colorsUnmatched[i]), GetGValue(colorsUnmatched[i]), GetBValue(colorsUnmatched[i]),
(KHBRUSH)GetArrayElement(psi, SYM(SERVERINFO), i == 0 ? "ahbrSystem" : NULL, i, SYM(KHBRUSH)));
++i;
}
}
if (opts & OFLAG(o)) {
#if 0 // LATER
OEMBITMAPINFO oembmi[OBI_COUNT];
for (i = 0; i < OBI_COUNT; ++i) {
}
Print("\toembmi @ 0x%p:\n\t\tx \ty \tcx \tcy\n", &psi->oembmi);
for (i = 0; i < OBI_COUNT; i++) {
Print("\tbm[%d]:\t%08x\t%08x\t%08x\t%08x\n",
i,
si.oembmi[i].x ,
si.oembmi[i].y ,
si.oembmi[i].cx,
si.oembmi[i].cy);
}
#else
Print("\tOEMINFO:\n");
#endif
_InitTypeRead(psi, SYM(SERVERINFO));
Print(
"\t\tPlanes = %d\n"
"\t\tBitsPixel = %d\n"
"\t\tBitCount = %d\n"
"\t\tdmLogPixels = %d\n"
"\t\trcScreen = (%d,%d)-(%d,%d) %dx%d\n"
,
(BYTE)ReadField(Planes) ,
(BYTE)ReadField(BitsPixel) ,
(WORD)ReadField(BitCount) ,
(UINT)ReadField(dmLogPixels),
(LONG)ReadField(rcScreen.left), (LONG)ReadField(rcScreen.top),
(LONG)ReadField(rcScreen.right), (LONG)ReadField(rcScreen.bottom),
(LONG)ReadField(rcScreen.right)-(LONG)ReadField(si.rcScreen.left),
(LONG)ReadField(rcScreen.bottom)-(LONG)ReadField(si.rcScreen.top));
}
if (opts & OFLAG(v)) {
ULONG ulOffsetTmp; // req
GetFieldOffset(SYM(SERVERINFO), "tmSysFont", &ulOffsetTmp);
Print(
"\tptCursor {%d, %d}\n"
"\tgclBorder 0x%08lx\n"
"\tdtScroll 0x%08lx\n"
"\tdtLBSearch 0x%08lx\n"
"\tdtCaretBlink 0x%08lx\n"
"\tdwDefaultHeapBase 0x%08lx\n"
"\tdwDefaultHeapSize 0x%08lx\n"
"\twMaxLeftOverlapChars 0x%08lx\n"
"\twMaxRightOverlapchars 0x%08lx\n"
"\tuiShellMsg 0x%08lx\n"
"\tcxSysFontChar 0x%08lx\n"
"\tcySysFontChar 0x%08lx\n"
"\tcxMsgFontChar 0x%08lx\n"
"\tcyMsgFontChar 0x%08lx\n"
"\ttmSysFont 0x%p\n"
"\tatomIconSmProp 0x%04lx\n"
"\tatomIconProp 0x%04lx\n"
"\thIconSmWindows 0x%08lp\n"
"\thIcoWindows 0x%08lp\n"
"\thCaptionFont 0x%08lp\n"
"\thMsgFont 0x%08lp\n"
"\tatomContextHelpIdProp 0x%08lx\n",
(LONG)ReadField(ptCursor.x),
(LONG)ReadField(ptCursor.y),
(int)ReadField(gclBorder),
(UINT)ReadField(dtScroll),
(UINT)ReadField(dtLBSearch),
(UINT)ReadField(dtCaretBlink),
(DWORD)ReadField(dwDefaultHeapBase),
(DWORD)ReadField(dwDefaultHeapSize),
(int)ReadField(wMaxLeftOverlapChars),
(int)ReadField(wMaxRightOverlapChars),
(UINT)ReadField(uiShellMsg),
(int)ReadField(cxSysFontChar),
(int)ReadField(cySysFontChar),
(int)ReadField(cxMsgFontChar),
(int)ReadField(cyMsgFontChar),
psi + ulOffsetTmp,
(ATOM)ReadField(atomIconSmProp),
(ATOM)ReadField(atomIconProp),
ReadField(hIconSmWindows),
ReadField(hIcoWindows),
ReadField(hCaptionFont),
ReadField(hMsgFont),
(ATOM)ReadField(atomContextHelpIdProp));
}
if (opts & OFLAG(h)) {
PTR pshi = 0;
pshi = EvalExp(VAR(gSharedInfo));
if (pshi == 0) {
return TRUE;
}
_InitTypeRead(pshi, SYM(SHAREDINFO));
Print("\nSHAREDINFO @ 0x%p:\n", pshi);
Print("\taheList 0x%p\n", ReadField(aheList));
}
} except (CONTINUE) {
}
return TRUE;
}
#ifdef KERNEL
/***************************************************************************\
* dsms - dump send message structures
*
* dsms - dumps all send message structures
* dsms v - dumps all verbose
* dsms address - dumps specific sms
* dsms v address - dumps verbose
* dsms l [address] - dumps sendlist of sms
*
*
* 06-20-91 ScottLu Created.
* 6/9/1995 SanfordS made to fit stdexts motif
\***************************************************************************/
BOOL Idsms(
DWORD opts,
ULONG64 param1)
{
ULONG64 psms;
ULONG offsetPsmsNext;
ULONG offsetSender;
ULONG offsetReceiver;
UINT c = 0;
UINT cm = 0;
GetFieldOffset(SYM(tagSMS), "psmsNext", &offsetPsmsNext);
GetFieldOffset(SYM(tagSMS), "ptiSender", &offsetSender);
GetFieldOffset(SYM(tagSMS), "ptiReceiver", &offsetReceiver);
if ((opts & (OFLAG(m) | OFLAG(s) | OFLAG(r))) || (param1 == 0)) {
psms = GetGlobalPointer(VAR(gpsmsList));
if (psms == NULL_PTR) {
Print("No send messages currently in the list.\n");
return TRUE;
}
if (opts & OFLAG(c)) {
UINT i = 0;
// just count the messages
SAFEWHILE (psms != 0) {
UINT cPrev = c;
if ((i++ & 0xf) == 0) {
ShowProgress();
}
if (opts & OFLAG(s)) {
if (GetPointer(psms + offsetSender) == param1) {
++c;
}
} else if (opts & OFLAG(r)) {
if (GetPointer(psms + offsetReceiver) == param1) {
++c;
}
} else {
++c;
}
if (c != cPrev && (c % 400) == 0) {
Print("%d (0x%lx)...\n", c, c);
}
psms = GetPointer(psms + offsetPsmsNext);
}
} else if (opts & OFLAG(m)) {
// show messages with msg == param1
SAFEWHILE (psms != NULL_PTR) {
UINT uMsg;
c++;
//move(sms, psms);
GetFieldValue(psms, SYM(tagSMS), "UINT", uMsg);
if (uMsg == (UINT)param1) {
cm++;
Idsms(opts & ~OFLAG(m), psms);
}
psms = GetPointer(psms + offsetPsmsNext);
}
Print("%d messages == 0x%x (out of a total of %d).\n", cm, (UINT)param1, c);
return TRUE;
} else {
SAFEWHILE (psms != NULL_PTR) {
if (param1 == NULL_PTR ||
((opts & OFLAG(s)) && GetPointer(psms + offsetSender) == param1) ||
((opts & OFLAG(r)) && GetPointer(psms + offsetReceiver) == param1)) {
c++;
DEBUGPRINT("calling Idsms(opts=%x, psms=%p)\n", opts, psms);
if (!Idsms(opts & ~(OFLAG(s) | OFLAG(r)), psms)) {
DEBUGPRINT("error!\n");
Print("%d (0x%lx) messages.\n", c, c);
return FALSE;
}
}
psms = GetPointer(psms + offsetPsmsNext);
}
}
Print("%d (0x%lx) messages.\n", c, c);
return TRUE;
}
psms = param1;
Print("PSMS @ 0x%p\n", psms);
_InitTypeRead(psms, SYM(tagSMS));
Print("SEND: ");
if (ReadField(ptiSender) != NULL_PTR) {
Idt(OFLAG(p), ReadField(ptiSender));
} else if (ReadField(ptiCallBackSender) != NULL_PTR) {
Print("*");
Idt(OFLAG(p), ReadField(ptiCallBackSender));
} else {
Print("NULL\n");
}
Print("RECV:");
if (ReadField(ptiReceiver) != NULL_PTR) {
Print(" ");
Idt(OFLAG(p), ReadField(ptiReceiver));
} else {
Print("NULL\n");
}
if (opts & OFLAG(v)) {
char ach[80];
UINT message = (UINT)ReadField(message);
Print("\tpsmsNext 0x%08p\n", ReadField(psmsNext));
if (IsChk()) {
Print("\tpsmsSendList 0x%p\n"
"\tpsmsSendNext 0x%p\n",
ReadField(psmsSendList),
ReadField(psmsSendNext));
}
Print("\tpsmsReceiveNext 0x%08p\n"
"\ttSent 0x%08lx\n"
"\tptiSender 0x%08p\n"
"\tptiCallBackSender 0x%08p\n"
"\tptiReceiver 0x%08p\n"
"\tlRet 0x%08p\n"
"\tflags %s\n"
"\twParam 0x%08p\n"
"\tlParam 0x%08p\n"
"\tmessage 0x%08lx %s\n",
ReadField(psmsReceiveNext),
(DWORD)ReadField(tSent),
ReadField(ptiSender),
ReadField(ptiCallBackSender),
ReadField(ptiReceiver),
ReadField(lRet),
GetFlags(GF_SMS, (WORD)ReadField(flags), NULL, TRUE),
ReadField(wParam),
ReadField(lParam),
message, GetWindowMessageNameInternal(message));
DebugGetWindowTextA(ReadField(spwnd), ach, ARRAY_SIZE(ach));
Print("\tspwnd 0x%08p \"%s\"\n", ReadField(spwnd), ach);
} else if (opts & OFLAG(w)) {
// a bit of verbose
char ach[80];
DebugGetWindowTextA(ReadField(spwnd), ach, ARRAY_SIZE(ach));
Print(" MSG: %08lx %08p %08p / lRet: %08p / tSend: %08lx\n",
(DWORD)ReadField(message), ReadField(wParam), ReadField(lParam),
ReadField(lRet), (DWORD)ReadField(tSent));
Print(" pwnd: %p \"%s\"\n", ReadField(spwnd), ach);
}
#ifdef LATER
if (IsChk()) {
if (opts & OFLAG(l)) {
DWORD idThread;
PTR psmsList; // PSMS
DWORD idThreadSender, idThreadReceiver;
CLIENT_ID Cid;
psmsList = ReadField(psmsSendList);
if (psmsList == NULL_PTR) {
Print("%p : Empty List\n", psms);
} else {
Print("%p : [tidSender](msg)[tidReceiver]\n", psms);
}
SAFEWHILE (psmsList != NULL_PTR) {
PTR ptiSender;
//move(sms, psmsList);
GetFieldValue(psmsList, SYM(tagSMS), ptiSender, ptiSender);
if (ptiSender == NULL_PTR) {
idThread = 0;
} else {
PTR pEThread;
GetFieldValue(ptiSender, SYM(THREADINFO), "pEThread", pETHread);
// up to here
GetEThreadData(ti.pEThread, EThreadCid, &Cid);
idThreadSender = PtrToUlong(Cid.UniqueThread);
}
if (sms.ptiReceiver == NULL_PTR) {
idThread = 0;
} else {
move(ti, sms.ptiReceiver);
GetEThreadData(ti.pEThread, EThreadCid, &Cid);
idThreadReceiver = PtrToUlong(Cid.UniqueThread);
}
Print("%p : [%x](%x)[%x]\n", psmsList, idThreadSender, sms.message,
idThreadReceiver);
if (psmsList == sms.psmsSendNext) {
Print("Loop in list?\n");
return FALSE;
}
psmsList = sms.psmsSendNext;
}
Print("\n");
}
}
#endif
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
/***************************************************************************\
* dt - dump thread
*
* dt - dumps simple thread info of all threads which have queues
* on server
* dt v - dumps verbose thread info of all threads which have queues
* on server
* dt id - dumps simple thread info of single server thread id
* dt v id - dumps verbose thread info of single server thread id
*
* 06-20-91 ScottLu Created.
* 6/9/1995 SanfordS made to fit stdexts motif
\***************************************************************************/
BOOL DumpThread(
DWORD opts,
PTR pEThread)
{
WCHAR ach[256];
PTR pq;
PTR ppi;
PTR pEThreadT;
PTR pti = NULL_PTR;
PTR pcti;
CLIENTTHREADINFO cti;
PTR psms;
ULONG64 ProcessId;
PTR pEProcess;
ULONG64 ThreadId;
GetFieldValue(pEThread, "nt!ETHREAD", "Tcb.Win32Thread", pti);
GetFieldValue(pEThread, "nt!ETHREAD", "Cid.UniqueProcess", ProcessId);
GetFieldValue(pEThread, "nt!ETHREAD", "Cid.UniqueThread", ThreadId);
GetFieldValue(pEThread, "nt!ETHREAD", "ThreadsProcess", pEProcess);
if (GetFieldValue(pti, "win32k!W32THREAD", "pEThread", pEThreadT)) {
if (!(opts & OFLAG(g))) {
Print(" s %-2d et 0x%p t 0x???????? q 0x???????? i %2x.%-3lx <unknown name>\n",
GetProcessSessionId(pEProcess),
pEThread,
(ULONG)ProcessId,
(ULONG)ThreadId);
}
return TRUE;
}
if (pEThreadT != pEThread || pti == 0) {
return FALSE;
} else { // Good thread
/*
* Print out simple thread info if this is in simple mode. Print
* out queue info if in verbose mode (printing out queue info
* also prints out simple thread info).
*/
if (!(opts & OFLAG(v))) {
PWCHAR pwch;
GetAppName(pEThread, pti, ach, sizeof(ach));
pwch = wcsrchr(ach, L'\\');
if (pwch == NULL_PTR) {
pwch = ach;
} else {
pwch++;
}
GetFieldValue(pti, SYM(THREADINFO), "pq", pq);
GetFieldValue(pti, SYM(THREADINFO), "ppi", ppi);
Print(" s %-2d et 0x%p t 0x%p q 0x%p ppi 0x%p i %2x.%-3lx %ws\n",
GetProcessSessionId(pEProcess),
pEThread,
pti,
pq,
ppi,
(ULONG)ProcessId,
(ULONG)ThreadId,
pwch);
/*
* Dump thread input state if required
*/
if (opts & OFLAG(s)) {
#define DT_INDENT "\t"
GetFieldValue(pti, SYM(THREADINFO), "pcti", pcti);
move(cti, pcti);
if (cti.fsWakeMask == 0) {
Print(DT_INDENT "Not waiting for USER input events.\n");
} else if ((cti.fsWakeMask & (QS_ALLINPUT | QS_EVENT)) == (QS_ALLINPUT | QS_EVENT)) {
Print(DT_INDENT "Waiting for any USER input event (== in GetMessage).\n");
} else if ((cti.fsWakeMask == (QS_SMSREPLY | QS_SENDMESSAGE))
|| (cti.fsWakeMask == QS_SMSREPLY)) {
GetFieldValue(pti, SYM(THREADINFO), "psmsSent", psms);
_InitTypeRead(psms, SYM(SMS));
Print(DT_INDENT "Waiting on thread 0x%p to reply to this SendMessage:\n", ReadField(ptiReceiver));
Print(DT_INDENT "pwnd:0x%p message:%#lx wParam:0x%p lParam:0x%p\n",
ReadField(pwnd), (UINT)ReadField(message), ReadField(wParam), ReadField(lParam));
if (cti.fsChangeBits & QS_SMSREPLY) {
Print(DT_INDENT "The receiver thread has replied to the message.\n");
}
} else {
Print(DT_INDENT "Waiting for: %s\n",
GetFlags(GF_QS, (WORD)cti.fsWakeMask, NULL, TRUE));
}
}
} else {
Idti(0, pti);
Print("--------\n");
}
}
return TRUE;
}
typedef struct _THREAD_DUMP_CONTEXT {
DWORD opts;
ULONG64 ThreadToDump;
} THREAD_DUMP_CONTEXT;
ULONG
DumpThreadsCallback (
PFIELD_INFO NextThread,
PVOID Context)
{
PTR pEThread = NextThread->address;
ULONG64 ThreadId;
THREAD_DUMP_CONTEXT *pTDC = (THREAD_DUMP_CONTEXT *)Context;
PTR UserProbeAddress;
ULONG Result;
//
// Read the user probe address from the target system.
//
// N.B. The user probe address is constant on MIPS, Alpha, and the PPC.
// On the x86, it may not be defined for the target system if it
// does not contain the code to support 3gb of user address space.
//
UserProbeAddress = GetExpression("nt!MmUserProbeAddress");
if ((UserProbeAddress == 0) ||
(ReadMemory(UserProbeAddress,
&UserProbeAddress,
sizeof(UserProbeAddress),
&Result) == FALSE)) {
UserProbeAddress = 0x7fff0000;
}
/*
* ThreadToDump is either 0 (all windows threads) or its
* a TID ( < UserProbeAddress or its a pEThread.
*/
GetFieldValue(pEThread, "nt!ETHREAD", "Cid.UniqueThread", ThreadId);
if (pTDC->ThreadToDump == 0 ||
(pTDC->ThreadToDump < UserProbeAddress &&
pTDC->ThreadToDump == ThreadId) ||
(pTDC->ThreadToDump >= UserProbeAddress &&
pTDC->ThreadToDump == pEThread)) {
if (!DumpThread(pTDC->opts, pEThread) && pTDC->ThreadToDump != 0) {
Print("Sorry, EThread %p is not a Win32 thread.\n",
pEThread);
}
if (pTDC->ThreadToDump != 0) {
return TRUE;
}
} // Chosen Thread
return FALSE;
}
VOID DumpProcessThreads(
DWORD opts,
PTR pEProcess,
ULONG64 ThreadToDump)
{
PTR pW32Process;
ULONG64 NextThread;
THREAD_DUMP_CONTEXT TDC = {
opts,
ThreadToDump
};
/*
* Dump threads of Win32 Processes only
*/
if ((GetFieldValue(pEProcess, "nt!EPROCESS", "Win32Process", pW32Process))
|| (pW32Process == 0)) {
return;
}
GetFieldValue(pEProcess, "nt!EPROCESS", "Pcb.ThreadListHead.Flink", NextThread);
ListType("nt!ETHREAD", NextThread, 1, "Tcb.ThreadListEntry.Flink", &TDC, DumpThreadsCallback);
}
ULONG
DumpProcessThreadsCallback (
PFIELD_INFO NextProcess,
PVOID Context)
{
THREAD_DUMP_CONTEXT *pTDC = (THREAD_DUMP_CONTEXT *)Context;
DumpProcessThreads(pTDC->opts, NextProcess->address, pTDC->ThreadToDump);
return FALSE;
}
BOOL Idt(
DWORD opts,
ULONG64 param1)
{
ULONG64 ThreadToDump;
ULONG64 NextProcess;
ULONG64 ProcessHead;
PTR pEThread;
PTR pti;
THREAD_DUMP_CONTEXT TDC;
ThreadToDump = param1;
/*
* If its a pti, validate it, and turn it into and idThread.
*/
if (opts & OFLAG(p)) {
if (!param1) {
Print("Expected a pti parameter.\n");
return FALSE;
}
pti = FIXKP(param1);
if (pti == 0) {
Print("WARNING: bad pti given!\n");
pti = param1;
} else {
GetFieldValue(pti, SYM(tagTHREADINFO), "pEThread", pEThread);
if (!DumpThread(opts, pEThread)) {
/*
* This thread either doesn't have a pti or something
* is whacked out. Just skip it if we want all
* threads.
*/
Print("Sorry, EThread %p is not a Win32 thread.\n",
pEThread);
return FALSE;
}
return TRUE;
}
}
/*
* If he just wants the current thread, located it.
*/
if (opts & OFLAG(c)) {
Print("Current Thread:");
GetCurrentThreadAddr(dwProcessor, &ThreadToDump);
if (ThreadToDump == 0) {
Print("Unable to get current thread pointer.\n");
return FALSE;
}
pEThread = ThreadToDump;
if (!DumpThread(opts, pEThread)) {
/*
* This thread either doesn't have a pti or something
* is whacked out. Just skip it if we want all
* threads.
*/
Print("Sorry, EThread %p is not a Win32 thread.\n",
pEThread);
return FALSE;
}
return TRUE;
} else if (ThreadToDump == 0) {
Print("**** NT ACTIVE WIN32 THREADINFO DUMP ****\n");
}
ProcessHead = EvalExp("PsActiveProcessHead");
if (!ProcessHead) {
Print("Unable to get value of PsActiveProcessHead\n");
return FALSE;
}
if (GetFieldValue(ProcessHead, "nt!LIST_ENTRY", "Flink", NextProcess)) {
Print("Unable to get value of PsActiveProcessHead\n");
return FALSE;
}
if (NextProcess == 0) {
Print("PsActiveProcessHead->Flink is NULL!\n");
return FALSE;
}
TDC.opts = opts;
TDC.ThreadToDump = ThreadToDump;
ListType("nt!EPROCESS", NextProcess, 1, "ActiveProcessLinks.Flink", &TDC, DumpProcessThreadsCallback);
if (opts & OFLAG(c)) {
Print("%p is not a windows thread.\n", ThreadToDump);
}
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
/***************************************************************************\
* dp - dump process
*
*
* 06-27-97 GerardoB Created.
\***************************************************************************/
BOOL DumpProcess(
DWORD opts,
PTR pEProcess)
{
WCHAR ach[256];
ULONG W32PF_Flags;
PTR ppi;
ULONG ulSessionId;
ULONG64 ulUniqueProcessId;
PTR pEProcessT;
GetFieldValue(pEProcess, "nt!EPROCESS", "Win32Process", ppi);
GetFieldValue(pEProcess, "nt!EPROCESS", "UniqueProcessId", ulUniqueProcessId);
_GetProcessSessionId(pEProcess, &ulSessionId);
if (GetFieldValue(ppi, "win32k!W32PROCESS", "Process", pEProcessT)) {
Print("sid %2d ep 0x%p p 0x???????? f 0x???????? i %3I64x <unknown name>\n",
ulSessionId,
pEProcess,
ulUniqueProcessId);
return TRUE;
}
if (pEProcessT != pEProcess || ppi == 0) {
return FALSE;
} else { // Good process
/*
* Print out simple process info if this is in simple mode.
*/
if (!(opts & OFLAG(v))) {
PWCHAR pwch;
GetProcessName(pEProcess, ach);
pwch = wcsrchr(ach, L'\\');
if (pwch == NULL) {
pwch = ach;
} else {
pwch++;
}
GetFieldValue(ppi, "win32k!W32PROCESS", "W32PF_Flags", W32PF_Flags);
Print("sid %2d ep 0x%p p 0x%p f 0x%08lx i %3I64x %ws\n",
ulSessionId,
pEProcess,
ppi,
W32PF_Flags,
ulUniqueProcessId,
pwch);
} else {
Idpi(0, ppi);
Print("--------\n");
}
/*
* Dump all threads if required
*/
if (opts & OFLAG(t)) {
DumpProcessThreads(opts, pEProcess, 0);
}
}
return TRUE;
}
typedef struct _PROCESS_DUMP_CONTEXT {
DWORD opts;
ULONG64 ProcessToDump;
} PROCESS_DUMP_CONTEXT;
ULONG
DumpProcessCallback(
PFIELD_INFO NextProcess,
PVOID Context)
{
ULONG64 pEProcess = NextProcess->address;
ULONG64 pW32Process;
ULONG64 ulUniqueProcessId;
PROCESS_DUMP_CONTEXT *pPDC = (PROCESS_DUMP_CONTEXT *)Context;
ULONG64 UserProbeAddress;
ULONG Result;
//
// Read the user probe address from the target system.
//
// N.B. The user probe address is constant on MIPS, Alpha, and the PPC.
// On the x86, it may not be defined for the target system if it
// does not contain the code to support 3gb of user address space.
//
UserProbeAddress = GetExpression("nt!MmUserProbeAddress");
if ((UserProbeAddress == 0) ||
(ReadMemory(UserProbeAddress,
&UserProbeAddress,
sizeof(UserProbeAddress),
&Result) == FALSE)) {
UserProbeAddress = 0x7fff0000;
}
/*
* Dump threads of Win32 Processes only
*/
if (GetFieldValue(pEProcess, "nt!EPROCESS", "Win32Process", pW32Process) || pW32Process == 0) {
return FALSE;
}
GetFieldValue(pEProcess, "nt!EPROCESS", "UniqueProcessId", ulUniqueProcessId);
/*
* ProcessToDump is either 0 (all windows processes) or its
* a TID ( < UserProbeAddress or its a pEPRocess.
*/
if (pPDC->ProcessToDump == 0 ||
(pPDC->ProcessToDump < UserProbeAddress &&
pPDC->ProcessToDump == ulUniqueProcessId) ||
(pPDC->ProcessToDump >= UserProbeAddress &&
pPDC->ProcessToDump == pEProcess)) {
if (!DumpProcess(pPDC->opts, pEProcess) && (pPDC->ProcessToDump != 0)) {
Print("Sorry, EProcess %p is not a Win32 process.\n",
pEProcess);
}
if (pPDC->ProcessToDump != 0) {
return TRUE;
}
}
return FALSE;
}
BOOL Idp(
DWORD opts,
ULONG64 param1)
{
ULONG64 ProcessToDump;
PTR ppi;
PTR pEProcess;
ULONG64 NextProcess;
ULONG64 ProcessHead;
PROCESS_DUMP_CONTEXT PDC;
ProcessToDump = param1;
/*
* If it's a ppi, validate it.
*/
if (opts & OFLAG(p)) {
if (!param1) {
Print("Expected a ppi parameter.\n");
return FALSE;
}
ppi = FIXKP(param1);
if (ppi == 0) {
Print("WARNING: bad ppi given!\n");
ppi = param1;
} else {
GetFieldValue(ppi, "win32k!W32PROCESS", "Process", pEProcess);
if (!DumpProcess(opts, pEProcess)) {
Print("EProcess %p is not a Win32 process.\n", pEProcess);
return FALSE;
}
return TRUE;
}
}
/*
* If he just wants the current process, locate it.
*/
if (opts & OFLAG(c)) {
Print("Current Process: ");
GetCurrentProcessAddr(dwProcessor, 0, &ProcessToDump);
if (ProcessToDump == 0) {
Print("Unable to get current process pointer.\n");
return FALSE;
}
pEProcess = ProcessToDump;
if (!DumpProcess(opts, pEProcess)) {
Print("Sorry, EProcess %p is not a Win32 process.\n", pEProcess);
return FALSE;
}
return TRUE;
/*
* else he must want all window threads.
*/
} else if (ProcessToDump == 0) {
Print("**** NT ACTIVE WIN32 PROCESSINFO DUMP ****\n");
}
ProcessHead = EvalExp("PsActiveProcessHead");
if (!ProcessHead) {
Print("Unable to get value of PsActiveProcessHead\n");
return FALSE;
}
if (GetFieldValue(ProcessHead, "nt!LIST_ENTRY", "Flink", NextProcess)) {
Print("Unable to get value of PsActiveProcessHead\n");
return FALSE;
}
if (NextProcess == 0) {
Print("PsActiveProcessHead->Flink is NULL!\n");
return FALSE;
}
PDC.opts = opts;
PDC.ProcessToDump = ProcessToDump;
ListType("nt!EPROCESS", NextProcess, 1, "ActiveProcessLinks.Flink", &PDC, DumpProcessCallback);
if (opts & OFLAG(c)) {
Print("%p is not a windows process.\n", ProcessToDump);
}
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
/***************************************************************************\
* dtdb - dump TDB
*
* dtdb address - dumps TDB structure at address
*
* 14-Sep-1993 DaveHart Created.
* 6/9/1995 SanfordS made to fit stdexts motif
\***************************************************************************/
ULONG
dtdbCallback(
PTR pti,
PVOID Data)
{
PTR ptdb;
UNREFERENCED_PARAMETER(Data);
GetFieldValue(pti, SYM(THREADINFO), "ptdb", ptdb);
SAFEWHILE (ptdb) {
Idtdb(0, ptdb);
GetFieldValue(ptdb, SYM(TDB), "ptdbNext", ptdb);
}
return FALSE;
}
BOOL Idtdb(
DWORD opts,
ULONG64 param1)
{
PTR ptdb;
UNREFERENCED_PARAMETER(opts);
if (param1 == 0) {
Print("Dumping all ptdbs:\n");
ForEachPti(dtdbCallback, NULL);
return TRUE;
}
ptdb = param1;
if (ptdb == 0) {
Print("Must supply a TDB address.\n");
return FALSE;
}
_InitTypeRead(ptdb, SYM(TDB));
Print("TDB (non preemptive scheduler task database) @ 0x%p\n", ptdb);
Print("\tptdbNext 0x%p\n", ReadField(ptdbNext));
Print("\tnEvents 0x%08lx\n", (ULONG)ReadField(nEvents));
Print("\tnPriority 0x%08lx\n", (ULONG)ReadField(nPriority));
Print("\tpti 0x%p\n", ReadField(pti));
return TRUE;
}
#endif // KERNEL
#ifndef KERNEL
/************************************************************************\
* Icbp
*
* Breaks into the debugger in context of csrss.exe.
*
* fSuccess
*
* 6/1/98 JerrySh
\************************************************************************/
BOOL Icbp(
VOID)
{
DWORD dwProcessId;
DWORD dwThreadId;
BOOL fServerProcess;
USER_API_MSG m;
PACTIVATEDEBUGGERMSG a = &m.u.ActivateDebugger;
moveExpValue(&fServerProcess, VAR(gfServerProcess));
if (fServerProcess) {
Print("Already debugging server process!\n");
} else {
/*
* Get the process and thread ID of a CSRSS thread.
*/
dwThreadId = GetWindowThreadProcessId(GetDesktopWindow(), &dwProcessId);
a->ClientId.UniqueProcess = LongToHandle(dwProcessId);
a->ClientId.UniqueThread = LongToHandle(dwThreadId);
/*
* Tell CSRSS to break on itself.
*/
CsrClientCallServer((PCSR_API_MSG)&m,
NULL,
CSR_MAKE_API_NUMBER(USERSRV_SERVERDLL_INDEX, UserpActivateDebugger),
sizeof(*a));
}
return TRUE;
}
#endif // !KERNEL
#ifdef KERNEL
/***************************************************************************\
* dkl - dump keyboard layout
*
* dkl address - dumps keyboard layout structure at address
*
* 05/21/95 GregoryW Created.
\***************************************************************************/
const char* GetCharSetText(
const BYTE bCharSet)
{
static struct _tagBASECHARSET {
const char* pstrCS;
DWORD dwValue;
} const CrackCS[] = {
{"ANSI_CHARSET" ,0 },
{"DEFAULT_CHARSET" ,1 },
{"SYMBOL_CHARSET" ,2 },
{"SHIFTJIS_CHARSET" ,128 },
{"HANGEUL_CHARSET" ,129 },
{"GB2312_CHARSET" ,134 },
{"CHINESEBIG5_CHARSET" ,136 },
{"OEM_CHARSET" ,255 },
{"JOHAB_CHARSET" ,130 },
{"HEBREW_CHARSET" ,177 },
{"ARABIC_CHARSET" ,178 },
{"GREEK_CHARSET" ,161 },
{"TURKISH_CHARSET" ,162 },
{"THAI_CHARSET" ,222 },
{"EASTEUROPE_CHARSET" ,238 },
{"RUSSIAN_CHARSET" ,204 },
{"MAC_CHARSET" ,77 }
};
UINT i;
for (i = 0; i < ARRAY_SIZE(CrackCS); ++i) {
if (CrackCS[i].dwValue == bCharSet) {
break;
}
}
if (i < ARRAY_SIZE(CrackCS)) {
return CrackCS[i].pstrCS;
}
return "ILLEGAL VALUE";
}
BOOL DumpKF(
DWORD opts,
DWORD n,
PTR spkf,
BOOL fActive)
{
ULONG offTmp;
PTR pKbdTbl;
DWORD fLocaleFlags;
WCHAR awchKF[9]; // size should match KBDFILE::awchKF
WCHAR awchDllName[32]; // size should match KBDFILE::awchDllName
DWORD dwType, dwSubType;
PTR pDeadKey;
if (spkf == 0) {
Print(" spkf 0x%p (NONE!)\n", NULL_PTR);
return TRUE;
}
_InitTypeRead(spkf, SYM(tagKBDFILE));
Print(" %c" "spkf[%02x] 0x%p (cLockObj = %d)\n",
fActive ? '*' : ' ',
n, spkf, ReadField(head.cLockObj));
if (opts & OFLAG(v)) {
Print(" pkfNext 0x%p\n", ReadField(pkfNext));
GetFieldOffset(SYM(tagKBDFILE), "awchKF", &offTmp);
if (offTmp) {
tryMoveBlock(awchKF, spkf + offTmp, sizeof(awchKF));
awchKF[ARRAY_SIZE(awchKF) - 1] = 0;
Print(" awchKF[] L\"%ws\"\n", awchKF);
}
}
GetFieldOffset(SYM(tagKBDFILE), "awchDllName", &offTmp);
if (offTmp) {
tryMoveBlock(awchDllName, spkf + offTmp, sizeof(awchDllName));
awchDllName[ARRAY_SIZE(awchDllName) - 1] = 0;
Print(" DllName[] L\"%ws\"\n", awchDllName);
}
pKbdTbl = ReadField(pKbdTbl);
Print(" pKbdTbl 0x%p\n", pKbdTbl);
GetFieldValue(pKbdTbl, SYM(tagKbdLayer), "dwType", dwType);
GetFieldValue(pKbdTbl, SYM(tagKbdLayer), "dwSubType", dwSubType);
Print(" Type:Sub (%x:%x)\n", dwType, dwSubType);
GetFieldValue(pKbdTbl, SYM(tagKbdLayer), "pDeadKey", pDeadKey);
if (opts & OFLAG(v)) {
Print(" hBase 0x%08lx\n", ReadField(hBase));
/*
* Dump pKbdTbl
*/
GetFieldValue(pKbdTbl, SYM(tagKbdLayer), "fLocaleFlags", fLocaleFlags);
Print(" pDeadKey: 0x%p\n", pDeadKey);
Print(" fLocaleFlags 0x%08lx\n", fLocaleFlags);
if (opts & OFLAG(d)) {
Iddk(OFLAG(i), pKbdTbl);
}
}
return TRUE;
}
typedef struct {
PTR hkl;
UINT n;
} KLCOUNT, *PKLCOUNT;
typedef struct {
DWORD opts;
KLCOUNT kl[128];
} KLCALLBACKINFO, *PKLCALLBACKINFO;
ULONG WDBGAPI ThreadKLCallback(PTR pti, PVOID Data)
{
PTR pkl;
PTR hkl, hklPrev;
PKLCALLBACKINFO pInfo = (PKLCALLBACKINFO)Data;
UINT i;
_InitTypeRead(pti, SYM(THREADINFO));
pkl = ReadField(spklActive);
hklPrev = ReadField(hklPrev);
Print(" pti 0x%p ", pti);
GetFieldValue(pkl, SYM(tagKL), "hkl", hkl);
Print(" spklActive %p hkl %08x (prev: %08x)\n", pkl, (DWORD)hkl, (DWORD)hklPrev);
/*
* Count the KL usage.
*/
for (i = 0; i < ARRAY_SIZE(pInfo->kl); ++i) {
if (pInfo->kl[i].hkl == 0) {
pInfo->kl[i].hkl = hkl;
++pInfo->kl[i].n;
break;
} else if (pInfo->kl[i].hkl == hkl) {
++pInfo->kl[i].n;
break;
}
}
return FALSE;
}
ULONG WDBGAPI KLProcessCallback(
PTR ppi,
PVOID Data)
{
PKLCALLBACKINFO pInfo = (PKLCALLBACKINFO)Data;
PTR pEProcess;
WCHAR awchProcessName[MAX_PATH];
PTI_CONTEXT ptic;
W32PID W32Pid;
GetFieldValue(ppi, SYM(_W32PROCESS), "Process", pEProcess);
if (!GetProcessName(pEProcess, awchProcessName)) {
awchProcessName[0] = 0;
}
GetFieldValue(pEProcess, SYM(_W32PROCESS), "W32Pid", W32Pid);
Print("Process 0x%p (ppi 0x%p) [%ws]\n", pEProcess, ppi, awchProcessName);
ptic.CallbackRoutine = ThreadKLCallback;
ptic.Data = Data;
ForEachPtiCallback(ppi, &ptic);
return FALSE;
}
BOOL Idkl(
DWORD opts,
ULONG64 param1)
{
try {
PTR gpkl = NULL_PTR;
PTR pkl, pklAnchor;
PTR pkfActive;
UINT i, nTables;
UINT iBaseCharset;
DWORD dwFontSigs;
if (opts & OFLAG(k)) {
/*
* Dump all the thread and its KL information.
*/
KLCALLBACKINFO info;
if (param1) {
return FALSE;
}
RtlZeroMemory(&info, sizeof info);
info.opts = opts & ~OFLAG(k);
ForEachPpi(KLProcessCallback, &info);
// Print the summary.
Print("\nSummary:\n");
for (i = 0; i < ARRAY_SIZE(info.kl) && info.kl[i].hkl; ++i) {
Print("%08x 0n%d\n", (DWORD)info.kl[i].hkl, info.kl[i].n);
}
return TRUE;
}
if (param1 == 0) {
BYTE bCharSet;
gpkl = GetGlobalPointer(VAR(gpkl));
if (opts & OFLAG(a)) {
Print("Using gspklBaseLayout\n");
pkl = GetGlobalPointer(VAR(gspklBaseLayout));
} else {
Print("Using gpkl\n");
pkl = gpkl;
}
moveExpValue(&bCharSet, VAR(gSystemCPCharSet));
Print("gpKL:%p gSystemCPCharSet:%s\n", gpkl, GetCharSetText(bCharSet));
} else {
pkl = FIXKP(param1);
}
if (pkl == NULL_PTR) {
return FALSE;
}
_InitTypeRead(pkl, SYM(tagKL));
Print("KL @ 0x%p (cLockObj = %d) %c\n", pkl, (DWORD)ReadField(head.cLockObj),
pkl == gpkl ? '*' : ' ');
Print(" hkl 0x%08p\n", ReadField(hkl));
Print(" KLID %08x\n", ReadField(dwKLID));
if (opts & OFLAG(v)) {
Print(" pklNext 0x%p\n", ReadField(pklNext));
Print(" pklPrev 0x%p\n", ReadField(pklPrev));
Print(" dwKL_Flags 0x%08p\n", ReadField(dwKL_Flags));
Print(" piiex 0x%p\n", ReadField(piiex));
GetFieldValue(pkl, SYM(tagKL), "dwFontSigs", dwFontSigs);
Print(" dwFontSigs %s\n", GetFlags(GF_CHARSETS, dwFontSigs, NULL, TRUE));
GetFieldValue(pkl, SYM(tagKL), "iBaseCharset", iBaseCharset);
Print(" iBaseCharset %s\n", GetCharSetText((BYTE)iBaseCharset));
}
_InitTypeRead(pkl, SYM(tagKL));
Print(" Codepage %d\n", (WORD)ReadField(CodePage));
pkfActive = ReadField(spkf);
DumpKF(opts, 0, ReadField(spkfPrimary), ReadField(spkfPrimary) == pkfActive);
_InitTypeRead(pkl, SYM(tagKL));
/*
* Dump extra tables
*/
nTables = (UINT)ReadField(uNumTbl);
Print(" Extra Tables: %x\n", nTables);
if (nTables > 0) {
PTR ppkfExtra = ReadField(pspkfExtra);
for (i = 0; i < nTables && !IsCtrlCHit(); ++i) {
PTR pkf;
ReadPointer(ppkfExtra + GetTypeSize("PVOID") * i, &pkf);
DumpKF(opts, i + 1, pkf, pkf == pkfActive);
}
}
if (opts & OFLAG(a)) {
PTR pklNext;
opts &= ~OFLAG(a);
pklAnchor = pkl;
GetFieldValue(pkl, SYM(tagKL), "pklNext", pklNext);
SAFEWHILE (pklNext && pklNext != pklAnchor) {
pkl = pklNext;
if (!Idkl(opts, pkl)) {
return FALSE;
}
if (GetFieldValue(pkl, SYM(tagKL), "pklNext", pklNext)) {
break;
}
}
}
} except (CONTINUE) {
}
return TRUE;
}
/***************************************************************************\
* ddk - dump deadkey table
*
* ddk address - dumps deadkey table address
*
* 09/28/95 GregoryW Created.
\***************************************************************************/
BOOL Iddk(
DWORD opts,
ULONG64 param1)
{
try {
PTR pKbdTbl; // KBDTABLES
PTR pDeadKey; // DEADKEY
ULONG cbDeadKey;
if (param1 == NULL_PTR) {
Print("Expected address\n");
return FALSE;
}
cbDeadKey = GetTypeSize(SYM(DEADKEY));
if (cbDeadKey == 0) {
Print("cannot get sizeof(DEADKEY), invalid symbol?\n");
return TRUE;
}
pKbdTbl = param1;
GetFieldValue(pKbdTbl, SYM(KBDTABLES), "pDeadKey", pDeadKey);
if (pDeadKey == NULL_PTR) {
Print("No deadkey table for this layout\n");
return TRUE;
}
SAFEWHILE (TRUE) {
DWORD dwBoth;
WCHAR wchComposed;
USHORT uFlags;
_InitTypeRead(pDeadKey, SYM(DEADKEY));
dwBoth = DOWNCAST(DWORD, ReadField(dwBoth));
if (dwBoth == 0) {
break;
}
wchComposed = DOWNCAST(WCHAR, ReadField(wchComposed));
uFlags = DOWNCAST(USHORT, ReadField(uFlags));
Print("%*c d 0x%04x ch 0x%04x => 0x%04x, f=%x\n", (opts & OFLAG(i)) ? 8 : 0, ' ', HIWORD(dwBoth), LOWORD(dwBoth), wchComposed, uFlags);
pDeadKey += cbDeadKey;
}
} except (CONTINUE) {
}
return TRUE;
}
#endif
#ifdef KERNEL
ULONG dtiFromPpiCallback(
ULONG64 ppi,
PVOID Data)
{
ULONG64 pti;
UNREFERENCED_PARAMETER(Data);
GetFieldValue(ppi, SYM(PROCESSINFO), "ptiList", pti);
SAFEWHILE (pti != 0) {
Print("pti ==> 0x%p [ppi = 0x%p]\n", pti, ppi);
Idti(0, pti);
GetFieldValue(pti, SYM(THREADINFO), "ptiSibling", pti);
}
return FALSE;
}
/***************************************************************************\
* dti - dump THREADINFO
*
* dti address - dumps THREADINFO structure at address
*
* 11-13-91 DavidPe Created.
* 6/9/1995 SanfordS made to fit stdexts motif
\***************************************************************************/
BOOL Idti(
DWORD opts,
ULONG64 param1)
{
PTR pti, pwinsta;
CLIENTTHREADINFO cti;
PTR pThread;
PTR pEProcess;
UCHAR PriorityClass;
WCHAR szDesktop[256], szWindowStation[256];
UNREFERENCED_PARAMETER(opts);
if (param1 == 0) {
PTR pq;
if (opts & OFLAG(c)) {
// !dti -c: Use the current thread.
pti = GetGlobalPointer(VAR(gptiCurrent));
} else if (opts & OFLAG(f)) {
pq = GetGlobalPointer(VAR(gpqForeground));
if (pq == 0) {
Print("No foreground queue!\n");
return FALSE;
}
GetFieldValue(pq, SYM(Q), "ptiKeyboard", pti);
} else {
Print("**** NT ACTIVE WIN32 THREADINFO DUMP ****\n");
ForEachPpi(dtiFromPpiCallback, NULL);
return TRUE;
}
} else {
pti = FIXKP(param1);
}
if (pti == 0) {
return FALSE;
}
Idt(OFLAG(p), pti);
_InitTypeRead(pti, SYM(tagTHREADINFO));
move(cti, ReadField(pcti));
Print("PTHREADINFO @ 0x%p\n", pti);
Print("\tPtiLink.Flink 0x%p\n"
"\tptl 0x%p\n"
"\tptlW32 0x%p\n"
"\tppi 0x%p\n"
"\tpq 0x%p\n"
"\tspklActive 0x%p\n"
"\tmlPost.pqmsgRead 0x%p\n"
"\tmlPost.pqmsgWriteLast 0x%p\n"
"\tmlPost.cMsgs 0x%08lx\n",
ReadField(PtiLink.Flink),
ReadField(ptl),
ReadField(ptlW32),
ReadField(ppi),
ReadField(pq),
ReadField(spklActive),
ReadField(mlPost.pqmsgRead),
ReadField(mlPost.pqmsgWriteLast),
(ULONG)ReadField(mlPost.cMsgs));
Print("\tspwndDefaultIme 0x%p\n"
"\tspDefaultImc 0x%p\n"
"\thklPrev 0x%08lx\n",
ReadField(spwndDefaultIme),
ReadField(spDefaultImc),
ReadField(hklPrev));
Print("\trpdesk 0x%p",
ReadField(rpdesk));
// If the pti has a desktop, display it and windowstation.
if (ReadField(rpdesk)) {
GetObjectName(ReadField(rpdesk), szDesktop, ARRAY_SIZE(szDesktop));
GetFieldValue(ReadField(rpdesk), SYM(DESKTOP), "rpwinstaParent", pwinsta);
GetObjectName(pwinsta, szWindowStation, ARRAY_SIZE(szWindowStation));
Print(" (%ws\\%ws)", szWindowStation, szDesktop);
}
Print("\n");
Print("\thdesk 0x%08lx\n",
ReadField(hdesk));
Print("\tamdesk 0x%08lx\n",
(ULONG)ReadField(amdesk));
Print("\tpDeskInfo 0x%p\n"
"\tpClientInfo 0x%p\n",
ReadField(pDeskInfo),
ReadField(pClientInfo));
Print("\tTIF_flags %s\n",
GetFlags(GF_TIF, (DWORD)ReadField(TIF_flags), NULL, TRUE));
Print("\tsphkCurrent 0x%p\n"
"\tpEventQueueServer 0x%p\n"
"\thEventQueueClient 0x%p\n",
ReadField(sphkCurrent),
ReadField(pEventQueueServer),
ReadField(hEventQueueClient));
Print("\tfsChangeBits %s\n",
GetFlags(GF_QS, (WORD)cti.fsChangeBits, NULL, TRUE));
Print("\tfsChangeBitsRemoved %s\n",
GetFlags(GF_QS, (WORD)ReadField(fsChangeBitsRemoved), NULL, TRUE));
Print("\tfsWakeBits %s\n",
GetFlags(GF_QS, (WORD)cti.fsWakeBits, NULL, TRUE));
Print("\tfsWakeMask %s\n",
GetFlags(GF_QS, (WORD)cti.fsWakeMask, NULL, TRUE));
Print("\tcPaintsReady 0x%04x\n"
"\tcTimersReady 0x%04x\n"
"\ttimeLast 0x%08lx\n"
"\tptLast.x 0x%08lx\n"
"\tptLast.y 0x%08lx\n"
"\tidLast 0x%p\n",
(ULONG)ReadField(cPaintsReady),
(ULONG)ReadField(cTimersReady),
(ULONG)ReadField(timeLast),
(ULONG)ReadField(ptLast.x),
(ULONG)ReadField(ptLast.y),
ReadField(idLast));
Print("\texitCode 0x%08lx\n"
"\tpSBTrack 0x%p\n"
"\tpsmsSent 0x%p\n"
"\tpsmsCurrent 0x%p\n",
(ULONG)ReadField(exitCode),
ReadField(pSBTrack),
ReadField(psmsSent),
ReadField(psmsCurrent));
Print("\tfsHooks 0x%08lx\n"
"\taphkStart 0x%p l%x\n"
"\tsphkCurrent 0x%p\n",
(ULONG)ReadField(fsHooks),
ReadField(aphkStart), CWINHOOKS,
ReadField(sphkCurrent));
Print("\tpsmsReceiveList 0x%p\n",
ReadField(psmsReceiveList));
Print("\tptdb 0x%p\n"
"\tThread 0x%p\n",
ReadField(ptdb),
ReadField(pEThread));
pThread = ReadField(pEThread);
GetFieldValue(pThread, "nt!ETHREAD", "ThreadsProcess", pEProcess);
GetFieldValue(pEProcess, "nt!EPROCESS", "PriorityClass", PriorityClass);
Print("\t PriorityClass %d\n",
PriorityClass);
_InitTypeRead(pti, SYM(tagTHREADINFO));
Print("\tcWindows 0x%08lx\n"
"\tcVisWindows 0x%08lx\n"
"\tpqAttach 0x%p\n"
"\tiCursorLevel 0x%08lx\n",
(ULONG)ReadField(cWindows),
(ULONG)ReadField(cVisWindows),
ReadField(pqAttach),
(ULONG)ReadField(iCursorLevel));
Print("\tpMenuState 0x%p\n",
ReadField(pMenuState));
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
BOOL ScanThreadlocks(PTR pti, char chType, PTR pvSearch);
ULONG WDBGAPI DumpThreadLocksCallback(PTR pti, PVOID pOpt)
{
UNREFERENCED_PARAMETER(pOpt);
Idtl(OFLAG(t) | OFLAG(x), pti);
return 0;
}
ULONG WDBGAPI ScanThreadLocksCallback(PTR pti, PVOID pOpt)
{
ScanThreadlocks(pti, 'o', *(PTR*)pOpt);
ScanThreadlocks(pti, 'k', *(PTR*)pOpt);
return 0;
}
/***************************************************************************\
* dtl handle|pointer
*
* !dtl <addr> Dumps all THREAD locks for object at <addr>
* !dtl -t <pti> Dumps all THREAD locks made by thread <pti>
* !dtl Dumps all THREAD locks made by all threads
*
* 02/27/1992 ScottLu Created.
* 06/09/1995 SanfordS Made to fit stdexts motif.
\***************************************************************************/
BOOL Idtl(
DWORD opts,
ULONG64 param1)
{
PTR pti;
if (param1 == 0) {
Print("Dumping all thread locks:\n");
Print("pti pObj Caller\n");
ForEachPti(DumpThreadLocksCallback, NULL);
return TRUE;
}
if (opts & OFLAG(t)) {
pti = FIXKP(param1);
if (pti == 0) {
return FALSE;
}
/*
* Regular thread-locked objects.
*/
if (!(opts & OFLAG(x))) { // x is not legal from user - internal only
Print("pti pObj Caller\n");
}
ScanThreadlocks(pti, 'o', 0);
ScanThreadlocks(pti, 'k', 0);
return TRUE;
}
if (!param1) {
return FALSE;
}
Print("Thread Locks for object %p:\n", param1);
Print("pti pObj Caller\n");
ForEachPti(ScanThreadLocksCallback, &param1);
Print("--- End Thread Lock List ---\n");
return TRUE;
}
/*
* Scans all threadlocked objects belonging to thread pti of type chType
* (o == regular objects, k == kernel objects, p == pool). Display each
* threadlock, or if pvSearch is non-NULL, just those locks on the object
* at pvSearch.
*/
BOOL
ScanThreadlocks(
PTR pti,
char chType,
PTR pvSearch)
{
PTR ptl;
if (pti == 0) {
return FALSE;
}
if (_InitTypeRead(pti, SYM(THREADINFO))) {
Print("Idtl: Can't get pti data from %p.\n", (ULONG_PTR)pti);
return FALSE;
}
switch (chType) {
case 'o':
ptl = ReadField(ptl);
break;
case 'k':
ptl = ReadField(ptlW32);
break;
default:
Print("Internal error, bad chType '%c' in ScanThreadlocks\n", chType);
return FALSE;
}
SAFEWHILE (ptl) {
char ach[80];
ULONG64 dwOffset;
if (_InitTypeRead(ptl, SYM(TL))) {
Print("Idtl: Can't get ptl data from %p.\n", (ULONG_PTR)ptl);
return FALSE;
}
if (!pvSearch || ReadField(pobj) == pvSearch) {
Print("0x%p 0x%p", pti, ReadField(pobj));
GetSym(ReadField(pfnCaller), ach, &dwOffset);
Print(" %s", ach);
if (dwOffset) {
Print("+0x%x", (ULONG)dwOffset);
}
if (chType == 'k') {
GetSym(ReadField(pfnFree), ach, &dwOffset);
Print(" (%s)", ach);
if (dwOffset) {
Print("+0x%x", (ULONG)dwOffset);
}
}
Print("\n");
}
ptl = ReadField(next);
}
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
/************************************************************************\
* FindTimerByID
*
* Looks up a timer based upon its ID. Worker function for !dtmr.
*
* 04/10/2001 JasonSch Wrote it.
\************************************************************************/
ULONG64 FindTimerByID(
ULONG64 tmr)
{
ULONG64 ptmr;
ptmr = GetGlobalPointer(VAR(gptmrFirst));
SAFEWHILE (ptmr) {
_InitTypeRead(ptmr, SYM(TIMER));
if (ReadField(nID) == tmr) {
break;
}
ptmr = ReadField(ptmrNext);
}
return ptmr;
}
/************************************************************************\
* Idtmr
*
* Dumps timer structures.
*
* 06/09/1995 SanfordS Created.
* 10/18/2000 Mohamed Port to 64 bit.
* 04/10/2002 JasonSch Added -i option.
\************************************************************************/
BOOL Idtmr(
DWORD opts,
PTR ptmr)
{
PTR pti;
if (ptmr == 0) {
ULONG ulTimerCnt = 0;
ptmr = GetGlobalPointer(VAR(gptmrFirst));
SAFEWHILE (ptmr) {
++ulTimerCnt;
Idtmr(0, ptmr);
Print("\n");
_InitTypeRead(ptmr, SYM(TIMER));
ptmr = ReadField(ptmrNext);
}
Print("0x%x total timers dumped.\n", ulTimerCnt);
return TRUE;
}
/*
* The -i option indicates that ptmr is an ID, not a pointer.
*/
if (opts & OFLAG(i)) {
ULONG64 ptmrT = FindTimerByID(ptmr);
if (ptmrT == 0) {
Print("Couldn't find timer with id 0x%p\n", ptmr);
return TRUE;
}
ptmr = ptmrT;
}
_InitTypeRead(ptmr, SYM(TIMER));
Print("Timer %p:\n"
" ptmrNext = %p\n"
" pti = %p",
ptmr,
ReadField(ptmrNext),
ReadField(pti));
pti = ReadField(pti);
if (pti && _InitTypeRead(pti, SYM(THREADINFO))) {
WCHAR awch[64];
if (GetAppName(ReadField(pEThread), pti, awch, ARRAY_SIZE(awch))) {
ULONG handleProcess, handleThread;
PWCHAR pwch = wcsrchr(awch, L'\\');
if (pwch == NULL) {
pwch = awch;
} else {
pwch++;
}
GetFieldValue(ReadField(pEThread), "nt!ETHREAD", "Cid.UniqueThread", handleProcess);
GetFieldValue(ReadField(pEThread), "nt!ETHREAD", "Cid.UniqueThread", handleThread);
Print(" q %p i %2x.%-3lx %ws",
ReadField(pq),
handleProcess,
handleThread,
pwch);
}
}
_InitTypeRead(ptmr, SYM(TIMER));
Print("\n"
" spwnd = %p",
ReadField(spwnd));
if (ReadField(spwnd)) {
char ach[80];
DebugGetWindowTextA(ReadField(spwnd), ach, ARRAY_SIZE(ach));
Print(" \"%s\"", ach);
}
Print("\n"
" nID = %x\n"
" cmsCountdown = %x\n"
" cmsRate = %x\n"
" flags = %s\n"
" pfn = %p\n"
" ptiOptCreator = %p\n",
(ULONG) ReadField(nID),
(ULONG) ReadField(cmsCountdown),
(ULONG) ReadField(cmsRate),
GetFlags(GF_TMRF, (WORD)ReadField(flags), NULL, TRUE),
ReadField(pfn),
ReadField(ptiOptCreator));
return TRUE;
}
#endif // KERNEL
#ifdef OLD_DEBUGGER
/************************************************************************\
* Idu
*
* Dump unknown object. Does what it can figure out.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Idu(
DWORD opts,
ULONG64 param1)
{
HANDLEENTRY he, *phe;
int i;
DWORD dw;
UNREFERENCED_PARAMETER(opts);
if (param1 == 0) {
FOREACHHANDLEENTRY(phe, he, i)
if (he.bType != TYPE_FREE && tryDword(&dw, FIXKP(he.phead))) {
Idu(OFLAG(x), he.phead);
}
NEXTEACHHANDLEENTRY()
return TRUE;
}
param1 = HorPtoP(FIXKP(param1), -1);
if (param1 == 0) {
return FALSE;
}
if (!getHEfromP(NULL, &he, param1)) {
return FALSE;
}
Print("--- %s object @ 0x%p ---\n", pszObjStr[he.bType], FIXKP(param1));
switch (he.bType) {
case TYPE_WINDOW:
return Idw(0, param1);
case TYPE_MENU:
return Idm(0, param1);
#ifdef KERNEL
case TYPE_CURSOR:
return Idcur(0, param1);
case TYPE_HOOK:
return Idhk(OFLAG(a) | OFLAG(g), NULL);
case TYPE_DDECONV:
case TYPE_DDEXACT:
return Idde(0, param1);
#endif // KERNEL
case TYPE_MONITOR:
// LATER: - add dmon command
case TYPE_CALLPROC:
case TYPE_ACCELTABLE:
case TYPE_SETWINDOWPOS:
case TYPE_DDEACCESS:
default:
Print("not supported.\n", pszObjStr[he.bType]);
}
return TRUE;
}
#ifdef KERNEL
/***************************************************************************\
* dumphmgr - dumps object allocation counts for handle-table.
*
* 10-18-94 ChrisWil Created.
* 6/9/1995 SanfordS made to fit stdexts motif
* 06-18-97 MCostea made it work
\***************************************************************************/
BOOL Idumphmgr(
DWORD opts)
{
PERFHANDLEINFO aLocalHti[TYPE_CTYPES], aLocalPrevHti[TYPE_CTYPES];
PPERFHANDLEINFO pgahti;
LONG lTotalAlloc, lTotalMax, lTotalCurrent;
LONG lPrevTotalAlloc, lPrevTotalMax, lPrevTotalCurrent;
SIZE_T lTotalSize, lPrevTotalSize;
int idx;
pgahti = EvalExp(VAR(gaPerfhti));
if (!pgahti) {
Print("\n!dumphmgr works only with debug versions of win32k.sys\n\n");
return TRUE;
}
move(aLocalHti, pgahti);
pgahti = EvalExp(VAR(gaPrevhti));
if (!pgahti) {
return TRUE;
}
move(aLocalPrevHti, pgahti);
lTotalSize = lTotalAlloc = lTotalMax = lTotalCurrent = 0;
lPrevTotalSize = lPrevTotalAlloc = lPrevTotalMax = lPrevTotalCurrent = 0;
if (aLocalPrevHti[TYPE_WINDOW].lTotalCount) {
Print("\nThe snapshot values come under the current ones\n");
Print("Type Allocated Maximum Count Size\n");
Print("______________________________________________________________________________");
for (idx = 1; idx < TYPE_CTYPES; idx++) {
Print("\n%-15s %8d %-+6d %7d %-+5d %6d %-+5d %9d %-+d",
aszTypeNames[idx],
aLocalHti[idx].lTotalCount, aLocalHti[idx].lTotalCount - aLocalPrevHti[idx].lTotalCount,
aLocalHti[idx].lMaxCount, aLocalHti[idx].lMaxCount - aLocalPrevHti[idx].lMaxCount,
aLocalHti[idx].lCount, aLocalHti[idx].lCount - aLocalPrevHti[idx].lCount,
aLocalHti[idx].lSize, aLocalHti[idx].lSize - aLocalPrevHti[idx].lSize);
if (aLocalPrevHti[TYPE_WINDOW].lTotalCount) {
Print("\n %8d %7d %6d %9d",
aLocalPrevHti[idx].lTotalCount,
aLocalPrevHti[idx].lMaxCount,
aLocalPrevHti[idx].lCount,
aLocalPrevHti[idx].lSize);
lPrevTotalAlloc += aLocalPrevHti[idx].lTotalCount;
lPrevTotalMax += aLocalPrevHti[idx].lMaxCount;
lPrevTotalCurrent += aLocalPrevHti[idx].lCount;
lPrevTotalSize += aLocalPrevHti[idx].lSize;
}
lTotalAlloc += aLocalHti[idx].lTotalCount;
lTotalMax += aLocalHti[idx].lMaxCount;
lTotalCurrent += aLocalHti[idx].lCount;
lTotalSize += aLocalHti[idx].lSize;
}
Print("\n______________________________________________________________________________\n");
Print("Totals %8d %-+6d %7d %-+5d %6d %+-5d %9d %-+d\n",
lTotalAlloc, lTotalAlloc - lPrevTotalAlloc,
lTotalMax, lTotalMax - lPrevTotalMax,
lTotalCurrent, lTotalCurrent - lPrevTotalCurrent,
lTotalSize, lTotalSize - lPrevTotalSize);
Print(" %8d %7d %6d %9d\n",
lPrevTotalAlloc, lPrevTotalMax, lPrevTotalCurrent, lPrevTotalSize);
} else {
Print("Type Allocated Maximum Count Size\n");
Print("______________________________________________________");
for (idx = 1; idx < TYPE_CTYPES; idx++) {
Print("\n%-17s %9d %7d %6d %d",
aszTypeNames[idx],
aLocalHti[idx].lTotalCount,
aLocalHti[idx].lMaxCount,
aLocalHti[idx].lCount,
aLocalHti[idx].lSize);
lTotalAlloc += aLocalHti[idx].lTotalCount;
lTotalMax += aLocalHti[idx].lMaxCount;
lTotalCurrent += aLocalHti[idx].lCount;
lTotalSize += aLocalHti[idx].lSize;
}
Print("\n______________________________________________________\n");
Print("Current totals %9d %7d %6d %d\n",
lTotalAlloc, lTotalMax, lTotalCurrent, lTotalSize);
}
/*
* If the argument-list contains the Snap option,
* then copy the current counts to the previous ones
*/
if (opts & OFLAG(s)) {
(lpExtensionApis->lpWriteProcessMemoryRoutine)(
(ULONG_PTR)&(pgahti[0]),
(PVOID)aLocalHti,
sizeof(aLocalHti),
NULL);
}
return TRUE;
}
#endif // KERNEL
#endif // OLD_DEBUGGER
/************************************************************************\
* dwrWorker
*
* Dumps pwnd structures compactly to show relationships.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL dwrWorker(
PTR pwnd,
int tab)
{
PTR pcls;
PTR lpszAnsiClassName;
PTR pwndChild;
PTR pwndOwner;
ULONG atomClassName;
ULONG atomNVClassName;
if (pwnd == 0) {
return FALSE;
}
do {
pwnd = FIXKP(pwnd);
DebugGetWindowTextA(pwnd, gach1, ARRAY_SIZE(gach1));
GetFieldValue(pwnd, SYM(WND), "pcls", pcls);
GetFieldValue(pcls, SYM(CLS), "atomClassName", atomClassName);
GetFieldValue(pcls, SYM(CLS), "atomNVClassName", atomNVClassName);
GetFieldValue(pcls, SYM(CLS), "lpszAnsiClassName", lpszAnsiClassName);
if (atomNVClassName < 0xC000) {
switch (atomNVClassName) {
case WC_DIALOG:
strcpy(gach1, "WC_DIALOG");
break;
case DESKTOPCLASS:
strcpy(gach1, "DESKTOP");
break;
case SWITCHWNDCLASS:
strcpy(gach1, "SWITCHWND");
break;
case ICONTITLECLASS:
strcpy(gach1, "ICONTITLE");
break;
default:
if (atomNVClassName == 0) {
move(gach1, FIXKP(lpszAnsiClassName));
} else {
sprintf(gach2, "0x%04x", atomNVClassName);
}
}
} else {
DebugGetClassNameA(lpszAnsiClassName, gach2);
}
if (atomClassName && (atomClassName < 0xC000)) {
sprintf(gach3, "0x%04x", atomClassName);
}
Print("%08p%*s [%s|%s|%s]", pwnd, tab, "", gach1, gach2, gach3);
GetFieldValue(pwnd, SYM(WND), "spwndOwner", pwndOwner);
if (pwndOwner != 0) {
Print(" <- Owned by:%08x", FIXKP(pwndOwner));
}
Print("\n");
GetFieldValue(pwnd, SYM(WND), "spwndChild", pwndChild);
if (pwndChild != 0) {
dwrWorker(pwndChild, tab + 2);
}
GetFieldValue(pwnd, SYM(WND), "spwndNext", pwnd);
} SAFEWHILE (pwnd && tab > 0);
return TRUE;
}
/************************************************************************\
* Idw
*
* Dumps pwnd structures
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Idw(
DWORD opts,
ULONG64 param1)
{
WW ww;
PTR lpfnWndProc;
RECT rcWindow;
RECT rcClient;
PTR pcls;
PTR pwnd = param1;
char ach[256];
ULONG64 dwOffset;
ULONG ix;
DWORD tempDWord;
DWORD dwWOW;
try {
if (opts & OFLAG(a)) {
#ifdef KERNEL
PTR pdesk;
PTR pDeskInfo;
PTR pwnd;
WCHAR wach[80];
if (param1 != 0) {
Print("window parameter ignored with -a option.\n");
}
FOREACHDESKTOP(pdesk)
if (!GetFieldValue(pdesk, SYM(DESKTOP), "pDeskInfo", pDeskInfo)) {
GetObjectName(pdesk, wach, ARRAY_SIZE(wach));
Print("\n----Windows for %ws desktop @ 0x%p:\n\n", wach, pdesk);
GetFieldValue(pDeskInfo, SYM(DESKTOPINFO), "spwnd", pwnd);
if (!Idw((opts & ~OFLAG(a)) | OFLAG(p), pwnd)) {
return FALSE;
}
}
NEXTEACHDESKTOP(pdesk)
#else // !KERNEL
PTR pteb = 0;
GetTebAddress(&pteb);
if (pteb) {
ULONG pciOffset;
PTR pdi;
GetFieldOffset(SYM(TEB), "Win32ClientInfo", &pciOffset);
GetFieldValue(pteb + pciOffset, SYM(CLIENTINFO), "pDeskInfo", pdi);
GetFieldValue(pdi, SYM(DESKTOPINFO), "spwnd", pwnd);
return Idw(opts & ~OFLAG(a) | OFLAG(p), FIXKP(pwnd));
}
#endif // !KERNEL
return TRUE;
}
/*
* t is like EnumThreadWindows.
*/
if (opts & OFLAG(t)) {
#ifdef KERNEL
PTR pti, ptiWnd;
PTR pdesk;
PTR pdi;
/*
* Get the desktop's first child window
*/
pti = param1;
if (GetFieldValue(pti, SYM(THREADINFO), "rpdesk", pdesk)
|| GetFieldValue(pdesk, SYM(DESKTOP), "pDeskInfo", pdi)
|| GetFieldValue(pdi, SYM(DESKTOPINFO), "spwnd", pwnd)
|| GetFieldValue(pwnd, SYM(WND), "spwndChild", pwnd)) {
return FALSE;
}
/*
* Walk the sibling chain looking for pwnd owned by pti.
*/
SAFEWHILE (pwnd) {
if (!GetFieldValue(pwnd, SYM(WND), "head.pti", ptiWnd) && (ptiWnd == pti)) {
if (!Idw(opts & ~OFLAG(t), pwnd)) {
return FALSE;
}
}
if (GetFieldValue(pwnd, SYM(WND), "spwndNext", pwnd)) {
return FALSE;
}
}
return TRUE;
#else // !KERNEL
Print("t parameter not supported for NTSD at this point\n");
#endif // !KERNEL
}
/*
* See if the user wants all top level windows.
*/
if (param1 == 0 || opts & (OFLAG(p) | OFLAG(s))) {
/*
* Make sure there was also a window argument if p or s.
*/
if (param1 == 0 && (opts & (OFLAG(p) | OFLAG(s)))) {
Print("Must specify window with '-p' or '-s' options.\n");
return FALSE;
}
if (param1 && (pwnd = HorPtoP(pwnd, TYPE_WINDOW)) == 0) {
return FALSE;
}
if (opts & OFLAG(p)) {
Print("pwndParent = 0x%p\n", pwnd);
if (GetFieldValue(FIXKP(pwnd), SYM(WND), "spwndChild", pwnd)) {
Print("<< Can't get WND >>\n");
return TRUE; // we don't need to have the flags explained!
}
SAFEWHILE (pwnd) {
if (!Idw(opts & ~OFLAG(p), pwnd)) {
return FALSE;
}
GetFieldValue(FIXKP(pwnd), SYM(WND), "spwndNext", pwnd);
}
return TRUE;
} else if (opts & OFLAG(s)) {
GetFieldValue(FIXKP(pwnd), SYM(WND), "spwndParent", pwnd);
return Idw((opts | OFLAG(p)) & ~OFLAG(s), pwnd);
} else {
#ifdef KERNEL
PTR pdesk = NULL_PTR;
PTR pDeskInfo, pwnd;
PTR pti, pq;
pq = GetGlobalPointer(VAR(gpqForeground));
GetFieldValue(pq, SYM(Q), "ptiKeyboard", pti);
GetFieldValue(pti, SYM(THREADINFO), "rpdesk", pdesk);
if (pdesk == 0) {
Print("Foreground thread doesn't have a desktop.\n");
Print("Using grpdeskRitInput ...\n");
pdesk = GetGlobalPointer(SYM(grpdeskRitInput));
if (pdesk == 0) {
Print("grpdeskRitInput is NULL!\n");
return FALSE;
}
GetFieldValue(pdesk, SYM(DESKTOP), "pDeskInfo", pDeskInfo);
GetFieldValue(pDeskInfo, SYM(DESKTOPINFO), "spwnd", pwnd);
} else {
GetFieldValue(pti, SYM(THREADINFO), "pDeskInfo", pDeskInfo);
GetFieldValue(pDeskInfo, SYM(DESKTOPINFO), "spwnd", pwnd);
}
Print("pwndDesktop = 0x%p\n", (ULONG_PTR)pwnd);
return Idw(opts | OFLAG(p), pwnd);
#else // !KERNEL
return Idw(opts | OFLAG(a), 0);
#endif // !KERNEL
}
}
if (param1 && (pwnd = HorPtoP(param1, TYPE_WINDOW)) == 0) {
Print("Idw: 0x%p is not a pwnd.\n", param1);
return FALSE;
}
if (opts & OFLAG(r)) {
dwrWorker(FIXKP(pwnd), 0);
return TRUE;
}
_InitTypeRead(pwnd, SYM(tagWND));
lpfnWndProc = ReadField(lpfnWndProc);
ww.state = (DWORD)ReadField(state);
ww.state2 = (DWORD)ReadField(state2);
ww.ExStyle = (DWORD)ReadField(ExStyle);
ww.style = (DWORD)ReadField(style);
#ifdef KERNEL
/*
* Print simple thread info.
*/
if (ReadField(head.pti)) {
Idt(OFLAG(p), ReadField(head.pti));
}
#endif // KERNEL
/*
* Print pwnd.
*/
Print("pwnd = 0x%p", pwnd);
/*
* Show z-ordering/activation relevant info
*/
if (opts & OFLAG(z)) {
PTR pwndOwner;
if (ReadField(ExStyle) & WS_EX_TOPMOST) {
Print(" TOPMOST");
}
if (!(ReadField(style) & WS_VISIBLE)) {
Print(" HIDDEN");
}
if (ReadField(style) & WS_DISABLED) {
Print(" DISABLED");
}
pwndOwner = ReadField(spwndOwner);
if (pwndOwner != 0) {
DebugGetWindowTextA(pwndOwner, ach, ARRAY_SIZE(ach));
Print(" OWNER:0x%p \"%s\"", pwndOwner, ach);
}
}
Print("\n");
if (!(opts & OFLAG(v))) {
/*
* Print title string.
*/
DebugGetWindowTextA(pwnd, ach, ARRAY_SIZE(ach));
Print("title = \"%s\"\n", ach);
/*
* Print wndproc symbol string.
*/
if (IsWOWProc (lpfnWndProc)) {
UnMarkWOWProc(lpfnWndProc,dwWOW);
Print("wndproc = %04lx:%04lx (WOW) (%s)",
HIWORD(dwWOW),LOWORD(dwWOW),
TestWWF(&ww, WFANSIPROC) ? "ANSI" : "Unicode");
} else {
GetSym(lpfnWndProc, ach, &dwOffset);
Print("wndproc = 0x%p = \"%s\" (%s)", lpfnWndProc, ach,
TestWWF(&ww, WFANSIPROC) ? "ANSI" : "Unicode");
}
/*
* Display the class name/atom.
*/
GetFieldValue(pwnd, SYM(tagWND), "pcls", pcls);
pcls = FIXKP(pcls);
_InitTypeRead(pcls, SYM(tagCLS));
DebugGetClassNameA(ReadField(lpszAnsiClassName), ach);
Print(" Class(V): 0x%04p, (NV): 0x%04p Name:\"%s\"\n", ReadField(atomClassName), ReadField(atomNVClassName), ach);
} else {
/*
* Get the PWND structure. Ignore class-specific data for now.
*/
_InitTypeRead(pwnd, SYM(tagWND));
Print("\thandle 0x%p\n", ReadField(head.h));
DebugGetWindowTextA(ReadField(spwndNext), ach, ARRAY_SIZE(ach));
Print("\tspwndNext 0x%p \"%s\"\n", ReadField(spwndNext), ach);
DebugGetWindowTextA(ReadField(spwndPrev), ach, ARRAY_SIZE(ach));
Print("\tspwndPrev 0x%p \"%s\"\n", ReadField(spwndPrev), ach);
DebugGetWindowTextA(ReadField(spwndParent), ach, ARRAY_SIZE(ach));
Print("\tspwndParent 0x%p \"%s\"\n", ReadField(spwndParent), ach);
DebugGetWindowTextA(ReadField(spwndChild), ach, ARRAY_SIZE(ach));
Print("\tspwndChild 0x%p \"%s\"\n", ReadField(spwndChild), ach);
DebugGetWindowTextA(ReadField(spwndOwner), ach, ARRAY_SIZE(ach));
Print("\tspwndOwner 0x%p \"%s\"\n", ReadField(spwndOwner), ach);
GetFieldValue(pwnd, SYM(tagWND), "rcWindow", rcWindow);
Print("\trcWindow (%d,%d)-(%d,%d) %dx%d\n",
rcWindow.left, rcWindow.top,
rcWindow.right, rcWindow.bottom,
rcWindow.right - rcWindow.left,
rcWindow.bottom - rcWindow.top);
GetFieldValue(pwnd, SYM(tagWND), "rcClient", rcClient);
Print("\trcClient (%d,%d)-(%d,%d) %dx%d\n",
rcClient.left, rcClient.top,
rcClient.right, rcClient.bottom,
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top);
if (IsWOWProc (lpfnWndProc)) {
UnMarkWOWProc(lpfnWndProc, dwWOW);
Print("\tlpfnWndProc %04lx:%04lx (WOW) (%s)\n",
HIWORD(dwWOW),LOWORD(dwWOW),
TestWWF(&ww, WFANSIPROC) ? "ANSI" : "Unicode");
} else {
GetSym(lpfnWndProc, ach, &dwOffset);
Print("\tlpfnWndProc 0x%p (%s) %s\n", lpfnWndProc, ach,
TestWWF(&ww, WFANSIPROC) ? "ANSI" : "Unicode");
}
pcls = ReadField(pcls);
pcls = FIXKP(pcls);
_InitTypeRead(pcls, SYM(tagCLS));
DebugGetClassNameA(ReadField(lpszAnsiClassName), ach);
Print("\tpcls 0x%p (V):0x%04p (NV):0x%04p Name:\"%s\"\n",
pcls, ReadField(atomClassName), ReadField(atomNVClassName), ach);
_InitTypeRead(pwnd, SYM(tagWND));
Print("\thrgnUpdate 0x%p\n",
ReadField(hrgnUpdate));
DebugGetWindowTextA(ReadField(spwndLastActive), ach, ARRAY_SIZE(ach));
Print("\tspwndLastActive 0x%p \"%s\"\n",
ReadField(spwndLastActive), ach);
Print("\tppropList 0x%p\n"
"\tpSBInfo 0x%p\n",
ReadField(ppropList),
ReadField(pSBInfo));
if (ReadField(pSBInfo)) {
SBINFO asb;
moveBlock(&asb, FIXKP(ReadField(pSBInfo)), sizeof(asb));
Print("\t SBO_FLAGS = %s\n"
"\t SBO_HMIN = %d\n"
"\t SBO_HMAX = %d\n"
"\t SBO_HPAGE = %d\n"
"\t SBO_HPOS = %d\n"
"\t SBO_VMIN = %d\n"
"\t SBO_VMAX = %d\n"
"\t SBO_VPAGE = %d\n"
"\t SBO_VPOS = %d\n",
GetFlags(GF_SB, (WORD)asb.WSBflags, NULL, TRUE),
asb.Horz.posMin,
asb.Horz.posMax,
asb.Horz.page,
asb.Horz.pos,
asb.Vert.posMin,
asb.Vert.posMax,
asb.Vert.page,
asb.Vert.pos);
}
Print("\tspmenuSys 0x%p\n"
"\tspmenu/id 0x%p\n",
ReadField(spmenuSys),
ReadField(spmenu));
Print("\thrgnClip 0x%p\n",
ReadField(hrgnClip));
/*
* Print title string.
*/
DebugGetWindowTextA(pwnd, ach, ARRAY_SIZE(ach));
Print("\tpName \"%s\"\n",
ach);
Print("\tdwUserData 0x%p\n",
(ULONG_PTR)ReadField(dwUserData));
Print("\tstate 0x%08lx\n"
"\tstate2 0x%08lx\n"
"\tExStyle 0x%08lx\n"
"\tstyle 0x%08lx\n"
"\tfnid 0x%08lx\n"
"\thImc 0x%08p\n"
"\tbFullScreen 0y%d\n"
"\thModule 0x%08lx\n"
#ifdef LAME_BUTTON
"\tpStackTrace 0x%p\n"
#endif // LAME_BUTTON
"\tpActCtx 0x%p\n",
ww.state,
ww.state2,
ww.ExStyle,
ww.style,
(DWORD)(WORD)ReadField(fnid),
ReadField(hImc),
TestWWF(&ww, WFFULLSCREENMASK),
ReadField(hModule),
#ifdef LAME_BUTTON
ReadField(pStackTrace),
#endif // LAME_BUTTON
ReadField(pActCtx));
}
/*
* Print out all the flags
*/
if (opts & OFLAG(f)) {
int i;
WORD wFlag;
ULONG cbHead;
PBYTE pbyte = (PBYTE)(&(ww.state));
cbHead = GetTypeSize(SYM(THRDESKHEAD));
for (i = 0; i < ARRAY_SIZE(aWindowFlags); i++) {
wFlag = aWindowFlags[i].wFlag;
if (pbyte[HIBYTE(wFlag)] & LOBYTE(wFlag)) {
Print("\t%-18s\t%p:%02lx\n",
aWindowFlags[i].pszText,
pwnd + cbHead + HIBYTE(wFlag),
LOBYTE(wFlag));
}
}
}
if (opts & OFLAG(w)) {
ULONG cbwnd = GetTypeSize(SYM(WND));
ULONG cbwndExtra = (ULONG)ReadField(cbwndExtra);
Print("\t%d window bytes: ", cbwndExtra);
if (cbwndExtra) {
for (ix=0; ix < cbwndExtra; ix += 4) {
PTR pdw;
pdw = pwnd + cbwnd + ix;
move(tempDWord, pdw);
Print("%08x ", tempDWord);
}
}
Print("\n");
}
/*
* Print window properties.
*/
if (opts & OFLAG(o)) {
PTR psi;
PTR ppropList;
ULONG iFirstFree;
ULONG cEntries;
ULONG cbProp;
ULONG cbOffset;
PTR pprop;
UINT i, j;
struct {
LPSTR pstrName;
ATOM atom;
BOOLEAN bGlobal;
LPSTR pstrSymbol;
} apropatom[] =
{
"Icon", 0, FALSE, "atomIconProp",
"IconSM", 0, FALSE, "atomIconSmProp",
"ContextHelpID",0, FALSE, "atomContextHelpIdProp",
"Checkpoint", 0, TRUE, VAR(atomCheckpointProp),
"Flash State", 0, TRUE, VAR(gaFlashWState),
"DDETrack", 0, TRUE, VAR(atomDDETrack),
"QOS", 0, TRUE, VAR(atomQOS),
"DDEImp", 0, TRUE, VAR(atomDDEImp),
"WNDOBJ", 0, TRUE, VAR(atomWndObj),
"IMELevel", 0, TRUE, VAR(atomImeLevel),
};
/*
* Get the atom values for internal properties and put them in apropatom.atom
*/
psi = GetGlobalPointer(VAR(gpsi));
for (i = 0; i < ARRAY_SIZE(apropatom); i++) {
if (!apropatom[i].bGlobal) {
/*
* The atom is stored in psi.
*/
GetFieldValue(psi, SYM(SERVERINFO), apropatom[i].pstrSymbol, apropatom[0].atom);
} else {
/*
* The atom is a global.
*/
moveExpValue(&apropatom[i].atom, apropatom[i].pstrSymbol);
}
}
/*
* Print the property list structure.
*/
GetFieldValue(pwnd, SYM(WND), "ppropList", ppropList);
if (!ppropList) {
Print("\tNULL Property List\n");
} else {
_InitTypeRead(ppropList, SYM(tagPROPLIST));
iFirstFree = (ULONG)ReadField(iFirstFree);
cEntries = (ULONG)ReadField(cEntries);
Print("\tProperty List @ 0x%p : %d Properties, %d total entries, %d free entries\n",
ppropList,
iFirstFree,
cEntries,
cEntries - iFirstFree);
/*
* Print each property.
*/
GetFieldOffset(SYM(PROPLIST), "aprop", &cbOffset);
pprop = ppropList + cbOffset;
cbProp = GetTypeSize(SYM(tagPROP));
for (i = 0; !IsCtrlCHit() && i < iFirstFree; i++, pprop += cbProp) {
LPSTR pstrInternal;
_InitTypeRead(pprop, SYM(tagPROP));
/*
* Find name for internal property.
*/
pstrInternal = "";
if (ReadField(fs) & PROPF_INTERNAL) {
for (j = 0; j < ARRAY_SIZE(apropatom); j++) {
if (ReadField(atomKey) == apropatom[j].atom) {
pstrInternal = apropatom[j].pstrName;
break;
}
}
}
Print("\tProperty %d\n", i);
Print("\t\tatomKey 0x%04x %s\n", (ULONG)ReadField(atomKey), pstrInternal);
Print("\t\tfs 0x%04x %s\n", (ULONG)ReadField(fs), GetFlags(GF_PROP, (DWORD)ReadField(fs), NULL, FALSE));
Print("\t\thData 0x%p (%I64d)\n", ReadField(hData), ReadField(hData));
#ifdef KERNEL
if (ReadField(fs) & PROPF_INTERNAL) {
if (j == 3) {
CHECKPOINT cp;
PTR pcp = ReadField(hData);
move(cp, pcp);
Print("\t\tCheckPoint:\n");
Print("\t\trcNormal (%d,%d),(%d,%d) %dx%d\n",
cp.rcNormal.left,
cp.rcNormal.top,
cp.rcNormal.right,
cp.rcNormal.bottom,
cp.rcNormal.right - cp.rcNormal.left,
cp.rcNormal.bottom - cp.rcNormal.top);
Print("\t\tptMin (%d,%d)\n", cp.ptMin.x, cp.ptMin.y);
Print("\t\tptMax (%d,%d)\n", cp.ptMax.x, cp.ptMax.y);
Print("\t\tfDragged:%d\n", cp.fDragged);
Print("\t\tfWasMaximizedBeforeMinimized:%d\n", cp.fWasMaximizedBeforeMinimized);
Print("\t\tfWasMinimizedBeforeMaximized:%d\n", cp.fWasMinimizedBeforeMaximized);
Print("\t\tfMinInitialized:%d\n", cp.fMinInitialized);
Print("\t\tfMaxInitiailized:%d\n", cp.fMaxInitialized);
}
}
#endif // ifdef KERNEL
Print("\n");
}
}
}
Print("---\n");
} except (CONTINUE) {
}
return TRUE;
}
#ifdef KERNEL
/***************************************************************************\
* dws - dump windows stations
* dws h - dump windows stations plus handle list
*
* Dump WindowStation
*
* 8-11-94 SanfordS Created
* 6/9/1995 SanfordS made to fit stdexts motif
\***************************************************************************/
BOOL Idws(
DWORD opts,
ULONG64 param1)
{
PTR pwinsta;
WCHAR ach[80];
PTR pHead;
PTR pNameBuffer;
ULONG ObjectHeaderOffset;
UCHAR NameInfoOffset;
PTR NameBuffer;
ULONG NameLength;
ULONG cOpen;
DWORD sid; // session id
UNREFERENCED_PARAMETER(opts);
if (param1 == 0) {
FOREACHWINDOWSTATION(pwinsta)
Idws(0, pwinsta);
Print("\n");
NEXTEACHWINDOWSTATION(pwinsta)
return TRUE;
}
pwinsta = param1;
GetFieldOffset("nt!OBJECT_HEADER", "Body", &ObjectHeaderOffset);
pHead = pwinsta - ObjectHeaderOffset;
GetFieldValue(pHead, "nt!OBJECT_HEADER", "NameInfoOffset", NameInfoOffset);
pNameBuffer = pHead - NameInfoOffset;
GetFieldValue(pNameBuffer, "nt!OBJECT_HEADER_NAME_INFO", "Name.Buffer", NameBuffer);
GetFieldValue(pNameBuffer, "nt!OBJECT_HEADER_NAME_INFO", "Name.Length", NameLength);
moveBlock(ach, FIXKP(NameBuffer), NameLength);
ach[NameLength / sizeof(WCHAR)] = L'\0';
GetFieldValue(pwinsta, SYM(tagWINDOWSTATION), "dwSessionId", sid);
Print("Windowstation: %ws @ 0x%p sid: 0n%d\n", ach, pwinsta, sid);
Print(" OBJECT_HEADER @ 0x%p\n", pHead);
GetFieldValue(pHead, "nt!OBJECT_HEADER", "HandleCount", cOpen);
Print(" HandleCount = 0n%d\n", cOpen);
GetFieldValue(pHead, "nt!OBJECT_HEADER", "PointerCount", cOpen);
Print(" PointerCount = 0n%d\n", cOpen);
_InitTypeRead(pwinsta, SYM(tagWINDOWSTATION));
Print(" pTerm = %p\n", ReadField(pTerm));
Print(" rpdeskList = %p\n", ReadField(rpdeskList));
Print(" dwFlags = %s\n", GetFlags(GF_WINDOWSTATIONFLAGS, (DWORD)ReadField(dwWSF_Flags), NULL, TRUE));
Print(" spklList = %p\n", ReadField(spklList));
Print(" ptiClipLock = %p\n", ReadField(ptiClipLock));
Print(" spwndClipOpen = %p\n", ReadField(spwndClipOpen));
Print(" spwndClipViewer = %p\n", ReadField(spwndClipViewer));
Print(" spwndClipOwner = %p\n", ReadField(spwndClipOwner));
Print(" pClipBase = %p\n", ReadField(pClipBase));
Print(" cNumClipFormats = 0x%0lx\n", (DWORD)ReadField(cNumClipFormats));
Print(" ptiDrawingClipboard= %p\n", ReadField(ptiDrawingClipboard));
Print(" fClipboardChanged = %d\n", ReadField(fClipboardChanged));
Print(" pGlobalAtomTable = %p\n", ReadField(pGlobalAtomTable));
Print(" luidUser = %0lx.%lx\n", (ULONG)ReadField(luidUser.HighPart),
(ULONG)ReadField(luidUser.LowPart));
return TRUE;
}
#endif
#ifdef OLD_DEBUGGER
#ifdef KERNEL
/************************************************************************\
* Idwpi
*
* Dumps WOWPROCESSINFO structs
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Idwpi(
DWORD opts,
ULONG64 param1)
{
PWOWPROCESSINFO pwpi;
WOWPROCESSINFO wpi;
PPROCESSINFO ppi;
if (param1 == 0) {
FOREACHPPI(ppi)
Print("Process %p.\n", FIXKP(ppi));
move(pwpi, FIXKP(&ppi->pwpi));
SAFEWHILE (pwpi) {
Idwpi(0, pwpi);
Print("\n");
move(pwpi, FIXKP(&pwpi->pwpiNext));
}
NEXTEACHPPI()
return TRUE;
}
if (opts & OFLAG(p)) {
ppi = (PPROCESSINFO)FIXKP(param1);
move(pwpi, &ppi->pwpi);
if (pwpi == NULL) {
Print("No pwpis for this process.\n");
return TRUE;
}
SAFEWHILE (pwpi) {
Idwpi(0, pwpi);
Print("\n");
move(pwpi, &pwpi->pwpiNext);
}
return TRUE;
}
pwpi = (PWOWPROCESSINFO)FIXKP(param1);
move(wpi, pwpi);
Print("PWOWPROCESSINFO @ 0x%p\n", pwpi);
Print("\tpwpiNext 0x%08lx\n", wpi.pwpiNext);
Print("\tptiScheduled 0x%08lx\n", wpi.ptiScheduled);
Print("\tptdbHead 0x%08lx\n", wpi.ptdbHead);
Print("\tlpfnWowExitTask 0x%08lx\n", wpi.lpfnWowExitTask);
Print("\tpEventWowExec 0x%08lx\n", wpi.pEventWowExec);
Print("\thEventWowExecClient 0x%08lx\n", wpi.hEventWowExecClient);
Print("\tnSendLock 0x%08lx\n", wpi.nSendLock);
Print("\tnRecvLock 0x%08lx\n", wpi.nRecvLock);
Print("\tCSOwningThread 0x%08lx\n", wpi.CSOwningThread);
Print("\tCSLockCount 0x%08lx\n", wpi.CSLockCount);
return TRUE;
}
#endif // KERNEL
#ifdef KERNEL
BOOL DHAVerifyHeap(
PWIN32HEAP pHeap,
BOOL bVerbose)
{
DbgHeapHead Alloc, *pAlloc = pHeap->pFirstAlloc;
int sizeHead, counter = 0;
char szHeadOrTail[HEAP_CHECK_SIZE];
if (pAlloc == NULL) {
return FALSE;
}
sizeHead = pHeap->dwFlags & WIN32_HEAP_USE_GUARDS ?
sizeof(pHeap->szHead) : 0;
do {
if (!tryMove(Alloc, pAlloc)) {
Print("Failed to read pAlloc from %p\n", pAlloc);
return FALSE;
}
/*
* Check the mark, header and tail
*/
if (Alloc.mark != HEAP_ALLOC_MARK) {
Print("!!! Bad mark found in allocation use !dso DbgHeapHead %p\n", pAlloc);
}
if (sizeHead) {
if (!tryMove(szHeadOrTail, (PBYTE)pAlloc-sizeof(szHeadOrTail))) {
Print("Failed to read szHead from %p\n", (PBYTE)pAlloc-sizeof(szHeadOrTail));
return FALSE;
}
if (!RtlEqualMemory(szHeadOrTail, pHeap->szHead, sizeHead)) {
Print("Head pattern corrupted for allocation %#p\n", pAlloc);
}
if (!tryMove(szHeadOrTail, (PBYTE)pAlloc + sizeof(DbgHeapHead) + Alloc.size)) {
Print("Failed to read szHead from %p\n", (PBYTE)pAlloc + sizeof(DbgHeapHead) + Alloc.size);
return FALSE;
}
if (!RtlEqualMemory(szHeadOrTail, pHeap->szTail, sizeHead)) {
Print("Tail pattern corrupted for allocation %#p\n", pAlloc);
}
}
if (bVerbose) {
Print("Allocation %#p, tag %04d size %08d\n", pAlloc, Alloc.tag, Alloc.size);
}
if (counter++ > 100) {
Print(".");
counter = 0;
}
pAlloc = Alloc.pNext;
} while (pAlloc != NULL);
if (bVerbose) {
Print("To dump an allocation use \"dt DBGHEAPHEAD address\"\n");
}
return TRUE;
}
/************************************************************************\
* Idha
*
* Walks the global array of heaps gWin32Heaps looking for an allocation that
* contain the address passed in. Then does a sanity check on the entire heap
* the allocations belongs to. DHAVerifyHeap is a helper procedure. Note that
* the passed in parameter is already mapped.
*
* 12/7/1998 Created MCostea
\************************************************************************/
BOOL Idha(
DWORD opts,
PVOID pointer)
{
int ind, counter;
SIZE_T sizeHead;
WIN32HEAP localgWin32Heaps[MAX_HEAPS];
if (pointer == 0 && (opts & OFLAG(a) ==0)) {
Print("Wrong usage: dha takes a pointer as a parameter\n");
return FALSE;
}
if (!tryMoveBlock(localgWin32Heaps, EvalExp(VAR(gWin32Heaps)), sizeof(localgWin32Heaps)))
{
Print("Can't read the heap globals fix symbols and !reload win32k.sys\n");
return TRUE;
}
/*
* Walk gWin32Heaps array and look for an allocation containing this pointer
*/
for (ind = counter = 0; ind < MAX_HEAPS; ind++) {
/*
* Is the address in this heap?
*/
if ((opts & OFLAG(a)) == 0) {
if ((PVOID)localgWin32Heaps[ind].heap > pointer ||
(PBYTE)localgWin32Heaps[ind].heap + localgWin32Heaps[ind].heapReserveSize < (PBYTE)pointer) {
continue;
}
}
Print("\nHeap number %d ", ind);
Print("at address %p, flags %d is ", localgWin32Heaps[ind].heap, localgWin32Heaps[ind].dwFlags);
if (localgWin32Heaps[ind].dwFlags & WIN32_HEAP_INUSE) {
DbgHeapHead Alloc, *pAlloc;
Print("in use\n");
if (localgWin32Heaps[ind].pFirstAlloc == NULL)
continue;
pAlloc = localgWin32Heaps[ind].pFirstAlloc;
if (localgWin32Heaps[ind].dwFlags & WIN32_HEAP_USE_GUARDS) {
sizeHead = sizeof(localgWin32Heaps[0].szHead);
Print(" has string quards szHead %s, szTail %s\n",
localgWin32Heaps[0].szHead,
localgWin32Heaps[0].szTail);
} else {
sizeHead = 0;
Print("no string quards\n");
}
if (opts & OFLAG(a)) {
if (DHAVerifyHeap(&localgWin32Heaps[ind], opts & OFLAG(v))) {
Print("WIN32HEAP at %p is healthy\n", localgWin32Heaps[ind].heap);
}
continue;
}
do {
if (!tryMove(Alloc, pAlloc)) {
Print("Failed to read pAlloc %p\n", pAlloc);
return TRUE;
}
if ((PBYTE)pAlloc - sizeHead < (PBYTE)pointer &&
(PBYTE)pAlloc + sizeof(DbgHeapHead) + Alloc.size + sizeHead > (PBYTE)pointer) {
/*
* Found the allocation
*/
Print("Found allocation %p ", pAlloc);
if (pointer == (PBYTE)pAlloc + sizeof(DbgHeapHead)) {
Print("as the begining of a heap allocated block\n");
} else {
Print("inside a heap allocated block\n");
}
Print("tag %04d size %08d now verify the heap\n", Alloc.tag, Alloc.size);
/*
* Verify the entire heap for corruption
*/
if (DHAVerifyHeap(&localgWin32Heaps[ind], opts & OFLAG(v))) {
Print("WIN32HEAP at %p is healthy\n", localgWin32Heaps[ind].heap);
}
return TRUE;
} else {
pAlloc = Alloc.pNext;
if (counter++ > 100) {
counter = 0;
Print(".");
}
}
} while (pAlloc != NULL);
} else {
Print("NOT in use\n");
}
}
Print("No heap contains this pointer %p\n", pointer);
return TRUE;
}
#endif // KERNEL
#endif // OLD_DEBUGGER
#ifdef KERNEL
/***************************************************************************\
* ddl - dump desktop log
*
* 12-03-97 CLupu Created
\***************************************************************************/
BOOL Iddl(
DWORD opts,
ULONG64 param1)
{
#ifdef LOGDESKTOPLOCKS
PTR pdesk, pLog, pObjHeader, pStack, ptr, dwOffset64;
ULONG dwOffset, dwTraceOffset, dwPVOIDSize, dwLogDSize;
OBJECT_HEADER Head;
BOOL bExtra = FALSE;
int i, ind, nLockCount, nLogCrt;
LONG HandleCount, PointerCount;
WORD type, tag;
CHAR symbol[160];
ULONG_PTR extra;
if (param1 == 0) {
Print("Use !ddl pdesk\n");
return TRUE;
}
pdesk = param1;
GetFieldOffset("nt!OBJECT_HEADER", "Body", &dwOffset);
pObjHeader = pdesk - dwOffset;
Print("Desktop locks:\n\n");
GetFieldValue(pObjHeader, "nt!OBJECT_HEADER", "HandleCount", HandleCount);
GetFieldValue(pObjHeader, "nt!OBJECT_HEADER", "PointerCount", PointerCount);
Print("# HandleCount = %d\n", HandleCount);
Print("# PointerCount = %d\n", PointerCount);
if (GetFieldValue(pdesk, SYM(DESKTOP), "nLockCount", nLockCount)) {
Print("Couldn't get PointerCount for pdesk %p\n", pdesk);
}
Print("# Log PointerCount = %d\n\n", nLockCount);
GetFieldValue(pdesk, SYM(DESKTOP), "pLog", pLog);
if (opts & OFLAG(v)) {
bExtra = TRUE;
}
dwLogDSize = GetTypeSize("LogD");
dwPVOIDSize = GetTypeSize("PVOID");
GetFieldOffset(SYM(LogD), "trace", &dwTraceOffset);
GetFieldValue(pdesk, SYM(DESKTOP), "nLogCrt", nLogCrt);
for (i = 0; i < nLogCrt; i++) {
if (IsCtrlCHit()) {
break;
}
GetFieldValue(pLog, "LogD", "tag", tag);
GetFieldValue(pLog, "LogD", "type", type);
GetFieldValue(pLog, "LogD", "extra", extra);
Print("%s Tag %6d Extra %8lx\n",
(type ? "LOCK " : "UNLOCK"),
tag, extra);
if (bExtra) {
Print("----------------------------------------------\n");
for (ind = 0; ind < 6; ind++) {
pStack = pLog + dwTraceOffset + dwPVOIDSize * ind;
ReadPointer(pStack, &ptr);
if (ptr == 0) {
break;
}
GetSym(ptr, symbol, &dwOffset64);
if (*symbol) {
Print("\t%s", symbol);
if (dwOffset64) {
Print(" +0x%x\n", (ULONG)dwOffset64);
}
}
}
Print("\n");
}
pLog += dwLogDSize;
}
return TRUE;
#else
Print("!ddl is available only on LOGDESKTOPLOCKS enabled builds of win32k.sys\n");
return FALSE;
UNREFERENCED_PARAMETER(opts);
UNREFERENCED_PARAMETER(param1);
#endif // LOGDESKTOPLOCKS
}
#endif // KERNEL
#ifdef KERNEL
/***************************************************************************\
* dcss - dump critical section stack
*
* Dump critical section stack
*
* 12-27-1996 CLupu Created
* 06-26-2001 JasonSch Made Win64-clean.
\***************************************************************************/
BOOL Idcss(
DWORD opts)
{
int nFrames;
PTR pStack;
UNREFERENCED_PARAMETER(opts);
moveExp(&pStack, SYM(gCritStack));
_InitTypeRead(pStack, SYM(CRITSTACK));
if ((nFrames = (int)ReadField(nFrames)) > 0) {
DumpThread(0, ReadField(thread));
#if 0
Print("\nthread : 0x%p\n", ReadField(thread));
#endif
Print("--- Critical section stack trace ---\n");
PrintStackTrace(ReadField(trace), nFrames);
}
return TRUE;
}
BOOL Idvs(
DWORD opts,
ULONG64 param1)
{
ULONG64 pSection;
ULONG64 pView;
BOOL bIncludeStackTrace = FALSE;
UNREFERENCED_PARAMETER(opts);
UNREFERENCED_PARAMETER(param1);
if (EvalExp(VAR(gpSections)) == 0) {
Print("!dvs is available if TRACE_MAP_VIEWS is defined\n");
return FALSE;
}
pSection = GetGlobalPointer(VAR(gpSections));
if (opts & OFLAG(s)) {
bIncludeStackTrace = TRUE;
}
while (pSection != 0) {
_InitTypeRead(pSection, SYM(tagWin32Section));
Print(">>--------------------------------------\n");
Print("Section %#p\n"
" pFirstView %#p\n"
" SectionObject %#p\n"
" SectionSize 0x%x\n"
" SectionTag 0x%x\n",
pSection,
ReadField(pFirstView),
ReadField(SectionObject),
ReadField(SectionSize),
ReadField(SectionTag));
if (bIncludeStackTrace) {
#ifdef MAP_VIEW_STACK_TRACE
PrintStackTrace(ReadField(trace), MAP_VIEW_STACK_TRACE_SIZE);
Print("\n");
#endif // MAP_VIEW_STACK_TRACE
}
pView = ReadField(pFirstView);
while (pView != 0) {
_InitTypeRead(pView, SYM(tagWin32MapView));
Print("Views: ---------------------------------\n"
" View %#p\n"
" pViewBase %#p\n"
" ViewSize %#p\n",
pView,
ReadField(pViewBase),
ReadField(View.ViewSize));
if (bIncludeStackTrace) {
#ifdef MAP_VIEW_STACK_TRACE
PrintStackTrace(ReadField(trace), MAP_VIEW_STACK_TRACE_SIZE);
Print("\n");
#endif // MAP_VIEW_STACK_TRACE
}
GetFieldValue(pView, SYM(tagWin32MapView), "pNext", pView);
}
GetFieldValue(pSection, SYM(tagWin32Section), "pNext", pSection);
}
return TRUE;
}
#ifdef OLD_DEBUGGER
BOOL Idfa(
DWORD opts,
ULONG64 param1)
{
ULONG64 dwOffset;
CHAR symbol[160];
int ind;
PVOID* pTrace;
PVOID trace;
DWORD dwAllocFailIndex;
DWORD* pdwAllocFailIndex;
PEPROCESS pep;
PEPROCESS* ppep;
PETHREAD pet;
PETHREAD* ppet;
UNREFERENCED_PARAMETER(opts);
UNREFERENCED_PARAMETER(param1);
if (EvalExp(VAR(gdwAllocFailIndex)) == NULL) {
Print("!dfa is available only in debug versions of win32k.sys\n");
return FALSE;
}
moveExp(&pdwAllocFailIndex, VAR(gdwAllocFailIndex));
if (!tryMove(dwAllocFailIndex, pdwAllocFailIndex)) {
Print("dfa failure");
return FALSE;
}
moveExp(&ppep, VAR(gpepRecorded));
if (!tryMove(pep, ppep)) {
Print("dfa failure");
return FALSE;
}
moveExp(&ppet, VAR(gpetRecorded));
if (!tryMove(pet, ppet)) {
Print("dfa failure");
return FALSE;
}
Print("Fail allocation index %d 0x%04x\n", dwAllocFailIndex, dwAllocFailIndex);
Print("pEProcess %#p pEThread %#p\n\n", pep, pet);
moveExp(&pTrace, VAR(gRecordedStackTrace));
for (ind = 0; ind < 12; ind++) {
if (!tryMove(trace, pTrace)) {
Print("dfa failure");
return FALSE;
}
if (trace == 0) {
break;
}
GetSym((PVOID)trace, symbol, &dwOffset);
if (*symbol) {
Print("\t%s", symbol);
if (dwOffset) {
Print("+%p\n", dwOffset);
}
}
pTrace++;
}
Print("\n");
return TRUE;
}
#endif // OLD_DEBUGGER
VOID PrintStackTrace(
PTR pStackTrace,
int tracesCount)
{
int traceInd;
ULONG64 dwOffset, pSymbol;
CHAR symbol[160];
DWORD dwPointerSize = GetTypeSize("PVOID");
for (traceInd = 0; traceInd < tracesCount; traceInd++) {
ReadPointer(pStackTrace, &pSymbol);
if (pSymbol == 0) {
break;
}
GetSym(pSymbol, symbol, &dwOffset);
if (*symbol) {
Print("\t%s", symbol);
if (dwOffset) {
Print("+%p\n", dwOffset);
} else {
Print("\n");
}
}
pStackTrace += dwPointerSize;
}
Print("\n");
}
/***************************************************************************\
* dpa - dump pool allocations
*
* Dump pool allocations.
*
* 12-27-96 CLupu Created
\***************************************************************************/
BOOL Idpa(
DWORD opts,
ULONG64 param1)
{
try {
PTR pAllocList;
DWORD dwPoolFlags;
DWORD dwSize = GetTypeSize(SYM(tagWin32PoolHead));
BOOL bIncludeStackTrace = FALSE;
moveExpValue(&dwPoolFlags, VAR(gdwPoolFlags));
if (!(dwPoolFlags & POOL_HEAVY_ALLOCS)) {
Print("win32k.sys doesn't have pool instrumentation !\n");
return FALSE;
}
if (opts & OFLAG(s)) {
if (dwPoolFlags & POOL_CAPTURE_STACK) {
bIncludeStackTrace = TRUE;
} else {
Print("win32k.sys doesn't have stack traces enabled for pool allocations\n");
}
}
moveExp(&pAllocList, VAR(gAllocList));
if (!pAllocList) {
Print("Could not get Win32AllocStats structure win32k!gAllocList\n");
return FALSE;
}
_InitTypeRead(pAllocList, SYM(tagWin32AllocStats));
if (opts & OFLAG(c)) {
Print("- pool instrumentation enabled for win32k.sys\n");
if (dwPoolFlags & POOL_CAPTURE_STACK) {
Print("- stack traces enabled for pool allocations\n");
} else {
Print("- stack traces disabled for pool allocations\n");
}
if (dwPoolFlags & POOL_KEEP_FAIL_RECORD) {
Print("- records of failed allocations enabled\n");
} else {
Print("- records of failed allocations disabled\n");
}
if (dwPoolFlags & POOL_KEEP_FREE_RECORD) {
Print("- records of free pool enabled\n");
} else {
Print("- records of free pool disabled\n");
}
Print("\n");
Print(" CrtM CrtA MaxM MaxA Head\n");
Print("------------|------------|------------|------------|------------|\n");
_InitTypeRead(pAllocList, SYM(Win32AllocStats));
Print(" 0x%08x 0x%08x 0x%08x 0x%08x 0x%I64x\n",
(ULONG)ReadField(dwCrtMem),
(ULONG)ReadField(dwCrtAlloc),
(ULONG)ReadField(dwMaxMem),
(ULONG)ReadField(dwMaxAlloc),
ReadField(pHead));
return TRUE;
}
_InitTypeRead(pAllocList, SYM(tagWin32AllocStats));
if (opts & OFLAG(f)) {
DWORD dwFailRecordCrtIndex, dwFailRecordTotalFailures;
DWORD dwFailRecords, Ind, dwFailuresToDump;
PTR pFailRecord, pFailRecordOrg;
if (!(dwPoolFlags & POOL_KEEP_FAIL_RECORD)) {
Print("win32k.sys doesn't have records of failed allocations!\n");
return TRUE;
}
dwFailRecordTotalFailures = (DWORD)EvalExp(VAR(gdwFailRecordTotalFailures));
if (dwFailRecordTotalFailures == 0) {
Print("No allocation failure in win32k.sys!\n");
return TRUE;
}
dwFailRecordCrtIndex = (DWORD)EvalExp(VAR(gdwFailRecordCrtIndex));
dwFailRecords = (DWORD)EvalExp(VAR(gdwFailRecords));
if (dwFailRecordTotalFailures < dwFailRecords) {
dwFailuresToDump = dwFailRecordTotalFailures;
} else {
dwFailuresToDump = dwFailRecords;
}
pFailRecord = GetGlobalPointer(VAR(gparrFailRecord));
if (!pFailRecord) {
Print("\nCouldn't get gparrFailRecord!\n");
return FALSE;
}
pFailRecordOrg = pFailRecord;
Print("\nFailures to dump : %d\n\n", dwFailuresToDump);
for (Ind = 0; Ind < dwFailuresToDump; Ind++) {
DWORD tag[2] = {0, 0};
if (dwFailRecordCrtIndex == 0) {
dwFailRecordCrtIndex = dwFailRecords - 1;
} else {
dwFailRecordCrtIndex--;
}
pFailRecord = pFailRecordOrg + dwFailRecordCrtIndex;
_InitTypeRead(pFailRecord, SYM(tagPOOLRECORD));
tag[0] = (DWORD)(DWORD_PTR)ReadField(ExtraData);
Print("Allocation for tag '%s' size 0x%x failed\n",
&tag,
(ULONG)ReadField(size));
PrintStackTrace(ReadField(pTrace), RECORD_STACK_TRACE_SIZE);
}
}
_InitTypeRead(pAllocList, SYM(tagWin32AllocStats));
if (opts & OFLAG(r)) {
DWORD dwFreeRecordCrtIndex, dwFreeRecordTotalFrees;
DWORD dwFreeRecords, Ind, dwFreesToDump;
PTR pFreeRecord, pFreeRecordOrg;
if (!(dwPoolFlags & POOL_KEEP_FREE_RECORD)) {
Print("win32k.sys doesn't have records of free pool !\n");
return FALSE;
}
dwFreeRecordTotalFrees = (DWORD)EvalExp(VAR(gdwFreeRecordTotalFrees));
if (dwFreeRecordTotalFrees == 0) {
Print("No free pool in win32k.sys !\n");
return FALSE;
}
dwFreeRecordCrtIndex = (DWORD)EvalExp(VAR(gdwFreeRecordCrtIndex));
dwFreeRecords = (DWORD)EvalExp(VAR(gdwFreeRecords));
if (dwFreeRecordTotalFrees < dwFreeRecords) {
dwFreesToDump = dwFreeRecordTotalFrees;
} else {
dwFreesToDump = dwFreeRecords;
}
pFreeRecord = GetGlobalPointer(VAR(gparrFreeRecord));
if (!pFreeRecord) {
Print("\nCouldn't get gparrFreeRecord!\n");
return FALSE;
}
pFreeRecordOrg = pFreeRecord;
Print("\nFrees to dump : %d\n\n", dwFreesToDump);
for (Ind = 0; Ind < dwFreesToDump; Ind++) {
if (dwFreeRecordCrtIndex == 0) {
dwFreeRecordCrtIndex = dwFreeRecords - 1;
} else {
dwFreeRecordCrtIndex--;
}
pFreeRecord = pFreeRecordOrg + dwFreeRecordCrtIndex;
/*
* Dump
*/
_InitTypeRead(pFreeRecord, SYM(tagPOOLRECORD));
Print("Free pool for p %#p size 0x%x\n",
ReadField(ExtraData),
(ULONG)ReadField(size));
PrintStackTrace(ReadField(pTrace), RECORD_STACK_TRACE_SIZE);
}
}
_InitTypeRead(pAllocList, SYM(tagWin32AllocStats));
if (opts & OFLAG(v)) {
PTR ph = ReadField(pHead);
while (ph != 0) {
_InitTypeRead(ph, SYM(tagWin32PoolHead));
Print("p %#p pHead %#p size %x\n",
ph + dwSize, ph, (ULONG)ReadField(size));
if (bIncludeStackTrace) {
PrintStackTrace(ReadField(pTrace), RECORD_STACK_TRACE_SIZE);
}
ph = (ULONG_PTR)ReadField(pNext);
}
return TRUE;
}
_InitTypeRead(pAllocList, SYM(tagWin32AllocStats));
if (opts & OFLAG(p)) {
PTR ph;
DWORD dwSize = GetTypeSize(SYM(tagWin32PoolHead));
if (param1 == 0) {
return TRUE;
}
ph = ReadField(pHead);
while (ph != 0) {
if ((param1 - ph) >= ((ULONG)ReadField(size) + dwSize)) {
Print("p %#p pHead %#p size %x\n",
ph + 1, ph, (ULONG)ReadField(size));
PrintStackTrace(ReadField(pTrace), RECORD_STACK_TRACE_SIZE);
return TRUE;
}
ph = ReadField(pNext);
}
return TRUE;
}
} except (CONTINUE) {
}
return TRUE;
}
#endif // KERNEL
#ifdef OLD_DEBUGGER
/************************************************************************\
* Ifno
*
* Find Nearest Objects - helps in figureing out references
* to freed objects or stale pointers.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Ifno(
DWORD opts,
ULONG64 param1)
{
HANDLEENTRY he, heBest, heAfter, *phe;
DWORD i;
DWORD hBest, hAfter;
DWORD_PTR dw;
UNREFERENCED_PARAMETER(opts);
if (param1 == 0) {
Print("Expected an address.\n");
return FALSE;
}
dw = (DWORD_PTR)FIXKP(param1);
heBest.phead = NULL;
heAfter.phead = (PVOID)-1;
if (dw != (DWORD_PTR)param1) {
/*
* no fixups needed - he's looking the kernel address range.
*/
FOREACHHANDLEENTRY(phe, he, i)
if ((DWORD_PTR)he.phead <= dw &&
heBest.phead < he.phead &&
he.bType != TYPE_FREE) {
heBest = he;
hBest = i;
}
if ((DWORD_PTR)he.phead > dw &&
heAfter.phead > he.phead &&
he.bType != TYPE_FREE) {
heAfter = he;
hAfter = i;
}
NEXTEACHHANDLEENTRY()
if (heBest.phead != NULL) {
Print("Nearest guy before %#p is a %s object located at %#p (i=%x).\n",
dw, aszTypeNames[heBest.bType], heBest.phead, hBest);
}
if (heAfter.phead != (PVOID)-1) {
Print("Nearest guy after %#p is a %s object located at %#p. (i=%x)\n",
dw, aszTypeNames[heAfter.bType], heAfter.phead, hAfter);
}
} else {
/*
* fixups are needed.
*/
FOREACHHANDLEENTRY(phe, he, i)
if ((DWORD_PTR)FIXKP(he.phead) <= dw &&
heBest.phead < he.phead &&
he.bType != TYPE_FREE) {
heBest = he;
hBest = i;
}
if ((DWORD_PTR)FIXKP(he.phead) > dw &&
heAfter.phead > he.phead &&
he.bType != TYPE_FREE) {
heAfter = he;
hAfter = i;
}
NEXTEACHHANDLEENTRY()
if (heBest.phead != NULL) {
Print("Nearest guy before %#p is a %s object located at %#p (i=%x).\n",
dw, aszTypeNames[heBest.bType], FIXKP(heBest.phead), hBest);
}
if (heAfter.phead != (PVOID)-1) {
Print("Nearest guy after %#p is a %s object located at %#p. (i=%x)\n",
dw, aszTypeNames[heAfter.bType], FIXKP(heAfter.phead), hAfter);
}
}
return TRUE;
}
/************************************************************************\
* Ifrr
*
* Finds Range References - helpful for finding stale pointers.
*
* fSuccess
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Ifrr(
DWORD opts,
ULONG64 param1,
ULONG64 param2,
ULONG64 param3,
ULONG64 param4)
{
DWORD_PTR pSrc1 = (DWORD_PTR)param1;
DWORD_PTR pSrc2 = (DWORD_PTR)param2;
DWORD_PTR pRef1 = (DWORD_PTR)param3;
DWORD_PTR pRef2 = (DWORD_PTR)param4;
DWORD_PTR dw;
DWORD_PTR buffer[PAGE_SIZE / sizeof(DWORD_PTR)];
UNREFERENCED_PARAMETER(opts);
if (pSrc2 < pSrc1) {
Print("Source range improper. Values reversed.\n");
dw = pSrc1;
pSrc1 = pSrc2;
pSrc2 = dw;
}
if (pRef2 == 0) {
pRef2 = pRef1;
}
if (pRef2 < pRef1) {
Print("Reference range improper. Values reversed.\n");
dw = pRef1;
pRef1 = pRef2;
pRef2 = dw;
}
pSrc1 &= MAXULONG_PTR - PAGE_SIZE + 1; // PAGE aligned
pSrc2 = (pSrc2 + (sizeof(DWORD_PTR)-1)) & (MAXULONG_PTR - (sizeof(DWORD_PTR)-1)); // dword_ptr aligned
Print("Searching range (%#p-%#p) for references to (%#p-%#p)...",
pSrc1, pSrc2, pRef1, pRef2);
for (; pSrc1 < pSrc2; pSrc1 += PAGE_SIZE) {
BOOL fSuccess;
if (!(pSrc1 & 0xFFFFFF)) {
Print("\nSearching %#p...", pSrc1);
}
fSuccess = tryMoveBlock(buffer, (PVOID)pSrc1, sizeof(buffer));
if (!fSuccess) {
/*
* Skip to next page
*/
} else {
for (dw = 0; dw < ARRAY_SIZE(buffer); dw++) {
if (buffer[dw] >= pRef1 && buffer[dw] <= pRef2) {
Print("\n[%#p] = %#p ",
pSrc1 + dw * sizeof(DWORD_PTR),
buffer[dw]);
}
}
}
if (IsCtrlCHit()) {
Print("\nSearch aborted.\n");
return TRUE;
}
}
Print("\nSearch complete.\n");
return TRUE;
}
#ifdef KERNEL
//PGDI_DEVICE undefined
#if 0
VOID ddGdiDevice(
PGDI_DEVICE pGdiDevice)
{
Print("\t\tGDI_DEVICE\n");
Print("\t\tcRefCount = %d\n", pGdiDevice->cRefCount);
Print("\t\thDevInfo = 0x%.8x\n", pGdiDevice->hDevInfo);
Print("\t\thDev = 0x%.8x\n", pGdiDevice->hDev);
Print("\t\trcScreen = (%d,%d)-(%d,%d) %dx%d\n",
pGdiDevice->rcScreen.left, pGdiDevice->rcScreen.top,
pGdiDevice->rcScreen.right, pGdiDevice->rcScreen.bottom,
pGdiDevice->rcScreen.right - pGdiDevice->rcScreen.left,
pGdiDevice->rcScreen.bottom - pGdiDevice->rcScreen.top);
Print("\t\tDEVMODEW\n");
}
#endif
#endif
#endif // OLD_DEBUGGER
VOID
DumpMonitor(
ULONG64 param1,
LPSTR pstrPrefix)
{
DWORD dwMONFlags;
RECT rc;
_InitTypeRead(param1, SYM(MONITOR));
Print("%shead.h = 0x%.8x\n", pstrPrefix, ReadField(head.h));
Print("%shead.cLockObj = 0x%.8x\n", pstrPrefix, ReadField(head.cLockObj));
Print("%spMonitorNext = 0x%p\n", pstrPrefix, ReadField(pMonitorNext));
dwMONFlags = (DWORD)ReadField(dwMONFlags);
Print("%sdwMONFlags = 0x%.8x %s\n", pstrPrefix, dwMONFlags, GetFlags(GF_MON, dwMONFlags, NULL, FALSE));
GetFieldValue(param1, SYM(MONITOR), "rcMonitor", rc);
Print("%srcMonitor = (%d,%d)-(%d,%d) %dx%d\n",
pstrPrefix, rc.left, rc.top, rc.right, rc.bottom, rc.right - rc.left, rc.bottom - rc.top);
GetFieldValue(param1, SYM(MONITOR), "rcWork", rc);
Print("%srcWork = (%d,%d)-(%d,%d) %dx%d\n",
pstrPrefix, rc.left, rc.top, rc.right, rc.bottom, rc.right - rc.left, rc.bottom - rc.top);
Print("%shrgnMonitor = 0x%.8x\n", pstrPrefix, ReadField(hrgnMonitor));
Print("%scFullScreen = %d\n", pstrPrefix, (short)ReadField(cFullScreen));
Print("%scwndStack = %d\n", pstrPrefix, (short)ReadField(cWndStack));
#ifdef SUBPIXEL_MOUSE
{
DWORD dwOffset;
FIXPOINT xTxf[SM_POINT_CNT], yTxf[SM_POINT_CNT];
FIXPOINT slope[SM_POINT_CNT - 1], yint[SM_POINT_CNT - 1];
GetFieldOffset(SYM(MONITOR), "xTxf", &dwOffset);
move(xTxf, param1 + dwOffset);
GetFieldOffset(SYM(MONITOR), "yTxf", &dwOffset);
move(yTxf, param1 + dwOffset);
GetFieldOffset(SYM(MONITOR), "slope", &dwOffset);
move(slope, param1 + dwOffset);
GetFieldOffset(SYM(MONITOR), "yint", &dwOffset);
move(yint, param1 + dwOffset);
Print("%sxTxf = {", pstrPrefix);
for (dwOffset = 0; dwOffset < SM_POINT_CNT; ++dwOffset) {
Print("0x%I64x", xTxf[dwOffset]);
if (dwOffset != SM_POINT_CNT - 1) {
Print(", ");
}
}
Print("}\n");
Print("%syTxf = {", pstrPrefix);
for (dwOffset = 0; dwOffset < SM_POINT_CNT; ++dwOffset) {
Print("0x%I64x", yTxf[dwOffset]);
if (dwOffset != SM_POINT_CNT - 1) {
Print(", ");
}
}
Print("}\n");
Print("%sslope = {", pstrPrefix);
for (dwOffset = 0; dwOffset < SM_POINT_CNT - 1; ++dwOffset) {
Print("0x%I64x", slope[dwOffset]);
if (dwOffset != SM_POINT_CNT - 2) {
Print(", ");
}
}
Print("}\n");
Print("%syint = {", pstrPrefix);
for (dwOffset = 0; dwOffset < SM_POINT_CNT - 1; ++dwOffset) {
Print("0x%I64x", yint[dwOffset]);
if (dwOffset != SM_POINT_CNT - 2) {
Print(", ");
}
}
Print("}\n");
}
#endif // SUBPIXEL_MOUSE
}
BOOL Idmon(
DWORD opts,
ULONG64 param1)
{
UNREFERENCED_PARAMETER(opts);
if (param1 == NULL_PTR) {
return FALSE;
}
Print("Dumping MONITOR at %p\n", param1);
DumpMonitor(param1, "\t");
return TRUE;
}
BOOL Idy(
DWORD opts,
ULONG64 param1)
{
PTR pdi, gpdi, pMonitor, pshi;
PTR psi;
ULONG i;
BOOLEAN fBool;
ULONG cMonitors;
RECT rcScreen;
WORD dmLogPixels;
UNREFERENCED_PARAMETER(opts);
GETSHAREDINFO(pshi);
GetFieldValue((PTR)pshi, SYM(SHAREDINFO), "pDispInfo", gpdi);
if (param1) {
pdi = param1;
} else {
pdi = gpdi;
}
psi = GetGlobalPointer(VAR(gpsi));
GetFieldValue(psi, SYM(SERVERINFO), "rcScreen", rcScreen);
GetFieldValue(psi, SYM(SERVERINFO), "dmLogPixels", dmLogPixels);
_InitTypeRead(pdi, SYM(DISPLAYINFO));
cMonitors = (ULONG)ReadField(cMonitors);
Print("Dumping DISPLAYINFO at 0x%.8x\n", pdi);
Print("\thDev = 0x%.8x\n", ReadField(hDev));
Print("\thdcScreen = 0x%.8x\n", ReadField(hdcScreen));
Print("\thdcBits = 0x%.8x\n", ReadField(hdcBits));
Print("\thdcGray = 0x%.8x\n", ReadField(hdcGray));
Print("\thbmGray = 0x%.8x\n", ReadField(hbmGray));
Print("\tcxGray = %d\n", ReadField(cxGray));
Print("\tcyGray = %d\n", ReadField(cyGray));
Print("\tpdceFirst = 0x%.8x\n", ReadField(pdceFirst));
Print("\tpspbFirst = 0x%.8x\n", ReadField(pspbFirst));
Print("\tcMonitors (visible) = %d\n", cMonitors);
Print("\tpMonitorPrimary = 0x%.8x\n", RebaseSharedPtr(ReadField(pMonitorPrimary)));
Print("\tpMonitorFirst = 0x%.8x\n", RebaseSharedPtr(ReadField(pMonitorFirst)));
Print("\trcScreen = (%d,%d)-(%d,%d) %dx%d\n",
rcScreen.left, rcScreen.top,
rcScreen.right, rcScreen.bottom,
rcScreen.right - rcScreen.left,
rcScreen.bottom - rcScreen.top);
Print("\thrgnScreen = 0x%.8x\n", ReadField(hrgnScreen));
Print("\tdmLogPixels = %d\n", (WORD)ReadField(dmLogPixels));
Print("\tBitCountMax = %d\n", (WORD)ReadField(BitCountMax));
GetFieldValue(pdi, SYM(DISPLAYINFO), "fDesktopIsRect", fBool);
Print("\tfDesktopIsRect = %d\n", fBool);
GetFieldValue(pdi, SYM(DISPLAYINFO), "fAnyPalette", fBool);
Print("\tfAnyPalette = %d\n", fBool);
Print("\n");
if (pdi == gpdi) {
if (dmLogPixels != (WORD)ReadField(dmLogPixels)) {
Print("\n\n");
Print("ERROR - dmLogPixels doesn't match in gpsi (%d) and gpDispInfo (%d)\n",
dmLogPixels, (WORD)ReadField(dmLogPixels));
Print("\n\n");
}
}
for ( pMonitor = ReadField(pMonitorFirst), i = 1;
pMonitor;
GetFieldValue(pMonitor, SYM(MONITOR), "pMonitorNext", pMonitor), i++) {
pMonitor = RebaseSharedPtr(pMonitor);
Print("\tMonitor %d, pMonitor = 0x%.8x\n", i, pMonitor);
DumpMonitor(pMonitor, "\t\t");
Print("\n");
}
return TRUE;
}
#ifdef KERNEL
/***************************************************************************\
* kbd [queue]
*
* Loads a DLL containing more debugging extensions
*
* 10/27/92 IanJa Created.
* 6/9/1995 SanfordS made to fit stdexts motif
\***************************************************************************/
typedef struct {
int iVK;
LPSTR pszVK;
} VK, *PVK;
VK aVK[] = {
{ VK_SHIFT, "SHIFT" },
{ VK_LSHIFT, "LSHIFT" },
{ VK_RSHIFT, "RSHIFT" },
{ VK_CONTROL, "CONTROL" },
{ VK_LCONTROL, "LCONTROL" },
{ VK_RCONTROL, "RCONTROL" },
{ VK_MENU, "MENU" },
{ VK_LMENU, "LMENU" },
{ VK_RMENU, "RMENU" },
{ VK_NUMLOCK, "NUMLOCK" },
{ VK_CAPITAL, "CAPITAL" },
{ VK_LBUTTON, "LBUTTON" },
{ VK_MBUTTON, "MBUTTON" },
{ VK_RBUTTON, "RBUTTON" },
{ VK_XBUTTON1, "XBUTTON1" },
{ VK_XBUTTON2, "XBUTTON2" },
{ VK_RETURN , "ENTER" },
{ VK_KANA, "KANA/HANJA" },
{ VK_OEM_8, "OEM_8" },
// { 0x52 , "R" }, // your key goes here
{ 0, NULL }
};
ULONG WDBGAPI KbdPti(PTR pti, PVOID pOpt)
{
Ikbd(DOWNCAST(DWORD, pOpt), pti);
return 0;
}
BOOL Ikbd(
DWORD opts,
ULONG64 param1)
{
if (opts & OFLAG(a)) {
ForEachPti(KbdPti, ULongToPtr(opts & ~OFLAG(a)));
return TRUE;
}
try {
PTR pq;
PTR ptiKeyboard;
PBYTE pb, pbr;
int i;
BYTE afKeyState[CBKEYSTATE + CBKEYSTATERECENTDOWN];
PTR pgafAsyncKeyState;
BYTE afAsyncKeyState[CBKEYSTATE];
PTR pgafRawKeyState;
BYTE afRawKeyState[CBKEYSTATE];
UINT PhysModifiers;
BYTE vkey;
/*
* If 'u' was specified, make sure there was also an address
*/
if (opts & OFLAG(u)) {
if (param1 == 0) {
Print("provide arg 2 of ProcessUpdateKeyEvent(), or WM_UPDATEKEYSTATE wParam\n");
return FALSE;
}
move(afKeyState, param1);
pb = afKeyState;
pbr = afKeyState + CBKEYSTATE;
Print("Key State: === NEW STATE ==== Asynchronous Physical\n");
} else {
if (opts & OFLAG(k)) {
vkey = (BYTE)param1;
param1 = NULL_PTR;
}
if (param1) {
pq = param1;
} else {
pq = GetGlobalPointer(VAR(gpqForeground));
}
/*
* Print out simple thread info for pq->ptiLock.
*/
GetFieldValue(pq, SYM(tagQ), "ptiKeyboard", ptiKeyboard);
if (ptiKeyboard) {
Idt(OFLAG(p), ptiKeyboard);
}
GetFieldValue(pq, SYM(tagQ), "afKeyState", afKeyState);
pb = afKeyState;
pbr = afKeyState + CBKEYSTATE;
Print("Key State: QUEUE %p Asynchronous Raw\n", pq);
}
moveExp(&pgafAsyncKeyState, VAR(gafAsyncKeyState));
move(afAsyncKeyState, pgafAsyncKeyState);
moveExp(&pgafRawKeyState, VAR(gafRawKeyState));
move(afRawKeyState, pgafRawKeyState);
Print(" Down Toggle Recent Down Toggle Down Toggle\n");
if (opts & OFLAG(s)) {
for (vkey = 1; vkey < VK_UNKNOWN; ++vkey) {
Print("%02x %10.10s:\t%d %d %d %d %d %d %d\n",
vkey,
_GetVKeyName(vkey, 0),
TestKeyDownBit(pb, vkey) != 0,
TestKeyToggleBit(pb, vkey) != 0,
TestKeyRecentDownBit(pbr, vkey) != 0,
TestKeyDownBit(afAsyncKeyState, vkey) != 0,
TestKeyToggleBit(afAsyncKeyState, vkey) != 0,
TestKeyDownBit(afRawKeyState, vkey) != 0,
TestKeyToggleBit(afRawKeyState, vkey) != 0);
}
} else {
for (i = 0; aVK[i].pszVK != NULL; i++) {
Print("VK_%s:\t%d %d %d %d %d %d %d\n",
aVK[i].pszVK,
TestKeyDownBit(pb, aVK[i].iVK) != 0,
TestKeyToggleBit(pb, aVK[i].iVK) != 0,
TestKeyRecentDownBit(pbr, aVK[i].iVK) != 0,
TestKeyDownBit(afAsyncKeyState, aVK[i].iVK) != 0,
TestKeyToggleBit(afAsyncKeyState, aVK[i].iVK) != 0,
TestKeyDownBit(afRawKeyState, aVK[i].iVK) != 0,
TestKeyToggleBit(afRawKeyState, aVK[i].iVK) != 0);
}
if (opts & OFLAG(k)) {
Print("%s:\t%d %d %d %d %d %d %d\n",
GetVKeyName(vkey),
TestKeyDownBit(pb, vkey) != 0,
TestKeyToggleBit(pb, vkey) != 0,
TestKeyRecentDownBit(pbr, vkey) != 0,
TestKeyDownBit(afAsyncKeyState, vkey) != 0,
TestKeyToggleBit(afAsyncKeyState, vkey) != 0,
TestKeyDownBit(afRawKeyState, vkey) != 0,
TestKeyToggleBit(afRawKeyState, vkey) != 0);
}
}
moveExpValue(&PhysModifiers, VAR(gfsSASModifiersDown));
Print("PhysModifiers = %x\n", PhysModifiers);
} except(CONTINUE) {
}
return TRUE;
}
#endif // KERNEL
/************************************************************************\
* Itest
*
* Tests the basic stdexts macros and functions - a good check on the
* debugger extensions in general before you waste time debuging entensions.
*
* 6/9/1995 Created SanfordS
\************************************************************************/
BOOL Itest()
{
PTR p;
ULONG64 cch;
CHAR ach[80];
Print("Print test!\n");
SAFEWHILE (TRUE) {
Print("SAFEWHILE test... Hit Ctrl-C NOW!\n");
}
p = EvalExp(VAR(gpsi));
Print("EvalExp(%s) = %#p\n", VAR(gpsi), p);
GetSym(p, ach, &cch);
Print("GetSym(%#p) = %s\n", p, ach);
if (IsWinDbg()) {
Print("I think windbg is calling me.\n");
} else {
Print("I don't think windbg is calling me.\n");
}
Print("MoveBlock test...\n");
moveBlock(&p, EvalExp(VAR(gpsi)), sizeof(p));
Print("MoveBlock(%#p) = %#p.\n", EvalExp(VAR(gpsi)), p);
Print("moveExp test...\n");
moveExp(&p, VAR(gpsi));
Print("moveExp(%s) = %p.\n", VAR(gpsi), p);
Print("moveExpValue test...\n");
p = GetGlobalPointer(VAR(gpsi));
Print("moveExpValue(%s) = %#p.\n", VAR(gpsi), p);
Print("Basic tests complete.\n");
return TRUE;
}
/************************************************************************\
* Iuver
*
* Dumps versions of extensions and winsrv/win32k
*
* 6/15/1995 Created SanfordS
\************************************************************************/
BOOL Iuver()
{
try {
PTR psi, wSRVIFlags;
BOOL bExtsIs64 = (sizeof(VOID*) == 8);
#if DBG
Print("USEREXTS version: Checked %s.\n"
"WIN32K.SYS version: ", bExtsIs64 ? "ia64" : "x86");
#else
Print("USEREXTS version: Free %s.\n"
"WIN32K.SYS version: ", bExtsIs64 ? "ia64" : "x86");
#endif
psi = GetGlobalPointer(VAR(gpsi));
GetFieldValue(psi, SYM(SERVERINFO), "wSRVIFlags", wSRVIFlags);
Print((wSRVIFlags & SRVIF_CHECKED) ? "Checked" : "Free");
Print(" %s", IsPtr64() ? "ia64" : "x86");
Print(".\n");
} except (CONTINUE) {
}
return TRUE;
}
#ifdef KERNEL
#ifdef OBSOLETE
#define DUMPSTATUS(status) if (tryMoveExpValue(&Status, VAR(g ## status))) { \
Print("g%s = %lx\n", #status, Status); \
}
#define DUMPTIME(time) if (tryMoveExpValue(&Time, VAR(g ## time))) { \
Print("g%s = %lx\n", #time, Time); \
}
#else
#define DUMPSTATUS(status) moveExpValue(&Status, VAR(g ## status)); \
Print("g%s = %lx\n", #status, Status);
#define DUMPTIME(time) moveExpValue(&Time, VAR(g ## time)); \
Print("g%s = %lx\n", #time, Time);
#endif
/***************************************************************************\
* dinp - dump input diagnostics
* dinp -v verbose
* dinp -i show input records
*
* 04/13/98 IanJa Created.
\***************************************************************************/
int gnIndent;
BOOL Idinp(
DWORD opts,
ULONG64 param1)
{
try {
DWORD Time;
PTR pDeviceInfo;
ULONG64 v;
DWORD dw;
int i = 0;
DWORD nKbd = 0;
BOOL bVerbose = FALSE;
#if 0
{
NTSTATUS Status;
DUMPSTATUS(KbdIoctlLEDSStatus);
}
#endif
DUMPTIME(MouseProcessMiceInputTime);
DUMPTIME(MouseQueueMouseEventTime);
DUMPTIME(MouseUnqueueMouseEventTime);
if (opts & OFLAG(v)) {
bVerbose = TRUE;
}
pDeviceInfo = GetGlobalPointer(VAR(gpDeviceInfoList));
if (pDeviceInfo == NULL_PTR) {
Print("win32k!gpDeviceInfoList is NULL\n");
}
SAFEWHILE (pDeviceInfo) {
if (param1 && (param1 != pDeviceInfo)) {
// skip it
} else {
WCHAR awchBuffer[100];
DWORD cbBuffer;
BYTE type;
PTR h;
ULONG64 cLockObj;
_InitTypeRead(pDeviceInfo, SYM(tagDEVICEINFO));
Print("#%d: ", i);
type = (BYTE)ReadField(type);
switch (type) {
case DEVICE_TYPE_MOUSE:
Print("MOU");
break;
case DEVICE_TYPE_KEYBOARD:
Print("KBD");
++nKbd;
break;
#ifdef DEVICE_TYPE_HID
case DEVICE_TYPE_HID:
Print("HID");
break;
#endif
default:
Print("%2d?", type);
}
h = ReadField(head.h);
cLockObj = ReadField(head.cLockObj);
Print(" @ 0x%p h:0x%p (lock:0x%x) ", pDeviceInfo, h, (DWORD)cLockObj);
v = ReadField(usActions);
if (v) {
Print("\n Pending action: %x %s", (USHORT)v,
GetFlags(GF_DIAF, (USHORT)v, NULL, TRUE));
}
v = ReadField(ustrName.Length);
if (v) {
cbBuffer = min((ULONG)v, sizeof(awchBuffer) - sizeof(WCHAR));
v = ReadField(ustrName.Buffer);
if (tryMoveBlock(awchBuffer, v, cbBuffer)) {
Print("\n %.*ws\n", cbBuffer / sizeof(WCHAR), awchBuffer);
} else {
Print("\n");
}
} else {
Print("\n NO-NAME!\n");
}
switch (type) {
case DEVICE_TYPE_KEYBOARD:
Print(" Type: %04x SubType: %04x (%x, %x)\n",
(DWORD)ReadField(keyboard.IdEx.Type),
(DWORD)ReadField(keyboard.IdEx.Subtype),
(DWORD)ReadField(keyboard.Attr.KeyboardIdentifier.Type),
(DWORD)ReadField(keyboard.Attr.KeyboardIdentifier.Subtype));
break;
}
if (bVerbose || (param1 == pDeviceInfo)) {
ULONG offset, offset2;
gnIndent += 2;
dso(SYM(tagGENERIC_DEVICE_INFO), pDeviceInfo, 0);
gnIndent += 2;
GetFieldOffset(SYM(tagDEVICEINFO), "iosb", &offset);
Print(" IOSB @ 0x%p\n", pDeviceInfo + offset);
dso(SYM(_IO_STATUS_BLOCK), pDeviceInfo + offset, 0);
gnIndent -= 2;
switch (type) {
case DEVICE_TYPE_MOUSE:
GetFieldOffset(SYM(tagDEVICEINFO), "mouse", &offset);
Print(" MOUSE_DEVICE_INFO @ 0x%p\n", pDeviceInfo + offset);
dso(SYM(tagMOUSE_DEVICE_INFO), pDeviceInfo + offset, 0);
gnIndent += 2;
GetFieldOffset(SYM(tagMOUSE_DEVICE_INFO), "Attr", &offset2);
Print(" Attr @ 0x%p\n", pDeviceInfo + offset + offset2);
dso(SYM(_MOUSE_ATTRIBUTES), pDeviceInfo + offset + offset2, 0);
gnIndent -= 2;
break;
case DEVICE_TYPE_KEYBOARD:
GetFieldOffset(SYM(tagDEVICEINFO), "keyboard", &offset);
Print(" KEYBOARD_DEVICE_INFO @ 0x%p\n", pDeviceInfo + offset);
dso(SYM(tagKEYBOARD_DEVICE_INFO), pDeviceInfo + offset, 0);
gnIndent += 2;
GetFieldOffset(SYM(tagKEYBOARD_DEVICE_INFO), "Attr", &offset2);
Print(" KEYBOARD_ATTRIBUTES @ 0x%p\n", pDeviceInfo + offset + offset2);
dso(SYM(_KEYBOARD_ATTRIBUTES), pDeviceInfo + offset + offset2, DBG_DUMP_RECUR_LEVEL(1));
gnIndent -= 2;
break;
#ifdef GENERIC_INPUT
case DEVICE_TYPE_HID:
{
PTR pTLCInfo;
GetFieldOffset(SYM(tagDEVICEINFO), "hid", &offset);
Print(" HID_DEVICE_INFO @ 0x%p\n", pDeviceInfo + offset);
dso(SYM(tagHID_DEVICE_INFO), pDeviceInfo + offset, 0);
GetFieldValue(pDeviceInfo, SYM(tagDEVICEINFO), "hid.pTLCInfo", pTLCInfo);
Print(" HID_TLC_INFO @ 0x%p\n", pTLCInfo);
dso(SYM(tagHID_TLC_INFO), pTLCInfo, 0);
}
break;
#endif
default:
Print("Unknown device type %d\n", type);
}
if ((opts & OFLAG(i))
#ifdef GENERIC_INPUT
&& type != DEVICE_TYPE_HID
#endif
) {
ULONG offset;
PTR pData;
ULONG64 Information;
ULONG64 sizeDataItem;
GetFieldOffset(SYM(tagDEVICEINFO), "keyboard.Data", &offset);
pData = pDeviceInfo + offset;
GetFieldValue(pDeviceInfo, SYM(tagDEVICEINFO), "iosb.Information", Information);
sizeDataItem = GetTypeSize(SYM(_KEYBOARD_INPUT_DATA));
Print(" Input Records:");
if (Information == 0) {
Print(" NONE\n");
} else {
UINT i;
Print("\n");
gnIndent += 2;
for (i = 0; i < Information / sizeDataItem; ++i) {
dso(SYM(_KEYBOARD_INPUT_DATA), pData, 0);
pData += sizeDataItem;
}
gnIndent -= 2;
}
}
gnIndent -= 2;
}
#ifdef GENERIC_INPUT
else if (type == DEVICE_TYPE_HID) {
PTR pHidDesc;
USHORT UsagePage, Usage;
GetFieldValue(pDeviceInfo, SYM(tagDEVICEINFO), "hid.pHidDesc", pHidDesc);
_InitTypeRead(pHidDesc, SYM(HIDDESC));
UsagePage = (USHORT)ReadField(hidpCaps.UsagePage);
Usage = (USHORT)ReadField(hidpCaps.Usage);
Print(" UsagePage:%04x Usage:%04x\n", UsagePage, Usage);
}
#endif
Print("\n");
}
GetFieldValue(pDeviceInfo, SYM(tagDEVICEINFO), "pNext", pDeviceInfo);
++i;
}
// Now display input related sytem metrics
{
PTR psi;
ULONG offset;
static SYSMET_ENTRY aSysMet[] = {
SMENTRY(MOUSEPRESENT),
SMENTRY(MOUSEWHEELPRESENT),
SMENTRY(CMOUSEBUTTONS),
};
psi = GetGlobalPointer(VAR(gpsi));
GetFieldOffset(SYM(tagSERVERINFO), "aiSysMet", &offset);
for (i = 0; !IsCtrlCHit() && i < ARRAY_SIZE(aSysMet); ++i) {
int metric;
move(metric, psi + offset + aSysMet[i].iMetric * sizeof(int));
Print("SM_%-18s = 0x%08lx = %d\n",
aSysMet[i].pstrMetric,
metric,
metric);
}
}
moveExpValue(&dw, VAR(gnHid));
Print("#HID = 0x%x #Kbd = 0x%x\n", dw, nKbd);
} except (CONTINUE) {
}
return TRUE;
}
BOOL I_dinp(
DWORD opts,
ULONG64 param1)
{
#ifdef _IA64_
UNREFERENCED_PARAMETER(opts);
UNREFERENCED_PARAMETER(param1);
return FALSE;
#else
DWORD Time;
NTSTATUS Status;
PDEVICEINFO pDeviceInfo, *ppDeviceInfo;
int i = 0;
#if 0
char ach[100];
#endif
DWORD nKbd;
BOOL bVerbose = FALSE;
DUMPSTATUS(KbdIoctlLEDSStatus);
DUMPTIME(MouseProcessMiceInputTime);
DUMPTIME(MouseQueueMouseEventTime);
DUMPTIME(MouseUnqueueMouseEventTime);
if (opts & OFLAG(v)) {
bVerbose = TRUE;
}
ppDeviceInfo = (PDEVICEINFO*)EvalExp(VAR(gpDeviceInfoList));
while (tryMove(pDeviceInfo, (PTR)ppDeviceInfo) && pDeviceInfo) {
if (param1 && (param1 != (PTR)pDeviceInfo)) {
; // skip it
} else if (pDeviceInfo != 0) {
DEVICEINFO DeviceInfo;
WCHAR awchBuffer[100];
DWORD cbBuffer;
Print("#%d: %p ", i, (PTR)pDeviceInfo);
if (tryMove(DeviceInfo, (PTR)pDeviceInfo)) {
if (DeviceInfo.type == DEVICE_TYPE_MOUSE) {
Print("MOU", i);
} else if (DeviceInfo.type == DEVICE_TYPE_KEYBOARD) {
Print("KBD");
} else {
Print("%2d?", DeviceInfo.type);
}
if (DeviceInfo.usActions) {
Print(" Pending action %x %s", DeviceInfo.usActions,
GetFlags(GF_DIAF, DeviceInfo.usActions, NULL, TRUE));
}
cbBuffer = min(DeviceInfo.ustrName.Length, sizeof(awchBuffer)-sizeof(WCHAR));
if (tryMoveBlock(awchBuffer, (PTR)DeviceInfo.ustrName.Buffer, cbBuffer)) {
awchBuffer[cbBuffer / sizeof(WCHAR)] = 0;
Print("\n %ws\n", awchBuffer);
} else {
Print("\n");
}
} else {
DeviceInfo.type = 0xFF;
}
#if 0
if (bVerbose || (param1 == (PTR)pDeviceInfo)) {
sprintf(ach, "GENERIC_DEVICE_INFO 0x%p", pDeviceInfo);
gnIndent += 2;
Idso(0, ach);
gnIndent += 2;
sprintf(ach, "IO_STATUS_BLOCK 0x%p",
(PBYTE)pDeviceInfo + FIELD_OFFSET(DEVICEINFO, iosb));
Idso(0, ach);
gnIndent -= 2;
if (DeviceInfo.type == DEVICE_TYPE_MOUSE) {
sprintf(ach, "MOUSE_DEVICE_INFO 0x%p",
(PBYTE)pDeviceInfo + FIELD_OFFSET(DEVICEINFO, mouse));
Idso(0, ach);
gnIndent += 2;
sprintf(ach, "MOUSE_ATTRIBUTES 0x%p",
(PBYTE)pDeviceInfo + FIELD_OFFSET(DEVICEINFO, mouse)
+ FIELD_OFFSET(MOUSE_DEVICE_INFO, Attr));
Idso(0, ach);
gnIndent -= 2;
} else if (DeviceInfo.type == DEVICE_TYPE_KEYBOARD) {
sprintf(ach, "KEYBOARD_DEVICE_INFO 0x%p",
(PBYTE)pDeviceInfo + FIELD_OFFSET(DEVICEINFO, keyboard));
Idso(0, ach);
gnIndent += 2;
sprintf(ach, "KEYBOARD_ATTRIBUTES 0x%p",
(PBYTE)pDeviceInfo + FIELD_OFFSET(DEVICEINFO, keyboard)
+ FIELD_OFFSET(KEYBOARD_DEVICE_INFO, Attr));
Idso(0, ach);
gnIndent -= 2;
} else {
Print("Unknown device type %d\n", DeviceInfo.type);
}
if (opts & OFLAG(i)) {
Print(" Input Records:");
if (DeviceInfo.iosb.Information == 0) {
Print(" NONE\n");
} else {
Print("\n");
gnIndent += 2;
sprintf(ach, "KEYBOARD_INPUT_DATA %p *%x",
&(pDeviceInfo->keyboard.Data[0]),
DeviceInfo.iosb.Information / sizeof(DeviceInfo.keyboard.Data[0]));
Idso(0, ach);
gnIndent -= 2;
}
}
gnIndent -= 2;
}
#endif
}
ppDeviceInfo = FIXKP(&pDeviceInfo->pNext);
i++;
}
// Now display input related sytem metrics
{
SERVERINFO si;
//PSERVERINFO psi;
PTR psi;
// #define SMENTRY(sm) {SM_##sm, #sm} (see above
/*
* Add mouse- and keyboard- related entries to this table
* with the prefix removed, in whatever order you think is rational
*/
static SYSMET_ENTRY aSysMet[] = {
SMENTRY(MOUSEPRESENT),
SMENTRY(MOUSEWHEELPRESENT),
SMENTRY(CMOUSEBUTTONS),
};
psi = GetGlobalPointer(VAR(gpsi));
move(si, psi);
for (i = 0; i < ARRAY_SIZE(aSysMet); i++) {
Print( "SM_%-18s = 0x%08lx = %d\n",
aSysMet[i].pstrMetric,
si.aiSysMet[aSysMet[i].iMetric],
si.aiSysMet[aSysMet[i].iMetric]);
}
moveExpValue(&nKbd, VAR(gnKeyboards));
Print("gnKeyboards = %d\n", nKbd);
moveExpValue(&nKbd, VAR(gnMice));
Print("gnMice = %d\n", nKbd);
moveExpValue(&nKbd, VAR(gnHid));
Print("ghMice = %d\n", nKbd);
}
return TRUE;
#endif // _IA64_
}
#endif // KERNEL
#ifdef KERNEL
/***************************************************************************\
* hh - dump the flags in gdwHydraHint
*
* 05/20/98 MCostea Created.
\***************************************************************************/
BOOL Ihh(
DWORD opts,
ULONG64 param1)
{
DWORD dwHHint;
PTR pdwHH;
ULONG ulSessionId;
PTR pulASessionId;
int i, maxFlags;
char * aHHstrings[] = {
"HH_DRIVERENTRY 0x00000001",
"HH_USERINITIALIZE 0x00000002",
"HH_INITVIDEO 0x00000004",
"HH_REMOTECONNECT 0x00000008",
"HH_REMOTEDISCONNECT 0x00000010",
"HH_REMOTERECONNECT 0x00000020",
"HH_REMOTELOGOFF 0x00000040",
"HH_DRIVERUNLOAD 0x00000080",
"HH_GRECLEANUP 0x00000100",
"HH_USERKCLEANUP 0x00000200",
"HH_INITIATEWIN32KCLEANUP 0x00000400",
"HH_ALLDTGONE 0x00000800",
"HH_RITGONE 0x00001000",
"HH_RITCREATED 0x00002000",
"HH_LOADCURSORS 0x00004000",
"HH_KBDLYOUTGLOBALCLEANUP 0x00008000",
"HH_KBDLYOUTFREEWINSTA 0x00010000",
"HH_CLEANUPRESOURCES 0x00020000",
"HH_DISCONNECTDESKTOP 0x00040000",
"HH_DTQUITPOSTED 0x00080000",
"HH_DTQUITRECEIVED 0x00100000",
"HH_DTNONEWDESKTOP 0x00200000",
"HH_DTWAITONHANDLES 0x00400000",
};
UNREFERENCED_PARAMETER(opts);
if (param1) {
dwHHint = (DWORD)((DWORD_PTR)param1);
Print("gdwHydraHint is 0x%x:\n", dwHHint);
} else {
pdwHH = EvalExp(VAR(gdwHydraHint));
if (!tryMove(dwHHint, pdwHH)) {
Print("Can't get value of gdwHydraHint\n");
return FALSE;
}
pulASessionId = EvalExp(VAR(gSessionId));
if (!tryMove(ulSessionId, pulASessionId)) {
Print("Can't get value of gSessionId\n");
return FALSE;
}
Print("Session 0x%x \n gdwHydraHint is 0x%x:\n", ulSessionId, dwHHint);
}
i = 0;
maxFlags = ARRAY_SIZE(aHHstrings);
while (dwHHint) {
if (dwHHint & 0x01) {
if (i >= maxFlags) {
Print("\n Error: Unknown flags: userkdx.dll might be outdated\n");
return TRUE;
}
Print(" %s\n", aHHstrings[i]);
}
i++;
dwHHint >>= 1;
}
// TO DO: Dump the protocol
{
USHORT usProtocol = (USHORT)EvalExp(VAR(gProtocolType));
BOOL bRemoteSession = (BOOL)EvalExp(VAR(gbRemoteSession));
BOOL fRemotingConsole = (BOOL)EvalExp(VAR(gfRemotingConsole));
BOOL fSwitchInProgress = (BOOL)EvalExp(VAR(gfSwitchInProgress));
BOOL bExitInProgress = (BOOL)EvalExp(VAR(gfSessionSwitchBlock));
USHORT usPreviousProtocolType = (USHORT)EvalExp(VAR(gPreviousProtocolType));
//dt nt!_KUSER_SHARED_DATA ffdf0000 ActiveConsoleId
}
return TRUE;
}
#endif // KERNEL
/************************************************************************\
* Procedure: Idupm
*
* 04/29/98 GerardoB Created
\************************************************************************/
#ifdef KERNEL
BOOL Idupm(
VOID)
{
char ach[80];
DWORD dwMask;
int i;
WORD w = GF_UPM0;
Print("UserPreferencesMask:\n");
for (i = 0; i < SPI_BOOLMASKDWORDSIZE; i++) {
sprintf(ach, "win32k!gpdwCPUserPreferencesMask + %#lx", i * sizeof(DWORD));
moveExpValue(&dwMask, ach);
w = GF_UPM0 + i;
Print("Offset: %d - %#lx: %s\n",
i, dwMask, GetFlags(w, dwMask, NULL, TRUE));
}
return TRUE;
}
#endif // KERNEL
/************************************************************************\
* Procedure: Idimc
*
* HiroYama Created
*
\************************************************************************/
static struct /*NoName*/ {
const char* terse;
const char* verbose;
} gaIMCAttr[] = {
"IN", "INPUT",
"TC", "TARGET_CONVERTED",
"CV", "CONVERTED",
"TN", "TARGET_NOTCONVERTED",
"IE", "INPUT_ERROR",
"FC", "FIXEDCONVERTED",
};
const char* GetInxAttr(BYTE bAttr)
{
if (bAttr < ARRAY_SIZE(gaIMCAttr)) {
return gaIMCAttr[bAttr].terse;
}
return "**";
}
VOID _PrintInxAttr(
const char* title,
PTR pCompStr,
DWORD offset,
DWORD len)
{
DWORD i;
PTR pAttr = pCompStr + offset;
if (title == NULL) {
// Print a legend
Print(" ");
for (i = 0; i < ARRAY_SIZE(gaIMCAttr); ++i) {
if (i && i % 4 == 0) {
Print("\n");
Print(" ");
}
Print("%s:%s ", gaIMCAttr[i].terse, gaIMCAttr[i].verbose);
}
Print("\n");
return;
}
if (offset == 0 || len == 0) {
return;
}
Print(" %-12s (@ 0x%p) off:0x%x len:0x%x (in byte)\n",
title, pAttr, offset, len);
Print(" ");
i = 0;
SAFEWHILE (i < len) {
Print("|%s", GetInxAttr(GetByte(pAttr + i)));
++i;
}
Print("|\n");
}
#define PrintInxAttr(name) \
_PrintInxAttr(#name, pCompStr, (DWORD)ReadField(dw ## name ## Offset), (DWORD)ReadField(dw ## name ## Len))
VOID _PrintInxClause(
const char* title,
PTR pCompStr,
DWORD offset,
DWORD len)
{
PTR pClause = pCompStr + offset;
DWORD i;
if (offset == 0 || len == 0) {
return;
}
Print(" %-12s (@ 0x%p) off:0x%x len:0x%x (0x%x dwords)\n",
title, pClause, offset, len, len / sizeof(DWORD));
Print(" ");
len /= sizeof(DWORD);
i = 0;
SAFEWHILE (i < len) {
Print("|0x%x", GetDWord(pClause + i));
++i;
}
Print("|\n");
}
#define PrintInxClause(name) \
_PrintInxClause(#name, pCompStr, (DWORD)ReadField(dw ## name ## Offset), (DWORD)ReadField(dw ## name ## Len))
const char* GetInxStr(
WCHAR wchar,
BOOLEAN fUnicode)
{
static char ach[32];
if (wchar >= 0x20 && wchar <= 0x7e) {
sprintf(ach, "'%c'", wchar);
} else if (fUnicode) {
sprintf(ach, "U+%04x", wchar);
} else {
sprintf(ach, "%02x", (BYTE)wchar);
}
return ach;
}
VOID _PrintInxStr(
const char* title,
PTR pCompStr,
DWORD offset,
DWORD len,
BOOLEAN fUnicode)
{
DWORD i;
if (offset == 0 || len == 0) {
return;
}
Print(" %-12s (@ 0x%p) off:0x%x len:0x%x (0x%x cch)\n",
title, pCompStr + offset, offset, len, len / (fUnicode + 1));
Print(" ");
i = 0;
SAFEWHILE (i < len) {
WCHAR wchar;
if (fUnicode) {
wchar = GetWord(pCompStr + offset + i * sizeof(WCHAR));
} else {
wchar = GetByte(pCompStr + offset + i);
}
Print("|%s", GetInxStr(wchar, fUnicode));
++i;
}
Print("|\n");
}
#define PrintInxStr(name) \
_PrintInxStr(#name, pCompStr, (DWORD)ReadField(dw ## name ## Offset), (DWORD)ReadField(dw ## name ## Len), fUnicode)
#define PrintInxElementA(name) \
do { \
PrintInxAttr(name ## Attr); \
PrintInxClause(name ## Clause); \
PrintInxStr(name ## Str); \
} while (0)
#define PrintInxElementB(name) \
do { \
PrintInxClause(name ## Clause); \
PrintInxStr(name ## Str); \
} while (0)
VOID _PrintInxFriendlyStr(
const char* title,
PTR pCompStr,
DWORD dwAttrOffset,
DWORD dwAttrLen,
DWORD dwClauseOffset,
DWORD dwClauseLen,
DWORD dwStrOffset,
DWORD dwStrLen,
BOOLEAN fUnicode)
{
DWORD i;
DWORD n;
DWORD dwClause;
Print(" %-11s", title);
if (dwStrOffset == 0 || dwStrLen == 0) {
Print("\n");
return;
}
for (i = 0, n = 0; i < dwStrLen; ++i) {
BYTE bAttr;
WCHAR wchar;
//move(dwClause, (PDWORD)(pCompStr + dwClauseOffset) + n);
dwClause = GetDWord(pCompStr + dwClauseOffset + n * sizeof(DWORD));
if (dwClause == i) {
++n;
if (i) {
Print("| ");
}
}
if (fUnicode) {
wchar = GetWord(pCompStr + dwStrOffset + i * sizeof(WCHAR));
//move(wchar, (PWCHAR)((PBYTE)pCompStr + dwStrOffset) + i);
} else {
wchar = GetByte(pCompStr + dwStrOffset + i);
}
if (dwAttrOffset != ~0) {
//move(bAttr, pCompStr + dwAttrOffset + i);
bAttr = GetByte(pCompStr + dwAttrOffset + i);
Print("|%s:%s", GetInxAttr(bAttr), GetInxStr(wchar, fUnicode));
} else {
Print("|%s", GetInxStr(wchar, fUnicode));
}
}
Print("|\n");
if (dwClauseLen / sizeof(DWORD) != (n + 1)) {
Print(" ** dwClauseLen (0x%x) doesn't match to n (0x%x) **\n", dwClauseLen, (n + 1) * sizeof(DWORD));
}
if (dwAttrOffset != ~0 && dwAttrLen != dwStrLen) {
Print(" ** dwAttrLen (0x%x) doesn't match to dwStrLen (0x%x) **\n", dwAttrLen, dwStrLen);
}
}
#define PrintInxFriendlyStrA(name) \
_PrintInxFriendlyStr(#name, \
pCompStr, \
(DWORD)ReadField(dw ## name ## AttrOffset), \
(DWORD)ReadField(dw ## name ## AttrLen), \
(DWORD)ReadField(dw ## name ## ClauseOffset), \
(DWORD)ReadField(dw ## name ## ClauseLen), \
(DWORD)ReadField(dw ## name ## StrOffset), \
(DWORD)ReadField(dw ## name ## StrLen), \
fUnicode)
#define PrintInxFriendlyStrB(name) \
_PrintInxFriendlyStr(#name, \
pCompStr, \
~0, \
0, \
(DWORD)ReadField(dw ## name ## ClauseOffset), \
(DWORD)ReadField(dw ## name ## ClauseLen), \
(DWORD)ReadField(dw ## name ## StrOffset), \
(DWORD)ReadField(dw ## name ## StrLen), \
fUnicode)
BOOL Idimc(
DWORD opts,
ULONG64 param1)
{
try {
PTR pImc; // PIMC
PTR pClientImc; // PCLIENTIMC
PTR pInputContext; // PINPUTCONTEXT
PTR hInputContext;
BOOLEAN fUnicode = FALSE;
BOOLEAN fVerbose, fDumpInputContext, fShowIMCMinInfo, fShowModeSaver, fShowCompStrRaw;
if (param1 == 0) {
Print("!dimc -? for help\n");
return FALSE;
}
//
// If "All" option is specified, set all bits in opts
// except type specifiers.
//
if (opts & OFLAG(a)) {
opts |= ~(OFLAG(w) | OFLAG(c) | OFLAG(i) | OFLAG(u) | OFLAG(v));
}
fVerbose = (opts & OFLAG(v)) != 0;
fShowCompStrRaw = (opts & OFLAG(s)) != 0;
fDumpInputContext = (opts & OFLAG(d)) != 0;
fShowIMCMinInfo = (opts & OFLAG(h)) || fDumpInputContext;
fShowModeSaver = (opts & OFLAG(r)) != 0;
if (opts & OFLAG(w)) {
//
// Arg is hwnd or pwnd.
//
PTR pwnd;
if ((pwnd = HorPtoP(param1, TYPE_WINDOW)) == 0) {
return FALSE;
}
Print("pwnd=%p\n", pwnd);
GetFieldValue(pwnd, SYM(tagWND), "hImc", param1);
if (param1 == 0) {
Print("Could not read pwnd->hImc.\n");
return FALSE;
}
}
if (opts & OFLAG(c)) {
//
// Arg is client side IMC
//
pClientImc = param1;
goto LClientImc;
}
if (opts & OFLAG(i)) {
//
// Arg is pInputContext.
//
pInputContext = param1;
opts |= OFLAG(h); // otherwise, nothing will be displayed !
hInputContext = 0;
if (opts & OFLAG(u)) {
Print("Assuming Input Context is UNICODE.\n");
} else {
Print("Assuming Input Context is ANSI.\n");
}
goto LInputContext;
}
//
// Otherwise, Arg is hImc.
//
if ((pImc = HorPtoP(param1, TYPE_INPUTCONTEXT)) == 0) {
Print("Idimc: %p is not an input context.\n", param1);
return FALSE;
}
Print("pImc=%p\n", pImc);
InitTypeRead(pImc, win32k!IMC);
Print("pti:%p\n", ReadField(head.pti));
#ifdef KERNEL
// Print simple thread info.
if (ReadField(head.pti)) {
Idt(OFLAG(p), ReadField(head.pti));
}
#endif
InitTypeRead(pImc, win32k!IMC);
//
// Basic information
//
Print("pImc = %08p pti:%08p\n", pImc, FIXKP(ReadField(head.pti)));
Print(" handle %08p\n", ReadField(head.h));
Print(" dwClientImc %08p\n", ReadField(dwClientImcData));
Print(" hImeWnd %08p\n", ReadField(hImeWnd));
//
// Show client IMC
//
pClientImc = ReadField(dwClientImcData);
Print("pClientImc: %p\n", pClientImc);
LClientImc:
if (pClientImc == 0) {
Print("pClientImc is NULL.\n");
return TRUE;
}
InitTypeRead(pClientImc, user32!CLIENTIMC);
if (fVerbose) {
dso("user32!CLIENTIMC", pClientImc, 0);
} else {
Print("pClientImc @ 0x%p cLockObj:0x%x\n", ReadField(dwClientImcData), ReadField(cLockObj));
}
Print(" dwFlags %s\n", GetFlags(GF_CLIENTIMC, (DWORD)ReadField(dwFlags), NULL, TRUE));
fUnicode = !!(ReadField(dwFlags) & IMCF_UNICODE);
//
// Show InputContext
//
hInputContext = ReadField(hInputContext);
if (hInputContext) {
pInputContext = GetPointer(hInputContext);
} else {
pInputContext = 0;
}
LInputContext:
Print("InputContext 0x%08p (@ 0x%08p)", hInputContext, pInputContext);
if (pInputContext == 0) {
Print("\n");
return TRUE;
}
//
// if UNICODE specified by the option,
// set the flag accordingly
//
if (opts & OFLAG(u)) {
fUnicode = TRUE;
}
InitTypeRead(pInputContext, win32k!INPUTCONTEXT);
Print(" hwnd=%p\n", ReadField(hWnd));
if (fVerbose) {
dso(SYM(INPUTCONTEXT), pInputContext, 0);
}
//
// Decipher InputContext.
//
if (fShowIMCMinInfo) {
// COMPOSITIONSTRING
PTR hCompStr = 0;
PTR pCompStr = NULL_PTR;
// CANDIDATEINFO
PTR hCandInfo = 0;
PTR pCandInfo = NULL_PTR;
// GUIDELINE
PTR hGuideLine = 0;
PTR pGuideLine = NULL_PTR;
// TRANSMSGLIST
PTR hMsgBuf = 0;
PTR pMsgBuf = NULL_PTR;
DWORD i;
Print(" dwRefCount: 0x%x fdwDirty: %s\n",
(DWORD)ReadField(dwRefCount), GetFlags(GF_IMEDIRTY, (DWORD)ReadField(fdwDirty), NULL, TRUE));
Print(" Conversion: %s\n", GetFlags(GF_CONVERSION, (DWORD)ReadField(fdwConversion), NULL, TRUE));
Print(" Sentence: %s\n", GetFlags(GF_SENTENCE, (DWORD)ReadField(fdwSentence), NULL, TRUE));
Print(" fChgMsg: %d uSaveVKey: %02x %s\n",
(DWORD)ReadField(fChgMsg),
(DWORD)ReadField(uSavedVKey), GetVKeyName((UINT)ReadField(uSavedVKey)));
Print(" StatusWnd: (0x%x,0x%x) SoftKbd: (0x%x,0x%x)\n",
(LONG)ReadField(ptStatusWndPos.x), (LONG)ReadField(ptStatusWndPos.y),
(LONG)ReadField(ptSoftKbdPos.x), (LONG)ReadField(ptSoftKbdPos.y));
Print(" fdwInit: %s\n", GetFlags(GF_IMEINIT, (DWORD)ReadField(fdwInit), NULL, TRUE));
// Font
{
PINPUTCONTEXT pIC; // dummy for sizeof
LPCSTR fmt = " Font: '%s' %dpt wt:%d charset: %s\n";
BYTE ach[max(sizeof(pIC->lfFont.A.lfFaceName), sizeof(pIC->lfFont.W.lfFaceName))];
if (fUnicode) {
ULONG offset;
fmt = " Font: '%S' %dpt wt:%d charset: %s\n";
GetFieldOffset(SYM(INPUTCONTEXT), "lfFont.W.lfFaceName", &offset);
tryMoveBlock(ach, pInputContext + offset, sizeof(pIC->lfFont.W.lfFaceName));
// assuming WCHAR and alignment is consistent cross-platform...
} else {
ULONG offset;
GetFieldOffset(SYM(INPUTCONTEXT), "lfFont.A.lfFaceName", &offset);
tryMoveBlock(ach, pInputContext + offset, sizeof(pIC->lfFont.A.lfFaceName));
}
Print(fmt,
ach,
ReadField(lfFont.A.lfHeight),
ReadField(lfFont.A.lfWeight),
GetMaskedEnum(EI_CHARSETTYPE, (DWORD)ReadField(lfFont.A.lfCharSet), NULL));
}
// COMPOSITIONFORM
Print(" cfCompForm: %s pos:(0x%x,0x%x) rc:(0x%x,0x%x)-(0x%x,0x%x)\n",
GetFlags(GF_IMECOMPFORM, (DWORD)ReadField(cfCompForm.dwStyle), NULL, TRUE),
(DWORD)ReadField(cfCompForm.ptCurrentPos.x), (DWORD)ReadField(cfCompForm.ptCurrentPos.y),
(DWORD)ReadField(cfCompForm.rcArea.left), (DWORD)ReadField(cfCompForm.rcArea.top),
(DWORD)ReadField(cfCompForm.rcArea.right), (DWORD)ReadField(cfCompForm.rcArea.bottom));
if (hCompStr = ReadField(hCompStr)) {
if ((pCompStr = GetPointer(hCompStr)) == 0) {
Print("Could not get hCompStr=%p\n", hCompStr);
} else if (fVerbose) {
dso(SYM(COMPOSITIONSTRING), pCompStr, 0);
}
}
if (hCandInfo = ReadField(hCandInfo)) {
if ((pCandInfo = GetPointer(hCandInfo)) == 0) {
Print("Could not get hCandInfo=%p\n", hCandInfo);
} else if (fVerbose) {
dso(SYM(CANDIDATEINFO), pCandInfo, 0);
}
}
if (hGuideLine = ReadField(hGuideLine)) {
if ((pGuideLine = GetPointer(hGuideLine)) == 0) {
Print("Could not get hGuideLine=%p\n", hGuideLine);
} else if (fVerbose) {
dso(SYM(GUIDELINE), pGuideLine, 0);
}
}
if (hMsgBuf = ReadField(hMsgBuf)) {
if ((pMsgBuf = GetPointer(hMsgBuf)) == 0) {
Print("Could not get hMsgBuf=%p\n", hMsgBuf);
} else if (fVerbose) {
dso(SYM(TRANSMSGLIST), pMsgBuf, 0);
}
}
if (!fDumpInputContext && !fVerbose) {
Print(" CompStr @ 0x%p CandInfo @ 0x%p GuideL @ 0x%p \n",
pCompStr, pCandInfo, pGuideLine);
Print(" MsgBuf @ 0x%p (0x%x)\n", pMsgBuf, ReadField(dwNumMsgBuf));
}
if (fDumpInputContext) {
//
// Composition String
//
if (pCompStr) {
InitTypeRead(pCompStr, win32k!COMPOSITIONSTRING);
Print(" hCompositionString: %p (@ 0x%p) dwSize=0x%x\n",
hCompStr, pCompStr, (ULONG)ReadField(dwSize));
if (fShowCompStrRaw) {
_PrintInxAttr(NULL, /*NULL*/0, 0, 0);
PrintInxElementA(CompRead);
PrintInxElementA(Comp);
PrintInxElementB(ResultRead);
PrintInxElementB(Result);
}
Print(" CursorPos=0x%x DeltaStart=0x%x\n",
ReadField(dwCursorPos), ReadField(dwDeltaStart));
Print(" Private: (@ 0x%p) off:0x%x len:0x%x\n",
(PBYTE)pCompStr + ReadField(dwPrivateOffset),
ReadField(dwPrivateOffset), ReadField(dwPrivateSize));
Print("\n");
PrintInxFriendlyStrA(CompRead);
PrintInxFriendlyStrA(Comp);
PrintInxFriendlyStrB(ResultRead);
PrintInxFriendlyStrB(Result);
Print("\n");
} else {
Print(" pCompStr is NULL\n");
}
//
// Candidate Info
//
if (pCandInfo) {
DWORD CandInfo_dwCount;
InitTypeRead(pCandInfo, win32k!CANDIDATEINFO);
CandInfo_dwCount = (DWORD)ReadField(dwCount);
Print(" hCandidateInfo: %p (@ 0x%p) dwSize=0x%x dwCount=0x%x PrivOffset=0x%x PrivSize=0x%x\n",
hCandInfo, pCandInfo, ReadField(dwSize), ReadField(dwCount),
ReadField(dwPrivateOffset), ReadField(dwPrivateSize));
for (i = 0; i < CandInfo_dwCount; ++i) {
PTR pCandList;
DWORD j;
DWORD CandList_dwCount;
pCandList = pCandInfo + GetArrayElement(pCandInfo, SYM(CANDIDATEINFO), "dwOffset", i, "DWORD");
InitTypeRead(pCandList, win32k!CANDIDATELIST);
Print(" CandList[%02x] (@ 0x%p) %s count=%x sel=%x pgStart=%x pgSize=%x\n",
i, pCandList, GetMaskedEnum(EI_IMECANDIDATESTYLE, (DWORD)ReadField(dwStyle), NULL),
(DWORD)ReadField(dwCount),
(DWORD)ReadField(dwSelection), (DWORD)ReadField(dwPageStart), (DWORD)ReadField(dwPageSize));
CandList_dwCount = (DWORD)ReadField(dwCount);
if (ReadField(dwStyle) == IME_CAND_CODE && CandList_dwCount == 1) {
// Special case
Print(" Special case: DBCS char = %04x", (DWORD)GetArrayElement(pCandList, SYM(CANDIDATEINFO), "dwOffset", 0, "DWORD"));
} else if (CandList_dwCount > 1) {
DWORD dwSelection = (DWORD)ReadField(dwSelection);
for (j = 0; j < CandList_dwCount; ++j) {
DWORD k;
DWORD dwOffset;
dwOffset = (DWORD)GetArrayElement(pCandList, SYM(CANDIDATEINFO), "dwOffset", j, "DWORD");
Print(" %c%c[%02x] @ 0x%p ",
j == dwSelection ? '*' : ' ',
(j >= ReadField(dwPageStart) && j < ReadField(dwPageStart) + ReadField(dwPageSize) ? '+' : ' ',
j, pCandList + dwOffset));
for (k = 0; k < 0x100; ++k) { // limit upto 0xff cch
WCHAR wchar;
if (fUnicode) {
wchar = GetWord(pCandList + dwOffset + k * sizeof(wchar));
} else {
wchar = GetByte(pCandList + dwOffset + k);
}
if (wchar == 0) {
break;
}
Print("|%s", GetInxStr(wchar, fUnicode));
}
Print("|\n");
}
}
}
}
if (pGuideLine) {
//GUIDELINE GuideLine;
DWORD GuideLine_dwStrLen, GuideLine_dwStrOffset;
InitTypeRead(pGuideLine, user32!GUIDELINE);
GuideLine_dwStrLen = (DWORD)ReadField(dwStrLen);
GuideLine_dwStrOffset = (DWORD)ReadField(dwStrOffset);
Print(" hGuideLine: %p (@ 0x%p) dwSize=0x%x\n",
hGuideLine, pGuideLine, (DWORD)ReadField(dwSize));
Print(" level:%x index;%x privOffset:%x privSize:%x\n",
(DWORD)ReadField(dwLevel), (DWORD)ReadField(dwIndex),
(DWORD)ReadField(dwPrivateSize), (DWORD)ReadField(dwPrivateOffset));
if (GuideLine_dwStrOffset && GuideLine_dwStrLen) {
// String
Print(" str @ 0x%p ", (PBYTE)pGuideLine + (DWORD)ReadField(dwStrOffset));
for (i = 0; i < GuideLine_dwStrLen; ++i) {
WCHAR wchar;
if (fUnicode) {
wchar = GetWord(pGuideLine + GuideLine_dwStrOffset + i * sizeof(WCHAR));
} else {
wchar = GetByte(pGuideLine + GuideLine_dwStrOffset + i);
}
Print("|%s", GetInxStr(wchar, fUnicode));
}
Print("|\n");
}
}
if (pMsgBuf) {
DWORD dwNumMsgBuf;
InitTypeRead(pInputContext, user32!INPUTCONTEXT);
dwNumMsgBuf = (DWORD)ReadField(dwNumMsgBuf);
InitTypeRead(pMsgBuf, user32!TRANSMSGLIST);
Print(" hMsgBuf: %p (@ 0x%p) dwNumMsgBuf=0x%x uMsgCount=0x%x\n",
hMsgBuf, pMsgBuf, dwNumMsgBuf,
ReadField(uMsgCount));
if (dwNumMsgBuf) {
ULONG offset;
PTR pTransMsg; // PTRANSMSG
ULONG size;
GetFieldOffset("user32!TRANSMSGLIST", "TransMsg", &offset);
pTransMsg = pMsgBuf + offset;
size = GetTypeSize("user32!TRANSMSG");
Print(" | ## |msg | wParam | lParam |\n");
Print(" +----+----+--------+--------+\n");
for (i = 0; i < dwNumMsgBuf; ++i, pTransMsg += size) {
const char* pszMsg = "";
//DWORD j;
UINT message;
InitTypeRead(pTransMsg, user32!TRANSMSG);
message = (UINT)ReadField(message);
pszMsg = GetWindowMessageNameInternal(message);
#if 0
// Try to find a readable name of the window message
for (j = 0; j < ARRAY_SIZE(gaMsgs); ++j) {
if (gaMsgs[i].msg == message) {
pszMsg = gaMsgs[j].pszMsg;
break;
}
}
#endif
Print(" | %02x |%04x|%08x|%08x| %s\n",
i,
message, ReadField(wParam), ReadField(lParam), pszMsg);
}
Print(" +----+----+--------+--------+\n");
}
}
}
}
//
// Recursively display Mode Savers.
//
if (fShowModeSaver) {
PTR pModeSaver;
InitTypeRead(pInputContext, user32!INPUTCONTEXT);
pModeSaver = ReadField(pImeModeSaver);
//
// Private Mode Savers.
//
while (pModeSaver) {
InitTypeRead(pModeSaver, user32!IMEMODESAVER);
Print("ImeModeSaver @ 0x%p -- LangId=%04p fOpen=%d\n",
pModeSaver, ReadField(langId), (int)ReadField(fOpen));
Print(" fdwInit %s\n", GetFlags(GF_IMEINIT, (DWORD)ReadField(fdwInit), NULL, TRUE));
Print(" Conversion %s\n", GetFlags(GF_CONVERSION, (DWORD)ReadField(fdwConversion), NULL, TRUE));
Print(" Sentence %s\n", GetFlags(GF_SENTENCE, (DWORD)ReadField(fdwSentence), NULL, TRUE));
pModeSaver = ReadField(next);
}
}
} except (CONTINUE) {
}
return TRUE;
}
#if OLD_FORM
//////////////////////////////////////////////////////////
// OLD_FORM, that doesn't require the user mode symbol
//////////////////////////////////////////////////////////
VOID __PrintInxAttr(
const char* title,
PVOID pCompStr,
DWORD offset,
DWORD len)
{
DWORD i;
PBYTE pAttr = (PBYTE)pCompStr + offset;
if (title == NULL) {
// Print a legend
Print(" ");
for (i = 0; i < ARRAY_SIZE(gaIMCAttr); ++i) {
if (i && i % 4 == 0) {
Print("\n");
Print(" ");
}
Print("%s:%s ", gaIMCAttr[i].terse, gaIMCAttr[i].verbose);
}
Print("\n");
return;
}
if (offset == 0 || len == 0) {
return;
}
Print(" %-12s (@ 0x%p) off:0x%x len:0x%x (in byte)\n",
title, pAttr, offset, len);
Print(" ");
for (i = 0; i < len; ++i) {
BYTE bAttr;
move(bAttr, pAttr + i);
Print("|%s", GetInxAttr(bAttr));
}
Print("|\n");
}
#define _PrintInxAttr(name) \
__PrintInxAttr(#name, pCompStr, CompStr.dw ## name ## Offset, CompStr.dw ## name ## Len)
VOID __PrintInxClause(
const char* title,
PVOID pCompStr,
DWORD offset,
DWORD len)
{
PDWORD pClause = (PDWORD)((PBYTE)pCompStr + offset);
DWORD i;
if (offset == 0 || len == 0) {
return;
}
Print(" %-12s (@ 0x%p) off:0x%x len:0x%x (0x%x dwords)\n",
title, pClause, offset, len, len / sizeof(DWORD));
Print(" ");
len /= sizeof(DWORD);
for (i = 0; i < len; ++i) {
DWORD dwData;
move(dwData, pClause + i);
Print("|0x%x", dwData);
}
Print("|\n");
}
#define _PrintInxClause(name) \
__PrintInxClause(#name, pCompStr, CompStr.dw ## name ## Offset, CompStr.dw ## name ## Len)
#if 0
const char* GetInxStr(WCHAR wchar, BOOLEAN fUnicode)
{
static char ach[32];
if (wchar >= 0x20 && wchar <= 0x7e) {
sprintf(ach, "'%c'", wchar);
} else if (fUnicode) {
sprintf(ach, "U+%04x", wchar);
} else {
sprintf(ach, "%02x", (BYTE)wchar);
}
return ach;
}
#endif
VOID __PrintInxStr(
const char* title,
PVOID pCompStr,
DWORD offset,
DWORD len,
BOOLEAN fUnicode)
{
DWORD i;
if (offset == 0 || len == 0) {
return;
}
Print(" %-12s (@ 0x%p) off:0x%x len:0x%x (0x%x cch)\n",
title, (PBYTE)pCompStr + offset, offset, len, len / (fUnicode + 1));
Print(" ");
for (i = 0; i < len; ++i) {
WCHAR wchar;
if (fUnicode) {
move(wchar, (PWCHAR)((PBYTE)pCompStr + offset) + i);
}
else {
BYTE bchar;
move(bchar, (PBYTE)pCompStr + offset + i);
wchar = bchar;
}
Print("|%s", GetInxStr(wchar, fUnicode));
}
Print("|\n");
}
#define PrintInxStr(name) \
_PrintInxStr(#name, pCompStr, CompStr.dw ## name ## Offset, CompStr.dw ## name ## Len, fUnicode)
#define _PrintInxElementA(name) \
do { \
__PrintInxAttr(name ## Attr); \
__PrintInxClause(name ## Clause); \
__PrintInxStr(name ## Str); \
} while (0)
#define _PrintInxElementB(name) \
do { \
__PrintInxClause(name ## Clause); \
__PrintInxStr(name ## Str); \
} while (0)
VOID __PrintInxFriendlyStr(
const char* title,
PBYTE pCompStr,
DWORD dwAttrOffset,
DWORD dwAttrLen,
DWORD dwClauseOffset,
DWORD dwClauseLen,
DWORD dwStrOffset,
DWORD dwStrLen,
BOOLEAN fUnicode)
{
DWORD i;
DWORD n;
DWORD dwClause;
Print(" %-11s", title);
if (dwStrOffset == 0 || dwStrLen == 0) {
Print("\n");
return;
}
for (i = 0, n = 0; i < dwStrLen; ++i) {
BYTE bAttr;
WCHAR wchar;
move(dwClause, (PDWORD)(pCompStr + dwClauseOffset) + n);
if (dwClause == i) {
++n;
if (i) {
Print("| ");
}
}
if (fUnicode) {
move(wchar, (PWCHAR)((PBYTE)pCompStr + dwStrOffset) + i);
}
else {
BYTE bchar;
move(bchar, (PBYTE)pCompStr + dwStrOffset + i);
wchar = bchar;
}
if (dwAttrOffset != ~0) {
move(bAttr, pCompStr + dwAttrOffset + i);
Print("|%s:%s", GetInxAttr(bAttr), GetInxStr(wchar, fUnicode));
}
else {
Print("|%s", GetInxStr(wchar, fUnicode));
}
}
Print("|\n");
if (dwClauseLen / sizeof(DWORD) != (n + 1)) {
Print(" ** dwClauseLen (0x%x) doesn't match to n (0x%x) **\n", dwClauseLen, (n + 1) * sizeof(DWORD));
}
if (dwAttrOffset != ~0 && dwAttrLen != dwStrLen) {
Print(" ** dwAttrLen (0x%x) doesn't match to dwStrLen (0x%x) **\n", dwAttrLen, dwStrLen);
}
}
#define __PrintInxFriendlyStrA(name) \
__PrintInxFriendlyStr(#name, \
(PBYTE)pCompStr, \
CompStr.dw ## name ## AttrOffset, \
CompStr.dw ## name ## AttrLen, \
CompStr.dw ## name ## ClauseOffset, \
CompStr.dw ## name ## ClauseLen, \
CompStr.dw ## name ## StrOffset, \
CompStr.dw ## name ## StrLen, \
fUnicode)
#define _PrintInxFriendlyStrB(name) \
__PrintInxFriendlyStr(#name, \
(PBYTE)pCompStr, \
~0, \
0, \
CompStr.dw ## name ## ClauseOffset, \
CompStr.dw ## name ## ClauseLen, \
CompStr.dw ## name ## StrOffset, \
CompStr.dw ## name ## StrLen, \
fUnicode)
BOOL I_dimc(DWORD opts, ULONG64 param1)
{
IMC imc;
PIMC pImc;
PCLIENTIMC pClientImc;
CLIENTIMC ClientImc;
PINPUTCONTEXT pInputContext;
INPUTCONTEXT InputContext;
HANDLE hInputContext;
BOOLEAN fUnicode = FALSE;
BOOLEAN fVerbose, fDumpInputContext, fShowIMCMinInfo, fShowModeSaver, fShowCompStrRaw;
char ach[32];
if (param1 == 0) {
Print("!dimc -? for help\n");
return FALSE;
}
//
// If "All" option is specified, set all bits in opts
// except type specifiers.
//
if (opts & OFLAG(a)) {
opts |= ~(OFLAG(w) | OFLAG(c) | OFLAG(i) | OFLAG(u));
}
fVerbose = !!(opts & OFLAG(v));
fShowCompStrRaw = (opts & OFLAG(s)) || fVerbose;
fDumpInputContext = (opts & OFLAG(d)) || fShowCompStrRaw || fVerbose;
fShowIMCMinInfo = (opts & OFLAG(h)) || fDumpInputContext || fVerbose;
fShowModeSaver = (opts & OFLAG(r)) || fVerbose;
if (opts & OFLAG(w)) {
//
// Arg is hwnd or pwnd.
//
PWND pwnd;
if ((pwnd = HorPtoP(param1, TYPE_WINDOW)) == 0) {
return FALSE;
}
Print("pwnd=%p\n", pwnd);
if (!tryMove(param1, &pwnd->hImc)) {
Print("Could not read pwnd->hImc.\n");
return FALSE;
}
}
if (opts & OFLAG(c)) {
//
// Arg is client side IMC
//
pClientImc = param1;
goto LClientImc;
}
if (opts & OFLAG(i)) {
//
// Arg is pInputContext.
//
pInputContext = param1;
opts |= OFLAG(h); // otherwise, nothing will be displayed !
hInputContext = 0;
if (opts & OFLAG(u)) {
Print("Assuming Input Context is UNICODE.\n");
}
else {
Print("Assuming Input Context is ANSI.\n");
}
goto LInputContext;
}
//
// Otherwise, Arg is hImc.
//
if ((pImc = HorPtoP(param1, TYPE_INPUTCONTEXT)) == 0) {
Print("Idimc: %x is not an input context.\n", param1);
return FALSE;
}
//move(imc, FIXKP(pImc));
move(imc, pImc);
#ifdef KERNEL
// Print simple thread info.
if (imc.head.pti) {
Idt(OFLAG(p), (PTR)imc.head.pti);
}
#endif
//
// Basic information
//
Print("pImc = %08lx pti:%08lx\n", pImc, FIXKP(imc.head.pti));
Print(" handle %08lx\n", imc.head.h);
Print(" dwClientImc %08lx\n", imc.dwClientImcData);
Print(" hImeWnd %08lx\n", imc.hImeWnd);
//
// Show client IMC
//
pClientImc = (PVOID)imc.dwClientImcData;
LClientImc:
if (pClientImc == NULL) {
Print("pClientImc is NULL.\n");
return TRUE;
}
move(ClientImc, pClientImc);
if (fVerbose) {
sprintf(ach, "CLIENTIMC %p", pClientImc);
Idso(0, ach);
}
else {
Print("pClientImc @ 0x%p cLockObj:0x%x\n", imc.dwClientImcData, ClientImc.cLockObj);
}
Print(" dwFlags %s\n", GetFlags(GF_CLIENTIMC, ClientImc.dwFlags, NULL, TRUE));
fUnicode = !!(ClientImc.dwFlags & IMCF_UNICODE);
//
// Show InputContext
//
hInputContext = ClientImc.hInputContext;
if (hInputContext) {
move(pInputContext, hInputContext);
}
else {
pInputContext = NULL;
}
LInputContext:
Print("InputContext %08lx (@ 0x%p)", hInputContext, pInputContext);
if (pInputContext == NULL) {
Print("\n");
return TRUE;
}
//
// if UNICODE specified by the option,
// set the flag accordingly
//
if (opts & OFLAG(u)) {
fUnicode = TRUE;
}
move(InputContext, pInputContext);
Print(" hwnd=%p\n", InputContext.hWnd);
if (fVerbose) {
sprintf(ach, "INPUTCONTEXT %p", pInputContext);
Idso(0, ach);
}
//
// Decipher InputContext.
//
if (fShowIMCMinInfo) {
PCOMPOSITIONSTRING pCompStr = NULL;
PCANDIDATEINFO pCandInfo = NULL;
PGUIDELINE pGuideLine = NULL;
PTRANSMSGLIST pMsgBuf = NULL;
DWORD i;
Print(" dwRefCount: 0x%x fdwDirty: %s\n",
InputContext.dwRefCount, GetFlags(GF_IMEDIRTY, InputContext.fdwDirty, NULL, TRUE));
Print(" Conversion: %s\n", GetFlags(GF_CONVERSION, InputContext.fdwConversion, NULL, TRUE));
Print(" Sentence: %s\n", GetFlags(GF_SENTENCE, InputContext.fdwSentence, NULL, TRUE));
Print(" fChgMsg: %d uSaveVKey: %02x %s\n",
InputContext.fChgMsg,
InputContext.uSavedVKey, GetVKeyName(InputContext.uSavedVKey));
Print(" StatusWnd: (0x%x,0x%x) SoftKbd: (0x%x,0x%x)\n",
InputContext.ptStatusWndPos.x, InputContext.ptStatusWndPos.y,
InputContext.ptSoftKbdPos.x, InputContext.ptSoftKbdPos.y);
Print(" fdwInit: %s\n", GetFlags(GF_IMEINIT, InputContext.fdwInit, NULL, TRUE));
// Font
{
LPCSTR fmt = " Font: '%s' %dpt wt:%d charset: %s\n";
if (fUnicode) {
fmt = " Font: '%S' %dpt wt:%d charset: %s\n";
}
Print(fmt,
InputContext.lfFont.A.lfFaceName,
InputContext.lfFont.A.lfHeight,
InputContext.lfFont.A.lfWeight,
GetMaskedEnum(EI_CHARSETTYPE, InputContext.lfFont.A.lfCharSet, NULL));
}
// COMPOSITIONFORM
Print(" cfCompForm: %s pos:(0x%x,0x%x) rc:(0x%x,0x%x)-(0x%x,0x%x)\n",
GetFlags(GF_IMECOMPFORM, InputContext.cfCompForm.dwStyle, NULL, TRUE),
InputContext.cfCompForm.ptCurrentPos.x, InputContext.cfCompForm.ptCurrentPos.y,
InputContext.cfCompForm.rcArea.left, InputContext.cfCompForm.rcArea.top,
InputContext.cfCompForm.rcArea.right, InputContext.cfCompForm.rcArea.bottom);
if (InputContext.hCompStr) {
if (!tryMove(pCompStr, InputContext.hCompStr)) {
Print("Could not get hCompStr=%08x\n", InputContext.hCompStr);
//return FALSE;
}
}
if (pCompStr && fVerbose) {
sprintf(ach, "COMPOSITIONSTRING %p", pCompStr);
Idso(0, ach);
}
if (InputContext.hCandInfo) {
if (!tryMove(pCandInfo, InputContext.hCandInfo)) {
Print("Could not get hCandInfo=%08x\n", InputContext.hCandInfo);
//return FALSE;
}
}
if (pCandInfo && fVerbose) {
sprintf(ach, "CANDIDATEINFO %p", pCandInfo);
Idso(0, ach);
}
if (InputContext.hGuideLine) {
if (!tryMove(pGuideLine, InputContext.hGuideLine)) {
Print("Could not get hGuideLine=%08x\n", InputContext.hGuideLine);
//return FALSE;
}
}
if (pGuideLine && fVerbose) {
sprintf(ach, "GUIDELINE %p", pGuideLine);
Idso(0, ach);
}
if (InputContext.hMsgBuf) {
if (!tryMove(pMsgBuf, InputContext.hMsgBuf)) {
Print("Could not get hMsgBuf=%08x\n", InputContext.hMsgBuf);
//return FALSE;
}
}
if (pMsgBuf && fVerbose) {
sprintf(ach, "TRANSMSGLIST %p", pMsgBuf);
Idso(0, ach);
}
if (!fDumpInputContext && !fVerbose) {
Print(" CompStr @ 0x%p CandInfo @ 0x%p GuideL @ 0x%p \n",
pCompStr, pCandInfo, pGuideLine);
Print(" MsgBuf @ 0x%p (0x%x)\n", pMsgBuf, InputContext.dwNumMsgBuf);
}
if (fDumpInputContext) {
//
// Composition String
//
if (pCompStr) {
COMPOSITIONSTRING CompStr;
move(CompStr, pCompStr);
Print(" hCompositionString: %p (@ 0x%p) dwSize=0x%x\n",
InputContext.hCompStr, pCompStr, CompStr.dwSize);
if (fShowCompStrRaw) {
__PrintInxAttr(NULL, NULL, 0, 0);
_PrintInxElementA(CompRead);
_PrintInxElementA(Comp);
_PrintInxElementB(ResultRead);
_PrintInxElementB(Result);
}
Print(" CursorPos=0x%x DeltaStart=0x%x\n",
CompStr.dwCursorPos, CompStr.dwDeltaStart);
Print(" Private: (@ 0x%p) off:0x%x len:0x%x\n",
(PBYTE)pCompStr + CompStr.dwPrivateOffset,
CompStr.dwPrivateOffset, CompStr.dwPrivateSize);
Print("\n");
_PrintInxFriendlyStrA(CompRead);
_PrintInxFriendlyStrA(Comp);
_PrintInxFriendlyStrB(ResultRead);
_PrintInxFriendlyStrB(Result);
Print("\n");
}
else {
Print(" pCompStr is NULL\n");
}
//
// Candidate Info
//
if (pCandInfo) {
CANDIDATEINFO CandInfo;
move(CandInfo, pCandInfo);
Print(" hCandidateInfo: %p (@ 0x%p) dwSize=0x%x dwCount=0x%x PrivOffset=0x%x PrivSize=0x%x\n",
InputContext.hCandInfo, pCandInfo, CandInfo.dwSize, CandInfo.dwCount,
CandInfo.dwPrivateOffset, CandInfo.dwPrivateSize);
for (i = 0; i < CandInfo.dwCount; ++i) {
PCANDIDATELIST pCandList;
CANDIDATELIST CandList;
DWORD j;
pCandList = (PCANDIDATELIST)((PBYTE)pCandInfo + CandInfo.dwOffset[i]);
move(CandList, pCandList);
Print(" CandList[%02x] (@ 0x%p) %s count=%x sel=%x pgStart=%x pgSize=%x\n",
i, pCandList, GetMaskedEnum(EI_IMECANDIDATESTYLE, CandList.dwStyle, NULL),
CandList.dwCount,
CandList.dwSelection, CandList.dwPageStart, CandList.dwPageSize);
if (CandList.dwStyle == IME_CAND_CODE && CandList.dwCount == 1) {
// Special case
Print(" Special case: DBCS char = %04x", CandList.dwOffset[0]);
}
else if (CandList.dwCount > 1) {
for (j = 0; j < CandList.dwCount; ++j) {
DWORD k;
DWORD dwOffset;
move(dwOffset, pCandList->dwOffset + j);
Print(" %c%c[%02x] @ 0x%p ",
j == CandList.dwSelection ? '*' : ' ',
(j >= CandList.dwPageStart && j < CandList.dwPageStart + CandList.dwPageSize) ? '+' : ' ',
j, (PBYTE)pCandList + dwOffset);
for (k = 0; k < 0x100; ++k) { // limit upto 0xff cch
WCHAR wchar;
if (fUnicode) {
move(wchar, (PWCHAR)((PBYTE)pCandList + dwOffset) + k);
}
else {
BYTE bchar;
move(bchar, (PBYTE)pCandList + dwOffset + k);
wchar = bchar;
}
if (wchar == 0) {
break;
}
Print("|%s", GetInxStr(wchar, fUnicode));
}
Print("|\n");
}
}
}
}
if (pGuideLine) {
GUIDELINE GuideLine;
move(GuideLine, pGuideLine);
Print(" hGuideLine: %p (@ 0x%p) dwSize=0x%x\n",
InputContext.hGuideLine, pGuideLine, GuideLine.dwSize);
Print(" level:%x index;%x privOffset:%x privSize:%x\n",
GuideLine.dwLevel, GuideLine.dwIndex,
GuideLine.dwPrivateSize, GuideLine.dwPrivateOffset);
if (GuideLine.dwStrOffset && GuideLine.dwStrLen) {
// String
Print(" str @ 0x%p ", (PBYTE)pGuideLine + GuideLine.dwStrOffset);
for (i = 0; i < GuideLine.dwStrLen; ++i) {
WCHAR wchar;
if (fUnicode) {
move(wchar, (PWCHAR)((PBYTE)pGuideLine + GuideLine.dwStrOffset) + i);
} else {
BYTE bchar;
move(bchar, (PBYTE)pGuideLine + GuideLine.dwStrOffset + i);
wchar = bchar;
}
Print("|%s", _GetInxStr(wchar, fUnicode));
}
Print("|\n");
}
}
if (pMsgBuf) {
TRANSMSGLIST TransMsgList;
move(TransMsgList, pMsgBuf);
Print(" hMsgBuf: %p (@ 0x%p) dwNumMsgBuf=0x%x uMsgCount=0x%x\n",
InputContext.hMsgBuf, pMsgBuf, InputContext.dwNumMsgBuf,
TransMsgList.uMsgCount);
if (InputContext.dwNumMsgBuf) {
PTRANSMSG pTransMsg = pMsgBuf->TransMsg;
Print(" | ## |msg | wParam | lParam |\n");
Print(" +----+----+--------+--------+\n");
for (i = 0; i < InputContext.dwNumMsgBuf; ++i, ++pTransMsg) {
const char* pszMsg = "";
TRANSMSG TransMsg;
//DWORD j;
move(TransMsg, pTransMsg);
#if 0
// Try to find a readable name of the window message
for (j = 0; j < ARRAY_SIZE(gaMsgs); ++j) {
if (gaMsgs[i].msg == TransMsg.message) {
pszMsg = gaMsgs[j].pszMsg;
break;
}
}
#else
pszMsg = GetWindowMessageNameInternal(TransMsg.message);
#endif
Print(" | %02x |%04x|%08x|%08x| %s\n",
i,
TransMsg.message, TransMsg.wParam, TransMsg.lParam, pszMsg);
}
Print(" +----+----+--------+--------+\n");
}
}
}
}
//
// Recursively display Mode Savers.
//
if (fShowModeSaver) {
PIMEMODESAVER pModeSaver = InputContext.pImeModeSaver;
//
// Private Mode Savers.
//
while (pModeSaver) {
IMEMODESAVER ImeModeSaver;
move(ImeModeSaver, pModeSaver);
Print("ImeModeSaver @ 0x%p -- LangId=0x%04x fOpen=0y%d\n",
pModeSaver, ImeModeSaver.langId, ImeModeSaver.fOpen);
Print(" fdwInit %s\n", GetFlags(GF_IMEINIT, ImeModeSaver.fdwInit, NULL, TRUE));
Print(" Conversion %s\n", GetFlags(GF_CONVERSION, ImeModeSaver.fdwConversion, NULL, TRUE));
Print(" Sentence %s\n", GetFlags(GF_SENTENCE, ImeModeSaver.fdwSentence, NULL, TRUE));
move(pModeSaver, &pModeSaver->next);
}
}
return TRUE;
}
#endif // OLD_FORM
#ifdef OLD_DEBUGGER
#ifndef KERNEL
/************************************************************************\
* Procedure: Ikc
*
* Dumps keyboard cues state for the window, and pertinent info on the
* parent KC state and the system settings related to this
*
* 06/11/98 MCostea Created
*
\************************************************************************/
BOOL Ikc(
DWORD opts,
ULONG64 param1)
{
WND wnd;
PWND pwnd, pwndParent;
char ach[80];
BOOL bHideFocus, bHideAccel;
SERVERINFO si;
PSERVERINFO psi;
if (param1 && (pwnd = HorPtoP(param1, TYPE_WINDOW)) == 0) {
Print("Idw: %p is not a pwnd.\n", param1);
return FALSE;
}
psi = GetGlobalPointer(VAR(gpsi));
move(si, psi);
if (si.bKeyboardPref) {
Print("gpsi->bKeyboardPref ON, KC mechanism is turned off\n");
}
if (!(si.PUSIFlags & (PUSIF_KEYBOARDCUES | PUSIF_UIEFFECTS) == PUSIF_KEYBOARDCUES | PUSIF_UIEFFECTS)) {
Print("Either the UI effects or PUSIF_KEYBOARDCUES are off\n");
}
if (!param1) {
return FALSE;
}
move(wnd, FIXKP(pwnd));
/*
* Print pwnd and title string.
*/
DebugGetWindowTextA(pwnd, ach, ARRAY_SIZE(ach));
Print("pwnd = %08lx \"%s\"\n", pwnd, ach);
bHideAccel = TestWF(pwnd, WEFPUIACCELHIDDEN);
bHideFocus = TestWF(pwnd, WEFPUIFOCUSHIDDEN);
switch(wnd.fnid) {
case FNID_BUTTON :
{
Print("FNID_BUTTON");
}
goto printCues;
case FNID_LISTBOX :
{
Print("FNID_LISTBOX");
}
goto printCues;
case FNID_DIALOG :
{
Print("FNID_DIALOG");
}
goto printCues;
case FNID_STATIC :
{
Print("FNID_STATIC");
}
printCues:
Print(bHideAccel ? " Hide Accel" : " Show Accel");
Print(bHideFocus ? " Hide Focus" : " Show Focus");
break;
default:
Print("Not KC interesting FNID 0x%x", wnd.fnid);
break;
}
Print("\n");
pwndParent = wnd.spwndParent;
move(wnd, FIXKP(wnd.spwndParent));
if (wnd.fnid == FNID_DIALOG) {
Print("The parent is a dialog:\n");
Ikc(opts, pwndParent);
} else {
Print("The parent is not a dialog\n");
}
return TRUE;
}
#endif // KERNEL
#endif // OLD_DEBUGGER
#ifdef KERNEL
/************************************************************************\
* Procedure: Idimk -- dump IME Hotkeys
*
* 08/09/98 HiroYama Created
*
\************************************************************************/
#define IHK_ITEM(x) { x, #x }
BOOL Idimk(DWORD opts, ULONG64 param1)
{
try {
// PIMEHOTKEYOBJ
PTR pObj;
static const struct {
DWORD mask;
const char* name;
} masks[] = {
IHK_ITEM(MOD_IGNORE_ALL_MODIFIER),
IHK_ITEM(MOD_ON_KEYUP),
IHK_ITEM(MOD_RIGHT),
IHK_ITEM(MOD_LEFT),
IHK_ITEM(MOD_SHIFT),
IHK_ITEM(MOD_CONTROL),
IHK_ITEM(MOD_ALT),
};
int nHotKeys = 0;
UNREFERENCED_PARAMETER(opts);
if (param1 == 0) {
pObj = GetGlobalPointer(VAR(gpImeHotKeyListHeader));
if (!pObj) {
Print("No IME HotKeys. win32k!gpImeHotKeyListHeader is NULL.\n\n");
return TRUE;
}
Print("using win32k!gpImeHotKeyListHeader (@ 0x%p)\n", pObj);
} else {
pObj = FIXKP(param1);
}
SAFEWHILE (pObj) {
int i, n;
InitTypeRead(pObj, win32k!IMEHOTKEYOBJ);
Print("ImeHotKeyObj @ 0x%p\n", pObj);
Print(" pNext 0x%p\n", ReadField(pNext));
Print(" dwHotKeyID 0x%04x ", ReadField(hk.dwHotKeyID));
//
// Show hotkey ID by name
//
if (ReadField(hk.dwHotKeyID) >= IME_HOTKEY_DSWITCH_FIRST && ReadField(hk.dwHotKeyID) <= IME_HOTKEY_DSWITCH_LAST) {
Print(" Direct Switch to HKL 0x%p", ReadField(hk.hKL));
} else {
Print(" %s", GetMaskedEnum(EI_IMEHOTKEYTYPE, (DWORD)ReadField(hk.dwHotKeyID), NULL));
}
//
// Show VKey value by name
//
Print("\n uVKey 0x%02x %s\n", (UINT)ReadField(hk.uVKey), GetVKeyName((DWORD)ReadField(hk.uVKey)));
//
// Show bit mask by name
//
Print( " Modifiers 0x%04x ", ReadField(hk.uModifiers));
n = 0;
for (i = 0; i < ARRAY_SIZE(masks); ++i) {
if (masks[i].mask & ReadField(hk.uModifiers)) {
Print("%s%s", n ? " | " : "", masks[i].name);
++n;
}
}
//
// Target HKL
//
Print("\n hKL 0x%p\n\n", ReadField(hk.hKL));
pObj = ReadField(pNext);
//
// If address is specified as an argument, just display one instance.
//
if (param1 != 0) {
break;
}
++nHotKeys;
}
if (nHotKeys) {
Print("Number of IME HotKeys: 0x%04x\n", nHotKeys);
}
} except (CONTINUE) {
}
return TRUE;
}
#undef IHK_ITEM
#endif // KERNEL
#ifdef KERNEL
/************************************************************************\
* Procedure: Igflags
*
* Dumps NT Global Flags
*
* 08/11/98 Hiroyama Created
*
\************************************************************************/
#define DGF_ITEM(x) { x, #x }
BOOL Igflags(DWORD opts)
{
static const struct {
DWORD dwFlag;
const char* name;
} names[] = {
DGF_ITEM(FLG_STOP_ON_EXCEPTION),
DGF_ITEM(FLG_SHOW_LDR_SNAPS),
DGF_ITEM(FLG_DEBUG_INITIAL_COMMAND),
DGF_ITEM(FLG_STOP_ON_HUNG_GUI),
DGF_ITEM(FLG_HEAP_ENABLE_TAIL_CHECK),
DGF_ITEM(FLG_HEAP_ENABLE_FREE_CHECK),
DGF_ITEM(FLG_HEAP_VALIDATE_PARAMETERS),
DGF_ITEM(FLG_HEAP_VALIDATE_ALL),
DGF_ITEM(FLG_POOL_ENABLE_TAGGING),
DGF_ITEM(FLG_HEAP_ENABLE_TAGGING),
DGF_ITEM(FLG_USER_STACK_TRACE_DB),
DGF_ITEM(FLG_KERNEL_STACK_TRACE_DB),
DGF_ITEM(FLG_MAINTAIN_OBJECT_TYPELIST),
DGF_ITEM(FLG_HEAP_ENABLE_TAG_BY_DLL),
DGF_ITEM(FLG_ENABLE_CSRDEBUG),
DGF_ITEM(FLG_ENABLE_KDEBUG_SYMBOL_LOAD),
DGF_ITEM(FLG_DISABLE_PAGE_KERNEL_STACKS),
DGF_ITEM(FLG_HEAP_DISABLE_COALESCING),
DGF_ITEM(FLG_ENABLE_CLOSE_EXCEPTIONS),
DGF_ITEM(FLG_ENABLE_EXCEPTION_LOGGING),
DGF_ITEM(FLG_ENABLE_HANDLE_TYPE_TAGGING),
DGF_ITEM(FLG_HEAP_PAGE_ALLOCS),
DGF_ITEM(FLG_DEBUG_INITIAL_COMMAND_EX),
DGF_ITEM(FLG_DISABLE_DBGPRINT),
};
DWORD dwFlags;
int i, n = 0;
moveExpValue(&dwFlags, "NT!NtGlobalFlag");
if (opts & OFLAG(v)) {
Print("NT!NtGlobalFlag %08lx\n\n", dwFlags);
} else {
Print("NT!NtGlobalFlag 0x%lx\n", dwFlags);
}
dwFlags &= FLG_VALID_BITS;
for (i = 0; i < ARRAY_SIZE(names); ++i) {
BOOLEAN on = (dwFlags & names[i].dwFlag) != 0;
if (opts & OFLAG(v)) {
Print(" %c%-34s %c(%08x)\n", on ? '*' : ' ', names[i].name, on ? '*' : ' ', names[i].dwFlag);
} else {
if (n++ % 2 == 0) {
Print("\n");
}
Print(" %c%-29s ", on ? '*' : ' ', names[i].name + sizeof("FLG_") - 1);
}
}
if (!(opts & OFLAG(v))) {
Print("\n");
}
return TRUE;
}
#undef DGF_ITEM
#endif // KERNEL
/************************************************************************\
* Procedure: Ivkey
*
* Dumps virtual keys
*
* 08/11/98 Hiroyama Created
*
\************************************************************************/
VOID PrintVKey(
int i)
{
Print(" %02x %s\n", gVKeyDef[i].dwVKey, gVKeyDef[i].name);
}
BOOL Ivkey(
DWORD opts,
LPSTR pszName)
{
int i;
if ((opts & OFLAG(a)) || (opts & OFLAG(o))) {
//
// List all virtual keys.
//
int n = 0;
for (i = 0; i < 0x100; ++i) {
const char* name = GetVKeyName(i);
if (*name) {
char buf[128];
int len;
sprintf(buf, " %02x %-35s", i, name);
if (opts & OFLAG(a)) {
//
// If it exceeds the second column width, begin new line.
//
if ((len = strlen(buf)) >= 40 && n % 2 == 1) {
Print("\n");
n = 0;
}
Print(buf);
//
// If it's in the second column, begin new line.
//
if (++n % 2 == 0 || len >= 40) {
Print("\n");
n = 0;
}
} else {
Print("%s\n", buf);
}
}
}
Print("\n");
} else if (*pszName == 'V' || *pszName == 'v') {
//
// Search by VK name.
//
int nFound = 0;
int len = strlen(pszName);
if (len == 4) {
int ch = pszName[3];
if ((ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')) {
Print(" %02x %s\n", ch, pszName);
++nFound;
}
}
for (i = 0; i < ARRAY_SIZE(gVKeyDef); ++i) {
if (_strnicmp(gVKeyDef[i].name, pszName, len) == 0) {
Print(" %02x %s\n", gVKeyDef[i].dwVKey, gVKeyDef[i].name);
++nFound;
}
}
if (nFound == 0) {
Print("Could not find it.\n");
}
} else {
//
// Search by VK value.
//
NTSTATUS status;
DWORD dwVKey;
const char* name;
status = GetInteger(pszName, 16, &dwVKey, NULL);
if (!NT_SUCCESS(status)) {
return FALSE;
}
name = GetVKeyName(dwVKey);
if (*name) {
Print(" %02x %s\n", dwVKey, name);
} else {
Print("Could not find it.\n");
}
}
return TRUE;
}
/************************************************************************\
* Procedure: Idisi
*
* Dumps event injection union
*
* 09/??/98 Hiroyama Created
*
\************************************************************************/
BOOL I_disi(DWORD opts, ULONG64 param1)
{
PINPUT pObj;
INPUT input;
#ifdef _IA64_
if (!IsPtr64()) {
Print("not on this platform");
return TRUE;
}
#else
if (IsPtr64()) {
Print("not on this platform");
return TRUE;
}
#endif
UNREFERENCED_PARAMETER(opts);
if (param1 == 0) {
return FALSE;
}
pObj = (PINPUT)FIXKP(param1);
move(input, (PTR)pObj);
Print("INPUT @ 0x%p - size: 0x%x\n", pObj, sizeof(input));
switch (input.type) {
case INPUT_MOUSE:
{
MOUSEINPUT* pmi = &input.mi;
Print("type: Mouse Input(%x)\n", input.type);
Print(" dx %lx (%ld in dec.)\n", pmi->dx, pmi->dx);
Print(" dy %lx (%ld in dec.)\n", pmi->dx, pmi->dx);
Print(" mouseData %lx (%ld in dec.)\n", pmi->mouseData, pmi->mouseData);
Print(" dwFlags %lx (%s)\n", pmi->dwFlags, GetFlags(GF_MI, pmi->dwFlags, NULL, TRUE));
Print(" time %lx\n", pmi->time);
Print(" dwExtraInfo %lx\n", pmi->dwExtraInfo);
}
break;
case INPUT_KEYBOARD:
{
KEYBDINPUT* pki = &input.ki;
const char* name;
Print("type: Keyboard Input(%x)\n", input.type);
//
// Print Vkey
//
Print(" wVk %lx", pki->wVk);
name = GetVKeyName(pki->wVk);
if (*name) {
Print(" (%s)\n", name);
} else {
Print("\n");
}
//
// Print scan code: if KEYEVENTF_UNICODE, it's UNICODE value.
//
if (pki->dwFlags & KEYEVENTF_UNICODE) {
Print(" UNICODE %lx\n", pki->wScan);
} else {
Print(" wScan %lx\n", pki->wScan);
}
//
// Print and decrypt dwFlags
//
Print(" dwFlags %lx (%s)\n", pki->dwFlags, GetFlags(GF_KI, pki->dwFlags, NULL, TRUE));
Print(" time %lx\n", pki->time);
Print(" dwExtraInfo %lx\n", pki->dwExtraInfo);
}
break;
case INPUT_HARDWARE:
Print("type: HardwareEvent(%x)\n", input.type);
Print(" uMsg %lx\n", input.hi.uMsg);
Print(" wParamH:wParamL %x:%x\n", input.hi.wParamH, input.hi.wParamL);
break;
default:
Print("Invalid type information(0x%lx)\n", input.type);
break;
}
return TRUE;
}
/************************************************************************\
* Procedure: Iwm
*
* Decrypt window message number
*
* 09/??/98 Hiroyama Created
*
\************************************************************************/
BOOL IwmWorker(DWORD opts, LPSTR pszName, BOOL fInternalToo)
{
int len = strlen(pszName);
UNREFERENCED_PARAMETER(opts);
if (!(opts & OFLAG(a)) && *pszName == 0) {
return FALSE;
}
if (len >= 3 && pszName[2] == '_' || (opts & OFLAG(a))) {
//
// Search by WM name.
//
int i;
int nFound = 0;
for (i = 0; i < ARRAY_SIZE(gaMsgs); ++i) {
if (((opts & OFLAG(a)) || _strnicmp(gaMsgs[i].pszMsg, pszName, len) == 0) && (!gaMsgs[i].fInternal || fInternalToo)) {
Print(" %04x %s\n", gaMsgs[i].msg, gaMsgs[i].pszMsg);
++nFound;
}
}
if (nFound == 0) {
Print("Could not find it.\n");
}
} else {
//
// Search by WM value.
//
DWORD value = (DWORD)EvalExp(pszName);
int i;
for (i = 0; i < ARRAY_SIZE(gaMsgs); ++i) {
if (gaMsgs[i].msg == value && (!gaMsgs[i].fInternal || fInternalToo)) {
Print(" %04x %s\n", gaMsgs[i].msg, gaMsgs[i].pszMsg);
break;
}
}
}
return TRUE;
}
BOOL Iwm(DWORD opts, LPSTR pszName)
{
return IwmWorker(opts, pszName, FALSE);
}
BOOL I_wm(DWORD opts, LPSTR pszName)
{
return IwmWorker(opts, pszName, TRUE);
}
//
// Dump Dialog Template
//
//
PBYTE SkipSz(UTCHAR *lpsz, UTCHAR* lpszCopy, UINT len)
{
UTCHAR c;
UINT n = 0;
lpszCopy[len - 1] = 0;
move(c, (PTR)lpsz);
if (c == 0xFF) {
if (lpszCopy) {
*lpszCopy = 0;
}
return (PBYTE)lpsz + 4;
}
do {
move(c, (PTR)lpsz);
++lpsz;
if (++n < len) {
if (lpszCopy) {
*lpszCopy ++ = c;
}
}
} while (c != 0);
return (PBYTE)lpsz;
}
#ifndef NextWordBoundary
#define NextWordBoundary(p) ((PBYTE)(p) + ((ULONG_PTR)(p) & 1))
#endif
#ifndef NextDWordBoundary
#define NextDWordBoundary(p) ((PBYTE)(p) + ((ULONG_PTR)(-(LONG_PTR)(p)) & 3))
#endif
PBYTE WordSkipSz(UTCHAR *lpsz, UTCHAR* lpszCopy, UINT len)
{
PBYTE pb = SkipSz(lpsz, lpszCopy, len);
return NextWordBoundary(pb);
}
PBYTE DWordSkipSz(UTCHAR *lpsz, UTCHAR* lpszCopy, UINT len)
{
PBYTE pb = SkipSz(lpsz, lpszCopy, len);
return NextDWordBoundary(pb);
}
LPCSTR GetCharSetName(BYTE charset)
{
return GetMaskedEnum(EI_CHARSETTYPE, charset, NULL);
}
VOID ParseDialogFont(LPWORD* lplpstr, LPDLGTEMPLATE2 lpdt)
{
LOGFONT LogFont;
short tmp;
int fontheight, fheight;
PSERVERINFO gpsi;
BOOL fDesktopCharset = FALSE;
WORD dmLogPixels;
//
// fheight = fontheight = (SHORT)(*((WORD *) *lplpstr)++);
//
move(tmp, (PTR)*lplpstr);
++*lplpstr;
fontheight = fheight = tmp;
if (fontheight == 0x7FFF) {
// a 0x7FFF height is our special code meaning use the message box font
Print("\
Font System Font (Messagebox font)\n");
return;
}
//
// The dialog template contains a font description! Use it.
//
// Fill the LogFont with default values
RtlZeroMemory(&LogFont, sizeof(LOGFONT));
moveExpValue(&gpsi, VAR(gpsi));
move(dmLogPixels, (ULONG64)&gpsi->dmLogPixels);
LogFont.lfHeight = -MultDiv(fontheight, dmLogPixels, 72);
if (lpdt->wDlgVer) {
WORD w;
BYTE b;
//
// LogFont.lfWeight = *((WORD FAR *) *lplpstr)++;
//
move(w, (PTR)*lplpstr);
++*lplpstr;
LogFont.lfWeight = w;
//
// LogFont.lfItalic = *((BYTE FAR *) *lplpstr)++;
//
move(b, (PTR)*lplpstr);
++((BYTE*)*lplpstr);
LogFont.lfItalic = b;
//
// LogFont.lfCharSet = *((BYTE FAR *) *lplpstr)++;
//
move(b, (PTR)*lplpstr);
++((BYTE*)*lplpstr);
LogFont.lfCharSet = b;
} else {
// DIALOG statement, which only has a facename.
// The new applications are not supposed to use DIALOG statement,
// they should use DIALOGEX instead.
LogFont.lfWeight = FW_BOLD;
LogFont.lfCharSet = 0; //(BYTE)GET_DESKTOP_CHARSET();
fDesktopCharset = TRUE;
}
*lplpstr = (WORD*)DWordSkipSz(*lplpstr, LogFont.lfFaceName, ARRAY_SIZE(LogFont.lfFaceName));
Print("\
Font %dpt (%d), Weight: %d, %s Italic, %s,\n\
\"%ls\"\n",
fontheight, LogFont.lfHeight,
LogFont.lfWeight,
LogFont.lfItalic ? "" : "Not",
fDesktopCharset ? "DESKTOP_CHARSET" : GetCharSetName(LogFont.lfCharSet),
LogFont.lfFaceName);
}
LPCSTR GetCtrlStyle(WORD iClass, DWORD style)
{
WORD type = GF_WS;
switch (iClass) {
case ICLS_DIALOG:
type = GF_DS;
break;
case ICLS_STATIC:
type = GF_SS;
break;
case ICLS_EDIT:
type = GF_ES;
break;
case ICLS_BUTTON:
type = GF_BS;
break;
case ICLS_COMBOBOX:
type = GF_CBS;
break;
case ICLS_LISTBOX:
type = GF_LBS;
break;
case ICLS_SCROLLBAR:
type = GF_SBS;
break;
default:
break;
}
return GetFlags(type, style, NULL, FALSE);
}
BOOL I_ddlgt(DWORD opts, ULONG64 param1)
{
#if defined(_IA64_)
UNREFERENCED_PARAMETER(opts);
UNREFERENCED_PARAMETER(param1);
return FALSE;
#else
LPDLGTEMPLATE lpdt = (LPDLGTEMPLATE)FIXKP(param1);
DLGTEMPLATE2 dt;
LPDLGTEMPLATE2 lpdt2 = &dt;
BOOLEAN fNewDialogTemplate = FALSE;
UTCHAR* lpszMenu;
UTCHAR* lpszClass;
UTCHAR* lpszText;
UTCHAR* lpStr;
UTCHAR* lpCreateParams;
LPCSTR lpszIClassName;
WORD w;
DLGITEMTEMPLATE2 dit;
LPDLGITEMTEMPLATE lpdit;
UTCHAR menuName[64];
UTCHAR className[64];
UTCHAR text[64];
PSERVERINFO gpsi;
UNREFERENCED_PARAMETER(opts);
if (opts == 0 && param1 == 0) {
return FALSE;
}
move(w, (PTR)&((LPDLGTEMPLATE2)lpdt)->wSignature);
if (w == 0xffff) {
move(dt, (PTR)lpdt);
fNewDialogTemplate = TRUE;
} else {
dt.wDlgVer = 0;
dt.wSignature = 0;
dt.dwHelpID = 0;
move(dt.dwExStyle, (ULONG64)&lpdt->dwExtendedStyle);
move(dt.style, (ULONG64)&lpdt->style);
move(dt.cDlgItems, (ULONG64)&lpdt->cdit);
move(dt.x, (PTR)&lpdt->x);
move(dt.y, (PTR)&lpdt->y);
move(dt.cx, (PTR)&lpdt->cx);
move(dt.cy, (PTR)&lpdt->cy);
}
Print("DlgTemplate%s @ 0x%p version 0n%d\n", dt.wDlgVer ? "2" : "", lpdt, dt.wDlgVer);
if (!(opts & OFLAG(v))) {
Print("\
(%d, %d)-(%d,%d) [%d, %d](dec)\n\
Style %08lx ExStyle %08lx items 0x%x\n",
dt.x, dt.y, dt.x + dt.cx, dt.y + dt.cy, dt.cx, dt.cy,
dt.style, dt.dwExStyle, dt.cDlgItems);
} else {
Print("\
(%d,%d)-(%d,%d) [%d,%d] (dec) item: 0x%lx\n",
dt.x, dt.y, dt.x + dt.cx, dt.y + dt.cy,
dt.cx, dt.cy,
dt.cDlgItems);
Print("\
Style %08lx %s", dt.style, OFLAG(v) ? GetFlags(GF_DS, dt.style, NULL, FALSE) : "");
if ((dt.style & DS_SHELLFONT) == DS_SHELLFONT) {
Print(" [DS_SHELLFONT]");
}
Print("\n");
Print("\
ExStyle %08lx %s\n", dt.dwExStyle, GetFlags(GF_WSEX, dt.dwExStyle, NULL, FALSE));
}
// If there's a menu name string, load it.
lpszMenu = (LPWSTR)(((PBYTE)(lpdt)) + (dt.wDlgVer ? sizeof(DLGTEMPLATE2) : sizeof(DLGTEMPLATE)));
/*
* If the menu id is expressed as an ordinal and not a string,
* skip all 4 bytes to get to the class string.
*/
move(w, (PTR)(WORD*)lpszMenu);
/*
* If there's a menu name string, load it.
*/
if (w != 0) {
if (w == 0xffff) {
LPWORD lpwMenu = (LPWORD)((LPBYTE)lpszMenu + 2);
move(w, (PTR)lpwMenu);
Print("\
menu id %lx\n", w);
}
}
if (w == 0xFFFF) {
lpszClass = (LPWSTR)((LPBYTE)lpszMenu + 4);
} else {
lpszClass = (UTCHAR *)WordSkipSz(lpszMenu, menuName, ARRAY_SIZE(menuName));
Print("\
menu @ 0x%p \"%ls\"\n", lpszMenu, menuName);
}
//
// Class name
//
lpszText = (UTCHAR *)WordSkipSz(lpszClass, className, ARRAY_SIZE(className));
Print("\
class @ 0x%p \"%ls\"\n", lpszClass, className);
//
// Window text
//
lpStr = (UTCHAR *)WordSkipSz(lpszText, text, ARRAY_SIZE(text));
Print("\
text @ 0x%p \"%ls\"\n", lpszText, text);
//
// Font
//
if (dt.style & DS_SETFONT) {
ParseDialogFont(&lpStr, &dt);
}
lpdit = (LPDLGITEMTEMPLATE)NextDWordBoundary(lpStr);
///////////////////////////////////////////////////
// if "-r" option is not specified, bail out.
///////////////////////////////////////////////////
if (!(opts & OFLAG(r))) {
return TRUE;
}
Print("\n");
/*
* Loop through the dialog controls, doing a CreateWindowEx() for each of
* them.
*/
while (dt.cDlgItems-- != 0) {
WORD iClass = 0;
//
// Retrieve basic information.
//
if (dt.wDlgVer) {
move(dit, (PTR)lpdit);
} else {
dit.dwHelpID = 0;
move(dit.dwExStyle, (PTR)&lpdit->dwExtendedStyle);
move(dit.style, (PTR)&lpdit->style);
move(dit.x, (PTR)&lpdit->x);
move(dit.y, (PTR)&lpdit->y);
move(dit.cx, (PTR)&lpdit->cx);
move(dit.cy, (PTR)&lpdit->cy);
move(w, (PTR)&lpdit->id);
dit.dwID = w;
}
Print("\
#ID:0x%04x @ 0x%p HelpID:0x%04x (0n%d, 0n%d)-(0n%d, 0n%d) [0n%d, 0n%d]\n",
dit.dwID,
lpdit,
dit.dwHelpID,
dit.x, dit.y, dit.x + dit.cx, dit.y + dit.cy,
dit.cx, dit.cy);
//
// Skip DLGITEMTEMPLATE or DLGITEMTEMPLATE2
//
lpszClass = (LPWSTR)(((PBYTE)(lpdit)) + (dt.wDlgVer ? sizeof(DLGITEMTEMPLATE2) : sizeof(DLGITEMTEMPLATE)));
/*
* If the first WORD is 0xFFFF the second word is the encoded class name index.
* Use it to look up the class name string.
*/
move(w, (PTR)lpszClass);
if (w == 0xFFFF) {
WORD wAtom;
lpszText = lpszClass + 2;
#ifdef ORG
lpszClass = (LPWSTR)(gpsi->atomSysClass[*(((LPWORD)lpszClass)+1) & ~CODEBIT]);
#endif
moveExpValue(&gpsi, VAR(gpsi));
move(iClass, (PTR)lpszClass + 1);
iClass &= ~CODEBIT;
if (*(lpszIClassName = GetMaskedEnum(EI_CLSTYPE, iClass, NULL)) == '\0') {
lpszIClassName = NULL;
}
move(wAtom, (PTR)&gpsi->atomSysClass[iClass]);
swprintf(className, L"#%lx", wAtom);
} else {
lpszText = (UTCHAR*)SkipSz(lpszClass, className, ARRAY_SIZE(className));
lpszIClassName = NULL;
}
Print("\
class @ 0x%p \"%ls\" ", lpszClass, className);
if (lpszIClassName) {
Print("= %s", lpszIClassName);
}
Print("\n");
lpszText = (UTCHAR*)NextWordBoundary(lpszText); // UINT align lpszText
// Our code in InternalCreateDialog does this.
// dit.dwExStyle |= WS_EX_NOPARENTNOTIFY;
//
/*
* Get pointer to additional data. lpszText can point to an encoded
* ordinal number for some controls (e.g. static icon control) so
* we check for that here.
*/
move(w, (PTR)lpszText);
if (w == 0xFFFF) {
swprintf(text, L"#%lx", w);
lpCreateParams = (LPWSTR)((PBYTE)lpszText + 4);
} else {
lpCreateParams = (LPWSTR)(PBYTE)WordSkipSz(lpszText, text, ARRAY_SIZE(text));
}
Print("\
text @ 0x%p \"%ls\"\n", lpszText, text);
Print("\
style %08lx %s%s", dit.style,
(opts & OFLAG(v)) ? GetCtrlStyle(iClass, dit.style) : "",
(opts & OFLAG(v)) ? "\n" : "");
Print("\
ExStyle %08lx %s\n", dit.dwExStyle, (opts & OFLAG(v)) ? GetFlags(GF_WSEX, dit.dwExStyle, NULL, FALSE) : "");
/*
* Point at next item template
*/
move(w, (PTR)lpCreateParams);
lpdit = (LPDLGITEMTEMPLATE)NextDWordBoundary(
(LPBYTE)(lpCreateParams + 1) + w);
Print("\n");
}
return TRUE;
#endif // _IA64_
}
#ifndef KERNEL
BOOL Idimedpi(DWORD opts, ULONG64 param1)
{
PTR pImeDpi; // IMEDPI
UNREFERENCED_PARAMETER(opts);
if (param1 == 0) {
pImeDpi = GetGlobalPointer("imm32!gpImeDpi");
}
else {
pImeDpi = FIXKP(param1);
}
while (pImeDpi) {
WCHAR wsz[80];
InitTypeRead(pImeDpi, imm32!IMEDPI);
Print("IMEDPI @ 0x%p hInst: 0x%p cLock: 0n%3d", pImeDpi, ReadField(hInst), (DWORD)ReadField(cLock));
CopyUnicodeString(pImeDpi, "imm32!IMEDPI", "wszUIClass", wsz, ARRAY_SIZE(wsz));
Print(" CodePage:%4d UI Class: \"%S\"\n", (DWORD)ReadField(dwCodePage), wsz);
if (opts & OFLAG(i)) {
DWORD dwOffset;
GetFieldOffset("imm32!IMEDPI", "ImeInfo", &dwOffset);
Print(" ImeInfo: @ 0x%p dwPrivateDataSize: %08x\n", dwOffset,
(DWORD)ReadField(ImeInfo.dwPrivateDataSize));
}
if (opts & OFLAG(v)) {
dso("imm32!IMEDPI", pImeDpi, 0);
}
Print("\n");
pImeDpi = ReadField(pNext);
}
return TRUE;
}
#endif // !KERNEL
/************************************************************************\
*
* Procedure: CopyUnicodeString
*
* 06/05/00 JStall Created (yeah, baby!)
*
\************************************************************************/
BOOL
CopyUnicodeString(
IN PTR pData,
IN char * pszStructName,
IN char * pszFieldName,
OUT WCHAR *pszDest,
IN ULONG cchMax)
{
ULONG Length;
PTR Buffer;
char szLengthName[256];
char szBufferName[256];
if (pData == 0) {
pszDest[0] = '\0';
return FALSE;
}
strcpy(szLengthName, pszFieldName);
strcat(szLengthName, ".Length");
strcpy(szBufferName, pszFieldName);
strcat(szBufferName, ".Buffer");
if (GetFieldValue(pData, pszStructName, szLengthName, Length) ||
GetFieldValue(pData, pszStructName, szBufferName, Buffer)) {
wcscpy(pszDest, L"<< Can't get name >>");
return FALSE;
}
if (Buffer == 0) {
wcscpy(pszDest, L"<null>");
} else {
ULONG cbText;
cbText = min(cchMax, Length + sizeof(WCHAR));
if (!(tryMoveBlock(pszDest, FIXKP(Buffer), cbText))) {
wcscpy(pszDest, L"<< Can't get value >>");
return FALSE;
}
}
return TRUE;
}
/************************************************************************\
*
* Procedure: Idhard
*
* 06/05/00 JStall Created (yeah, baby!)
*
\************************************************************************/
#ifdef KERNEL
BOOL Idhard(
VOID)
{
PTR phei, pheiNext, pthread;
WCHAR szText[256], szCaption[256];
int cErrors = 0;
DWORD dwClientId;
Print("Win32k hard error list:\n");
phei = GetGlobalPointer("winsrv!gphiList");
while (phei != 0) {
InitTypeRead(phei, winsrv!HARDERRORINFO);
pheiNext = ReadField(phiNext);
pthread = ReadField(pthread);
CopyUnicodeString(phei, "winsrv!HARDERRORINFO", "usCaption", szCaption, ARRAY_SIZE(szCaption));
CopyUnicodeString(phei, "winsrv!HARDERRORINFO", "usText", szText, ARRAY_SIZE(szText));
InitTypeRead(pthread, csrsrv!CSR_THREAD);
dwClientId = HandleToUlong((HANDLE) ReadField(ClientId.UniqueThread));
Print("0x%p: tid:0x%x '%S'- '%S'\n", phei, dwClientId, szCaption, szText);
phei = pheiNext;
cErrors++;
}
Print("%d queued errors\n", cErrors);
return TRUE;
}
typedef struct {
PTR thread;
ULONG64 time;
} KERNELTIME;
ULONG CpuHogCallback(
PFIELD_INFO NextProcess,
PVOID Context);
BOOL Ihogs(
DWORD dwOpts,
ULONG64 ul64Count)
{
KERNELTIME *pTimes;
TIME_FIELDS Times;
WCHAR appname[64];
PTR ProcessHead, NextProcess, Process;
THREAD_DUMP_CONTEXT TDC;
DWORD dwCount = (DWORD)ul64Count;
LARGE_INTEGER RunTime;
UNREFERENCED_PARAMETER(dwOpts);
// Default to dumping the top 10 threads
if (dwCount == 0) {
dwCount = 10;
}
pTimes = LocalAlloc(LPTR, dwCount * sizeof(KERNELTIME));
if (!pTimes) {
Print("Couldn't allocate memory for KERNELTIME buffer\n");
return TRUE;
}
ProcessHead = EvalExp("PsActiveProcessHead");
if (!ProcessHead) {
Print("Unable to get value of PsActiveProcessHead\n");
return FALSE;
}
if (GetFieldValue(ProcessHead, "nt!LIST_ENTRY", "Flink", NextProcess)) {
Print("Unable to get value of PsActiveProcessHead\n");
return FALSE;
}
if (NextProcess == 0) {
Print("PsActiveProcessHead->Flink is NULL!\n");
return FALSE;
}
TDC.opts = dwCount;
TDC.ThreadToDump = (ULONG_PTR)pTimes;
ListType("nt!EPROCESS", NextProcess, 1, "ActiveProcessLinks.Flink", &TDC, CpuHogCallback);
for (--dwCount; dwCount != -1; --dwCount) {
GetFieldValue(pTimes[dwCount].thread, "nt!ETHREAD", "ThreadsProcess", Process);
GetProcessName(Process, appname);
RunTime.QuadPart = pTimes[dwCount].time;
RtlTimeToElapsedTimeFields ( &RunTime, &Times);
Print("%d: thread %#p - %ws ==> %3ld:%02ld:%02ld.%04ld\n",TDC.opts - dwCount, pTimes[dwCount].thread, appname,
Times.Hour,
Times.Minute,
Times.Second,
Times.Milliseconds);
}
LocalFree(pTimes);
return TRUE;
}
VOID InsertTime(
KERNELTIME *pTimes,
DWORD cnt,
PTR thread,
ULONG64 time)
{
int i = cnt - 1;
for (; i >= 0; --i) {
if (time > pTimes[i].time) {
RtlMoveMemory(&pTimes[0], &pTimes[i], cnt);
pTimes[i].time = time;
pTimes[i].thread = thread;
break;
}
}
}
ULONG CpuHogCallback(
PFIELD_INFO NextProcess,
PVOID Context)
{
THREAD_DUMP_CONTEXT *pTDC = (THREAD_DUMP_CONTEXT *)Context;
KERNELTIME *pTimes = (KERNELTIME*)pTDC->ThreadToDump;
DWORD dwOffset;
ULONG64 thread, head, KernelTime;
TIME_FIELDS Times;
LARGE_INTEGER RunTime;
KDDEBUGGER_DATA64 KdDebuggerData;
static int counter = 0;
ULONG TimeIncrement = GetUlongFromAddress((GetDebuggerData(KDBG_TAG,
&KdDebuggerData, sizeof(KdDebuggerData)),
KdDebuggerData.KeTimeIncrement));
GetFieldOffset("nt!EPROCESS", "ThreadListHead", &dwOffset);
head = NextProcess->address + dwOffset;
ReadPointer(head, &thread);
GetFieldOffset("nt!ETHREAD", "ThreadListEntry", &dwOffset);
do {
ShowProgress();
thread -= dwOffset;
GetFieldValue(thread, "nt!ETHREAD", "Tcb.KernelTime", KernelTime);
RunTime.QuadPart = UInt32x32To64(KernelTime, TimeIncrement);
RtlTimeToElapsedTimeFields ( &RunTime, &Times);
InsertTime(pTimes, pTDC->opts, thread, RunTime.QuadPart);
// Get next thread in the list
ReadPointer(thread + dwOffset, &thread);
} SAFEWHILE (thread != head);
// Erase any symbol that might still be showing
Print("\r");
// Did we exit the loop because the user hit ^C?
if (thread != head) {
// Yes, so return TRUE to stop further callbacks
return TRUE;
}
return FALSE;
}
#endif // KERNEL
#ifdef KERNEL
/************************************************************************\
* Procedure: Idhid
*
* Dumps HID (Raw Input, aka Generic Input) information
*
* ??/??/2000 Hiroyama Created
\************************************************************************/
VOID DumpProcessHidRequest(
PTR pHidRequest)
{
_InitTypeRead(pHidRequest, SYM(tagPROCESS_HID_REQUEST));
Print(" (0x%x, 0x%x) @ 0x%p -> 0x%p pwnd: 0x%p sink: 0x%x\n",
(UINT)ReadField(usUsagePage), (UINT)ReadField(usUsage),
pHidRequest,
ReadField(pPORequest),
ReadField(spwndTarget),
(UINT)ReadField(fSinkable));
}
ULONG dhidCallback(
PTR ppi,
PVOID param)
{
DWORD opts = PtrToUlong(param);
PTR pHidTable;
ULONG64 maskRawInput;
static ULONG iSeq;
ShowProgress();
if (GetFieldValue(ppi, SYM(PROCESSINFO), "pHidTable", pHidTable)) {
Print("Cannot get pHidTable from ppi=%p\n", ppi);
return FALSE;
}
GetFieldValue(ppi, SYM(PROCESSINFO), "dwRawInputMask", maskRawInput);
if (pHidTable || maskRawInput) {
ULONG offset;
PTR pHidRequest;
PTR pStart;
Print(" \nHID for ppi: %p %s\n", ppi, ProcessName(ppi));
_InitTypeRead(pHidTable, SYM(tagPROCESS_HID_TABLE));
Print(" PROCESS_HID_TABLE @ 0x%p (sink: 0n%d)\n", pHidTable, (int)ReadField(nSinks));
Print(" Kbd: raw:0x%x sink:0x%x noleg:0x%x pwnd: 0x%p nohotkey:0x%x\n",
(DWORD)ReadField(fRawKeyboard), (DWORD)ReadField(fRawKeyboardSink), (DWORD)ReadField(fNoLegacyKeyboard),
ReadField(spwndTargetKbd),
(DWORD)ReadField(fNoHotKeys));
Print(" Mou: raw:%x sink:%x noleg:%x pwnd: %p capture:%x\n",
(DWORD)ReadField(fRawMouse), (DWORD)ReadField(fRawMouseSink), (DWORD)ReadField(fNoLegacyMouse),
ReadField(spwndTargetMouse), (DWORD)ReadField(fCaptureMouse));
if (opts & OFLAG(v)) {
dso(SYM(PROCESS_HID_TABLE), pHidTable, DBG_DUMP_RECUR_LEVEL(1));
}
GetFieldOffset(SYM(tagPROCESS_HID_TABLE), "InclusionList.Flink", &offset);
pStart = pHidTable + offset;
GetFieldValue(pHidTable, SYM(tagPROCESS_HID_TABLE), "InclusionList.Flink", pHidRequest);
if (pHidRequest == pStart) {
Print(" No Inclusion List\n");
} else {
Print(" Inclusion List:\n");
SAFEWHILE (pHidRequest && pHidRequest != pStart) {
DumpProcessHidRequest(pHidRequest);
/*
* N.b. DumpProcessHidRequest() sets the InitTypeRead
*/
pHidRequest = ReadField(link.Flink);
}
}
GetFieldOffset(SYM(tagPROCESS_HID_TABLE), "UsagePageList.Flink", &offset);
pStart = pHidTable + offset;
GetFieldValue(pHidTable, SYM(tagPROCESS_HID_TABLE), "UsagePageList.Flink", pHidRequest);
if (pHidRequest != pStart) {
Print(" UsagePageOnly List\n");
SAFEWHILE (pHidRequest && pHidRequest != pStart) {
DumpProcessHidRequest(pHidRequest);
pHidRequest = ReadField(link.Flink);
}
} else {
Print(" No UsagePageOnly List\n");
}
GetFieldOffset(SYM(tagPROCESS_HID_TABLE), "ExclusionList.Flink", &offset);
pStart = pHidTable + offset;
GetFieldValue(pHidTable, SYM(tagPROCESS_HID_TABLE), "ExclusionList.Flink", pHidRequest);
if (pHidRequest != pStart) {
Print(" Exclusion List\n");
SAFEWHILE (pHidRequest && pHidRequest != pStart) {
DumpProcessHidRequest(pHidRequest);
if (ReadField(spwndTarget) != 0) {
Print(" spwndTarget is not NULL!\n");
}
pHidRequest = ReadField(link.Flink);
}
} else {
Print(" No Exclusion List\n");
}
}
return FALSE;
}
BOOL Idhid(DWORD opts, ULONG64 param1)
{
try {
PTR pHidRequest;
PTR pStart;
pStart = GetGlobalMemberAddress(SYM(gHidRequestTable), SYM(tagHID_REQUEST_TABLE), "TLCInfoList.Flink");
pHidRequest = GetPointer(pStart);
if (pHidRequest == NULL_PTR) {
Print("pHidRequest is NULL ???\n");
return TRUE;
}
if (pHidRequest != pStart) {
Print("HID_TLC_INFO:\n");
}
SAFEWHILE (pHidRequest && pHidRequest != pStart) {
_InitTypeRead(pHidRequest, SYM(tagHID_TLC_INFO));
Print(" (0x%x, 0x%x) @ 0x%p\n",
(UINT)(USHORT)ReadField(usUsagePage), (UINT)(USHORT)ReadField(usUsage),
pHidRequest);
Print(" [cDevices:0x%x] [DirectReq:0x%x] [UsagePReq:0x%x] [ExclReq:0x%x] [ExclOrphaned:0x%x]\n",
(UINT)ReadField(cDevices),
(UINT)ReadField(cDirectRequest),
(UINT)ReadField(cUsagePageRequest),
(UINT)ReadField(cExcludeRequest),
(UINT)ReadField(cExcludeOrphaned));
pHidRequest = ReadField(link.Flink);
}
pStart = GetGlobalMemberAddress(SYM(gHidRequestTable), SYM(tagHID_REQUEST_TABLE), "UsagePageList.Flink");
pHidRequest = GetPointer(pStart);
if (pHidRequest != pStart) {
Print("HID_PAGEONLY_REQUEST:\n");
}
SAFEWHILE (pHidRequest && pHidRequest != pStart) {
_InitTypeRead(pHidRequest, SYM(tagHID_PAGEONLY_REQUEST));
Print(" (0x%x, 0) @ 0x%p cRefCount: 0x%x\n",
(UINT)(USHORT)ReadField(usUsagePage),
pHidRequest,
(UINT)ReadField(cRefCount));
pHidRequest = ReadField(link.Flink);
}
if (opts & OFLAG(p)) {
if (param1) {
dhidCallback(param1, ULongToPtr(opts));
} else {
ForEachPpi(dhidCallback, ULongToPtr(opts));
}
} else {
PTR gpqForeground = GetGlobalPointer(SYM(gpqForeground));
if (gpqForeground == NULL_PTR) {
Print("gpqForeground is NULL\n");
} else {
PTR ptiMouse = NULL_PTR;
PTR spwndMouse;
GetFieldValue(gpqForeground, SYM(tagQ), "spwndCapture", spwndMouse);
if (spwndMouse) {
GetFieldValue(spwndMouse, SYM(tagWND), "head.pti", ptiMouse);
} else {
GetFieldValue(gpqForeground, SYM(tagQ), "ptiMouse", ptiMouse);
}
if (ptiMouse == NULL_PTR) {
Print("ptiMouse is NULL.\n");
} else {
PTR ppi;
GetFieldValue(ptiMouse, SYM(tagTHREADINFO), "ppi", ppi);
Print("\nForeground ppi: %p\n", ppi);
dhidCallback(ppi, ULongToPtr(opts));
}
}
}
pStart = EvalExp(VAR(gHidCounters));
if (pStart) {
Print(" \nHID counter @ 0x%p\n", pStart);
dso(SYM(tagHID_COUNTERS), pStart, 0);
}
if (IsChk()) {
pStart = EvalExp(VAR(gHidAllocCounters));
if (pStart) {
Print(" \nDebug Allocate counter @ 0x%p\n", pStart);
dso(SYM(HidAllocateCounter), pStart, 0);
Print("gcAllocHidTotal: 0x%x\n", (UINT)GetGlobalPointer(VAR(gcAllocHidTotal)));
}
}
} except (CONTINUE) {
Print("AV!\n");
}
return TRUE;
}
#endif // KERNEL
BOOL Ipred(DWORD opts, ULONG64 param1)
{
UINT i = 0;
UNREFERENCED_PARAMETER(opts);
while (i < 64) {
Print("%cp%-2d ", param1 & (1 << i) ? '*' : ' ', i);
if (++i % 8 == 0) {
Print("\n");
}
}
return TRUE;
}
#ifdef KERNEL
#ifdef TRACK_PNP_NOTIFICATION
/************************************************************************\
* Procedure: Idhnr
*
* Dumps PnP notification record
*
* 09/19/2000 Hiroyama Created
*
\************************************************************************/
/*
* Do not call GetDeviceType twice within a sequence point!
* This function uses a static variable for the return value.
*/
const char* GetDeviceType(ULONG64 type)
{
static const char* devicetype[] = {
"mouse",
"keyboard",
"hid",
};
if (type >= ARRAY_SIZE(devicetype)) {
static char buf[32];
sprintf(buf, "<unknown type %x>", (DWORD)type);
return buf;
}
return devicetype[type];
}
BOOL Idhnr(DWORD opts, ULONG64 param1)
{
try {
PTR p, pStart;
PTR pTarget = 0;
PTR pTargetDeviceInfo = 0;
UCHAR szPathNameDevInfo[80] = "";
UINT iTarget = 0;
UINT iStartOffset = 0;
ULONG cbSize;
DWORD dwArraySize;
ULONG offsetPathName;
UINT iSeq, i;
GetFieldOffset(SYM(PNP_NOTIFICATION_RECORD), "szPathName", &offsetPathName);
if (offsetPathName == 0) {
Print("can't get offset to szPathName, make sure TRACK_PNP_NOTIFICATION is turned on.\n");
return TRUE;
}
if (opts & OFLAG(d)) {
if ((pTargetDeviceInfo = param1) == 0) {
return FALSE;
}
} else if (opts & OFLAG(p)) {
p = pTarget = param1;
if (pTarget) {
goto PrintHeader;
}
} else if (param1) {
iTarget = (UINT)param1;
opts |= OFLAG(v) | OFLAG(n);
}
if ((p = pStart = GetGlobalPointer(VAR(gpPnpNotificationRecord))) == 0) {
Print("can't get gPnpNotificationRecord\n");
return TRUE;
}
if ((cbSize = GetTypeSize(SYM(PNP_NOTIFICATION_RECORD))) == 0) {
Print("can't get sizeof(PNP_NOTIFICATION_RECORD)\n");
return TRUE;
}
moveExpValue(&dwArraySize, VAR(gdwPnpNotificationRecSize));
if (dwArraySize == 0) {
Print("can't get gdwPnpNotificationRecSize\n");
return TRUE;
}
/*
* Firstly, find out the lowest iSeq.
*/
iSeq = UINT_MAX;
for (i = 0; !IsCtrlCHit() && i < dwArraySize; ++i) {
UINT iSeqTmp;
_InitTypeRead(p, SYM(PNP_NOTIFICATION_RECORD));
iSeqTmp = (UINT)ReadField(iSeq);
ShowProgress();
if (iSeqTmp < iSeq && iSeqTmp != 0) {
iSeq = iSeqTmp;
iStartOffset = i;
}
/*
* For device name search, remember the path name
* that matches to pDeviceInfo.
*/
if (pTargetDeviceInfo && (opts & OFLAG(m)) &&
szPathNameDevInfo[0] == 0 && ReadField(pDeviceInfo) == pTargetDeviceInfo) {
move(szPathNameDevInfo, p + offsetPathName);
Print("\r\"%s\"\n", szPathNameDevInfo);
}
p = p + cbSize;
}
Print("\r");
/*
* Secondly, dump the records.
*/
PrintHeader:
Print(" seq %-*c%-20s %-*s %-*s code\n",
opts & OFLAG(p) ? PtrWidth() + 2 : 1, ' ',
"type", PtrWidth(), "pDevInfo", PtrWidth(), "thread");
if (pTarget) {
goto PrintOne;
}
for (i = 0; !IsCtrlCHit() && i < dwArraySize; ++i) {
UINT iOffset = (i + iStartOffset) % dwArraySize;
BOOLEAN fDump = FALSE;
p = pStart + cbSize * iOffset;
PrintOne:
_InitTypeRead(p, SYM(PNP_NOTIFICATION_RECORD));
iSeq = (UINT)ReadField(iSeq);
if (pTargetDeviceInfo) {
if (iSeq) {
if (ReadField(pDeviceInfo) == pTargetDeviceInfo) {
fDump = TRUE;
} else if ((opts & OFLAG(m)) && szPathNameDevInfo[0]) {
/*
* Try to dump the deviceinfo of the same device path.
*/
UCHAR szPathName[ARRAY_SIZE(szPathNameDevInfo)];
move(szPathName, p + offsetPathName);
if (strcmp(szPathName, szPathNameDevInfo) == 0) {
fDump = TRUE;
}
}
}
} else if (iTarget) {
if (iTarget == iSeq) {
/*
* Print just one by iSeq.
*/
fDump = TRUE;
}
} else if (pTarget) {
/*
* Print just one record by address.
*/
fDump = TRUE;
} else if (iSeq) {
/*
* Dump all valid records.
*/
fDump = TRUE;
}
if (fDump) {
UINT type = (UINT)ReadField(type);
PTR pDeviceInfo = ReadField(pDeviceInfo);
UCHAR szPathName[80];
ULONG64 NotificationCode = ReadField(NotificationCode);
PTR pThread = ReadField(pKThread);
static const char* symbols[] = {
"CLASSNOTIFY",
"CREATEDEVICEINFO",
"FREEDEVICEINFO",
"PROCESSDEVICECHANGES",
"REQUESTDEVICECHANGE",
"DEVICENOTIFY",
"FREE_DEFERRED",
"CLOSEDEVICE",
"DEVNOTIFY_UNLISTED",
"UNREGISTER_NOTIFY",
"UNREG_REMOTE_CANCEL",
};
const char* name;
if (type < ARRAY_SIZE(symbols)) {
name = symbols[type];
} else {
name = "<unknown>";
}
if (opts & OFLAG(p)) {
Print("[%04x] %p %x %-20s %08p %p ", iSeq, p, type, name, pDeviceInfo, pThread);
} else {
Print("[%04x] %x %-20s %08p %p ", iSeq, type, name, pDeviceInfo, pThread);
}
switch (type) {
case PNP_NTF_DEVICENOTIFY:
case PNP_NTF_REQUESTDEVICECHANGE:
case PNP_NTF_FREEDEVICEINFO:
case PNP_NTF_FREEDEVICEINFO_DEFERRED:
case PNP_NTF_CLOSEDEVICE:
case PNP_NTF_DEVICENOTIFY_UNLISTED:
case PNP_NTF_UNREGISTER_NOTIFICATION:
case PNP_NTF_UNREGISTER_REMOTE_CANCELLED:
Print("%s\n", GetFlags(GF_DIAF, (DWORD)NotificationCode, NULL, TRUE));
break;
case PNP_NTF_PROCESSDEVICECHANGES:
case PNP_NTF_CREATEDEVICEINFO:
case PNP_NTF_CLASSNOTIFY:
Print("(%s)\n", GetDeviceType(NotificationCode));
break;
default:
Print("%08p\n", NotificationCode);
break;
}
if (opts & OFLAG(n)) {
move(szPathName, p + offsetPathName);
Print(" \"%s\"\n", szPathName);
}
if (opts & OFLAG(v)) {
ULONG offset;
GetFieldOffset(SYM(PNP_NOTIFICATION_RECORD), "type", &offset);
dso(SYM(PNP_NOTIFICATION_TYPE), p + offset, 0);
GetFieldOffset(SYM(PNP_NOTIFICATION_RECORD), "trace", &offset);
PrintStackTrace(p + offset, LOCKRECORD_STACK);
}
/*
* If it is a one-shot dump, exit the loop here.
*/
if (iTarget || pTarget) {
break;
}
}
}
} except (CONTINUE) {
}
return TRUE;
}
#endif // TRACK_PNP_NOTIFICATION
#endif // KERNEL
BOOL Ichkfre(DWORD opts, ULONG64 param1)
{
UNREFERENCED_PARAMETER(param1);
if (opts & OFLAG(c)) {
gfChk = 1;
} else if (opts & OFLAG(f)) {
gfChk = 0;
} else if (opts & OFLAG(r)) {
gfChk = -1;
}
#ifdef KERNEL
Print("Win32k IsChk: %d\n", IsChk());
#else
Print("User32 IsChk: %d\n", IsChk());
#endif
return TRUE;
}
#ifdef KERNEL
/************************************************************************\
* Idghost
*
* Dump ghost thread associated information
*
* 12/05/2000 Created MSadek
\************************************************************************/
BOOL Idghost(
VOID)
{
PTR pGhost;
PTR pWnd;
PTR pWndGhost;
PTR pGhostThreadInfo;
PTR pEventScanGhosts;
PTR pCST;
LONG SignalGhost;
UINT i = 0;
UINT uID;
UINT uiThreadCount = 0;
// Dump ghost linked list data.
pGhost = GetGlobalPointer(SYM(gpghostFirst));
if (0 == pGhost) {
Print("Ghost global linked list is empty \n");
} else {
Print("Dumping ghost global linked list: \n");
do {
_InitTypeRead(pGhost, SYM(tagGHOST));
pWnd = ReadField(pwnd);
pWndGhost = ReadField(pwndGhost);
Print("Ghost entry #%i: \n\n", ++i);
Print("Ghosted window: %0lx\n", pWnd);
if (pWnd) {
Idw(0, pWnd);
}
Print("Ghost window: %0lx\n", pWndGhost);
if (pWndGhost) {
Idw(0, pWndGhost);
}
GetFieldValue(pGhost, SYM(tagGHOST), "pghostNext", pGhost);
} SAFEWHILE (pGhost);
}
// Dump ghost thread data.
pGhostThreadInfo = GetGlobalPointer(SYM(gptiGhost));
if (0 == pGhostThreadInfo) {
Print("No Ghost thread currently active\n");
} else {
Print("GhostThreadInfo 0x%p\n\n", pGhostThreadInfo);
Idti(0, pGhostThreadInfo);
}
// Dump the number of pending thread creation requests in CSR.
pCST = EvalExp(SYM(gCSTParam));
i = 0;
SAFEWHILE (i < CST_MAX_THREADS) {
uID = (UINT)GetArrayElement(pCST, SYM(CST_THREADS), "uID", i, "UINT");
if (CST_GHOST == uID) {
uiThreadCount++;
}
i++;
}
Print("Number of ghost threads waiting to be created in CSRSS is %i\n", uiThreadCount);
uiThreadCount = 0;
i = 0;
// Dump the number of pending thread creation requests in the shell process.
pCST = EvalExp(SYM(gCSTRemoteParam));
i = 0;
SAFEWHILE (i < CST_MAX_THREADS) {
uID = (UINT)GetArrayElement(pCST, SYM(CST_THREADS), "uID", i, "UINT");
if (CST_GHOST == uID) {
uiThreadCount++;
}
i++;
}
Print("Number of ghost threads waiting to be created in the shell process is %i\n", uiThreadCount);
// Dump the number of pending ghost windows created and freed since dirver last loaded.
Print("Number of ghost windows created and freed since driver last loaded is %i\n", GetGlobalPointer(SYM(guGhostUnlinked)));
// Dump signal state for gpEventScanGhosts
pEventScanGhosts = GetGlobalPointer(SYM(gpEventScanGhosts));
if (0 != pEventScanGhosts) {
Print("Scan Ghost event is 0x%p\n", pEventScanGhosts);
GetFieldValue(pEventScanGhosts, "nt!DISPATCHER_HEADER", "SignalState", SignalGhost);
if (SignalGhost) {
Print("Scan ghost event is signaled\n");
} else {
Print("Scan ghost event isn't signaled\n");
}
}
return TRUE;
}
/************************************************************************\
* dce
*
* Dump information about the DCE cache.
*
* 6/15/2001 Created JStall
\************************************************************************/
BOOL Idce(
DWORD opts,
ULONG64 param1)
{
try {
PTR gpDispInfo, pdceStart, pdceCur;
gpDispInfo = GetGlobalPointer(VAR(gpDispInfo));
if (gpDispInfo == 0) {
Print("ERROR: Unable to retreive win32!gpDispInfo\n");
} else {
_InitTypeRead(gpDispInfo, SYM(DISPLAYINFO));
pdceStart = ReadField(pdceFirst);
if (pdceStart == 0) {
Print("ERROR: Unable to retreive gpDispInfo->pdceFirst\n");
} else {
PTR pData;
DWORD dwData, cTotal, cFound;
BOOL fDisplay, fVerbose;
cTotal = cFound = 0;
fVerbose = opts & OFLAG(v);
pdceCur = pdceStart;
while (pdceCur != 0) {
fDisplay = FALSE;
_InitTypeRead(pdceCur, SYM(DCE));
if (param1 != 0) {
if (opts & OFLAG(c)) {
//
// pwndClip
//
pData = ReadField(pwndClip);
fDisplay = pData == param1;
} else if (opts & OFLAG(f)) {
//
// DCX flag filter
//
dwData = (DWORD) ReadField(DCX_flags);
fDisplay = (dwData & ((DWORD) param1)) != 0;
} else if (opts & OFLAG(h)) {
//
// HDC
//
pData = ReadField(hdc);
fDisplay = pData == param1;
} else if (opts & OFLAG(o)) {
//
// pwndOrg
//
pData = ReadField(pwndOrg);
fDisplay = pData == param1;
} else if (opts & OFLAG(r)) {
//
// hrgnClip
//
pData = ReadField(hrgnClip);
fDisplay = pData == param1;
} else if (opts & OFLAG(t)) {
//
// pti (THREADINFO)
//
pData = ReadField(ptiOwner);
fDisplay = pData == param1;
}
} else {
//
// No filter, so display information
//
fDisplay = TRUE;
}
if (fDisplay) {
if (fVerbose) {
PTR hdc, pwndOrg, pwndClip, hrgnClip, ptiOwner;
DWORD nFlags;
LPCSTR pszFlags;
char szOrg[256];
char szClip[256];
WCHAR szRawApp[80];
PWCHAR pszApp;
hdc = ReadField(hdc);
pwndOrg = ReadField(pwndOrg);
pwndClip = ReadField(pwndClip);
hrgnClip = ReadField(hrgnClip);
nFlags = (DWORD) ReadField(DCX_flags);
pszFlags = GetFlags(GF_DCXFLAGS, nFlags, NULL, TRUE);
ptiOwner = ReadField(ptiOwner);
szRawApp[0] = L'\0';
pszApp = szRawApp;
if (ptiOwner != 0) {
_InitTypeRead(ptiOwner, SYM(THREADINFO));
GetAppName(ReadField(pEThread), ptiOwner, szRawApp, sizeof(szRawApp));
pszApp = wcsrchr(szRawApp, L'\\');
if (pszApp == NULL_PTR) {
pszApp = szRawApp;
} else {
pszApp++;
}
}
DebugGetWindowTextA(pwndOrg, szOrg, ARRAY_SIZE(szOrg));
DebugGetWindowTextA(pwndClip, szClip, ARRAY_SIZE(szClip));
Print(
"DCE: 0x%p\n"
" HDC: 0x%p\n"
" pwndOrg: 0x%p \"%s\"\n"
" pwndClip: 0x%p \"%s\"\n"
" hrgnClip: 0x%p\n"
" ptiOwner: 0x%p \"%ws\"\n"
" nFlags: 0x%x\n"
" %s\n\n",
pdceCur,
hdc,
pwndOrg, szOrg,
pwndClip, szClip,
hrgnClip,
ptiOwner, pszApp,
nFlags,
pszFlags);
} else {
PTR hdc, pwndOrg;
char szOrg[256];
hdc = ReadField(hdc);
pwndOrg = ReadField(pwndOrg);
DebugGetWindowTextA(pwndOrg, szOrg, ARRAY_SIZE(szOrg));
Print("DCE: 0x%p HDC: 0x%p pwndOrg: 0x%p \"%s\"\n",
pdceCur, hdc, pwndOrg, szOrg);
}
cFound++;
}
// Get the next DCE
_InitTypeRead(pdceCur, SYM(DCE));
pdceCur = ReadField(pdceNext);
cTotal++;
}
Print(" Total 0x%x (%d) of 0x%x (%d) DCE's\n\n", cFound, cFound, cTotal, cTotal);
}
}
} except (CONTINUE) {
}
return TRUE;
}
#endif // KERNEL
#ifndef KERNEL
/************************************************************************\
* msft
*
* Dump Microsoft's current stock price.
*
* 12/13/2000 Created JasonSch
\************************************************************************/
BOOL Imsft(
VOID)
{
BOOL bResult;
DWORD dwBytesRead;
SYSTEMTIME systime;
CHAR buffer[256], *p;
HINTERNET hUrlHandle;
HINTERNET hInternet;
GetLocalTime(&systime);
if (systime.wMonth == 4 && systime.wDay == 1) {
static int n = 0;
if (n++ < 4) {
/*
* Let's pretend to be happy!
*/
Print("MSFT: 120.5625,+80.1875,\"04/01/%d\",\"%d:%02d%s\"\n",
systime.wYear, systime.wHour % 12, systime.wMinute, systime.wHour >= 12 ? "PM" : "AM");
return TRUE;
}
}
hInternet = InternetOpenW(L"Jo Mama!",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
if (hInternet == NULL) {
return FALSE;
}
hUrlHandle = InternetOpenUrlW(hInternet,
L"http://quote.yahoo.com/download/quotes.csv?symbols=msft&format=sl1c1d1t1&ext=.txt",
NULL,
0,
INTERNET_FLAG_RAW_DATA,
0);
if (!hUrlHandle) {
return FALSE;
}
bResult = InternetReadFile(hUrlHandle,
buffer,
sizeof(buffer),
&dwBytesRead);
if (!bResult) {
InternetCloseHandle(hInternet);
return FALSE;
}
InternetCloseHandle(hUrlHandle);
InternetCloseHandle(hInternet);
/*
* Buffer will now have a string that looks like:
* "MSFT",58.375,+0.3125,"12/12/2000","4:01PM"
*/
/*
* NULL-terminate buffer (remove \r\n, while we're at it).
*/
buffer[dwBytesRead - 2] = 0;
p = &buffer[7]; // Skip '"MSFT",' part.
Print("MSFT: %s\n", p);
return TRUE;
}
#endif // !KERNEL
/************************************************************************\
* Idaccel
*
* Dumps accelerator tables.
*
* 04/02/2001 Created JasonSch
\************************************************************************/
BOOL Idaccel(
DWORD dwFlags,
PTR pAccelTable)
{
ULONG dwOffset, dwSize;
PTR phe;
UINT i, cnt;
UNREFERENCED_PARAMETER(dwFlags);
/*
* pAccelTable could actually be a handle.
*/
if (HtoHE(pAccelTable, &phe)) {
GetFieldValue(phe, SYM(HANDLEENTRY), "phead", pAccelTable);
}
if (pAccelTable == 0) {
return FALSE;
}
if (_InitTypeRead(pAccelTable, SYM(ACCELTABLE))) {
Print("Couldn't read ACCELTABLE at %p\n", (ULONG_PTR)pAccelTable);
return FALSE;
}
cnt = (UINT)ReadField(cAccel);
GetFieldOffset(SYM(ACCELTABLE), "accel", &dwOffset);
dwSize = GetTypeSize(SYM(ACCEL));
pAccelTable += dwOffset;
for (i = 0; i < cnt; ++i) {
BYTE bVirt;
BOOL bPrintPlus = FALSE;
_InitTypeRead(pAccelTable, SYM(ACCEL));
bVirt = (BYTE)ReadField(fVirt);
Print("Flags: ");
if (bVirt & FVIRTKEY) {
Print("FVIRTKEY");
bPrintPlus = TRUE;
}
if (bVirt & FNOINVERT) {
if (bPrintPlus) {
Print(" + ");
}
Print("FNOINVERT");
}
if (bVirt & FLASTKEY) {
if (bPrintPlus) {
Print(" + ");
}
Print("FLASTKEY");
}
Print("\nKey: ");
if (bVirt & FALT) {
Print("ALT + ");
}
if (bVirt & FCONTROL) {
Print("CONTROL + ");
}
if (bVirt & FSHIFT) {
Print("SHIFT + ");
}
if (isprint((int)ReadField(key))) {
Print("'%c'\n", (char)ReadField(key));
} else {
Print("<unprintable> (0x%x)\n", (UINT)(WORD)ReadField(key));
}
Print("Cmd: 0x%x\n", (UINT)(WORD)ReadField(cmd));
pAccelTable += dwSize;
}
return TRUE;
}
#ifdef KERNEL
/************************************************************************\
* Idhproc
*
* Dumps a proc with this type of kernel handle.
* Similar to !handle 0 7 <eprocess> <type>
*
* 05/14 Created HiroYama
\************************************************************************/
#if 0
ULONG dhprocCallback(
PFIELD_INFO NextProcess,
PVOID Context)
{
static int progress;
ShowProgress();
return FALSE;
}
BOOL Idhproc(
DWORD dwFlags,
PTR ul)
{
PTR ProcessHead = EvalExp("PsActiveProcessHead");
PTR NextProcess;
THREAD_DUMP_CONTEXT tdc;
if (ProcessHead == NULL_PTR) {
Print("Unable to get value of PsActiveProcessHead\n");
return FALSE;
}
if (GetFieldValue(ProcessHead, "nt!LIST_ENTRY", "Flink", NextProcess)) {
Print("Unable to get value of PsActiveProcessHead\n");
return FALSE;
}
if (NextProcess == 0) {
Print("PsActiveProcessHead->Flink is NULL!\n");
return FALSE;
}
tdc.opts = dwFlags;
tdc.ThreadToDump = ul;
ListType("nt!EPROCESS", NextProcess, 1, "ActiveProcessLinks.Flink", &TDC, dhprocCallback);
return TRUE;
}
#endif
#endif // KERNEL
#ifdef LATER
#ifdef KERNEL
/************************************************************************\
* Procedure: Idwsl
*
* Dumps WinSta locking log
*
* 09/19/2000 Hiroyama Created
*
\************************************************************************/
BOOL Idwsl(
DWORD opts,
ULONG64 param1)
{
try {
PTR p, pStart;
PTR pTarget = 0;
PTR pTargetWinSta = NULL_PTR;
UCHAR szWinStaName[80] = "";
UINT iTarget = 0;
UINT iStartOffset = 0;
ULONG cbSize;
DWORD dwArraySize;
ULONG offsetWinStaName;
ULONG offsetImageFileName;
UINT iSeq, i;
if (opts & OFLAG(d)) {
if ((pTargetWinSta = param1) == NULL_PTR) {
return FALSE;
}
}
else if (opts & OFLAG(p)) {
p = pTarget = param1;
if (pTarget) {
goto PrintHeader;
}
}
else if (param1) {
iTarget = (UINT)param1;
opts |= OFLAG(v) | OFLAG(n);
}
offsetWinStaName = (ULONG)-1;
GetFieldOffset(SYM(WINSTA_RUNDOWN_RECORD), "szWinStaName", &offsetWinStaName);
if (offsetWinStaName == (ULONG)-1) {
Print("can't get offset to szWinStaName\n");
return TRUE;
}
GetFieldOffset(SYM(WINSTA_RUNDOWN_RECORD), "szImageFileName", &offsetImageFileName);
if (offsetImageFileName == 0) {
Print("can't get offset to szImageFileName\n");
return TRUE;
}
if ((p = pStart = EvalExp(SYM(gaWinStaRundownLog))) == NULL_PTR) {
Print("can't get gaWinStaRundownLog\n");
return TRUE;
}
if ((cbSize = GetTypeSize(SYM(WINSTA_RUNDOWN_RECORD))) == 0) {
Print("can't get sizeof(WINSTA_RUNDOWN_RECORD)\n");
return TRUE;
}
moveExpValue(&dwArraySize, VAR(gdwWinStaRecSize));
if (dwArraySize == 0) {
Print("can't get gdwWinStaRecSize\n");
return TRUE;
}
/*
* Firstly, find out the lowest iSeq.
*/
iSeq = UINT_MAX;
for (i = 0; !IsCtrlCHit() && i < dwArraySize; ++i) {
UINT iSeqTmp;
_InitTypeRead(p, SYM(WINSTA_RUNDOWN_RECORD));
iSeqTmp = (UINT)ReadField(iSeq);
ShowProgress();
if (iSeqTmp < iSeq && iSeqTmp != 0) {
iSeq = iSeqTmp;
iStartOffset = i;
}
/*
* For device name search, remember the path name
* that matches to pDeviceInfo.
*/
if (pTargetWinSta && (opts & OFLAG(m)) &&
szWinStaName[0] == 0 && ReadField(pwinsta) == pTargetWinSta) {
move(szWinStaName, p + offsetWinStaName);
Print("\r\"%s\"\n", szWinStaName);
}
p = p + cbSize;
}
Print("\r");
/*
* Secondly, dump the records.
*/
PrintHeader:
#if 0
Print(" seq %-*c%-20s %-*s %-*s code\n",
opts & OFLAG(p) ? PtrWidth() + 2 : 1, ' ',
"type", PtrWidth(), "pDevInfo", PtrWidth(), "thread");
#endif
if (pTarget) {
goto PrintOne;
}
for (i = 0; !IsCtrlCHit() && i < dwArraySize; ++i) {
UINT iOffset = (i + iStartOffset) % dwArraySize;
BOOLEAN fDump = FALSE;
p = pStart + cbSize * iOffset;
PrintOne:
_InitTypeRead(p, SYM(WINSTA_RUNDOWN_RECORD));
iSeq = (UINT)ReadField(iSeq);
if (pTargetWinSta) {
if (iSeq) {
if (ReadField(pwinsta) == pTargetWinSta) {
fDump = TRUE;
}
else if ((opts & OFLAG(m)) && szWinStaName[0]) {
/*
* Try to dump the winsta of the same device path.
*/
UCHAR szPathNameTmp[ARRAY_SIZE(szWinStaName)];
move(szPathNameTmp, p + offsetWinStaName);
if (strcmp(szWinStaName, szPathNameTmp) == 0) {
fDump = TRUE;
}
}
}
}
else if (iTarget) {
if (iTarget == iSeq) {
/*
* Print just one by iSeq.
*/
fDump = TRUE;
}
}
else if (pTarget) {
/*
* Print just one record by address.
*/
fDump = TRUE;
}
else if (opts & OFLAG(z)) {
/*
* Print only if the session id don't match.
*/
if ((DWORD)ReadField(dwSessionIdWinSta) != (DWORD)ReadField(dwCurrentSessionId)) {
fDump = TRUE;
}
}
else if (iSeq) {
/*
* Dump all valid records.
*/
fDump = TRUE;
}
if (fDump) {
UINT fReference = (UINT)ReadField(fReference);
PTR pwinsta = ReadField(pwinsta);
UCHAR szName[33];
//PTR NotificationCode = ReadField(NotificationCode);
PTR pThread = ReadField(pKThread);
if (opts & OFLAG(p)) {
Print("[0x%04x] @ 0x%p 0x%x ws 0x%08p t 0x%p ", iSeq, p, fReference, pwinsta, pThread);
} else {
Print("[0x%04x] 0x%x ws 0x%08p t 0x%p ", iSeq, fReference, pwinsta, pThread);
}
/*
* Print the windowstation name.
*/
move(szName, p + offsetWinStaName);
Print(" %02x %-20s", (DWORD)ReadField(dwSessionIdWinSta), szName);
/*
* Print the process name.
*/
move(szName, p + offsetImageFileName);
Print(" %02x %x.%x \"%s\"\n", (DWORD)ReadField(dwCurrentSessionId), (DWORD)ReadField(pid), (DWORD)ReadField(tid), szName);
/*
* If it is a one-shot dump, exit the loop here.
*/
if (iTarget || pTarget) {
break;
}
}
}
} except (CONTINUE) {
}
return TRUE;
}
#endif // KERNEL
#endif // LATER
#ifdef KERNEL
/************************************************************************\
* Iheapff
*
* Looks for a particular address in our global list of freed heap.
*
* 07/02/2001 Created JasonSch
\************************************************************************/
BOOL Iheapff(
DWORD dwFlags,
PTR pHeapBlock)
{
DWORD dwHeapRecordMax, i, dwSize, dwOffset;
PTR pHeapRecords;
UNREFERENCED_PARAMETER(pHeapBlock);
UNREFERENCED_PARAMETER(dwFlags);
moveExpValue(&dwHeapRecordMax, SYM(gdwFreeHeapRecordCrtIndex));
dwSize = GetTypeSize(SYM(HEAPRECORD));
GetFieldOffset(SYM(HEAPRECORD), "trace", &dwOffset);
pHeapRecords = EvalExp(SYM(garrFreeHeapRecord));
for (i = 0; i < dwHeapRecordMax; ++i, pHeapRecords += dwSize) {
_InitTypeRead(pHeapRecords, SYM(HEAPRECORD));
if (ReadField(p) == pHeapBlock) {
Print("Found heap block 0x%p (Heap: 0x%p, Size: 0x%p)\n",
pHeapBlock,
ReadField(pheap),
ReadField(size));
PrintStackTrace(pHeapRecords + dwOffset, 6);
}
}
Print("==========================================================\n");
moveExpValue(&dwHeapRecordMax, SYM(gdwFreeHeapRecordTotalFrees));
Print("Total heap allocations freed thus far: 0x%x\n", dwHeapRecordMax);
return TRUE;
}
#endif
ULONG SortBy;
#define SORT_SIZE 1
#define SORT_PID 2
#define SORT_TAG 3
int __cdecl
HeapInfoSort(const void *e1,const void *e2)
{
LONG64 diff;
WORD tag1, tag2;
WORD subtag1, subtag2;
ULONG64 size1, size2;
ULONG64 pid1, pid2;
_InitTypeRead(*((PULONG64) e1), SYM(DbgHeapHead));
tag1 = LOWORD(ReadField(tag));
subtag1 = HIWORD(ReadField(tag));
size1 = ReadField(size);
pid1 = ReadField(pid);
_InitTypeRead(*((PULONG64) e2), SYM(DbgHeapHead));
tag2 = LOWORD(ReadField(tag));
subtag2 = HIWORD(ReadField(tag));
size2 = ReadField(size);
pid2 = ReadField(pid);
switch (SortBy) {
case SORT_SIZE:
diff = size1 - size2;
break;
case SORT_PID:
diff = pid1 - pid2;
break;
case SORT_TAG:
diff = tag1 - tag2;
if (diff == 0) {
diff = subtag1 - subtag2;
}
break;
}
return (int) diff;
}
/************************************************************************\
* Idheap
*
* Dumps a win32Heap
*
* 08/15/2001 Created MSadek
\************************************************************************/
BOOL Idheap(
DWORD opts,
ULONG64 param1,
ULONG64 param2)
{
if (((opts & OFLAG(o)) && param2 == 0 ) || param1 == 0) {
Print("Wrong usage0: dheap takes a pointer as a parameter\n");
return FALSE;
}
try {
PTR pheap;
PTR pFirstAlloc;
ULONG64 cAllocations = 0;
ULONG64 cActualAllocations = 0;
ULONG64 cTotalHeap = 0, cTotalHeapRead = 0;
ULONG64 cClass = 0;
ULONG64 pid;
ULONG64 i = 0;
ULONG64 *pHeapDebugInfo = NULL;
BOOL bWarning = FALSE;
DWORD dwDbgInfoSize = GetTypeSize(SYM(DbgHeapHead));
WORD tag;
if (opts & OFLAG(o)) {
pheap = param2;
} else {
pheap = param1;
}
Print("\n***IMPORTANT***: If you are not dumping a desktop heap, the tag and subtag information is wrong.\n\n");
if (!opts || ((opts & (OFLAG(o))) && !(opts & (OFLAG(p) | OFLAG(t) | OFLAG(s))))) {
Print("\t%-10s%-10s%-18s%-18s%-10s%-10s\n","Heap Block", "Size","Tag","Subtag","Process","StackTrace");
Print("\t============================================================================\n");
}
_InitTypeRead(pheap, SYM(tagWIN32HEAP));
pFirstAlloc = ReadField(pFirstAlloc);
cActualAllocations = ReadField(crtAllocations);
cTotalHeap = ReadField(crtMemory);
do {
_InitTypeRead(pFirstAlloc, SYM(DbgHeapHead));
if (ReadField(pNext)) {
cAllocations++;
cTotalHeapRead += ReadField(size);
if (!opts || ((opts & (OFLAG(o))) && !(opts & (OFLAG(p) | OFLAG(t) | OFLAG(s))) && param1 == ReadField(pid))) {
Print("\t%-10x", pFirstAlloc + dwDbgInfoSize);
Print("%-10x", ReadField(size));
Print("%-18s", aszHeapTags[LOWORD(ReadField(tag))]);
Print("%-18s", aszHeapSubtags[HIWORD(ReadField(tag))]);
Print("%-10x", ReadField(pid));
Print("%-10x\n", ReadField(trace));
} else {
ShowProgress();
}
}
} while (pFirstAlloc = ReadField(pNext));
if (cActualAllocations > cAllocations) {
bWarning = TRUE;
}
if (!(opts & (OFLAG(p) | OFLAG(t) | OFLAG(s)))) {
goto PrintFooter;
} else if(opts & OFLAG(p)) {
SortBy= SORT_PID;
} else if(opts & OFLAG(t)) {
SortBy= SORT_TAG;
} else if(opts & OFLAG(s)) {
SortBy= SORT_SIZE;
}
pHeapDebugInfo = malloc((SIZE_T)(cAllocations * sizeof(ULONG64)));
if (!pHeapDebugInfo) {
Print("Couldn't allocate memory for heap info buffer\n");
return FALSE;
}
_InitTypeRead(pheap, SYM(tagWIN32HEAP));
pFirstAlloc = ReadField(pFirstAlloc);
for (i = 0; i < cAllocations; i++) {
ShowProgress();
pHeapDebugInfo[i] = pFirstAlloc;
_InitTypeRead(pFirstAlloc, SYM(DbgHeapHead));
pFirstAlloc = ReadField(pNext);
}
qsort((void *) pHeapDebugInfo, (size_t)cAllocations, (size_t)sizeof(ULONG64), HeapInfoSort);
for (i = 0; i < cAllocations; i++) {
_InitTypeRead(pHeapDebugInfo[i], SYM(DbgHeapHead));
if (((opts & OFLAG(s) && !(opts & OFLAG(o))) || ((opts & OFLAG(o)) && param1 == ReadField(pid)))) {
if (i == 0) {
Print("\t%-10s%-10s%-18s%-18s%-10s%-10s\n","Heap Block", "Size","Tag","Subtag","Process","StackTrace");
Print("\t============================================================================\n");
}
Print("\t%-10x", pHeapDebugInfo[i] + dwDbgInfoSize);
Print("%-10x", ReadField(size));
Print("%-18s", aszHeapTags[LOWORD(ReadField(tag))]);
Print("%-18s", aszHeapSubtags[HIWORD(ReadField(tag))]);
Print("%-10x", ReadField(pid));
Print("%-10x\n", ReadField(trace));
} else if (!(opts & OFLAG(o))){
if (i == 0) {
if (SortBy== SORT_PID) {
Print("\t%-10s%-15s%\n","Process", "Total Heap Size");
Print("\t=========================\n");
pid = ReadField(pid);
} else {
Print("\t%-18s%-15s%\n","Tag", "Total Heap Size");
Print("\t=================================\n");
tag = LOWORD(ReadField(tag));
}
}
if (SortBy== SORT_PID) {
if (pid == ReadField(pid)) {
cClass += (ULONG64)ReadField(size);
}
if (pid != ReadField(pid) || i == cAllocations - 1) {
Print("\t%-10x", pid);
Print("%-15x\n", cClass);
cClass = (ULONG64)ReadField(size);
if (pid != ReadField(pid) && i == cAllocations - 1) {
Print("\t%-10x", ReadField(pid));
Print("%-15x\n", cClass);
}
pid = ReadField(pid);
}
} else {
if (tag == LOWORD(ReadField(tag))) {
cClass += (ULONG64)ReadField(size);
}
if (tag != LOWORD(ReadField(tag)) || i == cAllocations - 1) {
Print("\t%-18s", aszHeapTags[tag]);
Print("%-15x\n", cClass);
cClass = (ULONG64)ReadField(size);
if (tag != LOWORD(ReadField(tag)) && i == cAllocations - 1) {
Print("\t%-18s", aszHeapTags[LOWORD(ReadField(tag))]);
Print("%-15x\n", cClass);
}
tag = LOWORD(ReadField(tag));
}
}
}
}
PrintFooter:
Print("\nTotal heap allocated (excluding headers): %dKb", cTotalHeap/1024, cTotalHeap);
Print(" in %d allocations.\n", cActualAllocations);
if(bWarning) {
Print("\n**WARNING**:Some of the heap memory is paged out.\n");
}
if (pHeapDebugInfo) {
free(pHeapDebugInfo);
}
} except(CONTINUE) {
}
return TRUE;
}
/************************************************************************\
* Ifcsrp
*
* Finds the CSR_PROCESS for the given PID.
*
* 09/13/2001 Created JasonSch
\************************************************************************/
BOOL Ifcsrp(
DWORD dwFlags,
ULONG64 pid)
{
PTR pProcess;
ULONG dwOffset;
GetFieldOffset("csrsrv!_CSR_PROCESS", "ListLink", &dwOffset);
UNREFERENCED_PARAMETER(dwFlags);
pProcess = GetGlobalPointer("csrsrv!CsrRootProcess");
SAFEWHILE (pProcess) {
_InitTypeRead(pProcess, "csrsrv!_CSR_PROCESS");
if (ReadField(ClientId.UniqueProcess) == pid) {
Print("Found specified CSR_PROCESS at 0x%p\n", pProcess);
break;
}
pProcess = (PTR)((PBYTE)ReadField(ListLink) - dwOffset);
}
return TRUE;
}
#ifdef KERNEL
typedef struct {
PTR ppi;
PTR pDesktop;
} PPI_DESKTOP, *PPPI_DESKTOP;
ULONG Findd_PtiCallback(
PTR pti,
PVOID pData)
{
PTR pDesktop;
PPPI_DESKTOP p = (PPPI_DESKTOP)pData;
ShowProgress();
GetFieldValue(pti, SYM(THREADINFO), "rpDesk", pDesktop);
if (p->pDesktop == pDesktop) {
Print("Pti 0x%p [ppi = 0x%p] using desktop 0x%p", pti, p->ppi, p->pDesktop);
}
return TRUE;
}
ULONG Findd_PpiCallback(
PTR ppi,
PVOID ppDesktop)
{
PPI_DESKTOP p = {ppi, *((PTR*)ppDesktop)};
ShowProgress();
ForEachPti(Findd_PtiCallback, &p);
return TRUE;
}
BOOL Ifindd(
DWORD dwOpts,
PTR pDesktop)
{
UNREFERENCED_PARAMETER(dwOpts);
ForEachPpi(Findd_PpiCallback, (PVOID)&pDesktop);
return TRUE;
}
#endif
/************************************************************************\
* Idcmu
*
* Dumps a rough estimate of the total amount of memory used by console
* screen buffers. Note that this currently just looks at the current
* screen buffer for each console. It should be augmented to look at all
* of them.
*
* 04/29/2002 Created JasonSch
\************************************************************************/
BOOL Idcmu(
DWORD opts)
{
ULONG64 pConsole, pConsoles, pScreenBuffer;
ULONG cConsoleHandles, cActualConsoleCount, i, PtrSize, CoordOffset;
ULONG dwTotalSize = 0, x, y;
PtrSize = GetTypeSize("PVOID");
pConsoles = GetGlobalPointer("winsrv!ConsoleHandles");
moveExpValue(&cConsoleHandles, "winsrv!NumberOfConsoleHandles");
for (i = 0, cActualConsoleCount = 0; i < cConsoleHandles; ++i) {
pConsole = GetPointer(pConsoles);
if (pConsole == 0) {
pConsoles += PtrSize;
continue;
}
++cActualConsoleCount;
GetFieldValue(pConsole,
"winsrv!_CONSOLE_INFORMATION",
"CurrentScreenBuffer",
pScreenBuffer);
GetFieldOffset("winsrv!_SCREEN_INFORMATION", "ScreenBufferSize", &CoordOffset);
_InitTypeRead(pScreenBuffer + CoordOffset, "COORD");
x = (ULONG)(WORD)ReadField(X);
y = (ULONG)(WORD)ReadField(Y);
dwTotalSize += x * y * 2;
if (opts & OFLAG(v)) {
Print("Console @ 0x%p has buffer size (0x%x, 0x%x)\n", pConsole, x, y);
}
pConsoles += PtrSize;
}
Print("There are 0x%x consoles using roughly %d bytes\n",
cActualConsoleCount,
dwTotalSize);
return TRUE;
}
LPWSTR _ReadCountedWideString(
ULONG64 pAddress,
ULONG cbSize)
{
LPWSTR pwstr;
pwstr = LocalAlloc(LPTR, (cbSize + 1) * sizeof(WCHAR));
if (pwstr) {
ULONG result;
ReadMemory(pAddress,
pwstr,
cbSize * sizeof(WCHAR),
&result);
pwstr[cbSize] = 0;
}
return pwstr;
}
ULONG _DumpConsoleAliasCallback(
PFIELD_INFO pFieldInfo,
PVOID Context)
{
LPWSTR lpwszAliasSource, lpwszAliasTarget;
UNREFERENCED_PARAMETER(Context);
_InitTypeRead(pFieldInfo->address, "winsrv!_ALIAS");
lpwszAliasSource = _ReadCountedWideString(ReadField(Source),
(ULONG)ReadField(SourceLength));
lpwszAliasTarget = _ReadCountedWideString(ReadField(Target),
(ULONG)ReadField(TargetLength));
Print("\t%ws ==> %ws (@ 0x%p)\n",
lpwszAliasSource,
lpwszAliasTarget,
pFieldInfo->address);
LocalFree(lpwszAliasSource);
LocalFree(lpwszAliasTarget);
return FALSE;
}
ULONG _DumpConsoleAliasListCallback(
PFIELD_INFO pFieldInfo,
PVOID Context)
{
LPWSTR lpwszExeName;
UNREFERENCED_PARAMETER(Context);
_InitTypeRead(pFieldInfo->address, "winsrv!_EXE_ALIAS_LIST");
//
// TODO: Print doesn't support %.*XXX.
//
// Print("Alias .exe ==> %.*ws", (ULONG)ReadField(ExeLength), ReadField(ExeName));
lpwszExeName = _ReadCountedWideString(ReadField(ExeName),
(ULONG)ReadField(ExeLength));
Print("Alias list @ 0x%p for %ws\n", pFieldInfo->address, lpwszExeName);
LocalFree(lpwszExeName);
ListType("winsrv!_ALIAS",
ReadField(AliasList),
1,
"ListLink.Flink",
NULL,
_DumpConsoleAliasCallback);
Print("\n");
return FALSE;
}
BOOL Idcalias(
DWORD dwOpts,
ULONG64 pConsole)
{
UNREFERENCED_PARAMETER(dwOpts);
//
// NULL pConsole means dump aliases for all consoles.
//
if (pConsole == 0) {
ULONG64 pConsoles;
ULONG cConsoleHandles, cActualConsoleCount, i, PtrSize;
PtrSize = GetTypeSize("PVOID");
pConsoles = GetGlobalPointer("winsrv!ConsoleHandles");
moveExpValue(&cConsoleHandles, "winsrv!NumberOfConsoleHandles");
for (i = 0, cActualConsoleCount = 0;
i < cConsoleHandles;
pConsoles += PtrSize,
++i) {
pConsole = GetPointer(pConsoles);
if (pConsole == 0) {
continue;
}
++cActualConsoleCount;
Idcalias(dwOpts, pConsole);
}
} else {
ULONG64 pExeAliasList;
GetFieldValue(pConsole,
"winsrv!_CONSOLE_INFORMATION",
"ExeAliasList",
pExeAliasList);
Print("Aliases for Console 0x%p\n", pConsole);
ListType("winsrv!_EXE_ALIAS_LIST",
pExeAliasList,
1,
"ListLink.Flink",
NULL,
_DumpConsoleAliasListCallback);
}
return TRUE;
}