| Index: src/plugin/PluginClass.cpp | 
| diff --git a/src/plugin/PluginClass.cpp b/src/plugin/PluginClass.cpp | 
| index 40a588413c802d75f564256c36800105100146d5..862ec4609acec989c2f9a4091fc447b7470bd4d1 100644 | 
| --- a/src/plugin/PluginClass.cpp | 
| +++ b/src/plugin/PluginClass.cpp | 
| @@ -202,163 +202,166 @@ DWORD WINAPI CPluginClass::StartInitObject(LPVOID thisPtr) | 
| // so we should handle that it is called this way several times during a session | 
| STDMETHODIMP CPluginClass::SetSite(IUnknown* unknownSite) | 
| { | 
| - CPluginSettings* settings = CPluginSettings::GetInstance(); | 
| - | 
| - MULTIPLE_VERSIONS_CHECK(); | 
| - | 
| - if (unknownSite) | 
| + return EntryPointWithHResult([&]()->HRESULT | 
| { | 
| - | 
| - DEBUG_GENERAL(L"================================================================================\nNEW TAB UI\n================================================================================") | 
| - | 
| - HRESULT hr = ::CoInitialize(NULL); | 
| - if (FAILED(hr)) | 
| - { | 
| - DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_COINIT, "Class::SetSite - CoInitialize"); | 
| - } | 
| - | 
| - s_criticalSectionBrowser.Lock(); | 
| - { | 
| - m_webBrowser2 = unknownSite; | 
| - } | 
| - s_criticalSectionBrowser.Unlock(); | 
| - | 
| - //register the mimefilter | 
| - //and only mimefilter | 
| - //on some few computers the mimefilter does not get properly registered when it is done on another thread | 
| - | 
| - s_criticalSectionLocal.Lock(); | 
| - { | 
| - // Always register on startup, then check if we need to unregister in a separate thread | 
| - s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); | 
| - s_asyncWebBrowser2 = unknownSite; | 
| - s_instances.insert(this); | 
| - } | 
| - s_criticalSectionLocal.Unlock(); | 
| - | 
| - try | 
| + CPluginSettings* settings = CPluginSettings::GetInstance(); | 
| + | 
| + MULTIPLE_VERSIONS_CHECK(); | 
| + | 
| + if (unknownSite) | 
| { | 
| - // Check if loaded as BHO | 
| - auto webBrowser = GetBrowser(); | 
| - if (webBrowser) | 
| + | 
| + DEBUG_GENERAL(L"================================================================================\nNEW TAB UI\n================================================================================") | 
| + | 
| + HRESULT hr = ::CoInitialize(NULL); | 
| + if (FAILED(hr)) | 
| { | 
| - DEBUG_GENERAL("Loaded as BHO"); | 
| - HRESULT hr = DispEventAdvise(webBrowser); | 
| - if (SUCCEEDED(hr)) | 
| + DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_COINIT, "Class::SetSite - CoInitialize"); | 
| + } | 
| + | 
| + s_criticalSectionBrowser.Lock(); | 
| + { | 
| + m_webBrowser2 = unknownSite; | 
| + } | 
| + s_criticalSectionBrowser.Unlock(); | 
| + | 
| + //register the mimefilter | 
| + //and only mimefilter | 
| + //on some few computers the mimefilter does not get properly registered when it is done on another thread | 
| + | 
| + s_criticalSectionLocal.Lock(); | 
| + { | 
| + // Always register on startup, then check if we need to unregister in a separate thread | 
| + s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); | 
| + s_asyncWebBrowser2 = unknownSite; | 
| + s_instances.insert(this); | 
| + } | 
| + s_criticalSectionLocal.Unlock(); | 
| + | 
| + try | 
| + { | 
| + // Check if loaded as BHO | 
| + auto webBrowser = GetBrowser(); | 
| + if (webBrowser) | 
| { | 
| - m_isAdvised = true; | 
| - try | 
| + DEBUG_GENERAL("Loaded as BHO"); | 
| + HRESULT hr = DispEventAdvise(webBrowser); | 
| + if (SUCCEEDED(hr)) | 
| { | 
| - std::thread startInitObjectThread(StartInitObject, this); | 
| - startInitObjectThread.detach(); // TODO: but actually we should wait for the thread in the dtr. | 
| + m_isAdvised = true; | 
| + try | 
| + { | 
| + std::thread startInitObjectThread(StartInitObject, this); | 
| + startInitObjectThread.detach(); // TODO: but actually we should wait for the thread in the dtr. | 
| + } | 
| + catch (const std::system_error& ex) | 
| + { | 
| + auto errDescription = std::string("Class::Thread - Failed to create StartInitObject thread, ") + | 
| + ex.code().message() + ex.what(); | 
| + DEBUG_ERROR_LOG(ex.code().value(), PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_THREAD_CREATE_PROCESS, errDescription.c_str()); | 
| + } | 
| } | 
| - catch (const std::system_error& ex) | 
| + else | 
| { | 
| - auto errDescription = std::string("Class::Thread - Failed to create StartInitObject thread, ") + | 
| - ex.code().message() + ex.what(); | 
| - DEBUG_ERROR_LOG(ex.code().value(), PLUGIN_ERROR_THREAD, PLUGIN_ERROR_MAIN_THREAD_CREATE_PROCESS, errDescription.c_str()); | 
| + DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_ADVICE, "Class::SetSite - Advice"); | 
| } | 
| } | 
| - else | 
| - { | 
| - DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_ADVICE, "Class::SetSite - Advice"); | 
| - } | 
| - } | 
| - else // Check if loaded as toolbar handler | 
| - { | 
| - DEBUG_GENERAL("Loaded as toolbar handler"); | 
| - CComPtr<IServiceProvider> pServiceProvider; | 
| - | 
| - HRESULT hr = unknownSite->QueryInterface(&pServiceProvider); | 
| - if (SUCCEEDED(hr)) | 
| + else // Check if loaded as toolbar handler | 
| { | 
| - if (pServiceProvider) | 
| + DEBUG_GENERAL("Loaded as toolbar handler"); | 
| + CComPtr<IServiceProvider> pServiceProvider; | 
| + | 
| + HRESULT hr = unknownSite->QueryInterface(&pServiceProvider); | 
| + if (SUCCEEDED(hr)) | 
| { | 
| - s_criticalSectionBrowser.Lock(); | 
| + if (pServiceProvider) | 
| { | 
| - HRESULT hr = pServiceProvider->QueryService(IID_IWebBrowserApp, &m_webBrowser2); | 
| - if (SUCCEEDED(hr)) | 
| + s_criticalSectionBrowser.Lock(); | 
| { | 
| - if (m_webBrowser2) | 
| + HRESULT hr = pServiceProvider->QueryService(IID_IWebBrowserApp, &m_webBrowser2); | 
| + if (SUCCEEDED(hr)) | 
| { | 
| - InitObject(false); | 
| + if (m_webBrowser2) | 
| + { | 
| + InitObject(false); | 
| + } | 
| + } | 
| + else | 
| + { | 
| + DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_QUERY_BROWSER, "Class::SetSite - QueryService (IID_IWebBrowserApp)"); | 
| } | 
| } | 
| - else | 
| - { | 
| - DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_QUERY_BROWSER, "Class::SetSite - QueryService (IID_IWebBrowserApp)"); | 
| - } | 
| + s_criticalSectionBrowser.Unlock(); | 
| } | 
| - s_criticalSectionBrowser.Unlock(); | 
| + } | 
| + else | 
| + { | 
| + DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_QUERY_SERVICE_PROVIDER, "Class::SetSite - QueryInterface (service provider)"); | 
| } | 
| } | 
| - else | 
| - { | 
| - DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_SET_SITE, PLUGIN_ERROR_SET_SITE_QUERY_SERVICE_PROVIDER, "Class::SetSite - QueryInterface (service provider)"); | 
| - } | 
| + } | 
| + catch (std::runtime_error e) | 
| + { | 
| + DEBUG_ERROR(e.what()); | 
| + Unadvise(); | 
| } | 
| } | 
| - catch (std::runtime_error e) | 
| + else | 
| { | 
| - DEBUG_ERROR(e.what()); | 
| Unadvise(); | 
| - } | 
| - } | 
| - else | 
| - { | 
| - Unadvise(); | 
| - | 
| - // Destroy window | 
| - if (m_pWndProcStatus) | 
| - { | 
| - ::SetWindowLongPtr(m_hStatusBarWnd, GWLP_WNDPROC, (LPARAM)(WNDPROC)m_pWndProcStatus); | 
| - | 
| - m_pWndProcStatus = NULL; | 
| - } | 
| - | 
| - if (m_hPaneWnd) | 
| - { | 
| - DestroyWindow(m_hPaneWnd); | 
| - m_hPaneWnd = NULL; | 
| - } | 
| - | 
| - m_hTabWnd = NULL; | 
| - m_hStatusBarWnd = NULL; | 
| - | 
| - // Remove instance from the list, shutdown threads | 
| - HANDLE hMainThread = NULL; | 
| - HANDLE hTabThread = NULL; | 
| - | 
| - s_criticalSectionLocal.Lock(); | 
| - { | 
| - s_instances.erase(this); | 
| - | 
| - std::map<DWORD,CPluginClass*>::iterator it = s_threadInstances.find(::GetCurrentThreadId()); | 
| - if (it != s_threadInstances.end()) | 
| + | 
| + // Destroy window | 
| + if (m_pWndProcStatus) | 
| { | 
| - s_threadInstances.erase(it); | 
| + ::SetWindowLongPtr(m_hStatusBarWnd, GWLP_WNDPROC, (LPARAM)(WNDPROC)m_pWndProcStatus); | 
| + | 
| + m_pWndProcStatus = NULL; | 
| } | 
| - if (s_instances.empty()) | 
| + | 
| + if (m_hPaneWnd) | 
| { | 
| - // TODO: Explicitly releasing a resource when a container becomes empty looks like a job better suited for shared_ptr | 
| - CPluginClientFactory::ReleaseMimeFilterClientInstance(); | 
| + DestroyWindow(m_hPaneWnd); | 
| + m_hPaneWnd = NULL; | 
| } | 
| + | 
| + m_hTabWnd = NULL; | 
| + m_hStatusBarWnd = NULL; | 
| + | 
| + // Remove instance from the list, shutdown threads | 
| + HANDLE hMainThread = NULL; | 
| + HANDLE hTabThread = NULL; | 
| + | 
| + s_criticalSectionLocal.Lock(); | 
| + { | 
| + s_instances.erase(this); | 
| + | 
| + std::map<DWORD,CPluginClass*>::iterator it = s_threadInstances.find(::GetCurrentThreadId()); | 
| + if (it != s_threadInstances.end()) | 
| + { | 
| + s_threadInstances.erase(it); | 
| + } | 
| + if (s_instances.empty()) | 
| + { | 
| + // TODO: Explicitly releasing a resource when a container becomes empty looks like a job better suited for shared_ptr | 
| + CPluginClientFactory::ReleaseMimeFilterClientInstance(); | 
| + } | 
| + } | 
| + s_criticalSectionLocal.Unlock(); | 
| + | 
| + // Release browser interface | 
| + s_criticalSectionBrowser.Lock(); | 
| + { | 
| + m_webBrowser2.Release(); | 
| + } | 
| + s_criticalSectionBrowser.Unlock(); | 
| + | 
| + DEBUG_GENERAL("================================================================================\nNEW TAB UI - END\n================================================================================") | 
| + | 
| + ::CoUninitialize(); | 
| } | 
| - s_criticalSectionLocal.Unlock(); | 
| - | 
| - // Release browser interface | 
| - s_criticalSectionBrowser.Lock(); | 
| - { | 
| - m_webBrowser2.Release(); | 
| - } | 
| - s_criticalSectionBrowser.Unlock(); | 
| - | 
| - DEBUG_GENERAL("================================================================================\nNEW TAB UI - END\n================================================================================") | 
| - | 
| - ::CoUninitialize(); | 
| - } | 
| - | 
| - return IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite); | 
| + | 
| + return IObjectWithSiteImpl<CPluginClass>::SetSite(unknownSite); | 
| + }); | 
| } | 
| bool CPluginClass::IsStatusBarEnabled() | 
| @@ -483,127 +486,145 @@ void STDMETHODCALLTYPE CPluginClass::OnBeforeNavigate2( | 
| /* [in] */ VARIANT* /*Headers*/, | 
| /* [in, out] */ VARIANT_BOOL* /*Cancel*/) | 
| { | 
| - ATL::CComQIPtr<IWebBrowser2> webBrowser = frameBrowserDisp; | 
| - if (!webBrowser) | 
| - { | 
| - return; | 
| - } | 
| - | 
| - if (!urlVariant || urlVariant->vt != VT_BSTR) | 
| - { | 
| - return; | 
| - } | 
| - std::wstring url(urlVariant->bstrVal, SysStringLen(urlVariant->bstrVal)); | 
| - UnescapeUrl(url); | 
| - | 
| - //Register a mime filter if it's not registered yet | 
| - if (s_mimeFilter == NULL) | 
| - { | 
| - s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); | 
| - } | 
| - | 
| - CString urlCString = ToCString(url); | 
| - | 
| - // If webbrowser2 is equal to top level browser (as set in SetSite), we are navigating new page | 
| - CPluginClient* client = CPluginClient::GetInstance(); | 
| - | 
| - if (urlCString.Find(L"javascript") == 0) | 
| + EntryPoint([&] | 
| { | 
| - } | 
| - else if (GetBrowser().IsEqualObject(webBrowser)) | 
| - { | 
| - m_tab->OnNavigate(urlCString); | 
| - | 
| - DEBUG_GENERAL(L"================================================================================\nBegin main navigation url:" + urlCString + "\n================================================================================") | 
| - | 
| + ATL::CComQIPtr<IWebBrowser2> webBrowser = frameBrowserDisp; | 
| + if (!webBrowser) | 
| + { | 
| + return; | 
| + } | 
| + | 
| + if (!urlVariant || urlVariant->vt != VT_BSTR) | 
| + { | 
| + return; | 
| + } | 
| + std::wstring url(urlVariant->bstrVal, SysStringLen(urlVariant->bstrVal)); | 
| + UnescapeUrl(url); | 
| + | 
| + //Register a mime filter if it's not registered yet | 
| + if (s_mimeFilter == NULL) | 
| + { | 
| + s_mimeFilter = CPluginClientFactory::GetMimeFilterClientInstance(); | 
| + } | 
| + | 
| + CString urlCString = ToCString(url); | 
| + | 
| + // If webbrowser2 is equal to top level browser (as set in SetSite), we are navigating new page | 
| + CPluginClient* client = CPluginClient::GetInstance(); | 
| + | 
| + if (urlCString.Find(L"javascript") == 0) | 
| + { | 
| + } | 
| + else if (GetBrowser().IsEqualObject(webBrowser)) | 
| + { | 
| + m_tab->OnNavigate(urlCString); | 
| + | 
| + DEBUG_GENERAL(L"================================================================================\nBegin main navigation url:" + urlCString + "\n================================================================================") | 
| + | 
| #ifdef ENABLE_DEBUG_RESULT | 
| - CPluginDebug::DebugResultDomain(urlCString); | 
| + CPluginDebug::DebugResultDomain(urlCString); | 
| #endif | 
| - | 
| - UpdateStatusBar(); | 
| - } | 
| - else | 
| - { | 
| - DEBUG_NAVI(L"Navi::Begin navigation url:" + urlCString) | 
| - m_tab->CacheFrame(urlCString); | 
| - } | 
| + | 
| + UpdateStatusBar(); | 
| + } | 
| + else | 
| + { | 
| + DEBUG_NAVI(L"Navi::Begin navigation url:" + urlCString) | 
| + m_tab->CacheFrame(urlCString); | 
| + } | 
| + }); | 
| } | 
| void STDMETHODCALLTYPE CPluginClass::OnDownloadBegin() | 
| { | 
| - DEBUG_NAVI("Navi::Download Begin") | 
| + EntryPoint([&] | 
| + { | 
| + DEBUG_NAVI("Navi::Download Begin") | 
| + }); | 
| } | 
| void STDMETHODCALLTYPE CPluginClass::OnDownloadComplete() | 
| { | 
| - DEBUG_NAVI("Navi::Download Complete") | 
| - ATL::CComPtr<IWebBrowser2> browser = GetBrowser(); | 
| - if (browser) | 
| + EntryPoint([&] | 
| { | 
| - m_tab->OnDownloadComplete(browser); | 
| - } | 
| + DEBUG_NAVI("Navi::Download Complete") | 
| + ATL::CComPtr<IWebBrowser2> browser = GetBrowser(); | 
| + if (browser) | 
| + { | 
| + m_tab->OnDownloadComplete(browser); | 
| + } | 
| + }); | 
| } | 
| void STDMETHODCALLTYPE CPluginClass::OnDocumentComplete(IDispatch* frameBrowserDisp, VARIANT* /*urlOrPidl*/) | 
| { | 
| - ATL::CComQIPtr<IWebBrowser2> webBrowser2 = frameBrowserDisp; | 
| - if (!webBrowser2) | 
| + EntryPoint([&] | 
| { | 
| - return; | 
| - } | 
| - ATL::CString frameSrc; | 
| - ATL::CComBSTR locationUrl; | 
| - if (FAILED(webBrowser2->get_LocationURL(&locationUrl)) && !!locationUrl) | 
| - { | 
| - return; | 
| - } | 
| - frameSrc = locationUrl; | 
| - CPluginClient::UnescapeUrl(frameSrc); | 
| - bool isRootPageBrowser = GetBrowser().IsEqualObject(webBrowser2); | 
| - m_tab->OnDocumentComplete(webBrowser2, frameSrc, isRootPageBrowser); | 
| + ATL::CComQIPtr<IWebBrowser2> webBrowser2 = frameBrowserDisp; | 
| + if (!webBrowser2) | 
| + { | 
| + return; | 
| + } | 
| + ATL::CString frameSrc; | 
| + ATL::CComBSTR locationUrl; | 
| + if (FAILED(webBrowser2->get_LocationURL(&locationUrl)) && !!locationUrl) | 
| + { | 
| + return; | 
| + } | 
| + frameSrc = locationUrl; | 
| + CPluginClient::UnescapeUrl(frameSrc); | 
| + bool isRootPageBrowser = GetBrowser().IsEqualObject(webBrowser2); | 
| + m_tab->OnDocumentComplete(webBrowser2, frameSrc, isRootPageBrowser); | 
| + }); | 
| } | 
| void STDMETHODCALLTYPE CPluginClass::OnWindowStateChanged(unsigned long flags, unsigned long validFlagsMask) | 
| { | 
| - DEBUG_GENERAL("Tab changed"); | 
| - bool newtabshown = validFlagsMask == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OLECMDIDF_WINDOWSTATE_ENABLED) | 
| - && flags == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OLECMDIDF_WINDOWSTATE_ENABLED); | 
| - if (newtabshown) | 
| + EntryPoint([&] | 
| { | 
| - std::map<DWORD,CPluginClass*>::const_iterator it = s_threadInstances.find(GetCurrentThreadId()); | 
| - if (it == s_threadInstances.end()) | 
| + DEBUG_GENERAL("Tab changed"); | 
| + bool newtabshown = validFlagsMask == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OLECMDIDF_WINDOWSTATE_ENABLED) | 
| + && flags == (OLECMDIDF_WINDOWSTATE_USERVISIBLE | OLECMDIDF_WINDOWSTATE_ENABLED); | 
| + if (newtabshown) | 
| { | 
| - s_threadInstances[::GetCurrentThreadId()] = this; | 
| - if (!m_isInitializedOk) | 
| + std::map<DWORD,CPluginClass*>::const_iterator it = s_threadInstances.find(GetCurrentThreadId()); | 
| + if (it == s_threadInstances.end()) | 
| { | 
| - m_isInitializedOk = true; | 
| - InitObject(true); | 
| - UpdateStatusBar(); | 
| + s_threadInstances[::GetCurrentThreadId()] = this; | 
| + if (!m_isInitializedOk) | 
| + { | 
| + m_isInitializedOk = true; | 
| + InitObject(true); | 
| + UpdateStatusBar(); | 
| + } | 
| } | 
| } | 
| - } | 
| - notificationMessage.Hide(); | 
| - DEBUG_GENERAL("Tab change end"); | 
| + notificationMessage.Hide(); | 
| + DEBUG_GENERAL("Tab change end"); | 
| + }); | 
| } | 
| void STDMETHODCALLTYPE CPluginClass::OnCommandStateChange(long /*command*/, VARIANT_BOOL /*enable*/) | 
| { | 
| - if (m_hPaneWnd == NULL) | 
| - { | 
| - CreateStatusBarPane(); | 
| - } | 
| - else | 
| + EntryPoint([&] | 
| { | 
| - if (AdblockPlus::IE::InstalledMajorVersion() > 6) | 
| + if (m_hPaneWnd == NULL) | 
| { | 
| - RECT rect; | 
| - BOOL rectRes = GetClientRect(m_hStatusBarWnd, &rect); | 
| - if (rectRes == TRUE) | 
| + CreateStatusBarPane(); | 
| + } | 
| + else | 
| + { | 
| + if (AdblockPlus::IE::InstalledMajorVersion() > 6) | 
| { | 
| - MoveWindow(m_hPaneWnd, rect.right - 200, 0, m_nPaneWidth, rect.bottom - rect.top, TRUE); | 
| + RECT rect; | 
| + BOOL rectRes = GetClientRect(m_hStatusBarWnd, &rect); | 
| + if (rectRes == TRUE) | 
| + { | 
| + MoveWindow(m_hPaneWnd, rect.right - 200, 0, m_nPaneWidth, rect.bottom - rect.top, TRUE); | 
| + } | 
| } | 
| } | 
| - } | 
| + }); | 
| } | 
| bool CPluginClass::InitObject(bool bBHO) | 
| @@ -982,12 +1003,15 @@ CPluginTab* CPluginClass::GetTab(DWORD dwThreadId) | 
| STDMETHODIMP CPluginClass::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT* pCmdText) | 
| { | 
| - if (cCmds == 0) return E_INVALIDARG; | 
| - if (prgCmds == 0) return E_POINTER; | 
| - | 
| - prgCmds[0].cmdf = OLECMDF_ENABLED; | 
| - | 
| - return S_OK; | 
| + return EntryPointWithHResult([&]()->HRESULT | 
| + { | 
| + if (cCmds == 0) return E_INVALIDARG; | 
| + if (prgCmds == 0) return E_POINTER; | 
| + | 
| + prgCmds[0].cmdf = OLECMDF_ENABLED; | 
| + | 
| + return S_OK; | 
| + }); | 
| } | 
| HMENU CPluginClass::CreatePluginMenu(const CString& url) | 
| @@ -1192,83 +1216,86 @@ bool CPluginClass::SetMenuBar(HMENU hMenu, const CString& url) | 
| STDMETHODIMP CPluginClass::Exec(const GUID*, DWORD nCmdID, DWORD, VARIANTARG*, VARIANTARG*) | 
| { | 
| - HWND hBrowserWnd = GetBrowserHWND(); | 
| - if (!hBrowserWnd) | 
| - { | 
| - return E_FAIL; | 
| - } | 
| - | 
| - // Create menu | 
| - HMENU hMenu = CreatePluginMenu(m_tab->GetDocumentUrl()); | 
| - if (!hMenu) | 
| - { | 
| - return E_FAIL; | 
| - } | 
| - | 
| - // Check if button in toolbar was pressed | 
| - int nIDCommand = -1; | 
| - BOOL bRightAlign = FALSE; | 
| - | 
| - POINT pt; | 
| - GetCursorPos(&pt); | 
| - | 
| - HWND hWndToolBar = ::WindowFromPoint(pt); | 
| - | 
| - DWORD nProcessId; | 
| - ::GetWindowThreadProcessId(hWndToolBar, &nProcessId); | 
| - | 
| - if (hWndToolBar && ::GetCurrentProcessId() == nProcessId) | 
| + return EntryPointWithHResult([&]()->HRESULT | 
| { | 
| - ::ScreenToClient(hWndToolBar, &pt); | 
| - int nButton = (int)::SendMessage(hWndToolBar, TB_HITTEST, 0, (LPARAM)&pt); | 
| - | 
| - if (nButton > 0) | 
| + HWND hBrowserWnd = GetBrowserHWND(); | 
| + if (!hBrowserWnd) | 
| { | 
| - TBBUTTON pTBBtn = {}; | 
| - | 
| - if (SendMessage(hWndToolBar, TB_GETBUTTON, nButton, (LPARAM)&pTBBtn)) | 
| + return E_FAIL; | 
| + } | 
| + | 
| + // Create menu | 
| + HMENU hMenu = CreatePluginMenu(m_tab->GetDocumentUrl()); | 
| + if (!hMenu) | 
| + { | 
| + return E_FAIL; | 
| + } | 
| + | 
| + // Check if button in toolbar was pressed | 
| + int nIDCommand = -1; | 
| + BOOL bRightAlign = FALSE; | 
| + | 
| + POINT pt; | 
| + GetCursorPos(&pt); | 
| + | 
| + HWND hWndToolBar = ::WindowFromPoint(pt); | 
| + | 
| + DWORD nProcessId; | 
| + ::GetWindowThreadProcessId(hWndToolBar, &nProcessId); | 
| + | 
| + if (hWndToolBar && ::GetCurrentProcessId() == nProcessId) | 
| + { | 
| + ::ScreenToClient(hWndToolBar, &pt); | 
| + int nButton = (int)::SendMessage(hWndToolBar, TB_HITTEST, 0, (LPARAM)&pt); | 
| + | 
| + if (nButton > 0) | 
| { | 
| - RECT rcButton; | 
| - nIDCommand = pTBBtn.idCommand; | 
| - | 
| - if (SendMessage(hWndToolBar, TB_GETRECT, nIDCommand, (LPARAM)&rcButton)) | 
| + TBBUTTON pTBBtn = {}; | 
| + | 
| + if (SendMessage(hWndToolBar, TB_GETBUTTON, nButton, (LPARAM)&pTBBtn)) | 
| { | 
| - pt.x = rcButton.left; | 
| - pt.y = rcButton.bottom; | 
| - ClientToScreen(hWndToolBar, &pt); | 
| - | 
| - RECT rcWorkArea; | 
| - SystemParametersInfo(SPI_GETWORKAREA, 0, (LPVOID)&rcWorkArea, 0); | 
| - if (rcWorkArea.right - pt.x < 150) | 
| + RECT rcButton; | 
| + nIDCommand = pTBBtn.idCommand; | 
| + | 
| + if (SendMessage(hWndToolBar, TB_GETRECT, nIDCommand, (LPARAM)&rcButton)) | 
| { | 
| - bRightAlign = TRUE; | 
| - pt.x = rcButton.right; | 
| + pt.x = rcButton.left; | 
| pt.y = rcButton.bottom; | 
| ClientToScreen(hWndToolBar, &pt); | 
| + | 
| + RECT rcWorkArea; | 
| + SystemParametersInfo(SPI_GETWORKAREA, 0, (LPVOID)&rcWorkArea, 0); | 
| + if (rcWorkArea.right - pt.x < 150) | 
| + { | 
| + bRightAlign = TRUE; | 
| + pt.x = rcButton.right; | 
| + pt.y = rcButton.bottom; | 
| + ClientToScreen(hWndToolBar, &pt); | 
| + } | 
| } | 
| } | 
| } | 
| + else | 
| + { | 
| + GetCursorPos(&pt); | 
| + } | 
| + } | 
| + | 
| + // Display menu | 
| + UINT nFlags = 0; | 
| + if (bRightAlign) | 
| + { | 
| + nFlags |= TPM_RIGHTALIGN; | 
| } | 
| else | 
| { | 
| - GetCursorPos(&pt); | 
| + nFlags |= TPM_LEFTALIGN; | 
| } | 
| - } | 
| - | 
| - // Display menu | 
| - UINT nFlags = 0; | 
| - if (bRightAlign) | 
| - { | 
| - nFlags |= TPM_RIGHTALIGN; | 
| - } | 
| - else | 
| - { | 
| - nFlags |= TPM_LEFTALIGN; | 
| - } | 
| - | 
| - DisplayPluginMenu(hMenu, nIDCommand, pt, nFlags); | 
| - | 
| - return S_OK; | 
| + | 
| + DisplayPluginMenu(hMenu, nIDCommand, pt, nFlags); | 
| + | 
| + return S_OK; | 
| + }); | 
| } | 
| ///////////////////////////////////////////////////////////////////////////// | 
| @@ -1596,7 +1623,10 @@ void CPluginClass::UpdateStatusBar() | 
| void STDMETHODCALLTYPE CPluginClass::OnOnQuit() | 
| { | 
| - Unadvise(); | 
| + EntryPoint([&] | 
| + { | 
| + Unadvise(); | 
| + }); | 
| } | 
| void CPluginClass::Unadvise() |