Index: src/ch/TBasicProgressInfo.cpp
===================================================================
diff -u
--- src/ch/TBasicProgressInfo.cpp	(revision 0)
+++ src/ch/TBasicProgressInfo.cpp	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -0,0 +1,92 @@
+// ============================================================================
+//  Copyright (C) 2001-2011 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.
+// ============================================================================
+/// @file  TBasicProgressInfo.cpp
+/// @date  2011/03/28
+/// @brief Contains implementation of class recording progress info.
+// ============================================================================
+#include "stdafx.h"
+#include "TBasicProgressInfo.h"
+
+
+TTaskBasicProgressInfo::TTaskBasicProgressInfo() :
+m_stCurrentIndex(0),
+m_ullCurrentFileProcessedSize(0),
+m_stSubOperationIndex(0)
+{
+}
+
+TTaskBasicProgressInfo::~TTaskBasicProgressInfo()
+{
+}
+
+void TTaskBasicProgressInfo::SetCurrentIndex(size_t stIndex)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_stCurrentIndex = stIndex;
+   m_ullCurrentFileProcessedSize = 0;
+}
+
+void TTaskBasicProgressInfo::IncreaseCurrentIndex()
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   ++m_stCurrentIndex;
+   m_ullCurrentFileProcessedSize = 0;
+}
+
+size_t TTaskBasicProgressInfo::GetCurrentIndex() const
+{
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   return m_stCurrentIndex;
+}
+
+void TTaskBasicProgressInfo::SetCurrentFileProcessedSize(unsigned long long ullSize)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_ullCurrentFileProcessedSize = ullSize;
+}
+
+unsigned long long TTaskBasicProgressInfo::GetCurrentFileProcessedSize() const
+{
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   return m_ullCurrentFileProcessedSize;
+}
+
+void TTaskBasicProgressInfo::IncreaseCurrentFileProcessedSize(unsigned long long ullSizeToAdd)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_ullCurrentFileProcessedSize += ullSizeToAdd;
+}
+
+void TTaskBasicProgressInfo::SetSubOperationIndex(size_t stSubOperationIndex)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_stSubOperationIndex = stSubOperationIndex;
+}
+
+size_t TTaskBasicProgressInfo::GetSubOperationIndex() const
+{
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   return m_stSubOperationIndex;
+}
+
+void TTaskBasicProgressInfo::IncreaseSubOperationIndex()
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   ++m_stSubOperationIndex;
+}
Index: src/ch/TBasicProgressInfo.h
===================================================================
diff -u
--- src/ch/TBasicProgressInfo.h	(revision 0)
+++ src/ch/TBasicProgressInfo.h	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -0,0 +1,93 @@
+// ============================================================================
+//  Copyright (C) 2001-2011 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.
+// ============================================================================
+/// @file  TBasicProgressInfo.h
+/// @date  2011/03/28
+/// @brief Contains class with progress tracking.
+// ============================================================================
+#ifndef __TBASICPROGRESSINFO_H__
+#define __TBASICPROGRESSINFO_H__
+
+
+///////////////////////////////////////////////////////////////////////////
+// TTaskBasicProgressInfo
+
+class TTaskBasicProgressInfo
+{
+public:
+   TTaskBasicProgressInfo();
+   ~TTaskBasicProgressInfo();
+
+   void SetCurrentIndex(size_t stIndex);	// might be unneeded when serialization is implemented
+   void IncreaseCurrentIndex();
+   size_t GetCurrentIndex() const;
+
+   void SetCurrentFileProcessedSize(unsigned long long ullSize);
+   unsigned long long GetCurrentFileProcessedSize() const;
+   void IncreaseCurrentFileProcessedSize(unsigned long long ullSizeToAdd);
+
+   void SetSubOperationIndex(size_t stSubOperationIndex);
+   size_t GetSubOperationIndex() const;
+   void IncreaseSubOperationIndex();
+
+   template<class Archive>
+   void load(Archive& ar, unsigned int /*uiVersion*/)
+   {
+      size_t stCurrentIndex = 0;
+      ar >> stCurrentIndex;
+
+      unsigned long long ullCurrentFileProcessedSize = 0;
+      ar >> ullCurrentFileProcessedSize;
+
+      size_t stSubOperationIndex = 0;
+      ar >> stSubOperationIndex;
+
+      boost::unique_lock<boost::shared_mutex> lock(m_lock);
+
+      m_stCurrentIndex = stCurrentIndex;
+      m_ullCurrentFileProcessedSize = ullCurrentFileProcessedSize;
+      m_stSubOperationIndex = stSubOperationIndex;
+   }
+
+   template<class Archive>
+   void save(Archive& ar, unsigned int /*uiVersion*/) const
+   {
+      m_lock.lock_shared();
+
+      size_t stCurrentIndex = m_stCurrentIndex;
+      unsigned long long ullCurrentFileProcessedSize = m_ullCurrentFileProcessedSize;
+      size_t stSubOperationIndex = m_stSubOperationIndex;
+
+      m_lock.unlock_shared();
+
+      ar << stCurrentIndex;
+      ar << ullCurrentFileProcessedSize;
+      ar << stSubOperationIndex;
+   }
+
+   BOOST_SERIALIZATION_SPLIT_MEMBER();
+
+private:
+   volatile size_t m_stSubOperationIndex;		 // index of sub-operation from TOperationDescription
+   volatile size_t m_stCurrentIndex;   // index to the m_files array stating currently processed item
+   volatile unsigned long long m_ullCurrentFileProcessedSize;	// count of bytes processed for current file
+
+   mutable boost::shared_mutex m_lock;
+};
+
+#endif
Index: src/ch/TLocalFilesystem.cpp
===================================================================
diff -u
--- src/ch/TLocalFilesystem.cpp	(revision 0)
+++ src/ch/TLocalFilesystem.cpp	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -0,0 +1,102 @@
+// ============================================================================
+//  Copyright (C) 2001-2010 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.
+// ============================================================================
+/// @file  TLocalFilesystem.cpp
+/// @date  2011/03/24
+/// @brief 
+// ============================================================================
+#include "stdafx.h"
+#include "TLocalFilesystem.h"
+#include "TAutoHandles.h"
+
+void TLocalFilesystem::GetDriveData(const chcore::TSmartPath& spPath, int* piDrvNum, UINT* puiDrvType)
+{
+	TCHAR drv[_MAX_DRIVE + 1];
+
+	_tsplitpath(spPath.ToString(), drv, NULL, NULL, NULL);
+	if(lstrlen(drv) != 0)
+	{
+		// add '\\'
+		lstrcat(drv, _T("\\"));
+		_tcsupr(drv);
+
+		// disk number
+		if(piDrvNum)
+			*piDrvNum=drv[0]-_T('A');
+
+		// disk type
+		if(puiDrvType)
+		{
+			*puiDrvType=GetDriveType(drv);
+			if(*puiDrvType == DRIVE_NO_ROOT_DIR)
+				*puiDrvType=DRIVE_UNKNOWN;
+		}
+	}
+	else
+	{
+		// there's no disk in a path
+		if(piDrvNum)
+			*piDrvNum=-1;
+
+		if(puiDrvType)
+		{
+			// check for unc path
+			if(_tcsncmp(spPath.ToString(), _T("\\\\"), 2) == 0)
+				*puiDrvType=DRIVE_REMOTE;
+			else
+				*puiDrvType=DRIVE_UNKNOWN;
+		}
+	}
+}
+
+bool TLocalFilesystem::PathExist(chcore::TSmartPath pathToCheck)
+{
+	WIN32_FIND_DATA fd;
+
+	// search by exact name
+	HANDLE hFind = FindFirstFile(pathToCheck.ToString(), &fd);
+	if(hFind != INVALID_HANDLE_VALUE)
+		return true;
+
+	// another try (add '\\' if needed and '*' for marking that we look for ie. c:\*
+	// instead of c:\, which would never be found prev. way)
+	pathToCheck.AppendIfNotExists(_T("*"), false);
+
+	hFind = FindFirstFile(pathToCheck.ToString(), &fd);
+	if(hFind != INVALID_HANDLE_VALUE)
+	{
+		::FindClose(hFind);
+		return true;
+	}
+	else
+		return false;
+}
+
+bool TLocalFilesystem::SetFileDirectoryTime(LPCTSTR lpszName, const FILETIME& ftCreationTime, const FILETIME& ftLastAccessTime, const FILETIME& ftLastWriteTime)
+{
+   TAutoFileHandle hFile = CreateFile(lpszName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
+   if(hFile == INVALID_HANDLE_VALUE)
+      return false;
+
+   BOOL bResult = (!SetFileTime(hFile, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime));
+
+   if(!hFile.Close())
+      return false;
+
+   return bResult != 0;
+}
Index: src/ch/TLocalFilesystem.h
===================================================================
diff -u
--- src/ch/TLocalFilesystem.h	(revision 0)
+++ src/ch/TLocalFilesystem.h	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -0,0 +1,38 @@
+// ============================================================================
+//  Copyright (C) 2001-2010 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.
+// ============================================================================
+/// @file  TLocalFilesystem.h
+/// @date  2011/03/24
+/// @brief Contains class responsible for accessing local filesystem.
+// ============================================================================
+#ifndef __TLOCALFILESYSTEM_H__
+#define __TLOCALFILESYSTEM_H__
+
+#include "../libchcore/TPath.h"
+
+class TLocalFilesystem
+{
+public:
+	static void GetDriveData(const chcore::TSmartPath& spPath, int *piDrvNum, UINT *puiDrvType);
+	static bool PathExist(chcore::TSmartPath strPath);	// check for file or folder existence
+   static bool SetFileDirectoryTime(LPCTSTR lpszName, const FILETIME& ftCreationTime, const FILETIME& ftLastAccessTime, const FILETIME& ftLastWriteTime);
+
+};
+
+#endif
+
Index: src/ch/TSubTaskBase.cpp
===================================================================
diff -u -rb7709acbab26fdb108b77d3e08d3872f54248af2 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TSubTaskBase.cpp	(.../TSubTaskBase.cpp)	(revision b7709acbab26fdb108b77d3e08d3872f54248af2)
+++ src/ch/TSubTaskBase.cpp	(.../TSubTaskBase.cpp)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -22,16 +22,116 @@
 // ============================================================================
 #include "stdafx.h"
 #include "TSubTaskBase.h"
+#include "TBasePathData.h"
+#include "TLocalFilesystem.h"
+#include "TSubTaskContext.h"
+#include "TTaskDefinition.h"
+#include "TTaskConfiguration.h"
 
 ///////////////////////////////////////////////////////////////////////////
 // TSubTaskBase
 
-TSubTaskBase::TSubTaskBase(TSubTaskContext& rContext, TSubTaskProgressInfo& rProgressInfo) :
-	m_rContext(rContext),
-	m_rProgressInfo(rProgressInfo)
+TSubTaskBase::TSubTaskBase(TSubTaskContext& rContext) :
+	m_rContext(rContext)
 {
 }
 
 TSubTaskBase::~TSubTaskBase()
 {
 }
+
+
+int TSubTaskBase::GetDriveNumber(const CFileInfoPtr& spFileInfo)
+{
+   if(!spFileInfo)
+      THROW(_T("Invalid pointer"), 0, 0, 0);
+   if(spFileInfo->GetSrcIndex() == std::numeric_limits<size_t>::max())
+      THROW(_T("Received non-relative (standalone) path info"), 0, 0, 0);
+
+   // check if this information has already been stored
+   size_t stBaseIndex = spFileInfo->GetSrcIndex();
+   if(stBaseIndex >= GetContext().GetBasePathDataContainer().GetCount())
+      THROW(_T("Index out of bounds"), 0, 0, 0);
+
+   TBasePathDataPtr spPathData = GetContext().GetBasePathDataContainer().GetAt(stBaseIndex);
+   if(spPathData->IsDriveNumberSet())
+      return spPathData->GetDriveNumber();
+
+   // drive number wasn't cached previously - read it now
+   int iDriveNumber = 0;
+   TLocalFilesystem::GetDriveData(GetContext().GetTaskDefinition().GetSourcePathAt(stBaseIndex), &iDriveNumber, NULL);
+
+   spPathData->SetDriveNumber(iDriveNumber);
+
+   return iDriveNumber;
+}
+
+
+chcore::TSmartPath TSubTaskBase::CalculateDestinationPath(const CFileInfoPtr& spFileInfo, chcore::TSmartPath pathDst, int iFlags) const
+{
+   const TBasePathDataContainer& rSourcePathsInfo = GetContext().GetBasePathDataContainer();
+
+   if(!spFileInfo)
+      THROW(_T("Invalid pointer"), 0, 0, 0);
+
+   // iFlags: bit 0-ignore folders; bit 1-force creating directories
+   if (iFlags & 0x02)
+   {
+      // force create directories
+      chcore::TSmartPath pathCombined = pathDst + spFileInfo->GetFullFilePath().GetFileDir();
+
+      // force create directory
+      SHCreateDirectoryEx(NULL, pathCombined.ToString(), NULL);
+
+      return pathCombined + spFileInfo->GetFullFilePath().GetFileName();
+   }
+   else
+   {
+      size_t stSrcIndex = spFileInfo->GetSrcIndex();
+
+      if (!(iFlags & 0x01) && stSrcIndex != std::numeric_limits<size_t>::max())
+      {
+         // generate new dest name
+         if(!rSourcePathsInfo.GetAt(stSrcIndex)->IsDestinationPathSet())
+         {
+            chcore::TSmartPath pathSubst = FindFreeSubstituteName(spFileInfo->GetFullFilePath(), pathDst);
+            rSourcePathsInfo.GetAt(stSrcIndex)->SetDestinationPath(pathSubst);
+         }
+
+         return pathDst + rSourcePathsInfo.GetAt(stSrcIndex)->GetDestinationPath() + spFileInfo->GetFilePath();
+      }
+      else
+         return pathDst + spFileInfo->GetFullFilePath().GetFileName();
+   }
+}
+
+
+// finds another name for a copy of src file(folder) in dest location
+chcore::TSmartPath TSubTaskBase::FindFreeSubstituteName(chcore::TSmartPath pathSrcPath, chcore::TSmartPath pathDstPath) const
+{
+   const TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+
+   // get the name from srcpath
+   pathSrcPath.StripSeparatorAtEnd();
+
+   chcore::TSmartPath pathFilename = pathSrcPath.GetFileName();
+
+   // set the dest path
+   CString strCheckPath;
+   ictranslate::CFormat fmt(GetTaskPropValue<eTO_AlternateFilenameFormatString_First>(rTaskDefinition.GetConfiguration()));
+   fmt.SetParam(_t("%name"), pathFilename.ToString());
+   chcore::TSmartPath pathCheckPath(chcore::PathFromString((PCTSTR)fmt));
+
+   // when adding to strDstPath check if the path already exists - if so - try again
+   int iCounter=1;
+   CString strFmt = GetTaskPropValue<eTO_AlternateFilenameFormatString_AfterFirst>(rTaskDefinition.GetConfiguration());
+   while(TLocalFilesystem::PathExist(pathDstPath + pathCheckPath))
+   {
+      fmt.SetFormat(strFmt);
+      fmt.SetParam(_t("%name"), pathFilename.ToString());
+      fmt.SetParam(_t("%count"), ++iCounter);
+      pathCheckPath.FromString((PCTSTR)fmt);
+   }
+
+   return pathCheckPath;
+}
Index: src/ch/TSubTaskBase.h
===================================================================
diff -u -rb7709acbab26fdb108b77d3e08d3872f54248af2 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TSubTaskBase.h	(.../TSubTaskBase.h)	(revision b7709acbab26fdb108b77d3e08d3872f54248af2)
+++ src/ch/TSubTaskBase.h	(.../TSubTaskBase.h)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -23,23 +23,43 @@
 #ifndef __TSUBTASKBASE_H__
 #define __TSUBTASKBASE_H__
 
+#include "FileInfo.h"
+
 class TSubTaskContext;
-class TSubTaskProgressInfo;
+class TBasePathDataContainer;
 
 ///////////////////////////////////////////////////////////////////////////
 // TSubTaskBase
 
 class TSubTaskBase
 {
 public:
-	TSubTaskBase(TSubTaskContext& rContext, TSubTaskProgressInfo& rProgressInfo);
+	enum ESubOperationResult
+	{
+		eSubResult_Continue,
+		eSubResult_KillRequest,
+		eSubResult_Error,
+		eSubResult_CancelRequest,
+		eSubResult_PauseRequest
+	};
+
+public:
+	TSubTaskBase(TSubTaskContext& rContext);
 	virtual ~TSubTaskBase();
 
-	virtual void Exec() = 0;
+	virtual ESubOperationResult Exec() = 0;
 
+   TSubTaskContext& GetContext() { return m_rContext; }
+   const TSubTaskContext& GetContext() const { return m_rContext; }
+
+protected:
+   // some common operations
+   int GetDriveNumber(const CFileInfoPtr& spFileInfo);
+   chcore::TSmartPath CalculateDestinationPath(const CFileInfoPtr& spFileInfo, chcore::TSmartPath strPath, int iFlags) const;
+   chcore::TSmartPath FindFreeSubstituteName(chcore::TSmartPath pathSrcPath, chcore::TSmartPath pathDstPath) const;
+
 private:
 	TSubTaskContext& m_rContext;
-	TSubTaskProgressInfo& m_rProgressInfo;
 };
 
 #endif
Index: src/ch/TSubTaskContext.cpp
===================================================================
diff -u -r3f72015a9db19bd1b0a5e20e0f1aa0ec00bda529 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TSubTaskContext.cpp	(.../TSubTaskContext.cpp)	(revision 3f72015a9db19bd1b0a5e20e0f1aa0ec00bda529)
+++ src/ch/TSubTaskContext.cpp	(.../TSubTaskContext.cpp)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -23,9 +23,17 @@
 #include "stdafx.h"
 #include "TSubTaskContext.h"
 
-TSubTaskContext::TSubTaskContext(TTaskDefinition& rTaskDefinition, CFileInfoArray& rFilesCache) :
+TSubTaskContext::TSubTaskContext(TTaskDefinition& rTaskDefinition, TBasePathDataContainer& rBasePathDataContainer, CFileInfoArray& rFilesCache, TTaskLocalStats& rTaskLocalStats, 
+                                 TTaskBasicProgressInfo& rTaskBasicProgressInfo, TTaskConfigTracker& rCfgTracker, icpf::log_file& rLog, chcore::IFeedbackHandler* piFeedbackHandler, TWorkerThreadController& rThreadController) :
 	m_rTaskDefinition(rTaskDefinition),
-	m_rFilesCache(rFilesCache)
+   m_rBasePathDataContainer(rBasePathDataContainer),
+	m_rFilesCache(rFilesCache),
+   m_rTaskLocalStats(rTaskLocalStats),
+   m_rTaskBasicProgressInfo(rTaskBasicProgressInfo),
+   m_rCfgTracker(rCfgTracker),
+	m_rLog(rLog),
+	m_piFeedbackHandler(piFeedbackHandler),
+   m_rThreadController(rThreadController)
 {
 }
 
Index: src/ch/TSubTaskContext.h
===================================================================
diff -u -r3f72015a9db19bd1b0a5e20e0f1aa0ec00bda529 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TSubTaskContext.h	(.../TSubTaskContext.h)	(revision 3f72015a9db19bd1b0a5e20e0f1aa0ec00bda529)
+++ src/ch/TSubTaskContext.h	(.../TSubTaskContext.h)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -26,21 +26,75 @@
 #include "FileInfo.h"
 
 class TTaskDefinition;
+namespace chcore { class IFeedbackHandler; }
+class TWorkerThreadController;
+class TBasePathDataContainer;
+class TTaskLocalStats;
+class TTaskConfigTracker;
+class TTaskBasicProgressInfo;
 
 ///////////////////////////////////////////////////////////////////////////
 // TSubTaskContext
 
 class TSubTaskContext
 {
 public:
-	TSubTaskContext(TTaskDefinition& rTaskDefinition, CFileInfoArray& rFilesCache);
+	TSubTaskContext(TTaskDefinition& rTaskDefinition, TBasePathDataContainer& rBasePathDataContainer, CFileInfoArray& rFilesCache, TTaskLocalStats& rTaskLocalStats,
+                  TTaskBasicProgressInfo& rTaskBasicProgressInfo, TTaskConfigTracker& rCfgTracker, icpf::log_file& rLog,
+                  chcore::IFeedbackHandler* piFeedbackHandler, TWorkerThreadController& rThreadController);
 	~TSubTaskContext();
 
+	TTaskDefinition& GetTaskDefinition() { return m_rTaskDefinition; }
+   const TTaskDefinition& GetTaskDefinition() const { return m_rTaskDefinition; }
+
+   TBasePathDataContainer& GetBasePathDataContainer() { return m_rBasePathDataContainer; }
+   const TBasePathDataContainer& GetBasePathDataContainer() const { return m_rBasePathDataContainer; }
+
+   CFileInfoArray& GetFilesCache() { return m_rFilesCache; }
+   const CFileInfoArray& GetFilesCache() const { return m_rFilesCache; }
+
+   TTaskLocalStats& GetTaskLocalStats() { return m_rTaskLocalStats; }
+   const TTaskLocalStats& GetTaskLocalStats() const { return m_rTaskLocalStats; }
+
+   TTaskBasicProgressInfo& GetTaskBasicProgressInfo() { return m_rTaskBasicProgressInfo; }
+   const TTaskBasicProgressInfo& GetTaskBasicProgressInfo() const { return m_rTaskBasicProgressInfo; }
+
+   TTaskConfigTracker& GetCfgTracker() { return m_rCfgTracker; }
+   const TTaskConfigTracker& GetCfgTracker() const { return m_rCfgTracker; }
+
+   icpf::log_file& GetLog() { return m_rLog; }
+   const icpf::log_file& GetLog() const { return m_rLog; }
+
+   chcore::IFeedbackHandler* GetFeedbackHandler() { return m_piFeedbackHandler; }
+   const chcore::IFeedbackHandler* GetFeedbackHandler() const { return m_piFeedbackHandler; }
+
+   TWorkerThreadController& GetThreadController() { return m_rThreadController; }
+   const TWorkerThreadController& GetThreadController() const { return m_rThreadController; }
+
 private:
 	TTaskDefinition& m_rTaskDefinition;
 
+   // information about input paths
+   TBasePathDataContainer& m_rBasePathDataContainer;
+
 	// data on which to operate
 	CFileInfoArray& m_rFilesCache;
+
+   // local stats for task
+   TTaskLocalStats& m_rTaskLocalStats;
+   TTaskBasicProgressInfo& m_rTaskBasicProgressInfo;
+
+   // configuration changes tracking
+   TTaskConfigTracker& m_rCfgTracker;
+
+	// additional data
+	icpf::log_file& m_rLog;
+
+	// feedback handling
+	chcore::IFeedbackHandler* m_piFeedbackHandler;
+
+   // thread control
+   TWorkerThreadController& m_rThreadController;
 };
 
 
Index: src/ch/TSubTaskCopyMove.cpp
===================================================================
diff -u -rb7709acbab26fdb108b77d3e08d3872f54248af2 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision b7709acbab26fdb108b77d3e08d3872f54248af2)
+++ src/ch/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -22,3 +22,1072 @@
 // ============================================================================
 #include "stdafx.h"
 #include "TSubTaskCopyMove.h"
