Maddening VC7 linkage problem resolved

I'm writing this mainly for Google: I searched high and low for a solution to this problem and ended up having to solve it myself. Two very long days.

I have a smallish (~20k lines) printing system that I build under Win32, and I just converted from MS Visual C version 6 (very old) to .NET2003 (VC7). The compiler is clearly running better, but I was getting linkage errors:

LIBC.lib(_wctype.obj) : error LNK2005: _iswlower already defined in file2.obj

The error was always with one of the wide-character ctype-like macros:

_iswalpha _iswupper _iswlower _iswdigit _iswxdigit _iswspace _iswpunct _iswalnum _iswprint _iswgraph _iswcntrl _iswascii

It seems that if one includes <tchar.h> before <windows.h>, the compiler instantiates these inline functions, so they end up being multiply defined. These code fragments demonstrate the problem:

file1.cpp
#include <windows.h>
#include <tchar.h>

int _tmain(void)
{
return iswlower('x') || iswalnum('x');
}
file2.cpp
#include <tchar.h>
#include <windows.h>

BOOL function2(wchar_t *s)
{
return iswlower(*s);
}

Note here that the two #include files are not in the same order, but in a very large system, this kind of thing doesn't jump out at you (especially when they are in a per-directory "common.h" file used as an anchor for precompiled headers).

Trying to build this:

C> cl -o main.exe /nologo /D_UNICODE file1.cpp file2.cpp
file1.cpp
file2.cpp
Generating Code...
LIBC.lib(_wctype.obj) : error LNK2005: _iswlower already defined in file2.obj
main.exe : fatal error LNK1169: one or more multiply defined symbols found

The solution has been to insure that <tchar.h> always follows <windows.h> (or <winsock.h>). I've queried the VC newsgroups, but it sure looks like a bug (or at least a misfeature) to me. Ugh.