降低单独进程中接收器的安全性

Windows Management Instrumentation (WMI) 可创建接收器,以在单独的进程中接收客户端应用程序的异步回调。 单独进程为 Unsecapp.exe。 使用 IWbemUnsecuredApartment 接口。 通过 IWbemUnsecuredApartment 可控制 Unsecapp.exe 是否验证对接收器的回调。 有关详细信息,请参阅设置异步调用的安全性

然后,可以降低该进程的安全性,这样 WMI 就能不受限制地访问接收器。 为了帮助使用这种技术,WMI 提供了 Unsecapp.exe 进程作为单独的进程运行。 可通过调用 IUnsecuredApartment 接口来托管 Unsecapp.exe。

通过 IUnsecuredApartment 接口,客户端应用程序可创建单独的专用进程,该进程运行 Unsecapp.exe 来托管 IWbemObjectSink 实现。 专用进程可调用 CoInitializeSecurity 来向 WMI 授予访问专用进程的权限,而不会损害主进程的安全性。 初始化后,专用进程充当主进程和 WMI 之间的中间方。

以下过程说明了如何使用 IUnsecuredApartment 执行异步调用。

使用 IUnsecuredApartment 执行异步调用

  1. 通过调用 CoCreateInstance 创建专用进程。

    以下代码示例调用 CoCreateInstance 来创建专用进程。

    IUnsecuredApartment* pUnsecApp = NULL;
    
    CoCreateInstance(CLSID_UnsecuredApartment, NULL, 
      CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, 
      (void**)&pUnsecApp);
    
  2. 实例化接收器对象。

    以下代码示例创建一个新的接收器对象。

    CMySink* pSink = new CMySink;
    pSink->AddRef();
    
  3. 为接收器创建一个存根。

    存根是从接收器生成的包装函数。

    以下代码示例调用 CreateObjectStub 来为接收器创建存根。

    IUnknown* pStubUnk = NULL; 
    pUnsecApp->CreateObjectStub(pSink, &pStubUnk);
    
  4. 为包装器调用 QueryInterface,并请求指向 IWbemObjectSink 接口的指针。

    以下代码示例调用 QueryInterface 并请求指向 IWbemObjectSink 接口的指针。

    IWbemObjectSink* pStubSink = NULL;
    pStubUnk->QueryInterface(IID_IWbemObjectSink, (void **)&pStubSink); pStubUnk->Release();
    
  5. 释放接收器对象指针。

    可以释放对象指针,因为存根现在拥有该指针。

    以下代码示例释放接收器对象指针。

    pSink->Release();
    
  6. 在任何异步调用中使用存根。

    调用完成后,释放本地引用计数。

    以下代码示例在异步调用中使用存根。

    // pServices is an IWbemServices* object
    pServices->CreateInstanceEnumAsync(strClassName, 0, NULL, pStubSink);
    

    有时可能必须在调用后取消异步调用。 如果需要取消调用,请使用最初发出调用的同一指针进行取消。

    以下代码示例显示如何取消异步调用。

    pServices->CancelAsyncCall(pStubSink);
    
  7. 使用完异步调用后,释放本地引用计数。

    确保仅在确认不需要取消异步调用后才释放 pStubSink 指针。 此外,在 WMI 释放 pSink 接收器指针后,不要释放 pStubSink。 在 pSink 之后释放 pStubSink 会创建一个循环引用计数,其中接收器和存根将永久保留在内存中。 相反,可能会在 IWbemObjectSink::SetStatus 调用中释放指针,该调用由 WMI 发出来报告原始异步调用已完成。

  8. 完成后,通过调用 Release() 来取消初始化 COM。

    以下代码示例展示了如何在 pUnsecApp 指针上调用 Release()

    pUnsecApp->Release();
    

    本主题中的代码示例需要以下引用和 #include 语句才能正确编译。

    #include <wbemidl.h>
    #pragma comment(lib, "wbemuuid.lib")
    

有关 CoInitializeSecurity 函数和参数的详细信息,请参阅平台软件开发工具包 (SDK) 中的 COM 文档。