Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define a COM class that is only createable from the same EXE where it is registered

  1. If have an EXE with a STA in the main thread
  2. Inside the EXE a second thread with another STA is created.
  3. This second thread with the STA should publish a class factory with CoRegisterClassObject that is only available from this process.

When I use CoRegisterClassObject with CLSCTX_INPROC_SERVER and REGCLS_MULTIPLEUSE the main thread creates the object with CLSCTX_ALL I get the error "class not registered".

When I use CoRegisterClassObject with CLSCTX_LOCAL_SERVER and REGCLS_MULTIPLEUSE the main thread can create the object. But the next instance of the program will create the object inside the first process.

Using CLSCTX_INPROC flag inside CoCreateInstance will always say that the class is not registered.

BTW: Because I register the class by my own always when the program is started there are no registry keys except the required one the the typelib.

More detailed explanation why I need this: The created class uses pointers and function internally created in the context of the EXE. Just think that I am programming an "Application" object that should support only functions inside this process and files and objects managed by this session. And I need this COM object because it is used inside a VBScripting Host and is again exposed to other COM objects.

Is there a way to registering a class factory that only support creation from inside my EXE?

like image 621
xMRi Avatar asked Jul 28 '14 10:07

xMRi


1 Answers

The problem here is CLSCTX_INPROC_SERVER makes the registration "visible" to calling apartment only and next option CLSCTX_LOCAL_SERVER makes it cross-apartment cross-process. That is, as you discovered, without specific option cross-apartment but within process, so that 2+ processes could expose class objects within their process scope.

Also it looks relevant that CoRegisterClassObject along with registration itself instructs COM to use the apartment of the call for further instantiation, and this prevents from registrations on thread that might be blocked, and even involvement of these apartments in marshaling of the pointers.

A workaround there is to expose class objects through Running Object Table using process specific names. Standard RegisterActiveObject would use "!{CLSID}" name and you are interested in names like "!{CLSID}-processid" (this flexibility is available through IRunningObjectTable::Register ROT registration instead of RegisterActiveObject) so that separate processes could look up their own object. Having ROT registration called from side STA thread would then result in marshaling calls there back directly bypassing "blocked" main STA.

like image 80
Roman R. Avatar answered Oct 02 '22 08:10

Roman R.