Index: src/ch/DataBuffer.cpp
===================================================================
diff -u -r5057e08b0cc064972abeb94a488e5f12d9db14a0 -r45cf96558ba334192ef42687d4dac01c46d6ffd8
--- src/ch/DataBuffer.cpp	(.../DataBuffer.cpp)	(revision 5057e08b0cc064972abeb94a488e5f12d9db14a0)
+++ src/ch/DataBuffer.cpp	(.../DataBuffer.cpp)	(revision 45cf96558ba334192ef42687d4dac01c46d6ffd8)
@@ -32,6 +32,23 @@
 			&& m_uiLANSize == bsSizes.m_uiLANSize);
 }
 
+CDataBuffer::CDataBuffer() :
+	m_pBuffer(NULL),
+	m_uiRealSize(0)
+{
+	m_bsSizes.m_uiDefaultSize=0;
+	m_bsSizes.m_uiOneDiskSize=0;
+	m_bsSizes.m_uiTwoDisksSize=0;
+	m_bsSizes.m_uiCDSize=0;
+	m_bsSizes.m_uiLANSize=0;
+	m_bsSizes.m_bOnlyDefault=false;
+}
+
+CDataBuffer::~CDataBuffer()
+{
+	Delete();
+}
+
 const BUFFERSIZES* CDataBuffer::Create(const BUFFERSIZES* pbsSizes)
 {
 	// if trying to set 0-size buffer
@@ -64,33 +81,33 @@
 	}
 	
 	// modify buffer size to the next 64k boundary
-	UINT uiRealSize=ROUNDTODS(uiLargest);
+	UINT uiRealSize = ROUNDTODS(uiLargest);
 	TRACE("Size: %lu, rounded: %lu\n", uiLargest, uiRealSize);
 
-	if (m_uiRealSize == uiRealSize)
+	if(m_uiRealSize == uiRealSize)
 	{
-		// real buffersize doesn't changed
-		m_bsSizes=bsSizes;
-		
+		// real buffersize hasn't changed
+		m_bsSizes = bsSizes;
+
 		return &m_bsSizes;
 	}
 
-	// try to allocate
-	LPVOID pBuffer=VirtualAlloc(NULL, uiRealSize, MEM_COMMIT, PAGE_READWRITE);
-	if (pBuffer == NULL)
+	// try to allocate buffer
+	LPVOID pBuffer = VirtualAlloc(NULL, uiRealSize, MEM_COMMIT, PAGE_READWRITE);
+	if(pBuffer == NULL)
 	{
-		if (m_pBuffer == NULL)
+		if(m_pBuffer == NULL)
 		{
 			// try safe buffesize
-			pBuffer=VirtualAlloc(NULL, DEFAULT_SIZE, MEM_COMMIT, PAGE_READWRITE);
-			if (pBuffer == NULL)
+			pBuffer = VirtualAlloc(NULL, DEFAULT_SIZE, MEM_COMMIT, PAGE_READWRITE);
+			if(pBuffer == NULL)
 				return &m_bsSizes;		// do not change anything
 			
 			// delete old buffer
 			Delete();
 			
 			// store data
-			m_pBuffer=static_cast<unsigned char*>(pBuffer);
+			m_pBuffer = static_cast<unsigned char*>(pBuffer);
 			m_uiRealSize=DEFAULT_SIZE;
 			m_bsSizes.m_bOnlyDefault=bsSizes.m_bOnlyDefault;
 			m_bsSizes.m_uiDefaultSize=DEFAULT_SIZE;
@@ -113,17 +130,17 @@
 		Delete();	// get rid of old buffer
 		
 		// store data
-		m_pBuffer=static_cast<unsigned char*>(pBuffer);
-		m_uiRealSize=uiRealSize;
-		m_bsSizes=bsSizes;
+		m_pBuffer = static_cast<unsigned char*>(pBuffer);
+		m_uiRealSize = uiRealSize;
+		m_bsSizes = bsSizes;
 		
 		return &m_bsSizes;
 	}
 }
 
 void CDataBuffer::Delete()
 {
-	if (m_pBuffer != NULL)
+	if(m_pBuffer != NULL)
 	{
 		VirtualFree(static_cast<LPVOID>(m_pBuffer), 0, MEM_RELEASE);
 		m_pBuffer=NULL;
@@ -135,3 +152,11 @@
 		m_bsSizes.m_uiLANSize=0;
 	}
 }
+
+void CDataBuffer::CutDataFromBuffer(UINT uiCount)
+{
+	if(uiCount >= m_uiRealSize || !m_pBuffer)
+		return;	// nothing to do
+
+	memmove(m_pBuffer, m_pBuffer + uiCount, m_uiRealSize - uiCount);
+}
Index: src/ch/DataBuffer.h
===================================================================
diff -u -r5057e08b0cc064972abeb94a488e5f12d9db14a0 -r45cf96558ba334192ef42687d4dac01c46d6ffd8
--- src/ch/DataBuffer.h	(.../DataBuffer.h)	(revision 5057e08b0cc064972abeb94a488e5f12d9db14a0)
+++ src/ch/DataBuffer.h	(.../DataBuffer.h)	(revision 45cf96558ba334192ef42687d4dac01c46d6ffd8)
@@ -71,8 +71,8 @@
 class CDataBuffer
 {
 public:
-	CDataBuffer() { m_pBuffer=NULL; m_uiRealSize=0; m_bsSizes.m_uiDefaultSize=0; m_bsSizes.m_uiOneDiskSize=0; m_bsSizes.m_uiTwoDisksSize=0; m_bsSizes.m_uiCDSize=0; m_bsSizes.m_uiLANSize=0; m_bsSizes.m_bOnlyDefault=false; };
-	~CDataBuffer() { Delete(); };
+	CDataBuffer();
+	~CDataBuffer();
 
 	const BUFFERSIZES* Create(const BUFFERSIZES* pbsSizes);	// (re)allocates the buffer; if there's an error - restores previous buffer size
 	void Delete();				// deletes buffer
@@ -85,6 +85,9 @@
 	UINT GetLANSize() { return m_bsSizes.m_uiLANSize; };
 	const BUFFERSIZES* GetSizes() { return &m_bsSizes; }; 
 
+	// shifts data from buffer from position uiCount to 0 (effectively cuts uiCount bytes of data at the beginning of buffer)
+	void CutDataFromBuffer(UINT uiCount);
+
 	// operators
 	operator unsigned char*() { return m_pBuffer; };
 
Index: src/ch/FileInfo.cpp
===================================================================
diff -u -r012e8c96dde85616cf4ecbd594afa91517d81a0d -r45cf96558ba334192ef42687d4dac01c46d6ffd8
--- src/ch/FileInfo.cpp	(.../FileInfo.cpp)	(revision 012e8c96dde85616cf4ecbd594afa91517d81a0d)
+++ src/ch/FileInfo.cpp	(.../FileInfo.cpp)	(revision 45cf96558ba334192ef42687d4dac01c46d6ffd8)
@@ -507,14 +507,13 @@
 
 CString CFileInfo::GetFullFilePath() const
 {
-	BOOST_ASSERT(m_pClipboard);
-	if(!m_pClipboard)
-		THROW(_T("Invalid pointer"), 0, 0, 0);
-
 	CString strPath;
 	if(m_stSrcIndex != std::numeric_limits<size_t>::max())
 	{
-		ASSERT(m_pClipboard);
+		BOOST_ASSERT(m_pClipboard);
+		if(!m_pClipboard)
+			THROW(_T("Invalid pointer"), 0, 0, 0);
+
 		strPath += m_pClipboard->GetAt(m_stSrcIndex)->GetPath();
 	}
 	strPath += m_strFilePath;
@@ -595,6 +594,21 @@
 	return ullSize;
 }
 
+int CFileInfoArray::GetBufferIndexAt(size_t stIndex, const CDestPath& rDestPath)
+{
+	boost::shared_lock<boost::shared_mutex> lock(m_lock);
+	if(stIndex >= m_vFiles.size())
+		return 0;
+	else
+	{
+		CFileInfoPtr& spFileInfo = m_vFiles[stIndex];
+		if(!spFileInfo)
+			THROW(_T("Invalid pointer"), 0, 0, 0);
+
+		return spFileInfo->GetBufferIndex(rDestPath);
+	}
+}
+
 unsigned long long CFileInfoArray::CalculatePartialSize(size_t stCount)
 {
 	unsigned long long ullSize = 0;
Index: src/ch/FileInfo.h
===================================================================
diff -u -rb0825410932da4f8c51bf3173aceb7ea758ef544 -r45cf96558ba334192ef42687d4dac01c46d6ffd8
--- src/ch/FileInfo.h	(.../FileInfo.h)	(revision b0825410932da4f8c51bf3173aceb7ea758ef544)
+++ src/ch/FileInfo.h	(.../FileInfo.h)	(revision 45cf96558ba334192ef42687d4dac01c46d6ffd8)
@@ -275,6 +275,9 @@
 	/// Calculates the size of all file info objects inside this object
 	unsigned long long CalculateTotalSize();
 
+	/// Retrieves buffer index for an item at a specified index
+	int GetBufferIndexAt(size_t stIndex, const CDestPath& rDestPath);
+
 	/// Stores infos about elements in the archive
 	template<class Archive>
 	void Store(Archive& ar, unsigned int /*uiVersion*/, bool bOnlyFlags);
Index: src/ch/task.cpp
===================================================================
diff -u -r3ba4fcc537059e952471a77c3cc9893e779bce98 -r45cf96558ba334192ef42687d4dac01c46d6ffd8
--- src/ch/task.cpp	(.../task.cpp)	(revision 3ba4fcc537059e952471a77c3cc9893e779bce98)
+++ src/ch/task.cpp	(.../task.cpp)	(revision 45cf96558ba334192ef42687d4dac01c46d6ffd8)
@@ -380,13 +380,60 @@
 	}
 }
 
