Index: src/ch/FeedbackFileErrorDlg.cpp
===================================================================
diff -u -r25b3c85ea493809ee084271d5101a015d349da95 -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/ch/FeedbackFileErrorDlg.cpp	(.../FeedbackFileErrorDlg.cpp)	(revision 25b3c85ea493809ee084271d5101a015d349da95)
+++ src/ch/FeedbackFileErrorDlg.cpp	(.../FeedbackFileErrorDlg.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -86,23 +86,23 @@
 void CFeedbackFileErrorDlg::OnBnClickedRetryButton()
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_Retry);
+	EndDialog(chcore::EFeedbackResult::eResult_Retry);
 }
 
 void CFeedbackFileErrorDlg::OnBnClickedSkipButton()
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_Skip);
+	EndDialog(chcore::EFeedbackResult::eResult_Skip);
 }
 
 void CFeedbackFileErrorDlg::OnBnClickedPauseButton()
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_Pause);
+	EndDialog(chcore::EFeedbackResult::eResult_Pause);
 }
 
 void CFeedbackFileErrorDlg::OnBnClickedCancel()
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_Cancel);
+	EndDialog(chcore::EFeedbackResult::eResult_Cancel);
 }
Index: src/ch/FeedbackHandler.cpp
===================================================================
diff -u -r1da7ee476d3e1e818d3af54210ba55d7063d1a2c -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/ch/FeedbackHandler.cpp	(.../FeedbackHandler.cpp)	(revision 1da7ee476d3e1e818d3af54210ba55d7063d1a2c)
+++ src/ch/FeedbackHandler.cpp	(.../FeedbackHandler.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -25,122 +25,86 @@
 #include "ch.h"
 #include "mmsystem.h"
 
+using namespace chcore;
+
 CFeedbackHandler::CFeedbackHandler() :
-	chcore::IFeedbackHandler()
+	chcore::TFeedbackHandlerBase()
 {
-	memset(m_aeFeedbackTypeStatus, 0, sizeof(m_aeFeedbackTypeStatus));
 }
 
 CFeedbackHandler::~CFeedbackHandler()
 {
 }
 
-ull_t CFeedbackHandler::RequestFeedback(ull_t ullFeedbackID, ptr_t pFeedbackParam)
+chcore::EFeedbackResult CFeedbackHandler::FileError(const TString& strSrcPath, const TString& strDstPath, EFileError eFileError, unsigned long ulError)
 {
-	BOOST_ASSERT(ullFeedbackID < eFT_LastType);
-	if(ullFeedbackID >= eFT_LastType)
-		return eResult_Unknown;
+	chcore::EFeedbackResult eResult = TFeedbackHandlerBase::FileError(strSrcPath, strDstPath, eFileError, ulError);
+	if (eResult == chcore::eResult_Unknown)
+	{
+		CFeedbackFileErrorDlg dlg(strSrcPath.c_str(), strDstPath.c_str(), ulError);
+		eResult = (chcore::EFeedbackResult)dlg.DoModal();
+		
+		if (dlg.m_bAllItems)
+			SetFileErrorPermanentResponse(eResult);
+	}
 
-	// if we have an action selected for this type (e.g. by selecting 'use for all items')
-	if(m_aeFeedbackTypeStatus[ullFeedbackID] != eResult_Unknown)
-		return m_aeFeedbackTypeStatus[ullFeedbackID];
+	return eResult;
+}
 
-	// standard processing of feedback
-	EFeedbackResult eFeedbackResult = eResult_Unknown;
-	BOOL bUseForAllItems = FALSE;
-	switch(ullFeedbackID)
+chcore::EFeedbackResult CFeedbackHandler::FileAlreadyExists(const TFileInfoPtr& spSrcFileInfo, const TFileInfoPtr& spDstFileInfo)
+{
+	chcore::EFeedbackResult eResult = TFeedbackHandlerBase::FileAlreadyExists(spSrcFileInfo, spDstFileInfo);
+	if (eResult == chcore::eResult_Unknown)
 	{
-	case eFT_FileAlreadyExists:
-		{
-			BOOST_ASSERT(pFeedbackParam);
-			if(!pFeedbackParam)
-				return eResult_Unknown;
+		CFeedbackReplaceDlg dlg(spSrcFileInfo, spDstFileInfo);
+		eResult = (EFeedbackResult)dlg.DoModal();
 
-			chcore::FEEDBACK_ALREADYEXISTS* pData = (chcore::FEEDBACK_ALREADYEXISTS*)pFeedbackParam;
-			CFeedbackReplaceDlg dlg(pData->spSrcFileInfo, pData->spDstFileInfo);
-			eFeedbackResult = (EFeedbackResult)dlg.DoModal();
-			bUseForAllItems = dlg.m_bAllItems;
+		if(dlg.m_bAllItems)
+			SetFileAlreadyExistsPermanentResponse(eResult);
+	}
 
-			break;
-		}
-	case eFT_FileError:
-		{
-			BOOST_ASSERT(pFeedbackParam);
-			if(!pFeedbackParam)
-				return eResult_Unknown;
+	return eResult;
+}
 
-			chcore::FEEDBACK_FILEERROR* pData = (chcore::FEEDBACK_FILEERROR*)pFeedbackParam;
-			CFeedbackFileErrorDlg dlg(pData->strSrcPath.c_str(), pData->strDstPath.c_str(), pData->ulError);
-			eFeedbackResult = (EFeedbackResult)dlg.DoModal();
-			bUseForAllItems = dlg.m_bAllItems;
+chcore::EFeedbackResult CFeedbackHandler::NotEnoughSpace(const TString& strSrcPath, const TString& strDstPath, unsigned long long ullRequiredSize)
+{
+	chcore::EFeedbackResult eResult = TFeedbackHandlerBase::NotEnoughSpace(strSrcPath, strDstPath, ullRequiredSize);
+	if (eResult == chcore::eResult_Unknown)
+	{
+		CFeedbackNotEnoughSpaceDlg dlg(ullRequiredSize, strSrcPath.c_str(), strDstPath.c_str());
+		eResult = (EFeedbackResult) dlg.DoModal();
 
-			break;
-		}
-	case eFT_NotEnoughSpace:
-		{
-			BOOST_ASSERT(pFeedbackParam);
-			if(!pFeedbackParam)
-				return eResult_Unknown;
+		if (dlg.m_bAllItems)
+			SetNotEnoughSpacePermanentResponse(eResult);
+	}
 
-			chcore::FEEDBACK_NOTENOUGHSPACE* pData = (chcore::FEEDBACK_NOTENOUGHSPACE*)pFeedbackParam;
-			CFeedbackNotEnoughSpaceDlg dlg(pData->ullRequiredSize, pData->strSrcPath.c_str(), pData->strDstPath.c_str());
-			eFeedbackResult = (EFeedbackResult)dlg.DoModal();
-			bUseForAllItems = dlg.m_bAllItems;
+	return eResult;
+}
 
-			break;
-		}
-	case eFT_OperationFinished:
-		{
-			if(GetPropValue<PP_SNDPLAYSOUNDS>(GetConfig()))
-			{
-				CString strPath = GetPropValue<PP_SNDFINISHEDSOUNDPATH>(GetConfig());
-				GetApp().ExpandPath(strPath.GetBufferSetLength(_MAX_PATH));
-				strPath.ReleaseBuffer();
+chcore::EFeedbackResult CFeedbackHandler::OperationFinished()
+{
+	if (GetPropValue<PP_SNDPLAYSOUNDS>(GetConfig()))
+	{
+		CString strPath = GetPropValue<PP_SNDFINISHEDSOUNDPATH>(GetConfig());
+		GetApp().ExpandPath(strPath.GetBufferSetLength(_MAX_PATH));
+		strPath.ReleaseBuffer();
 
-				PlaySound(strPath, NULL, SND_FILENAME | SND_ASYNC);
-			}
-
-			break;
-		}
-	case eFT_OperationError:
-		{
-			if(GetPropValue<PP_SNDPLAYSOUNDS>(GetConfig()))
-			{
-				CString strPath = GetPropValue<PP_SNDERRORSOUNDPATH>(GetConfig());
-				GetApp().ExpandPath(strPath.GetBufferSetLength(_MAX_PATH));
-				strPath.ReleaseBuffer();
-
-				PlaySound(strPath, NULL, SND_FILENAME | SND_ASYNC);
-			}
-
-			break;
-		}
-	default:
-		BOOST_ASSERT(false);
-		return eResult_Unknown;
+		PlaySound(strPath, NULL, SND_FILENAME | SND_ASYNC);
 	}
 
-	// remember feedback option for next time
-	if(bUseForAllItems)
-		m_aeFeedbackTypeStatus[ullFeedbackID] = eFeedbackResult;
-
-	return eFeedbackResult;
+	return eResult_Unknown;
 }
 
-void CFeedbackHandler::RestoreDefaults()
+chcore::EFeedbackResult CFeedbackHandler::OperationError()
 {
-	memset(m_aeFeedbackTypeStatus, 0, sizeof(m_aeFeedbackTypeStatus));
-}
+	if (GetPropValue<PP_SNDPLAYSOUNDS>(GetConfig()))
+	{
+		CString strPath = GetPropValue<PP_SNDERRORSOUNDPATH>(GetConfig());
+		GetApp().ExpandPath(strPath.GetBufferSetLength(_MAX_PATH));
+		strPath.ReleaseBuffer();
 
-chcore::IFeedbackHandlerPtr CFeedbackHandlerFactory::Create()
-{
-	return chcore::IFeedbackHandlerPtr(new CFeedbackHandler);
-}
+		PlaySound(strPath, NULL, SND_FILENAME | SND_ASYNC);
+	}
 
-CFeedbackHandlerFactory::CFeedbackHandlerFactory()
-{
+	return eResult_Unknown;
 }
-
-CFeedbackHandlerFactory::~CFeedbackHandlerFactory()
-{
-}
Index: src/ch/FeedbackHandler.h
===================================================================
diff -u -r1da7ee476d3e1e818d3af54210ba55d7063d1a2c -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/ch/FeedbackHandler.h	(.../FeedbackHandler.h)	(revision 1da7ee476d3e1e818d3af54210ba55d7063d1a2c)
+++ src/ch/FeedbackHandler.h	(.../FeedbackHandler.h)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -20,35 +20,25 @@
 #define __FEEDBACKHANDLER_H__
 
 #include "../libchcore/IFeedbackHandlerFactory.h"
+#include "../libchcore/TFeedbackHandlerBase.h"
+#include "../libchcore/EFeedbackResult.h"
 
-class CFeedbackHandler : public chcore::IFeedbackHandler
+class CFeedbackHandler : public chcore::TFeedbackHandlerBase
 {
 public:
 	CFeedbackHandler();
 	virtual ~CFeedbackHandler();
 
-public:
-	virtual ull_t RequestFeedback(ull_t ullFeedbackID, ptr_t pFeedbackParam) override;
-	virtual void RestoreDefaults() override;
+	virtual chcore::EFeedbackResult FileError(const chcore::TString& strSrcPath, const chcore::TString& strDstPath, chcore::EFileError eFileError, unsigned long ulError) override;
+	virtual chcore::EFeedbackResult FileAlreadyExists(const chcore::TFileInfoPtr& spSrcFileInfo, const chcore::TFileInfoPtr& spDstFileInfo) override;
+	virtual chcore::EFeedbackResult NotEnoughSpace(const chcore::TString& strSrcPath, const chcore::TString& strDstPath, unsigned long long ullRequiredSize) override;
+	virtual chcore::EFeedbackResult OperationFinished() override;
+	virtual chcore::EFeedbackResult OperationError() override;
 
 protected:
-	EFeedbackResult m_aeFeedbackTypeStatus[eFT_LastType];
-
 	friend class CFeedbackHandlerFactory;
 };
 
 typedef boost::shared_ptr<CFeedbackHandler> CFeedbackHandlerPtr;
 
-class CFeedbackHandlerFactory : public chcore::IFeedbackHandlerFactory
-{
-public:
-	CFeedbackHandlerFactory();
-	virtual ~CFeedbackHandlerFactory();
-
-public:
-	virtual chcore::IFeedbackHandlerPtr Create() override;
-};
-
-typedef boost::shared_ptr<CFeedbackHandlerFactory> CFeedbackHandlerFactoryPtr;
-
 #endif
Index: src/ch/FeedbackHandlerFactory.cpp
===================================================================
diff -u
--- src/ch/FeedbackHandlerFactory.cpp	(revision 0)
+++ src/ch/FeedbackHandlerFactory.cpp	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -0,0 +1,34 @@
+// ============================================================================
+//  Copyright (C) 2001-2015 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "FeedbackHandlerFactory.h"
+#include "FeedbackHandler.h"
+
+CFeedbackHandlerFactory::CFeedbackHandlerFactory()
+{
+}
+
+CFeedbackHandlerFactory::~CFeedbackHandlerFactory()
+{
+}
+
+chcore::IFeedbackHandlerPtr CFeedbackHandlerFactory::Create()
+{
+	return boost::make_shared<CFeedbackHandler>();
+}
Index: src/ch/FeedbackHandlerFactory.h
===================================================================
diff -u
--- src/ch/FeedbackHandlerFactory.h	(revision 0)
+++ src/ch/FeedbackHandlerFactory.h	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -0,0 +1,36 @@
+// ============================================================================
+//  Copyright (C) 2001-2015 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#ifndef __FEEDBACKHANDLERFACTORY_H__
+#define __FEEDBACKHANDLERFACTORY_H__
+
+#include "..\libchcore\IFeedbackHandlerFactory.h"
+#include "..\libchcore\IFeedbackHandler.h"
+
+class CFeedbackHandlerFactory : public chcore::IFeedbackHandlerFactory
+{
+public:
+	CFeedbackHandlerFactory();
+	virtual ~CFeedbackHandlerFactory();
+
+	virtual chcore::IFeedbackHandlerPtr Create() override;
+};
+
+typedef boost::shared_ptr<CFeedbackHandlerFactory> CFeedbackHandlerFactoryPtr;
+
+#endif
Index: src/ch/FeedbackNotEnoughSpaceDlg.cpp
===================================================================
diff -u -r25b3c85ea493809ee084271d5101a015d349da95 -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/ch/FeedbackNotEnoughSpaceDlg.cpp	(.../FeedbackNotEnoughSpaceDlg.cpp)	(revision 25b3c85ea493809ee084271d5101a015d349da95)
+++ src/ch/FeedbackNotEnoughSpaceDlg.cpp	(.../FeedbackNotEnoughSpaceDlg.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -140,7 +140,7 @@
 			if (m_ullRequired <= ullFree)
 			{
 				CLanguageDialog::OnTimer(nIDEvent);
-				EndDialog(CFeedbackHandler::eResult_Retry);
+				EndDialog(chcore::EFeedbackResult::eResult_Retry);
 			}
 		}
 	}
