Skip to content

Instantly share code, notes, and snippets.

@Kreijstal
Created June 5, 2025 13:01
Show Gist options
  • Save Kreijstal/38080e9b6aaa7b76846d628cce4eb533 to your computer and use it in GitHub Desktop.
Save Kreijstal/38080e9b6aaa7b76846d628cce4eb533 to your computer and use it in GitHub Desktop.
let us print debug messages.
//gcc KernelDbgPrint.c -o KernelDbgPrint.exe -lkernel32 -luser32
#include <windows.h>
#include <stdio.h> // For printf, fprintf, getchar
#include <string.h> // For strncpy_s if available, or strncpy + manual null termination
// Names of the synchronization objects
#define BUFFER_NAME L"DBWIN_BUFFER"
#define DATA_READY_EVENT_NAME L"DBWIN_DATA_READY"
#define BUFFER_READY_EVENT_NAME L"DBWIN_BUFFER_READY"
// Shared memory buffer structure (simplified)
// The first DWORD is the ProcessID, followed by the null-terminated string.
#define SHARED_MEM_SIZE 4096 // Standard size for DBWIN_BUFFER
HANDLE hBufferMapping = NULL;
LPVOID pBufferView = NULL;
HANDLE hDataReadyEvent = NULL;
HANDLE hBufferReadyEvent = NULL;
// Global flag to signal the monitoring thread to stop
volatile BOOL g_bRunning = TRUE;
void Cleanup() {
if (pBufferView) {
UnmapViewOfFile(pBufferView);
pBufferView = NULL;
}
if (hBufferMapping) {
CloseHandle(hBufferMapping);
hBufferMapping = NULL;
}
if (hDataReadyEvent) {
CloseHandle(hDataReadyEvent);
hDataReadyEvent = NULL;
}
if (hBufferReadyEvent) {
CloseHandle(hBufferReadyEvent);
hBufferReadyEvent = NULL;
}
printf("Cleanup complete.\n");
}
BOOL InitializeDebugMonitor() {
// 1. Create/Open the "DBWIN_BUFFER_READY" event.
hBufferReadyEvent = CreateEventW(NULL, FALSE, FALSE, BUFFER_READY_EVENT_NAME);
if (!hBufferReadyEvent) {
fprintf(stderr, "Failed to create/open DBWIN_BUFFER_READY event. Error: %lu\n", GetLastError());
return FALSE;
}
// 2. Create/Open the "DBWIN_DATA_READY" event.
hDataReadyEvent = CreateEventW(NULL, FALSE, FALSE, DATA_READY_EVENT_NAME);
if (!hDataReadyEvent) {
fprintf(stderr, "Failed to create/open DBWIN_DATA_READY event. Error: %lu\n", GetLastError());
CloseHandle(hBufferReadyEvent);
return FALSE;
}
// 3. Create/Open the shared memory file mapping "DBWIN_BUFFER".
hBufferMapping = CreateFileMappingW(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
SHARED_MEM_SIZE,
BUFFER_NAME
);
if (!hBufferMapping) {
fprintf(stderr, "Failed to create/open file mapping object DBWIN_BUFFER. Error: %lu\n", GetLastError());
CloseHandle(hDataReadyEvent);
CloseHandle(hBufferReadyEvent);
return FALSE;
}
// 4. Map the shared memory.
pBufferView = MapViewOfFile(
hBufferMapping,
FILE_MAP_READ,
0,
0,
SHARED_MEM_SIZE
);
if (!pBufferView) {
fprintf(stderr, "Failed to map view of file. Error: %lu\n", GetLastError());
CloseHandle(hBufferMapping);
CloseHandle(hDataReadyEvent);
CloseHandle(hBufferReadyEvent);
return FALSE;
}
printf("Debug monitor initialized. Waiting for messages...\n");
// Signal that the buffer is ready for the first message.
SetEvent(hBufferReadyEvent);
return TRUE;
}
// Thread function for monitoring debug messages
DWORD WINAPI DebugMonitorThreadFunc(LPVOID lpParam) {
UNREFERENCED_PARAMETER(lpParam); // Unused parameter
while (g_bRunning) {
DWORD waitResult = WaitForSingleObject(hDataReadyEvent, 1000); // Timeout after 1 sec
if (!g_bRunning) { // Check flag again after wait
break;
}
if (waitResult == WAIT_OBJECT_0) {
DWORD processId = *((DWORD*)pBufferView);
char* messageAnsi = (char*)pBufferView + sizeof(DWORD);
// Create a local buffer to safely copy and null-terminate the string
char safeMessage[SHARED_MEM_SIZE - sizeof(DWORD)];
// strncpy_s is safer if available (MSVC)
#if defined(_MSC_VER)
strncpy_s(safeMessage, sizeof(safeMessage), messageAnsi, _TRUNCATE);
#else
// Standard C strncpy (less safe, manual termination needed)
strncpy(safeMessage, messageAnsi, sizeof(safeMessage) - 1);
safeMessage[sizeof(safeMessage) - 1] = '\0'; // Ensure null termination
#endif
printf("[PID: %lu] %s", processId, safeMessage);
// DbgPrint messages often don't include a newline by default.
// If the last character is not a newline, and the message is not empty, print one.
size_t len = strlen(safeMessage);
if (len > 0 && safeMessage[len - 1] != '\n') {
printf("\n");
}
fflush(stdout); // Ensure output is displayed immediately
SetEvent(hBufferReadyEvent);
} else if (waitResult == WAIT_TIMEOUT) {
// Timeout occurred, loop again to check g_bRunning
continue;
} else {
fprintf(stderr, "WaitForSingleObject on DBWIN_DATA_READY failed. Error: %lu\n", GetLastError());
g_bRunning = FALSE; // Stop monitoring on error
break;
}
}
printf("Debug monitor loop stopped.\n");
return 0; // Return value for the thread
}
int main() {
HANDLE hMonitorThread = NULL;
if (!InitializeDebugMonitor()) {
fprintf(stderr, "Failed to initialize debug monitor. Exiting.\n");
Cleanup();
return 1;
}
hMonitorThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
DebugMonitorThreadFunc, // thread function name
NULL, // argument to thread function
0, // use default creation flags
NULL); // returns the thread identifier (we don't need it)
if (hMonitorThread == NULL) {
fprintf(stderr, "Failed to create monitor thread. Error: %lu\n", GetLastError());
Cleanup();
return 1;
}
printf("Press Enter to stop monitoring...\n");
getchar(); // Wait for user to press Enter
g_bRunning = FALSE; // Signal the monitor thread to stop
// Wait for the monitor thread to finish
if (hMonitorThread != NULL) {
WaitForSingleObject(hMonitorThread, INFINITE);
CloseHandle(hMonitorThread);
}
Cleanup();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment