wWinMain entry point warning

Pages: 12
I've been getting a 'Inconsistent annotation for 'wWinMain' warning for a long while now and I decided to look into it. My entry point currently looks like this:

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)

I've tried different variations from online sources of changing APIENTRY to WINAPI and LPWSTR to PWSTR or PSTR. I even went back to just WinMain. Every combination so far compiles with the same warning.

I'm using Visual Studio.

What do I need to change to get the warning to go away?
Last edited on
You should probably use the exact function signature given here:

https://docs.microsoft.com/en-us/windows/win32/learnwin32/winmain--the-application-entry-point

(certainly don't use PSTR instead of PWSTR for wWinMain function!)


But I think the warning is about the declaration and the definition of the function not being consistent.

https://docs.microsoft.com/en-us/cpp/code-quality/c28251?view=msvc-170

Do you happen to have any forward declaration of the wWinMain function anywhere in your code, before the actual definition? If so, make sure that they match exactly. It would appear that they don't.
Last edited on
That's my only declaration of wWinMain.

I tried that exact link prior to posting and it still gives me the warning. I just tried it again.

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow)
Last edited on
Ah, MS does loves its SAL Annotations.

https://docs.microsoft.com/en-us/cpp/c-runtime-library/sal-annotations?view=msvc-170

Here's a SAL annotated Unicode wWinMain, VS won't kvetch about "inconsistent annotation":
1
2
3
4
int WINAPI wWinMain(_In_     HINSTANCE hInstance,
                    _In_opt_ HINSTANCE hPrevInstance,
                    _In_     PWSTR     pCmdLine,
                    _In_     int       nShowCmd)

LPWSTR is a pointer type without a difference now, it's a long pointer. An artifact of 16-bit Windows. The distinction died along with Win98/Me.

https://docs.microsoft.com/en-us/windows/win32/learnwin32/windows-coding-conventions
My winbase.h file from the path of the warning message shows:

int
#if defined(_M_CEE_PURE)
__clrcall
#else
WINAPI
#endif
wWinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nShowCmd
);

only difference being PWSTR to LPWSTR, but doesn't matter.

So, what you are saying is that the warning is just there for VS users?
Think SAL, Microsoft's "source-code annotation language."

https://docs.microsoft.com/en-us/cpp/code-quality/understanding-sal?view=msvc-170
Not sure if this what you were getting at, but I declared wWinMain at the top of my code file, and the warning went away.
Overloading WinMain with a custom declaration is not recommended. You are using a cannon to get rid of a gnat.

The warning is just a frinkkin' warning. You can either use SAL to shut up VS, or simply ignore the warning.

winbase.h uses SAL in its WinMain declarartion. Why not use SAL in your code?

Notice only WinMain complains about inconsistent notation. Not WndProc, which is NOT SAL-led up the wazoo.
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-wndproc

Only one of the two required functions for any normal WinAPI Dekstop app whinges about SAL.

SAL is a good idea, in theory. On paper. Similar to Hungarian Notation. A good idea that substandard programmers latch onto to salve their tender egos and end up making the "cure worse than the disease."

Thanks for your answers. I had never heard of SAL before this post. Being in embedded software for 40 years and only dipping into VS recently, I have never used MS tools much. So, I wasn't sure how to answer your questions without first reading about SAL. I can certainly see where it would be helpful in analyzing software compiles, but since I have never had any of those type of warnings in my VS code, I didn't investigate this one warning until now.

Not sure I would ever use SAL in my programming unless needed. Maybe that's because I've never used it before, and have my own programming preferences. Since you have now enlightened me on the subject, I can keep my eyes out for those type of warnings.

Thanks. Oh, and I like killing gnats with cannons. It's more interesting that way. :)
you get the warning because vs is unicode by default
i had the same warning

this should be fine and your warning should go away
 
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)


PWSTR = ANSI Code, dont use that.
LPWSTR = UNICODE, all languages, russian, chinese etc. are supported.

In 32 bit/64 bit windows, PWSTR and LPWSTR have the same meaning and can be interchanged. The difference between these only applied to 16 bit versions of Windows when long and short pointers were used.

