Index: src/ch/FeedbackHandler.cpp
===================================================================
diff -u -rd12e49decb8a3df3e28f6786d38542390484ac07 -r4d20d0e58f37f06ac91287015b960308db54d47e
--- src/ch/FeedbackHandler.cpp	(.../FeedbackHandler.cpp)	(revision d12e49decb8a3df3e28f6786d38542390484ac07)
+++ src/ch/FeedbackHandler.cpp	(.../FeedbackHandler.cpp)	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -57,7 +57,7 @@
 			if(!pFeedbackParam)
 				return eResult_Unknown;
 
-			FEEDBACK_ALREADYEXISTS* pData = (FEEDBACK_ALREADYEXISTS*)pFeedbackParam;
+			chcore::FEEDBACK_ALREADYEXISTS* pData = (chcore::FEEDBACK_ALREADYEXISTS*)pFeedbackParam;
 			CFeedbackReplaceDlg dlg(pData->spSrcFileInfo, pData->spDstFileInfo);
 			eFeedbackResult = (EFeedbackResult)dlg.DoModal();
 			bUseForAllItems = dlg.m_bAllItems;
@@ -70,7 +70,7 @@
 			if(!pFeedbackParam)
 				return eResult_Unknown;
 
-			FEEDBACK_FILEERROR* pData = (FEEDBACK_FILEERROR*)pFeedbackParam;
+			chcore::FEEDBACK_FILEERROR* pData = (chcore::FEEDBACK_FILEERROR*)pFeedbackParam;
 			CFeedbackFileErrorDlg dlg(pData->pszSrcPath, pData->pszDstPath, pData->ulError);
 			eFeedbackResult = (EFeedbackResult)dlg.DoModal();
 			bUseForAllItems = dlg.m_bAllItems;
@@ -83,7 +83,7 @@
 			if(!pFeedbackParam)
 				return eResult_Unknown;
 
-			FEEDBACK_NOTENOUGHSPACE* pData = (FEEDBACK_NOTENOUGHSPACE*)pFeedbackParam;
+			chcore::FEEDBACK_NOTENOUGHSPACE* pData = (chcore::FEEDBACK_NOTENOUGHSPACE*)pFeedbackParam;
 			CFeedbackNotEnoughSpaceDlg dlg(pData->ullRequiredSize, pData->pszSrcPath, pData->pszDstPath);
 			eFeedbackResult = (EFeedbackResult)dlg.DoModal();
 			bUseForAllItems = dlg.m_bAllItems;
Index: src/ch/FeedbackHandler.h
===================================================================
diff -u -r2aea3ad6f3c68be709ac65c70d9646eafe3b034c -r4d20d0e58f37f06ac91287015b960308db54d47e
--- src/ch/FeedbackHandler.h	(.../FeedbackHandler.h)	(revision 2aea3ad6f3c68be709ac65c70d9646eafe3b034c)
+++ src/ch/FeedbackHandler.h	(.../FeedbackHandler.h)	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -21,55 +21,8 @@
 
 #include "../libchcore/FeedbackHandlerBase.h"
 
