views:

161

answers:

1

Background
I'm maintaining a plugin for an application. I'm Using Visual C++ 2003.

The plugin is composed of several DLLs - there's the main DLL, that's the one that the application loads using LoadLibrary, and there are several utility DLLs that are used by the main DLL and by each other.
Dependencies generally look like this:

  • plugin.dll -> utilA.dll, utilB.dll
  • utilA.dll -> utilB.dll
  • utilB.dll -> utilA.dll, utilC.dll

You get the picture.

Some of the dependencies between the DLLs are load-time and some run-time.

All the DLL files are stored in the executable's directory (not a requirement, just how it works now).

The problem
There's a new requirement - running multiple instances of the plugin within the application.
The application runs each instance of a plugin in its own thread, i.e. each thread calls functions exported by plugin.dll. The plugin's code, however, is anything but thread-safe - lots of global variables etc..

Unfortunately, fixing the whole thing isn't currently an option, so I need a way to load multiple (at most 3) copies of the plugin's DLLs in the same process.

Option 1: The distinct names approach
Creating 3 copies of each DLL file, so that each file has a distinct name. e.g. plugin1.dll, plugin2.dll, plugin3.dll, utilA1.dll, utilA2.dll, utilA3.dll, utilB1.dll, etc.. The application will load plugin1.dll, plugin2.dll and plugin3.dll. The files will be in the executable's directory.

For each group of DLLs to know each other by name (so the inter-dependencies work), the names need to be known at compilation time - meaning the DLLs need to be compiled multiple times, only each time with different output file names.

Not very complicated, but I'd hate having 3 copies of the VS project files, and don't like having to compile the same files over and over.

Option 2: The side-by-side assemblies approach
Creating 3 copies of the DLL files, each group in its own directory, and defining each group as an assembly by putting an assembly manifest file in the directory, listing the plugin's DLLs.
Each DLL will have an application manifest pointing to the assembly, so that the loader finds the copies of the utility DLLs that reside in the same directory. The manifest needs to be embedded for it to be found when a DLL is loaded using LoadLibrary. I'll use mt.exe from a later VS version for the job, since VS2003 has no built-in manifest embedding support.

I've tried this approach with partial success - dependencies are found during load-time of the DLLs, but not when a DLL function is called that loads another DLL.
This seems to be the expected behavior according to this article - A DLL's activation context is only used at the DLL's load-time, and afterwards it's deactivated and the process's activation context is used.

Edit: Works with ISOLATION_AWARE_ENABLED as expected - runtime loading of DLLs uses the original activation context of the loading DLL.

Questions
Got any other options? Any quick & dirty solution will do. :-)

Will ISOLATION_AWARE_ENABLED even work with VS2003? Edit: It does.

Comments will be greatly appreciated.

Thanks!

A: 

ISOLATION_AWARE_ENABLED is implemented by the Windows SDK header files and thus probably wont worth with VS2003 at all. However, it is possible to download the latest Windows 7 SDK and use that with VS2003.

You don't need to use MT to link in manifests. Manifests can be embedded as resources in environments that dont have explicit knowledge.

Add the following to a dll's .rc file to embed a manifest. (With a recent enough platform sdk RT_MANIFEST should already be defined):

#define RT_MANIFEST 24 
#define APP_MANIFEST 1
#define DLL_MANIFEST 2

DLL_MANIFEST RT_MANIFEST dllName.dll.embed.manifest
Chris Becke
ISOLATION_AWARE_ENABLED actually does work with VS2003, I guess the SDK that shipped with it was recent enough to include winsxs support.I wasn't aware of embedding manifests using the .rc file - thanks for the info.
george