#ifndef __ProgressInfo_h__ #define __ProgressInfo_h__ #include #include "stdstring.h" #include "httpfilepost.h" enum TRANSFER_STATUS { TRANSFER_FATAL_ERROR = -1, // transfer is aborting due to unrecoverable error TRANSFER_OK, // currently not used TRANSFER_SKIPPING_FILE, // file transfer failed, non-fatal, continuing with remaining files TRANSFER_SESSION_INITIATE, // beginning batch file transfer (only agragate vars are valid) TRANSFER_FILE_INITATE, // starting the transfer of a file (current file vars are now valid) TRANSFER_FILE_TRANSFERING, // all vars reflect current progress TRANSFER_FILE_COMPLETE, // file has completed transfering TRANSFER_SESSION_COMPLETE, // session compelete, last callback that will be sent unless // there is an unrecoverable error in which case // TRANSFER_FATAL_ERROR will be the final message }; #include // Windows Multimedia Support (for timeGetTime()) class CProgressInfo; class CWebCabPublisher; typedef UINT (*CS_PROGRESS_PROC)(CProgressInfo*); #define STATUS_BUFFSIZE 1024 class CProgressInfo { public: // while the upload/download thread is updating the variables, // critsec will be locked. users of this class must lock // this critsec before accessing the variables, or they // may get only partially updated values CRITICAL_SECTION critsec; DWORD dwStatusCallback; // status from WinInet char szStatusString[STATUS_BUFFSIZE]; //buffer for status message TRANSFER_STATUS dwStatus; DWORD dwErrorCount; // count of errors encountered this transfer CStdString strFilename; // full path of the currently transfering file CStdString strTitle; // friendly (user specified) title of the file DWORD dwTotalFiles; // total count of files to transfer DWORD dwDoneFiles; // count of files done DWORD dwTotalBytes; // total bytes to transfer DWORD dwTotalDone; // bytes transfered DWORD dwCurrentBytes; // total bytes to transfer for this file DWORD dwCurrentDone; // bytes transfered for this file DWORD dwStartMS; // time started (milliseconds) DWORD dwTransferRate; // (estimated) transfer rate time_t timeElapsed; // time elapsed time_t timeRemaining; // (estimated) time remaining DWORD dwOverallPercent; // overall percent done DWORD dwCurrentPercent; // percent done for this file // these two are used for updating a progress ctrl DWORD dwOverallPos; // (estimated) overall progress (range 0-ffffffff) DWORD dwCurrentPos; // (estimated) current progress (range 0-ffffffff) CS_PROGRESS_PROC pfnProgress; // pointer to callback function LPARAM lParam; // lParam (caller defined value passed back to caller) // caller returns 0 to continue, non-zero to abort (value will be reason for abort) // if caller didn't specify a callback, then assume continue (0) void NotifyCaller() { if(pfnProgress && (*pfnProgress)(this)) { ThrowUploaderException(0); } } void StartSession(DWORD dwCountFiles, DWORD dwCountBytes) { InitializeCriticalSection(&critsec); EnterCriticalSection(&critsec); { // critical section dwStatus = TRANSFER_SESSION_INITIATE; dwErrorCount = 0; strFilename = ""; dwTotalFiles = dwCountFiles; dwDoneFiles = 0; dwTotalDone = 0; dwTotalBytes = dwCountBytes; dwTotalDone = 0; dwCurrentBytes = 0; dwCurrentDone = 0; dwStartMS = timeGetTime(); dwTransferRate = 0; timeElapsed = 0; timeRemaining = 0; dwOverallPercent = 0; dwCurrentPercent = 0; dwOverallPos = 0; dwCurrentPos = 0; } LeaveCriticalSection(&critsec); NotifyCaller(); } void EndSession(UINT uSuccess) { EnterCriticalSection(&critsec); { dwStatus = uSuccess ? TRANSFER_SESSION_COMPLETE : TRANSFER_FATAL_ERROR; } LeaveCriticalSection(&critsec); //DeleteCriticalSection(&critsec); NotifyCaller(); } void StartFile(const CStdString& name, const CStdString& title, DWORD size) { EnterCriticalSection(&critsec); { // critical section dwStatus = TRANSFER_FILE_INITATE; strFilename = name; strTitle = title; dwCurrentBytes = size; dwCurrentDone = 0; dwCurrentPercent = 0; dwCurrentPos = 0; } LeaveCriticalSection(&critsec); NotifyCaller(); } void UpdateProgress(DWORD dwBytesTransfered) { EnterCriticalSection(&critsec); { // critical section dwStatus = TRANSFER_FILE_TRANSFERING; dwTotalDone += dwBytesTransfered; dwCurrentDone += dwBytesTransfered; dwOverallPos = dwTotalBytes ? MulDiv(dwTotalDone, 0xFFFF, dwTotalBytes) : 0; dwCurrentPos = dwCurrentBytes ? MulDiv(dwCurrentDone, 0xFFFF, dwCurrentBytes) : 0; dwOverallPercent = (dwOverallPos * 100) / 0xFFFF; dwCurrentPercent = (dwCurrentPos * 100) / 0xFFFF; DWORD dwElapsedMS = timeGetTime() - dwStartMS; dwTransferRate = MulDiv(dwTotalDone, 1000, dwElapsedMS); DWORD dwTimeRemaining = MulDiv(dwElapsedMS, dwTotalBytes, dwTotalDone) - dwElapsedMS; timeRemaining = dwTimeRemaining / 1000; timeElapsed = dwElapsedMS / 1000; } LeaveCriticalSection(&critsec); NotifyCaller(); } void EndFile() { EnterCriticalSection(&critsec); { // critical section dwStatus = TRANSFER_FILE_COMPLETE; dwDoneFiles++; } LeaveCriticalSection(&critsec); NotifyCaller(); } }; #endif //__ProgressInfo_h__