Short version: How can an MFC ActiveX control loaded into a web page by Internet Explorer guarantee that its associated DLLs are loaded from its own directory, rather than picking up identically-named DLLs that might already be loaded into the process?
Long version, with gory detail: I have an application myapp.exe
that uses a set of DLLs: one.dll
, two.dll
and three.dll
.
The same DLLs are also used by an MFC ActiveX control that exposes some of the same functionality as myapp.exe
, so there's a mycontrol.ocx
that also links with those DLLs. The ActiveX control is associated with the application/myapp
MIME type, so that IE will use it to display documents created with myapp.exe
.
It's possible to have both versions 1 and 2 of myapp.exe
installed, but only the most recent version of mycontrol.ocx
(version 2) is associated with the application/myapp
MIME type:
c:\Program Files\MyApp\Version 1\
myapp.exe
mycontrol.ocx
one.dll
two.dll
three.dll
c:\Program Files\MyApp\Version 2\
myapp.exe
mycontrol.ocx <-- registered with the MIME type
one.dll
two.dll
three.dll
Here's where it it gets difficult: myapp.exe
has an embedded Internet Explorer control for displaying web content. You can run version 1 of myapp.exe
, point that embedded Internet Explorer at an application/myapp
document, and IE will load up version 2 of mycontrol.ocx
to view it. This ought to be fine, but it's not:
What happens is that Windows loads mycontrol.ocx
, sees that it has a dependency on one.dll
and that there's already a one.dll
in the process, and points the import table of mycontrol.ocx
with the already-loaded (version 1) one.dll
, rather than loading version 2 of one.dll
. This fails because version 2 of mycontrol.ocx
uses new APIs in version 2 of one.dll
that weren't there in version 1.
How do I stop it doing that? If one.dll
weren't already loaded, Windows would look in c:\Program Files\MyApp\Version 2
for it, and all would be well. (And I can't rename all my modules for every version of the software!)
Failed solution #1: I gave mycontrol.ocx
a manifest that specifies <file ...>
elements for all the DLLs, but that doesn't work. one.dll
gets loaded from the Version 2
directory, but two.dll
doesn't. I assume this is because two.dll
is being loaded as a result of one.dll
referencing it, and one.dll
doesn't have such a manifest.
Failed solution #2: So I added a manifest to all the DLLs, each listing its dependncies in <file ...>
elements. But that broke myapp.exe
completely, because MFC now treats each DLL as having its own activation context and that's not right - there should be one MFC context for the whole process (in the case of myapp.exe
) or the whole instance of the control (in the case of mycontrol.exe
). I can't have a new activation context for each module; I need one for the whole of mycontrol.ocx
and its attendant DLLs.
I changed all the manifests to use the same name=
attribute, in the hope that that would put them all into the same context, but that had no effect.
Failed solution #3: I gave myapp.exe
a manifest that said <file name="mycontrol.ocx"/>
in the hope of forcing version 1 of the app to use version 1 of the control, which would be fine. But that fails because when Internet Explorer loads mycontrol.ocx
it calls LoadLibrary
with the full path to version 2 of mycontrol.ocx
, and manifest redirection doesn't work when modules are loaded using a full path.
Something I can't do: I can't change the code that loads the control, because it's Internet Explorer doing that (via the MIME type).
Any solutions, suggestions or simple messages of sympathy will be gratefully received.