+TTaskProgressInfo::TTaskProgressInfo() :
+	m_stCurrentIndex(0),
+	m_ullCurrentFileProcessedSize(0)
+{
+}
+
+TTaskProgressInfo::~TTaskProgressInfo()
+{
+}
+
+void TTaskProgressInfo::SetCurrentIndex(size_t stIndex)
+{
+	boost::unique_lock<boost::shared_mutex> lock(m_lock);
+	m_stCurrentIndex = stIndex;
+	m_ullCurrentFileProcessedSize = 0;
+}
+
+void TTaskProgressInfo::IncreaseCurrentIndex()
+{
+	boost::unique_lock<boost::shared_mutex> lock(m_lock);
+	++m_stCurrentIndex;
+	m_ullCurrentFileProcessedSize = 0;
+}
+
+size_t TTaskProgressInfo::GetCurrentIndex() const
+{
+	boost::shared_lock<boost::shared_mutex> lock(m_lock);
+	return m_stCurrentIndex;
+}
+
+void TTaskProgressInfo::SetCurrentFileProcessedSize(unsigned long long ullSize)
+{
+	boost::unique_lock<boost::shared_mutex> lock(m_lock);
+	m_ullCurrentFileProcessedSize = ullSize;
+}
+
+unsigned long long TTaskProgressInfo::GetCurrentFileProcessedSize() const
+{
+	boost::shared_lock<boost::shared_mutex> lock(m_lock);
+	return m_ullCurrentFileProcessedSize;
+}
+
+void TTaskProgressInfo::IncreaseCurrentFileProcessedSize(unsigned long long ullSizeToAdd)
+{
+	boost::unique_lock<boost::shared_mutex> lock(m_lock);
+	m_ullCurrentFileProcessedSize += ullSizeToAdd;
+}
+
 ////////////////////////////////////////////////////////////////////////////
 // CTask members
 CTask::CTask(chcore::IFeedbackHandler* piFeedbackHandler, size_t stSessionUniqueID) :
 	m_log(),
 	m_piFeedbackHandler(piFeedbackHandler),
 	m_files(m_clipboard),
-	m_stCurrentIndex(0),
 	m_nStatus(ST_NULL_STATUS),
 	m_nPriority(THREAD_PRIORITY_NORMAL),
 	m_bForce(false),
@@ -405,42 +452,42 @@
 
 	_itot((int)time(NULL), m_strUniqueName.GetBufferSetLength(16), 10);
 	m_strUniqueName.ReleaseBuffer();
-	}
+}
 
-	CTask::~CTask()
-	{
-		KillThread();
-		if(m_piFeedbackHandler)
-			m_piFeedbackHandler->Delete();
-	}
+CTask::~CTask()
+{
+	KillThread();
+	if(m_piFeedbackHandler)
+		m_piFeedbackHandler->Delete();
+}
 
-	void CTask::OnRegisterTask(TTasksGlobalStats& rtGlobalStats)
-	{
-		m_localStats.ConnectGlobalStats(rtGlobalStats);
-	}
+void CTask::OnRegisterTask(TTasksGlobalStats& rtGlobalStats)
+{
+	m_localStats.ConnectGlobalStats(rtGlobalStats);
+}
 
-	void CTask::OnUnregisterTask()
-	{
-		m_localStats.DisconnectGlobalStats();
-	}
+void CTask::OnUnregisterTask()
+{
+	m_localStats.DisconnectGlobalStats();
+}
 
-	// m_clipboard
-	void CTask::AddClipboardData(const CClipboardEntryPtr& spEntry)
-	{
-		m_clipboard.Add(spEntry);
-	}
+// m_clipboard
+void CTask::AddClipboardData(const CClipboardEntryPtr& spEntry)
+{
+	m_clipboard.Add(spEntry);
+}
 
-	CClipboardEntryPtr CTask::GetClipboardData(size_t stIndex)
-	{
-		return m_clipboard.GetAt(stIndex);
-	}
+CClipboardEntryPtr CTask::GetClipboardData(size_t stIndex)
+{
+	return m_clipboard.GetAt(stIndex);
+}
 
-	size_t CTask::GetClipboardDataSize()
-	{
-		return m_clipboard.GetSize();
-	}
+size_t CTask::GetClipboardDataSize()
+{
+	return m_clipboard.GetSize();
+}
 
-	int CTask::ReplaceClipboardStrings(CString strOld, CString strNew)
+int CTask::ReplaceClipboardStrings(CString strOld, CString strNew)
 {
 	return m_clipboard.ReplacePathsPrefix(strOld, strNew);
 }
@@ -515,13 +562,9 @@
 
 CFileInfoPtr CTask::FilesGetAtCurrentIndex()
 {
-	size_t stCurrentIndex = 0;
+	boost::shared_lock<boost::shared_mutex> lock(m_lock);
 
-	m_lock.lock_shared();
-	stCurrentIndex = m_stCurrentIndex;
-	m_lock.unlock_shared();
-
-	return m_files.GetAt(m_stCurrentIndex);
+	return m_files.GetAt(m_tTaskProgressInfo.GetCurrentIndex());
 }
 
 void CTask::FilesRemoveAll()
@@ -534,25 +577,6 @@
 	return m_files.GetSize();
 }
 
