This fork extends Paul Toth's WinMD Parser into a full Win32 API code generator producing ready-to-use Delphi units covering the entire Windows.Win32 namespace — functions, records, enums, callbacks, and COM interfaces.
Generator (WinMDGen.exe):
- Two output modes: Alias (compatible with VCL/RTL/third-party) and Native (strict handle-type checking)
- Correct parameter directions (
out/var/[Ref] const) derived from WinMD metadata - Automatic circular unit reference detection and breaking
{$EXTERNALSYM}annotations and XML doc comments from WinMD- Optional delayed DLL loading (
delayedkeyword on all externals; disable with--no-delay)
Parser extensions:
- Parameter direction flags read from the Param metadata table
- Enum
[Ref] constunwrapping, void-buffer out-param detection - Nested/anonymous type inlining, fixed-size array fields
- SQLite metadata DB for offline inspection and cycle analysis
Use --help for all command-line options.
- Windows.Win32.winmd — download from NuGet, extract
Windows.Win32.winmdand place inbin/(or supply the path as the first argument) - SQLite DLL (
sqlite3.dll) — required for the metadata DB. If not already on your system PATH, placesqlite3.dllinbin/. Download from sqlite.org (Precompiled Binaries for Windows, 64-bit DLL).
- Pipeline overview — birds-eye flowchart of the generation pipeline
- Generation modes and nil pointer handling
- Metadata DB schema
- DB population sequence
- Circular reference analysis
The WinMD metadata parser was created by Paul Toth.
This Delphi application allows you to read Windows Metadata (WinMD) files.
You can find some WinMD files in C:\Windows\System32\WinMetadata
But the main purpose of this project is to read Windows.Win32.winmd, the metafile of Win32 API, like CsWin32 but to generate Delphi files.
WinMDGen supports two output modes, selected via the --native command-line flag.
NativeSwappable types (BOOL, HANDLE, HWND, RECT, etc.) are declared as aliases
in Winmd.Winapi.Windows.pas, resolving to the same underlying types that Winapi.Windows
and the Delphi RTL already use:
HWND = Winapi.Windows.HWND // = NativeUInt
HANDLE = THandle // = NativeUInt
BOOL = LongBool
BOOLEAN = ByteBool
RECT = System.Types.TRect // has Width, Height, helpersAll generated units are fully compatible with VCL, RTL, third-party component libraries,
and existing Delphi code that uses Winapi.Windows.
Trade-off: No compile-time distinction between handle types — the compiler accepts
an HFONT where HWND was expected, since both resolve to NativeUInt.
Handle and struct types generate as WinMD record wrappers, exactly as the metadata defines them:
HWND = record Value: NativeUInt; end;
HANDLE = record Value: NativeUInt; end;
HFONT = record Value: NativeUInt; end;
HRESULT = record Value: LONG; end;
RECT = record left, top, right, bottom: INT32; end;Primitive boolean and string-pointer types flatten to Delphi built-ins:
BOOL = LongBool // 32-bit integer, any nonzero = True (matches Win32 BOOL = int)
BOOLEAN = ByteBool // 8-bit integer, any nonzero = True (matches Win32 BOOLEAN = BYTE)
PWSTR = PWideChar
PSTR = PAnsiCharGain: The compiler enforces handle type correctness — passing HFONT where HWND
is expected is a compile error, matching C's typedef-based type checking.
Pitfalls — do not use Native mode if your project:
| Scenario | Problem |
|---|---|
| Uses VCL | TWinControl.Handle returns Winapi.Windows.HWND = NativeUInt, not a record — every SendMessage / PostMessage call fails with E2010 |
| Uses RTL Win32 wrappers | LocalFree, CreateFile, FindFirstFile etc. take Winapi.Windows handle types — type mismatch at every call |
| Uses third-party components | DevExpress, Indy, FastReport and virtually every Delphi component library uses Winapi.Windows types — incompatible |
| Uses COM/OLE | OleCheck, Succeeded, Failed expect HRESULT = Longint; native HRESULT = record breaks all COM interop |
| Uses TRect helpers | Native RECT is a bare record with no Width, Height, Union, Intersect methods |
Native mode is viable only for a self-contained project with no dependency on
Winapi.Windows, VCL, or third-party Delphi components — for example, a pure Win32
service or tool that controls all its type dependencies end-to-end.
Win32 APIs that accept a pointer to an enum (e.g. PFIRMWARE_TYPE, PFILE_COMPRESSION_TYPE)
are generated as [Ref] const parameters — the pointer is stripped and Delphi passes the
value by hidden const reference, matching the C calling convention.
By default the parameter is emitted with its enum type:
function SetupDecompressOrCopyFile(SourceFile: PWSTR; TargetFile: PWSTR;
[Ref] const CompressionType: FILE_COMPRESSION_TYPE): DWORD; stdcall;Delphi 12/13 workaround: a compiler bug (F2084/C2792) fires when a typed
[Ref] const EnumType parameter is nested inside certain expressions. If you hit
this, define WINMD_UNTYPED_ENUM_REFCONST in the WinMDGen project options and
recompile the generator. The output will switch to an untyped form:
function SetupDecompressOrCopyFile(SourceFile: PWSTR; TargetFile: PWSTR;
[Ref] const CompressionType): DWORD; stdcall;The untyped form is fully ABI-compatible and works on all supported Delphi versions.
Both modes correctly distinguish the two Windows boolean types:
| Win32 type | C definition | Delphi mapping | Semantics |
|---|---|---|---|
BOOL |
typedef int (32-bit) |
LongBool |
Any nonzero = True |
BOOLEAN |
typedef BYTE (8-bit) |
ByteBool |
Any nonzero = True |
Using Boolean (strict 0/1) for either would silently misclassify Win32 API return values
that use nonzero values other than 1 to signal success.
Requires Delphi 10 Seattle or later.
cd src
~BuildDEBUG.cmd