SXS Activation Context --- Activate and Deactivate

In Windows XP the Side-by-Side technology is officially introduced:

https://msdn.microsoft.com/library/default.asp?url=/library/en-us/sbscs/setup/isolated_applications_and_side_by_side_assemblies_start_page.asp

In a nutshell, applications/components write data to a special XML file called Sxs Manifest File. Later the data can be retrieved by various components in application or OS. Different components use their own manifests so they don’t interfere with other components. For details please refer to the MSDN document.

Today there are three kinds of data can be described in Sxs manifest files:

1. File redirection, used for LoadLibrary

2. COM class registration, for inproc COM

3. Window class registration, for CreateWindow/Ex

In the future more information may be enabled in Sxs manifests.

Activation Context is the runtime data structure to maintain the data in Sxs manifests. It is the boundary for Sxs data isolation. When components (for example, nt library loader, COM, User32) look up their registration data, the search is performed in the following order:

1. The most recent activated Activation Context

2. The process default Activation Context

3. The system default Activation Context

CreateProcess automatically creates a process default Activation Context if the application has a Sxs manifest, either as an external file as app.exe.manifest, or as internal Win32 resource of type RT_MANIFEST, ID 1.

Activation Context can also be created by calling API CreateActCtx.

(The system default Activation Context is not interesting. It only exists for backward compatibility reason.)

To activate/deactivate an ActivationContext, call ActivateActCtx/DeactivateActCtx.

Since components search their data in the most recent activated Activation Context, care is neede to be taken when using Sxs technology.

1. Be sure to call ActivateActCtx when entering your isolation boundary so that you don’t read data from other people’s activation context. .

2. Be sure to call DeactivateCtx when leaving your isolation boundary so that you don’t pollute other people’s activation context.

To enforce this rule, Sxs maintains activation contexts in a way like a stack:

1. ActivateActCtx pushes the activation context to the top of the stack, and it becomes the most recent activated activation context.

2. DeactivateActCtx pops the activation context from the top of the stack, and the next one in the stack becomes the most recent activated action context.

3. On deactivation, Sxs checks to see if the activation context to be deactivated is on the top of the stack or not. If it is not the top of the stack, Sxs throws one of the following two exceptions:

a. If the activation context is on the stack, but not the top of the stack, Sxs throws exception STATUS_SXS_EARLY_DEACTIVATION (0xC015000F), with the message “The activation context being deactivated is not the most recently activated one.”

b. If the activate context can not be found in the stack, exception STATUS_SXS_INVALID_DEACTIVATION (0xC0150010) is thrown, with the message “The activation context being deactivated is not active for the current thread of execution.”

You may see those two exceptions occasionally. The most likely reason is that someone calls ActivateActCtx on entrance, but forgets to call DeactivateActCtx on exit.

To ensure that this never happen in your code, use __try/__finally:

ActivateActCtx(hActCtx, &dwCookie);
__try
{

}
__finally {
DeactivateActCtx(0, dwCookie);
}

If you don’t clean up the activation context stack correctly, someone on top of you may try to clean up their stack, and end up with the deactivation exceptions.