+#include "TSubTaskContext.h"
+#include "TTaskConfiguration.h"
+#include "TTaskDefinition.h"
+#include "task.h"
+#include "TLocalFilesystem.h"
+#include "FeedbackHandler.h"
+#include "..\Common\FileSupport.h"
+#include "Device IO.h"
+
+// assume max sectors of 4kB (for rounding)
+#define MAXSECTORSIZE			4096
+
+struct CUSTOM_COPY_PARAMS
+{
+   CFileInfoPtr spSrcFile;		// CFileInfo - src file
+   chcore::TSmartPath pathDstFile;			// dest path with filename
+
+   CDataBuffer dbBuffer;		// buffer handling
+   bool bOnlyCreate;			// flag from configuration - skips real copying - only create
+   bool bProcessed;			// has the element been processed ? (false if skipped)
+};
+
+TSubTaskCopyMove::TSubTaskCopyMove(TSubTaskContext& tSubTaskContext) :
+   TSubTaskBase(tSubTaskContext)
+{
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::Exec()
+{
+   icpf::log_file& rLog = GetContext().GetLog();
+   CFileInfoArray& rFilesCache = GetContext().GetFilesCache();
+   TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+   TTaskConfigTracker& rCfgTracker = GetContext().GetCfgTracker();
+   TTaskBasicProgressInfo& rBasicProgressInfo = GetContext().GetTaskBasicProgressInfo();
+   TWorkerThreadController& rThreadController = GetContext().GetThreadController();
+   chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+   TTaskLocalStats& rLocalStats = GetContext().GetTaskLocalStats();
+
+   BOOST_ASSERT(piFeedbackHandler != NULL);
+   if(piFeedbackHandler == NULL)
+      return eSubResult_Error;
+
+   // log
+   rLog.logi(_T("Processing files/folders (ProcessFiles)"));
+
+   // count how much has been done (updates also a member in TSubTaskCopyMoveArray)
+   rLocalStats.SetProcessedSize(rFilesCache.CalculatePartialSize(rBasicProgressInfo.GetCurrentIndex()));
+
+   // begin at index which wasn't processed previously
+   size_t stSize = rFilesCache.GetSize();
+   bool bIgnoreFolders = GetTaskPropValue<eTO_IgnoreDirectories>(rTaskDefinition.GetConfiguration());
+   bool bForceDirectories = GetTaskPropValue<eTO_CreateDirectoriesRelativeToRoot>(rTaskDefinition.GetConfiguration());
+
+   // create a buffer of size m_nBufferSize
+   CUSTOM_COPY_PARAMS ccp;
+   ccp.bProcessed = false;
+   ccp.bOnlyCreate = GetTaskPropValue<eTO_CreateEmptyFiles>(rTaskDefinition.GetConfiguration());
+
+   // remove changes in buffer sizes to avoid re-creation later
+   rCfgTracker.RemoveModificationSet(TOptionsSet() % eTO_DefaultBufferSize % eTO_OneDiskBufferSize % eTO_TwoDisksBufferSize % eTO_CDBufferSize % eTO_LANBufferSize % eTO_UseOnlyDefaultBuffer);
+
+   BUFFERSIZES bs;
+   bs.m_bOnlyDefault = GetTaskPropValue<eTO_UseOnlyDefaultBuffer>(rTaskDefinition.GetConfiguration());
+   bs.m_uiDefaultSize = GetTaskPropValue<eTO_DefaultBufferSize>(rTaskDefinition.GetConfiguration());
+   bs.m_uiOneDiskSize = GetTaskPropValue<eTO_OneDiskBufferSize>(rTaskDefinition.GetConfiguration());
+   bs.m_uiTwoDisksSize = GetTaskPropValue<eTO_TwoDisksBufferSize>(rTaskDefinition.GetConfiguration());
+   bs.m_uiCDSize = GetTaskPropValue<eTO_CDBufferSize>(rTaskDefinition.GetConfiguration());
+   bs.m_uiLANSize = GetTaskPropValue<eTO_LANBufferSize>(rTaskDefinition.GetConfiguration());
+
+   ccp.dbBuffer.Create(&bs);
+
+   // helpers
+   DWORD dwLastError = 0;
+
+   // log
+   const BUFFERSIZES* pbs = ccp.dbBuffer.GetSizes();
+
+   ictranslate::CFormat fmt;
+   fmt.SetFormat(_T("Processing files/folders (ProcessFiles):\r\n\tOnlyCreate: %create\r\n\tBufferSize: [Def:%defsize, One:%onesize, Two:%twosize, CD:%cdsize, LAN:%lansize]\r\n\tFiles/folders count: %filecount\r\n\tIgnore Folders: %ignorefolders\r\n\tDest path: %dstpath\r\n\tCurrent index (0-based): %currindex"));
+   fmt.SetParam(_t("%create"), ccp.bOnlyCreate);
+   fmt.SetParam(_t("%defsize"), pbs->m_uiDefaultSize);
+   fmt.SetParam(_t("%onesize"), pbs->m_uiOneDiskSize);
+   fmt.SetParam(_t("%twosize"), pbs->m_uiTwoDisksSize);
+   fmt.SetParam(_t("%cdsize"), pbs->m_uiCDSize);
+   fmt.SetParam(_t("%lansize"), pbs->m_uiLANSize);
+   fmt.SetParam(_t("%filecount"), stSize);
+   fmt.SetParam(_t("%ignorefolders"), bIgnoreFolders);
+   fmt.SetParam(_t("%dstpath"), rTaskDefinition.GetDestinationPath().ToString());
+   fmt.SetParam(_t("%currindex"), rBasicProgressInfo.GetCurrentIndex());
+
+   rLog.logi(fmt);
+
+   for(size_t stIndex = rBasicProgressInfo.GetCurrentIndex(); stIndex < stSize; stIndex++)
+   {
+      // should we kill ?
+      if(rThreadController.KillRequested())
+      {
+         // log
+         rLog.logi(_T("Kill request while processing file in ProcessFiles"));
+         return TSubTaskBase::eSubResult_KillRequest;
+      }
+
+      // update m_stNextIndex, getting current CFileInfo
+      CFileInfoPtr spFileInfo = rFilesCache.GetAt(rBasicProgressInfo.GetCurrentIndex());
+
+      // set dest path with filename
+      ccp.pathDstFile = CalculateDestinationPath(spFileInfo, rTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1 | (int)bIgnoreFolders);
+
+      // are the files/folders lie on the same partition ?
+      int iDstDriveNumber = 0;
+      bool bMove = rTaskDefinition.GetOperationType() == eOperation_Move;
+      if(bMove)
+         TLocalFilesystem::GetDriveData(rTaskDefinition.GetDestinationPath(), &iDstDriveNumber, NULL);
+      if(bMove && iDstDriveNumber != -1 && iDstDriveNumber == GetDriveNumber(spFileInfo) && GetMove(spFileInfo))
+      {
+         bool bRetry = true;
+         if(bRetry && !MoveFile(spFileInfo->GetFullFilePath().ToString(), ccp.pathDstFile.ToString()))
+         {
+            dwLastError=GetLastError();
+            //log
+            fmt.SetFormat(_T("Error %errno while calling MoveFile %srcpath -> %dstpath (ProcessFiles)"));
+            fmt.SetParam(_t("%errno"), dwLastError);
+            fmt.SetParam(_t("%srcpath"), spFileInfo->GetFullFilePath().ToString());
+            fmt.SetParam(_t("%dstpath"), ccp.pathDstFile.ToString());
+            rLog.loge(fmt);
+
+            FEEDBACK_FILEERROR ferr = { spFileInfo->GetFullFilePath().ToString(), ccp.pathDstFile.ToString(), eFastMoveError, dwLastError };
+            CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
+            switch(frResult)
+            {
+            case CFeedbackHandler::eResult_Cancel:
+               return TSubTaskBase::eSubResult_CancelRequest;
+
+            case CFeedbackHandler::eResult_Retry:
+               continue;
+
+            case CFeedbackHandler::eResult_Pause:
+               return TSubTaskBase::eSubResult_PauseRequest;
+
+            case CFeedbackHandler::eResult_Skip:
+               bRetry = false;
+               break;		// just do nothing
+            default:
+               BOOST_ASSERT(FALSE);		// unknown result
+               THROW(_T("Unhandled case"), 0, 0, 0);
+            }
+         }
+         else
+            spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED);
+      }
+      else
+      {
+         // if folder - create it
+         if(spFileInfo->IsDirectory())
+         {
+            bool bRetry = true;
+            if(bRetry && !CreateDirectory(ccp.pathDstFile.ToString(), NULL) && (dwLastError=GetLastError()) != ERROR_ALREADY_EXISTS )
+            {
+               // log
+               fmt.SetFormat(_T("Error %errno while calling CreateDirectory %path (ProcessFiles)"));
+               fmt.SetParam(_t("%errno"), dwLastError);
+               fmt.SetParam(_t("%path"), ccp.pathDstFile.ToString());
+               rLog.loge(fmt);
+
+               FEEDBACK_FILEERROR ferr = { ccp.pathDstFile.ToString(), NULL, eCreateError, dwLastError };
+               CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
+               switch(frResult)
+               {
+               case CFeedbackHandler::eResult_Cancel:
+                  return TSubTaskBase::eSubResult_CancelRequest;
+
+               case CFeedbackHandler::eResult_Retry:
+                  continue;
+
+               case CFeedbackHandler::eResult_Pause:
+                  return TSubTaskBase::eSubResult_PauseRequest;
+
+               case CFeedbackHandler::eResult_Skip:
+                  bRetry = false;
+                  break;		// just do nothing
+               default:
+                  BOOST_ASSERT(FALSE);		// unknown result
+                  THROW(_T("Unhandled case"), 0, 0, 0);
+               }
+            }
+
+            rLocalStats.IncreaseProcessedSize(spFileInfo->GetLength64());
+            spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED);
+         }
+         else
+         {
+            // start copying/moving file
+            ccp.spSrcFile = spFileInfo;
+            ccp.bProcessed = false;
+
+            // kopiuj dane
+            TSubTaskBase::ESubOperationResult eResult = CustomCopyFileFB(&ccp);
+            if(eResult != TSubTaskBase::eSubResult_Continue)
+               return eResult;
+
+            spFileInfo->SetFlags(ccp.bProcessed ? FIF_PROCESSED : 0, FIF_PROCESSED);
+
+            // if moving - delete file (only if config flag is set)
+            if(bMove && spFileInfo->GetFlags() & FIF_PROCESSED && !GetTaskPropValue<eTO_DeleteInSeparateSubTask>(rTaskDefinition.GetConfiguration()))
+            {
+               if(!GetTaskPropValue<eTO_ProtectReadOnlyFiles>(rTaskDefinition.GetConfiguration()))
+                  SetFileAttributes(spFileInfo->GetFullFilePath().ToString(), FILE_ATTRIBUTE_NORMAL);
+               DeleteFile(spFileInfo->GetFullFilePath().ToString());	// there will be another try later, so I don't check
+               // if succeeded
+            }
+         }
+
+         // set a time
+         if(GetTaskPropValue<eTO_SetDestinationDateTime>(rTaskDefinition.GetConfiguration()))
+            TLocalFilesystem::SetFileDirectoryTime(ccp.pathDstFile.ToString(), spFileInfo->GetCreationTime(), spFileInfo->GetLastAccessTime(), spFileInfo->GetLastWriteTime()); // no error checking (but most probably it should be checked)
+
+         // attributes
+         if(GetTaskPropValue<eTO_SetDestinationAttributes>(rTaskDefinition.GetConfiguration()))
+            SetFileAttributes(ccp.pathDstFile.ToString(), spFileInfo->GetAttributes());	// as above
+      }
+
+      rBasicProgressInfo.SetCurrentIndex(stIndex + 1);
+   }
+
+   // delete buffer - it's not needed
+   ccp.dbBuffer.Delete();
+
+   // to look better (as 100%) - increase current index by 1
+   rBasicProgressInfo.SetCurrentIndex(stSize);
+
+   // log
+   rLog.logi(_T("Finished processing in ProcessFiles"));
+
+   return TSubTaskBase::eSubResult_Continue;
+}
+
+bool TSubTaskCopyMove::GetMove(const CFileInfoPtr& spFileInfo)
+{
+   if(!spFileInfo)
+      THROW(_T("Invalid pointer"), 0, 0, 0);
+   if(spFileInfo->GetSrcIndex() == std::numeric_limits<size_t>::max())
+      THROW(_T("Received non-relative (standalone) path info"), 0, 0, 0);
+
+   // check if this information has already been stored
+   size_t stBaseIndex = spFileInfo->GetSrcIndex();
+   if(stBaseIndex >= GetContext().GetBasePathDataContainer().GetCount())
+      THROW(_T("Index out of bounds"), 0, 0, 0);
+
+   TBasePathDataPtr spPathData = GetContext().GetBasePathDataContainer().GetAt(stBaseIndex);
+   return spPathData->GetMove();
+}
+
+int TSubTaskCopyMove::GetBufferIndex(const CFileInfoPtr& spFileInfo)
+{
+   TBasePathDataContainer& rSrcPathsInfo = GetContext().GetBasePathDataContainer();
+   TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+
+   if(!spFileInfo)
+      THROW(_T("Invalid pointer"), 0, 0, 0);
+   if(spFileInfo->GetSrcIndex() == std::numeric_limits<size_t>::max())
+      THROW(_T("Received non-relative (standalone) path info"), 0, 0, 0);
+
+   // check if this information has already been stored
+   size_t stBaseIndex = spFileInfo->GetSrcIndex();
+   if(stBaseIndex >= rSrcPathsInfo.GetCount())
+      THROW(_T("Index out of bounds"), 0, 0, 0);
+
+   TBasePathDataPtr spPathData = rSrcPathsInfo.GetAt(stBaseIndex);
+   if(spPathData->IsBufferIndexSet())
+      return spPathData->GetBufferIndex();
+
+   // buffer index wasn't cached previously - read it now
+   int iDriveNumber = 0;
+   UINT uiDriveType = 0;
+   int iDstDriveNumber = 0;
+   UINT uiDstDriveType = 0;
+   TLocalFilesystem::GetDriveData(rTaskDefinition.GetSourcePathAt(stBaseIndex), &iDriveNumber, &uiDriveType);
+   TLocalFilesystem::GetDriveData(rTaskDefinition.GetDestinationPath(), &iDstDriveNumber, &uiDstDriveType);
+
+   // what kind of buffer
+   int iBufferIndex = BI_DEFAULT;
+   if(uiDriveType == DRIVE_REMOTE || uiDstDriveType == DRIVE_REMOTE)
+      iBufferIndex = BI_LAN;
+   else if(uiDriveType == DRIVE_CDROM || uiDstDriveType == DRIVE_CDROM)
+      iBufferIndex = BI_CD;
+   else if(uiDriveType == DRIVE_FIXED && uiDstDriveType == DRIVE_FIXED)
+   {
+      // two hdd's - is this the same physical disk ?
+      if(iDriveNumber == iDstDriveNumber || IsSamePhysicalDisk(iDriveNumber, iDstDriveNumber))
+         iBufferIndex = BI_ONEDISK;
+      else
+         iBufferIndex = BI_TWODISKS;
+   }
+   else
+      iBufferIndex = BI_DEFAULT;
+
+   spPathData->SetBufferIndex(iBufferIndex);
+
+   return iBufferIndex;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::CustomCopyFileFB(CUSTOM_COPY_PARAMS* pData)
+{
+   TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+   TTaskBasicProgressInfo& rBasicProgressInfo = GetContext().GetTaskBasicProgressInfo();
+   TWorkerThreadController& rThreadController = GetContext().GetThreadController();
+   TTaskLocalStats& rLocalStats = GetContext().GetTaskLocalStats();
+   icpf::log_file& rLog = GetContext().GetLog();
+   TTaskConfigTracker& rCfgTracker = GetContext().GetCfgTracker();
+
+   TAutoFileHandle hSrc = INVALID_HANDLE_VALUE,
+      hDst = INVALID_HANDLE_VALUE;
+   ictranslate::CFormat fmt;
+   TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue;
+   bool bSkip = false;
+
+   // calculate if we want to disable buffering for file transfer
+   // NOTE: we are using here the file size read when scanning directories for files; it might be
+   //       outdated at this point, but at present we don't want to re-read file size since it
+   //       will cost additional disk access
+   bool bNoBuffer = (GetTaskPropValue<eTO_DisableBuffering>(rTaskDefinition.GetConfiguration()) &&
+      pData->spSrcFile->GetLength64() >= GetTaskPropValue<eTO_DisableBufferingMinSize>(rTaskDefinition.GetConfiguration()));
+
+   // first open the source file and handle any failures
+   eResult = OpenSourceFileFB(hSrc, pData->spSrcFile, bNoBuffer);
+   if(eResult != TSubTaskBase::eSubResult_Continue)
+      return eResult;
+   else if(hSrc == INVALID_HANDLE_VALUE)
+   {
+      // invalid handle = operation skipped by user
+      rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+      pData->bProcessed = false;
+      return TSubTaskBase::eSubResult_Continue;
+   }
+
+   // change attributes of a dest file
+   // NOTE: probably should be removed from here and report problems with read-only files
+   //       directly to the user (as feedback request)
+   if(!GetTaskPropValue<eTO_ProtectReadOnlyFiles>(rTaskDefinition.GetConfiguration()))
+      SetFileAttributes(pData->pathDstFile.ToString(), FILE_ATTRIBUTE_NORMAL);
+
+   // open destination file, handle the failures and possibly existence of the destination file
+   unsigned long long ullSeekTo = 0;
+   bool bDstFileFreshlyCreated = false;
+
+   if(rBasicProgressInfo.GetCurrentFileProcessedSize() == 0)
+   {
+      // open destination file for case, when we start operation on this file (i.e. it is not resume of the
+      // old operation)
+      eResult = OpenDestinationFileFB(hDst, pData->pathDstFile, bNoBuffer, pData->spSrcFile, ullSeekTo, bDstFileFreshlyCreated);
+      if(eResult != TSubTaskBase::eSubResult_Continue)
+         return eResult;
+      else if(hDst == INVALID_HANDLE_VALUE)
+      {
+         rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+         pData->bProcessed = false;
+         return TSubTaskBase::eSubResult_Continue;
+      }
+   }
+   else
+   {
+      // we are resuming previous operation
+      eResult = OpenExistingDestinationFileFB(hDst, pData->pathDstFile, bNoBuffer);
+      if(eResult != TSubTaskBase::eSubResult_Continue)
+         return eResult;
+      else if(hDst == INVALID_HANDLE_VALUE)
+      {
+         rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+         pData->bProcessed = false;
+         return TSubTaskBase::eSubResult_Continue;
+      }
+
+      ullSeekTo = rBasicProgressInfo.GetCurrentFileProcessedSize();
+   }
+
+   if(!pData->bOnlyCreate)
+   {
+      // seek to the position where copying will start
+      if(ullSeekTo != 0)		// src and dst files exists, requested resume at the specified index
+      {
+         // try to move file pointers to the end
+         ULONGLONG ullMove = (bNoBuffer ? ROUNDDOWN(ullSeekTo, MAXSECTORSIZE) : ullSeekTo);
+
+         eResult = SetFilePointerFB(hSrc, ullMove, pData->spSrcFile->GetFullFilePath(), bSkip);
+         if(eResult != TSubTaskBase::eSubResult_Continue)
+            return eResult;
+         else if(bSkip)
+         {
+            rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+            pData->bProcessed = false;
+            return TSubTaskBase::eSubResult_Continue;
+         }
+
+         eResult = SetFilePointerFB(hDst, ullMove, pData->pathDstFile, bSkip);
+         if(eResult != TSubTaskBase::eSubResult_Continue)
+            return eResult;
+         else if(bSkip)
+         {
+            // with either first or second seek we got 'skip' answer...
+            rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+            pData->bProcessed = false;
+            return TSubTaskBase::eSubResult_Continue;
+         }
+
+         rBasicProgressInfo.IncreaseCurrentFileProcessedSize(ullMove);
+         rLocalStats.IncreaseProcessedSize(ullMove);
+      }
+
+      // if the destination file already exists - truncate it to the current file position
+      if(!bDstFileFreshlyCreated)
+      {
+         // if destination file was opened (as opposed to newly created)
+         eResult = SetEndOfFileFB(hDst, pData->pathDstFile, bSkip);
+         if(eResult != TSubTaskBase::eSubResult_Continue)
+            return eResult;
+         else if(bSkip)
+         {
+            pData->bProcessed = false;
+            return TSubTaskBase::eSubResult_Continue;
+         }
+      }
+
+      // copying
+      unsigned long ulToRead = 0;
+      unsigned long ulRead = 0;
+      unsigned long ulWritten = 0;
+      int iBufferIndex = 0;
+      bool bLastPart = false;
+
+      do
+      {
+         // kill flag checks
+         if(rThreadController.KillRequested())
+         {
+            // log
+            fmt.SetFormat(_T("Kill request while main copying file %srcpath -> %dstpath"));
+            fmt.SetParam(_t("%srcpath"), pData->spSrcFile->GetFullFilePath().ToString());
+            fmt.SetParam(_t("%dstpath"), pData->pathDstFile.ToString());
+            rLog.logi(fmt);
+            return TSubTaskBase::eSubResult_KillRequest;
+         }
+
+         // recreate buffer if needed
+         if(rCfgTracker.IsModified() && rCfgTracker.IsModified(TOptionsSet() % eTO_DefaultBufferSize % eTO_OneDiskBufferSize % eTO_TwoDisksBufferSize % eTO_CDBufferSize % eTO_LANBufferSize % eTO_UseOnlyDefaultBuffer, true))
+         {
+            BUFFERSIZES bs;
+            bs.m_bOnlyDefault = GetTaskPropValue<eTO_UseOnlyDefaultBuffer>(rTaskDefinition.GetConfiguration());
+            bs.m_uiDefaultSize = GetTaskPropValue<eTO_DefaultBufferSize>(rTaskDefinition.GetConfiguration());
+            bs.m_uiOneDiskSize = GetTaskPropValue<eTO_OneDiskBufferSize>(rTaskDefinition.GetConfiguration());
+            bs.m_uiTwoDisksSize = GetTaskPropValue<eTO_TwoDisksBufferSize>(rTaskDefinition.GetConfiguration());
+            bs.m_uiCDSize = GetTaskPropValue<eTO_CDBufferSize>(rTaskDefinition.GetConfiguration());
+            bs.m_uiLANSize = GetTaskPropValue<eTO_LANBufferSize>(rTaskDefinition.GetConfiguration());
+
+            // log
+            const BUFFERSIZES* pbs1 = pData->dbBuffer.GetSizes();
+
+            fmt.SetFormat(_T("Changing buffer size from [Def:%defsize, One:%onesize, Two:%twosize, CD:%cdsize, LAN:%lansize] to [Def:%defsize2, One:%onesize2, Two:%twosize2, CD:%cdsize2, LAN:%lansize2] wile copying %srcfile -> %dstfile (CustomCopyFileFB)"));
+
+            fmt.SetParam(_t("%defsize"), pbs1->m_uiDefaultSize);
+            fmt.SetParam(_t("%onesize"), pbs1->m_uiOneDiskSize);
+            fmt.SetParam(_t("%twosize"), pbs1->m_uiTwoDisksSize);
+            fmt.SetParam(_t("%cdsize"), pbs1->m_uiCDSize);
+            fmt.SetParam(_t("%lansize"), pbs1->m_uiLANSize);
+            fmt.SetParam(_t("%defsize2"), bs.m_uiDefaultSize);
+            fmt.SetParam(_t("%onesize2"), bs.m_uiOneDiskSize);
+            fmt.SetParam(_t("%twosize2"), bs.m_uiTwoDisksSize);
+            fmt.SetParam(_t("%cdsize2"), bs.m_uiCDSize);
+            fmt.SetParam(_t("%lansize2"), bs.m_uiLANSize);
+            fmt.SetParam(_t("%srcfile"), pData->spSrcFile->GetFullFilePath().ToString());
+            fmt.SetParam(_t("%dstfile"), pData->pathDstFile.ToString());
+
+            rLog.logi(fmt);
+            pData->dbBuffer.Create(&bs);
+         }
+
+         // establish count of data to read
+         if(GetTaskPropValue<eTO_UseOnlyDefaultBuffer>(rTaskDefinition.GetConfiguration()))
+            iBufferIndex = BI_DEFAULT;
+         else
+            iBufferIndex = GetBufferIndex(pData->spSrcFile);
+         rLocalStats.SetCurrentBufferIndex(iBufferIndex);
+
+         ulToRead = bNoBuffer ? ROUNDUP(pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex], MAXSECTORSIZE) : pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex];
+
+         // read data from file to buffer
+         eResult = ReadFileFB(hSrc, pData->dbBuffer, ulToRead, ulRead, pData->spSrcFile->GetFullFilePath(), bSkip);
+         if(eResult != TSubTaskBase::eSubResult_Continue)
+            return eResult;
+         else if(bSkip)
+         {
+            rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+            pData->bProcessed = false;
+            return TSubTaskBase::eSubResult_Continue;
+         }
+
+         if(ulRead > 0)
+         {
+            // determine if this is the last chunk of data we could get from the source file (EOF condition)
+            bLastPart = (ulToRead != ulRead);
+
+            // handle not aligned part at the end of file when no buffering is enabled
+            if(bNoBuffer && bLastPart)
+            {
+               // count of data read from the file is less than requested - we're at the end of source file
+               // and this is the operation with system buffering turned off
+
+               // write as much as possible to the destination file with no buffering
+               // NOTE: as an alternative, we could write more data to the destination file and then truncate the file
+               unsigned long ulDataToWrite = ROUNDDOWN(ulRead, MAXSECTORSIZE);
+               if(ulDataToWrite > 0)
+               {
+                  eResult = WriteFileFB(hDst, pData->dbBuffer, ulDataToWrite, ulWritten, pData->pathDstFile, bSkip);
+                  if(eResult != TSubTaskBase::eSubResult_Continue)
+                     return eResult;
+                  else if(bSkip)
+                  {
+                     rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+                     pData->bProcessed = false;
+                     return TSubTaskBase::eSubResult_Continue;
+                  }
+
+                  // increase count of processed data
+                  rBasicProgressInfo.IncreaseCurrentFileProcessedSize(ulWritten);
+                  rLocalStats.IncreaseProcessedSize(ulWritten);
+
+                  // calculate count of bytes left to be written
+                  ulRead -= ulWritten;
+
+                  // now remove part of data from buffer (ulWritten bytes)
+                  pData->dbBuffer.CutDataFromBuffer(ulWritten);
+               }
+
+               // close and re-open the destination file with buffering option for append
+               hDst.Close();
+
+               // are there any more data to be written?
+               if(ulRead != 0)
+               {
+                  // re-open the destination file, this time with standard buffering to allow writing not aligned part of file data
+                  eResult = OpenExistingDestinationFileFB(hDst, pData->pathDstFile, false);
+                  if(eResult != TSubTaskBase::eSubResult_Continue)
+                     return eResult;
+                  else if(hDst == INVALID_HANDLE_VALUE)
+                  {
+                     rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+                     pData->bProcessed = false;
+                     return TSubTaskBase::eSubResult_Continue;
+                  }
+
+                  // move file pointer to the end of destination file
+                  eResult = SetFilePointerFB(hDst, rBasicProgressInfo.GetCurrentFileProcessedSize(), pData->pathDstFile, bSkip);
+                  if(eResult != TSubTaskBase::eSubResult_Continue)
+                     return eResult;
+                  else if(bSkip)
+                  {
+                     // with either first or second seek we got 'skip' answer...
+                     rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+                     pData->bProcessed = false;
+                     return TSubTaskBase::eSubResult_Continue;
+                  }
+               }
+            }
+
+            // write
+            if(ulRead != 0)
+            {
+               eResult = WriteFileFB(hDst, pData->dbBuffer, ulRead, ulWritten, pData->pathDstFile, bSkip);
+               if(eResult != TSubTaskBase::eSubResult_Continue)
+                  return eResult;
+               else if(bSkip)
+               {
+                  rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+                  pData->bProcessed = false;
+                  return TSubTaskBase::eSubResult_Continue;
+               }
+
+               // increase count of processed data
+               rBasicProgressInfo.IncreaseCurrentFileProcessedSize(ulRead);
+               rLocalStats.IncreaseProcessedSize(ulRead);
+            }
+         }
+      }
+      while(ulRead != 0 && !bLastPart);
+   }
+   else
+   {
+      // we don't copy contents, but need to increase processed size
+      rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+   }
+
+   pData->bProcessed = true;
+   rBasicProgressInfo.SetCurrentFileProcessedSize(0);
+
+   return TSubTaskBase::eSubResult_Continue;
+}
+
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::OpenSourceFileFB(TAutoFileHandle& hOutFile, const CFileInfoPtr& spSrcFileInfo, bool bNoBuffering)
+{
+   chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+   icpf::log_file& rLog = GetContext().GetLog();
+
+   BOOST_ASSERT(spSrcFileInfo);
+   if(!spSrcFileInfo)
+      THROW(_T("Invalid argument"), 0, 0, 0);
+
+   bool bRetry = false;
+   CString strPath = spSrcFileInfo->GetFullFilePath().ToString();
+
+   hOutFile = INVALID_HANDLE_VALUE;
+
+   TAutoFileHandle hFile;
+   do
+   {
+      bRetry = false;
+
+      hFile = CreateFile(strPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
+      if(hFile == INVALID_HANDLE_VALUE)
+      {
+         DWORD dwLastError = GetLastError();
+
+         FEEDBACK_FILEERROR feedStruct = { (PCTSTR)strPath, NULL, eCreateError, dwLastError };
+         CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
+
+         switch(frResult)
+         {
+         case CFeedbackHandler::eResult_Skip:
+            break;	// will return INVALID_HANDLE_VALUE
+
+         case CFeedbackHandler::eResult_Cancel:
+            {
+               // log
+               ictranslate::CFormat fmt;
+               fmt.SetFormat(_T("Cancel request [error %errno] while opening source file %path (OpenSourceFileFB)"));
+               fmt.SetParam(_t("%errno"), dwLastError);
+               fmt.SetParam(_t("%path"), strPath);
+               rLog.loge(fmt);
+
+               return TSubTaskBase::eSubResult_CancelRequest;
+            }
+
+         case CFeedbackHandler::eResult_Pause:
+            return TSubTaskBase::eSubResult_PauseRequest;
+
+         case CFeedbackHandler::eResult_Retry:
+            {
+               // log
+               ictranslate::CFormat fmt;
+               fmt.SetFormat(_T("Retrying [error %errno] to open source file %path (OpenSourceFileFB)"));
+               fmt.SetParam(_t("%errno"), dwLastError);
+               fmt.SetParam(_t("%path"), strPath);
+               rLog.loge(fmt);
+
+               bRetry = true;
+               break;
+            }
+
+         default:
+            BOOST_ASSERT(FALSE);		// unknown result
+            THROW(_T("Unhandled case"), 0, 0, 0);
+         }
+      }
+   }
+   while(bRetry);
+
+   hOutFile = hFile.Detach();
+
+   return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::OpenDestinationFileFB(TAutoFileHandle& hOutFile, const chcore::TSmartPath& pathDstFile, bool bNoBuffering, const CFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated)
+{
+   chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+   icpf::log_file& rLog = GetContext().GetLog();
+
+   bool bRetry = false;
+   TAutoFileHandle hFile;
+
+   ullSeekTo = 0;
+   bFreshlyCreated = true;
+   hOutFile = INVALID_HANDLE_VALUE;
+
+   do
+   {
+      bRetry = false;
+
+      hFile = ::CreateFile(pathDstFile.ToString(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
+      if(hFile == INVALID_HANDLE_VALUE)
+      {
+         DWORD dwLastError = GetLastError();
+         if(dwLastError == ERROR_FILE_EXISTS)
+         {
+            bFreshlyCreated = false;
+
+            // pass it to the specialized method
+            TSubTaskBase::ESubOperationResult eResult = OpenExistingDestinationFileFB(hFile, pathDstFile, bNoBuffering);
+            if(eResult != TSubTaskBase::eSubResult_Continue)
+               return eResult;
+            else if(hFile == INVALID_HANDLE_VALUE)
+               return TSubTaskBase::eSubResult_Continue;
+
+            // read info about the existing destination file,
+            // NOTE: it is not known which one would be faster - reading file parameters
+            //       by using spDstFileInfo->Create() (which uses FindFirstFile()) or by
+            //       reading parameters using opened handle; need to be tested in the future
+            CFileInfoPtr spDstFileInfo(boost::make_shared<CFileInfo>());
+            if(!spDstFileInfo->Create(pathDstFile, std::numeric_limits<size_t>::max()))
+               THROW(_T("Cannot get information about file which has already been opened!"), 0, GetLastError(), 0);
+
+            // src and dst files are the same
+            FEEDBACK_ALREADYEXISTS feedStruct = { spSrcFileInfo, spDstFileInfo };
+            CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileAlreadyExists, &feedStruct);
+            // check for dialog result
+            switch(frResult)
+            {
+            case CFeedbackHandler::eResult_Overwrite:
+               ullSeekTo = 0;
+               break;
+
+            case CFeedbackHandler::eResult_CopyRest:
+               ullSeekTo = spDstFileInfo->GetLength64();
+               break;
+
+            case CFeedbackHandler::eResult_Skip:
+               return TSubTaskBase::eSubResult_Continue;
+
+            case CFeedbackHandler::eResult_Cancel:
+               {
+                  // log
+                  ictranslate::CFormat fmt;
+                  fmt.SetFormat(_T("Cancel request while checking result of dialog before opening source file %path (CustomCopyFileFB)"));
+                  fmt.SetParam(_t("%path"), pathDstFile.ToString());
+                  rLog.logi(fmt);
+
+                  return TSubTaskBase::eSubResult_CancelRequest;
+               }
+            case CFeedbackHandler::eResult_Pause:
+               return TSubTaskBase::eSubResult_PauseRequest;
+
+            default:
+               BOOST_ASSERT(FALSE);		// unknown result
+               THROW(_T("Unhandled case"), 0, 0, 0);
+            }
+         }
+         else
+         {
+            FEEDBACK_FILEERROR feedStruct = { pathDstFile.ToString(), NULL, eCreateError, dwLastError };
+            CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
+            switch (frResult)
+            {
+            case CFeedbackHandler::eResult_Retry:
+               {
+                  // log
+                  ictranslate::CFormat fmt;
+                  fmt.SetFormat(_T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)"));
+                  fmt.SetParam(_t("%errno"), dwLastError);
+                  fmt.SetParam(_t("%path"), pathDstFile.ToString());
+                  rLog.loge(fmt);
+
+                  bRetry = true;
+
+                  break;
+               }
+            case CFeedbackHandler::eResult_Cancel:
+               {
+                  // log
+                  ictranslate::CFormat fmt;
+
+                  fmt.SetFormat(_T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)"));
+                  fmt.SetParam(_t("%errno"), dwLastError);
+                  fmt.SetParam(_t("%path"), pathDstFile.ToString());
+                  rLog.loge(fmt);
+
+                  return TSubTaskBase::eSubResult_CancelRequest;
+               }
+
+            case CFeedbackHandler::eResult_Skip:
+               break;		// will return invalid handle value
+
+            case CFeedbackHandler::eResult_Pause:
+               return TSubTaskBase::eSubResult_PauseRequest;
+
+            default:
+               BOOST_ASSERT(FALSE);		// unknown result
+               THROW(_T("Unhandled case"), 0, 0, 0);
+            }
+         }
+      }
+   }
+   while(bRetry);
+
+   hOutFile = hFile.Detach();
+
+   return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::OpenExistingDestinationFileFB(TAutoFileHandle& hOutFile, const chcore::TSmartPath& pathDstFile, bool bNoBuffering)
+{
+   chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+   icpf::log_file& rLog = GetContext().GetLog();
+
+   bool bRetry = false;
+   TAutoFileHandle hFile;
+
+   hOutFile = INVALID_HANDLE_VALUE;
+
+   do
+   {
+      bRetry = false;
+
+      hFile = CreateFile(pathDstFile.ToString(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
+      if(hFile == INVALID_HANDLE_VALUE)
+      {
+         DWORD dwLastError = GetLastError();
+         FEEDBACK_FILEERROR feedStruct = { pathDstFile.ToString(), NULL, eCreateError, dwLastError };
+         CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
+         switch (frResult)
+         {
+         case CFeedbackHandler::eResult_Retry:
+            {
+               // log
+               ictranslate::CFormat fmt;
+               fmt.SetFormat(_T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)"));
+               fmt.SetParam(_t("%errno"), dwLastError);
+               fmt.SetParam(_t("%path"), pathDstFile.ToString());
+               rLog.loge(fmt);
+
+               bRetry = true;
+
+               break;
+            }
+         case CFeedbackHandler::eResult_Cancel:
+            {
+               // log
+               ictranslate::CFormat fmt;
+
+               fmt.SetFormat(_T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)"));
+               fmt.SetParam(_t("%errno"), dwLastError);
+               fmt.SetParam(_t("%path"), pathDstFile.ToString());
+               rLog.loge(fmt);
+
+               return TSubTaskBase::eSubResult_CancelRequest;
+            }
+
+         case CFeedbackHandler::eResult_Skip:
+            break;		// will return invalid handle value
+
+         case CFeedbackHandler::eResult_Pause:
+            return TSubTaskBase::eSubResult_PauseRequest;
+
+         default:
+            BOOST_ASSERT(FALSE);		// unknown result
+            THROW(_T("Unhandled case"), 0, 0, 0);
+         }
+      }
+   }
+   while(bRetry);
+
+   hOutFile = hFile.Detach();
+
+   return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::SetFilePointerFB(HANDLE hFile, long long llDistance, const chcore::TSmartPath& pathFile, bool& bSkip)
+{
+   chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+   icpf::log_file& rLog = GetContext().GetLog();
+
+   bSkip = false;
+   bool bRetry = false;
+   do
+   {
+      bRetry = false;
+
+      if(SetFilePointer64(hFile, llDistance, FILE_BEGIN) == -1)
+      {
+         DWORD dwLastError = GetLastError();
+
+         // log
+         ictranslate::CFormat fmt;
+
+         fmt.SetFormat(_T("Error %errno while moving file pointer of %path to %pos"));
+         fmt.SetParam(_t("%errno"), dwLastError);
+         fmt.SetParam(_t("%path"), pathFile.ToString());
+         fmt.SetParam(_t("%pos"), llDistance);
+         rLog.loge(fmt);
+
+         FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eSeekError, dwLastError };
+         CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
+         switch(frResult)
+         {
+         case CFeedbackHandler::eResult_Cancel:
+            return TSubTaskBase::eSubResult_CancelRequest;
+
+         case CFeedbackHandler::eResult_Retry:
+            bRetry = true;
+            break;
+
+         case CFeedbackHandler::eResult_Pause:
+            return TSubTaskBase::eSubResult_PauseRequest;
+
+         case CFeedbackHandler::eResult_Skip:
+            bSkip = true;
+            return TSubTaskBase::eSubResult_Continue;
+
+         default:
+            BOOST_ASSERT(FALSE);		// unknown result
+            THROW(_T("Unhandled case"), 0, 0, 0);
+         }
+      }
+   }
+   while(bRetry);
+
+   return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::SetEndOfFileFB(HANDLE hFile, const chcore::TSmartPath& pathFile, bool& bSkip)
+{
+   chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+   icpf::log_file& rLog = GetContext().GetLog();
+
+   bSkip = false;
+
+   bool bRetry = false;
+   do
+   {
+      if(!SetEndOfFile(hFile))
+      {
+         // log
+         DWORD dwLastError = GetLastError();
+
+         ictranslate::CFormat fmt;
+         fmt.SetFormat(_T("Error %errno while setting size of file %path to 0"));
+         fmt.SetParam(_t("%errno"), dwLastError);
+         fmt.SetParam(_t("%path"), pathFile.ToString());
+         rLog.loge(fmt);
+
+         FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eResizeError, dwLastError };
+         CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
+         switch(frResult)
+         {
+         case CFeedbackHandler::eResult_Cancel:
+            return TSubTaskBase::eSubResult_CancelRequest;
+
+         case CFeedbackHandler::eResult_Retry:
+            bRetry = true;
+
+         case CFeedbackHandler::eResult_Pause:
+            return TSubTaskBase::eSubResult_PauseRequest;
+
+         case CFeedbackHandler::eResult_Skip:
+            bSkip = true;
+            return TSubTaskBase::eSubResult_Continue;
+
+         default:
+            BOOST_ASSERT(FALSE);		// unknown result
+            THROW(_T("Unhandled case"), 0, 0, 0);
+         }
+      }
+   }
+   while(bRetry);
+
+   return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::ReadFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToRead, DWORD& rdwBytesRead, const chcore::TSmartPath& pathFile, bool& bSkip)
+{
+   chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+   icpf::log_file& rLog = GetContext().GetLog();
+
+   bSkip = false;
+   bool bRetry = false;
+   do
+   {
+      bRetry = false;
+
+      if(!ReadFile(hFile, rBuffer, dwToRead, &rdwBytesRead, NULL))
+      {
+         // log
+         DWORD dwLastError = GetLastError();
+
+         ictranslate::CFormat fmt;
+         fmt.SetFormat(_T("Error %errno while trying to read %count bytes from source file %path (CustomCopyFileFB)"));
+         fmt.SetParam(_t("%errno"), dwLastError);
+         fmt.SetParam(_t("%count"), dwToRead);
+         fmt.SetParam(_t("%path"), pathFile.ToString());
+         rLog.loge(fmt);
+
+         FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eReadError, dwLastError };
+         CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
+         switch(frResult)
+         {
+         case CFeedbackHandler::eResult_Cancel:
+            return TSubTaskBase::eSubResult_CancelRequest;
+
+         case CFeedbackHandler::eResult_Retry:
+            bRetry = true;
+            break;
+
+         case CFeedbackHandler::eResult_Pause:
+            return TSubTaskBase::eSubResult_PauseRequest;
+
+         case CFeedbackHandler::eResult_Skip:
+            bSkip = true;
+            return TSubTaskBase::eSubResult_Continue;
+
+         default:
+            BOOST_ASSERT(FALSE);		// unknown result
+            THROW(_T("Unhandled case"), 0, 0, 0);
+         }
+      }
+   }
+   while(bRetry);
+
+   return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::WriteFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToWrite, DWORD& rdwBytesWritten, const chcore::TSmartPath& pathFile, bool& bSkip)
+{
+   chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+   icpf::log_file& rLog = GetContext().GetLog();
+
+   bSkip = false;
+
+   bool bRetry = false;
+   do
+   {
+      bRetry = false;
+
+      if(!WriteFile(hFile, rBuffer, dwToWrite, &rdwBytesWritten, NULL) || dwToWrite != rdwBytesWritten)
+      {
+         // log
+         DWORD dwLastError = GetLastError();
+
+         ictranslate::CFormat fmt;
+         fmt.SetFormat(_T("Error %errno while trying to write %count bytes to destination file %path (CustomCopyFileFB)"));
+         fmt.SetParam(_t("%errno"), dwLastError);
+         fmt.SetParam(_t("%count"), dwToWrite);
+         fmt.SetParam(_t("%path"), pathFile.ToString());
+         rLog.loge(fmt);
+
+         FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eWriteError, dwLastError };
+         CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
+         switch(frResult)
+         {
+         case CFeedbackHandler::eResult_Cancel:
+            return TSubTaskBase::eSubResult_CancelRequest;
+
+         case CFeedbackHandler::eResult_Retry:
+            bRetry = true;
+            break;
+
+         case CFeedbackHandler::eResult_Pause:
+            return TSubTaskBase::eSubResult_PauseRequest;
+
+         case CFeedbackHandler::eResult_Skip:
+            bSkip = true;
+            return TSubTaskBase::eSubResult_Continue;
+
+         default:
+            BOOST_ASSERT(FALSE);		// unknown result
+            THROW(_T("Unhandled case"), 0, 0, 0);
+         }
+      }
+   }
+   while(bRetry);
+
+   return TSubTaskBase::eSubResult_Continue;
+}
Index: src/ch/TSubTaskCopyMove.h
===================================================================
diff -u -rb7709acbab26fdb108b77d3e08d3872f54248af2 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TSubTaskCopyMove.h	(.../TSubTaskCopyMove.h)	(revision b7709acbab26fdb108b77d3e08d3872f54248af2)
+++ src/ch/TSubTaskCopyMove.h	(.../TSubTaskCopyMove.h)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -23,4 +23,34 @@
 #ifndef __TSUBTASKCOPYMOVE_H__
 #define __TSUBTASKCOPYMOVE_H__
 
+#include "TSubTaskBase.h"
+
+struct CUSTOM_COPY_PARAMS;
+class TAutoFileHandle;
+class CDataBuffer;
+
+class TSubTaskCopyMove : public TSubTaskBase
+{
+public:
+   TSubTaskCopyMove(TSubTaskContext& tSubTaskContext);
+
+   ESubOperationResult Exec();
+
+private:
+   bool GetMove(const CFileInfoPtr& spFileInfo);
+   int GetBufferIndex(const CFileInfoPtr& spFileInfo);
+
+   TSubTaskBase::ESubOperationResult CustomCopyFileFB(CUSTOM_COPY_PARAMS* pData);
+
+   TSubTaskBase::ESubOperationResult OpenSourceFileFB(TAutoFileHandle& hFile, const CFileInfoPtr& spSrcFileInfo, bool bNoBuffering);
+   TSubTaskBase::ESubOperationResult OpenDestinationFileFB(TAutoFileHandle& hFile, const chcore::TSmartPath& pathDstFile, bool bNoBuffering, const CFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated);
+   TSubTaskBase::ESubOperationResult OpenExistingDestinationFileFB(TAutoFileHandle& hFile, const chcore::TSmartPath& pathDstFilePath, bool bNoBuffering);
+
+   TSubTaskBase::ESubOperationResult SetFilePointerFB(HANDLE hFile, long long llDistance, const chcore::TSmartPath& pathFile, bool& bSkip);
+   TSubTaskBase::ESubOperationResult SetEndOfFileFB(HANDLE hFile, const chcore::TSmartPath& pathFile, bool& bSkip);
+
+   TSubTaskBase::ESubOperationResult ReadFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToRead, DWORD& rdwBytesRead, const chcore::TSmartPath& pathFile, bool& bSkip);
+   TSubTaskBase::ESubOperationResult WriteFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToWrite, DWORD& rdwBytesWritten, const chcore::TSmartPath& pathFile, bool& bSkip);
+};
+
 #endif
Index: src/ch/TSubTaskProgressInfo.cpp
===================================================================
diff -u -rae09c8430aad5eaa8225df84878b7d9050bdccd6 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TSubTaskProgressInfo.cpp	(.../TSubTaskProgressInfo.cpp)	(revision ae09c8430aad5eaa8225df84878b7d9050bdccd6)
+++ src/ch/TSubTaskProgressInfo.cpp	(.../TSubTaskProgressInfo.cpp)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -22,6 +22,7 @@
 // ============================================================================
 #include "stdafx.h"
 #include "TSubTaskProgressInfo.h"
+/*
 
 ///////////////////////////////////////////////////////////////////////////
 // TSubTaskProgressInfo
@@ -250,3 +251,4 @@
 		m_timeLast = timeCurrent;
 	}
 }
+*/
Index: src/ch/TSubTaskProgressInfo.h
===================================================================
diff -u -rae09c8430aad5eaa8225df84878b7d9050bdccd6 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TSubTaskProgressInfo.h	(.../TSubTaskProgressInfo.h)	(revision ae09c8430aad5eaa8225df84878b7d9050bdccd6)
+++ src/ch/TSubTaskProgressInfo.h	(.../TSubTaskProgressInfo.h)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -23,6 +23,7 @@
 #ifndef __TSUBTASKPROGRESSINFO_H__
 #define __TSUBTASKPROGRESSINFO_H__
 
+/*
 
 ///////////////////////////////////////////////////////////////////////////
 // TSubTaskProgressInfo
@@ -93,5 +94,6 @@
 };
 
 typedef boost::shared_ptr<TSubTaskProgressInfo> TSubTaskProgressInfoPtr;
+*/
 
 #endif // __TSUBTASKPROGRESSINFO_H__
\ No newline at end of file
Index: src/ch/TSubTaskScanDirectory.cpp
===================================================================
diff -u -rb7709acbab26fdb108b77d3e08d3872f54248af2 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TSubTaskScanDirectory.cpp	(.../TSubTaskScanDirectory.cpp)	(revision b7709acbab26fdb108b77d3e08d3872f54248af2)
+++ src/ch/TSubTaskScanDirectory.cpp	(.../TSubTaskScanDirectory.cpp)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -22,4 +22,249 @@
 // ============================================================================
 #include "stdafx.h"
 #include "TSubTaskScanDirectory.h"
+#include "TSubTaskContext.h"
+#include "TTaskConfiguration.h"
+#include "TTaskDefinition.h"
+#include "FeedbackHandler.h"
+#include "TLocalFilesystem.h"
+#include "..\libchcore\FeedbackHandlerBase.h"
+#include "TBasePathData.h"
+#include "TWorkerThreadController.h"
+#include "TTaskLocalStats.h"
 
+TSubTaskScanDirectories::TSubTaskScanDirectories(TSubTaskContext& rContext) :
+	TSubTaskBase(rContext)
+{
+}
+
+TSubTaskScanDirectories::~TSubTaskScanDirectories()
+{
+}
+
+TSubTaskScanDirectories::ESubOperationResult TSubTaskScanDirectories::Exec()
+{
+	// log
+	icpf::log_file& rLog = GetContext().GetLog();
+	CFileInfoArray& rFilesCache = GetContext().GetFilesCache();
+	TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+	chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+	const TBasePathDataContainer& rarrSourcePathsInfo = GetContext().GetTaskDefinition().GetSourcePaths();
+   TWorkerThreadController& rThreadController = GetContext().GetThreadController();
+
+	rLog.logi(_T("Searching for files..."));
+
+	// delete the content of rFilesCache
+	rFilesCache.Clear();
+
+	// read filtering options
+	CFiltersArray afFilters;
+	GetTaskPropValue<eTO_Filters>(rTaskDefinition.GetConfiguration(), afFilters);
+
+	// enter some data to rFilesCache
+	int iDestDrvNumber = 0;
+	TLocalFilesystem::GetDriveData(rTaskDefinition.GetDestinationPath(), &iDestDrvNumber, NULL);
+
+	bool bIgnoreDirs = GetTaskPropValue<eTO_IgnoreDirectories>(rTaskDefinition.GetConfiguration());
+	bool bForceDirectories = GetTaskPropValue<eTO_CreateDirectoriesRelativeToRoot>(rTaskDefinition.GetConfiguration());
+	bool bMove = rTaskDefinition.GetOperationType() == eOperation_Move;
+
+	// add everything
+	ictranslate::CFormat fmt;
+	bool bRetry = true;
+	bool bSkipInputPath = false;
+
+	size_t stSize = rTaskDefinition.GetSourcePathCount();
+	for(size_t stIndex = 0; stIndex < stSize ; stIndex++)
+	{
+		CFileInfoPtr spFileInfo;
+
+		bSkipInputPath = false;
+
+		spFileInfo.reset(new CFileInfo());
+		spFileInfo->SetClipboard(&rTaskDefinition.GetSourcePaths());
+
+		// try to get some info about the input path; let user know if the path does not exist.
+		do
+		{
+			bRetry = false;
+
+			// read attributes of src file/folder
+			bool bExists = spFileInfo->Create(rTaskDefinition.GetSourcePathAt(stIndex), stIndex);
+			if(!bExists)
+			{
+				FEEDBACK_FILEERROR ferr = { rTaskDefinition.GetSourcePathAt(stIndex).ToString(), NULL, eFastMoveError, ERROR_FILE_NOT_FOUND };
+				CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
+				switch(frResult)
+				{
+				case CFeedbackHandler::eResult_Cancel:
+					rFilesCache.Clear();
+					return eSubResult_CancelRequest;
+
+				case CFeedbackHandler::eResult_Retry:
+					bRetry = true;
+					break;
+
+				case CFeedbackHandler::eResult_Pause:
+					rFilesCache.Clear();
+					return eSubResult_PauseRequest;
+
+				case CFeedbackHandler::eResult_Skip:
+					bSkipInputPath = true;
+					break;		// just do nothing
+
+				default:
+					BOOST_ASSERT(FALSE);		// unknown result
+					THROW(_T("Unhandled case"), 0, 0, 0);
+				}
+			}
+		}
+		while(bRetry);
+
+		// if we have chosen to skip the input path then there's nothing to do
+		if(bSkipInputPath)
+			continue;
+
+		// log
+		fmt.SetFormat(_T("Adding file/folder (clipboard) : %path ..."));
+		fmt.SetParam(_t("%path"), rTaskDefinition.GetSourcePathAt(stIndex).ToString());
+		rLog.logi(fmt);
+
+		// found file/folder - check if the dest name has been generated
+		if(!rarrSourcePathsInfo.GetAt(stIndex)->IsDestinationPathSet())
+		{
+			// generate something - if dest folder == src folder - search for copy
+			if(rTaskDefinition.GetDestinationPath() == spFileInfo->GetFullFilePath().GetFileRoot())
+			{
+				chcore::TSmartPath pathSubst = FindFreeSubstituteName(spFileInfo->GetFullFilePath(), rTaskDefinition.GetDestinationPath());
+				rarrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(pathSubst);
+			}
+			else
+				rarrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(spFileInfo->GetFullFilePath().GetFileName());
+		}
+
+		// add if needed
+		if(spFileInfo->IsDirectory())
+		{
+			// add if folder's aren't ignored
+			if(!bIgnoreDirs && !bForceDirectories)
+			{
+				// add directory info; it is not to be filtered with afFilters
+				rFilesCache.AddFileInfo(spFileInfo);
+
+				// log
+				fmt.SetFormat(_T("Added folder %path"));
+				fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString());
+				rLog.logi(fmt);
+			}
+
+			// don't add folder contents when moving inside one disk boundary
+			if(bIgnoreDirs || !bMove || iDestDrvNumber == -1 || iDestDrvNumber != GetDriveNumber(spFileInfo) ||
+				TLocalFilesystem::PathExist(CalculateDestinationPath(spFileInfo, rTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1)) )
+			{
+				// log
+				fmt.SetFormat(_T("Recursing folder %path"));
+				fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString());
+				rLog.logi(fmt);
+
+				// no movefile possibility - use CustomCopyFileFB
+				rarrSourcePathsInfo.GetAt(stIndex)->SetMove(false);
+
+				ScanDirectory(spFileInfo->GetFullFilePath(), stIndex, true, !bIgnoreDirs || bForceDirectories, afFilters);
+			}
+
+			// check for kill need
+			if(rThreadController.KillRequested())
+			{
+				// log
+				rLog.logi(_T("Kill request while adding data to files array (RecurseDirectories)"));
+				rFilesCache.Clear();
+				return eSubResult_KillRequest;
+			}
+		}
+		else
+		{
+			if(bMove && iDestDrvNumber != -1 && iDestDrvNumber == GetDriveNumber(spFileInfo) &&
+            !TLocalFilesystem::PathExist(CalculateDestinationPath(spFileInfo, rTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1)) )
+			{
+				// if moving within one partition boundary set the file size to 0 so the overall size will
+				// be ok
+				spFileInfo->SetLength64(0);
+			}
+			else
+				rarrSourcePathsInfo.GetAt(stIndex)->SetMove(false);	// no MoveFile
+
+			// add file info if passes filters
+			if(afFilters.Match(spFileInfo))
+				rFilesCache.AddFileInfo(spFileInfo);
+
+			// log
+			fmt.SetFormat(_T("Added file %path"));
+			fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString());
+			rLog.logi(fmt);
+		}
+	}
+
+	// calc size of all files
+   GetContext().GetTaskLocalStats().SetTotalSize(rFilesCache.CalculateTotalSize());
+
+	// log
+	rLog.logi(_T("Searching for files finished"));
+
+	return eSubResult_Continue;
+}
+
+int TSubTaskScanDirectories::ScanDirectory(chcore::TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs, CFiltersArray& afFilters)
+{
+	CFileInfoArray& rFilesCache = GetContext().GetFilesCache();
+	TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+   TWorkerThreadController& rThreadController = GetContext().GetThreadController();
+
+	WIN32_FIND_DATA wfd;
+	chcore::TSmartPath pathCurrent;
+
+	pathCurrent = pathDirName + chcore::PathFromString(_T("*"));
+
+	// Iterate through dirs & files
+	HANDLE hFind = FindFirstFile(pathCurrent.ToString(), &wfd);
+	if(hFind != INVALID_HANDLE_VALUE)
+	{
+		do
+		{
+			if(!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+			{
+				CFileInfoPtr spFileInfo(boost::make_shared<CFileInfo>());
+				spFileInfo->SetClipboard(&rTaskDefinition.GetSourcePaths());	// this is the link table (CClipboardArray)
+
+				spFileInfo->Create(&wfd, pathDirName, stSrcIndex);
+				if(afFilters.Match(spFileInfo))
+					rFilesCache.AddFileInfo(spFileInfo);
+			}
+			else if(wfd.cFileName[0] != _T('.') || (wfd.cFileName[1] != _T('\0') && (wfd.cFileName[1] != _T('.') || wfd.cFileName[2] != _T('\0'))))
+			{
+				if(bIncludeDirs)
+				{
+					CFileInfoPtr spFileInfo(boost::make_shared<CFileInfo>());
+					spFileInfo->SetClipboard(&rTaskDefinition.GetSourcePaths());	// this is the link table (CClipboardArray)
+
+					// Add directory itself
+					spFileInfo->Create(&wfd, pathDirName, stSrcIndex);
+					rFilesCache.AddFileInfo(spFileInfo);
+				}
+				if(bRecurse)
+				{
+					pathCurrent = pathDirName + chcore::PathFromString(wfd.cFileName) + chcore::PathFromString(_T("\\"));
+					// Recurse Dirs
+					ScanDirectory(pathCurrent, stSrcIndex, bRecurse, bIncludeDirs, afFilters);
+				}
+			}
+
+			if(rThreadController.KillRequested())
+				break;
+		}
+		while(FindNextFile(hFind, &wfd));
+
+		FindClose(hFind);
+	}
+
+	return 0;
+}
Index: src/ch/TSubTaskScanDirectory.h
===================================================================
diff -u -rb7709acbab26fdb108b77d3e08d3872f54248af2 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TSubTaskScanDirectory.h	(.../TSubTaskScanDirectory.h)	(revision b7709acbab26fdb108b77d3e08d3872f54248af2)
+++ src/ch/TSubTaskScanDirectory.h	(.../TSubTaskScanDirectory.h)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -24,17 +24,22 @@
 #define __TSUBTASKSCANDIRECTORY_H__
 
 #include "TSubTaskBase.h"
+#include "../libchcore/TPath.h"
+#include "FileFilter.h"
 
 ///////////////////////////////////////////////////////////////////////////
 // TSubTaskScanDirectories
 
 class TSubTaskScanDirectories : public TSubTaskBase
 {
 public:
-	TSubTaskScanDirectories();
+	TSubTaskScanDirectories(TSubTaskContext& rContext);
 	virtual ~TSubTaskScanDirectories();
 
-	virtual void Exec();
+	virtual ESubOperationResult Exec();
+
+private:
+	int ScanDirectory(chcore::TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs, CFiltersArray& afFilters);
 };
 
 #endif
Index: src/ch/TTaskGlobalStats.cpp
===================================================================
diff -u
--- src/ch/TTaskGlobalStats.cpp	(revision 0)
+++ src/ch/TTaskGlobalStats.cpp	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -0,0 +1,118 @@
+// ============================================================================
+//  Copyright (C) 2001-2009 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.
+// ============================================================================
+/// @file  TTaskGlobalStats.cpp
+/// @date  2011/03/28
+/// @brief Contains declarations of classes responsible for maintaining task global stats.
+// ============================================================================
+#include "stdafx.h"
+#include "TTaskGlobalStats.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// TTasksGlobalStats members
+
+TTasksGlobalStats::TTasksGlobalStats() :
+   m_ullGlobalTotalSize(0),
+   m_ullGlobalProcessedSize(0),
+   m_stRunningTasks(0)
+{
+}
+
+TTasksGlobalStats::~TTasksGlobalStats()
+{
+}
+
+void TTasksGlobalStats::IncreaseGlobalTotalSize(unsigned long long ullModify)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_ullGlobalTotalSize += ullModify;
+}
+
+void TTasksGlobalStats::DecreaseGlobalTotalSize(unsigned long long ullModify)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_ullGlobalTotalSize -= ullModify;
+}
+
+unsigned long long TTasksGlobalStats::GetGlobalTotalSize() const
+{
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   return m_ullGlobalTotalSize;
+}
+
+void TTasksGlobalStats::IncreaseGlobalProcessedSize(unsigned long long ullModify)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_ullGlobalProcessedSize += ullModify;
+}
+
+void TTasksGlobalStats::DecreaseGlobalProcessedSize(unsigned long long ullModify)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_ullGlobalProcessedSize -= ullModify;
+}
+
+unsigned long long TTasksGlobalStats::GetGlobalProcessedSize() const
+{
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   return m_ullGlobalProcessedSize;
+}
+
+void TTasksGlobalStats::IncreaseGlobalProgressData(unsigned long long ullTasksPosition, unsigned long long ullTasksSize)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_ullGlobalTotalSize += ullTasksSize;
+   m_ullGlobalProcessedSize += ullTasksPosition;
+}
+
+void TTasksGlobalStats::DecreaseGlobalProgressData(unsigned long long ullTasksPosition, unsigned long long ullTasksSize)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_ullGlobalTotalSize -= ullTasksSize;
+   m_ullGlobalProcessedSize -= ullTasksPosition;
+}
+
+int TTasksGlobalStats::GetProgressPercents() const
+{
+   unsigned long long llPercent = 0;
+
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+
+   if(m_ullGlobalTotalSize != 0)
+      llPercent = m_ullGlobalProcessedSize * 100 / m_ullGlobalTotalSize;
+
+   return boost::numeric_cast<int>(llPercent);
+}
+
+void TTasksGlobalStats::IncreaseRunningTasks()
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   ++m_stRunningTasks;
+}
+
+void TTasksGlobalStats::DecreaseRunningTasks()
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   --m_stRunningTasks;
+}
+
+size_t TTasksGlobalStats::GetRunningTasksCount() const
+{
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   return m_stRunningTasks;
+}
Index: src/ch/TTaskGlobalStats.h
===================================================================
diff -u
--- src/ch/TTaskGlobalStats.h	(revision 0)
+++ src/ch/TTaskGlobalStats.h	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -0,0 +1,59 @@
+// ============================================================================
+//  Copyright (C) 2001-2009 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.
+// ============================================================================
+/// @file  TTaskGlobalStats.h
+/// @date  2011/03/28
+/// @brief Contains declarations of classes responsible for maintaining task global stats.
+// ============================================================================
+#ifndef __TTASKGLOBALSTATS_H__
+#define __TTASKGLOBALSTATS_H__
+
+///////////////////////////////////////////////////////////////////////////
+// TTasksGlobalStats
+class TTasksGlobalStats
+{
+public:
+   TTasksGlobalStats();
+   ~TTasksGlobalStats();
+
+   void IncreaseGlobalTotalSize(unsigned long long ullModify);
+   void DecreaseGlobalTotalSize(unsigned long long ullModify);
+   unsigned long long GetGlobalTotalSize() const;
+
+   void IncreaseGlobalProcessedSize(unsigned long long ullModify);
+   void DecreaseGlobalProcessedSize(unsigned long long ullModify);
+   unsigned long long GetGlobalProcessedSize() const;
+
+   void IncreaseGlobalProgressData(unsigned long long ullTasksPosition, unsigned long long ullTasksSize);
+   void DecreaseGlobalProgressData(unsigned long long ullTasksPosition, unsigned long long ullTasksSize);
+
+   int GetProgressPercents() const;
+
+   void IncreaseRunningTasks();
+   void DecreaseRunningTasks();
+   size_t GetRunningTasksCount() const;
+
+private:
+   volatile unsigned long long m_ullGlobalTotalSize;
+   volatile unsigned long long m_ullGlobalProcessedSize;
+
+   volatile size_t m_stRunningTasks;		// count of current operations
+   mutable boost::shared_mutex m_lock;
+};
+
+#endif
Index: src/ch/TTaskLocalStats.cpp
===================================================================
diff -u
--- src/ch/TTaskLocalStats.cpp	(revision 0)
+++ src/ch/TTaskLocalStats.cpp	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -0,0 +1,257 @@
+// ============================================================================
+//  Copyright (C) 2001-2011 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.
+// ============================================================================
+/// @file  TTaskLocalStats.cpp
+/// @date  2011/03/28
+/// @brief Contains implementation of classes responsible for maintaining local task stats.
+// ============================================================================
+#include "stdafx.h"
+#include "TTaskLocalStats.h"
+#include "TTaskGlobalStats.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// TTasksGlobalStats members
+TTaskLocalStats::TTaskLocalStats() :
+   m_prtGlobalStats(NULL),
+   m_ullProcessedSize(0),
+   m_ullTotalSize(0),
+   m_bTaskIsRunning(false),
+   m_timeElapsed(0),
+   m_timeLast(-1),
+   m_iCurrentBufferIndex(0)
+{
+}
+
+TTaskLocalStats::~TTaskLocalStats()
+{
+   DisconnectGlobalStats();
+}
+
+void TTaskLocalStats::ConnectGlobalStats(TTasksGlobalStats& rtGlobalStats)
+{
+   DisconnectGlobalStats();
+
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+
+   m_prtGlobalStats = &rtGlobalStats;
+   m_prtGlobalStats->IncreaseGlobalProgressData(m_ullProcessedSize, m_ullTotalSize);
+   if(m_bTaskIsRunning)
+      m_prtGlobalStats->IncreaseRunningTasks();
+}
+
+void TTaskLocalStats::DisconnectGlobalStats()
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+
+   if(m_prtGlobalStats)
+   {
+      m_prtGlobalStats->DecreaseGlobalProgressData(m_ullProcessedSize, m_ullTotalSize);
+      if(m_bTaskIsRunning)
+         m_prtGlobalStats->DecreaseRunningTasks();
+      m_prtGlobalStats = NULL;
+   }
+}
+
+void TTaskLocalStats::IncreaseProcessedSize(unsigned long long ullAdd)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+
+   if(m_prtGlobalStats)
+      m_prtGlobalStats->IncreaseGlobalProcessedSize(ullAdd);
+
+   m_ullProcessedSize += ullAdd;
+}
+
+void TTaskLocalStats::DecreaseProcessedSize(unsigned long long ullSub)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   if(m_prtGlobalStats)
+      m_prtGlobalStats->DecreaseGlobalProcessedSize(ullSub);
+
+   m_ullProcessedSize -= ullSub;
+}
+
+void TTaskLocalStats::SetProcessedSize(unsigned long long ullSet)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+
+   if(m_prtGlobalStats)
+   {
+      if(ullSet < m_ullProcessedSize)
+         m_prtGlobalStats->DecreaseGlobalProcessedSize(m_ullProcessedSize - ullSet);
+      else
+         m_prtGlobalStats->IncreaseGlobalProcessedSize(ullSet - m_ullProcessedSize);
+   }
+
+   m_ullProcessedSize = ullSet;
+}
+
+unsigned long long TTaskLocalStats::GetProcessedSize() const
+{
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   return m_ullProcessedSize;
+}
+
+unsigned long long TTaskLocalStats::GetUnProcessedSize() const
+{
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   return m_ullTotalSize - m_ullProcessedSize;
+}
+
+void TTaskLocalStats::IncreaseTotalSize(unsigned long long ullAdd)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+
+   if(m_prtGlobalStats)
+      m_prtGlobalStats->IncreaseGlobalTotalSize(ullAdd);
+   m_ullTotalSize += ullAdd;
+}
+
+void TTaskLocalStats::DecreaseTotalSize(unsigned long long ullSub)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+
+   if(m_prtGlobalStats)
+      m_prtGlobalStats->DecreaseGlobalTotalSize(ullSub);
+
+   m_ullTotalSize -= ullSub;
+}
+
+void TTaskLocalStats::SetTotalSize(unsigned long long ullSet)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+
+   if(m_prtGlobalStats)
+   {
+      if(ullSet < m_ullTotalSize)
+         m_prtGlobalStats->DecreaseGlobalTotalSize(m_ullTotalSize - ullSet);
+      else
+         m_prtGlobalStats->IncreaseGlobalTotalSize(ullSet - m_ullTotalSize);
+   }
+
+   m_ullTotalSize = ullSet;
+}
+
+unsigned long long TTaskLocalStats::GetTotalSize() const
+{
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   return m_ullTotalSize;
+}
+
+int TTaskLocalStats::GetProgressInPercent() const
+{
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+
+   unsigned long long ullPercent = 0;
+
+   if(m_ullTotalSize != 0)
+      ullPercent = m_ullProcessedSize * 100 / m_ullTotalSize;
+
+   return boost::numeric_cast<int>(ullPercent);
+}
+
+void TTaskLocalStats::MarkTaskAsRunning()
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   if(!m_bTaskIsRunning)
+   {
+      if(m_prtGlobalStats)
+         m_prtGlobalStats->IncreaseRunningTasks();
+      m_bTaskIsRunning = true;
+   }
+}
+
+void TTaskLocalStats::MarkTaskAsNotRunning()
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   if(m_bTaskIsRunning)
+   {
+      if(m_prtGlobalStats)
+         m_prtGlobalStats->DecreaseRunningTasks();
+      m_bTaskIsRunning = false;
+   }
+}
+
+bool TTaskLocalStats::IsRunning() const
+{
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   return m_bTaskIsRunning;
+}
+
+void TTaskLocalStats::SetTimeElapsed(time_t timeElapsed)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_timeElapsed = timeElapsed;
+}
+
+time_t TTaskLocalStats::GetTimeElapsed()
+{
+   UpdateTime();
+
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   return m_timeElapsed;
+}
+
+void TTaskLocalStats::EnableTimeTracking()
+{
+   boost::upgrade_lock<boost::shared_mutex> lock(m_lock);
+   if(m_timeLast == -1)
+   {
+      boost::upgrade_to_unique_lock<boost::shared_mutex> lock_upgraded(lock);
+      m_timeLast = time(NULL);
+   }
+}
+
+void TTaskLocalStats::DisableTimeTracking()
+{
+   UpdateTime();
+
+   boost::upgrade_lock<boost::shared_mutex> lock(m_lock);
+   if(m_timeLast != -1)
+   {
+      boost::upgrade_to_unique_lock<boost::shared_mutex> lock_upgraded(lock);
+      m_timeLast = -1;
+   }
+}
+
+void TTaskLocalStats::UpdateTime()
+{
+   boost::upgrade_lock<boost::shared_mutex> lock(m_lock);
+   if(m_timeLast != -1)
+   {
+      time_t timeCurrent = time(NULL);
+
+      boost::upgrade_to_unique_lock<boost::shared_mutex> lock_upgraded(lock);
+      m_timeElapsed += timeCurrent - m_timeLast;
+      m_timeLast = timeCurrent;
+   }
+}
+
+void TTaskLocalStats::SetCurrentBufferIndex(int iCurrentIndex)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   m_iCurrentBufferIndex = iCurrentIndex;
+}
+
+int TTaskLocalStats::GetCurrentBufferIndex() const
+{
+   // locking possibly not needed, not entirely sure now
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+   int iResult = m_iCurrentBufferIndex;
+   return iResult;
+}
Index: src/ch/TTaskLocalStats.h
===================================================================
diff -u
--- src/ch/TTaskLocalStats.h	(revision 0)
+++ src/ch/TTaskLocalStats.h	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -0,0 +1,80 @@
+// ============================================================================
+//  Copyright (C) 2001-2011 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.
+// ============================================================================
+/// @file  TTaskLocalStats.h
+/// @date  2011/03/28
+/// @brief Contains classes responsible for maintaining local task stats.
+// ============================================================================
+#ifndef __TTASKLOCALSTATS_H__
+#define __TTASKLOCALSTATS_H__
+
+class TTasksGlobalStats;
+
+class TTaskLocalStats
+{
+public:
+   TTaskLocalStats();
+   ~TTaskLocalStats();
+
+   void ConnectGlobalStats(TTasksGlobalStats& rtGlobalStats);
+   void DisconnectGlobalStats();
+
+   void IncreaseProcessedSize(unsigned long long ullAdd);
+   void DecreaseProcessedSize(unsigned long long ullSub);
+   void SetProcessedSize(unsigned long long ullSet);
+   unsigned long long GetProcessedSize() const;
+   unsigned long long GetUnProcessedSize() const;
+
+   void IncreaseTotalSize(unsigned long long ullAdd);
+   void DecreaseTotalSize(unsigned long long ullSub);
+   void SetTotalSize(unsigned long long ullSet);
+   unsigned long long GetTotalSize() const;
+
+   int GetProgressInPercent() const;
+
+   void MarkTaskAsRunning();
+   void MarkTaskAsNotRunning();
+   bool IsRunning() const;
+
+   void SetTimeElapsed(time_t timeElapsed);
+   time_t GetTimeElapsed();
+
+   void EnableTimeTracking();
+   void DisableTimeTracking();
+   void UpdateTime();
+
+   void SetCurrentBufferIndex(int iCurrentIndex);
+   int GetCurrentBufferIndex() const;
+
+private:
+   volatile unsigned long long m_ullProcessedSize;
+   volatile unsigned long long m_ullTotalSize;
+
+   volatile bool m_bTaskIsRunning;
+
+   // time
+   volatile time_t m_timeElapsed;
+   volatile time_t m_timeLast;
+
+   volatile int m_iCurrentBufferIndex;
+
+   mutable boost::shared_mutex m_lock;
+   TTasksGlobalStats* m_prtGlobalStats;
+};
+
+#endif
Index: src/ch/TTaskProgressInfo.cpp
===================================================================
diff -u -rae09c8430aad5eaa8225df84878b7d9050bdccd6 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TTaskProgressInfo.cpp	(.../TTaskProgressInfo.cpp)	(revision ae09c8430aad5eaa8225df84878b7d9050bdccd6)
+++ src/ch/TTaskProgressInfo.cpp	(.../TTaskProgressInfo.cpp)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -22,6 +22,7 @@
 // ============================================================================
 #include "stdafx.h"
 #include "TTaskProgressInfo.h"
