问题描述
我有以下设置。有一个COM服务器安装到COM +(在单独的进程中运行),并具有此接口定义:
/ 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中有内置编组器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!