Index: src/ch/task.cpp =================================================================== diff -u -N -rb684bec49aaaea4b89ab2e599497f4085d8698a3 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4 --- src/ch/task.cpp (.../task.cpp) (revision b684bec49aaaea4b89ab2e599497f4085d8698a3) +++ src/ch/task.cpp (.../task.cpp) (revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4) @@ -32,388 +32,10 @@ #include "TSubTaskContext.h" #include "Device IO.h" +#include "TLocalFilesystem.h" +#include "TSubTaskScanDirectory.h" +#include "TSubTaskCopyMove.h" -// assume max sectors of 4kB (for rounding) -#define MAXSECTORSIZE 4096 - -//////////////////////////////////////////////////////////////////////////////// -// TTasksGlobalStats members - -TTasksGlobalStats::TTasksGlobalStats() : - m_ullGlobalTotalSize(0), - m_ullGlobalProcessedSize(0), - m_stRunningTasks(0) -{ -} - -TTasksGlobalStats::~TTasksGlobalStats() -{ -} - -void TTasksGlobalStats::IncreaseGlobalTotalSize(unsigned long long ullModify) -{ - boost::unique_lock lock(m_lock); - m_ullGlobalTotalSize += ullModify; -} - -void TTasksGlobalStats::DecreaseGlobalTotalSize(unsigned long long ullModify) -{ - boost::unique_lock lock(m_lock); - m_ullGlobalTotalSize -= ullModify; -} - -unsigned long long TTasksGlobalStats::GetGlobalTotalSize() const -{ - boost::shared_lock lock(m_lock); - return m_ullGlobalTotalSize; -} - -void TTasksGlobalStats::IncreaseGlobalProcessedSize(unsigned long long ullModify) -{ - boost::unique_lock lock(m_lock); - m_ullGlobalProcessedSize += ullModify; -} - -void TTasksGlobalStats::DecreaseGlobalProcessedSize(unsigned long long ullModify) -{ - boost::unique_lock lock(m_lock); - m_ullGlobalProcessedSize -= ullModify; -} - -unsigned long long TTasksGlobalStats::GetGlobalProcessedSize() const -{ - boost::shared_lock lock(m_lock); - return m_ullGlobalProcessedSize; -} - -void TTasksGlobalStats::IncreaseGlobalProgressData(unsigned long long ullTasksPosition, unsigned long long ullTasksSize) -{ - boost::unique_lock lock(m_lock); - m_ullGlobalTotalSize += ullTasksSize; - m_ullGlobalProcessedSize += ullTasksPosition; -} - -void TTasksGlobalStats::DecreaseGlobalProgressData(unsigned long long ullTasksPosition, unsigned long long ullTasksSize) -{ - boost::unique_lock lock(m_lock); - m_ullGlobalTotalSize -= ullTasksSize; - m_ullGlobalProcessedSize -= ullTasksPosition; -} - -int TTasksGlobalStats::GetProgressPercents() const -{ - unsigned long long llPercent = 0; - - boost::shared_lock lock(m_lock); - - if(m_ullGlobalTotalSize != 0) - llPercent = m_ullGlobalProcessedSize * 100 / m_ullGlobalTotalSize; - - return boost::numeric_cast(llPercent); -} - -void TTasksGlobalStats::IncreaseRunningTasks() -{ - boost::unique_lock lock(m_lock); - ++m_stRunningTasks; -} - -void TTasksGlobalStats::DecreaseRunningTasks() -{ - boost::unique_lock lock(m_lock); - --m_stRunningTasks; -} - -size_t TTasksGlobalStats::GetRunningTasksCount() const -{ - boost::shared_lock lock(m_lock); - return m_stRunningTasks; -} - -//////////////////////////////////////////////////////////////////////////////// -// TTasksGlobalStats members -TTaskLocalStats::TTaskLocalStats() : - m_prtGlobalStats(NULL), - m_ullProcessedSize(0), - m_ullTotalSize(0), - m_bTaskIsRunning(false), - m_timeElapsed(0), - m_timeLast(-1) -{ -} - -TTaskLocalStats::~TTaskLocalStats() -{ - DisconnectGlobalStats(); -} - -void TTaskLocalStats::ConnectGlobalStats(TTasksGlobalStats& rtGlobalStats) -{ - DisconnectGlobalStats(); - - boost::unique_lock lock(m_lock); - - m_prtGlobalStats = &rtGlobalStats; - m_prtGlobalStats->IncreaseGlobalProgressData(m_ullProcessedSize, m_ullTotalSize); - if(m_bTaskIsRunning) - m_prtGlobalStats->IncreaseRunningTasks(); -} - -void TTaskLocalStats::DisconnectGlobalStats() -{ - boost::unique_lock lock(m_lock); - - if(m_prtGlobalStats) - { - m_prtGlobalStats->DecreaseGlobalProgressData(m_ullProcessedSize, m_ullTotalSize); - if(m_bTaskIsRunning) - m_prtGlobalStats->DecreaseRunningTasks(); - m_prtGlobalStats = NULL; - } -} - -void TTaskLocalStats::IncreaseProcessedSize(unsigned long long ullAdd) -{ - boost::unique_lock lock(m_lock); - - if(m_prtGlobalStats) - m_prtGlobalStats->IncreaseGlobalProcessedSize(ullAdd); - - m_ullProcessedSize += ullAdd; -} - -void TTaskLocalStats::DecreaseProcessedSize(unsigned long long ullSub) -{ - boost::unique_lock lock(m_lock); - if(m_prtGlobalStats) - m_prtGlobalStats->DecreaseGlobalProcessedSize(ullSub); - - m_ullProcessedSize -= ullSub; -} - -void TTaskLocalStats::SetProcessedSize(unsigned long long ullSet) -{ - boost::unique_lock lock(m_lock); - - if(m_prtGlobalStats) - { - if(ullSet < m_ullProcessedSize) - m_prtGlobalStats->DecreaseGlobalProcessedSize(m_ullProcessedSize - ullSet); - else - m_prtGlobalStats->IncreaseGlobalProcessedSize(ullSet - m_ullProcessedSize); - } - - m_ullProcessedSize = ullSet; -} - -unsigned long long TTaskLocalStats::GetProcessedSize() const -{ - boost::shared_lock lock(m_lock); - return m_ullProcessedSize; -} - -unsigned long long TTaskLocalStats::GetUnProcessedSize() const -{ - boost::shared_lock lock(m_lock); - return m_ullTotalSize - m_ullProcessedSize; -} - -void TTaskLocalStats::IncreaseTotalSize(unsigned long long ullAdd) -{ - boost::unique_lock lock(m_lock); - - if(m_prtGlobalStats) - m_prtGlobalStats->IncreaseGlobalTotalSize(ullAdd); - m_ullTotalSize += ullAdd; -} - -void TTaskLocalStats::DecreaseTotalSize(unsigned long long ullSub) -{ - boost::unique_lock lock(m_lock); - - if(m_prtGlobalStats) - m_prtGlobalStats->DecreaseGlobalTotalSize(ullSub); - - m_ullTotalSize -= ullSub; -} - -void TTaskLocalStats::SetTotalSize(unsigned long long ullSet) -{ - boost::unique_lock lock(m_lock); - - if(m_prtGlobalStats) - { - if(ullSet < m_ullTotalSize) - m_prtGlobalStats->DecreaseGlobalTotalSize(m_ullTotalSize - ullSet); - else - m_prtGlobalStats->IncreaseGlobalTotalSize(ullSet - m_ullTotalSize); - } - - m_ullTotalSize = ullSet; -} - -unsigned long long TTaskLocalStats::GetTotalSize() const -{ - boost::shared_lock lock(m_lock); - return m_ullTotalSize; -} - -int TTaskLocalStats::GetProgressInPercent() const -{ - boost::shared_lock lock(m_lock); - - unsigned long long ullPercent = 0; - - if(m_ullTotalSize != 0) - ullPercent = m_ullProcessedSize * 100 / m_ullTotalSize; - - return boost::numeric_cast(ullPercent); -} - -void TTaskLocalStats::MarkTaskAsRunning() -{ - boost::unique_lock lock(m_lock); - if(!m_bTaskIsRunning) - { - if(m_prtGlobalStats) - m_prtGlobalStats->IncreaseRunningTasks(); - m_bTaskIsRunning = true; - } -} - -void TTaskLocalStats::MarkTaskAsNotRunning() -{ - boost::unique_lock lock(m_lock); - if(m_bTaskIsRunning) - { - if(m_prtGlobalStats) - m_prtGlobalStats->DecreaseRunningTasks(); - m_bTaskIsRunning = false; - } -} - -bool TTaskLocalStats::IsRunning() const -{ - boost::shared_lock lock(m_lock); - return m_bTaskIsRunning; -} - -void TTaskLocalStats::SetTimeElapsed(time_t timeElapsed) -{ - boost::unique_lock lock(m_lock); - m_timeElapsed = timeElapsed; -} - -time_t TTaskLocalStats::GetTimeElapsed() -{ - UpdateTime(); - - boost::shared_lock lock(m_lock); - return m_timeElapsed; -} - -void TTaskLocalStats::EnableTimeTracking() -{ - boost::upgrade_lock lock(m_lock); - if(m_timeLast == -1) - { - boost::upgrade_to_unique_lock lock_upgraded(lock); - m_timeLast = time(NULL); - } -} - -void TTaskLocalStats::DisableTimeTracking() -{ - UpdateTime(); - - boost::upgrade_lock lock(m_lock); - if(m_timeLast != -1) - { - boost::upgrade_to_unique_lock lock_upgraded(lock); - m_timeLast = -1; - } -} - -void TTaskLocalStats::UpdateTime() -{ - boost::upgrade_lock lock(m_lock); - if(m_timeLast != -1) - { - time_t timeCurrent = time(NULL); - - boost::upgrade_to_unique_lock lock_upgraded(lock); - m_timeElapsed += timeCurrent - m_timeLast; - m_timeLast = timeCurrent; - } -} - -TTaskBasicProgressInfo::TTaskBasicProgressInfo() : - m_stCurrentIndex(0), - m_ullCurrentFileProcessedSize(0), - m_stSubOperationIndex(0) -{ -} - -TTaskBasicProgressInfo::~TTaskBasicProgressInfo() -{ -} - -void TTaskBasicProgressInfo::SetCurrentIndex(size_t stIndex) -{ - boost::unique_lock lock(m_lock); - m_stCurrentIndex = stIndex; - m_ullCurrentFileProcessedSize = 0; -} - -void TTaskBasicProgressInfo::IncreaseCurrentIndex() -{ - boost::unique_lock lock(m_lock); - ++m_stCurrentIndex; - m_ullCurrentFileProcessedSize = 0; -} - -size_t TTaskBasicProgressInfo::GetCurrentIndex() const -{ - boost::shared_lock lock(m_lock); - return m_stCurrentIndex; -} - -void TTaskBasicProgressInfo::SetCurrentFileProcessedSize(unsigned long long ullSize) -{ - boost::unique_lock lock(m_lock); - m_ullCurrentFileProcessedSize = ullSize; -} - -unsigned long long TTaskBasicProgressInfo::GetCurrentFileProcessedSize() const -{ - boost::shared_lock lock(m_lock); - return m_ullCurrentFileProcessedSize; -} - -void TTaskBasicProgressInfo::IncreaseCurrentFileProcessedSize(unsigned long long ullSizeToAdd) -{ - boost::unique_lock lock(m_lock); - m_ullCurrentFileProcessedSize += ullSizeToAdd; -} - -void TTaskBasicProgressInfo::SetSubOperationIndex(size_t stSubOperationIndex) -{ - boost::unique_lock lock(m_lock); - m_stSubOperationIndex = stSubOperationIndex; -} - -size_t TTaskBasicProgressInfo::GetSubOperationIndex() const -{ - boost::shared_lock lock(m_lock); - return m_stSubOperationIndex; -} - -void TTaskBasicProgressInfo::IncreaseSubOperationIndex() -{ - boost::unique_lock lock(m_lock); - ++m_stSubOperationIndex; -} - //////////////////////////////////////////////////////////////////////////// // CTask members CTask::CTask(chcore::IFeedbackHandler* piFeedbackHandler, size_t stSessionUniqueID) : @@ -457,59 +79,6 @@ m_localStats.DisconnectGlobalStats(); } -// m_files -int CTask::ScanDirectory(chcore::TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs) -{ - WIN32_FIND_DATA wfd; - chcore::TSmartPath pathCurrent; - - pathCurrent = pathDirName + chcore::PathFromString(_T("*")); - - // Iterate through dirs & files - HANDLE hFind = FindFirstFile(pathCurrent.ToString(), &wfd); - if(hFind != INVALID_HANDLE_VALUE) - { - do - { - if(!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - { - CFileInfoPtr spFileInfo(boost::make_shared()); - spFileInfo->SetClipboard(&m_tTaskDefinition.GetSourcePaths()); // this is the link table (CClipboardArray) - - spFileInfo->Create(&wfd, pathDirName, stSrcIndex); - if(m_afFilters.Match(spFileInfo)) - m_files.AddFileInfo(spFileInfo); - } - else if(wfd.cFileName[0] != _T('.') || (wfd.cFileName[1] != _T('\0') && (wfd.cFileName[1] != _T('.') || wfd.cFileName[2] != _T('\0')))) - { - if(bIncludeDirs) - { - CFileInfoPtr spFileInfo(boost::make_shared()); - spFileInfo->SetClipboard(&m_tTaskDefinition.GetSourcePaths()); // this is the link table (CClipboardArray) - - // Add directory itself - spFileInfo->Create(&wfd, pathDirName, stSrcIndex); - m_files.AddFileInfo(spFileInfo); - } - if(bRecurse) - { - pathCurrent = pathDirName + chcore::PathFromString(wfd.cFileName) + chcore::PathFromString(_T("\\")); - // Recurse Dirs - ScanDirectory(pathCurrent, stSrcIndex, bRecurse, bIncludeDirs); - } - } - - if(m_workerThread.KillRequested()) - break; - } - while(FindNextFile(hFind, &wfd)); - - FindClose(hFind); - } - - return 0; -} - void CTask::SetTaskState(ETaskCurrentState eTaskState) { // NOTE: we could check some transition rules here @@ -547,7 +116,7 @@ int CTask::GetCurrentBufferIndex() { - return GetBufferIndex(m_files.GetAt(m_tTaskBasicProgressInfo.GetCurrentIndex())); + return m_localStats.GetCurrentBufferIndex(); } // thread @@ -556,20 +125,6 @@ SetTaskPropValue(m_tTaskDefinition.GetConfiguration(), nPriority); } -void CTask::CalculateTotalSize() -{ - unsigned long long ullTotalSize = 0; - - boost::shared_lock lock(m_lock); - size_t nSize = m_files.GetSize(); - for(size_t i = 0; i < nSize; i++) - { - ullTotalSize += m_files.GetAt(i)->GetLength64(); - } - - m_localStats.SetTotalSize(ullTotalSize); -} - void CTask::CalculateProcessedSize() { boost::shared_lock lock(m_lock); @@ -841,7 +396,7 @@ pData->m_bCreateEmptyFiles = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); if(m_files.GetSize() > 0) - pData->m_iCurrentBufferIndex = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()) ? BI_DEFAULT : GetBufferIndex(m_files.GetAt((stCurrentIndex < m_files.GetSize()) ? stCurrentIndex : 0)); + pData->m_iCurrentBufferIndex = m_localStats.GetCurrentBufferIndex(); else pData->m_iCurrentBufferIndex = BI_DEFAULT; @@ -977,31 +532,10 @@ } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool CTask::SetFileDirectoryTime(LPCTSTR lpszName, const CFileInfoPtr& spFileInfo) -{ - TAutoFileHandle hFile = CreateFile(lpszName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | (spFileInfo->IsDirectory() ? FILE_FLAG_BACKUP_SEMANTICS : 0), NULL); - if(hFile == INVALID_HANDLE_VALUE) - return false; - BOOL bResult = (!SetFileTime(hFile, &spFileInfo->GetCreationTime(), &spFileInfo->GetLastAccessTime(), &spFileInfo->GetLastWriteTime())); - - if(!hFile.Close()) - return false; - - return bResult != 0; -} - void CTask::CalculateTotalSizeNL() { - unsigned long long ullTotalSize = 0; - - size_t nSize = m_files.GetSize(); - for(size_t stIndex = 0; stIndex < nSize; stIndex++) - { - ullTotalSize += m_files.GetAt(stIndex)->GetLength64(); - } - - m_localStats.SetTotalSize(ullTotalSize); + m_localStats.SetTotalSize(m_files.CalculateTotalSize()); } void CTask::SetForceFlagNL(bool bFlag) @@ -1024,176 +558,8 @@ return m_bContinue; } -// searching for files -CTask::ESubOperationResult CTask::RecurseDirectories() -{ - // log - m_log.logi(_T("Searching for files...")); - - // delete the content of m_files - m_files.Clear(); - - // read filtering options - GetTaskPropValue(m_tTaskDefinition.GetConfiguration(), m_afFilters); - - // enter some data to m_files - int iDestDrvNumber = 0; - GetDriveData(m_tTaskDefinition.GetDestinationPath(), &iDestDrvNumber, NULL); - - bool bIgnoreDirs = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bool bForceDirectories = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bool bMove = m_tTaskDefinition.GetOperationType() == eOperation_Move; - - // add everything - ictranslate::CFormat fmt; - bool bRetry = true; - bool bSkipInputPath = false; - - size_t stSize = m_tTaskDefinition.GetSourcePathCount(); - for(size_t stIndex = 0; stIndex < stSize ; stIndex++) - { - CFileInfoPtr spFileInfo; - - bSkipInputPath = false; - - spFileInfo.reset(new CFileInfo()); - spFileInfo->SetClipboard(&m_tTaskDefinition.GetSourcePaths()); - - // try to get some info about the input path; let user know if the path does not exist. - do - { - bRetry = false; - - // read attributes of src file/folder - bool bExists = spFileInfo->Create(m_tTaskDefinition.GetSourcePathAt(stIndex), stIndex); - if(!bExists) - { - FEEDBACK_FILEERROR ferr = { m_tTaskDefinition.GetSourcePathAt(stIndex).ToString(), NULL, eFastMoveError, ERROR_FILE_NOT_FOUND }; - CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr); - switch(frResult) - { - case CFeedbackHandler::eResult_Cancel: - m_files.Clear(); - return eSubResult_CancelRequest; - - case CFeedbackHandler::eResult_Retry: - bRetry = true; - break; - - case CFeedbackHandler::eResult_Pause: - m_files.Clear(); - return eSubResult_PauseRequest; - - case CFeedbackHandler::eResult_Skip: - bSkipInputPath = true; - break; // just do nothing - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW(_T("Unhandled case"), 0, 0, 0); - } - } - } - while(bRetry); - - // if we have chosen to skip the input path then there's nothing to do - if(bSkipInputPath) - continue; - - // log - fmt.SetFormat(_T("Adding file/folder (clipboard) : %path ...")); - fmt.SetParam(_t("%path"), m_tTaskDefinition.GetSourcePathAt(stIndex).ToString()); - m_log.logi(fmt); - - // found file/folder - check if the dest name has been generated - if(!m_arrSourcePathsInfo.GetAt(stIndex)->IsDestinationPathSet()) - { - // generate something - if dest folder == src folder - search for copy - if(m_tTaskDefinition.GetDestinationPath() == spFileInfo->GetFullFilePath().GetFileRoot()) - { - chcore::TSmartPath pathSubst = FindFreeSubstituteName(spFileInfo->GetFullFilePath(), m_tTaskDefinition.GetDestinationPath()); - m_arrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(pathSubst); - } - else - m_arrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(spFileInfo->GetFullFilePath().GetFileName()); - } - - // add if needed - if(spFileInfo->IsDirectory()) - { - // add if folder's aren't ignored - if(!bIgnoreDirs && !bForceDirectories) - { - // add directory info; it is not to be filtered with m_afFilters - m_files.AddFileInfo(spFileInfo); - - // log - fmt.SetFormat(_T("Added folder %path")); - fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString()); - m_log.logi(fmt); - } - - // don't add folder contents when moving inside one disk boundary - if(bIgnoreDirs || !bMove || iDestDrvNumber == -1 || iDestDrvNumber != GetDriveNumber(spFileInfo) || - PathExist(GetDestinationPath(spFileInfo, m_tTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1)) ) - { - // log - fmt.SetFormat(_T("Recursing folder %path")); - fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString()); - m_log.logi(fmt); - - // no movefile possibility - use CustomCopyFileFB - m_arrSourcePathsInfo.GetAt(stIndex)->SetMove(false); - - ScanDirectory(spFileInfo->GetFullFilePath(), stIndex, true, !bIgnoreDirs || bForceDirectories); - } - - // check for kill need - if(m_workerThread.KillRequested()) - { - // log - m_log.logi(_T("Kill request while adding data to files array (RecurseDirectories)")); - m_files.Clear(); - return eSubResult_KillRequest; - } - } - else - { - if(bMove && iDestDrvNumber != -1 && iDestDrvNumber == GetDriveNumber(spFileInfo) && - !PathExist(GetDestinationPath(spFileInfo, m_tTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1)) ) - { - // if moving within one partition boundary set the file size to 0 so the overall size will - // be ok - spFileInfo->SetLength64(0); - } - else - m_arrSourcePathsInfo.GetAt(stIndex)->SetMove(false); // no MoveFile - - // add file info if passes filters - if(m_afFilters.Match(spFileInfo)) - m_files.AddFileInfo(spFileInfo); - - // log - fmt.SetFormat(_T("Added file %path")); - fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString()); - m_log.logi(fmt); - } - } - - // calc size of all files - CalculateTotalSize(); - - // save task status - Store(); - - // log - m_log.logi(_T("Searching for files finished")); - - return eSubResult_Continue; -} - // delete files - after copying -CTask::ESubOperationResult CTask::DeleteFiles() +TSubTaskBase::ESubOperationResult CTask::DeleteFiles() { // log m_log.logi(_T("Deleting files (DeleteFiles)...")); @@ -1215,7 +581,7 @@ { // log m_log.logi(_T("Kill request while deleting files (Delete Files)")); - return eSubResult_KillRequest; + return TSubTaskBase::eSubResult_KillRequest; } // current processed element @@ -1257,13 +623,13 @@ { case CFeedbackHandler::eResult_Cancel: m_log.logi(_T("Cancel request while deleting file.")); - return eSubResult_CancelRequest; + return TSubTaskBase::eSubResult_CancelRequest; case CFeedbackHandler::eResult_Retry: continue; // no stIndex bump, since we are trying again case CFeedbackHandler::eResult_Pause: - return eSubResult_PauseRequest; + return TSubTaskBase::eSubResult_PauseRequest; case CFeedbackHandler::eResult_Skip: break; // just do nothing @@ -1286,947 +652,11 @@ // log m_log.logi(_T("Deleting files finished")); - return eSubResult_Continue; + return TSubTaskBase::eSubResult_Continue; } -CTask::ESubOperationResult CTask::OpenSourceFileFB(TAutoFileHandle& hOutFile, const CFileInfoPtr& spSrcFileInfo, bool bNoBuffering) +TSubTaskBase::ESubOperationResult CTask::CheckForWaitState() { - BOOST_ASSERT(spSrcFileInfo); - if(!spSrcFileInfo) - THROW(_T("Invalid argument"), 0, 0, 0); - - bool bRetry = false; - CString strPath = spSrcFileInfo->GetFullFilePath().ToString(); - - hOutFile = INVALID_HANDLE_VALUE; - - TAutoFileHandle hFile; - do - { - bRetry = false; - - hFile = CreateFile(strPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 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)strPath, NULL, eCreateError, dwLastError }; - CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &feedStruct); - - switch(frResult) - { - case CFeedbackHandler::eResult_Skip: - break; // will return INVALID_HANDLE_VALUE - - case CFeedbackHandler::eResult_Cancel: - { - // log - ictranslate::CFormat fmt; - fmt.SetFormat(_T("Cancel request [error %errno] while opening source file %path (CustomCopyFileFB)")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%path"), strPath); - m_log.loge(fmt); - - return eSubResult_CancelRequest; - } - - case CFeedbackHandler::eResult_Pause: - return eSubResult_PauseRequest; - - case CFeedbackHandler::eResult_Retry: - { - // log - ictranslate::CFormat fmt; - fmt.SetFormat(_T("Retrying [error %errno] to open source file %path (CustomCopyFileFB)")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%path"), strPath); - m_log.loge(fmt); - - bRetry = true; - break; - } - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW(_T("Unhandled case"), 0, 0, 0); - } - } - } - while(bRetry); - - hOutFile = hFile.Detach(); - - return eSubResult_Continue; -} - -CTask::ESubOperationResult CTask::OpenDestinationFileFB(TAutoFileHandle& hOutFile, const chcore::TSmartPath& pathDstFile, bool bNoBuffering, const CFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated) -{ - bool bRetry = false; - TAutoFileHandle hFile; - - ullSeekTo = 0; - bFreshlyCreated = true; - hOutFile = INVALID_HANDLE_VALUE; - - do - { - bRetry = false; - - hFile = ::CreateFile(pathDstFile.ToString(), 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 - CTask::ESubOperationResult eResult = OpenExistingDestinationFileFB(hFile, pathDstFile, bNoBuffering); - if(eResult != eSubResult_Continue) - return eResult; - else if(hFile == INVALID_HANDLE_VALUE) - return eSubResult_Continue; - - // 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()); - if(!spDstFileInfo->Create(pathDstFile, std::numeric_limits::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 eSubResult_Continue; - - case CFeedbackHandler::eResult_Cancel: - { - // log - ictranslate::CFormat fmt; - fmt.SetFormat(_T("Cancel request while checking result of dialog before opening source file %path (CustomCopyFileFB)")); - fmt.SetParam(_t("%path"), pathDstFile.ToString()); - m_log.logi(fmt); - - return eSubResult_CancelRequest; - } - case CFeedbackHandler::eResult_Pause: - return eSubResult_PauseRequest; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW(_T("Unhandled case"), 0, 0, 0); - } - } - else - { - FEEDBACK_FILEERROR feedStruct = { pathDstFile.ToString(), 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 (CustomCopyFileFB)")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%path"), pathDstFile.ToString()); - 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 (CustomCopyFileFB)")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%path"), pathDstFile.ToString()); - m_log.loge(fmt); - - return eSubResult_CancelRequest; - } - - case CFeedbackHandler::eResult_Skip: - break; // will return invalid handle value - - case CFeedbackHandler::eResult_Pause: - return eSubResult_PauseRequest; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW(_T("Unhandled case"), 0, 0, 0); - } - } - } - } - while(bRetry); - - hOutFile = hFile.Detach(); - - return eSubResult_Continue; -} - -CTask::ESubOperationResult CTask::OpenExistingDestinationFileFB(TAutoFileHandle& hOutFile, const chcore::TSmartPath& pathDstFile, bool bNoBuffering) -{ - bool bRetry = false; - TAutoFileHandle hFile; - - hOutFile = INVALID_HANDLE_VALUE; - - do - { - bRetry = false; - - hFile = CreateFile(pathDstFile.ToString(), 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 = { pathDstFile.ToString(), 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 (CustomCopyFileFB)")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%path"), pathDstFile.ToString()); - 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 (CustomCopyFileFB)")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%path"), pathDstFile.ToString()); - m_log.loge(fmt); - - return eSubResult_CancelRequest; - } - - case CFeedbackHandler::eResult_Skip: - break; // will return invalid handle value - - case CFeedbackHandler::eResult_Pause: - return eSubResult_PauseRequest; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW(_T("Unhandled case"), 0, 0, 0); - } - } - } - while(bRetry); - - hOutFile = hFile.Detach(); - - return eSubResult_Continue; -} - -CTask::ESubOperationResult CTask::SetFilePointerFB(HANDLE hFile, long long llDistance, const chcore::TSmartPath& pathFile, bool& bSkip) -{ - bSkip = false; - bool bRetry = false; - do - { - bRetry = false; - - if(SetFilePointer64(hFile, llDistance, FILE_BEGIN) == -1) - { - DWORD dwLastError = GetLastError(); - - // log - ictranslate::CFormat fmt; - - fmt.SetFormat(_T("Error %errno while moving file pointer of %path to %pos")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%path"), pathFile.ToString()); - fmt.SetParam(_t("%pos"), llDistance); - m_log.loge(fmt); - - FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eSeekError, dwLastError }; - CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr); - switch(frResult) - { - case CFeedbackHandler::eResult_Cancel: - return eSubResult_CancelRequest; - - case CFeedbackHandler::eResult_Retry: - bRetry = true; - break; - - case CFeedbackHandler::eResult_Pause: - return eSubResult_PauseRequest; - - case CFeedbackHandler::eResult_Skip: - bSkip = true; - return eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW(_T("Unhandled case"), 0, 0, 0); - } - } - } - while(bRetry); - - return eSubResult_Continue; -} - -CTask::ESubOperationResult CTask::SetEndOfFileFB(HANDLE hFile, const chcore::TSmartPath& pathFile, bool& bSkip) -{ - bSkip = false; - - bool bRetry = false; - do - { - if(!SetEndOfFile(hFile)) - { - // log - DWORD dwLastError = GetLastError(); - - ictranslate::CFormat fmt; - fmt.SetFormat(_T("Error %errno while setting size of file %path to 0")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%path"), pathFile.ToString()); - m_log.loge(fmt); - - FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eResizeError, dwLastError }; - CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr); - switch(frResult) - { - case CFeedbackHandler::eResult_Cancel: - return eSubResult_CancelRequest; - - case CFeedbackHandler::eResult_Retry: - bRetry = true; - - case CFeedbackHandler::eResult_Pause: - return eSubResult_PauseRequest; - - case CFeedbackHandler::eResult_Skip: - bSkip = true; - return eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW(_T("Unhandled case"), 0, 0, 0); - } - } - } - while(bRetry); - - return eSubResult_Continue; -} - -CTask::ESubOperationResult CTask::ReadFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToRead, DWORD& rdwBytesRead, const chcore::TSmartPath& pathFile, bool& bSkip) -{ - bSkip = false; - bool bRetry = false; - do - { - bRetry = false; - - if(!ReadFile(hFile, rBuffer, dwToRead, &rdwBytesRead, NULL)) - { - // log - DWORD dwLastError = GetLastError(); - - ictranslate::CFormat fmt; - fmt.SetFormat(_T("Error %errno while trying to read %count bytes from source file %path (CustomCopyFileFB)")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%count"), dwToRead); - fmt.SetParam(_t("%path"), pathFile.ToString()); - m_log.loge(fmt); - - FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eReadError, dwLastError }; - CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr); - switch(frResult) - { - case CFeedbackHandler::eResult_Cancel: - return eSubResult_CancelRequest; - - case CFeedbackHandler::eResult_Retry: - bRetry = true; - break; - - case CFeedbackHandler::eResult_Pause: - return eSubResult_PauseRequest; - - case CFeedbackHandler::eResult_Skip: - bSkip = true; - return eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW(_T("Unhandled case"), 0, 0, 0); - } - } - } - while(bRetry); - - return eSubResult_Continue; -} - -CTask::ESubOperationResult CTask::WriteFileFB(HANDLE hFile, CDataBuffer& rBuffer, DWORD dwToWrite, DWORD& rdwBytesWritten, const chcore::TSmartPath& pathFile, bool& bSkip) -{ - bSkip = false; - - bool bRetry = false; - do - { - bRetry = false; - - if(!WriteFile(hFile, rBuffer, dwToWrite, &rdwBytesWritten, NULL) || dwToWrite != rdwBytesWritten) - { - // log - DWORD dwLastError = GetLastError(); - - ictranslate::CFormat fmt; - fmt.SetFormat(_T("Error %errno while trying to write %count bytes to destination file %path (CustomCopyFileFB)")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%count"), dwToWrite); - fmt.SetParam(_t("%path"), pathFile.ToString()); - m_log.loge(fmt); - - FEEDBACK_FILEERROR ferr = { pathFile.ToString(), NULL, eWriteError, dwLastError }; - CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr); - switch(frResult) - { - case CFeedbackHandler::eResult_Cancel: - return eSubResult_CancelRequest; - - case CFeedbackHandler::eResult_Retry: - bRetry = true; - break; - - case CFeedbackHandler::eResult_Pause: - return eSubResult_PauseRequest; - - case CFeedbackHandler::eResult_Skip: - bSkip = true; - return eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW(_T("Unhandled case"), 0, 0, 0); - } - } - } - while(bRetry); - - return eSubResult_Continue; -} - -CTask::ESubOperationResult CTask::CustomCopyFileFB(CUSTOM_COPY_PARAMS* pData) -{ - TAutoFileHandle hSrc = INVALID_HANDLE_VALUE, - hDst = INVALID_HANDLE_VALUE; - ictranslate::CFormat fmt; - CTask::ESubOperationResult eResult = eSubResult_Continue; - bool bSkip = false; - - // 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 = (GetTaskPropValue(m_tTaskDefinition.GetConfiguration()) && - pData->spSrcFile->GetLength64() >= GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); - - // first open the source file and handle any failures - eResult = OpenSourceFileFB(hSrc, pData->spSrcFile, bNoBuffer); - if(eResult != eSubResult_Continue) - return eResult; - else if(hSrc == INVALID_HANDLE_VALUE) - { - // invalid handle = operation skipped by user - m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize()); - pData->bProcessed = false; - return eSubResult_Continue; - } - - // change attributes of a dest file - // NOTE: probably should be removed from here and report problems with read-only files - // directly to the user (as feedback request) - if(!GetTaskPropValue(m_tTaskDefinition.GetConfiguration())) - SetFileAttributes(pData->pathDstFile.ToString(), FILE_ATTRIBUTE_NORMAL); - - // open destination file, handle the failures and possibly existence of the destination file - unsigned long long ullSeekTo = 0; - bool bDstFileFreshlyCreated = false; - - if(m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize() == 0) - { - // open destination file for case, when we start operation on this file (i.e. it is not resume of the - // old operation) - eResult = OpenDestinationFileFB(hDst, pData->pathDstFile, bNoBuffer, pData->spSrcFile, ullSeekTo, bDstFileFreshlyCreated); - if(eResult != eSubResult_Continue) - return eResult; - else if(hDst == INVALID_HANDLE_VALUE) - { - m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize()); - pData->bProcessed = false; - return eSubResult_Continue; - } - } - else - { - // we are resuming previous operation - eResult = OpenExistingDestinationFileFB(hDst, pData->pathDstFile, bNoBuffer); - if(eResult != eSubResult_Continue) - return eResult; - else if(hDst == INVALID_HANDLE_VALUE) - { - m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize()); - pData->bProcessed = false; - return eSubResult_Continue; - } - - ullSeekTo = m_tTaskBasicProgressInfo.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 - { - // try to move file pointers to the end - ULONGLONG ullMove = (bNoBuffer ? ROUNDDOWN(ullSeekTo, MAXSECTORSIZE) : ullSeekTo); - - eResult = SetFilePointerFB(hSrc, ullMove, pData->spSrcFile->GetFullFilePath(), bSkip); - if(eResult != eSubResult_Continue) - return eResult; - else if(bSkip) - { - m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize()); - pData->bProcessed = false; - return eSubResult_Continue; - } - - eResult = SetFilePointerFB(hDst, ullMove, pData->pathDstFile, bSkip); - if(eResult != eSubResult_Continue) - return eResult; - else if(bSkip) - { - // with either first or second seek we got 'skip' answer... - m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize()); - pData->bProcessed = false; - return eSubResult_Continue; - } - - m_tTaskBasicProgressInfo.IncreaseCurrentFileProcessedSize(ullMove); - m_localStats.IncreaseProcessedSize(ullMove); - } - - // if the destination file already exists - truncate it to the current file position - if(!bDstFileFreshlyCreated) - { - // if destination file was opened (as opposed to newly created) - eResult = SetEndOfFileFB(hDst, pData->pathDstFile, bSkip); - if(eResult != eSubResult_Continue) - return eResult; - else if(bSkip) - { - pData->bProcessed = false; - return eSubResult_Continue; - } - } - - // copying - unsigned long ulToRead = 0; - unsigned long ulRead = 0; - unsigned long ulWritten = 0; - int iBufferIndex = 0; - bool bLastPart = false; - - 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().ToString()); - fmt.SetParam(_t("%dstpath"), pData->pathDstFile.ToString()); - m_log.logi(fmt); - return eSubResult_KillRequest; - } - - // recreate buffer if needed - if(m_cfgTracker.IsModified() && m_cfgTracker.IsModified(TOptionsSet() % eTO_DefaultBufferSize % eTO_OneDiskBufferSize % eTO_TwoDisksBufferSize % eTO_CDBufferSize % eTO_LANBufferSize % eTO_UseOnlyDefaultBuffer, true)) - { - BUFFERSIZES bs; - bs.m_bOnlyDefault = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bs.m_uiDefaultSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bs.m_uiOneDiskSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bs.m_uiTwoDisksSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bs.m_uiCDSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bs.m_uiLANSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - - // log - const BUFFERSIZES* pbs1 = pData->dbBuffer.GetSizes(); - - 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 (CustomCopyFileFB)")); - - 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"), bs.m_uiDefaultSize); - fmt.SetParam(_t("%onesize2"), bs.m_uiOneDiskSize); - fmt.SetParam(_t("%twosize2"), bs.m_uiTwoDisksSize); - fmt.SetParam(_t("%cdsize2"), bs.m_uiCDSize); - fmt.SetParam(_t("%lansize2"), bs.m_uiLANSize); - fmt.SetParam(_t("%srcfile"), pData->spSrcFile->GetFullFilePath().ToString()); - fmt.SetParam(_t("%dstfile"), pData->pathDstFile.ToString()); - - m_log.logi(fmt); - pData->dbBuffer.Create(&bs); - } - - // establish count of data to read - if(GetTaskPropValue(m_tTaskDefinition.GetConfiguration())) - iBufferIndex = BI_DEFAULT; - else - iBufferIndex = GetBufferIndex(pData->spSrcFile); - - ulToRead = bNoBuffer ? ROUNDUP(pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex], MAXSECTORSIZE) : pData->dbBuffer.GetSizes()->m_auiSizes[iBufferIndex]; - - // read data from file to buffer - eResult = ReadFileFB(hSrc, pData->dbBuffer, ulToRead, ulRead, pData->spSrcFile->GetFullFilePath(), bSkip); - if(eResult != eSubResult_Continue) - return eResult; - else if(bSkip) - { - m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize()); - pData->bProcessed = false; - return eSubResult_Continue; - } - - if(ulRead > 0) - { - // determine if this is the last chunk of data we could get from the source file (EOF condition) - bLastPart = (ulToRead != ulRead); - - // handle not aligned part at the end of file when no buffering is enabled - if(bNoBuffer && bLastPart) - { - // 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 - - // 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) - { - eResult = WriteFileFB(hDst, pData->dbBuffer, ulDataToWrite, ulWritten, pData->pathDstFile, bSkip); - if(eResult != eSubResult_Continue) - return eResult; - else if(bSkip) - { - m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize()); - pData->bProcessed = false; - return eSubResult_Continue; - } - - // increase count of processed data - m_tTaskBasicProgressInfo.IncreaseCurrentFileProcessedSize(ulWritten); - m_localStats.IncreaseProcessedSize(ulWritten); - - // calculate count of bytes left to be written - ulRead -= ulWritten; - - // now remove part of data from buffer (ulWritten bytes) - pData->dbBuffer.CutDataFromBuffer(ulWritten); - } - - // 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 - eResult = OpenExistingDestinationFileFB(hDst, pData->pathDstFile, false); - if(eResult != eSubResult_Continue) - return eResult; - else if(hDst == INVALID_HANDLE_VALUE) - { - m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize()); - pData->bProcessed = false; - return eSubResult_Continue; - } - - // move file pointer to the end of destination file - eResult = SetFilePointerFB(hDst, m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize(), pData->pathDstFile, bSkip); - if(eResult != eSubResult_Continue) - return eResult; - else if(bSkip) - { - // with either first or second seek we got 'skip' answer... - m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize()); - pData->bProcessed = false; - return eSubResult_Continue; - } - } - } - - // write - if(ulRead != 0) - { - eResult = WriteFileFB(hDst, pData->dbBuffer, ulRead, ulWritten, pData->pathDstFile, bSkip); - if(eResult != eSubResult_Continue) - return eResult; - else if(bSkip) - { - m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize()); - pData->bProcessed = false; - return eSubResult_Continue; - } - - // increase count of processed data - m_tTaskBasicProgressInfo.IncreaseCurrentFileProcessedSize(ulRead); - m_localStats.IncreaseProcessedSize(ulRead); - } - } - } - while(ulRead != 0 && !bLastPart); - } - else - { - // we don't copy contents, but need to increase processed size - m_localStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tTaskBasicProgressInfo.GetCurrentFileProcessedSize()); - } - - pData->bProcessed = true; - m_tTaskBasicProgressInfo.SetCurrentFileProcessedSize(0); - - return eSubResult_Continue; -} - -// function processes files/folders -CTask::ESubOperationResult CTask::ProcessFiles() -{ - // log - m_log.logi(_T("Processing files/folders (ProcessFiles)")); - - // count how much has been done (updates also a member in CTaskArray) - CalculateProcessedSize(); - - // begin at index which wasn't processed previously - size_t stSize = m_files.GetSize(); - bool bIgnoreFolders = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bool bForceDirectories = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - - // create a buffer of size m_nBufferSize - CUSTOM_COPY_PARAMS ccp; - ccp.bProcessed = false; - ccp.bOnlyCreate = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - - // remove changes in buffer sizes to avoid re-creation later - m_cfgTracker.RemoveModificationSet(TOptionsSet() % eTO_DefaultBufferSize % eTO_OneDiskBufferSize % eTO_TwoDisksBufferSize % eTO_CDBufferSize % eTO_LANBufferSize % eTO_UseOnlyDefaultBuffer); - - BUFFERSIZES bs; - bs.m_bOnlyDefault = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bs.m_uiDefaultSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bs.m_uiOneDiskSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bs.m_uiTwoDisksSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bs.m_uiCDSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - bs.m_uiLANSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - - ccp.dbBuffer.Create(&bs); - - // helpers - DWORD dwLastError = 0; - - // log - const BUFFERSIZES* pbs = ccp.dbBuffer.GetSizes(); - - ictranslate::CFormat fmt; - fmt.SetFormat(_T("Processing files/folders (ProcessFiles):\r\n\tOnlyCreate: %create\r\n\tBufferSize: [Def:%defsize, One:%onesize, Two:%twosize, CD:%cdsize, LAN:%lansize]\r\n\tFiles/folders count: %filecount\r\n\tIgnore Folders: %ignorefolders\r\n\tDest path: %dstpath\r\n\tCurrent index (0-based): %currindex")); - 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"), stSize); - fmt.SetParam(_t("%ignorefolders"), bIgnoreFolders); - fmt.SetParam(_t("%dstpath"), m_tTaskDefinition.GetDestinationPath().ToString()); - fmt.SetParam(_t("%currindex"), m_tTaskBasicProgressInfo.GetCurrentIndex()); - - m_log.logi(fmt); - - for(size_t stIndex = m_tTaskBasicProgressInfo.GetCurrentIndex(); stIndex < stSize; stIndex++) - { - // should we kill ? - if(m_workerThread.KillRequested()) - { - // log - m_log.logi(_T("Kill request while processing file in ProcessFiles")); - return eSubResult_KillRequest; - } - - // update m_stNextIndex, getting current CFileInfo - CFileInfoPtr spFileInfo = m_files.GetAt(m_tTaskBasicProgressInfo.GetCurrentIndex()); - - // set dest path with filename - ccp.pathDstFile = GetDestinationPath(spFileInfo, m_tTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1 | (int)bIgnoreFolders); - - // are the files/folders lie on the same partition ? - int iDstDriveNumber = 0; - bool bMove = m_tTaskDefinition.GetOperationType() == eOperation_Move; - if(bMove) - GetDriveData(m_tTaskDefinition.GetDestinationPath(), &iDstDriveNumber, NULL); - if(bMove && iDstDriveNumber != -1 && iDstDriveNumber == GetDriveNumber(spFileInfo) && GetMove(spFileInfo)) - { - bool bRetry = true; - if(bRetry && !MoveFile(spFileInfo->GetFullFilePath().ToString(), ccp.pathDstFile.ToString())) - { - dwLastError=GetLastError(); - //log - fmt.SetFormat(_T("Error %errno while calling MoveFile %srcpath -> %dstpath (ProcessFiles)")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%srcpath"), spFileInfo->GetFullFilePath().ToString()); - fmt.SetParam(_t("%dstpath"), ccp.pathDstFile.ToString()); - m_log.loge(fmt); - - FEEDBACK_FILEERROR ferr = { spFileInfo->GetFullFilePath().ToString(), ccp.pathDstFile.ToString(), eFastMoveError, dwLastError }; - CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr); - switch(frResult) - { - case CFeedbackHandler::eResult_Cancel: - return eSubResult_CancelRequest; - - case CFeedbackHandler::eResult_Retry: - continue; - - case CFeedbackHandler::eResult_Pause: - return eSubResult_PauseRequest; - - case CFeedbackHandler::eResult_Skip: - bRetry = false; - break; // just do nothing - default: - BOOST_ASSERT(FALSE); // unknown result - THROW(_T("Unhandled case"), 0, 0, 0); - } - } - else - spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED); - } - else - { - // if folder - create it - if(spFileInfo->IsDirectory()) - { - bool bRetry = true; - if(bRetry && !CreateDirectory(ccp.pathDstFile.ToString(), NULL) && (dwLastError=GetLastError()) != ERROR_ALREADY_EXISTS ) - { - // log - fmt.SetFormat(_T("Error %errno while calling CreateDirectory %path (ProcessFiles)")); - fmt.SetParam(_t("%errno"), dwLastError); - fmt.SetParam(_t("%path"), ccp.pathDstFile.ToString()); - m_log.loge(fmt); - - FEEDBACK_FILEERROR ferr = { ccp.pathDstFile.ToString(), NULL, eCreateError, dwLastError }; - CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr); - switch(frResult) - { - case CFeedbackHandler::eResult_Cancel: - return eSubResult_CancelRequest; - - case CFeedbackHandler::eResult_Retry: - continue; - - case CFeedbackHandler::eResult_Pause: - return eSubResult_PauseRequest; - - case CFeedbackHandler::eResult_Skip: - bRetry = false; - break; // just do nothing - default: - BOOST_ASSERT(FALSE); // unknown result - THROW(_T("Unhandled case"), 0, 0, 0); - } - } - - m_localStats.IncreaseProcessedSize(spFileInfo->GetLength64()); - spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED); - } - else - { - // start copying/moving file - ccp.spSrcFile = spFileInfo; - ccp.bProcessed = false; - - // kopiuj dane - ESubOperationResult eResult = CustomCopyFileFB(&ccp); - if(eResult != eSubResult_Continue) - return eResult; - - spFileInfo->SetFlags(ccp.bProcessed ? FIF_PROCESSED : 0, FIF_PROCESSED); - - // if moving - delete file (only if config flag is set) - if(bMove && spFileInfo->GetFlags() & FIF_PROCESSED && !GetTaskPropValue(m_tTaskDefinition.GetConfiguration())) - { - if(!GetTaskPropValue(m_tTaskDefinition.GetConfiguration())) - SetFileAttributes(spFileInfo->GetFullFilePath().ToString(), FILE_ATTRIBUTE_NORMAL); - DeleteFile(spFileInfo->GetFullFilePath().ToString()); // there will be another try later, so I don't check - // if succeeded - } - } - - // set a time - if(GetTaskPropValue(m_tTaskDefinition.GetConfiguration())) - SetFileDirectoryTime(ccp.pathDstFile.ToString(), spFileInfo); // no error checking (but most probably it should be checked) - - // attributes - if(GetTaskPropValue(m_tTaskDefinition.GetConfiguration())) - SetFileAttributes(ccp.pathDstFile.ToString(), spFileInfo->GetAttributes()); // as above - } - - m_tTaskBasicProgressInfo.SetCurrentIndex(stIndex + 1); - } - - // delete buffer - it's not needed - ccp.dbBuffer.Delete(); - - // to look better (as 100%) - increase current index by 1 - m_tTaskBasicProgressInfo.SetCurrentIndex(stSize); - - // log - m_log.logi(_T("Finished processing in ProcessFiles")); - - return eSubResult_Continue; -} - -CTask::ESubOperationResult CTask::CheckForWaitState() -{ // limiting operation count SetTaskState(eTaskState_Waiting); bool bContinue = false; @@ -2248,14 +678,14 @@ { // log m_log.logi(_T("Kill request while waiting for begin permission (wait state)")); - return eSubResult_KillRequest; + return TSubTaskBase::eSubResult_KillRequest; } } - return eSubResult_Continue; + return TSubTaskBase::eSubResult_Continue; } -CTask::ESubOperationResult CTask::CheckForFreeSpaceFB() +TSubTaskBase::ESubOperationResult CTask::CheckForFreeSpaceFB() { ull_t ullNeededSize = 0, ullAvailableSize = 0; bool bRetry = false; @@ -2284,7 +714,7 @@ { case CFeedbackHandler::eResult_Cancel: m_log.logi(_T("Cancel request while checking for free space on disk.")); - return eSubResult_CancelRequest; + return TSubTaskBase::eSubResult_CancelRequest; case CFeedbackHandler::eResult_Retry: m_log.logi(_T("Retrying to read drive's free space...")); @@ -2293,7 +723,7 @@ case CFeedbackHandler::eResult_Ignore: m_log.logi(_T("Ignored warning about not enough place on disk to copy data.")); - return eSubResult_Continue; + return TSubTaskBase::eSubResult_Continue; default: BOOST_ASSERT(FALSE); // unknown result @@ -2304,7 +734,7 @@ } while(bRetry); - return eSubResult_Continue; + return TSubTaskBase::eSubResult_Continue; } DWORD WINAPI CTask::DelegateThreadProc(LPVOID pParam) @@ -2321,7 +751,7 @@ { try { - CTask::ESubOperationResult eResult = eSubResult_Continue; + TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue; // initialize log file CString strPath = GetRelatedPath(ePathType_TaskLogFile); @@ -2350,7 +780,10 @@ // start tracking time for this thread m_localStats.EnableTimeTracking(); - for(; stSubOperationIndex < m_tTaskDefinition.GetOperationPlan().GetSubOperationsCount() && eResult == eSubResult_Continue; ++stSubOperationIndex) + // prepare context for subtasks + TSubTaskContext tSubTaskContext(m_tTaskDefinition, m_arrSourcePathsInfo, m_files, m_localStats, m_tTaskBasicProgressInfo, m_cfgTracker, m_log, m_piFeedbackHandler, m_workerThread); + + for(; stSubOperationIndex < m_tTaskDefinition.GetOperationPlan().GetSubOperationsCount() && eResult == TSubTaskBase::eSubResult_Continue; ++stSubOperationIndex) { // set current sub-operation index to allow resuming m_tTaskBasicProgressInfo.SetSubOperationIndex(stSubOperationIndex); @@ -2359,33 +792,41 @@ switch(eSubOperation) { case eSubOperation_Scanning: - // get rid of info about processed sizes - m_localStats.SetProcessedSize(0); - m_localStats.SetTotalSize(0); + { + // get rid of info about processed sizes + m_localStats.SetProcessedSize(0); + m_localStats.SetTotalSize(0); - // start searching - eResult = RecurseDirectories(); + // start searching + TSubTaskScanDirectories tSubTaskScanDir(tSubTaskContext); + //eResult = RecurseDirectories(); + eResult = tSubTaskScanDir.Exec(); - // check for free space - if(eResult == eSubResult_Continue) - eResult = CheckForFreeSpaceFB(); + // check for free space + if(eResult == TSubTaskBase::eSubResult_Continue) + eResult = CheckForFreeSpaceFB(); - // if we didn't wait for permission to start earlier, then ask now (but only in case this is the first search) - if(eResult == eSubResult_Continue && bReadTasksSize && stSubOperationIndex == 0) - { - m_localStats.DisableTimeTracking(); + // if we didn't wait for permission to start earlier, then ask now (but only in case this is the first search) + if(eResult == TSubTaskBase::eSubResult_Continue && bReadTasksSize && stSubOperationIndex == 0) + { + m_localStats.DisableTimeTracking(); - eResult = CheckForWaitState(); + eResult = CheckForWaitState(); - m_localStats.EnableTimeTracking(); - } + m_localStats.EnableTimeTracking(); + } - break; + break; + } case eSubOperation_Copying: - eResult = ProcessFiles(); - break; + { + TSubTaskCopyMove tSubTaskCopyMove(tSubTaskContext); + eResult = tSubTaskCopyMove.Exec(); + break; + } + case eSubOperation_Deleting: eResult = DeleteFiles(); break; @@ -2403,26 +844,26 @@ // change task status switch(eResult) { - case eSubResult_Error: + case TSubTaskBase::eSubResult_Error: m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_OperationError, NULL); SetTaskState(eTaskState_Error); break; - case eSubResult_CancelRequest: + case TSubTaskBase::eSubResult_CancelRequest: SetTaskState(eTaskState_Cancelled); break; - case eSubResult_PauseRequest: + case TSubTaskBase::eSubResult_PauseRequest: SetTaskState(eTaskState_Paused); break; - case eSubResult_KillRequest: + case TSubTaskBase::eSubResult_KillRequest: // the only operation if(GetTaskState() == eTaskState_Waiting) SetTaskState(eTaskState_Processing); break; - case eSubResult_Continue: + case TSubTaskBase::eSubResult_Continue: m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_OperationFinished, NULL); SetTaskState(eTaskState_Finished); break; @@ -2572,220 +1013,6 @@ } } -// finds another name for a copy of src file(folder) in dest location -chcore::TSmartPath CTask::FindFreeSubstituteName(chcore::TSmartPath pathSrcPath, chcore::TSmartPath pathDstPath) const -{ - // get the name from srcpath - pathSrcPath.StripSeparatorAtEnd(); - - chcore::TSmartPath pathFilename = pathSrcPath.GetFileName(); - - // set the dest path - CString strCheckPath; - ictranslate::CFormat fmt(GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); - fmt.SetParam(_t("%name"), pathFilename.ToString()); - chcore::TSmartPath pathCheckPath(chcore::PathFromString((PCTSTR)fmt)); - - // when adding to strDstPath check if the path already exists - if so - try again - int iCounter=1; - CString strFmt = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); - while(PathExist(pathDstPath + pathCheckPath)) - { - fmt.SetFormat(strFmt); - fmt.SetParam(_t("%name"), pathFilename.ToString()); - fmt.SetParam(_t("%count"), ++iCounter); - pathCheckPath.FromString((PCTSTR)fmt); - } - - return pathCheckPath; -} - -chcore::TSmartPath CTask::GetDestinationPath(const CFileInfoPtr& spFileInfo, chcore::TSmartPath pathDst, int iFlags) const -{ - if(!spFileInfo) - THROW(_T("Invalid pointer"), 0, 0, 0); - - // iFlags: bit 0-ignore folders; bit 1-force creating directories - if (iFlags & 0x02) - { - // force create directories - chcore::TSmartPath pathCombined = pathDst + spFileInfo->GetFullFilePath().GetFileDir(); - - // force create directory - SHCreateDirectoryEx(NULL, pathCombined.ToString(), NULL); - - return pathCombined + spFileInfo->GetFullFilePath().GetFileName(); - } - else - { - size_t stSrcIndex = spFileInfo->GetSrcIndex(); - - if (!(iFlags & 0x01) && stSrcIndex != std::numeric_limits::max()) - { - // generate new dest name - if(!m_arrSourcePathsInfo.GetAt(stSrcIndex)->IsDestinationPathSet()) - { - chcore::TSmartPath pathSubst = FindFreeSubstituteName(spFileInfo->GetFullFilePath(), pathDst); - m_arrSourcePathsInfo.GetAt(stSrcIndex)->SetDestinationPath(pathSubst); - } - - return pathDst + m_arrSourcePathsInfo.GetAt(stSrcIndex)->GetDestinationPath() + spFileInfo->GetFilePath(); - } - else - return pathDst + spFileInfo->GetFullFilePath().GetFileName(); - } -} - -int CTask::GetBufferIndex(const CFileInfoPtr& spFileInfo) -{ - if(!spFileInfo) - THROW(_T("Invalid pointer"), 0, 0, 0); - if(spFileInfo->GetSrcIndex() == std::numeric_limits::max()) - THROW(_T("Received non-relative (standalone) path info"), 0, 0, 0); - - // check if this information has already been stored - size_t stBaseIndex = spFileInfo->GetSrcIndex(); - if(stBaseIndex >= m_arrSourcePathsInfo.GetCount()) - THROW(_T("Index out of bounds"), 0, 0, 0); - - TBasePathDataPtr spPathData = m_arrSourcePathsInfo.GetAt(stBaseIndex); - if(spPathData->IsBufferIndexSet()) - return spPathData->GetBufferIndex(); - - // buffer index wasn't cached previously - read it now - int iDriveNumber = 0; - UINT uiDriveType = 0; - int iDstDriveNumber = 0; - UINT uiDstDriveType = 0; - GetDriveData(m_tTaskDefinition.GetSourcePathAt(stBaseIndex), &iDriveNumber, &uiDriveType); - GetDriveData(m_tTaskDefinition.GetDestinationPath(), &iDstDriveNumber, &uiDstDriveType); - - // what kind of buffer - int iBufferIndex = BI_DEFAULT; - if(uiDriveType == DRIVE_REMOTE || uiDstDriveType == DRIVE_REMOTE) - iBufferIndex = BI_LAN; - else if(uiDriveType == DRIVE_CDROM || uiDstDriveType == DRIVE_CDROM) - iBufferIndex = BI_CD; - else if(uiDriveType == DRIVE_FIXED && uiDstDriveType == DRIVE_FIXED) - { - // two hdd's - is this the same physical disk ? - if(iDriveNumber == iDstDriveNumber || IsSamePhysicalDisk(iDriveNumber, iDstDriveNumber)) - iBufferIndex = BI_ONEDISK; - else - iBufferIndex = BI_TWODISKS; - } - else - iBufferIndex = BI_DEFAULT; - - spPathData->SetBufferIndex(iBufferIndex); - - return iBufferIndex; -} - -int CTask::GetDriveNumber(const CFileInfoPtr& spFileInfo) -{ - if(!spFileInfo) - THROW(_T("Invalid pointer"), 0, 0, 0); - if(spFileInfo->GetSrcIndex() == std::numeric_limits::max()) - THROW(_T("Received non-relative (standalone) path info"), 0, 0, 0); - - // check if this information has already been stored - size_t stBaseIndex = spFileInfo->GetSrcIndex(); - if(stBaseIndex >= m_arrSourcePathsInfo.GetCount()) - THROW(_T("Index out of bounds"), 0, 0, 0); - - TBasePathDataPtr spPathData = m_arrSourcePathsInfo.GetAt(stBaseIndex); - if(spPathData->IsDriveNumberSet()) - return spPathData->GetDriveNumber(); - - // buffer index wasn't cached previously - read it now - int iDriveNumber = 0; - GetDriveData(m_tTaskDefinition.GetSourcePathAt(stBaseIndex), &iDriveNumber, NULL); - - spPathData->SetDriveNumber(iDriveNumber); - - return iDriveNumber; -} - -bool CTask::GetMove(const CFileInfoPtr& spFileInfo) -{ - if(!spFileInfo) - THROW(_T("Invalid pointer"), 0, 0, 0); - if(spFileInfo->GetSrcIndex() == std::numeric_limits::max()) - THROW(_T("Received non-relative (standalone) path info"), 0, 0, 0); - - // check if this information has already been stored - size_t stBaseIndex = spFileInfo->GetSrcIndex(); - if(stBaseIndex >= m_arrSourcePathsInfo.GetCount()) - THROW(_T("Index out of bounds"), 0, 0, 0); - - TBasePathDataPtr spPathData = m_arrSourcePathsInfo.GetAt(stBaseIndex); - return spPathData->GetMove(); -} - -void CTask::GetDriveData(const chcore::TSmartPath& spPath, int* piDrvNum, UINT* puiDrvType) -{ - TCHAR drv[_MAX_DRIVE+1]; - - _tsplitpath(spPath.ToString(), drv, NULL, NULL, NULL); - if(lstrlen(drv) != 0) - { - // add '\\' - lstrcat(drv, _T("\\")); - _tcsupr(drv); - - // disk number - if(piDrvNum) - *piDrvNum=drv[0]-_T('A'); - - // disk type - if(puiDrvType) - { - *puiDrvType=GetDriveType(drv); - if(*puiDrvType == DRIVE_NO_ROOT_DIR) - *puiDrvType=DRIVE_UNKNOWN; - } - } - else - { - // there's no disk in a path - if(piDrvNum) - *piDrvNum=-1; - - if(puiDrvType) - { - // check for unc path - if(_tcsncmp(spPath.ToString(), _T("\\\\"), 2) == 0) - *puiDrvType=DRIVE_REMOTE; - else - *puiDrvType=DRIVE_UNKNOWN; - } - } -} - -bool CTask::PathExist(chcore::TSmartPath pathToCheck) -{ - WIN32_FIND_DATA fd; - - // search by exact name - HANDLE hFind = FindFirstFile(pathToCheck.ToString(), &fd); - if(hFind != INVALID_HANDLE_VALUE) - return true; - - // another try (add '\\' if needed and '*' for marking that we look for ie. c:\* - // instead of c:\, which would never be found prev. way) - pathToCheck.AppendIfNotExists(_T("*"), false); - - hFind = FindFirstFile(pathToCheck.ToString(), &fd); - if(hFind != INVALID_HANDLE_VALUE) - { - ::FindClose(hFind); - return true; - } - else - return false; -} - //////////////////////////////////////////////////////////////////////////////// // CTaskArray members CTaskArray::CTaskArray() :