Index: src/libchcore/TSubTaskDelete.cpp
===================================================================
diff -u -rd468098a278a0d16c5b700236ea276b9c9677c9f -r25722a1d39e5d4bb49c5a60cbee3dda6c02cb193
--- src/libchcore/TSubTaskDelete.cpp	(.../TSubTaskDelete.cpp)	(revision d468098a278a0d16c5b700236ea276b9c9677c9f)
+++ src/libchcore/TSubTaskDelete.cpp	(.../TSubTaskDelete.cpp)	(revision 25722a1d39e5d4bb49c5a60cbee3dda6c02cb193)
@@ -39,6 +39,7 @@
 #include <boost/make_shared.hpp>
 #include "TBufferSizes.h"
 #include "TFileException.h"
+#include "TFilesystemFeedbackWrapper.h"
 
 namespace chcore
 {
@@ -67,6 +68,8 @@
 		TWorkerThreadController& rThreadController = GetContext().GetThreadController();
 		IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem();
 
+		TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, rLog);
+
 		// log
 		rLog.logi(_T("Deleting files (DeleteFiles)..."));
 
@@ -111,10 +114,11 @@
 
 			ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue;
 			// delete data
+			bool bProtectReadOnlyFiles = GetTaskPropValue<eTO_ProtectReadOnlyFiles>(GetContext().GetConfig());
 			if (spFileInfo->IsDirectory())
-				eResult = RemoveDirectoryFB(spFeedbackHandler, spFileInfo);
+				eResult = tFilesystemFBWrapper.RemoveDirectoryFB(spFileInfo, bProtectReadOnlyFiles);
 			else
-				eResult = DeleteFileFB(spFeedbackHandler, spFileInfo);
+				eResult = tFilesystemFBWrapper.DeleteFileFB(spFileInfo, bProtectReadOnlyFiles);
 
 			++fcIndex;
 		}
@@ -129,144 +133,6 @@
 		return TSubTaskBase::eSubResult_Continue;
 	}
 
-	TSubTaskBase::ESubOperationResult TSubTaskDelete::RemoveDirectoryFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TFileInfoPtr& spFileInfo)
-	{
-		const TConfig& rConfig = GetContext().GetConfig();
-		IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem();
-		icpf::log_file& rLog = GetContext().GetLog();
-
-		bool bRetry = false;
-		do
-		{
-			bRetry = false;
-
-			// #bug - changing read-only attribute should only be done when user explicitly requests it (via feedback response)
-			// for now it is ignored
-			try
-			{
-				if (!GetTaskPropValue<eTO_ProtectReadOnlyFiles>(rConfig))
-					spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY);
-			}
-			catch (const TFileException&)
-			{
-			}
-
-			DWORD dwLastError = ERROR_SUCCESS;
-			try
-			{
-				spFilesystem->RemoveDirectory(spFileInfo->GetFullFilePath());
-				return TSubTaskBase::eSubResult_Continue;
-			}
-			catch (const TFileException& e)
-			{
-				dwLastError = e.GetNativeError();
-			}
-
-			if (dwLastError == ERROR_PATH_NOT_FOUND || dwLastError == ERROR_FILE_NOT_FOUND)
-				return TSubTaskBase::eSubResult_Continue;
-
-			// log
-			TString 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.c_str());
-
-			EFeedbackResult frResult = spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError);
-			switch (frResult)
-			{
-			case EFeedbackResult::eResult_Cancel:
-				rLog.logi(_T("Cancel request while deleting file."));
-				return TSubTaskBase::eSubResult_CancelRequest;
-
-			case EFeedbackResult::eResult_Retry:
-				bRetry = true;
-				continue;	// no fcIndex bump, since we are trying again
-
-			case EFeedbackResult::eResult_Pause:
-				return TSubTaskBase::eSubResult_PauseRequest;
-
-			case EFeedbackResult::eResult_Skip:
-				break;		// just do nothing
-
-			default:
-				BOOST_ASSERT(FALSE);		// unknown result
-				THROW_CORE_EXCEPTION(eErr_UnhandledCase);
-			}
-		}
-		while (bRetry);
-
-		return TSubTaskBase::eSubResult_Continue;
-	}
-
-	TSubTaskBase::ESubOperationResult TSubTaskDelete::DeleteFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TFileInfoPtr& spFileInfo)
-	{
-		const TConfig& rConfig = GetContext().GetConfig();
-		IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem();
-		icpf::log_file& rLog = GetContext().GetLog();
-
-		bool bRetry = false;
-		do
-		{
-			bRetry = false;
-
-			// #bug - changing read-only attribute should only be done when user explicitly requests it (via feedback response)
-			// for now it is ignored
-			try
-			{
-				if (!GetTaskPropValue<eTO_ProtectReadOnlyFiles>(rConfig))
-					spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY);
-			}
-			catch (const TFileException&)
-			{
-			}
-
-			DWORD dwLastError = ERROR_SUCCESS;
-			try
-			{
-				spFilesystem->DeleteFile(spFileInfo->GetFullFilePath());
-				return TSubTaskBase::eSubResult_Continue;
-			}
-			catch (const TFileException& e)
-			{
-				dwLastError = e.GetNativeError();
-			}
-
-			if (dwLastError == ERROR_PATH_NOT_FOUND || dwLastError == ERROR_FILE_NOT_FOUND)
-				return TSubTaskBase::eSubResult_Continue;
-
-			// log
-			TString 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.c_str());
-
-			EFeedbackResult frResult = spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError);
-			switch (frResult)
-			{
-			case EFeedbackResult::eResult_Cancel:
-				rLog.logi(_T("Cancel request while deleting file."));
-				return TSubTaskBase::eSubResult_CancelRequest;
-
-			case EFeedbackResult::eResult_Retry:
-				bRetry = true;
-				continue;	// no fcIndex bump, since we are trying again
-
-			case EFeedbackResult::eResult_Pause:
-				return TSubTaskBase::eSubResult_PauseRequest;
-
-			case EFeedbackResult::eResult_Skip:
-				break;		// just do nothing
-
-			default:
-				BOOST_ASSERT(FALSE);		// unknown result
-				THROW_CORE_EXCEPTION(eErr_UnhandledCase);
-			}
-		}
-		while (bRetry);
-
-		return TSubTaskBase::eSubResult_Continue;
-	}
-
 	void TSubTaskDelete::GetStatsSnapshot(TSubTaskStatsSnapshotPtr& spStats) const
 	{
 		m_tSubTaskStats.GetSnapshot(spStats);