-// m_stCurrentIndex
-void CTask::IncreaseCurrentIndex()
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	++m_stCurrentIndex;
-}
-
-size_t CTask::GetCurrentIndex()
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_stCurrentIndex;
-}
-
-void CTask::SetCurrentIndex(size_t stIndex)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_stCurrentIndex = stIndex;
-}
-
 // m_strDestPath - adds '\\'
 void CTask::SetDestPath(LPCTSTR lpszPath)
 {
@@ -603,15 +627,7 @@
 
 int CTask::GetCurrentBufferIndex()
 {
-	int rv = 0;
-
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-
-	size_t stSize = m_files.GetSize();
-	if(stSize > 0 && m_stCurrentIndex != std::numeric_limits<size_t>::max())
-		rv = m_bsSizes.m_bOnlyDefault ? 0 : m_files.GetAt((m_stCurrentIndex < stSize) ? m_stCurrentIndex : 0)->GetBufferIndex(m_dpDestPath);
-
-	return rv;
+	return m_files.GetBufferIndexAt(m_tTaskProgressInfo.GetCurrentIndex(),m_dpDestPath);
 }
 
 // m_pThread
@@ -651,7 +667,7 @@
 
 void CTask::CalculateProcessedSizeNL()
 {
-	m_localStats.SetProcessedSize(m_files.CalculatePartialSize(m_stCurrentIndex));
+	m_localStats.SetProcessedSize(m_files.CalculatePartialSize(m_tTaskProgressInfo.GetCurrentIndex()));
 }
 
 // m_strUniqueName
@@ -683,11 +699,9 @@
 	}
 	else
 	{
-		size_t stData = 0;
 		UINT uiData = 0;
 
-		ar >> stData;
-		m_stCurrentIndex = stData;
+		ar >> m_tTaskProgressInfo;
 
 		CalculateProcessedSizeNL();
 
@@ -747,8 +761,8 @@
 	}
 	else
 	{
-		size_t stCurrentIndex = m_stCurrentIndex;
-		ar << stCurrentIndex;
+		ar << m_tTaskProgressInfo;
+
 		UINT uiStatus = (m_nStatus & ST_WRITE_MASK);
 		ar << uiStatus;
 
@@ -813,7 +827,8 @@
 	SetStatus(0, ST_ERROR);
 	SetStatus(ST_NULL_STATUS, ST_STEP_MASK);
 	m_localStats.SetTimeElapsed(0);
-	SetCurrentIndex(0);
+	m_tTaskProgressInfo.SetCurrentIndex(0);
+
 	BeginProcessing();
 }
 
