windowskernelwindbgbsod

How can I get the BSOD bugcheck code text description by code/windows API


I can get the bugcheck code and the parameters for one BSOD.

And then I can get the text descriptions from Bug Check Code Reference.

But how can I use some windows API or c++ code to get such text description from the bugcheck code and parameters.

For example, for the bugcheck code 0x9F, how can I get the text as

DRIVER_POWER_STATE_FAILURE (9f) A driver has failed to complete a power IRP within a specific time.

with some windows API or reading from some DLL.

Or to say, how to implement similar function as WinDbg :

1: kd> !analyze -show 0x9F 0x3
DRIVER_POWER_STATE_FAILURE (9f)
A driver has failed to complete a power IRP within a specific time.
Arguments:
Arg1: 0000000000000003, A device object has been blocking an Irp for too long a time
Arg2: 0000000000000000, Physical Device Object of the stack
Arg3: 0000000000000000, nt!TRIAGE_9F_POWER on Win7 and higher, otherwise the Functional Device Object of the stack
Arg4: 0000000000000000, The blocked IRP

I saw there's API like KeGetBugMessageText(), but it's preserved by Windows itself.

Could someone help on this and give some clue or suggestion on that?

Update: The main part of code used to execute command with 'blabb' suggestion:

#pragma comment ( lib ,"dbgeng.lib")
#include <iostream>
#include <dbgeng.h>
#include "StdioOutputCallbacks.h"

//#include <wdbgexts.h>
//WINDBG_EXTENSION_APIS64 ExtensionApis;
StdioOutputCallbacks g_OutputCb;
int main()
{
    IDebugClient* DebugClient = NULL;
    HRESULT Hr = S_OK;

    if ((Hr = DebugCreate(__uuidof(IDebugClient),
       (void**)&DebugClient)) != S_OK) {
       return Hr;
    }
    
    PDEBUG_CONTROL DebugControl;
    if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
       (void**)&DebugControl)) == S_OK) {
       DebugClient->SetOutputCallbacks(&g_OutputCb);

       Hr = DebugClient->OpenDumpFile("C:\\Dev\\Deem\\bug\\dcp938\\MEMORY.DMP");
       if (Hr != S_OK) {
          return Hr;
       }
       
       DebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "!analyze -show 9f 3", DEBUG_EXECUTE_DEFAULT);
       DebugControl->Release();
    }
    // done
    DebugClient->Release();
}
and in outputcallback, kept as the msdn sample:
STDMETHODIMP
StdioOutputCallbacks::Output(
   THIS_
   _In_ ULONG Mask,
   _In_ PCSTR Text
)
{
   UNREFERENCED_PARAMETER(Mask);
   fputs(Text, stdout);
   return S_OK;
}

But the result of the execute "!analyze -show 9f 3"(the content of Text in fputs()) is "No export analyze found". I also try the command ".opendump C:\...MEMORY.DMP;!analyze -show 9f 3", the opendump command executed correctly, the dmp is loaded and got the text output including "For analysis of this file, run !analyze -v", but both "!analyze -v" and "!analyze -show ..." got "No export analyze found". The command without '!' will lead to command resolve error.


