// CopyFileThread.cpp : implementation file
//

#include "stdafx.h"
#include "proofclient.h"
#include "CopyFileThread.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CCopyFileThread

IMPLEMENT_DYNCREATE(CCopyFileThread, CWinThread)

CCopyFileThread::CCopyFileThread()
: m_strSource(""), m_strDest("")
{
        m_pNotifyWnd=NULL;
        m_bAutoDelete=FALSE;
}

CCopyFileThread::~CCopyFileThread()
{
}

BOOL CCopyFileThread::InitInstance()
{
        return TRUE;
}

int CCopyFileThread::ExitInstance()
{
        return CWinThread::ExitInstance();
}

BEGIN_MESSAGE_MAP(CCopyFileThread, CWinThread)
        //{{AFX_MSG_MAP(CCopyFileThread)
                // NOTE - the ClassWizard will add and remove mapping macros here.
        //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCopyFileThread message handlers
// this static function encapsulates the thread creation stuff...
CCopyFileThread * CCopyFileThread::CreateCopyThread(LPCSTR szSrc, LPCSTR szDest, CWnd *pNotifyWnd /*= NULL*/)
{
        CCopyFileThread *pThread = (CCopyFileThread*)AfxBeginThread(RUNTIME_CLASS(CCopyFileThread), 
                                                                    THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
        if (pThread!=NULL)
        {
                pThread->Init(szSrc, szDest, pNotifyWnd);
                pThread->ResumeThread();
        }
        return pThread;
}
DWORD WINAPI CCopyFileThread::CopyProgressRoutine(LARGE_INTEGER TotalFileSize, 
                                                                 LARGE_INTEGER TotalBytesTransferred, 
                                                                 LARGE_INTEGER StreamSize, 
                                                                 LARGE_INTEGER StreamBytesTransferred, 
                                                                 DWORD dwStreamNumber, 
                                                                 DWORD dwCallbackReason, 
                                                                 HANDLE hSourceFile, 
                                                                 HANDLE hDestinationFile, 
                                                                 LPVOID lpData )
{
        CCopyFileThread *pThis = (CCopyFileThread *)lpData;
        if (dwCallbackReason == CALLBACK_CHUNK_FINISHED)
        {
                TRACE("CB: size=%ld, total=%ld\n",
                        TotalFileSize.LowPart, TotalBytesTransferred.LowPart);
                if (pThis->m_pNotifyWnd)
                {
                        double dval = (double)TotalBytesTransferred.LowPart / (double)TotalFileSize.LowPart;
                        dval *= 100;
                        pThis->m_pNotifyWnd->SendNotifyMessage(WM_USER_THREAD_MSG, COPYTHREAD_PROGRESS, (LPARAM)dval);
                }
        }

        if (WaitForSingleObject(pThis->m_evAbort, 0) == WAIT_OBJECT_0)
                return PROGRESS_CANCEL;
        Sleep(0);
        return PROGRESS_CONTINUE;
}


int CCopyFileThread::Run() 
{
        BOOL bCancel=FALSE;
        if (m_pNotifyWnd)
                m_pNotifyWnd->SendNotifyMessage(WM_USER_THREAD_MSG, COPYTHREAD_START, 0L);
        
        if (CopyFileEx(m_strSource, 
                                        m_strDest,
                                        CopyProgressRoutine, 
                                        (LPVOID)this,
                                        &bCancel, 
                                        COPY_FILE_RESTARTABLE)
                && m_pNotifyWnd)
                m_pNotifyWnd->SendNotifyMessage(WM_USER_THREAD_MSG, COPYTHREAD_DONE, 0L);
        else if (m_pNotifyWnd)
                m_pNotifyWnd->SendNotifyMessage(WM_USER_THREAD_MSG, COPYTHREAD_ABORT, 0L);

        m_evExit.SetEvent();
        return TRUE;
}

void CCopyFileThread::Init(LPCSTR szSource, LPCSTR szDest, CWnd *pNotifyWnd /*= NULL*/)
{
        m_strSource = szSource;
        m_strDest = szDest;
        m_pNotifyWnd = pNotifyWnd;
}

void CCopyFileThread::Abort()
{
        m_evAbort.SetEvent();
}