@@ -151,13 +151,13 @@
 void CFeedbackNotEnoughSpaceDlg::OnRetryButton() 
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_Retry);	
+	EndDialog(chcore::EFeedbackResult::eResult_Retry);
 }
 
 void CFeedbackNotEnoughSpaceDlg::OnIgnoreButton() 
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_Ignore);
+	EndDialog(chcore::EFeedbackResult::eResult_Ignore);
 }
 
 void CFeedbackNotEnoughSpaceDlg::OnLanguageChanged()
@@ -168,5 +168,5 @@
 void CFeedbackNotEnoughSpaceDlg::OnBnClickedCancel()
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_Cancel);
+	EndDialog(chcore::EFeedbackResult::eResult_Cancel);
 }
Index: src/ch/FeedbackReplaceDlg.cpp
===================================================================
diff -u -ra5aa3c3cb78f3767641de2627d1a49a1dc35b429 -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/ch/FeedbackReplaceDlg.cpp	(.../FeedbackReplaceDlg.cpp)	(revision a5aa3c3cb78f3767641de2627d1a49a1dc35b429)
+++ src/ch/FeedbackReplaceDlg.cpp	(.../FeedbackReplaceDlg.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -132,29 +132,29 @@
 void CFeedbackReplaceDlg::OnBnClickedReplaceButton()
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_Overwrite);
+	EndDialog(chcore::EFeedbackResult::eResult_Overwrite);
 }
 
 void CFeedbackReplaceDlg::OnBnClickedCopyRestButton()
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_CopyRest);
+	EndDialog(chcore::EFeedbackResult::eResult_CopyRest);
 }
 
 void CFeedbackReplaceDlg::OnBnClickedSkipButton()
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_Skip);
+	EndDialog(chcore::EFeedbackResult::eResult_Skip);
 }
 
 void CFeedbackReplaceDlg::OnBnClickedPauseButton()
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_Pause);
+	EndDialog(chcore::EFeedbackResult::eResult_Pause);
 }
 
 void CFeedbackReplaceDlg::OnBnClickedCancelButton()
 {
 	UpdateData(TRUE);
-	EndDialog(CFeedbackHandler::eResult_Cancel);
+	EndDialog(chcore::EFeedbackResult::eResult_Cancel);
 }
Index: src/ch/MainWnd.cpp
===================================================================
diff -u -r39864b5fbb931e3b257afbd60cfb7f36f71d146d -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision 39864b5fbb931e3b257afbd60cfb7f36f71d146d)
+++ src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -44,6 +44,7 @@
 #include "../libchcore/TSQLiteSerializerFactory.h"
 #include "TRecentPathsTools.h"
 #include "DirectoryChooser.h"
+#include "FeedbackHandlerFactory.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
Index: src/ch/ch.vc120.vcxproj
===================================================================
diff -u -r122f5f17f602b989c626ab31bb7f32c4211f93bd -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/ch/ch.vc120.vcxproj	(.../ch.vc120.vcxproj)	(revision 122f5f17f602b989c626ab31bb7f32c4211f93bd)
+++ src/ch/ch.vc120.vcxproj	(.../ch.vc120.vcxproj)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -513,6 +513,7 @@
     <ClInclude Include="..\common\version.h" />
     <ClInclude Include="DirectoryChooser.h" />
     <ClInclude Include="FeedbackHandler.h" />
+    <ClInclude Include="FeedbackHandlerFactory.h" />
     <ClInclude Include="structs.h" />
     <ClInclude Include="AppHelper.h" />
     <ClInclude Include="CfgProperties.h" />
@@ -752,6 +753,7 @@
     <ClCompile Include="..\common\TShellExtMenuConfig.cpp" />
     <ClCompile Include="DirectoryChooser.cpp" />
     <ClCompile Include="FeedbackHandler.cpp" />
+    <ClCompile Include="FeedbackHandlerFactory.cpp" />
     <ClCompile Include="structs.cpp" />
     <ClCompile Include="AppHelper.cpp" />
     <ClCompile Include="ClipboardMonitor.cpp" />
Index: src/ch/ch.vc120.vcxproj.filters
===================================================================
diff -u -refef4b7b215e689180d0c02a3f7a89f8089bdc8e -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/ch/ch.vc120.vcxproj.filters	(.../ch.vc120.vcxproj.filters)	(revision efef4b7b215e689180d0c02a3f7a89f8089bdc8e)
+++ src/ch/ch.vc120.vcxproj.filters	(.../ch.vc120.vcxproj.filters)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -206,6 +206,9 @@
     <ClInclude Include="DirectoryChooser.h">
       <Filter>Source Files\Tools</Filter>
     </ClInclude>
+    <ClInclude Include="FeedbackHandlerFactory.h">
+      <Filter>Source Files\Core</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\common\TShellExtMenuConfig.cpp">
@@ -343,6 +346,9 @@
     <ClCompile Include="DirectoryChooser.cpp">
       <Filter>Source Files\Tools</Filter>
     </ClCompile>
+    <ClCompile Include="FeedbackHandlerFactory.cpp">
+      <Filter>Source Files\Core</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="res\ch.rc2">
Fisheye: tag 458af7bf8c35950fdeb4b906950437596324aea1 is not in file src/libchcore/EFeedbackResult.h
Index: src/libchcore/IFeedbackHandler.h
===================================================================
diff -u -r1da7ee476d3e1e818d3af54210ba55d7063d1a2c -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/IFeedbackHandler.h	(.../IFeedbackHandler.h)	(revision 1da7ee476d3e1e818d3af54210ba55d7063d1a2c)
+++ src/libchcore/IFeedbackHandler.h	(.../IFeedbackHandler.h)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -20,78 +20,45 @@
 #define __FEEDBACKHANDLERBASE_H__
 
 #include "libchcore.h"
