3

I'm currently trying to get a rather tangled scheme running with registration free COM.

It's not that it is not working, it's that I have hit a kind of confusing situation, where it seems I should active the manifest of the assembly dependency directly in the application context, rather than have the application context point at the dependent assembly.

It is rather easy to explain by the example project MS themselves publish:

Normally, you have an application, an app manifest, a (server-)dll and it's assembly manifest. These correspond to what the example gives:

  • client.exe
  • client.exe.manifest (This one points to SideBySide.X as dependentAssembly)
  • SideBySide.dll
  • SideBySide.X.manifest

Now, one standard case is to embed the client application manifest inside the client executable, and then use the DLL and its external manifest file.

Now, if for whatever reason the correct application manifest isn't known at compile time, you can load a manifest file at runtime via the Activation Context API.

And this is where it gets confusing:

According to the article, the client application now directly switches its Activation Context to the assembly manifest:

If you look at the _tmain function in client.cpp ... a new section of code that initializes the activation context as follows:

actCtx.lpSource = "SideBySide.X.manifest";

I have cross checked this, and it would also work to dynamically load a file that contains the info from client.exe.manifest, i.e. just the reference to SideBySide.X, and continue with this Activation Context - which would also correspond to the ActCtx in use when we embed a correct application manifest into the executable.

That is, actCtx.lpSource = "client.exe.manifest"; would also work.

TL;DR What is the implication, if any, of directly activating an Activation Context "containing" an assembly manifest inside application code.

Is this how it's supposed to be done when loading manifests from files? (And if so, why can't we directly embed the assembly manifest into the executable, when it is known at compile time.)


Note: (This should really be a comment to @Eric Brown's answer, but it's getting rather lengthy)

The linked article does a decent job of explaining the two RT_MANIFESTresource types, but with regard to regFreeCOm, it leaves a few loose ends. I'll throw in some quotes that jumped at me:

ISOLATIONAWARE_MANIFEST_RESOURCE_ID is used primarily for DLLs. It should be used if the dll wants private dependencies other than the process default. ... the NT library loader checks to see if the dll has a resource of type RT_MANIFEST, ID ISOLATIONAWARE_MANIFEST_RESOURCE_ID. If it does, the loader calls CreateActCtx with the resource, and use the generated activation context to probe the dll's static dependencies.

What I understand this to mean is that the only point of RT_MANIFEST/2 is for the static DLL dependency loader to find the correct resource to use for resolving DLL dependencies. (Not COM dependencies, see below.)

Sometimes, you want to use the activation context outside of probing the dll's static dependencies. You can define macro ISOLATION_AWARE_ENABLED when you compile the module.

When ISOLATION_AWARE_ENABLED is defined, Windows re-defines certain APIs. For example LoadLibraryExW is redefined to IsolationAwareLoadLibraryExW.

... Not all APIs affected by activation context are wrapped. For example, ..., and neither is any of the COM APIs.

So, to sum up: I think the RT_MANIFEST mechanism is mostly orthogonal to regFreeCOM as COM doesn't care at all where it's activation context comes from and there is no built-in help for regFreeCOM wrt. Isolation Awareness.

Martin Ba
  • 33,741
  • 27
  • 150
  • 304

1 Answers1

4

Yes, this is how it's supposed to be done, and you can embed the assembly manifest into the executable (well, the resource section). That's what the RT_MANIFEST resource type is for. There are two default types of manifest resources

  • Process manifests, with ID CREATEPROCESS_MANIFEST_RESOURCE_ID (1), used during process creation,
  • Isolation-Aware manifests, with ID ISOLATIONAWARE_MANIFEST_RESOURCE_ID (2), used during DLL loading.

There are a couple of uses (primarily around Click-once deployment) that illustrate the ability to embed registration-free COM manifests in subsidiary DLLs, using RT_MANIFEST. In particular, if a DLL has a CREATEPROCESS_MANIFEST_RESOURCE_ID, that manifest will be used as well.

An example seems like a good thing here.

Given

  • client.exe
  • sidebyside.dll

If sidebyside.dll has an RT_MANIFEST resource with ID 1 (CREATEPROCESS_MANIFEST_RESOURCE_ID) which has the appropriate registration-free COM entries in it, and client.exe has an RT_MANIFEST resource with ID 1 that has a <file> entry for sidebyside.dll, then Win32 will automatically handle the registration-free COM management.

Part 8 of the example article strongly implies this, and I've seen it done in a number of in-house projects.

Ajay
  • 16,823
  • 9
  • 50
  • 94
Eric Brown
  • 13,308
  • 7
  • 28
  • 67
  • "...you *can* embed the assembly manifest into the executable ..." - Yeah, I can embed it, but it won't be used for the [default activation context for the process](http://blogs.msdn.com/b/junfeng/archive/2007/06/26/rt-manifest-resource-and-isolation-aware-enabled.aspx#CREATEPROCESS_MANIFEST_RESOURCE_ID) as far as I understand. – Martin Ba Oct 15 '13 at 20:30
  • See my rather lengthy note in the q. What it tries to say in too many words is: Everything you wrote after "*Yes, this is how it's supposed to be done*" does not seem to apply to regFreeCOM :-) - Your answer was very helpful as it made me re-read the article with the correct emphasis again, it would be stellar if you could elaborate on "*Yes, this is how it's supposed to be done*" ;-) – Martin Ba Oct 15 '13 at 20:53
  • @MartinBa See extremely long update to answer. I hope this is elaborate enough. – Eric Brown Oct 15 '13 at 23:26
  • I will note one thing: When I create a DLL prj in VS2005, a manifest for the CRT libs will automatically be embedded into the DLL. (implicitly via `mt.exe`) This manifest will be at ID 2 (ISOLATIONAWARE). The DLL normally hasn't got RT_MANIFEST/1 (of course I could embed one manually). The example article doesn't talk about *where* (ID 1 or 2) to embed the manifest, so maybe it works both ways, i.e. it doesn't matter if RT_MANIFEST #1 or #2 for [embed your assembly manifest in your assembly as an RT_MANIFEST resource](http://msdn.microsoft.com/en-us/library/ms973913.aspx#rfacomwalk_topic10). – Martin Ba Oct 16 '13 at 07:44
  • Looking over the in-house projects, some use ID 1, some use ID 2 for the DLLs. I can't find details on which one is required, unfortunately. – Eric Brown Oct 16 '13 at 16:53
  • The amazing thing here really is, that an article entitled "A Walkthrough" seems to be my (our?) primary source of documentation on all this mess. :-) – Martin Ba Oct 17 '13 at 09:03
  • @MartinBa - it's a handy (and public) resource. I can't point to private inhouse projects (for obvious reasons). – Eric Brown Oct 17 '13 at 17:15
  • I was more commenting on the lack of good and exhaustive reference-type docs from MS. The article is really good, but still it's a walk through type thing and leaves some holes. – Martin Ba Oct 17 '13 at 19:43