Where did WIN32_LEAN_AND_MEAN come from?


Commenter asdf wonders where WIN32_LEAN_AND_MEAN came from.

The WIN32_LEAN_AND_MEAN symbol was introduced in the Windows 95 time frame as a way to exclude a bunch of Windows header files when you include windows.h. You can take a look at your windows.h file to see which ones they are.

The symbol was added as part of the transition from 16-bit Windows to 32-bit Windows. The 16-bit windows.h header file didn't include all of those header files, and defining WIN32_LEAN_AND_MEAN brought you back to the 16-bit Windows philosophy of a minimal set of header files for writing a bare-bones Windows program. This appeased the programmers who liked to micro-manage their header files, and it was a big help because, at the time the symbol was introduced, precompiled header files were not in common use. As I recall, on a 50MHz 80486 with 8MB of memory, switching to WIN32_LEAN_AND_MEAN shaved three seconds off the compile time of each C file. When your project consists of 20 C files, that's a whole minute saved right there.

Moore's Law and precompiled headers have conspired to render the WIN32_LEAN_AND_MEAN symbol relative useless. It doesn't really save you much any more. But at one point, it did.

Comments (25)
  1. John says:

    The only problem I’ve run into is that windows.h includes winsock.h if you don’t define that symbol; this creates havoc if you want to include winsock2.h, as everything gets redefined.

  2. Vilx- says:

    The funny thing is that it is still a part of the default C++ Windows application template in Visual Studio.

  3. porter says:

    > It doesn’t really save you much any more.

    It does save you pollution of the C namespace which assists in writing portable code.

  4. Adrian says:

    >It does save you pollution of the C namespace which assists in writing portable code.

    +1.  And not just the language namespace, but the preprocessor’s macro namespace as well.

  5. Random832 says:

    I think the assumption is that someone who includes windows.h at all doesn’t have writing portable code as a priority.

  6. Neil (SM) says:

    If the goal is to write portable code, you’ve already lost when you started adding WIN32 headers.

  7. Niels says:

    I’ve also experienced code that broke in compilation when WIN32_LEAN_AND_MEAN was undefined, because some header defined some symbol with an excessively generic name.

    Related, many MSDN pages tell that a function is declared in some specific header file but then notes “include windows.h” afterwards. Is that a suggestion, recommendation or requirement (for compatibility)?

    [It’s saying “This header file comes along for the ride when you include windows.h, so just include windows.h and call it good.” -Raymond]
  8. Gabe says:

    Most portable software I’ve encountered runs on Windows as well as other OSes. Firefox is the first thing that comes to mind, but there are thousands of other examples.

  9. Starfish says:

    I learnt the hard way that GDI+ doesn’t work if you define WIN32_LEAN_AND_MEAN. Not a fun error to track down on account of it making no sense whatsoever why it should make a difference.

    You live and learn!

  10. Nick Bastin says:

    It does save you pollution of the C namespace which assists in writing portable code.

    +1.  Spewing conflicting symbols all over my cross-platform code always makes me happy.

  11. Random832 says:

    Why is your cross-platform code including windows.h? Shouldn’t your windows code be in the file that includes windows.h and your cross-platform code be in some other file?

  12. porter says:

    > Why is your cross-platform code including windows.h? Shouldn’t your windows code be in the file that includes windows.h and your cross-platform code be in some other file?

    There are many ways to write portable code, for example WINSOCK requires windows.h but that does not mean all winsock calls have to be in another file.

    Perhaps Windows programmers are not aware of the phrase "mechanism not policy".

  13. porter says:

    > you’ve already lost when you started adding WIN32 headers

    Perhaps you have not heard of "#ifdef".

  14. porter says:

    > Have you ever wondered how much of your life you’ve spent staring at an hourglass cursor?

    I don’t remember an hour glass using MSC 7.0 in a DPMI DOS console window.

  15. Hourglasses? Real Programmers (TM) can remember getting their fan-fold printed compile results from the data center the next morning.

  16. Worf says:

    The winsock one gets me every time – you tend to want winsock2.h always these days, but forgetting WIN32_LEAN_AND_MEAN always meant duplicated symbols.

    I always wondered why no one hasn’t consolidated the two. It’s not like that parameters to socket() or struct sockaddr have differed too much…

  17. steveg says:

    I have quite fond memories of WIN32_LEAN_AND_MEAN and windowsx.h — the latter based on the design pattern of having a *separate* function per message instead of the "traditional" incredibly long switch() statement prone to blowing 64k CS limits (depending on your memory model).

    Compiling code on a 33Mhz 386… whee! Have you ever wondered how much of your life you’ve spent staring at an hourglass cursor?

  18. Daniel says:

    @steveg: I *love* compiling code on slow machine — http://xkcd.com/303/

  19. Goran says:

    "It does save you pollution of the C namespace which assists in writing portable code."

    What, you mean portable between Win16 and Win16+? ;-) Yeah, that old code support is a bitch…

    In a way, you want to pollute as much as you can, so that you know you are using names that might fail compilation on a given platform tomorrow, when you include another header from it. Because if you do need that header, and you do have a symbol clash, you might have to break your own compilation to change your symbol (easier than changing platform’s symbol).

    BTW, isn’t this why prefixing is the norm for cross-platform code?

  20. I still use windowsx.h and the function macros.  I figured I was just hard-core Win32 C– programmer.

  21. porter says:

    > BTW, isn’t this why prefixing is the norm for cross-platform code?

    There was a time when OS/2 was the successor to the graphical DOS extender and DosXXX, WinXXX, GpiXXX etc were the prefix on the APIs.

    I think argument is that everybody does prefixing except simple applications and Microsoft.

  22. Nick Bastin says:

    BTW, isn’t this why prefixing is the norm for cross-platform code?

    Yeah, don’t you think it’d be nice if Microsoft stuck DOMDocument in a namespace?

    Why is your cross-platform code including windows.h?

    Of course you have it #ifdef’d to win32, but writing portable code often means using 3rd party libraries to replicate a functionality that might be available on one OS and not another, and so it’s pretty annoying when both your 3rd party library and Microsoft define something like DOMDocument – and you’re not even using MSXML, but it’s dragged in by windows.h.

  23. Nicholas says:

    RANDOM POSTER: *rolls eyes* "Well, if you’re writing portable code and including windows.h then blah blah blah"

    I guess some of you people are young and pampered by WinXP, or some of you don’t remember the 90’s.  Writing a Windows application for both Win9x and WinNT was in effect an excercise in crafting portable code.

  24. easy fix says:

    Then put WIN32_LEAN_AND_MEAN inside #ifdef

  25. joe says:

    Namespace pollution needs to be avoided if you’re either *writing* or *using* portable code.

    The canonical example is that the C++ standard library functions std::min and std::max are hit by the win32 #defines of min and max macros (there’s a way to disable this – but often you’ll need to #undef something)

    In addition, platform specific routines we write have a single header file associated with a set of source files (with extensions like .win32.cpp). This requires that the header file must be compilable in the presence of namespace pollution from *any* of the platform specific APIs we’re using, despite the fact that it is itself portable.

Comments are closed.

Skip to main content