Solution

  • Adding another answer as the prior answer is too cluttered and commented.

    contents of directory pre compilation and linking

    F:\bugdesc>ls -lg
    -rw-r--r-- 1 197121 156689581 Aug 17 23:49 MEMORY.DMP                                                                   
    -rw-r--r-- 1 197121       600 Aug 26 01:22 bugdesc.cpp
    -rw-r--r-- 1 197121       109 Aug 19 00:04 complink.bat
    -rw-r--r-- 1 197121      1019 Aug 26 01:21 stdioimpl.h
    

    contents of bat file

    F:\bugdesc>cat complink.bat
    cl  /nologo /W4 /Od  /Zi /EHsc /I"C:\Program Files (x86)\Windows Kits\10\Debuggers\inc" %1.cpp /link /RELEASE
    

    file containing implementation of StdioOutputCallbacks

    F:\bugdesc>cat stdioimpl.h
    #include <windows.h>
    #include <stdio.h>
    #include <dbgeng.h>
    #pragma comment(lib, "dbgeng.lib")
    class StdioOutputCallbacks : public IDebugOutputCallbacks {
    public:
        STDMETHOD(QueryInterface)(THIS_ _In_ REFIID ifid, _Out_ PVOID *iface);
        STDMETHOD_(ULONG, AddRef)(THIS);
        STDMETHOD_(ULONG, Release)(THIS);
        STDMETHOD(Output)(THIS_ IN ULONG Mask, IN PCSTR Text);
    };
    STDMETHODIMP
    StdioOutputCallbacks::QueryInterface(THIS_ _In_ REFIID ifid, _Out_ PVOID *iface){
        *iface = NULL;
        if (IsEqualIID(ifid, __uuidof(IDebugOutputCallbacks))){
            *iface = (IDebugOutputCallbacks *)this;
            AddRef();
            return S_OK;
        }    else    {
            return E_NOINTERFACE;
        }
    }
    STDMETHODIMP_(ULONG)
    StdioOutputCallbacks::AddRef(THIS) { return 1; }
    STDMETHODIMP_(ULONG)
    StdioOutputCallbacks::Release(THIS) { return 0; }
    STDMETHODIMP StdioOutputCallbacks::Output(THIS_ IN ULONG, IN PCSTR Text){
        fputs(Text, stdout);
        return S_OK;
    }
    

    contents of main source file

    F:\bugdesc>cat bugdesc.cpp
    #include "stdioimpl.h"
    //implement proper error handling and release of Interfaces
    void __cdecl main(void)
    {
        IDebugClient *g_Client;
        IDebugControl *g_Control;
        StdioOutputCallbacks g_OutputCb;
        DebugCreate(__uuidof(IDebugClient), (void **)&g_Client);
        g_Client->QueryInterface(__uuidof(IDebugControl), (void **)&g_Control);
        g_Client->SetOutputCallbacks(&g_OutputCb);
        g_Client->SetOutputCallbacks(&g_OutputCb);
        g_Client->OpenDumpFile("F:\\bugdesc\\memory.dmp");
        g_Control->WaitForEvent(0, INFINITE);
        g_Control->Execute(0, "!analyze -show 9f 3", 0);
    }
    

    compiled and linked with vs-community 2017 as x64

    F:\bugdesc>complink.bat bugdesc
    
    F:\bugdesc>cl  /nologo /W4 /Od  /Zi /EHsc /I"C:\Program Files (x86)\Windows Kits\10\Debuggers\inc" bugdesc.cpp /link /RELEASE
    bugdesc.cpp
    

    contents of directory post compilation and linking

    F:\bugdesc>ls -lg
    total 159485
    -rw-r--r-- 1 197121 156689581 Aug 17 23:49 MEMORY.DMP
    -rw-r--r-- 1 197121       600 Aug 26 01:22 bugdesc.cpp
    -rwxr-xr-x 1 197121    406016 Aug 26 01:25 bugdesc.exe
    -rw-r--r-- 1 197121     30072 Aug 26 01:25 bugdesc.obj
    -rw-r--r-- 1 197121   5992448 Aug 26 01:25 bugdesc.pdb
    -rw-r--r-- 1 197121       109 Aug 19 00:04 complink.bat
    -rw-r--r-- 1 197121      1019 Aug 26 01:21 stdioimpl.h
    -rw-r--r-- 1 197121    176128 Aug 26 01:25 vc140.pdb
    

    executing without proper dlls and failure

    F:\bugdesc>bugdesc.exe
    No .natvis files found at C:\WINDOWS\SYSTEM32\Visualizers.
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip 
    Microsoft (R) Windows Debugger Version 10.0.18362.1 AMD64
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip
    Loading Dump File [F:\bugdesc\memory.dmp]
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip
    ***    Type referenced: nt!_MMPTE_TRANSITION                          ***
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip
    For analysis of this file, run !analyze -v
    No export analyze found<<<<<<<<<<<<<<<<<<
    

    copying relevent dlls from windbg installation folder

    F:\bugdesc>copy ..\windbg_dlls\*.* .
    ..\windbg_dlls\dbgeng.dll
    ..\windbg_dlls\dbghelp.dll
    ..\windbg_dlls\ext.dll
    ..\windbg_dlls\symsrv.dll
            4 file(s) copied.
    

    execution and success

    F:\bugdesc>bugdesc.exe
    
    Microsoft (R) Windows Debugger Version 10.0.17763.132 AMD64
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip
    Loading Dump File [F:\bugdesc\memory.dmp]
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip
    *******************************************************************************
    *                                                                             *
    *                        Bugcheck Analysis                                    *
    *                                                                             *
    *******************************************************************************
    
    Use !analyze -v to get detailed debugging information.
    
    BugCheck E2, {0, 0, 0, 0}
    
    Probably caused by : Unknown_Image
     *** Followup info cannot be found !!! Please contact "BADEV"
    
    ---------
    
    DRIVER_POWER_STATE_FAILURE (9f)<<<<<<<<<<<<<<<<<<<<<<<
    A driver has failed to complete a power IRP within a specific time.
    Arguments:
    Arg1: 0000000000000003, A device object has been blocking an Irp for too long a time
    Arg2: 0000000000000000, Physical Device Object of the stack
    Arg3: 0000000000000000, nt!TRIAGE_9F_POWER on Win7 and higher, otherwise the Functional Device Object of the stack
    Arg4: 0000000000000000, The blocked IRP
    xxxxxxxxxxxxxxxxxxxxxxxxxxx snip