当接口确实实现并且在 Windows 中具有内置编组器时,为什么 QueryInterface() 会失败? [英] Why would QueryInterface() fail when the interface is surely implemented and has built-in marshaller in Windows?
问题描述
我有以下设置.有一个 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 correspondingCOM_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_cast
到 IStream
并让它正常工作.
The callee in this scenario can just reinterpret_cast
to IStream
and have it nicely working.
这篇关于当接口确实实现并且在 Windows 中具有内置编组器时,为什么 QueryInterface() 会失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!