+/*
 
 ///////////////////////////////////////////////////////////////////////////
 // TProgressSnapshot
@@ -123,3 +124,4 @@
 	++m_stSubOperationIndex;
 }
 
+*/
Index: src/ch/TTaskProgressInfo.h
===================================================================
diff -u -rae09c8430aad5eaa8225df84878b7d9050bdccd6 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/TTaskProgressInfo.h	(.../TTaskProgressInfo.h)	(revision ae09c8430aad5eaa8225df84878b7d9050bdccd6)
+++ src/ch/TTaskProgressInfo.h	(.../TTaskProgressInfo.h)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -22,6 +22,7 @@
 // ============================================================================
 #ifndef __TTASKPROGRESSINFO_H__
 #define __TTASKPROGRESSINFO_H__
+/*
 
 #include "TTaskOperationPlan.h"
 #include "TSubTaskProgressInfo.h"
@@ -83,10 +84,10 @@
 
 	// serialization
 	template<class Archive>
-	void load(Archive& ar, unsigned int /*uiVersion*/);
+	void load(Archive& ar, unsigned int / *uiVersion* /);
 
 	template<class Archive>
-	void save(Archive& ar, unsigned int /*uiVersion*/) const;
+	void save(Archive& ar, unsigned int / *uiVersion* /) const;
 
 	BOOST_SERIALIZATION_SPLIT_MEMBER();
 