@@ -842,8 +857,10 @@
 void CTask::GetMiniSnapshot(TASK_MINI_DISPLAY_DATA *pData)
 {
 	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	if(m_stCurrentIndex >= 0 && m_stCurrentIndex < m_files.GetSize())
-		pData->m_strPath = m_files.GetAt(m_stCurrentIndex)->GetFileName();
+	size_t stCurrentIndex = m_tTaskProgressInfo.GetCurrentIndex();
+
+	if(stCurrentIndex < m_files.GetSize())
+		pData->m_strPath = m_files.GetAt(stCurrentIndex)->GetFileName();
 	else
 	{
 		if(m_files.GetSize() > 0)
@@ -867,10 +884,11 @@
 {
 	boost::unique_lock<boost::shared_mutex> lock(m_lock);
 
-	if(m_stCurrentIndex >= 0 && m_stCurrentIndex < m_files.GetSize())
+	size_t stCurrentIndex = m_tTaskProgressInfo.GetCurrentIndex();
+	if(stCurrentIndex < m_files.GetSize())
 	{
-		pData->m_strFullFilePath = m_files.GetAt(m_stCurrentIndex)->GetFullFilePath();
-		pData->m_strFileName = m_files.GetAt(m_stCurrentIndex)->GetFileName();
+		pData->m_strFullFilePath = m_files.GetAt(stCurrentIndex)->GetFullFilePath();
+		pData->m_strFileName = m_files.GetAt(stCurrentIndex)->GetFileName();
 	}
 	else
 	{
@@ -899,14 +917,14 @@
 	pData->m_pdpDestPath=&m_dpDestPath;
 	pData->m_pafFilters=&m_afFilters;
 	pData->m_uiStatus=m_nStatus;
-	pData->m_stIndex=m_stCurrentIndex;
+	pData->m_stIndex = stCurrentIndex;
 	pData->m_ullProcessedSize = m_localStats.GetProcessedSize();
 	pData->m_stSize=m_files.GetSize();
 	pData->m_ullSizeAll = m_localStats.GetTotalSize();
 	pData->m_pstrUniqueName=&m_strUniqueName;
 
-	if(m_files.GetSize() > 0 && m_stCurrentIndex != std::numeric_limits<size_t>::max())
-		pData->m_iCurrentBufferIndex=m_bsSizes.m_bOnlyDefault ? 0 : m_files.GetAt((m_stCurrentIndex < m_files.GetSize()) ? m_stCurrentIndex : 0)->GetBufferIndex(m_dpDestPath);
+	if(m_files.GetSize() > 0)
+		pData->m_iCurrentBufferIndex=m_bsSizes.m_bOnlyDefault ? 0 : m_files.GetAt((stCurrentIndex < m_files.GetSize()) ? stCurrentIndex : 0)->GetBufferIndex(m_dpDestPath);
 	else
 		pData->m_iCurrentBufferIndex=0;
 
@@ -1084,22 +1102,6 @@
 	return bResult != 0;
 }
 
-// m_stCurrentIndex
-void CTask::IncreaseCurrentIndexNL()
-{
-	++m_stCurrentIndex;
-}
-
-size_t CTask::GetCurrentIndexNL()
-{
-	return m_stCurrentIndex;
-}
-
-void CTask::SetCurrentIndexNL(size_t stIndex)
-{
-	m_stCurrentIndex = stIndex;
-}
-
 // m_strDestPath - adds '\\'
 void CTask::SetDestPathNL(LPCTSTR lpszPath)
 {
@@ -1141,17 +1143,6 @@
 	return &m_bsSizes;
 }
 
-int CTask::GetCurrentBufferIndexNL()
-{
-	int rv = 0;
-
-	size_t stSize = m_files.GetSize();
-	if(stSize > 0 && m_stCurrentIndex != std::numeric_limits<size_t>::max())
-		rv = m_bsSizes.m_bOnlyDefault ? 0 : m_files.GetAt((m_stCurrentIndex < stSize) ? m_stCurrentIndex : 0)->GetBufferIndex(m_dpDestPath);
-
-	return rv;
-}
-
 // m_pThread
 // m_nPriority
 int CTask::GetPriorityNL()
@@ -1380,11 +1371,11 @@
 	ictranslate::CFormat fmt;
 
 	// index points to 0 or next item to process
-	size_t stIndex = GetCurrentIndex();
+	size_t stIndex = m_tTaskProgressInfo.GetCurrentIndex();
 	while(stIndex < FilesGetSize())
 	{
 		// set index in pTask to currently deleted element
-		SetCurrentIndex(stIndex);
+		m_tTaskProgressInfo.SetCurrentIndex(stIndex);
 
 		// check for kill flag
 		if(m_workerThread.KillRequested())
@@ -1456,8 +1447,8 @@
 	// change status to finished
 	SetStatus(ST_FINISHED, ST_STEP_MASK);
 
-	// add 1 to current index - looks better
-	IncreaseCurrentIndex();
+	// add 1 to current index
+	m_tTaskProgressInfo.IncreaseCurrentIndex();
 
 	// log
 	m_log.logi(_T("Deleting files finished"));
@@ -1528,20 +1519,138 @@
 	return hFile;
 }
 
-HANDLE CTask::OpenDestinationFileFB(const CString& strDstFilePath, bool bNoBuffering)
+HANDLE CTask::OpenDestinationFileFB(const CString& strDstFilePath, bool bNoBuffering, const CFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated)
 {
 	bool bRetry = false;
-	HANDLE hFile = INVALID_HANDLE_VALUE;
+	TAutoFileHandle hFile;
 
+	ullSeekTo = 0;
+	bFreshlyCreated = true;
+
 	do
 	{
 		bRetry = false;
 
-		hFile = CreateFile(strDstFilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
+		hFile = CreateFile(strDstFilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
 		if(hFile == INVALID_HANDLE_VALUE)
 		{
 			DWORD dwLastError = GetLastError();
+			if(dwLastError == ERROR_FILE_EXISTS)
+			{
+				bFreshlyCreated = false;
 
+				// pass it to the specialized method
+				hFile = OpenExistingDestinationFileFB(strDstFilePath, bNoBuffering);
+				if(hFile == INVALID_HANDLE_VALUE)
+					return hFile;
+
+				// read info about the existing destination file,
+				// NOTE: it is not known which one would be faster - reading file parameters
+				//       by using spDstFileInfo->Create() (which uses FindFirstFile()) or by
+				//       reading parameters using opened handle; need to be tested in the future
+				CFileInfoPtr spDstFileInfo(boost::make_shared<CFileInfo>());
+				if(!spDstFileInfo->Create(strDstFilePath, std::numeric_limits<size_t>::max()))
+					THROW(_T("Cannot get information about file which has already been opened!"), 0, GetLastError(), 0);
+
+				// src and dst files are the same
+				FEEDBACK_ALREADYEXISTS feedStruct = { spSrcFileInfo, spDstFileInfo };
+				CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileAlreadyExists, &feedStruct);
+				// check for dialog result
+				switch(frResult)
+				{
+				case CFeedbackHandler::eResult_Overwrite:
+					ullSeekTo = 0;
+					break;
+
+				case CFeedbackHandler::eResult_CopyRest:
+					ullSeekTo = spDstFileInfo->GetLength64();
+					break;
+
+				case CFeedbackHandler::eResult_Skip:
+					return INVALID_HANDLE_VALUE;
+
+				case CFeedbackHandler::eResult_Cancel:
+					{
+						// log
+						ictranslate::CFormat fmt;
+						fmt.SetFormat(_T("Cancel request while checking result of dialog before opening source file %path (CustomCopyFile)"));
+						fmt.SetParam(_t("%path"), strDstFilePath);
+						m_log.logi(fmt);
+
+						throw new CProcessingException(E_CANCEL);
+					}
+				case CFeedbackHandler::eResult_Pause:
+					throw new CProcessingException(E_PAUSE);
+
+				default:
+					BOOST_ASSERT(FALSE);		// unknown result
+					THROW(_T("Unhandled case"), 0, 0, 0);
+				}
+			}
+			else
+			{
+				FEEDBACK_FILEERROR feedStruct = { (PCTSTR)strDstFilePath, NULL, eCreateError, dwLastError };
+				CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
+				switch (frResult)
+				{
+				case CFeedbackHandler::eResult_Retry:
+					{
+						// log
+						ictranslate::CFormat fmt;
+						fmt.SetFormat(_T("Retrying [error %errno] to open destination file %path (CustomCopyFile)"));
+						fmt.SetParam(_t("%errno"), dwLastError);
+						fmt.SetParam(_t("%path"), strDstFilePath);
+						m_log.loge(fmt);
+
+						bRetry = true;
+
+						break;
+					}
+				case CFeedbackHandler::eResult_Cancel:
+					{
+						// log
+						ictranslate::CFormat fmt;
+
+						fmt.SetFormat(_T("Cancel request [error %errno] while opening destination file %path (CustomCopyFile)"));
+						fmt.SetParam(_t("%errno"), dwLastError);
+						fmt.SetParam(_t("%path"), strDstFilePath);
+						m_log.loge(fmt);
+
+						throw new CProcessingException(E_CANCEL);
+					}
+
+				case CFeedbackHandler::eResult_Skip:
+					break;		// will return invalid handle value
+
+				case CFeedbackHandler::eResult_Pause:
+					throw new CProcessingException(E_PAUSE);
+
+				default:
+					BOOST_ASSERT(FALSE);		// unknown result
+					THROW(_T("Unhandled case"), 0, 0, 0);
+				}
+			}
+		}
+	}
+	while(bRetry);
+
+	return hFile.Detach();
+
+}
+
+HANDLE CTask::OpenExistingDestinationFileFB(const CString& strDstFilePath, bool bNoBuffering)
+{
+	bool bRetry = false;
+	HANDLE hFile = INVALID_HANDLE_VALUE;
+
+	do
+	{
+		bRetry = false;
+
+		hFile = CreateFile(strDstFilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH : 0), NULL);
+		if(hFile == INVALID_HANDLE_VALUE)
+		{
+			DWORD dwLastError = GetLastError();
 			FEEDBACK_FILEERROR feedStruct = { (PCTSTR)strDstFilePath, NULL, eCreateError, dwLastError };
 			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct);
 			switch (frResult)
@@ -1764,11 +1873,8 @@
 				throw new CProcessingException(E_PAUSE);
 
 			case CFeedbackHandler::eResult_Skip:
-/*
-				m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64());
-				pData->bProcessed = false;
-*/
 				return false;
+
 			default:
 				BOOST_ASSERT(FALSE);		// unknown result
 				THROW(_T("Unhandled case"), 0, 0, 0);
@@ -1786,603 +1892,235 @@
 					hDst = INVALID_HANDLE_VALUE;
 	ictranslate::CFormat fmt;
 
-	try
+	// calculate if we want to disable buffering for file transfer
+	// NOTE: we are using here the file size read when scanning directories for files; it might be
+	//       outdated at this point, but at present we don't want to re-read file size since it
+	//       will cost additional disk access
+	bool bNoBuffer = (GetConfig().get_bool(PP_BFUSENOBUFFERING) && pData->spSrcFile->GetLength64() >= (unsigned long long)GetConfig().get_signed_num(PP_BFBOUNDARYLIMIT));
+
+	// first open the source file and handle any failures
+	hSrc = OpenSourceFileFB(pData->spSrcFile, bNoBuffer);
+	if(hSrc == INVALID_HANDLE_VALUE)
 	{
-		// do we copy rest or recopy ?
-		bool bCopyRest = false;
+		// invalid handle = operation skipped by user
+		m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskProgressInfo.GetCurrentFileProcessedSize());
+		pData->bProcessed = false;
+		return;
+	}
 
-		// Data regarding dest file
-		CFileInfoPtr spDestFileInfo(boost::make_shared<CFileInfo>());
-		bool bExist = spDestFileInfo->Create(pData->strDstFile, std::numeric_limits<size_t>::max());
+	// 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(!GetConfig().get_bool(PP_CMPROTECTROFILES))
+		SetFileAttributes(pData->strDstFile, FILE_ATTRIBUTE_NORMAL);
 
-		// if dest file size >0 - we can do something more than usual
-		if(bExist)
-		{
-			// src and dst files are the same
-			FEEDBACK_ALREADYEXISTS feedStruct = { pData->spSrcFile, spDestFileInfo };
-			CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_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:
-				{
-					m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64());
-					pData->bProcessed = false;
-					return;
-				}
-			case CFeedbackHandler::eResult_Cancel:
-				{
-					// log
-					fmt.SetFormat(_T("Cancel request while checking result of dialog before opening source file %path (CustomCopyFile)"));
-					fmt.SetParam(_t("%path"), pData->spSrcFile->GetFullFilePath());
-					m_log.logi(fmt);
+	// open destination file, handle the failures and possibly existence of the destination file
+	unsigned long long ullSeekTo = 0;
+	bool bDstFileFreshlyCreated = false;
 
-					throw new CProcessingException(E_CANCEL);
-				}
-			case CFeedbackHandler::eResult_Pause:
-				throw new CProcessingException(E_PAUSE);
-			default:
-				BOOST_ASSERT(FALSE);		// unknown result
-				THROW(_T("Unhandled case"), 0, 0, 0);
-			}
-		}// 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->spSrcFile->GetLength64() >= (unsigned long long)GetConfig().get_signed_num(PP_BFBOUNDARYLIMIT));
-
-		// refresh data about file
-		if(!bFirstPass)
-			bExist = spDestFileInfo->Create(pData->strDstFile, std::numeric_limits<size_t>::max());
-
-		// open src
-		hSrc = OpenSourceFileFB(pData->spSrcFile, bNoBuffer);
-		if(hSrc == INVALID_HANDLE_VALUE)
+	if(m_tTaskProgressInfo.GetCurrentFileProcessedSize() == 0)
+	{
+		// open destination file for case, when we start operation on this file (i.e. it is not resume of the
+		// old operation)
+		hDst = OpenDestinationFileFB(pData->strDstFile, bNoBuffer, pData->spSrcFile, ullSeekTo, bDstFileFreshlyCreated);
+		if(hDst == INVALID_HANDLE_VALUE)
 		{
-			// invalid handle = operation skipped by user
-			m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64());
+			m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskProgressInfo.GetCurrentFileProcessedSize());
 			pData->bProcessed = false;
 			return;
 		}
-
-		// open dest
-		hDst = OpenDestinationFileFB(pData->strDstFile, bNoBuffer);
+	}
+	else
+	{
+		// we are resuming previous operation
+		hDst = OpenExistingDestinationFileFB(pData->strDstFile, bNoBuffer);
 		if(hDst == INVALID_HANDLE_VALUE)
 		{
-			m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64());
+			m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskProgressInfo.GetCurrentFileProcessedSize());
 			pData->bProcessed = false;
