I'm wondering why so many Win API functions are only defines to their real implemenation in MinGW.
Example:
MessageBox() function as described in the MSDN documenation:
int WINAPI MessageBox(
_In_opt_ HWND hWnd,
_In_opt_ LPCTSTR lpText,
_In_opt_ LPCTSTR lpCaption,
_In_ UINT uType
);
And here's the implementation of MinGW (winuser.h):
#define MessageBox MessageBoxA
/* ... */
WINUSERAPI int WINAPI MessageBoxA(HWND,LPCSTR,LPCSTR,UINT);
So MessageBox is not a function, it's only a define for the real function.
Another one (taken from winbase.h:
#define GetVersionEx GetVersionExA
/* ... */
WINBASEAPI BOOL WINAPI GetVersionExA(LPOSVERSIONINFOA);
As you can see in most cases the functions are implemented as macros to their real implementation.
Is there any reason for doing this? And why are they not implemented as "real" functions (using their real name)?
From GetVersionEx documentation:
Unicode and ANSI names: GetVersionExW (Unicode) and GetVersionExA (ANSI)
From Conventions for Function Prototypes documentation:
The preprocessor expands the macro into either the Windows code page or Unicode function name. The letter "A" (ANSI) or "W" (Unicode) is added at the end of the generic function name, as appropriate. The header file then provides two specific prototypes, one for Windows code pages and one for Unicode, as shown in the following examples.
In your case, GetVersionEx will expand to GetVersionExA because it looks like you are using Windows code page.
Using the DEFINEs enable you to use the same code with difference compiler options. For example: MessageBox will use MessageBoxW if using unicode, but MessageBoxA if not. It would be a pain to have to go through an entire code base just to change the method names.
Edit: Also see Christoph's reference, which this answer is referring to.
Related
So going through a source of a winapi program I found online I noticed there was no WinMain anywhere, I wonder if is possible in anyway to ever make a winapi program work like this, why do you think the original programmer did anything like this, we have the dialog procedure like this :
static INT_PTR CALLBACK mainDialogProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam)
{
switch(msg)
{
case WM_INITDIALOG:
{
//..............
}
}
}
and the main entrypoint was like this instead of void WINAPI WinMain (void);
void WINAPI entryPoint(void)
{
//........
}
Is this really possible? it goes against all that I have studied so far...
I'm really sure I'm missing something...
The entry point for an executable image is specified through the linker setting /ENTRY. If not explicitly set, it defaults to mainCRTStartup (or wmainCRTStartup) for a console application, WinMainCRTStartup (or wWinMainCRTStartup) for a GUI application, and _DllMainCRTStartup for a DLL. When using the CRT that ships as part of Visual Studio, all of the aforementioned raw entry points call into the user-provided entry points main (or wmain), WinMain (or wWinMain), and DllMain, respectively. This is implemented in crt0.c that ships as part of Visual Studio's CRT source code.
If you provide your own entry point (by specifying the /ENTRY linker option), it must have the following signature (for a 32-bit application):
DWORD CALLBACK RawEntryPoint(void);
Bonus reading: WinMain is just the conventional name for the Win32 process entry point
It is mostly compiler dependent, but the "entry point" of an executable is a function declared in the linker by means of appropriate options. WinMainCRTStarup is just the default, that -after an initialization of the default library- calls WinMain.
Anyway, code written like this, is probably defined to be self-contained, with the idea that you will call enrypoint from you own WinMain, where you can also do anything else.
You can use the /ENTRY:"entryPoint" linker option to set an arbitrary entry point.
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 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.
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.
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.