Without registration, COM doesn't play well with single threaded objects. Activation context was disabled during marshaling

I am working on integrating a COM / CLI based library into a Java based application via JNI (yes it is a bit of a mess). For the most part, it works, but I hit a little bit about how activation contexts interact with single threaded COM objects. The situation I can summarize with the code snippet below.

// This function, workGlue, will be called from an MTA thread.
int workGlue(int foo)
{
    ULONG_PTR cookie;
    ActivateActCtx(myActivationContext, &cookie);

    // The doWork function is part of an external library.
    // Internally it will call CoCreateInstance to create
    // a single threaded COM object which needs to be looked up
    // in the activation context.
    int result = doWork(foo);

    DeactivateActCtx(0, cookie);
    return result;
}

      

Deploying the library and application forces me to use registration-free COM access. Also, since the main application is written in Java, I cannot connect the manifest resource to the exe file or something. Hence, I need to use the COM activation context mechanism so that the library can search for its COM classes. Also, the library itself is single threaded, so it requires an STA. My application, however, will call the library from all kinds of threads.

From what I understand, COM will deploy a new "default STA thread" the first time CoCreateInstance is called from the MTA thread if the object being created is single-threaded. The actual object is then created in the default STA, and the return value of CoCreateInstance will then be the proxy object that takes the method call back and forth by the default STA. It's okay and I want it to work.

My problem occurs when my code is not the first one that causes the default STA thread to start. It looks like even though object creation is tied to STA by default, the current activation context is not. The default STA is stuck with the activation context that was active at the time it was created. For me, this means that if I am not the first to initialize the default STA initialization, my calls to CoCreateInstance will fail as the default STA is unaware of my activation context. This is a great enterprise app and I can't be sure my code will be the first to call CoCreateInstance, even if it might seem like a fragile decision to me.

Thus, I need one of the following:

  • The default way to bind activation context to STA.

  • A way to create a new STA with the correct activation context in which my objects will live, and calls to CoCreateInstance and method should be merged into this STA instead of the default STA.

  • Rebuild my integration to make sure all calls to the problematic library are from the same STA that I manage to avoid the marshaling step. This is my backup plan, but I believe there should be an easier way.

+3


source to share





All Articles