-
+			return;
 		}
 
-		// seeking
-		if(!pData->bOnlyCreate)
+		ullSeekTo = m_tTaskProgressInfo.GetCurrentFileProcessedSize();
+	}
+
+	if(!pData->bOnlyCreate)
+	{
+		// seek to the position where copying will start
+		if(ullSeekTo != 0)		// src and dst files exists, requested resume at the specified index
 		{
-			if(bCopyRest)	// if copy rest
-			{
-				if(!bFirstPass || (bExist && spDestFileInfo->GetLength64() > 0))
-				{
-					// try to move file pointers to the end
-					ULONGLONG ullMove = (bNoBuffer ? ROUNDDOWN(spDestFileInfo->GetLength64(), MAXSECTORSIZE) : spDestFileInfo->GetLength64());
+			// try to move file pointers to the end
+			ULONGLONG ullMove = (bNoBuffer ? ROUNDDOWN(ullSeekTo, MAXSECTORSIZE) : ullSeekTo);
 
-					if(!SetFilePointerFB(hSrc, ullMove, pData->spSrcFile->GetFullFilePath()) || !SetFilePointerFB(hDst, ullMove, pData->strDstFile))
-					{
-						// with either first or second seek we got 'skip' answer...
-						m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64());
-						pData->bProcessed = false;
-						return;
-					}
-					else if(bFirstPass)
-						m_localStats.IncreaseProcessedSize(ullMove);
-				}
-			}
-			else
+			if(!SetFilePointerFB(hSrc, ullMove, pData->spSrcFile->GetFullFilePath()) || !SetFilePointerFB(hDst, ullMove, pData->strDstFile))
 			{
-				if(!SetEndOfFileFB(hDst, pData->strDstFile))
-				{
-					pData->bProcessed = false;
-					return;
-				}
+				// with either first or second seek we got 'skip' answer...
+				m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskProgressInfo.GetCurrentFileProcessedSize());
+				pData->bProcessed = false;
+				return;
 			}
 
-			// copying
-			unsigned long ulToRead = 0, ulRead = 0, ulWritten = 0;
-			int iBufferIndex = 0;
-			do
-			{
-				// kill flag checks
-				if(m_workerThread.KillRequested())
-				{
-					// log
-					fmt.SetFormat(_T("Kill request while main copying file %srcpath -> %dstpath"));
-					fmt.SetParam(_t("%srcpath"), pData->spSrcFile->GetFullFilePath());
-					fmt.SetParam(_t("%dstpath"), pData->strDstFile);
-					m_log.logi(fmt);
-					throw new CProcessingException(E_KILL_REQUEST);
-				}
-
-				// recreate buffer if needed
-				if(!(*pData->dbBuffer.GetSizes() == *GetBufferSizes()))
-				{
-					// log
-					const BUFFERSIZES *pbs1=pData->dbBuffer.GetSizes(), *pbs2=GetBufferSizes();
-
-					fmt.SetFormat(_T("Changing buffer size from [Def:%defsize, One:%onesize, Two:%twosize, CD:%cdsize, LAN:%lansize] to [Def:%defsize2, One:%onesize2, Two:%twosize2, CD:%cdsize2, LAN:%lansize2] wile copying %srcfile -> %dstfile (CustomCopyFile)"));
-
-					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->spSrcFile->GetFullFilePath());
-					fmt.SetParam(_t("%dstfile"), pData->strDstFile);
-
-					m_log.logi(fmt);
-					SetBufferSizes(pData->dbBuffer.Create(GetBufferSizes()));
-				}
-
-				// establish count of data to read
-				if(GetBufferSizes()->m_bOnlyDefault)
-					iBufferIndex = BI_DEFAULT;
-				else
-					iBufferIndex = pData->spSrcFile->GetBufferIndex(m_dpDestPath);
-
-				ulToRead=bNoBuffer ? ROUNDUP(pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex], MAXSECTORSIZE) : pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex];
-
-				// read
-				if(!ReadFileFB(hSrc, pData->dbBuffer, ulToRead, ulRead, pData->spSrcFile->GetFullFilePath()))
-				{
-					m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64());
-					pData->bProcessed = false;
-					return;
-				}
-
-				// change count of stored data
-				if(bNoBuffer && (ROUNDUP(ulRead, MAXSECTORSIZE)) != ulRead)
-				{
-					// we need to copy rest so do the second pass
-					// close files
-					hSrc.Close();
-					hDst.Close();
-
-					// second pass
-					bFirstPass=false;
-					bCopyRest=true;		// need to copy rest
-
-					goto l_start;
-				}
-
-				// write
-				if(!WriteFileFB(hDst, pData->dbBuffer, ulRead, ulWritten, pData->strDstFile))
-				{
-					m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64());
-					pData->bProcessed = false;
-					return;
-				}
-
-				// increase count of processed data
-				m_localStats.IncreaseProcessedSize(ulRead);
-			}
-			while(ulRead != 0);
+			m_tTaskProgressInfo.IncreaseCurrentFileProcessedSize(ullMove);
+			m_localStats.IncreaseProcessedSize(ullMove);
 		}
-		else
-		{
-			// we don't copy contents, but need to increase processed size
-			m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64());
-		}
 
