Index: src/ch/MainWnd.cpp =================================================================== diff -u -r3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision 3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4) +++ src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -692,57 +692,6 @@ break; } - case WM_GETCONFIG: - { - try - { - chcore::TConfig& rConfig = GetConfig(); - - TShellExtMenuConfig cfgShellExt; - - // experimental - doesn't work on all systems - cfgShellExt.SetShowShortcutIcons(GetPropValue(rConfig)); - - cfgShellExt.SetInterceptDragAndDrop(GetPropValue(rConfig)); - cfgShellExt.SetInterceptKeyboardActions(GetPropValue(rConfig)); - cfgShellExt.SetInterceptCtxMenuActions(GetPropValue(rConfig)); - - cfgShellExt.GetFormatter()->SetValues( - GetResManager().LoadString(IDS_BYTE_STRING), - GetResManager().LoadString(IDS_KBYTE_STRING), - GetResManager().LoadString(IDS_MBYTE_STRING), - GetResManager().LoadString(IDS_GBYTE_STRING), - GetResManager().LoadString(IDS_TBYTE_STRING) - ); - - cfgShellExt.SetShowFreeSpace(GetPropValue(rConfig)); - - PrepareDragAndDropMenuItems(cfgShellExt); - PrepareNormalMenuItems(cfgShellExt); - - chcore::TConfig cfgStorage; - chcore::TString wstrData; - - cfgShellExt.StoreInConfig(cfgStorage, _T("ShellExtCfg")); - cfgStorage.WriteToString(wstrData); - - std::wstring strSHMName = IPCSupport::GenerateSHMName((unsigned long)lParam); - - m_tCHExtharedMemory.Create(strSHMName.c_str(), wstrData); - } - catch(const std::exception& e) - { - _ASSERTE(FALSE); - CString strMsg; - strMsg.Format(L"Encountered problem trying to retrieve shell ext configuration.\nReason: %S", e.what()); - LOG_ERROR(m_spLog) << strMsg; - - return FALSE; - } - - return TRUE; - } - case WM_IDENTIFY: { //decode @@ -794,160 +743,6 @@ return CWnd::WindowProc(message, wParam, lParam); } -void CMainWnd::PrepareDragAndDropMenuItems(TShellExtMenuConfig &cfgShellExt) const -{ - chcore::TConfig& rConfig = GetConfig(); - ictranslate::CResourceManager& rResManager = GetResManager(); - - TShellMenuItemPtr spDragAndDropRootItem = cfgShellExt.GetDragAndDropRoot(); - bool bAddedAnyOption = false; - if(GetPropValue(rConfig)) - { - spDragAndDropRootItem->AddChild(std::make_shared(rResManager.LoadString(IDS_MENUCOPY_STRING), rResManager.LoadString(IDS_MENUTIPCOPY_STRING), - TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), - TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeIDataObject), - TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializePidlFolder, chcore::TSmartPath()), false, chcore::eOperation_Copy)); - bAddedAnyOption = true; - } - - if(GetPropValue(rConfig)) - { - spDragAndDropRootItem->AddChild(std::make_shared(rResManager.LoadString(IDS_MENUMOVE_STRING), rResManager.LoadString(IDS_MENUTIPMOVE_STRING), - TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Move), - TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeIDataObject), - TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializePidlFolder, chcore::TSmartPath()), false, chcore::eOperation_Move)); - bAddedAnyOption = true; - } - - if(GetPropValue(rConfig)) - { - spDragAndDropRootItem->AddChild(std::make_shared(rResManager.LoadString(IDS_MENUCOPYMOVESPECIAL_STRING), rResManager.LoadString(IDS_MENUTIPCOPYMOVESPECIAL_STRING), - TOperationTypeInfo(TOperationTypeInfo::eOpType_Autodetect, chcore::eOperation_Copy), - TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeIDataObject), - TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializePidlFolder, chcore::TSmartPath()), true)); - bAddedAnyOption = true; - } - - if(bAddedAnyOption) - { - // insert separator as an addition to other items - spDragAndDropRootItem->AddChild(std::make_shared()); - } -} - -void CMainWnd::PrepareNormalMenuItems(TShellExtMenuConfig &cfgShellExt) const -{ - chcore::TConfig& rConfig = GetConfig(); - ictranslate::CResourceManager& rResManager = GetResManager(); - - TShellMenuItemPtr spNormalRootItem = cfgShellExt.GetNormalRoot(); - - if(GetPropValue(rConfig)) - { - spNormalRootItem->AddChild(std::make_shared(rResManager.LoadString(IDS_MENUPASTE_STRING), rResManager.LoadString(IDS_MENUTIPPASTE_STRING), - TOperationTypeInfo(TOperationTypeInfo::eOpType_Autodetect, chcore::eOperation_Copy), - TSourcePathsInfo(TSourcePathsInfo::eSrcType_Clipboard), - TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializeAuto, chcore::TSmartPath()), false)); - } - - if(GetPropValue(rConfig)) - { - spNormalRootItem->AddChild(std::make_shared(rResManager.LoadString(IDS_MENUPASTESPECIAL_STRING), rResManager.LoadString(IDS_MENUTIPPASTESPECIAL_STRING), - TOperationTypeInfo(TOperationTypeInfo::eOpType_Autodetect, chcore::eOperation_Copy), - TSourcePathsInfo(TSourcePathsInfo::eSrcType_Clipboard), - TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializeAuto, chcore::TSmartPath()), true)); - } - - if(GetPropValue(rConfig) || GetPropValue(rConfig) || GetPropValue(rConfig)) - { - // prepare shortcuts for all menu options - std::vector vShortcutStrings; - GetPropValue(rConfig, vShortcutStrings); - - std::vector vShortcuts; - - for(const CString& strShortcutString : vShortcutStrings) - { - CShortcut tShortcut; - if(tShortcut.FromString(strShortcutString)) - vShortcuts.push_back(tShortcut); - else - BOOST_ASSERT(false); // non-critical, but not very nice - } - - if(GetPropValue(rConfig)) - { - std::shared_ptr menuItem(std::make_shared(rResManager.LoadString(IDS_MENUCOPYTO_STRING), rResManager.LoadString(IDS_MENUTIPCOPYTO_STRING))); - for(const CShortcut& tShortcut : vShortcuts) - { - menuItem->AddChild(std::make_shared((PCTSTR)tShortcut.m_strName, (PCTSTR)tShortcut.m_strPath, - TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), - TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), - TDestinationPathInfo(TDestinationPathInfo::eDstType_Specified, chcore::PathFromString((PCTSTR)tShortcut.m_strPath)), false)); - } - - spNormalRootItem->AddChild(menuItem); - - // optionally separator - if(!vShortcuts.empty()) - menuItem->AddChild(std::make_shared()); - - // "Choose" menu option - menuItem->AddChild(std::make_shared(rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_STRING), rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_TOOLTIP_STRING), - TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), - TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), - TDestinationPathInfo(TDestinationPathInfo::eDstType_Choose, chcore::TSmartPath()), false)); - } - - if(GetPropValue(rConfig)) - { - std::shared_ptr menuItem(std::make_shared(rResManager.LoadString(IDS_MENUMOVETO_STRING), rResManager.LoadString(IDS_MENUTIPMOVETO_STRING))); - for(const CShortcut& tShortcut : vShortcuts) - { - menuItem->AddChild(std::make_shared((PCTSTR)tShortcut.m_strName, (PCTSTR)tShortcut.m_strPath, - TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Move), - TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), - TDestinationPathInfo(TDestinationPathInfo::eDstType_Specified, chcore::PathFromString((PCTSTR)tShortcut.m_strPath)), false)); - } - - spNormalRootItem->AddChild(menuItem); - - // optionally separator - if(!vShortcuts.empty()) - menuItem->AddChild(std::make_shared()); - - // "Choose" menu option - menuItem->AddChild(std::make_shared(rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_STRING), rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_TOOLTIP_STRING), - TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Move), - TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), - TDestinationPathInfo(TDestinationPathInfo::eDstType_Choose, chcore::TSmartPath()), false)); - } - - if(GetPropValue(rConfig)) - { - std::shared_ptr menuItem(std::make_shared(rResManager.LoadString(IDS_MENUCOPYMOVETOSPECIAL_STRING), rResManager.LoadString(IDS_MENUTIPCOPYMOVETOSPECIAL_STRING))); - for(const CShortcut& tShortcut : vShortcuts) - { - menuItem->AddChild(std::make_shared((PCTSTR)tShortcut.m_strName, (PCTSTR)tShortcut.m_strPath, - TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), - TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), - TDestinationPathInfo(TDestinationPathInfo::eDstType_Specified, chcore::PathFromString((PCTSTR)tShortcut.m_strPath)), true)); - } - - spNormalRootItem->AddChild(menuItem); - - // optionally separator - if(!vShortcuts.empty()) - menuItem->AddChild(std::make_shared()); - - // "Choose" menu option - menuItem->AddChild(std::make_shared(rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_STRING), rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_TOOLTIP_STRING), - TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), - TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), - TDestinationPathInfo(TDestinationPathInfo::eDstType_Choose, chcore::TSmartPath()), true)); - } - } -} void CMainWnd::OnAppAbout() { CAboutDlg *pdlg=new CAboutDlg; Index: src/ch/OptionsDlg.cpp =================================================================== diff -u -ra008bec4207ec5e71dfa8fd85cfe71d72e996a48 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/ch/OptionsDlg.cpp (.../OptionsDlg.cpp) (revision a008bec4207ec5e71dfa8fd85cfe71d72e996a48) +++ src/ch/OptionsDlg.cpp (.../OptionsDlg.cpp) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -39,7 +39,8 @@ // COptionsDlg dialog COptionsDlg::COptionsDlg(CWnd* pParent /*=nullptr*/) - :ictranslate::CLanguageDialog(IDD_OPTIONS_DIALOG, pParent, &m_bLock) + :ictranslate::CLanguageDialog(IDD_OPTIONS_DIALOG, pParent, &m_bLock), + m_spLog(logger::MakeLogger(GetLogFileData(), L"OptionsDlg")) { } @@ -211,6 +212,7 @@ ApplyProperties(); SendClosingNotify(); + CLanguageDialog::OnOK(); } @@ -473,6 +475,18 @@ rConfig.ResumeNotifications(); rConfig.Write(); + + LOG_INFO(m_spLog) << L"Updating shell extension configuration"; + try + { + TShellExtensionConfigPtr spConfig = GetShellExtensionConfig(); + if(spConfig) + spConfig->PrepareConfig(); + } + catch(const std::exception& e) + { + LOG_INFO(m_spLog) << L"Failed to set shell extension configuration. Error: " << e.what(); + } } void COptionsDlg::OnCancel() Index: src/ch/OptionsDlg.h =================================================================== diff -u -r8068e0c351055554340ac9755d1bc846893bf2b8 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/ch/OptionsDlg.h (.../OptionsDlg.h) (revision 8068e0c351055554340ac9755d1bc846893bf2b8) +++ src/ch/OptionsDlg.h (.../OptionsDlg.h) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -61,6 +61,7 @@ DECLARE_MESSAGE_MAP() private: + logger::TLoggerPtr m_spLog; static bool m_bLock; // locker std::vector m_cvRecent; Index: src/ch/TShellExtensionConfig.cpp =================================================================== diff -u --- src/ch/TShellExtensionConfig.cpp (revision 0) +++ src/ch/TShellExtensionConfig.cpp (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -0,0 +1,229 @@ +// ============================================================================ +// Copyright (C) 2001-2016 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "TShellExtensionConfig.h" +#include "ch.h" +#include "../common/TShellExtMenuConfig.h" +#include "CfgProperties.h" +#include "resource.h" +#include "shortcuts.h" + +TShellExtensionConfig::TShellExtensionConfig(const logger::TLogFileDataPtr& spLogData) : + m_spLog(logger::MakeLogger(spLogData, L"ShellExtConfig")) +{ +} + +void TShellExtensionConfig::PrepareConfig() +{ + try + { + chcore::TConfig& rConfig = GetConfig(); + + TShellExtMenuConfig cfgShellExt; + + // experimental - doesn't work on all systems + cfgShellExt.SetShowShortcutIcons(GetPropValue(rConfig)); + + cfgShellExt.SetInterceptDragAndDrop(GetPropValue(rConfig)); + cfgShellExt.SetInterceptKeyboardActions(GetPropValue(rConfig)); + cfgShellExt.SetInterceptCtxMenuActions(GetPropValue(rConfig)); + + cfgShellExt.GetFormatter()->SetValues( + GetResManager().LoadString(IDS_BYTE_STRING), + GetResManager().LoadString(IDS_KBYTE_STRING), + GetResManager().LoadString(IDS_MBYTE_STRING), + GetResManager().LoadString(IDS_GBYTE_STRING), + GetResManager().LoadString(IDS_TBYTE_STRING) + ); + + cfgShellExt.SetShowFreeSpace(GetPropValue(rConfig)); + + PrepareDragAndDropMenuItems(cfgShellExt); + PrepareNormalMenuItems(cfgShellExt); + + chcore::TConfig cfgStorage; + chcore::TString wstrData; + + cfgShellExt.StoreInConfig(cfgStorage, _T("ShellExtCfg")); + cfgStorage.WriteToString(wstrData); + + m_shellExtProvider.SetConfigData(wstrData); + } + catch(const std::exception& e) + { + CString strMsg; + strMsg.Format(L"Encountered problem trying to provide shell ext configuration.\nReason: %S", e.what()); + LOG_ERROR(m_spLog) << strMsg; + } +} + +void TShellExtensionConfig::PrepareDragAndDropMenuItems(TShellExtMenuConfig &cfgShellExt) const +{ + chcore::TConfig& rConfig = GetConfig(); + ictranslate::CResourceManager& rResManager = GetResManager(); + + TShellMenuItemPtr spDragAndDropRootItem = cfgShellExt.GetDragAndDropRoot(); + bool bAddedAnyOption = false; + if(GetPropValue(rConfig)) + { + spDragAndDropRootItem->AddChild(std::make_shared(rResManager.LoadString(IDS_MENUCOPY_STRING), rResManager.LoadString(IDS_MENUTIPCOPY_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeIDataObject), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializePidlFolder, chcore::TSmartPath()), false, chcore::eOperation_Copy)); + bAddedAnyOption = true; + } + + if(GetPropValue(rConfig)) + { + spDragAndDropRootItem->AddChild(std::make_shared(rResManager.LoadString(IDS_MENUMOVE_STRING), rResManager.LoadString(IDS_MENUTIPMOVE_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Move), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeIDataObject), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializePidlFolder, chcore::TSmartPath()), false, chcore::eOperation_Move)); + bAddedAnyOption = true; + } + + if(GetPropValue(rConfig)) + { + spDragAndDropRootItem->AddChild(std::make_shared(rResManager.LoadString(IDS_MENUCOPYMOVESPECIAL_STRING), rResManager.LoadString(IDS_MENUTIPCOPYMOVESPECIAL_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Autodetect, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeIDataObject), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializePidlFolder, chcore::TSmartPath()), true)); + bAddedAnyOption = true; + } + + if(bAddedAnyOption) + { + // insert separator as an addition to other items + spDragAndDropRootItem->AddChild(std::make_shared()); + } +} + +void TShellExtensionConfig::PrepareNormalMenuItems(TShellExtMenuConfig &cfgShellExt) const +{ + chcore::TConfig& rConfig = GetConfig(); + ictranslate::CResourceManager& rResManager = GetResManager(); + + TShellMenuItemPtr spNormalRootItem = cfgShellExt.GetNormalRoot(); + + if(GetPropValue(rConfig)) + { + spNormalRootItem->AddChild(std::make_shared(rResManager.LoadString(IDS_MENUPASTE_STRING), rResManager.LoadString(IDS_MENUTIPPASTE_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Autodetect, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_Clipboard), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializeAuto, chcore::TSmartPath()), false)); + } + + if(GetPropValue(rConfig)) + { + spNormalRootItem->AddChild(std::make_shared(rResManager.LoadString(IDS_MENUPASTESPECIAL_STRING), rResManager.LoadString(IDS_MENUTIPPASTESPECIAL_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Autodetect, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_Clipboard), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializeAuto, chcore::TSmartPath()), true)); + } + + if(GetPropValue(rConfig) || GetPropValue(rConfig) || GetPropValue(rConfig)) + { + // prepare shortcuts for all menu options + std::vector vShortcutStrings; + GetPropValue(rConfig, vShortcutStrings); + + std::vector vShortcuts; + + for(const CString& strShortcutString : vShortcutStrings) + { + CShortcut tShortcut; + if(tShortcut.FromString(strShortcutString)) + vShortcuts.push_back(tShortcut); + else + BOOST_ASSERT(false); // non-critical, but not very nice + } + + if(GetPropValue(rConfig)) + { + std::shared_ptr menuItem(std::make_shared(rResManager.LoadString(IDS_MENUCOPYTO_STRING), rResManager.LoadString(IDS_MENUTIPCOPYTO_STRING))); + for(const CShortcut& tShortcut : vShortcuts) + { + menuItem->AddChild(std::make_shared((PCTSTR)tShortcut.m_strName, (PCTSTR)tShortcut.m_strPath, + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), + TDestinationPathInfo(TDestinationPathInfo::eDstType_Specified, chcore::PathFromString((PCTSTR)tShortcut.m_strPath)), false)); + } + + spNormalRootItem->AddChild(menuItem); + + // optionally separator + if(!vShortcuts.empty()) + menuItem->AddChild(std::make_shared()); + + // "Choose" menu option + menuItem->AddChild(std::make_shared(rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_STRING), rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_TOOLTIP_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), + TDestinationPathInfo(TDestinationPathInfo::eDstType_Choose, chcore::TSmartPath()), false)); + } + + if(GetPropValue(rConfig)) + { + std::shared_ptr menuItem(std::make_shared(rResManager.LoadString(IDS_MENUMOVETO_STRING), rResManager.LoadString(IDS_MENUTIPMOVETO_STRING))); + for(const CShortcut& tShortcut : vShortcuts) + { + menuItem->AddChild(std::make_shared((PCTSTR)tShortcut.m_strName, (PCTSTR)tShortcut.m_strPath, + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Move), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), + TDestinationPathInfo(TDestinationPathInfo::eDstType_Specified, chcore::PathFromString((PCTSTR)tShortcut.m_strPath)), false)); + } + + spNormalRootItem->AddChild(menuItem); + + // optionally separator + if(!vShortcuts.empty()) + menuItem->AddChild(std::make_shared()); + + // "Choose" menu option + menuItem->AddChild(std::make_shared(rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_STRING), rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_TOOLTIP_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Move), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), + TDestinationPathInfo(TDestinationPathInfo::eDstType_Choose, chcore::TSmartPath()), false)); + } + + if(GetPropValue(rConfig)) + { + std::shared_ptr menuItem(std::make_shared(rResManager.LoadString(IDS_MENUCOPYMOVETOSPECIAL_STRING), rResManager.LoadString(IDS_MENUTIPCOPYMOVETOSPECIAL_STRING))); + for(const CShortcut& tShortcut : vShortcuts) + { + menuItem->AddChild(std::make_shared((PCTSTR)tShortcut.m_strName, (PCTSTR)tShortcut.m_strPath, + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), + TDestinationPathInfo(TDestinationPathInfo::eDstType_Specified, chcore::PathFromString((PCTSTR)tShortcut.m_strPath)), true)); + } + + spNormalRootItem->AddChild(menuItem); + + // optionally separator + if(!vShortcuts.empty()) + menuItem->AddChild(std::make_shared()); + + // "Choose" menu option + menuItem->AddChild(std::make_shared(rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_STRING), rResManager.LoadString(IDS_SHELLEXT_CHOOSE_DIR_TOOLTIP_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), + TDestinationPathInfo(TDestinationPathInfo::eDstType_Choose, chcore::TSmartPath()), true)); + } + } +} Index: src/ch/TShellExtensionConfig.h =================================================================== diff -u --- src/ch/TShellExtensionConfig.h (revision 0) +++ src/ch/TShellExtensionConfig.h (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -0,0 +1,45 @@ +// ============================================================================ +// Copyright (C) 2001-2016 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __TSHELLEXTENSIONCONFIG_H__ +#define __TSHELLEXTENSIONCONFIG_H__ + +#include "../common/TShellExtIpcConfigDataProvider.h" +#include "../liblogger/TLogFileData.h" +#include "../liblogger/TLogger.h" + +class TShellExtMenuConfig; + +class TShellExtensionConfig +{ +public: + TShellExtensionConfig(const logger::TLogFileDataPtr& spLogData); + + void PrepareConfig(); + + void PrepareDragAndDropMenuItems(TShellExtMenuConfig &cfgShellExt) const; + void PrepareNormalMenuItems(TShellExtMenuConfig &cfgShellExt) const; + +private: + TShellExtIpcConfigDataProvider m_shellExtProvider; + logger::TLoggerPtr m_spLog; +}; + +using TShellExtensionConfigPtr = std::shared_ptr; + +#endif Index: src/ch/ch.cpp =================================================================== diff -u -rb2102d724fda96a2533b866dbf1efca9f499713b -r306fbe693c70290af9de9a5779084a697de22d75 --- src/ch/ch.cpp (.../ch.cpp) (revision b2102d724fda96a2533b866dbf1efca9f499713b) +++ src/ch/ch.cpp (.../ch.cpp) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -475,6 +475,18 @@ SetAutorun(GetPropValue(rCfg)); #endif + // ================================= Shell extension config ============================= + LOG_INFO(m_spLog) << _T("Initializing shell extension configuration"); + try + { + m_shellExtConfig = std::make_unique(m_spLog->GetLogFileData()); + m_shellExtConfig->PrepareConfig(); + } + catch(const std::exception& e) + { + LOG_ERROR(m_spLog) << L"Failed to initialize shell extension configuration. Shell extension will be inactive. Error: " << e.what(); + } + // ================================= Main window ======================================== LOG_INFO(m_spLog) << _T("Creating main application window"); // create main window @@ -610,6 +622,11 @@ return m_spEngineLoggerConfig; } +TShellExtensionConfigPtr CCopyHandlerApp::GetShellExtensionConfig() const +{ + return m_shellExtConfig; +} + void CCopyHandlerApp::RegisterShellExtension() { CString strPath = CString(m_pathProcessor.GetProgramPath()) + _T("\\"); Index: src/ch/ch.h =================================================================== diff -u -rb2102d724fda96a2533b866dbf1efca9f499713b -r306fbe693c70290af9de9a5779084a697de22d75 --- src/ch/ch.h (.../ch.h) (revision b2102d724fda96a2533b866dbf1efca9f499713b) +++ src/ch/ch.h (.../ch.h) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -26,6 +26,7 @@ #include "TCommandLineParser.h" #include "../liblogger/TLogger.h" #include "../libchcore/TCoreEngine.h" +#include "TShellExtensionConfig.h" class CCopyHandlerApp : public CWinApp, public CAppHelper { @@ -48,6 +49,7 @@ logger::TLogFileDataPtr GetLogFileData() const; logger::TMultiLoggerConfigPtr GetEngineLoggerConfig() const; + TShellExtensionConfigPtr GetShellExtensionConfig() const; void RegisterShellExtension(); void UnregisterShellExtension(); @@ -73,6 +75,7 @@ logger::TMultiLoggerConfigPtr m_spAppLoggerConfig; logger::TMultiLoggerConfigPtr m_spEngineLoggerConfig; + TShellExtensionConfigPtr m_shellExtConfig; CWnd *m_pMainWindow; bool m_bComInitialized = false; @@ -103,4 +106,9 @@ return CCopyHandlerApp::GetConfig(); } +inline TShellExtensionConfigPtr GetShellExtensionConfig() +{ + return GetApp().GetShellExtensionConfig(); +} + #endif Index: src/ch/ch.vc140.vcxproj =================================================================== diff -u -r3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/ch/ch.vc140.vcxproj (.../ch.vc140.vcxproj) (revision 3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4) +++ src/ch/ch.vc140.vcxproj (.../ch.vc140.vcxproj) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -518,6 +518,7 @@ + @@ -537,6 +538,7 @@ + @@ -769,6 +771,7 @@ NotUsing NotUsing + @@ -786,6 +789,7 @@ + Index: src/ch/ch.vc140.vcxproj.filters =================================================================== diff -u -r3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/ch/ch.vc140.vcxproj.filters (.../ch.vc140.vcxproj.filters) (revision 3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4) +++ src/ch/ch.vc140.vcxproj.filters (.../ch.vc140.vcxproj.filters) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -242,6 +242,12 @@ Source Files\Core + + Source Files\Shared + + + Source Files\Tools + @@ -412,6 +418,12 @@ Source Files\Core + + Source Files\Shared + + + Source Files\Tools + Index: src/chext/ShellExtControl.cpp =================================================================== diff -u -rebc7fabbd2d59f9a0f723ea480b5374cc393ec12 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/chext/ShellExtControl.cpp (.../ShellExtControl.cpp) (revision ebc7fabbd2d59f9a0f723ea480b5374cc393ec12) +++ src/chext/ShellExtControl.cpp (.../ShellExtControl.cpp) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -22,39 +22,25 @@ #include "ShellExtControl.h" #include "../common/version.h" #include "Logger.h" +#include "../libchcore/TIpcMutexLock.h" CShellExtControl::CShellExtControl() : m_pShellExtData(nullptr), m_hMemory(nullptr), - m_hMutex(nullptr), + m_mutex(L"CHShellExtControlDataMutex"), m_spLog(GetLogger(L"ShellExtControl")) { LOG_DEBUG(m_spLog) << L"Constructing CShellExtControl"; // create protection mutex - m_hMutex = ::CreateMutex(nullptr, FALSE, _T("CHShellExtControlDataMutex")); - if(!m_hMutex) - { - LOG_ERROR(m_spLog) << L"Cannot create mutex."; - return; - } + chcore::TIpcMutexLock lock(m_mutex); - DWORD dwRes = WaitForSingleObject(m_hMutex, 10000); - if(dwRes != WAIT_OBJECT_0) - { - LOG_ERROR(m_spLog) << L"Timeout or fail waiting for mutex."; - ReleaseMutex(m_hMutex); - return; - } - // 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."; - ReleaseMutex(m_hMutex); - CloseHandle(m_hMutex); return; } @@ -64,8 +50,6 @@ 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."; - ReleaseMutex(m_hMutex); - CloseHandle(m_hMutex); CloseHandle(m_hMemory); m_hMemory = nullptr; return; @@ -84,8 +68,6 @@ m_pShellExtData->m_lFlags = 0; m_pShellExtData->m_lID = GetTickCount(); } - - ReleaseMutex(m_hMutex); } CShellExtControl::~CShellExtControl() @@ -97,9 +79,6 @@ // Close the process's handle to the file-mapping object. CloseHandle(m_hMemory); } - - if(m_hMutex) - CloseHandle(m_hMutex); } STDMETHODIMP CShellExtControl::GetVersion(LONG* plVersion, BSTR* pbstrVersion) @@ -125,32 +104,25 @@ { LOG_DEBUG(m_spLog) << L"Setting flags: " << LOG_PARAMS2(lFlags, lMask); - if(!m_hMutex || !m_pShellExtData) + if(!m_pShellExtData) { LOG_ERROR(m_spLog) << "Wrong internal state."; return E_FAIL; } - DWORD dwRes = WaitForSingleObject(m_hMutex, 10000); - if(dwRes != WAIT_OBJECT_0) - { - LOG_ERROR(m_spLog) << "Failed waiting for mutex."; - 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); - ReleaseMutex(m_hMutex); - return S_OK; } STDMETHODIMP CShellExtControl::GetFlags(LONG* plFlags) { LOG_DEBUG(m_spLog) << "Retrieving flags"; - if(!m_hMutex || !m_pShellExtData) + if(!m_pShellExtData) { LOG_ERROR(m_spLog) << "Wrong internal state."; return E_FAIL; @@ -162,18 +134,11 @@ return E_INVALIDARG; } - DWORD dwRes = WaitForSingleObject(m_hMutex, 10000); - if(dwRes != WAIT_OBJECT_0) - { - LOG_ERROR(m_spLog) << "Failed waiting for mutex."; - return E_FAIL; - } + chcore::TIpcMutexLock lock(m_mutex); (*plFlags) = m_pShellExtData->m_lFlags; LOG_DEBUG(m_spLog) << "Returning flags: " << LOG_PARAM(m_pShellExtData->m_lFlags); - ReleaseMutex(m_hMutex); - return S_OK; } Index: src/chext/ShellExtControl.h =================================================================== diff -u -rebc7fabbd2d59f9a0f723ea480b5374cc393ec12 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/chext/ShellExtControl.h (.../ShellExtControl.h) (revision ebc7fabbd2d59f9a0f723ea480b5374cc393ec12) +++ src/chext/ShellExtControl.h (.../ShellExtControl.h) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -20,7 +20,9 @@ #define __SHELLEXTCONTROL_H_ #include "resource.h" // main symbols -#include "..\liblogger\TLogger.h" +#include "../liblogger/TLogger.h" +#include "../libchcore/TIpcMutex.h" +#include "../libchcore/TSharedMemory.h" ///////////////////////////////////////////////////////////////////////////// // CDropMenuExt @@ -48,7 +50,8 @@ protected: HANDLE m_hMemory; - HANDLE m_hMutex; + chcore::TIpcMutex m_mutex; + struct SHELLEXT_DATA { long m_lID; @@ -57,6 +60,7 @@ CComAutoCriticalSection m_lock; logger::TLoggerPtr m_spLog; + chcore::TSharedMemory m_shmConfiguration; }; #endif //__SHELLEXTCONTROL_H_ Index: src/chext/ShellExtControl.rgs =================================================================== diff -u -rd0fdcc905035e648382256101a3d99f429af6d56 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/chext/ShellExtControl.rgs (.../ShellExtControl.rgs) (revision d0fdcc905035e648382256101a3d99f429af6d56) +++ src/chext/ShellExtControl.rgs (.../ShellExtControl.rgs) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -18,7 +18,7 @@ ForceRemove 'Programmable' InprocServer32 = s '%MODULE%' { - val ThreadingModel = s 'Neutral' + val ThreadingModel = s 'Both' } 'TypeLib' = s '{68FAFC14-8EB8-4DA1-90EB-6B3D22010505}' } Index: src/chext/ShellExtensionVerifier.cpp =================================================================== diff -u -r3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/chext/ShellExtensionVerifier.cpp (.../ShellExtensionVerifier.cpp) (revision 3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4) +++ src/chext/ShellExtensionVerifier.cpp (.../ShellExtensionVerifier.cpp) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -19,11 +19,11 @@ #include "stdafx.h" #include "ShellExtensionVerifier.h" #include "Logger.h" -#include "../libchcore/TSharedMemory.h" #include "../libchcore/TConfig.h" #include "../liblogger/TLogger.h" #include "../common/TShellExtMenuConfig.h" #include +#include "../common/TShellExtIpcConfigDataConsumer.h" HWND ShellExtensionVerifier::VerifyShellExt(IShellExtControl* piShellExtControl) { @@ -72,31 +72,11 @@ if(hWnd == nullptr) return E_FAIL; - // generate a random number for naming shared memory - unsigned int uiSHMID = 0; - if(rand_s(&uiSHMID) != 0 || uiSHMID == 0) - { - LOG_WARNING(spLogger) << L"Failed to generate random number for shared memory naming. Falling back to tick count."; - uiSHMID = GetTickCount(); - } + LOG_DEBUG(spLogger) << L"Requesting CH configuration"; - LOG_DEBUG(spLogger) << L"Requesting CH configuration. Shared memory identifier " << uiSHMID; - - if(::SendMessage(hWnd, WM_GETCONFIG, 0, uiSHMID) != TRUE) - { - LOG_ERROR(spLogger) << L"Failed to retrieve configuration from Copy Handler"; - return E_FAIL; - } - - std::wstring strSHMName = IPCSupport::GenerateSHMName(uiSHMID); - - chcore::TSharedMemory tSharedMemory; - chcore::TString wstrData; + chcore::TString wstrData = TShellExtIpcConfigDataConsumer::GetConfigData(); chcore::TConfig cfgShellExtData; - tSharedMemory.Open(strSHMName.c_str()); - tSharedMemory.Read(wstrData); - LOG_TRACE(spLogger) << L"Retrieved shell ext config: " << wstrData; cfgShellExtData.ReadFromString(wstrData); Index: src/chext/chext.vc140.vcxproj =================================================================== diff -u -rf0b3178897bcff99beb7fde44dfe952ccbf40bec -r306fbe693c70290af9de9a5779084a697de22d75 --- src/chext/chext.vc140.vcxproj (.../chext.vc140.vcxproj) (revision f0b3178897bcff99beb7fde44dfe952ccbf40bec) +++ src/chext/chext.vc140.vcxproj (.../chext.vc140.vcxproj) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -553,6 +553,7 @@ NotUsing NotUsing + @@ -596,6 +597,7 @@ + Index: src/chext/chext.vc140.vcxproj.filters =================================================================== diff -u -rebc7fabbd2d59f9a0f723ea480b5374cc393ec12 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/chext/chext.vc140.vcxproj.filters (.../chext.vc140.vcxproj.filters) (revision ebc7fabbd2d59f9a0f723ea480b5374cc393ec12) +++ src/chext/chext.vc140.vcxproj.filters (.../chext.vc140.vcxproj.filters) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -77,6 +77,9 @@ Source Files\Tools + + Source Files\Common + @@ -127,6 +130,9 @@ Source Files\Tools + + Source Files\Common + Index: src/common/TShellExtIpcConfigDataConsumer.cpp =================================================================== diff -u --- src/common/TShellExtIpcConfigDataConsumer.cpp (revision 0) +++ src/common/TShellExtIpcConfigDataConsumer.cpp (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -0,0 +1,31 @@ +// ============================================================================ +// Copyright (C) 2001-2016 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "TShellExtIpcConfigDataConsumer.h" + +chcore::TString TShellExtIpcConfigDataConsumer::GetConfigData() +{ + chcore::TSharedMemory shmConfigData; + + chcore::TString strData; + shmConfigData.Open(L"CHShellExtConfig"); + shmConfigData.Read(strData); + + return strData; +} Index: src/common/TShellExtIpcConfigDataConsumer.h =================================================================== diff -u --- src/common/TShellExtIpcConfigDataConsumer.h (revision 0) +++ src/common/TShellExtIpcConfigDataConsumer.h (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -0,0 +1,30 @@ +// ============================================================================ +// Copyright (C) 2001-2016 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __TSHELLEXTIPCCONFIGDATACONSUMER_H__ +#define __TSHELLEXTIPCCONFIGDATACONSUMER_H__ + +#include "../libchcore/TSharedMemory.h" + +class TShellExtIpcConfigDataConsumer +{ +public: + static chcore::TString GetConfigData(); +}; + +#endif Index: src/common/TShellExtIpcConfigDataProvider.cpp =================================================================== diff -u --- src/common/TShellExtIpcConfigDataProvider.cpp (revision 0) +++ src/common/TShellExtIpcConfigDataProvider.cpp (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -0,0 +1,26 @@ +// ============================================================================ +// Copyright (C) 2001-2016 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "TShellExtIpcConfigDataProvider.h" + +void TShellExtIpcConfigDataProvider::SetConfigData(const chcore::TString& strConfigData) +{ + m_shmConfigData.Close(); + m_shmConfigData.Create(L"CHShellExtConfig", strConfigData); +} Index: src/common/TShellExtIpcConfigDataProvider.h =================================================================== diff -u --- src/common/TShellExtIpcConfigDataProvider.h (revision 0) +++ src/common/TShellExtIpcConfigDataProvider.h (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -0,0 +1,33 @@ +// ============================================================================ +// Copyright (C) 2001-2016 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __TSHELLEXTIPCCONFIGDATAPROVIDER_H__ +#define __TSHELLEXTIPCCONFIGDATAPROVIDER_H__ + +#include "../libchcore/TSharedMemory.h" + +class TShellExtIpcConfigDataProvider +{ +public: + void SetConfigData(const chcore::TString& pszConfigData); + +private: + chcore::TSharedMemory m_shmConfigData; +}; + +#endif Index: src/common/ipcstructs.h =================================================================== diff -u -rb165add706c4fab9d783f0564b1dd398492da491 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/common/ipcstructs.h (.../ipcstructs.h) (revision b165add706c4fab9d783f0564b1dd398492da491) +++ src/common/ipcstructs.h (.../ipcstructs.h) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -19,32 +19,12 @@ #ifndef __SHAREDDATA_H__ #define __SHAREDDATA_H__ -#include - // messages used -#define WM_GETCONFIG WM_USER+20 - enum ECopyDataType { eCDType_TaskDefinitionContent, eCDType_TaskDefinitionContentSpecial, eCDType_CommandLineArguments, }; -enum ELocation -{ - eLocation_DragAndDropMenu, - eLocation_ContextMenu -}; - -namespace IPCSupport -{ - static std::wstring GenerateSHMName(unsigned long ulRequestID) - { - std::wstring wstrName = _T("CHExtSHM_"); - wstrName += boost::lexical_cast(ulRequestID); - return wstrName; - } -} - #endif Index: src/libchcore/ErrorCodes.h =================================================================== diff -u -r4fe995b304ea342b50293f92d3c1992b43b820f7 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/libchcore/ErrorCodes.h (.../ErrorCodes.h) (revision 4fe995b304ea342b50293f92d3c1992b43b820f7) +++ src/libchcore/ErrorCodes.h (.../ErrorCodes.h) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -50,6 +50,7 @@ eErr_WaitingFailed = 1007, eErr_CannotSuspendThread = 1008, eErr_CannotSetEvent = 1009, + eErr_CannotCreateMutex = 1010, // string errors (1500+) Index: src/libchcore/TIpcMutex.cpp =================================================================== diff -u --- src/libchcore/TIpcMutex.cpp (revision 0) +++ src/libchcore/TIpcMutex.cpp (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -0,0 +1,79 @@ +// ============================================================================ +// Copyright (C) 2001-2016 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "TIpcMutex.h" +#include "TCoreWin32Exception.h" + +namespace chcore +{ + TIpcMutex::TIpcMutex() + { + } + + TIpcMutex::TIpcMutex(const wchar_t* pszName) + { + m_hMutex = ::CreateMutex(nullptr, FALSE, pszName); + if(!m_hMutex) + throw TCoreWin32Exception(eErr_CannotCreateMutex, GetLastError(), L"Cannot create mutex", LOCATION); + } + + TIpcMutex::~TIpcMutex() + { + if(m_bLocked) + Unlock(); + + if(m_hMutex) + CloseHandle(m_hMutex); + } + + void TIpcMutex::CreateMutex(const wchar_t* pszName) + { + m_hMutex = ::CreateMutex(nullptr, FALSE, pszName); + if(!m_hMutex) + throw TCoreWin32Exception(eErr_CannotCreateMutex, GetLastError(), L"Cannot create mutex", LOCATION); + } + + void TIpcMutex::Lock(DWORD dwTimeout) + { + if(!m_hMutex) + throw TCoreException(eErr_InvalidData, L"Mutex not created. Cannot lock.", LOCATION); + if(m_bLocked) + throw TCoreException(eErr_InvalidData, L"Mutex already locked.", LOCATION); + + DWORD dwRes = WaitForSingleObject(m_hMutex, dwTimeout); + if(dwRes != WAIT_OBJECT_0) + { + ReleaseMutex(m_hMutex); + throw TCoreWin32Exception(eErr_CannotCreateMutex, GetLastError(), L"Wait for mutex failed", LOCATION); + } + + m_bLocked = true; + } + + void TIpcMutex::Unlock() + { + if(!m_hMutex) + throw TCoreException(eErr_InvalidData, L"Mutex not created. Cannot lock.", LOCATION); + if(!m_bLocked) + throw TCoreException(eErr_InvalidData, L"Mutex not locked. Cannot unlock.", LOCATION); + + ReleaseMutex(m_hMutex); + m_bLocked = false; + } +} Index: src/libchcore/TIpcMutex.h =================================================================== diff -u --- src/libchcore/TIpcMutex.h (revision 0) +++ src/libchcore/TIpcMutex.h (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -0,0 +1,44 @@ +// ============================================================================ +// Copyright (C) 2001-2016 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __TIPCMUTEX_H__ +#define __TIPCMUTEX_H__ + +#include "libchcore.h" + +namespace chcore +{ + class LIBCHCORE_API TIpcMutex + { + public: + TIpcMutex(); + TIpcMutex(const wchar_t* pszName); + ~TIpcMutex(); + + void CreateMutex(const wchar_t* pszName); + + void Lock(DWORD dwTimeout = INFINITE); + void Unlock(); + + private: + HANDLE m_hMutex = nullptr; + bool m_bLocked = false; + }; +} + +#endif Index: src/libchcore/TIpcMutexLock.cpp =================================================================== diff -u --- src/libchcore/TIpcMutexLock.cpp (revision 0) +++ src/libchcore/TIpcMutexLock.cpp (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -0,0 +1,34 @@ +// ============================================================================ +// Copyright (C) 2001-2016 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "TIpcMutexLock.h" + +namespace chcore +{ + TIpcMutexLock::TIpcMutexLock(TIpcMutex& rMutex) : + m_rMutex(rMutex) + { + m_rMutex.Lock(); + } + + TIpcMutexLock::~TIpcMutexLock() + { + m_rMutex.Unlock(); + } +} Index: src/libchcore/TIpcMutexLock.h =================================================================== diff -u --- src/libchcore/TIpcMutexLock.h (revision 0) +++ src/libchcore/TIpcMutexLock.h (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -0,0 +1,38 @@ +// ============================================================================ +// Copyright (C) 2001-2016 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __TIPCMUTEXLOCK_H__ +#define __TIPCMUTEXLOCK_H__ + +#include "libchcore.h" +#include "TIpcMutex.h" + +namespace chcore +{ + class LIBCHCORE_API TIpcMutexLock + { + public: + explicit TIpcMutexLock(TIpcMutex& rMutex); + ~TIpcMutexLock(); + + private: + TIpcMutex& m_rMutex; + }; +} + +#endif Index: src/libchcore/TSharedMemory.cpp =================================================================== diff -u -r8068e0c351055554340ac9755d1bc846893bf2b8 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/libchcore/TSharedMemory.cpp (.../TSharedMemory.cpp) (revision 8068e0c351055554340ac9755d1bc846893bf2b8) +++ src/libchcore/TSharedMemory.cpp (.../TSharedMemory.cpp) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -25,42 +25,19 @@ #include #include "ErrorCodes.h" #include "TCoreException.h" +#include "TIpcMutexLock.h" namespace chcore { -#define MUTEX_SUFFIX _T("_Mutex") + #define MUTEX_SUFFIX _T("_Mutex") - class TMutexLock - { - public: - explicit TMutexLock(HANDLE hMutex) : - m_hMutex(hMutex) - { - if (m_hMutex) - { - DWORD dwRes = WaitForSingleObject(hMutex, 10000); - if (dwRes != WAIT_OBJECT_0) - throw TCoreException(eErr_MutexTimedOut, L"Waiting for object failed", LOCATION); - } - } - - ~TMutexLock() - { - if (m_hMutex) - ReleaseMutex(m_hMutex); - } - - private: - HANDLE m_hMutex; - }; - /////////////////////////////////////////////////////////////////////////////////////// // TSharedMemory class TSharedMemory::TSharedMemory() : m_hFileMapping(nullptr), m_pMappedMemory(nullptr), - m_hMutex(nullptr), + m_mutex(nullptr), m_stSize(0) { } @@ -84,26 +61,12 @@ std::wstring wstrMutexName = pszName; wstrMutexName += MUTEX_SUFFIX; - SECURITY_DESCRIPTOR secDesc; - if (!InitializeSecurityDescriptor(&secDesc, SECURITY_DESCRIPTOR_REVISION)) - throw TCoreException(eErr_CannotOpenSharedMemory, L"Failed to initialize security descriptor", LOCATION); + m_mutex.CreateMutex(wstrMutexName.c_str()); - SECURITY_ATTRIBUTES secAttr; - secAttr.nLength = sizeof(secAttr); - secAttr.bInheritHandle = FALSE; - secAttr.lpSecurityDescriptor = &secDesc; - - if (!SetSecurityDescriptorDacl(secAttr.lpSecurityDescriptor, TRUE, 0, FALSE)) - throw TCoreException(eErr_CannotOpenSharedMemory, L"Failed to set dacl", LOCATION); - - m_hMutex = ::CreateMutex(&secAttr, FALSE, wstrMutexName.c_str()); - if (!m_hMutex) - throw TCoreException(eErr_CannotOpenSharedMemory, L"Failed to create mutex", LOCATION); - - m_hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, &secAttr, PAGE_READWRITE, 0, boost::numeric_cast(stSize + sizeof(size_t)), pszName); + m_hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, boost::numeric_cast(stSize + sizeof(size_t)), pszName); if (!m_hFileMapping) throw TCoreException(eErr_CannotOpenSharedMemory, L"Failed to create file mapping", LOCATION); - else if (GetLastError() == ERROR_ALREADY_EXISTS) + if(GetLastError() == ERROR_ALREADY_EXISTS) throw TCoreException(eErr_SharedMemoryAlreadyExists, L"File mapping already exists", LOCATION); // shared memory already exists - cannot guarantee that the size is correct // Get a pointer to the file-mapped shared memory. @@ -117,7 +80,7 @@ throw; } - TMutexLock lock(m_hMutex); + TIpcMutexLock lock(m_mutex); m_stSize = stSize + sizeof(shm_size_t); *(shm_size_t*)m_pMappedMemory = sizeof(shm_size_t); // no data inside (set just in case) @@ -132,7 +95,7 @@ { Create(pszName, stSize); - TMutexLock lock(m_hMutex); + TIpcMutexLock lock(m_mutex); *(shm_size_t*)m_pMappedMemory = stSize; memcpy(m_pMappedMemory + sizeof(shm_size_t), pbyData, stSize); @@ -159,7 +122,7 @@ throw; } - TMutexLock lock(m_hMutex); + TIpcMutexLock lock(m_mutex); m_stSize = *(shm_size_t*)m_pMappedMemory + sizeof(shm_size_t); } @@ -168,12 +131,6 @@ { try { - if (m_hMutex) - { - CloseHandle(m_hMutex); - m_hMutex = nullptr; - } - if (m_pMappedMemory) { UnmapViewOfFile(m_pMappedMemory); @@ -197,7 +154,7 @@ if (!m_hFileMapping || !m_pMappedMemory || m_stSize <= sizeof(shm_size_t)) throw TCoreException(eErr_SharedMemoryNotOpen, L"Invalid shared memory state", LOCATION); - TMutexLock lock(m_hMutex); + TIpcMutexLock lock(m_mutex); shm_size_t stByteSize = *(shm_size_t*)m_pMappedMemory; if ((stByteSize % 2) != 0) @@ -222,7 +179,7 @@ if (stSize + sizeof(shm_size_t) > m_stSize) throw TCoreException(eErr_BoundsExceeded, L"stSize", LOCATION); - TMutexLock lock(m_hMutex); + TIpcMutexLock lock(m_mutex); *(shm_size_t*)m_pMappedMemory = stSize; memcpy(m_pMappedMemory + sizeof(shm_size_t), pbyData, stSize); @@ -256,7 +213,7 @@ if (!m_hFileMapping || !m_pMappedMemory || m_stSize <= sizeof(shm_size_t)) return 0; - TMutexLock lock(m_hMutex); + TIpcMutexLock lock(m_mutex); return *(shm_size_t*)m_pMappedMemory; } Index: src/libchcore/TSharedMemory.h =================================================================== diff -u -re96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/libchcore/TSharedMemory.h (.../TSharedMemory.h) (revision e96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3) +++ src/libchcore/TSharedMemory.h (.../TSharedMemory.h) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -24,6 +24,7 @@ #define __TSHAREDMEMORY_H__ #include "TString.h" +#include "TIpcMutex.h" namespace chcore { @@ -59,7 +60,7 @@ BYTE* m_pMappedMemory; shm_size_t m_stSize; // contains full size of the allocated shared memory (in case we created the memory), size of occupied memory in case we opened the memory. - HANDLE m_hMutex; + mutable TIpcMutex m_mutex; }; } Index: src/libchcore/libchcore.vc140.vcxproj =================================================================== diff -u -r3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/libchcore/libchcore.vc140.vcxproj (.../libchcore.vc140.vcxproj) (revision 3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4) +++ src/libchcore/libchcore.vc140.vcxproj (.../libchcore.vc140.vcxproj) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -511,6 +511,8 @@ + + @@ -818,6 +820,8 @@ + + Index: src/libchcore/libchcore.vc140.vcxproj.filters =================================================================== diff -u -r3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4 -r306fbe693c70290af9de9a5779084a697de22d75 --- src/libchcore/libchcore.vc140.vcxproj.filters (.../libchcore.vc140.vcxproj.filters) (revision 3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4) +++ src/libchcore/libchcore.vc140.vcxproj.filters (.../libchcore.vc140.vcxproj.filters) (revision 306fbe693c70290af9de9a5779084a697de22d75) @@ -518,6 +518,12 @@ Source Files\Tools + + Source Files\Tools + + + Source Files\Tools + @@ -958,5 +964,11 @@ Source Files\Tools + + Source Files\Tools + + + Source Files\Tools + \ No newline at end of file