-struct FEEDBACK_ALREADYEXISTS
-{
-	chcore::TFileInfoPtr spSrcFileInfo;
-	chcore::TFileInfoPtr spDstFileInfo;
-};
-
-struct FEEDBACK_FILEERROR
-{
-	const tchar_t* pszSrcPath;
-	const tchar_t* pszDstPath;
-	EFileError eFileError;			// error type
-	ulong_t ulError;				// system error
-};
-
-struct FEEDBACK_NOTENOUGHSPACE
-{
-	ull_t ullRequiredSize;
-	const tchar_t* pszSrcPath;
-	const tchar_t* pszDstPath;
-};
-
 class CFeedbackHandler : public chcore::IFeedbackHandler
 {
-public:
-	enum EFeedbackType
-	{
-		eFT_Unknown = 0,
-		// requests for use feedback
-		eFT_FileAlreadyExists,
-		eFT_FileError,
-		eFT_NotEnoughSpace,
-		// notifications
-		eFT_OperationFinished,	///< Task has finished processing
-		eFT_OperationError,		///< Error encountered while processing task
-		eFT_LastType
-	};
-
-	enum EFeedbackResult
-	{
-		eResult_Unknown = 0,
-		eResult_Overwrite,
-		eResult_CopyRest,
-		eResult_Skip,
-		eResult_Cancel,
-		eResult_Pause,
-		eResult_Retry,
-		eResult_Ignore
-	};
-
 protected:
 	CFeedbackHandler();
 	~CFeedbackHandler();
Fisheye: Tag 4d20d0e58f37f06ac91287015b960308db54d47e refers to a dead (removed) revision in file `src/ch/TSubTaskContext.h'.
Fisheye: No comparison available.  Pass `N' to diff?
Fisheye: Tag 4d20d0e58f37f06ac91287015b960308db54d47e refers to a dead (removed) revision in file `src/ch/TSubTaskCopyMove.h'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/ch/ch.vc90.vcproj
===================================================================
diff -u -rfb4c4006dee5aaf815d08bc3e89312445b994307 -r4d20d0e58f37f06ac91287015b960308db54d47e
--- src/ch/ch.vc90.vcproj	(.../ch.vc90.vcproj)	(revision fb4c4006dee5aaf815d08bc3e89312445b994307)
+++ src/ch/ch.vc90.vcproj	(.../ch.vc90.vcproj)	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -434,14 +434,6 @@
 					RelativePath=".\task.h"
 					>
 				</File>
-				<File
-					RelativePath=".\TSubTaskContext.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\TSubTaskContext.h"
-					>
-				</File>
 				<Filter
 					Name="NewProgressTracking"
 					>
@@ -462,42 +454,6 @@
 						>
 					</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>
 			<Filter
 				Name="Tools"
Index: src/ch/task.cpp
===================================================================
diff -u -rfb4c4006dee5aaf815d08bc3e89312445b994307 -r4d20d0e58f37f06ac91287015b960308db54d47e
--- src/ch/task.cpp	(.../task.cpp)	(revision fb4c4006dee5aaf815d08bc3e89312445b994307)
+++ src/ch/task.cpp	(.../task.cpp)	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -28,12 +28,12 @@
 #include "FeedbackHandler.h"
 
 #include "../libchcore/TTaskConfiguration.h"
-#include "TSubTaskContext.h"
+#include "../libchcore/TSubTaskContext.h"
 
 #include "../libchcore/TLocalFilesystem.h"
-#include "TSubTaskScanDirectory.h"
-#include "TSubTaskCopyMove.h"
-#include "TSubTaskDelete.h"
+#include "../libchcore/TSubTaskScanDirectory.h"
+#include "../libchcore/TSubTaskCopyMove.h"
+#include "../libchcore/TSubTaskDelete.h"
 #include "FileSupport.h"
 #include "../libchcore/TBinarySerializer.h"
 #include "../libchcore/SerializationHelpers.h"
@@ -556,7 +556,7 @@
 	return m_bContinue;
 }
 
-TSubTaskBase::ESubOperationResult CTask::CheckForWaitState()
+chcore::TSubTaskBase::ESubOperationResult CTask::CheckForWaitState()
 {
 	// limiting operation count
 	SetTaskState(eTaskState_Waiting);
@@ -579,11 +579,11 @@
 		{
 			// log
 			m_log.logi(_T("Kill request while waiting for begin permission (wait state)"));
-			return TSubTaskBase::eSubResult_KillRequest;
+			return chcore::TSubTaskBase::eSubResult_KillRequest;
 		}
 	}
 
-	return TSubTaskBase::eSubResult_Continue;
+	return chcore::TSubTaskBase::eSubResult_Continue;
 }
 
 DWORD WINAPI CTask::DelegateThreadProc(LPVOID pParam)
@@ -600,7 +600,7 @@
 {
 	try
 	{
-		TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue;
+		chcore::TSubTaskBase::ESubOperationResult eResult = chcore::TSubTaskBase::eSubResult_Continue;
 
 		// initialize log file
 		chcore::TSmartPath pathLogFile = GetRelatedPath(ePathType_TaskLogFile);
@@ -630,9 +630,9 @@
 		m_localStats.EnableTimeTracking();
 
 		// prepare context for subtasks
-		TSubTaskContext tSubTaskContext(m_tTaskDefinition, m_arrSourcePathsInfo, m_files, m_localStats, m_tTaskBasicProgressInfo, m_cfgTracker, m_log, m_piFeedbackHandler, m_workerThread, m_fsLocal);
+		chcore::TSubTaskContext tSubTaskContext(m_tTaskDefinition, m_arrSourcePathsInfo, m_files, m_localStats, m_tTaskBasicProgressInfo, m_cfgTracker, m_log, m_piFeedbackHandler, m_workerThread, m_fsLocal);
 
-		for(; stSubOperationIndex < m_tTaskDefinition.GetOperationPlan().GetSubOperationsCount() && eResult == TSubTaskBase::eSubResult_Continue; ++stSubOperationIndex)
+		for(; stSubOperationIndex < m_tTaskDefinition.GetOperationPlan().GetSubOperationsCount() && eResult == chcore::TSubTaskBase::eSubResult_Continue; ++stSubOperationIndex)
 		{
 			// set current sub-operation index to allow resuming
 			m_tTaskBasicProgressInfo.SetSubOperationIndex(stSubOperationIndex);
@@ -643,12 +643,11 @@
 			case chcore::eSubOperation_Scanning:
 				{
 					// start searching
-					TSubTaskScanDirectories tSubTaskScanDir(tSubTaskContext);
-					//eResult = RecurseDirectories();
+					chcore::TSubTaskScanDirectories tSubTaskScanDir(tSubTaskContext);
 					eResult = tSubTaskScanDir.Exec();
 
 					// 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)
+					if(eResult == chcore::TSubTaskBase::eSubResult_Continue && bReadTasksSize && stSubOperationIndex == 0)
 					{
 						m_localStats.DisableTimeTracking();
 
@@ -662,15 +661,15 @@
 
 			case chcore::eSubOperation_Copying:
 				{
-					TSubTaskCopyMove tSubTaskCopyMove(tSubTaskContext);
+					chcore::TSubTaskCopyMove tSubTaskCopyMove(tSubTaskContext);
 
 					eResult = tSubTaskCopyMove.Exec();
 					break;
 				}
 
 			case chcore::eSubOperation_Deleting:
 				{
-					TSubTaskDelete tSubTaskDelete(tSubTaskContext);
+					chcore::TSubTaskDelete tSubTaskDelete(tSubTaskContext);
 					eResult = tSubTaskDelete.Exec();
 					break;
 				}
@@ -682,7 +681,7 @@
 		}
 
 		// change status to finished
-		if(eResult == TSubTaskBase::eSubResult_Continue)
+		if(eResult == chcore::TSubTaskBase::eSubResult_Continue)
 			SetTaskState(eTaskState_Finished);
 
 		// refresh time
@@ -692,26 +691,26 @@
 		// change task status
 		switch(eResult)
 		{
-		case TSubTaskBase::eSubResult_Error:
+		case chcore::TSubTaskBase::eSubResult_Error:
 			m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_OperationError, NULL);
 			SetTaskState(eTaskState_Error);
 			break;
 
-		case TSubTaskBase::eSubResult_CancelRequest:
+		case chcore::TSubTaskBase::eSubResult_CancelRequest:
 			SetTaskState(eTaskState_Cancelled);
 			break;
 
-		case TSubTaskBase::eSubResult_PauseRequest:
+		case chcore::TSubTaskBase::eSubResult_PauseRequest:
 			SetTaskState(eTaskState_Paused);
 			break;
 
-		case TSubTaskBase::eSubResult_KillRequest:
+		case chcore::TSubTaskBase::eSubResult_KillRequest:
 			// the only operation 
 			if(GetTaskState() == eTaskState_Waiting)
 				SetTaskState(eTaskState_Processing);
 			break;
 
-		case TSubTaskBase::eSubResult_Continue:
+		case chcore::TSubTaskBase::eSubResult_Continue:
 			m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_OperationFinished, NULL);
 			SetTaskState(eTaskState_Finished);
 			break;
Index: src/ch/task.h
===================================================================
diff -u -rfb4c4006dee5aaf815d08bc3e89312445b994307 -r4d20d0e58f37f06ac91287015b960308db54d47e
--- src/ch/task.h	(.../task.h)	(revision fb4c4006dee5aaf815d08bc3e89312445b994307)
+++ src/ch/task.h	(.../task.h)	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -28,7 +28,7 @@
 #include "../libchcore/TTaskDefinition.h"
 #include "../libchcore/TTaskConfigTracker.h"
 #include "../libchcore/TBasePathData.h"
-#include "TSubTaskBase.h"
+#include "../libchcore/TSubTaskBase.h"
 #include "../libchcore/TTaskLocalStats.h"
 #include "../libchcore/TTaskGlobalStats.h"
 #include "../libchcore/TBasicProgressInfo.h"
@@ -174,7 +174,7 @@
 	/// Main function for the task processing thread
 	DWORD WINAPI ThrdProc();
 
-	TSubTaskBase::ESubOperationResult CheckForWaitState();
+	chcore::TSubTaskBase::ESubOperationResult CheckForWaitState();
 
 	// m_nStatus
 	void SetStatusNL(UINT nStatus, UINT nMask);
Index: src/libchcore/ErrorCodes.h
===================================================================
diff -u -rfb4c4006dee5aaf815d08bc3e89312445b994307 -r4d20d0e58f37f06ac91287015b960308db54d47e
--- src/libchcore/ErrorCodes.h	(.../ErrorCodes.h)	(revision fb4c4006dee5aaf815d08bc3e89312445b994307)
+++ src/libchcore/ErrorCodes.h	(.../ErrorCodes.h)	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -69,6 +69,7 @@
 
 	// Filesystem errors
 	eErr_FixedDriveWithoutDriveLetter = 3000,
+	eErr_CannotGetFileInfo = 3001,
 };
 
 END_CHCORE_NAMESPACE
Index: src/libchcore/FeedbackHandlerBase.h
===================================================================
diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r4d20d0e58f37f06ac91287015b960308db54d47e
--- src/libchcore/FeedbackHandlerBase.h	(.../FeedbackHandlerBase.h)	(revision d5c3edd0d167db9b5d47d04248820fda49499a5e)
+++ src/libchcore/FeedbackHandlerBase.h	(.../FeedbackHandlerBase.h)	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -21,12 +21,60 @@
 
 #include "libchcore.h"
 #include "../libicpf/interface.h"
+#include "../common/ErrorConstants.h"
 
 BEGIN_CHCORE_NAMESPACE
 
+struct FEEDBACK_ALREADYEXISTS
+{
+	chcore::TFileInfoPtr spSrcFileInfo;
+	chcore::TFileInfoPtr spDstFileInfo;
+};
+
+struct FEEDBACK_FILEERROR
+{
+	const wchar_t* pszSrcPath;
+	const wchar_t* pszDstPath;
+	EFileError eFileError;			// error type
+	ulong_t ulError;				// system error
+};
+
+struct FEEDBACK_NOTENOUGHSPACE
+{
+	ull_t ullRequiredSize;
+	const wchar_t* pszSrcPath;
+	const wchar_t* pszDstPath;
+};
+
 class IFeedbackHandler : public icpf::IInterface
 {
 public:
+	enum EFeedbackType
+	{
+		eFT_Unknown = 0,
+		// requests for use feedback
+		eFT_FileAlreadyExists,
+		eFT_FileError,
+		eFT_NotEnoughSpace,
+		// notifications
+		eFT_OperationFinished,	///< Task has finished processing
+		eFT_OperationError,		///< Error encountered while processing task
+		eFT_LastType
+	};
+
+	enum EFeedbackResult
+	{
+		eResult_Unknown = 0,
+		eResult_Overwrite,
+		eResult_CopyRest,
+		eResult_Skip,
+		eResult_Cancel,
+		eResult_Pause,
+		eResult_Retry,
+		eResult_Ignore
+	};
+
+public:
 	virtual ull_t RequestFeedback(ull_t ullFeedbackID, ptr_t pFeedbackParam) = 0;
 };
 
Index: src/libchcore/TSubTaskBase.cpp
===================================================================
diff -u
--- src/libchcore/TSubTaskBase.cpp	(revision 0)
+++ src/libchcore/TSubTaskBase.cpp	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -0,0 +1,113 @@
+// ============================================================================
+//  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  TSubTaskBase.cpp
+/// @date  2010/09/19
+/// @brief Contains implementation of some common subtask elements.
+// ============================================================================
+#include "stdafx.h"
+#include "TSubTaskBase.h"
+#include "TBasePathData.h"
+#include "TLocalFilesystem.h"
+#include "TSubTaskContext.h"
+#include "TTaskDefinition.h"
+#include "TTaskConfiguration.h"
+#include <boost/lexical_cast.hpp>
+
+BEGIN_CHCORE_NAMESPACE
+
+///////////////////////////////////////////////////////////////////////////
+// TSubTaskBase
+
+TSubTaskBase::TSubTaskBase(TSubTaskContext& rContext) :
+m_rContext(rContext)
+{
+}
+
+TSubTaskBase::~TSubTaskBase()
+{
+}
+
+TSmartPath TSubTaskBase::CalculateDestinationPath(const TFileInfoPtr& spFileInfo, TSmartPath pathDst, int iFlags) const
+{
+	const TBasePathDataContainer& rSourcePathsInfo = GetContext().GetBasePathDataContainer();
+
+	if(!spFileInfo)
+		THROW_CORE_EXCEPTION(eErr_InvalidArgument);
+
+	// iFlags: bit 0-ignore folders; bit 1-force creating directories
+	if(iFlags & 0x02)
+	{
+		// force create directories
+		TSmartPath pathCombined = pathDst + spFileInfo->GetFullFilePath().GetFileDir();
+
+		// force create directory
+		TLocalFilesystem::CreateDirectory(pathCombined, true);
+
+		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())
+			{
+				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
+TSmartPath TSubTaskBase::FindFreeSubstituteName(TSmartPath pathSrcPath, TSmartPath pathDstPath) const
+{
+	const TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+
+	// get the name from src path
+	pathSrcPath.StripSeparatorAtEnd();
+
+	TSmartPath pathFilename = pathSrcPath.GetFileName();
+
+	// set the dest path
+	TString strCheckPath = GetTaskPropValue<eTO_AlternateFilenameFormatString_First>(rTaskDefinition.GetConfiguration());
+	strCheckPath.Replace(_T("%name"), pathFilename.ToString());
+	TSmartPath pathCheckPath(PathFromString(strCheckPath));
+
+	// when adding to strDstPath check if the path already exists - if so - try again
+	int iCounter = 1;
+	TString strFmt = GetTaskPropValue<eTO_AlternateFilenameFormatString_AfterFirst>(rTaskDefinition.GetConfiguration());
+	while(TLocalFilesystem::PathExist(pathDstPath + pathCheckPath))
+	{
+		strCheckPath = strFmt;
+		strCheckPath.Replace(_t("%name"), pathFilename.ToString());
+		strCheckPath.Replace(_t("%count"), boost::lexical_cast<std::wstring>(++iCounter).c_str());
+		pathCheckPath.FromString(strCheckPath);
+	}
+
+	return pathCheckPath;
+}
+
+END_CHCORE_NAMESPACE
Fisheye: tag 2aea3ad6f3c68be709ac65c70d9646eafe3b034c is not in file src/libchcore/TSubTaskBase.h
Fisheye: Tag 4d20d0e58f37f06ac91287015b960308db54d47e refers to a dead (removed) revision in file `src/ch/TSubTaskBase.h'.
Fisheye: No comparison available.  Pass `N' to diff?
Fisheye: tag fb4c4006dee5aaf815d08bc3e89312445b994307 is not in file src/libchcore/TSubTaskContext.cpp
Fisheye: Tag 4d20d0e58f37f06ac91287015b960308db54d47e refers to a dead (removed) revision in file `src/ch/TSubTaskContext.cpp'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/libchcore/TSubTaskContext.h
===================================================================
diff -u
--- src/libchcore/TSubTaskContext.h	(revision 0)
+++ src/libchcore/TSubTaskContext.h	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -0,0 +1,121 @@
+// ============================================================================
+//  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  TSubTaskContext.h
+/// @date  2010/09/19
+/// @brief Contains declaration of subtask context class.
+// ============================================================================
+#ifndef __TSUBTASKCONTEXT_H__
+#define __TSUBTASKCONTEXT_H__
+
+#include "libchcore.h"
+
+namespace icpf
+{
+	class log_file;
+}
+
+BEGIN_CHCORE_NAMESPACE
+
+class IFeedbackHandler;
+class TTaskDefinition;
+class TWorkerThreadController;
+class TBasePathDataContainer;
+class TTaskConfigTracker;
+class TLocalFilesystem;
+class TTaskLocalStats;
+class TTaskBasicProgressInfo;
+class TFileInfoArray;
+
+///////////////////////////////////////////////////////////////////////////
+// TSubTaskContext
+
+class LIBCHCORE_API TSubTaskContext
+{
+public:
+	TSubTaskContext(TTaskDefinition& rTaskDefinition, TBasePathDataContainer& rBasePathDataContainer, TFileInfoArray& rFilesCache, TTaskLocalStats& rTaskLocalStats,
+		TTaskBasicProgressInfo& rTaskBasicProgressInfo, TTaskConfigTracker& rCfgTracker, icpf::log_file& rLog,
+		IFeedbackHandler* piFeedbackHandler, TWorkerThreadController& rThreadController, TLocalFilesystem& rfsLocal);
+	~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; }
+
+	TFileInfoArray& GetFilesCache() { return m_rFilesCache; }
+	const TFileInfoArray& 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; }
+
+	IFeedbackHandler* GetFeedbackHandler() { return m_piFeedbackHandler; }
+	const IFeedbackHandler* GetFeedbackHandler() const { return m_piFeedbackHandler; }
+
+	TWorkerThreadController& GetThreadController() { return m_rThreadController; }
+	const TWorkerThreadController& GetThreadController() const { return m_rThreadController; }
+
+	TLocalFilesystem& GetLocalFilesystem() { return m_rfsLocal; }
+	const TLocalFilesystem& GetLocalFilesystem() const { return m_rfsLocal; }
+
+private:
+	TSubTaskContext(const TSubTaskContext& rSrc);
+	TSubTaskContext& operator=(const TSubTaskContext& rSrc);
+
+private:
+	TTaskDefinition& m_rTaskDefinition;
+
+	// information about input paths
+	TBasePathDataContainer& m_rBasePathDataContainer;
+
+	// data on which to operate
+	TFileInfoArray& m_rFilesCache;
+
+	// local stats for task
+	TTaskLocalStats& m_rTaskLocalStats;
+	TTaskBasicProgressInfo& m_rTaskBasicProgressInfo;
+
+	// configuration changes tracking
+	TTaskConfigTracker& m_rCfgTracker;
+
+	// local filesystem access functions
+	TLocalFilesystem& m_rfsLocal;
+
+	// additional data
+	icpf::log_file& m_rLog;
+
+	// feedback handling
+	IFeedbackHandler* m_piFeedbackHandler;
+
+	// thread control
+	TWorkerThreadController& m_rThreadController;
+};
+
+END_CHCORE_NAMESPACE
+
+#endif // __TSUBTASKCONTEXT_H__
Index: src/libchcore/TSubTaskCopyMove.cpp
===================================================================
diff -u
--- src/libchcore/TSubTaskCopyMove.cpp	(revision 0)
+++ src/libchcore/TSubTaskCopyMove.cpp	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -0,0 +1,1123 @@
+// ============================================================================
+//  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  TSubTaskCopyMove.cpp
+/// @date  2010/09/19
+/// @brief Contains implementations of classes responsible for copy and move sub-operation.
+// ============================================================================
+#include "stdafx.h"
+#include "TSubTaskCopyMove.h"
+#include "TSubTaskContext.h"
+#include "TTaskConfiguration.h"
+#include "TTaskDefinition.h"
+#include "TLocalFilesystem.h"
+#include "DataBuffer.h"
+#include "../libicpf/log.h"
+#include "TTaskLocalStats.h"
+#include "TBasicProgressInfo.h"
+#include "TTaskConfigTracker.h"
+#include "TWorkerThreadController.h"
+#include "FeedbackHandlerBase.h"
+#include <boost/lexical_cast.hpp>
+#include "TBasePathData.h"
+#include <boost/smart_ptr/make_shared.hpp>
+
+BEGIN_CHCORE_NAMESPACE
+
+// assume max sectors of 4kB (for rounding)
+#define MAXSECTORSIZE			4096
+
+struct CUSTOM_COPY_PARAMS
+{
+	TFileInfoPtr spSrcFile;		// CFileInfo - src file
+	TSmartPath pathDstFile;			// dest path with filename
+
+	TDataBuffer 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();
+	TFileInfoArray& rFilesCache = GetContext().GetFilesCache();
+	TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+	TTaskConfigTracker& rCfgTracker = GetContext().GetCfgTracker();
+	TTaskBasicProgressInfo& rBasicProgressInfo = GetContext().GetTaskBasicProgressInfo();
+	TWorkerThreadController& rThreadController = GetContext().GetThreadController();
+	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()));
+
+	// now it's time to check if there is enough space on destination device
+	TSubTaskBase::ESubOperationResult eResult = CheckForFreeSpaceFB();
+	if(eResult != TSubTaskBase::eSubResult_Continue)
+		return eResult;
+
+	// 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);
+
+	TBufferSizes bs;
+	bs.SetOnlyDefault(GetTaskPropValue<eTO_UseOnlyDefaultBuffer>(rTaskDefinition.GetConfiguration()));
+	bs.SetDefaultSize(GetTaskPropValue<eTO_DefaultBufferSize>(rTaskDefinition.GetConfiguration()));
+	bs.SetOneDiskSize(GetTaskPropValue<eTO_OneDiskBufferSize>(rTaskDefinition.GetConfiguration()));
+	bs.SetTwoDisksSize(GetTaskPropValue<eTO_TwoDisksBufferSize>(rTaskDefinition.GetConfiguration()));
+	bs.SetCDSize(GetTaskPropValue<eTO_CDBufferSize>(rTaskDefinition.GetConfiguration()));
+	bs.SetLANSize(GetTaskPropValue<eTO_LANBufferSize>(rTaskDefinition.GetConfiguration()));
+
+	ccp.dbBuffer.Create(bs);
+
+	// helpers
+	DWORD dwLastError = 0;
+
+	// log
+	const TBufferSizes& rbs = ccp.dbBuffer.GetSizes();
+
+	TString strFormat;
+	strFormat = _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");
+	strFormat.Replace(_T("%create"), boost::lexical_cast<std::wstring>(ccp.bOnlyCreate).c_str());
+	strFormat.Replace(_T("%defsize"), boost::lexical_cast<std::wstring>(rbs.GetDefaultSize()).c_str());
+	strFormat.Replace(_T("%onesize"), boost::lexical_cast<std::wstring>(rbs.GetOneDiskSize()).c_str());
+	strFormat.Replace(_T("%twosize"), boost::lexical_cast<std::wstring>(rbs.GetTwoDisksSize()).c_str());
+	strFormat.Replace(_T("%cdsize"), boost::lexical_cast<std::wstring>(rbs.GetCDSize()).c_str());
+	strFormat.Replace(_T("%lansize"), boost::lexical_cast<std::wstring>(rbs.GetLANSize()).c_str());
+	strFormat.Replace(_T("%filecount"), boost::lexical_cast<std::wstring>(stSize).c_str());
+	strFormat.Replace(_T("%ignorefolders"), boost::lexical_cast<std::wstring>(bIgnoreFolders).c_str());
+	strFormat.Replace(_T("%dstpath"), rTaskDefinition.GetDestinationPath().ToString());
+	strFormat.Replace(_T("%currindex"), boost::lexical_cast<std::wstring>(rBasicProgressInfo.GetCurrentIndex()).c_str());
+
+	rLog.logi(strFormat);
+
+	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
+		TFileInfoPtr 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 ?
+		wchar_t wchDestinationDrive = rTaskDefinition.GetDestinationPath().GetDriveLetter();
+		bool bMove = rTaskDefinition.GetOperationType() == eOperation_Move;
+		TSmartPath pathCurrent = spFileInfo->GetFullFilePath();
+		if(bMove && wchDestinationDrive != L'\0' && wchDestinationDrive == pathCurrent.GetDriveLetter() && GetMove(spFileInfo))
+		{
+			bool bRetry = true;
+			if(bRetry && !TLocalFilesystem::FastMove(pathCurrent, ccp.pathDstFile))
+			{
+				dwLastError=GetLastError();
+				//log
+				strFormat = _T("Error %errno while calling MoveFile %srcpath -> %dstpath (ProcessFiles)");
+				strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+				strFormat.Replace(_T("%srcpath"), spFileInfo->GetFullFilePath().ToString());
+				strFormat.Replace(_T("%dstpath"), ccp.pathDstFile.ToString());
+				rLog.loge(strFormat);
+
+				FEEDBACK_FILEERROR ferr = { spFileInfo->GetFullFilePath().ToString(), ccp.pathDstFile.ToString(), eFastMoveError, dwLastError };
+				IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+				switch(frResult)
+				{
+				case IFeedbackHandler::eResult_Cancel:
+					return TSubTaskBase::eSubResult_CancelRequest;
+
+				case IFeedbackHandler::eResult_Retry:
+					continue;
+
+				case IFeedbackHandler::eResult_Pause:
+					return TSubTaskBase::eSubResult_PauseRequest;
+
+				case IFeedbackHandler::eResult_Skip:
+					bRetry = false;
+					break;		// just do nothing
+				default:
+					BOOST_ASSERT(FALSE);		// unknown result
+					THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+				}
+			}
+			else
+				spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED);
+		}
+		else
+		{
+			// if folder - create it
+			if(spFileInfo->IsDirectory())
+			{
+				bool bRetry = true;
+				if(bRetry && !TLocalFilesystem::CreateDirectory(ccp.pathDstFile, false) && (dwLastError=GetLastError()) != ERROR_ALREADY_EXISTS )
+				{
+					// log
+					strFormat = _T("Error %errno while calling CreateDirectory %path (ProcessFiles)");
+					strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+					strFormat.Replace(_T("%path"), ccp.pathDstFile.ToString());
+					rLog.loge(strFormat);
+
+					FEEDBACK_FILEERROR ferr = { ccp.pathDstFile.ToString(), NULL, eCreateError, dwLastError };
+					IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+					switch(frResult)
+					{
+					case IFeedbackHandler::eResult_Cancel:
+						return TSubTaskBase::eSubResult_CancelRequest;
+
+					case IFeedbackHandler::eResult_Retry:
+						continue;
+
+					case IFeedbackHandler::eResult_Pause:
+						return TSubTaskBase::eSubResult_PauseRequest;
+
+					case IFeedbackHandler::eResult_Skip:
+						bRetry = false;
+						break;		// just do nothing
+					default:
+						BOOST_ASSERT(FALSE);		// unknown result
+						THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+					}
+				}
+
+				rLocalStats.IncreaseProcessedSize(spFileInfo->GetLength64());
+				spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED);
+			}
+			else
+			{
+				// start copying/moving file
+				ccp.spSrcFile = spFileInfo;
+				ccp.bProcessed = false;
+
+				// copy data
+				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()))
+						TLocalFilesystem::SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL);
+					TLocalFilesystem::DeleteFile(spFileInfo->GetFullFilePath());	// 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, spFileInfo->GetCreationTime(), spFileInfo->GetLastAccessTime(), spFileInfo->GetLastWriteTime()); // no error checking (but most probably it should be checked)
+
+			// attributes
+			if(GetTaskPropValue<eTO_SetDestinationAttributes>(rTaskDefinition.GetConfiguration()))
+				TLocalFilesystem::SetAttributes(ccp.pathDstFile, 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 TFileInfoPtr& spFileInfo)
+{
+	if(!spFileInfo)
+		THROW_CORE_EXCEPTION(eErr_InvalidArgument);
+	if(spFileInfo->GetSrcIndex() == std::numeric_limits<size_t>::max())
+		THROW_CORE_EXCEPTION(eErr_InvalidArgument);
+
+	// check if this information has already been stored
+	size_t stBaseIndex = spFileInfo->GetSrcIndex();
+	if(stBaseIndex >= GetContext().GetBasePathDataContainer().GetCount())
+		THROW_CORE_EXCEPTION(eErr_BoundsExceeded);
+
+	TBasePathDataPtr spPathData = GetContext().GetBasePathDataContainer().GetAt(stBaseIndex);
+	return spPathData->GetMove();
+}
+
+int TSubTaskCopyMove::GetBufferIndex(const TFileInfoPtr& spFileInfo)
+{
+	if(!spFileInfo)
+		THROW_CORE_EXCEPTION(eErr_InvalidArgument);
+
+	TSmartPath pathSource = spFileInfo->GetFullFilePath();
+	TSmartPath pathDestination = GetContext().GetTaskDefinition().GetDestinationPath();
+
+	TLocalFilesystem::EPathsRelation eRelation = GetContext().GetLocalFilesystem().GetPathsRelation(pathSource, pathDestination);
+	switch(eRelation)
+	{
+	case TLocalFilesystem::eRelation_Network:
+		return TBufferSizes::eBuffer_LAN;
+
+	case TLocalFilesystem::eRelation_CDRom:
+		return TBufferSizes::eBuffer_CD;
+
+	case TLocalFilesystem::eRelation_TwoPhysicalDisks:
+		return TBufferSizes::eBuffer_TwoDisks;
+
+	case TLocalFilesystem::eRelation_SinglePhysicalDisk:
+		return TBufferSizes::eBuffer_OneDisk;
+
+	//case eRelation_Other:
+	default:
+		return TBufferSizes::eBuffer_Default;
+	}
+}
+
+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();
+
+	TLocalFilesystemFile fileSrc = TLocalFilesystem::CreateFileObject();
+	TLocalFilesystemFile fileDst = TLocalFilesystem::CreateFileObject();
+
+	TString strFormat;
+	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(fileSrc, pData->spSrcFile->GetFullFilePath(), bNoBuffer);
+	if(eResult != TSubTaskBase::eSubResult_Continue)
+		return eResult;
+	else if(!fileSrc.IsOpen())
+	{
+		// 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(fileDst, pData->pathDstFile, bNoBuffer, pData->spSrcFile, ullSeekTo, bDstFileFreshlyCreated);
+		if(eResult != TSubTaskBase::eSubResult_Continue)
+			return eResult;
+		else if(!fileDst.IsOpen())
+		{
+			rLocalStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - rBasicProgressInfo.GetCurrentFileProcessedSize());
+			pData->bProcessed = false;
+			return TSubTaskBase::eSubResult_Continue;
+		}
+	}
+	else
+	{
+		// we are resuming previous operation
+		eResult = OpenExistingDestinationFileFB(fileDst, pData->pathDstFile, bNoBuffer);
+		if(eResult != TSubTaskBase::eSubResult_Continue)
+			return eResult;
+		else if(!fileDst.IsOpen())
+		{
+			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(fileSrc, 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(fileDst, 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(fileDst, 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
+				strFormat = _T("Kill request while main copying file %srcpath -> %dstpath");
+				strFormat.Replace(_T("%srcpath"), pData->spSrcFile->GetFullFilePath().ToString());
+				strFormat.Replace(_T("%dstpath"), pData->pathDstFile.ToString());
+				rLog.logi(strFormat);
+				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))
+			{
+				TBufferSizes bs;
+				bs.SetOnlyDefault(GetTaskPropValue<eTO_UseOnlyDefaultBuffer>(rTaskDefinition.GetConfiguration()));
+				bs.SetDefaultSize(GetTaskPropValue<eTO_DefaultBufferSize>(rTaskDefinition.GetConfiguration()));
+				bs.SetOneDiskSize(GetTaskPropValue<eTO_OneDiskBufferSize>(rTaskDefinition.GetConfiguration()));
+				bs.SetTwoDisksSize(GetTaskPropValue<eTO_TwoDisksBufferSize>(rTaskDefinition.GetConfiguration()));
+				bs.SetCDSize(GetTaskPropValue<eTO_CDBufferSize>(rTaskDefinition.GetConfiguration()));
+				bs.SetLANSize(GetTaskPropValue<eTO_LANBufferSize>(rTaskDefinition.GetConfiguration()));
+
+				// log
+				const TBufferSizes& rbs1 = pData->dbBuffer.GetSizes();
+
+				strFormat = _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)");
+
+				strFormat.Replace(_T("%defsize"), boost::lexical_cast<std::wstring>(rbs1.GetDefaultSize()).c_str());
+				strFormat.Replace(_T("%onesize"), boost::lexical_cast<std::wstring>(rbs1.GetOneDiskSize()).c_str());
+				strFormat.Replace(_T("%twosize"), boost::lexical_cast<std::wstring>(rbs1.GetTwoDisksSize()).c_str());
+				strFormat.Replace(_T("%cdsize"), boost::lexical_cast<std::wstring>(rbs1.GetCDSize()).c_str());
+				strFormat.Replace(_T("%lansize"), boost::lexical_cast<std::wstring>(rbs1.GetLANSize()).c_str());
+				strFormat.Replace(_T("%defsize2"), boost::lexical_cast<std::wstring>(bs.GetDefaultSize()).c_str());
+				strFormat.Replace(_T("%onesize2"), boost::lexical_cast<std::wstring>(bs.GetOneDiskSize()).c_str());
+				strFormat.Replace(_T("%twosize2"), boost::lexical_cast<std::wstring>(bs.GetTwoDisksSize()).c_str());
+				strFormat.Replace(_T("%cdsize2"), boost::lexical_cast<std::wstring>(bs.GetCDSize()).c_str());
+				strFormat.Replace(_T("%lansize2"), boost::lexical_cast<std::wstring>(bs.GetLANSize()).c_str());
+				strFormat.Replace(_T("%srcfile"), pData->spSrcFile->GetFullFilePath().ToString());
+				strFormat.Replace(_T("%dstfile"), pData->pathDstFile.ToString());
+
+				rLog.logi(strFormat);
+				pData->dbBuffer.Create(bs);
+			}
+
+			// establish count of data to read
+			if(GetTaskPropValue<eTO_UseOnlyDefaultBuffer>(rTaskDefinition.GetConfiguration()))
+				iBufferIndex = TBufferSizes::eBuffer_Default;
+			else
+				iBufferIndex = GetBufferIndex(pData->spSrcFile);
+			rLocalStats.SetCurrentBufferIndex(iBufferIndex);
+
+			ulToRead = bNoBuffer ? ROUNDUP(pData->dbBuffer.GetSizes().GetSizeByType((TBufferSizes::EBufferType)iBufferIndex), MAXSECTORSIZE) : pData->dbBuffer.GetSizes().GetSizeByType((TBufferSizes::EBufferType)iBufferIndex);
+
+			// read data from file to buffer
+			eResult = ReadFileFB(fileSrc, 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(fileDst, 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
+					fileDst.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(fileDst, pData->pathDstFile, false);
+						if(eResult != TSubTaskBase::eSubResult_Continue)
+							return eResult;
+						else if(!fileDst.IsOpen())
+						{
+							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(fileDst, 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(fileDst, 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(TLocalFilesystemFile& fileSrc, const TSmartPath& spPathToOpen, bool bNoBuffering)
+{
+	IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+	icpf::log_file& rLog = GetContext().GetLog();
+
+	BOOST_ASSERT(!spPathToOpen.IsEmpty());
+	if(spPathToOpen.IsEmpty())
+		THROW_CORE_EXCEPTION(eErr_InvalidArgument);
+
+	bool bRetry = false;
+
+	fileSrc.Close();
+
+	do
+	{
+		bRetry = false;
+
+		if(!fileSrc.OpenExistingForReading(spPathToOpen, bNoBuffering))
+		{
+			DWORD dwLastError = GetLastError();
+
+			FEEDBACK_FILEERROR feedStruct = { spPathToOpen.ToString(), NULL, eCreateError, dwLastError };
+			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &feedStruct);
+
+			switch(frResult)
+			{
+			case IFeedbackHandler::eResult_Skip:
+				break;	// will return INVALID_HANDLE_VALUE
+
+			case IFeedbackHandler::eResult_Cancel:
+				{
+					// log
+					TString strFormat = _T("Cancel request [error %errno] while opening source file %path (OpenSourceFileFB)");
+					strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+					strFormat.Replace(_T("%path"), spPathToOpen.ToString());
+					rLog.loge(strFormat);
+
+					return TSubTaskBase::eSubResult_CancelRequest;
+				}
+
+			case IFeedbackHandler::eResult_Pause:
+				return TSubTaskBase::eSubResult_PauseRequest;
+
+			case IFeedbackHandler::eResult_Retry:
+				{
+					// log
+					TString strFormat = _T("Retrying [error %errno] to open source file %path (OpenSourceFileFB)");
+					strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+					strFormat.Replace(_T("%path"), spPathToOpen.ToString());
+					rLog.loge(strFormat);
+
+					bRetry = true;
+					break;
+				}
+
+			default:
+				BOOST_ASSERT(FALSE);		// unknown result
+				THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+			}
+		}
+	}
+	while(bRetry);
+
+	return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::OpenDestinationFileFB(TLocalFilesystemFile& fileDst, const TSmartPath& pathDstFile, bool bNoBuffering, const TFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated)
+{
+	IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+	icpf::log_file& rLog = GetContext().GetLog();
+
+	bool bRetry = false;
+
+	ullSeekTo = 0;
+	bFreshlyCreated = true;
+
+	fileDst.Close();
+	do
+	{
+		bRetry = false;
+
+		if(!fileDst.CreateNewForWriting(pathDstFile, bNoBuffering))
+		{
+			DWORD dwLastError = GetLastError();
+			if(dwLastError == ERROR_FILE_EXISTS)
+			{
+				bFreshlyCreated = false;
+
+				// pass it to the specialized method
+				TSubTaskBase::ESubOperationResult eResult = OpenExistingDestinationFileFB(fileDst, pathDstFile, bNoBuffering);
+				if(eResult != TSubTaskBase::eSubResult_Continue)
+					return eResult;
+				else if(!fileDst.IsOpen())
+					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
+				TFileInfoPtr spDstFileInfo(boost::make_shared<TFileInfo>());
+
+				if(!TLocalFilesystem::GetFileInfo(pathDstFile, spDstFileInfo))
+					THROW_CORE_EXCEPTION_WIN32(eErr_CannotGetFileInfo, GetLastError());
+
+				// src and dst files are the same
+				FEEDBACK_ALREADYEXISTS feedStruct = { spSrcFileInfo, spDstFileInfo };
+				IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileAlreadyExists, &feedStruct);
+				// check for dialog result
+				switch(frResult)
+				{
+				case IFeedbackHandler::eResult_Overwrite:
+					ullSeekTo = 0;
+					break;
+
+				case IFeedbackHandler::eResult_CopyRest:
+					ullSeekTo = spDstFileInfo->GetLength64();
+					break;
+
+				case IFeedbackHandler::eResult_Skip:
+					return TSubTaskBase::eSubResult_Continue;
+
+				case IFeedbackHandler::eResult_Cancel:
+					{
+						// log
+						TString strFormat = _T("Cancel request while checking result of dialog before opening source file %path (CustomCopyFileFB)");
+						strFormat.Replace(_T("%path"), pathDstFile.ToString());
+						rLog.logi(strFormat);
+
+						return TSubTaskBase::eSubResult_CancelRequest;
+					}
+				case IFeedbackHandler::eResult_Pause:
+					return TSubTaskBase::eSubResult_PauseRequest;
+
+				default:
+					BOOST_ASSERT(FALSE);		// unknown result
+					THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+				}
+			}
+			else
+			{
+				FEEDBACK_FILEERROR feedStruct = { pathDstFile.ToString(), NULL, eCreateError, dwLastError };
+				IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &feedStruct);
+				switch(frResult)
+				{
+				case IFeedbackHandler::eResult_Retry:
+					{
+						// log
+						TString strFormat = _T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)");
+						strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+						strFormat.Replace(_T("%path"), pathDstFile.ToString());
+						rLog.loge(strFormat);
+
+						bRetry = true;
+
+						break;
+					}
+				case IFeedbackHandler::eResult_Cancel:
+					{
+						// log
+						TString strFormat = _T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)");
+						strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+						strFormat.Replace(_T("%path"), pathDstFile.ToString());
+						rLog.loge(strFormat);
+
+						return TSubTaskBase::eSubResult_CancelRequest;
+					}
+
+				case IFeedbackHandler::eResult_Skip:
+					break;		// will return invalid handle value
+
+				case IFeedbackHandler::eResult_Pause:
+					return TSubTaskBase::eSubResult_PauseRequest;
+
+				default:
+					BOOST_ASSERT(FALSE);		// unknown result
+					THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+				}
+			}
+		}
+	}
+	while(bRetry);
+
+	return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::OpenExistingDestinationFileFB(TLocalFilesystemFile& fileDst, const TSmartPath& pathDstFile, bool bNoBuffering)
+{
+	IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+	icpf::log_file& rLog = GetContext().GetLog();
+
+	bool bRetry = false;
+
+	fileDst.Close();
+
+	do
+	{
+		bRetry = false;
+
+		if(!fileDst.OpenExistingForWriting(pathDstFile, bNoBuffering))
+		{
+			DWORD dwLastError = GetLastError();
+			FEEDBACK_FILEERROR feedStruct = { pathDstFile.ToString(), NULL, eCreateError, dwLastError };
+			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &feedStruct);
+			switch (frResult)
+			{
+			case IFeedbackHandler::eResult_Retry:
+				{
+					// log
+					TString strFormat = _T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)");
+					strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+					strFormat.Replace(_t("%path"), pathDstFile.ToString());
+					rLog.loge(strFormat);
+
+					bRetry = true;
+
+					break;
+				}
+			case IFeedbackHandler::eResult_Cancel:
+				{
+					// log
+					TString strFormat = _T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)");
+					strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+					strFormat.Replace(_T("%path"), pathDstFile.ToString());
+					rLog.loge(strFormat);
+
+					return TSubTaskBase::eSubResult_CancelRequest;
+				}
+
+			case IFeedbackHandler::eResult_Skip:
+				break;		// will return invalid handle value
+
+			case IFeedbackHandler::eResult_Pause:
+				return TSubTaskBase::eSubResult_PauseRequest;
+
+			default:
+				BOOST_ASSERT(FALSE);		// unknown result
+				THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+			}
+		}
+	}
+	while(bRetry);
+
+	return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::SetFilePointerFB(TLocalFilesystemFile& file, long long llDistance, const TSmartPath& pathFile, bool& bSkip)
+{
+	IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+	icpf::log_file& rLog = GetContext().GetLog();
+
+	bSkip = false;
+	bool bRetry = false;
+	do
+	{
+		bRetry = false;
+
+		if(!file.SetFilePointer(llDistance, FILE_BEGIN))
+		{
+			DWORD dwLastError = GetLastError();
+
+			// log
+			TString strFormat = _T("Error %errno while moving file pointer of %path to %pos");
+			strFormat.Replace(_t("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+			strFormat.Replace(_t("%path"), pathFile.ToString());
+			strFormat.Replace(_t("%pos"), boost::lexical_cast<std::wstring>(llDistance).c_str());
+			rLog.loge(strFormat);
+
+			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eSeekError, dwLastError };
+			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+			switch(frResult)
+			{
+			case IFeedbackHandler::eResult_Cancel:
+				return TSubTaskBase::eSubResult_CancelRequest;
+
+			case IFeedbackHandler::eResult_Retry:
+				bRetry = true;
+				break;
+
+			case IFeedbackHandler::eResult_Pause:
+				return TSubTaskBase::eSubResult_PauseRequest;
+
+			case IFeedbackHandler::eResult_Skip:
+				bSkip = true;
+				return TSubTaskBase::eSubResult_Continue;
+
+			default:
+				BOOST_ASSERT(FALSE);		// unknown result
+				THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+			}
+		}
+	}
+	while(bRetry);
+
+	return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::SetEndOfFileFB(TLocalFilesystemFile& file, const TSmartPath& pathFile, bool& bSkip)
+{
+	IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+	icpf::log_file& rLog = GetContext().GetLog();
+
+	bSkip = false;
+
+	bool bRetry = false;
+	do
+	{
+		if(!file.SetEndOfFile())
+		{
+			// log
+			DWORD dwLastError = GetLastError();
+
+			TString strFormat = _T("Error %errno while setting size of file %path to 0");
+			strFormat.Replace(_t("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+			strFormat.Replace(_t("%path"), pathFile.ToString());
+			rLog.loge(strFormat);
+
+			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eResizeError, dwLastError };
+			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+			switch(frResult)
+			{
+			case IFeedbackHandler::eResult_Cancel:
+				return TSubTaskBase::eSubResult_CancelRequest;
+
+			case IFeedbackHandler::eResult_Retry:
+				bRetry = true;
+
+			case IFeedbackHandler::eResult_Pause:
+				return TSubTaskBase::eSubResult_PauseRequest;
+
+			case IFeedbackHandler::eResult_Skip:
+				bSkip = true;
+				return TSubTaskBase::eSubResult_Continue;
+
+			default:
+				BOOST_ASSERT(FALSE);		// unknown result
+				THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+			}
+		}
+	}
+	while(bRetry);
+
+	return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::ReadFileFB(TLocalFilesystemFile& file, TDataBuffer& rBuffer, DWORD dwToRead, DWORD& rdwBytesRead, const TSmartPath& pathFile, bool& bSkip)
+{
+	IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+	icpf::log_file& rLog = GetContext().GetLog();
+
+	bSkip = false;
+	bool bRetry = false;
+	do
+	{
+		bRetry = false;
+
+		if(!file.ReadFile(rBuffer, dwToRead, rdwBytesRead))
+		{
+			// log
+			DWORD dwLastError = GetLastError();
+
+			TString strFormat = _T("Error %errno while trying to read %count bytes from source file %path (CustomCopyFileFB)");
+			strFormat.Replace(_t("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+			strFormat.Replace(_t("%count"), boost::lexical_cast<std::wstring>(dwToRead).c_str());
+			strFormat.Replace(_t("%path"), pathFile.ToString());
+			rLog.loge(strFormat);
+
+			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eReadError, dwLastError };
+			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+			switch(frResult)
+			{
+			case IFeedbackHandler::eResult_Cancel:
+				return TSubTaskBase::eSubResult_CancelRequest;
+
+			case IFeedbackHandler::eResult_Retry:
+				bRetry = true;
+				break;
+
+			case IFeedbackHandler::eResult_Pause:
+				return TSubTaskBase::eSubResult_PauseRequest;
+
+			case IFeedbackHandler::eResult_Skip:
+				bSkip = true;
+				return TSubTaskBase::eSubResult_Continue;
+
+			default:
+				BOOST_ASSERT(FALSE);		// unknown result
+				THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+			}
+		}
+	}
+	while(bRetry);
+
+	return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::WriteFileFB(TLocalFilesystemFile& file, TDataBuffer& rBuffer, DWORD dwToWrite, DWORD& rdwBytesWritten, const TSmartPath& pathFile, bool& bSkip)
+{
+	IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+	icpf::log_file& rLog = GetContext().GetLog();
+
+	bSkip = false;
+
+	bool bRetry = false;
+	do
+	{
+		bRetry = false;
+
+		if(!file.WriteFile(rBuffer, dwToWrite, rdwBytesWritten))
+		{
+			// log
+			DWORD dwLastError = GetLastError();
+
+			TString strFormat = _T("Error %errno while trying to write %count bytes to destination file %path (CustomCopyFileFB)");
+			strFormat.Replace(_t("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+			strFormat.Replace(_t("%count"), boost::lexical_cast<std::wstring>(dwToWrite).c_str());
+			strFormat.Replace(_t("%path"), pathFile.ToString());
+			rLog.loge(strFormat);
+
+			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eWriteError, dwLastError };
+			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+			switch(frResult)
+			{
+			case IFeedbackHandler::eResult_Cancel:
+				return TSubTaskBase::eSubResult_CancelRequest;
+
+			case IFeedbackHandler::eResult_Retry:
+				bRetry = true;
+				break;
+
+			case IFeedbackHandler::eResult_Pause:
+				return TSubTaskBase::eSubResult_PauseRequest;
+
+			case IFeedbackHandler::eResult_Skip:
+				bSkip = true;
+				return TSubTaskBase::eSubResult_Continue;
+
+			default:
+				BOOST_ASSERT(FALSE);		// unknown result
+				THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+			}
+		}
+	}
+	while(bRetry);
+
+	return TSubTaskBase::eSubResult_Continue;
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskCopyMove::CheckForFreeSpaceFB()
+{
+	icpf::log_file& rLog = GetContext().GetLog();
+	TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+	IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+	TTaskLocalStats& rLocalStats = GetContext().GetTaskLocalStats();
+	TLocalFilesystem& rLocalFilesystem = GetContext().GetLocalFilesystem();
+
+	ull_t ullNeededSize = 0, ullAvailableSize = 0;
+	bool bRetry = false;
+
+	do
+	{
+		bRetry = false;
+
+		rLog.logi(_T("Checking for free space on destination disk..."));
+
+		ullNeededSize = rLocalStats.GetUnProcessedSize(); // it'd be nice to round up to take cluster size into consideration,
+
+		// get free space
+		bool bResult = rLocalFilesystem.GetDynamicFreeSpace(rTaskDefinition.GetDestinationPath(), ullAvailableSize);
+		if(bResult && ullNeededSize > ullAvailableSize)
+		{
+			TString strFormat = _T("Not enough free space on disk - needed %needsize bytes for data, available: %availablesize bytes.");
+			strFormat.Replace(_t("%needsize"), boost::lexical_cast<std::wstring>(ullNeededSize).c_str());
+			strFormat.Replace(_t("%availablesize"), boost::lexical_cast<std::wstring>(ullAvailableSize).c_str());
+			rLog.logw(strFormat);
+
+			if(rTaskDefinition.GetSourcePathCount() > 0)
+			{
+				FEEDBACK_NOTENOUGHSPACE feedStruct = { ullNeededSize, rTaskDefinition.GetSourcePathAt(0).ToString(), rTaskDefinition.GetDestinationPath().ToString() };
+				IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_NotEnoughSpace, &feedStruct);
+
+				// default
+				switch(frResult)
+				{
+				case IFeedbackHandler::eResult_Cancel:
+					rLog.logi(_T("Cancel request while checking for free space on disk."));
+					return TSubTaskBase::eSubResult_CancelRequest;
+
+				case IFeedbackHandler::eResult_Retry:
+					rLog.logi(_T("Retrying to read drive's free space..."));
+					bRetry = true;
+					break;
+
+				case IFeedbackHandler::eResult_Ignore:
+					rLog.logi(_T("Ignored warning about not enough place on disk to copy data."));
+					return TSubTaskBase::eSubResult_Continue;
+
+				default:
+					BOOST_ASSERT(FALSE);		// unknown result
+					THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+				}
+			}
+		}
+	}
+	while(bRetry);
+
+	return TSubTaskBase::eSubResult_Continue;
+}
+
+END_CHCORE_NAMESPACE
Index: src/libchcore/TSubTaskCopyMove.h
===================================================================
diff -u
--- src/libchcore/TSubTaskCopyMove.h	(revision 0)
+++ src/libchcore/TSubTaskCopyMove.h	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -0,0 +1,65 @@
+// ============================================================================
+//  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  TSubTaskCopyMove.h
+/// @date  2010/09/18
+/// @brief Contains declarations of classes responsible for copy and move sub-operation.
+// ============================================================================
+#ifndef __TSUBTASKCOPYMOVE_H__
+#define __TSUBTASKCOPYMOVE_H__
+
+#include "libchcore.h"
+#include "TSubTaskBase.h"
+
+BEGIN_CHCORE_NAMESPACE
+
+class TDataBuffer;
+class TLocalFilesystemFile;
+typedef boost::shared_ptr<TFileInfo> TFileInfoPtr;
+struct CUSTOM_COPY_PARAMS;
+
+class LIBCHCORE_API TSubTaskCopyMove : public TSubTaskBase
+{
+public:
+	TSubTaskCopyMove(TSubTaskContext& tSubTaskContext);
+
+	ESubOperationResult Exec();
+
+private:
+	bool GetMove(const TFileInfoPtr& spFileInfo);
+	int GetBufferIndex(const TFileInfoPtr& spFileInfo);
+
+	ESubOperationResult CustomCopyFileFB(CUSTOM_COPY_PARAMS* pData);
+
+	ESubOperationResult OpenSourceFileFB(TLocalFilesystemFile& fileSrc, const TSmartPath& spPathToOpen, bool bNoBuffering);
+	ESubOperationResult OpenDestinationFileFB(TLocalFilesystemFile& fileDst, const TSmartPath& pathDstFile, bool bNoBuffering, const TFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated);
+	ESubOperationResult OpenExistingDestinationFileFB(TLocalFilesystemFile& fileDst, const TSmartPath& pathDstFilePath, bool bNoBuffering);
+
+	ESubOperationResult SetFilePointerFB(TLocalFilesystemFile& file, long long llDistance, const TSmartPath& pathFile, bool& bSkip);
+	ESubOperationResult SetEndOfFileFB(TLocalFilesystemFile& file, const TSmartPath& pathFile, bool& bSkip);
+
+	ESubOperationResult ReadFileFB(TLocalFilesystemFile& file, TDataBuffer& rBuffer, DWORD dwToRead, DWORD& rdwBytesRead, const TSmartPath& pathFile, bool& bSkip);
+	ESubOperationResult WriteFileFB(TLocalFilesystemFile& file, TDataBuffer& rBuffer, DWORD dwToWrite, DWORD& rdwBytesWritten, const TSmartPath& pathFile, bool& bSkip);
+	ESubOperationResult CreateDirectoryFB(const TSmartPath& pathDirectory);
+
+	ESubOperationResult CheckForFreeSpaceFB();
+};
+
+END_CHCORE_NAMESPACE
+
+#endif
Index: src/libchcore/TSubTaskDelete.cpp
===================================================================
diff -u
--- src/libchcore/TSubTaskDelete.cpp	(revision 0)
+++ src/libchcore/TSubTaskDelete.cpp	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -0,0 +1,144 @@
+// ============================================================================
+//  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  TSubTaskDelete.cpp
+/// @date  2010/09/19
+/// @brief Contains implementation of classes responsible for delete sub-operation.
+// ============================================================================
+#include "stdafx.h"
+#include "TSubTaskDelete.h"
+#include "TSubTaskContext.h"
+#include "TBasicProgressInfo.h"
+#include "TWorkerThreadController.h"
+#include "TTaskConfiguration.h"
+#include "TTaskDefinition.h"
+//#include "FeedbackHandler.h"
+#include "TLocalFilesystem.h"
+#include "..\libicpf\log.h"
+#include "FeedbackHandlerBase.h"
+#include <boost\lexical_cast.hpp>
+
+BEGIN_CHCORE_NAMESPACE
+
+TSubTaskDelete::TSubTaskDelete(TSubTaskContext& rContext) : 
+	TSubTaskBase(rContext)
+{
+}
+
+TSubTaskBase::ESubOperationResult TSubTaskDelete::Exec()
+{
+	// log
+	icpf::log_file& rLog = GetContext().GetLog();
+	TFileInfoArray& rFilesCache = GetContext().GetFilesCache();
+	TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+	TTaskBasicProgressInfo& rBasicProgressInfo = GetContext().GetTaskBasicProgressInfo();
+	TWorkerThreadController& rThreadController = GetContext().GetThreadController();
+	IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+
+	// log
+	rLog.logi(_T("Deleting files (DeleteFiles)..."));
+
+	// current processed path
+	BOOL bSuccess;
+	TFileInfoPtr spFileInfo;
+	TString strFormat;
+
+	// index points to 0 or next item to process
+	size_t stIndex = rBasicProgressInfo.GetCurrentIndex();
+	while(stIndex < rFilesCache.GetSize())
+	{
+		// set index in pTask to currently deleted element
+		rBasicProgressInfo.SetCurrentIndex(stIndex);
+
+		// check for kill flag
+		if(rThreadController.KillRequested())
+		{
+			// log
+			rLog.logi(_T("Kill request while deleting files (Delete Files)"));
+			return TSubTaskBase::eSubResult_KillRequest;
+		}
+
+		// current processed element
+		spFileInfo = rFilesCache.GetAt(rFilesCache.GetSize() - stIndex - 1);
+		if(!(spFileInfo->GetFlags() & FIF_PROCESSED))
+		{
+			++stIndex;
+			continue;
+		}
+
+		// delete data
+		if(spFileInfo->IsDirectory())
+		{
+			if(!GetTaskPropValue<eTO_ProtectReadOnlyFiles>(rTaskDefinition.GetConfiguration()))
+				TLocalFilesystem::SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY);
+			bSuccess = TLocalFilesystem::RemoveDirectory(spFileInfo->GetFullFilePath());
+		}
+		else
+		{
+			// set files attributes to normal - it'd slow processing a bit, but it's better.
+			if(!GetTaskPropValue<eTO_ProtectReadOnlyFiles>(rTaskDefinition.GetConfiguration()))
+				TLocalFilesystem::SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL);
+			bSuccess = TLocalFilesystem::DeleteFile(spFileInfo->GetFullFilePath());
+		}
+
+		// operation failed
+		DWORD dwLastError = GetLastError();
+		if(!bSuccess && dwLastError != ERROR_PATH_NOT_FOUND && dwLastError != ERROR_FILE_NOT_FOUND)
+		{
+			// log
+			strFormat = _T("Error #%errno while deleting file/folder %path");
+			strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
+			strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString());
+			rLog.loge(strFormat);
+
+			FEEDBACK_FILEERROR ferr = { spFileInfo->GetFullFilePath().ToString(), NULL, eDeleteError, dwLastError };
+			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+			switch(frResult)
+			{
+			case IFeedbackHandler::eResult_Cancel:
+				rLog.logi(_T("Cancel request while deleting file."));
+				return TSubTaskBase::eSubResult_CancelRequest;
+
+			case IFeedbackHandler::eResult_Retry:
+				continue;	// no stIndex bump, since we are trying again
+
+			case IFeedbackHandler::eResult_Pause:
+				return TSubTaskBase::eSubResult_PauseRequest;
+
+			case IFeedbackHandler::eResult_Skip:
+				break;		// just do nothing
+
+			default:
+				BOOST_ASSERT(FALSE);		// unknown result
+				THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+			}
+		}
+
+		++stIndex;
+	}//while
+
+	// add 1 to current index
+	rBasicProgressInfo.IncreaseCurrentIndex();
+
+	// log
+	rLog.logi(_T("Deleting files finished"));
+
+	return TSubTaskBase::eSubResult_Continue;
+}
+
+END_CHCORE_NAMESPACE
Fisheye: tag c866a5e96f5eaf160278a8c128bf86e342cc2409 is not in file src/libchcore/TSubTaskDelete.h
Fisheye: Tag 4d20d0e58f37f06ac91287015b960308db54d47e refers to a dead (removed) revision in file `src/ch/TSubTaskDelete.h'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/libchcore/TSubTaskScanDirectory.cpp
===================================================================
diff -u
--- src/libchcore/TSubTaskScanDirectory.cpp	(revision 0)
+++ src/libchcore/TSubTaskScanDirectory.cpp	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -0,0 +1,266 @@
+// ============================================================================
+//  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  TSubTaskScanDirectory.cpp
+/// @date  2010/09/18
+/// @brief Contains implementation of classes related to scan directory subtask.
+// ============================================================================
+#include "stdafx.h"
+#include "TSubTaskScanDirectory.h"
+#include "TSubTaskContext.h"
+#include "TTaskConfiguration.h"
+#include "TTaskDefinition.h"
+//#include "FeedbackHandler.h"
+#include "TLocalFilesystem.h"
+#include "FeedbackHandlerBase.h"
+#include "TBasePathData.h"
+#include "TWorkerThreadController.h"
+#include "TTaskLocalStats.h"
+#include <boost\smart_ptr\make_shared.hpp>
+#include "..\libicpf\log.h"
+
+BEGIN_CHCORE_NAMESPACE
+
+TSubTaskScanDirectories::TSubTaskScanDirectories(TSubTaskContext& rContext) :
+	TSubTaskBase(rContext)
+{
+}
+
+TSubTaskScanDirectories::~TSubTaskScanDirectories()
+{
+}
+
+TSubTaskScanDirectories::ESubOperationResult TSubTaskScanDirectories::Exec()
+{
+	// log
+	icpf::log_file& rLog = GetContext().GetLog();
+	TFileInfoArray& rFilesCache = GetContext().GetFilesCache();
+	TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+	IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler();
+	const TBasePathDataContainer& rarrSourcePathsInfo = GetContext().GetBasePathDataContainer();
+	TWorkerThreadController& rThreadController = GetContext().GetThreadController();
+	TTaskLocalStats& rTaskLocalStats = GetContext().GetTaskLocalStats();
+
+	rLog.logi(_T("Searching for files..."));
+
+	// reset progress
+	rTaskLocalStats.SetProcessedSize(0);
+	rTaskLocalStats.SetTotalSize(0);
+
+	// delete the content of rFilesCache
+	rFilesCache.Clear();
+
+	// read filtering options
+	TFiltersArray afFilters;
+	GetTaskPropValue<eTO_Filters>(rTaskDefinition.GetConfiguration(), afFilters);
+
+	// enter some data to rFilesCache
+	wchar_t wchDestinationDriveLetter = rTaskDefinition.GetDestinationPath().GetDriveLetter();
+
+	bool bIgnoreDirs = GetTaskPropValue<eTO_IgnoreDirectories>(rTaskDefinition.GetConfiguration());
+	bool bForceDirectories = GetTaskPropValue<eTO_CreateDirectoriesRelativeToRoot>(rTaskDefinition.GetConfiguration());
+	bool bMove = rTaskDefinition.GetOperationType() == eOperation_Move;
+
+	// add everything
+	TString strFormat;
+	bool bRetry = true;
+	bool bSkipInputPath = false;
+
+	size_t stSize = rTaskDefinition.GetSourcePathCount();
+	for(size_t stIndex = 0; stIndex < stSize ; stIndex++)
+	{
+		TFileInfoPtr spFileInfo;
+
+		bSkipInputPath = false;
+
+		spFileInfo.reset(new TFileInfo());
+
+		// 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 = TLocalFilesystem::GetFileInfo(rTaskDefinition.GetSourcePathAt(stIndex), spFileInfo, stIndex, &rTaskDefinition.GetSourcePaths());
+			if(!bExists)
+			{
+				FEEDBACK_FILEERROR ferr = { rTaskDefinition.GetSourcePathAt(stIndex).ToString(), NULL, eFastMoveError, ERROR_FILE_NOT_FOUND };
+				IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+				switch(frResult)
+				{
+				case IFeedbackHandler::eResult_Cancel:
+					rFilesCache.Clear();
+					return eSubResult_CancelRequest;
+
+				case IFeedbackHandler::eResult_Retry:
+					bRetry = true;
+					break;
+
+				case IFeedbackHandler::eResult_Pause:
+					rFilesCache.Clear();
+					return eSubResult_PauseRequest;
+
+				case IFeedbackHandler::eResult_Skip:
+					bSkipInputPath = true;
+					break;		// just do nothing
+
+				default:
+					BOOST_ASSERT(FALSE);		// unknown result
+					THROW_CORE_EXCEPTION(eErr_UnhandledCase);
+				}
+			}
+		}
+		while(bRetry);
+
+		// if we have chosen to skip the input path then there's nothing to do
+		if(bSkipInputPath)
+			continue;
+
+		// log
+		strFormat = _T("Adding file/folder (clipboard) : %path ...");
+		strFormat.Replace(_T("%path"), rTaskDefinition.GetSourcePathAt(stIndex).ToString());
+		rLog.logi(strFormat);
+
+		// 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())
+			{
+				TSmartPath pathSubst = FindFreeSubstituteName(spFileInfo->GetFullFilePath(), rTaskDefinition.GetDestinationPath());
+				rarrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(pathSubst);
+			}
+			else
+				rarrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(spFileInfo->GetFullFilePath().GetFileName());
+		}
+
+		wchar_t wchSourceDriveLetter = spFileInfo->GetFullFilePath().GetDriveLetter();
+
+		// 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
+				strFormat = _T("Added folder %path");
+				strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString());
+				rLog.logi(strFormat);
+			}
+
+			// don't add folder contents when moving inside one disk boundary
+			if(bIgnoreDirs || !bMove || wchDestinationDriveLetter == L'\0' || wchDestinationDriveLetter != wchSourceDriveLetter ||
+				TLocalFilesystem::PathExist(CalculateDestinationPath(spFileInfo, rTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1)) )
+			{
+				// log
+				strFormat = _T("Recursing folder %path");
+				strFormat.Replace(_t("%path"), spFileInfo->GetFullFilePath().ToString());
+				rLog.logi(strFormat);
+
+				// 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 && wchDestinationDriveLetter != L'\0' && wchDestinationDriveLetter == wchSourceDriveLetter &&
+				!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
+			strFormat = _T("Added file %path");
+			strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString());
+			rLog.logi(strFormat);
+		}
+	}
+
+	// calc size of all files
+	rTaskLocalStats.SetTotalSize(rFilesCache.CalculateTotalSize());
+
+	// log
+	rLog.logi(_T("Searching for files finished"));
+
+	return eSubResult_Continue;
+}
+
+int TSubTaskScanDirectories::ScanDirectory(TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs, TFiltersArray& afFilters)
+{
+	TFileInfoArray& rFilesCache = GetContext().GetFilesCache();
+	TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition();
+	TWorkerThreadController& rThreadController = GetContext().GetThreadController();
+
+	TLocalFilesystemFind finder = TLocalFilesystem::CreateFinderObject(pathDirName, PathFromString(_T("*")));
+	TFileInfoPtr spFileInfo(boost::make_shared<TFileInfo>());
+
+	while(finder.FindNext(spFileInfo))
+	{
+		if(rThreadController.KillRequested())
+			break;
+
+		if(!spFileInfo->IsDirectory())
+		{
+			if(afFilters.Match(spFileInfo))
+			{
+				spFileInfo->SetParentObject(stSrcIndex, &rTaskDefinition.GetSourcePaths());
+				rFilesCache.AddFileInfo(spFileInfo);
+				spFileInfo = boost::make_shared<TFileInfo>();
+			}
+		}
+		else
+		{
+			TSmartPath pathCurrent = spFileInfo->GetFullFilePath();
+			if(bIncludeDirs)
+			{
+				spFileInfo->SetParentObject(stSrcIndex, &rTaskDefinition.GetSourcePaths());
+				rFilesCache.AddFileInfo(spFileInfo);
+				spFileInfo = boost::make_shared<TFileInfo>();
+			}
+
+			if(bRecurse)
+				ScanDirectory(pathCurrent, stSrcIndex, bRecurse, bIncludeDirs, afFilters);
+		}
+	}
+
+	return 0;
+}
+
+END_CHCORE_NAMESPACE
Fisheye: tag 2aea3ad6f3c68be709ac65c70d9646eafe3b034c is not in file src/libchcore/TSubTaskScanDirectory.h
Fisheye: Tag 4d20d0e58f37f06ac91287015b960308db54d47e refers to a dead (removed) revision in file `src/ch/TSubTaskScanDirectory.h'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/libchcore/TTaskConfiguration.h
===================================================================
diff -u -rfb4c4006dee5aaf815d08bc3e89312445b994307 -r4d20d0e58f37f06ac91287015b960308db54d47e
--- src/libchcore/TTaskConfiguration.h	(.../TTaskConfiguration.h)	(revision fb4c4006dee5aaf815d08bc3e89312445b994307)
+++ src/libchcore/TTaskConfiguration.h	(.../TTaskConfiguration.h)	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -122,8 +122,8 @@
 TASK_PROPERTY(eTO_Filters, chcore::TFiltersArray, _T("Operation.Filtering"), chcore::TFiltersArray());
 
 // Naming settings
-TASK_PROPERTY(eTO_AlternateFilenameFormatString_First, CString, _T("Naming.AlternateFilenameFormatFirst"), _T("Copy of %name"));
-TASK_PROPERTY(eTO_AlternateFilenameFormatString_AfterFirst, CString, _T("Naming.AlternateFilenameFormatAfterFirst"), _T("Copy (%count) of %name"));
+TASK_PROPERTY(eTO_AlternateFilenameFormatString_First, TString, _T("Naming.AlternateFilenameFormatFirst"), _T("Copy of %name"));
+TASK_PROPERTY(eTO_AlternateFilenameFormatString_AfterFirst, TString, _T("Naming.AlternateFilenameFormatAfterFirst"), _T("Copy (%count) of %name"));
 
 /////////////////////////////////////////////////////////////////////////////////////////////
 // other properties names
Index: src/libchcore/libchcore.vc90.vcproj
===================================================================
diff -u -rfb4c4006dee5aaf815d08bc3e89312445b994307 -r4d20d0e58f37f06ac91287015b960308db54d47e
--- src/libchcore/libchcore.vc90.vcproj	(.../libchcore.vc90.vcproj)	(revision fb4c4006dee5aaf815d08bc3e89312445b994307)
+++ src/libchcore/libchcore.vc90.vcproj	(.../libchcore.vc90.vcproj)	(revision 4d20d0e58f37f06ac91287015b960308db54d47e)
@@ -392,6 +392,14 @@
 					>
 				</File>
 				<File
+					RelativePath=".\TSubTaskContext.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\TSubTaskContext.h"
+					>
+				</File>
+				<File
 					RelativePath=".\TTaskConfigTracker.cpp"
 					>
 				</File>
@@ -419,6 +427,42 @@
 					RelativePath=".\TTaskLocalStats.h"
 					>
 				</File>
+				<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>
 			<Filter
 				Name="Base services"