TL;DR - How do I prevent -Embedding
startup of a CLSCTX_LOCAL_SERVER
server? Preferably so that the clients get a decent error code immediately.
We have a native C++ interactive Desktop application that interacts with a COM object in another native C++ interactive Desktop application.
Basically, COM is used as an interprocess communication mechanism.
Now, when the "server" application is started interactively after the user has brought it into the correct state, it will prepare the COM interface: CoRegisterClassObject
etc etc.
When the client application is used and then does it's CoCreateInstance
for the coclass, it will communicate with the already running other Desktop application, which is what is intended.
However, when the "server" application is not running, starting the client will launch the server application interactively, which is NOT what we want, because it needs quite some processing and setting up before the client can meaningfully communicate with it.
So, what would make more sense is for the client to just error out in case the server is not running, instead of having the COM infrastructure start an interactive application that can't service the request meaningfully anyways.
We've toyed around with the following ideas:
CLSCTX_DISABLE_AAA
flag on the client side.
0x80070005 ERROR_ACCESS_DENIED
, but we're rather unsure whether this is the correct approach.-Embedding
switch and immediately exit the application on this.
CoRegisterClassObject
should be enough.
HKCR\AppID (...)
HKCR\CLSID\{...}
plus subkeys ProgID
, VersionIndependentProgID
, LocalServer32
, Typelib
Is there any "standard" way to prevent COM local server executable activation for a given registered COM class?
My idea is this ...
Just set a global flag in your EXE when you detect the server is started with -Embedding. I would probably create a special class factory only when you startup with the -Embedding flag. This class factory would return a fail code when IClassFactory::CreateInstance() is called. You would not register the standard class factory as running with CoRegisterClassObject(), but you'd register only your alternative factory that always returns the fail code.
Yes, there would still be a slight delay on starting up the EXE, but when the CreateInstance() is called, it would immediately return the fail code and so the caller would not have a long timeout...maybe 1-5 seconds only.
Write up of what I learned from comments so far:
You do not have to use CoCreateInstance
, but you can use GetActiveObject
, which
Retrieves a pointer to a running object that has been registered with OLE.
so there you have a way to get an object without activating it, but relying on it already being registered. (But this is not done by CoRegosterClassObject
, instead you need to ...?)
Similar to the GetActiveObject
approach, you can use the machinery around IRunningObjectTable
- which may be what's used by GetActiveObject under the covers anyway. i git kind of lost there.
Another piece of info is that the registry is claimed to be kinda "optional" in all this: (paraphrasing)
CoRegisterClassObject
is just to publish your object to COM (as an oop server), ...simply not register your object
CLSID
in the registry. If the server has not yet calledCoRegisterClassObject
, client gets errorREGDB_E_CLASSNOTREG
, otherwise callCoRegisterClassObject
is enough. ...you not need add it to Running Object Table - the single call
CoRegisterClassObject
is enough - the client can create instance after this. No need for any registration in the registry - ...... you of course need, for any remote interface, an entry in registry
Interface\{..}\ProxyStubClsid32
but not need this forCLSID
.
CoRegisterClassObject
does not need the registry at all ... But you need still marshal your interface(s). For this you need therInterface\{..}\ProxyStubClsid32
key.The
TypeLib
you need if you do this type of marshaling - set {00020424-0000-0000-C000-000000000046} here. TheCLSID
andAppID
you do not need.
CLSID
andAPPID
you need for starting your app, if it is not started (or load dll).If you already are running and call
CoRegisterClassObject
- this is enough for client call connect to you. But without CLSID, client can not exec your app (simply unknown what).If you do not do custom marshaling - need for every interface have info in registry - which dll ProxyStubClsid32 do this marshaling. This can be or custom dll or if standard {00020424-0000-0000-C000-000000000046}, then you need a typelib for use by oleaut32.
In summary, it would appear the way to prevent having an app activated by Windows is to
CoCreateInstance
and retrieving the object via another route.User contributions licensed under CC BY-SA 3.0