Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2191 lines
63 KiB

/*++
Copyright (c) 1992-2000 Microsoft Corporation
Module Name:
bugcheck.cpp
Abstract:
WinDbg Extension Api
Environment:
User Mode.
Revision History:
Andre Vachon (andreva)
bugcheck analyzer.
--*/
#include "precomp.h"
#include <kdextsfn.h>
#pragma hdrstop
extern BUGDESC_APIREFS g_BugDescApiRefs[];
extern ULONG g_NumBugDescApiRefs;
PSTR g_PoolRegion[DbgPoolRegionMax] = {
"Unknown", // DbgPoolRegionUnknown,
"Special pool", // DbgPoolRegionSpecial,
"Paged pool", // DbgPoolRegionPaged,
"Nonpaged pool", // DbgPoolRegionNonPaged,
"Pool code", // DbgPoolRegionCode,
"Nonpaged pool expansion", // DbgPoolRegionNonPagedExpansion,
};
BOOL
AnalyzeCrashInfo(
PBUGCHECK_ANALYSIS Bc,
BOOL Verbose
);
void
GetCrashInfoFromBugCheck(
PBUGCHECK_ANALYSIS Bc,
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
);
HRESULT
BugCheckCE(
PDEBUG_CLIENT Client,
PBUGCHECK_ANALYSIS Bc
)
{
HRESULT Status;
ULONG Index;
ULONG64 BaseAddress;
CHAR ImageNameBuffer[512];
//
// The address at fault is in parameter 1
//
dprintf("Faulting code address : %p\n", Bc->Args[0]);
Status = E_FAIL;
if (Bc->Args[0])
{
Status = g_ExtSymbols->GetModuleByOffset(Bc->Args[0], 0,
&Index, &BaseAddress);
if (Status == S_OK)
{
Status = g_ExtSymbols->GetModuleNames(DEBUG_ANY_ID, BaseAddress,
ImageNameBuffer,
sizeof(ImageNameBuffer),
NULL, NULL, 0, NULL,
NULL, 0, NULL);
}
}
if (Status == S_OK)
{
dprintf("Possible faulting driver name : %s\n", ImageNameBuffer);
dprintf(" BaseAddress = %p\n", BaseAddress);
dprintf(" Offset = %p\n", Bc->Args[0]-BaseAddress);
}
else
{
dprintf("Faulting driver name : UNKNOWN\n");
}
return Status;
}
/*
Get the description record for a bugcheck code.
*/
BOOL
GetBugCheckDescription(
PBUGCHECK_ANALYSIS Bc
)
{
ULONG i;
for (i=0; i<g_NumBugDescApiRefs; i++) {
if (g_BugDescApiRefs[i].Code == Bc->Code) {
(g_BugDescApiRefs[i].pExamineRoutine)(Bc);
return TRUE;
}
}
return FALSE;
}
void
PrintBugDescription(
PBUGCHECK_ANALYSIS pBugCheck
)
{
LPTSTR Name = pBugCheck->szName;
LPTSTR Description = pBugCheck->szDescription;
if (!Name)
{
Name = "Unknown bugcheck code";
}
if (!Description)
{
Description = "Unknown bugcheck description\n";
}
dprintf("%s (%lx)\n%s", Name, pBugCheck->Code, Description);
dprintf("Arguments:\n");
for (ULONG i=0; i<4; i++) {
dprintf("Arg%lx: %p",i+1,pBugCheck->Args[i]);
if (pBugCheck->szParamsDesc[i]) {
dprintf(", %s", pBugCheck->szParamsDesc[i]);
}
dprintf("\n");
}
}
DECLARE_API( analyzebugcheck )
/*++
Routine Description:
analyze a bugcheck.
Arguments:
None.
Return Value:
None.
--*/
{
BUGCHECK_ANALYSIS Bc = {0};
BOOL Verbose=FALSE;
INIT_API();
while (*args == ' ' || *args == '\t') args++;
while (*args == '-') {
++args;
switch (*args) {
case 'v':
Verbose = TRUE;
++args;
break;
case 's':
if (!strncmp(args, "show",4))
{
ULONG64 Code;
args+=4;
GetExpressionEx(args, &Code, &args);
Bc.Code = (ULONG)Code;
GetBugCheckDescription(&Bc);
PrintBugDescription(&Bc);
EXIT_API();
return Status;
}
default:
dprintf("Unknown option %c\n", *args);
break;
}
while (*args == ' ' || *args == '\t') args++;
}
Status = g_ExtControl->ReadBugCheckData(&Bc.Code, &Bc.Args[0], &Bc.Args[1],
&Bc.Args[2], &Bc.Args[3]);
if (Status != S_OK)
{
EXIT_API();
return Status;
}
#if 0
// disable this
if (Bc.Code == 0) {
//
// It might be watchdog bugcheck
//
ULONG64 WdBcAddr;
ULONG res;
WdBcAddr = GetExpression("watchdog!g_WdBugCheckData");
if (WdBcAddr &&
ReadMemory(WdBcAddr, &Bc.Code, sizeof(Bc.Code), &res) &&
ReadPointer(WdBcAddr+sizeof(Bc.Code), &Bc.Args[0]) &&
ReadPointer(WdBcAddr+sizeof(Bc.Code), &Bc.Args[1]) &&
ReadPointer(WdBcAddr+sizeof(Bc.Code), &Bc.Args[2]) &&
ReadPointer(WdBcAddr+sizeof(Bc.Code), &Bc.Args[3])) {
dprintf("\n*** Watchdog bugcheck.\n");
}
}
#endif
Status = AnalyzeCrashInfo(&Bc, Verbose) ? S_OK : E_FAIL;
if (!Verbose) {
EXIT_API();
return Status;
}
switch (Bc.Code)
{
case 0xCE:
Status = BugCheckCE(Client, &Bc);
break;
default:
break;
}
//
// Create a new minidump file of this crash
//
#if 0
ULONG FailTime = 0;
ULONG UpTime = 0;
CHAR CurrentTime[20];
CHAR CurrentDate[20];
CHAR Buffer[MAX_PATH];
g_ExtControl->GetCurrentTimeDate(&FailTime);
g_ExtControl->GetCurrentSystemUpTime(&UpTime);
_strtime(CurrentTime);
_strdate(CurrentDate);
if (CurrentTime && UpTime)
{
sprintf(Buffer, "Dump%s-%s-%08lx-%08lx-%s.dmp",
FailTime, Uptime, Currentdate, CurrentTime);
Status = g_ExtClient->WriteDumpFile(Buffer ,DEBUG_DUMP_SMALL);
}
#endif
CHAR Buffer[MAX_PATH];
if (GetTempFileName(".", "DMP", 0, Buffer))
{
Status = g_ExtClient->WriteDumpFile(Buffer ,DEBUG_DUMP_SMALL);
if (Status == S_OK)
{
//
// We create a file - now lets send it to the database
//
//CopyFile(Buffer, "c:\\xxxx", 0);
DeleteFile(Buffer);
}
}
dprintf("\n\n");
EXIT_API();
return S_OK;
}
EXTENSION_API( GetKerFailureAnalysis )(
IN PDEBUG_CLIENT Client,
OUT PDEBUG_FAILURE_ANALYSIS* pAnalysis
)
{
BUGCHECK_ANALYSIS Bc = {0};
BOOL Verbose;
INIT_API();
Status = g_ExtControl->ReadBugCheckData(&Bc.Code, &Bc.Args[0], &Bc.Args[1],
&Bc.Args[2], &Bc.Args[3]);
if (Status != S_OK)
{
EXIT_API();
return Status;
}
GetCrashInfoFromBugCheck(&Bc, pAnalysis);
Status = *pAnalysis ? S_OK : E_FAIL;
EXIT_API();
return Status;
}
#define MAX_STACK_FRAMES 50
#define DWORD_ALIGN(n) (((n+sizeof(DWORD)-1)/n)*n)
#define DECL_GETINFO(bcname) \
void \
GetInfoFor##bcname ( \
PBUGCHECK_ANALYSIS Bc, \
PDEBUG_FAILURE_ANALYSIS *pCrashInfo \
)
DECL_GETINFO( DRIVER_CAUGHT_MODIFYING_FREED_POOL );
DECL_GETINFO( DRIVER_VERIFIER_IOMANAGER_VIOLATION );
DECL_GETINFO( IRQL_NOT_LESS_OR_EQUAL );
DECL_GETINFO( KMODE_EXCEPTION_NOT_HANDLED );
DECL_GETINFO( SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION );
DECL_GETINFO( TIMER_OR_DPC_INVALID );
DECL_GETINFO( UNEXPECTED_KERNEL_MODE_TRAP );
DECL_GETINFO( DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL );
BOOL
AddContextInfoFromStack(
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
);
BOOL
GetTrapFromStackFrameFPO(
PDEBUG_STACK_FRAME StackFrame,
PULONG64 TrapFrame
);
ULONG64
GetImplicitContextInstrOffset( void )
{
ULONG64 IP=0;
switch (TargetMachine) {
case IMAGE_FILE_MACHINE_I386:
IP = GetExpression("@eip");
break;
case IMAGE_FILE_MACHINE_IA64:
IP = GetExpression("@iip");
break;
case IMAGE_FILE_MACHINE_AMD64:
IP = GetExpression("@rip");
break;
}
return IP;
}
BOOL
AnalyzeValue(
PDEBUG_FLR_PARAM_VALUES pCrashParam,
BOOL Verbose,
BOOL ShowFollowup
)
{
CHAR Buffer[MAX_PATH];
CHAR Module[MAX_PATH];
ULONG64 Base;
ULONG64 Address;
BOOL ShowFollowForBufferName = FALSE;
ULONG OutCtl;
if (!Verbose) {
// show only info directly related to faulting driver
if (((pCrashParam->ParamType & 0xf0000000) != DEBUG_FLR_IP) &&
((pCrashParam->ParamType & 0xf0000000) != DEBUG_FLR_THREAD)) {
return FALSE;
}
OutCtl = DEBUG_OUTCTL_IGNORE;
} else {
OutCtl = DEBUG_OUTCTL_AMBIENT;
}
switch (pCrashParam->ParamType) {
default:
dprintf("Unknown type %lx, value %p\n", pCrashParam->ParamType, pCrashParam->Value);
return FALSE;
case DEBUG_FLR_CONTEXT:
if (Verbose) {
dprintf("Context %p\n", pCrashParam->Value);
}
sprintf(Buffer, ".cxr %I64lx", pCrashParam->Value);
g_ExtControl->Execute(OutCtl,Buffer,DEBUG_EXECUTE_DEFAULT);
if (Verbose) {
g_ExtControl->Execute(OutCtl,"k",DEBUG_EXECUTE_DEFAULT);
} else if (ShowFollowup) {
ULONG64 Disp;
// Get symbol for IP in the context
Address = GetImplicitContextInstrOffset();
Buffer[0] = 0;
GetSymbol(Address, Buffer, &Disp);
Module[0] = 0;
g_ExtSymbols->GetModuleByOffset(Address,0, NULL, &Base);
g_ExtSymbols->GetModuleNameString(DEBUG_MODNAME_IMAGE,DEBUG_ANY_ID, Base, &Module[0], sizeof(Module), NULL);
dprintf("Faulting driver %s ( %s+%I64lx )\n",
Module,
Buffer,
Disp);
ShowFollowForBufferName = TRUE;
}
g_ExtControl->Execute(OutCtl,".cxr",DEBUG_EXECUTE_DEFAULT);
break;
case DEBUG_FLR_CURRENT_IRQL:
dprintf("Current IRQL %lx\n", pCrashParam->Value);
break;
case DEBUG_FLR_DEVICE_OBJECT:
dprintf("Device Object %p\n", pCrashParam->Value);
sprintf(Buffer, "!devobj %I64lx", pCrashParam->Value);
g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Buffer,DEBUG_EXECUTE_DEFAULT);
case DEBUG_FLR_DRIVER_OBJECT:
dprintf("Driver Object %p\n", pCrashParam->Value);
if (g_ExtControl) {
sprintf(Buffer, "!drvobj %I64lx", pCrashParam->Value);
g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Buffer,DEBUG_EXECUTE_DEFAULT);
}
case DEBUG_FLR_EXCEPTION_CODE:
dprintf("Unhandled exception %lx\n", pCrashParam->Value);
break;
case DEBUG_FLR_EXCEPTION_PARAMETER1:
dprintf("Exception parameter 1 : %p\n", pCrashParam->Value);
break;
case DEBUG_FLR_EXCEPTION_PARAMETER2:
dprintf("Exception parameter 2 : %p\n", pCrashParam->Value);
break;
case DEBUG_FLR_EXCEPTION_RECORD:
dprintf("Exception Record %p\n", pCrashParam->Value);
if (g_ExtControl) {
sprintf(Buffer, ".exr %I64lx", pCrashParam->Value);
g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Buffer,DEBUG_EXECUTE_DEFAULT);
}
break;
case DEBUG_FLR_POSSIBLE_FAULTING_MODULE:
case DEBUG_FLR_FAULTING_MODULE:
case DEBUG_FLR_IP: {
if (pCrashParam->ParamType == DEBUG_FLR_POSSIBLE_FAULTING_MODULE) {
dprintf("Probably caused by ");
} else {
dprintf("Fault occurred in ");
}
GetSymbol(pCrashParam->Value, Buffer, &Address);
Module[0] = 0;
g_ExtSymbols->GetModuleByOffset(pCrashParam->Value,0, NULL, &Base);
g_ExtSymbols->GetModuleNameString(DEBUG_MODNAME_IMAGE,DEBUG_ANY_ID, Base, &Module[0], sizeof(Module), NULL);
dprintf("driver %s ( %s+%I64lx )\n",
Module,
Buffer,
Address);
ShowFollowForBufferName = TRUE;
break;
}
case DEBUG_FLR_FOLLOWUP_IP: {
GetSymbol(pCrashParam->Value, Buffer, &Address);
ShowFollowForBufferName = TRUE;
break;
}
case DEBUG_FLR_IRP_ADDRESS:
dprintf("Irp %p\n", pCrashParam->Value);
if (g_ExtControl) {
sprintf(Buffer, "!irp %I64lx", pCrashParam->Value);
g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Buffer,DEBUG_EXECUTE_DEFAULT);
}
case DEBUG_FLR_IRP_CANCEL_ROUTINE:
GetSymbol(pCrashParam->Value, Buffer, &Address);
dprintf("Irp cancel routine %p ( %s+%I64lx )\n",
pCrashParam->Value,
Buffer,
Address);
break;
case DEBUG_FLR_MM_INTERNAL_CODE:
dprintf("Mm internal code %lx\n", pCrashParam->Value);
break;
case DEBUG_FLR_POOL_ADDRESS: {
dprintf("Relevant Pool %p\n", pCrashParam->Value);
if (g_ExtControl) {
sprintf(Buffer, "!pool %I64lx", pCrashParam->Value);
g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Buffer,DEBUG_EXECUTE_DEFAULT);
}
break;
}
case DEBUG_FLR_PREVIOUS_IRQL:
dprintf("Previous IRQL %lx\n", pCrashParam->Value);
break;
case DEBUG_FLR_PREVIOUS_MODE:
dprintf("Crash occured in %s mode\n", pCrashParam->Value ? "User" : "Kernel");
break;
case DEBUG_FLR_READ_ADDRESS: {
PSTR PoolRegion = NULL;
PGET_POOL_REGION GetPoolRegion = NULL;
dprintf("Read address %p", pCrashParam->Value);
if (g_ExtControl->GetExtensionFunction(0, "GetPoolRegion", (FARPROC*)&GetPoolRegion) == S_OK) {
if (GetPoolRegion) {
DEBUG_POOL_REGION RegionId;
(*GetPoolRegion)(g_ExtClient, pCrashParam->Value,&RegionId);
PoolRegion = g_PoolRegion[RegionId];
}
}
if (PoolRegion) {
dprintf(", %s\n",PoolRegion);
} else {
dprintf("\n");
}
break;
}
case DEBUG_FLR_TRAP:
if (Verbose) {
dprintf("TrapFrame %p\n", pCrashParam->Value);
}
sprintf(Buffer, ".trap %I64lx", pCrashParam->Value);
g_ExtControl->Execute(OutCtl,Buffer,DEBUG_EXECUTE_DEFAULT);
if (Verbose) {
g_ExtControl->Execute(OutCtl,"k",DEBUG_EXECUTE_DEFAULT);
} else {
ULONG64 Disp;
// Get symbol for IP in the context
Address = GetImplicitContextInstrOffset();
Buffer[0] = 0;
GetSymbol(Address, Buffer, &Disp);
Module[0] = 0;
g_ExtSymbols->GetModuleByOffset(Address,0, NULL, &Base);
g_ExtSymbols->GetModuleNameString(DEBUG_MODNAME_IMAGE,DEBUG_ANY_ID, Base, &Module[0], sizeof(Module), NULL);
dprintf("Faulting driver %s ( %s+%I64lx )\n",
Module,
Buffer,
Disp);
ShowFollowForBufferName = TRUE;
}
g_ExtControl->Execute(OutCtl,".trap",DEBUG_EXECUTE_DEFAULT);
break;
case DEBUG_FLR_TRAP_EXCEPTION:
dprintf("Unhandled exception %lx\n", pCrashParam->Value);
break;
case DEBUG_FLR_TSS:
if (Verbose) {
dprintf("TSS %p\n", pCrashParam->Value);
}
sprintf(Buffer, ".tss %I64lx", pCrashParam->Value);
g_ExtControl->Execute(OutCtl,Buffer,DEBUG_EXECUTE_DEFAULT);
g_ExtControl->Execute(OutCtl,"k",DEBUG_EXECUTE_DEFAULT);
g_ExtControl->Execute(OutCtl,".trap",DEBUG_EXECUTE_DEFAULT);
break;
case DEBUG_FLR_WORK_ITEM:
dprintf("Work Item %p\n", pCrashParam->Value);
break;
case DEBUG_FLR_WORKER_ROUTINE:
GetSymbol(pCrashParam->Value, Buffer, &Address);
dprintf("Wroket routine %p ( %s+%I64lx )\n",
pCrashParam->Value,
Buffer,
Address);
break;
case DEBUG_FLR_WRITE_ADDRESS: {
PSTR PoolRegion = NULL;
PGET_POOL_REGION GetPoolRegion = NULL;
dprintf("Write address %p", pCrashParam->Value);
if (g_ExtControl->GetExtensionFunction(0, "GetPoolRegion", (FARPROC*)&GetPoolRegion) == S_OK) {
if (GetPoolRegion) {
DEBUG_POOL_REGION RegionId;
(*GetPoolRegion)(g_ExtClient, pCrashParam->Value,&RegionId);
PoolRegion = g_PoolRegion[RegionId];
}
}
if (PoolRegion) {
dprintf(", %s\n",PoolRegion);
} else {
dprintf("\n");
}
break;
}
}
if (!ShowFollowForBufferName || !ShowFollowup) {
return 1;
}
EXT_TRIAGE_FOLLOWP FollowUp = NULL;
if (g_ExtControl->GetExtensionFunction(0, "GetTriageFollowupFromSymbol", (FARPROC *)&FollowUp) == S_OK) {
DEBUG_TRIAGE_FOLLOWUP_INFO fInfo;
if (FollowUp) {
fInfo.SizeOfStruct = sizeof(fInfo);
fInfo.OwnerName.Buffer = &Module[0];
fInfo.OwnerName.MaximumLength = sizeof(Module);
if ((*FollowUp)(Buffer, &fInfo)) {
dprintf("Followup : %s\n", fInfo.OwnerName.Buffer);
return 3;
}
}
}
return 1;
}
PDEBUG_FAILURE_ANALYSIS
FAInitMemBlock(
ULONG Size
)
/*
Allocate and initialize memory for FAILUSER_ANALYZER
*/
{
PDEBUG_FAILURE_ANALYSIS CrashInfo;
CrashInfo = (PDEBUG_FAILURE_ANALYSIS) malloc(Size);
if (!CrashInfo) {
return NULL;
}
ZeroMemory(CrashInfo, Size);
CrashInfo->SizeOfHeader = sizeof(DEBUG_FLR_PARAM_VALUES);
CrashInfo->Size = Size;
return CrashInfo;
}
PDEBUG_FAILURE_ANALYSIS
FAReInitMemBlock(
PDEBUG_FAILURE_ANALYSIS pOldBlock,
ULONG Size
)
/*
Allocate and initialize memory for FAILUSER_ANALYZER from pOldBlock
*/
{
PDEBUG_FAILURE_ANALYSIS CrashInfo;
if (pOldBlock && (Size < pOldBlock->Size)) {
return NULL;
}
CrashInfo = (PDEBUG_FAILURE_ANALYSIS) malloc(Size);
if (!CrashInfo) {
return NULL;
}
ZeroMemory(CrashInfo, Size);
if (pOldBlock) {
memcpy(CrashInfo, pOldBlock, pOldBlock->Size);
}
CrashInfo->SizeOfHeader = sizeof(DEBUG_FLR_PARAM_VALUES);
CrashInfo->Size = Size;
return CrashInfo;
}
void
GetCrashInfoFromBugCheck(
PBUGCHECK_ANALYSIS Bc,
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
)
{
*pCrashInfo = NULL;
switch (Bc->Code) {
#define GETINFOCASE(bcname) \
case bcname : \
GetInfoFor##bcname (Bc, pCrashInfo); \
break;
#define DUPINFOCASE(bcname) \
case bcname:
GETINFOCASE( DRIVER_CAUGHT_MODIFYING_FREED_POOL );
DUPINFOCASE( PAGE_FAULT_IN_FREED_SPECIAL_POOL );
DUPINFOCASE( PAGE_FAULT_BEYOND_END_OF_ALLOCATION );
DUPINFOCASE( TERMINAL_SERVER_DRIVER_MADE_INCORRECT_MEMORY_REFERENCE );
DUPINFOCASE( PAGE_FAULT_IN_NONPAGED_AREA );
DUPINFOCASE( DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION );
GETINFOCASE( DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL );
DUPINFOCASE( DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS )
GETINFOCASE( DRIVER_VERIFIER_IOMANAGER_VIOLATION );
DUPINFOCASE( DRIVER_IRQL_NOT_LESS_OR_EQUAL );
GETINFOCASE( IRQL_NOT_LESS_OR_EQUAL );
GETINFOCASE( KMODE_EXCEPTION_NOT_HANDLED );
GETINFOCASE( SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION );
GETINFOCASE( TIMER_OR_DPC_INVALID );
GETINFOCASE( UNEXPECTED_KERNEL_MODE_TRAP );
#undef DUPINFOCASE
#undef GETINFOCASE
default:
break;
}
AddContextInfoFromStack(pCrashInfo);
if (*pCrashInfo) {
(*pCrashInfo)->FailureType = DEBUG_FLR_BUGCHECK;
} else {
}
return;
}
BOOL
AnalyzeCrashInfo(
PBUGCHECK_ANALYSIS Bc,
BOOL Verbose
)
{
PDEBUG_FAILURE_ANALYSIS pCrashInfo;
ULONG ValCount;
BOOL StackShown=FALSE;
if (!Bc) {
dprintf("No analysis without BugCheckInfo\n");
return FALSE;
}
pCrashInfo = NULL;
GetCrashInfoFromBugCheck(Bc, &pCrashInfo);
dprintf("*******************************************************************************\n");
dprintf("* *\n");
dprintf("* Bugcheck Analysis *\n");
dprintf("* *\n");
dprintf("*******************************************************************************\n");
dprintf("\n");
if (Verbose)
{
GetBugCheckDescription(Bc);
PrintBugDescription(Bc);
dprintf("\n\nDetails:\n");
} else {
dprintf("Use !analyzebugcheck -v to get more information.\n\n");
}
if (Bc->Code && !Verbose) {
dprintf("BugCheck %lX, {%1p, %1p, %1p, %1p}\n",
Bc->Code,
Bc->Args[0],Bc->Args[1],Bc->Args[2],Bc->Args[3]);
}
if (!pCrashInfo) {
return FALSE;
}
BOOL FollowUpShown = FALSE;
BOOL DriverShown = FALSE;
if (!Verbose) {
// First show what we thought caused failure
for (ValCount=0; ValCount<pCrashInfo->ParamCount; ValCount++) {
ULONG retval;
if (pCrashInfo->Params[ValCount].ParamType == DEBUG_FLR_POSSIBLE_FAULTING_MODULE) {
if (retval = AnalyzeValue(&pCrashInfo->Params[ValCount], Verbose, !FollowUpShown)) {
DriverShown = TRUE;
FollowUpShown = FollowUpShown || (retval & 2);
if (!Verbose && FollowUpShown) {
// We got the faulting driver
break;
}
}
}
}
// Now check for any other things showing faulting IP
for (ValCount=0; ValCount<pCrashInfo->ParamCount; ValCount++) {
ULONG retval;
if ((((pCrashInfo->Params[ValCount].ParamType & 0xf0000000) == DEBUG_FLR_THREAD) ||
(pCrashInfo->Params[ValCount].ParamType == DEBUG_FLR_IP) ||
(pCrashInfo->Params[ValCount].ParamType == DEBUG_FLR_FAULTING_MODULE) ||
(pCrashInfo->Params[ValCount].ParamType == DEBUG_FLR_POSSIBLE_FAULTING_MODULE)) &&
DriverShown) {
continue;
}
if ((pCrashInfo->Params[ValCount].ParamType & 0xf0000000) == DEBUG_FLR_IP) {
if (retval = AnalyzeValue(&pCrashInfo->Params[ValCount], Verbose, !FollowUpShown)) {
DriverShown = TRUE;
FollowUpShown = FollowUpShown || (retval & 2);
if (!Verbose && FollowUpShown) {
// We got the followup info
break;
}
}
}
}
} else {
for (ValCount=0; ValCount<pCrashInfo->ParamCount; ValCount++) {
ULONG retval;
if (retval = AnalyzeValue(&pCrashInfo->Params[ValCount], Verbose, !FollowUpShown)) {
DriverShown = TRUE;
FollowUpShown = FollowUpShown || (retval & 2);
}
if ((pCrashInfo->Params[ValCount].ParamType & 0xf0000000) == DEBUG_FLR_THREAD) {
StackShown = TRUE;
}
}
}
if (!FollowUpShown) {
EXT_TRIAGE_FOLLOWP FollowUp = NULL;
if (g_ExtControl->GetExtensionFunction(0, "GetTriageFollowupFromSymbol", (FARPROC *)&FollowUp) == S_OK) {
DEBUG_TRIAGE_FOLLOWUP_INFO fInfo;
if (FollowUp) {
CHAR Buffer[100];
fInfo.SizeOfStruct = sizeof(fInfo);
fInfo.OwnerName.Buffer = &Buffer[0];
fInfo.OwnerName.MaximumLength = sizeof(Buffer);
if ((*FollowUp)("default", &fInfo)) {
dprintf("Followup : %s\n", fInfo.OwnerName.Buffer);
}
}
}
}
if (pCrashInfo->DriverNameOffset && Verbose) {
PWCHAR DriverName;
DriverName = (PWCHAR) ((PCHAR) pCrashInfo + pCrashInfo->DriverNameOffset);
dprintf("Driver at fault : %ws\n", DriverName);
}
free (pCrashInfo);
if (!Verbose) {
dprintf("\n");
} else if (!StackShown) {
g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS, NULL, 20,
DEBUG_STACK_FRAME_ADDRESSES |
DEBUG_STACK_COLUMN_NAMES);
}
return TRUE;
}
BOOL
ReadUnicodeString(
ULONG64 Address,
PWCHAR Buffer,
ULONG BufferSize,
PULONG StringSize)
{
UNICODE_STRING64 uStr;
UNICODE_STRING32 uStr32;
ULONG res;
if (!Buffer) {
return FALSE;
}
if (!IsPtr64()) {
if (!ReadMemory(Address, &uStr32, sizeof(uStr32), &res)) {
return FALSE;
}
uStr.Length = uStr32.Length;
uStr.MaximumLength = uStr32.MaximumLength;
uStr.Buffer = (ULONG64) (LONG64) (LONG) uStr32.Buffer;
} else {
if (!ReadMemory(Address, &uStr, sizeof(uStr), &res)) {
return FALSE;
}
}
if (StringSize) {
*StringSize = uStr.Length;
}
uStr.Length = (USHORT) min(BufferSize, uStr.Length);
if (!ReadMemory(uStr.Buffer, Buffer, uStr.Length, &res)) {
return FALSE;
}
return TRUE;
}
BOOL
AddKiBugcheckDriver(
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
)
/*
Add driver name to CrashInfo if a KiBugCheckReferences a valid name
*/
{
ULONG64 KiBugCheckDriver;
WCHAR DriverName[MAX_PATH];
KiBugCheckDriver = GetExpression("NT!KiBugCheckDriver");
if (KiBugCheckDriver) {
ULONG length;
PDEBUG_FAILURE_ANALYSIS NewInfo;
ZeroMemory(DriverName, sizeof(DriverName));
if (!ReadUnicodeString(KiBugCheckDriver, DriverName, sizeof(DriverName), &length)) {
return FALSE;
}
DriverName[sizeof(DriverName) - 1] = 0;
length = wcslen(DriverName);
if (length) {
NewInfo = FAInitMemBlock((*pCrashInfo)->Size + length + sizeof(WCHAR));
if (!NewInfo) {
return FALSE;
}
memcpy(NewInfo, *pCrashInfo, (*pCrashInfo)->Size);
NewInfo->Size = (*pCrashInfo)->Size + length + sizeof(WCHAR);
NewInfo->DriverNameOffset = (*pCrashInfo)->Size;
memcpy((PCHAR) NewInfo + NewInfo->DriverNameOffset, DriverName, length + sizeof(WCHAR));
*pCrashInfo = NewInfo;
return TRUE;
}
}
return FALSE;
}
BOOL
IsFunctionAddr(
ULONG64 IP,
PSTR FuncName
)
// Check if IP is in the function FuncName
{
CHAR Buffer[MAX_PATH], *scan, *FnIP;
ULONG64 Disp;
GetSymbol(IP, Buffer, &Disp);
if (scan = strchr(Buffer, '!')) {
FnIP = scan+1;
while (*FnIP == '_') ++FnIP;
} else {
FnIP = &Buffer[0];
}
return !strncmp(FnIP, FuncName, strlen(FuncName));
}
BOOL
GetFirstNonNtModOnStack(
PDEBUG_STACK_FRAME Stack,
ULONG nFrames,
PDEBUG_STACK_FRAME *pFrame
);
BOOL
IsNtModuleAddress(
ULONG64 Address
);
BOOL
GetFirstTriageableRoutineOnStack(
PDEBUG_STACK_FRAME Stack,
ULONG nFrames,
PDEBUG_STACK_FRAME *pFollowupFrame,
PDEBUG_STACK_FRAME *pNonNtFrame
);
BOOL
GetFollowupInfo(
IN OPTIONAL ULONG64 Addr,
IN OPTIONAL PSTR SymbolName,
OUT OPTIONAL PCHAR *pOwner,
ULONG OwnerSize
);
BOOL
AddContextInfoFromStack(
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
)
//
// Add trap frame, context info from the current stack
//
// Note(kksharma):We only need one of these to get to faulting stack (and only
// one of them should should be available otherwise somethings wrong)
//
{
PDEBUG_FAILURE_ANALYSIS CrashInfo;
ULONG i;
ULONG ContextInfoIndex = -1;
ULONG FaultingAddressIndex = -1;
ULONG64 TrapFrame = 0;
ULONG64 Exr=0, Cxr=0;
DEBUG_STACK_FRAME stk[MAX_STACK_FRAMES];
ULONG frames;
ULONG64 FollowupAddress = 0;
ULONG64 PossibleFaultingAddress = 0;
ULONG64 OriginalFaultingAddress = 0;
ULONG nNewEntries = 0;
CrashInfo = *pCrashInfo;
if (CrashInfo) {
// Check if we have anything to get context from
for (i=0; i<CrashInfo->ParamCount; ++i) {
if ((CrashInfo->Params[i].ParamType == DEBUG_FLR_TRAP) ||
(CrashInfo->Params[i].ParamType == DEBUG_FLR_CONTEXT) ||
(CrashInfo->Params[i].ParamType == DEBUG_FLR_THREAD)) {
// We already have context info
ContextInfoIndex = i;
}
if ((CrashInfo->Params[i].ParamType & 0xf0000000) == DEBUG_FLR_IP) {
// We already have context info
FaultingAddressIndex = i;
OriginalFaultingAddress = CrashInfo->Params[i].Value;
}
if ((ContextInfoIndex != -1) &&
(FaultingAddressIndex != -1)) {
break;
}
}
}
if (ContextInfoIndex == -1) {
//
// Get the current stack and check if we can get tarp frame/context from it
//
ULONG64 ExceptionPointers = 0;
if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &frames ) == S_OK) {
for (i=0; i<frames; ++i) {
#if 0
// Stack walker taskes care of these when walking stack
if (GetTrapFromStackFrameFPO(&stk[i], &TrapFrame)) {
break;
}
// ebp of KiTrap0E is the trap frame
if (IsFunctionAddr(stk[i].InstructionOffset, "KiTrap0E")) {
TrapFrame = stk[i].FrameOffset;
break;
}
#endif
// First arg of KiMemoryFault is the trap frame
if (IsFunctionAddr(stk[i].InstructionOffset, "KiMemoryFault")) {
TrapFrame = stk[i].Params[0];
break;
}
// Third arg of KiMemoryFault is the trap frame
if (IsFunctionAddr(stk[i].InstructionOffset, "KiDispatchException")) {
TrapFrame = stk[i].Params[2];
break;
}
// First argument of this function is EXCEPTION_POINTERS
if (IsFunctionAddr(stk[i].InstructionOffset, "PspUnhandledExceptionInSystemThread")) {
ExceptionPointers = stk[i].Params[0];
break;
}
}
}
if (ExceptionPointers) {
ULONG PtrSize= IsPtr64() ? 8 : 4;
if (!ReadPointer(ExceptionPointers, &Exr) ||
!ReadPointer(ExceptionPointers + PtrSize, &Cxr)) {
// dprintf("Unable to read exception poointers at %p\n", ExcepPtr);
}
}
if (TrapFrame) nNewEntries++;
if (Exr) nNewEntries++;
if (Cxr) nNewEntries++;
}
//
// We are done with context info, now track down faulting module / IP
//
if (FaultingAddressIndex != -1) {
// We are done if this has some followup info available
if (GetFollowupInfo((*pCrashInfo)->Params[FaultingAddressIndex].Value, NULL, NULL, 0)) {
if (nNewEntries) {
goto AddNewEntries;
}
return TRUE;
}
}
//
// Set the context
//
CHAR Command[50] = {0};
if (ContextInfoIndex != -1) {
switch ((*pCrashInfo)->Params[i].ParamType) {
case DEBUG_FLR_CONTEXT:
sprintf(Command, ".cxr %I64lx", (*pCrashInfo)->Params[i].Value);
break;
case DEBUG_FLR_TRAP:
sprintf(Command, ".trap %I64lx", (*pCrashInfo)->Params[i].Value);
break;
case DEBUG_FLR_TSS:
sprintf(Command, ".tss %I64lx", (*pCrashInfo)->Params[i].Value);
break;
case DEBUG_FLR_THREAD:
sprintf(Command, ".thread %I64lx", (*pCrashInfo)->Params[i].Value);
break;
}
if (Command[0]) {
g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE, Command, DEBUG_EXECUTE_NOT_LOGGED);
}
} else {
if (TrapFrame) {
sprintf(Command, ".trap %I64lx", TrapFrame);
} else if (Cxr) {
sprintf(Command, ".cxr %I64lx", Cxr);
}
if (Command[0]) {
g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE, Command, DEBUG_EXECUTE_NOT_LOGGED);
}
}
//
// Get relevant stack
//
if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &frames ) != S_OK) {
frames = 0;
}
//
// Last resort, Go through stack to guess likely culprit
//
CrashInfo = *pCrashInfo;
PDEBUG_STACK_FRAME FollowupFrame = NULL, FirstNonNtFrame = NULL;
GetFirstTriageableRoutineOnStack(&stk[0], frames, &FollowupFrame, &FirstNonNtFrame);
if (Command[0]) {
//
// Clear the set context
//
g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE, ".cxr", DEBUG_EXECUTE_NOT_LOGGED);
}
if (FollowupFrame && FollowupFrame->InstructionOffset) {
FollowupAddress = FollowupFrame->InstructionOffset;
nNewEntries++;
}
//
// If the faulting address we had doesn't seem right, check FollowupFrame
//
if ((FaultingAddressIndex == -1) || !OriginalFaultingAddress ||
IsNtModuleAddress(OriginalFaultingAddress)) {
//
// If we got the FollowupFrame, use it as the possible cause of fault
//
if (FollowupFrame && FollowupFrame->InstructionOffset &&
(FollowupFrame->InstructionOffset != OriginalFaultingAddress)) {
PossibleFaultingAddress = FollowupFrame->InstructionOffset;
nNewEntries++;
}
}
AddNewEntries:
if (nNewEntries) {
PDEBUG_FAILURE_ANALYSIS NewInfo;
if (CrashInfo) {
NewInfo = FAReInitMemBlock(CrashInfo, CrashInfo->Size+ (nNewEntries*sizeof(DEBUG_FLR_PARAM_VALUES)));
free(CrashInfo);
} else {
NewInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + (nNewEntries * sizeof(DEBUG_FLR_PARAM_VALUES)));
}
if (!NewInfo) {
return FALSE;
}
if (PossibleFaultingAddress) {
NewInfo->Params[NewInfo->ParamCount].ParamType = DEBUG_FLR_POSSIBLE_FAULTING_MODULE;
NewInfo->Params[NewInfo->ParamCount].Value = PossibleFaultingAddress;
NewInfo->ParamCount++;
}
if (FollowupAddress) {
NewInfo->Params[NewInfo->ParamCount].ParamType = DEBUG_FLR_FOLLOWUP_IP;
NewInfo->Params[NewInfo->ParamCount].Value = FollowupAddress;
NewInfo->ParamCount++;
}
if (TrapFrame) {
NewInfo->Params[NewInfo->ParamCount].ParamType = DEBUG_FLR_TRAP;
NewInfo->Params[NewInfo->ParamCount].Value = TrapFrame;
ContextInfoIndex = NewInfo->ParamCount;
NewInfo->ParamCount++;
}
if (Exr) {
NewInfo->Params[NewInfo->ParamCount].ParamType = DEBUG_FLR_EXCEPTION_RECORD;
NewInfo->Params[NewInfo->ParamCount].Value = Exr;
NewInfo->ParamCount++;
}
if (Cxr) {
NewInfo->Params[NewInfo->ParamCount].ParamType = DEBUG_FLR_CONTEXT;
NewInfo->Params[NewInfo->ParamCount].Value = Cxr;
ContextInfoIndex = NewInfo->ParamCount;
NewInfo->ParamCount++;
}
*pCrashInfo = NewInfo;
}
return TRUE;
}
void
GetModuleBaseAndOffset(
ULONG64 Address,
PULONG64 Base,
PULONG64 Offset
)
//
// Split the address into module base and offset in module
//
{
CHAR Buffer[MAX_PATH], *scan;
Buffer[0] = 0;
GetSymbol(Address, Buffer, Offset);
*Base = 0;
if (scan = strchr(Buffer, '!')) {
*scan = 0;
*Base = GetExpression(Buffer);
*Offset = Address - *Base;
}
}
BOOL
GetFollowupInfo(
IN OPTIONAL ULONG64 Addr,
IN OPTIONAL PSTR SymbolName,
OUT OPTIONAL PCHAR *pOwner,
ULONG OwnerSize
)
{
static CHAR Buffer[MAX_PATH], Owner[100];
EXT_TRIAGE_FOLLOWP FollowUp = NULL;
if (g_ExtControl->GetExtensionFunction(0, "GetTriageFollowupFromSymbol", (FARPROC *)&FollowUp) == S_OK) {
DEBUG_TRIAGE_FOLLOWUP_INFO fInfo;
if (!SymbolName) {
ULONG64 Disp;
GetSymbol(Addr, Buffer, &Disp);
SymbolName = &Buffer[0];
}
if (FollowUp && *SymbolName) {
fInfo.SizeOfStruct = sizeof(fInfo);
if (pOwner) {
fInfo.OwnerName.Buffer = *pOwner;
fInfo.OwnerName.MaximumLength = (USHORT)OwnerSize;
} else {
fInfo.OwnerName.Buffer = &Owner[0];
fInfo.OwnerName.MaximumLength = sizeof(Owner);
}
if ((*FollowUp)(SymbolName, &fInfo)) {
// This is an interesting routine to followup on
return TRUE;
}
}
}
return FALSE;
}
BOOL
IsNtModuleAddress(
ULONG64 Address
)
{
ULONG64 Disp, KernBase=0;
ULONG KernSize=0,i;
if (g_ExtSymbols->GetModuleByModuleName("nt", 0, &i, &KernBase) == S_OK) {
DEBUG_MODULE_PARAMETERS Params;
if (g_ExtSymbols->GetModuleParameters(1, &KernBase, i, &Params) == S_OK) {
KernSize = Params.Size;
if (((ULONG) (Address - KernBase) < KernSize) &&
(Address >= KernBase)) {
return TRUE;
}
}
}
return FALSE;
}
BOOL
GetFirstTriageableRoutineOnStack(
PDEBUG_STACK_FRAME Stack,
ULONG nFrames,
PDEBUG_STACK_FRAME *pFollowupFrame,
PDEBUG_STACK_FRAME *pNonNtFrame
)
//
// Find and return first routine on stack which can be succesfully traiged
// If no such routine is found, this will default to first non-nt routine
//
{
ULONG i;
CHAR Buffer[MAX_PATH], *scan, Owner[100];
ULONG64 Disp, KernBase=0;
ULONG KernSize=0;
*pFollowupFrame = NULL;
*pNonNtFrame = NULL;
if (g_ExtSymbols->GetModuleByModuleName("nt", 0, &i, &KernBase) == S_OK) {
DEBUG_MODULE_PARAMETERS Params;
if (g_ExtSymbols->GetModuleParameters(1, &KernBase, i, &Params) == S_OK) {
KernSize = Params.Size;
}
}
EXT_TRIAGE_FOLLOWP FollowUp = NULL;
if (g_ExtControl->GetExtensionFunction(0, "GetTriageFollowupFromSymbol", (FARPROC *)&FollowUp) != S_OK) {
FollowUp = NULL;
}
for (i=0; i<nFrames; ++i) {
DEBUG_TRIAGE_FOLLOWUP_INFO fInfo;
Buffer[0] = 0;
GetSymbol(Stack[i].InstructionOffset, Buffer, &Disp);
if (FollowUp && (*pFollowupFrame == NULL)) {
fInfo.SizeOfStruct = sizeof(fInfo);
fInfo.OwnerName.Buffer = &Owner[0];
fInfo.OwnerName.MaximumLength = sizeof(Owner);
if ((*FollowUp)(Buffer, &fInfo)) {
// This is an interesting routine to followup on
*pFollowupFrame = &Stack[i];
}
}
if (*pNonNtFrame == NULL) {
if (KernSize && KernBase) {
if ((KernBase > Stack[i].InstructionOffset) ||
(KernBase + KernSize) <= Stack[i].InstructionOffset) {
*pNonNtFrame = &Stack[i];
}
} else {
if (strncmp(Buffer, "nt", 2)) {
*pNonNtFrame = &Stack[i];
}
}
}
if (*pFollowupFrame && *pNonNtFrame) {
return TRUE;
}
}
if (*pFollowupFrame || *pNonNtFrame) {
return TRUE;
}
return FALSE;
}
BOOL
GetFirstNonNtModOnStack(
PDEBUG_STACK_FRAME Stack,
ULONG nFrames,
PDEBUG_STACK_FRAME *pFrame
)
//
// Find and return first routine on stack which is not from nt module
//
{
ULONG i;
CHAR Buffer[MAX_PATH], *scan;
ULONG64 Disp, KernBase=0;
ULONG KernSize=0;
if (g_ExtSymbols->GetModuleByModuleName("nt", 0, &i, &KernBase) == S_OK) {
DEBUG_MODULE_PARAMETERS Params;
if (g_ExtSymbols->GetModuleParameters(1, &KernBase, i, &Params) == S_OK) {
KernSize = Params.Size;
}
}
for (i=0; i<nFrames; ++i) {
if (KernSize && KernBase) {
if (KernBase <= Stack[i].InstructionOffset &&
(KernBase + KernSize) >= Stack[i].InstructionOffset) {
*pFrame = &Stack[i];
return TRUE;
}
} else {
Buffer[0] = 0;
GetSymbol(Stack[i].InstructionOffset, Buffer, &Disp);
if (strncmp(Buffer, "nt", 2)) {
*pFrame = &Stack[i];
return TRUE;
}
}
}
return FALSE;
}
BOOL
GetFirstNonNtModAddr(
ULONG64 *pAddr
)
//
// Find and return first routine on stack which is not from nt module
//
{
DEBUG_STACK_FRAME stk[MAX_STACK_FRAMES], *Frame;
ULONG nFrames;
if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &nFrames ) == S_OK) {
if (GetFirstNonNtModOnStack(&stk[0], nFrames, &Frame)) {
*pAddr = Frame->InstructionOffset;
return TRUE;
}
}
return FALSE;
}
BOOL
GetTssFromStackFrameFPO(
PDEBUG_STACK_FRAME StackFrame,
PULONG Tss
)
{
if (TargetMachine != IMAGE_FILE_MACHINE_I386) {
return FALSE;
}
if (StackFrame->FuncTableEntry) {
PFPO_DATA FpoData = (PFPO_DATA)StackFrame->FuncTableEntry;
if (FpoData->cbFrame == FRAME_TSS) {
*Tss = (ULONG)StackFrame->Reserved[1];
return TRUE;
}
}
return FALSE;
}
BOOL
GetIPFromTss(
ULONG Tss,
PULONG64 IP
)
{
CHAR Buffer[MAX_PATH];
HRESULT Hr = E_FAIL;
if (g_ExtControl) {
sprintf(Buffer, ".tss %lx", Tss);
g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE,Buffer,DEBUG_EXECUTE_DEFAULT);
Hr = g_ExtRegisters->GetInstructionOffset(IP);
g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE,".thread",DEBUG_EXECUTE_DEFAULT);
}
return Hr == S_OK;
}
BOOL
GetTrapFromStackFrameFPO(
PDEBUG_STACK_FRAME StackFrame,
PULONG64 TrapFrame
)
//
// Check stack frame if it has trap info in it.
// Return TRUE if trap frame address is initialised in TrapFrame
//
{
if (TargetMachine != IMAGE_FILE_MACHINE_I386) {
return FALSE;
}
if (StackFrame->FuncTableEntry) {
PFPO_DATA FpoData = (PFPO_DATA)StackFrame->FuncTableEntry;
if (FpoData->cbFrame == FRAME_TRAP) {
*TrapFrame = StackFrame->Reserved[2];
return TRUE;
}
}
return FALSE;
}
void
GetInfoForKMODE_EXCEPTION_NOT_HANDLED( // (1e)
PBUGCHECK_ANALYSIS Bc,
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
)
/*
*/
{
DEBUG_STACK_FRAME stk[MAX_STACK_FRAMES];
ULONG frames, i;
ULONG64 TrapFrame=0;
ULONG ParamCount = 4;
PDEBUG_FAILURE_ANALYSIS CrashInfo;
#if 0
// This is now grabbed in another generic routine
if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &frames ) == S_OK) {
for (i=0; i<frames; ++i) {
if (IsFunctionAddr(stk[i].InstructionOffset, "KiDispatchException")) {
TrapFrame = stk[i].Params[2];
break;
}
}
}
if (TrapFrame) {
ParamCount++;
}
#endif
CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
if (!CrashInfo) {
*pCrashInfo = NULL;
return;
}
CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
CrashInfo->BugCode = Bc->Code;
// Initialize known parameters
CrashInfo->ParamCount = ParamCount;
CrashInfo->Params[0].ParamType = DEBUG_FLR_EXCEPTION_CODE;
CrashInfo->Params[0].Value = Bc->Args[0];
CrashInfo->Params[1].ParamType = DEBUG_FLR_IP;
CrashInfo->Params[1].Value = Bc->Args[1];
CrashInfo->Params[2].ParamType = DEBUG_FLR_EXCEPTION_PARAMETER1;
CrashInfo->Params[2].Value = Bc->Args[2];
CrashInfo->Params[3].ParamType = DEBUG_FLR_EXCEPTION_PARAMETER2;
CrashInfo->Params[3].Value = Bc->Args[3];
if (TrapFrame) {
CrashInfo->Params[4].ParamType = DEBUG_FLR_TRAP;
CrashInfo->Params[4].Value = TrapFrame;
}
*pCrashInfo = CrashInfo;
return;
}
void
GetInfoForUNEXPECTED_KERNEL_MODE_TRAP( // (7f)
PBUGCHECK_ANALYSIS Bc,
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
)
// It would be good to have TSS or TRAP address as exception parameter
{
DEBUG_STACK_FRAME stk[MAX_STACK_FRAMES];
ULONG frames, i;
ULONG Tss=0;
ULONG64 TrapFrame=0;
ULONG ParamCount = 1;
PDEBUG_FAILURE_ANALYSIS CrashInfo;
#if 0
// unnecessary
if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &frames ) == S_OK) {
for (i=0; i<frames; ++i) {
if (GetTssFromStackFrameFPO(&stk[i], &Tss)) {
break;
}
if (GetTrapFromStackFrameFPO(&stk[i], &TrapFrame)) {
break;
}
if (IsFunctionAddr(stk[i].InstructionOffset, "KiTrap")) {
TrapFrame = stk[i].FrameOffset;
break;
}
}
}
#endif
if (Tss || TrapFrame) {
ParamCount++;
}
CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
if (!CrashInfo) {
*pCrashInfo = NULL;
return;
}
CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
CrashInfo->BugCode = Bc->Code;
// Initialize known parameters
CrashInfo->ParamCount = ParamCount;
CrashInfo->Params[0].ParamType = DEBUG_FLR_TRAP_EXCEPTION;
CrashInfo->Params[0].Value = Bc->Args[0];
if (Tss) {
CrashInfo->Params[1].ParamType = DEBUG_FLR_TSS;
CrashInfo->Params[1].Value = Tss;
} else if (TrapFrame) {
CrashInfo->Params[1].ParamType = DEBUG_FLR_TRAP;
CrashInfo->Params[1].Value = TrapFrame;
}
*pCrashInfo = CrashInfo;
}
void GetInfoForIRQL_NOT_LESS_OR_EQUAL( // (a)
PBUGCHECK_ANALYSIS Bc,
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
)
/*
* Parameters
*
* Parameter 1 Memory referenced
* Parameter 2 IRQL Value
* Parameter 3 0 - Read 1 - Write
* Parameter 4 Address that referenced the memory
*
*
* Special Case
*
* If Parameter 3 is nonzero and equal to Parameter 1, this means that
* a worker routine returned at a raised IRQL.
* In this case:
*
* Parameter 1 Address of work routine
* Parameter 2 IRQL at time of reference
* Parameter 3 Address of work routine
* Parameter 4 Work item
*
*/
{
ULONG ParamCount = 3;
PDEBUG_FAILURE_ANALYSIS CrashInfo;
CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
if (!CrashInfo) {
*pCrashInfo = NULL;
return;
}
*pCrashInfo = CrashInfo;
CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
CrashInfo->BugCode = Bc->Code;
// Initialize known parameters
CrashInfo->ParamCount = ParamCount;
if ((Bc->Args[0] == Bc->Args[2]) && Bc->Args[2]) {
// special case
CrashInfo->Params[0].ParamType = DEBUG_FLR_WORKER_ROUTINE;
CrashInfo->Params[0].Value = Bc->Args[2];
CrashInfo->Params[1].ParamType = DEBUG_FLR_WORK_ITEM;
CrashInfo->Params[1].Value = Bc->Args[3];
CrashInfo->Params[2].ParamType = DEBUG_FLR_CURRENT_IRQL;
CrashInfo->Params[2].Value = Bc->Args[1];
return;
}
CrashInfo->Params[0].ParamType = Bc->Args[2] ? DEBUG_FLR_WRITE_ADDRESS : DEBUG_FLR_READ_ADDRESS;
CrashInfo->Params[0].Value = Bc->Args[0];
CrashInfo->Params[1].ParamType = DEBUG_FLR_CURRENT_IRQL;
CrashInfo->Params[1].Value = Bc->Args[1];
CrashInfo->Params[2].ParamType = DEBUG_FLR_IP;
CrashInfo->Params[2].Value = Bc->Args[3];
return;
}
void GetInfoForSPECIAL_POOL_DETECTED_MEMORY_CORRUPTION( // (c1)
PBUGCHECK_ANALYSIS Bc,
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
)
/*
*/
{
PDEBUG_FAILURE_ANALYSIS CrashInfo;
DEBUG_STACK_FRAME stk[MAX_STACK_FRAMES], *Frame;
ULONG ParamCount = 1;
ULONG frames;
ULONG64 ModBase, Offset;
if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &frames ) == S_OK) {
if (GetFirstNonNtModOnStack(&stk[0], frames, &Frame)) {
GetModuleBaseAndOffset(Frame->InstructionOffset, &ModBase, &Offset);
ParamCount = 3;
}
}
CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
if (!CrashInfo) {
*pCrashInfo = NULL;
return;
}
CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
CrashInfo->BugCode = Bc->Code;
// Initialize known parameters
CrashInfo->ParamCount = ParamCount;
CrashInfo->Params[0].ParamType = DEBUG_FLR_SPECIAL_POOL_CORRUPTION_TYPE;
CrashInfo->Params[0].Value = Bc->Args[3];
if (ParamCount == 3) {
CrashInfo->Params[1].ParamType = DEBUG_FLR_POSSIBLE_FAULTING_MODULE;
CrashInfo->Params[1].Value = ModBase;
CrashInfo->Params[2].ParamType = DEBUG_FLR_POSSIBLE_FAULTING_MODULE_OFFSET;
CrashInfo->Params[2].Value = Offset;
}
*pCrashInfo = CrashInfo;
return;
}
void GetInfoForDRIVER_CAUGHT_MODIFYING_FREED_POOL( // (c6)
PBUGCHECK_ANALYSIS Bc,
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
)
/*
An attempt was made to access freed pool memory. The faulty component is
displayed in the current kernel stack.
Arguments:
Arg1: memory referenced
Arg2: value 0 = read operation, 1 = write operation
Arg3: previous mode.
Arg4: 4.
*/
{
DEBUG_POOL_DATA PoolData;
ULONG ParamCount = 3;
PDEBUG_FAILURE_ANALYSIS CrashInfo;
CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
if (!CrashInfo) {
*pCrashInfo = NULL;
return;
}
CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
CrashInfo->BugCode = Bc->Code;
// Initialize known parameters
CrashInfo->ParamCount = ParamCount;
CrashInfo->Params[0].ParamType = Bc->Args[1] ? DEBUG_FLR_WRITE_ADDRESS : DEBUG_FLR_READ_ADDRESS;
CrashInfo->Params[0].Value = Bc->Args[0];
CrashInfo->Params[1].ParamType = DEBUG_FLR_PREVIOUS_MODE;
CrashInfo->Params[1].Value = Bc->Args[2];
CrashInfo->Params[2].ParamType = DEBUG_FLR_POOL_ADDRESS;
CrashInfo->Params[2].Value = Bc->Args[0]; // This is address in the pool,
// _EFN_GetPoolData will give more info
*pCrashInfo = CrashInfo;
return;
}
void GetInfoForTIMER_OR_DPC_INVALID( // (c7)
PBUGCHECK_ANALYSIS Bc,
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
)
/*
*
* This is issued if a kernel timer or DPC is found somewhere in
* memory where it is not permitted.
*
* Bugcheck Parameters
*
* Parameter 1 0: Timer object 1: DPC object 2: DPC routine
* Parameter 2 Address of object
* Parameter 3 Beginning of memory range checked
* Parameter 4 End of memory range checked
*
* This condition is usually caused by a driver failing to cancel a
* timer or DPC before freeing the memory where it resides.
*
* This returns the address of DPC routine
*/
{
ULONG ParamCount = 0;
PDEBUG_FAILURE_ANALYSIS CrashInfo;
ULONG PtrSize = IsPtr64() ? 8 : 4;
ULONG64 ObjAddress;
ULONG64 ModBase, ModOffset;
CHAR Buffer[MAX_PATH];
ObjAddress = Bc->Args[1];
switch (Bc->Args[0]) {
case 0: //Timer object
ULONG DpcOffsetInTimer;
/*
KTIMER struct:
+0x000 Header :
+0x000 Type : UChar
+0x001 Absolute : UChar
+0x002 Size : UChar
+0x003 Inserted : UChar
+0x004 SignalState : Int4B
+0x008 WaitListHead :
+0x000 Flink : Ptr
+0x004 Blink : Ptr
+0x010 DueTime :
+0x000 LowPart : Uint4B
+0x004 HighPart : Uint4B
+0x000 u :
+0x000 LowPart : Uint4B
+0x004 HighPart : Uint4B
+0x000 QuadPart : Uint8B
+0x018 TimerListEntry :
+0x000 Flink : Ptr
+0x004 Blink : Ptr
+0x020 Dpc : Ptr
*/
if (GetFieldOffset("nt!_KTIMER", "Dpc", &DpcOffsetInTimer)) {
// we don't have types
DpcOffsetInTimer = 0x10 + PtrSize*4;
}
if (!ReadPointer(ObjAddress + DpcOffsetInTimer, &ObjAddress)) {
// fail
break;
}
// Fall thru
case 1:
ULONG DeferredRoutinOffsetInKDPC;
/*
KDPC struct
+0x000 Type : Int2B
+0x002 Number : UChar
+0x003 Importance : UChar
+0x004 DpcListEntry : _LIST_ENTRY
+0x00c DeferredRoutine : Ptr32
*/
if (GetFieldOffset("nt!_KDPC", "DeferredRoutine", &DeferredRoutinOffsetInKDPC)) {
DeferredRoutinOffsetInKDPC = 4 + PtrSize*2;
}
if (!ReadPointer(ObjAddress + DeferredRoutinOffsetInKDPC, &ObjAddress)) {
// fail
break;
}
// Fall thru
case 2:
GetModuleBaseAndOffset(ObjAddress, &ModBase, &ModOffset);
if (ModBase) {
ParamCount = 3;
}
}
ULONG64 Disp;
ULONG NameLen;
ULONG ParamSize;
ParamSize = ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES);
GetSymbol(ObjAddress, Buffer, &Disp);
NameLen = strlen(Buffer) + 1;
NameLen = DWORD_ALIGN(NameLen);
CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamSize + NameLen);
if (!CrashInfo) {
*pCrashInfo = NULL;
return;
}
CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
CrashInfo->BugCode = Bc->Code;
// Initialize known parameters
CrashInfo->ParamCount = ParamCount;
if (ParamCount) {
CrashInfo->Params[0].ParamType = DEBUG_FLR_INVALID_DPC_FOUND;
CrashInfo->Params[0].Value = ObjAddress;
CrashInfo->Params[1].ParamType = DEBUG_FLR_POSSIBLE_FAULTING_MODULE;
CrashInfo->Params[1].Value = ModBase;
CrashInfo->Params[2].ParamType = DEBUG_FLR_POSSIBLE_FAULTING_MODULE_OFFSET;
CrashInfo->Params[2].Value = ModOffset;
CrashInfo->SymNameOffset = sizeof(DEBUG_FAILURE_ANALYSIS) + ParamSize;
strncpy(((char *) CrashInfo) + CrashInfo->SymNameOffset, Buffer, NameLen);
}
*pCrashInfo = CrashInfo;
return;
}
void GetInfoForDRIVER_VERIFIER_IOMANAGER_VIOLATION( // (c9)
PBUGCHECK_ANALYSIS Bc,
PDEBUG_FAILURE_ANALYSIS *pCrashInfo
)
/*
The IO manager has caught a misbehaving driver
*/
{
ULONG ParamCount = 0;
PDEBUG_FAILURE_ANALYSIS CrashInfo;
DEBUG_FLR_PARAM_VALUES Values[6];
ULONG64 Irp, DevObj, DrvObj;
Values[0].ParamType = DEBUG_FLR_DRIVER_VERIFIER_IOMANAGER_VIOLATION_TYPE;
Values[0].Value = Bc->Args[0];
ParamCount = 1;
Irp = DevObj = DrvObj = 0;
if (Bc->Args[ 0 ] == 0x1) {
// "Invalid IRP passed to IoFreeIrp";
Irp = Bc->Args[1];
Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
Values[1].Value = Irp;
ParamCount++;
} else if (Bc->Args[ 0 ] == 0x2) {
// "IRP still associated with a thread at IoFreeIrp";
Irp = Bc->Args[1];
Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
Values[1].Value = Irp;
ParamCount++;
} else if (Bc->Args[ 0 ] == 0x3) {
// "Invalid IRP passed to IoCallDriver";
Irp = Bc->Args[1];
Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
Values[1].Value = Irp;
ParamCount++;
} else if (Bc->Args[ 0 ] == 0x4) {
// "Invalid Device object passed to IoCallDriver";
DevObj = Bc->Args[1];
Values[1].ParamType = DEBUG_FLR_DEVICE_OBJECT;
Values[1].Value = DevObj;
ParamCount++;
} else if (Bc->Args[ 0 ] == 0x5) {
// "Irql not equal across call to the driver dispatch routine"
DevObj = Bc->Args[1];
Values[1].ParamType = DEBUG_FLR_DEVICE_OBJECT;
Values[1].Value = DevObj;
Values[2].ParamType = DEBUG_FLR_PREVIOUS_IRQL;
Values[2].Value = Bc->Args[2];
Values[3].ParamType = DEBUG_FLR_CURRENT_IRQL;
Values[3].Value = Bc->Args[3];
ParamCount+=3;
} else if (Bc->Args[ 0 ] == 0x6) {
// "IRP passed to IoCompleteRequest contains invalid status"
// Param 1 = "the status";
Irp = Bc->Args[2];
Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
Values[1].Value = Irp;
ParamCount++;
} else if (Bc->Args[ 0 ] == 0x7) {
// "IRP passed to IoCompleteRequest still has cancel routine"
Irp = Bc->Args[2];
Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
Values[1].Value = Irp;
Values[2].ParamType = DEBUG_FLR_IRP_CANCEL_ROUTINE;
Values[2].Value = Bc->Args[1];
ParamCount+=2;
} else if (Bc->Args[ 0 ] == 0x8) {
// "Call to IoBuildAsynchronousFsdRequest threw an exce
DevObj = Bc->Args[1];
Values[1].ParamType = DEBUG_FLR_DEVICE_OBJECT;
Values[1].Value = DevObj;
Values[2].ParamType = DEBUG_FLR_IRP_MAJOR_FN;
Values[2].Value = Bc->Args[2];
Values[3].ParamType = DEBUG_FLR_EXCEPTION_CODE;
Values[3].Value = Bc->Args[3];
ParamCount+=3;
} else if (Bc->Args[ 0 ] == 0x9) {
// "Call to IoBuildDeviceIoControlRequest threw an exce
DevObj = Bc->Args[1];
Values[1].ParamType = DEBUG_FLR_DEVICE_OBJECT;
Values[1].Value = DevObj;
Values[2].ParamType = DEBUG_FLR_IOCONTROL_CODE;
Values[2].Value = Bc->Args[2];
Values[3].ParamType = DEBUG_FLR_EXCEPTION_CODE;
Values[3].Value = Bc->Args[3];
ParamCount+=3;
} else if (Bc->Args[ 0 ] == 0x10) {
// "Reinitialization of Device object timer";
DevObj = Bc->Args[1];
Values[1].ParamType = DEBUG_FLR_DEVICE_OBJECT;
Values[1].Value = DevObj;
ParamCount++;
} else if (Bc->Args[ 0 ] == 0x12) {
// "Invalid IOSB in IRP at APC IopCompleteRequest (appe
Values[1].ParamType = DEBUG_FLR_IOSB_ADDRESS;
Values[1].Value = DevObj;
ParamCount++;
} else if (Bc->Args[ 0 ] == 0x13) {
// "Invalid UserEvent in IRP at APC IopCompleteRequest
Values[1].ParamType = DEBUG_FLR_INVALID_USEREVENT;
Values[1].Value = Bc->Args[1];
ParamCount++;
} else if (Bc->Args[ 0 ] == 0x14) {
// "Irql > DPC at IoCompleteRequest";
Irp = Bc->Args[2];
Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
Values[1].Value = Irp;
Values[2].ParamType = DEBUG_FLR_CURRENT_IRQL;
Values[2].Value = Bc->Args[1];
ParamCount+=2;
}
ULONG ParamSize;
ParamSize = ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES);
if (Irp != 0) {
DEBUG_IRP_INFO IrpInfo;
PGET_IRP_INFO GetIrpInfo;
if (g_ExtControl->GetExtensionFunction(0, "GetIrpInfo", (FARPROC*)&GetIrpInfo) == S_OK) {
IrpInfo.SizeOfStruct = sizeof(IrpInfo);
if (GetIrpInfo &&
((*GetIrpInfo)(g_ExtClient,Irp, &IrpInfo) == S_OK)) {
DevObj = IrpInfo.CurrentStack.DeviceObject;
}
}
}
if (DevObj != 0) {
DEBUG_DEVICE_OBJECT_INFO DevObjInfo;
PGET_DEVICE_OBJECT_INFO GetDevObjInfo;
if (g_ExtControl->GetExtensionFunction(0, "GetDevObjInfo", (FARPROC*)&GetDevObjInfo) == S_OK) {
DevObjInfo.SizeOfStruct = sizeof(DEBUG_DEVICE_OBJECT_INFO);
if (GetDevObjInfo &&
((*GetDevObjInfo)(g_ExtClient,DevObj, &DevObjInfo) == S_OK)) {
DrvObj = DevObjInfo.DriverObject;
}
}
}
ULONG64 DriverName = 0;
ULONG DriverNameLen = 0;
if (DrvObj != 0) {
DEBUG_DRIVER_OBJECT_INFO DrvObjInfo;
PGET_DRIVER_OBJECT_INFO GetDrvObjInfo;
if (g_ExtControl->GetExtensionFunction(0, "GetDrvObjInfo", (FARPROC*)&GetDrvObjInfo) == S_OK) {
DrvObjInfo.SizeOfStruct = sizeof(DEBUG_DRIVER_OBJECT_INFO);
if (GetDrvObjInfo &&
((*GetDrvObjInfo)(g_ExtClient,DrvObj, &DrvObjInfo) == S_OK)) {
DriverNameLen = DrvObjInfo.DriverName.Length;
DriverName = DrvObjInfo.DriverName.Buffer;
}
}
}
if (DriverName) {
if (DriverNameLen > 1024) { // sanity check
DriverNameLen = 1024;
}
DriverNameLen = DWORD_ALIGN(DriverNameLen + sizeof(WCHAR));
}
CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamSize + DriverNameLen);
if (!CrashInfo) {
*pCrashInfo = NULL;
return;
}
*pCrashInfo = CrashInfo;
CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
CrashInfo->BugCode = Bc->Code;
// Initialize known parameters
CrashInfo->ParamCount = ParamCount;
memcpy(&CrashInfo->Params, Values, ParamSize);
if (DriverName) {
ULONG result, b;
CrashInfo->DriverNameOffset = sizeof(DEBUG_FAILURE_ANALYSIS) + ParamSize;
b = ReadMemory(DriverName,
((PCHAR) CrashInfo) + CrashInfo->DriverNameOffset,
DriverNameLen,
&result);
if (!b || (result != DriverNameLen)) {
wcscpy((PWCHAR) (((PCHAR) CrashInfo) + CrashInfo->DriverNameOffset),L"Name paged out");
}
*((PWCHAR) (((PCHAR) CrashInfo) + DriverNameLen)) = 0;
}
}
DECL_GETINFO( DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL ) // 0xD5
/*
* Parameters
*
* Parameter 1 Memory referenced
* Parameter 2 0: Read 1: Write
* Parameter 3 Address that referenced memory (if known)
* Parameter 4 Reserved
*
*/
{
ULONG ParamCount;
PDEBUG_FAILURE_ANALYSIS CrashInfo;
ParamCount = Bc->Args[2] ? 3 : 2;
CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
if (!CrashInfo) {
*pCrashInfo = NULL;
return;
}
CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
CrashInfo->BugCode = Bc->Code;
// Initialize known parameters
CrashInfo->ParamCount = ParamCount;
CrashInfo->Params[0].ParamType = Bc->Args[1] ? DEBUG_FLR_WRITE_ADDRESS : DEBUG_FLR_READ_ADDRESS;
CrashInfo->Params[0].Value = Bc->Args[0];
if (Bc->Args[2]) {
CrashInfo->Params[1].ParamType = DEBUG_FLR_IP;
CrashInfo->Params[1].Value = Bc->Args[2];
}
CrashInfo->Params[ParamCount - 1].ParamType = DEBUG_FLR_MM_INTERNAL_CODE;
CrashInfo->Params[ParamCount - 1].Value = Bc->Args[3];
*pCrashInfo = CrashInfo;
AddKiBugcheckDriver(pCrashInfo);
}
DECL_GETINFO( DRIVER_VERIFIER_DETECTED_VIOLATION ) // 0xC4
/*
* Parameters
*
* Parameter 1 subclass of violation
* Parameter 2, 3, 4 vary depending on parameter 1
*
*/
{
ULONG64 DriverNameAddr;
WCHAR DriverName[MAX_PATH];
CHAR RoutineName[MAX_PATH];
ULONG res;
ULONG ParamCount = 0;
PDEBUG_FAILURE_ANALYSIS CrashInfo;
DriverName[0] = 0;
if (DriverNameAddr = GetExpression("ViBadDriver")) {
if (ReadMemory(DriverNameAddr, DriverName, sizeof(DriverName), &res)) {
// We have driver name
}
}
RoutineName[0] = 0;
ULONG64 Addr, Disp;
if (GetFirstNonNtModAddr(&Addr)) {
GetSymbol(Addr, &RoutineName[0], &Disp);
}
}
#undef DECL_GETINFO