| 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() |