Index: src/ch/FeedbackHandler.cpp
===================================================================
diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/FeedbackHandler.cpp	(.../FeedbackHandler.cpp)	(revision d5c3edd0d167db9b5d47d04248820fda49499a5e)
+++ src/ch/FeedbackHandler.cpp	(.../FeedbackHandler.cpp)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -21,6 +21,8 @@
 #include "FeedbackReplaceDlg.h"
 #include "FeedbackFileErrorDlg.h"
 #include "FeedbackNotEnoughSpaceDlg.h"
+#include "ch.h"
+#include "mmsystem.h"
 
 CFeedbackHandler::CFeedbackHandler() :
 	chcore::IFeedbackHandler()
@@ -35,8 +37,8 @@
 
 ull_t CFeedbackHandler::RequestFeedback(ull_t ullFeedbackID, ptr_t pFeedbackParam)
 {
-	BOOST_ASSERT(pFeedbackParam && ullFeedbackID < eFT_LastType);
-	if(!pFeedbackParam || ullFeedbackID >= eFT_LastType)
+	BOOST_ASSERT(ullFeedbackID < eFT_LastType);
+	if(ullFeedbackID >= eFT_LastType)
 		return eResult_Unknown;
 
 	// if we have an action selected for this type (e.g. by selecting 'use for all items')
@@ -50,6 +52,10 @@
 	{
 	case eFT_FileAlreadyExists:
 		{
+			BOOST_ASSERT(pFeedbackParam);
+			if(!pFeedbackParam)
+				return eResult_Unknown;
+
 			FEEDBACK_ALREADYEXISTS* pData = (FEEDBACK_ALREADYEXISTS*)pFeedbackParam;
 			CFeedbackReplaceDlg dlg(pData->pfiSrc, pData->pfiDst);
 			eFeedbackResult = (EFeedbackResult)dlg.DoModal();
@@ -59,6 +65,10 @@
 		}
 	case eFT_FileError:
 		{
+			BOOST_ASSERT(pFeedbackParam);
+			if(!pFeedbackParam)
+				return eResult_Unknown;
+
 			FEEDBACK_FILEERROR* pData = (FEEDBACK_FILEERROR*)pFeedbackParam;
 			CFeedbackFileErrorDlg dlg(pData->pszPath, pData->ulError);
 			eFeedbackResult = (EFeedbackResult)dlg.DoModal();
@@ -68,13 +78,43 @@
 		}
 	case eFT_NotEnoughSpace:
 		{
+			BOOST_ASSERT(pFeedbackParam);
+			if(!pFeedbackParam)
+				return eResult_Unknown;
+
 			FEEDBACK_NOTENOUGHSPACE* pData = (FEEDBACK_NOTENOUGHSPACE*)pFeedbackParam;
 			CFeedbackNotEnoughSpaceDlg dlg(pData->ullRequiredSize, pData->pszSrcPath, pData->pszDstPath);
 			eFeedbackResult = (EFeedbackResult)dlg.DoModal();
 			bUseForAllItems = dlg.m_bAllItems;
 
 			break;
 		}
+	case eFT_OperationFinished:
+		{
+			if(GetConfig().get_bool(PP_SNDPLAYSOUNDS))
+			{
+				TCHAR* pszPath = new TCHAR[_MAX_PATH];
+				GetConfig().get_string(PP_SNDFINISHEDSOUNDPATH, pszPath, _MAX_PATH);
+				GetApp().ExpandPath(pszPath);
+				PlaySound(pszPath, NULL, SND_FILENAME | SND_ASYNC);
+				delete [] pszPath;
+			}
+
+			break;
+		}
+	case eFT_OperationError:
+		{
+			if(GetConfig().get_bool(PP_SNDPLAYSOUNDS))
+			{
+				TCHAR* pszPath = new TCHAR[_MAX_PATH];
+				GetConfig().get_string(PP_SNDERRORSOUNDPATH, pszPath, _MAX_PATH);
+				GetApp().ExpandPath(pszPath);
+				PlaySound(pszPath, NULL, SND_FILENAME | SND_ASYNC);
+				delete [] pszPath;
+			}
+
+			break;
+		}
 	default:
 		BOOST_ASSERT(false);
 		return eResult_Unknown;
Index: src/ch/FeedbackHandler.h
===================================================================
diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/FeedbackHandler.h	(.../FeedbackHandler.h)	(revision d5c3edd0d167db9b5d47d04248820fda49499a5e)
+++ src/ch/FeedbackHandler.h	(.../FeedbackHandler.h)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -47,9 +47,13 @@
 	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
 	};
 
Index: src/ch/MainWnd.cpp
===================================================================
diff -u -raa6bff57279b9f9cfc276e9adab2763e2900878d -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision aa6bff57279b9f9cfc276e9adab2763e2900878d)
+++ src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -27,10 +27,6 @@
 #include "structs.h"
 #include "dialogs.h"
 
-#pragma warning (disable : 4201)
-#include "mmsystem.h"
-#pragma warning (default : 4201)
-
 #include "FolderDialog.h"
 
 #include "CustomCopyDlg.h"
@@ -61,9 +57,6 @@
 #define TM_AUTORESUME			1000
 #define TM_ACCEPTING			100
 
-// assume max sectors of 4kB (for rounding)
-#define MAXSECTORSIZE			4096
-
 extern CSharedConfigStruct* g_pscsShared;
 
 extern int iCount;
@@ -164,1017 +157,6 @@
 		m_pFeedbackFactory->Delete();
 }
 
-// case insensitive replacement
-inline void ReplaceNoCase(CString& rString, CString strOld, CString strNew)
-{
-	if (rString.Left(strOld.GetLength()).CompareNoCase(strOld) == 0)
-		rString=strNew+rString.Right(rString.GetLength()-strOld.GetLength());
-}
-
-bool TimeToFileTime(const COleDateTime& time, LPFILETIME pFileTime)
-{
-	SYSTEMTIME sysTime;
-	sysTime.wYear = (WORD)time.GetYear();
-	sysTime.wMonth = (WORD)time.GetMonth();
-	sysTime.wDay = (WORD)time.GetDay();
-	sysTime.wHour = (WORD)time.GetHour();
-	sysTime.wMinute = (WORD)time.GetMinute();
-	sysTime.wSecond = (WORD)time.GetSecond();
-	sysTime.wMilliseconds = 0;
-
-	// convert system time to local file time
-	FILETIME localTime;
-	if (!SystemTimeToFileTime((LPSYSTEMTIME)&sysTime, &localTime))
-		return false;
-
-	// convert local file time to UTC file time
-	if (!LocalFileTimeToFileTime(&localTime, pFileTime))
-		return false;
-
-	return true;
-}
-
-bool SetFileDirectoryTime(LPCTSTR lpszName, CFileInfo* pSrcInfo)
-{
-	FILETIME creation, lastAccess, lastWrite;
-
-	if (!TimeToFileTime(pSrcInfo->GetCreationTime(), &creation)
-		|| !TimeToFileTime(pSrcInfo->GetLastAccessTime(), &lastAccess)
-		|| !TimeToFileTime(pSrcInfo->GetLastWriteTime(), &lastWrite) )
-		return false;
-
-	HANDLE handle=CreateFile(lpszName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-	if (handle == INVALID_HANDLE_VALUE)
-		return false;
-
-	if (!SetFileTime(handle, &creation, &lastAccess, &lastWrite))
-	{
-		CloseHandle(handle);
-		return false;
-	}
-
-	if (!CloseHandle(handle))
-		return false;
-
-	return true;
-}
-
-// searching for files
-inline void RecurseDirectories(CTask* pTask)
-{
-	TRACE("Searching for files...\n");
-
-	// log
-	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFSEARCHINGFORFILES_STRING));
-	
-	// update status
-	pTask->SetStatus(ST_SEARCHING, ST_STEP_MASK);
-
-	// delete the content of m_files
-	pTask->FilesRemoveAll();
-
-	// enter some data to m_files
-	int nSize=pTask->GetClipboardDataSize();	// size of m_clipboard
-	const CFiltersArray* pFilters=pTask->GetFilters();
-	int iDestDrvNumber=pTask->GetDestDriveNumber();
-	bool bIgnoreDirs=(pTask->GetStatus(ST_SPECIAL_MASK) & ST_IGNORE_DIRS) != 0;
-	bool bForceDirectories=(pTask->GetStatus(ST_SPECIAL_MASK) & ST_FORCE_DIRS) != 0;
-	bool bMove=pTask->GetStatus(ST_OPERATION_MASK) == ST_MOVE;
-	CFileInfo fi;
-	fi.SetClipboard(pTask->GetClipboard());
-
-	// add everything
-	ictranslate::CFormat fmt;
-	for (int i=0;i<nSize;i++)
-	{
-		// read attributes of src file/folder
-		if (!fi.Create(pTask->GetClipboardData(i)->GetPath(), i))
-		{
-			// log
-			fmt.SetFormat(GetResManager().LoadString(IDS_OTFMISSINGCLIPBOARDINPUT_STRING));
-			fmt.SetParam(_t("%path"), pTask->GetClipboardData(i)->GetPath());
-			pTask->m_log.logw(fmt);
-			continue;
-		}
-		else
-		{
-			// log
-			fmt.SetFormat(GetResManager().LoadString(IDS_OTFADDINGCLIPBOARDFILE_STRING));
-			fmt.SetParam(_t("%path"), pTask->GetClipboardData(i)->GetPath());
-			pTask->m_log.logi(fmt);
-		}
-
-		// found file/folder - check if the dest name has been generated
-		if (pTask->GetClipboardData(i)->m_astrDstPaths.GetSize() == 0)
-		{
-			// generate something - if dest folder == src folder - search for copy
-			if (pTask->GetDestPath().GetPath() == fi.GetFileRoot())
-			{
-				CString strSubst;
-				FindFreeSubstituteName(fi.GetFullFilePath(), pTask->GetDestPath().GetPath(), &strSubst);
-				pTask->GetClipboardData(i)->m_astrDstPaths.Add(strSubst);
-			}
-			else
-				pTask->GetClipboardData(i)->m_astrDstPaths.Add(fi.GetFileName());
-		}
-		
-		// add if needed
-		if (fi.IsDirectory())
-		{
-			// add if folder's aren't ignored
-			if (!bIgnoreDirs && !bForceDirectories)
-			{
-				pTask->FilesAdd(fi);
-
-				// log
-				fmt.SetFormat(GetResManager().LoadString(IDS_OTFADDEDFOLDER_STRING));
-				fmt.SetParam(_t("%path"), fi.GetFullFilePath());
-				pTask->m_log.logi(fmt);
-			}
-
-			// don't add folder contents when moving inside one disk boundary
-			if (bIgnoreDirs || !bMove || pTask->GetCopies() > 1 || iDestDrvNumber == -1
-				|| iDestDrvNumber != fi.GetDriveNumber() || CFileInfo::Exist(fi.GetDestinationPath(pTask->GetDestPath().GetPath(), 0, ((int)bForceDirectories) << 1)) )
-			{
-				// log
-				fmt.SetFormat(GetResManager().LoadString(IDS_OTFRECURSINGFOLDER_STRING));
-				fmt.SetParam(_t("%path"), fi.GetFullFilePath());
-				pTask->m_log.logi(fmt);
-				
-				// no movefile possibility - use CustomCopyFile
-				pTask->GetClipboardData(i)->SetMove(false);
-
-				pTask->FilesAddDir(fi.GetFullFilePath(), pFilters, i, true, !bIgnoreDirs || bForceDirectories);
-			}
-
-			// check for kill need
-			if (pTask->GetKillFlag())
-			{
-				// log
-				pTask->m_log.logi(GetResManager().LoadString(IDS_OTFADDINGKILLREQEST_STRING));
-				throw new CProcessingException(E_KILL_REQUEST, pTask);
-			}
-		}
-		else
-		{
-			if (bMove && pTask->GetCopies() == 1 && iDestDrvNumber != -1 && iDestDrvNumber == fi.GetDriveNumber() &&
-				!CFileInfo::Exist(fi.GetDestinationPath(pTask->GetDestPath().GetPath(), 0, ((int)bForceDirectories) << 1)) )
-			{
-				// if moving within one partition boundary set the file size to 0 so the overall size will
-				// be ok
-				fi.SetLength64(0);
-			}
-			else
-				pTask->GetClipboardData(i)->SetMove(false);	// no MoveFile
-			
-			pTask->FilesAdd(fi);		// file - add
-
-			// log
-			fmt.SetFormat(GetResManager().LoadString(IDS_OTFADDEDFILE_STRING));
-			fmt.SetParam(_t("%path"), fi.GetFullFilePath());
-			pTask->m_log.logi(fmt);
-		}
-	}
-	
-	// calc size of all files
-	pTask->CalcAllSize();
-	
-	// update *m_pnTasksAll;
-	pTask->IncreaseAllTasksSize(pTask->GetAllSize());
-	
-	// change state to ST_COPYING - finished searching for files
-	pTask->SetStatus(ST_COPYING, ST_STEP_MASK);
-	
-	// save task status
-	pTask->Store(true);
-	pTask->Store(false);
-
-	// log
-	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFSEARCHINGFINISHED_STRING));
-}
-
-// delete files - after copying
-void DeleteFiles(CTask* pTask)
-{
-	// log
-	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFDELETINGFILES_STRING));
-
-	// current processed path
-	BOOL bSuccess;
-	CFileInfo fi;
-	ictranslate::CFormat fmt;
-
-	// index points to 0 or next item to process
-	for (int i=pTask->GetCurrentIndex();i<pTask->FilesGetSize();i++)
-	{
-		// set index in pTask to currently deleted element
-		pTask->SetCurrentIndex(i);
-		
-		// check for kill flag
-		if (pTask->GetKillFlag())
-		{
-			// log
-			pTask->m_log.logi(GetResManager().LoadString(IDS_OTFDELETINGKILLREQUEST_STRING));
-			throw new CProcessingException(E_KILL_REQUEST, pTask);
-		}
-		
-		// current processed element
-		fi=pTask->FilesGetAt(pTask->FilesGetSize()-i-1);
-		if(!(fi.GetFlags() & FIF_PROCESSED))
-			continue;
-		
-		// delete data
-		if (fi.IsDirectory())
-		{
-			if (!GetConfig().get_bool(PP_CMPROTECTROFILES))
-				SetFileAttributes(fi.GetFullFilePath(), FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY);
-			bSuccess=RemoveDirectory(fi.GetFullFilePath());
-		}
-		else
-		{
-			// set files attributes to normal - it'd slow processing a bit, but it's better.
-			if (!GetConfig().get_bool(PP_CMPROTECTROFILES))
-				SetFileAttributes(fi.GetFullFilePath(), FILE_ATTRIBUTE_NORMAL);
-			bSuccess=DeleteFile(fi.GetFullFilePath());
-		}
-		
-		// operation failed
-		DWORD dwLastError=GetLastError();
-		if (!bSuccess && dwLastError != ERROR_PATH_NOT_FOUND && dwLastError != ERROR_FILE_NOT_FOUND)
-		{
-			// log
-			fmt.SetFormat(GetResManager().LoadString(IDS_OTFDELETINGERROR_STRING));
-			fmt.SetParam(_t("%errno"), dwLastError);
-			fmt.SetParam(_t("%path"), fi.GetFullFilePath());
-			pTask->m_log.loge(fmt);
-			throw new CProcessingException(E_ERROR, pTask, dwLastError, fmt);
-		}
-	}//for
-
-	// change status to finished
-	pTask->SetStatus(ST_FINISHED, ST_STEP_MASK);
-
-	// add 1 to current index - looks better
-	pTask->IncreaseCurrentIndex();
-
-	// log
-	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFDELETINGFINISHED_STRING));
-}
-
-void CustomCopyFile(PCUSTOM_COPY_PARAMS pData)
-{
-	HANDLE hSrc=INVALID_HANDLE_VALUE, hDst=INVALID_HANDLE_VALUE;
-	ictranslate::CFormat fmt;
-	try
-	{
-		// do we copy rest or recopy ?
-		bool bCopyRest=GetConfig().get_bool(PP_CMUSEAUTOCOMPLETEFILES);
-
-		// Data regarding dest file
-		CFileInfo fiDest;
-		bool bExist=fiDest.Create(pData->strDstFile, -1);
-
-		chcore::IFeedbackHandler* piFeedbackHandler = pData->pTask->GetFeedbackHandler();
-		BOOST_ASSERT(piFeedbackHandler);
-
-		pData->pTask->SetLastProcessedIndex(-1);
-
-		// if dest file size >0 - we can do somethng more than usual
-		if(bExist)
-		{
-			// src and dst files are the same
-			FEEDBACK_ALREADYEXISTS feedStruct = { pData->pfiSrcFile, &fiDest };
-			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileAlreadyExists, &feedStruct);
-			// check for dialog result
-			switch(frResult)
-			{
-			case CFeedbackHandler::eResult_Overwrite:
-				{
-					bCopyRest=false;
-					break;
-				}
-			case CFeedbackHandler::eResult_CopyRest:
-				{
-					bCopyRest=true;
-					break;
-				}
-			case CFeedbackHandler::eResult_Skip:
-				{
-					pData->pTask->IncreaseProcessedSize(pData->pfiSrcFile->GetLength64());
-					pData->pTask->IncreaseProcessedTasksSize(pData->pfiSrcFile->GetLength64());
-					pData->bProcessed = false;
-					return;
-				}
-			case CFeedbackHandler::eResult_Cancel:
-				{
-					// log
-					if (GetConfig().get_bool(PP_CMCREATELOG))
-					{
-						fmt.SetFormat(GetResManager().LoadString(IDS_OTFPRECHECKCANCELREQUEST_STRING));
-						fmt.SetParam(_t("%path"), pData->pfiSrcFile->GetFullFilePath());
-						pData->pTask->m_log.logi(fmt);
-					}
-					throw new CProcessingException(E_CANCEL, pData->pTask);
-					break;
-				}
-			case CFeedbackHandler::eResult_Pause:
-				{
-					throw new CProcessingException(E_PAUSE, pData->pTask);
-					break;
-				}
-			default:
-				{
-					BOOST_ASSERT(FALSE);		// unknown result
-					throw new CProcessingException(E_ERROR, pData->pTask, 0, _t("Unknown feedback result type"));
-					break;
-				}
-			}
-		}// bExist
-
-		// change attributes of a dest file
-		if (!GetConfig().get_bool(PP_CMPROTECTROFILES))
-			SetFileAttributes(pData->strDstFile, FILE_ATTRIBUTE_NORMAL);
-
-		// first or second pass ? only for FFNB
-		bool bFirstPass=true;
-
-		// check size of src file to know whether use flag FILE_FLAG_NOBUFFERING
-l_start:
-		bool bNoBuffer=(bFirstPass && GetConfig().get_bool(PP_BFUSENOBUFFERING) && pData->pfiSrcFile->GetLength64() >= (unsigned long long)GetConfig().get_signed_num(PP_BFBOUNDARYLIMIT));
-
-		// refresh data about file
-		if (!bFirstPass)
-			bExist=fiDest.Create(pData->strDstFile, -1);
-
-		// open src
-l_openingsrc:
-		hSrc=CreateFile(pData->pfiSrcFile->GetFullFilePath(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffer ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
-		if (hSrc == INVALID_HANDLE_VALUE)
-		{
-			DWORD dwLastError=GetLastError();
-			CString strFile = pData->pfiSrcFile->GetFullFilePath();
-			FEEDBACK_FILEERROR feedStruct = { (PCTSTR)strFile, dwLastError };
-			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
-
-			switch (frResult)
-			{
-			case CFeedbackHandler::eResult_Skip:
-				pData->pTask->IncreaseProcessedSize(pData->pfiSrcFile->GetLength64());
-				pData->pTask->IncreaseProcessedTasksSize(pData->pfiSrcFile->GetLength64());
-				pData->bProcessed = false;
-				return;
-				break;
-			case CFeedbackHandler::eResult_Cancel:
-				// log
-				fmt.SetFormat(GetResManager().LoadString(IDS_OTFOPENINGCANCELREQUEST_STRING));
-				fmt.SetParam(_t("%errno"), dwLastError);
-				fmt.SetParam(_t("%path"), pData->pfiSrcFile->GetFullFilePath());
-				pData->pTask->m_log.loge(fmt);
-				throw new CProcessingException(E_CANCEL, pData->pTask);
-				break;
-			case CFeedbackHandler::eResult_Pause:
-				throw new CProcessingException(E_PAUSE, pData->pTask);
-				break;
-			case CFeedbackHandler::eResult_Retry:
-				// log
-				fmt.SetFormat(GetResManager().LoadString(IDS_OTFOPENINGRETRY_STRING));
-				fmt.SetParam(_t("%errno"), dwLastError);
-				fmt.SetParam(_t("%path"), pData->pfiSrcFile->GetFullFilePath());
-				pData->pTask->m_log.loge(fmt);
-				goto l_openingsrc;
-				break;
-			default:
-				{
-					BOOST_ASSERT(FALSE);		// unknown result
-					throw new CProcessingException(E_ERROR, pData->pTask, 0, _t("Unknown feedback result type"));
-					break;
-				}
-			}
-		}
-
-		// open dest
-l_openingdst:
-		hDst=CreateFile(pData->strDstFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffer ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
-		if (hDst == INVALID_HANDLE_VALUE)
-		{
-			DWORD dwLastError=GetLastError();
-			CString strFile = pData->strDstFile;
- 
-			FEEDBACK_FILEERROR feedStruct = { (PCTSTR)strFile, dwLastError };
-			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
-			switch (frResult)
-			{
-			case CFeedbackHandler::eResult_Retry:
-				// change attributes
-				if (!GetConfig().get_bool(PP_CMPROTECTROFILES))
-					SetFileAttributes(pData->strDstFile, FILE_ATTRIBUTE_NORMAL);
-
-				// log
-				fmt.SetFormat(GetResManager().LoadString(IDS_OTFDESTOPENINGRETRY_STRING));
-				fmt.SetParam(_t("%errno"), dwLastError);
-				fmt.SetParam(_t("%path"), pData->strDstFile);
-				pData->pTask->m_log.loge(fmt);
-				goto l_openingdst;
-				break;
-			case CFeedbackHandler::eResult_Cancel:
-				// log
-				fmt.SetFormat(GetResManager().LoadString(IDS_OTFDESTOPENINGCANCELREQUEST_STRING));
-				fmt.SetParam(_t("%errno"), dwLastError);
-				fmt.SetParam(_t("%path"), pData->strDstFile);
-				pData->pTask->m_log.loge(fmt);
-				throw new CProcessingException(E_CANCEL, pData->pTask);
-				break;
-			case CFeedbackHandler::eResult_Skip:
-				pData->pTask->IncreaseProcessedSize(pData->pfiSrcFile->GetLength64());
-				pData->pTask->IncreaseProcessedTasksSize(pData->pfiSrcFile->GetLength64());
-				pData->bProcessed = false;
-				return;
-				break;
-			case CFeedbackHandler::eResult_Pause:
-				throw new CProcessingException(E_PAUSE, pData->pTask);
-				break;
-			default:
-				{
-					BOOST_ASSERT(FALSE);		// unknown result
-					throw new CProcessingException(E_ERROR, pData->pTask, 0, _t("Unknown feedback result type"));
-					break;
-				}
-			}
-		}
-
-		// seeking
-		DWORD dwLastError=0;
-		if (!pData->bOnlyCreate)
-		{
-			if ( bCopyRest )	// if copy rest
-			{
-				if (!bFirstPass || (bExist && fiDest.GetLength64() > 0))
-				{
-					// try to move file pointers to the end
-					ULONGLONG ullMove=(bNoBuffer ? ROUNDDOWN(fiDest.GetLength64(), MAXSECTORSIZE) : fiDest.GetLength64());
-					if (SetFilePointer64(hSrc, ullMove, FILE_BEGIN) == -1 || SetFilePointer64(hDst, ullMove, FILE_BEGIN) == -1)
-					{
-						// log
-						fmt.SetFormat(GetResManager().LoadString(IDS_OTFMOVINGPOINTERSERROR_STRING));
-						fmt.SetParam(_t("%errno"), GetLastError());
-						fmt.SetParam(_t("%srcpath"), pData->pfiSrcFile->GetFullFilePath());
-						fmt.SetParam(_t("%dstpath"), pData->strDstFile);
-						fmt.SetParam(_t("%pos"), ullMove);
-						pData->pTask->m_log.loge(fmt);
-
-						// seek failed - seek to begin
-						if (SetFilePointer64(hSrc, 0, FILE_BEGIN) == -1 || SetFilePointer64(hDst, 0, FILE_BEGIN) == -1)
-						{
-							// log
-							dwLastError=GetLastError();
-							fmt.SetFormat(GetResManager().LoadString(IDS_OTFRESTORINGPOINTERSERROR_STRING));
-							fmt.SetParam(_t("%errno"), dwLastError);
-							fmt.SetParam(_t("%srcpath"), pData->pfiSrcFile->GetFullFilePath());
-							fmt.SetParam(_t("%dstpath"), pData->strDstFile);
-							pData->pTask->m_log.loge(fmt);
-							throw new CProcessingException(E_ERROR, pData->pTask, dwLastError, fmt);
-						}
-						else
-						{
-							// file pointers restored - if second pass subtract what's needed
-							if (!bFirstPass)
-							{
-								pData->pTask->IncreaseProcessedSize(-static_cast<__int64>(ullMove));
-								pData->pTask->IncreaseProcessedTasksSize(-static_cast<__int64>(ullMove));
-							}
-						}
-					}
-					else
-					{
-						// file pointers moved - so we have skipped some work - update positions
-						if (bFirstPass)	// przy drugim obiegu jest ju� uwzgl�dnione
-						{
-							pData->pTask->IncreaseProcessedSize(ullMove);
-							pData->pTask->IncreaseProcessedTasksSize(ullMove);
-						}
-					}
-				}
-			}
-			else
-				if (!SetEndOfFile(hDst))	// if recopying - reset the dest file
-				{
-					// log
-					dwLastError=GetLastError();
-					fmt.SetFormat(GetResManager().LoadString(IDS_OTFSETTINGZEROSIZEERROR_STRING));
-					fmt.SetParam(_t("%errno"), dwLastError);
-					fmt.SetParam(_t("%path"), pData->strDstFile);
-					pData->pTask->m_log.loge(fmt);
-					throw new CProcessingException(E_ERROR, pData->pTask, dwLastError, fmt);
-				}
-				
-			// copying
-			unsigned long tord, rd, wr;
-			int iBufferIndex;
-			do
-			{
-				// kill flag checks
-				if (pData->pTask->GetKillFlag())
-				{
-					// log
-					fmt.SetFormat(GetResManager().LoadString(IDS_OTFCOPYINGKILLREQUEST_STRING));
-					fmt.SetParam(_t("%srcpath"), pData->pfiSrcFile->GetFullFilePath());
-					fmt.SetParam(_t("%dstpath"), pData->strDstFile);
-					pData->pTask->m_log.logi(fmt);
-					throw new CProcessingException(E_KILL_REQUEST, pData->pTask);
-				}
-				
-				// recreate buffer if needed
-				if (!(*pData->dbBuffer.GetSizes() == *pData->pTask->GetBufferSizes()))
-				{
-					// log
-					const BUFFERSIZES *pbs1=pData->dbBuffer.GetSizes(), *pbs2=pData->pTask->GetBufferSizes();
-
-					fmt.SetFormat(GetResManager().LoadString(IDS_OTFCHANGINGBUFFERSIZE_STRING));
-					
-					fmt.SetParam(_t("%defsize"), pbs1->m_uiDefaultSize);
-					fmt.SetParam(_t("%onesize"), pbs1->m_uiOneDiskSize);
-					fmt.SetParam(_t("%twosize"), pbs1->m_uiTwoDisksSize);
-					fmt.SetParam(_t("%cdsize"), pbs1->m_uiCDSize);
-					fmt.SetParam(_t("%lansize"), pbs1->m_uiLANSize);
-					fmt.SetParam(_t("%defsize2"), pbs2->m_uiDefaultSize);
-					fmt.SetParam(_t("%onesize2"), pbs2->m_uiOneDiskSize);
-					fmt.SetParam(_t("%twosize2"), pbs2->m_uiTwoDisksSize);
-					fmt.SetParam(_t("%cdsize2"), pbs2->m_uiCDSize);
-					fmt.SetParam(_t("%lansize2"), pbs2->m_uiLANSize);
-					fmt.SetParam(_t("%srcfile"), pData->pfiSrcFile->GetFullFilePath());
-					fmt.SetParam(_t("%dstfile"), pData->strDstFile);
-
-					pData->pTask->m_log.logi(fmt);
-					pData->pTask->SetBufferSizes(pData->dbBuffer.Create(pData->pTask->GetBufferSizes()));
-				}
-				
-				// establish count of data to read
-				iBufferIndex=pData->pTask->GetBufferSizes()->m_bOnlyDefault ? 0 : pData->pfiSrcFile->GetBufferIndex();
-				tord=bNoBuffer ? ROUNDUP(pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex], MAXSECTORSIZE) : pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex];
-
-				// read
-				if (!ReadFile(hSrc, pData->dbBuffer, tord, &rd, NULL))
-				{
-					// log
-					dwLastError=GetLastError();
-					fmt.SetFormat(GetResManager().LoadString(IDS_OTFREADINGERROR_STRING));
-					fmt.SetParam(_t("%errno"), dwLastError);
-					fmt.SetParam(_t("%count"), tord);
-					fmt.SetParam(_t("%path"), pData->pfiSrcFile->GetFullFilePath());
-					pData->pTask->m_log.loge(fmt);
-					throw new CProcessingException(E_ERROR, pData->pTask, dwLastError, fmt);
-				}
-				
-				// change count of stored data
-				if (bNoBuffer && (ROUNDUP(rd, MAXSECTORSIZE)) != rd)
-				{
-					// we need to copy rest so do the second pass
-					// close files
-					CloseHandle(hSrc);
-					CloseHandle(hDst);
-
-					// second pass
-					bFirstPass=false;
-					bCopyRest=true;		// nedd to copy rest
-
-					goto l_start;
-				}
-
-				// zapisz
-				if (!WriteFile(hDst, pData->dbBuffer, rd, &wr, NULL) || wr != rd)
-				{
-					// log
-					dwLastError=GetLastError();
-					fmt.SetFormat(GetResManager().LoadString(IDS_OTFWRITINGERROR_STRING));
-					fmt.SetParam(_t("%errno"), dwLastError);
-					fmt.SetParam(_t("%count"), rd);
-					fmt.SetParam(_t("%path"), pData->strDstFile);
-					pData->pTask->m_log.loge(fmt);
-					throw new CProcessingException(E_ERROR, pData->pTask, dwLastError, fmt);
-				}
-				
-				// increase count of processed data
-				pData->pTask->IncreaseProcessedSize(rd);
-				pData->pTask->IncreaseProcessedTasksSize(rd);
-//				TRACE("Read: %d, Written: %d\n", rd, wr);
-			}
-			while ( rd != 0 );
-		}
-		else
-		{
-			// we don't copy contents, but need to increase processed size
-			pData->pTask->IncreaseProcessedSize(pData->pfiSrcFile->GetLength64());
-			pData->pTask->IncreaseProcessedTasksSize(pData->pfiSrcFile->GetLength64());
-		}
-
-		// close files
-		CloseHandle(hSrc);
-		CloseHandle(hDst);
-
-		pData->bProcessed = true;
-	}
-	catch(...)
-	{
-		// log
-		fmt.SetFormat(GetResManager().LoadString(IDS_OTFCAUGHTEXCEPTIONCCF_STRING));
-		fmt.SetParam(_t("%errno"), GetLastError());
-		fmt.SetParam(_t("%timestamp"), GetTickCount());
-		pData->pTask->m_log.loge(fmt);
-
-		// close handles
-		if (hSrc != INVALID_HANDLE_VALUE)
-			CloseHandle(hSrc);
-		if (hDst != INVALID_HANDLE_VALUE)
-			CloseHandle(hDst);
-		
-		throw;
-	}
-}
-
-// function processes files/folders
-void ProcessFiles(CTask* pTask)
-{
-	// log
-	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFPROCESSINGFILES_STRING));
-
-	// count how much has been done (updates also a member in CTaskArray)
-	pTask->CalcProcessedSize();
-	
-	// create a buffer of size pTask->m_nBufferSize
-	CUSTOM_COPY_PARAMS ccp;
-	ccp.bProcessed = false;
-	ccp.pTask=pTask;
-	ccp.bOnlyCreate=(pTask->GetStatus(ST_SPECIAL_MASK) & ST_IGNORE_CONTENT) != 0;
-	ccp.dbBuffer.Create(pTask->GetBufferSizes());
-	
-	// helpers
-	//CFileInfo fi;	// for currently processed element
-	DWORD dwLastError;
-	
-	// begin at index which wasn't processed previously
-	int nSize=pTask->FilesGetSize();	// wielko�� tablicy
-	int iCopiesCount=pTask->GetCopies();	// ilo�� kopii
-	bool bIgnoreFolders=(pTask->GetStatus(ST_SPECIAL_MASK) & ST_IGNORE_DIRS) != 0;
-	bool bForceDirectories=(pTask->GetStatus(ST_SPECIAL_MASK) & ST_FORCE_DIRS) != 0;
-	const CDestPath& dpDestPath=pTask->GetDestPath();
-
-	// log
-	const BUFFERSIZES* pbs=ccp.dbBuffer.GetSizes();
-
-	ictranslate::CFormat fmt;
-	fmt.SetFormat(GetResManager().LoadString(IDS_OTFPROCESSINGFILESDATA_STRING));
-	fmt.SetParam(_t("%create"), ccp.bOnlyCreate);
-	fmt.SetParam(_t("%defsize"), pbs->m_uiDefaultSize);
-	fmt.SetParam(_t("%onesize"), pbs->m_uiOneDiskSize);
-	fmt.SetParam(_t("%twosize"), pbs->m_uiTwoDisksSize);
-	fmt.SetParam(_t("%cdsize"), pbs->m_uiCDSize);
-	fmt.SetParam(_t("%lansize"), pbs->m_uiLANSize);
-	fmt.SetParam(_t("%filecount"), nSize);
-	fmt.SetParam(_t("%copycount"), iCopiesCount);
-	fmt.SetParam(_t("%ignorefolders"), bIgnoreFolders);
-	fmt.SetParam(_t("%dstpath"), dpDestPath.GetPath());
-	fmt.SetParam(_t("%currpass"), pTask->GetCurrentCopy());
-	fmt.SetParam(_t("%currindex"), pTask->GetCurrentIndex());
-
-	pTask->m_log.logi(fmt);
-
-	for (unsigned char j=pTask->GetCurrentCopy();j<iCopiesCount;j++)
-	{
-		pTask->SetCurrentCopy(j);
-		for (int i=pTask->GetCurrentIndex();i<nSize;i++)
-		{
-			// update m_nCurrentIndex, getting current CFileInfo
-			pTask->SetCurrentIndex(i);
-			CFileInfo& fi=pTask->FilesGetAtCurrentIndex();
-			
-			// should we kill ?
-			if (pTask->GetKillFlag())
-			{
-				// log
-				pTask->m_log.logi(GetResManager().LoadString(IDS_OTFPROCESSINGKILLREQUEST_STRING));
-				throw new CProcessingException(E_KILL_REQUEST, pTask);
-			}
-			
-			// set dest path with filename
-			ccp.strDstFile=fi.GetDestinationPath(dpDestPath.GetPath(), j, ((int)bForceDirectories) << 1 | (int)bIgnoreFolders);
-			
-			// are the files/folders lie on the same partition ?
-			bool bMove=pTask->GetStatus(ST_OPERATION_MASK) == ST_MOVE;
-			if (bMove && dpDestPath.GetDriveNumber() != -1 && dpDestPath.GetDriveNumber() == fi.GetDriveNumber() && iCopiesCount == 1 && fi.GetMove())
-			{
-				if (!MoveFile(fi.GetFullFilePath(), ccp.strDstFile))
-				{
-					dwLastError=GetLastError();
-					//log
-					fmt.SetFormat(GetResManager().LoadString(IDS_OTFMOVEFILEERROR_STRING));
-					fmt.SetParam(_t("%errno"), dwLastError);
-					fmt.SetParam(_t("%srcpath"), fi.GetFullFilePath());
-					fmt.SetParam(_t("%dstpath"), ccp.strDstFile);
-					pTask->m_log.loge(fmt);
-					throw new CProcessingException(E_ERROR, pTask, dwLastError, fmt);
-				}
-				else
-					fi.SetFlags(FIF_PROCESSED, FIF_PROCESSED);
-			}
-			else
-			{
-				// if folder - create it
-				if ( fi.IsDirectory() )
-				{
-					if (!CreateDirectory(ccp.strDstFile, NULL) && (dwLastError=GetLastError()) != ERROR_ALREADY_EXISTS )
-					{
-						// log
-						fmt.SetFormat(GetResManager().LoadString(IDS_OTFCREATEDIRECTORYERROR_STRING));
-						fmt.SetParam(_t("%errno"), dwLastError);
-						fmt.SetParam(_t("%path"), ccp.strDstFile);
-						pTask->m_log.loge(fmt);
-						throw new CProcessingException(E_ERROR, pTask, dwLastError, fmt);
-					}
-					
-					pTask->IncreaseProcessedSize(fi.GetLength64());
-					pTask->IncreaseProcessedTasksSize(fi.GetLength64());
-					fi.SetFlags(FIF_PROCESSED, FIF_PROCESSED);
-				}
-				else
-				{
-					// start copying/moving file
-					ccp.pfiSrcFile=&fi;
-					ccp.bProcessed = false;
-					
-					// kopiuj dane
-					CustomCopyFile(&ccp);
-					fi.SetFlags(ccp.bProcessed ? FIF_PROCESSED : 0, FIF_PROCESSED);
-
-					// if moving - delete file (only if config flag is set)
-					if (bMove && fi.GetFlags() & FIF_PROCESSED && !GetConfig().get_bool(PP_CMDELETEAFTERFINISHED) && j == iCopiesCount-1)
-					{
-						if (!GetConfig().get_bool(PP_CMPROTECTROFILES))
-							SetFileAttributes(fi.GetFullFilePath(), FILE_ATTRIBUTE_NORMAL);
-						DeleteFile(fi.GetFullFilePath());	// there will be another try later, so I don't check
-															// if succeeded
-					}
-				}
-				
-				// set a time
-				if (GetConfig().get_bool(PP_CMSETDESTDATE))
-					SetFileDirectoryTime(ccp.strDstFile, &fi); // no error check - ma�o istotne
-				
-				// attributes
-				if (GetConfig().get_bool(PP_CMSETDESTATTRIBUTES))
-					SetFileAttributes(ccp.strDstFile, fi.GetAttributes());	// j.w.
-			}
-		}
-
-		// current copy finished - change what's needed
-		pTask->SetCurrentIndex(0);
-	}
-
-	// delete buffer - it's not needed
-	ccp.dbBuffer.Delete();
-	
-	// change status
-	if (pTask->GetStatus(ST_OPERATION_MASK) == ST_MOVE)
-	{
-		pTask->SetStatus(ST_DELETING, ST_STEP_MASK);
-		// set the index to 0 before deleting
-		pTask->SetCurrentIndex(0);
-	}
-	else
-	{
-		pTask->SetStatus(ST_FINISHED, ST_STEP_MASK);
-
-		// to look better - increase current index by 1
-		pTask->SetCurrentIndex(nSize);
-	}
-	// log
-	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFPROCESSINGFINISHED_STRING));
-}
-
-void CheckForWaitState(CTask* pTask)
-{
-	// limiting operation count
-	pTask->SetStatus(ST_WAITING, ST_WAITING_MASK);
-	bool bContinue=false;
-	while (!bContinue)
-	{
-		if (pTask->CanBegin())
-		{
-			TRACE("CAN BEGIN ALLOWED TO CONTINUE...\n");
-			pTask->SetStatus(0, ST_WAITING);
-			bContinue=true;
-			
-			pTask->m_log.logi(GetResManager().LoadString(IDS_OTFWAITINGFINISHED_STRING));
-
-//			return; // skips sleep and kill flag checking
-		}
-		
-		Sleep(50);	// not to make it too hard for processor
-		
-		if (pTask->GetKillFlag())
-		{
-			// log
-			pTask->m_log.logi(GetResManager().LoadString(IDS_OTFWAITINGKILLREQUEST_STRING));
-			throw new CProcessingException(E_KILL_REQUEST, pTask);
-		}
-	}
-}
-
-UINT ThrdProc(LPVOID pParam)
-{
-	TRACE("\n\nENTERING ThrdProc (new task started)...\n");
-	CTask* pTask=static_cast<CTask*>(pParam);
-
-	TCHAR szPath[_MAX_PATH];
-
-	tstring_t strPath = pTask->GetTaskPath();
-	strPath += pTask->GetUniqueName()+_T(".log");
-
-	pTask->m_log.init(strPath.c_str(), 262144, icpf::log_file::level_debug, false, false);
-
-	// set thread boost
-	HANDLE hThread=GetCurrentThread();
-	::SetThreadPriorityBoost(hThread, GetConfig().get_bool(PP_CMDISABLEPRIORITYBOOST));
-
-	CTime tm=CTime::GetCurrentTime();
-
-	ictranslate::CFormat fmt;
-	fmt.SetFormat(GetResManager().LoadString(IDS_OTFTHREADSTART_STRING));
-	fmt.SetParam(_t("%year"), tm.GetYear());
-	fmt.SetParam(_t("%month"), tm.GetMonth());
-	fmt.SetParam(_t("%day"), tm.GetDay());
-	fmt.SetParam(_t("%hour"), tm.GetHour());
-	fmt.SetParam(_t("%minute"), tm.GetMinute());
-	fmt.SetParam(_t("%second"), tm.GetSecond());
-	pTask->m_log.logi(fmt);
-
-	try
-	{
-		// to make the value stable
-		bool bReadTasksSize=GetConfig().get_bool(PP_CMREADSIZEBEFOREBLOCKING);
-
-		if (!bReadTasksSize)
-			CheckForWaitState(pTask);	// operation limiting
-
-		// set what's needed
-		pTask->m_lLastTime=(long)time(NULL);	// last time (start counting)
-
-		// search for files if needed
-		if ((pTask->GetStatus(ST_STEP_MASK) == ST_NULL_STATUS
-			|| pTask->GetStatus(ST_STEP_MASK) == ST_SEARCHING))
-		{
-			// get rid of info about processed sizes
-			pTask->DecreaseProcessedTasksSize(pTask->GetProcessedSize());
-			pTask->SetProcessedSize(0);
-			pTask->DecreaseAllTasksSize(pTask->GetAllSize());
-			pTask->SetAllSize(0);
-
-			// start searching
-			RecurseDirectories(pTask);
-		}
-
-		// check for free space
-		ull_t ullNeededSize = 0, ullAvailableSize = 0;
-l_showfeedback:
-		pTask->m_log.logi(GetResManager().LoadString(IDS_OTFCHECKINGSPACE_STRING));
-
-		if (!pTask->GetRequiredFreeSpace(&ullNeededSize, &ullAvailableSize))
-		{
-			fmt.SetFormat(GetResManager().LoadString(IDS_OTFNOTENOUGHFREESPACE_STRING));
-			fmt.SetParam(_t("%needsize"), ullNeededSize);
-			fmt.SetParam(_t("%availablesize"), ullAvailableSize);
-			pTask->m_log.logw(fmt);
-			
-			chcore::IFeedbackHandler* piFeedbackHandler = pTask->GetFeedbackHandler();
-			BOOST_ASSERT(piFeedbackHandler);
-
-			if(pTask->GetClipboardDataSize() > 0)
-			{
-				CString strSrcPath = pTask->GetClipboardData(0)->GetPath();
-				CString strDstPath = pTask->GetDestPath().GetPath();
-				FEEDBACK_NOTENOUGHSPACE feedStruct = { ullNeededSize, (PCTSTR)strSrcPath, (PCTSTR)strDstPath };
-				CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_NotEnoughSpace, &feedStruct);
-
-				// default
-				switch (frResult)
-				{
-				case CFeedbackHandler::eResult_Cancel:
-					{
-						pTask->m_log.logi(GetResManager().LoadString(IDS_OTFFREESPACECANCELREQUEST_STRING));
-						throw new CProcessingException(E_CANCEL, pTask);
-						break;
-					}
-				case CFeedbackHandler::eResult_Retry:
-					pTask->m_log.logi(GetResManager().LoadString(IDS_OTFFREESPACERETRYING_STRING));
-					goto l_showfeedback;
-					break;
-				case CFeedbackHandler::eResult_Skip:
-					pTask->m_log.logi(GetResManager().LoadString(IDS_OTFFREESPACEIGNORE_STRING));
-					break;
-				default:
-					BOOST_ASSERT(FALSE);		// unknown result
-					throw new CProcessingException(E_ERROR, pTask, 0, _t("Unknown feedback result type"));
-					break;
-				}
-			}
-		}
-
-		if (bReadTasksSize)
-		{
-			pTask->UpdateTime();
-			pTask->m_lLastTime=-1;
-
-			CheckForWaitState(pTask);
-
-			pTask->m_lLastTime=(long)time(NULL);
-		}
-		
-		// Phase II - copying/moving
-		if (pTask->GetStatus(ST_STEP_MASK) == ST_COPYING)
-		{
-			// decrease processed in ctaskarray - the rest will be done in ProcessFiles
-			pTask->DecreaseProcessedTasksSize(pTask->GetProcessedSize());
-			ProcessFiles(pTask);
-		}
-		
-		// deleting data - III phase
-		if (pTask->GetStatus(ST_STEP_MASK) == ST_DELETING)
-			DeleteFiles(pTask);
-		
-		// refresh time
-		pTask->UpdateTime();
-
-		// save progress before killed
-		pTask->Store(false);
-		
-		// we are ending
-		pTask->DecreaseOperationsPending();
-
-		// play sound
-		if (GetConfig().get_bool(PP_SNDPLAYSOUNDS))
-		{
-			GetConfig().get_string(PP_SNDFINISHEDSOUNDPATH, szPath, _MAX_PATH);
-			GetApp().ExpandPath(szPath);
-			PlaySound(szPath, NULL, SND_FILENAME | SND_ASYNC);
-		}
-
-		tm=CTime::GetCurrentTime();
-		fmt.SetFormat(GetResManager().LoadString(IDS_OTFTHREADFINISHED_STRING));
-		fmt.SetParam(_t("%year"), tm.GetYear());
-		fmt.SetParam(_t("%month"), tm.GetMonth());
-		fmt.SetParam(_t("%day"), tm.GetDay());
-		fmt.SetParam(_t("%hour"), tm.GetHour());
-		fmt.SetParam(_t("%minute"), tm.GetMinute());
-		fmt.SetParam(_t("%second"), tm.GetSecond());
-		pTask->m_log.logi(fmt);
-
-		// we have been killed - the last operation
-		InterlockedIncrement(pTask->m_plFinished);
-		pTask->CleanupAfterKill();
-		pTask->SetKilledFlag();
-	}
-	catch(CProcessingException* e)
-	{
-		// increment count of beginnings
-		InterlockedIncrement(pTask->m_plFinished);
-		
-		// refresh time
-		pTask->UpdateTime();
-		
-		// log
-		fmt.SetFormat(GetResManager().LoadString(IDS_OTFCAUGHTEXCEPTIONMAIN_STRING));
-		fmt.SetParam(_t("%errno"), e->m_dwError);
-		fmt.SetParam(_t("%type"), e->m_iType);
-		pTask->m_log.loge(fmt);
-
-		if (e->m_iType == E_ERROR && GetConfig().get_bool(PP_SNDPLAYSOUNDS))
-		{
-			GetConfig().get_string(PP_SNDERRORSOUNDPATH, szPath, _MAX_PATH);
-			GetApp().ExpandPath(szPath);
-			PlaySound(szPath, NULL, SND_FILENAME | SND_ASYNC);
-		}
-
-		// pause task if requested
-		if(e->m_iType == E_PAUSE)
-			pTask->SetStatus(ST_PAUSED, ST_PAUSED);
-
-		// cleanup changes flags and calls cleanup for a task
-		e->Cleanup();
-		delete e;
-
-		if (pTask->GetStatus(ST_WAITING_MASK) & ST_WAITING)
-			pTask->SetStatus(0, ST_WAITING);
-
-		pTask->DecreaseOperationsPending();
-		pTask->SetContinueFlag(false);
-		pTask->SetForceFlag(false);
-
-		return 0xffffffff;	// almost like -1
-	}
-
-	TRACE("TASK FINISHED - exiting ThrdProc.\n");
-	return 0;
-}
-
 UINT ClipboardMonitorProc(LPVOID pParam)
 {
 	volatile CLIPBOARDMONITORDATA* pData=static_cast<CLIPBOARDMONITORDATA *>(pParam);
@@ -1436,7 +418,7 @@
 	ShowTrayIcon();
 
 	// initialize CTaskArray
-	m_tasks.Create(m_pFeedbackFactory, &ThrdProc);
+	m_tasks.Create(m_pFeedbackFactory);
 
 	// load last state
 	CString strPath;
Index: src/ch/MainWnd.h
===================================================================
diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/MainWnd.h	(.../MainWnd.h)	(revision d5c3edd0d167db9b5d47d04248820fda49499a5e)
+++ src/ch/MainWnd.h	(.../MainWnd.h)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -27,18 +27,6 @@
 #include "StatusDlg.h"
 #include "FeedbackHandler.h"
 
-typedef struct _CUSTOM_COPY_PARAMS
-{
-	CTask* pTask;			// ptr to CTask object on which we do the operation
-
-	CFileInfo* pfiSrcFile;	// CFileInfo - src file
-	CString strDstFile;		// dest path with filename
-
-	CDataBuffer dbBuffer;	// buffer handling
-	bool bOnlyCreate;		// flag from configuration - skips real copying - only create
-	bool bProcessed;		// has the element been processed ? (false if skipped)
-} CUSTOM_COPY_PARAMS, *PCUSTOM_COPY_PARAMS;
-
 class CMainWnd : public CWnd
 {
 public:
Index: src/ch/MiniViewDlg.cpp
===================================================================
diff -u -rcaa71fb57fcfdd3b3731ed038cecc280ff69a78e -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/MiniViewDlg.cpp	(.../MiniViewDlg.cpp)	(revision caa71fb57fcfdd3b3731ed038cecc280ff69a78e)
+++ src/ch/MiniViewDlg.cpp	(.../MiniViewDlg.cpp)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -20,6 +20,7 @@
 #include "MiniViewDlg.h"
 #include "ch.h"
 #include <assert.h>
+#include "MemDC.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
Index: src/ch/ProgressListBox.cpp
===================================================================
diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/ProgressListBox.cpp	(.../ProgressListBox.cpp)	(revision d5c3edd0d167db9b5d47d04248820fda49499a5e)
+++ src/ch/ProgressListBox.cpp	(.../ProgressListBox.cpp)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -18,6 +18,7 @@
 ***************************************************************************/
 #include "stdafx.h"
 #include "ProgressListBox.h"
+#include "MemDC.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
Index: src/ch/ProgressListBox.h
===================================================================
diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/ProgressListBox.h	(.../ProgressListBox.h)	(revision d5c3edd0d167db9b5d47d04248820fda49499a5e)
+++ src/ch/ProgressListBox.h	(.../ProgressListBox.h)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -19,10 +19,10 @@
 #ifndef __PROGRESSLISTBOX_H__
 #define __PROGRESSLISTBOX_H__
 
-#include "memdc.h"
 #include "afxtempl.h"
-#include "structs.h"
 
+class CTask;
+
 /////////////////////////////////////////////////////////////////////////////
 // CProgressListBox window
 struct _PROGRESSITEM_
Index: src/ch/ReplacePathsDlg.h
===================================================================
diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/ReplacePathsDlg.h	(.../ReplacePathsDlg.h)	(revision d5c3edd0d167db9b5d47d04248820fda49499a5e)
+++ src/ch/ReplacePathsDlg.h	(.../ReplacePathsDlg.h)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -19,7 +19,7 @@
 #ifndef __REPLACEPATHSDLG_H__
 #define __REPLACEPATHSDLG_H__
 
-#include "structs.h"
+class CTask;
 
 /////////////////////////////////////////////////////////////////////////////
 // CReplacePathsDlg dialog
Index: src/ch/StatusDlg.cpp
===================================================================
diff -u -raa6bff57279b9f9cfc276e9adab2763e2900878d -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/StatusDlg.cpp	(.../StatusDlg.cpp)	(revision aa6bff57279b9f9cfc276e9adab2763e2900878d)
+++ src/ch/StatusDlg.cpp	(.../StatusDlg.cpp)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -24,6 +24,7 @@
 #include "ReplacePathsDlg.h"
 #include "StringHelpers.h"
 #include "StaticEx.h"
+#include "Structs.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
Index: src/ch/Structs.h
===================================================================
diff -u -r49b67b7417f8b42ce581ebfe604f47df841f763b -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/Structs.h	(.../Structs.h)	(revision 49b67b7417f8b42ce581ebfe604f47df841f763b)
+++ src/ch/Structs.h	(.../Structs.h)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -32,18 +32,8 @@
 int PriorityClassToIndex(int iPriority);
 
 ///////////////////////////////////////////////////////////////////////////
-// Exceptions
-
-#define E_KILL_REQUEST		0x00
-#define E_ERROR				0x01
-#define E_CANCEL			0x02
-#define E_PAUSE				0x03
-
-
-///////////////////////////////////////////////////////////////////////////
 // CLIPBOARDMONITORDATA
 class CTaskArray;
-class CTask;
 
 struct CLIPBOARDMONITORDATA
 {
@@ -53,24 +43,4 @@
 	volatile bool bKill, bKilled;
 };
 
-///////////////////////////////////////////////////////////////////////////
-// CProcessingException
-
-class CProcessingException
-{
-public:
-	CProcessingException(int iType, CTask* pTask) { m_iType=iType; m_pTask=pTask; m_dwError=0; };
-	CProcessingException(int iType, CTask* pTask, UINT uiFmtID, DWORD dwError, ...);
-	CProcessingException(int iType, CTask* pTask, DWORD dwError, const tchar_t* pszDesc);
-	void Cleanup();
-
-// Implementation
-public:
-	int m_iType;	// kill request, error, ...
-	CTask* m_pTask;
-
-	CString m_strErrorDesc;
-	DWORD m_dwError;
-};
-
 #endif
\ No newline at end of file
Index: src/ch/task.cpp
===================================================================
diff -u -r49b67b7417f8b42ce581ebfe604f47df841f763b -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/task.cpp	(.../task.cpp)	(revision 49b67b7417f8b42ce581ebfe604f47df841f763b)
+++ src/ch/task.cpp	(.../task.cpp)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -21,7 +21,11 @@
 #include "StringHelpers.h"
 #include "../common/FileSupport.h"
 #include "ch.h"
+#include "FeedbackHandler.h"
 
+// assume max sectors of 4kB (for rounding)
+#define MAXSECTORSIZE			4096
+
 ////////////////////////////////////////////////////////////////////////////
 // CTask members
 
@@ -49,7 +53,6 @@
 	m_bKill=false;
 	m_bKilled=true;
 	m_pcs=pCreateData->pcs;
-	m_pfnTaskProc=pCreateData->pfnTaskProc;
 	m_lTimeElapsed=0;
 	m_lLastTime=-1;
 	m_puiOperationsPending=pCreateData->puiOperationsPending;
@@ -639,7 +642,7 @@
 	m_bSaved=false;			// save
 	SetKillFlag(false);
 	SetKilledFlag(false);
-	CWinThread* pThread=AfxBeginThread(m_pfnTaskProc, this, GetPriority());
+	CWinThread* pThread=AfxBeginThread(ThrdProc, this, GetPriority());
 
 	m_cs.Lock();
 	m_pThread=pThread;
@@ -1112,12 +1115,11 @@
 	// NOTE: do not delete the feedback factory, since we are not responsible for releasing it
 }
 
-void CTaskArray::Create(chcore::IFeedbackHandlerFactory* piFeedbackHandlerFactory, UINT (*pfnTaskProc)(LPVOID pParam))
+void CTaskArray::Create(chcore::IFeedbackHandlerFactory* piFeedbackHandlerFactory)
 {
-	BOOST_ASSERT(piFeedbackHandlerFactory && pfnTaskProc);
+	BOOST_ASSERT(piFeedbackHandlerFactory);
 
 	m_tcd.pcs=&m_cs;
-	m_tcd.pfnTaskProc=pfnTaskProc;
 	m_tcd.pTasksAll=&m_uhRange;
 	m_tcd.pTasksProcessed=&m_uhPosition;
 	m_tcd.puiOperationsPending=&m_uiOperationsPending;
@@ -1494,3 +1496,1006 @@
 	m_cs.Unlock();
 	return bFlag;
 }
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// case insensitive replacement
+void CTask::ReplaceNoCase(CString& rString, CString strOld, CString strNew)
+{
+	if (rString.Left(strOld.GetLength()).CompareNoCase(strOld) == 0)
+		rString=strNew+rString.Right(rString.GetLength()-strOld.GetLength());
+}
+
+bool CTask::TimeToFileTime(const COleDateTime& time, LPFILETIME pFileTime)
+{
+	SYSTEMTIME sysTime;
+	sysTime.wYear = (WORD)time.GetYear();
+	sysTime.wMonth = (WORD)time.GetMonth();
+	sysTime.wDay = (WORD)time.GetDay();
+	sysTime.wHour = (WORD)time.GetHour();
+	sysTime.wMinute = (WORD)time.GetMinute();
+	sysTime.wSecond = (WORD)time.GetSecond();
+	sysTime.wMilliseconds = 0;
+
+	// convert system time to local file time
+	FILETIME localTime;
+	if (!SystemTimeToFileTime((LPSYSTEMTIME)&sysTime, &localTime))
+		return false;
+
+	// convert local file time to UTC file time
+	if (!LocalFileTimeToFileTime(&localTime, pFileTime))
+		return false;
+
+	return true;
+}
+
+bool CTask::SetFileDirectoryTime(LPCTSTR lpszName, CFileInfo* pSrcInfo)
+{
+	FILETIME creation, lastAccess, lastWrite;
+
+	if (!TimeToFileTime(pSrcInfo->GetCreationTime(), &creation)
+		|| !TimeToFileTime(pSrcInfo->GetLastAccessTime(), &lastAccess)
+		|| !TimeToFileTime(pSrcInfo->GetLastWriteTime(), &lastWrite) )
+		return false;
+
+	HANDLE handle=CreateFile(lpszName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+	if (handle == INVALID_HANDLE_VALUE)
+		return false;
+
+	if (!SetFileTime(handle, &creation, &lastAccess, &lastWrite))
+	{
+		CloseHandle(handle);
+		return false;
+	}
+
+	if (!CloseHandle(handle))
+		return false;
+
+	return true;
+}
+
+// searching for files
+void CTask::RecurseDirectories(CTask* pTask)
+{
+	TRACE("Searching for files...\n");
+
+	// log
+	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFSEARCHINGFORFILES_STRING));
+
+	// update status
+	pTask->SetStatus(ST_SEARCHING, ST_STEP_MASK);
+
+	// delete the content of m_files
+	pTask->FilesRemoveAll();
+
+	// enter some data to m_files
+	int nSize=pTask->GetClipboardDataSize();	// size of m_clipboard
+	const CFiltersArray* pFilters=pTask->GetFilters();
+	int iDestDrvNumber=pTask->GetDestDriveNumber();
+	bool bIgnoreDirs=(pTask->GetStatus(ST_SPECIAL_MASK) & ST_IGNORE_DIRS) != 0;
+	bool bForceDirectories=(pTask->GetStatus(ST_SPECIAL_MASK) & ST_FORCE_DIRS) != 0;
+	bool bMove=pTask->GetStatus(ST_OPERATION_MASK) == ST_MOVE;
+	CFileInfo fi;
+	fi.SetClipboard(pTask->GetClipboard());
+
+	// add everything
+	ictranslate::CFormat fmt;
+	for (int i=0;i<nSize;i++)
+	{
+		// read attributes of src file/folder
+		if (!fi.Create(pTask->GetClipboardData(i)->GetPath(), i))
+		{
+			// log
+			fmt.SetFormat(GetResManager().LoadString(IDS_OTFMISSINGCLIPBOARDINPUT_STRING));
+			fmt.SetParam(_t("%path"), pTask->GetClipboardData(i)->GetPath());
+			pTask->m_log.logw(fmt);
+			continue;
+		}
+		else
+		{
+			// log
+			fmt.SetFormat(GetResManager().LoadString(IDS_OTFADDINGCLIPBOARDFILE_STRING));
+			fmt.SetParam(_t("%path"), pTask->GetClipboardData(i)->GetPath());
+			pTask->m_log.logi(fmt);
+		}
+
+		// found file/folder - check if the dest name has been generated
+		if (pTask->GetClipboardData(i)->m_astrDstPaths.GetSize() == 0)
+		{
+			// generate something - if dest folder == src folder - search for copy
+			if (pTask->GetDestPath().GetPath() == fi.GetFileRoot())
+			{
+				CString strSubst;
+				FindFreeSubstituteName(fi.GetFullFilePath(), pTask->GetDestPath().GetPath(), &strSubst);
+				pTask->GetClipboardData(i)->m_astrDstPaths.Add(strSubst);
+			}
+			else
+				pTask->GetClipboardData(i)->m_astrDstPaths.Add(fi.GetFileName());
+		}
+
+		// add if needed
+		if (fi.IsDirectory())
+		{
+			// add if folder's aren't ignored
+			if (!bIgnoreDirs && !bForceDirectories)
+			{
+				pTask->FilesAdd(fi);
+
+				// log
+				fmt.SetFormat(GetResManager().LoadString(IDS_OTFADDEDFOLDER_STRING));
+				fmt.SetParam(_t("%path"), fi.GetFullFilePath());
+				pTask->m_log.logi(fmt);
+			}
+
+			// don't add folder contents when moving inside one disk boundary
+			if (bIgnoreDirs || !bMove || pTask->GetCopies() > 1 || iDestDrvNumber == -1
+				|| iDestDrvNumber != fi.GetDriveNumber() || CFileInfo::Exist(fi.GetDestinationPath(pTask->GetDestPath().GetPath(), 0, ((int)bForceDirectories) << 1)) )
+			{
+				// log
+				fmt.SetFormat(GetResManager().LoadString(IDS_OTFRECURSINGFOLDER_STRING));
+				fmt.SetParam(_t("%path"), fi.GetFullFilePath());
+				pTask->m_log.logi(fmt);
+
+				// no movefile possibility - use CustomCopyFile
+				pTask->GetClipboardData(i)->SetMove(false);
+
+				pTask->FilesAddDir(fi.GetFullFilePath(), pFilters, i, true, !bIgnoreDirs || bForceDirectories);
+			}
+
+			// check for kill need
+			if (pTask->GetKillFlag())
+			{
+				// log
+				pTask->m_log.logi(GetResManager().LoadString(IDS_OTFADDINGKILLREQEST_STRING));
+				throw new CProcessingException(E_KILL_REQUEST, pTask);
+			}
+		}
+		else
+		{
+			if (bMove && pTask->GetCopies() == 1 && iDestDrvNumber != -1 && iDestDrvNumber == fi.GetDriveNumber() &&
+				!CFileInfo::Exist(fi.GetDestinationPath(pTask->GetDestPath().GetPath(), 0, ((int)bForceDirectories) << 1)) )
+			{
+				// if moving within one partition boundary set the file size to 0 so the overall size will
+				// be ok
+				fi.SetLength64(0);
+			}
+			else
+				pTask->GetClipboardData(i)->SetMove(false);	// no MoveFile
+
+			pTask->FilesAdd(fi);		// file - add
+
+			// log
+			fmt.SetFormat(GetResManager().LoadString(IDS_OTFADDEDFILE_STRING));
+			fmt.SetParam(_t("%path"), fi.GetFullFilePath());
+			pTask->m_log.logi(fmt);
+		}
+	}
+
+	// calc size of all files
+	pTask->CalcAllSize();
+
+	// update *m_pnTasksAll;
+	pTask->IncreaseAllTasksSize(pTask->GetAllSize());
+
+	// change state to ST_COPYING - finished searching for files
+	pTask->SetStatus(ST_COPYING, ST_STEP_MASK);
+
+	// save task status
+	pTask->Store(true);
+	pTask->Store(false);
+
+	// log
+	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFSEARCHINGFINISHED_STRING));
+}
+
+// delete files - after copying
+void CTask::DeleteFiles(CTask* pTask)
+{
+	// log
+	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFDELETINGFILES_STRING));
+
+	// current processed path
+	BOOL bSuccess;
+	CFileInfo fi;
+	ictranslate::CFormat fmt;
+
+	// index points to 0 or next item to process
+	for (int i=pTask->GetCurrentIndex();i<pTask->FilesGetSize();i++)
+	{
+		// set index in pTask to currently deleted element
+		pTask->SetCurrentIndex(i);
+
+		// check for kill flag
+		if (pTask->GetKillFlag())
+		{
+			// log
+			pTask->m_log.logi(GetResManager().LoadString(IDS_OTFDELETINGKILLREQUEST_STRING));
+			throw new CProcessingException(E_KILL_REQUEST, pTask);
+		}
+
+		// current processed element
+		fi=pTask->FilesGetAt(pTask->FilesGetSize()-i-1);
+		if(!(fi.GetFlags() & FIF_PROCESSED))
+			continue;
+
+		// delete data
+		if (fi.IsDirectory())
+		{
+			if (!GetConfig().get_bool(PP_CMPROTECTROFILES))
+				SetFileAttributes(fi.GetFullFilePath(), FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY);
+			bSuccess=RemoveDirectory(fi.GetFullFilePath());
+		}
+		else
+		{
+			// set files attributes to normal - it'd slow processing a bit, but it's better.
+			if (!GetConfig().get_bool(PP_CMPROTECTROFILES))
+				SetFileAttributes(fi.GetFullFilePath(), FILE_ATTRIBUTE_NORMAL);
+			bSuccess=DeleteFile(fi.GetFullFilePath());
+		}
+
+		// operation failed
+		DWORD dwLastError=GetLastError();
+		if (!bSuccess && dwLastError != ERROR_PATH_NOT_FOUND && dwLastError != ERROR_FILE_NOT_FOUND)
+		{
+			// log
+			fmt.SetFormat(GetResManager().LoadString(IDS_OTFDELETINGERROR_STRING));
+			fmt.SetParam(_t("%errno"), dwLastError);
+			fmt.SetParam(_t("%path"), fi.GetFullFilePath());
+			pTask->m_log.loge(fmt);
+			throw new CProcessingException(E_ERROR, pTask, dwLastError, fmt);
+		}
+	}//for
+
+	// change status to finished
+	pTask->SetStatus(ST_FINISHED, ST_STEP_MASK);
+
+	// add 1 to current index - looks better
+	pTask->IncreaseCurrentIndex();
+
+	// log
+	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFDELETINGFINISHED_STRING));
+}
+
+void CTask::CustomCopyFile(CUSTOM_COPY_PARAMS* pData)
+{
+	HANDLE hSrc=INVALID_HANDLE_VALUE, hDst=INVALID_HANDLE_VALUE;
+	ictranslate::CFormat fmt;
+	try
+	{
+		// do we copy rest or recopy ?
+		bool bCopyRest=GetConfig().get_bool(PP_CMUSEAUTOCOMPLETEFILES);
+
+		// Data regarding dest file
+		CFileInfo fiDest;
+		bool bExist=fiDest.Create(pData->strDstFile, -1);
+
+		chcore::IFeedbackHandler* piFeedbackHandler = pData->pTask->GetFeedbackHandler();
+		BOOST_ASSERT(piFeedbackHandler);
+
+		pData->pTask->SetLastProcessedIndex(-1);
+
+		// if dest file size >0 - we can do somethng more than usual
+		if(bExist)
+		{
+			// src and dst files are the same
+			FEEDBACK_ALREADYEXISTS feedStruct = { pData->pfiSrcFile, &fiDest };
+			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileAlreadyExists, &feedStruct);
+			// check for dialog result
+			switch(frResult)
+			{
+			case CFeedbackHandler::eResult_Overwrite:
+				{
+					bCopyRest=false;
+					break;
+				}
+			case CFeedbackHandler::eResult_CopyRest:
+				{
+					bCopyRest=true;
+					break;
+				}
+			case CFeedbackHandler::eResult_Skip:
+				{
+					pData->pTask->IncreaseProcessedSize(pData->pfiSrcFile->GetLength64());
+					pData->pTask->IncreaseProcessedTasksSize(pData->pfiSrcFile->GetLength64());
+					pData->bProcessed = false;
+					return;
+				}
+			case CFeedbackHandler::eResult_Cancel:
+				{
+					// log
+					if (GetConfig().get_bool(PP_CMCREATELOG))
+					{
+						fmt.SetFormat(GetResManager().LoadString(IDS_OTFPRECHECKCANCELREQUEST_STRING));
+						fmt.SetParam(_t("%path"), pData->pfiSrcFile->GetFullFilePath());
+						pData->pTask->m_log.logi(fmt);
+					}
+					throw new CProcessingException(E_CANCEL, pData->pTask);
+					break;
+				}
+			case CFeedbackHandler::eResult_Pause:
+				{
+					throw new CProcessingException(E_PAUSE, pData->pTask);
+					break;
+				}
+			default:
+				{
+					BOOST_ASSERT(FALSE);		// unknown result
+					throw new CProcessingException(E_ERROR, pData->pTask, 0, _t("Unknown feedback result type"));
+					break;
+				}
+			}
+		}// bExist
+
+		// change attributes of a dest file
+		if (!GetConfig().get_bool(PP_CMPROTECTROFILES))
+			SetFileAttributes(pData->strDstFile, FILE_ATTRIBUTE_NORMAL);
+
+		// first or second pass ? only for FFNB
+		bool bFirstPass=true;
+
+		// check size of src file to know whether use flag FILE_FLAG_NOBUFFERING
+l_start:
+		bool bNoBuffer=(bFirstPass && GetConfig().get_bool(PP_BFUSENOBUFFERING) && pData->pfiSrcFile->GetLength64() >= (unsigned long long)GetConfig().get_signed_num(PP_BFBOUNDARYLIMIT));
+
+		// refresh data about file
+		if (!bFirstPass)
+			bExist=fiDest.Create(pData->strDstFile, -1);
+
+		// open src
+l_openingsrc:
+		hSrc=CreateFile(pData->pfiSrcFile->GetFullFilePath(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffer ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
+		if (hSrc == INVALID_HANDLE_VALUE)
+		{
+			DWORD dwLastError=GetLastError();
+			CString strFile = pData->pfiSrcFile->GetFullFilePath();
+			FEEDBACK_FILEERROR feedStruct = { (PCTSTR)strFile, dwLastError };
+			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
+
+			switch (frResult)
+			{
+			case CFeedbackHandler::eResult_Skip:
+				pData->pTask->IncreaseProcessedSize(pData->pfiSrcFile->GetLength64());
+				pData->pTask->IncreaseProcessedTasksSize(pData->pfiSrcFile->GetLength64());
+				pData->bProcessed = false;
+				return;
+				break;
+			case CFeedbackHandler::eResult_Cancel:
+				// log
+				fmt.SetFormat(GetResManager().LoadString(IDS_OTFOPENINGCANCELREQUEST_STRING));
+				fmt.SetParam(_t("%errno"), dwLastError);
+				fmt.SetParam(_t("%path"), pData->pfiSrcFile->GetFullFilePath());
+				pData->pTask->m_log.loge(fmt);
+				throw new CProcessingException(E_CANCEL, pData->pTask);
+				break;
+			case CFeedbackHandler::eResult_Pause:
+				throw new CProcessingException(E_PAUSE, pData->pTask);
+				break;
+			case CFeedbackHandler::eResult_Retry:
+				// log
+				fmt.SetFormat(GetResManager().LoadString(IDS_OTFOPENINGRETRY_STRING));
+				fmt.SetParam(_t("%errno"), dwLastError);
+				fmt.SetParam(_t("%path"), pData->pfiSrcFile->GetFullFilePath());
+				pData->pTask->m_log.loge(fmt);
+				goto l_openingsrc;
+				break;
+			default:
+				{
+					BOOST_ASSERT(FALSE);		// unknown result
+					throw new CProcessingException(E_ERROR, pData->pTask, 0, _t("Unknown feedback result type"));
+					break;
+				}
+			}
+		}
+
+		// open dest
+l_openingdst:
+		hDst=CreateFile(pData->strDstFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffer ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
+		if (hDst == INVALID_HANDLE_VALUE)
+		{
+			DWORD dwLastError=GetLastError();
+			CString strFile = pData->strDstFile;
+
+			FEEDBACK_FILEERROR feedStruct = { (PCTSTR)strFile, dwLastError };
+			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
+			switch (frResult)
+			{
+			case CFeedbackHandler::eResult_Retry:
+				// change attributes
+				if (!GetConfig().get_bool(PP_CMPROTECTROFILES))
+					SetFileAttributes(pData->strDstFile, FILE_ATTRIBUTE_NORMAL);
+
+				// log
+				fmt.SetFormat(GetResManager().LoadString(IDS_OTFDESTOPENINGRETRY_STRING));
+				fmt.SetParam(_t("%errno"), dwLastError);
+				fmt.SetParam(_t("%path"), pData->strDstFile);
+				pData->pTask->m_log.loge(fmt);
+				goto l_openingdst;
+				break;
+			case CFeedbackHandler::eResult_Cancel:
+				// log
+				fmt.SetFormat(GetResManager().LoadString(IDS_OTFDESTOPENINGCANCELREQUEST_STRING));
+				fmt.SetParam(_t("%errno"), dwLastError);
+				fmt.SetParam(_t("%path"), pData->strDstFile);
+				pData->pTask->m_log.loge(fmt);
+				throw new CProcessingException(E_CANCEL, pData->pTask);
+				break;
+			case CFeedbackHandler::eResult_Skip:
+				pData->pTask->IncreaseProcessedSize(pData->pfiSrcFile->GetLength64());
+				pData->pTask->IncreaseProcessedTasksSize(pData->pfiSrcFile->GetLength64());
+				pData->bProcessed = false;
+				return;
+				break;
+			case CFeedbackHandler::eResult_Pause:
+				throw new CProcessingException(E_PAUSE, pData->pTask);
+				break;
+			default:
+				{
+					BOOST_ASSERT(FALSE);		// unknown result
+					throw new CProcessingException(E_ERROR, pData->pTask, 0, _t("Unknown feedback result type"));
+					break;
+				}
+			}
+		}
+
+		// seeking
+		DWORD dwLastError=0;
+		if (!pData->bOnlyCreate)
+		{
+			if ( bCopyRest )	// if copy rest
+			{
+				if (!bFirstPass || (bExist && fiDest.GetLength64() > 0))
+				{
+					// try to move file pointers to the end
+					ULONGLONG ullMove=(bNoBuffer ? ROUNDDOWN(fiDest.GetLength64(), MAXSECTORSIZE) : fiDest.GetLength64());
+					if (SetFilePointer64(hSrc, ullMove, FILE_BEGIN) == -1 || SetFilePointer64(hDst, ullMove, FILE_BEGIN) == -1)
+					{
+						// log
+						fmt.SetFormat(GetResManager().LoadString(IDS_OTFMOVINGPOINTERSERROR_STRING));
+						fmt.SetParam(_t("%errno"), GetLastError());
+						fmt.SetParam(_t("%srcpath"), pData->pfiSrcFile->GetFullFilePath());
+						fmt.SetParam(_t("%dstpath"), pData->strDstFile);
+						fmt.SetParam(_t("%pos"), ullMove);
+						pData->pTask->m_log.loge(fmt);
+
+						// seek failed - seek to begin
+						if (SetFilePointer64(hSrc, 0, FILE_BEGIN) == -1 || SetFilePointer64(hDst, 0, FILE_BEGIN) == -1)
+						{
+							// log
+							dwLastError=GetLastError();
+							fmt.SetFormat(GetResManager().LoadString(IDS_OTFRESTORINGPOINTERSERROR_STRING));
+							fmt.SetParam(_t("%errno"), dwLastError);
+							fmt.SetParam(_t("%srcpath"), pData->pfiSrcFile->GetFullFilePath());
+							fmt.SetParam(_t("%dstpath"), pData->strDstFile);
+							pData->pTask->m_log.loge(fmt);
+							throw new CProcessingException(E_ERROR, pData->pTask, dwLastError, fmt);
+						}
+						else
+						{
+							// file pointers restored - if second pass subtract what's needed
+							if (!bFirstPass)
+							{
+								pData->pTask->IncreaseProcessedSize(-static_cast<__int64>(ullMove));
+								pData->pTask->IncreaseProcessedTasksSize(-static_cast<__int64>(ullMove));
+							}
+						}
+					}
+					else
+					{
+						// file pointers moved - so we have skipped some work - update positions
+						if (bFirstPass)	// przy drugim obiegu jest ju� uwzgl�dnione
+						{
+							pData->pTask->IncreaseProcessedSize(ullMove);
+							pData->pTask->IncreaseProcessedTasksSize(ullMove);
+						}
+					}
+				}
+			}
+			else
+				if (!SetEndOfFile(hDst))	// if recopying - reset the dest file
+				{
+					// log
+					dwLastError=GetLastError();
+					fmt.SetFormat(GetResManager().LoadString(IDS_OTFSETTINGZEROSIZEERROR_STRING));
+					fmt.SetParam(_t("%errno"), dwLastError);
+					fmt.SetParam(_t("%path"), pData->strDstFile);
+					pData->pTask->m_log.loge(fmt);
+					throw new CProcessingException(E_ERROR, pData->pTask, dwLastError, fmt);
+				}
+
+				// copying
+				unsigned long tord, rd, wr;
+				int iBufferIndex;
+				do
+				{
+					// kill flag checks
+					if (pData->pTask->GetKillFlag())
+					{
+						// log
+						fmt.SetFormat(GetResManager().LoadString(IDS_OTFCOPYINGKILLREQUEST_STRING));
+						fmt.SetParam(_t("%srcpath"), pData->pfiSrcFile->GetFullFilePath());
+						fmt.SetParam(_t("%dstpath"), pData->strDstFile);
+						pData->pTask->m_log.logi(fmt);
+						throw new CProcessingException(E_KILL_REQUEST, pData->pTask);
+					}
+
+					// recreate buffer if needed
+					if (!(*pData->dbBuffer.GetSizes() == *pData->pTask->GetBufferSizes()))
+					{
+						// log
+						const BUFFERSIZES *pbs1=pData->dbBuffer.GetSizes(), *pbs2=pData->pTask->GetBufferSizes();
+
+						fmt.SetFormat(GetResManager().LoadString(IDS_OTFCHANGINGBUFFERSIZE_STRING));
+
+						fmt.SetParam(_t("%defsize"), pbs1->m_uiDefaultSize);
+						fmt.SetParam(_t("%onesize"), pbs1->m_uiOneDiskSize);
+						fmt.SetParam(_t("%twosize"), pbs1->m_uiTwoDisksSize);
+						fmt.SetParam(_t("%cdsize"), pbs1->m_uiCDSize);
+						fmt.SetParam(_t("%lansize"), pbs1->m_uiLANSize);
+						fmt.SetParam(_t("%defsize2"), pbs2->m_uiDefaultSize);
+						fmt.SetParam(_t("%onesize2"), pbs2->m_uiOneDiskSize);
+						fmt.SetParam(_t("%twosize2"), pbs2->m_uiTwoDisksSize);
+						fmt.SetParam(_t("%cdsize2"), pbs2->m_uiCDSize);
+						fmt.SetParam(_t("%lansize2"), pbs2->m_uiLANSize);
+						fmt.SetParam(_t("%srcfile"), pData->pfiSrcFile->GetFullFilePath());
+						fmt.SetParam(_t("%dstfile"), pData->strDstFile);
+
+						pData->pTask->m_log.logi(fmt);
+						pData->pTask->SetBufferSizes(pData->dbBuffer.Create(pData->pTask->GetBufferSizes()));
+					}
+
+					// establish count of data to read
+					iBufferIndex=pData->pTask->GetBufferSizes()->m_bOnlyDefault ? 0 : pData->pfiSrcFile->GetBufferIndex();
+					tord=bNoBuffer ? ROUNDUP(pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex], MAXSECTORSIZE) : pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex];
+
+					// read
+					if (!ReadFile(hSrc, pData->dbBuffer, tord, &rd, NULL))
+					{
+						// log
+						dwLastError=GetLastError();
+						fmt.SetFormat(GetResManager().LoadString(IDS_OTFREADINGERROR_STRING));
+						fmt.SetParam(_t("%errno"), dwLastError);
+						fmt.SetParam(_t("%count"), tord);
+						fmt.SetParam(_t("%path"), pData->pfiSrcFile->GetFullFilePath());
+						pData->pTask->m_log.loge(fmt);
+						throw new CProcessingException(E_ERROR, pData->pTask, dwLastError, fmt);
+					}
+
+					// change count of stored data
+					if (bNoBuffer && (ROUNDUP(rd, MAXSECTORSIZE)) != rd)
+					{
+						// we need to copy rest so do the second pass
+						// close files
+						CloseHandle(hSrc);
+						CloseHandle(hDst);
+
+						// second pass
+						bFirstPass=false;
+						bCopyRest=true;		// nedd to copy rest
+
+						goto l_start;
+					}
+
+					// zapisz
+					if (!WriteFile(hDst, pData->dbBuffer, rd, &wr, NULL) || wr != rd)
+					{
+						// log
+						dwLastError=GetLastError();
+						fmt.SetFormat(GetResManager().LoadString(IDS_OTFWRITINGERROR_STRING));
+						fmt.SetParam(_t("%errno"), dwLastError);
+						fmt.SetParam(_t("%count"), rd);
+						fmt.SetParam(_t("%path"), pData->strDstFile);
+						pData->pTask->m_log.loge(fmt);
+						throw new CProcessingException(E_ERROR, pData->pTask, dwLastError, fmt);
+					}
+
+					// increase count of processed data
+					pData->pTask->IncreaseProcessedSize(rd);
+					pData->pTask->IncreaseProcessedTasksSize(rd);
+					//				TRACE("Read: %d, Written: %d\n", rd, wr);
+				}
+				while ( rd != 0 );
+		}
+		else
+		{
+			// we don't copy contents, but need to increase processed size
+			pData->pTask->IncreaseProcessedSize(pData->pfiSrcFile->GetLength64());
+			pData->pTask->IncreaseProcessedTasksSize(pData->pfiSrcFile->GetLength64());
+		}
+
+		// close files
+		CloseHandle(hSrc);
+		CloseHandle(hDst);
+
+		pData->bProcessed = true;
+	}
+	catch(...)
+	{
+		// log
+		fmt.SetFormat(GetResManager().LoadString(IDS_OTFCAUGHTEXCEPTIONCCF_STRING));
+		fmt.SetParam(_t("%errno"), GetLastError());
+		fmt.SetParam(_t("%timestamp"), GetTickCount());
+		pData->pTask->m_log.loge(fmt);
+
+		// close handles
+		if (hSrc != INVALID_HANDLE_VALUE)
+			CloseHandle(hSrc);
+		if (hDst != INVALID_HANDLE_VALUE)
+			CloseHandle(hDst);
+
+		throw;
+	}
+}
+
+// function processes files/folders
+void CTask::ProcessFiles(CTask* pTask)
+{
+	// log
+	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFPROCESSINGFILES_STRING));
+
+	// count how much has been done (updates also a member in CTaskArray)
+	pTask->CalcProcessedSize();
+
+	// create a buffer of size pTask->m_nBufferSize
+	CUSTOM_COPY_PARAMS ccp;
+	ccp.bProcessed = false;
+	ccp.pTask=pTask;
+	ccp.bOnlyCreate=(pTask->GetStatus(ST_SPECIAL_MASK) & ST_IGNORE_CONTENT) != 0;
+	ccp.dbBuffer.Create(pTask->GetBufferSizes());
+
+	// helpers
+	//CFileInfo fi;	// for currently processed element
+	DWORD dwLastError;
+
+	// begin at index which wasn't processed previously
+	int nSize=pTask->FilesGetSize();	// wielko�� tablicy
+	int iCopiesCount=pTask->GetCopies();	// ilo�� kopii
+	bool bIgnoreFolders=(pTask->GetStatus(ST_SPECIAL_MASK) & ST_IGNORE_DIRS) != 0;
+	bool bForceDirectories=(pTask->GetStatus(ST_SPECIAL_MASK) & ST_FORCE_DIRS) != 0;
+	const CDestPath& dpDestPath=pTask->GetDestPath();
+
+	// log
+	const BUFFERSIZES* pbs=ccp.dbBuffer.GetSizes();
+
+	ictranslate::CFormat fmt;
+	fmt.SetFormat(GetResManager().LoadString(IDS_OTFPROCESSINGFILESDATA_STRING));
+	fmt.SetParam(_t("%create"), ccp.bOnlyCreate);
+	fmt.SetParam(_t("%defsize"), pbs->m_uiDefaultSize);
+	fmt.SetParam(_t("%onesize"), pbs->m_uiOneDiskSize);
+	fmt.SetParam(_t("%twosize"), pbs->m_uiTwoDisksSize);
+	fmt.SetParam(_t("%cdsize"), pbs->m_uiCDSize);
+	fmt.SetParam(_t("%lansize"), pbs->m_uiLANSize);
+	fmt.SetParam(_t("%filecount"), nSize);
+	fmt.SetParam(_t("%copycount"), iCopiesCount);
+	fmt.SetParam(_t("%ignorefolders"), bIgnoreFolders);
+	fmt.SetParam(_t("%dstpath"), dpDestPath.GetPath());
+	fmt.SetParam(_t("%currpass"), pTask->GetCurrentCopy());
+	fmt.SetParam(_t("%currindex"), pTask->GetCurrentIndex());
+
+	pTask->m_log.logi(fmt);
+
+	for (unsigned char j=pTask->GetCurrentCopy();j<iCopiesCount;j++)
+	{
+		pTask->SetCurrentCopy(j);
+		for (int i=pTask->GetCurrentIndex();i<nSize;i++)
+		{
+			// update m_nCurrentIndex, getting current CFileInfo
+			pTask->SetCurrentIndex(i);
+			CFileInfo& fi=pTask->FilesGetAtCurrentIndex();
+
+			// should we kill ?
+			if (pTask->GetKillFlag())
+			{
+				// log
+				pTask->m_log.logi(GetResManager().LoadString(IDS_OTFPROCESSINGKILLREQUEST_STRING));
+				throw new CProcessingException(E_KILL_REQUEST, pTask);
+			}
+
+			// set dest path with filename
+			ccp.strDstFile=fi.GetDestinationPath(dpDestPath.GetPath(), j, ((int)bForceDirectories) << 1 | (int)bIgnoreFolders);
+
+			// are the files/folders lie on the same partition ?
+			bool bMove=pTask->GetStatus(ST_OPERATION_MASK) == ST_MOVE;
+			if (bMove && dpDestPath.GetDriveNumber() != -1 && dpDestPath.GetDriveNumber() == fi.GetDriveNumber() && iCopiesCount == 1 && fi.GetMove())
+			{
+				if (!MoveFile(fi.GetFullFilePath(), ccp.strDstFile))
+				{
+					dwLastError=GetLastError();
+					//log
+					fmt.SetFormat(GetResManager().LoadString(IDS_OTFMOVEFILEERROR_STRING));
+					fmt.SetParam(_t("%errno"), dwLastError);
+					fmt.SetParam(_t("%srcpath"), fi.GetFullFilePath());
+					fmt.SetParam(_t("%dstpath"), ccp.strDstFile);
+					pTask->m_log.loge(fmt);
+					throw new CProcessingException(E_ERROR, pTask, dwLastError, fmt);
+				}
+				else
+					fi.SetFlags(FIF_PROCESSED, FIF_PROCESSED);
+			}
+			else
+			{
+				// if folder - create it
+				if ( fi.IsDirectory() )
+				{
+					if (!CreateDirectory(ccp.strDstFile, NULL) && (dwLastError=GetLastError()) != ERROR_ALREADY_EXISTS )
+					{
+						// log
+						fmt.SetFormat(GetResManager().LoadString(IDS_OTFCREATEDIRECTORYERROR_STRING));
+						fmt.SetParam(_t("%errno"), dwLastError);
+						fmt.SetParam(_t("%path"), ccp.strDstFile);
+						pTask->m_log.loge(fmt);
+						throw new CProcessingException(E_ERROR, pTask, dwLastError, fmt);
+					}
+
+					pTask->IncreaseProcessedSize(fi.GetLength64());
+					pTask->IncreaseProcessedTasksSize(fi.GetLength64());
+					fi.SetFlags(FIF_PROCESSED, FIF_PROCESSED);
+				}
+				else
+				{
+					// start copying/moving file
+					ccp.pfiSrcFile=&fi;
+					ccp.bProcessed = false;
+
+					// kopiuj dane
+					CustomCopyFile(&ccp);
+					fi.SetFlags(ccp.bProcessed ? FIF_PROCESSED : 0, FIF_PROCESSED);
+
+					// if moving - delete file (only if config flag is set)
+					if (bMove && fi.GetFlags() & FIF_PROCESSED && !GetConfig().get_bool(PP_CMDELETEAFTERFINISHED) && j == iCopiesCount-1)
+					{
+						if (!GetConfig().get_bool(PP_CMPROTECTROFILES))
+							SetFileAttributes(fi.GetFullFilePath(), FILE_ATTRIBUTE_NORMAL);
+						DeleteFile(fi.GetFullFilePath());	// there will be another try later, so I don't check
+						// if succeeded
+					}
+				}
+
+				// set a time
+				if (GetConfig().get_bool(PP_CMSETDESTDATE))
+					SetFileDirectoryTime(ccp.strDstFile, &fi); // no error check - ma�o istotne
+
+				// attributes
+				if (GetConfig().get_bool(PP_CMSETDESTATTRIBUTES))
+					SetFileAttributes(ccp.strDstFile, fi.GetAttributes());	// j.w.
+			}
+		}
+
+		// current copy finished - change what's needed
+		pTask->SetCurrentIndex(0);
+	}
+
+	// delete buffer - it's not needed
+	ccp.dbBuffer.Delete();
+
+	// change status
+	if (pTask->GetStatus(ST_OPERATION_MASK) == ST_MOVE)
+	{
+		pTask->SetStatus(ST_DELETING, ST_STEP_MASK);
+		// set the index to 0 before deleting
+		pTask->SetCurrentIndex(0);
+	}
+	else
+	{
+		pTask->SetStatus(ST_FINISHED, ST_STEP_MASK);
+
+		// to look better - increase current index by 1
+		pTask->SetCurrentIndex(nSize);
+	}
+	// log
+	pTask->m_log.logi(GetResManager().LoadString(IDS_OTFPROCESSINGFINISHED_STRING));
+}
+
+void CTask::CheckForWaitState(CTask* pTask)
+{
+	// limiting operation count
+	pTask->SetStatus(ST_WAITING, ST_WAITING_MASK);
+	bool bContinue=false;
+	while (!bContinue)
+	{
+		if (pTask->CanBegin())
+		{
+			TRACE("CAN BEGIN ALLOWED TO CONTINUE...\n");
+			pTask->SetStatus(0, ST_WAITING);
+			bContinue=true;
+
+			pTask->m_log.logi(GetResManager().LoadString(IDS_OTFWAITINGFINISHED_STRING));
+
+			//			return; // skips sleep and kill flag checking
+		}
+
+		Sleep(50);	// not to make it too hard for processor
+
+		if (pTask->GetKillFlag())
+		{
+			// log
+			pTask->m_log.logi(GetResManager().LoadString(IDS_OTFWAITINGKILLREQUEST_STRING));
+			throw new CProcessingException(E_KILL_REQUEST, pTask);
+		}
+	}
+}
+
+UINT CTask::ThrdProc(LPVOID pParam)
+{
+	TRACE("\n\nENTERING ThrdProc (new task started)...\n");
+	CTask* pTask=static_cast<CTask*>(pParam);
+	chcore::IFeedbackHandler* piFeedbackHandler = pTask->GetFeedbackHandler();
+
+	TCHAR szPath[_MAX_PATH];
+
+	tstring_t strPath = pTask->GetTaskPath();
+	strPath += pTask->GetUniqueName()+_T(".log");
+
+	pTask->m_log.init(strPath.c_str(), 262144, icpf::log_file::level_debug, false, false);
+
+	// set thread boost
+	HANDLE hThread=GetCurrentThread();
+	::SetThreadPriorityBoost(hThread, GetConfig().get_bool(PP_CMDISABLEPRIORITYBOOST));
+
+	CTime tm=CTime::GetCurrentTime();
+
+	ictranslate::CFormat fmt;
+	fmt.SetFormat(GetResManager().LoadString(IDS_OTFTHREADSTART_STRING));
+	fmt.SetParam(_t("%year"), tm.GetYear());
+	fmt.SetParam(_t("%month"), tm.GetMonth());
+	fmt.SetParam(_t("%day"), tm.GetDay());
+	fmt.SetParam(_t("%hour"), tm.GetHour());
+	fmt.SetParam(_t("%minute"), tm.GetMinute());
+	fmt.SetParam(_t("%second"), tm.GetSecond());
+	pTask->m_log.logi(fmt);
+
+	try
+	{
+		// to make the value stable
+		bool bReadTasksSize=GetConfig().get_bool(PP_CMREADSIZEBEFOREBLOCKING);
+
+		if (!bReadTasksSize)
+			CheckForWaitState(pTask);	// operation limiting
+
+		// set what's needed
+		pTask->m_lLastTime=(long)time(NULL);	// last time (start counting)
+
+		// search for files if needed
+		if ((pTask->GetStatus(ST_STEP_MASK) == ST_NULL_STATUS
+			|| pTask->GetStatus(ST_STEP_MASK) == ST_SEARCHING))
+		{
+			// get rid of info about processed sizes
+			pTask->DecreaseProcessedTasksSize(pTask->GetProcessedSize());
+			pTask->SetProcessedSize(0);
+			pTask->DecreaseAllTasksSize(pTask->GetAllSize());
+			pTask->SetAllSize(0);
+
+			// start searching
+			RecurseDirectories(pTask);
+		}
+
+		// check for free space
+		ull_t ullNeededSize = 0, ullAvailableSize = 0;
+l_showfeedback:
+		pTask->m_log.logi(GetResManager().LoadString(IDS_OTFCHECKINGSPACE_STRING));
+
+		if (!pTask->GetRequiredFreeSpace(&ullNeededSize, &ullAvailableSize))
+		{
+			fmt.SetFormat(GetResManager().LoadString(IDS_OTFNOTENOUGHFREESPACE_STRING));
+			fmt.SetParam(_t("%needsize"), ullNeededSize);
+			fmt.SetParam(_t("%availablesize"), ullAvailableSize);
+			pTask->m_log.logw(fmt);
+
+			BOOST_ASSERT(piFeedbackHandler);
+
+			if(pTask->GetClipboardDataSize() > 0)
+			{
+				CString strSrcPath = pTask->GetClipboardData(0)->GetPath();
+				CString strDstPath = pTask->GetDestPath().GetPath();
+				FEEDBACK_NOTENOUGHSPACE feedStruct = { ullNeededSize, (PCTSTR)strSrcPath, (PCTSTR)strDstPath };
+				CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_NotEnoughSpace, &feedStruct);
+
+				// default
+				switch (frResult)
+				{
+				case CFeedbackHandler::eResult_Cancel:
+					{
+						pTask->m_log.logi(GetResManager().LoadString(IDS_OTFFREESPACECANCELREQUEST_STRING));
+						throw new CProcessingException(E_CANCEL, pTask);
+						break;
+					}
+				case CFeedbackHandler::eResult_Retry:
+					pTask->m_log.logi(GetResManager().LoadString(IDS_OTFFREESPACERETRYING_STRING));
+					goto l_showfeedback;
+					break;
+				case CFeedbackHandler::eResult_Skip:
+					pTask->m_log.logi(GetResManager().LoadString(IDS_OTFFREESPACEIGNORE_STRING));
+					break;
+				default:
+					BOOST_ASSERT(FALSE);		// unknown result
+					throw new CProcessingException(E_ERROR, pTask, 0, _t("Unknown feedback result type"));
+					break;
+				}
+			}
+		}
+
+		if (bReadTasksSize)
+		{
+			pTask->UpdateTime();
+			pTask->m_lLastTime=-1;
+
+			CheckForWaitState(pTask);
+
+			pTask->m_lLastTime=(long)time(NULL);
+		}
+
+		// Phase II - copying/moving
+		if (pTask->GetStatus(ST_STEP_MASK) == ST_COPYING)
+		{
+			// decrease processed in ctaskarray - the rest will be done in ProcessFiles
+			pTask->DecreaseProcessedTasksSize(pTask->GetProcessedSize());
+			ProcessFiles(pTask);
+		}
+
+		// deleting data - III phase
+		if (pTask->GetStatus(ST_STEP_MASK) == ST_DELETING)
+			DeleteFiles(pTask);
+
+		// refresh time
+		pTask->UpdateTime();
+
+		// save progress before killed
+		pTask->Store(false);
+
+		// we are ending
+		pTask->DecreaseOperationsPending();
+
+		// play sound
+		piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_OperationFinished, NULL);
+
+		tm=CTime::GetCurrentTime();
+		fmt.SetFormat(GetResManager().LoadString(IDS_OTFTHREADFINISHED_STRING));
+		fmt.SetParam(_t("%year"), tm.GetYear());
+		fmt.SetParam(_t("%month"), tm.GetMonth());
+		fmt.SetParam(_t("%day"), tm.GetDay());
+		fmt.SetParam(_t("%hour"), tm.GetHour());
+		fmt.SetParam(_t("%minute"), tm.GetMinute());
+		fmt.SetParam(_t("%second"), tm.GetSecond());
+		pTask->m_log.logi(fmt);
+
+		// we have been killed - the last operation
+		InterlockedIncrement(pTask->m_plFinished);
+		pTask->CleanupAfterKill();
+		pTask->SetKilledFlag();
+	}
+	catch(CProcessingException* e)
+	{
+		// increment count of beginnings
+		InterlockedIncrement(pTask->m_plFinished);
+
+		// refresh time
+		pTask->UpdateTime();
+
+		// log
+		fmt.SetFormat(GetResManager().LoadString(IDS_OTFCAUGHTEXCEPTIONMAIN_STRING));
+		fmt.SetParam(_t("%errno"), e->m_dwError);
+		fmt.SetParam(_t("%type"), e->m_iType);
+		pTask->m_log.loge(fmt);
+
+		if (e->m_iType == E_ERROR)
+			piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_OperationError, NULL);
+
+		// pause task if requested
+		if(e->m_iType == E_PAUSE)
+			pTask->SetStatus(ST_PAUSED, ST_PAUSED);
+
+		// cleanup changes flags and calls cleanup for a task
+		e->Cleanup();
+		delete e;
+
+		if (pTask->GetStatus(ST_WAITING_MASK) & ST_WAITING)
+			pTask->SetStatus(0, ST_WAITING);
+
+		pTask->DecreaseOperationsPending();
+		pTask->SetContinueFlag(false);
+		pTask->SetForceFlag(false);
+
+		return 0xffffffff;	// almost like -1
+	}
+
+	TRACE("TASK FINISHED - exiting ThrdProc.\n");
+	return 0;
+}
Index: src/ch/task.h
===================================================================
diff -u -r49b67b7417f8b42ce581ebfe604f47df841f763b -r9c71c0a84781c524c0091ee86914d5cc3bbf5190
--- src/ch/task.h	(.../task.h)	(revision 49b67b7417f8b42ce581ebfe604f47df841f763b)
+++ src/ch/task.h	(.../task.h)	(revision 9c71c0a84781c524c0091ee86914d5cc3bbf5190)
@@ -58,10 +58,19 @@
 #define ST_WAITING_MASK		0x00f00000
 #define ST_WAITING			0x00100000
 
