Skip to content

Instantly share code, notes, and snippets.

@pavel-a
Created April 10, 2018 21:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pavel-a/1b00e87831e40cab6e69b9d4d2011a14 to your computer and use it in GitHub Desktop.
Save pavel-a/1b00e87831e40cab6e69b9d4d2011a14 to your computer and use it in GitHub Desktop.
Print to the Windows kernel debugger from usermode
////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Print to kernel debugger from user mode
///
/// Usage:
/// #include "winKdprintUm.h"
///
/// ULONG getKdPrintPointers(void);
///
/// ULONG KdPrintEx((ULONG ComponentId, ULONG Level, PCHAR Format, ...));
/// ULONG KdPrintExWithPrefix((PCHAR prefix, ULONG ComponentId, ULONG Level, PCHAR Format, ...));
///
/// ULONG DbgPrintEx(ULONG ComponentId, ULONG Level, PCHAR Format, ...);
/// ULONG DbgPrintExWithPrefix(PCHAR prefix, ULONG ComponentId, ULONG Level, PCHAR Format, ...);
///
/// ULONG vDbgPrintEx(IN ULONG ComponentId, ULONG Level, PCHAR Format, va_list arglist);
/// ULONG vDbgPrintExWithPrefix(PCHAR pref, ULONG ComponentId, ULONG Level, PCCH Fmt, va_list arglist);
///
/// Return value is NTSTATUS (0=success)
///
/// This module can be compiled as either C or C++
////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 // minimal platform: WinXP
#endif
#if (_WIN32_WINNT < 0x0501)
#error "No, this won't work on win2k"
#endif
#include <windows.h>
#include "WinKdPrintUm.h" /*self*/
// NOTE: all (...) variants are __cdecl. All (va_list) variants are __stdcall.
ULONG ( __cdecl *f_DbgPrintEx)(ULONG ComponentId, ULONG Level, PCHAR Format, ...) = 0;
ULONG ( __stdcall *f_vDbgPrintExWithPrefix)(IN PCCH pref, ULONG ComponentId, ULONG Level, PCCH Fmt, va_list arglist) = 0;
ULONG ( __stdcall *f_vDbgPrintEx)(IN ULONG ComponentId, IN ULONG Level, IN PCCH Format, IN va_list arglist) = 0;
extern ULONG g_KdPrintAvailable = 0;
extern
ULONG __cdecl DbgPrintExWithPrefix(IN PCCH pref, ULONG ComponentId, ULONG Level, PCCH Fmt, ...)
{
ULONG n;
va_list arglist;
va_start( arglist, Fmt );
n = f_vDbgPrintExWithPrefix( pref, ComponentId, Level, Fmt, arglist );
va_end( arglist );
return n;
}
//-- Get the kernel debug print interfaces ---
// Note: ntdll.dll is always present,
// so we use GetModuleHandle instead of LoadLibrary, no "release" action is needed.
int getKdPrintPointers_i(void)
{
FARPROC f;
HMODULE hm = GetModuleHandle(TEXT("ntdll.dll"));
if( !hm ) return 0;
f = GetProcAddress( hm, "DbgPrintEx" );
if( !f ) return 0;
memcpy( &f_DbgPrintEx, &f, sizeof(f) );
f = GetProcAddress( hm, "vDbgPrintExWithPrefix" );
if( !f ) return 0;
memcpy( &f_vDbgPrintExWithPrefix, &f, sizeof(f) );
f = GetProcAddress( hm, "vDbgPrintEx" );
if( !f ) return 0;
memcpy( &f_vDbgPrintEx, &f, sizeof(f) );
return 1;
}
extern
ULONG getKdPrintPointers(void)
{
if ( !g_KdPrintAvailable ) {
g_KdPrintAvailable = getKdPrintPointers_i();
}
return g_KdPrintAvailable;
}
#if __cplusplus
} // extern "C"
#endif //c++
#ifdef _WITH_TESTMAIN
int _tmain(int argc, _TCHAR* argv[])
{
getKdPrintPointers();
if( !isKdPrintAvailable() ) return 1;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "test %d\n", 42);
DbgPrintExWithPrefix("myprefix:", DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "test2 %d\n", 84);
return 0;
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Print to kernel debugger from user mode
///
/// Usage:
///
/// ULONG getKdPrintPointers(void);
/// int isKdPrintAvailable(void);
///
/// ULONG KdPrintEx((ULONG ComponentId, ULONG Level, PCHAR Format, ...));
/// ULONG KdPrintExWithPrefix((PCHAR prefix, ULONG ComponentId, ULONG Level, PCHAR Format, ...));
///
/// ULONG DbgPrintEx(ULONG ComponentId, ULONG Level, PCHAR Format, ...);
/// ULONG DbgPrintExWithPrefix(PCHAR prefix, ULONG ComponentId, ULONG Level, PCHAR Format, ...);
///
/// ULONG vDbgPrintEx(IN ULONG ComponentId, ULONG Level, PCHAR Format, va_list arglist);
/// ULONG vDbgPrintExWithPrefix(PCHAR pref, ULONG ComponentId, ULONG Level, PCCH Fmt, va_list arglist);
///
/// Return value is NTSTATUS (0=success)
///
/// * Single debug print is limited to 512 chars, using any variant.
/// * Debug print filters are set in HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter
/// In kernel debugger: dd nt!Kd_XXXX_Mask, where XXXX is the desired component name.
/// Typically the component name to use is IHVDRIVER on NT6 or DEFAULT on NT5
/// * For more details see WDK docum: _Reading and Filtering Debugging Messages_.
////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
// Include windows.h here to get the types ...
//#include <Windows.h>
#ifndef _NO_KDPRINT_FILTER_DEFS
// Borrow some filter defs from DDK/WDK dpfilter.h
enum {
DPFLTR_ERROR_LEVEL = 0,
DPFLTR_WARNING_LEVEL = 1,
DPFLTR_TRACE_LEVEL = 2,
DPFLTR_INFO_LEVEL = 3,
DPFLTR_MASK = 0x8000000,
};
enum {
DPFLTR_IHVDRIVER_ID = 77,
DPFLTR_SYSTEM_ID = 0,
DPFLTR_VERIFIER_ID = 93,
DPFLTR_APPCOMPAT_ID = 123,
};
#endif /* _NO_KDPRINT_FILTER_DEFS */
#if __cplusplus
extern "C" {
#endif
// NOTE: all variadic (...) wrappers are __cdecl. All (va_list) functions in ntdll are __stdcall.
extern ULONG ( __cdecl *f_DbgPrintEx)(ULONG ComponentId, ULONG Level, PCHAR Format, ...);
extern ULONG ( __stdcall *f_vDbgPrintExWithPrefix)(IN PCCH pref, ULONG ComponentId, ULONG Level, PCCH Fmt, va_list arglist);
extern ULONG ( __stdcall *f_vDbgPrintEx)(IN ULONG ComponentId, IN ULONG Level, IN PCCH Format, IN va_list arglist);
extern ULONG __cdecl DbgPrintExWithPrefix(IN PCCH pref, ULONG ComponentId, ULONG Level, PCCH Fmt, ...);
extern ULONG g_KdPrintAvailable;
extern ULONG getKdPrintPointers(void);
__inline int isKdPrintAvailable(void) { return g_KdPrintAvailable; }
#define DbgPrintEx f_DbgPrintEx
#define vDbgPrintEx f_vDbgPrintEx
#define vDbgPrintExWithPrefix f_vDbgPrintExWithPrefix
#define KdPrintEx(_varlist_) DbgPrintEx _varlist_
#define KdPrintExWithPrefix(_varlist_) DbgPrintExWithPrefix _varlist_
#if __cplusplus
} // extern "C"
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment