123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- // FileCopy.cpp: implementation of the CFileCopy class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "FileCopyDemo.h"
- #include "FileCopy.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- #include <Windows.h>
- #include <strsafe.h>
- #include <process.h>
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- class CAutoLock
- {
- private:
- LPCRITICAL_SECTION m_pcsLcok;
-
- public:
- CAutoLock(LPCRITICAL_SECTION pcsLcok)
- {
- m_pcsLcok = pcsLcok;
- if (m_pcsLcok)
- {
- EnterCriticalSection(m_pcsLcok);
- }
- }
-
- ~CAutoLock()
- {
- if (m_pcsLcok)
- {
- LeaveCriticalSection(m_pcsLcok);
- m_pcsLcok = NULL;
- }
- }
- };
- class CStopwatch
- {
- public:
- CStopwatch()
- {
- QueryPerformanceFrequency(&m_liPerfFreq);
- Start();
- }
-
- void Start()
- {
- QueryPerformanceCounter(&m_liPerfStart);
- }
-
- __int64 Now() const
- {
- LARGE_INTEGER liPerfNow;
- QueryPerformanceCounter(&liPerfNow);
-
- return (liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000 / m_liPerfFreq.QuadPart;
- }
-
- __int64 NowInMicro() const
- {
- LARGE_INTEGER liPerfNow;
- QueryPerformanceCounter(&liPerfNow);
-
- return (liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000000 / m_liPerfFreq.QuadPart;
- }
- private:
- LARGE_INTEGER m_liPerfFreq; //counter per second
- LARGE_INTEGER m_liPerfStart; //starting count
- };
- CFileCopy::CFileCopy()
- {
- m_bCancel = FALSE;
- m_dw64TotalFileSize = 0;
- m_dw64TotalBytesTransferred = 0;
- m_bIsCoping = FALSE;
- m_hPauseEvent = NULL;
- m_hFeedbackExitEvent = NULL;
- m_hAsyncCopyThreadHandle = NULL;
- m_hFeedbackProgressThreadHandle = NULL;
- m_pUserData = NULL;
- m_pAsyncCopyResultCB = NULL;
- m_pCopingProgressCB = NULL;
- m_dwProgressFeedbackTime = 0;
- InitializeCriticalSection(&m_csLock);
- }
- CFileCopy::~CFileCopy()
- {
- Cancel();
- DeleteCriticalSection(&m_csLock);
- }
- BOOL CFileCopy::CopyFile(IN LPCTSTR lpSrcFileName,
- IN LPCTSTR lpDesFileName,
- IN const BOOL bSynchronousCopy,
- IN const DWORD dwProgressFeedbackTime,
- OUT DOUBLE &dbSpeed,
- OUT tstring &strErrorMsg)
- {
- {
- CAutoLock autolock(&m_csLock);
- if (m_bIsCoping)
- {
- strErrorMsg = _T("In coping.");
- return FALSE;
- }
- m_bIsCoping = TRUE;
- }
- // 同步复制
- if (bSynchronousCopy)
- {
- m_dwProgressFeedbackTime = dwProgressFeedbackTime;
- BOOL bRet = SynchronousCopyFile(
- lpSrcFileName,
- lpDesFileName,
- dwProgressFeedbackTime,
- dbSpeed,
- strErrorMsg
- );
- m_bIsCoping = FALSE;
- return bRet;
- }
- // 异步复制
- m_strSrcFile = lpSrcFileName;
- m_strDesFile = lpDesFileName;
- m_dwProgressFeedbackTime = dwProgressFeedbackTime;
- unsigned threadID = 0;
- m_hAsyncCopyThreadHandle =
- (HANDLE)_beginthreadex(NULL, 0, &AsyncCopyThreadFunc, this, 0, &threadID);
- if (NULL == m_hAsyncCopyThreadHandle)
- {
- strErrorMsg = GetLastErrorMsg(_T("_beginthreadex"), GetLastError());
- return FALSE;
- }
- return TRUE;
- }
- BOOL CFileCopy::SynchronousCopyFile(LPCTSTR lpSrcFileName,
- LPCTSTR lpDesFileName,
- const DWORD dwProgressFeedbackTime,
- DOUBLE &dbSpeed,
- tstring &strErrorMsg)
- {
- m_bCancel = FALSE;
- m_dw64TotalFileSize = 0;
- m_dw64TotalBytesTransferred = 0;
- if (NULL == (m_hPauseEvent = CreateEvent(NULL, TRUE, TRUE, NULL)))
- {
- strErrorMsg = GetLastErrorMsg(_T("CreateEvent"), GetLastError());
- return FALSE;
- }
- if (0 != dwProgressFeedbackTime)
- {
- if (NULL == (m_hFeedbackExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
- {
- strErrorMsg = GetLastErrorMsg(_T("CreateEvent"), GetLastError());
- CloseAllHandles();
- return FALSE;
- }
- unsigned threadID = 0;
- m_hFeedbackProgressThreadHandle =
- (HANDLE)_beginthreadex(NULL, 0, &FeedbackProgressThreadFunc, this, 0, &threadID);
- if (NULL == m_hFeedbackProgressThreadHandle)
- {
- strErrorMsg = GetLastErrorMsg(_T("_beginthreadex"), GetLastError());
- CloseAllHandles();
- return FALSE;
- }
- }
- CStopwatch stopwatch;
- BOOL bRet = CopyFileEx(lpSrcFileName,
- lpDesFileName,
- CopyProgressRoutine,
- this,
- &m_bCancel,
- COPY_FILE_ALLOW_DECRYPTED_DESTINATION | COPY_FILE_FAIL_IF_EXISTS);
- if (!bRet)
- {
- strErrorMsg = GetLastErrorMsg(_T("CopyFileEx"), GetLastError());
- }
- else
- {
- // 成功了才需计算速度
- __int64 n64ElapseTimeInMs = stopwatch.Now();
- dbSpeed = (DOUBLE)(__int64)m_dw64TotalFileSize / n64ElapseTimeInMs;
- }
- if (0 != dwProgressFeedbackTime)
- {
- SetEvent(m_hFeedbackExitEvent);
- WaitForSingleObject(m_hFeedbackProgressThreadHandle, INFINITE);
- }
-
- CloseAllHandles();
-
- return bRet;
- }
- DWORD CALLBACK CFileCopy::CopyProgressRoutine(
- LARGE_INTEGER TotalFileSize,
- LARGE_INTEGER TotalBytesTransferred,
- LARGE_INTEGER StreamSize,
- LARGE_INTEGER StreamBytesTransferred,
- DWORD dwStreamNumber,
- DWORD dwCallbackReason,
- HANDLE hSourceFile,
- HANDLE hDestinationFile,
- LPVOID lpData
- )
- {
- CFileCopy *pFileCopy = (CFileCopy *)lpData;
- if (!pFileCopy)
- {
- return PROGRESS_CANCEL;
- }
- pFileCopy->m_dw64TotalFileSize = TotalFileSize.QuadPart;
- pFileCopy->m_dw64TotalBytesTransferred = TotalBytesTransferred.QuadPart;
- // 用于控制暂停
- WaitForSingleObject(pFileCopy->m_hPauseEvent, INFINITE);
- return PROGRESS_CONTINUE;
- }
- tstring CFileCopy::GetLastErrorMsg(LPCTSTR lpszFunction, const DWORD dwLastError)
- {
- LPVOID lpMsgBuf = NULL;
- LPVOID lpDisplayBuf = NULL;
-
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- dwLastError,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf,
- 0, NULL );
-
- lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
- (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
- StringCchPrintf((LPTSTR)lpDisplayBuf,
- LocalSize(lpDisplayBuf) / sizeof(TCHAR),
- TEXT("%s failed with error %d: %s"),
- lpszFunction, dwLastError, lpMsgBuf);
-
- tstring strLastError = (LPTSTR)lpDisplayBuf;
-
- LocalFree(lpMsgBuf);
- LocalFree(lpDisplayBuf);
-
- return strLastError;
- }
- void CFileCopy::CloseAllHandles()
- {
- if (m_hPauseEvent)
- {
- CloseHandle(m_hPauseEvent);
- m_hPauseEvent = NULL;
- }
- if (m_hFeedbackExitEvent)
- {
- CloseHandle(m_hFeedbackExitEvent);
- m_hFeedbackExitEvent = NULL;
- }
- if (m_hAsyncCopyThreadHandle)
- {
- CloseHandle(m_hAsyncCopyThreadHandle);
- m_hAsyncCopyThreadHandle = NULL;
- }
- if (m_hFeedbackProgressThreadHandle)
- {
- CloseHandle(m_hFeedbackProgressThreadHandle);
- m_hFeedbackProgressThreadHandle = NULL;
- }
- }
- void CFileCopy::Pause()
- {
- if (m_hPauseEvent)
- {
- ResetEvent(m_hPauseEvent);
- }
- }
- void CFileCopy::Resume()
- {
- if (m_hPauseEvent)
- {
- SetEvent(m_hPauseEvent);
- }
- }
- void CFileCopy::Cancel()
- {
- m_bCancel = TRUE;
- Resume();
- }
- unsigned CFileCopy::AsyncCopy()
- {
- unsigned usRet = 1;
-
- DOUBLE dbSpeed = 0.0;
- tstring strErrorMsg;
-
- BOOL bCopySuccess = SynchronousCopyFile(
- m_strSrcFile.c_str(),
- m_strDesFile.c_str(),
- m_dwProgressFeedbackTime,
- dbSpeed,
- strErrorMsg
- );
- if (m_pAsyncCopyResultCB)
- {
- m_pAsyncCopyResultCB(m_pUserData, bCopySuccess, dbSpeed, strErrorMsg);
- }
- m_bIsCoping = FALSE;
-
- return usRet;
- }
- unsigned CFileCopy::AsyncCopyThreadFunc(void* pArguments)
- {
- CFileCopy *pThis = (CFileCopy *)pArguments;
- if (NULL == pThis)
- {
- _endthreadex (1);
- return 1;
- }
-
- unsigned usRet = pThis->AsyncCopy();
- _endthreadex (usRet);
- return usRet;
- }
- unsigned CFileCopy::FeedbackProgress()
- {
- unsigned usRet = 1;
- DWORD64 dw64TotalBytesTransferred = 0;
- DWORD64 dw64TotalBytesTransferredBak = 0;
- DOUBLE dbSpeed = 0.0;
- DWORD dwPercentage = 0;
- __int64 n64ElapseTimeInMs = 0;
- __int64 n64UsedTimeInMs = 0;
- __int64 n64NowInMs = 0;
- CStopwatch stopwatch;
- while (WAIT_TIMEOUT == WaitForSingleObject(m_hFeedbackExitEvent, m_dwProgressFeedbackTime))
- {
- n64NowInMs = stopwatch.Now();
- dw64TotalBytesTransferred = m_dw64TotalBytesTransferred;
- n64ElapseTimeInMs = n64NowInMs - n64UsedTimeInMs;
- n64UsedTimeInMs = n64NowInMs;
- if (0 == n64ElapseTimeInMs)
- {
- dbSpeed = 0.0;
- }
- else
- {
- dbSpeed = (DOUBLE)(__int64)(dw64TotalBytesTransferred - dw64TotalBytesTransferredBak)
- / n64ElapseTimeInMs;
- }
- dw64TotalBytesTransferredBak = dw64TotalBytesTransferred;
-
- if (0 == m_dw64TotalFileSize)
- {
- dwPercentage = 0;
- }
- else
- {
- dwPercentage = m_dw64TotalBytesTransferred * 100 / m_dw64TotalFileSize;
- }
- if (m_pCopingProgressCB)
- {
- m_pCopingProgressCB(m_pUserData, dbSpeed, dwPercentage);
- }
- }
-
- return usRet;
- }
- unsigned CFileCopy::FeedbackProgressThreadFunc(void* pArguments)
- {
- CFileCopy *pThis = (CFileCopy *)pArguments;
- if (NULL == pThis)
- {
- _endthreadex (1);
- return 1;
- }
-
- unsigned usRet = pThis->FeedbackProgress();
- _endthreadex (usRet);
- return usRet;
- }
|