+///////////////////////////////////////////////////////////////////////////
+// Exceptions
+
+#define E_KILL_REQUEST		0x00
+#define E_ERROR				0x01
+#define E_CANCEL			0x02
+#define E_PAUSE				0x03
+
 /////////////////////////////////////////////////////////////////////
 // CTask
 
 class CFileInfo;
+class CTask;
 
 struct TASK_CREATE_DATA
 {
@@ -72,8 +81,6 @@
 	LONG *plFinished;
 
 	CCriticalSection* pcs;
-
-	UINT (*pfnTaskProc)(LPVOID pParam);
 };
 
 // structure for gettings status of a task
@@ -116,15 +123,24 @@
 	int		m_nPercent;
 };
 
+struct CUSTOM_COPY_PARAMS
+{
+	CTask* pTask;			// ptr to CTask object on which we do the operation
+
+	CFileInfo* pfiSrcFile;	// CFileInfo - src file
+	CString strDstFile;		// dest path with filename
+
+	CDataBuffer dbBuffer;	// buffer handling
+	bool bOnlyCreate;		// flag from configuration - skips real copying - only create
+	bool bProcessed;		// has the element been processed ? (false if skipped)
+};
+
 class CTask
 {
 public:
 	CTask(chcore::IFeedbackHandler* piFeedbackHandler, const TASK_CREATE_DATA *pCreateData);
 	~CTask();
-public:
 
-	// Attributes
-public:
 	// m_clipboard
 	int		AddClipboardData(CClipboardEntry* pEntry);
 	CClipboardEntry* GetClipboardData(int nIndex);
@@ -244,8 +260,47 @@
 
 	chcore::IFeedbackHandler* GetFeedbackHandler() const { return m_piFeedbackHandler; }
 
-	// Implementation
+	void SetForceFlag(bool bFlag=true);
+	bool GetForceFlag();
+	void SetContinueFlag(bool bFlag=true);
+	bool GetContinueFlag();
+
 protected:
+	static UINT ThrdProc(LPVOID pParam);
+	static void CheckForWaitState(CTask* pTask);
+	static void ProcessFiles(CTask* pTask);
+	static void CustomCopyFile(CUSTOM_COPY_PARAMS* pData);
+	static void DeleteFiles(CTask* pTask);
+	static void RecurseDirectories(CTask* pTask);
+	static bool SetFileDirectoryTime(LPCTSTR lpszName, CFileInfo* pSrcInfo);
+	static bool TimeToFileTime(const COleDateTime& time, LPFILETIME pFileTime);
+	static void ReplaceNoCase(CString& rString, CString strOld, CString strNew);
+
+public:
+	//	CLogFile m_log;
+	icpf::log_file m_log;
+	mutable CCriticalSection m_cs;	// protection for this class
+
+	UINT m_uiResumeInterval;	// works only if the thread is off
+	// time
+	long m_lTimeElapsed;	// store
+	long m_lLastTime;		// not store
+
+	// feedback
+	chcore::IFeedbackHandler* m_piFeedbackHandler;
+	int m_iIdentical;
+	int m_iDestinationLess;
+	int m_iDestinationGreater;
+	int m_iMissingInput;
+	int m_iOutputError;
+	int m_iMoveFile;
+
+	// ptr to count of currently started tasks
+	LONG* m_plFinished;
+	bool m_bForce;		// if the continuation of tasks should be independent of limitation
+	bool m_bContinue;	// used by ClipboardMonitorProc
+
+protected:
 	CClipboardArray m_clipboard;
 	CFileInfoArray m_files;
 	volatile int m_nCurrentIndex;
@@ -290,39 +345,27 @@
 	tstring_t m_strTaskBasePath;	// base path at which the files will be stored
 	bool m_bSaved;		// has the state been saved ('til next modification)
 
-public:
-	UINT m_uiResumeInterval;	// works only if the thread is off
-	// time
-	long m_lTimeElapsed;	// store
-	long m_lLastTime;		// not store
+	CCriticalSection* m_pcs;	// protects *m_pnTasksProcessed & *m_pnTasksAll from external array
+};
 