+#include "EFeedbackResult.h"
 #include "TString.h"
+#include "TFileInfo.h"
+#include "ISerializerRowReader.h"
+#include "ISerializerRowData.h"
 
 BEGIN_CHCORE_NAMESPACE
 
-class TFileInfo;
-typedef boost::shared_ptr<TFileInfo> TFileInfoPtr;
-
-enum EFileError
+enum class EFileError
 {
-	eDeleteError,		///< Problem occured when tried to delete the fs object
-	eSeekError,			///< Problem occured when tried to set file pointer
-	eResizeError,		///< Problem occured when tried to change size of the fs object
-	eReadError,			///< Problem occured when tried to read data from file
-	eWriteError,		///< Problem occured when tried to write data to a file
-	eFastMoveError,		///< Problem occured when tried to perform fast move operation (that does not involve copying contents)
-	eCreateError		///< Problem occured when tried to create the fs object
+	eDeleteError,		///< Problem occurred when tried to delete the fs object
+	eSeekError,			///< Problem occurred when tried to set file pointer
+	eResizeError,		///< Problem occurred when tried to change size of the fs object
+	eReadError,			///< Problem occurred when tried to read data from file
+	eWriteError,		///< Problem occurred when tried to write data to a file
+	eFastMoveError,		///< Problem occurred when tried to perform fast move operation (that does not involve copying contents)
+	eCreateError		///< Problem occurred when tried to create the fs object
 };
 
-struct FEEDBACK_ALREADYEXISTS
-{
-	TFileInfoPtr spSrcFileInfo;
-	TFileInfoPtr spDstFileInfo;
-};
-
-struct FEEDBACK_FILEERROR
-{
-	TString strSrcPath;
-	TString strDstPath;
-	EFileError eFileError;			// error type
-	ulong_t ulError;				// system error
-};
-
-struct FEEDBACK_NOTENOUGHSPACE
-{
-	ull_t ullRequiredSize;
-	TString strSrcPath;
-	TString strDstPath;
-};
-
 class LIBCHCORE_API 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
-	};
+	virtual ~IFeedbackHandler();
 
-	enum EFeedbackResult
-	{
-		eResult_Unknown = 0,
-		eResult_Overwrite,
-		eResult_CopyRest,
-		eResult_Skip,
-		eResult_Cancel,
-		eResult_Pause,
-		eResult_Retry,
-		eResult_Ignore
-	};
+	// requests with some processing data
+	virtual EFeedbackResult FileError(const TString& strSrcPath, const TString& strDstPath, EFileError eFileError, unsigned long ulError) = 0;
+	virtual EFeedbackResult FileAlreadyExists(const TFileInfoPtr& spSrcFileInfo, const TFileInfoPtr& spDstFileInfo) = 0;
+	virtual EFeedbackResult NotEnoughSpace(const TString& strSrcPath, const TString& strDstPath, unsigned long long ullRequiredSize) = 0;
 
-public:
-	virtual ~IFeedbackHandler();
+	// no-data requests
+	virtual EFeedbackResult OperationFinished() = 0;
+	virtual EFeedbackResult OperationError() = 0;
 
-	virtual unsigned long long RequestFeedback(unsigned long long ullFeedbackID, void* pFeedbackParam) = 0;
+	// reset permanent states
 	virtual void RestoreDefaults() = 0;
+
+	//serialization
+	virtual void Store(const ISerializerContainerPtr& spContainer) const = 0;
+	virtual void Load(const ISerializerContainerPtr& spContainer) = 0;
 };
 
 typedef boost::shared_ptr<IFeedbackHandler> IFeedbackHandlerPtr;
Index: src/libchcore/IFeedbackHandlerFactory.h
===================================================================
diff -u -r458af7bf8c35950fdeb4b906950437596324aea1 -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/IFeedbackHandlerFactory.h	(.../IFeedbackHandlerFactory.h)	(revision 458af7bf8c35950fdeb4b906950437596324aea1)
+++ src/libchcore/IFeedbackHandlerFactory.h	(.../IFeedbackHandlerFactory.h)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -28,7 +28,6 @@
 {
 public:
 	virtual ~IFeedbackHandlerFactory();
-
 	virtual IFeedbackHandlerPtr Create() = 0;
 };
 
