An unmanaged C ++ library of the same name coexisting in one process

Using Visual Studio C ++ V10, I am trying to figure out how to create a DLL and resolve a DLL namespace conflict. Here are the details.

Company S ships a product called M.EXE . Suppose that M.EXE set to \S\BIN\M.EXE . Company S statically references a DLL called U.DLL , which is installed in \S\BIN\U.DLL . U.DLL contains open source code and is built with Visual C ++ /Zc:wchar_t- compiler options, which does not recognize wchar as a native type.

Company C sends a DLL called O.DLL and publishes an API for this DLL and sends an import library for O.DLL . Assume O.DLL installed in \C\BIN\O.DLL . O.DLL statically refers to a DLL called U.DLL , which is installed in \C\BIN\U.DLL . U.DLL built on the same open source code, but built with Visual C ++ /Zc:wchar_t compiler options /Zc:wchar_t , which recognizes wchar_t as a native type.

Ideally, company C and company S will agree to create U.DLL using the same Visual C ++ features, but this is not possible.

M.EXE from company S is expanding because I can create my own DLL in unmanaged C ++, call it NODE.DLL , which M.EXE is called if I configure everything correctly. I would like to build NODE.DLL so that it statically binds to O.DLL from company C. But the problem is that after running M.EXE it loaded the U.DLL library from \S\BIN , and the characters from \S\BIN\U.DLL slightly different from those specified in \C\BIN\U.DLL , due to how U.DLL was built by each company. Therefore, when M.EXE tries to load NODE.DLL , it fails, because when NODE.DLL loads O.DLL , which requires U.DLL , the characters needed from \C\BIN\U.DLL do not exist, since Windows sees U.DLL as it is already loading.

The situation diagram is as follows:

 M.EXE static link to -> \S\BIN\U.DLL M.EXE dynamic link to -> NODE.DLL NODE.DLL static link to O.DLL O.DLL static link to \C\BIN\U.DLL 

In fact, I need \S\BIN\U.DLL and \C\BIN\U.DLL coexist in the same process space and M.EXE use their version of U.DLL and O.DLL to use their version of U.DLL .

Please note that I have no way to rebuild M.EXE or O.DLL to change how each U.DLL download U.DLL . They come from third parties, so static links cannot be changed. I also have no way to use LoadLibrary on O.DLL , because it is a C ++ library equipped with an import library.

I believe that manifests can be used so that when I build NODE.DLL statically linked to O.DLL, I set things up in the NODE.DLL manifest NODE.DLL that O.DLL its own copy of U.DLL , which is set to \C\BIN\U.DLL . I just can't figure out how to do this. Ideally, I would not want to modify the O.DLL manifest, but if this is the only solution, I will live with it.

+6
source share
4 answers

In the same process, you can have multiple DLLs with the same file name by loading one or more of them using absolute paths. This requires dynamic loading of the DLL, but the behavior is otherwise identical.

Instead of binding during the build process, you need std::string moduleName = appPath + "\s\bin\u.dll"; LoadModule(moduleName.c_str()) std::string moduleName = appPath + "\s\bin\u.dll"; LoadModule(moduleName.c_str()) . Since this is unambiguous regarding loading a DLL, it allows you to load multiple with the "same" name.

Once you load the module, you can assign each of the necessary functions to function pointers, then either wrap them, or use the legal but underused syntax of call function pointers as regular functions ( funcPtr(params) ).

If you are using a later version of Windows, you can use DLL manifests to strengthen version / name control modulo and force the EXE to load a different DLL than usual. I am not familiar with how exactly this will be done, although it is documented on MSDN (and probably here as well).

+3
source

You can resolve the source DLL programmatically in runtiome using the linker parameter / delayload linker (Linker / Input / Delay Loaded DLL in the properties of the VS project) along with the user connection. In one of your source files, you need to define and register the hookload delayload function. In the hooked dliNotePreLoadLibrary notification handler, just call LoadLibrary with an explicit path to the desired DLL, then pass the HMODULE DLL back to the delay code. The delayload code will allow the imported functions to the DLLs that you give, regardless of whether another DLL with the same name is loaded into this process.

At the top of my head, your hook will look something like this (where MyCustomLoadLibrary needs to be replaced with code that calls LoadLibrary with the full path to the desired DLL in the conflicting case or just an unqualified file name otherwise):

 #include <delayimp.h> FARPROC WINAPI MyDliNotifyHook( unsigned dliNotify, PDelayLoadInfo pdli ) { if( dliNotify == dliNotePreLoadLibrary ) return (FARPROC)MyCustomLoadLibrary( pdli->szDll ); return NULL; } extern "C" PfnDliHook __pfnDliNotifyHook2 = MyDliNotifyHook; 
+1
source

Try using LoadLibrary and GetProcAddress. This will require restructuring your code to use function pointers everywhere. Cm:

MSDN Webpage for LoadLibrary

0
source

You are fortunate that U.DLL is Open Source. You will need to create a version that supports the functions /Zc:wchar_t- and /Zc:wchar_t . The first option simply defines wchar_t- as unsigned short . You will get a ton of linker warnings for duplicate characters for every function that doesn't have the wchar_t argument, but otherwise you just get a thicker DLL.

Remember that if there are global or static variables using wchar_t , then you will also have two copies. But you will have the same effect if you executed two copies of U.DLL in one process.

0
source

All Articles