Index: src/ch/MainWnd.cpp =================================================================== diff -u -ra0a0c78670588f86c6be24afb076e6b304441563 -rf2eab440135dd8052881aa3e9af83ec85e9bf1bf --- src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision a0a0c78670588f86c6be24afb076e6b304441563) +++ src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision f2eab440135dd8052881aa3e9af83ec85e9bf1bf) @@ -1,5 +1,5 @@ /*************************************************************************** -* Copyright (C) 2001-2008 by Jozef Starosczyk * +* Copyright (C) 2001-2011 by Jozef Starosczyk * * ixen@copyhandler.com * * * * This program is free software; you can redistribute it and/or modify * @@ -32,8 +32,14 @@ #include "MiniviewDlg.h" #include "StatusDlg.h" #include "ClipboardMonitor.h" - #include +#include +#include "../common/TShellExtMenuConfig.h" +#include "../libchcore/TConfig.h" +#include "FileSupport.h" +#include "StringHelpers.h" +#include "../libchcore/TCoreException.h" +#include "../libicpf/exception.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -52,8 +58,6 @@ #define TM_AUTOREMOVE 1000 #define TM_ACCEPTING 100 -extern CSharedConfigStruct* g_pscsShared; - extern int iCount; extern unsigned short msg[]; @@ -115,7 +119,8 @@ HICON hIcon = (HICON)GetResManager().LoadImage(MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR | LR_VGACOLOR); CString strText = GetApp().GetAppNameVer(); - strText += GetResManager().LoadString(IDS_CH_PORTABLE_STRING); + if(GetApp().IsInPortableMode()) + strText += GetResManager().LoadString(IDS_CH_PORTABLE_STRING); bool bRes=m_ctlTray.CreateIcon(m_hWnd, WM_TRAYNOTIFY, strText, hIcon, 0); if(!bRes) @@ -164,90 +169,126 @@ lpCreateStruct->dwExStyle |= WS_EX_TOPMOST; if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; + + bool bCaughtError = false; + const size_t stMaxErrInfo = 1024; + boost::shared_array szErrInfo(new wchar_t[stMaxErrInfo]); - // get msg id of taskbar created message - m_uiTaskbarRestart=RegisterWindowMessage(_T("TaskbarCreated")); + try + { + // get msg id of taskbar created message + m_uiTaskbarRestart = RegisterWindowMessage(_T("TaskbarCreated")); - // Create the tray icon - ShowTrayIcon(); + // Create the tray icon + ShowTrayIcon(); - // initialize CTaskArray - m_tasks.Create(m_pFeedbackFactory); + // initialize CTaskArray + m_tasks.Create(m_pFeedbackFactory); - // load last state - LOG_INFO(_T("Loading existing tasks...")); - CString strPath; - GetApp().GetProgramDataPath(strPath); - strPath += _T("\\Tasks\\"); - m_tasks.SetTasksDir(strPath); - m_tasks.LoadDataProgress(); - m_tasks.TasksRetryProcessing(); + // load last state + LOG_INFO(_T("Loading existing tasks...")); + CString strPath; + GetApp().GetProgramDataPath(strPath); + strPath += _T("\\Tasks\\"); + m_tasks.SetTasksDir(chcore::PathFromString(strPath)); - // start clipboard monitoring - LOG_INFO(_T("Starting clipboard monitor...")); - CClipboardMonitor::StartMonitor(&m_tasks); - - EUpdatesFrequency eFrequency = (EUpdatesFrequency)GetPropValue(GetConfig()); - if(eFrequency != eFreq_Never) - { - unsigned long long ullMinInterval = 0; - switch(eFrequency) - { - case eFreq_Daily: - ullMinInterval = 1*24*60*60; - break; - case eFreq_Weekly: - ullMinInterval = 7*24*60*60; - break; - case eFreq_OnceEvery2Weeks: - ullMinInterval = 14*24*60*60; - break; - case eFreq_Monthly: - ullMinInterval = 30*24*60*60; // we don't really care if it is a day less or more - break; - case eFreq_Quarterly: - ullMinInterval = 90*24*60*60; - break; - case eFreq_EveryStartup: - default: - ullMinInterval = 0; - } + // load tasks + m_tasks.LoadDataProgress(); - // get last check time stored in configuration - unsigned long long ullCurrentStamp = _time64(NULL); - unsigned long long ullTimestamp = GetPropValue(GetConfig()); + // import tasks specified at command line (before loading current tasks) + const TCommandLineParser& cmdLine = GetApp().GetCommandLine(); + ProcessCommandLine(cmdLine); - // perform checking for updates only when the minimal interval has passed - if(ullCurrentStamp - ullTimestamp >= ullMinInterval) - { - LOG_INFO(_T("Checking for updates...")); + // start processing of the tasks loaded above and added by a command line + m_tasks.TasksRetryProcessing(); - CUpdaterDlg* pDlg = new CUpdaterDlg(true); - pDlg->m_bAutoDelete = true; + // start clipboard monitoring + LOG_INFO(_T("Starting clipboard monitor...")); + CClipboardMonitor::StartMonitor(&m_tasks); - pDlg->Create(); - chcore::TConfig& rConfig = GetConfig(); - try + EUpdatesFrequency eFrequency = (EUpdatesFrequency)GetPropValue(GetConfig()); + if(eFrequency != eFreq_Never) + { + unsigned long long ullMinInterval = 0; + switch(eFrequency) { - SetPropValue(rConfig, _time64(NULL)); - rConfig.Write(); + case eFreq_Daily: + ullMinInterval = 1*24*60*60; + break; + case eFreq_Weekly: + ullMinInterval = 7*24*60*60; + break; + case eFreq_OnceEvery2Weeks: + ullMinInterval = 14*24*60*60; + break; + case eFreq_Monthly: + ullMinInterval = 30*24*60*60; // we don't really care if it is a day less or more + break; + case eFreq_Quarterly: + ullMinInterval = 90*24*60*60; + break; + case eFreq_EveryStartup: + default: + ullMinInterval = 0; } - catch(icpf::exception& /*e*/) + + // get last check time stored in configuration + unsigned long long ullCurrentStamp = _time64(NULL); + unsigned long long ullTimestamp = GetPropValue(GetConfig()); + + // perform checking for updates only when the minimal interval has passed + if(ullCurrentStamp - ullTimestamp >= ullMinInterval) { - LOG_ERROR(_T("Storing last update check timestamp in configuration failed")); + LOG_INFO(_T("Checking for updates...")); + + CUpdaterDlg* pDlg = new CUpdaterDlg(true); + pDlg->m_bAutoDelete = true; + + pDlg->Create(); + chcore::TConfig& rConfig = GetConfig(); + try + { + SetPropValue(rConfig, _time64(NULL)); + rConfig.Write(); + } + catch(icpf::exception& /*e*/) + { + LOG_ERROR(_T("Storing last update check timestamp in configuration failed")); + } } } - } - // start saving timer - SetTimer(1023, GetPropValue(GetConfig()), NULL); + // start saving timer + SetTimer(1023, GetPropValue(GetConfig()), NULL); - SetTimer(3245, TM_AUTOREMOVE, NULL); - SetTimer(8743, TM_ACCEPTING, NULL); // ends wait state in tasks + SetTimer(3245, TM_AUTOREMOVE, NULL); + SetTimer(8743, TM_ACCEPTING, NULL); // ends wait state in tasks - if (GetPropValue(GetConfig())) - PostMessage(WM_SHOWMINIVIEW); + if (GetPropValue(GetConfig())) + PostMessage(WM_SHOWMINIVIEW); + } + catch(chcore::TCoreException& e) + { + bCaughtError = true; + e.GetErrorInfo(szErrInfo.get(), stMaxErrInfo); + } + catch(std::exception& e) + { + bCaughtError = true; + _snwprintf_s(szErrInfo.get(), stMaxErrInfo, _TRUNCATE, _T("%S"), e.what()); + szErrInfo.get()[stMaxErrInfo - 1] = _T('\0'); + } + catch(...) + { + bCaughtError = true; + _snwprintf_s(szErrInfo.get(), stMaxErrInfo, _TRUNCATE, _T("Caught an unknown exception")); + } + if(bCaughtError) + { + LOG_ERROR(szErrInfo.get()); + return -1; + } return 0; } @@ -323,7 +364,12 @@ m_ctlTray.SetTooltipText(text); } else - m_ctlTray.SetTooltipText(GetApp().GetAppNameVer()); + { + CString strText = GetApp().GetAppNameVer(); + if(GetApp().IsInPortableMode()) + strText += GetResManager().LoadString(IDS_CH_PORTABLE_STRING); + m_ctlTray.SetTooltipText(strText); + } break; } } @@ -403,148 +449,137 @@ pDlg->Create(); } -BOOL CMainWnd::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) +BOOL CMainWnd::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) { - // copying or moving ? - bool bMove=false; - switch(pCopyDataStruct->dwData & CSharedConfigStruct::OPERATION_MASK) + if(!pCopyDataStruct) + return CWnd::OnCopyData(pWnd, pCopyDataStruct); + + switch(pCopyDataStruct->dwData) { - case CSharedConfigStruct::DD_MOVE_FLAG: - case CSharedConfigStruct::EC_MOVETO_FLAG: - bMove=true; - break; - case CSharedConfigStruct::EC_PASTE_FLAG: - case CSharedConfigStruct::EC_PASTESPECIAL_FLAG: - bMove=(pCopyDataStruct->dwData & ~CSharedConfigStruct::OPERATION_MASK) != 0; - break; - } + case eCDType_TaskDefinitionContentSpecial: + case eCDType_TaskDefinitionContent: + { + // load task from buffer + wchar_t* pszBuffer = static_cast(pCopyDataStruct->lpData); + unsigned long ulLen = pCopyDataStruct->cbData / sizeof(wchar_t); - // buffer with: dst path and src paths separated by single '\0' - TCHAR *pBuffer=static_cast(pCopyDataStruct->lpData); - unsigned long ulLen=pCopyDataStruct->cbData / sizeof(TCHAR); + // check if the string ends with '\0', so we can safely use it without length checks + if(!pszBuffer || ulLen == 0 || pszBuffer[ulLen - 1] != L'\0') + return FALSE; - CString str, strDstPath; - CStringArray astrFiles; - UINT iOffset=0; + chcore::TString wstrData(pszBuffer); - do - { - str=pBuffer+iOffset; - if (iOffset == 0) - strDstPath=str; - else - astrFiles.Add(str); + chcore::TTaskDefinition tTaskDefinition; + tTaskDefinition.LoadFromString(wstrData); - iOffset+=str.GetLength()+1; - } - while (iOffset < ulLen); + // apply current options from global config; in the future we might want to merge the incoming options with global ones instead of overwriting... + chcore::TConfig& rConfig = GetConfig(); + rConfig.ExtractSubConfig(BRANCH_TASK_SETTINGS, tTaskDefinition.GetConfiguration()); - chcore::TConfig& rConfig = GetConfig(); + // special operation - modify stuff + if(pCopyDataStruct->dwData == eCDType_TaskDefinitionContentSpecial) + { + CCustomCopyDlg dlg(tTaskDefinition); - // special operation - modify stuff - CFiltersArray ffFilters; - int iPriority = boost::numeric_cast(GetPropValue(GetConfig())); - BUFFERSIZES bsSizes; - bsSizes.m_bOnlyDefault=GetPropValue(GetConfig()); - bsSizes.m_uiDefaultSize=GetPropValue(GetConfig()); - bsSizes.m_uiOneDiskSize=GetPropValue(GetConfig()); - bsSizes.m_uiTwoDisksSize=GetPropValue(GetConfig()); - bsSizes.m_uiCDSize=GetPropValue(GetConfig()); - bsSizes.m_uiLANSize=GetPropValue(GetConfig()); + GetPropValue(rConfig, dlg.m_vRecent); - BOOL bOnlyCreate=FALSE; - BOOL bIgnoreDirs=FALSE; - BOOL bForceDirectories=FALSE; - switch(pCopyDataStruct->dwData & CSharedConfigStruct::OPERATION_MASK) - { - case CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG: - case CSharedConfigStruct::EC_PASTESPECIAL_FLAG: - case CSharedConfigStruct::EC_COPYMOVETOSPECIAL_FLAG: - CCustomCopyDlg dlg; - dlg.m_ccData.m_astrPaths.Copy(astrFiles); - dlg.m_ccData.m_iOperation=bMove ? 1 : 0; - dlg.m_ccData.m_iPriority=iPriority; - dlg.m_ccData.m_strDestPath=strDstPath; - dlg.m_ccData.m_bsSizes=bsSizes; - dlg.m_ccData.m_bIgnoreFolders=(bIgnoreDirs != 0); - dlg.m_ccData.m_bForceDirectories=(bForceDirectories != 0); - dlg.m_ccData.m_bCreateStructure=(bOnlyCreate != 0); + INT_PTR iModalResult; + if((iModalResult = dlg.DoModal()) == IDCANCEL) + return CWnd::OnCopyData(pWnd, pCopyDataStruct); + else if(iModalResult == -1) // windows has been closed by a parent + return TRUE; - dlg.m_ccData.m_vRecent.clear(); + dlg.m_vRecent.push_back(dlg.m_tTaskDefinition.GetDestinationPath().ToString()); - GetPropValue(rConfig, dlg.m_ccData.m_vRecent); + SetPropValue(rConfig, dlg.m_vRecent); - INT_PTR iModalResult; - if ( (iModalResult=dlg.DoModal()) == IDCANCEL) - return CWnd::OnCopyData(pWnd, pCopyDataStruct); - else if (iModalResult == -1) // windows has been closed by a parent - return TRUE; + tTaskDefinition = dlg.m_tTaskDefinition; + } - astrFiles.Copy(dlg.m_ccData.m_astrPaths); - bMove=(dlg.m_ccData.m_iOperation != 0); - iPriority=dlg.m_ccData.m_iPriority; - strDstPath=dlg.m_ccData.m_strDestPath; - bsSizes=dlg.m_ccData.m_bsSizes; - ffFilters = dlg.m_ccData.m_afFilters; - bIgnoreDirs=dlg.m_ccData.m_bIgnoreFolders; - bForceDirectories=dlg.m_ccData.m_bForceDirectories; - bOnlyCreate=dlg.m_ccData.m_bCreateStructure; - dlg.m_ccData.m_vRecent.insert(dlg.m_ccData.m_vRecent.begin(), strDstPath); + // load resource strings + SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_FIRSTCOPY_STRING)); + SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_NEXTCOPY_STRING)); - SetPropValue(rConfig, dlg.m_ccData.m_vRecent); - } + // create task with the above definition + CTaskPtr spTask = m_tasks.CreateTask(tTaskDefinition); - // create new task - TTaskDefinition tTaskDefinition; - tTaskDefinition.SetDestinationPath(chcore::PathFromString(strDstPath)); + // add to task list and start processing + spTask->BeginProcessing(); - // files - for(int i = 0; i < astrFiles.GetSize(); i++) - { - tTaskDefinition.AddSourcePath(chcore::PathFromString(astrFiles.GetAt(i))); - } + break; + } + case eCDType_CommandLineArguments: + { + // load task from buffer + wchar_t* pszBuffer = static_cast(pCopyDataStruct->lpData); + unsigned long ulLen = pCopyDataStruct->cbData / sizeof(wchar_t); - tTaskDefinition.SetOperationType(bMove ? eOperation_Move : eOperation_Copy); + // check if the string ends with '\0', so we can safely use it without length checks + if(!pszBuffer || ulLen == 0 || pszBuffer[ulLen - 1] != L'\0') + return FALSE; - // set the default options for task - GetConfig().ExtractSubConfig(BRANCH_TASK_SETTINGS, tTaskDefinition.GetConfiguration()); + TCommandLineParser cmdLineParser; + cmdLineParser.ParseCommandLine(pszBuffer); - // and override them with manual settings - SetTaskPropValue(tTaskDefinition.GetConfiguration(), bOnlyCreate != FALSE); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), bForceDirectories != FALSE); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), bIgnoreDirs != FALSE); + ProcessCommandLine(cmdLineParser); + m_tasks.TasksRetryProcessing(); - // buffer sizes - SetTaskPropValue(tTaskDefinition.GetConfiguration(), bsSizes.m_uiDefaultSize); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), bsSizes.m_uiOneDiskSize); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), bsSizes.m_uiTwoDisksSize); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), bsSizes.m_uiCDSize); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), bsSizes.m_uiLANSize); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), bsSizes.m_bOnlyDefault); + return TRUE; + } + } - // Task priority - SetTaskPropValue(tTaskDefinition.GetConfiguration(), iPriority); + return CWnd::OnCopyData(pWnd, pCopyDataStruct); +} - // load resource strings - SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_FIRSTCOPY_STRING)); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_NEXTCOPY_STRING)); +void CMainWnd::ProcessCommandLine(const TCommandLineParser& rCommandLine) +{ + if(rCommandLine.HasTaskDefinitionPath()) + { + chcore::TPathContainer vTaskPaths; + rCommandLine.GetTaskDefinitionPaths(vTaskPaths); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), ffFilters); + const size_t stBufferSize = 4096; + boost::shared_array szBuffer(new wchar_t[stBufferSize]); - // create task with the above definition - CTaskPtr spTask = m_tasks.CreateTask(); + for(size_t stIndex = 0; stIndex < vTaskPaths.GetCount(); ++stIndex) + { + const chcore::TSmartPath& strPath = vTaskPaths.GetAt(stIndex); - spTask->SetTaskDefinition(tTaskDefinition); - - m_tasks.Add(spTask); + bool bImported = false; - // save state of a task - spTask->Store(); + try + { + CTaskPtr spTask = m_tasks.ImportTask(strPath); + if(spTask) + spTask->Store(); + bImported = true; + } + catch(icpf::exception& e) + { + bImported = false; + e.get_info(szBuffer.get(), stBufferSize); + } + catch(...) + { + bImported = false; + szBuffer.get()[0] = _T('\0'); + } - // add to task list and start processing - spTask->BeginProcessing(); + if(!bImported) + { + ictranslate::CFormat fmt; + fmt.SetFormat(_T("Error encountered while importing task from path '%path'. Error: %err.")); + fmt.SetParam(_T("%path"), strPath.ToString()); + fmt.SetParam(_T("%error"), szBuffer.get()); - return CWnd::OnCopyData(pWnd, pCopyDataStruct); + LOG_ERROR(fmt); + + fmt.SetFormat(GetResManager().LoadString(IDS_TASK_IMPORT_FAILED)); + fmt.SetParam(_T("%path"), strPath.ToString()); + AfxMessageBox(fmt, MB_OK | MB_ICONERROR); + } + } + } } void CMainWnd::OnShowMiniView() @@ -560,76 +595,25 @@ chcore::TConfig& rConfig = GetConfig(); CCustomCopyDlg dlg; - dlg.m_ccData.m_iOperation=0; - dlg.m_ccData.m_iPriority = boost::numeric_cast(GetPropValue(rConfig)); - dlg.m_ccData.m_bsSizes.m_bOnlyDefault=GetPropValue(rConfig); - dlg.m_ccData.m_bsSizes.m_uiDefaultSize=GetPropValue(rConfig); - dlg.m_ccData.m_bsSizes.m_uiOneDiskSize=GetPropValue(rConfig); - dlg.m_ccData.m_bsSizes.m_uiTwoDisksSize=GetPropValue(rConfig); - dlg.m_ccData.m_bsSizes.m_uiCDSize=GetPropValue(rConfig); - dlg.m_ccData.m_bsSizes.m_uiLANSize=GetPropValue(rConfig); - dlg.m_ccData.m_bCreateStructure=false; - dlg.m_ccData.m_bForceDirectories=false; - dlg.m_ccData.m_bIgnoreFolders=false; + GetPropValue(rConfig, dlg.m_vRecent); - dlg.m_ccData.m_vRecent.clear(); - - GetPropValue(rConfig, dlg.m_ccData.m_vRecent); - - if (dlg.DoModal() == IDOK) + if(dlg.DoModal() == IDOK) { - SetPropValue(rConfig, dlg.m_ccData.m_vRecent); + dlg.m_vRecent.push_back(dlg.m_tTaskDefinition.GetDestinationPath().ToString()); - // save recent paths - dlg.m_ccData.m_vRecent.push_back((PCTSTR)dlg.m_ccData.m_strDestPath); + SetPropValue(rConfig, dlg.m_vRecent); - TTaskDefinition tTaskDefinition; + chcore::TTaskDefinition tTaskDefinition = dlg.m_tTaskDefinition; - for (int iIndex = 0; iIndex < dlg.m_ccData.m_astrPaths.GetSize(); iIndex++) - { - tTaskDefinition.AddSourcePath(chcore::PathFromString(dlg.m_ccData.m_astrPaths.GetAt(iIndex))); - } - - tTaskDefinition.SetDestinationPath(chcore::PathFromString(dlg.m_ccData.m_strDestPath)); - - tTaskDefinition.SetOperationType((dlg.m_ccData.m_iOperation == 1) ? eOperation_Move : eOperation_Copy); - - // set the default options for task - GetConfig().ExtractSubConfig(BRANCH_TASK_SETTINGS, tTaskDefinition.GetConfiguration()); - - // and override them with manual settings - SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_bCreateStructure); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_bForceDirectories); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_bIgnoreFolders); - - // Buffer settings - SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_bsSizes.m_uiDefaultSize); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_bsSizes.m_uiOneDiskSize); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_bsSizes.m_uiTwoDisksSize); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_bsSizes.m_uiCDSize); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_bsSizes.m_uiLANSize); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_bsSizes.m_bOnlyDefault); - - // Task priority - SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_iPriority); - // load resource strings SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_FIRSTCOPY_STRING)); SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_NEXTCOPY_STRING)); - SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_afFilters); - // new task - CTaskPtr spTask = m_tasks.CreateTask(); - spTask->SetTaskDefinition(tTaskDefinition); - - m_tasks.Add(spTask); + CTaskPtr spTask = m_tasks.CreateTask(tTaskDefinition); - // save - spTask->Store(); - - // store and start + // start spTask->BeginProcessing(); } } @@ -666,90 +650,167 @@ { chcore::TConfig& rConfig = GetConfig(); - // std config values - g_pscsShared->bShowFreeSpace=GetPropValue(rConfig); - + TShellExtMenuConfig cfgShellExt; + // experimental - doesn't work on all systems - g_pscsShared->bShowShortcutIcons=GetPropValue(rConfig); - g_pscsShared->uiFlags = (GetPropValue(rConfig) ? CSharedConfigStruct::eFlag_InterceptDragAndDrop : 0) | - (GetPropValue(rConfig) ? CSharedConfigStruct::eFlag_InterceptKeyboardActions : 0) | - (GetPropValue(rConfig) ? CSharedConfigStruct::eFlag_InterceptCtxMenuActions : 0); - - // sizes - for (int i=0;i<6;i++) - _tcscpy(g_pscsShared->szSizes[i], GetResManager().LoadString(IDS_BYTE_STRING+i)); + cfgShellExt.SetShowShortcutIcons(GetPropValue(rConfig)); - // convert to list of _COMMAND's - _COMMAND *pCommand = g_pscsShared->GetCommandsPtr(); + cfgShellExt.SetInterceptDragAndDrop(GetPropValue(rConfig)); + cfgShellExt.SetInterceptKeyboardActions(GetPropValue(rConfig)); + cfgShellExt.SetInterceptCtxMenuActions(GetPropValue(rConfig)); + TShellMenuItemPtr spRootItem = cfgShellExt.GetCommandRoot(); + // what kind of menu ? switch (wParam) { - case GC_DRAGDROP: + case eLocation_DragAndDropMenu: { - g_pscsShared->iCommandCount=3; - g_pscsShared->iShortcutsCount=0; - g_pscsShared->uiFlags |= (GetPropValue(rConfig) ? CSharedConfigStruct::DD_COPY_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::DD_MOVE_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG : 0); + bool bAddedAnyOption = false; + if(GetPropValue(rConfig)) + { + spRootItem->AddChild(boost::make_shared(GetResManager().LoadString(IDS_MENUCOPY_STRING), GetResManager().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; + } - pCommand[0].uiCommandID=CSharedConfigStruct::DD_COPY_FLAG; - GetResManager().LoadStringCopy(IDS_MENUCOPY_STRING, pCommand[0].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPCOPY_STRING, pCommand[0].szDesc, 128); - - pCommand[1].uiCommandID=CSharedConfigStruct::DD_MOVE_FLAG; - GetResManager().LoadStringCopy(IDS_MENUMOVE_STRING, pCommand[1].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPMOVE_STRING, pCommand[1].szDesc, 128); - - pCommand[2].uiCommandID=CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG; - GetResManager().LoadStringCopy(IDS_MENUCOPYMOVESPECIAL_STRING, pCommand[2].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPCOPYMOVESPECIAL_STRING, pCommand[2].szDesc, 128); + if(GetPropValue(rConfig)) + { + spRootItem->AddChild(boost::make_shared(GetResManager().LoadString(IDS_MENUMOVE_STRING), GetResManager().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)) + { + spRootItem->AddChild(boost::make_shared(GetResManager().LoadString(IDS_MENUCOPYMOVESPECIAL_STRING), GetResManager().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 + spRootItem->AddChild(boost::make_shared()); + } } break; - case GC_EXPLORER: + case eLocation_ContextMenu: { - g_pscsShared->iCommandCount=5; - g_pscsShared->uiFlags |= (GetPropValue(rConfig) ? CSharedConfigStruct::EC_PASTE_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::EC_PASTESPECIAL_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::EC_COPYTO_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::EC_MOVETO_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::EC_COPYMOVETOSPECIAL_FLAG : 0); - - pCommand[0].uiCommandID=CSharedConfigStruct::EC_PASTE_FLAG; - GetResManager().LoadStringCopy(IDS_MENUPASTE_STRING, pCommand[0].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPPASTE_STRING, pCommand[0].szDesc, 128); - pCommand[1].uiCommandID=CSharedConfigStruct::EC_PASTESPECIAL_FLAG; - GetResManager().LoadStringCopy(IDS_MENUPASTESPECIAL_STRING, pCommand[1].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPPASTESPECIAL_STRING, pCommand[1].szDesc, 128); - pCommand[2].uiCommandID=CSharedConfigStruct::EC_COPYTO_FLAG; - GetResManager().LoadStringCopy(IDS_MENUCOPYTO_STRING, pCommand[2].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPCOPYTO_STRING, pCommand[2].szDesc, 128); - pCommand[3].uiCommandID=CSharedConfigStruct::EC_MOVETO_FLAG; - GetResManager().LoadStringCopy(IDS_MENUMOVETO_STRING, pCommand[3].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPMOVETO_STRING, pCommand[3].szDesc, 128); - pCommand[4].uiCommandID=CSharedConfigStruct::EC_COPYMOVETOSPECIAL_FLAG; - GetResManager().LoadStringCopy(IDS_MENUCOPYMOVETOSPECIAL_STRING, pCommand[4].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPCOPYMOVETOSPECIAL_STRING, pCommand[4].szDesc, 128); - - // prepare shortcuts - std::vector cvShortcuts; - GetPropValue(rConfig, cvShortcuts); + if(GetPropValue(rConfig)) + { + spRootItem->AddChild(boost::make_shared(GetResManager().LoadString(IDS_MENUPASTE_STRING), GetResManager().LoadString(IDS_MENUTIPPASTE_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Autodetect, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_Clipboard), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializeAuto, chcore::TSmartPath()), false)); + } - // count of shortcuts to store - g_pscsShared->iShortcutsCount = boost::numeric_cast(std::min(cvShortcuts.size(), (SHARED_BUFFERSIZE - 5 * sizeof(_COMMAND)) / sizeof(_SHORTCUT))); - _SHORTCUT* pShortcut = g_pscsShared->GetShortcutsPtr(); - CShortcut sc; - for (int i=0;iiShortcutsCount;i++) + if(GetPropValue(rConfig)) { - sc=CString(cvShortcuts.at(i)); - _tcsncpy(pShortcut[i].szName, sc.m_strName, 128); - _tcsncpy(pShortcut[i].szPath, sc.m_strPath, _MAX_PATH); + spRootItem->AddChild(boost::make_shared(GetResManager().LoadString(IDS_MENUPASTESPECIAL_STRING), GetResManager().LoadString(IDS_MENUTIPPASTESPECIAL_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Autodetect, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_Clipboard), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializeAuto, chcore::TSmartPath()), false)); } + + if(GetPropValue(rConfig) || GetPropValue(rConfig) || GetPropValue(rConfig)) + { + // prepare shortcuts for all menu options + std::vector vShortcutStrings; + GetPropValue(rConfig, vShortcutStrings); + + bool bRetrieveFreeSpace = GetPropValue(rConfig); + + std::vector vShortcuts; + const size_t stSizeBufferSize = 64; + boost::shared_array spSizeBuffer(new wchar_t[stSizeBufferSize]); + + BOOST_FOREACH(const CString& strShortcutString, vShortcutStrings) + { + CShortcut tShortcut; + if(tShortcut.FromString(strShortcutString)) + { + unsigned long long ullSize = 0; + + // retrieving free space might fail, but it's not critical - we just won't show the free space + if(bRetrieveFreeSpace && GetDynamicFreeSpace(tShortcut.m_strPath, &ullSize, NULL)) + { + CString strNameFormat; + strNameFormat.Format(_T("%s (%s)"), tShortcut.m_strName, GetSizeString(ullSize, spSizeBuffer.get(), stSizeBufferSize)); + + tShortcut.m_strName = strNameFormat; + } + + vShortcuts.push_back(tShortcut); + } + else + BOOST_ASSERT(false); // non-critical, but not very nice + } + + if(GetPropValue(rConfig)) + { + boost::shared_ptr menuItem(boost::make_shared(GetResManager().LoadString(IDS_MENUCOPYTO_STRING), GetResManager().LoadString(IDS_MENUTIPCOPYTO_STRING))); + BOOST_FOREACH(const CShortcut& tShortcut, vShortcuts) + { + menuItem->AddChild(boost::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)); + } + + spRootItem->AddChild(menuItem); + } + + if(GetPropValue(rConfig)) + { + boost::shared_ptr menuItem(boost::make_shared(GetResManager().LoadString(IDS_MENUMOVETO_STRING), GetResManager().LoadString(IDS_MENUTIPMOVETO_STRING))); + BOOST_FOREACH(const CShortcut& tShortcut, vShortcuts) + { + menuItem->AddChild(boost::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)); + } + + spRootItem->AddChild(menuItem); + } + + if(GetPropValue(rConfig)) + { + boost::shared_ptr menuItem(boost::make_shared(GetResManager().LoadString(IDS_MENUCOPYMOVETOSPECIAL_STRING), GetResManager().LoadString(IDS_MENUTIPCOPYMOVETOSPECIAL_STRING))); + BOOST_FOREACH(const CShortcut& tShortcut, vShortcuts) + { + menuItem->AddChild(boost::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)); + } + + spRootItem->AddChild(menuItem); + } + } } + break; default: - ASSERT(false); // what's happening ? + ASSERT(false); // unhandled case } + + 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); } break;