Windows2003-3790/termsrv/tsdbg/exts.cpp

514 lines
16 KiB
C++

/*-----------------------------------------------------------------------------
Copyright (c) 2000 Microsoft Corporation
Module:
exts.cpp
Sampe file showing couple of extension examples
-----------------------------------------------------------------------------*/
#include "tsdbg.h"
bool IsUserDbg()
{
/*
// Specific types of kernel debuggees.
#define DEBUG_KERNEL_CONNECTION 0
#define DEBUG_KERNEL_LOCAL 1
#define DEBUG_KERNEL_EXDI_DRIVER 2
#define DEBUG_KERNEL_SMALL_DUMP DEBUG_DUMP_SMALL
#define DEBUG_KERNEL_DUMP DEBUG_DUMP_DEFAULT
#define DEBUG_KERNEL_FULL_DUMP DEBUG_DUMP_FULL
// Specific types of Windows user debuggees.
#define DEBUG_USER_WINDOWS_PROCESS 0
#define DEBUG_USER_WINDOWS_PROCESS_SERVER 1
#define DEBUG_USER_WINDOWS_SMALL_DUMP DEBUG_DUMP_SMALL
#define DEBUG_USER_WINDOWS_DUMP DEBUG_DUMP_DEFAULT
*/
/*
#define DEBUG_CLASS_UNINITIALIZED 0
#define DEBUG_CLASS_KERNEL 1
#define DEBUG_CLASS_USER_WINDOWS 2
*/
ULONG Class, Qualifier;
// Figure out if this is KD or NTSD piped to KD.
if (S_OK != g_ExtControl->GetDebuggeeType(&Class, &Qualifier))
{
dprintf("*** GetDebuggeeType failed ***\n\n");
}
if (Class == DEBUG_CLASS_USER_WINDOWS)
return true;
else
return false;
}
/*
Sample extension to demonstrace ececuting debugger command
*/
HRESULT CALLBACK
cmdsample(PDEBUG_CLIENT Client, PCSTR args)
{
CHAR Input[256];
INIT_API();
UNREFERENCED_PARAMETER(args);
//
// Output a 10 frame stack
//
g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS | // Flags on what to do with output
DEBUG_OUTCTL_OVERRIDE_MASK |
DEBUG_OUTCTL_NOT_LOGGED,
NULL,
10, // number of frames to display
DEBUG_STACK_FUNCTION_INFO | DEBUG_STACK_COLUMN_NAMES |
DEBUG_STACK_ARGUMENTS | DEBUG_STACK_FRAME_ADDRESSES);
//
// Engine interface for print
//
g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\nDebugger module list\n");
//
// list all the modules by executing lm command
//
g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
DEBUG_OUTCTL_OVERRIDE_MASK |
DEBUG_OUTCTL_NOT_LOGGED,
"lm", // Command to be executed
DEBUG_EXECUTE_DEFAULT );
//
// Ask for user input
//
g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\n***User Input sample\n\nEnter Command to run : ");
GetInputLine(NULL, &Input[0], sizeof(Input));
g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
DEBUG_OUTCTL_OVERRIDE_MASK |
DEBUG_OUTCTL_NOT_LOGGED,
Input, // Command to be executed
DEBUG_EXECUTE_DEFAULT );
EXIT_API();
return S_OK;
}
/*
Sample extension to read and dump a struct on target
This reads the struct _EXCEPTION_RECORD which is defined as:
typedef struct _EXCEPTION_RECORD {
NTSTATUS ExceptionCode;
ULONG ExceptionFlags;
struct _EXCEPTION_RECORD *ExceptionRecord;
PVOID ExceptionAddress;
ULONG NumberParameters;
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD;
*/
HRESULT CALLBACK
structsample(PDEBUG_CLIENT /*Client*/, PCSTR /*args*/)
{
/*
ULONG64 Address;
INIT_API();
Address = GetExpression(args);
DWORD Buffer[4], cb;
// Read and display first 4 dwords at Address
if (ReadMemory(Address, &Buffer, sizeof(Buffer), &cb) && cb == sizeof(Buffer)) {
dprintf("%p: %08lx %08lx %08lx %08lx\n\n", Address,
Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
}
//
// Method 1 to dump a struct
//
dprintf("Method 1:\n");
// Inititalze type read from the Address
if (InitTypeRead(Address, _EXCEPTION_RECORD) != 0) {
dprintf("Error in reading _EXCEPTION_RECORD at %p", // Use %p to print pointer values
Address);
} else {
// read and dump the fields
dprintf("_EXCEPTION_RECORD @ %p\n", Address);
dprintf("\tExceptionCode : %lx\n", (ULONG) ReadField(ExceptionCode));
dprintf("\tExceptionAddress : %p\n", ReadField(ExceptionAddress));
dprintf("\tExceptionInformation[1] : %I64lx\n", ReadField(ExceptionInformation[1]));
// And so on...
}
//
// Method 2 to read a struct
//
ULONG64 ExceptionInformation_1, ExceptionAddress, ExceptionCode;
dprintf("\n\nMethod 2:\n");
// Read and dump the fields by specifying type and address individually
if (GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionCode", ExceptionCode)) {
dprintf("Error in reading _EXCEPTION_RECORD at %p\n",
Address);
} else {
// Pointers are read as ULONG64 values
GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionAddress", ExceptionAddress);
GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionInformation[1]", ExceptionInformation_1);
// And so on..
dprintf("_EXCEPTION_RECORD @ %p\n", Address);
dprintf("\tExceptionCode : %lx\n", ExceptionCode);
dprintf("\tExceptionAddress : %p\n", ExceptionAddress);
dprintf("\tExceptionInformation[1] : %I64lx\n", ExceptionInformation_1);
}
ULONG64 Module;
ULONG i, TypeId;
CHAR Name[MAX_PATH];
//
// To get/list field names
//
g_ExtSymbols->GetSymbolTypeId("_EXCEPTION_RECORD", &TypeId, &Module);
dprintf("Fields of _EXCEPTION_RECORD\n");
for (i=0; ;i++) {
HRESULT Hr;
ULONG Offset=0;
Hr = g_ExtSymbols2->GetFieldName(Module, TypeId, i, Name, MAX_PATH, NULL);
if (Hr == S_OK) {
g_ExtSymbols->GetFieldOffset(Module, TypeId, Name, &Offset);
dprintf("%lx (+%03lx) %s\n", i, Offset, Name);
} else if (Hr == E_INVALIDARG) {
// All Fields done
break;
} else {
dprintf("GetFieldName Failed %lx\n", Hr);
break;
}
}
//
// Get name for an enumerate
//
// typedef enum {
// Enum1,
// Enum2,
// Enum3,
// } TEST_ENUM;
//
ULONG ValueOfEnum = 0;
g_ExtSymbols->GetSymbolTypeId("TEST_ENUM", &TypeId, &Module);
g_ExtSymbols2->GetConstantName(Module, TypeId, ValueOfEnum, Name, MAX_PATH, NULL);
dprintf("Testenum %I64lx == %s\n", ExceptionCode, Name);
// This prints out, Testenum 0 == Enum1
//
// Read an array
//
// typedef struct FOO_TYPE {
// ULONG Bar;
// ULONG Bar2;
// } FOO_TYPE;
//
// FOO_TYPE sampleArray[20];
ULONG Bar, Bar2;
CHAR TypeName[100];
for (i=0; i<20; i++) {
sprintf(TypeName, "sampleArray[%lx]", i);
if (GetFieldValue(0, TypeName, "Bar", Bar))
break;
GetFieldValue(0, TypeName, "Bar2", Bar2);
dprintf("%16s - Bar %2ld Bar2 %ld\n", TypeName, Bar, Bar2);
}
EXIT_API();
*/
return S_OK;
}
/*
This gets called (by DebugExtensionNotify whentarget is halted and is accessible
*/
HRESULT
NotifyOnTargetAccessible(PDEBUG_CONTROL /* Control */)
{/*
dprintf("Extension dll detected a break");
if (Connected) {
dprintf(" connected to ");
switch (TargetMachine) {
case IMAGE_FILE_MACHINE_I386:
dprintf("X86");
break;
case IMAGE_FILE_MACHINE_AMD64:
dprintf("AMD64");
break;
case IMAGE_FILE_MACHINE_IA64:
dprintf("IA64");
break;
default:
dprintf("Other");
break;
}
}
dprintf("\n");
//
// show the top frame and execute dv to dump the locals here and return
//
Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
DEBUG_OUTCTL_OVERRIDE_MASK |
DEBUG_OUTCTL_NOT_LOGGED,
".frame", // Command to be executed
DEBUG_EXECUTE_DEFAULT );
Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
DEBUG_OUTCTL_OVERRIDE_MASK |
DEBUG_OUTCTL_NOT_LOGGED,
"dv", // Command to be executed
DEBUG_EXECUTE_DEFAULT );
*/
return S_OK;
}
/*
A built-in help for the extension dll
*/
HRESULT CALLBACK
help(PDEBUG_CLIENT Client, PCSTR args)
{
INIT_API();
UNREFERENCED_PARAMETER(args);
dprintf("Help for tsdbg.dll\n"
" qwinsta - lists winstation data structures\n"
" help = Shows this help\n"
// " structsample <addr> - This dumps a struct at given address\n"
//" cmdsample - This does stacktrace and lists\n"
);
EXIT_API();
return S_OK;
}
void PrintBuildNumber()
{
ULONG64 Address;
Address = GetExpression("poi(nt!ntbuildnumber)");
if (Address & 0xf0000000)
{
Address &= 0x0fffffff;
dprintf("Build Number = %d Free\n", Address);
}
else if (Address & 0xc0000000)
{
Address &= 0x0fffffff;
dprintf("Build Number = %d Chk\n", Address);
}
else
{
dprintf("Error getting Build Number!\n");
}
}
HRESULT CALLBACK
qwinsta(PDEBUG_CLIENT Client, PCSTR args)
{
ULONG64 winstationlisthead, FLink;
ULONG64 TermSrvProcPerTermDD = 0;
bool bDebugMode = false;
INIT_API();
dprintf("qwinsta 1.2\n");
if (strstr(args, "debug"))
bDebugMode = true;
if (bDebugMode)
{
dprintf("*** in debug mode *** \n");
}
if (bDebugMode)
dprintf("IsUserDebugger = %s\n", (IsUserDbg() ? "true" : "false"));
dprintf("----------------------------------------------------------------------------------------------------\n");
//
// Find Termsrv proccess id.
//
if (!IsUserDbg())
{
TermSrvProcPerTermDD = GetExpression("poi(termdd!g_TermServProcessID)");
dprintf("termsrv process = %p \n", TermSrvProcPerTermDD);
if (!TermSrvProcPerTermDD)
{
dprintf("ERROR:tsdbg failed to retrive the value for termdd!g_TermServProcessID\n");
dprintf("please make sure that the symbols are alright\n");
goto doneError;
}
ULONG64 ImpliciteProcess;
g_ExtSysObjects2->GetImplicitProcessDataOffset(&ImpliciteProcess);
dprintf("Implicit Process = %p \n", ImpliciteProcess);
ULONG64 CurrentProcess;
g_ExtSysObjects2->GetCurrentProcessDataOffset(&CurrentProcess);
dprintf("current Process = %p \n", CurrentProcess);
if (ImpliciteProcess != TermSrvProcPerTermDD)
{
dprintf("ERROR:tsdbg for this command to work current implicite process must be termsrv.\n");
dprintf("please do .process /p %p and then try again.\n", TermSrvProcPerTermDD);
goto doneError;
}
}
//
// get active console session id.
//
LONG ActiveConsoleId = STATUS_UNSUCCESSFUL;
if (GetFieldValue((ULONG64) MM_SHARED_USER_DATA_VA, "termsrv!KUSER_SHARED_DATA", "ActiveConsoleId", ActiveConsoleId))
ActiveConsoleId = STATUS_UNSUCCESSFUL;
dprintf("ActiveConsoleId = %d \n", ActiveConsoleId);
//
// winstation list head.
//
winstationlisthead = GetExpression("termsrv!winstationlisthead");
if (!winstationlisthead)
{
dprintf("ERROR:tsdbg failed to retrive the value for termsrv!winstationlisthead\n");
dprintf("please make sure that the symbols are alright\n");
goto doneError;
}
dprintf("winstationlisthead = %p \n", winstationlisthead);
if (GetFieldValue(winstationlisthead, "termsrv!LIST_ENTRY", "Flink", FLink))
{
dprintf("failed to get winstationlisthead.flink\n\n");
goto doneError;
}
UINT uiWinstations = 0;
//
// print winstation list.
//
dprintf("----------------------------------------------------------------------------------------------------\n");
dprintf("%8s", "Winsta");
dprintf(" ");
dprintf("%7s", "LogonId");
dprintf(" ");
dprintf("%-10s", "Name");
dprintf(" ");
dprintf("%-22s", "State");
dprintf(" ");
dprintf("%8s", "Flags");
dprintf(" ");
dprintf("%8s", "SFlags");
dprintf(" ");
dprintf("%-10s", "Starting");
dprintf(" ");
dprintf("%-10s", "Terminating");
dprintf("\n");
while (winstationlisthead != FLink && uiWinstations < 500)
{
if (CheckControlC()) goto doneError;
uiWinstations++;
ULONG ret = 0;
ULONG LogonId, State, Flags, StateFlags;
WCHAR WinStationName[33];
UCHAR Starting, Terminating;
// InitTypeRead(FLink, Type)
ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "LogonId", LogonId);
ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "WinStationName", WinStationName);
ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "State", State);
ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "Flags", Flags);
ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "Starting", Starting);
ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "LogonId", LogonId);
ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "Terminating", Terminating);
ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "StateFlags", StateFlags);
//
// get string value for the enum _WINSTATIONSTATECLASS.
//
ULONG64 Module;
ULONG TypeId;
char StateName[MAX_PATH];
g_ExtSymbols->GetSymbolTypeId("_WINSTATIONSTATECLASS", &TypeId, &Module);
g_ExtSymbols2->GetConstantName(Module, TypeId, State, StateName, MAX_PATH, NULL);
if (ret)
{
dprintf("failed to get winstationlisthead.flink\n\n");
goto doneError;
}
dprintf("%p", FLink);
dprintf(" ");
dprintf("%#7x", LogonId);
dprintf(" ");
dprintf("%-10S", WinStationName);
dprintf(" ");
dprintf("%1x:%-20s", State, StateName);
dprintf(" ");
dprintf("%08x", Flags);
dprintf(" ");
dprintf("%08x", StateFlags);
dprintf(" ");
dprintf("%-10s", (Starting ? "True" : "False"));
dprintf(" ");
dprintf("%-10s", (Terminating ? "True" : "False"));
dprintf("\n");
//dprintf("%10p %7d %-10S %5d:%-20s %5d %10d %-8s %-11s\n", FLink, LogonId, WinStationName, State, StateName, Flags, StateFlags, (Starting ? "true" : "false"), (Terminating ? "true" : "false"));
if (GetFieldValue(FLink, "termsrv!LIST_ENTRY", "Flink", FLink))
{
dprintf("failed to get winstationlisthead.flink\n\n");
goto doneError;
}
}
dprintf("----------------------------------------------------------------------------------------------------\n");
// dprintf("Total Winstations = %d\n", uiWinstations);
doneError:
EXIT_API();
return S_OK;
}