-	// feedback
-	chcore::IFeedbackHandler* m_piFeedbackHandler;
-	int m_iIdentical;
-	int m_iDestinationLess;
-	int m_iDestinationGreater;
-	int m_iMissingInput;
-	int m_iOutputError;
-	int m_iMoveFile;
+///////////////////////////////////////////////////////////////////////////
+// CProcessingException
 
-	// ptr to count of currently started tasks
-	LONG* m_plFinished;
-	bool m_bForce;		// if the continuation of tasks should be independent of limitation
-	bool m_bContinue;	// used by ClipboardMonitorProc
+class CProcessingException
+{
+public:
+	CProcessingException(int iType, CTask* pTask) { m_iType=iType; m_pTask=pTask; m_dwError=0; };
+	CProcessingException(int iType, CTask* pTask, UINT uiFmtID, DWORD dwError, ...);
+	CProcessingException(int iType, CTask* pTask, DWORD dwError, const tchar_t* pszDesc);
+	void Cleanup();
 
-protected:
-	CCriticalSection* m_pcs;	// protects *m_pnTasksProcessed & *m_pnTasksAll from external array
-
-	UINT (*m_pfnTaskProc)(LPVOID pParam);	// external function that processes this task
+	// Implementation
 public:
-	void SetForceFlag(bool bFlag=true);
-	bool GetForceFlag();
-	void SetContinueFlag(bool bFlag=true);
-	bool GetContinueFlag();
+	int m_iType;	// kill request, error, ...
+	CTask* m_pTask;
 
-	//	CLogFile m_log;
-	icpf::log_file m_log;
-	mutable CCriticalSection m_cs;	// protection for this class
+	CString m_strErrorDesc;
+	DWORD m_dwError;
 };
 
 ///////////////////////////////////////////////////////////////////////////
@@ -334,7 +377,7 @@
 	CTaskArray();
 	~CTaskArray();
 
-	void Create(chcore::IFeedbackHandlerFactory* piFeedbackHandlerFactory, UINT (*pfnTaskProc)(LPVOID pParam));
+	void Create(chcore::IFeedbackHandlerFactory* piFeedbackHandlerFactory);
 
 	CTask* CreateTask();