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