For example:
int WINAPI WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show )
WINAPI is a a define that looks like this:
#define WINAPI __stdcall
why can't you just do:
int __stdcall WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show )
actually I think my problem is that I'm sort of confusing defines with typedef's. Can someone explain this to me? what does the define do and why can't you just write __stdcall in its place?
Because the WINAPI calling convention is not guaranteed to be __stdcall. Code that uses WINAPI will still be correct even when it isn't.
You can write the function as in your latter example, and it'd work fine - it's just not good practice and would not be portable to a platform where the calling convention is something else.
This was originally done during the switchover from 16-bit to 32-bit code. In the 16-bit version of <windows.h> it was:
#define WINAPI __pascal
WINAPI let you compile for either without modifying the source code. Of course, 16-bit Windows is no longer a factor (at least for most people), but it's still not worth changing all the source code to use __stdcall directly (especially since it could change again someday).
You can just write __stdcall in its place, but don't. They've seen fit to #define WINAPI to __stdcall to make that opaque, which is just good programming practice.
Also, back in the day, some Windows libraries used Pascal calling convention and other libraries used C convention. A preprocessor define helped gloss over that.
Because WINAPI is a macro (well a #define anyway) it can be "pre-processed" to mean something else or even nothing at all.
That means you can write more portable code, as you can put in WINAPI when it is required by Win32 to mean __stdcall but, or if it is required in another environment to mean something else or nothing.
Related
In VS2010, I'm working on updating an application to a new version of a third party library that requires _WIN32_WINNT to be at least 0x501 but another third party shared library that provides binary shared libraries defines it as 0x500 in a header that is included in the application.
If this is modified, can there be a binary incompatibility or is this an insignificant change? Will I have to request new binaries from the library that defines it as 0x500? I'm not sure how to tell if this requires new bins -- I would think if any classes/structs change in size or naming, or any method/function signatures change then a new compile is necessary.
Short answer: Probably not, but if it does you're in a pretty pickle.
Long answer:
_WIN32_WINNT controls the version of the WinAPI (and related libraries such as MFC) that your code is going to use. The intent is to ensure that compiler errors are generated if you use Windows features that were introduced after the Windows version you're targeting.
Mostly this controls which functions, structs etc. are visible to you. This part cannot cause binary incompatibilities except with the Windows versions you're not targeting. However...
There are some structs in the WinAPI that were extended over the life of Windows. Take a look, for example, at the definition of OPENFILENAME:
typedef struct tagOFN {
DWORD lStructSize;
HWND hwndOwner;
HINSTANCE hInstance;
LPCTSTR lpstrFilter;
LPTSTR lpstrCustomFilter;
DWORD nMaxCustFilter;
DWORD nFilterIndex;
LPTSTR lpstrFile;
DWORD nMaxFile;
LPTSTR lpstrFileTitle;
DWORD nMaxFileTitle;
LPCTSTR lpstrInitialDir;
LPCTSTR lpstrTitle;
DWORD Flags;
WORD nFileOffset;
WORD nFileExtension;
LPCTSTR lpstrDefExt;
LPARAM lCustData;
LPOFNHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
#if (_WIN32_WINNT >= 0x0500)
void *pvReserved;
DWORD dwReserved;
DWORD FlagsEx;
#endif
} OPENFILENAME, *LPOPENFILENAME;
See that last bit at the end? That spells potential trouble -- one part of your code is going to assume that this struct is smaller than the other if one is compiled with _WIN32_WINNT set to 0x400 and the other to 0x500.
The WinAPI designers did think about this problem. You will notice that the first member of OPENFILE is lStructSize; you are supposed to initialize this with sizeof(OPENFILE). For you, sizeof(OPENFILE) is a compile time constant, for functions in the Windows runtime library, it's the tag by which they decide which version of the OPENSTRUCT struct you're passing into them.
This spells potential trouble in one scenario: If the binary library and the rest of your code exchange WinAPI types or pointers to such types, and if those types were extended between 0x500 and 0x501, then things are going to explode. Happily, I don't expect there to be many such structs because the version range is very narrow. If this is a worry, however, then you should definitely request new binaries because working around it is going to be difficult and tedious with many opportunities to make mistakes.
Other than that, I think you're (probably) safe.
I'm using \W4 warning level on Visual Studio and I'm writing a Windows program.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
All these parameters are not used in my application, so I get warnings at compile time.
I know there are two ways of dealing with this:
Commenting parameters HINSTANCE /*hInstance*/ ...
Using the UNREFERENCED_PARAMETER macro
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
Which one is the correct one? Which one is the safer to use? Are there any problems with using the macro?
I would prefer commenting the parameters.
The macro UNREFERENCED_PARAMETER is defined in winnt.h and therefore not portable.
And if later you do reference it, you might overlook to remove the macro.
Edit: With C++17 you can now use the [[maybe_unused]] attribute. This is useful for code depending on preprocessor macros:
void foo( [[maybe_unused]] int value )
{
#ifdef USE_VALUE
useValue(value);
#endif
}
Now there won't be warnings even if USE_VALUE is undefined.
I consider the name-removing version the first to go with. It can have a disadvantage to confuse the information system so tooltip shows the crippled version. But healthy ones would use the declaration, where the names are there. (and for static and one-use things you should not have unused params, right?)
Otherwise it's matter of taste really.
In C++, both are the correct ways to handle and do not introduce any unsafe-ness directly. However, the use of UNREFERENCED_PARAMETER can cause a maintenance issue because you need to remove the use of the macro if the parameter is used in the future updates, yet compilers do not warn that situation. To audit correct use of the macro, developers have to manually inspect that the parameters are still unused.
As others pointed out, cross-platform portability could be an issue too.
In C, it is not possible to remove the parameter name; hence the macro is the reasonable solution on the Windows platform, especially in Win32 programming.
I found this code and I don't understand it. I can't find references for NTAPI. For me, it's defining a function called TestForWr but NTAPI is confusing.
VOID NTAPI TestForWr(PVOID Ad, ULONG Le, ULONG Al);
From WinNT.h
#define NTAPI __stdcall
The __stdcall calling convention is used to call Win32 API functions.
The callee cleans the stack, so the compiler makes vararg functions
__cdecl.
The prefix NTAPI is a Function calling convention that is used in native mode Programming.
Also, it is not part of a windows subsystem like win32.
For example, it will look something like that: NTSTATUS NTAPI NtForceReset(PVOID Response); .
I am learning about C++ and programming to the windows api. My first "Hello Windows API" program just displays a MessageBox(). But, I have questions that the book I'm reading isn't explaining.
First, here's the program:
// HelloWin32 Program
#include<Windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
MessageBox(NULL, "This gets displayed in the message.", "This is the title bar of the message dialog.", MB_OK | MB_ICONEXCLAMATION);
}
This compiles and runs fine. My question has to do with the WinMain() declaration that says int WINAPI WinMain(...). As I read it, the WinMain function (method?) returns an integer. But what does WINAPI communicate?
Obviously, I'm writing to the Windows API. Does WINAPI somehow flag the function so the program uses Windows API to execute it or something?
WINAPI is a preprocessor definition defined as __stdcall, a calling convention; when functions have __stdcall before their name, it is a directive to the compiler to make the function use that calling convention. This is so both your function and the function calling your function agree to use the stdcall calling convention and the call executes correctly.
This is necessary because the default calling convention of your compiler may or may not be stdcall, so you have to explicitly tell the compiler to make it that way for that function. The designers of the Windows API decided, mainly for compatibility reasons and the universality of the stdcall calling convention, to make all function calls use the stdcall calling convention.
Also, you can have functions with different calling conventions being used in the same program. So for instance, WinMain has to be stdcall but the other functions of your program do not; they can use the compiler default.
A calling convention is a method for doing things like the order in which parameters should go on the stack, who should remove them from the stack when the function returns, where to put return values, and other things. Different calling conventions do this in different ways. Above all, it is extremely important that both the caller and the callee follow the same calling convention. For more info on calling conventions, see the Wikipedia article.
Could you please explain to me the WINAPI word in the WinMain() function?
In the simplest way..
#include <windows.h>
int -->WINAPI<-- WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, "Goodbye, cruel world!", "Note", MB_OK);
return 0;
}
Is it just some Windows funky mode?
What does it do? Or rather what is this C++ feature I haven't encountered yet?
WINAPI is a macro that evaluates to __stdcall, a Microsoft-specific keyword that specifies a calling convention where the callee cleans the stack. The function's caller and callee need to agree on a calling convention to avoid corrupting the stack.
WINAPI is a macro that expands to __stdcall which means that the callee cleans the stack.
This is a macro definition intended to denote the Windows calling convention. From MSDN:
The way the name is decorated depends
on the language and how the compiler
is instructed to make the function
available, that is, the calling
convention. The standard inter-process
calling convention for Windows used by
DLLs is known as the WinAPI
convention. It is defined in Windows
header files as WINAPI, which is in
turn defined using the Win32
declarator __stdcall.
It's Windows-specific. It specifies the calling convention. WinMain gets called by Windows, and this ensures that the caller and callee agree on the calling convention.