// TransferrableFile.cpp: implementation of the CTransferrableFile class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "TransferrableFile.h" #include ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CDataBlock CTransferrableFile::m_DataBlock; const int BLOCKSPERMACROBLOCK=8; CTransferrableFile::CTransferrableFile() { m_bAbort=false; m_hThread=INVALID_HANDLE_VALUE; ::InitializeCriticalSection(&m_Lock); } CTransferrableFile::~CTransferrableFile() { ::DeleteCriticalSection(&m_Lock); } unsigned int CTransferrableFile::GetLength() { BY_HANDLE_FILE_INFORMATION fileInfo; BOOL success; success=::GetFileInformationByHandle(m_hFile, &fileInfo); if (success==FALSE) { return false; } // // yaroze memory cannot handle files bigger than 2Mb. // return fileInfo.nFileSizeLow; } bool CTransferrableFile::StartSend() { DWORD threadID; m_BytesTransferred=0; m_hThread=::CreateThread(NULL, 0, SendStatic, (LPVOID)this, 0, &threadID); if (m_hThread==INVALID_HANDLE_VALUE) { return false; } else { return true; } } DWORD WINAPI CTransferrableFile::SendStatic(LPVOID thisPointer) { bool bSuccess; bSuccess=((CTransferrableFile*)thisPointer)->SendThread(); if (bSuccess) { return 0; } else { return 1; } } void CTransferrableFile::Abort() { ::EnterCriticalSection(&m_Lock); m_bAbort=true; ::LeaveCriticalSection(&m_Lock); ::WaitForSingleObject(m_hThread, INFINITE); } DWORD CTransferrableFile::WriteBigEndianDWORD(CSerialPort& port, DWORD dword) { DWORD bytesTransferred; unsigned char bigEndian[4]; bigEndian[0]=(unsigned char)(dword/0x1000000); bigEndian[1]=(unsigned char)((dword/0x10000)%256); bigEndian[2]=(unsigned char)((dword/0x100)%256); bigEndian[3]=(unsigned char)(dword%256); bytesTransferred=port.PutBytes(bigEndian, 4); return bytesTransferred; } unsigned int CTransferrableFile::GetBytesTransferred() { unsigned int bytesTransferred; ::EnterCriticalSection(&m_Lock); bytesTransferred=m_BytesTransferred; ::LeaveCriticalSection(&m_Lock); return bytesTransferred; } bool CTransferrableFile::WaitForString(CSerialPort& port, char* string) { unsigned int characters; unsigned int currentPosition; unsigned char buffer; DWORD bytesTransferred; characters=strlen(string); currentPosition=0; do { bytesTransferred=port.GetBytes(&buffer, 1); if (buffer==*(string+currentPosition)) { currentPosition++; } } while (bytesTransferred==1 && currentPosition0) { ::EnterCriticalSection(&m_Lock); bAbort=m_bAbort; ::LeaveCriticalSection(&m_Lock); bReadSuccess=::ReadFile(m_hFile, m_DataBlock.GetDataPointer(), length-(blocks*BLOCKSIZE), &bytesRead, NULL); if (bAbort || !bReadSuccess) { // // abort send // port.PutBytes((unsigned char*)"\xff", 1); return false; } bSuccess=m_DataBlock.Send(port, *this); if (!bSuccess) { return false; } } ::EnterCriticalSection(&m_Lock); m_BytesTransferred+=length-(blocks*BLOCKSIZE); ::LeaveCriticalSection(&m_Lock); return true; } bool CTransferrableFile::TransferDataToFile(CSerialPort& port, unsigned int address, unsigned int length) { bool bAbort; bool bSuccess; unsigned int a; DWORD bytesWritten; BOOL bWriteSuccess; DWORD bytesTransferred; unsigned int blocks; ::EnterCriticalSection(&m_Lock); bAbort=m_bAbort; ::LeaveCriticalSection(&m_Lock); if (bAbort) { // // abort send // port.PutBytes((unsigned char*)"\xff", 1); return false; } bytesTransferred=port.PutBytes((unsigned char*)"\x01", 1); if (bytesTransferred!=1) { return false; } bytesTransferred=CTransferrableFile::WriteBigEndianDWORD(port, address); if (bytesTransferred!=4) { return false; } bytesTransferred=CTransferrableFile::WriteBigEndianDWORD(port, length); if (bytesTransferred!=4) { return false; } // // now receive each block // blocks=length/BLOCKSIZE; for (a=0; a0) { ::EnterCriticalSection(&m_Lock); bAbort=m_bAbort; ::LeaveCriticalSection(&m_Lock); bSuccess=m_DataBlock.Receive(port, *this); if (!bSuccess) { return false; } bWriteSuccess=::WriteFile(m_hFile, m_DataBlock.GetDataPointer(), length-(blocks*BLOCKSIZE), &bytesWritten, NULL); if (bAbort || !bWriteSuccess) { // // abort send // port.PutBytes((unsigned char*)"\xff", 1); return false; } } return true; } bool CTransferrableFile::ShouldAbort() { bool bAbort; ::EnterCriticalSection(&m_Lock); bAbort=m_bAbort; ::LeaveCriticalSection(&m_Lock); return bAbort; } bool CTransferrableFile::StartBinaryWrite(CSerialPort& port) { bool bSuccess; // // write 'BWR', wait for 'binary' // bSuccess=CTransferrableFile::WriteString(port, "BWR\r"); if (!bSuccess) { return false; } bSuccess=CTransferrableFile::WaitForString(port, "binary\r"); return bSuccess; } bool CTransferrableFile::EndBinaryWrite(CSerialPort& port) { bool bSuccess; DWORD bytesTransferred; // // write CR then wait for 'end binary' // bytesTransferred=port.PutBytes((unsigned char*)"\r", 1); if (bytesTransferred!=1) { return false; } bSuccess=CTransferrableFile::WaitForString(port, "end binary\r"); return bSuccess; } bool CTransferrableFile::StartBinaryRead(CSerialPort& port) { bool bSuccess; // // write 'BRD', wait for 'binary' // bSuccess=CTransferrableFile::WriteString(port, "BRD\r"); if (!bSuccess) { return false; } ::Sleep(200); bSuccess=CTransferrableFile::WaitForString(port, "binary\r"); return bSuccess; } bool CTransferrableFile::EndBinaryRead(CSerialPort& port) { bool bSuccess; bSuccess=CTransferrableFile::WaitForString(port, "end binary\r"); return bSuccess; } bool CTransferrableFile::WaitForTransferComplete(DWORD millisecondsToWait) { bool bComplete; DWORD result; result=::WaitForSingleObject(m_hThread, millisecondsToWait); switch(result) { case WAIT_OBJECT_0: bComplete=true; break; case WAIT_TIMEOUT: bComplete=false; break; default: bComplete=false; } return bComplete; }