2016-10-10 9 views
1

JavaScriptに埋め込みIE11コントロールの外部オブジェクトを提供するためにIDocHostUIHandlerの実装を記述しました。 1つのクラスは、IUnknown、IDispatch、およびIDocHostUIHandlerの実装を提供します。 IDispatchインターフェイスは、外部オブジェクトとしてGetExternalに返されます。 GetExternal以外のIDocHostUIHandlerを呼び出すと、元のハンドラが呼び出されます。 JavaScriptでHideUIを呼び出した後にmshtmlがFAST_FAIL_INCORRECT_STACKで失敗します

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

Iは、以下を実行する:

同じパターンがあるGetExternal除く他のすべてのメソッドのために使用される

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

例えばHideUIは、以下のように実装されています

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から戻ると、ecx = FAST_FAIL_INCORRECT_STACKでINT 29hエラーが発生します。予想されるスタックは0x18D9C4であり、実際のスタックは0x18D9A4であり、0x20の不一致です。

私は完全に神秘的です。私のインターフェイスへの他の呼び出しは正しく動作し、私はHideUIの実装からE_NOTIMPLを返すだけで何の違いもありません。おそらく何がスタックのバランスを崩しているのでしょうか?

答えて

0

答えは、mshtmlがWebBrowserコントロールによってホストされているときにブラウザドキュメントでICustomDocを使用していたようです。これは明らかに良い考えではありません!代わりにWebBrowserコントロールによって提供される既存のサイトを使用する必要があります。私はここにIDocHostUIを実装する正しい方法の例を見つけましたhttps://github.com/FastSpring/FsprgEmbeddedStoreWinMFCそしてそれは非常に有用でした。

+0

これは受け入れられた回答としてマークする必要があります。 –

2

関数では、後で参照カウントの不一致につながる参照カウントをインクリメントせずにインターフェイスポインタを返します。より良い実装は次のようになります:

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()を呼び出すmshtml.dllによって取得され、その後、AddRefになるように所有されているので、参照で完了すると解放されます。 –

+2

はい、COMエキスパートではないというのは正しいです。 COMでそのようなポインタを取得すると、呼び出し元がRelease()を呼び出すときに、すべてが平衡しているようにAddleef()インターフェイスが呼び出されます。 –

+0

マイクロソフトはあなたに同意していないようです。 https://msdn.microsoft.com/en-us/library/aa770041(v=vs.85).aspx –

関連する問題