Index: src/libchcore/TFilesystemFeedbackWrapper.cpp
===================================================================
diff -u -r89f857792bba8752de98ddd477949e45cef5ba5a -rd3b1a109f2ace158e828715205592615d6e33fd0
--- src/libchcore/TFilesystemFeedbackWrapper.cpp	(.../TFilesystemFeedbackWrapper.cpp)	(revision 89f857792bba8752de98ddd477949e45cef5ba5a)
+++ src/libchcore/TFilesystemFeedbackWrapper.cpp	(.../TFilesystemFeedbackWrapper.cpp)	(revision d3b1a109f2ace158e828715205592615d6e33fd0)
@@ -197,21 +197,14 @@
 		do
 		{
 			bRetry = false;
+			DWORD dwLastError = ERROR_SUCCESS;
 
-			// #bug - changing read-only attribute should only be done when user explicitly requests it (via feedback response)
-			// for now it is ignored
 			try
 			{
-				if (!bProtectReadOnlyFiles)
-					m_spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY);
-			}
-			catch (const TFileException&)
-			{
-			}
+				DWORD dwAttributes = spFileInfo->GetAttributes();
+				if((dwAttributes & FILE_ATTRIBUTE_READONLY) && !bProtectReadOnlyFiles)
+					m_spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), dwAttributes & ~FILE_ATTRIBUTE_READONLY);
 
-			DWORD dwLastError = ERROR_SUCCESS;
-			try
-			{
 				m_spFilesystem->RemoveDirectory(spFileInfo->GetFullFilePath());
 				return TSubTaskBase::eSubResult_Continue;
 			}
@@ -220,11 +213,11 @@
 				dwLastError = e.GetNativeError();
 			}
 
-			if (dwLastError == ERROR_PATH_NOT_FOUND || dwLastError == ERROR_FILE_NOT_FOUND)
+			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");
+			TString strFormat = _T("Error #%errno while deleting folder %path");
 			strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 			strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString());
 			m_rLog.loge(strFormat.c_str());
@@ -266,20 +259,13 @@
 		{
 			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 (!bProtectReadOnlyFiles)
-					m_spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY);
-			}
-			catch (const TFileException&)
-			{
-			}
-
 			DWORD dwLastError = ERROR_SUCCESS;
 			try
 			{
+				DWORD dwAttributes = spFileInfo->GetAttributes();
+				if((dwAttributes & FILE_ATTRIBUTE_READONLY) && !bProtectReadOnlyFiles)
+					m_spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), dwAttributes & ~FILE_ATTRIBUTE_READONLY);
+
 				m_spFilesystem->DeleteFile(spFileInfo->GetFullFilePath());
 				return TSubTaskBase::eSubResult_Continue;
 			}
@@ -292,7 +278,7 @@
 				return TSubTaskBase::eSubResult_Continue;
 
 			// log
-			TString strFormat = _T("Error #%errno while deleting file/folder %path");
+			TString strFormat = _T("Error #%errno while deleting file %path");
 			strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 			strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString());
 			m_rLog.loge(strFormat.c_str());
Index: src/libchcore/TFilesystemFileFeedbackWrapper.cpp
===================================================================
diff -u -r89f857792bba8752de98ddd477949e45cef5ba5a -rd3b1a109f2ace158e828715205592615d6e33fd0
--- src/libchcore/TFilesystemFileFeedbackWrapper.cpp	(.../TFilesystemFileFeedbackWrapper.cpp)	(revision 89f857792bba8752de98ddd477949e45cef5ba5a)
+++ src/libchcore/TFilesystemFileFeedbackWrapper.cpp	(.../TFilesystemFileFeedbackWrapper.cpp)	(revision d3b1a109f2ace158e828715205592615d6e33fd0)
@@ -26,11 +26,14 @@
 
 namespace chcore
 {
-	TFilesystemFileFeedbackWrapper::TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, icpf::log_file& rLog, TWorkerThreadController& rThreadController) :
+	TFilesystemFileFeedbackWrapper::TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, icpf::log_file& rLog, TWorkerThreadController& rThreadController, const IFilesystemPtr& spFilesystem) :
 		m_spFeedbackHandler(spFeedbackHandler),
 		m_rLog(rLog),