@@ -99,7 +100,7 @@
 };
 
 template<class Archive>
-void TTaskProgressInfo::load(Archive& ar, unsigned int /*uiVersion*/)
+void TTaskProgressInfo::load(Archive& ar, unsigned int / *uiVersion* /)
 {
 	boost::unique_lock<boost::shared_mutex> lock(m_lock);
 
@@ -113,12 +114,12 @@
 }
 
 template<class Archive>
-void TTaskProgressInfo::save(Archive& ar, unsigned int /*uiVersion*/) const
+void TTaskProgressInfo::save(Archive& ar, unsigned int / *uiVersion* /) const
 {
 	boost::shared_lock<boost::shared_mutex> lock(m_lock);
 
 	ar << m_vProgressInfo;
 	ar << m_stSubOperationIndex;
-}
+}*/
 
 #endif // __TTASKPROGRESSINFO_H__
\ No newline at end of file
Index: src/ch/ch.vc90.vcproj
===================================================================
diff -u -r3cd8d4a64a63e4fb32d7dc96e46789c713698435 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/ch.vc90.vcproj	(.../ch.vc90.vcproj)	(revision 3cd8d4a64a63e4fb32d7dc96e46789c713698435)
+++ src/ch/ch.vc90.vcproj	(.../ch.vc90.vcproj)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -479,54 +479,30 @@
 					>
 				</File>
 				<File