(L)PSTR - ANSI code
(L)PWSTR - UNICODE as underlying type wchar_t
(L)PTSTR - ANSI or UNICODE depending upon compiler option
Last edited on
SAL is a good idea, in theory. On paper. Similar to Hungarian Notation.


they are great if you code in VI or notepad, for sure.
modern tools provide the hungarian information directly in a mouse-over, without the clutter.
the in/out thing ... not a fan of out parameters to functions, but you pretty much HAVE to go out, in ordering (otherwise, default values get weird) so at most you need 1 marker to say where the split happens. You don't need a do-nothing false keyword for that, thanks to /*word*/ inline commenting. The tool you need is already in the language, and its portable, does not require some funky include or learning new redundant things. It will be syntax lit too, so you don't have to visually hunt for the special magic word: it stands out.

Some relics of 16 bit days can be overlooked, but most of the trainwreck of MFC was deliberate and unnecessary even when you look through the (c++98) lens.
Doesn't cl.exe only whinge about non-use of SAL at the highest warning level, what is it - /W4 I think?
The "inconsistent annotation" warning is not a compile-time warning. It is an IDE warning that will erupt no matter what warning level is set.
JohnOfC wrote:
PWSTR = ANSI Code, dont use that.
LPWSTR = UNICODE, all languages, russian, chinese etc. are supported.
Not true.

https://docs.microsoft.com/en-us/windows/win32/learnwin32/winmain--the-application-entry-point

MS Docs wrote:
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
PWSTR is for Unicode. Pointer to a Wide Character C-String.

MS Docs wrote:
pCmdLine contains the command-line arguments as a Unicode string.
Golly gee, a Unicode string. Now how did that get in there with PWSTR?

MS Docs wrote:
PWSTR, A pointer to a null-terminated string of 16-bit Unicode characters.
https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types

The typedefs for LPWSTR and PWSTR in WinNT.h both derive from WCHAR, itself a typedef for wchar_t.

The LP meant something with 8-bit Windows, kinda carried over to 16-bit Windows, Win3.11/95/98/Me, but they are dead. Now with 32/64-bit Windows they are typedefed to be the same.

Speaking of Unicode it is recommended for modern WinAPI apps to use wWinMain and Unicode, NOT use WinMain. WinMain passes the command-line arguments as ANSI using PSTR or LPSTR. LPSTR/PSTR is a pointer to a null-terminated string of 8-bit Windows (ANSI) characters. Both derived from CHAR in WinNT.h, CHAR derived from C/C++ char data type.

BTW, the "inconsistent annotation" warning is all about NOT using SAL with WinMain/wWinMain, period. It has nothing to do with using PWSTR or LPWSTR as a parameter type at all.
Can you tell me George (or anyone) why this GUI entry point function doesn't work with GCC (mingw)?

 
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevIns, LPWSTR lpszArgument, int iShow)


I've noted this issue for a very, very long time (at least 10 years) with many versions of mingw. The one I presently have on this box I'm typing this is TDM-GCC 9.2 which I got from an Embarcadero Bloodshed C++ download/installation. That doesn't matter though. History of this goes way back, like I said. I used to install the TDM compiler suites independently of Embarcadero's use of it.

Here's the test program I just tried....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//g++ Form1.cpp -luser32 -lkernel32 -oForm1_gcc.exe -mwindows -m64 -s -Os
#ifndef UNICODE
    #define UNICODE
#endif
#ifndef _UNICODE
    #define _UNICODE
#endif
#include <windows.h>

LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 if(msg==WM_DESTROY)       // This is the Window Procedure.  The concept of the
 {                         // Window Procedure is the most important concept to
    PostQuitMessage(0);    // grasp in C/C++ WinApi coding.  You never call this
    return 0;              // function with your code; rather, Windows calls it
 }                         // to inform code here of events occurring.  The events
                           // are reported here as messages.
 return (DefWindowProc(hwnd, msg, wParam, lParam));
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevIns, LPWSTR lpszArgument, int iShow)
{
 MSG messages;    // The concept of the Window Class and its associated Window Procedure are
 WNDCLASS wc;     // the most important concepts in Windows Programming.

 wc.lpszClassName = L"Form1",    wc.lpfnWndProc   = fnWndProc; // The Class Name Will Be Form1 And The Symbol fnWndProc
 wc.hInstance     = hInstance,   wc.style         = 0;         // Will Be Resolved At Runtime To The Virtual Address Of
 wc.cbClsExtra    = 0,           wc.cbWndExtra    = 0;         // Form1's Window Procedure, Which Windows Will Call
 wc.hIcon         = NULL,        wc.hCursor       = NULL;      // Through This Address Rather Than Through It's Name.
 wc.lpszMenuName  = NULL,        wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
 RegisterClass(&wc);                                           // Register The Window Class With Windows
 CreateWindow(L"Form1", L"Form1", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 200, 100, 325, 300, HWND_DESKTOP, 0, hInstance, 0);
 while (GetMessage(&messages, NULL, 0, 0))   // The message pump retrieves messages from the program's
 {                                           // message queue with GetMessage(), does some translation
    TranslateMessage(&messages);             // work in terms of character messages, then calls the
    DispatchMessage(&messages);              // Window Procedure associated with the HWND of the message
 }                                           // being processed.  Note that an app can have many Window
 
 return (int)messages.wParam;
}


Here's the error one gets...

 
C:/crossdev/src/mingw-w64-v7-git20191109/mingw-w64-crt/crt/crt0_c.c:18: undefined reference to `WinMain' 


However, if one replaces the wWinMain with WinMain, and the LPWSTR with LPSTR, it builds fine. Using Microsoft's compilers, one can use either the WinMain or wWinMain entry points, provided the UNICODE and _UNICODE defines match.

Just curious is all. I don't use mingw much anymore.
I suspect GCC/E's Dev-C++ isn't compiling the WinAPI as Unicode, only ANSI. The original Bloodshed, and Orwell's fork, lacked Unicode support being originally crafted during the Win9x days when it was ANSI, ANSI, ANSI and Unicode support was from a half-arsed lib/DLL. unicows.dll.

https://en.wikipedia.org/wiki/Microsoft_Layer_for_Unicode

So far everything I've seen about E's Dev-C++ shows they left the IDE as crippled as they found it. I looked and can't find anyway to enable it from the IDE compiler property pages.

I honestly don't know how to kick GCC/MinGW in the rump to enable Unicode support via some obscure command-line flag.

I use Visual Studio and get Unicode support by default. I have to manually disable it from the project's/solution's IDE property pages.

I get the same WinMain error using Code::Blocks, and no easy-to-find way to enable Unicode in that IDE as well.
Interestingly GCC's/MinGW's port of winbase.h doesn't SAL WinMain/wWinMain up the wazoo as the current Windows Kits for VS are set up to do. If'n it was possible to generate Unicode compliant code with GCC/MinGW there would be no whinging nag of "inconsistent annotation."
M'ok, maybe, just maybe, I found a compiler flag that would allow for Unicode compiling with GCC/MinGW.

To compile Unicode applications, define _UNICODE and UNICODE in your files when compiling and add -municode when linking. GCC will use the appropriate C startups for linking.


https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/

Bingo!!!!!! Add -municode to E's Dev-C++ project's property pages - > Project Option - > Parameters -> Linker and Hosannas! It compiles without a hitch as Unicode.

Doing the same for Code::Blocks, adding -municode as a linker parameter, works. Project - > Build options... - > Linker Settings tab - > Other linker options.

So.....maybe E's Dev-C++ isn't as abysmally crippled as I thought. Though the IDE project property pages won't let the language standard to be set to another ISO standard other than C++11. Lots of GNU language options. Maybe setting the langage standard via a flag would work?
@freddie1,

Adding -municode to the linker options for Orwell's Dev-C++ 5.11 (TDM-GCC 4.9.2) compiles your wWinMain code snippet.

I still like VS better since I can create both 32- and 64- bit apps with a batch build, release and/or debug as needed.
Pages: 12