How to re-route std::clog in another CRT lib? - c++

I have a Win32 program that's built with VS2008, so my code is linked with MSVCR90.DLL and MSVCP90.DLL. However, it's also running code in a DLL (which I can't modify) that's been built with VS2005 and when code in that DLL prints to the clog stream it does it via MSVCR80.DLL and MSVCP80.DLL. Here's the problem: if I re-route std::clog in my code, I only affect code built against crt 9.0 libs, code using the older crt 8.0 wont have its output re-routed. So is there a way to re-route the clog stream in a DLL built against an older CRT?
I've investigated calling GetModuleHandle() and GetProcAddress() on the older CRT DLLs and have managed to re-route the C stderr stream (via _open_osfhandle and _dup2), however the C++ clog stream still seems to be unaffected. I think I also need to call ios_base::sync_with_stdio() in the older CRT lib but I couldn't get a valid address to that function. Any help would be greatly appreciated.
Thanks.

Build a helper DLL using VS2005 - This DLL should simply export some functions to do the setup you need for VS8 runtime.

Try also freopen... but this too might need to be called in the older CRT. Eric's suggestion of a helper DLL is massive overkill though, just use GetProcAddress to get a pointer to the VC8 version.
The most effective option is to redirect the standard streams when launching the process in the first place.
Another possibility is to delay-load the helper DLL, and perform the stream redirection before loading it. That way when MSVCRT80 loads, it will attach to the redirected stream.

Related

How to prevent DLL from loading other standard DLLs?

I was experimenting with DLL injection via CreateRemoteThread() (see my other question for details). I injected it into CMD.exe process (note, not the conhost.exe process). The thing is, I noticed that it actually loads 8 other Windows DLLs along with it. It loads them even if I never use any functions from those DLLs.
Now I wonder, is there a way to prevent this? My only guess for now is to not include <windows.h>, then copy definitions for most macros and load libraries that are actually needed via calls to LoadLibrary(). Yet, I guess, it's not the most elegant solution.
Maybe there is some well established method of preventing standard satellite DLL loads?
An option for cases where you only occasionally rely on a particular library is to treat it as delay-loaded.
In Visual Studio, this setting is found in the project properties window under Linker -> Input.
So, for example, if you expect to only sometimes call something from user32.dll you could add "user32.dll" to the Delay Loaded DLLs line (note that this does take .dll not .lib as for input libraries).

Does DLL linking on windows results in GetProcAddress on runtime?

I'm curious about how Dynamic Linking works on windows. Since we CAN NOT link to a directly, windows usually link your executable to a LIB file which contains the stub of functions exported by the DLL. Does this type of linking results in LoadLibrary and GetProcAddress at runtime? If not, how does the linking work internally?
The answer is maybe.
The default method is to create an Import Table, which lists all required DLL's and the functions used from there. This table is parsed directly by the OS. It will probably reuse some of the same code behind LoadLibrary for that. It most likely will not use the code from GetProcAddress but prefer to do a single bulk lookup of all necessary functions.
However there's an MSVC feature called delay-loading. With this feature, MSVC++ will not build such an import table, but insert actual LoadLibrary and GetProcAddress calls. The benefit is that these calls are made at the latest possible moment. While you don't need a particular DLL, it's not loaded. This can accelerate program start up.

How to run without a dependent DLL when that DLL is not used?

I have a VC++ application compiled against a third party DLL (using their LIB file, of course).
The thing is that not every scenario involves the code of that DLL, but Windows refuses to start the application, if the particular DLL is missing.
I am wondering, how can I workaround this constraint. I would like the application to crash only if the aforementioned DLL is really needed.
Please, ignore the question, whether it is a good taste when an application crashes after it has successfully started - I will take care of it.
How can I defer the DLL resolution until that DLL actually needs to be loaded?
Thanks.
See the /DELAYLOAD linker option:
The Visual C++ linker now supports the delayed loading of DLLs. This relieves you of the need to use the Windows SDK functions LoadLibrary and GetProcAddress to implement DLL delayed loading.
Before Visual C++ 6.0, the only way to load a DLL at run time was by using LoadLibrary and GetProcAddress; the operating system would load the DLL when the executable or DLL using it was loaded.
Beginning with Visual C++ 6.0, when statically linking with a DLL, the linker provides options to delay load the DLL until the program calls a function in that DLL.
An application can delay load a DLL using the /DELAYLOAD (Delay Load Import) linker option with a helper function (default implementation provided by Visual C++). The helper function will load the DLL at run time by calling LoadLibrary and GetProcAddress for you.

Writing a DLL that loads msvcr80.dll and exposes the free()-function

I have a third-party DLL that depends on MSVCR80 and allocates resources that I need to cleanup. The library does not expose a free-function for doing this. Instead, I need to load the same runtime library and manually call the free function.
As a workaround I'm trying to write a "wrapper" DLL that loads the correct runtime and exposes the free function. This DLL is created using Visual Studio 2010 and is dependent on a separate runtime library. Doing LoadLibrary("msvcr80.dll") fails with error R6034 which I guess is because of manifest issues.
Is it even possible to load msvcr80.dll using LoadLibrary? Do I need to create a manifest, embed it into the DLL and store msvcr80.dll in the same directory as my wrapper DLL?
I realize that this is a flaw in the third-party library, but I'm pretty much stuck with this version. Getting the vendor to fix this is most likely not an option.
Probably there are better solutions, but in case everything else failed you could find somewhere a copy of VC++ 2005 Express Edition (=free, no piracy is needed ;) ), which uses the version 8.0 of the compiler, and thus the same runtime of the defective dll.
Then you would build your wrapper dll with it, which would just call the free provided by its CRT (double check that you're using the dll version!).

Returning C++ objects from Windows DLL

Due to how Microsoft implements the heap in their non-DLL versions of the runtime, returning a C++ object from a DLL can cause problems:
// dll.h
DLL_EXPORT std::string somefunc();
and:
// app.c - not part of DLL but in the main executable
void doit()
{
std::string str(somefunc());
}
The above code runs fine provided both the DLL and the EXE are built with the Multi-threaded DLL runtime library.
But if the DLL and EXE are built without the DLL runtime library (either the single or multi-threaded versions), the code above fails (with a debug runtime, the code aborts immediately due to the assertion _CrtIsValidHeapPointer(pUserData) failing; with a non-debug runtime the heap gets corrupted and the program eventually fails elsewhere).
Two questions:
Is there a way to solve this other then requiring that all code use the DLL runtime?
For people who distribute their libraries to third parties, how do you handle this? Do you not use C++ objects in your API? Do you require users of your library to use the DLL runtime? Something else?
Is there a way to solve this other then requiring that all code use the DLL runtime?
Not that I know of.
For people who distribute their libraries to third parties, how do you handle this? Do you not use C++ objects in your API? Do you require users of your library to use the DLL runtime? Something else?
In the past I distributed an SDK w/ dlls but it was COM based. With COM all the marshalling of parameters and IPC is done for you automatically. Users can also integrate in with any language that way.
Your code has two potential problems: you addressed the first one - CRT runtime. You have another problem here: the std::string could change among VC++ versions. In fact, it did change in the past.
The safe way to deal with is to export only C basic types. And exports both create and release functions from the DLL. Instead of export a std::string, export a pointer.
__declspec(export) void* createObject()
{
std::string* p = __impl_createObject();
return (void*)p;
}
__declspec(export) void releasePSTRING(void* pObj)
{
delete ((std::string*)(pObj));
}
There is a way to deal with this, but it's somewhat non-trivial. Like most of the rest of the library, std::string doesn't allocate memory directly with new -- instead, it uses an allocator (std::allocator<char>, by default).
You can provide your own allocator that uses your own heap allocation routines that are common to the DLL and the executable, such as by using HeapAlloc to obtain memory, and suballocate blocks from there.
If you have a DLL that you want to distribute and you don't want to bind your callers to a specific version to the C-Runtime, do any of the following:
I. Link the DLL to the static version of the C-Runtime library. From the Visual Studio Project Properties page, select the tab for Configuration Properties-> C/C++ -> Code Generation. These an option for selecting the "Runtime library". Select "Multithread" or "Multithreaded Debug" instead of the DLL versions. (Command line equilvalent is /MT or /MTd)
There are a couple of different drawbacks to this approach:
a. If Microsoft ever releases a security patch of the CRT, your shipped components may be vulnerable until your recompile and redist your binary.
b. Heap pointers allocated by "malloc" or "new" in the DLL can not be "free"d or "delete"d by the EXE or other binary. You'll crash otherwise. The same holds true for FILE handles created by fopen. You can't call fopen in teh DLL and expect the EXE to be able to fclose on it. Again, crash if you do. You will need to build the interface to your DLL to be resilient to all of these issues. For starters, a function that returns an instance to std::string is likely going to be an issue. Provide functions exported by your DLL to handle the releasing of resources as needed.
Other options:
II. Ship with no c-runtime depedency. This is a bit harder. You first have to remove all calls to the CRT out of your code, provide some stub functions to get the DLL to link, and specify "no default libraries" linking option. Can be done.
III. C++ classes can be exported cleanly from a DLL by using COM interface pointers. You'll still need to address the issues in 1a above, but ATL classes are a great way to get the overhead of COM out of the way.
The simple fact here is, Microsofts implementation aside, C++ is NOT an ABI. You cannot export C++ objects, on any platform, from a dynamic module, and expect them to work with a different compiler or language.
Exporting c++ classes from Dlls is a largely pointless excercise - because of the name mangling, and lack of support in c++ for dynamically loaded classes - the dlls have to be loaded statically - so you loose the biggest benefit of splitting a project into dlls - the ability to only load functionality as needed.