mshtml 在调用 HideUI 后失败并显示 FAST_FAIL_INCORRECT_STACK

mshtml fails with FAST_FAIL_INCORRECT_STACK after calling HideUI

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

例如 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 的最终 return 导致 ECx = FAST_FAIL_INCORRECT_STACK 的 INT 29h 错误。预期堆栈为0x18D9C4,实际堆栈为0x18D9A4,相差0x20.

我完全懵了。对我的接口的其他调用工作正常,如果我只是 return E_NOTIMPL 从我的 HideUI 实现中,它没有任何区别。什么可能导致堆栈失衡?

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

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

或在其中使用 QueryInterface。如果这是 ATL,InternalQueryInterface。我怀疑这是导致错误的原因,因为您引用了可能由于 Release 次调用多于 AddRef 次调用而被破坏的对象。

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