-		// close files
-		hSrc.Close();
-		hDst.Close();
-
-		pData->bProcessed = true;
-	}
-	catch(...)
-	{
-		// close handles
-		hSrc.Close();
-		hDst.Close();
-
-		throw;
-	}
-}
-/*
-
-void CTask::CustomCopyFile2(CUSTOM_COPY_PARAMS* / *pData* /)
-{
-	// 1. DetermineStartupData:
-	bool bNoBuffering = false;	// TODO: read from config file
-
-	// additional variables
-	bool bRetry = false;
-
-	// 2. Open source file
-	HANDLE hFile = INVALID_HANDLE_VALUE;
-	do
-	{
-		bRetry = false;
-
-		hFile = CreateFile(_T("source_path"), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, bNoBuffering ? FILE_FLAG_NO_BUFFERING : 0, NULL);
-		if(hFile == INVALID_HANDLE_VALUE)
+		// if the destination file already exists - truncate it to the current file position
+		if(!bDstFileFreshlyCreated)
 		{
-			int iResponse = 0;	// Ask user what to do
-			switch(iResponse)
+			// if destination file was opened (as opposed to newly created)
+			if(!SetEndOfFileFB(hDst, pData->strDstFile))
 			{
-			case 0://eSkip:
+				pData->bProcessed = false;
 				return;
-				break;
-			case 1://eRetry:
-				bRetry = true;
-				break;
-			case 2://eCancel:
-				break;
-			case 3: //ePause:
-				break;
-			default:
-				throw;
 			}
 		}
-	}
-	while(bRetry);
 
-	// 3. Open destination file - a more complex part
-	do 
-	{
-		bRetry = false;
+		// copying
+		unsigned long ulToRead = 0;
+		unsigned long ulRead = 0;
+		unsigned long ulWritten = 0;
+		int iBufferIndex = 0;
 
-		hFile = CreateFile(_T("destination_path"), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, bNoBuffering ? FILE_FLAG_NO_BUFFERING : 0, NULL);
-		if(hFile == INVALID_HANDLE_VALUE)
+		do
 		{
-			// creating new destination file have failed - either file exists or some other problem occurred
-			DWORD dwLastError = GetLastError();
-			if(dwLastError == ERROR_FILE_EXISTS)
+			// kill flag checks
+			if(m_workerThread.KillRequested())
 			{
-				// destination file already exists - try to open existing file
-				do
-				{
-					hFile = CreateFile(_T("destination_path"), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, bNoBuffering ? FILE_FLAG_NO_BUFFERING : 0, NULL);
-					if(hFile == INVALID_HANDLE_VALUE)
-					{
-						// opening existing destination file failed...
-						dwLastError = GetLastError();
-						if(dwLastError == ERROR_ACCESS_DENIED)
-						{
-							// access to the file was denied - is it read only?
-							// ask user what to do (reset read-only attr, skip, pause, cancel, retry)
-						}
-						else
-						{
-							// some other error occurred when trying to open existing destination file
-							// ask user what todo
-						}
-					}
-					else
-					{
-						// existing destination file was successfully opened - gather information about it
-						// and ask user if he want to overwrite/append/skip/...
-					}
-				}
-				while(bRetry);
+				// log
+				fmt.SetFormat(_T("Kill request while main copying file %srcpath -> %dstpath"));
+				fmt.SetParam(_t("%srcpath"), pData->spSrcFile->GetFullFilePath());
+				fmt.SetParam(_t("%dstpath"), pData->strDstFile);
+				m_log.logi(fmt);
+				throw new CProcessingException(E_KILL_REQUEST);
 			}
-			else
+
+			// recreate buffer if needed
+			if(!(*pData->dbBuffer.GetSizes() == *GetBufferSizes()))
 			{
-				// there is other reason for file creation failure
-			}
-		}
-	}
-	while(bRetry);
-			
-			/ *
-			
-			
-			
-			switch ERROR
-				{
-					* File already exists:
-					{
-						loop
-						{
-							ReOpenDestinationFile (OPEN_EXISTING, NoBuffering ? NO_BUFFER : NORMAL)
-								if FAILED
-								{
-									switch ERROR
-									{
-										* Access denied =
-										{
-											GetFileAttributes
-											RESPONSE = Ask user
-											switch RESPONSE
-											{
-												* Skip / Retry / Cancel / Pause =
-													Standard
+				// log
+				const BUFFERSIZES* pbs1 = pData->dbBuffer.GetSizes();
+				const BUFFERSIZES* pbs2 = GetBufferSizes();
 
-													????????????????????????
-													- problem with read only -> Delete ReadOnly attr
-													- standard options - skip/retry/cancel/pause
-													- rename option
-													- 
-													????????????????????????
-											}
-										}
+				fmt.SetFormat(_T("Changing buffer size from [Def:%defsize, One:%onesize, Two:%twosize, CD:%cdsize, LAN:%lansize] to [Def:%defsize2, One:%onesize2, Two:%twosize2, CD:%cdsize2, LAN:%lansize2] wile copying %srcfile -> %dstfile (CustomCopyFile)"));
 
-										* Other errors =
-										{
+				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->spSrcFile->GetFullFilePath());
+				fmt.SetParam(_t("%dstfile"), pData->strDstFile);
 
-										}
-									}
-								else if SUCCEEDED
-								{
-									// append/overwrite?
-									// skip/cancel/pause (no retry?)
-								}
-								}
-								while RETRY
+				m_log.logi(fmt);
+				SetBufferSizes(pData->dbBuffer.Create(GetBufferSizes()));
+			}
 
-									RESPONSE = Ask user
-									switch RESPONSE
-								{
-									* Skip / Retry / Cancel / Pause =
-										Standard
+			// establish count of data to read
+			if(GetBufferSizes()->m_bOnlyDefault)
+				iBufferIndex = BI_DEFAULT;
+			else
+				iBufferIndex = pData->spSrcFile->GetBufferIndex(m_dpDestPath);
 
-										* Replace =
-									{
-										loop
-										{
-											ReOpenDestinationFile (OPEN_EXISTING, NoBuffering ? NO_BUFFER : NORMAL)
-												if FAILED
-												{
+			ulToRead = bNoBuffer ? ROUNDUP(pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex], MAXSECTORSIZE) : pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex];
 
-													RESPONSE = Ask user
-														switch RESPONSE
-													{
-														* Skip / Retry / Cancel / Pause =
-															Standard
+			// read data from file to buffer
+			if(!ReadFileFB(hSrc, pData->dbBuffer, ulToRead, ulRead, pData->spSrcFile->GetFullFilePath()))
+			{
+				m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskProgressInfo.GetCurrentFileProcessedSize());
+				pData->bProcessed = false;
+				return;
+			}
 
+			if(ulRead > 0)
+			{
+				// handle not aligned part at the end of file when no buffering is enabled
+				if(bNoBuffer && ulToRead != ulRead)
+				{
+					// count of data read from the file is less than requested - we're at the end of source file
+					// and this is the operation with system buffering turned off
 
-															????????????????????????
-															- problem with read only -> Delete ReadOnly attr
-															- standard options - skip/retry/cancel/pause
-															- rename option
-															- 
-															????????????????????????
-													}
-												}
-										}
-										while RETRY
+					// write as much as possible to the destination file with no buffering
+					// NOTE: as an alternative, we could write more data to the destination file and then truncate the file
+					unsigned long ulDataToWrite = ROUNDDOWN(ulRead, MAXSECTORSIZE);
+					if(ulDataToWrite > 0)
+					{
+						if(!WriteFileFB(hDst, pData->dbBuffer, ulDataToWrite, ulWritten, pData->strDstFile))
+						{
+							m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskProgressInfo.GetCurrentFileProcessedSize());
+							pData->bProcessed = false;
+							return;
+						}
 
-											loop
-										{
-											SetEndOfFile at current file position (0)
-												if FAILED
-												{
-													* Skip =
-														exit proc -> continue with next src file
-														* Retry =
-														RETRY LOOP
-														* Cancel =
-														stop processing completely with cancelled status
-														* Pause =
-														stop processing completely with paused status
-												}
-										}
-										while RETRY
-									}
+						// increase count of processed data
+						m_tTaskProgressInfo.IncreaseCurrentFileProcessedSize(ulWritten);
+						m_localStats.IncreaseProcessedSize(ulWritten);
 
-									* Append =
-									{
-										loop
-										{
-											ReOpen dst file (OPEN_EXISTING, NoBuffering ? NO_BUFFER : NORMAL)
-												if FAILED
-												{
-													RESPONSE = Ask user
-														switch RESPONSE
-													{
-														????????????????????????
-													}
-												}
-										}
-										while RETRY
+						// calculate count of bytes left to be written
+						ulRead -= ulWritten;
 
-											loop
-										{
-											SeekToEnd (possibly round down when NoBuffering)
-												if FAILED
-												{
-													* Skip =
-														exit proc -> continue with next src file
-														* Retry =
-														RETRY LOOP
-														* Cancel =
-														stop processing completely with cancelled status
-														* Pause =
-														stop processing completely with paused status
-												}
-										}
-										while RETRY
+						// now remove part of data from buffer (ulWritten bytes)
+						pData->dbBuffer.CutDataFromBuffer(ulWritten);
+					}
 
-											loop
-										{
-											SeekToPosition for source file opened at pt 1 to position at which dst file has been set
-												if FAILED
-												{
-													* Skip =
-														exit proc -> continue with next src file
-														* Retry =
-														RETRY LOOP
-														* Cancel =
-														stop processing completely with cancelled status
-														* Pause =
-														stop processing completely with paused status
-												}
-										}
-										while RETRY
-									}
-									* Rename =
-									{
-										Store new filename + goto 2
-									}
-								}
+					// close and re-open the destination file with buffering option for append
+					hDst.Close();
+
+					// are there any more data to be written?
+					if(ulRead != 0)
+					{
+						// re-open the destination file, this time with standard buffering to allow writing not aligned part of file data
+						hDst = OpenExistingDestinationFileFB(pData->strDstFile, false);
+						if(hDst == INVALID_HANDLE_VALUE)
+						{
+							m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskProgressInfo.GetCurrentFileProcessedSize());
+							pData->bProcessed = false;
+							return;
 						}
 
-						* Other problems:
+						// move file pointer to the end of destination file
+						if(!SetFilePointerFB(hDst, m_tTaskProgressInfo.GetCurrentFileProcessedSize(), pData->strDstFile))
 						{
-							- Skip
-								- Retry
-								- Cancel
-								- Pause
-								- Rename =
-								Store new filename + goto 2
+							// with either first or second seek we got 'skip' answer...
+							m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskProgressInfo.GetCurrentFileProcessedSize());
+							pData->bProcessed = false;
+							return;
 						}
 					}
 				}
-			}
-			while RETRY
-	}
-	while(bRetry);
 
+				// write
+				if(ulRead != 0)
+				{
+					if(!WriteFileFB(hDst, pData->dbBuffer, ulRead, ulWritten, pData->strDstFile))
+					{
+						m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskProgressInfo.GetCurrentFileProcessedSize());
+						pData->bProcessed = false;
+						return;
+					}
 
-				3. Copy contents of source file to destination file
-				- loop:
-			- Read xxx bytes from source file (take NoBuffer requirements into consideration)
-				- If bytes read are equal to those requested:
-			- write bytes to destination filename
-				- else
-				- 
-
-
-
-
-				//////////////////////////////////////
-				Standard options when asking user for feedback:
-			* Skip =
-				exit proc -> continue with next src file
-				* Retry =
-				RETRY LOOP
-				* Cancel =
-				stop processing completely with cancelled status
-				* Pause =
-				stop processing completely with paused status
-* /
-}
-*/
-/*
-
-HANDLE CTask::OpenSourceFile(const CString& strPath, bool bNoBuffering/ *, FeedbackSettings* /)
-{
-	bool bRetry = false;
-	HANDLE hFile = INVALID_HANDLE_VALUE;
-	do
-	{
-		bRetry = false;
-
-		hFile = CreateFile(_T("source_path"), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, bNoBuffering ? FILE_FLAG_NO_BUFFERING : 0, NULL);
-		if(hFile == INVALID_HANDLE_VALUE)
-		{
-			int iResponse = 0;	// Ask user what to do
-			switch(iResponse)
-			{
-			case 0://eSkip:
-				return;
-				break;
-			case 1://eRetry:
-				bRetry = true;
-				break;
-			case 2://eCancel:
-				break;
-			case 3: //ePause:
-				break;
-			default:
-				throw;
+					// increase count of processed data
+					m_tTaskProgressInfo.IncreaseCurrentFileProcessedSize(ulRead);
+					m_localStats.IncreaseProcessedSize(ulRead);
+				}
 			}
 		}
+		while(ulRead != 0);
 	}
-	while(bRetry);
-
-	return hFile;
-}
-
-HANDLE CTask::CreateNewDestinationFile(const CString& strPath, bool bNoBuffering/ *, FeedbackSettings* /)
-{
-	bool bRetry = false;
-	HANDLE hFile = INVALID_HANDLE_VALUE;
-	do 
+	else
 	{
-		bRetry = false;
-
-		hFile = CreateFile(_T("destination_path"), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, bNoBuffering ? FILE_FLAG_NO_BUFFERING : 0, NULL);
-		if(hFile == INVALID_HANDLE_VALUE)
-		{
-			// creating new destination file have failed - either file exists or some other problem occurred
-			DWORD dwLastError = GetLastError();
-			if(dwLastError == ERROR_FILE_EXISTS)
-			{
-				// destination file already exists - try to open existing file
-				return OpenExistingDestinationFile(strPath, bNoBuffering);
-			}
-			else
-			{
-				// there is other reason for file creation failure
-				int iResponse = 0;	// Ask user what to do
-				switch(iResponse)
-				{
-				case 0://eSkip:
-					return;
-					break;
-				case 1://eRetry:
-					bRetry = true;
-					break;
-				case 2://eCancel:
-					break;
-				case 3: //ePause:
-					break;
-				default:
-					throw;
-			}
-		}
+		// we don't copy contents, but need to increase processed size
+		m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskProgressInfo.GetCurrentFileProcessedSize());
 	}
-	while(bRetry);
 
-	return hFile;
+	pData->bProcessed = true;
+	m_tTaskProgressInfo.SetCurrentFileProcessedSize(0);
 }
 
-HANDLE CTask::OpenExistingDestinationFile(const CString& strPath, bool bNoBuffering/ *, FeedbackSettings* /)
-{
-
-}
-
-void CTask::SetEndOfFile(HANDLE hFile)
-{
-
-}
-
-void CTask::SeekToPosition(HANDLE hFile, unsigned long long ullPos)
-{
-
-}
-*/
-
 // function processes files/folders
 void CTask::ProcessFiles()
 {
@@ -2422,11 +2160,11 @@
 	fmt.SetParam(_t("%filecount"), stSize);
 	fmt.SetParam(_t("%ignorefolders"), bIgnoreFolders);
 	fmt.SetParam(_t("%dstpath"), dpDestPath.GetPath());
-	fmt.SetParam(_t("%currindex"), GetCurrentIndex());
+	fmt.SetParam(_t("%currindex"), m_tTaskProgressInfo.GetCurrentIndex());
 
 	m_log.logi(fmt);
 
-	for (size_t i = GetCurrentIndex(); i < stSize; i++)
+	for(size_t stIndex = m_tTaskProgressInfo.GetCurrentIndex(); stIndex < stSize; stIndex++)
 	{
 		// should we kill ?
 		if(m_workerThread.KillRequested())
@@ -2437,7 +2175,6 @@
 		}
 
 		// update m_stCurrentIndex, getting current CFileInfo
-		SetCurrentIndex(i);
 		CFileInfoPtr spFileInfo = FilesGetAtCurrentIndex();
 
 		// set dest path with filename
@@ -2552,6 +2289,8 @@
 			if(GetConfig().get_bool(PP_CMSETDESTATTRIBUTES))
 				SetFileAttributes(ccp.strDstFile, spFileInfo->GetAttributes());	// as above
 		}
