2025-04-27 07:49:33 -04:00

1265 lines
45 KiB
C

/***************************** Module Header ******************************\
* Module Name: conexts.c
*
* Copyright (c) 1985 - 2001, Microsoft Corporation
*
* This module contains console-related debugging functions.
*
* History:
* ????
* 30-Jan-2001 JasonSch Moved to ntcon\exts and made to fix the STDEXTS model.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
CONST PSTR pszExtName = "CONEXTS";
#include <stdext64.h>
#include <stdext64.c>
#define SYM(s) "winsrv!" #s
#define NO_FLAG IntToPtr(0xFFFFFFFF) // use this for non-meaningful entries.
VOID
DbgGetConsoleTitle(
IN ULONG64 pConsole,
OUT PWCHAR buffer,
IN UINT cbSize);
BOOL
CopyUnicodeString(
IN ULONG64 pData,
IN char * pszStructName,
IN char * pszFieldName,
OUT WCHAR *pszDest,
IN ULONG cchMax);
WINDBG_EXTENSION_APIS ExtensionApis;
USHORT SavedMajorVersion;
USHORT SavedMinorVersion;
BOOL bDebuggingChecked;
EXT_API_VERSION ApiVersion = { VER_PRODUCTVERSION_W >> 8,
VER_PRODUCTVERSION_W & 0xff,
EXT_API_VERSION_NUMBER64, 0 };
#define GF_CONSOLE 1
LPSTR apszConsoleFlags[] = {
"CONSOLE_IS_ICONIC" , // 0x000001
"CONSOLE_OUTPUT_SUSPENDED" , // 0x000002
"CONSOLE_HAS_FOCUS" , // 0x000004
"CONSOLE_IGNORE_NEXT_MOUSE_INPUT", // 0x000008
"CONSOLE_SELECTING" , // 0x000010
"CONSOLE_SCROLLING" , // 0x000020
"CONSOLE_DISABLE_CLOSE" , // 0x000040
"CONSOLE_NOTIFY_LAST_CLOSE" , // 0x000080
"CONSOLE_NO_WINDOW" , // 0x000100
"CONSOLE_VDM_REGISTERED" , // 0x000200
"CONSOLE_UPDATING_SCROLL_BARS" , // 0x000400
"CONSOLE_QUICK_EDIT_MODE" , // 0x000800
"CONSOLE_TERMINATING" , // 0x001000
"CONSOLE_CONNECTED_TO_EMULATOR" , // 0x002000
"CONSOLE_FULLSCREEN_NOPAINT" , // 0x004000
"CONSOLE_SHUTTING_DOWN" , // 0x008000
"CONSOLE_AUTO_POSITION" , // 0x010000
"CONSOLE_IGNORE_NEXT_KEYUP" , // 0x020000
"CONSOLE_WOW_REGISTERED" , // 0x040000
"CONSOLE_USE_PRIVATE_FLAGS" , // 0x080000
"CONSOLE_HISTORY_NODUP" , // 0x100000
"CONSOLE_SCROLLBAR_TRACKING" , // 0x200000
"CONSOLE_IN_DESTRUCTION" , // 0x400000
"CONSOLE_SETTING_WINDOW_SIZE" , // 0x800000
"CONSOLE_DEFAULT_BUFFER_SIZE" , // 0x0100000
NULL // no more
};
#define GF_CONSOLESEL 2
LPSTR apszConsoleSelectionFlags[] = {
"CONSOLE_SELECTION_NOT_EMPTY" , // 1
"CONSOLE_MOUSE_SELECTION" , // 2
"CONSOLE_MOUSE_DOWN" , // 4
"CONSOLE_SELECTION_INVERTED" , // 8
NULL // no more
};
#define GF_FULLSCREEN 3
LPSTR apszFullScreenFlags[] = {
"CONSOLE_FULLSCREEN", // 0
"CONSOLE_FULLSCREEN_HARDWARE", // 1
NULL
};
#define GF_CMDHIST 4
LPSTR apszCommandHistoryFlags[] = {
"CLE_ALLOCATED", // 0x01
"CLE_RESET", // 0x02
NULL
};
/*
* 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 ..."
*/
LPSTR GetFlags(
WORD wType,
DWORD dwFlags,
LPSTR pszBuf)
{
static char szT[400];
DWORD i;
BOOL fFirst = TRUE;
BOOL fNoMoreNames = FALSE;
LPSTR *apszFlags;
if (pszBuf == NULL) {
pszBuf = szT;
}
*pszBuf = '\0';
switch (wType) {
case GF_CONSOLE:
apszFlags = apszConsoleFlags;
break;
case GF_CONSOLESEL:
apszFlags = apszConsoleSelectionFlags;
break;
case GF_FULLSCREEN:
apszFlags = apszFullScreenFlags;
break;
case GF_CMDHIST:
apszFlags = apszCommandHistoryFlags;
break;
default:
strcpy(pszBuf, " = Invalid flag type.");
return(pszBuf);
}
for (i = 0; dwFlags; dwFlags >>= 1, i++) {
if (!fNoMoreNames && (apszFlags[i] == NULL)) {
fNoMoreNames = TRUE;
}
if (dwFlags & 1) {
if (!fFirst) {
strcat(pszBuf, " | ");
} else {
strcat(pszBuf, " = ");
fFirst = FALSE;
}
if (fNoMoreNames || (apszFlags[i] == NO_FLAG)) {
char ach[16];
sprintf(ach, "0x%lx", 1 << i);
strcat(pszBuf, ach);
} else {
strcat(pszBuf, apszFlags[i]);
}
}
}
return pszBuf;
}
/***************************************************************************\
* dc - Dump Console - dump CONSOLE_INFORMATION struct
*
* dc address - dumps simple info for console at address
* (takes handle too)
\***************************************************************************/
BOOL Idc(
DWORD opts,
ULONG64 pConsole)
{
BOOL fPrintLine;
ULONG i, NumberOfConsoleHandles;
DWORD dwOffset, dwOffset2;
WCHAR buffer[256];
if (!pConsole) {
/*
* If no console is specified, loop through all of them
*/
moveExpValue(&NumberOfConsoleHandles,
SYM(NumberOfConsoleHandles));
moveExpValuePtr(&pConsole,
SYM(ConsoleHandles));
fPrintLine = FALSE;
for (i = 0; i < NumberOfConsoleHandles; i++) {
ULONG64 pc;
ReadPtr(pConsole, &pc);
if (pc && InitTypeRead(pc, SYM(CONSOLE_INFORMATION))) {
if (fPrintLine) {
Print("==========================================\n");
}
Idc(opts, pc);
fPrintLine = TRUE;
}
(ULONG_PTR)pConsole += GetTypeSize(SYM(PCONSOLE_INFORMATION));
}
return TRUE;
}
if (!InitTypeRead(pConsole, SYM(CONSOLE_INFORMATION))) {
Print("Couldn't read console at 0x%p\n", pConsole);
return FALSE;
}
DbgGetConsoleTitle(pConsole, buffer, ARRAY_SIZE(buffer));
Print("PCONSOLE @ %#p \"%ws\"\n", pConsole, buffer);
if (opts & OFLAG(h)) {
ULONG64 ListHead, ListNext, pHistory;
GetFieldOffset(SYM(CONSOLE_INFORMATION), "CommandHistoryList", &dwOffset);
ListHead = pConsole + dwOffset;
ListNext = ReadField(CommandHistoryList.Flink);
while (ListNext != ListHead) {
pHistory = (ULONG64)CONTAINING_RECORD(ListNext, COMMAND_HISTORY, ListLink);
Idch(0, pHistory);
GetFieldValue(ListNext, SYM(LIST_ENTRY), "Flink", ListNext);
Print("----\n");
}
return TRUE;
}
GetFieldOffset(SYM(CONSOLE_INFORMATION), "ConsoleLock", &dwOffset);
GetFieldOffset(SYM(CONSOLE_INFORMATION), "InputBuffer", &dwOffset2);
Print("\t pConsoleLock %#p\n"
"\t RefCount 0x%04lX\n"
"\t WaitCount 0x%04lX\n"
"\t pInputBuffer %#p\n"
"\t pCurrentScreenBuffer %#p\n"
"\t pScreenBuffers %#p\n"
"\t hWnd 0x%08lX\n"
"\t hDC 0x%08lX\n"
"\t LastAttributes 0x%04lX\n",
pConsole + dwOffset,
ReadField(RefCount),
ReadField(WaitCount),
pConsole + dwOffset2,
ReadField(CurrentScreenBuffer),
ReadField(ScreenBuffers),
ReadField(hWnd),
ReadField(hDC),
ReadField(LastAttributes));
Print("\t Flags 0x%08lX%s\n",
ReadField(Flags), GetFlags(GF_CONSOLE, (DWORD)ReadField(Flags), NULL));
Print("\t FullScreenFlags 0x%04lX%s\n",
ReadField(FullScreenFlags),
GetFlags(GF_FULLSCREEN, (DWORD)ReadField(FullScreenFlags), NULL));
Print("\t ConsoleHandle 0x%08lX\n"
"\t CtrlFlags 0x%08lX\n",
ReadField(ConsoleHandle),
ReadField(CtrlFlags)
);
if (opts & OFLAG(v)) {
Print("\t hMenu 0x%08lX\n"
"\t hHeirMenu 0x%08lX\n"
"\t hSysPalette 0x%08lX\n"
"\t WindowRect.L T R B 0x%08lX 0x%08lX 0x%08lX 0x%08lX\n"
"\t ResizeFlags 0x%08lX\n"
"\t OutputQueue.F B 0x%08lX 0x%08lX\n"
"\t InitEvents[] 0x%08lX 0x%08lX\n"
"\t ClientThreadHandle 0x%08lX\n"
"\t ProcessHandleList.F B %#p %#p\n"
"\t CommandHistoryList.F B %#p %#p\n"
"\t ExeAliasList.F B %#p %#p\n",
ReadField(hMenu),
ReadField(hHeirMenu),
ReadField(hSysPalette),
ReadField(WindowRect.left),
ReadField(WindowRect.top),
ReadField(WindowRect.right),
ReadField(WindowRect.bottom),
ReadField(ResizeFlags),
ReadField(OutputQueue.Flink),
ReadField(OutputQueue.Blink),
ReadField(InitEvents[0]),
ReadField(InitEvents[1]),
ReadField(ClientThreadHandle),
ReadField(ProcessHandleList.Flink),
ReadField(ProcessHandleList.Blink),
ReadField(CommandHistoryList.Flink),
ReadField(CommandHistoryList.Blink),
ReadField(ExeAliasList.Flink),
ReadField(ExeAliasList.Blink)
);
Print("\t NumCommandHistories 0x%04lX\n"
"\t MaxCommandHistories 0x%04lX\n"
"\t CommandHistorySize 0x%04lX\n"
"\t OriginalTitleLength 0x%04lX\n"
"\t TitleLength 0x%04lX\n"
"\t OriginalTitle %ws\n"
"\t dwHotKey 0x%08lX\n"
"\t hIcon 0x%08lX\n"
"\t iIcondId 0x%08lX\n"
"\t ReserveKeys 0x%02lX\n"
"\t WaitQueue 0x%08lX\n",
ReadField(NumCommandHistories),
ReadField(MaxCommandHistories),
ReadField(CommandHistorySize),
ReadField(OriginalTitleLength),
ReadField(TitleLength),
ReadField(dwHotKey),
ReadField(hIcon),
ReadField(iIconId),
ReadField(ReserveKeys),
ReadField(WaitQueue)
);
Print("\t SelectionFlags 0x%08lX%s\n"
"\t SelectionRect.L T R B 0x%04lX 0x%04lX 0x%04lX 0x%04lX\n"
"\t SelectionAnchor.X Y 0x%04lX 0x%04lX\n"
"\t TextCursorPosition.X Y 0x%04lX 0x%04lX\n"
"\t TextCursorSize 0x%08lX\n"
"\t TextCursorVisible 0x%02lX\n"
"\t InsertMode 0x%02lX\n"
"\t wShowWindow 0x%04lX\n"
"\t dwWindowOriginX 0x%08lX\n"
"\t dwWindowOriginY 0x%08lX\n"
"\t PopupCount 0x%04lX\n",
ReadField(SelectionFlags),
GetFlags(GF_CONSOLESEL, (DWORD)ReadField(SelectionFlags), NULL),
ReadField(SelectionRect.Left),
ReadField(SelectionRect.Top),
ReadField(SelectionRect.Right),
ReadField(SelectionRect.Bottom),
ReadField(SelectionAnchor.X),
ReadField(SelectionAnchor.Y),
ReadField(TextCursorPosition.X),
ReadField(TextCursorPosition.Y),
ReadField(TextCursorSize),
ReadField(TextCursorVisible),
ReadField(InsertMode),
ReadField(wShowWindow),
ReadField(dwWindowOriginX),
ReadField(dwWindowOriginY),
ReadField(PopupCount)
);
Print("\t VDMStartHardwareEvent 0x%08lX\n"
"\t VDMEndHardwareEvent 0x%08lX\n"
"\t VDMProcessHandle 0x%08lX\n"
"\t VDMProcessId 0x%08lX\n"
"\t VDMBufferSectionHandle 0x%08lX\n"
"\t VDMBuffer 0x%08lX\n"
"\t VDMBufferClient 0x%08lX\n"
"\t VDMBufferSize.X Y 0x%04lX 0x%04lX\n"
"\t StateSectionHandle 0x%08lX\n"
"\t StateBuffer 0x%08lX\n"
"\t StateBufferClient 0x%08lX\n"
"\t StateLength 0x%08lX\n",
ReadField(VDMStartHardwareEvent),
ReadField(VDMEndHardwareEvent),
ReadField(VDMProcessHandle),
ReadField(VDMProcessId),
ReadField(VDMBufferSectionHandle),
ReadField(VDMBuffer),
ReadField(VDMBufferClient),
ReadField(VDMBufferSize.X),
ReadField(VDMBufferSize.Y),
ReadField(StateSectionHandle),
ReadField(StateBuffer),
ReadField(StateBufferClient),
ReadField(StateLength)
);
Print("\t CP 0x%08lX\n"
"\t OutputCP 0x%08lX\n"
"\t hWndProgMan 0x%08lX\n"
"\t bIconInit 0x%08lX\n"
"\t LimitingProcessId 0x%08lX\n"
"\t TerminationEvent 0x%08lX\n"
"\t VerticalClientToWin 0x%04lX\n"
"\t HorizontalClientToWin 0x%04lX\n",
ReadField(CP),
ReadField(OutputCP),
ReadField(hWndProgMan),
ReadField(bIconInit),
ReadField(LimitingProcessId),
ReadField(TerminationEvent),
ReadField(VerticalClientToWindow),
ReadField(HorizontalClientToWindow)
);
#ifdef FE_SB
Print("\t EudcInformation 0x%08lX\n"
"\t FontCacheInformation 0x%08lX\n",
ReadField(EudcInformation),
ReadField(FontCacheInformation)
);
#ifdef FE_IME
Print("\tConsoleIme:\n"
"\t ScrollFlag 0x%08lX\n"
"\t ScrollWaitTimeout 0x%08lX\n"
"\t ScrollWaitCountDown 0x%08lX\n"
"\t CompStrData 0x%08lX\n"
"\t ConvAreaMode 0x%08lX\n"
"\t ConvAreaSystem 0x%08lX\n"
"\t NumberOfConvAreaCompStr 0x%08lX\n"
"\t ConvAreaCompStr 0x%08lX\n"
"\t ConvAreaRoot 0x%08lX\n",
ReadField(ConsoleIme.ScrollFlag),
ReadField(ConsoleIme.ScrollWaitTimeout),
ReadField(ConsoleIme.ScrollWaitCountDown),
ReadField(ConsoleIme.CompStrData),
ReadField(ConsoleIme.ConvAreaMode),
ReadField(ConsoleIme.ConvAreaSystem),
ReadField(ConsoleIme.NumberOfConvAreaCompStr),
ReadField(ConsoleIme.ConvAreaCompStr),
ReadField(ConsoleIme.ConvAreaRoot)
);
#endif // FE_IME
#endif // FE_SB
}
return TRUE;
}
/***************************************************************************\
* dt - Dump Text - dump text buffer information
*
* dt address - dumps text buffer information for console at address
*
\***************************************************************************/
BOOL Idt(
DWORD opts,
ULONG64 pConsole)
{
BOOL fPrintLine;
ULONG i, NumberOfConsoleHandles;
SHORT sh;
DWORD FrameBufPtr;
ULONG64 pRow;
if (!pConsole) {
/*
* If no console is specified, dt all of them
*/
moveExpValue(&NumberOfConsoleHandles,
SYM(NumberOfConsoleHandles));
Print("got %d handles", NumberOfConsoleHandles); // TODO
moveExpValuePtr(&pConsole,
SYM(ConsoleHandles));
Print("got ConsoleHandles ptr at %#p", pConsole); // TODO
fPrintLine = FALSE;
for (i = 0; i < NumberOfConsoleHandles; i++) {
if (pConsole) {
InitTypeRead(pConsole, SYM(CONSOLE_INFORMATION));
if (fPrintLine) {
Print("==========================================\n");
}
if (!Idt(opts, pConsole)) {
return FALSE;
}
fPrintLine = TRUE;
}
(ULONG_PTR)pConsole += GetTypeSize(SYM(PCONSOLE_INFORMATION));
}
return TRUE;
}
InitTypeRead(pConsole, SYM(CONSOLE_INFORMATION));
Print("PCONSOLE @ %#p\n", pConsole);
Print("\t Title %ws\n"
"\t pCurrentScreenBuffer 0x%08lX\n"
"\t pScreenBuffers 0x%08lX\n"
"\t VDMBuffer 0x%08lx\n"
"\t CP %d, OutputCP %d\n",
ReadField(Title),
ReadField(CurrentScreenBuffer),
ReadField(ScreenBuffers),
ReadField(VDMBuffer),
ReadField(Console.CP),
ReadField(OutputCP)
);
moveExpValue(&FrameBufPtr, SYM(FrameBufPtr));
InitTypeRead(ReadField(CurrentScreenBuffer), SYM(SCREEN_INFORMATION));
if (ReadField(Flags) & CONSOLE_TEXTMODE_BUFFER) {
Print("\t TextInfo.Rows 0x%08X\n"
"\t TextInfo.TextRows 0x%08X\n"
"\t TextInfo.FirstRow 0x%08X\n"
"\t FrameBufPtr 0x%08X\n",
ReadField(BufferInfo.TextInfo.Rows),
ReadField(BufferInfo.TextInfo.TextRows),
ReadField(BufferInfo.TextInfo.FirstRow),
FrameBufPtr);
}
pRow = ReadField(BufferInfo.TextInfo.Rows);
if (opts & OFLAG(c)) {
SHORT Y = (SHORT)ReadField(ScreenBufferSize.Y);
Print("Checking BufferInfo...\n");
for (sh = 0; sh < Y; sh++) {
InitTypeRead(pRow, SYM(ROW));
/*
* Check that Attrs points to the in-place AttrPair if there
* if only one AttrPair for this Row.
*/
if (ReadField(AttrRow.Length) == 1) {
DWORD dwOffset;
GetFieldOffset(SYM(ATTR_ROW), "AttrPair", &dwOffset);
if (ReadField(AttrRow.Attrs) != ReadField(AttrRow) + dwOffset) {
Print("Bad Row[%lx]: Attrs %#p should be %lx\n",
sh, ReadField(AttrRow.Attrs), ReadField(AttrRow) + dwOffset);
}
}
/*
* Some other checks?
*/
(ULONG_PTR)pRow += GetTypeSize(SYM(PROW));
}
Print("...check completed\n");
}
#if 0
//
// BUGBUG
// This routine had some screwy logic where -v was followed by an integer
// (nLines). I'm ignoring that for now.
//
if (!(opts & OFLAG(v))) {
return TRUE;
}
GetFieldValue(pScreen, SYM(SCREEN_INFORMATION), "BufferInfo.TextInfo.Rows", pRow);
for (i = 0; i < nLines; i++) {
InitTypeRead(pRow, SYM(ROW));
Print("Row %2d: %4x %4x, %4x %4x, %lx:\"%ws\"\n",
i,
(USHORT)ReadField(CharRow.Right),
(USHORT)ReadField(CharRow.OldRight),
(USHORT)ReadField(CharRow.Left),
(USHORT)ReadField(CharRow.OldLeft),
ReadField(CharRow.Chars), ReadField(CharRow.Chars));
Print(" %4x %4x,%04x or %lx\n",
(USHORT)ReadField(AttrRow.Length),
(USHORT)ReadField(AttrRow.AttrPair.Length),
(WORD)ReadField(Row.AttrRow.AttrPair.Attr),
ReadField(AttrRow.Attrs));
(ULONG_PTR)pRow += GetTypeSize(SYM(PROW));
}
#endif
return TRUE;
}
/***************************************************************************\
* df - Dump Font - dump Font information
*
* df address - dumps simple info for console at address
* (takes handle too)
\***************************************************************************/
BOOL Idf(
VOID)
{
ULONG64 pFN, pFontInfo;
DWORD NumberOfFonts, FontInfoLength, dw;
Print("Faces:\n");
moveExpValuePtr(&pFN, SYM(gpFaceNames));
while (pFN != 0) {
InitTypeRead(pFN, SYM(FACENODE));
Print(" \"%ls\"\t%s %s %s %s %s %s\n",
ReadField(awch[0]),
ReadField(dwFlag) & EF_NEW ? "NEW" : " ",
ReadField(dwFlag) & EF_OLD ? "OLD" : " ",
ReadField(dwFlag) & EF_ENUMERATED ? "ENUMERATED" : " ",
ReadField(dwFlag) & EF_OEMFONT ? "OEMFONT" : " ",
ReadField(dwFlag) & EF_TTFONT ? "TTFONT" : " ",
ReadField(dwFlag) & EF_DEFFACE ? "DEFFACE" : " ");
pFN = ReadField(pNext);
}
moveExpValue(&FontInfoLength, SYM(FontInfoLength));
moveExpValue(&NumberOfFonts, SYM(NumberOfFonts));
moveExpValuePtr(&pFontInfo, SYM(FontInfo));
Print("0x%lx fonts cached, 0x%lx allocated:\n", NumberOfFonts, FontInfoLength);
for (dw = 0; dw < NumberOfFonts; dw++, pFontInfo++) {
InitTypeRead(pFontInfo, SYM(FONTINFO));
Print("%04x hFont 0x%08lX \"%ls\"\n"
" SizeWant (%d;%d)\n"
" Size (%d;%d)\n"
" Family %02X\n"
" Weight 0x%08lX\n",
dw,
ReadField(hFont),
ReadField(FaceName),
ReadField(SizeWant.X), ReadField(FontInfo.SizeWant.Y),
ReadField(Size.X), ReadField(Size.Y),
ReadField(Family),
ReadField(Weight));
#ifdef FE_SB
Print(" CharSet 0x%02X\n",
ReadField(tmCharSet));
#endif // FE_SB
}
return TRUE;
}
/***************************************************************************\
* di - Dump Input - dump input buffer
*
* di address - dumps simple info for input at address
*
\***************************************************************************/
BOOL Idi(
DWORD opts,
ULONG64 pInput)
{
/*
* If no INPUT_INFORMATION is specified, dt all of them
*/
if (!pInput) {
BOOL fPrintLine;
ULONG64 pConsole;
ULONG NumberOfConsoleHandles, i;
moveExpValue(&NumberOfConsoleHandles, SYM(NumberOfConsoleHandles));
moveExpValuePtr(&pConsole, SYM(ConsoleHandles));
fPrintLine = FALSE;
for (i = 0; i < NumberOfConsoleHandles; i++) {
if (pConsole) {
DWORD dwOffset;
if (fPrintLine) {
Print("---\n");
}
GetFieldOffset(SYM(CONSOLE_INFORMATION), "InputBuffer", &dwOffset);
pInput = pConsole + dwOffset;
if (!Idi(opts, pInput)) {
return FALSE;
}
fPrintLine = TRUE;
}
(ULONG_PTR)pConsole += GetTypeSize(SYM(PCONSOLE_INFORMATION));
}
return TRUE;
}
InitTypeRead(pInput, SYM(INPUT_INFORMATION));
Print("PINPUT @ 0x%lX\n", pInput);
Print("\t pInputBuffer %#p\n"
"\t InputBufferSize 0x%08lX\n"
"\t AllocatedBufferSize 0x%08lX\n"
"\t InputMode 0x%08lX\n"
"\t RefCount 0x%08lX\n"
"\t First %#p\n"
"\t In %#p\n"
"\t Out %#p\n"
"\t Last %#p\n"
"\t ReadWaitQueue.Flink %#p\n"
"\t ReadWaitQueue.Blink %#p\n"
"\t InputWaitEvent %#p\n",
ReadField(InputBuffer),
ReadField(InputBufferSize),
ReadField(AllocatedBufferSize),
ReadField(InputMode),
ReadField(RefCount),
ReadField(First),
ReadField(In),
ReadField(Out),
ReadField(Last),
ReadField(ReadWaitQueue.Flink),
ReadField(ReadWaitQueue.Blink),
ReadField(InputWaitEvent)
);
return TRUE;
}
/***************************************************************************\
* dir - Dump Input Record - dump input buffer
*
* dir address number - dumps simple info for input at address
*
\***************************************************************************/
BOOL Idir(
DWORD opts,
ULONG64 pInputRecord,
ULONG64 NumRecords)
{
DWORD i;
UNREFERENCED_PARAMETER(opts);
if (NumRecords == 0) {
NumRecords = 25;
}
Print("%x PINPUTRECORDs @ %#p\n", NumRecords, pInputRecord);
for (i = 0; i < NumRecords; ++i) {
InitTypeRead(pInputRecord, SYM(INPUT_RECORD));
switch (ReadField(EventType)) {
case KEY_EVENT:
Print("\t KEY_EVENT\n");
if (ReadField(Event.KeyEvent.bKeyDown)) {
Print("\t KeyDown\n");
} else {
Print("\t KeyUp\n");
}
Print("\t wRepeatCount %d\n",
ReadField(Event.KeyEvent.wRepeatCount));
Print("\t wVirtualKeyCode %x\n",
ReadField(Event.KeyEvent.wVirtualKeyCode));
Print("\t wVirtualScanCode %x\n",
ReadField(Event.KeyEvent.wVirtualScanCode));
Print("\t aChar is %c",
ReadField(Event.KeyEvent.uChar.AsciiChar));
Print("\n");
Print("\t uChar is %x\n",
ReadField(Event.KeyEvent.uChar.UnicodeChar));
Print("\t dwControlKeyState %x\n",
ReadField(Event.KeyEvent.dwControlKeyState));
break;
case MOUSE_EVENT:
Print("\t MOUSE_EVENT\n"
"\t dwMousePosition %x %x\n"
"\t dwButtonState %x\n"
"\t dwControlKeyState %x\n"
"\t dwEventFlags %x\n",
ReadField(Event.MouseEvent.dwMousePosition.X),
ReadField(Event.MouseEvent.dwMousePosition.Y),
ReadField(Event.MouseEvent.dwButtonState),
ReadField(Event.MouseEvent.dwControlKeyState),
ReadField(Event.MouseEvent.dwEventFlags)
);
break;
case WINDOW_BUFFER_SIZE_EVENT:
Print("\t WINDOW_BUFFER_SIZE_EVENT\n"
"\t dwSize %x %x\n",
ReadField(Event.WindowBufferSizeEvent.dwSize.X),
ReadField(Event.WindowBufferSizeEvent.dwSize.Y)
);
break;
case MENU_EVENT:
Print("\t MENU_EVENT\n"
"\t dwCommandId %x\n",
ReadField(Event.MenuEvent.dwCommandId)
);
break;
case FOCUS_EVENT:
Print("\t FOCUS_EVENT\n");
if (ReadField(Event.FocusEvent.bSetFocus)) {
Print("\t bSetFocus is TRUE\n");
} else {
Print("\t bSetFocus is FALSE\n");
}
break;
default:
Print("\t Unknown event type 0x%x\n", ReadField(EventType));
break;
}
(ULONG_PTR)pInputRecord += GetTypeSize(SYM(INPUT_RECORD));
}
return TRUE;
}
/***************************************************************************\
* ds - Dump Screen - dump SCREEN_INFORMATION struct
*
* ds address - dumps simple info for input at address
\***************************************************************************/
BOOL Ids(
DWORD opts,
ULONG64 pScreen)
{
UNREFERENCED_PARAMETER(opts);
InitTypeRead(pScreen, SYM(SCREEN_INFORMATION));
Print("PSCREEN @ %#p\n", pScreen);
Print("\t pConsole %#p\n"
"\t Flags 0x%08lX %s | %s\n"
"\t OutputMode 0x%08lX\n"
"\t RefCount 0x%08lX\n"
"\t ScreenBufferSize.X Y 0x%08X 0x%08X\n"
"\t Window.L T R B 0x%08X 0x%08X 0x%08X 0x%08X\n"
"\t ResizingWindow 0x%08X\n",
ReadField(Console),
ReadField(Flags),
ReadField(Flags) & CONSOLE_TEXTMODE_BUFFER ? "TEXTMODE" : "GRAPHICS",
ReadField(Flags) & CONSOLE_OEMFONT_DISPLAY ? "OEMFONT" : "TT FONT",
ReadField(OutputMode),
ReadField(RefCount),
(DWORD)ReadField(ScreenBufferSize.X),
(DWORD)ReadField(ScreenBufferSize.Y),
(DWORD)ReadField(Window.Left),
(DWORD)ReadField(Window.Top),
(DWORD)ReadField(Window.Right),
(DWORD)ReadField(Window.Bottom),
ReadField(ResizingWindow)
);
Print("\t Attributes 0x%08X\n"
"\t PopupAttributes 0x%08X\n"
"\t WindowMaximizedX 0x%08X\n"
"\t WindowMaximizedY 0x%08X\n"
"\t WindowMaximized 0x%08X\n"
"\t CommandIdLow High 0x%08X 0x%08X\n"
"\t CursorHandle 0x%08X\n"
"\t hPalette 0x%08X\n"
"\t dwUsage 0x%08X\n"
"\t CursorDisplayCount 0x%08X\n"
"\t WheelDelta 0x%08X\n",
ReadField(Attributes),
ReadField(PopupAttributes),
ReadField(WindowMaximizedX),
ReadField(WindowMaximizedY),
ReadField(WindowMaximized),
ReadField(CommandIdLow),
ReadField(CommandIdHigh),
ReadField(CursorHandle),
ReadField(hPalette),
ReadField(dwUsage),
ReadField(CursorDisplayCount),
ReadField(WheelDelta)
);
if (ReadField(Flags) & CONSOLE_TEXTMODE_BUFFER) {
Print("\t TextInfo.Rows %#p\n"
"\t TextInfo.TextRows %#p\n"
"\t TextInfo.FirstRow 0x%08X\n",
ReadField(BufferInfo.TextInfo.Rows),
ReadField(BufferInfo.TextInfo.TextRows),
ReadField(BufferInfo.TextInfo.FirstRow));
Print("\t TextInfo.CurrentTextBufferFont.FontSize 0x%04X,0x%04X\n"
"\t TextInfo.CurrentTextBufferFont.FontNumber 0x%08X\n",
ReadField(BufferInfo.TextInfo.CurrentTextBufferFont.FontSize.X),
ReadField(BufferInfo.TextInfo.CurrentTextBufferFont.FontSize.Y),
ReadField(Screen.BufferInfo.TextInfo.CurrentTextBufferFont.FontNumber));
Print("\t TextInfo.CurrentTextBufferFont.Family, Weight 0x%08X, 0x%08X\n"
"\t TextInfo.CurrentTextBufferFont.FaceName %ls\n"
"\t TextInfo.CurrentTextBufferFont.FontCodePage %d\n",
ReadField(BufferInfo.TextInfo.CurrentTextBufferFont.Family),
ReadField(Screen.BufferInfo.TextInfo.CurrentTextBufferFont.Weight),
ReadField(BufferInfo.TextInfo.CurrentTextBufferFont.FaceName),
ReadField(BufferInfo.TextInfo.CurrentTextBufferFont.FontCodePage));
if (ReadField(BufferInfo.TextInfo.ListOfTextBufferFont)) {
ULONG64 pLinkFont;
ULONG Count = 0;
pLinkFont = ReadField(BufferInfo.TextInfo.ListOfTextBufferFont);
while (pLinkFont != 0) {
InitTypeRead(pLinkFont, SYM(TEXT_BUFFER_FONT_INFO));
Print("\t Link Font #%d\n", Count++);
Print("\t TextInfo.LinkOfTextBufferFont.FontSize 0x%04X,0x%04X\n"
"\t TextInfo.LinkOfTextBufferFont.FontNumber 0x%08X\n",
ReadField(FontSize.X),
ReadField(FontSize.Y),
ReadField(FontNumber));
Print("\t TextInfo.LinkOfTextBufferFont.Family, Weight 0x%08X, 0x%08X\n"
"\t TextInfo.LinkOfTextBufferFont.FaceName %ls\n"
"\t TextInfo.LinkOfTextBufferFont.FontCodePage %d\n",
ReadField(Family),
ReadField(Weight),
ReadField(FaceName),
ReadField(FontCodePage));
pLinkFont = ReadField(NextTextBufferFont);
}
Print("\n");
}
InitTypeRead(pScreen, SYM(SCREEN_INFORMATION));
Print("\t TextInfo.ModeIndex 0x%08X\n"
#ifdef i386
"\t TextInfo.WindowedWindowSize.X Y 0x%08X 0x%08X\n"
"\t TextInfo.WindowedScreenSize.X Y 0x%08X 0x%08X\n"
"\t TextInfo.MousePosition.X Y 0x%08X 0x%08X\n"
#endif
"\t TextInfo.Flags 0x%08X\n",
ReadField(BufferInfo.TextInfo.ModeIndex),
#ifdef i386
ReadField(BufferInfo.TextInfo.WindowedWindowSize.X),
ReadField(BufferInfo.TextInfo.WindowedWindowSize.Y),
ReadField(BufferInfo.TextInfo.WindowedScreenSize.X),
ReadField(BufferInfo.TextInfo.WindowedScreenSize.Y),
ReadField(BufferInfo.TextInfo.MousePosition.X),
ReadField(BufferInfo.TextInfo.MousePosition.Y),
#endif
ReadField(BufferInfo.TextInfo.Flags));
Print("\t TextInfo.CursorVisible 0x%08X\n"
"\t TextInfo.CursorOn 0x%08X\n"
"\t TextInfo.DelayCursor 0x%08X\n"
"\t TextInfo.CursorPosition.X Y 0x%08X 0x%08X\n"
"\t TextInfo.CursorSize 0x%08X\n"
"\t TextInfo.CursorYSize 0x%08X\n"
"\t TextInfo.UpdatingScreen 0x%08X\n",
ReadField(BufferInfo.TextInfo.CursorVisible),
ReadField(BufferInfo.TextInfo.CursorOn),
ReadField(BufferInfo.TextInfo.DelayCursor),
ReadField(BufferInfo.TextInfo.CursorPosition.X),
ReadField(BufferInfo.TextInfo.CursorPosition.Y),
ReadField(BufferInfo.TextInfo.CursorSize),
ReadField(BufferInfo.TextInfo.CursorYSize),
ReadField(BufferInfo.TextInfo.UpdatingScreen));
} else {
Print("\t GraphicsInfo.BitMapInfoLength 0x%08X\n"
"\t GraphicsInfo.lpBitMapInfo 0x%08X\n"
"\t GraphicsInfo.BitMap 0x%08X\n"
"\t GraphicsInfo.ClientBitMap 0x%08X\n"
"\t GraphicsInfo.ClientProcess 0x%08X\n"
"\t GraphicsInfo.hMutex 0x%08X\n"
"\t GraphicsInfo.hSection 0x%08X\n"
"\t GraphicsInfo.dwUsage 0x%08X\n",
ReadField(BufferInfo.GraphicsInfo.BitMapInfoLength),
ReadField(BufferInfo.GraphicsInfo.lpBitMapInfo),
ReadField(BufferInfo.GraphicsInfo.BitMap),
ReadField(BufferInfo.GraphicsInfo.ClientBitMap),
ReadField(BufferInfo.GraphicsInfo.ClientProcess),
ReadField(BufferInfo.GraphicsInfo.hMutex),
ReadField(BufferInfo.GraphicsInfo.hSection),
ReadField(BufferInfo.GraphicsInfo.dwUsage)
);
}
return TRUE;
}
/***************************************************************************\
* dcpt - Dump CPTABLEINFO
*
* dcpt address - dumps CPTABLEINFO at address
* dcpt - dumps CPTABLEINFO at GlyphCP
*
\***************************************************************************/
BOOL Idcpt(
DWORD opts,
ULONG64 pcpt)
{
UNREFERENCED_PARAMETER(opts);
if (!pcpt) {
moveExpValuePtr(&pcpt, SYM(GlyphCP));
}
InitTypeRead(pcpt, SYM(CPTABLEINFO));
Print("CPTABLEINFO @ %#p\n", pcpt);
Print(" CodePage = 0x%x (%d)\n"
" MaximumCharacterSize = %x\n"
" DefaultChar = %x\n",
ReadField(CodePage), ReadField(CodePage),
ReadField(MaximumCharacterSize),
ReadField(DefaultChar));
Print(" UniDefaultChar = 0x%04x\n"
" TransDefaultChar = %x\n"
" TransUniDefaultChar = 0x%04x\n"
" DBCSCodePage = 0x%x (%d)\n",
ReadField(UniDefaultChar),
ReadField(TransDefaultChar),
ReadField(TransUniDefaultChar),
ReadField(DBCSCodePage), ReadField(DBCSCodePage));
Print(" LeadByte[MAXIMUM_LEADBYTES] = %04x,%04x,%04x,...\n"
" MultiByteTable = %x\n"
" WideCharTable = %lx\n"
" DBCSRanges = %lx\n"
" DBCSOffsets = %lx\n",
ReadField(LeadByte[0]), ReadField(LeadByte[1]), ReadField(LeadByte[2]),
ReadField(MultiByteTable),
ReadField(WideCharTable),
ReadField(DBCSRanges),
ReadField(DBCSOffsets));
return TRUE;
}
/***************************************************************************\
* dch - Dump Command History
*
* dch address - dumps COMMAND_HISTORY at address
*
\***************************************************************************/
BOOL Idch(
DWORD opts,
ULONG64 pCmdHist)
{
SHORT NumberOfCommands;
DWORD dwTypeSize, dwOffset, CommandLength;
WCHAR Buffer[512];
int i;
UNREFERENCED_PARAMETER(opts);
InitTypeRead(pCmdHist, SYM(COMMAND_HISTORY));
Print("COMMAND_HISTORY @ %#p\n", pCmdHist);
Print(" Flags = 0x%08lX%s\n",
ReadField(Flags), GetFlags(GF_CMDHIST, (DWORD)ReadField(Flags), NULL));
Print(" ListLink.F B = %#p %#p\n",
ReadField(ListLink.Flink), ReadField(ListLink.Blink));
Print(" AppName = %ws\n", ReadField(AppName));
Print(" NumberOfCommands = 0x%lx\n"
" LastAdded = 0x%lx\n"
" LastDisplayed = 0x%lx\n"
" FirstCommand = 0x%lx\n"
" MaximumNumberOfCommands = 0x%lx\n",
ReadField(NumberOfCommands),
ReadField(LastAdded),
ReadField(LastDisplayed),
ReadField(FirstCommand),
ReadField(MaximumNumberOfCommands));
Print(" ProcessHandle = 0x%08lX\n",
ReadField(ProcessHandle));
Print(" PopupList.F B = %#p %#p\n",
ReadField(PopupList.Flink), ReadField(PopupList.Blink));
dwTypeSize = GetTypeSize(SYM(COMMAND));
NumberOfCommands = (SHORT)ReadField(NumberOfCommands);
GetFieldOffset(SYM(COMMAND_HISTORY), "Command", &dwOffset);
for (i = 0; i < NumberOfCommands; i++) {
ULONG64 pCmd = pCmdHist + i * dwTypeSize;
GetFieldValue(pCmd, SYM(COMMAND_HISTORY), "CommandLength", CommandLength);
moveBlock(Buffer, pCmd + dwOffset, min(CommandLength, ARRAY_SIZE(Buffer)));
Print(" %03d: %d chars = \"%ws\"\n", i,
CommandLength,
Buffer);
if (i == ReadField(LastAdded)) {
Print(" (Last Added)\n");
} else if (i == ReadField(LastDisplayed)) {
Print(" (Last Displayed)\n");
} else if (i == ReadField(FirstCommand)) {
Print(" (First Command)\n");
}
}
return TRUE;
}
#define HEAP_GRANULARITY 8
#define HEAP_SIZE(Size) (((Size) + (HEAP_GRANULARITY - 1) + HEAP_GRANULARITY) & ~(HEAP_GRANULARITY - 1))
/***************************************************************************\
* dmem - Dump Memory - Dumps memory used by console stuff.
*
\***************************************************************************/
BOOL Idmem(
DWORD opts,
ULONG64 pConsole)
{
ULONG i, NumberOfConsoleHandles;
ULONG64 pScreen;
ULONG cbTotal = 0;
ULONG cbConsole = 0;
ULONG cbInput = 0;
ULONG cbOutput = 0;
ULONG cbFE = 0;
WCHAR buffer[256];
if (!pConsole) {
/*
* If no console is specified, loop through all of them
*/
moveExpValue(&NumberOfConsoleHandles,
SYM(NumberOfConsoleHandles));
moveExpValuePtr(&pConsole,
SYM(ConsoleHandles));
for (i = 0; i < NumberOfConsoleHandles; i++) {
ULONG64 ptr;
ReadPointer(pConsole, &ptr);
if (ptr) {
cbTotal += Idmem(opts, ptr);
Print("==========================================\n");
}
(ULONG_PTR)pConsole += GetTypeSize(SYM(PCONSOLE_INFORMATION));
}
Print("Total Size for all consoles = %d bytes\n", cbTotal);
return cbTotal;
}
InitTypeRead(pConsole, winsrv!CONSOLE_INFORMATION);
DbgGetConsoleTitle(pConsole, buffer, ARRAY_SIZE(buffer));
Print("PCONSOLE @ %#p \"%ws\"\n", pConsole, buffer);
cbConsole = HEAP_SIZE(GetTypeSize(SYM(CONSOLE_INFORMATION))) +
HEAP_SIZE((ULONG)ReadField(TitleLength)) +
HEAP_SIZE((ULONG)ReadField(OriginalTitleLength));
cbInput = HEAP_SIZE((ULONG)ReadField(InputBuffer.AllocatedBufferSize));
pScreen = ReadField(ScreenBuffers);
while (pScreen) {
InitTypeRead(pScreen, winsrv!SCREEN_INFORMATION);
cbOutput += HEAP_SIZE(GetTypeSize(SYM(SCREEN_INFORMATION)));
if (ReadField(Flags) & CONSOLE_TEXTMODE_BUFFER) {
cbOutput += HEAP_SIZE((ULONG)ReadField(ScreenBufferSize.Y) *
GetTypeSize(SYM(ROW))) +
HEAP_SIZE((ULONG)ReadField(ScreenBufferSize.X) *
(ULONG)ReadField(ScreenBufferSize.Y) *
sizeof(WCHAR));
if (ReadField(BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferCharacter)) {
cbFE += HEAP_SIZE((ULONG)ReadField(ScreenBufferSize.X) *
(ULONG)ReadField(ScreenBufferSize.Y * sizeof(WCHAR)));
}
if (ReadField(BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferAttribute)) {
cbFE += HEAP_SIZE((ULONG)ReadField(ScreenBufferSize.X) *
(ULONG)ReadField(ScreenBufferSize.Y) * sizeof(BYTE));
}
if (ReadField(BufferInfo.TextInfo.DbcsScreenBuffer.TransWriteConsole)) {
cbFE += HEAP_SIZE((ULONG)ReadField(ScreenBufferSize.X) *
(ULONG)ReadField(ScreenBufferSize.Y) * sizeof(WCHAR));
}
if (ReadField(BufferInfo.TextInfo.DbcsScreenBuffer.KAttrRows)) {
cbFE += HEAP_SIZE((ULONG)ReadField(ScreenBufferSize.X) *
(ULONG)ReadField(ScreenBufferSize.Y) * sizeof(BYTE));
}
}
pScreen = ReadField(Next);
}
cbTotal = cbConsole + cbInput + cbOutput + cbFE;
if (opts & OFLAG(v)) {
Print(" Console Size = %7d\n", cbConsole);
Print(" Input Size = %7d\n", cbInput);
Print(" Output Size = %7d\n", cbOutput);
Print(" FE Size = %7d\n", cbFE);
}
Print("Total Size = %7d\n", cbTotal);
return cbTotal;
}
LPEXT_API_VERSION
ExtensionApiVersion(
VOID)
{
return &ApiVersion;
}
VOID
WinDbgExtensionDllInit(
WINDBG_EXTENSION_APIS *lpExtensionApis,
USHORT MajorVersion,
USHORT MinorVersion
)
{
ExtensionApis = *lpExtensionApis;
SavedMajorVersion = MajorVersion;
SavedMinorVersion = MinorVersion;
bDebuggingChecked = (SavedMajorVersion == 0x0c);
}
BOOL
CopyUnicodeString(
IN ULONG64 pData,
IN char * pszStructName,
IN char * pszFieldName,
OUT WCHAR *pszDest,
IN ULONG cchMax)
{
ULONG Length;
ULONG64 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)) {
Print("1\n");
wcscpy(pszDest, L"<< Can't get name >>");
return FALSE;
}
if (Buffer == 0) {
wcscpy(pszDest, L"<null>");
} else {
ULONG cbText;
cbText = min(cchMax, Length + sizeof(WCHAR));
if (!(tryMoveBlock(pszDest, Buffer, cbText))) {
wcscpy(pszDest, L"<< Can't get value >>");
Print("2\n");
return FALSE;
}
}
pszDest[cchMax] = L'\0';
return TRUE;
}
VOID
DbgGetConsoleTitle(
IN ULONG64 pConsole,
OUT PWCHAR buffer,
IN UINT cbSize)
{
ULONG64 ptr;
ULONG dwOffset, TitleLength;
GetFieldOffset(SYM(CONSOLE_INFORMATION), "Title", &dwOffset);
ReadPointer(pConsole + dwOffset, &ptr);
GetFieldValue(pConsole, SYM(CONSOLE_INFORMATION), "TitleLength", TitleLength);
cbSize = min(cbSize, TitleLength);
moveBlock(buffer, ptr, (DWORD)ReadField(TitleLength) * sizeof(WCHAR));
buffer[cbSize] = L'\0';
}