阻止COM激活服务器可执行文件?

时间:2019-03-05 08:47:46

标签: windows winapi visual-c++ com

TL; DR -如何防止-Embedding服务器CLSCTX_LOCAL_SERVER的启动?最好让客户立即获得体面的错误代码。

背景

我们有一个本机C ++交互式桌面应用程序,该应用程序与另一个本机C ++交互式桌面应用程序中的COM对象进行交互。

基本上,COM被用作进程间通信机制。

现在,当用户将其进入正确状态后以交互方式启动“服务器”应用程序时,它将准备COM接口:CoRegisterClassObject等。

使用客户端应用程序,然后对协类使用CoCreateInstance时,它将与已经运行的其他桌面应用程序进行通信,这就是预期的目的。

但是,当“服务器”应用程序未运行时,启动客户端将以交互方式启动服务器应用程序,这不是我们想要的,因为在客户端进行有意义的通信之前,它需要进行大量的处理和设置。

问题

因此,更有意义的是,在服务器未运行的情况下,客户端只是出错,而不是让COM基础结构启动一个交互式应用程序,该应用程序无论如何都无法有效地为请求提供服务。

我们玩弄了以下想法:

  • 每次关闭服务器时注销服务器。
    • 似乎这行不通,因为我们需要具有管理权限才能注册/注销服务器。
  • 在客户端使用CLSCTX_DISABLE_AAA标志。
    • 这似乎可行,如果客户端指定了该选项,并且服务器未运行,它将得到0x80070005 ERROR_ACCESS_DENIED,但我们不确定这是否正确。
  • 在服务器应用程序中进行早期检查,以检测到-Embedding开关,然后立即退出此应用程序。
    • 客户端应用程序将运行超时(〜2分钟),这不是非常友好的操作。
  • 来自注释不要将信息写入注册表-CoRegisterClassObject should be enough
    • 目前,我有:
      • HKCR\AppID (...)
      • HKCR\CLSID\{...}加上子键ProgIDVersionIndependentProgIDLocalServer32Typelib
    • 客户端当前从VersionIndependentProgID解析CLSID
    • 因此,我想知道注册表的哪些部分确实是可选的。

对于给定的注册COM类,是否有任何“标准”方法来阻止COM本地服务器可执行文件激活?

2 个答案:

答案 0 :(得分:1)

我的想法是这个...

当您检测到服务器以-Embedding启动时,只需在EXE中设置全局标志即可。我可能只有在使用-Embedding标志启动时才创建特殊类工厂。调用IClassFactory :: CreateInstance()时,此类工厂将返回失败代码。您不会将标准类工厂注册为与CoRegisterClassObject()一起运行,而是仅注册始终返回失败代码的替代工厂。

是的,在启动EXE时仍然会稍有延迟,但是当调用CreateInstance()时,它将立即返回失败代码,因此调用方将不会有很长的超时时间...也许是1-仅5秒。

答案 1 :(得分:-1)

总结我到目前为止从评论中学到的东西:


您不必使用CoCreateInstance,但是您可以使用GetActiveObject

  

检索指向已使用OLE注册的运行对象的指针。

因此,您有一种获取对象的方法,而无需激活它,而是依靠它已经被注册。 (但这不是CoRegosterClassObject完成的,您需要...?)


类似于GetActiveObject的方法,您可以使用IRunningObjectTable周围的机器-无论如何,这可能是GetActiveObject在幕后使用的。我在那儿迷路了。


另一条信息是registry is claimed to be kinda "optional"的所有含义:(解释)

  

CoRegisterClassObject仅用于将对象发布到COM(作为oop服务器),   ...

     

只需不在注册表中注册对象CLSID。   如果服务器尚未调用CoRegisterClassObject,则客户端将收到错误REGDB_E_CLASSNOTREG,否则调用CoRegisterClassObject就足够了。   ...

     

您不需要将其添加到“运行对象表”中-单个调用CoRegisterClassObject就足够了-客户端可以在此之后创建实例。无需在注册表中进行任何注册-...

     

...对于任何远程接口,您当然都需要注册表Interface\{..}\ProxyStubClsid32中的一个条目,但对于CLSID不需要

     

CoRegisterClassObject完全不需要注册表... 但是,您仍然需要编组您的界面。为此,您需要Interface\{..}\ProxyStubClsid32键。

     

如果进行这种封送处理,则需要TypeLib-在此处设置{00020424-0000-0000-C000-000000000046}。您不需要的CLSIDAppID

     

CLSIDAPPID,如果尚未启动(或加载dll),则需要启动它。

     

如果您已经在运行并致电CoRegisterClassObject-这足以使客户端呼叫连接到您。   但是,如果没有CLSID,客户端将无法执行您的应用程序(根本不知道是什么)。

     

如果您不进行自定义封送处理-每个接口都需要在注册表中包含信息-哪个dll ProxyStubClsid32可以进行此封送处理。这可以是自定义dll,也可以是自定义dll,或者如果是标准{00020424-0000-0000-C000-000000000046},则需要供oleaut32使用的typelib。


摘要中,看来阻止Windows启动应用的方法是

  • 首先不要将激活所需的信息写入注册表。
    • 但只有封送所需的信息。
  • 和/或不调用CoCreateInstance并通过另一条路线检索对象。