-					RelativePath=".\TSubTaskBase.cpp"
+					RelativePath=".\TBasicProgressInfo.cpp"
 					>
 				</File>
 				<File
-					RelativePath=".\TSubTaskBase.h"
+					RelativePath=".\TBasicProgressInfo.h"
 					>
 				</File>
 				<File
-					RelativePath=".\TSubTaskContext.cpp"
+					RelativePath=".\TLocalFilesystem.cpp"
 					>
 				</File>
 				<File
-					RelativePath=".\TSubTaskContext.h"
+					RelativePath=".\TLocalFilesystem.h"
 					>
 				</File>
 				<File
-					RelativePath=".\TSubTaskCopyMove.cpp"
+					RelativePath=".\TSubTaskContext.cpp"
 					>
 				</File>
 				<File
-					RelativePath=".\TSubTaskCopyMove.h"
+					RelativePath=".\TSubTaskContext.h"
 					>
 				</File>
 				<File
-					RelativePath=".\TSubTaskDelete.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\TSubTaskDelete.h"
-					>
-				</File>
-				<File
-					RelativePath=".\TSubTaskProgressInfo.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\TSubTaskProgressInfo.h"
-					>
-				</File>
-				<File
-					RelativePath=".\TSubTaskScanDirectory.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\TSubTaskScanDirectory.h"
-					>
-				</File>
-				<File
 					RelativePath=".\TTaskConfigTracker.cpp"
 					>
 				</File>
@@ -555,21 +531,89 @@
 					>
 				</File>
 				<File
-					RelativePath=".\TTaskProgressInfo.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\TTaskProgressInfo.h"
-					>
-				</File>
-				<File
 					RelativePath=".\TWorkerThreadController.cpp"
 					>
 				</File>
 				<File
 					RelativePath=".\TWorkerThreadController.h"
 					>
 				</File>
+				<Filter
+					Name="NewProgressTracking"
+					>
+					<File
+						RelativePath=".\TSubTaskProgressInfo.cpp"
+						>
+					</File>
+					<File
+						RelativePath=".\TSubTaskProgressInfo.h"
+						>
+					</File>
+					<File
+						RelativePath=".\TTaskProgressInfo.cpp"
+						>
+					</File>
+					<File
+						RelativePath=".\TTaskProgressInfo.h"
+						>
+					</File>
+				</Filter>
+				<Filter
+					Name="SubTasks"
+					>
+					<File
+						RelativePath=".\TSubTaskBase.cpp"
+						>
+					</File>
+					<File
+						RelativePath=".\TSubTaskBase.h"
+						>
+					</File>
+					<File
+						RelativePath=".\TSubTaskCopyMove.cpp"
+						>
+					</File>
+					<File
+						RelativePath=".\TSubTaskCopyMove.h"
+						>
+					</File>
+					<File
+						RelativePath=".\TSubTaskDelete.cpp"
+						>
+					</File>
+					<File
+						RelativePath=".\TSubTaskDelete.h"
+						>
+					</File>
+					<File
+						RelativePath=".\TSubTaskScanDirectory.cpp"
+						>
+					</File>
+					<File
+						RelativePath=".\TSubTaskScanDirectory.h"
+						>
+					</File>
+				</Filter>
+				<Filter
+					Name="OldProgressTracking"
+					>
+					<File
+						RelativePath=".\TTaskGlobalStats.cpp"
+						>
+					</File>
+					<File
+						RelativePath=".\TTaskGlobalStats.h"
+						>
+					</File>
+					<File
+						RelativePath=".\TTaskLocalStats.cpp"
+						>
+					</File>
+					<File
+						RelativePath=".\TTaskLocalStats.h"
+						>
+					</File>
+				</Filter>
 			</Filter>
 			<Filter
 				Name="Tools"
Index: src/ch/task.cpp
===================================================================
diff -u -rb684bec49aaaea4b89ab2e599497f4085d8698a3 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/task.cpp	(.../task.cpp)	(revision b684bec49aaaea4b89ab2e599497f4085d8698a3)
+++ src/ch/task.cpp	(.../task.cpp)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -32,388 +32,10 @@
 #include "TSubTaskContext.h"
 
 #include "Device IO.h"
+#include "TLocalFilesystem.h"
+#include "TSubTaskScanDirectory.h"
+#include "TSubTaskCopyMove.h"
 
-// assume max sectors of 4kB (for rounding)
-#define MAXSECTORSIZE			4096
-
-////////////////////////////////////////////////////////////////////////////////
-// TTasksGlobalStats members
-
-TTasksGlobalStats::TTasksGlobalStats() :
-	m_ullGlobalTotalSize(0),
-	m_ullGlobalProcessedSize(0),
-	m_stRunningTasks(0)
-{
-}
-
-TTasksGlobalStats::~TTasksGlobalStats()
-{
-}
-
-void TTasksGlobalStats::IncreaseGlobalTotalSize(unsigned long long ullModify)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_ullGlobalTotalSize += ullModify;
-}
-
-void TTasksGlobalStats::DecreaseGlobalTotalSize(unsigned long long ullModify)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_ullGlobalTotalSize -= ullModify;
-}
-
-unsigned long long TTasksGlobalStats::GetGlobalTotalSize() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_ullGlobalTotalSize;
-}
-
-void TTasksGlobalStats::IncreaseGlobalProcessedSize(unsigned long long ullModify)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_ullGlobalProcessedSize += ullModify;
-}
-
-void TTasksGlobalStats::DecreaseGlobalProcessedSize(unsigned long long ullModify)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_ullGlobalProcessedSize -= ullModify;
-}
-
-unsigned long long TTasksGlobalStats::GetGlobalProcessedSize() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_ullGlobalProcessedSize;
-}
-
-void TTasksGlobalStats::IncreaseGlobalProgressData(unsigned long long ullTasksPosition, unsigned long long ullTasksSize)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_ullGlobalTotalSize += ullTasksSize;
-	m_ullGlobalProcessedSize += ullTasksPosition;
-}
-
-void TTasksGlobalStats::DecreaseGlobalProgressData(unsigned long long ullTasksPosition, unsigned long long ullTasksSize)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_ullGlobalTotalSize -= ullTasksSize;
-	m_ullGlobalProcessedSize -= ullTasksPosition;
-}
-
-int TTasksGlobalStats::GetProgressPercents() const
-{
-	unsigned long long llPercent = 0;
-
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-
-	if(m_ullGlobalTotalSize != 0)
-		llPercent = m_ullGlobalProcessedSize * 100 / m_ullGlobalTotalSize;
-
-	return boost::numeric_cast<int>(llPercent);
-}
-
-void TTasksGlobalStats::IncreaseRunningTasks()
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	++m_stRunningTasks;
-}
-
-void TTasksGlobalStats::DecreaseRunningTasks()
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	--m_stRunningTasks;
-}
-
-size_t TTasksGlobalStats::GetRunningTasksCount() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_stRunningTasks;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TTasksGlobalStats members
-TTaskLocalStats::TTaskLocalStats() :
-	m_prtGlobalStats(NULL),
-	m_ullProcessedSize(0),
-	m_ullTotalSize(0),
-	m_bTaskIsRunning(false),
-	m_timeElapsed(0),
-	m_timeLast(-1)
-{
-}
-
-TTaskLocalStats::~TTaskLocalStats()
-{
-	DisconnectGlobalStats();
-}
-
-void TTaskLocalStats::ConnectGlobalStats(TTasksGlobalStats& rtGlobalStats)
-{
-	DisconnectGlobalStats();
-
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-
-	m_prtGlobalStats = &rtGlobalStats;
-	m_prtGlobalStats->IncreaseGlobalProgressData(m_ullProcessedSize, m_ullTotalSize);
-	if(m_bTaskIsRunning)
-		m_prtGlobalStats->IncreaseRunningTasks();
-}
-
-void TTaskLocalStats::DisconnectGlobalStats()
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-
-	if(m_prtGlobalStats)
-	{
-		m_prtGlobalStats->DecreaseGlobalProgressData(m_ullProcessedSize, m_ullTotalSize);
-		if(m_bTaskIsRunning)
-			m_prtGlobalStats->DecreaseRunningTasks();
-		m_prtGlobalStats = NULL;
-	}
-}
-
-void TTaskLocalStats::IncreaseProcessedSize(unsigned long long ullAdd)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-
-	if(m_prtGlobalStats)
-		m_prtGlobalStats->IncreaseGlobalProcessedSize(ullAdd);
-
-	m_ullProcessedSize += ullAdd;
-}
-
-void TTaskLocalStats::DecreaseProcessedSize(unsigned long long ullSub)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	if(m_prtGlobalStats)
-		m_prtGlobalStats->DecreaseGlobalProcessedSize(ullSub);
-
-	m_ullProcessedSize -= ullSub;
-}
-
-void TTaskLocalStats::SetProcessedSize(unsigned long long ullSet)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-
-	if(m_prtGlobalStats)
-	{
-		if(ullSet < m_ullProcessedSize)
-			m_prtGlobalStats->DecreaseGlobalProcessedSize(m_ullProcessedSize - ullSet);
-		else
-			m_prtGlobalStats->IncreaseGlobalProcessedSize(ullSet - m_ullProcessedSize);
-	}
-
-	m_ullProcessedSize = ullSet;
-}
-
-unsigned long long TTaskLocalStats::GetProcessedSize() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_ullProcessedSize;
-}
-
-unsigned long long TTaskLocalStats::GetUnProcessedSize() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_ullTotalSize - m_ullProcessedSize;
-}
-
-void TTaskLocalStats::IncreaseTotalSize(unsigned long long ullAdd)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-
-	if(m_prtGlobalStats)
-		m_prtGlobalStats->IncreaseGlobalTotalSize(ullAdd);
-	m_ullTotalSize += ullAdd;
-}
-
-void TTaskLocalStats::DecreaseTotalSize(unsigned long long ullSub)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-
-	if(m_prtGlobalStats)
-		m_prtGlobalStats->DecreaseGlobalTotalSize(ullSub);
-
-	m_ullTotalSize -= ullSub;
-}
-
-void TTaskLocalStats::SetTotalSize(unsigned long long ullSet)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-
-	if(m_prtGlobalStats)
-	{
-		if(ullSet < m_ullTotalSize)
-			m_prtGlobalStats->DecreaseGlobalTotalSize(m_ullTotalSize - ullSet);
-		else
-			m_prtGlobalStats->IncreaseGlobalTotalSize(ullSet - m_ullTotalSize);
-	}
-
-	m_ullTotalSize = ullSet;
-}
-
-unsigned long long TTaskLocalStats::GetTotalSize() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_ullTotalSize;
-}
-
-int TTaskLocalStats::GetProgressInPercent() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-
-	unsigned long long ullPercent = 0;
-
-	if(m_ullTotalSize != 0)
-		ullPercent = m_ullProcessedSize * 100 / m_ullTotalSize;
-
-	return boost::numeric_cast<int>(ullPercent);
-}
-
-void TTaskLocalStats::MarkTaskAsRunning()
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	if(!m_bTaskIsRunning)
-	{
-		if(m_prtGlobalStats)
-			m_prtGlobalStats->IncreaseRunningTasks();
-		m_bTaskIsRunning = true;
-	}
-}
-
-void TTaskLocalStats::MarkTaskAsNotRunning()
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	if(m_bTaskIsRunning)
-	{
-		if(m_prtGlobalStats)
-			m_prtGlobalStats->DecreaseRunningTasks();
-		m_bTaskIsRunning = false;
-	}
-}
-
-bool TTaskLocalStats::IsRunning() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_bTaskIsRunning;
-}
-
-void TTaskLocalStats::SetTimeElapsed(time_t timeElapsed)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_timeElapsed = timeElapsed;
-}
-
-time_t TTaskLocalStats::GetTimeElapsed()
-{
-	UpdateTime();
-
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_timeElapsed;
-}
-
-void TTaskLocalStats::EnableTimeTracking()
-{
-	boost::upgrade_lock<boost::shared_mutex> lock(m_lock);
-	if(m_timeLast == -1)
-	{
-		boost::upgrade_to_unique_lock<boost::shared_mutex> lock_upgraded(lock);
-		m_timeLast = time(NULL);
-	}
-}
-
-void TTaskLocalStats::DisableTimeTracking()
-{
-	UpdateTime();
-
-	boost::upgrade_lock<boost::shared_mutex> lock(m_lock);
-	if(m_timeLast != -1)
-	{
-		boost::upgrade_to_unique_lock<boost::shared_mutex> lock_upgraded(lock);
-		m_timeLast = -1;
-	}
-}
-
-void TTaskLocalStats::UpdateTime()
-{
-	boost::upgrade_lock<boost::shared_mutex> lock(m_lock);
-	if(m_timeLast != -1)
-	{
-		time_t timeCurrent = time(NULL);
-
-		boost::upgrade_to_unique_lock<boost::shared_mutex> lock_upgraded(lock);
-		m_timeElapsed += timeCurrent - m_timeLast;
-		m_timeLast = timeCurrent;
-	}
-}
-
-TTaskBasicProgressInfo::TTaskBasicProgressInfo() :
-	m_stCurrentIndex(0),
-	m_ullCurrentFileProcessedSize(0),
-	m_stSubOperationIndex(0)
-{
-}
-
-TTaskBasicProgressInfo::~TTaskBasicProgressInfo()
-{
-}
-
-void TTaskBasicProgressInfo::SetCurrentIndex(size_t stIndex)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_stCurrentIndex = stIndex;
-	m_ullCurrentFileProcessedSize = 0;
-}
-
-void TTaskBasicProgressInfo::IncreaseCurrentIndex()
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	++m_stCurrentIndex;
-	m_ullCurrentFileProcessedSize = 0;
-}
-
-size_t TTaskBasicProgressInfo::GetCurrentIndex() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_stCurrentIndex;
-}
-
-void TTaskBasicProgressInfo::SetCurrentFileProcessedSize(unsigned long long ullSize)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_ullCurrentFileProcessedSize = ullSize;
-}
-
-unsigned long long TTaskBasicProgressInfo::GetCurrentFileProcessedSize() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_ullCurrentFileProcessedSize;
-}
-
-void TTaskBasicProgressInfo::IncreaseCurrentFileProcessedSize(unsigned long long ullSizeToAdd)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_ullCurrentFileProcessedSize += ullSizeToAdd;
-}
-
-void TTaskBasicProgressInfo::SetSubOperationIndex(size_t stSubOperationIndex)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_stSubOperationIndex = stSubOperationIndex;
-}
-
-size_t TTaskBasicProgressInfo::GetSubOperationIndex() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_stSubOperationIndex;
-}
-
-void TTaskBasicProgressInfo::IncreaseSubOperationIndex()
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	++m_stSubOperationIndex;
-}
-
 ////////////////////////////////////////////////////////////////////////////
 // CTask members
 CTask::CTask(chcore::IFeedbackHandler* piFeedbackHandler, size_t stSessionUniqueID) :
@@ -457,59 +79,6 @@
 	m_localStats.DisconnectGlobalStats();
 }
 
