/****************************** 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 #include /***************************************************************************\ * 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"", 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, ""); } 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, ""); } else { if (!tryMove(ach, FIXKP(lpszClassName))) { strcpy(achDest, ""); } 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] = { "", "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 %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(" 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(" 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 - dumps EVENTHOOK at address. * dwe -n - dumps all NOTIFYs. * dwe -n - 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, ¶m1); 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 \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 \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 Dumps all THREAD locks for object at * !dtl -t Dumps all THREAD locks made by thread * !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, ¶m1); 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""); } 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, "", (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 = ""; } 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(" (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 * * 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; }