-		m_rThreadController(rThreadController)
+		m_rThreadController(rThreadController),
+		m_spFilesystem(spFilesystem)
 	{
+		if(!spFeedbackHandler || !spFilesystem)
+			THROW_CORE_EXCEPTION_MSG(eErr_InvalidArgument, L"Missing filesystem or feedback handler");
 	}
 
 	TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::OpenSourceFileFB(const IFilesystemFilePtr& fileSrc)
@@ -100,9 +103,10 @@
 		return TSubTaskBase::eSubResult_Continue;
 	}
 
-	TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::OpenExistingDestinationFileFB(const IFilesystemFilePtr& fileDst)
+	TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::OpenExistingDestinationFileFB(const IFilesystemFilePtr& fileDst, bool bProtectReadOnlyFiles)
 	{
 		bool bRetry = false;
+		bool bAttributesChanged = false;
 
 		fileDst->Close();
 
@@ -121,6 +125,29 @@
 				dwLastError = e.GetNativeError();
 			}
 
+			// when access is denied it might mean the read-only attribute prevents from opening file for writing;
+			// try to remove the attribute and retry (attributes are changed only once)
+			if(dwLastError == ERROR_ACCESS_DENIED && !bProtectReadOnlyFiles && !bAttributesChanged)
+			{
+				try
+				{
+					TFileInfoPtr spDstFileInfo(boost::make_shared<TFileInfo>());
+					m_spFilesystem->GetFileInfo(fileDst->GetFilePath(), spDstFileInfo);
+
+					if(spDstFileInfo->IsReadOnly())
+					{
+						m_spFilesystem->SetAttributes(fileDst->GetFilePath(), spDstFileInfo->GetAttributes() & ~FILE_ATTRIBUTE_READONLY);
+						bRetry = true;
+						bAttributesChanged = true;
+						continue;
+					}
+				}
+				catch(const TFileException& e)
+				{
+					dwLastError = e.GetErrorCode();
+				}
+			}
+
 			TFeedbackResult frResult = m_spFeedbackHandler->FileError(fileDst->GetFilePath().ToWString(), TString(), EFileError::eCreateError, dwLastError);
 			switch (frResult.GetResult())
 			{
@@ -169,7 +196,8 @@
 		const TFileInfoPtr& spSrcFileInfo,
 		unsigned long long& ullSeekTo,
 		bool& bFreshlyCreated,
-		bool& bSkip)
+		bool& bSkip,
+		bool bProtectReadOnlyFiles)
 	{
 		bool bRetry = false;
 		bSkip = false;
@@ -198,7 +226,7 @@
 				bFreshlyCreated = false;
 
 				// pass it to the specialized method
-				TSubTaskBase::ESubOperationResult eResult = OpenExistingDestinationFileFB(fileDst);
+				TSubTaskBase::ESubOperationResult eResult = OpenExistingDestinationFileFB(fileDst, bProtectReadOnlyFiles);
 				if (eResult != TSubTaskBase::eSubResult_Continue)
 					return eResult;
 				else if (!fileDst->IsOpen())
Index: src/libchcore/TFilesystemFileFeedbackWrapper.h
===================================================================
diff -u -rbfc7a8378a96c5b58def559b343918fca32f05a6 -rd3b1a109f2ace158e828715205592615d6e33fd0
--- src/libchcore/TFilesystemFileFeedbackWrapper.h	(.../TFilesystemFileFeedbackWrapper.h)	(revision bfc7a8378a96c5b58def559b343918fca32f05a6)
+++ src/libchcore/TFilesystemFileFeedbackWrapper.h	(.../TFilesystemFileFeedbackWrapper.h)	(revision d3b1a109f2ace158e828715205592615d6e33fd0)
@@ -33,13 +33,13 @@
 	class TFilesystemFileFeedbackWrapper
 	{
 	public:
-		TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, icpf::log_file& rLog, TWorkerThreadController& rThreadController);
+		TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, icpf::log_file& rLog, TWorkerThreadController& rThreadController, const IFilesystemPtr& spFilesystem);
 		TFilesystemFileFeedbackWrapper& operator=(const TFilesystemFileFeedbackWrapper&) = delete;
 
 		TSubTaskBase::ESubOperationResult OpenSourceFileFB(const IFilesystemFilePtr& fileSrc);
