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.
Related
today I have been trying to get standard functions to work in my application such as sprintf, ect.
When ever using functions like sprintf, fgets or anything else standard my application crashes with runtime error - CRT not initialized
Current linker options:
/ignore:4098 /dll /entry:"_DllMainCRTStartup" /include:"XboxKrnlBuildNumber" /ALIGN:128,4096
Entry point:
BOOL APIENTRY DllMain(HANDLE hInstDLL, DWORD reason, LPVOID lpReserved)
Tried to init it my self by defining _CRT_INIT is an extern that takes no arguments and calling it in my DLL_PROCESS_ATTACH with no luck.
I've been stuck on this issue for months but just thought i'd come back to it and look a little deeper.
If you are doing something non-trivial in your DllMain function, this may be of help:
http://blog.barthe.ph/2009/07/30/no-stdlib-in-dllmai/
http://blogs.msdn.com/b/larryosterman/archive/2006/06/15/632502.aspx
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.
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.
OK, so I have a situation in which I call LoadLibrary on a DLL that I wrote. This call to LoadLibrary returns error #998, or ERROR_NOACCESS "Invalid access to memory location."
The DLL in question uses MFC in one configuration, and not in another; only the MFC configuration has this problem. It used to work, but I have no idea what I changed: I'd actually moved on to the non-MFC version and been tinkering quite a lot with that and I have no idea what I could have done that affected the MFC version.
I don't know a lot about DLLs. The original loading code was actually given to me, and I haven't changed it. Below is that code:
// submodule loading
#ifndef MFC
// Project uses standard windows libraries, define an entry point for the DLL to handle loading/unloading
BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
{
_MESSAGE("DllMain called.");
switch(dwReason)
{
case DLL_PROCESS_ATTACH: // dll loaded
hModule = (HMODULE)hDllHandle; // store module handle
_MESSAGE("Attaching Submodule ...");
break;
case DLL_PROCESS_DETACH: // dll unloaded
_MESSAGE("Detaching Submodule ...");
break;
}
return true;
}
#else
// Project uses MFC, we define here an instance of CWinApp to make this a 'well-formed' DLL
class CSubmoduleApp : public CWinApp
{
public:
virtual BOOL InitInstance()
{// dll loaded
hModule = m_hInstance; // store module handle
_MESSAGE("Attaching Submodule ...");
return true;
}
virtual int ExitInstance()
{// dll unloaded
_MESSAGE("Detaching Submodule ...");
return CWinApp::ExitInstance();
}
} gApp;
#endif
Obviously, MFC is defined in the MFC configuration, and not otherwise.
I doubt this is enough information to solve this problem; I realize that. What I'm actually hoping to learn is where to look for problems that might cause this error. I'll be happy to supply any information you need — once I know it's needed.
Thanks for any tips.
OK, this question was answered by a friend of mine (no idea if he has a StackOverflow account; not going to pester him with answering it twice).
The deal is that I had a global object, the class of which had a constructor that called a function that depended upon another global object (ironically enough, the function in question was _MESSAGE, but by the time DllMain or InitInstance gets called, that function works fine). C++ doesn't allow you to specify the order in which globals get initialized, so when this global's constructor got run (when the computer attempted to load the DLL), it caused a memory error by attempting to use another global that hadn't been created yet.
So... that's the answer. A really specific case, but I guess if anyone else finds they're getting 998 errors and need to know what sorts of problems to check, this is something to look for: make sure all your globals are independent!
I've got a function imported from a DLL. I control the source of both the host executable and the dynamic library. Now, in DLLMain then I used MessageBox to pop up the address of the function I'm exporting, and compared it using a breakpoint to the function pointer returned by GetProcAddress, and they're identical.
However, when I try to call the function, I get an access violation. The function in question just returns NULL and has no logic, so it can't be thrown by the function specifically.
How can calling a known valid function pointer, with the correct signature, and verified safe logic, yield an access violation?
Edit: Information gained through another separate question about why the debugger is dying in this situation suggests that my stack is being smashed too? That would make more sense than an AV, but the function pointer and the function are completely compatible and the address is correct.
extern "C" Render* __cdecl CreateRender(WindowsOS* ptr) {
return nullptr;
}
typedef Render*(__cdecl *RendererCreateFunction)(WindowsOS*);
I used a simple, small piece of code in DLLMain to qualify that they are in fact compatible as far as the compiler is concerned.
BOOL WINAPI DllMain(
__in HINSTANCE hinstDLL,
__in DWORD fdwReason,
__in LPVOID lpvReserved
) {
RendererCreateFunction func = &CreateRender;
}
If they aren't compatible (they include the same header) then the compiler should throw an error and refuse to build the DLL, but it accepts this just fine.
If this is DLLMain you use in your code then it has no return statement and most likely returns a not initialized value, quite probably 0 as a good main function, which effectively unloads the DLL from the memory. Make sure DLLMain returns TRUE.
I completely failed this one. Wrote a class that manages a resource without respecting my move and copy semantics properly. Turns out that I was calling FreeLibrary() on the library in question mistakenly before I needed to use it.