__stdcall - WINAPI vs STDMETHODCALLTYPE vs APIENTRY - c++

Im reading some of the game fix codes which deal with memory manipulation to fix a game's "issue". I found out that the code uses 2 macros that are WINAPI and STDMETHODCALLTYPE. These macros all get evaluated into __stdcall which specifies the calling convention for a function. I also found out that APIENTRY is also another macro alias for WINAPI. So are there any differences between these macros ? It seems to me that they are just aliases. Why are there so many of them ?

All data types and calling conventions in the Windows API are defined as aliases (preprocessor macros or typedefs). This allows for a stable ABI, irrespective of the compiler or toolchain. It also allows to change the ABI without breaking existing code (e.g. when 64-bit Windows was introduced).
Both WINAPI and STDMETHODCALLTYPE expand to the same thing: __stdcall for x86 and nothing for everything else. So why have 2 aliases for the same thing then? Because they control the calling convention for different subsets:
WINAPI specifies the calling convention for the flat C-based Windows API.
STDMETHODCALLTYPE, on the other hand, controls the calling convention for COM (Component Object Model).
COM and the Windows API are independent. Having 2 aliases to control the calling convention for either makes perfect sense. You wouldn't want to break all COM, just because you're moving to a new ABI for Win128.

Because back in 16-bit all these were different conventions. Since x86 flat mode, everything windows-related is __stdcall (Push right to left, callee clears the stack). __cdecl, __fastcall also exists.
Since x64, there is practically only one and all these are ignored.
The same occurs to many other Windows elements, like WPARAM and LPARAM. Once WPARAM was 16 bit, in x86 they are both 32-bit and in x64 they are both 64 bit.

Related

Do I need to prefix this function with __stdcall?

