调用HideUI

时间:2016-10-10 10:38:04

标签: c++ com internet-explorer-11 mshtml

我编写了一个IDocHostUIHandler的实现,以便为JavaScript提供嵌入式IE11控件的外部对象。一个类提供IUnknown,IDispatch和IDocHostUIHandler的实现。 IDispatch接口作为外部对象返回到GetExternal。 所有对IDocHostUIHandler的调用除GetExternal调用之外都调用原始处理程序。

例如,HideUI实现为:

HRESULT STDMETHODCALLTYPE mtQtWebBrowserDocHandler::HideUI(void)
{
    qDebug("Calling HideUI");
    if(m_defaultDocHostUIHandler)
    {
        HRESULT hr = m_defaultDocHostUIHandler->HideUI();
        qDebug("Called HideUI");
        return hr;
    }
    return E_NOTIMPL;
}

除了GetExternal之外的所有其他方法使用相同的模式:

HRESULT STDMETHODCALLTYPE mtQtWebBrowserDocHandler::GetExternal(IDispatch **ppDispatch)
{
    qDebug("Calling GetExternal");
    *ppDispatch = (IDispatch*)this;
    return S_OK;
}

在JavaScript中,我执行以下操作:

var r1 = window.external.Test1();

这导致以下调试输出尾部:

'2016-10-10 11:09:19'    DEBUG  Calling GetHostInfo
'2016-10-10 11:09:19'    DEBUG  Called GetHostInfo
'2016-10-10 11:09:19'    DEBUG  mtQtWebBrowserDocHandler Release (ref now = 2)
'2016-10-10 11:09:19'    DEBUG  mtQtWebBrowserDocHandler AddRef (ref now = 3)
'2016-10-10 11:09:19'    DEBUG  Calling GetHostInfo
'2016-10-10 11:09:19'    DEBUG  Called GetHostInfo
'2016-10-10 11:09:19'    DEBUG  mtQtWebBrowserDocHandler Release (ref now = 2)
'2016-10-10 11:09:19'    DEBUG  Calling GetExternal
'2016-10-10 11:09:21'    DEBUG  mtQtWebBrowserDocHandler - IDispatch requested
'2016-10-10 11:09:21'    DEBUG  mtQtWebBrowserDocHandler AddRef (ref now = 3)
'2016-10-10 11:09:21'    DEBUG  mtQtWebBrowserDocHandler Release (ref now = 2)
'2016-10-10 11:09:21'    DEBUG  Calling ShowUI
'2016-10-10 11:09:21'    DEBUG  Called ShowUI
'2016-10-10 11:09:21'    DEBUG  Calling HideUI
'2016-10-10 11:09:21'    DEBUG  Called HideUI

HideUI的最终返回会导致INT 29h错误,ecx = FAST_FAIL_INCORRECT_STACK。预期的堆栈为0x18D9C4,实际堆栈为0x18D9A4,差异为0x20。

我完全神秘化了。对我的界面的其他调用正常工作,如果我只是从我的HideUI实现返回E_NOTIMPL,它没有任何区别。什么可能会使堆栈失去平衡?

2 个答案:

答案 0 :(得分:2)

GetExternal函数中,您将返回一个接口指针,而不会增加引用计数,这将导致引用计数不匹配。更好的实施方式是:

HRESULT STDMETHODCALLTYPE mtQtWebBrowserDocHandler::GetExternal(IDispatch **ppDispatch)
{
    qDebug("Calling GetExternal");
    *ppDispatch = (IDispatch*)this;
    this->AddRef();
    return S_OK;
}

或在那里使用QueryInterface。如果这是ATL,InternalQueryInterface。我怀疑这是导致错误的原因,因为您引用的对象可能因ReleaseAddRef次调用而被销毁。

答案 1 :(得分:0)

答案似乎是当我在WebBrowser控件托管mshtml时,我在浏览器文档中使用了ICustomDoc。这显然不是一个好主意!相反,您应该使用WebBrowser控件提供的现有站点。我找到了一个在这里https://github.com/FastSpring/FsprgEmbeddedStoreWinMFC实现IDocHostUI的正确方法的例子,它非常有帮助。