Holy cow, I wrote a book!
Okay, so there are
all these different ways you can specify
what version of the Windows header files you want.†
#define WINVER 0x0400
#define _WIN32_WINNT 0x0400
#define _WIN32_WINDOWS 0x0400
#define _WIN32_IE 0x0400
Let's take them in order.
The WINVER symbol is the earliest one.
That's the symbol that 16-bit Windows used to control the
versioning of its header files,
and its use carried forward into the 32-bit header files,
presumably from the people who did the initial conversion
of the header files to 32-bit and who grew up with the
This symbol is still used a lot in the header files that
can trace their origins to 16-bit Windows, such as
The _WIN32_WINNT symbol came next.
I'm not sure where it came from, but from its name
it probably was invented by the Windows NT team
in order to allow them to block off sections of the
header file that are available only in the Windows NT implementation
Don't forget that in the early days, there was also Win32s,
a subset of Win32 that could run on 16-bit Windows 3.1.
The single WINVER symbol wasn't enough to
specify exactly what you wanted to be compatible with.
For example, a function available only in Windows NT 3.1
would be guarded with #if _WIN32_WINNT >= 0x030A
so that programs that wanted to run on Win32s could set
_WIN32_WINNT to zero and keep that function off-limits.
#if _WIN32_WINNT >= 0x030A
Similarly, both Windows 95 and Windows NT 4 identified
themselves as Windows major version 4, so
the WINVER symbol was insufficient to distinguish them.
Functions that existed in Windows NT 4 but
not in Window 95 were therefore guarded with _WIN32_WINNT.
On the other hand, there were also functions that were first introduced
in Windows 95 and did not exist in
the original version of Windows NT 4.
The _WIN32_WINDOWS symbol let you specify that
you wanted access to stuff that was new for Windows 95 and
which would also be ported to Windows NT 4 and future
versions of Windows NT.
The next symbol in this progression is
_WIN32_IE, which lets you specify what version
of Internet Explorer you require to be installed on the system.
This was more important back in the days when Internet Explorer
included updates to selected operating system components.
For example, Internet Explorer 4 came not only with an
updated comctl32.dll but also a new
shell32.dll that gave you Active Desktop.
(Wow, remember Active Desktop?
That was when everybody thought that HTML
was going to take over the world and people would write
entire applications in HTML.
People are still trying.)
And history repeated itself:
We saw it before when we tried to puzzle out why
some functions return
NULL while others return INVALID_HANDLE_VALUE.
Each time somebody added a new feature to Windows and had to
add an #ifdef guard,
it was pretty much a toss-up whether they would use
Once Internet Explorer stopped including updates to shell components,
_WIN32_IE fell into the "toss-up" bucket as well.
In an attempt to make some sense out of this disaster,
the SDK and DDK teams came up with a new plan for Windows Vista
There's now just one symbol you define to specify your minimum
target operating system: NTDDI_VERSION.
Once you set that, all the other symbols are set automatically
to the appropriate values for your target operating system.
(And no, I don't know what the letters NTDDI stand for,
though there is one
With any luck,
everybody wll standardize on
NTDDI_VERSION and this article will become one of those
"quaint historical novelties" like all the ones about
Just "a little story about what people had to do back in the
crazy days of the early 21st century.
Boy am I glad we don't have to worry about that any more!"
I'd appreciate it if people would extend me the courtesy of not
stepping on my announced topic.
(I wonder if these are the same people who go to a comedy show
and shout out the punch lines before the performer gets to say them.)
I did say that I would pick up the topic today, after all.
If you really want to steal my topic,
at least be polite enough to post your essay on your own blog.
†This list is not intended to be comprehensive.