Honey, you are the [_tWin]Main source of joy in my life!

by Michael S. Kaplan, published on 2007/05/24 08:41 -04:00, original URI: http://blogs.msdn.com/b/michkap/archive/2007/05/24/2840970.aspx

Human gjcoram asks:

I'm developing a unicode e-mail client (nPOPuk) -- works in Win32, Win32Unicode, and various WinCE platforms. I was tracking down a memory leak that originated from the fact that "lpCmdLine" is a char* rather than a TCHAR* in the declaration of WinMain in winbase.h:

    IN HINSTANCE hInstance,
    IN HINSTANCE hPrevInstance,
    IN LPSTR lpCmdLine,
    IN int nShowCmd

The original developer just blithely cast the LPSTR to a TCHAR*, and what was a nice "\0" was NOT the same as TEXT("\0").

Shouldn't it be
    IN LPTSTR lpCmdLine

Well, it isn't as simple as that, though at least you noticed the obvious bug in the original developer's code!

If you look at the WinMain MSDN topic, it explains a bit about what is going on here:

ANSI applications can use the lpCmdLine parameter of the WinMain function to access the command-line string, excluding the program name. Note that lpCmdLine uses the LPSTR data type instead of the LPTSTR data type. This means that WinMain cannot be used by Unicode programs. The GetCommandLineW function can be used to obtain the command line as a Unicode string. Some programming frameworks might provide an alternative entry point that provides a Unicode command line. For example, the Microsoft Visual Studio C++ complier uses the name wWinMain for the Unicode entry point.

Another interesting tidbit can be found by looking at the Windows CE version of the WinMain topic, looking at the prototype in particular (note the piece highlighted in red!):

int WINAPI WinMain(
  HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  LPWSTR lpCmdLine,
  int nShowCmd

There is even an old comment to one of Raymond Chen's blog posts that regular SIAO reader Mike Dimmick made that covers the CE issue and talks about what the original WinMain topic kind of hinted at -- that wWinMain is a Microsoft CRT illusion that may not work everywhere.

For good measure, there is even that KB article that talks about how to fix when the illusion breaks (MSKB 125750)....

But maybe with everything considered, GetCommandLineW is the best way to go here, though if you are using the CRT even the Routine Mappings page points out the existence of _tWinMain, which will go what gjcoram was originally thinking about....


This post brought to you by (U+1588, a.k.a. CANADIAN SYLLABICS TLHO)

# gjcoram on 25 May 2007 6:33 AM:

The original code had #ifdef _WIN32_WCE to switch between the CE command line prototype (with LPTSTR) and the non-Unicode prototype; I tried to switch it to #ifdef UNICODE but this didn't work.

Thanks for the pointer on GetCommandLineW.

go to newer or older post, or back to index or month or day