-// m_files
-int CTask::ScanDirectory(chcore::TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs)
-{
-	WIN32_FIND_DATA wfd;
-	chcore::TSmartPath pathCurrent;
-
-	pathCurrent = pathDirName + chcore::PathFromString(_T("*"));
-
-	// Iterate through dirs & files
-	HANDLE hFind = FindFirstFile(pathCurrent.ToString(), &wfd);
-	if(hFind != INVALID_HANDLE_VALUE)
-	{
-		do
-		{
-			if(!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
-			{
-				CFileInfoPtr spFileInfo(boost::make_shared<CFileInfo>());
-				spFileInfo->SetClipboard(&m_tTaskDefinition.GetSourcePaths());	// this is the link table (CClipboardArray)
-				
-				spFileInfo->Create(&wfd, pathDirName, stSrcIndex);
-				if(m_afFilters.Match(spFileInfo))
-					m_files.AddFileInfo(spFileInfo);
-			}
-			else if(wfd.cFileName[0] != _T('.') || (wfd.cFileName[1] != _T('\0') && (wfd.cFileName[1] != _T('.') || wfd.cFileName[2] != _T('\0'))))
-			{
-				if(bIncludeDirs)
-				{
-					CFileInfoPtr spFileInfo(boost::make_shared<CFileInfo>());
-					spFileInfo->SetClipboard(&m_tTaskDefinition.GetSourcePaths());	// this is the link table (CClipboardArray)
-
-					// Add directory itself
-					spFileInfo->Create(&wfd, pathDirName, stSrcIndex);
-					m_files.AddFileInfo(spFileInfo);
-				}
-				if(bRecurse)
-				{
-					pathCurrent = pathDirName + chcore::PathFromString(wfd.cFileName) + chcore::PathFromString(_T("\\"));
-					// Recurse Dirs
-					ScanDirectory(pathCurrent, stSrcIndex, bRecurse, bIncludeDirs);
-				}
-			}
-
-			if(m_workerThread.KillRequested())
-				break;
-		}
-		while(FindNextFile(hFind, &wfd));
-		
-		FindClose(hFind);
-	}
-
-	return 0;
-}
-
 void CTask::SetTaskState(ETaskCurrentState eTaskState)
 {
 	// NOTE: we could check some transition rules here
@@ -547,7 +116,7 @@
 
 int CTask::GetCurrentBufferIndex()
 {
-	return GetBufferIndex(m_files.GetAt(m_tTaskBasicProgressInfo.GetCurrentIndex()));
+   return m_localStats.GetCurrentBufferIndex();
 }
 
 // thread
@@ -556,20 +125,6 @@
 	SetTaskPropValue<eTO_ThreadPriority>(m_tTaskDefinition.GetConfiguration(), nPriority);
 }
 
-void CTask::CalculateTotalSize()
-{
-	unsigned long long ullTotalSize = 0;
-
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	size_t nSize = m_files.GetSize();
-	for(size_t i = 0; i < nSize; i++)
-	{
-		ullTotalSize += m_files.GetAt(i)->GetLength64();
-	}
-
-	m_localStats.SetTotalSize(ullTotalSize);
-}
-
 void CTask::CalculateProcessedSize()
 {
 	boost::shared_lock<boost::shared_mutex> lock(m_lock);
@@ -841,7 +396,7 @@
 	pData->m_bCreateEmptyFiles = GetTaskPropValue<eTO_CreateEmptyFiles>(m_tTaskDefinition.GetConfiguration());
 
 	if(m_files.GetSize() > 0)
-		pData->m_iCurrentBufferIndex = GetTaskPropValue<eTO_UseOnlyDefaultBuffer>(m_tTaskDefinition.GetConfiguration()) ? BI_DEFAULT : GetBufferIndex(m_files.GetAt((stCurrentIndex < m_files.GetSize()) ? stCurrentIndex : 0));
+		pData->m_iCurrentBufferIndex = m_localStats.GetCurrentBufferIndex();
 	else
 		pData->m_iCurrentBufferIndex = BI_DEFAULT;
 
@@ -977,31 +532,10 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
-bool CTask::SetFileDirectoryTime(LPCTSTR lpszName, const CFileInfoPtr& spFileInfo)
-{
-	TAutoFileHandle hFile = CreateFile(lpszName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | (spFileInfo->IsDirectory() ? FILE_FLAG_BACKUP_SEMANTICS : 0), NULL);
-	if(hFile == INVALID_HANDLE_VALUE)
-		return false;
 
-	BOOL bResult = (!SetFileTime(hFile, &spFileInfo->GetCreationTime(), &spFileInfo->GetLastAccessTime(), &spFileInfo->GetLastWriteTime()));
-
-	if(!hFile.Close())
-		return false;
-
-	return bResult != 0;
-}
-
 void CTask::CalculateTotalSizeNL()
 {
-	unsigned long long ullTotalSize = 0;
-
-	size_t nSize = m_files.GetSize();
-	for(size_t stIndex = 0; stIndex < nSize; stIndex++)
-	{
-		ullTotalSize += m_files.GetAt(stIndex)->GetLength64();
-	}
-
-	m_localStats.SetTotalSize(ullTotalSize);
+	m_localStats.SetTotalSize(m_files.CalculateTotalSize());
 }
 
 void CTask::SetForceFlagNL(bool bFlag)
@@ -1024,176 +558,8 @@
 	return m_bContinue;
 }
 
-// searching for files
-CTask::ESubOperationResult CTask::RecurseDirectories()
-{
-	// log
-	m_log.logi(_T("Searching for files..."));
-
-	// delete the content of m_files
-	m_files.Clear();
-
-	// read filtering options
-	GetTaskPropValue<eTO_Filters>(m_tTaskDefinition.GetConfiguration(), m_afFilters);
-
-	// enter some data to m_files
-	int iDestDrvNumber = 0;
-	GetDriveData(m_tTaskDefinition.GetDestinationPath(), &iDestDrvNumber, NULL);
-
-	bool bIgnoreDirs = GetTaskPropValue<eTO_IgnoreDirectories>(m_tTaskDefinition.GetConfiguration());
-	bool bForceDirectories = GetTaskPropValue<eTO_CreateDirectoriesRelativeToRoot>(m_tTaskDefinition.GetConfiguration());
-	bool bMove = m_tTaskDefinition.GetOperationType() == eOperation_Move;
-
-	// add everything
-	ictranslate::CFormat fmt;
-	bool bRetry = true;
-	bool bSkipInputPath = false;
-
-	size_t stSize = m_tTaskDefinition.GetSourcePathCount();
-	for(size_t stIndex = 0; stIndex < stSize ; stIndex++)
-	{
-		CFileInfoPtr spFileInfo;
-
-		bSkipInputPath = false;
-
-		spFileInfo.reset(new CFileInfo());
-		spFileInfo->SetClipboard(&m_tTaskDefinition.GetSourcePaths());
-
-		// try to get some info about the input path; let user know if the path does not exist.
-		do
-		{
-			bRetry = false;
-
-			// read attributes of src file/folder
-			bool bExists = spFileInfo->Create(m_tTaskDefinition.GetSourcePathAt(stIndex), stIndex);
-			if(!bExists)
-			{
-				FEEDBACK_FILEERROR ferr = { m_tTaskDefinition.GetSourcePathAt(stIndex).ToString(), NULL, eFastMoveError, ERROR_FILE_NOT_FOUND };
-				CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
-				switch(frResult)
-				{
-				case CFeedbackHandler::eResult_Cancel:
-					m_files.Clear();
-					return eSubResult_CancelRequest;
-
-				case CFeedbackHandler::eResult_Retry:
-					bRetry = true;
-					break;
-
-				case CFeedbackHandler::eResult_Pause:
-					m_files.Clear();
-					return eSubResult_PauseRequest;
-
-				case CFeedbackHandler::eResult_Skip:
-					bSkipInputPath = true;
-					break;		// just do nothing
-
-				default:
-					BOOST_ASSERT(FALSE);		// unknown result
-					THROW(_T("Unhandled case"), 0, 0, 0);
-				}
-			}
-		}
-		while(bRetry);
-
-		// if we have chosen to skip the input path then there's nothing to do
-		if(bSkipInputPath)
-			continue;
-
-		// log
-		fmt.SetFormat(_T("Adding file/folder (clipboard) : %path ..."));
-		fmt.SetParam(_t("%path"), m_tTaskDefinition.GetSourcePathAt(stIndex).ToString());
-		m_log.logi(fmt);
-
-		// found file/folder - check if the dest name has been generated
-		if(!m_arrSourcePathsInfo.GetAt(stIndex)->IsDestinationPathSet())
-		{
-			// generate something - if dest folder == src folder - search for copy
-			if(m_tTaskDefinition.GetDestinationPath() == spFileInfo->GetFullFilePath().GetFileRoot())
-			{
-				chcore::TSmartPath pathSubst = FindFreeSubstituteName(spFileInfo->GetFullFilePath(), m_tTaskDefinition.GetDestinationPath());
-				m_arrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(pathSubst);
-			}
-			else
-				m_arrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(spFileInfo->GetFullFilePath().GetFileName());
-		}
-
-		// add if needed
-		if(spFileInfo->IsDirectory())
-		{
-			// add if folder's aren't ignored
-			if(!bIgnoreDirs && !bForceDirectories)
-			{
-				// add directory info; it is not to be filtered with m_afFilters
-				m_files.AddFileInfo(spFileInfo);
-
-				// log
-				fmt.SetFormat(_T("Added folder %path"));
-				fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString());
-				m_log.logi(fmt);
-			}
-
-			// don't add folder contents when moving inside one disk boundary
-			if(bIgnoreDirs || !bMove || iDestDrvNumber == -1 || iDestDrvNumber != GetDriveNumber(spFileInfo) ||
-				PathExist(GetDestinationPath(spFileInfo, m_tTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1)) )
-			{
-				// log
-				fmt.SetFormat(_T("Recursing folder %path"));
-				fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString());
-				m_log.logi(fmt);
-
-				// no movefile possibility - use CustomCopyFileFB
-				m_arrSourcePathsInfo.GetAt(stIndex)->SetMove(false);
-
-				ScanDirectory(spFileInfo->GetFullFilePath(), stIndex, true, !bIgnoreDirs || bForceDirectories);
-			}
-
-			// check for kill need
-			if(m_workerThread.KillRequested())
-			{
-				// log
-				m_log.logi(_T("Kill request while adding data to files array (RecurseDirectories)"));
-				m_files.Clear();
-				return eSubResult_KillRequest;
-			}
-		}
-		else
-		{
-			if(bMove && iDestDrvNumber != -1 && iDestDrvNumber == GetDriveNumber(spFileInfo) &&
-				!PathExist(GetDestinationPath(spFileInfo, m_tTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1)) )
-			{
-				// if moving within one partition boundary set the file size to 0 so the overall size will
-				// be ok
-				spFileInfo->SetLength64(0);
-			}
-			else
-				m_arrSourcePathsInfo.GetAt(stIndex)->SetMove(false);	// no MoveFile
-
-			// add file info if passes filters
-			if(m_afFilters.Match(spFileInfo))
-				m_files.AddFileInfo(spFileInfo);
-
-			// log
-			fmt.SetFormat(_T("Added file %path"));
-			fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString());
-			m_log.logi(fmt);
-		}
-	}
-
-	// calc size of all files
-	CalculateTotalSize();
-
-	// save task status
-	Store();
-
-	// log
-	m_log.logi(_T("Searching for files finished"));
-
-	return eSubResult_Continue;
-}
-
 // delete files - after copying
