Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I finally had some time to figure out what is happening, so I wrote a short test to see what is going on.</p> <pre><code>// MarshalTest.cpp : Defines the entry point for the console application. // #include "stdafx.h" enum { WM_THEREYOUGO = WM_USER+1, WM_THANKYOU, WM_YOURWELCOME }; DWORD WINAPI TheOtherThread(DWORD * main_thread_id) { MSG msg = { 0 }; HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); assert(SUCCEEDED(hr)); { // create web browser CComPtr&lt;IWebBrowser2&gt; wb; hr = wb.CoCreateInstance(CLSID_InternetExplorer, 0, CLSCTX_SERVER); assert(SUCCEEDED(hr) &amp;&amp; wb); // navigate hr = wb-&gt;Navigate2(&amp;CComVariant(_T("stackoverflow.com")), &amp;CComVariant(0), &amp;CComVariant(_T("")), &amp;CComVariant(), &amp;CComVariant()); assert(SUCCEEDED(hr)); hr = wb-&gt;put_Visible(VARIANT_TRUE); assert(SUCCEEDED(hr)); // Marshal DWORD the_cookie = 0; { CComPtr&lt;IGlobalInterfaceTable&gt; com_broker; hr = com_broker.CoCreateInstance(CLSID_StdGlobalInterfaceTable); assert(SUCCEEDED(hr)); hr = com_broker-&gt;RegisterInterfaceInGlobal(wb, __uuidof(IWebBrowser2), &amp;the_cookie); } // notify main thread PostThreadMessage(*main_thread_id, WM_THEREYOUGO, the_cookie, NULL); // message loop while(GetMessage(&amp;msg, 0, 0, 0)) { if(msg.hwnd == NULL) { // thread message switch(msg.message) { case WM_THANKYOU: PostQuitMessage(0); break; } } else { TranslateMessage(&amp;msg); DispatchMessage(&amp;msg); } } } CoUninitialize(); PostThreadMessage(*main_thread_id, WM_YOURWELCOME, 0, NULL); return msg.wParam; } int _tmain(int argc, _TCHAR* argv[]) { MSG msg = {0}; DWORD main_thread_id = GetCurrentThreadId(); HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); assert(SUCCEEDED(hr)); { DWORD ThreadId = 0; HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TheOtherThread, &amp;main_thread_id, 0, &amp;ThreadId); DWORD the_cookie = 0; CComPtr&lt;IWebBrowser2&gt; wb, wb2; while(GetMessage(&amp;msg, 0, 0, 0)) { if(msg.hwnd == NULL) { // thread message switch(msg.message) { case WM_THEREYOUGO: // we got the cookie. the_cookie = msg.wParam; // get the browser. This should work. { CComPtr&lt;IGlobalInterfaceTable&gt; com_broker; hr = com_broker.CoCreateInstance(CLSID_StdGlobalInterfaceTable); assert(SUCCEEDED(hr)); hr = com_broker-&gt;GetInterfaceFromGlobal(the_cookie, __uuidof(IWebBrowser2), (void**)&amp;wb); assert(SUCCEEDED(hr) &amp;&amp; wb); } // do something with it. hr = wb-&gt;put_FullScreen(VARIANT_TRUE); assert(SUCCEEDED(hr)); // signal the other thread. PostThreadMessage(ThreadId, WM_THANKYOU, 0, NULL); break; case WM_YOURWELCOME: // the other thread has ended. PostQuitMessage(0); break; } } else { TranslateMessage(&amp;msg); DispatchMessage(&amp;msg); } } // the other thread has ended. Try getting the interface again. { CComPtr&lt;IGlobalInterfaceTable&gt; com_broker; hr = com_broker.CoCreateInstance(CLSID_StdGlobalInterfaceTable); assert(SUCCEEDED(hr)); hr = com_broker-&gt;GetInterfaceFromGlobal(the_cookie, __uuidof(IWebBrowser2), (void**)&amp;wb2); //assert(SUCCEEDED(hr) &amp;&amp; wb2); // this fails, hr == E_INVALIDARG. // clean up, will not be executed. if(SUCCEEDED(hr)) { hr = com_broker-&gt;RevokeInterfaceFromGlobal(the_cookie); } } // try using it if(wb2) { hr = wb2-&gt;put_FullScreen(VARIANT_FALSE); assert(SUCCEEDED(hr)); } else if(wb) { // this succeeds hr = wb-&gt;put_FullScreen(VARIANT_FALSE); assert(SUCCEEDED(hr)); } CloseHandle(hThread); } CoUninitialize(); return msg.wParam; } </code></pre> <hr> <p>The bottom line is this:</p> <ul> <li>Ending the thread that registered the interface invalidates the cookie.</li> <li>The already marshaled interface stays valid. (In this case, that is.)</li> </ul> <p>This means that I get a proxy to the IE process instead of to the other thread's object.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload