Index: src/chext/DropMenuExt.cpp =================================================================== diff -u -r3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4 -r134983cab6122e3fff73994a6f9c417aaeab3bc2 --- src/chext/DropMenuExt.cpp (.../DropMenuExt.cpp) (revision 3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4) +++ src/chext/DropMenuExt.cpp (.../DropMenuExt.cpp) (revision 134983cab6122e3fff73994a6f9c417aaeab3bc2) @@ -51,157 +51,221 @@ STDMETHODIMP CDropMenuExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/) { - LOG_DEBUG(m_spLog) << L"Initializing"; + try + { + LOG_DEBUG(m_spLog) << L"Initializing"; - // When called: - // 1. R-click on a directory - // 2. R-click on a directory background - // 3. Pressed Ctrl+C, Ctrl+X on a specified file/directory + // When called: + // 1. R-click on a directory + // 2. R-click on a directory background + // 3. Pressed Ctrl+C, Ctrl+X on a specified file/directory - if(!pidlFolder && !piDataObject) - { - LOG_ERROR(m_spLog) << L"Missing both pointers."; - return E_FAIL; - } + if(!pidlFolder && !piDataObject) + { + LOG_ERROR(m_spLog) << L"Missing both pointers."; + return E_FAIL; + } - if(!pidlFolder || !piDataObject) - LOG_WARNING(m_spLog) << L"Missing at least one parameter - it's unexpected."; + if(!pidlFolder || !piDataObject) + LOG_WARNING(m_spLog) << L"Missing at least one parameter - it's unexpected."; - if(!piDataObject) + if(!piDataObject) + { + LOG_ERROR(m_spLog) << L"Missing piDataObject."; + return E_FAIL; + } + + // check options + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); + if(hWnd == nullptr) + return E_FAIL; + + HRESULT hResult = ShellExtensionVerifier::ReadShellConfig(m_piShellExtControl, m_tShellExtMenuConfig); + LOG_HRESULT(m_spLog, hResult) << L"Read shell config"; + if(SUCCEEDED(hResult)) + { + hResult = m_tShellExtData.GatherDataFromInitialize(pidlFolder, piDataObject); + LOG_HRESULT(m_spLog, hResult) << L"Gather data from initialize"; + } + + return hResult; + } + catch(const std::exception& e) { - LOG_ERROR(m_spLog) << L"Missing piDataObject."; + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); return E_FAIL; } - - // check options - HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); - if(hWnd == nullptr) - return E_FAIL; - - HRESULT hResult = ShellExtensionVerifier::ReadShellConfig(m_piShellExtControl, m_tShellExtMenuConfig); - LOG_HRESULT(m_spLog, hResult) << L"Read shell config"; - if(SUCCEEDED(hResult)) + catch(...) { - hResult = m_tShellExtData.GatherDataFromInitialize(pidlFolder, piDataObject); - LOG_HRESULT(m_spLog, hResult) << L"Gather data from initialize"; + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; } - - return hResult; } STDMETHODIMP CDropMenuExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) { - LOG_DEBUG(m_spLog) << L"Querying context menu"; + try + { + LOG_DEBUG(m_spLog) << L"Querying context menu"; - // check options - HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); - if(!hWnd) - return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); + if(!hMenu) + { + LOG_ERROR(m_spLog) << L"Parameter hMenu is null"; + return E_INVALIDARG; + } - // retrieve the default menu item; if not available, fallback to the default heuristics - m_tShellExtData.ReadDefaultSelectionStateFromMenu(hMenu); + // check options + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); + if(!hWnd) + return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); - // retrieve the action information to be performed - TShellExtData::EActionSource eActionSource = m_tShellExtData.GetActionSource(); + // retrieve the default menu item; if not available, fallback to the default heuristics + m_tShellExtData.ReadDefaultSelectionStateFromMenu(hMenu); - // determine if we want to perform override based on user options and detected action source - bool bIntercept = (m_tShellExtMenuConfig.GetInterceptDragAndDrop() && eActionSource == TShellExtData::eSrc_DropMenu || - m_tShellExtMenuConfig.GetInterceptKeyboardActions() && eActionSource == TShellExtData::eSrc_Keyboard || - m_tShellExtMenuConfig.GetInterceptCtxMenuActions() && eActionSource == TShellExtData::eSrc_CtxMenu); + // retrieve the action information to be performed + TShellExtData::EActionSource eActionSource = m_tShellExtData.GetActionSource(); - TShellMenuItemPtr spRootMenuItem = m_tShellExtMenuConfig.GetDragAndDropRoot(); - m_tContextMenuHandler.Init(spRootMenuItem, hMenu, idCmdFirst, indexMenu, m_tShellExtData, m_tShellExtMenuConfig.GetFormatter(), - m_tShellExtMenuConfig.GetShowFreeSpace(), m_tShellExtMenuConfig.GetShowShortcutIcons(), bIntercept); + // determine if we want to perform override based on user options and detected action source + bool bIntercept = (m_tShellExtMenuConfig.GetInterceptDragAndDrop() && eActionSource == TShellExtData::eSrc_DropMenu || + m_tShellExtMenuConfig.GetInterceptKeyboardActions() && eActionSource == TShellExtData::eSrc_Keyboard || + m_tShellExtMenuConfig.GetInterceptCtxMenuActions() && eActionSource == TShellExtData::eSrc_CtxMenu); - return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, m_tContextMenuHandler.GetLastCommandID() - idCmdFirst + 1); + TShellMenuItemPtr spRootMenuItem = m_tShellExtMenuConfig.GetDragAndDropRoot(); + m_tContextMenuHandler.Init(spRootMenuItem, hMenu, idCmdFirst, indexMenu, m_tShellExtData, m_tShellExtMenuConfig.GetFormatter(), + m_tShellExtMenuConfig.GetShowFreeSpace(), m_tShellExtMenuConfig.GetShowShortcutIcons(), bIntercept); + + return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, m_tContextMenuHandler.GetLastCommandID() - idCmdFirst + 1); + } + catch(const std::exception& e) + { + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); + return E_FAIL; + } + catch(...) + { + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; + } } STDMETHODIMP CDropMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) { - LOG_DEBUG(m_spLog) << L"Invoking command"; + try + { + LOG_DEBUG(m_spLog) << L"Invoking command"; - HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); - if(hWnd == nullptr) - return E_FAIL; + if(!lpici) + { + LOG_ERROR(m_spLog) << L"Parameter lpici is null"; + return E_INVALIDARG; + } - // find command to be executed, if not found - fail - TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(lpici->lpVerb)); - if(!spSelectedItem) - return E_FAIL; + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); + if(hWnd == nullptr) + return E_FAIL; - // data retrieval and validation - if(!m_tShellExtData.VerifyItemCanBeExecuted(spSelectedItem)) - return E_FAIL; + // find command to be executed, if not found - fail + TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(lpici->lpVerb)); + if(!spSelectedItem) + return E_FAIL; - chcore::TPathContainer vSourcePaths; - chcore::TSmartPath spDestinationPath; - chcore::EOperationType eOperationType = chcore::eOperation_None; + // data retrieval and validation + if(!m_tShellExtData.VerifyItemCanBeExecuted(spSelectedItem)) + return E_FAIL; - if(!m_tShellExtData.GetSourcePathsByItem(spSelectedItem, vSourcePaths)) - return E_FAIL; - if(!m_tShellExtData.GetDestinationPathByItem(spSelectedItem, spDestinationPath)) - return E_FAIL; - if(!m_tShellExtData.GetOperationTypeByItem(spSelectedItem, eOperationType)) - return E_FAIL; + chcore::TPathContainer vSourcePaths; + chcore::TSmartPath spDestinationPath; + chcore::EOperationType eOperationType = chcore::eOperation_None; - chcore::TTaskDefinition tTaskDefinition; - tTaskDefinition.SetSourcePaths(vSourcePaths); - tTaskDefinition.SetDestinationPath(spDestinationPath); - tTaskDefinition.SetOperationType(eOperationType); + if(!m_tShellExtData.GetSourcePathsByItem(spSelectedItem, vSourcePaths)) + return E_FAIL; + if(!m_tShellExtData.GetDestinationPathByItem(spSelectedItem, spDestinationPath)) + return E_FAIL; + if(!m_tShellExtData.GetOperationTypeByItem(spSelectedItem, eOperationType)) + return E_FAIL; - // get task data as xml - chcore::TString wstrData; - tTaskDefinition.StoreInString(wstrData); + chcore::TTaskDefinition tTaskDefinition; + tTaskDefinition.SetSourcePaths(vSourcePaths); + tTaskDefinition.SetDestinationPath(spDestinationPath); + tTaskDefinition.SetOperationType(eOperationType); - // fill struct - COPYDATASTRUCT cds; - cds.dwData = spSelectedItem->IsSpecialOperation() ? eCDType_TaskDefinitionContentSpecial : eCDType_TaskDefinitionContent; - cds.lpData = (void*)wstrData.c_str(); - cds.cbData = (DWORD)((wstrData.GetLength() + 1) * sizeof(wchar_t)); + // get task data as xml + chcore::TString wstrData; + tTaskDefinition.StoreInString(wstrData); - // send a message - ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); + // fill struct + COPYDATASTRUCT cds; + cds.dwData = spSelectedItem->IsSpecialOperation() ? eCDType_TaskDefinitionContentSpecial : eCDType_TaskDefinitionContent; + cds.lpData = (void*)wstrData.c_str(); + cds.cbData = (DWORD)((wstrData.GetLength() + 1) * sizeof(wchar_t)); - return S_OK; + // send a message + ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); + + return S_OK; + } + catch(const std::exception& e) + { + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); + return E_FAIL; + } + catch(...) + { + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; + } } STDMETHODIMP CDropMenuExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax) { - LOG_DEBUG(m_spLog) << L"Retrieving command string for cmd: " << idCmd; + try + { + LOG_DEBUG(m_spLog) << L"Retrieving command string for cmd: " << idCmd; - memset(pszName, 0, cchMax); + memset(pszName, 0, cchMax); - if(uFlags != GCS_HELPTEXTW && uFlags != GCS_HELPTEXTA) - return S_OK; + if(uFlags != GCS_HELPTEXTW && uFlags != GCS_HELPTEXTA) + return S_OK; - // check options - HRESULT hResult = ShellExtensionVerifier::IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult)) - return hResult; - else if(hResult == S_FALSE) - return S_OK; + // check options + HRESULT hResult = ShellExtensionVerifier::IsShellExtEnabled(m_piShellExtControl); + if(FAILED(hResult)) + return hResult; + else if(hResult == S_FALSE) + return S_OK; - TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(idCmd)); - if(!spSelectedItem || !spSelectedItem->SpecifiesDestinationPath()) - return E_FAIL; + TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(idCmd)); + if(!spSelectedItem || !spSelectedItem->SpecifiesDestinationPath()) + return E_FAIL; - switch(uFlags) - { - case GCS_HELPTEXTW: + switch(uFlags) { + case GCS_HELPTEXTW: + { wcsncpy(reinterpret_cast(pszName), spSelectedItem->GetItemTip().c_str(), spSelectedItem->GetItemTip().GetLength() + 1); break; } - case GCS_HELPTEXTA: + case GCS_HELPTEXTA: { USES_CONVERSION; CT2A ct2a(spSelectedItem->GetItemTip().c_str()); strncpy(reinterpret_cast(pszName), ct2a, strlen(ct2a) + 1); break; } - } + } - return S_OK; + return S_OK; + } + catch(const std::exception& e) + { + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); + return E_FAIL; + } + catch(...) + { + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; + } } STDMETHODIMP CDropMenuExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -213,6 +277,5 @@ STDMETHODIMP CDropMenuExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* /*plResult*/) { uMsg; wParam; lParam; - ATLTRACE(_T("CDropMenuExt::HandleMenuMsg2(): uMsg = %lu, wParam = %lu, lParam = %lu\n"), uMsg, wParam, lParam); return S_FALSE; } Index: src/chext/MenuExt.cpp =================================================================== diff -u -r3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4 -r134983cab6122e3fff73994a6f9c417aaeab3bc2 --- src/chext/MenuExt.cpp (.../MenuExt.cpp) (revision 3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4) +++ src/chext/MenuExt.cpp (.../MenuExt.cpp) (revision 134983cab6122e3fff73994a6f9c417aaeab3bc2) @@ -23,7 +23,6 @@ #include "stdio.h" #include "memory.h" #include -#include "ShellPathsHelpers.h" #include "../common/TShellExtMenuConfig.h" #include "../libchcore/TSharedMemory.h" #include "../libchcore/TTaskDefinition.h" @@ -68,140 +67,192 @@ STDMETHODIMP CMenuExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/) { - LOG_DEBUG(m_spLog) << L"Initializing"; - - if(!pidlFolder && !piDataObject) + try { - LOG_ERROR(m_spLog) << L"Missing both pointers."; - return E_INVALIDARG; - } + LOG_DEBUG(m_spLog) << L"Initializing"; - // check options - HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); - if(!hWnd) - return S_OK; + if(!pidlFolder && !piDataObject) + { + LOG_ERROR(m_spLog) << L"Missing both pointers."; + return E_INVALIDARG; + } - HRESULT hResult = ShellExtensionVerifier::ReadShellConfig(m_piShellExtControl, m_tShellExtMenuConfig); - LOG_HRESULT(m_spLog, hResult) << L"Read shell config"; + // check options + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); + if(!hWnd) + return S_OK; - if(SUCCEEDED(hResult)) + HRESULT hResult = ShellExtensionVerifier::ReadShellConfig(m_piShellExtControl, m_tShellExtMenuConfig); + LOG_HRESULT(m_spLog, hResult) << L"Read shell config"; + + if(SUCCEEDED(hResult)) + { + hResult = m_tShellExtData.GatherDataFromInitialize(pidlFolder, piDataObject); + LOG_HRESULT(m_spLog, hResult) << L"Gather data from initialize"; + } + + return hResult; + } + catch(const std::exception& e) { - hResult = m_tShellExtData.GatherDataFromInitialize(pidlFolder, piDataObject); - LOG_HRESULT(m_spLog, hResult) << L"Gather data from initialize"; + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); + return E_FAIL; } - - return hResult; + catch(...) + { + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; + } } STDMETHODIMP CMenuExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) { - LOG_DEBUG(m_spLog) << L"Querying context menu"; + try + { + LOG_DEBUG(m_spLog) << L"Querying context menu"; - // check options - HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); - if(!hWnd) - return S_OK; + if(!hMenu) + { + LOG_ERROR(m_spLog) << L"Received null hMenu from caller"; + return E_INVALIDARG; + } - // current commands count in menu - TCHAR szText[_MAX_PATH]; - int iCount = ::GetMenuItemCount(hMenu); + // check options + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); + if(!hWnd) + return S_OK; - MENUITEMINFO mii; - mii.cbSize=sizeof(mii); - mii.fMask=MIIM_TYPE; - mii.dwTypeData=szText; - mii.cch=_MAX_PATH; + // current commands count in menu + TCHAR szText[ _MAX_PATH ]; + int iCount = ::GetMenuItemCount(hMenu); - // find a place where the commands should be inserted - for (int i=0;ilpVerb) != 0) - return E_FAIL; + if(!lpici) + { + LOG_ERROR(m_spLog) << L"Parameter lpici is null"; + return E_INVALIDARG; + } - // check options - HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); - if(hWnd == nullptr) - return E_FAIL; + // textual verbs are not supported by this extension + if(HIWORD(lpici->lpVerb) != 0) + return E_FAIL; - // find command to be executed, if not found - fail - TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(lpici->lpVerb)); - if(!spSelectedItem) - return E_FAIL; + // check options + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); + if(hWnd == nullptr) + return E_FAIL; - // data retrieval and validation - if(!m_tShellExtData.VerifyItemCanBeExecuted(spSelectedItem)) - return E_FAIL; + // find command to be executed, if not found - fail + TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(lpici->lpVerb)); + if(!spSelectedItem) + return E_FAIL; - chcore::TPathContainer vSourcePaths; - chcore::TSmartPath spDestinationPath; - chcore::EOperationType eOperationType = chcore::eOperation_None; + // data retrieval and validation + if(!m_tShellExtData.VerifyItemCanBeExecuted(spSelectedItem)) + return E_FAIL; - if(!m_tShellExtData.GetSourcePathsByItem(spSelectedItem, vSourcePaths)) - return E_FAIL; - if(!m_tShellExtData.GetDestinationPathByItem(spSelectedItem, spDestinationPath)) - return E_FAIL; - if(!m_tShellExtData.GetOperationTypeByItem(spSelectedItem, eOperationType)) - return E_FAIL; + chcore::TPathContainer vSourcePaths; + chcore::TSmartPath spDestinationPath; + chcore::EOperationType eOperationType = chcore::eOperation_None; - chcore::TTaskDefinition tTaskDefinition; - tTaskDefinition.SetSourcePaths(vSourcePaths); - tTaskDefinition.SetDestinationPath(spDestinationPath); - tTaskDefinition.SetOperationType(eOperationType); + if(!m_tShellExtData.GetSourcePathsByItem(spSelectedItem, vSourcePaths)) + return E_FAIL; + if(!m_tShellExtData.GetDestinationPathByItem(spSelectedItem, spDestinationPath)) + return E_FAIL; + if(!m_tShellExtData.GetOperationTypeByItem(spSelectedItem, eOperationType)) + return E_FAIL; - // get task data as xml - chcore::TString wstrData; - tTaskDefinition.StoreInString(wstrData); + chcore::TTaskDefinition tTaskDefinition; + tTaskDefinition.SetSourcePaths(vSourcePaths); + tTaskDefinition.SetDestinationPath(spDestinationPath); + tTaskDefinition.SetOperationType(eOperationType); - // fill struct - COPYDATASTRUCT cds; - cds.dwData = spSelectedItem->IsSpecialOperation() ? eCDType_TaskDefinitionContentSpecial : eCDType_TaskDefinitionContent; - cds.lpData = (void*)wstrData.c_str(); - cds.cbData = (DWORD)((wstrData.GetLength() + 1) * sizeof(wchar_t)); + // get task data as xml + chcore::TString wstrData; + tTaskDefinition.StoreInString(wstrData); - // send a message - ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); + // fill struct + COPYDATASTRUCT cds; + cds.dwData = spSelectedItem->IsSpecialOperation() ? eCDType_TaskDefinitionContentSpecial : eCDType_TaskDefinitionContent; + cds.lpData = (void*)wstrData.c_str(); + cds.cbData = (DWORD)((wstrData.GetLength() + 1) * sizeof(wchar_t)); - return S_OK; + // send a message + ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); + + return S_OK; + } + catch(const std::exception& e) + { + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); + return E_FAIL; + } + catch(...) + { + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; + } } HRESULT CMenuExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -211,18 +262,20 @@ HRESULT CMenuExt::HandleMenuMsg2(UINT uMsg, WPARAM /*wParam*/, LPARAM lParam, LRESULT* /*plResult*/) { - LOG_DEBUG(m_spLog) << L"Handle menu message (2)"; - - switch(uMsg) + try { - case WM_INITMENUPOPUP: - break; - - case WM_DRAWITEM: - return DrawMenuItem((LPDRAWITEMSTRUCT)lParam); - - case WM_MEASUREITEM: + LOG_DEBUG(m_spLog) << L"Handle menu message (2)"; + + switch(uMsg) { + case WM_INITMENUPOPUP: + break; + + case WM_DRAWITEM: + return DrawMenuItem((LPDRAWITEMSTRUCT)lParam); + + case WM_MEASUREITEM: + { LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam; if(!lpmis) return E_FAIL; @@ -261,110 +314,147 @@ break; } - } + } - return S_OK; + return S_OK; + } + catch(const std::exception& e) + { + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); + return E_FAIL; + } + catch(...) + { + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; + } } HRESULT CMenuExt::DrawMenuItem(LPDRAWITEMSTRUCT lpdis) { - LOG_DEBUG(m_spLog) << L"Drawing menu item"; - - if(!lpdis) + try { - LOG_ERROR(m_spLog) << L"Missing argument"; - return E_FAIL; - } + LOG_DEBUG(m_spLog) << L"Drawing menu item"; - // check if menu - if(lpdis->CtlType != ODT_MENU) - return S_OK; + if(!lpdis) + { + LOG_ERROR(m_spLog) << L"Missing argument"; + return E_FAIL; + } - // find command to be executed, if not found - fail - TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByItemID(LOWORD(lpdis->itemID)); - if(!spSelectedItem || !spSelectedItem->SpecifiesDestinationPath()) - return E_FAIL; + // check if menu + if(lpdis->CtlType != ODT_MENU) + return S_OK; - // margins and other stuff - const int iSmallIconWidth = GetSystemMetrics(SM_CXSMICON); - const int iSmallIconHeight = GetSystemMetrics(SM_CYSMICON); - const int iLeftMargin = GetSystemMetrics(SM_CXMENUCHECK) / 2; - const int iRightMargin = GetSystemMetrics(SM_CXMENUCHECK) - iLeftMargin; - - // text color - HBRUSH hBrush = nullptr; - if(lpdis->itemState & ODS_SELECTED) - { - SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); - SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); - hBrush = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); - } - else - { - SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT)); - SetBkColor(lpdis->hDC, GetSysColor(COLOR_MENU)); - hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU)); - } + // find command to be executed, if not found - fail + TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByItemID(LOWORD(lpdis->itemID)); + if(!spSelectedItem || !spSelectedItem->SpecifiesDestinationPath()) + return E_FAIL; - // draw background - RECT rcSelect = lpdis->rcItem; - rcSelect.top++; - rcSelect.bottom--; + // margins and other stuff + const int iSmallIconWidth = GetSystemMetrics(SM_CXSMICON); + const int iSmallIconHeight = GetSystemMetrics(SM_CYSMICON); + const int iLeftMargin = GetSystemMetrics(SM_CXMENUCHECK) / 2; + const int iRightMargin = GetSystemMetrics(SM_CXMENUCHECK) - iLeftMargin; - FillRect(lpdis->hDC, &rcSelect, hBrush); - DeleteObject(hBrush); + // text color + HBRUSH hBrush = nullptr; + if(lpdis->itemState & ODS_SELECTED) + { + SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); + hBrush = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); + } + else + { + SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT)); + SetBkColor(lpdis->hDC, GetSysColor(COLOR_MENU)); + hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU)); + } - // get img list - SHFILEINFO sfi; - HIMAGELIST hImageList = (HIMAGELIST)SHGetFileInfo(spSelectedItem->GetDestinationPathInfo().GetDefaultDestinationPath().ToString(), FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), SHGFI_SMALLICON | SHGFI_ICON | SHGFI_SYSICONINDEX); - ImageList_Draw(hImageList, sfi.iIcon, lpdis->hDC, lpdis->rcItem.left + iLeftMargin, lpdis->rcItem.top + (lpdis->rcItem.bottom - lpdis->rcItem.top + 1 - iSmallIconHeight) / 2, ILD_TRANSPARENT); + // draw background + RECT rcSelect = lpdis->rcItem; + rcSelect.top++; + rcSelect.bottom--; - RECT rcText; - rcText.left = iLeftMargin + iSmallIconWidth + iRightMargin; - rcText.top = lpdis->rcItem.top; - rcText.right = lpdis->rcItem.right; - rcText.bottom = lpdis->rcItem.bottom; + FillRect(lpdis->hDC, &rcSelect, hBrush); + DeleteObject(hBrush); - DrawText(lpdis->hDC, spSelectedItem->GetLocalName().c_str(), -1, &rcText, DT_LEFT | DT_SINGLELINE | DT_VCENTER); + // get img list + SHFILEINFO sfi; + HIMAGELIST hImageList = (HIMAGELIST)SHGetFileInfo(spSelectedItem->GetDestinationPathInfo().GetDefaultDestinationPath().ToString(), FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), SHGFI_SMALLICON | SHGFI_ICON | SHGFI_SYSICONINDEX); + ImageList_Draw(hImageList, sfi.iIcon, lpdis->hDC, lpdis->rcItem.left + iLeftMargin, lpdis->rcItem.top + (lpdis->rcItem.bottom - lpdis->rcItem.top + 1 - iSmallIconHeight) / 2, ILD_TRANSPARENT); - return S_OK; + RECT rcText; + rcText.left = iLeftMargin + iSmallIconWidth + iRightMargin; + rcText.top = lpdis->rcItem.top; + rcText.right = lpdis->rcItem.right; + rcText.bottom = lpdis->rcItem.bottom; + + DrawText(lpdis->hDC, spSelectedItem->GetLocalName().c_str(), -1, &rcText, DT_LEFT | DT_SINGLELINE | DT_VCENTER); + + return S_OK; + } + catch(const std::exception& e) + { + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); + return E_FAIL; + } + catch(...) + { + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; + } } STDMETHODIMP CMenuExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax) { - LOG_DEBUG(m_spLog) << L"Retrieving command string for cmd " << idCmd; + try + { + LOG_DEBUG(m_spLog) << L"Retrieving command string for cmd " << idCmd; - memset(pszName, 0, cchMax); + memset(pszName, 0, cchMax); - if(uFlags != GCS_HELPTEXTW && uFlags != GCS_HELPTEXTA) - return S_OK; + if(uFlags != GCS_HELPTEXTW && uFlags != GCS_HELPTEXTA) + return S_OK; - // check options - HRESULT hResult = ShellExtensionVerifier::IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult)) - return hResult; - else if(hResult == S_FALSE) - return S_OK; + // check options + HRESULT hResult = ShellExtensionVerifier::IsShellExtEnabled(m_piShellExtControl); + if(FAILED(hResult)) + return hResult; + else if(hResult == S_FALSE) + return S_OK; - TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(idCmd)); - if(!spSelectedItem || !spSelectedItem->SpecifiesDestinationPath()) - return E_FAIL; + TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(idCmd)); + if(!spSelectedItem || !spSelectedItem->SpecifiesDestinationPath()) + return E_FAIL; - switch(uFlags) - { - case GCS_HELPTEXTW: + switch(uFlags) { - wcsncpy(reinterpret_cast(pszName), spSelectedItem->GetItemTip().c_str(), spSelectedItem->GetItemTip().GetLength() + 1); - break; + case GCS_HELPTEXTW: + { + wcsncpy(reinterpret_cast(pszName), spSelectedItem->GetItemTip().c_str(), spSelectedItem->GetItemTip().GetLength() + 1); + break; + } + case GCS_HELPTEXTA: + { + USES_CONVERSION; + CT2A ct2a(spSelectedItem->GetItemTip().c_str()); + strncpy(reinterpret_cast(pszName), ct2a, strlen(ct2a) + 1); + break; + } } - case GCS_HELPTEXTA: - { - USES_CONVERSION; - CT2A ct2a(spSelectedItem->GetItemTip().c_str()); - strncpy(reinterpret_cast(pszName), ct2a, strlen(ct2a) + 1); - break; - } - } - return S_OK; + return S_OK; + } + catch(const std::exception& e) + { + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); + return E_FAIL; + } + catch(...) + { + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; + } } Index: src/chext/ShellExtControl.cpp =================================================================== diff -u -r306fbe693c70290af9de9a5779084a697de22d75 -r134983cab6122e3fff73994a6f9c417aaeab3bc2 --- src/chext/ShellExtControl.cpp (.../ShellExtControl.cpp) (revision 306fbe693c70290af9de9a5779084a697de22d75) +++ src/chext/ShellExtControl.cpp (.../ShellExtControl.cpp) (revision 134983cab6122e3fff73994a6f9c417aaeab3bc2) @@ -31,43 +31,6 @@ m_spLog(GetLogger(L"ShellExtControl")) { LOG_DEBUG(m_spLog) << L"Constructing CShellExtControl"; - - // create protection mutex - chcore::TIpcMutexLock lock(m_mutex); - - // memory mapped file - m_hMemory = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, sizeof(SHELLEXT_DATA), _T("CHShellExtControlData")); // name of map object - DWORD dwLastError = GetLastError(); // NOTE: last error is needed also for success case (for already exists status) - if(!m_hMemory) - { - LOG_HRESULT(m_spLog, dwLastError) << L"Cannot create file mapping."; - return; - } - - m_pShellExtData = (SHELLEXT_DATA*)MapViewOfFile(m_hMemory, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); - if(!m_pShellExtData) - { - DWORD dwError = GetLastError(); // NOTE: do not overwrite dwLastError, as the value is needed later - - LOG_HRESULT(m_spLog, dwError) << L"Cannot map view of file."; - CloseHandle(m_hMemory); - m_hMemory = nullptr; - return; - } - - if(dwLastError != ERROR_ALREADY_EXISTS) - { - if(dwLastError == ERROR_SUCCESS) - { - LOG_DEBUG(m_spLog) << L"Copy Handler is not running. Disabling shell extension."; - } - else - { - LOG_HRESULT(m_spLog, dwLastError) << L"Copy Handler is not running. Disabling shell extension."; - } - m_pShellExtData->m_lFlags = 0; - m_pShellExtData->m_lID = GetTickCount(); - } } CShellExtControl::~CShellExtControl() @@ -83,62 +46,167 @@ STDMETHODIMP CShellExtControl::GetVersion(LONG* plVersion, BSTR* pbstrVersion) { - LOG_DEBUG(m_spLog) << "Retrieving version"; - - if(!plVersion || !pbstrVersion || (*pbstrVersion)) + try { - LOG_ERROR(m_spLog) << "Invalid arguments."; - return E_INVALIDARG; - } + LOG_DEBUG(m_spLog) << "Retrieving version"; - (*plVersion) = PRODUCT_VERSION1 << 24 | PRODUCT_VERSION2 << 16 | PRODUCT_VERSION3 << 8 | PRODUCT_VERSION4; - _bstr_t strVer(SHELLEXT_PRODUCT_FULL_VERSION); - *pbstrVersion = strVer.Detach(); + HRESULT hResult = Initialize(); + if(FAILED(hResult)) + { + LOG_ERROR(m_spLog) << L"CShellExtControl initialization failed"; + return hResult; + } - LOG_DEBUG(m_spLog) << LOG_PARAMS2(*plVersion, *pbstrVersion); + if(!plVersion || !pbstrVersion || (*pbstrVersion)) + { + LOG_ERROR(m_spLog) << "Invalid arguments."; + return E_INVALIDARG; + } - return S_OK; -} + (*plVersion) = PRODUCT_VERSION1 << 24 | PRODUCT_VERSION2 << 16 | PRODUCT_VERSION3 << 8 | PRODUCT_VERSION4; + _bstr_t strVer(SHELLEXT_PRODUCT_FULL_VERSION); + *pbstrVersion = strVer.Detach(); -STDMETHODIMP CShellExtControl::SetFlags(LONG lFlags, LONG lMask) -{ - LOG_DEBUG(m_spLog) << L"Setting flags: " << LOG_PARAMS2(lFlags, lMask); + LOG_DEBUG(m_spLog) << LOG_PARAMS2(*plVersion, *pbstrVersion); - if(!m_pShellExtData) + return S_OK; + } + catch(const std::exception& e) { - LOG_ERROR(m_spLog) << "Wrong internal state."; + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); return E_FAIL; } + catch(...) + { + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; + } +} - chcore::TIpcMutexLock lock(m_mutex); - m_pShellExtData->m_lFlags = (m_pShellExtData->m_lFlags & ~lMask) | (lFlags & lMask); +STDMETHODIMP CShellExtControl::SetFlags(LONG lFlags, LONG lMask) +{ + try + { + LOG_DEBUG(m_spLog) << L"Setting flags: " << LOG_PARAMS2(lFlags, lMask); - LOG_DEBUG(m_spLog) << L"Set flags: " << LOG_PARAM(m_pShellExtData->m_lFlags); + HRESULT hResult = Initialize(); + if(FAILED(hResult)) + { + LOG_ERROR(m_spLog) << L"CShellExtControl initialization failed"; + return hResult; + } - return S_OK; + if(!m_pShellExtData) + { + LOG_ERROR(m_spLog) << "Wrong internal state."; + return E_FAIL; + } + + chcore::TIpcMutexLock lock(m_mutex); + m_pShellExtData->m_lFlags = (m_pShellExtData->m_lFlags & ~lMask) | (lFlags & lMask); + + LOG_DEBUG(m_spLog) << L"Set flags: " << LOG_PARAM(m_pShellExtData->m_lFlags); + + return S_OK; + } + catch(const std::exception& e) + { + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); + return E_FAIL; + } + catch(...) + { + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; + } } STDMETHODIMP CShellExtControl::GetFlags(LONG* plFlags) { - LOG_DEBUG(m_spLog) << "Retrieving flags"; + try + { + LOG_DEBUG(m_spLog) << "Retrieving flags"; - if(!m_pShellExtData) + HRESULT hResult = Initialize(); + if(FAILED(hResult)) + { + LOG_ERROR(m_spLog) << L"CShellExtControl initialization failed"; + return hResult; + } + + if(!m_pShellExtData) + { + LOG_ERROR(m_spLog) << "Wrong internal state."; + return E_FAIL; + } + + if(!plFlags) + { + LOG_ERROR(m_spLog) << "Invalid argument."; + return E_INVALIDARG; + } + + chcore::TIpcMutexLock lock(m_mutex); + + (*plFlags) = m_pShellExtData->m_lFlags; + + LOG_DEBUG(m_spLog) << "Returning flags: " << LOG_PARAM(m_pShellExtData->m_lFlags); + + return S_OK; + } + catch(const std::exception& e) { - LOG_ERROR(m_spLog) << "Wrong internal state."; + LOG_CRITICAL(m_spLog) << L"Unexpected std exception encountered in " << __FUNCTION__ << L": " << e.what(); return E_FAIL; } - - if(!plFlags) + catch(...) { - LOG_ERROR(m_spLog) << "Invalid argument."; - return E_INVALIDARG; + LOG_CRITICAL(m_spLog) << L"Unexpected other exception encountered in " << __FUNCTION__ << L"."; + return E_FAIL; } +} +HRESULT CShellExtControl::Initialize() +{ + if(m_bInitialized) + return S_OK; + + // create protection mutex chcore::TIpcMutexLock lock(m_mutex); - (*plFlags) = m_pShellExtData->m_lFlags; + // memory mapped file + m_hMemory = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, sizeof(SHELLEXT_DATA), _T("CHShellExtControlData")); // name of map object + DWORD dwLastError = GetLastError(); // NOTE: last error is needed also for success case (for already exists status) + if(!m_hMemory) + { + LOG_HRESULT(m_spLog, dwLastError) << L"Cannot create file mapping."; + return E_FAIL; + } - LOG_DEBUG(m_spLog) << "Returning flags: " << LOG_PARAM(m_pShellExtData->m_lFlags); + m_pShellExtData = (SHELLEXT_DATA*)MapViewOfFile(m_hMemory, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); + if(!m_pShellExtData) + { + DWORD dwError = GetLastError(); // NOTE: do not overwrite dwLastError, as the value is needed later + LOG_HRESULT(m_spLog, dwError) << L"Cannot map view of file."; + CloseHandle(m_hMemory); + m_hMemory = nullptr; + return E_FAIL; + } + + if(dwLastError != ERROR_ALREADY_EXISTS) + { + if(dwLastError == ERROR_SUCCESS) + { + LOG_DEBUG(m_spLog) << L"Copy Handler is not running. Disabling shell extension."; + } + else + { + LOG_HRESULT(m_spLog, dwLastError) << L"Copy Handler is not running. Disabling shell extension."; + } + m_pShellExtData->m_lFlags = 0; + } + + m_bInitialized = true; return S_OK; } Index: src/chext/ShellExtControl.h =================================================================== diff -u -r306fbe693c70290af9de9a5779084a697de22d75 -r134983cab6122e3fff73994a6f9c417aaeab3bc2 --- src/chext/ShellExtControl.h (.../ShellExtControl.h) (revision 306fbe693c70290af9de9a5779084a697de22d75) +++ src/chext/ShellExtControl.h (.../ShellExtControl.h) (revision 134983cab6122e3fff73994a6f9c417aaeab3bc2) @@ -48,19 +48,22 @@ COM_INTERFACE_ENTRY(IShellExtControl) END_COM_MAP() -protected: - HANDLE m_hMemory; +private: + HRESULT Initialize(); + +private: + HANDLE m_hMemory = nullptr; chcore::TIpcMutex m_mutex; struct SHELLEXT_DATA { - long m_lID; - long m_lFlags; + long m_lFlags = 0; } *m_pShellExtData; CComAutoCriticalSection m_lock; logger::TLoggerPtr m_spLog; chcore::TSharedMemory m_shmConfiguration; + bool m_bInitialized = false; }; #endif //__SHELLEXTCONTROL_H_ Index: src/liblogger/TLogger.h =================================================================== diff -u -r7de00e54431d78b6c54fad6fb163dbc306381ef5 -r134983cab6122e3fff73994a6f9c417aaeab3bc2 --- src/liblogger/TLogger.h (.../TLogger.h) (revision 7de00e54431d78b6c54fad6fb163dbc306381ef5) +++ src/liblogger/TLogger.h (.../TLogger.h) (revision 134983cab6122e3fff73994a6f9c417aaeab3bc2) @@ -84,6 +84,6 @@ #define LOG_INFO(log) if(logger::info >= (log)->GetMinSeverity()) LOG(log, logger::info) #define LOG_WARNING(log) if(logger::warning >= (log)->GetMinSeverity()) LOG(log, logger::warning) #define LOG_ERROR(log) if(logger::error >= (log)->GetMinSeverity()) LOG(log, logger::error) -#define LOG_FATAL(log) if(logger::fatal >= (log)->GetMinSeverity()) LOG(log, logger::fatal) +#define LOG_CRITICAL(log) if(logger::critical >= (log)->GetMinSeverity()) LOG(log, logger::critical) #endif