Benowin Blanc — Windows through a detective's lens.
(Name credits go to my beloved spouse. ꨄ︎)
A set of command-line tools that parse Windows SDK and PHNT headers via libclang
and let you inspect what's actually in them: struct layouts, field offsets,
enum values, constants, #define macros, and function declarations with full ABI breakdowns — the works.
Think of it as dt + x from WinDbg, but you don't need a debugger running,
and it works against any SDK version, architecture, or PHNT release you throw at it.
bb-viewer — a vanilla TypeScript SPA built with Bun, powered by bb's JSON exports.
Browse 8,000+ functions, 5,000+ types, and 25,000+ constants from the Windows SDK and PHNT headers across all architectures (amd64, x86, arm64, arm) — with ABI layouts, memory visualizations, C expressions, and an interactive type graph. No install required.
![]() |
![]() |
| Dashboard — stats, charts, top types | CreateFileW — ABI layout, metadata, known values |
bb-typesStruct and class layouts, right in your terminal
|
bb-constsConstants, enums, and macro definitions
|
bb-types-tuiInteractive struct browser
|
bb-consts-tuiInteractive constant browser
|
Windows ships with thousands of C/C++ headers (the Windows SDK) that define every struct, enum, constant, macro, and function the OS exposes. Separately, the community-maintained PHNT (Process Hacker NT headers) documents internal structures and syscalls that Microsoft doesn't publish.
bb parses these headers with libclang and gives you fast, searchable, pretty-printed access to all of it — struct layouts, constant values, function ABIs with per-parameter register/stack locations, and more (hell, even TUIs!) — no debugger, no IDE, no digging through .h files by hand.
| **You might want this if you...** - Reverse-engineer Windows internals; - Write kernel drivers or need to check struct layouts across architectures; - Want a quick `dt`-style lookup without spinning up WinDbg; - Need to see exactly which register or stack slot each function parameter lands in; - Need to export struct/constant/function definitions as JSON or SQLite for your own tooling; - Are just curious about what's inside those headers! |
On a Windows host, you will need the following:
- Visual Studio 2019/2022 Build Tools
- LLVM + Clang (libclang.dll) version >=18.1
- Rust 2024 edition
- uv (Python package + project manager — winget install --id=astral-sh.uv -e). Plain Python >=3.10 also works as a fallback.
Afterwards, you may produce the binaries by invoking the following command:
.\update-submodules.ps1 # init + generate submodule data
cargo build --release
The project uses two submodules, managed by update-submodules.ps1:
| Submodule | Purpose | Required for | Setup |
|---|---|---|---|
| phnt | PHNT NT header generation (phnt-single-header) | --phnt flag |
.\update-submodules.ps1 phnt |
| sparse | MSDN API metadata (sparse) — embeds both the SDK and driver datasets | Enriched function views | .\update-submodules.ps1 sparse |
You can update them individually or all at once (.\update-submodules.ps1). Both support env var overrides for custom data:
| Env var | What it does |
|---|---|
BB_PHNT_HEADER |
Use a custom phnt.h instead of generating from the submodule |
BB_SPARSE_SDK_JSON |
Use a pre-generated sdk-api.json instead of running sparse in SDK mode (alias: BB_SPARSE_JSON) |
BB_SPARSE_DRIVER_JSON |
Use a pre-generated driver-docs.json instead of running sparse in driver mode |
BB_NO_CACHE |
Bypass the on-disk AST cache (parse from headers every time) |
After the first bb-funcs / bb-types / bb-consts invocation, the parsed
translation unit is saved (via clang_saveTranslationUnit) under
%LOCALAPPDATA%\bb\ast\<sha256>.ast. Subsequent runs with the same SDK
+ arch + mode load the AST directly and skip libclang's full re-parse.
Typical numbers on this SDK / WDK combo:
| invocation | cold | warm |
|---|---|---|
--mode user --name CreateFileW |
10.3s | 5.5s |
--mode user --name __nonexistent |
4.8s | 3.8s |
--mode kernel --name __nonexistent |
2.4s | 1.3s |
The cache key hashes the synthetic header content, every clang
argument, and the bb-sdk crate version — any change to header config,
SDK install path, target arch, or a bb-sdk release invalidates
automatically. Saved ASTs are ~80 MB; delete the bb/ast/ directory
to nuke them, or set BB_NO_CACHE=1 to bypass per-invocation.
Inspect a struct layout:
bb-types --struct _PEB
Recurse into nested types:
bb-types --phnt --struct _PEB --depth 2
Search for constants by wildcard:
bb-consts --name GENERIC_*
Scope to a specific enum:
bb-consts --enum _MINIDUMP_TYPE
Use Enum::Constant syntax to search within enums:
bb-consts --name "_MINIDUMP_TYPE::*"
Target a different architecture from your host:
bb-types --arch arm64 --struct _CONTEXT
Inspect a function's ABI breakdown:
bb-funcs --name CreateFileW
List exported functions from a header:
bb-funcs --name "Create*" --filter fileapi.h --exported
Filter functions with SQL WHERE clauses:
bb-funcs --where "params > 3 AND return_type = 'BOOL'"
bb-funcs --where "name LIKE '%File%' AND is_exported = true"
Filter kernel/driver functions by IRQL constraint:
bb-funcs --mode kernel --name "Wdf*" --irql "<= DISPATCH_LEVEL"
bb-funcs --mode kernel --irql PASSIVE_LEVEL
Export as JSON or SQLite for your own tooling:
bb-types --arch arm64 --struct _CONTEXT --json
bb-consts --name "PROCESS_*" --json
bb-funcs --name "Nt*" --phnt --json
# or export to SQLite
bb-funcs --name "Create*" --sqlite funcs.db
bb-types --struct "_*" --sqlite types.db
JSON mode in bb-types performs full nested type expansion, producing all matched types alongside their deduplicated referenced_types — regardless of the --depth flag. SQLite exports mirror the same level of detail as JSON.
Typo? Both CLIs suggest close matches:
bb-types --struct _PBE
error: no structs matching '_PBE'
did you mean?
_ABC
_PSP
_PEB
| ### CLI applications | Crate | What it does | | --- | --- | | [`bb-types`](cli/bb-types/) | Inspect struct and class layouts | | [`bb-consts`](cli/bb-consts/) | Inspect constants, enums, and `#define` macros | | [`bb-funcs`](cli/bb-funcs/) | Inspect function declarations with ABI parameter locations | | ### TUI applications | Crate | What it does | | --- | --- | | [`bb-types-tui`](tui/bb-types-tui/) | Interactive struct browser | | [`bb-consts-tui`](tui/bb-consts-tui/) | Interactive constant browser | |
| ### Libraries | Crate | What it does | | --- | --- | | [`bb-arch`](crates/bb-arch/) | Architecture definitions, register sets, and ABI location types | | [`bb-clang`](crates/bb-clang/) | libclang abstractions for types, constants, and functions | | [`bb-sparse`](crates/bb-sparse/) | Embedded Windows API metadata from MSDN (via [sparse](https://github.com/cristeigabriela/sparse)) | | [`bb-sdk`](crates/bb-sdk/) | Windows SDK / PHNT header management | | [`bb-sql`](crates/bb-sql/) | SQL WHERE evaluator + SQLite export | | [`bb-cli`](crates/bb-cli/) | Shared CLI argument definitions | | [`bb-tui`](crates/bb-tui/) | Shared TUI framework on [`ratatui`](https://ratatui.rs/) | | [`bb-shared`](crates/bb-shared/) | Small shared utilities | |
| What it does | |
|---|---|
| bb-viewer | Web explorer for bb's JSON output — functions, types, constants, type graph |
| ### Windows SDK Uses whatever version is available in your Developer Command Prompt environment. User mode — Win32 + COM IDL surface (click to expand) Winsock 2, networking (winhttp, wininet, iphlpapi, dhcpsapi, dns, ldap, snmp, ws2spi, http server, p2p alt, mprapi, rtmv2), security (acl, sddl, wincrypt, bcrypt, ncrypt, authz, wintrust, certenroll, cryptxml, slpublic, msdrm, winbio), shell/UI (shobjidl, shobjidl_core, commctrl, commdlg, uxtheme, dwmapi, magnification, prsht, interactioncontext, winwlx, highlevelmonitorconfigurationapi), GDI helpers (icm, fci), Media Foundation (mfapi, mfidl, mfreadwrite, mfmediaengine), Core Audio (mmdeviceapi, audioclient, audiopolicy), DirectShow (strmif, vfw), Direct3D 11/12 + DXGI 1.6 + d3dcompiler, UI Automation, Bluetooth, XInput, ETW + TraceLogging + TDH, BITS, Windows Update, MSI (msi, msiquery), Task Scheduler, DBGENG (debugger engine), AD (iads, adshlp, dsgetdc), PDH, WIA, WMP, COM+ (azroles, comsvcs, xpsobjectmodel, msinkaut, tom), virtdisk, fltuser (filter manager user side), peerdist, EAP (eapmethodpeerapis), WinUSB, projfs, WER, WMI consumers (wbemcli), Image helpers (traceloggingprovider, perflib), LM DFS, pathcch, traffic, sphelper (excluded — see notes), strsafe, intsafe, ntmsapi, mscat, drt, npapi, wdspxe / wdstpdi / wdsclientapi, roerrorapi, wtsapi32, lmaccess, setupapi, cfgmgr32, wlanapi + ras + rasdlg, powrprof, gpedit, oleauto, appmodel, hbaapi, propvarutil, propsys, traffic, mstcpip, windns, wincred, userenv, ktmw32, sapi, cfapi, diagnosticdataquery, clfsw32, usp10, winevt, **`ntstatus.h`** (full set of `STATUS_*` codes — reached via the `WIN32_NO_STATUS` dance that lets `winnt.h`'s tiny inline subset coexist with `ntstatus.h`'s ~2800 codes), … Kernel mode — NT / WDF / NDIS / streaming (click to expand) Built on the `ntifs.h` umbrella (which transitively pulls `ntddk.h`, `wdm.h`, in the right order so `PEPROCESS` / `PETHREAD` don't redefine). On top of that: `ntstrsafe`, `wsk` (Winsock Kernel), `fltkernel` (minifilter), `aux_klib`, `usb` + `usbdi` + `usbdlib`, **WDF** (`wdf.h`, `wdfusb.h` — KMDF version auto-discovered from `Include/wdf/kmdf//`), **NetAdapterCx** (modern NDIS-on-WDF — also version-discovered from `Include//km/netcx/kmdf/adapter//`), `ndis`, kernel streaming (`ks`, `ksmedia`, `portcls`), HID (`hidpi`, `hidclass`, `hidsdi`, `hidusage`), `swenum`, `pep_x`, `ndischimney`. Plus a direct `ntstatus.h` include as a safety net so `STATUS_*` codes still flow when the WDK kernel-mode headers aren't installed — `ntstatus.h` lives in `shared/` (always shipped with the plain SDK). Excluded (with rationale) Each is documented inline in `crates/bb-sdk/src/winsdk/{user,kernel}.rs`: - **storport.h** — `ntddstor.h` ships without include guards, so it re-runs all `DEFINE_GUID(GUID_DEVINTERFACE_*, …)` and clang flags redefinitions. - **d3dkmthk.h / bdasup.h / fwpsk.h / ksproxy.h** — drag in COM `wtypes.h` whose `VARENUM` / `VT_EMPTY` enumerators collide with the ones `ks.h` already declares. - **video.h / miniport.h** — miniport.h redefines `_QUAD` and `_PROCESSOR_NUMBER` against the kernel core types in scope. - **dbghelp.h (kernel)** — pulls `minidumpapiset.h` which needs user-mode-only types (`VS_FIXEDFILEINFO`, `TIME_ZONE_INFORMATION`). - **wdbgexts.h** — clang resolves `` from `um/` before `km/`, and the user-mode header uses `LPTR` which isn't defined in the kernel chain. - **bthsdpddi.h** — implicit-int header bug. - **dwrite.h / rtworkq.h** — use C++ syntax (`static_cast`, untagged interface names) that won't parse in C mode. - **sphelper.h** — heavy C++ speech-API templates that balloon |