I'm trying to get my code as perfect as possible, and I've cleaned up all errors and (other) warnings. I'm left with these two:
Warning C28253 Inconsistent annotation for 'WinMain': _Param_(2) has 'SAL_null(__no)' on this instance.
Warning C28252 Inconsistent annotation for 'WinMain': _Param_(2) has 'SAL_null(__maybe)' on the prior instance.
Here is my WinMain function
int CALLBACK WinMain( _In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow );
Why is my second paramater HINSTANCE hPrevInstance not annotated correctly despite it being ripped straight from MSDN with the _In_ info?
It is because the hPrevInstance argument actually has the _In_opt_ annotation rather than just _In_.
Related
I have been able to fine the WinMain function. Now I'm trying to make a win32 app:
#include <Windows.h>
int WINAPI WinMain() {
MessageBox(NULL,"Test", "Hello World", NULL);
return 0;
}
and then I get error C2731.
You haven't provided any parameters to the WinMain() method, and the error C2731 is saying that this method cannot be overloaded.
From MSDN:
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow);
Error C2664 is most likely your call to MessageBox, so try changing to something like:
MessageBox(NULL, L"Test", L"Hello World", NULL);
I figured it out I wasn't useint main.cpp as my main source code file and my WinMain needed to be switched to wWinMain
Code:
#include <tchar.h>
#include <windows.h>
typedef INT (WINAPI * lolMessageBoxA)(HWND,LPCSTR,LPCSTR,UINT);
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
lolMessageBoxA UchwytMessageBoxA;
UchwytMessageBoxA = lolMessageBoxA(GetProcAddress(GetModuleHandle("User32.dll"),"MessageBoxA"));
UchwytMessageBoxA(NULL,"TEST WINDOWS","TEXT 2", MB_OKCANCEL | MB_ICONWARNING);
return 0;
}
When i called MessageBoxA normally before making hook the hooking part worked good. But when i erased that part and leaved only the 'hooking' part it fails...
Solved:
#include <tchar.h>
#include <windows.h>
typedef INT (WINAPI * lolMessageBoxA)(HWND,LPCSTR,LPCSTR,UINT);
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
lolMessageBoxA UchwytMessageBoxA;
LoadLibraryA("User32.dll");
UchwytMessageBoxA = lolMessageBoxA(GetProcAddress(GetModuleHandle("User32.dll"),"MessageBoxA"));
UchwytMessageBoxA(NULL,"TEST WINDOWS","TEXT 2", MB_OKCANCEL | MB_ICONWARNING);
return 0;
}
As presented here, there's no reason for the process to have loaded user32.dll. So the call to GetModuleHandle will return NULL. Then the call to GetProcAddress will also fail and return NULL. And well, you can see what happens next.
When you called MessageBoxA directly, the linker would have produced an import table that forced the loader to load user32.dll. But when you removed the call to MessageBoxA, there was no need for it to do so.
You should replace the call to GetModuleHandle with a call to LoadLibrary, and so force the library to be loaded.
Finally, the real reason for you having asked this question is that your code neglects error checking. Don't do that. Check the values returned by the Win32 function calls. Had you done so you would have been able to work this out for yourself.
I upgraded an old project from VC6 to VS2008, and now I get this compile error:
error C2731: 'wWinMain' : function cannot be overloaded
At these lines of code:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
The same project compiles fine under VC6.
Thanks everyone, I finally found the real culprit, it's a typo, I use LPSTR lpCmdLine instead of LPTSTR lpCmdLine. The real mystery is why it compiled at all under VC6 - it did use wWinMain, but somehow it was OK for lpCmdLine to be char * instead of WCHAR *.
Now I changed it to:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
And it works under VS2008 too.
Edit: I successfully compiled and even ran the program with this function definition under VC6:
int APIENTRY wWinMain(int *hInstance, float hPrevInstance, int *lpCmdLine, float nCmdShow)
{
MessageBox(0,L"Running.",0,0);
return 0;
}
Interestingly, replacing float nCmdShow to double nCmdShow does give a linker error, I assume because float is 32-bits but double is not.
For me it worked after changing WinMain to wWinMain in VS 2019
I had the same error with a Win32 Console Application. The fix was:
Open Project > Properties ...,
Expand Configuration Properties > Linker > System
Set SubSystem to Not Set
Click OK
I am new to C++, trying to make bootstrapper for an executable. I wanted to send additional parameters along with lpCmdLine
typedef int (__cdecl *BooterMain_t)(HINSTANCE, HINSTANCE, LPSTR, int);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
I load the library
HMODULE Program = LoadLibraryExA(".\\bin\\program.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
this is how I launch it
BooterMain_t procBooterMain = (BooterMain_t)GetProcAddress(Program,"BooterMain");
procBooterMain(hInstance, hPrevInstance, InternalParameters, nCmdShow);
May I know how to pass InternalParameters along with lpCmdline? Currently it seems to be ignored.
Edit: About Internal Parameters,
char InternalParameters[MAX_PATH] = {0};
_snprintf_s(InternalParameters, _TRUNCATE, "-verify -console");
How do I go about adding support to my Windows Forms Application to be able to launch with parameters?
I'm using C++.
If you are writing Win32 gui application then your entry point it WinMain:
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
);
The third parameter, lpCmdLine is the command line passed to the application. The command line parameters passed to the application will be in that string.
You can either add an args array to your Main method or use Environment::GetCommandLineArgs()
So either
int Main(array<String^>^ args)
or
array<String^>^ args = Environment::GetCommandLineArgs();
Then loop through the args array and determine what to do based on what is in the array.
There's a main(int argc, char** argv) function for any executable program. You just need to parse the command line parameters passed in argv and pass theese to your main form.