I'm trying to build a console application without using the CRT, or any other imports than kernel32.lib in any case. I get my code to compile, but can't wrap the linker around a few problems:
unresolved external symbol #__security_check_cookie#4
unresolved external symbol "int __cdecl FreeLibrary(void *)" (?FreeLibrary##YAHPAX#Z)
unresolved external symbol "void * __cdecl LoadLibraryW(wchar_t *)" (?LoadLibraryW##YAPAXPA_W#Z)
unresolved external symbol "int (__cdecl*__cdecl GetProcAddress(void *,char *))(void)" (?GetProcAddress##YAP6AHXZPAXPAD#Z)
unresolved external symbol _wmainCRTStartup
FreeLibrary, LoadLibraryW and GetProcAddress I've brought in to program explicitly, not using windows.h:
#pragma comment(lib, "kernel32.lib")
typedef int(*FARPROC)();
void* LoadLibraryW( wchar_t* lpLibFileName );
FARPROC GetProcAddress( void* hModule, char* lpProcName );
int FreeLibrary( void* hLibModule );
I suppose something is wrong with my prototypes.
However, the bigger problem are __security_check_cookie and _wmainCRTStartup, which obviously have something to do with the CRT.
So I'm wondering how I'd go about overriding the default int wmain(int argc, wchar_t* argv[]) for entrypoint, and how to get rid of whatever the security cookie is.
_wmainCRTStartup is the function that calls wmain()
IIRC it should be available in some .o file that you can link with, look in your lib directory.
Maybe this is useful reading too: Reduce EXE and DLL Size with LIBCTINY.LIB (and Matt Pietrek rocks :-)
Well, answering myself here to sum up, in case someone else finds this page looking for info.
As MSalters advised, the security cookie code can be stolen from the CRT source, but doing that I found that the /GS- compiler flag can be used to avoid the security stuff altogether.
As SoapBox said, the API functions need to be __stdcall, as well as the entry point does.
I fixed the entry point issue with linker command line flag /entry:wmain.
And finally, as Tomek pointed out, the API functions gotta be in extern C!
So:
#pragma comment(lib, "kernel32.lib")
typedef int(*FARPROC)();
extern "C" {
void* __stdcall LoadLibraryW( wchar_t* lpLibFileName );
FARPROC __stdcall GetProcAddress( void* hModule, char* lpProcName );
int __stdcall FreeLibrary( void* hLibModule );
typedef int (__stdcall *f_MessageBoxW_t)( unsigned long hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned long uType);
f_MessageBoxW_t fnMsg;
void* hUser;
};
int __stdcall wmain(int argc, wchar_t* argv[])
{
hUser = LoadLibraryW( L"user32.dll" );
fnMsg = (f_MessageBoxW_t)GetProcAddress( hUser, "MessageBoxW" );
fnMsg( 0, L"foo", L"bar", 0 );
FreeLibrary( hUser );
return 0;
}
More correct entry point declaration will be:
int __stdcall wmain(PVOID ThreadParam)
Without CRT entry point called directly by BaseThreadInitThunk. Its passes pointer to something, but not argc+argv.
You can look in Windows.h to see the prototypes you need for your kernel32 imports. In general, windows functions are defined WINAPI which is actually __stdcall and not __cdecl. That will fix that problem at least.
As for your other problem, you need to explore the linker commandline arguments and see if there is a way to get it to not look for things from CRT. I don't know if there is a way to do that or not. But you're going to have to find a way or define those functions your self (which you probably don't want to do).
I'd recommend just using a different compiler/linker.
You need to declare windows.h functions as extern "C".
The proper entry point is main(), not wmain() (since you're compiling a console app).
The security cookie code can be nicked from the CRT source code; no need to link it in.
Related
I have read a lot about how to change the WinMain entry point procedure, some say you can change the entry point from the linker and some others say you can put the WinMain into DLL (dllMain) and so on.
Honestly, I am confused. I believe that there are one or more ways to change the entry point procedure to a custom procedure because there are some examples like MFC don't have a direct WinMain function and the Qt framework also has a custom entry point procedure it's similar to the console application main function int main(int argc, char *argv[]), so, there are ways as I expected.
I want a whatever way to replace/change the entry point procedure for GUI application on Windows from the traditional procedural WinMain to int main(int argc, char *argv[]) like Qt or even any other custom function but it must be compatible with (MS, GCC, Clang) compilers.
///////////Windows main/////////////
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdParam, int cmdShow){
}
///////////Console main and Qt framework////////////
int main(int argc, char *argv[]) {
}
//////////MFC////////////
class CMyFrame : public CFrameWnd {
public:
CMyFrame() {}
};
class CExample : public CWinApp {
BOOL InitInstance() {}
};
CExample theApp;
How do I do that?
entry point of exe can by any function with signature
ULONG CALLBACK ep(void* )
possible and use ULONG CALLBACK ep() - despite on x86 will be wrong stack pointer (esp) after return, this not lead to error, because windows just call ExitThread after entry return, if it return control at all - usually it call ExitProcess instead return.
the name of this entry point of course not play any role at all - it can be any valid c/c++ name. entry point found/called not by name but by AddressOfEntryPoint offset from IMAGE_OPTIONAL_HEADER
but when we build PE - we need tell linker name of this function, for it can set AddressOfEntryPoint, but this info (name of function) used only during build process (not used in runtime)
different linkers of course have different options for do this, link.exe have option /ENTRY. this option is optional and by default, the starting address is a function name from the C run-time library.
if /ENTRY:MyEntry explicitly stated - it used as is - MyEntry will be used as entry point. if no /ENTRY option set - used default:
if /SUBSYSTEM:CONSOLE set - used mainCRTStartup or if it not found wmainCRTStartup
if /SUBSYSTEM:WINDOWS set - used WinMainCRTStartup or if it not found wWinMainCRTStartup
but in most case c/c++ developers use CRT libraries. regardless of whether static or dynamic linking used with CRT - some lib code always statically linked with your exe and this code containing function which you used as entry point. for ms windows crt - this is mainCRTStartup or wmainCRTStartup (for console apps), WinMainCRTStartup or wWinMainCRTStartup for gui apps.
in all this 4 functions - called hardcoded function by name
mainCRTStartup call main
wmainCRTStartup call wmain
WinMainCRTStartup call WinMain
wWinMainCRTStartup call wWinMain
of course called function must be implemented somewhere in your code or in another lib code. for example if you use MFC - it implement wWinMain by self and called your code in another way ( via calling virtual functions on object which you override - InitApplication and InitInstance)
if back to question how change name of your custom entry point - but for what ? you really not need change name. you need only understand how your entry point is called. if you understand this - you can do almost all.
assume we want use main as "entry point". i take this in quotes because we really want have real entry point in CRT code and we want that CRT code call exactly main function.
possible ? simply !
set /ENTRY: mainCRTStartup linker option. so mainCRTStartup will be real entry point and it call main.
another question, i personally think that this is senseless trick, which nothing change and nothing give
also possible simply call main from WinMain
typedef struct
{
int newmode;
} _startupinfo;
/*
* new mode flag -- when set, makes malloc() behave like new()
*/
EXTERN_C _CRTIMP int __cdecl _query_new_mode( );
EXTERN_C _CRTIMP int __cdecl _set_new_mode( _In_ int _NewMode);
EXTERN_C
_CRTIMP int __cdecl __getmainargs(__out int * _Argc,
__deref_out_ecount(*_Argc) char *** _Argv,
__deref_out_opt char *** _Env,
__in int _DoWildCard,
__in _startupinfo * _StartInfo);
int __cdecl main(__in int _Argc, __in_ecount_z(_Argc) char ** _Argv, ...);
int CALLBACK WinMain( _In_ HINSTANCE , _In_opt_ HINSTANCE , _In_ LPSTR , _In_ int )
{
int _Argc, r;
char ** _Argv;
char ** _Env;
_startupinfo _StartInfo { _query_new_mode( ) };
if (!(r = __getmainargs(&_Argc, &_Argv, &_Env, 0, &_StartInfo)))
{
r = main(_Argc, _Argv, _Env);
if (_Argv) free(_Argv);
}
return r;
}
it must be compatible with (MS, GCC, Clang) compilers
How you do that depends on your compiler. Most of them will have some flags to choose which "subsystem" (the Windows term) you are targeting and even customize the entry point manually.
Put another way, there is no standard way of doing so because this is outside the scope of the C++ standard.
Having said that, some compilers provide the means to emulate the flags of other compilers. For instance, Clang can imitate Microsoft's.
I want to write a very, very small program that parses the launch arguments and chooses one of several DLLs to "boot into."
I've already written an application that I'd like to "run" as a DLL by writing it as an application, then changing the Visual Studio project properties to build it as a DLL instead. I know I need to use LoadLibrary and GetProcAddress in concert to get the functionality I want, but I'm having trouble finding clear and comprehensive documentation on this, as a lot of the use cases aren't really of this nature. Also, I have to go this route based on the project and platform restrictions.
I found this page, which has some information, but it's not clear enough for me to adapt for my purposes.
Edit: Here's where I'm at right now.
I have a DLL project whose main function signature looks something like this:
__declspec(dllexport) int cdecl main(int argc, char *argv[])
I also have an application project whose attempt at loading the DLL and running the above function looks like this:
typedef int (CALLBACK* LPFNDLLFUNC1)(int, char *);
...
HMODULE dllHandle = NULL;
BOOL freeResult, runTimeLinkSuccess = FALSE;
LPFNDLLFUNC1 lpfnDllFunc1; // Function pointer
if (args->IsEmpty())
{
dllHandle = LoadLibrary(L"TrueApplication.dll");
if (NULL != dllHandle)
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(dllHandle, "main");
if (lpfnDllFunc1)
{
int retVal = lpfnDllFunc1(0, "1");
}
Currently, the LoadLibrary call works, but not GetProcAddress.
First of all, changing project type from executable to DLL is not enough to make a DLL. You also need to export some symbols to create your API. At least, you need to decorate the functions you are exporting with __declspec(dllexport). However, I recommend that you export C API, meaning extern "C" functions with C-compatible arguments. So, the functions you export should be prepended with extern "C" __declspec(dllexport).
Once you have done that, you can dynamically load your DLL like this:
const char* dllname = "myfile.dll";
h = LoadLibrary(dllname);
if( h == nullptr )
{
/*handle error*/
}
using myfunc_type = bool (*)(int x, double y); //example
auto myfunc = reinterpret_cast<myfunc_type>(GetProcAddress(h, "myfunc"));
//......
myfunc(x,y); //call the imported function
This solution takes more work than static loading with /delayload shown by Jerry Coffin, but it has an advantage: if a DLL is required but not found, you can give users your own error message instead of relying on the message coming from Windows (which is often unacceptable for non-tech people). You can also include API version verification with its own custom error message in the API.
Edit: the code sample will work if you change it like this
extern "C" __declspec(dllexport) int main(int argc, char *argv[]){...}
typedef int (* LPFNDLLFUNC1)(int, char **);
You do not need GetProcAddress (...) to do this, though that approach (Option #2) is simpler once you understand how the compiler generates symbol names.
Option #1
DllMain Spawns a Main Thread
Never do anything complicated inside of DllMain, you may deadlock your software.
DLLs have their own entry-point (and exit-point and thread attach-point ... it's a really busy function). Just calling LoadLibrary (...) on your DLL causes at minimum one call to DllMain (...) for process attach.
BOOL
APIENTRY
DllMain ( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved )
You can actually treat ul_reason_for_call == DLL_PROCESS_ATTACH as a mandate to execute DllMain as if it were your program's main function.
Now, by no means should you actually start a program loop here... anytime DllMain runs it holds a very important operating system lock (DLL Loader) and you need to release that by returning for normal program operation.
That means if you want to use DllMain as your program's entry-point, it needs to spawn a thread and your original main method must not return until that thread finishes...
Option #2
DLL Exports a main Function.
Be very mindful of calling convention, the compiler will rename the symbols for you and make locating functions in a DLL with GetProcAddress less than intuitive.
In your DLL, export main:
__declspec (dllexport)
int
__cdecl main (int argc, char *argv [])
{
printf ("foobar");
return 0;
}
In your program, import main from the DLL:
// Need a typedef for the function you are going to get from the DLL
typedef int (__cdecl *main_pfn)(int argc, char *argv[]);
int main (int argc, char *argv[])
{
HMODULE hModMyDLL = LoadLibraryA ("MyDll.dll");
if (hModMyDLL != 0) {
//
// The preceding underscore deals with automatic decorations
// the compiler added to the __cdecl function name.
//
// It is possible to do away with this completely if you use a .def
// file to assign export names and ordinals manually, but then you
// lose the ability to tell a function's calling convention by its
// name alone.
//
main_pfn MyMain = (main_pfn)
GetProcAddress (hModMyDLL, "_main");
// Call the main function in your DLL and return when it does
if (MyMain != nullptr)
return MyMain (argc, argv);
}
return -1;
}
Both approaches have their merits.
Spawning a thread from DllMain avoids knowing anything at all about how the DLL you want to load is is implemented, but it also requires you to design your main function never to return -- the DLL will call ExitProcess (...).
Exporting functions and later importing them by name allows you to avoid pussyfooting around the Windows DLL loaderlock. However, if you do not use a .def file to explicitly name the exported symbols, the compiler is going to add decorations such as _... (__cdecl) or ...#n (__stdcall) to the names and you have to learn these conventions to do anything useful with GetProcAddress.
You don't have to use LoadLibrary and GetProcAddress to invoke the functionality in the DLL.
More often, you'd create your DLLs, each with its own entry point. For the moment, let's assume you want to parse the command line, choose a DLL, and invoke its entry point without arguments. You end up with something like this:
void DLL_a();
void DLL_b();
void DLL_c();
int main(int argc, char **argv) {
// we'll assume DLL_a is the default:
if (argc < 2)
DLL_a();
// For now, we'll do a *really* trivial version of parsing the command line
// to choose the right DLL:
if (argv[1][0] == 'A')
DLL_a();
else if (argv[1]][0] == 'B')
DLL_b();
else if (argv[1][0] == 'C')
DLL_c();
else {
std::cerr << "Unrecognized argument\n";
return 1;
}
}
When you link your main, you'll specify the .lib corresponding to each DLL, and you'll probably want to specify the /delayload flag to the linker. This means a DLL won't be loaded until a function in the DLL is actually invoked. If, for example, you want to distribute a reduced-functionality version of your program that only includes DLL A, it'll still be able run (without DLL B or C present on the user's system) as long as no function from DLL B or C is ever called. If you don't specify /delayload, the loader will attempt to map all the DLLs to RAM as the program starts up, run their DllMain to initialize them for use, do the same recursively for all the DLLs they depend on, etc.
/delayload has one other advantage: it avoids mapping the other DLLs to addresses at all if they're never used. It sounds like any given invocation will only use one DLL, so that's probably a win in your case.
I wrote some native C++ code with the help of the Internet that loads the .NET Runtime and invokes a method that has the signature: public static int MethodNameHere(String pwzArgument) from a class in a managed assembly.
However, I can't seem to compile the code using Visual Studio into a native DLL (64-bit), because there seems to be a linking issue with CLRCreateInstance(), even though I am including "MetaHost.h" in the .cpp source file.
Here is the entire code:
#include "MetaHost.h"
extern "C" {
__declspec(dllexport) DWORD __stdcall CallManagedMethod(LPCWSTR managedDLLPath, LPCWSTR classPathInAssembly, LPCWSTR methodName, LPCWSTR parameter) {
// Bind to the CLR runtime..
ICLRMetaHost* pMetaHost = nullptr;
CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*) &pMetaHost);
ICLRRuntimeInfo* pRuntimeInfo = nullptr;
pMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*) &pRuntimeInfo);
ICLRRuntimeHost* pClrRuntimeHost = nullptr;
pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*) &pClrRuntimeHost);
pClrRuntimeHost->Start();
// Okay, the CLR is up and running in this (previously native) process.
// Now call a method on our managed C# class library.
DWORD dwRet = 0;
pClrRuntimeHost->ExecuteInDefaultAppDomain(managedDLLPath, classPathInAssembly, methodName, parameter, &dwRet);
// Don't forget to clean up.
pClrRuntimeHost->Release();
pRuntimeInfo->Release();
pMetaHost->Release();
return dwRet;
}
}
Any help?
A .h file does not solve a linking problem, it merely adds them. The MSDN article you linked to fumbles the usual way that include and link hints are documented, "Included as a resource" is quite unhelpful. In C++ you have to link mscoree.lib to get the symbol resolved. It is the import library for mscoree.dll and included in the SDK.
Simplest way is to add #pragma comment(lib, "mscoree.lib") after your #include.
I have seen:
Convert BSTR to CHAR* and CHAR* to BSTR in C
Problems converting BSTR to char *
Convert BSTR to char*
using these question I am attempting to convert a BSTR to a char* via
#include "comutil.h"
STDMETHODIMP CServer::Initialise(BSTR strCmdFilePath,
VARIANT_BOOL bDiagErr, VARIANT_BOOL bProcErr, BSTR* RESULT)
{
char *p = _com_util::ConvertBSTRToString(strCmdFilePath);
...
}
but I am getting:
Error 1 error LNK2019: unresolved external symbol "char * __stdcall _com_util::ConvertBSTRToString(wchar_t *)" (?ConvertBSTRToString#_com_util##YGPADPA_W#Z) referenced in function "public: virtual long __stdcall CServer::Initialise(wchar_t *,short,short,wchar_t * *)" (?Initialise#CServer##UAGJPA_WFFPAPA_W#Z)
Why am I getting this error?
Your project is not linking the required library. Which is comsuppw.lib for the Release build, comsuppwd.lib for the Debug build. Do note that you can always see the required library in the MSDN article. It is annotated at the bottom of the article. "Header" tells you what you need to #include, "Lib" tells you what you need to link.
There's an easier way for this library, the best way to get the linker instruction embedded so it is automatic is by #including the .h file that contains the #pragma comment. Fix:
#include <comdef.h> // Added
#include <comutil.h>
code:
#include <cstdlib>
#include <iostream>
#include <windows.h>
using namespace std;
void calldll();
int main(int argc, char *argv[])
{
calldll();
system("PAUSE");
return EXIT_SUCCESS;
}
void calldll()
{
HINSTANCE LoadMe;
LoadMe = LoadLibrary("Trans_ATL.dll");
if(LoadMe!=0)
cout<<"loaded successfully\n";
else
cout<<"loading error\n";
/* get pointer to the functions in the dll*/
FARPROC function01 = GetProcAddress(LoadMe,"EnableLastCharTashkeel");
FARPROC function02 = GetProcAddress(LoadMe,"EnableEmphaticLAM_RAA");
FARPROC function03 = GetProcAddress(LoadMe,"SetText");
FARPROC function04 = GetProcAddress(LoadMe,"GetResult");
typedef void (__stdcall * pICFUNC01)(bool);
typedef void (__stdcall * pICFUNC02)(bool);
typedef bool (__stdcall * pICFUNC03)(string);
typedef string (__stdcall * pICFUNC04)(string);
pICFUNC01 EnableLastCharTashkeel_function;
EnableLastCharTashkeel_function = pICFUNC01(function01);
pICFUNC02 EnableEmphaticLAM_RAA_function;
EnableEmphaticLAM_RAA_function = pICFUNC02(function02);
pICFUNC03 SetText_function;
SetText_function = pICFUNC03(function03);
pICFUNC04 GetResult_function;
GetResult_function = pICFUNC04(function04);
EnableLastCharTashkeel_function(true);
EnableEmphaticLAM_RAA_function(true);
FreeLibrary(LoadMe);
}
in this code i call a dll it load successfully but when i try to use any function it compile without any errors but at the line
EnableLastCharTashkeel_function(true); (first call for a function)
it froozes and give me the following
Unhandled exception at 0x00000000 in test_trans_new.exe: 0xC0000005: Access violation reading location 0x00000000.
i guess that this becuse the function pointer point to NULL but i don't know how to fix it
i use visual c++ 2010
thanks in advance
thank you for all your replies which are realy helpfull but the problem still ocurrs but i approximately know the reason if i correct the problem is that the functions i try to access are of type COM so any idea about using this type
thanks in advance
FARPROC function01 = GetProcAddress(LoadMe,"EnableLastCharTashkeel");
That's a guaranteed NULL. Calling it does go kaboom, you didn't check if the function succeeded. The exported function is not named "EnableLastCharTashkeel". A more likely string is "?EnableLastCharTashkeel##YAX_N#Z". That's the name of the function after the C++ compiler mangled it, a trick to support overloaded functions.
You can declare the function extern "C", that suppresses name mangling and makes the function name "_EnableLastCharTashkeel". Note the leading underscore, used by the 32-bit compiler to mark that the function uses the __cdecl calling convention. To be sure, run Dumpbin.exe /exports on your DLL from the Visual Studio Command Prompt, it shows the exported names.
It's most likely 0 because the symbol you were trying to find in the DLL wasn't found, which would suggest that (a) it's either not there or (b) there might be a typo in the function name or (c) the function name might be mangled because it's being exported as a decorated name. This happens quite a lot in C++...
Unless the library exporting those four functions is under your control, use dumpbin /EXPORTS and have a look at the correct spelling of the symbols.