-		TSubTaskBase::ESubOperationResult OpenExistingDestinationFileFB(const IFilesystemFilePtr& fileDst);
+		TSubTaskBase::ESubOperationResult OpenExistingDestinationFileFB(const IFilesystemFilePtr& fileDst, bool bProtectReadOnlyFiles);
 		TSubTaskBase::ESubOperationResult OpenDestinationFileFB(const IFilesystemFilePtr& fileDst, const TFileInfoPtr& spSrcFileInfo,
-			unsigned long long& ullSeekTo, bool& bFreshlyCreated, bool& bSkip);
+			unsigned long long& ullSeekTo, bool& bFreshlyCreated, bool& bSkip, bool bProtectReadOnlyFiles);
 
 		TSubTaskBase::ESubOperationResult TruncateFileFB(const IFilesystemFilePtr& spFile, file_size_t fsNewSize,
 			const TSmartPath& pathFile, bool& bSkip);
Index: src/libchcore/TSubTaskCopyMove.cpp
===================================================================
diff -u -r89f857792bba8752de98ddd477949e45cef5ba5a -rd3b1a109f2ace158e828715205592615d6e33fd0
--- src/libchcore/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision 89f857792bba8752de98ddd477949e45cef5ba5a)
+++ src/libchcore/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision d3b1a109f2ace158e828715205592615d6e33fd0)
@@ -280,7 +280,7 @@
 		const TConfig& rConfig = GetContext().GetConfig();
 		IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem();
 
-		TFilesystemFileFeedbackWrapper tFileFBWrapper(spFeedbackHandler, rLog, rThreadController);
+		TFilesystemFileFeedbackWrapper tFileFBWrapper(spFeedbackHandler, rLog, rThreadController, spFilesystem);
 
 		TString strFormat;
 		TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue;
@@ -580,21 +580,6 @@
 			pData->spSrcFile->SetLength64(fsNewSize);
 		}
 
-		// 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>(rConfig))
-		{
-			try
-			{
-				spFilesystem->SetAttributes(pData->pathDstFile, FILE_ATTRIBUTE_NORMAL);
-			}
-			catch (const TFileException&)
-			{
-				// currently ignore that problem; this should be handled with user feedback
-			}
-		}
-
 		// open destination file, handle the failures and possibly existence of the destination file
 		unsigned long long ullSeekTo = ullProcessedSize;
 		bool bDstFileFreshlyCreated = false;
@@ -604,13 +589,13 @@
 		if (m_tSubTaskStats.CanCurrentItemSilentResume())
 		{
 			bool bContinue = true;
-			// verify that the file qualifies for silent resume
 			TFileInfoPtr spDstFileInfo(boost::make_shared<TFileInfo>());
+			// verify that the file qualifies for silent resume
 			try
 			{
 				spFilesystem->GetFileInfo(spFileDst->GetFilePath(), spDstFileInfo);
 			}
-			catch (const TFileException&)
+			catch(const TFileException&)
 			{
 				bContinue = false;
 			}
@@ -621,7 +606,7 @@
 			// we are resuming previous operation
 			if(bContinue)
 			{
-				eResult = rFileFBWrapper.OpenExistingDestinationFileFB(spFileDst);
+				eResult = rFileFBWrapper.OpenExistingDestinationFileFB(spFileDst, GetTaskPropValue<eTO_ProtectReadOnlyFiles>(rConfig));
 				if (eResult != TSubTaskBase::eSubResult_Continue)
 					return eResult;
 				else if (!spFileDst->IsOpen())
@@ -641,7 +626,7 @@
 		{
 			// open destination file for case, when we start operation on this file (i.e. it is not resume of the
 			// old operation)
-			eResult = rFileFBWrapper.OpenDestinationFileFB(spFileDst, pData->spSrcFile, ullSeekTo, bDstFileFreshlyCreated, bSkip);
+			eResult = rFileFBWrapper.OpenDestinationFileFB(spFileDst, pData->spSrcFile, ullSeekTo, bDstFileFreshlyCreated, bSkip, GetTaskPropValue<eTO_ProtectReadOnlyFiles>(rConfig));
 			if(eResult != TSubTaskBase::eSubResult_Continue)
 				return eResult;
 			else if(bSkip)