2
votes

Suppose we have an in-process server. The client thread is in the MTA, but the object is not free-threaded (i.e. lives in an STA).

Does CoGetClassObject create the class object in the MTA, or in a new STA?

Does a class object always create objects in the same apartment that the class object resides, or can it create them in other apartments?

1

1 Answers

4
votes

So your COM server is in-process COM class marked as "apartment" threaded and you are instantiating it from MTA thread.

Your CoGetClassObject (or CoCreateInstance) call does the following:

  • using the CLSID passed, COM detects the server needs STA and the caller is MTA
  • STA is created if needed, that is if the process does not have STA to use use, COM creates a worker thread
  • COM loads the server DLL if necessary and calls DllGetClassObject on the STA thread
  • COM creates proxy/stub pair for the obtained class factory and passes control back to the caller thread
  • the MTA callers receive IClassFactory* interface pointer, which points to proxy and not to real factory; the proxy takes calls on its MTA end to transfer them into native STA of the server
  • further client calls are received on MTA threads and are internally passed to the STA thread, where the real class factory calls takes place and then real instantiation occurs (marhsaling)

COM will do its best to transfer all [legal] calls to the mentioned STA. If you find ways to fool it, e.g. you obtain direct pointer to class factory in your MTA code (via GetModuleHandle, GetProcAddress, DllGetClassObject OR getting the pointer on STA then passing it to MTA without marshaling), it WILL work on the start even though might have some unexpected behavior. Once in while later when/if you reach a call through proxy, you will get RPC_E_WRONG_THREAD error. That is, you are in general interested to comply with COM rules even though sometimes their violation do not result in failures immediately.