+
+		m_tTaskProgressInfo.SetCurrentIndex(stIndex + 1);
 	}
 
 	// delete buffer - it's not needed
@@ -2562,14 +2301,14 @@
 	{
 		SetStatus(ST_DELETING, ST_STEP_MASK);
 		// set the index to 0 before deleting
-		SetCurrentIndex(0);
+		m_tTaskProgressInfo.SetCurrentIndex(0);
 	}
 	else
 	{
 		SetStatus(ST_FINISHED, ST_STEP_MASK);
 
 		// to look better - increase current index by 1
-		SetCurrentIndex(stSize);
+		m_tTaskProgressInfo.SetCurrentIndex(stSize);
 	}
 	// log
 	m_log.logi(_T("Finished processing in ProcessFiles"));
Index: src/ch/task.h
===================================================================
diff -u -r266560162ac9f14f94b48a7c84fee323aa259c0d -r45cf96558ba334192ef42687d4dac01c46d6ffd8
--- src/ch/task.h	(.../task.h)	(revision 266560162ac9f14f94b48a7c84fee323aa259c0d)
+++ src/ch/task.h	(.../task.h)	(revision 45cf96558ba334192ef42687d4dac01c46d6ffd8)
@@ -156,8 +156,7 @@
 	// ============================================================================
 	~TAutoFileHandle()
 	{
-		_ASSERTE(m_hHandle == INVALID_HANDLE_VALUE);
-		Close();
+		VERIFY(Close());
 	}
 
 	// ============================================================================