Index: src/libchcore/TFeedbackHandlerBase.cpp
===================================================================
diff -u
--- src/libchcore/TFeedbackHandlerBase.cpp	(revision 0)
+++ src/libchcore/TFeedbackHandlerBase.cpp	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -0,0 +1,144 @@
+// ============================================================================
+//  Copyright (C) 2001-2015 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "TFeedbackHandlerBase.h"
+#include "SerializerDataTypes.h"
+#include "ISerializerContainer.h"
+
+BEGIN_CHCORE_NAMESPACE
+
+TFeedbackHandlerBase::TFeedbackHandlerBase() :
+	m_eFileError(m_setModifications, EFeedbackResult::eResult_Unknown),
+	m_eFileAlreadyExists(m_setModifications, EFeedbackResult::eResult_Unknown),
+	m_eNotEnoughSpace(m_setModifications, EFeedbackResult::eResult_Unknown),
+	m_eOperationFinished(m_setModifications, EFeedbackResult::eResult_Unknown),
+	m_eOperationError(m_setModifications, EFeedbackResult::eResult_Unknown)
+{
+	m_setModifications[eMod_Added] = true;
+}
+
+TFeedbackHandlerBase::~TFeedbackHandlerBase()
+{
+}
+
+void TFeedbackHandlerBase::Store(const ISerializerContainerPtr& spContainer) const
+{
+	boost::shared_lock<boost::shared_mutex> lock(m_lock);
+
+	if (m_setModifications.any())
+	{
+		InitColumns(spContainer);
+
+		bool bAdded = m_setModifications[eMod_Added];
+		ISerializerRowData& rRowData = spContainer->GetRow(0, bAdded);
+
+		if (bAdded || m_eFileError.IsModified())
+			rRowData.SetValue(_T("file_error"), m_eFileError);
+
+		if (bAdded || m_eFileAlreadyExists.IsModified())
+			rRowData.SetValue(_T("file_already_exists"), m_eFileAlreadyExists);
+
+		if (bAdded || m_eNotEnoughSpace.IsModified())
+			rRowData.SetValue(_T("not_enough_space"), m_eNotEnoughSpace);
+
+		if (bAdded || m_eOperationFinished.IsModified())
+			rRowData.SetValue(_T("operation_finished"), m_eOperationFinished);
+
+		if (bAdded || m_eOperationError.IsModified())
+			rRowData.SetValue(_T("operation_error"), m_eOperationError);
+
+		m_setModifications.reset();
+	}
+}
+
+void TFeedbackHandlerBase::InitColumns(const ISerializerContainerPtr& spContainer)
+{
+	IColumnsDefinition& rColumnDefs = spContainer->GetColumnsDefinition();
+	if (rColumnDefs.IsEmpty())
+	{
+		rColumnDefs.AddColumn(_T("id"), ColumnType<object_id_t>::value);
+		rColumnDefs.AddColumn(_T("file_error"), IColumnsDefinition::eType_int);
+		rColumnDefs.AddColumn(_T("file_already_exists"), IColumnsDefinition::eType_int);
+		rColumnDefs.AddColumn(_T("not_enough_space"), IColumnsDefinition::eType_int);
+		rColumnDefs.AddColumn(_T("operation_finished"), IColumnsDefinition::eType_int);
+		rColumnDefs.AddColumn(_T("operation_error"), IColumnsDefinition::eType_int);
+	}
+}
+
+void TFeedbackHandlerBase::Load(const ISerializerContainerPtr& spContainer)
+{
+	boost::unique_lock<boost::shared_mutex> lock(m_lock);
+
+	InitColumns(spContainer);
+	ISerializerRowReaderPtr spRowReader = spContainer->GetRowReader();
+	if (spRowReader->Next())
+	{
+		int iFeedbackResult = eResult_Unknown;
+
+		spRowReader->GetValue(_T("file_error"), iFeedbackResult);
+		m_eFileError = (EFeedbackResult) iFeedbackResult;
+
+		spRowReader->GetValue(_T("file_already_exists"), iFeedbackResult);
+		m_eFileAlreadyExists = (EFeedbackResult) iFeedbackResult;
+		spRowReader->GetValue(_T("not_enough_space"), iFeedbackResult);
+		m_eNotEnoughSpace = (EFeedbackResult) iFeedbackResult;
+		spRowReader->GetValue(_T("operation_finished"), iFeedbackResult);
+		m_eOperationFinished = (EFeedbackResult) iFeedbackResult;
+		spRowReader->GetValue(_T("operation_error"), iFeedbackResult);
+		m_eOperationError = (EFeedbackResult) iFeedbackResult;
+
+		m_setModifications.reset();
+	}
+}
+
+void TFeedbackHandlerBase::RestoreDefaults()
+{
+	m_eFileError = EFeedbackResult::eResult_Unknown;
+	m_eFileAlreadyExists = EFeedbackResult::eResult_Unknown;
+	m_eNotEnoughSpace = EFeedbackResult::eResult_Unknown;
+	m_eOperationFinished = EFeedbackResult::eResult_Unknown;
+	m_eOperationError = EFeedbackResult::eResult_Unknown;
+}
+
+chcore::EFeedbackResult TFeedbackHandlerBase::FileError(const TString& /*strSrcPath*/, const TString& /*strDstPath*/, EFileError /*eFileError*/, unsigned long /*ulError*/)
+{
+	return m_eFileError;
+}
+
+chcore::EFeedbackResult TFeedbackHandlerBase::FileAlreadyExists(const TFileInfoPtr& /*spSrcFileInfo*/, const TFileInfoPtr& /*spDstFileInfo*/)
+{
+	return m_eFileAlreadyExists;
+}
+
+chcore::EFeedbackResult TFeedbackHandlerBase::NotEnoughSpace(const TString& /*strSrcPath*/, const TString& /*strDstPath*/, unsigned long long /*ullRequiredSize*/)
+{
+	return m_eNotEnoughSpace;
+}
+
+chcore::EFeedbackResult TFeedbackHandlerBase::OperationFinished()
+{
+	return m_eOperationFinished;
+}
+
+chcore::EFeedbackResult TFeedbackHandlerBase::OperationError()
+{
+	return m_eOperationError;
+}
+
+END_CHCORE_NAMESPACE
Index: src/libchcore/TFeedbackHandlerBase.h
===================================================================
diff -u
--- src/libchcore/TFeedbackHandlerBase.h	(revision 0)
+++ src/libchcore/TFeedbackHandlerBase.h	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -0,0 +1,102 @@
+// ============================================================================
+//  Copyright (C) 2001-2015 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#ifndef __TFEEDBACKHANDLERBASE_H__
+#define __TFEEDBACKHANDLERBASE_H__
+
+#include "libchcore.h"
+#include "IFeedbackHandler.h"
+#include "ISerializerRowData.h"
+#include "IColumnsDefinition.h"
+#include "ISerializerRowReader.h"
+#include <bitset>
+#include "TSharedModificationTracker.h"
+
+BEGIN_CHCORE_NAMESPACE
+
+class LIBCHCORE_API TFeedbackHandlerBase : public IFeedbackHandler
+{
+public:
+	TFeedbackHandlerBase();
+	virtual ~TFeedbackHandlerBase();
+
+	virtual EFeedbackResult FileError(const TString& strSrcPath, const TString& strDstPath, EFileError eFileError, unsigned long ulError) override;
+	virtual EFeedbackResult FileAlreadyExists(const TFileInfoPtr& spSrcFileInfo, const TFileInfoPtr& spDstFileInfo) override;
+	virtual EFeedbackResult NotEnoughSpace(const TString& strSrcPath, const TString& strDstPath, unsigned long long ullRequiredSize) override;
+
+	virtual EFeedbackResult OperationFinished() override;
+	virtual EFeedbackResult OperationError() override;
+
+	// marking responses as permanent
+	void SetFileErrorPermanentResponse(EFeedbackResult ePermanentResult) { m_eFileError = ePermanentResult; }
+	EFeedbackResult GetFileErrorPermanentResponse() const { return m_eFileError; }
+
+	void SetFileAlreadyExistsPermanentResponse(EFeedbackResult ePermanentResult) { m_eFileAlreadyExists = ePermanentResult; }
+	EFeedbackResult GetFileAlreadyExistsPermanentResponse() const { return m_eFileAlreadyExists; }
+
+	void SetNotEnoughSpacePermanentResponse(EFeedbackResult ePermanentResult) { m_eNotEnoughSpace = ePermanentResult; }
+	EFeedbackResult GetNotEnoughSpacePermanentResponse() const { return m_eNotEnoughSpace; }
+
+	void SetOperationFinishedPermanentResponse(EFeedbackResult ePermanentResult) { m_eOperationFinished = ePermanentResult; }
+	EFeedbackResult GetOperationFinishedPermanentResponse() const { return m_eOperationFinished; }
+
+	void SetOperationErrorPermanentResponse(EFeedbackResult ePermanentResult) { m_eOperationError = ePermanentResult; }
+	EFeedbackResult GetOperationErrorPermanentResponse() const { return m_eOperationError; }
+
+	// resets the permanent status from all responses
+	virtual void RestoreDefaults() override;
+
+	// serialization
+	void Store(const ISerializerContainerPtr& spContainer) const;
+	static void InitColumns(const ISerializerContainerPtr& spContainer);
+	void Load(const ISerializerContainerPtr& spContainer);
+
+private:
+	enum EModifications
+	{
+		eMod_Added = 0,
+		eMod_FileError,
+		eMod_FileAlreadyExists,
+		eMod_NotEnoughSpace,
+		eMod_OperationFinished,
+		eMod_OperationError,
+
+		// last item
+		eMod_Last
+	};
+
+#pragma warning(push)
+#pragma warning(disable: 4251)
+	mutable boost::shared_mutex m_lock;
+
+	using Bitset = std::bitset<eMod_Last>;
+	mutable Bitset m_setModifications;
+
+	TSharedModificationTracker<EFeedbackResult, Bitset, eMod_FileError> m_eFileError;
+	TSharedModificationTracker<EFeedbackResult, Bitset, eMod_FileAlreadyExists> m_eFileAlreadyExists;
+	TSharedModificationTracker<EFeedbackResult, Bitset, eMod_NotEnoughSpace> m_eNotEnoughSpace;
+	TSharedModificationTracker<EFeedbackResult, Bitset, eMod_OperationFinished> m_eOperationFinished;
+	TSharedModificationTracker<EFeedbackResult, Bitset, eMod_OperationError> m_eOperationError;
+#pragma warning(pop)
+};
+
+typedef boost::shared_ptr<TFeedbackHandlerBase> TFeedbackHandlerBasePtr;
+
+END_CHCORE_NAMESPACE
+
+#endif
Index: src/libchcore/TFeedbackHandlerWrapper.cpp
===================================================================
diff -u -r1da7ee476d3e1e818d3af54210ba55d7063d1a2c -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/TFeedbackHandlerWrapper.cpp	(.../TFeedbackHandlerWrapper.cpp)	(revision 1da7ee476d3e1e818d3af54210ba55d7063d1a2c)
+++ src/libchcore/TFeedbackHandlerWrapper.cpp	(.../TFeedbackHandlerWrapper.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -32,16 +32,54 @@
 {
 }
 
-unsigned long long TFeedbackHandlerWrapper::RequestFeedback(unsigned long long ullFeedbackID, void* pFeedbackParam)
+chcore::EFeedbackResult TFeedbackHandlerWrapper::FileError(const TString& strSrcPath, const TString& strDstPath, EFileError eFileError, unsigned long ulError)
 {
 	TScopedRunningTimeTrackerPause scopedTimePause(m_rTimeGuard);
 
-	return m_spFeedbackHandler->RequestFeedback(ullFeedbackID, pFeedbackParam);
+	return m_spFeedbackHandler->FileError(strSrcPath, strDstPath, eFileError, ulError);
 }
 
+chcore::EFeedbackResult TFeedbackHandlerWrapper::FileAlreadyExists(const TFileInfoPtr& spSrcFileInfo, const TFileInfoPtr& spDstFileInfo)
+{
+	TScopedRunningTimeTrackerPause scopedTimePause(m_rTimeGuard);
+
+	return m_spFeedbackHandler->FileAlreadyExists(spSrcFileInfo, spDstFileInfo);
+}
+
+chcore::EFeedbackResult TFeedbackHandlerWrapper::NotEnoughSpace(const TString& strSrcPath, const TString& strDstPath, unsigned long long ullRequiredSize)
+{
+	TScopedRunningTimeTrackerPause scopedTimePause(m_rTimeGuard);
+
+	return m_spFeedbackHandler->NotEnoughSpace(strSrcPath, strDstPath, ullRequiredSize);
+}
+
+chcore::EFeedbackResult TFeedbackHandlerWrapper::OperationFinished()
+{
+	TScopedRunningTimeTrackerPause scopedTimePause(m_rTimeGuard);
+
+	return m_spFeedbackHandler->OperationFinished();
+}
+
+chcore::EFeedbackResult TFeedbackHandlerWrapper::OperationError()
+{
+	TScopedRunningTimeTrackerPause scopedTimePause(m_rTimeGuard);
+
+	return m_spFeedbackHandler->OperationError();
+}
+
 void TFeedbackHandlerWrapper::RestoreDefaults()
 {
 	return m_spFeedbackHandler->RestoreDefaults();
 }
 
+void TFeedbackHandlerWrapper::Store(const ISerializerContainerPtr& spContainer) const
+{
+	return m_spFeedbackHandler->Store(spContainer);
+}
+
+void TFeedbackHandlerWrapper::Load(const ISerializerContainerPtr& spContainer)
+{
+	return m_spFeedbackHandler->Load(spContainer);
+}
+
 END_CHCORE_NAMESPACE
Index: src/libchcore/TFeedbackHandlerWrapper.h
===================================================================
diff -u -r1da7ee476d3e1e818d3af54210ba55d7063d1a2c -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/TFeedbackHandlerWrapper.h	(.../TFeedbackHandlerWrapper.h)	(revision 1da7ee476d3e1e818d3af54210ba55d7063d1a2c)
+++ src/libchcore/TFeedbackHandlerWrapper.h	(.../TFeedbackHandlerWrapper.h)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -36,9 +36,17 @@
 	TFeedbackHandlerWrapper(const TFeedbackHandlerWrapper&) = delete;
 	TFeedbackHandlerWrapper& operator=(const TFeedbackHandlerWrapper&) = delete;
 
-	virtual unsigned long long RequestFeedback(unsigned long long ullFeedbackID, void* pFeedbackParam) override;
+	virtual EFeedbackResult FileError(const TString& strSrcPath, const TString& strDstPath, EFileError eFileError, unsigned long ulError) override;
+	virtual EFeedbackResult FileAlreadyExists(const TFileInfoPtr& spSrcFileInfo, const TFileInfoPtr& spDstFileInfo) override;
+	virtual EFeedbackResult NotEnoughSpace(const TString& strSrcPath, const TString& strDstPath, unsigned long long ullRequiredSize) override;
+	virtual EFeedbackResult OperationFinished() override;
+	virtual EFeedbackResult OperationError() override;
+
 	virtual void RestoreDefaults() override;
 
+	virtual void Store(const ISerializerContainerPtr& spContainer) const override;
+	virtual void Load(const ISerializerContainerPtr& spContainer) override;
+
 private:
 	IFeedbackHandlerPtr m_spFeedbackHandler;
 	TScopedRunningTimeTracker& m_rTimeGuard;
Index: src/libchcore/TSQLiteTaskSchema.cpp
===================================================================
diff -u -ra476ced2f2235ee21c69176e88eba1cf7aea861f -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/TSQLiteTaskSchema.cpp	(.../TSQLiteTaskSchema.cpp)	(revision a476ced2f2235ee21c69176e88eba1cf7aea861f)
+++ src/libchcore/TSQLiteTaskSchema.cpp	(.../TSQLiteTaskSchema.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -43,136 +43,175 @@
 	// that's why the initialization always creates the latest version of database, whithout going
 	// through all the intermediate migrations
 	if(tVersion.GetVersion() == 0)
+		CreateNewDatabase(spDatabase, tVersion);
+	else
 	{
-		sqlite::TSQLiteStatement tStatement(spDatabase);
-		tStatement.Prepare(_T("CREATE TABLE task(id BIGINT UNIQUE, name varchar(256) NOT NULL, log_path VARCHAR(32768), current_state INT NOT NULL, destination_path varchar(32768) NOT NULL)"));
-		tStatement.Step();
+		// migrate current database to the newest version
+		if (tVersion.GetVersion() == 1)
+			Migrate_001_002(spDatabase, tVersion);
 
-		tStatement.Prepare(_T("CREATE TABLE base_paths(id BIGINT UNIQUE, src_path varchar(32768) NOT NULL, skip_processing boolean NOT NULL, dst_path varchar(32768) NOT NULL)"));
-		tStatement.Step();
+		if (tVersion.GetVersion() == 2)
+			Migrate_002_003(spDatabase, tVersion);
 
-		tStatement.Prepare(_T("CREATE TABLE scanned_files(id BIGINT UNIQUE, rel_path varchar(32768) NOT NULL, base_path_id BIGINT NOT NULL, attr INT NOT NULL, size BIGINT NOT NULL, time_created BIGINT NOT NULL, time_last_write BIGINT NOT NULL, time_last_access BIGINT NOT NULL, flags INT NOT NULL)"));
-		tStatement.Step();
+		if (tVersion.GetVersion() == 3)
+			Migrate_003_004(spDatabase, tVersion);
+	}
 
-		tStatement.Prepare(_T("CREATE TABLE task_config(id BIGINT UNIQUE, name varchar(256) NOT NULL, node_order INT NOT NULL, value varchar(32768) NOT NULL)"));
-		tStatement.Step();
+	tTransaction.Commit();
+}
 
-		tStatement.Prepare(_T("CREATE TABLE filters(id BIGINT UNIQUE, use_mask INT NOT NULL, mask varchar(32768) NOT NULL, ")
-			_T("use_exclude_mask INT NOT NULL, exclude_mask varchar(32768) NOT NULL, ")
-			_T("use_size_1 INT NOT NULL, compare_type_1 INT NOT NULL, size_1 BIGINT NOT NULL, ")
-			_T("use_size_2 INT NOT NULL, compare_type_2 INT NOT NULL, size_2 BIGINT NOT NULL, ")
-			_T("date_type INT NOT NULL,")
-			_T("use_date_time_1 INT NOT NULL, date_compare_type_1 INT NOT NULL, use_date_1 INT NOT NULL, use_time_1 INT NOT NULL, datetime_1 varchar(64) NOT NULL, ")
-			_T("use_date_time_2 INT NOT NULL, date_compare_type_2 INT NOT NULL, use_date_2 INT NOT NULL, use_time_2 INT NOT NULL, datetime_2 varchar(64) NOT NULL, ")
-			_T("use_attributes INT NOT NULL, attr_archive INT NOT NULL, attr_ro INT NOT NULL, attr_hidden INT NOT NULL, attr_system INT NOT NULL, attr_directory INT NOT NULL")
-			_T(")"));
-		tStatement.Step();
+void TSQLiteTaskSchema::CreateNewDatabase(const sqlite::TSQLiteDatabasePtr& spDatabase, TSerializerVersion &tVersion)
+{
+	sqlite::TSQLiteStatement tStatement(spDatabase);
+	tStatement.Prepare(_T("CREATE TABLE task(id BIGINT UNIQUE, name varchar(256) NOT NULL, log_path VARCHAR(32768), current_state INT NOT NULL, destination_path varchar(32768) NOT NULL)"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("CREATE TABLE local_stats(id BIGINT UNIQUE, elapsed_time BIGINT NOT NULL)"));
-		tStatement.Step();
+	tStatement.Prepare(_T("CREATE TABLE base_paths(id BIGINT UNIQUE, src_path varchar(32768) NOT NULL, skip_processing boolean NOT NULL, dst_path varchar(32768) NOT NULL)"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("CREATE TABLE subtasks(id BIGINT UNIQUE, type INT NOT NULL, is_current boolean NOT NULL, is_estimation boolean NOT NULL)"));
-		tStatement.Step();
+	tStatement.Prepare(_T("CREATE TABLE scanned_files(id BIGINT UNIQUE, rel_path varchar(32768) NOT NULL, base_path_id BIGINT NOT NULL, attr INT NOT NULL, size BIGINT NOT NULL, time_created BIGINT NOT NULL, time_last_write BIGINT NOT NULL, time_last_access BIGINT NOT NULL, flags INT NOT NULL)"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("CREATE TABLE subtasks_info(id BIGINT UNIQUE, operation INT NOT NULL)"));
-		tStatement.Step();
+	tStatement.Prepare(_T("CREATE TABLE task_config(id BIGINT UNIQUE, name varchar(256) NOT NULL, node_order INT NOT NULL, value varchar(32768) NOT NULL)"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("CREATE TABLE subtask_fastmove(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
-							_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
-							_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
-		tStatement.Step();
+	tStatement.Prepare(_T("CREATE TABLE filters(id BIGINT UNIQUE, use_mask INT NOT NULL, mask varchar(32768) NOT NULL, ")
+		_T("use_exclude_mask INT NOT NULL, exclude_mask varchar(32768) NOT NULL, ")
+		_T("use_size_1 INT NOT NULL, compare_type_1 INT NOT NULL, size_1 BIGINT NOT NULL, ")
+		_T("use_size_2 INT NOT NULL, compare_type_2 INT NOT NULL, size_2 BIGINT NOT NULL, ")
+		_T("date_type INT NOT NULL,")
+		_T("use_date_time_1 INT NOT NULL, date_compare_type_1 INT NOT NULL, use_date_1 INT NOT NULL, use_time_1 INT NOT NULL, datetime_1 varchar(64) NOT NULL, ")
+		_T("use_date_time_2 INT NOT NULL, date_compare_type_2 INT NOT NULL, use_date_2 INT NOT NULL, use_time_2 INT NOT NULL, datetime_2 varchar(64) NOT NULL, ")
+		_T("use_attributes INT NOT NULL, attr_archive INT NOT NULL, attr_ro INT NOT NULL, attr_hidden INT NOT NULL, attr_system INT NOT NULL, attr_directory INT NOT NULL")
+		_T(")"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("CREATE TABLE subtask_delete(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
-							_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
-							_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
-		tStatement.Step();
+	tStatement.Prepare(_T("CREATE TABLE local_stats(id BIGINT UNIQUE, elapsed_time BIGINT NOT NULL)"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("CREATE TABLE subtask_copymove(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
-							_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
-							_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
-		tStatement.Step();
+	tStatement.Prepare(_T("CREATE TABLE subtasks(id BIGINT UNIQUE, type INT NOT NULL, is_current boolean NOT NULL, is_estimation boolean NOT NULL)"));
+	tStatement.Step();
 
-		// and finally set the database version to current one
-		tVersion.SetVersion(3);
-	}
+	tStatement.Prepare(_T("CREATE TABLE subtasks_info(id BIGINT UNIQUE, operation INT NOT NULL)"));
+	tStatement.Step();
 
-	if (tVersion.GetVersion() == 1)
-	{
-		sqlite::TSQLiteStatement tStatement(spDatabase);
+	tStatement.Prepare(_T("CREATE TABLE subtask_fastmove(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
+		_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
+		_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("ALTER TABLE subtask_fastmove ADD COLUMN ci_silent_resume boolean NOT NULL DEFAULT false"));
-		tStatement.Step();
-		tStatement.Prepare(_T("ALTER TABLE subtask_delete ADD COLUMN ci_silent_resume boolean NOT NULL DEFAULT false"));
-		tStatement.Step();
-		tStatement.Prepare(_T("ALTER TABLE subtask_copymove ADD COLUMN ci_silent_resume boolean NOT NULL DEFAULT false"));
-		tStatement.Step();
+	tStatement.Prepare(_T("CREATE TABLE subtask_delete(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
+		_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
+		_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
+	tStatement.Step();
 
-		tVersion.SetVersion(2);
-	}
+	tStatement.Prepare(_T("CREATE TABLE subtask_copymove(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
+		_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
+		_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
+	tStatement.Step();
 
-	if (tVersion.GetVersion() == 2)
-	{
-		sqlite::TSQLiteStatement tStatement(spDatabase);
+	tStatement.Prepare(_T("CREATE TABLE feedback(id BIGINT UNIQUE, file_error INT NOT NULL, file_already_exists INT NOT NULL, not_enough_space INT NOT NULL, operation_finished INT NOT NULL, operation_error INT NOT NULL)"));
+	tStatement.Step();
 
-		// drop column from fastmove
-		tStatement.Prepare(_T("CREATE TABLE subtask_fastmove_new(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
-			_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
-			_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
-		tStatement.Step();
+	// and finally set the database version to current one
+	tVersion.SetVersion(4);
+}
 
-		tStatement.Prepare(_T("INSERT INTO subtask_fastmove_new(id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, ")
-			_T("total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume)")
-			_T("SELECT id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, ")
-			_T("total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume ")
-			_T("FROM subtask_fastmove"));
-		tStatement.Step();
+void TSQLiteTaskSchema::Migrate_001_002(const sqlite::TSQLiteDatabasePtr& spDatabase, TSerializerVersion &tVersion)
+{
+	sqlite::TSQLiteStatement tStatement(spDatabase);
 
-		tStatement.Prepare(_T("DROP TABLE subtask_fastmove"));
-		tStatement.Step();
+	tStatement.Prepare(_T("ALTER TABLE subtask_fastmove ADD COLUMN ci_silent_resume boolean NOT NULL DEFAULT false"));
+	tStatement.Step();
+	tStatement.Prepare(_T("ALTER TABLE subtask_delete ADD COLUMN ci_silent_resume boolean NOT NULL DEFAULT false"));
+	tStatement.Step();
+	tStatement.Prepare(_T("ALTER TABLE subtask_copymove ADD COLUMN ci_silent_resume boolean NOT NULL DEFAULT false"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("ALTER TABLE subtask_fastmove_new RENAME TO subtask_fastmove"));
-		tStatement.Step();
+	tVersion.SetVersion(2);
+}
 
-		// drop column from subtask delete
-		tStatement.Prepare(_T("CREATE TABLE subtask_delete_new(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
-			_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
-			_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
-		tStatement.Step();
+void TSQLiteTaskSchema::Migrate_002_003(const sqlite::TSQLiteDatabasePtr& spDatabase, TSerializerVersion &tVersion)
+{
+	sqlite::TSQLiteStatement tStatement(spDatabase);
 
-		//id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume
-		tStatement.Prepare(_T("INSERT INTO subtask_delete_new(id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume)")
-			_T("SELECT id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume ")
-			_T("FROM subtask_delete"));
-		tStatement.Step();
+	// drop column from fastmove
+	tStatement.Prepare(_T("CREATE TABLE subtask_fastmove_new(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
+		_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
+		_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("DROP TABLE subtask_delete"));
-		tStatement.Step();
+	tStatement.Prepare(_T("INSERT INTO subtask_fastmove_new(id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, ")
+		_T("total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume)")
+		_T("SELECT id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, ")
+		_T("total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume ")
+		_T("FROM subtask_fastmove"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("ALTER TABLE subtask_delete_new RENAME TO subtask_delete"));
-		tStatement.Step();
+	tStatement.Prepare(_T("DROP TABLE subtask_fastmove"));
+	tStatement.Step();
 
-		// drop column from subtask copymove
-		tStatement.Prepare(_T("CREATE TABLE subtask_copymove_new(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
-			_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
-			_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
-		tStatement.Step();
+	tStatement.Prepare(_T("ALTER TABLE subtask_fastmove_new RENAME TO subtask_fastmove"));
+	tStatement.Step();
 
-		//id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume
-		tStatement.Prepare(_T("INSERT INTO subtask_copymove_new(id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume)")
-			_T("SELECT id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume ")
-			_T("FROM subtask_copymove"));
-		tStatement.Step();
+	// drop column from subtask delete
+	tStatement.Prepare(_T("CREATE TABLE subtask_delete_new(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
+		_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
+		_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("DROP TABLE subtask_copymove"));
-		tStatement.Step();
+	//id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume
+	tStatement.Prepare(_T("INSERT INTO subtask_delete_new(id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume)")
+		_T("SELECT id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume ")
+		_T("FROM subtask_delete"));
+	tStatement.Step();
 
-		tStatement.Prepare(_T("ALTER TABLE subtask_copymove_new RENAME TO subtask_copymove"));
-		tStatement.Step();
+	tStatement.Prepare(_T("DROP TABLE subtask_delete"));
+	tStatement.Step();
 
-		tVersion.SetVersion(3);
-	}
+	tStatement.Prepare(_T("ALTER TABLE subtask_delete_new RENAME TO subtask_delete"));
+	tStatement.Step();
 
-	tTransaction.Commit();
+	// drop column from subtask copymove
+	tStatement.Prepare(_T("CREATE TABLE subtask_copymove_new(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, is_initialized boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ")
+		_T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ")
+		_T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, ci_silent_resume boolean NOT NULL)"));
+	tStatement.Step();
+
+	//id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume
+	tStatement.Prepare(_T("INSERT INTO subtask_copymove_new(id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume)")
+		_T("SELECT id, current_index, is_running, is_initialized, total_size, processed_size, size_speed, total_count, processed_count, count_speed, ci_processed_size, ci_total_size, timer, buffer_index, current_path, ci_silent_resume ")
+		_T("FROM subtask_copymove"));
+	tStatement.Step();
+
+	tStatement.Prepare(_T("DROP TABLE subtask_copymove"));
+	tStatement.Step();
+
+	tStatement.Prepare(_T("ALTER TABLE subtask_copymove_new RENAME TO subtask_copymove"));
+	tStatement.Step();
+
+	tVersion.SetVersion(3);
 }
 
+void TSQLiteTaskSchema::Migrate_003_004(const sqlite::TSQLiteDatabasePtr& spDatabase, TSerializerVersion &tVersion)
+{
+	sqlite::TSQLiteStatement tStatement(spDatabase);
+
+	tStatement.Prepare(_T("CREATE TABLE feedback(id BIGINT UNIQUE, file_error INT NOT NULL, file_already_exists INT NOT NULL, not_enough_space INT NOT NULL, operation_finished INT NOT NULL, operation_error INT NOT NULL)"));
+	tStatement.Step();
+
+	// for tasks being migrated we have to insert some defaults for feedback
+	tStatement.Prepare(_T("INSERT INTO feedback(id, file_error, file_already_exists, not_enough_space, operation_finished, operation_error) VALUES(?1, ?2, ?3, ?4, ?5, ?6)"));
+	tStatement.BindValue(1, 0);
+	tStatement.BindValue(2, 0);
+	tStatement.BindValue(3, 0);
+	tStatement.BindValue(4, 0);
+	tStatement.BindValue(5, 0);
+	tStatement.BindValue(6, 0);
+
+	tStatement.Step();
+
+	tVersion.SetVersion(4);
+}
+
 END_CHCORE_NAMESPACE
Index: src/libchcore/TSQLiteTaskSchema.h
===================================================================
diff -u -rd32a79f0e9220bad2c6eeb5e8a986228b6e832fb -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/TSQLiteTaskSchema.h	(.../TSQLiteTaskSchema.h)	(revision d32a79f0e9220bad2c6eeb5e8a986228b6e832fb)
+++ src/libchcore/TSQLiteTaskSchema.h	(.../TSQLiteTaskSchema.h)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -24,13 +24,22 @@
 
 BEGIN_CHCORE_NAMESPACE
 
+class TSerializerVersion;
+
 class LIBCHCORE_API TSQLiteTaskSchema : public ISQLiteSerializerSchema
 {
 public:
 	TSQLiteTaskSchema();
 	virtual ~TSQLiteTaskSchema();
 
 	virtual void Setup(const sqlite::TSQLiteDatabasePtr& spDatabase);
+
+private:
+	void CreateNewDatabase(const sqlite::TSQLiteDatabasePtr& spDatabase, TSerializerVersion &tVersion);
+
+	void Migrate_001_002(const sqlite::TSQLiteDatabasePtr& spDatabase, TSerializerVersion &tVersion);
+	void Migrate_002_003(const sqlite::TSQLiteDatabasePtr& spDatabase, TSerializerVersion &tVersion);
+	void Migrate_003_004(const sqlite::TSQLiteDatabasePtr& spDatabase, TSerializerVersion &tVersion);
 };
 
 typedef boost::shared_ptr<TSQLiteTaskSchema> TSQLiteTaskSchemaPtr;
Index: src/libchcore/TSubTaskCopyMove.cpp
===================================================================
diff -u -rc66b22f786f8434075a09e92de52bba8a53a85db -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision c66b22f786f8434075a09e92de52bba8a53a85db)
+++ src/libchcore/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -671,15 +671,13 @@
 		{
 			DWORD dwLastError = GetLastError();
 
-			FEEDBACK_FILEERROR feedStruct = { spPathToOpen.ToString(), NULL, eCreateError, dwLastError };
-			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &feedStruct);
-
+			EFeedbackResult frResult = spFeedbackHandler->FileError(spPathToOpen.ToWString(), TString(), EFileError::eCreateError, dwLastError);
 			switch(frResult)
 			{
-			case IFeedbackHandler::eResult_Skip:
+			case EFeedbackResult::eResult_Skip:
 				break;	// will return INVALID_HANDLE_VALUE
 
-			case IFeedbackHandler::eResult_Cancel:
+			case EFeedbackResult::eResult_Cancel:
 				{
 					// log
 					TString strFormat = _T("Cancel request [error %errno] while opening source file %path (OpenSourceFileFB)");
@@ -690,10 +688,10 @@
 					return TSubTaskBase::eSubResult_CancelRequest;
 				}
 
-			case IFeedbackHandler::eResult_Pause:
+			case EFeedbackResult::eResult_Pause:
 				return TSubTaskBase::eSubResult_PauseRequest;
 
-			case IFeedbackHandler::eResult_Retry:
+			case EFeedbackResult::eResult_Retry:
 				{
 					// log
 					TString strFormat = _T("Retrying [error %errno] to open source file %path (OpenSourceFileFB)");
@@ -754,23 +752,21 @@
 					THROW_CORE_EXCEPTION_WIN32(eErr_CannotGetFileInfo, GetLastError());
 
 				// src and dst files are the same
-				FEEDBACK_ALREADYEXISTS feedStruct = { spSrcFileInfo, spDstFileInfo };
-				IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileAlreadyExists, &feedStruct);
-				// check for dialog result
+				EFeedbackResult frResult = spFeedbackHandler->FileAlreadyExists(spSrcFileInfo, spDstFileInfo);
 				switch(frResult)
 				{
-				case IFeedbackHandler::eResult_Overwrite:
+				case EFeedbackResult::eResult_Overwrite:
 					ullSeekTo = 0;
 					break;
 
-				case IFeedbackHandler::eResult_CopyRest:
+				case EFeedbackResult::eResult_CopyRest:
 					ullSeekTo = spDstFileInfo->GetLength64();
 					break;
 
-				case IFeedbackHandler::eResult_Skip:
+				case EFeedbackResult::eResult_Skip:
 					return TSubTaskBase::eSubResult_Continue;
 
-				case IFeedbackHandler::eResult_Cancel:
+				case EFeedbackResult::eResult_Cancel:
 					{
 						// log
 						TString strFormat = _T("Cancel request while checking result of dialog before opening source file %path (CustomCopyFileFB)");
@@ -779,7 +775,7 @@
 
 						return TSubTaskBase::eSubResult_CancelRequest;
 					}
-				case IFeedbackHandler::eResult_Pause:
+				case EFeedbackResult::eResult_Pause:
 					return TSubTaskBase::eSubResult_PauseRequest;
 
 				default:
@@ -789,11 +785,10 @@
 			}
 			else
 			{
-				FEEDBACK_FILEERROR feedStruct = { pathDstFile.ToString(), NULL, eCreateError, dwLastError };
-				IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &feedStruct);
+				EFeedbackResult frResult = spFeedbackHandler->FileError(pathDstFile.ToWString(), TString(), EFileError::eCreateError, dwLastError);
 				switch(frResult)
 				{
-				case IFeedbackHandler::eResult_Retry:
+				case EFeedbackResult::eResult_Retry:
 					{
 						// log
 						TString strFormat = _T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)");
@@ -805,7 +800,7 @@
 
 						break;
 					}
-				case IFeedbackHandler::eResult_Cancel:
+				case EFeedbackResult::eResult_Cancel:
 					{
 						// log
 						TString strFormat = _T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)");
@@ -816,10 +811,10 @@
 						return TSubTaskBase::eSubResult_CancelRequest;
 					}
 
-				case IFeedbackHandler::eResult_Skip:
+				case EFeedbackResult::eResult_Skip:
 					break;		// will return invalid handle value
 
-				case IFeedbackHandler::eResult_Pause:
+				case EFeedbackResult::eResult_Pause:
 					return TSubTaskBase::eSubResult_PauseRequest;
 
 				default:
@@ -849,11 +844,11 @@
 		if(!fileDst.OpenExistingForWriting(pathDstFile, bNoBuffering))
 		{
 			DWORD dwLastError = GetLastError();
-			FEEDBACK_FILEERROR feedStruct = { pathDstFile.ToString(), NULL, eCreateError, dwLastError };
-			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &feedStruct);
+
+			EFeedbackResult frResult = spFeedbackHandler->FileError(pathDstFile.ToWString(), TString(), EFileError::eCreateError, dwLastError);
 			switch (frResult)
 			{
-			case IFeedbackHandler::eResult_Retry:
+			case EFeedbackResult::eResult_Retry:
 				{
 					// log
 					TString strFormat = _T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)");
@@ -865,7 +860,7 @@
 
 					break;
 				}
-			case IFeedbackHandler::eResult_Cancel:
+			case EFeedbackResult::eResult_Cancel:
 				{
 					// log
 					TString strFormat = _T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)");
@@ -876,10 +871,10 @@
 					return TSubTaskBase::eSubResult_CancelRequest;
 				}
 
-			case IFeedbackHandler::eResult_Skip:
+			case EFeedbackResult::eResult_Skip:
 				break;		// will return invalid handle value
 
-			case IFeedbackHandler::eResult_Pause:
+			case EFeedbackResult::eResult_Pause:
 				return TSubTaskBase::eSubResult_PauseRequest;
 
 			default:
@@ -914,21 +909,20 @@
 			strFormat.Replace(_t("%pos"), boost::lexical_cast<std::wstring>(llDistance).c_str());
 			rLog.loge(strFormat.c_str());
 
-			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eSeekError, dwLastError };
-			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+			EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eSeekError, dwLastError);
 			switch(frResult)
 			{
-			case IFeedbackHandler::eResult_Cancel:
+			case EFeedbackResult::eResult_Cancel:
 				return TSubTaskBase::eSubResult_CancelRequest;
 
-			case IFeedbackHandler::eResult_Retry:
+			case EFeedbackResult::eResult_Retry:
 				bRetry = true;
 				break;
 
-			case IFeedbackHandler::eResult_Pause:
+			case EFeedbackResult::eResult_Pause:
 				return TSubTaskBase::eSubResult_PauseRequest;
 
-			case IFeedbackHandler::eResult_Skip:
+			case EFeedbackResult::eResult_Skip:
 				bSkip = true;
 				return TSubTaskBase::eSubResult_Continue;
 
@@ -962,20 +956,19 @@
 			strFormat.Replace(_t("%path"), pathFile.ToString());
 			rLog.loge(strFormat.c_str());
 
-			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eResizeError, dwLastError };
-			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+			EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eResizeError, dwLastError);
 			switch(frResult)
 			{
-			case IFeedbackHandler::eResult_Cancel:
+			case EFeedbackResult::eResult_Cancel:
 				return TSubTaskBase::eSubResult_CancelRequest;
 
-			case IFeedbackHandler::eResult_Retry:
+			case EFeedbackResult::eResult_Retry:
 				bRetry = true;
 
-			case IFeedbackHandler::eResult_Pause:
+			case EFeedbackResult::eResult_Pause:
 				return TSubTaskBase::eSubResult_PauseRequest;
 
-			case IFeedbackHandler::eResult_Skip:
+			case EFeedbackResult::eResult_Skip:
 				bSkip = true;
 				return TSubTaskBase::eSubResult_Continue;
 
@@ -1011,21 +1004,20 @@
 			strFormat.Replace(_t("%path"), pathFile.ToString());
 			rLog.loge(strFormat.c_str());
 
-			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eReadError, dwLastError };
-			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+			EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eReadError, dwLastError);
 			switch(frResult)
 			{
-			case IFeedbackHandler::eResult_Cancel:
+			case EFeedbackResult::eResult_Cancel:
 				return TSubTaskBase::eSubResult_CancelRequest;
 
-			case IFeedbackHandler::eResult_Retry:
+			case EFeedbackResult::eResult_Retry:
 				bRetry = true;
 				break;
 
-			case IFeedbackHandler::eResult_Pause:
+			case EFeedbackResult::eResult_Pause:
 				return TSubTaskBase::eSubResult_PauseRequest;
 
-			case IFeedbackHandler::eResult_Skip:
+			case EFeedbackResult::eResult_Skip:
 				bSkip = true;
 				return TSubTaskBase::eSubResult_Continue;
 
@@ -1062,21 +1054,20 @@
 			strFormat.Replace(_t("%path"), pathFile.ToString());
 			rLog.loge(strFormat.c_str());
 
-			FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eWriteError, dwLastError };
-			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+			EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eWriteError, dwLastError);
 			switch(frResult)
 			{
-			case IFeedbackHandler::eResult_Cancel:
+			case EFeedbackResult::eResult_Cancel:
 				return TSubTaskBase::eSubResult_CancelRequest;
 
-			case IFeedbackHandler::eResult_Retry:
+			case EFeedbackResult::eResult_Retry:
 				bRetry = true;
 				break;
 
-			case IFeedbackHandler::eResult_Pause:
+			case EFeedbackResult::eResult_Pause:
 				return TSubTaskBase::eSubResult_PauseRequest;
 
-			case IFeedbackHandler::eResult_Skip:
+			case EFeedbackResult::eResult_Skip:
 				bSkip = true;
 				return TSubTaskBase::eSubResult_Continue;
 
@@ -1171,21 +1162,20 @@
 		strFormat.Replace(_T("%path"), pathDirectory.ToString());
 		rLog.loge(strFormat.c_str());
 
-		FEEDBACK_FILEERROR ferr = { pathDirectory.ToString(), NULL, eCreateError, dwLastError };
-		IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+		EFeedbackResult frResult = spFeedbackHandler->FileError(pathDirectory.ToWString(), TString(), EFileError::eCreateError, dwLastError);
 		switch(frResult)
 		{
-		case IFeedbackHandler::eResult_Cancel:
+		case EFeedbackResult::eResult_Cancel:
 			return TSubTaskBase::eSubResult_CancelRequest;
 
-		case IFeedbackHandler::eResult_Retry:
+		case EFeedbackResult::eResult_Retry:
 			bRetry = false;
 			break;
 
-		case IFeedbackHandler::eResult_Pause:
+		case EFeedbackResult::eResult_Pause:
 			return TSubTaskBase::eSubResult_PauseRequest;
 
-		case IFeedbackHandler::eResult_Skip:
+		case EFeedbackResult::eResult_Skip:
 			bRetry = false;
 			break;		// just do nothing
 
@@ -1228,22 +1218,19 @@
 
 			if(!spSrcPaths->IsEmpty())
 			{
-				FEEDBACK_NOTENOUGHSPACE feedStruct = { ullNeededSize, spSrcPaths->GetAt(0)->GetSrcPath().ToString(), pathDestination.ToString() };
-				IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_NotEnoughSpace, &feedStruct);
-
-				// default
+				EFeedbackResult frResult = spFeedbackHandler->NotEnoughSpace(spSrcPaths->GetAt(0)->GetSrcPath().ToWString(), pathDestination.ToWString(), ullNeededSize);
 				switch(frResult)
 				{
-				case IFeedbackHandler::eResult_Cancel:
+				case EFeedbackResult::eResult_Cancel:
 					rLog.logi(_T("Cancel request while checking for free space on disk."));
 					return TSubTaskBase::eSubResult_CancelRequest;
 
-				case IFeedbackHandler::eResult_Retry:
+				case EFeedbackResult::eResult_Retry:
 					rLog.logi(_T("Retrying to read drive's free space..."));
 					bRetry = true;
 					break;
 
-				case IFeedbackHandler::eResult_Ignore:
+				case EFeedbackResult::eResult_Ignore:
 					rLog.logi(_T("Ignored warning about not enough place on disk to copy data."));
 					return TSubTaskBase::eSubResult_Continue;
 
Index: src/libchcore/TSubTaskDelete.cpp
===================================================================
diff -u -ra476ced2f2235ee21c69176e88eba1cf7aea861f -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/TSubTaskDelete.cpp	(.../TSubTaskDelete.cpp)	(revision a476ced2f2235ee21c69176e88eba1cf7aea861f)
+++ src/libchcore/TSubTaskDelete.cpp	(.../TSubTaskDelete.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -134,21 +134,20 @@
 			strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString());
 			rLog.loge(strFormat.c_str());
 
-			FEEDBACK_FILEERROR ferr = { spFileInfo->GetFullFilePath().ToString(), NULL, eDeleteError, dwLastError };
-			IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+			EFeedbackResult frResult = spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError);
 			switch(frResult)
 			{
-			case IFeedbackHandler::eResult_Cancel:
+			case EFeedbackResult::eResult_Cancel:
 				rLog.logi(_T("Cancel request while deleting file."));
 				return TSubTaskBase::eSubResult_CancelRequest;
 
-			case IFeedbackHandler::eResult_Retry:
+			case EFeedbackResult::eResult_Retry:
 				continue;	// no fcIndex bump, since we are trying again
 
-			case IFeedbackHandler::eResult_Pause:
+			case EFeedbackResult::eResult_Pause:
 				return TSubTaskBase::eSubResult_PauseRequest;
 
-			case IFeedbackHandler::eResult_Skip:
+			case EFeedbackResult::eResult_Skip:
 				break;		// just do nothing
 
 			default:
Index: src/libchcore/TSubTaskFastMove.cpp
===================================================================
diff -u -ra476ced2f2235ee21c69176e88eba1cf7aea861f -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/TSubTaskFastMove.cpp	(.../TSubTaskFastMove.cpp)	(revision a476ced2f2235ee21c69176e88eba1cf7aea861f)
+++ src/libchcore/TSubTaskFastMove.cpp	(.../TSubTaskFastMove.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -123,21 +123,20 @@
 			bool bExists = TLocalFilesystem::GetFileInfo(pathCurrent, spFileInfo, spBasePath);
 			if(!bExists)
 			{
-				FEEDBACK_FILEERROR ferr = { pathCurrent.ToString(), NULL, eFastMoveError, ERROR_FILE_NOT_FOUND };
-				IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+				EFeedbackResult frResult = spFeedbackHandler->FileError(pathCurrent.ToWString(), TString(), EFileError::eFastMoveError, ERROR_FILE_NOT_FOUND);
 				switch(frResult)
 				{
-				case IFeedbackHandler::eResult_Cancel:
+				case EFeedbackResult::eResult_Cancel:
 					return eSubResult_CancelRequest;
 
-				case IFeedbackHandler::eResult_Retry:
+				case EFeedbackResult::eResult_Retry:
 					bRetry = true;
 					break;
 
-				case IFeedbackHandler::eResult_Pause:
+				case EFeedbackResult::eResult_Pause:
 					return eSubResult_PauseRequest;
 
-				case IFeedbackHandler::eResult_Skip:
+				case EFeedbackResult::eResult_Skip:
 					bSkipInputPath = true;
 					break;		// just do nothing
 
@@ -187,23 +186,23 @@
 					strFormat.Replace(_T("%dstpath"), pathDestination.ToString());
 					rLog.loge(strFormat.c_str());
 
-					FEEDBACK_FILEERROR ferr = { pathSrc.ToString(), pathDestinationPath.ToString(), eFastMoveError, dwLastError };
-					IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+					EFeedbackResult frResult = spFeedbackHandler->FileError(pathSrc.ToWString(), pathDestinationPath.ToWString(), EFileError::eFastMoveError, dwLastError);
 					switch(frResult)
 					{
-					case IFeedbackHandler::eResult_Cancel:
+					case EFeedbackResult::eResult_Cancel:
 						return TSubTaskBase::eSubResult_CancelRequest;
 
-					case IFeedbackHandler::eResult_Retry:
+					case EFeedbackResult::eResult_Retry:
 						continue;
 
-					case IFeedbackHandler::eResult_Pause:
+					case EFeedbackResult::eResult_Pause:
 						return TSubTaskBase::eSubResult_PauseRequest;
 
-					case IFeedbackHandler::eResult_Skip:
+					case EFeedbackResult::eResult_Skip:
 						//bSkipInputPath = true;		// not needed, since we will break the loop anyway and there is no other processing for this path either
 						bRetry = false;
 						break;		// just do nothing
+
 					default:
 						BOOST_ASSERT(FALSE);		// unknown result
 						THROW_CORE_EXCEPTION(eErr_UnhandledCase);
Index: src/libchcore/TSubTaskScanDirectory.cpp
===================================================================
diff -u -ra476ced2f2235ee21c69176e88eba1cf7aea861f -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/TSubTaskScanDirectory.cpp	(.../TSubTaskScanDirectory.cpp)	(revision a476ced2f2235ee21c69176e88eba1cf7aea861f)
+++ src/libchcore/TSubTaskScanDirectory.cpp	(.../TSubTaskScanDirectory.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -126,23 +126,22 @@
 			bool bExists = TLocalFilesystem::GetFileInfo(pathCurrent, spFileInfo, spBasePath);
 			if(!bExists)
 			{
-				FEEDBACK_FILEERROR ferr = { pathCurrent.ToString(), NULL, eFastMoveError, ERROR_FILE_NOT_FOUND };
-				IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr);
+				EFeedbackResult frResult = spFeedbackHandler->FileError(pathCurrent.ToWString(), TString(), EFileError::eFastMoveError, ERROR_FILE_NOT_FOUND);
 				switch(frResult)
 				{
-				case IFeedbackHandler::eResult_Cancel:
+				case EFeedbackResult::eResult_Cancel:
 					rFilesCache.Clear();
 					return eSubResult_CancelRequest;
 
-				case IFeedbackHandler::eResult_Retry:
+				case EFeedbackResult::eResult_Retry:
 					bRetry = true;
 					break;
 
-				case IFeedbackHandler::eResult_Pause:
+				case EFeedbackResult::eResult_Pause:
 					rFilesCache.Clear();
 					return eSubResult_PauseRequest;
 
-				case IFeedbackHandler::eResult_Skip:
+				case EFeedbackResult::eResult_Skip:
 					bSkipInputPath = true;
 					break;		// just do nothing
 
Index: src/libchcore/TTask.cpp
===================================================================
diff -u -rc66b22f786f8434075a09e92de52bba8a53a85db -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/TTask.cpp	(.../TTask.cpp)	(revision c66b22f786f8434075a09e92de52bba8a53a85db)
+++ src/libchcore/TTask.cpp	(.../TTask.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -160,6 +160,9 @@
 		spContainer = m_spSerializer->GetContainer(_T("local_stats"));
 		m_tLocalStats.Load(spContainer);
 
+		spContainer = m_spSerializer->GetContainer(_T("feedback"));
+		m_spInternalFeedbackHandler->Load(spContainer);
+
 		m_tSubTasksArray.Load(m_spSerializer);
 
 		// ensure copy-based context entries are properly updated after loading
@@ -231,6 +234,9 @@
 		spContainer = m_spSerializer->GetContainer(_T("local_stats"));
 		m_tLocalStats.Store(spContainer);
 
+		spContainer = m_spSerializer->GetContainer(_T("feedback"));
+		m_spInternalFeedbackHandler->Store(spContainer);
+
 		m_tSubTasksArray.Store(m_spSerializer);
 	}
 
@@ -518,7 +524,7 @@
 		switch(eResult)
 		{
 		case TSubTaskBase::eSubResult_Error:
-			spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_OperationError, NULL);
+			spFeedbackHandler->OperationError();
 			SetTaskState(eTaskState_Error);
 			break;
 
@@ -537,7 +543,7 @@
 			break;
 
 		case TSubTaskBase::eSubResult_Continue:
-			spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_OperationFinished, NULL);
+			spFeedbackHandler->OperationFinished();
 			SetTaskState(eTaskState_Finished);
 			break;
 
@@ -576,7 +582,7 @@
 	m_log.loge(_T("Caught exception in ThrdProc"));
 
 	// let others know some error happened
-	spFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_OperationError, NULL);
+	spFeedbackHandler->OperationError();
 	SetTaskState(eTaskState_Error);
 
 	SetContinueFlag(false);
Index: src/libchcore/libchcore.vc120.vcxproj
===================================================================
diff -u -r7d59ab9183c933f2fc2682a95fb5d26cf2f952d7 -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/libchcore.vc120.vcxproj	(.../libchcore.vc120.vcxproj)	(revision 7d59ab9183c933f2fc2682a95fb5d26cf2f952d7)
+++ src/libchcore/libchcore.vc120.vcxproj	(.../libchcore.vc120.vcxproj)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -507,6 +507,7 @@
   <ItemGroup>
     <ClInclude Include="ConfigNode.h" />
     <ClInclude Include="ConfigNodeContainer.h" />
+    <ClInclude Include="EFeedbackResult.h" />
     <ClInclude Include="ESubTaskTypes.h" />
     <ClInclude Include="IColumnsDefinition.h" />
     <ClInclude Include="IFeedbackHandler.h" />
@@ -524,6 +525,7 @@
     <ClInclude Include="TBaseException.h" />
     <ClInclude Include="TConfigArray.h" />
     <ClInclude Include="TConfigNotifier.h" />
+    <ClInclude Include="TFeedbackHandlerBase.h" />
     <ClInclude Include="TFeedbackHandlerWrapper.h" />
     <ClInclude Include="TFileTime.h" />
     <ClInclude Include="TModificationTracker.h" />
@@ -683,6 +685,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="TFeedbackHandlerBase.cpp" />
     <ClCompile Include="TFeedbackHandlerWrapper.cpp" />
     <ClCompile Include="TFileTime.cpp" />
     <ClCompile Include="TModPathContainer.cpp" />
Index: src/libchcore/libchcore.vc120.vcxproj.filters
===================================================================
diff -u -r7d59ab9183c933f2fc2682a95fb5d26cf2f952d7 -r671f4b1792a20d98b186f4e0a9cc6a620dede019
--- src/libchcore/libchcore.vc120.vcxproj.filters	(.../libchcore.vc120.vcxproj.filters)	(revision 7d59ab9183c933f2fc2682a95fb5d26cf2f952d7)
+++ src/libchcore/libchcore.vc120.vcxproj.filters	(.../libchcore.vc120.vcxproj.filters)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
@@ -332,6 +332,12 @@
     <ClInclude Include="IRunningTimeControl.h">
       <Filter>Source Files\Stats</Filter>
     </ClInclude>
+    <ClInclude Include="TFeedbackHandlerBase.h">
+      <Filter>Source Files\Feedback</Filter>
+    </ClInclude>
+    <ClInclude Include="EFeedbackResult.h">
+      <Filter>Source Files\Feedback</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="TSubTaskArray.cpp">
@@ -616,5 +622,8 @@
     <ClCompile Include="IRunningTimeControl.cpp">
       <Filter>Source Files\Stats</Filter>
     </ClCompile>
+    <ClCompile Include="TFeedbackHandlerBase.cpp">
+      <Filter>Source Files\Feedback</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file