-CTask::ESubOperationResult CTask::DeleteFiles()
+TSubTaskBase::ESubOperationResult CTask::DeleteFiles()
 {
 	// log
 	m_log.logi(_T("Deleting files (DeleteFiles)..."));
@@ -1215,7 +581,7 @@
 		{
 			// log
 			m_log.logi(_T("Kill request while deleting files (Delete Files)"));
-			return eSubResult_KillRequest;
+			return TSubTaskBase::eSubResult_KillRequest;
 		}
 
 		// current processed element
@@ -1257,13 +623,13 @@
 			{
 			case CFeedbackHandler::eResult_Cancel:
 				m_log.logi(_T("Cancel request while deleting file."));
-				return eSubResult_CancelRequest;
+				return TSubTaskBase::eSubResult_CancelRequest;
 
 			case CFeedbackHandler::eResult_Retry:
 				continue;	// no stIndex bump, since we are trying again
 
 			case CFeedbackHandler::eResult_Pause:
-				return eSubResult_PauseRequest;
+				return TSubTaskBase::eSubResult_PauseRequest;
 
 			case CFeedbackHandler::eResult_Skip:
 				break;		// just do nothing
@@ -1286,947 +652,11 @@
 	// log
 	m_log.logi(_T("Deleting files finished"));
 
-	return eSubResult_Continue;
+	return TSubTaskBase::eSubResult_Continue;
 }
 
-CTask::ESubOperationResult CTask::OpenSourceFileFB(TAutoFileHandle& hOutFile, const CFileInfoPtr& spSrcFileInfo, bool bNoBuffering)
+TSubTaskBase::ESubOperationResult CTask::CheckForWaitState()
 {
-	BOOST_ASSERT(spSrcFileInfo);
-	if(!spSrcFileInfo)
-		THROW(_T("Invalid argument"), 0, 0, 0);
-
-	bool bRetry = false;
-	CString strPath = spSrcFileInfo->GetFullFilePath().ToString();
-
-	hOutFile = INVALID_HANDLE_VALUE;
-
-	TAutoFileHandle hFile;
-	do
-	{
-		bRetry = false;
-
-		hFile = CreateFile(strPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
-		if(hFile == INVALID_HANDLE_VALUE)
-		{
-			DWORD dwLastError = GetLastError();
-
-			FEEDBACK_FILEERROR feedStruct = { (PCTSTR)strPath, NULL, eCreateError, dwLastError };
-			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
-
-			switch(frResult)
-			{
-			case CFeedbackHandler::eResult_Skip:
-				break;	// will return INVALID_HANDLE_VALUE
-
-			case CFeedbackHandler::eResult_Cancel:
-				{
-					// log
-					ictranslate::CFormat fmt;
-					fmt.SetFormat(_T("Cancel request [error %errno] while opening source file %path (CustomCopyFileFB)"));
-					fmt.SetParam(_t("%errno"), dwLastError);
-					fmt.SetParam(_t("%path"), strPath);
-					m_log.loge(fmt);
-
-					return eSubResult_CancelRequest;
-				}
-
-			case CFeedbackHandler::eResult_Pause:
-				return eSubResult_PauseRequest;
-
-			case CFeedbackHandler::eResult_Retry:
-				{
-					// log
-					ictranslate::CFormat fmt;
-					fmt.SetFormat(_T("Retrying [error %errno] to open source file %path (CustomCopyFileFB)"));
-					fmt.SetParam(_t("%errno"), dwLastError);
-					fmt.SetParam(_t("%path"), strPath);
-					m_log.loge(fmt);
-
-					bRetry = true;
-					break;
-				}
-
-			default:
-				BOOST_ASSERT(FALSE);		// unknown result
-				THROW(_T("Unhandled case"), 0, 0, 0);
-			}
-		}
-	}
-	while(bRetry);
-
-	hOutFile = hFile.Detach();
-
-	return eSubResult_Continue;
-}
-
-CTask::ESubOperationResult CTask::OpenDestinationFileFB(TAutoFileHandle& hOutFile, const chcore::TSmartPath& pathDstFile, bool bNoBuffering, const CFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated)
-{
-	bool bRetry = false;
-	TAutoFileHandle hFile;
-
-	ullSeekTo = 0;
-	bFreshlyCreated = true;
-	hOutFile = INVALID_HANDLE_VALUE;
-
-	do
-	{
-		bRetry = false;
-
-		hFile = ::CreateFile(pathDstFile.ToString(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
-		if(hFile == INVALID_HANDLE_VALUE)
-		{
-			DWORD dwLastError = GetLastError();
-			if(dwLastError == ERROR_FILE_EXISTS)
-			{
-				bFreshlyCreated = false;
-
-				// pass it to the specialized method
-				CTask::ESubOperationResult eResult = OpenExistingDestinationFileFB(hFile, pathDstFile, bNoBuffering);
-				if(eResult != eSubResult_Continue)
-					return eResult;
-				else if(hFile == INVALID_HANDLE_VALUE)
-					return eSubResult_Continue;
-
-				// read info about the existing destination file,
-				// NOTE: it is not known which one would be faster - reading file parameters
-				//       by using spDstFileInfo->Create() (which uses FindFirstFile()) or by
-				//       reading parameters using opened handle; need to be tested in the future
-				CFileInfoPtr spDstFileInfo(boost::make_shared<CFileInfo>());
-				if(!spDstFileInfo->Create(pathDstFile, std::numeric_limits<size_t>::max()))
-					THROW(_T("Cannot get information about file which has already been opened!"), 0, GetLastError(), 0);
-
-				// src and dst files are the same
-				FEEDBACK_ALREADYEXISTS feedStruct = { spSrcFileInfo, spDstFileInfo };
-				CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileAlreadyExists, &feedStruct);
-				// check for dialog result
-				switch(frResult)
-				{
-				case CFeedbackHandler::eResult_Overwrite:
-					ullSeekTo = 0;
-					break;
-
-				case CFeedbackHandler::eResult_CopyRest:
-					ullSeekTo = spDstFileInfo->GetLength64();
-					break;
-
-				case CFeedbackHandler::eResult_Skip:
-					return eSubResult_Continue;
-
-				case CFeedbackHandler::eResult_Cancel:
-					{
-						// log
-						ictranslate::CFormat fmt;
-						fmt.SetFormat(_T("Cancel request while checking result of dialog before opening source file %path (CustomCopyFileFB)"));
-						fmt.SetParam(_t("%path"), pathDstFile.ToString());
-						m_log.logi(fmt);
-
-						return eSubResult_CancelRequest;
-					}
-				case CFeedbackHandler::eResult_Pause:
-					return eSubResult_PauseRequest;
-
-				default:
-					BOOST_ASSERT(FALSE);		// unknown result
-					THROW(_T("Unhandled case"), 0, 0, 0);
-				}
-			}
-			else
-			{
-				FEEDBACK_FILEERROR feedStruct = { pathDstFile.ToString(), NULL, eCreateError, dwLastError };
-				CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
-				switch (frResult)
-				{
-				case CFeedbackHandler::eResult_Retry:
-					{
-						// log
-						ictranslate::CFormat fmt;
-						fmt.SetFormat(_T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)"));
-						fmt.SetParam(_t("%errno"), dwLastError);
-						fmt.SetParam(_t("%path"), pathDstFile.ToString());
-						m_log.loge(fmt);
-
-						bRetry = true;
-
-						break;
-					}
-				case CFeedbackHandler::eResult_Cancel:
-					{
-						// log
-						ictranslate::CFormat fmt;
-
-						fmt.SetFormat(_T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)"));
-						fmt.SetParam(_t("%errno"), dwLastError);
-						fmt.SetParam(_t("%path"), pathDstFile.ToString());
-						m_log.loge(fmt);
-
-						return eSubResult_CancelRequest;
-					}
-
-				case CFeedbackHandler::eResult_Skip:
-					break;		// will return invalid handle value
-
-				case CFeedbackHandler::eResult_Pause:
-					return eSubResult_PauseRequest;
-
-				default:
-					BOOST_ASSERT(FALSE);		// unknown result
-					THROW(_T("Unhandled case"), 0, 0, 0);
-				}
-			}
-		}
-	}
-	while(bRetry);
-
-	hOutFile = hFile.Detach();
-
-	return eSubResult_Continue;
-}
-
-CTask::ESubOperationResult CTask::OpenExistingDestinationFileFB(TAutoFileHandle& hOutFile, const chcore::TSmartPath& pathDstFile, bool bNoBuffering)
-{
-	bool bRetry = false;
-	TAutoFileHandle hFile;
-
-	hOutFile = INVALID_HANDLE_VALUE;
-
-	do
-	{
-		bRetry = false;
-
-		hFile = CreateFile(pathDstFile.ToString(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
-		if(hFile == INVALID_HANDLE_VALUE)
-		{
-			DWORD dwLastError = GetLastError();
-			FEEDBACK_FILEERROR feedStruct = { pathDstFile.ToString(), NULL, eCreateError, dwLastError };
-			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
-			switch (frResult)
-			{
-			case CFeedbackHandler::eResult_Retry:
-				{
-					// log
-					ictranslate::CFormat fmt;
-					fmt.SetFormat(_T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)"));
-					fmt.SetParam(_t("%errno"), dwLastError);
-					fmt.SetParam(_t("%path"), pathDstFile.ToString());
-					m_log.loge(fmt);
-
-					bRetry = true;
-
-					break;
-				}
-			case CFeedbackHandler::eResult_Cancel:
-				{
-					// log
-					ictranslate::CFormat fmt;
-
-					fmt.SetFormat(_T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)"));
-					fmt.SetParam(_t("%errno"), dwLastError);
-					fmt.SetParam(_t("%path"), pathDstFile.ToString());
-					m_log.loge(fmt);
-
-					return eSubResult_CancelRequest;
-				}
-
-			case CFeedbackHandler::eResult_Skip:
-				break;		// will return invalid handle value
-
-			case CFeedbackHandler::eResult_Pause:
-				return eSubResult_PauseRequest;
-
-			default:
-				BOOST_ASSERT(FALSE);		// unknown result
-				THROW(_T("Unhandled case"), 0, 0, 0);
-			}
-		}
-	}
-	while(bRetry);
-
-	hOutFile = hFile.Detach();
-
-	return eSubResult_Continue;
-}
-
-CTask::ESubOperationResult CTask::SetFilePointerFB(HANDLE hFile, long long llDistance, const chcore::TSmartPath& pathFile, bool& bSkip)
-{
-	bSkip = false;
-	bool bRetry = false;
-	do
-	{
-		bRetry = false;
-
-		if(SetFilePointer64(hFile, llDistance, FILE_BEGIN) == -1)
-		{
-			DWORD dwLastError = GetLastError();
-
-			// log
-			ictranslate::CFormat fmt;
-
-			fmt.SetFormat(_T("Error %errno while moving file pointer of %path to %pos"));
-			fmt.SetParam(_t("%errno"), dwLastError);
-			fmt.SetParam(_t("%path"), pathFile.ToString());
-			fmt.SetParam(_t("%pos"), llDistance);
-			m_log.loge(fmt);
-
-			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eSeekError, dwLastError };
-			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
-			switch(frResult)
-			{
-			case CFeedbackHandler::eResult_Cancel:
-				return eSubResult_CancelRequest;
-
-			case CFeedbackHandler::eResult_Retry:
-				bRetry = true;
-				break;
-
-			case CFeedbackHandler::eResult_Pause:
-				return eSubResult_PauseRequest;
-
-			case CFeedbackHandler::eResult_Skip:
-				bSkip = true;
-				return eSubResult_Continue;
-
-			default:
-				BOOST_ASSERT(FALSE);		// unknown result
-				THROW(_T("Unhandled case"), 0, 0, 0);
-			}
-		}
-	}
-	while(bRetry);
-
-	return eSubResult_Continue;
-}
-
-CTask::ESubOperationResult CTask::SetEndOfFileFB(HANDLE hFile, const chcore::TSmartPath& pathFile, bool& bSkip)
-{
-	bSkip = false;
-
-	bool bRetry = false;
-	do
-	{
-		if(!SetEndOfFile(hFile))
-		{
-			// log
-			DWORD dwLastError = GetLastError();
-
-			ictranslate::CFormat fmt;
-			fmt.SetFormat(_T("Error %errno while setting size of file %path to 0"));
-			fmt.SetParam(_t("%errno"), dwLastError);
-			fmt.SetParam(_t("%path"), pathFile.ToString());
-			m_log.loge(fmt);
-
-			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eResizeError, dwLastError };
-			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
-			switch(frResult)
-			{
-			case CFeedbackHandler::eResult_Cancel:
-				return eSubResult_CancelRequest;
-
-			case CFeedbackHandler::eResult_Retry:
-				bRetry = true;
-
-			case CFeedbackHandler::eResult_Pause:
-				return eSubResult_PauseRequest;
-
-			case CFeedbackHandler::eResult_Skip:
-				bSkip = true;
-				return eSubResult_Continue;
-
-			default:
-				BOOST_ASSERT(FALSE);		// unknown result
-				THROW(_T("Unhandled case"), 0, 0, 0);
-			}
-		}
-	}
-	while(bRetry);
-
-	return eSubResult_Continue;
-}
-
-CTask::ESubOperationResult CTask::ReadFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToRead, DWORD& rdwBytesRead, const chcore::TSmartPath& pathFile, bool& bSkip)
-{
-	bSkip = false;
-	bool bRetry = false;
-	do
-	{
-		bRetry = false;
-
-		if(!ReadFile(hFile, rBuffer, dwToRead, &rdwBytesRead, NULL))
-		{
-			// log
-			DWORD dwLastError = GetLastError();
-
-			ictranslate::CFormat fmt;
-			fmt.SetFormat(_T("Error %errno while trying to read %count bytes from source file %path (CustomCopyFileFB)"));
-			fmt.SetParam(_t("%errno"), dwLastError);
-			fmt.SetParam(_t("%count"), dwToRead);
-			fmt.SetParam(_t("%path"), pathFile.ToString());
-			m_log.loge(fmt);
-
-			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eReadError, dwLastError };
-			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
-			switch(frResult)
-			{
-			case CFeedbackHandler::eResult_Cancel:
-				return eSubResult_CancelRequest;
-
-			case CFeedbackHandler::eResult_Retry:
-				bRetry = true;
-				break;
-
-			case CFeedbackHandler::eResult_Pause:
-				return eSubResult_PauseRequest;
-
-			case CFeedbackHandler::eResult_Skip:
-				bSkip = true;
-				return eSubResult_Continue;
-
-			default:
-				BOOST_ASSERT(FALSE);		// unknown result
-				THROW(_T("Unhandled case"), 0, 0, 0);
-			}
-		}
-	}
-	while(bRetry);
-
-	return eSubResult_Continue;
-}
-
-CTask::ESubOperationResult CTask::WriteFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToWrite, DWORD& rdwBytesWritten, const chcore::TSmartPath& pathFile, bool& bSkip)
-{
-	bSkip = false;
-
-	bool bRetry = false;
-	do
-	{
-		bRetry = false;
-
-		if(!WriteFile(hFile, rBuffer, dwToWrite, &rdwBytesWritten, NULL) || dwToWrite != rdwBytesWritten)
-		{
-			// log
-			DWORD dwLastError = GetLastError();
-
-			ictranslate::CFormat fmt;
-			fmt.SetFormat(_T("Error %errno while trying to write %count bytes to destination file %path (CustomCopyFileFB)"));
-			fmt.SetParam(_t("%errno"), dwLastError);
-			fmt.SetParam(_t("%count"), dwToWrite);
-			fmt.SetParam(_t("%path"), pathFile.ToString());
-			m_log.loge(fmt);
-
-			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eWriteError, dwLastError };
-			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
-			switch(frResult)
-			{
-			case CFeedbackHandler::eResult_Cancel:
-				return eSubResult_CancelRequest;
-
-			case CFeedbackHandler::eResult_Retry:
-				bRetry = true;
-				break;
-
-			case CFeedbackHandler::eResult_Pause:
-				return eSubResult_PauseRequest;
-
-			case CFeedbackHandler::eResult_Skip:
-				bSkip = true;
-				return eSubResult_Continue;
-
-			default:
-				BOOST_ASSERT(FALSE);		// unknown result
-				THROW(_T("Unhandled case"), 0, 0, 0);
-			}
-		}
-	}
-	while(bRetry);
-
-	return eSubResult_Continue;
-}
-
-CTask::ESubOperationResult CTask::CustomCopyFileFB(CUSTOM_COPY_PARAMS* pData)
-{
-	TAutoFileHandle hSrc = INVALID_HANDLE_VALUE,
-		hDst = INVALID_HANDLE_VALUE;
-	ictranslate::CFormat fmt;
-	CTask::ESubOperationResult eResult = eSubResult_Continue;
-	bool bSkip = false;
-
-	// calculate if we want to disable buffering for file transfer
-	// NOTE: we are using here the file size read when scanning directories for files; it might be
-	//       outdated at this point, but at present we don't want to re-read file size since it
-	//       will cost additional disk access
-	bool bNoBuffer = (GetTaskPropValue<eTO_DisableBuffering>(m_tTaskDefinition.GetConfiguration()) &&
-						pData->spSrcFile->GetLength64() >= GetTaskPropValue<eTO_DisableBufferingMinSize>(m_tTaskDefinition.GetConfiguration()));
-
-	// first open the source file and handle any failures
-	eResult = OpenSourceFileFB(hSrc, pData->spSrcFile, bNoBuffer);
-	if(eResult != eSubResult_Continue)
-		return eResult;
-	else if(hSrc == INVALID_HANDLE_VALUE)
-	{
-		// invalid handle = operation skipped by user
-		m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize());
-		pData->bProcessed = false;
-		return eSubResult_Continue;
-	}
-
-	// change attributes of a dest file
-	// NOTE: probably should be removed from here and report problems with read-only files
-	//       directly to the user (as feedback request)
-	if(!GetTaskPropValue<eTO_ProtectReadOnlyFiles>(m_tTaskDefinition.GetConfiguration()))
-		SetFileAttributes(pData->pathDstFile.ToString(), FILE_ATTRIBUTE_NORMAL);
-
-	// open destination file, handle the failures and possibly existence of the destination file
-	unsigned long long ullSeekTo = 0;
-	bool bDstFileFreshlyCreated = false;
-
-	if(m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize() == 0)
-	{
-		// open destination file for case, when we start operation on this file (i.e. it is not resume of the
-		// old operation)
-		eResult = OpenDestinationFileFB(hDst, pData->pathDstFile, bNoBuffer, pData->spSrcFile, ullSeekTo, bDstFileFreshlyCreated);
-		if(eResult != eSubResult_Continue)
-			return eResult;
-		else if(hDst == INVALID_HANDLE_VALUE)
-		{
-			m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize());
-			pData->bProcessed = false;
-			return eSubResult_Continue;
-		}
-	}
-	else
-	{
-		// we are resuming previous operation
-		eResult = OpenExistingDestinationFileFB(hDst, pData->pathDstFile, bNoBuffer);
-		if(eResult != eSubResult_Continue)
-			return eResult;
-		else if(hDst == INVALID_HANDLE_VALUE)
-		{
-			m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize());
-			pData->bProcessed = false;
-			return eSubResult_Continue;
-		}
-
-		ullSeekTo = m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize();
-	}
-
-	if(!pData->bOnlyCreate)
-	{
-		// seek to the position where copying will start
-		if(ullSeekTo != 0)		// src and dst files exists, requested resume at the specified index
-		{
-			// try to move file pointers to the end
-			ULONGLONG ullMove = (bNoBuffer ? ROUNDDOWN(ullSeekTo, MAXSECTORSIZE) : ullSeekTo);
-
-			eResult = SetFilePointerFB(hSrc, ullMove, pData->spSrcFile->GetFullFilePath(), bSkip);
-			if(eResult != eSubResult_Continue)
-				return eResult;
-			else if(bSkip)
-			{
-				m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize());
-				pData->bProcessed = false;
-				return eSubResult_Continue;
-			}
-
-			eResult = SetFilePointerFB(hDst, ullMove, pData->pathDstFile, bSkip);
-			if(eResult != eSubResult_Continue)
-				return eResult;
-			else if(bSkip)
-			{
-				// with either first or second seek we got 'skip' answer...
-				m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize());
-				pData->bProcessed = false;
-				return eSubResult_Continue;
-			}
-
-			m_tTaskBasicProgressInfo.IncreaseCurrentFileProcessedSize(ullMove);
-			m_localStats.IncreaseProcessedSize(ullMove);
-		}
-
-		// if the destination file already exists - truncate it to the current file position
-		if(!bDstFileFreshlyCreated)
-		{
-			// if destination file was opened (as opposed to newly created)
-			eResult = SetEndOfFileFB(hDst, pData->pathDstFile, bSkip);
-			if(eResult != eSubResult_Continue)
-				return eResult;
-			else if(bSkip)
-			{
-				pData->bProcessed = false;
-				return eSubResult_Continue;
-			}
-		}
-
-		// copying
-		unsigned long ulToRead = 0;
-		unsigned long ulRead = 0;
-		unsigned long ulWritten = 0;
-		int iBufferIndex = 0;
-		bool bLastPart = false;
-
-		do
-		{
-			// kill flag checks
-			if(m_workerThread.KillRequested())
-			{
-				// log
-				fmt.SetFormat(_T("Kill request while main copying file %srcpath -> %dstpath"));
-				fmt.SetParam(_t("%srcpath"), pData->spSrcFile->GetFullFilePath().ToString());
-				fmt.SetParam(_t("%dstpath"), pData->pathDstFile.ToString());
-				m_log.logi(fmt);
-				return eSubResult_KillRequest;
-			}
-
-			// recreate buffer if needed
-			if(m_cfgTracker.IsModified() && m_cfgTracker.IsModified(TOptionsSet() % eTO_DefaultBufferSize % eTO_OneDiskBufferSize % eTO_TwoDisksBufferSize % eTO_CDBufferSize % eTO_LANBufferSize % eTO_UseOnlyDefaultBuffer, true))
-			{
-				BUFFERSIZES bs;
-				bs.m_bOnlyDefault = GetTaskPropValue<eTO_UseOnlyDefaultBuffer>(m_tTaskDefinition.GetConfiguration());
-				bs.m_uiDefaultSize = GetTaskPropValue<eTO_DefaultBufferSize>(m_tTaskDefinition.GetConfiguration());
-				bs.m_uiOneDiskSize = GetTaskPropValue<eTO_OneDiskBufferSize>(m_tTaskDefinition.GetConfiguration());
-				bs.m_uiTwoDisksSize = GetTaskPropValue<eTO_TwoDisksBufferSize>(m_tTaskDefinition.GetConfiguration());
-				bs.m_uiCDSize = GetTaskPropValue<eTO_CDBufferSize>(m_tTaskDefinition.GetConfiguration());
-				bs.m_uiLANSize = GetTaskPropValue<eTO_LANBufferSize>(m_tTaskDefinition.GetConfiguration());
-
-				// log
-				const BUFFERSIZES* pbs1 = pData->dbBuffer.GetSizes();
-
-				fmt.SetFormat(_T("Changing buffer size from [Def:%defsize, One:%onesize, Two:%twosize, CD:%cdsize, LAN:%lansize] to [Def:%defsize2, One:%onesize2, Two:%twosize2, CD:%cdsize2, LAN:%lansize2] wile copying %srcfile -> %dstfile (CustomCopyFileFB)"));
-
-				fmt.SetParam(_t("%defsize"), pbs1->m_uiDefaultSize);
-				fmt.SetParam(_t("%onesize"), pbs1->m_uiOneDiskSize);
-				fmt.SetParam(_t("%twosize"), pbs1->m_uiTwoDisksSize);
-				fmt.SetParam(_t("%cdsize"), pbs1->m_uiCDSize);
-				fmt.SetParam(_t("%lansize"), pbs1->m_uiLANSize);
-				fmt.SetParam(_t("%defsize2"), bs.m_uiDefaultSize);
-				fmt.SetParam(_t("%onesize2"), bs.m_uiOneDiskSize);
-				fmt.SetParam(_t("%twosize2"), bs.m_uiTwoDisksSize);
-				fmt.SetParam(_t("%cdsize2"), bs.m_uiCDSize);
-				fmt.SetParam(_t("%lansize2"), bs.m_uiLANSize);
-				fmt.SetParam(_t("%srcfile"), pData->spSrcFile->GetFullFilePath().ToString());
-				fmt.SetParam(_t("%dstfile"), pData->pathDstFile.ToString());
-
-				m_log.logi(fmt);
-				pData->dbBuffer.Create(&bs);
-			}
-
-			// establish count of data to read
-			if(GetTaskPropValue<eTO_UseOnlyDefaultBuffer>(m_tTaskDefinition.GetConfiguration()))
-				iBufferIndex = BI_DEFAULT;
-			else
-				iBufferIndex = GetBufferIndex(pData->spSrcFile);
-
-			ulToRead = bNoBuffer ? ROUNDUP(pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex], MAXSECTORSIZE) : pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex];
-
-			// read data from file to buffer
-			eResult = ReadFileFB(hSrc, pData->dbBuffer, ulToRead, ulRead, pData->spSrcFile->GetFullFilePath(), bSkip);
-			if(eResult != eSubResult_Continue)
-				return eResult;
-			else if(bSkip)
-			{
-				m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize());
-				pData->bProcessed = false;
-				return eSubResult_Continue;
-			}
-
-			if(ulRead > 0)
-			{
-				// determine if this is the last chunk of data we could get from the source file (EOF condition)
-				bLastPart = (ulToRead != ulRead);
-
-				// handle not aligned part at the end of file when no buffering is enabled
-				if(bNoBuffer && bLastPart)
-				{
-					// count of data read from the file is less than requested - we're at the end of source file
-					// and this is the operation with system buffering turned off
-
-					// write as much as possible to the destination file with no buffering
-					// NOTE: as an alternative, we could write more data to the destination file and then truncate the file
-					unsigned long ulDataToWrite = ROUNDDOWN(ulRead, MAXSECTORSIZE);
-					if(ulDataToWrite > 0)
-					{
-						eResult = WriteFileFB(hDst, pData->dbBuffer, ulDataToWrite, ulWritten, pData->pathDstFile, bSkip);
-						if(eResult != eSubResult_Continue)
-							return eResult;
-						else if(bSkip)
-						{
-							m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize());
-							pData->bProcessed = false;
-							return eSubResult_Continue;
-						}
-
-						// increase count of processed data
-						m_tTaskBasicProgressInfo.IncreaseCurrentFileProcessedSize(ulWritten);
-						m_localStats.IncreaseProcessedSize(ulWritten);
-
-						// calculate count of bytes left to be written
-						ulRead -= ulWritten;
-
-						// now remove part of data from buffer (ulWritten bytes)
-						pData->dbBuffer.CutDataFromBuffer(ulWritten);
-					}
-
-					// close and re-open the destination file with buffering option for append
-					hDst.Close();
-
-					// are there any more data to be written?
-					if(ulRead != 0)
-					{
-						// re-open the destination file, this time with standard buffering to allow writing not aligned part of file data
-						eResult = OpenExistingDestinationFileFB(hDst, pData->pathDstFile, false);
-						if(eResult != eSubResult_Continue)
-							return eResult;
-						else if(hDst == INVALID_HANDLE_VALUE)
-						{
-							m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize());
-							pData->bProcessed = false;
-							return eSubResult_Continue;
-						}
-
-						// move file pointer to the end of destination file
-						eResult = SetFilePointerFB(hDst, m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize(), pData->pathDstFile, bSkip);
-						if(eResult != eSubResult_Continue)
-							return eResult;
-						else if(bSkip)
-						{
-							// with either first or second seek we got 'skip' answer...
-							m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize());
-							pData->bProcessed = false;
-							return eSubResult_Continue;
-						}
-					}
-				}
-
-				// write
-				if(ulRead != 0)
-				{
-					eResult = WriteFileFB(hDst, pData->dbBuffer, ulRead, ulWritten, pData->pathDstFile, bSkip);
-					if(eResult != eSubResult_Continue)
-						return eResult;
-					else if(bSkip)
-					{
-						m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize());
-						pData->bProcessed = false;
-						return eSubResult_Continue;
-					}
-
-					// increase count of processed data
-					m_tTaskBasicProgressInfo.IncreaseCurrentFileProcessedSize(ulRead);
-					m_localStats.IncreaseProcessedSize(ulRead);
-				}
-			}
-		}
-		while(ulRead != 0 && !bLastPart);
-	}
-	else
-	{
-		// we don't copy contents, but need to increase processed size
-		m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize());
-	}
-
-	pData->bProcessed = true;
-	m_tTaskBasicProgressInfo.SetCurrentFileProcessedSize(0);
-
-	return eSubResult_Continue;
-}
-
-// function processes files/folders
-CTask::ESubOperationResult CTask::ProcessFiles()
-{
-	// log
-	m_log.logi(_T("Processing files/folders (ProcessFiles)"));
-
-	// count how much has been done (updates also a member in CTaskArray)
-	CalculateProcessedSize();
-
-	// begin at index which wasn't processed previously
-	size_t stSize = m_files.GetSize();
-	bool bIgnoreFolders = GetTaskPropValue<eTO_IgnoreDirectories>(m_tTaskDefinition.GetConfiguration());
-	bool bForceDirectories = GetTaskPropValue<eTO_CreateDirectoriesRelativeToRoot>(m_tTaskDefinition.GetConfiguration());
-
-	// create a buffer of size m_nBufferSize
-	CUSTOM_COPY_PARAMS ccp;
-	ccp.bProcessed = false;
-	ccp.bOnlyCreate = GetTaskPropValue<eTO_CreateEmptyFiles>(m_tTaskDefinition.GetConfiguration());
-
-	// remove changes in buffer sizes to avoid re-creation later
-	m_cfgTracker.RemoveModificationSet(TOptionsSet() % eTO_DefaultBufferSize % eTO_OneDiskBufferSize % eTO_TwoDisksBufferSize % eTO_CDBufferSize % eTO_LANBufferSize % eTO_UseOnlyDefaultBuffer);
-
-	BUFFERSIZES bs;
-	bs.m_bOnlyDefault = GetTaskPropValue<eTO_UseOnlyDefaultBuffer>(m_tTaskDefinition.GetConfiguration());
-	bs.m_uiDefaultSize = GetTaskPropValue<eTO_DefaultBufferSize>(m_tTaskDefinition.GetConfiguration());
-	bs.m_uiOneDiskSize = GetTaskPropValue<eTO_OneDiskBufferSize>(m_tTaskDefinition.GetConfiguration());
-	bs.m_uiTwoDisksSize = GetTaskPropValue<eTO_TwoDisksBufferSize>(m_tTaskDefinition.GetConfiguration());
-	bs.m_uiCDSize = GetTaskPropValue<eTO_CDBufferSize>(m_tTaskDefinition.GetConfiguration());
-	bs.m_uiLANSize = GetTaskPropValue<eTO_LANBufferSize>(m_tTaskDefinition.GetConfiguration());
-
-	ccp.dbBuffer.Create(&bs);
-
-	// helpers
-	DWORD dwLastError = 0;
-
-	// log
-	const BUFFERSIZES* pbs = ccp.dbBuffer.GetSizes();
-
-	ictranslate::CFormat fmt;
-	fmt.SetFormat(_T("Processing files/folders (ProcessFiles):\r\n\tOnlyCreate: %create\r\n\tBufferSize: [Def:%defsize, One:%onesize, Two:%twosize, CD:%cdsize, LAN:%lansize]\r\n\tFiles/folders count: %filecount\r\n\tIgnore Folders: %ignorefolders\r\n\tDest path: %dstpath\r\n\tCurrent index (0-based): %currindex"));
-	fmt.SetParam(_t("%create"), ccp.bOnlyCreate);
-	fmt.SetParam(_t("%defsize"), pbs->m_uiDefaultSize);
-	fmt.SetParam(_t("%onesize"), pbs->m_uiOneDiskSize);
-	fmt.SetParam(_t("%twosize"), pbs->m_uiTwoDisksSize);
-	fmt.SetParam(_t("%cdsize"), pbs->m_uiCDSize);
-	fmt.SetParam(_t("%lansize"), pbs->m_uiLANSize);
-	fmt.SetParam(_t("%filecount"), stSize);
-	fmt.SetParam(_t("%ignorefolders"), bIgnoreFolders);
-	fmt.SetParam(_t("%dstpath"), m_tTaskDefinition.GetDestinationPath().ToString());
-	fmt.SetParam(_t("%currindex"), m_tTaskBasicProgressInfo.GetCurrentIndex());
-
-	m_log.logi(fmt);
-
-	for(size_t stIndex = m_tTaskBasicProgressInfo.GetCurrentIndex(); stIndex < stSize; stIndex++)
-	{
-		// should we kill ?
-		if(m_workerThread.KillRequested())
-		{
-			// log
-			m_log.logi(_T("Kill request while processing file in ProcessFiles"));
-			return eSubResult_KillRequest;
-		}
-
-		// update m_stNextIndex, getting current CFileInfo
-		CFileInfoPtr spFileInfo = m_files.GetAt(m_tTaskBasicProgressInfo.GetCurrentIndex());
-
-		// set dest path with filename
-		ccp.pathDstFile = GetDestinationPath(spFileInfo, m_tTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1 | (int)bIgnoreFolders);
-
-		// are the files/folders lie on the same partition ?
-		int iDstDriveNumber = 0;
-		bool bMove = m_tTaskDefinition.GetOperationType() == eOperation_Move;
-		if(bMove)
-			GetDriveData(m_tTaskDefinition.GetDestinationPath(), &iDstDriveNumber, NULL);
-		if(bMove && iDstDriveNumber != -1 && iDstDriveNumber == GetDriveNumber(spFileInfo) && GetMove(spFileInfo))
-		{
-			bool bRetry = true;
-			if(bRetry && !MoveFile(spFileInfo->GetFullFilePath().ToString(), ccp.pathDstFile.ToString()))
-			{
-				dwLastError=GetLastError();
-				//log
-				fmt.SetFormat(_T("Error %errno while calling MoveFile %srcpath -> %dstpath (ProcessFiles)"));
-				fmt.SetParam(_t("%errno"), dwLastError);
-				fmt.SetParam(_t("%srcpath"), spFileInfo->GetFullFilePath().ToString());
-				fmt.SetParam(_t("%dstpath"), ccp.pathDstFile.ToString());
-				m_log.loge(fmt);
-
-				FEEDBACK_FILEERROR ferr = { spFileInfo->GetFullFilePath().ToString(), ccp.pathDstFile.ToString(), eFastMoveError, dwLastError };
-				CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
-				switch(frResult)
-				{
-				case CFeedbackHandler::eResult_Cancel:
-					return eSubResult_CancelRequest;
-
-				case CFeedbackHandler::eResult_Retry:
-					continue;
-
-				case CFeedbackHandler::eResult_Pause:
-					return eSubResult_PauseRequest;
-
-				case CFeedbackHandler::eResult_Skip:
-					bRetry = false;
-					break;		// just do nothing
-				default:
-					BOOST_ASSERT(FALSE);		// unknown result
-					THROW(_T("Unhandled case"), 0, 0, 0);
-				}
-			}
-			else
-				spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED);
-		}
-		else
-		{
-			// if folder - create it
-			if(spFileInfo->IsDirectory())
-			{
-				bool bRetry = true;
-				if(bRetry && !CreateDirectory(ccp.pathDstFile.ToString(), NULL) && (dwLastError=GetLastError()) != ERROR_ALREADY_EXISTS )
-				{
-					// log
-					fmt.SetFormat(_T("Error %errno while calling CreateDirectory %path (ProcessFiles)"));
-					fmt.SetParam(_t("%errno"), dwLastError);
-					fmt.SetParam(_t("%path"), ccp.pathDstFile.ToString());
-					m_log.loge(fmt);
-
-					FEEDBACK_FILEERROR ferr = { ccp.pathDstFile.ToString(), NULL, eCreateError, dwLastError };
-					CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr);
-					switch(frResult)
-					{
-					case CFeedbackHandler::eResult_Cancel:
-						return eSubResult_CancelRequest;
-
-					case CFeedbackHandler::eResult_Retry:
-						continue;
-
-					case CFeedbackHandler::eResult_Pause:
-						return eSubResult_PauseRequest;
-
-					case CFeedbackHandler::eResult_Skip:
-						bRetry = false;
-						break;		// just do nothing
-					default:
-						BOOST_ASSERT(FALSE);		// unknown result
-						THROW(_T("Unhandled case"), 0, 0, 0);
-					}
-				}
-
-				m_localStats.IncreaseProcessedSize(spFileInfo->GetLength64());
-				spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED);
-			}
-			else
-			{
-				// start copying/moving file
-				ccp.spSrcFile = spFileInfo;
-				ccp.bProcessed = false;
-
-				// kopiuj dane
-				ESubOperationResult eResult = CustomCopyFileFB(&ccp);
-				if(eResult != eSubResult_Continue)
-					return eResult;
-
-				spFileInfo->SetFlags(ccp.bProcessed ? FIF_PROCESSED : 0, FIF_PROCESSED);
-
-				// if moving - delete file (only if config flag is set)
-				if(bMove && spFileInfo->GetFlags() & FIF_PROCESSED && !GetTaskPropValue<eTO_DeleteInSeparateSubTask>(m_tTaskDefinition.GetConfiguration()))
-				{
-					if(!GetTaskPropValue<eTO_ProtectReadOnlyFiles>(m_tTaskDefinition.GetConfiguration()))
-						SetFileAttributes(spFileInfo->GetFullFilePath().ToString(), FILE_ATTRIBUTE_NORMAL);
-					DeleteFile(spFileInfo->GetFullFilePath().ToString());	// there will be another try later, so I don't check
-					// if succeeded
-				}
-			}
-
-			// set a time
-			if(GetTaskPropValue<eTO_SetDestinationDateTime>(m_tTaskDefinition.GetConfiguration()))
-				SetFileDirectoryTime(ccp.pathDstFile.ToString(), spFileInfo); // no error checking (but most probably it should be checked)
-
-			// attributes
-			if(GetTaskPropValue<eTO_SetDestinationAttributes>(m_tTaskDefinition.GetConfiguration()))
-				SetFileAttributes(ccp.pathDstFile.ToString(), spFileInfo->GetAttributes());	// as above
-		}
-
-		m_tTaskBasicProgressInfo.SetCurrentIndex(stIndex + 1);
-	}
-
-	// delete buffer - it's not needed
-	ccp.dbBuffer.Delete();
-
-	// to look better (as 100%) - increase current index by 1
-	m_tTaskBasicProgressInfo.SetCurrentIndex(stSize);
-
-	// log
-	m_log.logi(_T("Finished processing in ProcessFiles"));
-
-	return eSubResult_Continue;
-}
-
-CTask::ESubOperationResult CTask::CheckForWaitState()
-{
 	// limiting operation count
 	SetTaskState(eTaskState_Waiting);
 	bool bContinue = false;
@@ -2248,14 +678,14 @@
 		{
 			// log
 			m_log.logi(_T("Kill request while waiting for begin permission (wait state)"));
-			return eSubResult_KillRequest;
+			return TSubTaskBase::eSubResult_KillRequest;
 		}
 	}
 
-	return eSubResult_Continue;
+	return TSubTaskBase::eSubResult_Continue;
 }
 
-CTask::ESubOperationResult CTask::CheckForFreeSpaceFB()
+TSubTaskBase::ESubOperationResult CTask::CheckForFreeSpaceFB()
 {
 	ull_t ullNeededSize = 0, ullAvailableSize = 0;
 	bool bRetry = false;
@@ -2284,7 +714,7 @@
 				{
 				case CFeedbackHandler::eResult_Cancel:
 					m_log.logi(_T("Cancel request while checking for free space on disk."));
-					return eSubResult_CancelRequest;
+					return TSubTaskBase::eSubResult_CancelRequest;
 
 				case CFeedbackHandler::eResult_Retry:
 					m_log.logi(_T("Retrying to read drive's free space..."));
@@ -2293,7 +723,7 @@
 
 				case CFeedbackHandler::eResult_Ignore:
 					m_log.logi(_T("Ignored warning about not enough place on disk to copy data."));
-					return eSubResult_Continue;
+					return TSubTaskBase::eSubResult_Continue;
 
 				default:
 					BOOST_ASSERT(FALSE);		// unknown result
@@ -2304,7 +734,7 @@
 	}
 	while(bRetry);
 
-	return eSubResult_Continue;
+	return TSubTaskBase::eSubResult_Continue;
 }
 
 DWORD WINAPI CTask::DelegateThreadProc(LPVOID pParam)
