当接口确实实现并且在 Windows 中具有内置编组器时,为什么 QueryInterface() 会失败? [英] Why would QueryInterface() fail when the interface is surely implemented and has built-in marshaller in Windows?

查看:28
本文介绍了当接口确实实现并且在 Windows 中具有内置编组器时,为什么 QueryInterface() 会失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下设置.有一个 COM 服务器安装到 COM+(在单独的进程中运行)并具有以下接口定义:

I have the following setup. There's a COM server that is installed into COM+ (to run in a separate process) and has this interface definition:

[object, uuid("InterfaceIdHere"), nonextensible, oleautomation, hidden]
interface IMyInterface : IUnknown {
   HRESULT MyMethod( [in] IUnknown* param );
};

调用者这样称呼它:

HRESULT callComObject(IStream* stream)
{
    return comObject->MyMethod(stream);
}

请注意,这里的 IStream* 隐式向上转换为 IUnknown*.这样做是因为在 IDL 中声明 IStream* 类型的参数会导致一些我现在想不起来的问题.无论如何,它始终是一个有效的 IStream* 代替 IUnknown* 传递.

Note that here IStream* is implicitly upcasted to IUnknown*. This is done because declaring a parameter of type IStream* in IDL caused some problems that I can't recall right now. Anyway it's always a valid IStream* that is passed in place of IUnknown*.

COM 服务器端有这个 MyMethod() 的实现:

The COM server side has this implementation of MyMethod():

STDMETHODIMP CServer::MyMethod(IUnknown* param)
{
    if(param == 0) {
       return E_INVALIDARG;
    }   
    ATL::CComQIPtr<IStream> stream(param);
    if(stream == 0) {
       return E_INVALIDARG;// control passes HERE
    }
    // whatever
}

所以我将 IStream* 传递到客户端的 callComObject() 中,它被隐式向上转换为 IUnknown* 并且后者被传递到 COM 编组器.编组的 IUnknown* 在另一个进程中到达服务器,并在那里获得 IUnknown*,然后有一个 QueryInterface() 调用 marshall 来自同一个对象的 IStream* 并且 QueryInterface() 失败.

So I have IStream* passed into callComObject() on the client side which is implicitly upcasted to IUnknown* and the latter is passed to the COM marshaller. The marshalled IUnknown* reaches the server in another process and there IUnknown* is obtained and then there's a QueryInterface() call to marshall IStream* from the same object and that QueryInterface() fails.

这看起来很疯狂,因为编组 IStream* 应该一直有效 - Windows 中预装了一个用于此接口的编组器.

This looks insane, because marshalling IStream* should just work at all times - there's a marshaller for this interface pre-installed in Windows.

为什么它可能不起作用,我如何找到原因?

Why could it possible not work and how do I find the reason?

推荐答案

与行为匹配的可能方案之一如下:

One of the possible scenarios that matches the behavior is the following:

  • 调用者和被调用者之间没有任何编组
  • 接口指针有效
  • 然而,实现 IStream 的对象没有对应的 COM_INTERFACE_ENTRY 映射条目并且没有使接口可用,调用者可能通过非COM方式,例如直接 C++ 强制转换
  • you don't have any marhshaling between caller and callee
  • the interface pointer is valid
  • however the object which implements IStream, does not have a corresponding COM_INTERFACE_ENTRY map entry and does not make the interface available, the caller might have obtained the pointer via non-COM way, e.g. direct C++ cast

这很容易通过在调用之前QueryInterface在调用方端发送流来检查.

This is easy to check by QueryInterface'ing the stream on the caller side before the call.

在这种情况下,被调用者只需reinterpret_castIStream 并让它正常工作.

The callee in this scenario can just reinterpret_cast to IStream and have it nicely working.

这篇关于当接口确实实现并且在 Windows 中具有内置编组器时,为什么 QueryInterface() 会失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