When learning about debugging OpenGL I implemented a function callback which would receive any debug error messages from the OpenGL API whenever something went wrong. In the tutorial it said that the function signature was:
typedef void APIENTRY funcname(GLenum source​, GLenum type​, GLuint id​,
GLenum severity​, GLsizei length​, const GLchar* message​, const void* userParam​);
So on Windows I implemented this callback. On Windows APIENTRY is a define for __stdcall. __stdcall I believe is a Windows-specific keyword specifying the calling convention. Later I ported my code to Linux, and for starters my GCC with Eclipse didn't recognise APIENTRY, because it's a Windows define. So I changed it to __stdcall, which I'm not sure if it recognised or not, but regardless it threw an error saying:
"Expected initialiser before glCheckError_"
As my callback function is void __stdcall glCheckError_(/Params/).
Removing the __stdcall preface makes the program work fine without it.
I'm wondering whether this prefix is necessary, for either Windows or Linux? The funny thing is that the place that suggested I add __stdcall to the function signature was the Khronos webpage, which holds documentation for OpenGL, so as far as I can tell it shouldn't be specifying OS-specific information, as OpenGL is cross-platform. So do I need this __stdcall prefix?
On windows, and only under 32bit, then it will make a difference. (The default is __cdecl calling convention, v.s. the __stdcall used by openGL). This can end up corrupting the stack if you use the wrong convention (the compiler should error with any luck).
On 64bit windows, it makes no difference (because stdcall isn't available, so all __stdcall/__cdecl will default to __fastcall).
It make no difference to linux/macos/android/ios.
Wrapping this in a macro should be all that's needed.
#if definded(_WIN32) && !defined(_WIN64)
# define STDCALL __stdcall
#else
# define STDCALL
#endif

_WIN32_WINNT definition changed in header, does this cause a binary incompatibility?

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.

“The value of ESP was not properly saved across a function call.”

I have a DLL written in Delphi 7 that I need to use in Visual C++ 2008.
From documentation that came with DLL, I can see that function is declared as (Delphi 7):
function ReadInfo(pCOM, pBuf, pErr: Pointer):boolean;
where pCom is pointer to data structure:
TCOM = record
dwBaudRate: Longword;
nCom,
nErr,
nLang : Byte;
end;
pBuf is pointer to "array of byte" (as it is written in DLL's documentation).
pErr - not used.
So now in c++ (after successfully loading DLL with LoadLibrary), I call:
myFunc = (MY_FUNC_POINTER)GetProcAddress(dllHandle, "ReadInfo");
which also doesn't return any errors.
MY_FUNC_POINTER is defined as:
typedef bool (*MY_FUNC_POINTER)(TCOM*, BYTE*, void*);
where TCOM is:
struct TCOM
{
unsigned long dwBaudRate;
BYTE nComm;
BYTE nError;
BYTE nLanguage;
};
I defined:
TCOM MyCom;
BYTE *myRes;
myRes = new BYTE[1024*1024];
But after calling
myFunc(&MyCom, myRes, NULL)
I get “The value of ESP was not properly saved across a function call.” error.
There would appear to be a calling convention mismatch. On the face of it, the function declares no calling convention in the Delphi, so the default Borland register convention is used. Your C++ code does not declare a calling convention for the import so the default of cdecl is used. But it is plausible that the Delphi code and documentation are not aligned and the Delphi code actually uses a different calling convention. Check the Delphi code, or contact the vendor. No matter what, the error message that you report does indicate a binary mis-match across the boundary between your module and the other module.
If the function really does use the Borland register calling convention (but see below for more), then you cannot readily call the function from languages other than Delphi. In that case you'd need a bridge to adapt that to a standard calling convention such as stdcall. By that I mean a Delphi DLL that can call the original DLL and expose it's functionality a way suited to interop. A better solution would be to fix the root problem and build the DLL again using standard calling conventions.
In fact, I now suspect that all the other commentators are correct. I suspect that the Delphi documentation does not match the Delphi code. I suspect that the function really is stdcall. So you can, probably, solve your problem by changing the function pointer typedef to be as follows:
typedef bool (__stdcall *MY_FUNC_POINTER)(TCOM*, BYTE*, void*);
My reasoning for this is that in stdcall the callee is responsible for cleaning the stack. That's not the case for cdecl, and since all the parameters, and the return value, fit in registers, it's not the case for Delphi register calling convention, for this function. Since there is a stack pointer mis-match, it follows that the most likely explanation is that the Delphi function is stdcall.
All the same, it's not comfortable to be working out calling conventions this way. If you cannot get any help from the DLL vendor then I'd be inclined to dig a little deeper by looking at the DLL function's code under a disassembler.

What is better to declare for calling convention of Windows program?

I have read an article about Calling convention (__stdcall, __fastcall, pascal, cdecl etc...)
And I wonder: Why is often __stdcall (WinAPI) declared for WinMain() function?
As I read, __stdcall operates with the stack, __fastcall operates on registers and not using stack at all.
So , I've tried to declare WinMain() with the __fastcall. Compiler (Visual C++) has given me an error.
error C2373: 'WinMain' : redefinition; different type modifiers
c:\program files\microsoft sdks\windows\v6.0a\include\winbase.h(2560) : see declaration of 'WinMain'
Why can't I use __fastcall for WinMain() and is there any possibility to use it for it?
Because to work on registers without using stack is miles faster, isn't it?
PS
My suggestion is, that there are some method contracts that disallow me to use __fastcall, but it's only my suggestion.
You can only specify the calling convention on functions that you write and/or you have the source code of.
You cannot change calling conventions of function that are in a library (static/dynamic) since those are already compiled/linked.
Important is that the declaration and definition have the same convention.
BTW : you wouldn't gain anything by having (win-)main having the fastcall convention since it's only called once!
You would consider fastcall on functions with many small parameters (that fit in registers) that are called very very often during long periodes of time.
The (buildin) startup routine for windows programs will call either WinMain or main (depending on GUI or Console app) with a specific convention.
If you write a WinMain or main with a different convention then the linker will complain.
WinMain must be __stdcall. It's called by the CRT start-up code, which is already built to pass parameters in a way defined by __stdcall convention.

Is preceding a function with CALLBACK or WINAPI or PASCAL (in MFC) is absolutely necessary or only for readability purpose?

In MFC VC++, setTimer function is setted using a CALLBACK procedure. From the link I read that
A function that is marked with __stdcall uses the standard calling
convention so named because all Win32 API functions (except the few
that take variable arguments) use it.
And from that, this is what I have understand, ALL THE VC++ MFC FUNCTIONS USE __stdcall as their calling conversions.
And CALLBACK is defined as follows....
#define CALLBACK __stdcall
What I have read:
Preceding a function with CALLBACK is used to emphasise that the particular function will be called automatically whenever necessary(like in this setTimer case or onClick case in javascript),
My doubt is , In MFC VC++ all functions(except the few
that take variable arguments) has a default calling convention of __stdcall. Hence either preceding or not preceding a function with CALLBACK or WINAPI or PASCAL has a same effect?
Is it absolutely necessary for the computer? It depends on the context. When you mismatch the calling convention, you could either get lucky because the datatypes on the stack happen to match the requirements of the API, or it could fail miserably when your code is run on a different architecture like x64 and crashes every time.
Is it absolutely necessary for the maintenance programmer? Yes, it is. You know, the poor person who will have to figure out your non-standard conventions and clever "optimizations." Some day, that poor person might be you.
The compiler was yelling at you for a reason when you tried to subvert the API.