@@ -2321,7 +751,7 @@
 {
 	try
 	{
-		CTask::ESubOperationResult eResult = eSubResult_Continue;
+		TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue;
 
 		// initialize log file
 		CString strPath = GetRelatedPath(ePathType_TaskLogFile);
@@ -2350,7 +780,10 @@
 		// start tracking time for this thread
 		m_localStats.EnableTimeTracking();
 
-		for(; stSubOperationIndex < m_tTaskDefinition.GetOperationPlan().GetSubOperationsCount() && eResult == eSubResult_Continue; ++stSubOperationIndex)
+      // prepare context for subtasks
+      TSubTaskContext tSubTaskContext(m_tTaskDefinition, m_arrSourcePathsInfo, m_files, m_localStats, m_tTaskBasicProgressInfo, m_cfgTracker, m_log, m_piFeedbackHandler, m_workerThread);
+
+		for(; stSubOperationIndex < m_tTaskDefinition.GetOperationPlan().GetSubOperationsCount() && eResult == TSubTaskBase::eSubResult_Continue; ++stSubOperationIndex)
 		{
 			// set current sub-operation index to allow resuming
 			m_tTaskBasicProgressInfo.SetSubOperationIndex(stSubOperationIndex);
@@ -2359,33 +792,41 @@
 			switch(eSubOperation)
 			{
 			case eSubOperation_Scanning:
-				// get rid of info about processed sizes
-				m_localStats.SetProcessedSize(0);
-				m_localStats.SetTotalSize(0);
+            {
+               // get rid of info about processed sizes
+               m_localStats.SetProcessedSize(0);
+               m_localStats.SetTotalSize(0);
 
-				// start searching
-				eResult = RecurseDirectories();
+               // start searching
+               TSubTaskScanDirectories tSubTaskScanDir(tSubTaskContext);
+               //eResult = RecurseDirectories();
+               eResult = tSubTaskScanDir.Exec();
 
-				// check for free space
-				if(eResult == eSubResult_Continue)
-					eResult = CheckForFreeSpaceFB();
+               // check for free space
+               if(eResult == TSubTaskBase::eSubResult_Continue)
+                  eResult = CheckForFreeSpaceFB();
 
-				// if we didn't wait for permission to start earlier, then ask now (but only in case this is the first search)
-				if(eResult == eSubResult_Continue && bReadTasksSize && stSubOperationIndex == 0)
-				{
-					m_localStats.DisableTimeTracking();
+               // if we didn't wait for permission to start earlier, then ask now (but only in case this is the first search)
+               if(eResult == TSubTaskBase::eSubResult_Continue && bReadTasksSize && stSubOperationIndex == 0)
+               {
+                  m_localStats.DisableTimeTracking();
 
-					eResult = CheckForWaitState();
+                  eResult = CheckForWaitState();
 
-					m_localStats.EnableTimeTracking();
-				}
+                  m_localStats.EnableTimeTracking();
+               }
 
-				break;
+               break;
+            }
 
 			case eSubOperation_Copying:
-				eResult = ProcessFiles();
-				break;
+            {
+               TSubTaskCopyMove tSubTaskCopyMove(tSubTaskContext);
 
+               eResult = tSubTaskCopyMove.Exec();
+               break;
+            }
+
 			case eSubOperation_Deleting:
 				eResult = DeleteFiles();
 				break;
@@ -2403,26 +844,26 @@
 		// change task status
 		switch(eResult)
 		{
-		case eSubResult_Error:
+		case TSubTaskBase::eSubResult_Error:
 			m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_OperationError, NULL);
 			SetTaskState(eTaskState_Error);
 			break;
 
-		case eSubResult_CancelRequest:
+		case TSubTaskBase::eSubResult_CancelRequest:
 			SetTaskState(eTaskState_Cancelled);
 			break;
 
-		case eSubResult_PauseRequest:
+		case TSubTaskBase::eSubResult_PauseRequest:
 			SetTaskState(eTaskState_Paused);
 			break;
 
-		case eSubResult_KillRequest:
+		case TSubTaskBase::eSubResult_KillRequest:
 			// the only operation 
 			if(GetTaskState() == eTaskState_Waiting)
 				SetTaskState(eTaskState_Processing);
 			break;
 
-		case eSubResult_Continue:
+		case TSubTaskBase::eSubResult_Continue:
 			m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_OperationFinished, NULL);
 			SetTaskState(eTaskState_Finished);
 			break;
@@ -2572,220 +1013,6 @@
 	}
 }
 
-// finds another name for a copy of src file(folder) in dest location
-chcore::TSmartPath CTask::FindFreeSubstituteName(chcore::TSmartPath pathSrcPath, chcore::TSmartPath pathDstPath) const
-{
-	// get the name from srcpath
-	pathSrcPath.StripSeparatorAtEnd();
-
-	chcore::TSmartPath pathFilename = pathSrcPath.GetFileName();
-
-	// set the dest path
-	CString strCheckPath;
-	ictranslate::CFormat fmt(GetTaskPropValue<eTO_AlternateFilenameFormatString_First>(m_tTaskDefinition.GetConfiguration()));
-	fmt.SetParam(_t("%name"), pathFilename.ToString());
-	chcore::TSmartPath pathCheckPath(chcore::PathFromString((PCTSTR)fmt));
-
-	// when adding to strDstPath check if the path already exists - if so - try again
-	int iCounter=1;
-	CString strFmt = GetTaskPropValue<eTO_AlternateFilenameFormatString_AfterFirst>(m_tTaskDefinition.GetConfiguration());
-	while(PathExist(pathDstPath + pathCheckPath))
-	{
-		fmt.SetFormat(strFmt);
-		fmt.SetParam(_t("%name"), pathFilename.ToString());
-		fmt.SetParam(_t("%count"), ++iCounter);
-		pathCheckPath.FromString((PCTSTR)fmt);
-	}
-
-	return pathCheckPath;
-}
-
-chcore::TSmartPath CTask::GetDestinationPath(const CFileInfoPtr& spFileInfo, chcore::TSmartPath pathDst, int iFlags) const
-{
-	if(!spFileInfo)
-		THROW(_T("Invalid pointer"), 0, 0, 0);
-
-	// iFlags: bit 0-ignore folders; bit 1-force creating directories
-	if (iFlags & 0x02)
-	{
-		// force create directories
-		chcore::TSmartPath pathCombined = pathDst + spFileInfo->GetFullFilePath().GetFileDir();
-
-		// force create directory
-		SHCreateDirectoryEx(NULL, pathCombined.ToString(), NULL);
-
-		return pathCombined + spFileInfo->GetFullFilePath().GetFileName();
-	}
-	else
-	{
-		size_t stSrcIndex = spFileInfo->GetSrcIndex();
-
-		if (!(iFlags & 0x01) && stSrcIndex != std::numeric_limits<size_t>::max())
-		{
-			// generate new dest name
-			if(!m_arrSourcePathsInfo.GetAt(stSrcIndex)->IsDestinationPathSet())
-			{
-				chcore::TSmartPath pathSubst = FindFreeSubstituteName(spFileInfo->GetFullFilePath(), pathDst);
-				m_arrSourcePathsInfo.GetAt(stSrcIndex)->SetDestinationPath(pathSubst);
-			}
-
-			return pathDst + m_arrSourcePathsInfo.GetAt(stSrcIndex)->GetDestinationPath() + spFileInfo->GetFilePath();
-		}
-		else
-			return pathDst + spFileInfo->GetFullFilePath().GetFileName();
-	}
-}
-
-int CTask::GetBufferIndex(const CFileInfoPtr& spFileInfo)
-{
-	if(!spFileInfo)
-		THROW(_T("Invalid pointer"), 0, 0, 0);
-	if(spFileInfo->GetSrcIndex() == std::numeric_limits<size_t>::max())
-		THROW(_T("Received non-relative (standalone) path info"), 0, 0, 0);
-
-	// check if this information has already been stored
-	size_t stBaseIndex = spFileInfo->GetSrcIndex();
-	if(stBaseIndex >= m_arrSourcePathsInfo.GetCount())
-		THROW(_T("Index out of bounds"), 0, 0, 0);
-
-	TBasePathDataPtr spPathData = m_arrSourcePathsInfo.GetAt(stBaseIndex);
-	if(spPathData->IsBufferIndexSet())
-		return spPathData->GetBufferIndex();
-
-	// buffer index wasn't cached previously - read it now
-	int iDriveNumber = 0;
-	UINT uiDriveType = 0;
-	int iDstDriveNumber = 0;
-	UINT uiDstDriveType = 0;
-	GetDriveData(m_tTaskDefinition.GetSourcePathAt(stBaseIndex), &iDriveNumber, &uiDriveType);
-	GetDriveData(m_tTaskDefinition.GetDestinationPath(), &iDstDriveNumber, &uiDstDriveType);
-
-	// what kind of buffer
-	int iBufferIndex = BI_DEFAULT;
-	if(uiDriveType == DRIVE_REMOTE || uiDstDriveType == DRIVE_REMOTE)
-		iBufferIndex = BI_LAN;
-	else if(uiDriveType == DRIVE_CDROM || uiDstDriveType == DRIVE_CDROM)
-		iBufferIndex = BI_CD;
-	else if(uiDriveType == DRIVE_FIXED && uiDstDriveType == DRIVE_FIXED)
-	{
-		// two hdd's - is this the same physical disk ?
-		if(iDriveNumber == iDstDriveNumber || IsSamePhysicalDisk(iDriveNumber, iDstDriveNumber))
-			iBufferIndex = BI_ONEDISK;
-		else
-			iBufferIndex = BI_TWODISKS;
-	}
-	else
-		iBufferIndex = BI_DEFAULT;
-
-	spPathData->SetBufferIndex(iBufferIndex);
-
-	return iBufferIndex;
-}
-
-int CTask::GetDriveNumber(const CFileInfoPtr& spFileInfo)
-{
-	if(!spFileInfo)
-		THROW(_T("Invalid pointer"), 0, 0, 0);
-	if(spFileInfo->GetSrcIndex() == std::numeric_limits<size_t>::max())
-		THROW(_T("Received non-relative (standalone) path info"), 0, 0, 0);
-
-	// check if this information has already been stored
-	size_t stBaseIndex = spFileInfo->GetSrcIndex();
-	if(stBaseIndex >= m_arrSourcePathsInfo.GetCount())
-		THROW(_T("Index out of bounds"), 0, 0, 0);
-
-	TBasePathDataPtr spPathData = m_arrSourcePathsInfo.GetAt(stBaseIndex);
-	if(spPathData->IsDriveNumberSet())
-		return spPathData->GetDriveNumber();
-
-	// buffer index wasn't cached previously - read it now
-	int iDriveNumber = 0;
-	GetDriveData(m_tTaskDefinition.GetSourcePathAt(stBaseIndex), &iDriveNumber, NULL);
-
-	spPathData->SetDriveNumber(iDriveNumber);
-
-	return iDriveNumber;
-}
-
-bool CTask::GetMove(const CFileInfoPtr& spFileInfo)
-{
-	if(!spFileInfo)
-		THROW(_T("Invalid pointer"), 0, 0, 0);
-	if(spFileInfo->GetSrcIndex() == std::numeric_limits<size_t>::max())
-		THROW(_T("Received non-relative (standalone) path info"), 0, 0, 0);
-
-	// check if this information has already been stored
-	size_t stBaseIndex = spFileInfo->GetSrcIndex();
-	if(stBaseIndex >= m_arrSourcePathsInfo.GetCount())
-		THROW(_T("Index out of bounds"), 0, 0, 0);
-
-	TBasePathDataPtr spPathData = m_arrSourcePathsInfo.GetAt(stBaseIndex);
-	return spPathData->GetMove();
-}
-
-void CTask::GetDriveData(const chcore::TSmartPath& spPath, int* piDrvNum, UINT* puiDrvType)
-{
-	TCHAR drv[_MAX_DRIVE+1];
-
-	_tsplitpath(spPath.ToString(), drv, NULL, NULL, NULL);
-	if(lstrlen(drv) != 0)
-	{
-		// add '\\'
-		lstrcat(drv, _T("\\"));
-		_tcsupr(drv);
-
-		// disk number
-		if(piDrvNum)
-			*piDrvNum=drv[0]-_T('A');
-
-		// disk type
-		if(puiDrvType)
-		{
-			*puiDrvType=GetDriveType(drv);
-			if(*puiDrvType == DRIVE_NO_ROOT_DIR)
-				*puiDrvType=DRIVE_UNKNOWN;
-		}
-	}
-	else
-	{
-		// there's no disk in a path
-		if(piDrvNum)
-			*piDrvNum=-1;
-
-		if(puiDrvType)
-		{
-			// check for unc path
-			if(_tcsncmp(spPath.ToString(), _T("\\\\"), 2) == 0)
-				*puiDrvType=DRIVE_REMOTE;
-			else
-				*puiDrvType=DRIVE_UNKNOWN;
-		}
-	}
-}
-
-bool CTask::PathExist(chcore::TSmartPath pathToCheck)
-{
-	WIN32_FIND_DATA fd;
-
-	// search by exact name
-	HANDLE hFind = FindFirstFile(pathToCheck.ToString(), &fd);
-	if(hFind != INVALID_HANDLE_VALUE)
-		return true;
-
-	// another try (add '\\' if needed and '*' for marking that we look for ie. c:\*
-	// instead of c:\, which would never be found prev. way)
-	pathToCheck.AppendIfNotExists(_T("*"), false);
-
-	hFind = FindFirstFile(pathToCheck.ToString(), &fd);
-	if(hFind != INVALID_HANDLE_VALUE)
-	{
-		::FindClose(hFind);
-		return true;
-	}
-	else
-		return false;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // CTaskArray members
 CTaskArray::CTaskArray() :
Index: src/ch/task.h
===================================================================
diff -u -rb684bec49aaaea4b89ab2e599497f4085d8698a3 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4
--- src/ch/task.h	(.../task.h)	(revision b684bec49aaaea4b89ab2e599497f4085d8698a3)
+++ src/ch/task.h	(.../task.h)	(revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4)
@@ -28,6 +28,10 @@
 #include "TTaskDefinition.h"
 #include "TTaskConfigTracker.h"
 #include "TBasePathData.h"
+#include "TSubTaskBase.h"
+#include "TTaskLocalStats.h"
+#include "TTaskGlobalStats.h"
+#include "TBasicProgressInfo.h"
 
 // enum representing current processing state of the task
 enum ETaskCurrentState
@@ -88,180 +92,11 @@
 	int m_nPercent;
 };
 
-struct CUSTOM_COPY_PARAMS
-{
-	CFileInfoPtr spSrcFile;		// CFileInfo - src file
-	chcore::TSmartPath pathDstFile;			// dest path with filename
-
-	CDataBuffer dbBuffer;		// buffer handling
-	bool bOnlyCreate;			// flag from configuration - skips real copying - only create
-	bool bProcessed;			// has the element been processed ? (false if skipped)
-};
-
 ///////////////////////////////////////////////////////////////////////////
-// TTasksGlobalStats
-class TTasksGlobalStats
-{
-public:
-	TTasksGlobalStats();
-	~TTasksGlobalStats();
-
-	void IncreaseGlobalTotalSize(unsigned long long ullModify);
-	void DecreaseGlobalTotalSize(unsigned long long ullModify);
-	unsigned long long GetGlobalTotalSize() const;
-
-	void IncreaseGlobalProcessedSize(unsigned long long ullModify);
-	void DecreaseGlobalProcessedSize(unsigned long long ullModify);
-	unsigned long long GetGlobalProcessedSize() const;
-
-	void IncreaseGlobalProgressData(unsigned long long ullTasksPosition, unsigned long long ullTasksSize);
-	void DecreaseGlobalProgressData(unsigned long long ullTasksPosition, unsigned long long ullTasksSize);
-
-	int GetProgressPercents() const;
-
-	void IncreaseRunningTasks();
-	void DecreaseRunningTasks();
-	size_t GetRunningTasksCount() const;
-
-private:
-	volatile unsigned long long m_ullGlobalTotalSize;
-	volatile unsigned long long m_ullGlobalProcessedSize;
-
-	volatile size_t m_stRunningTasks;		// count of current operations
-	mutable boost::shared_mutex m_lock;
-};
-
-///////////////////////////////////////////////////////////////////////////
-// TTaskLocalStats
-class TTaskLocalStats
-{
-public:
-	TTaskLocalStats();
-	~TTaskLocalStats();
-
-	void ConnectGlobalStats(TTasksGlobalStats& rtGlobalStats);
-	void DisconnectGlobalStats();
-
-	void IncreaseProcessedSize(unsigned long long ullAdd);
-	void DecreaseProcessedSize(unsigned long long ullSub);
-	void SetProcessedSize(unsigned long long ullSet);
-	unsigned long long GetProcessedSize() const;
-	unsigned long long GetUnProcessedSize() const;
-
-	void IncreaseTotalSize(unsigned long long ullAdd);
-	void DecreaseTotalSize(unsigned long long ullSub);
-	void SetTotalSize(unsigned long long ullSet);
-	unsigned long long GetTotalSize() const;
-
-	int GetProgressInPercent() const;
-
-	void MarkTaskAsRunning();
-	void MarkTaskAsNotRunning();
-	bool IsRunning() const;
-
-	void SetTimeElapsed(time_t timeElapsed);
-	time_t GetTimeElapsed();
-
-	void EnableTimeTracking();
-	void DisableTimeTracking();
-	void UpdateTime();
-
-private:
-	volatile unsigned long long m_ullProcessedSize;
-	volatile unsigned long long m_ullTotalSize;
-
-	volatile bool m_bTaskIsRunning;
-
-	// time
-	volatile time_t m_timeElapsed;
-	volatile time_t m_timeLast;
-
-	mutable boost::shared_mutex m_lock;
-	TTasksGlobalStats* m_prtGlobalStats;
-};
-
-///////////////////////////////////////////////////////////////////////////
-// TTaskBasicProgressInfo
-
-class TTaskBasicProgressInfo
-{
-public:
-	TTaskBasicProgressInfo();
-	~TTaskBasicProgressInfo();
-
-	void SetCurrentIndex(size_t stIndex);	// might be unneeded when serialization is implemented
-	void IncreaseCurrentIndex();
-	size_t GetCurrentIndex() const;
-
-	void SetCurrentFileProcessedSize(unsigned long long ullSize);
-	unsigned long long GetCurrentFileProcessedSize() const;
-	void IncreaseCurrentFileProcessedSize(unsigned long long ullSizeToAdd);
-
-	void SetSubOperationIndex(size_t stSubOperationIndex);
-	size_t GetSubOperationIndex() const;
-	void IncreaseSubOperationIndex();
-
-	template<class Archive>
-	void load(Archive& ar, unsigned int /*uiVersion*/)
-	{
-		size_t stCurrentIndex = 0;
-		ar >> stCurrentIndex;
-
-		unsigned long long ullCurrentFileProcessedSize = 0;
-		ar >> ullCurrentFileProcessedSize;
-
-		size_t stSubOperationIndex = 0;
-		ar >> stSubOperationIndex;
-
-		boost::unique_lock<boost::shared_mutex> lock(m_lock);
-
-		m_stCurrentIndex = stCurrentIndex;
-		m_ullCurrentFileProcessedSize = ullCurrentFileProcessedSize;
-		m_stSubOperationIndex = stSubOperationIndex;
-	}
-
-	template<class Archive>
-	void save(Archive& ar, unsigned int /*uiVersion*/) const
-	{
-		m_lock.lock_shared();
-
-		size_t stCurrentIndex = m_stCurrentIndex;
-		unsigned long long ullCurrentFileProcessedSize = m_ullCurrentFileProcessedSize;
-		size_t stSubOperationIndex = m_stSubOperationIndex;
-		
-		m_lock.unlock_shared();
-
-		ar << stCurrentIndex;
-		ar << ullCurrentFileProcessedSize;
-		ar << stSubOperationIndex;
-	}
-
-	BOOST_SERIALIZATION_SPLIT_MEMBER();
-
-private:
-	volatile size_t m_stSubOperationIndex;		 // index of sub-operation from TOperationDescription
-	volatile size_t m_stCurrentIndex;   // index to the m_files array stating currently processed item
-	volatile unsigned long long m_ullCurrentFileProcessedSize;	// count of bytes processed for current file
-
-	mutable boost::shared_mutex m_lock;
-};
-
-///////////////////////////////////////////////////////////////////////////
 // CTask
 
 class CTask
 {
-protected:
-	// enum using internally by the CTask class to pass the operation results between methods
-	enum ESubOperationResult
-	{
-		eSubResult_Continue,
-		eSubResult_KillRequest,
-		eSubResult_Error,
-		eSubResult_CancelRequest,
-		eSubResult_PauseRequest
-	};
-
 public:
 	enum EPathType
 	{
@@ -336,41 +171,22 @@
 	/// Main function for the task processing thread
 	DWORD WINAPI ThrdProc();
 
-	ESubOperationResult RecurseDirectories();
-	int ScanDirectory(chcore::TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs);
+	TSubTaskBase::ESubOperationResult DeleteFiles();
 
-	ESubOperationResult ProcessFiles();
-	ESubOperationResult CustomCopyFileFB(CUSTOM_COPY_PARAMS* pData);
+	TSubTaskBase::ESubOperationResult CheckForWaitState();
 
-	ESubOperationResult DeleteFiles();
-
-	ESubOperationResult CheckForWaitState();
-
 	// Helper filesystem methods
-	static bool SetFileDirectoryTime(LPCTSTR lpszName, const CFileInfoPtr& spFileInfo);
-
 	bool GetRequiredFreeSpace(ull_t *pi64Needed, ull_t *pi64Available);
 
-	ESubOperationResult OpenSourceFileFB(TAutoFileHandle& hFile, const CFileInfoPtr& spSrcFileInfo, bool bNoBuffering);
-	ESubOperationResult OpenDestinationFileFB(TAutoFileHandle& hFile, const chcore::TSmartPath& pathDstFile, bool bNoBuffering, const CFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated);
-	ESubOperationResult OpenExistingDestinationFileFB(TAutoFileHandle& hFile, const chcore::TSmartPath& pathDstFilePath, bool bNoBuffering);
+	TSubTaskBase::ESubOperationResult CheckForFreeSpaceFB();
 
-	ESubOperationResult SetFilePointerFB(HANDLE hFile, long long llDistance, const chcore::TSmartPath& pathFile, bool& bSkip);
-	ESubOperationResult SetEndOfFileFB(HANDLE hFile, const chcore::TSmartPath& pathFile, bool& bSkip);
-
-	ESubOperationResult ReadFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToRead, DWORD& rdwBytesRead, const chcore::TSmartPath& pathFile, bool& bSkip);
-	ESubOperationResult WriteFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToWrite, DWORD& rdwBytesWritten, const chcore::TSmartPath& pathFile, bool& bSkip);
-
-	ESubOperationResult CheckForFreeSpaceFB();
-
 	// m_nStatus
 	void SetStatusNL(UINT nStatus, UINT nMask);
 	UINT GetStatusNL(UINT nMask = 0xffffffff);
 
 	void CalculateProcessedSize();
 	void CalculateProcessedSizeNL();
 
-	void CalculateTotalSize();
 	void CalculateTotalSizeNL();
 
 	void DeleteProgress();
@@ -392,16 +208,6 @@
 
 	static void OnCfgOptionChanged(const std::set<std::wstring>& rsetChanges, void* pParam);
 
-	chcore::TSmartPath FindFreeSubstituteName(chcore::TSmartPath pathSrcPath, chcore::TSmartPath pathDstPath) const;
-	chcore::TSmartPath GetDestinationPath(const CFileInfoPtr& spFileInfo, chcore::TSmartPath strPath, int iFlags) const;
-
-	int GetBufferIndex(const CFileInfoPtr& spFileInfo);
-	int GetDriveNumber(const CFileInfoPtr& spFileInfo);
-	bool GetMove(const CFileInfoPtr& spFileInfo);
-
-	static void GetDriveData(const chcore::TSmartPath& spPath, int *piDrvNum, UINT *puiDrvType);
-	static bool PathExist(chcore::TSmartPath strPath);	// check for file or folder existence
-
 private:
 	// task initial information (needed to start a task); might be a bit processed.
 	TTaskDefinition m_tTaskDefinition;