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

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

问题描述

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

  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 *



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

  STDMETHODIMP CServer :: MyMethod(IUnknown * param)
{
if(param == 0){
return E_INVALIDARG;
}
ATL :: CComQIPtr< IStream> stream(param);
if(stream == 0){
return E_INVALIDARG; //控制权通过此处
}
//无论
}
IStream *
传入 callComObject() / code>在客户端被隐式转换为 IUnknown * ,后者被传递给COM编组器。编组 IUnknown * 在另一个进程中到达服务器,并且获得 IUnknown * ,然后有 QueryInterface()从同一对象调用marshall IStream * ,并且 QueryInterface()失败。



这看起来很疯狂,因为编组 IStream * 应该在任何时候都工作 - 有一个marshaller



为什么可能无法正常工作,如何找到原因?

解决方案

符合行为的一种可能情况如下:




  • 在调用者和被调用者之间没有任何区别

  • 接口指针有效

  • 但是实现 IStream ,没有相应的 COM_INTERFACE_ENTRY 映射条目,并且不使接口可用,调用者可能已通过非COM方式获取指针,例如直接C ++转换



这很容易通过 QueryInterface 在呼叫前的呼叫方。



此方案中的被调用者只需 reinterpret_cast IStream 并且它很好地工作。


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 );
};

The caller calls it like this:

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

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*.

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
}

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.

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:

  • 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

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

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

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

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