2016-10-10 59 views
1

我已經編寫了一個IDocHostUIHandler實現,以便爲嵌入式IE11控件提供一個JavaScript對象。一類提供IUnknown,IDispatch和IDocHostUIHandler的實現。 IDispatch接口作爲外部對象返回到GetExternal。 所有調用IDocHostUIHandler除GetExternal調用原始處理程序。mshtml在調用HideUI後失敗並返回FAST_FAIL_INCORRECT_STACK

例如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,它沒有任何區別。什麼可能會失去平衡?

回答

0

答案似乎是當Web瀏覽器控件託管mshtml時,我在瀏覽器文檔上使用ICustomDoc。這顯然不是一個好主意!相反,您應該使用WebBrowser控件提供的現有網站。我找到了一個在這裏實現IDocHostUI的正確方法的例子,它非常有幫助。

+0

您應該將此標記爲接受的答案。 –

2

GetExternal函數中,您將返回一個接口指針,但不會增加引用計數,這將導致稍後引用計數不匹配。一個更好的實施將是:

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

或使用QueryInterface在那裏。如果這是ATL,InternalQueryInterface。我懷疑這是你錯誤的原因,因爲你有一個引用的對象可能已被銷燬,因爲更多的Release調用比AddRef調用。

+0

我不是一個COM專家,但我確信事實並非如此。這個引用是通過調用GetExternal()調用GetExternal()獲得的,然後由它擁有,所以它將AddRef然後釋放,當它完成引用時。 –

+2

是的,你是不是一個COM專家是正確的。每當你在COM中得到一個像這樣的指針時,被調用者應該使用AddRef()這個接口,這樣當調用者調用Release()時,所有的東西都會被平衡。 –

+0

微軟似乎並不同意你的看法。 https://msdn.microsoft.com/zh-cn/library/aa770041(v=vs.85).aspx –