winapivisual-c++side-by-sideregfreecomactivation-context-api

Is it correct to load the assembly manifest directly into the application context?


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:

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.


Solution

  • 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

    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

    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.