@@ -209,6 +208,20 @@
 		return bResult;
 	}
 
+	// ============================================================================
+	/// TAutoFileHandle::Detach
+	/// @date 2010/09/12
+	///
+	/// @brief     Detaches the handle, so it won't be closed in destructor.
+	/// @return	   Returns current handle.
+	// ============================================================================
+	HANDLE Detach()
+	{
+		HANDLE hHandle = m_hHandle;
+		m_hHandle = INVALID_HANDLE_VALUE;
+		return hHandle;
+	}
+
 private:
 	HANDLE m_hHandle;		///< System handle
 };
@@ -297,6 +310,61 @@
 
 ///////////////////////////////////////////////////////////////////////////
 // CTask
+
+class TTaskProgressInfo
+{
+public:
+	TTaskProgressInfo();
+	~TTaskProgressInfo();
+
+	void SetCurrentIndex(size_t stIndex);	// might be unneeded when serialization is implemented
+	void IncreaseCurrentIndex();
+	size_t GetCurrentIndex() const;
+
+	void SetCurrentFileProcessedSize(unsigned long long ullSize);
+	unsigned long long GetCurrentFileProcessedSize() const;
+	void IncreaseCurrentFileProcessedSize(unsigned long long ullSizeToAdd);
+
+	template<class Archive>
+	void load(Archive& ar, unsigned int /*uiVersion*/)
+	{
+		size_t stCurrentIndex = 0;
+		ar >> stCurrentIndex;
+
+		unsigned long long ullCurrentFileProcessedSize = 0;
+		ar >> ullCurrentFileProcessedSize;
+
+		boost::unique_lock<boost::shared_mutex> lock(m_lock);
+
+		m_stCurrentIndex = stCurrentIndex;
+		m_ullCurrentFileProcessedSize = ullCurrentFileProcessedSize;
+	}
+
+	template<class Archive>
+	void save(Archive& ar, unsigned int /*uiVersion*/) const
+	{
+		m_lock.lock_shared();
+
+		size_t stCurrentIndex = m_stCurrentIndex;
+		unsigned long long ullCurrentFileProcessedSize = m_ullCurrentFileProcessedSize;
+		
+		m_lock.unlock_shared();
+
+		ar << stCurrentIndex;
+		ar << ullCurrentFileProcessedSize;
+	}
+
+	BOOST_SERIALIZATION_SPLIT_MEMBER();
+
+private:
+	volatile size_t m_stCurrentIndex;   // index to the m_files array stating currently processed item
+	volatile unsigned long long m_ullCurrentFileProcessedSize;	// count of bytes processed for current file
+
+	mutable boost::shared_mutex m_lock;
+};
+
+///////////////////////////////////////////////////////////////////////////
+// CTask
 class CTask
 {
 public:
@@ -388,28 +456,15 @@
 	static bool SetFileDirectoryTime(LPCTSTR lpszName, const CFileInfoPtr& spFileInfo);
 
 	HANDLE OpenSourceFileFB(const CFileInfoPtr& spSrcFileInfo, bool bNoBuffering);
-	HANDLE OpenDestinationFileFB(const CString& strDstFilePath, bool bNoBuffering);
+	HANDLE OpenDestinationFileFB(const CString& strDstFilePath, bool bNoBuffering, const CFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated);
+	HANDLE OpenExistingDestinationFileFB(const CString& strDstFilePath, bool bNoBuffering);
 
 	bool SetFilePointerFB(HANDLE hFile, long long llDistance, const CString& strFilePath);
 	bool SetEndOfFileFB(HANDLE hFile, const CString& strFilePath);
 
 	bool ReadFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToRead, DWORD& rdwBytesRead, const CString& strFilePath);
 	bool WriteFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToWrite, DWORD& rdwBytesWritten, const CString& strFilePath);
 
-	// Playground
-/*
-	void CustomCopyFile2(CUSTOM_COPY_PARAMS* / *pData* /);
-
-	HANDLE CreateNewDestinationFile(const CString& strPath, bool bNoBuffering/ *, FeedbackSettings* /);
-	HANDLE OpenExistingDestinationFile(const CString& strPath, bool bNoBuffering/ *, FeedbackSettings* /);
-	void SetEndOfFile(HANDLE hFile);
-	void SeekToPosition(HANDLE hFile, unsigned long long ullPos);
-*/
-
-
-	// End of playground
-
-
 	// m_files
 	int FilesAddDir(CString strDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs);
 	void FilesAdd(const CFileInfoPtr& spFileInfo);
@@ -418,15 +473,6 @@
 	void FilesRemoveAll();
 	size_t FilesGetSize();
 
-	// m_stCurrentIndex
-	void IncreaseCurrentIndex();
-	size_t GetCurrentIndex();
-	void SetCurrentIndex(size_t stIndex);
-
-	void IncreaseCurrentIndexNL();
-	size_t GetCurrentIndexNL();
-	void SetCurrentIndexNL(size_t stIndex);
-
 	// m_strDestPath
 	void SetDestPathNL(LPCTSTR lpszPath);
 	const CDestPath& GetDestPathNL();
@@ -440,7 +486,6 @@
 	// m_nBufferSize
 	void SetBufferSizesNL(const BUFFERSIZES* bsSizes);
 	const BUFFERSIZES* GetBufferSizesNL();
-	int GetCurrentBufferIndexNL();
 
 	// m_nPriority
 	int  GetPriorityNL();
@@ -492,7 +537,7 @@
 	// changing fast
 	volatile UINT m_nStatus;            // what phase of the operation is this task in
 
-	volatile size_t m_stCurrentIndex;   // index to the m_files array stating currently processed item
+	TTaskProgressInfo m_tTaskProgressInfo;	// task progress information
 
 	// task control variables (per-session state)
 	TTaskLocalStats m_localStats;       // local statistics