#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <cstdio>
#include <string>
#include "dbgeng.h"
class DebugOutput final : public IDebugOutputCallbacks {
public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, void** result) override {
if (id == __uuidof(IUnknown) || id == __uuidof(IDebugOutputCallbacks)) {
*result = this; AddRef(); return S_OK;
}
*result = nullptr; return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef() override { return 1; }
ULONG STDMETHODCALLTYPE Release() override { return 1; }
HRESULT STDMETHODCALLTYPE Output(ULONG, PCSTR value) override {
std::fputs(value, stdout); std::fflush(stdout); return S_OK;
}
};
int wmain(int argc, wchar_t** argv) {
if (argc != 3) { std::fputs("Usage: DumpAnalysis <dump> <image-directory>\n", stderr); return 2; }
const auto engine = LoadLibraryExW(L"dbgeng.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!engine) return 3;
const auto create = reinterpret_cast<HRESULT(WINAPI*)(REFIID, PVOID*)>(GetProcAddress(engine, "DebugCreate"));
IDebugClient4* client{};
if (!create || FAILED(create(__uuidof(IDebugClient4), reinterpret_cast<void**>(&client)))) return 4;
DebugOutput output;
client->SetOutputCallbacks(&output);
IDebugControl* control{};
IDebugSymbols3* symbols{};
client->QueryInterface(__uuidof(IDebugControl), reinterpret_cast<void**>(&control));
client->QueryInterface(__uuidof(IDebugSymbols3), reinterpret_cast<void**>(&symbols));
if (!control || !symbols) return 5;
// Local dump, local binaries, no symbol-server upload or dump submission.
symbols->SetSymbolPath("");
symbols->SetImagePathWide(argv[2]);
auto hr = client->OpenDumpFileWide(argv[1], 0);
if (SUCCEEDED(hr)) hr = control->WaitForEvent(DEBUG_WAIT_DEFAULT, 30000);
if (FAILED(hr)) { std::fprintf(stderr, "Open/wait failed: %08lx\n", hr); return 6; }
control->Execute(DEBUG_OUTCTL_THIS_CLIENT, ".ecxr; r; kv 40; lm; ~* k 6", DEBUG_EXECUTE_DEFAULT);
client->EndSession(DEBUG_END_PASSIVE);
symbols->Release(); control->Release(); client->Release();
return 0;
}
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <cstdio>
#include <string>
#include "dbgeng.h"
class DebugOutput final : public IDebugOutputCallbacks {
public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, void** result) override {
if (id == __uuidof(IUnknown) || id == __uuidof(IDebugOutputCallbacks)) {
*result = this; AddRef(); return S_OK;
}
*result = nullptr; return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef() override { return 1; }
ULONG STDMETHODCALLTYPE Release() override { return 1; }
HRESULT STDMETHODCALLTYPE Output(ULONG, PCSTR value) override {
std::fputs(value, stdout); std::fflush(stdout); return S_OK;
}
};
int wmain(int argc, wchar_t** argv) {
if (argc != 3) { std::fputs("Usage: DumpAnalysis <dump> <image-directory>\n", stderr); return 2; }
const auto engine = LoadLibraryExW(L"dbgeng.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!engine) return 3;
const auto create = reinterpret_cast<HRESULT(WINAPI*)(REFIID, PVOID*)>(GetProcAddress(engine, "DebugCreate"));
IDebugClient4* client{};
if (!create || FAILED(create(__uuidof(IDebugClient4), reinterpret_cast<void**>(&client)))) return 4;
DebugOutput output;
client->SetOutputCallbacks(&output);
IDebugControl* control{};
IDebugSymbols3* symbols{};
client->QueryInterface(__uuidof(IDebugControl), reinterpret_cast<void**>(&control));
client->QueryInterface(__uuidof(IDebugSymbols3), reinterpret_cast<void**>(&symbols));
if (!control || !symbols) return 5;
// Local dump, local binaries, no symbol-server upload or dump submission.
symbols->SetSymbolPath("");
symbols->SetImagePathWide(argv[2]);
auto hr = client->OpenDumpFileWide(argv[1], 0);
if (SUCCEEDED(hr)) hr = control->WaitForEvent(DEBUG_WAIT_DEFAULT, 30000);
if (FAILED(hr)) { std::fprintf(stderr, "Open/wait failed: %08lx\n", hr); return 6; }
control->Execute(DEBUG_OUTCTL_THIS_CLIENT, ".ecxr; r; kv 40; lm; ~* k 6", DEBUG_EXECUTE_DEFAULT);
client->EndSession(DEBUG_END_PASSIVE);
symbols->Release(); control->Release(); client->Release();
return 0;
}